home *** CD-ROM | disk | FTP | other *** search
/ CP/M / CPM_CDROM.iso / mbug / mbug097.arc / WINDOW.MAC < prev   
Text File  |  1979-12-31  |  46KB  |  2,711 lines

  1. ;
  2. ;    *************************************************
  3. ;    *                        *
  4. ;    *          WINDOW.SYS            *
  5. ;    *                        *
  6. ;    *    512k/256k enhanced BIOS.        *
  7. ;    *    System control window program.        *
  8. ;    *                        *
  9. ;    *    Copyright 1986/7/8 Peter Broughton.    *
  10. ;    *                        *
  11. ;    *************************************************
  12. ;
  13. ;
  14. ;
  15. ;
  16.  
  17.  
  18. true        equ    -1
  19. false        equ    0
  20.  
  21. version    macro
  22.     db    'Version 2, 7th Jul., 1988'
  23.     endm
  24.  
  25. fake_standard    equ    false    ; Makes Premium think it is a standard.
  26.  
  27. start_address    equ    5D00h
  28.  
  29. num_fn_keys    equ    12
  30.  
  31. fn_store    equ    8000h-(num_fn_keys*128)
  32.  
  33. spare_fn_str    equ    fn_store-128    ; space for returning date, time
  34.  
  35. fn_key_1    equ    81h    ; code returned by scn_in
  36.  
  37. fn_key_1_code    equ    81h    ; code in function string
  38.  
  39. fn_key_1_us    equ    '1'+80h    ; code for new keyboard unshifted F1
  40.  
  41. fn_str_end    equ    0FFh
  42.  
  43. fn_str_pause    equ    0FEh
  44.  
  45. fn_str_wait    equ    0FDh
  46.  
  47. window_key    equ    0A0h    ; this is the key returned by scn_in when
  48.                 ; user presses window combination
  49.  
  50. curs_key    equ    90h    ; values returned by scn_in for cursor keys
  51.                 ; start with this one
  52.  
  53. window_start    equ    08000h+80+((80-num_cols)/2)
  54.  
  55. window_attr    equ    1    ; value to put in attribute RAM if premium
  56.  
  57. ; window size
  58. num_lines    equ    13
  59. num_cols    equ    40
  60.  
  61. def_bios_start    equ    0E700h    ; may not work unless bios start is this addr
  62.  
  63. print_s_line    equ    5806h    ; BIOS routine to update status line
  64.  
  65. ; offsets in definition section of (MY!) BIOS
  66. screen_colour    equ    12Ah
  67.  
  68. status_on    equ    3Ah
  69.  
  70. status_colour    equ    228h
  71.  
  72. is_premium    equ    21Ch
  73.  
  74. curs_key_tab    equ    26Bh
  75.  
  76. click_length    equ    223h
  77.  
  78. click_tone    equ    224h
  79.  
  80. caps_lock    equ    27Bh+17
  81.  
  82. cpu_speed    equ    28Dh
  83. fast_bit    equ    2
  84. speed_port    equ    9
  85.  
  86. ; graphic characters
  87. pcg_1        equ    8Ch
  88. char_tl        equ    pcg_1+0
  89. char_t        equ    pcg_1+1
  90. char_tr        equ    pcg_1+2
  91. char_l        equ    pcg_1+3
  92. char_bl        equ    pcg_1+4
  93. char_br        equ    pcg_1+5
  94. char_lm        equ    pcg_1+6
  95. char_rm        equ    pcg_1+7
  96. char_curs    equ    pcg_1+8
  97. char_pause    equ    pcg_1+9
  98. char_ctrl    equ    pcg_1+10
  99. char_fn        equ    pcg_1+11
  100. char_wait    equ    pcg_1+12
  101.  
  102. first_char    equ    8800h+(16*(pcg_1-80h))
  103. num_pcg        equ    13
  104.  
  105. get_char    equ    27Bh+0
  106. get_rtc        equ    27Bh+2
  107. put_rtc        equ    27Bh+4
  108. con_out        equ    27Bh+9
  109. ptr_out        equ    27Bh+11
  110.                         
  111. col_latch    equ    8
  112.     if    fake_standard
  113. vml        equ    0
  114.     else
  115. vml        equ    1Ch
  116.     endif
  117.  
  118. ; 128 bytes with addresses etc.
  119.  
  120.         aseg
  121.  
  122.         org    100h
  123.         .phase    start_address-128
  124.  
  125.     dw    8000h            ; Min BIOS start
  126.     dw    start_address        ; Start address
  127.     dw    end_code-start_address    ; length
  128.  
  129.     ds    (start_address)-$
  130.  
  131. ; Start of code
  132.  
  133.     ld    (save_sp),sp
  134.     ld    sp,stack
  135. ; all used regs except a, bc, hl must be saved
  136.     push    de
  137.     push    ix
  138.  
  139.     call    do_checks
  140.  
  141.     call    save_screen
  142.  
  143. ; main loop
  144. main_loop:
  145.     call    main_menu
  146.  
  147. m_lp1:
  148.     call    get_a_key
  149.     jr    nz,m_lp1
  150.  
  151.     cp    ' '
  152.     jr    z,main_loop
  153.     call    conv_upper
  154.     cp    'C'
  155.     jp    z,set_curs_key
  156.     cp    'F'
  157.     jp    z,set_fn
  158.     cp    'K'
  159.     jp    z,set_click
  160.     cp    'M'
  161.     jp    z,misc_functions
  162.     cp    'S'
  163.     jp    z,screen_functions
  164.     cp    'T'
  165.     jp    z,time_functions
  166.     cp    'W'
  167.     jp    z,warm_boot
  168.  
  169. m_lp_2:
  170.     ld    hl,last_key
  171.     cp    (hl)
  172.     ld    (hl),a
  173.     jr    nz,m_lp_3
  174.     cp    'V'
  175.     call    z,prt_version
  176.     cp    'X'-40h
  177.     call    z,prt_hello_a
  178.  
  179. m_lp_3:
  180. ; ESC = exit
  181.     cp    '['-40h
  182.     jr    nz,m_lp1
  183.  
  184. exit_window:
  185.     call    restore_screen
  186.  
  187.     pop    ix
  188.     pop    de
  189.     ld    sp,(save_sp)
  190.     ret
  191.  
  192.  
  193. main_menu:
  194.     call    prt_hello
  195.     call    clear_lower
  196.     ld    hl,main_menu_3
  197.     call    print_string
  198.     ld    hl,main_menu_4
  199.     call    print_string
  200.     ld    hl,main_menu_5
  201.     call    print_string
  202.     ld    hl,main_menu_6
  203.     call    print_string
  204.     ld    hl,main_menu_7
  205.     call    print_string
  206.     ld    hl,main_menu_8
  207.     call    print_string
  208.     ld    hl,main_menu_9
  209.     call    print_string
  210.     xor    a
  211.     ld    (last_key),a
  212.     ret
  213.  
  214. prt_hello:
  215.     ld    a,r
  216.     or    a
  217.     ret    nz
  218.     pop    hl
  219. prt_hello_a:
  220.     call    clear_lower
  221.     call    h_dec
  222.     ld    hl,hello_1
  223.     call    print_string
  224.     ld    hl,hello_2
  225.     call    print_string
  226.     ld    hl,hello_3
  227.     call    print_string
  228.     ld    hl,hello_4
  229.     call    print_string
  230.     ld    hl,hello_5
  231.     call    print_string
  232.     ld    hl,hello_6
  233.     call    print_string
  234.     call    h_dec
  235.     xor    a
  236.     ld    (last_key),a
  237.     ret
  238.  
  239. h_dec:
  240.     ld    hl,h31
  241.     ld    b,4
  242. h_d1:
  243.     ld    a,(hl)
  244.     cp    255
  245.     jr    z,h_d2
  246.     neg
  247.     ld    (hl),a
  248.     inc    hl
  249.     jr    h_d1
  250. h_d2:
  251.     inc    hl
  252.     inc    hl
  253.     inc    hl
  254.     djnz    h_d1
  255.     ret
  256.  
  257. hello_3:
  258.     dw    window_start+(80*6)+((40-(h32-h31))/2)
  259. h31:    db    -'B',-'r',-'o',-'u',-'g',-'h',-'t',-' ',-'t',-'o',-' '
  260.     db    -'y',-'o',-'u',-' ',-'b',-'y',-' ',-'t',-'h',-'e',-' '
  261.     db    -'p',-'r',-'o',-'g',-'r',-'a',-'m',-'m',-'i',-'n',-'g'
  262. h32:    db    255
  263. hello_4:
  264.     dw    window_start+(80*7)+((40-(h42-h41))/2)
  265. h41:    db    -'s',-'k',-'i',-'l',-'l',-'s',-' ',-'o',-'f',-' '
  266.     db    -'P',-'e',-'t',-'e',-'r',-' '
  267.     db    -'B',-'r',-'o',-'u',-'g',-'h',-'t',-'o',-'n',-'.'
  268. h42:    db    255
  269. hello_5:
  270.     dw    window_start+(80*8)+((40-(h52-h51))/2)
  271. h51:    db    -'N',-'o',-'t',-'e',-':',-' ',-'T',-'h',-'i',-'s',-' '
  272.     db    -'i',-'s',-' ',-'i',-'n',-'e',-'x',-'p',-'e',-'n',-'s',-'i'
  273.     db    -'v',-'e',-' ',-'S',-'/',-'W',-','
  274. h52:    db    255
  275. hello_6:
  276.     dw    window_start+(80*9)+((40-(h62-h61))/2)
  277. h61:    db    -'p',-'l',-'e',-'a',-'s',-'e',-' ',-'d',-'o',-'n',-'''',-'t'
  278.     db    -' ',-'c',-'o',-'p',-'y',-' ',-'i',-'t',-' '
  279.     db    -'i',-'l',-'l',-'e',-'g',-'a',-'l',-'l',-'y',-' ',-'!',-'!'
  280. h62:    db    255
  281.  
  282.  
  283. ;    The above lines read :
  284.  
  285. ;Microbee 512k/256k
  286. ;Enhanced Operating System v2.2
  287. ;Brought to you by the programming
  288. ;skills of Peter Broughton.
  289. ;Note: This is inexpensive S/W,
  290. ;please don't copy it illegally !!
  291.  
  292.  
  293. prt_version:
  294.     call    clear_lower
  295.     ld    hl,hello_1
  296.     call    print_string
  297.     ld    hl,hello_2
  298.     call    print_string
  299.     ld    hl,version_1
  300.     call    print_string
  301.     ld    hl,version_2
  302.     call    print_string
  303.     xor    a
  304.     ld    (last_key),a
  305.     ret
  306.  
  307.  
  308. hello_1:
  309.     dw    window_start+(80*4)+((40-(h12-h11))/2)
  310. h11:    db    9,9,'  Microbee 512k/256k  ',13,13
  311. h12:    db    255
  312.  
  313. hello_2:
  314.     dw    window_start+(80*5)+((40-(h22-h21))/2)
  315. h21:    db    'Enhanced Operating System v2.2'
  316. h22:    db    255
  317.  
  318. ; System Setup Window.
  319. ; Version x.x, xx/xx/xx.
  320.  
  321. version_1:
  322.     dw    window_start+(80*6)+((40-(v12-v11))/2)
  323. v11:    db    'System Setup Window.'
  324. v12:    db    255
  325.  
  326. version_2:
  327.     dw    window_start+(80*7)+((40-(v22-v21))/2)
  328. v21:    version
  329. v22:    db    255
  330.  
  331.  
  332. do_function:
  333.     sub    fn_key_1
  334.  
  335. ; jump to this point will 'do' fn in A ( 0.. , or -1 for time/date stamp )
  336. do_fn_A:
  337.     add    a,high (fn_store*2)
  338.     ld    c,0
  339.     srl    a
  340.     rr    c
  341.     ld    b,a
  342.     ld    hl,def_bios_start+27Bh+6
  343.     ld    (hl),true
  344.     inc    hl
  345.     ld    (hl),c
  346.     inc    hl
  347.     ld    (hl),b
  348.     jp    exit_window
  349.  
  350.  
  351. misc_functions:
  352.     call    clear_lower
  353.     ld    hl,misc_fn_1
  354.     call    print_string
  355.     ld    hl,misc_fn_2
  356.     call    print_string
  357. mf_1:
  358.     call    get_a_key
  359.     call    conv_upper
  360.     cp    'F'
  361.     jr    z,set_fast
  362.     cp    'S'
  363.     jr    z,set_slow
  364.     cp    '['-40h
  365.     jr    nz,mf_1
  366.     jp    main_loop
  367.  
  368. set_fast:
  369.     ld    a,true
  370. sf_1:
  371.     ld    (def_bios_start+cpu_speed),a
  372.     and    fast_bit
  373.     in    a,(speed_port)
  374.     jr    mf_1
  375.  
  376. set_slow:
  377.     xor    a
  378.     jr    sf_1
  379.  
  380. warm_boot:
  381. ; must reset pointers to extended command line
  382.     ld    hl,def_bios_start+15Ch
  383.     ld    e,(hl)
  384.     ld    (hl),60h    ; low (bios_start)+160h
  385.     inc    hl
  386.     ld    (hl),h        ; high (bios_start)+160h
  387.     inc    hl
  388.     ld    (hl),128    ; total length of command buffer
  389.     inc    hl
  390.     ld    (hl),0        ; length of command buffer used
  391.     inc    hl
  392.     ld    d,h
  393.     ld    a,e
  394.     cp    60h
  395.     jr    c,w_b_5        ; illegal if e < 60h
  396. ;    cp    60h+128        ; or if e > 60h+128
  397. ;    jr    nc,w_b_5    ; then fill buffer with 0h's
  398. ; at this stage hl --> start of command buffer
  399. ;        de --> start of valid section of command line
  400. ; now move back valid section to start of command buffer
  401. w_b_4:
  402.     ld    a,e
  403.     cp    60h+128
  404.     jr    nc,w_b_5
  405.     ld    a,(de)
  406.     ld    (hl),a
  407.     inc    hl
  408.     inc    de
  409.     jr    w_b_4
  410. w_b_5:
  411. ; pad rest of line with 0h's
  412.     ld    a,l
  413.     cp    60h+128
  414.     jr    z,w_b_6
  415.     ld    (hl),0
  416.     inc    hl
  417.     jr    w_b_5
  418. w_b_6:
  419.     call    clear_lower
  420.     ld    hl,w_boot_1
  421.     call    print_string
  422.     ld    hl,w_boot_2
  423.     call    print_string
  424.     ld    hl,w_boot_3
  425.     call    print_string
  426.     ld    hl,w_boot_4
  427.     call    print_string
  428. w_b2:
  429.     call    get_a_key
  430.     call    conv_upper
  431.     cp    'B'
  432.     jr    z,do_boot
  433.     cp    'S'
  434.     jr    z,force_shell
  435.     cp    'C'
  436.     jr    z,force_ccp
  437.     cp    'E'
  438.     jr    z,mod_com
  439.     cp    '['-40h
  440.     jr    nz,w_b2
  441.     jp    main_loop
  442. ; force to boot to shell
  443. force_shell:
  444.     ld    a,1
  445.     jr    w_b3
  446. force_ccp:
  447.     xor    a
  448. w_b3:
  449.     ld    (def_bios_start+128h),a
  450.  
  451. ; do the actual boot
  452. do_boot:
  453.     call    restore_screen
  454.     call    clear_screen
  455.     ld    hl,def_bios_start
  456.     inc    hl
  457.     inc    hl
  458.     inc    hl
  459.     jp    (hl)
  460.  
  461. ; modify command line
  462. mod_com:
  463.     ld    hl,def_bios_start+160h
  464.     push    hl
  465.     ld    de,temp_string
  466.     ld    bc,128
  467.     ldir
  468.     xor    a
  469.     call    clear_lower
  470.     call    enter_string
  471.     pop    de
  472.     jp    z,warm_boot
  473.     ld    hl,temp_string
  474.     ld    bc,128
  475.     ldir
  476.     jp    warm_boot
  477.  
  478. set_click:
  479.     call    clear_lower
  480.     ld    hl,click_1
  481.     call    print_string
  482.     ld    hl,click_2
  483.     call    print_string
  484. s_cl1:
  485.     call    get_a_key
  486.     call    conv_upper
  487.     cp    '['-40h
  488.     jp    z,main_loop
  489.     cp    '1'
  490.     jr    c,s_cl1
  491.     cp    '9'+1
  492.     jr    c,s_cl_tone
  493.     cp    'L'
  494.     jr    nz,s_cl1
  495.  
  496. s_cl_len:
  497.     call    get_a_key
  498.     jr    nz,s_cl_len
  499.     sub    '0'
  500.     jr    c,s_cl1
  501.     cp    9+1
  502.     jr    nc,s_cl1
  503.     ld    hl,click_lengths
  504.     ld    de,def_bios_start+click_length
  505. s_cl2:
  506.     ld    b,0
  507.     ld    c,a
  508.     add    hl,bc
  509.     ld    a,(hl)
  510.     ld    (de),a
  511.     jr    s_cl1
  512.  
  513. s_cl_tone:
  514.     sub    '1'
  515.     ld    hl,click_tones
  516.     ld    de,def_bios_start+click_tone
  517.     jr    s_cl2
  518.  
  519.  
  520. ; program function keys
  521. set_fn:
  522.     call    clear_lower
  523. s_fn3:
  524.     ld    hl,set_fn_1
  525.     call    print_string
  526.     ld    hl,set_fn_2
  527.     call    print_string
  528.     ld    hl,set_fn_3
  529.     call    print_string
  530.     ld    a,(def_bios_start+220h)
  531.     ld    hl,set_fn_on    ; fn active message
  532.     or    a
  533.     jr    nz,s_fn4
  534.     ld    hl,set_fn_off
  535. s_fn4:
  536.     call    print_string
  537. s_fn1:
  538.     call    get_a_key
  539.     call    conv_upper
  540.     cp    'O'
  541.     jr    z,fn_toggle
  542.     cp    'N'
  543.     jr    z,fn_number
  544.     cp    '['-40h
  545.     jp    z,main_loop
  546. ; any one of a number of keys can get fn up : '1'.. (&'"','#','$','%'),
  547. ; F1.., 'unshifted' F1..
  548.     cp    '"'
  549.     jr    c,s_fn9
  550.     cp    '%'+1
  551.     jr    nc,s_fn8
  552. ; convert to F9..F12 (8..11)
  553.     sub    '"'-8
  554.     jr    s_fn10
  555. s_fn8:
  556.     or    80h
  557. s_fn9:
  558. ; convert '1'+80h to F1
  559.     cp    fn_key_1_us
  560.     jr    c,s_fn7
  561.     sub    fn_key_1_us-fn_key_1
  562. s_fn7:
  563.     cp    fn_key_1
  564.     jr    c,s_fn1
  565.     cp    fn_key_1+num_fn_keys
  566.     jr    nc,s_fn1
  567.  
  568. ; function key is pressed so program it, first find its memory location
  569.     sub    fn_key_1
  570. s_fn10:
  571. ; and save its number (0.. ) for later printing
  572.     push    af
  573.     ld    l,0
  574.     srl    a
  575.     rr    l
  576.     add    a,high fn_store
  577.     ld    h,a
  578.     ld    (prog_fn_addr),hl
  579.     ld    de,temp_string
  580.     ld    bc,128
  581.     ldir
  582.     call    clear_lower
  583.     ld    hl,window_start+(4*80)+4
  584.     ld    (hl),char_fn
  585.     inc    hl
  586.     pop    af
  587. ; print fn number, first is it =>F10 ( 9 actually since now F1 = 0 )
  588.     cp    9
  589.     jr    c,s_fn6
  590.     ld    (hl),'1'
  591.     inc    hl
  592.     sub    10        ; convert to second digit
  593. s_fn6:
  594.     add    a,'1'
  595.     ld    (hl),a
  596.     ld    a,true
  597.     call    enter_string
  598.     jp    z,s_fn3
  599.     ld    hl,temp_string
  600.     ld    de,(prog_fn_addr)
  601.     ld    bc,128
  602.     ldir
  603.     jp    set_fn
  604.     
  605. ; toggle function keys on/off
  606. fn_toggle:
  607.     call    fn_tog1
  608.     jp    s_fn3
  609. fn_tog1:
  610.     ld    hl,def_bios_start+220h
  611.     ld    a,(hl)
  612.     xor    true
  613.     ld    (hl),a
  614.     ret
  615.  
  616. ; assign numbers to unshifted function keys ( for Simply Write etc.)
  617. fn_number:
  618.     ld    hl,fn_num_1
  619.     call    print_string
  620. fn_n_1:
  621.     call    get_a_key
  622.     jr    nz,fn_n_1
  623.     call    conv_upper
  624.     cp    'Y'
  625.     jp    nz,set_fn    
  626.     ld    hl,fn_store
  627.     ld    b,8
  628.     ld    a,'1'
  629.     ld    de,127
  630. s_fn5:
  631.     ld    (hl),a
  632.     inc    hl
  633.     ld    (hl),fn_str_end
  634.     add    hl,de
  635.     inc    a
  636.     djnz    s_fn5
  637.     jp    set_fn
  638.  
  639.  
  640. ; enter text into 128 byte buffer (temp_string)
  641. ; max 127 chars
  642. ; a is true for function string, ie. allow entering of control codes, etc.,
  643. ;      false for command line, no control codes.
  644. ; returns nz if can save, ie. wasn't aborted
  645. enter_string:
  646.     ld    ix,fn_flag
  647.     ld    (ix),a
  648.     or    a
  649.     ld    a,fn_str_end    ; if true then end char is 0FFh or whatever
  650.     jr    nz,es_2
  651.     xor    a        ; else is 0h
  652. es_2:
  653.     ld    hl,temp_string
  654.     ld    c,0
  655. es_3:
  656.     cp    (hl)
  657.     jr    z,es_4        ; found end
  658.     inc    c        ; one more char in valid line
  659.     bit    7,c        ; has it gone too far
  660.     jr    nz,es_8
  661.     inc    hl
  662.     jr    es_3
  663. ; physical end found first
  664. es_8:
  665.     ld    (hl),a        ; give it an end char
  666.     dec    c
  667. es_4:
  668.     ld    a,c
  669.     ld    (line_length),a
  670.     call    clear_p_lower
  671.     ld    hl,ent_str_1
  672.     call    print_string
  673.     bit    0,(ix)
  674.     jr    z,es_10
  675.     ld    hl,ent_str_2
  676.     call    print_string
  677.     ld    hl,ent_str_3
  678.     call    print_string
  679.     ld    hl,ent_str_4
  680.     call    print_string
  681. es_10:
  682.     xor    a
  683. ; this is the main loop that is gone through once for every successful key
  684. new_c_pos_1:
  685.     ld    (pointer),a    ; where cursor is
  686.     call    print_line
  687. es_1:
  688.     ld    a,(pointer)
  689.     ld    c,a
  690.     call    get_a_key_c
  691.     jr    nz,es_1
  692.     bit    7,(ix)
  693.     jr    nz,es_15
  694.     call    conv_upper    ; convert to upper case if command line
  695.     jr    es_17        ; and skip the next stuff
  696. es_15:
  697. ; controls that are only available when entering function string
  698.     cp    'P'-40h
  699.     jp    z,es_pause    ; enter pause
  700.     cp    'W'-40h
  701.     jp    z,es_wait
  702.     cp    '^'
  703.     jp    z,es_lit    ; enter CTRL code
  704. ; is 'unshifted' function key pressed
  705. ;    cp    fn_key_1_us
  706. ;    jr    c,es_16
  707. ;    cp    fn_key_1_us+num_fn_keys    
  708. ;    jp    c,es_chain
  709. ;es_16:
  710. ; is function key pressed (ie. chain to new function)
  711.     cp    fn_key_1
  712.     jr    c,es_17
  713.     cp    fn_key_1+num_fn_keys
  714.     jp    c,es_chain
  715. ; controls available for entering fn and command
  716. es_17:
  717.     cp    80h        ; don't let through any other high bit codes
  718.     jr    nc,es_1
  719.     cp    127
  720.     jp    z,es_del_u
  721.     cp    ' '
  722.     jp    nc,es_norm
  723.     cp    'A'-40h
  724.     jr    z,es_left_lots
  725.     cp    'D'-40h
  726.     jr    z,es_right
  727.     cp    'E'-40h
  728.     jr    z,es_start
  729.     cp    'F'-40h
  730.     jr    z,es_right_lots
  731.     cp    'G'-40h
  732.     jr    z,es_del_u
  733.     cp    'H'-40h
  734.     jp    z,es_del
  735.     cp    'S'-40h
  736.     jr    z,es_left
  737.     cp    'X'-40h
  738.     jr    z,es_end
  739.     cp    'Y'-40h
  740.     jr    z,es_kill
  741.     cp    '['-40h
  742.     jr    z,es_quit
  743.     cp    'M'-40h
  744.     jr    nz,es_1
  745. ; <RETURN> : return nz
  746.     or    0FFh
  747. ; <ESC> : return z
  748. es_quit:
  749.     push    af
  750.     call    clear_lower
  751.     pop    af
  752.     ret
  753.  
  754. ; ^A : 8 left
  755. es_left_lots:
  756.     ld    a,c
  757.     sub    8
  758.     jr    nc,new_c_pos
  759. ; ^E : start of line
  760. es_start:
  761.     xor    a
  762.     jr    new_c_pos
  763. ; ^S : 1 left
  764. es_left:
  765.     ld    a,c
  766.     dec    a
  767.     cp    255
  768.     jr    nz,new_c_pos
  769.     jr    es_start
  770. ; ^D : 1 right
  771. es_right:
  772.     ld    a,c
  773.     inc    a
  774. check_right:
  775.     ld    b,a
  776.     ld    a,(line_length)
  777.     inc    a
  778.     ld    c,a
  779.     ld    a,b
  780.     cp    c
  781.     jr    c,new_c_pos
  782. ; ^X : end of line
  783. es_end:
  784.     ld    a,(line_length)
  785. new_c_pos:
  786.     jp    new_c_pos_1
  787.  
  788. ; ^F : 8 right
  789. es_right_lots:
  790.     ld    a,c
  791.     add    a,8
  792.     jr    check_right
  793. ; ^Y : delete line
  794. es_kill:
  795.     ld    hl,temp_string
  796.     ld    b,128
  797.     xor    a
  798.     bit    0,(ix)
  799.     jr    z,es_k1
  800.     ld    a,fn_str_end
  801. es_k1:
  802.     ld    (hl),a
  803.     inc    hl
  804.     djnz    es_k1
  805.     xor    a
  806.     ld    (line_length),a
  807.     jr    new_c_pos
  808. ; BS : delete char to left
  809. es_del:
  810.     xor    a
  811.     or    c
  812.     jp    z,es_1
  813.     call    del_char
  814.     dec    a
  815.     jr    new_c_pos
  816. ; ^G, DEL : delete char under (above) cursor
  817. es_del_u:
  818.     ld    a,(line_length)
  819.     cp    c
  820.     jp    z,es_1
  821.     inc    c
  822.     call    del_char
  823.     jr    new_c_pos
  824. ; ^ : enter control code
  825. es_lit:
  826.     call    get_a_key_c
  827.     jr    nz,es_lit
  828.     cp    7Fh        ; let through DEL char
  829.     jr    z,es_norm
  830.     cp    '^'        ; let through ^
  831.     jr    z,es_norm
  832.     and    31        ; else convert to CTRL
  833.     jr    es_norm
  834. ; ^P : enter pause char into string
  835. es_pause:
  836.     ld    a,fn_str_pause
  837.     jr    es_norm
  838.  
  839. ; ^W : enter wait char into string
  840. es_wait:
  841.     ld    a,fn_str_wait
  842. ;    jr    es_norm
  843.  
  844. ; chain to new function
  845. es_chain:
  846.  
  847. ; enter character in A into string
  848. es_norm:
  849.     push    af
  850.     ld    a,(line_length)
  851.     cp    127        ; is line already full
  852.     jr    z,str_full
  853.     inc    a
  854.     ld    (line_length),a
  855.     ld    hl,temp_string+126    ; move rest of string to right
  856.     ld    d,h
  857.     ld    e,l
  858.     inc    de
  859.     ld    a,127
  860.     sub    c        ; num chars to move
  861.     ld    c,a
  862.     ld    b,0
  863.     lddr
  864.     pop    af
  865.     ld    (de),a        ; insert new char
  866.     ld    a,(pointer)
  867.     inc    a
  868.     jp    new_c_pos
  869.  
  870. str_full:
  871.     pop    af
  872.     jp    es_1
  873.  
  874. ; toggle function keys on/off so that 'unshifted' F1.. can be entered
  875. ; with a standard keyboard
  876. ;es_fn_toggle:
  877. ;    call    fn_tog1
  878. ;    jp    es_1
  879.  
  880. ; delete char to left of c, ie. move chars from c to end left one
  881. ; return current pointer in a
  882. del_char:
  883.     ld    b,0
  884.     ld    hl,temp_string
  885.     add    hl,bc
  886.     ld    d,h
  887.     ld    e,l
  888.     dec    de
  889.     ld    a,128
  890.     sub    c
  891.     ld    c,a
  892.     ldir
  893.     ld    hl,line_length
  894.     dec    (hl)
  895.     ld    a,(pointer)
  896.     ret
  897.  
  898. ; print section of line around cursor position ( in A )
  899. ; Try to position cursor at 13th column from start of line,
  900. ; else somewhere to left of this.
  901. print_line:
  902. ; clear cursor line first
  903.     ld    hl,window_start+(80*5)+8
  904.     ld    b,28
  905. p_l12:
  906.     ld    (hl),' '
  907.     inc    hl
  908.     djnz    p_l12
  909. ; find pos to start display from
  910.     ld    hl,temp_string
  911.     ld    c,a
  912.     ld    b,0
  913.     add    hl,bc
  914.     ld    b,16
  915.     ld    c,a
  916. p_l1:
  917.     dec    hl
  918.     dec    c
  919.     ld    a,(hl)
  920. ; if chain to new fn then can display 1 or 2 less chars
  921. ; ditto for 'unshifted' F1..
  922.     cp    fn_key_1_us
  923.     jr    c,p_l19
  924.     cp    fn_key_1_us+num_fn_keys
  925.     jr    nc,p_l19
  926.     sub    fn_key_1_us-fn_key_1
  927. p_l19:
  928.     cp    fn_key_1
  929.     jr    c,p_l17
  930.     cp    fn_key_1+num_fn_keys
  931.     jr    nc,p_l17
  932.     dec    b
  933.     jr    z,p_l3
  934.     cp    fn_key_1+9        ; >=F10 so 2 chars
  935.     jr    nc,p_l18
  936. p_l17:
  937.     cp    ' '        ; ditto for control code
  938.     jr    nc,p_l2
  939. p_l18:
  940.     dec    b
  941.     jr    z,p_l3
  942. p_l2:
  943.     djnz    p_l1
  944. p_l3:
  945.     bit    7,c
  946.     jr    z,p_l10
  947. ; cursor is close to start of line and the above code went back too far so..
  948.     ld    c,0
  949.     ld    hl,temp_string
  950. p_l10:
  951. ; at this stage HL should point to the start of the section to be displayed
  952. ;  and C should contain the number of the character to start display with
  953.     ex    de,hl
  954.     ld    hl,window_start+(80*4)+8
  955. ; load B with end of line character
  956.     ld    b,0
  957.     bit    0,(ix)
  958.     jr    z,p_l7
  959.     ld    b,fn_str_end
  960. p_l7:
  961. ; loop printing characters until full or end of line encountered
  962. p_l11:
  963. ; is this where the cursor is
  964.     ld    a,(pointer)
  965.     cp    c
  966.     jr    nz,p_l8
  967.     push    bc
  968.     push    hl
  969.     ld    bc,80
  970.     add    hl,bc
  971.     ld    (hl),char_curs    ; if yes then print cursor on line below
  972.     pop    hl
  973.     pop    bc
  974. p_l8:
  975.     ld    a,(de)
  976.     cp    b        ; end of line
  977.     jr    z,p_l4
  978.     cp    fn_str_pause    ; pause character
  979.     jr    nz,p_l5
  980.     ld    a,char_pause
  981.     jr    p_l6
  982. p_l5:
  983.     cp    fn_str_wait    ; wait character
  984.     jr    nz,p_l21
  985.     ld    a,char_wait
  986.     jr    p_l6
  987. p_l21:
  988.     cp    fn_key_1    ; chain to fn
  989.     jr    c,p_l15
  990. ;    call    check_eol
  991. ;    jr    z,p_l13
  992.     ld    (hl),char_fn
  993. ; is it actually 'unshifted' F1..
  994. ;    cp    fn_key_1_us
  995. ;    jr    c,p_l20
  996. ;    ld    (hl),char_fn_us
  997. ;    sub    fn_key_1_us-fn_key_1
  998. p_l20:
  999.     inc    hl
  1000.     sub    fn_key_1
  1001.     cp    9
  1002.     jr    c,p_l16
  1003.     ld    (hl),'1'
  1004.     inc    hl
  1005.     sub    10
  1006. p_l16:
  1007.     add    a,'1'
  1008.     jr    p_l6
  1009. p_l15:
  1010.     cp    ' '
  1011.     jr    nc,p_l6
  1012. ;    call    check_eol
  1013. ;    jr    z,p_l13        ; not enough room on line
  1014.     ld    (hl),char_ctrl    ; control character
  1015.     inc    hl
  1016.     add    a,40h
  1017. p_l6:
  1018.     ld    (hl),a        ; put it on the screen
  1019. ; next character until end
  1020.     inc    hl
  1021.     inc    de
  1022.     inc    c
  1023. ; end of physical line, should not reach here as there should be an
  1024. ; EOL character
  1025.     ld    a,128
  1026.     cp    c
  1027.     jr    z,p_l13
  1028.     push    bc
  1029.     ld    bc,window_start+(80*4)+8+24
  1030.     or    a
  1031.     push    hl
  1032.     sbc    hl,bc
  1033.     pop    hl
  1034.     pop    bc
  1035.     jr    c,p_l11
  1036.     jr    p_l13
  1037. ; finished printing line but must add end of line character
  1038. p_l4:
  1039.     ld    (hl),13
  1040.     inc    hl
  1041. ; now clear any unused positions
  1042. p_l13:
  1043.     ex    de,hl
  1044.     ld    hl,window_start+(80*4)+8+25+2    ; +2 for a bit extra
  1045.     or    a
  1046.     sbc    hl,de
  1047.     ld    b,l        ; num unused
  1048.     ex    de,hl
  1049. p_l14:
  1050.     ld    (hl),' '
  1051.     inc    hl
  1052.     djnz    p_l14
  1053. ; print number of characters on line
  1054. print_bin:
  1055.     ld    hl,window_start+(5*80)+28
  1056.     ld    c,false                ; leading zero flag
  1057.     ld    a,(line_length)
  1058. ; hundred
  1059.     cp    100
  1060.     ld    b,' '
  1061.     jr    c,p_b_1
  1062.     ld    b,'1'
  1063.     ld    c,true
  1064.     sub    100
  1065. p_b_1:
  1066.     ld    (hl),b
  1067.     inc    hl
  1068. ; tens
  1069.     ld    d,10
  1070.     ld    e,0
  1071. p_b_3:
  1072.     sub    d
  1073.     jr    c,p_b_2
  1074.     inc    e
  1075.     jr    p_b_3
  1076. p_b_2:
  1077.     add    a,d
  1078.     ld    d,a
  1079.     ld    a,c    ; blank if =0 and is leading number
  1080.     or    e
  1081.     ld    a,' '
  1082.     jr    z,p_b_4
  1083.     ld    a,'0'
  1084.     add    a,e
  1085. p_b_4:
  1086.     ld    (hl),a
  1087.     inc    hl
  1088. ; units
  1089.     ld    a,'0'
  1090.     add    a,d
  1091.     ld    (hl),a
  1092.     inc    hl
  1093.     ex    de,hl
  1094.     ld    hl,char_word
  1095.     ld    bc,len_char_word
  1096.     ldir
  1097.     ld    a,(line_length)
  1098.     cp    1
  1099.     ld    a,' '
  1100.     jr    z,p_b_5
  1101.     ld    a,'s'
  1102. p_b_5:
  1103.     ld    (de),a
  1104.     ret
  1105.  
  1106. char_word:
  1107.     db    ' char'
  1108. len_char_word    equ    $-char_word
  1109.  
  1110. ; have we reached end of usable line
  1111. ;check_eol:
  1112. ;    push    bc
  1113. ;    ld    bc,window_start+(80*4)+8+23
  1114. ;    or    a
  1115. ;    push    hl
  1116. ;    sbc    hl,bc
  1117. ;    pop    hl
  1118. ;    pop    bc
  1119. ;    ret
  1120.  
  1121.  
  1122. ; define premium cursor control keys
  1123. set_curs_key:
  1124.     call    clear_lower
  1125.     ld    hl,set_curs_1
  1126.     call    print_string
  1127. s_ck1:
  1128.     call    get_a_key
  1129.     cp    '['-40h
  1130.     jp    z,main_loop
  1131.     cp    curs_key
  1132.     jr    c,s_ck1
  1133.     cp    curs_key+10h
  1134.     jr    nc,s_ck1
  1135.  
  1136. ; key has been found
  1137. s_ck3:
  1138.     and    0Fh
  1139.     ld    hl,def_bios_start+curs_key_tab
  1140.     ld    c,a
  1141.     ld    b,0
  1142.     add    hl,bc
  1143.     push    hl
  1144.     ld    b,(hl)            ; present value
  1145.     ld    hl,set_curs_2
  1146.     call    print_string
  1147.     ld    hl,set_curs_3
  1148.     call    print_string
  1149.     ld    hl,window_start+6*80+22    ; print it
  1150.     ld    a,b
  1151.     cp    ' '
  1152.     jr    nc,s_ck8
  1153.     ld    (hl),'^'
  1154.     inc    hl
  1155.     add    a,40h
  1156. s_ck8:
  1157.     ld    (hl),a
  1158. s_ck7:
  1159.     call    get_a_key_c    ; get value to replace it with
  1160.     jr    nz,s_ck7
  1161.     cp    80h        ; don't want a 'key' above 80h
  1162.     jr    nc,s_ck7
  1163.     pop    hl
  1164.     ld    (hl),a        ; put it in table
  1165.     jr    set_curs_key    
  1166.  
  1167. time_functions:
  1168.     ld    a,(no_clock)
  1169.     or    a
  1170.     jp    nz,main_loop
  1171.     call    clear_lower
  1172.     ld    hl,time_1
  1173.     call    print_string
  1174.     ld    hl,time_2
  1175.     call    print_string
  1176.     ld    hl,time_3
  1177.     call    print_string
  1178.     ld    hl,time_4
  1179.     call    print_string
  1180.     ld    hl,time_5
  1181.     call    print_string
  1182.     ld    hl,time_6
  1183.     call    print_string
  1184. t_f1:
  1185.     ld    hl,spare_fn_str        ; space for returning time
  1186.     call    get_a_key
  1187.     cp    '['-40h
  1188.     jp    z,main_loop
  1189.     call    conv_upper
  1190.     cp    '1'
  1191.     jp    z,date_st_1
  1192.     cp    '2'
  1193.     jp    z,date_st_2
  1194.     cp    '3'
  1195.     jp    z,date_st_3
  1196.     cp    '4'
  1197.     jp    z,date_st_4
  1198.     cp    'T'
  1199.     jp    z,time_st
  1200.     cp    'S'
  1201.     jr    nz,t_f1
  1202.  
  1203. ; Set time, date
  1204.     call    clear_lower
  1205.     ld    hl,set_time_1
  1206.     call    print_string
  1207.     ld    hl,set_time_2
  1208.     call    print_string
  1209.     ld    hl,set_time_3
  1210.     call    print_string
  1211.     ld    hl,set_time_4
  1212.     call    print_string
  1213.     ld    ix,t_f_digits_info
  1214.     ld    hl,time
  1215.     ld    de,entered_time
  1216.     ld    bc,10
  1217.     ldir
  1218. s_t_1:
  1219.     push    ix
  1220.     ld    ix,entered_time
  1221.     call    s_t_dow
  1222.     jr    z,s_t_18
  1223.     call    s_t_getdays        ; if illegal then       
  1224.     dec    a            ; try max date for month
  1225.     ld    (entered_time+2),a
  1226.     call    s_t_dow
  1227.     jr    z,s_t_18
  1228.     ld    a,1            ; still illegal then
  1229.     ld    (entered_time),a    ; reset date to 1st Jan 1901
  1230.     ld    (entered_time+1),a
  1231.     ld    (entered_time+2),a
  1232.     ld    a,3            ; which is a Tuesday
  1233. s_t_18:
  1234.     ld    (entered_time+3),a
  1235.     ld    hl,window_start+(80*4)+7
  1236.     call    display_time
  1237.     pop    ix
  1238.     ld    hl,window_start+(80*5)
  1239.     call    clear_a_line
  1240.     ld    hl,window_start+(80*5)
  1241.     ld    d,0
  1242.     ld    e,(ix+0)
  1243.     add    hl,de
  1244.     ld    b,(ix+1)
  1245. s_t_3:
  1246.     ld    (hl),char_curs
  1247.     inc    hl
  1248.     djnz    s_t_3
  1249.     ld    hl,entered_time
  1250.     ld    e,(ix+4)
  1251.     add    hl,de
  1252. s_t_2:
  1253.     call    get_a_key
  1254.     call    conv_upper
  1255.     cp    'M'-40h
  1256.     jp    z,save_time
  1257.     cp    '['-40h
  1258.     jp    z,time_functions
  1259.     cp    'D'
  1260.     jp    z,save_date
  1261.     cp    'Z'-40h
  1262.     jp    z,s_t_zero_digits
  1263.     ld    bc,-6
  1264.     cp    93h            ; Left
  1265.     jp    z,s_t_move_digits
  1266.     cp    'S'-40h
  1267.     jp    z,s_t_move_digits
  1268.     ld    bc,6
  1269.     cp    96h            ; Right
  1270.     jr    z,s_t_move_digits
  1271.     cp    'D'-40h
  1272.     jr    z,s_t_move_digits
  1273.     ld    c,1
  1274.     cp    90h            ; Up
  1275.     jr    z,s_t_inc_digits
  1276.     cp    'E'-40h
  1277.     jr    z,s_t_inc_digits
  1278.     ld    c,(ix+5)
  1279.     cp    98h            ; Shift Up
  1280.     jr    z,s_t_inc_digits
  1281.     cp    'R'-40h
  1282.     jr    z,s_t_inc_digits
  1283.     cp    9Ah            ; Shift Down
  1284.     jr    z,s_t_dec_digits
  1285.     cp    'C'-40h
  1286.     jr    z,s_t_dec_digits
  1287.     ld    c,1
  1288.     cp    92h            ; Down
  1289.     jr    z,s_t_dec_digits
  1290.     cp    'X'-40h
  1291.     jr    nz,s_t_2
  1292.  
  1293. s_t_dec_digits:
  1294.     ld    a,(hl)
  1295.     sub    c
  1296.     daa
  1297.     ld    b,a
  1298.     ld    a,(ix+3)    ; maximum +1
  1299.     cp    0FFh        ; date? then get max for month
  1300.     call    z,s_t_getdays
  1301.     or    a
  1302.     ld    c,a
  1303.     ld    a,b
  1304.     jr    z,s_t_24    ; special case for years
  1305.     ld    b,(ix+2)    ; minimum limit
  1306.     cp    b
  1307.     jr    nc,s_t_8
  1308. s_t_7:
  1309.     sub    b
  1310.     daa
  1311.     add    a,c
  1312.     daa
  1313.     jr    s_t_6
  1314. s_t_8:
  1315.     cp    c
  1316.     jr    nc,s_t_7
  1317. s_t_6:
  1318.     ld    (hl),a
  1319.     jp    s_t_1
  1320. s_t_24:
  1321.     or    a
  1322.     jr    nz,s_t_6
  1323.     ld    a,99h
  1324.     jr    s_t_6
  1325.  
  1326. s_t_inc_digits:
  1327.     ld    a,(hl)
  1328.     add    a,c
  1329.     daa
  1330.     ld    b,a
  1331.     ld    a,(ix+3)
  1332.     cp    0FFh        ; is this date? then get max for month
  1333.     call    z,s_t_getdays
  1334.     or    a
  1335.     ld    c,a
  1336.     ld    a,b
  1337.     jr    z,s_t_23    ; special case for years
  1338.     cp    c
  1339.     jr    c,s_t_6
  1340.     sub    c
  1341.     daa
  1342.     add    a,(ix+2)
  1343.     daa
  1344.     jr    s_t_6
  1345. s_t_23:
  1346.     or    a
  1347.     jr    nz,s_t_6
  1348.     inc    a
  1349.     jr    s_t_6
  1350.  
  1351. s_t_zero_digits:
  1352.     ld    a,(ix+2)
  1353.     jr    s_t_6
  1354.  
  1355. s_t_move_digits:
  1356.     add    ix,bc
  1357.     push    ix
  1358.     pop    hl
  1359.     ld    d,h
  1360.     ld    e,l
  1361.     ld    bc,t_f_digits_info
  1362.     xor    a
  1363.     sbc    hl,bc
  1364.     jr    c,s_t_m_left
  1365.     ld    h,d
  1366.     ld    l,e
  1367.     ld    bc,t_f_digits_end
  1368.     sbc    hl,bc
  1369.     jp    c,s_t_1
  1370. ; too far to right
  1371.     ld    ix,t_f_digits_info
  1372.     jp    s_t_1
  1373. ; too far to left
  1374. s_t_m_left:
  1375.     ld    ix,t_f_digits_end-6
  1376.     jp    s_t_1
  1377.  
  1378. save_time:
  1379.     ld    b,10        ; 10 regs
  1380. s_t_9:
  1381.     ld    de,put_rtc
  1382.     call    get_address
  1383.     ld    (call_p_rtc+1),hl
  1384.     ld    hl,entered_time
  1385.     ld    e,0        ; read from reg 0
  1386. call_p_rtc:
  1387.     call    0
  1388.     jp    time_functions
  1389.  
  1390. ; only change date, leave time unaltered
  1391. save_date:
  1392.     ld    b,4        ; 4 regs only
  1393.     jr    s_t_9
  1394.  
  1395.  
  1396. ; Return in A day of week of date (1 = SUN)
  1397. ; also returns nz if illegal
  1398. ; destroys - BC, DE, HL
  1399. s_t_dow:    
  1400. ;    push    de
  1401. ;    push    hl
  1402.     ld    hl,2-1        ; 1st Jan 1901 = Tuesday but sub 1 extra
  1403.     ld    a,(ix+0)    ; year
  1404.     or    a
  1405.     jr    z,s_t_d_err
  1406.     call    conv_bin
  1407.     dec    a
  1408.     ld    c,a
  1409.     ld    b,0
  1410.     add    hl,bc        ; one extra day per year
  1411.     xor    a
  1412.     srl    c        ; leap years
  1413.     rra
  1414.     srl    c
  1415.     rra
  1416.     add    hl,bc        ; and one more for each completed leap year
  1417.     cp    0C0h        ; is this a leap year ?
  1418.     ld    a,(ix+1)    ; months
  1419.     jr    nz,s_t_21
  1420.     cp    3        ; and after Feb ?
  1421.     jr    c,s_t_21
  1422.     inc    hl        ; then add 1 to day
  1423. s_t_21:
  1424.     call    conv_bin
  1425.     dec    a        ; month 0..11
  1426.     cp    12
  1427.     jr    nc,s_t_d_err
  1428.     or    a
  1429.     jr    z,s_t_19
  1430.     ld    de,days_in_month
  1431. s_t_20:                ; count number of days in completed month
  1432.     push    af
  1433.     ld    a,(de)
  1434.     call    conv_bin
  1435.     dec    a
  1436.     ld    c,a
  1437.     add    hl,bc
  1438.     pop    af
  1439.     inc    de
  1440.     dec    a
  1441.     jr    nz,s_t_20
  1442. s_t_19:
  1443.     ld    a,(ix+2)    ; date
  1444.     or    a
  1445.     jr    z,s_t_d_err
  1446.     ld    c,a
  1447.     call    s_t_getdays
  1448.     dec    a        ; max for month
  1449.     cp    c
  1450.     jr    c,s_t_d_err    ; illegal if max<date
  1451.     ld    a,c
  1452.     call    conv_bin
  1453.     ld    c,a
  1454.     add    hl,bc
  1455. ;    xor    a        ; clear carry, but add hl,bc does it
  1456.     ld    c,7        ; MOD 7
  1457. s_t_22:
  1458.     sbc    hl,bc
  1459.     jr    nc,s_t_22
  1460.     ld    a,l        ; now -7..-1
  1461.     add    a,c        ; now 0..6
  1462.     inc    a        ; now 1..7
  1463.     cp    a        ; makes Z - legal date
  1464. ;    pop    hl
  1465. ;    pop    de
  1466.     ret
  1467. s_t_d_err:
  1468.     or    0FFh        ; makes NZ - illegal date
  1469.     ret
  1470.  
  1471. ; Return in A days+1 in month
  1472. s_t_getdays:    
  1473.     push    bc
  1474.     push    hl
  1475.     ld    hl,days_in_month-1
  1476.     ld    a,(entered_time+1)    ; get month
  1477.     call    conv_bin
  1478.     ld    c,a
  1479.     ld    b,0
  1480.     add    hl,bc
  1481.     ld    a,c
  1482.     cp    2
  1483.     ld    a,(hl)            ; get days in month
  1484.     jr    nz,s_t_14
  1485. ; February :
  1486.     ld    c,a
  1487.     ld    a,(entered_time)    ; get year
  1488.     and    3            ; see if leap year
  1489.     ld    a,c
  1490.     jr    nz,s_t_14
  1491.     inc    a            ; inc for leap year
  1492. s_t_14:
  1493.     pop    hl
  1494.     pop    bc
  1495.     ret
  1496.  
  1497. days_in_month:
  1498. ;    actually days+1 (BCD) for compatability with checking code
  1499. ;    db    Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
  1500. ;    db     31,  28,  31,  30,  31,  30,  31,  31,  30,  31,  30,  31
  1501.     db    32h, 29h, 32h, 31h, 32h, 31h, 32h, 32h, 31h, 32h, 31h, 32h
  1502.  
  1503. t_f_digits_info:
  1504. ;    db    pos. of digits, num. of digits, min., max.+1 (BCD), reg., incr
  1505.     db     7, 2, 0, 24h, 4, 12    ; hour
  1506.     db    10, 2, 0, 60h, 5, 10    ; min
  1507.     db    13, 2, 0, 60h, 6, 10    ; sec
  1508. ;    db    19, 3, 1, 08h, 3,  0    ; day -- will be handled by DOW code
  1509.     db    24, 2, 1,0FFh, 2, 10    ; date -- FFh -> depends on month
  1510.     db    27, 3, 1, 13h, 1,  6    ; month
  1511.     db    31, 2, 1, 00h, 0, 10    ; year
  1512.  
  1513. t_f_digits_end    equ    $
  1514.  
  1515. date_st_1:
  1516.     call    d_s_pr_date
  1517.     ld    (hl),' '
  1518.     inc    hl
  1519.     call    d_s_pr_month
  1520. d_s_1:
  1521.     ex    de,hl            ; print ', 19'
  1522.     ld    hl,d_s_year
  1523.     ld    bc,len_d_s_year
  1524.     ldir
  1525.     ex    de,hl
  1526.     ld    a,(time)        ; year
  1527.     call    print_bcd
  1528. do_time_fn:
  1529.     ld    (hl),fn_str_end
  1530.     ld    a,-1            ; spare function number
  1531.     jp    do_fn_a
  1532.  
  1533. date_st_2:
  1534.     call    d_s_pr_month
  1535.     ld    (hl),' '
  1536.     inc    hl
  1537.     call    d_s_pr_date
  1538.     jr    d_s_1
  1539.  
  1540. d_s_year:
  1541.     db    ', 19'
  1542. len_d_s_year    equ    $-d_s_year
  1543.  
  1544. d_s_pr_date:
  1545.     ld    a,(time+2)        ; date
  1546.     ld    c,a
  1547.     call    print_bcd_1
  1548.     ld    de,'t'*256+'h'        ; 4th etc
  1549.     ld    a,0F0h
  1550.     and    c
  1551.     cp    10h            ; skip 11th, 12th etc.
  1552.     jr    z,d_s_2
  1553.     ld    a,0Fh
  1554.     and    c
  1555.     cp    1
  1556.     jr    nz,d_s_3
  1557.     ld    de,'s'*256+'t'        ; 1st etc
  1558.     jr    d_s_2
  1559. d_s_3:
  1560.     cp    2
  1561.     jr    nz,d_s_4
  1562.     ld    de,'n'*256+'d'        ; 2nd etc
  1563.     jr    d_s_2
  1564. d_s_4:
  1565.     cp    3
  1566.     jr    nz,d_s_2
  1567.     ld    de,'r'*256+'d'        ;3rd etc
  1568. d_s_2:
  1569.     ld    (hl),d
  1570.     inc    hl
  1571.     ld    (hl),e
  1572.     inc    hl
  1573.     ret
  1574.  
  1575. d_s_pr_month:
  1576.     ex    de,hl
  1577.     ld    hl,month_1
  1578.     ld    a,(time+1)        ; month
  1579.     call    conv_bin
  1580.     dec    a
  1581.     ld    c,a            ; *3
  1582.     add    a,c
  1583.     add    a,c
  1584.     ld    c,a
  1585.     ld    b,0
  1586.     add    hl,bc
  1587.     ld    bc,3
  1588.     ldir
  1589.     ex    de,hl
  1590.     ld    a,(time+1)
  1591.     cp    5
  1592.     ret    z            ; if not May then add '.'
  1593.     ld    (hl),'.'
  1594.     inc    hl
  1595.     ret
  1596.  
  1597. ; date 16/1/86
  1598. date_st_3:
  1599.     ld    a,(time+2)
  1600.     call    print_bcd_1
  1601.     ld    (hl),'/'
  1602.     inc    hl
  1603.     ld    a,(time+1)
  1604. d_s_3_1:
  1605.     call    print_bcd_1
  1606.     ld    (hl),'/'
  1607.     inc    hl
  1608.     ld    a,(time+0)
  1609.     call    print_bcd
  1610.     jp    do_time_fn
  1611.  
  1612. ; date 1/16/86 - American (yuk) format
  1613. date_st_4:
  1614.     ld    a,(time+1)
  1615.     call    print_bcd_1
  1616.     ld    (hl),'/'
  1617.     inc    hl
  1618.     ld    a,(time+2)
  1619.     jr    d_s_3_1
  1620.  
  1621. time_st:
  1622.     ld    c,'A'
  1623.     ld    a,(time+4)    ; hours
  1624.     or    a
  1625.     jr    nz,t_s_1
  1626.     ld    a,12h        ; 12 AM (midnight)
  1627. t_s_1:
  1628.     cp    13h
  1629.     jr    c,t_s_2
  1630.     sub    12h        ; 1..11 PM
  1631.     daa
  1632.     ld    c,'P'
  1633. t_s_2:
  1634.     cp    12h
  1635.     jr    nz,t_s_5
  1636.     ld    c,'P'        ; 12 PM (midday)
  1637. t_s_5:
  1638.     call    print_bcd_1
  1639.     ld    (hl),':'
  1640.     inc    hl
  1641.     ld    a,(time+5)    ; minutes
  1642.     call    print_bcd
  1643.     ld    (hl),' '
  1644.     inc    hl
  1645.     ld    (hl),c        ; A or P
  1646.     inc    hl
  1647.     ld    (hl),'M'
  1648.     inc    hl
  1649.     jp    do_time_fn
  1650.  
  1651.  
  1652. screen_functions:
  1653.     call    clear_lower
  1654.     ld    hl,screen_1
  1655.     call    print_string
  1656.     ld    hl,screen_2
  1657.     call    print_string
  1658.     ld    hl,screen_3
  1659.     call    print_string
  1660.     ld    hl,screen_4
  1661.     call    print_string
  1662.     ld    hl,screen_5
  1663.     call    print_string
  1664.     ld    hl,screen_6
  1665.     call    print_string
  1666.     ld    hl,screen_7
  1667.     call    print_string
  1668.     ld    a,(def_bios_start+is_premium)
  1669.     ld    ix,premium_col_masks
  1670.     or    a
  1671.     jr    nz,sc_f_1
  1672.     ld    ix,standard_col_masks
  1673. sc_f_1:
  1674.     call    get_a_key
  1675.     cp    '['-40h
  1676.     jp    z,main_loop
  1677.     ld    b,a
  1678.     ld    a,(colour_fitted)
  1679.     or    a
  1680.     ld    a,b
  1681.     jr    z,sc_f_5
  1682.     ld    hl,def_bios_start+caps_lock
  1683.     bit    0,(hl)
  1684.     jr    z,sc_f_12
  1685. ; caps lock is on
  1686.     xor    'a'-'A'        ; removes effect of caps lock
  1687. sc_f_12:
  1688.     ld    c,false        ; 'increment'
  1689.     cp    'a'        ; if upper case then shift is pressed
  1690.     jr    nc,sc_f_11
  1691.     ld    c,true        ; 'decrement' flag
  1692. sc_f_11:
  1693.     call    conv_upper
  1694.     cp    'F'
  1695.     jp    z,sc_f_fore
  1696.     cp    'B'
  1697.     jp    z,sc_f_back
  1698.     cp    'C'
  1699.     jp    z,sc_f_w_fore
  1700.     cp    'V'
  1701.     jp    z,sc_f_w_back
  1702. sc_f_5:
  1703.     call    conv_upper
  1704.     cp    'L'
  1705.     jp    z,sc_f_w_toggle
  1706.     ld    bc,7*256+1        ; up
  1707.     cp    90h
  1708.     jr    z,sc_f_move
  1709.     cp    'E'-40h
  1710.     jr    z,sc_f_move
  1711.     ld    bc,7*256+255        ; down
  1712.     cp    92h
  1713.     jr    z,sc_f_move
  1714.     cp    'X'-40h
  1715.     jr    z,sc_f_move
  1716.     ld    bc,2*256+1        ; left
  1717.     cp    93h
  1718.     jr    z,sc_f_move
  1719.     cp    'S'-40h
  1720.     jr    z,sc_f_move
  1721.     ld    bc,2*256+255        ; right
  1722.     cp    96h
  1723.     jr    z,sc_f_move
  1724.     cp    'D'-40h
  1725.     jr    nz,sc_f_1
  1726.  
  1727.  
  1728. sc_f_move:
  1729.     ld    hl,def_bios_start
  1730.     ld    a,34h
  1731.     add    a,b
  1732.     ld    e,a
  1733.     ld    d,0
  1734.     add    hl,de
  1735.     ld    a,(hl)
  1736.     add    a,c
  1737.     ld    (hl),a
  1738.     ld    c,a
  1739.     ld    a,b
  1740.     out    (12),a
  1741.     ld    a,c
  1742.     out    (13),a
  1743.     jp    sc_f_1
  1744.  
  1745. sc_f_fore:
  1746.     ld    a,c        ; true to decrement
  1747.     ld    hl,def_bios_start+screen_colour
  1748.     ld    b,(hl)
  1749.     ld    c,b
  1750.     inc    c        ; increment
  1751.     or    a
  1752.     jr    z,sc_f_3
  1753.     dec    c        ; no actually decrement
  1754.     dec    c
  1755. sc_f_3:
  1756.     ld    a,(ix+0)    ; 0Fh / 1Fh
  1757.     and    c
  1758.     ld    c,a
  1759.     ld    a,(ix+1)    ; 0F0h / 0E0h
  1760. sc_f_2:
  1761.     and    b
  1762.     add    a,c
  1763.     ld    (hl),a
  1764.     ld    c,a
  1765.     ld    a,40h
  1766.     out    (8),a
  1767.     ld    hl,8800h
  1768.     ld    (hl),c
  1769.     ld    de,8801h
  1770.     ld    bc,24*80-1
  1771.     ldir
  1772.     call    window_colour
  1773.     jp    sc_f_1
  1774.  
  1775. sc_f_back:
  1776.     ld    hl,def_bios_start+screen_colour
  1777.     ld    b,(hl)
  1778.     ld    a,b
  1779.     ld    d,(ix+2)    ; 10h / 20h
  1780.     add    a,d        ; increment
  1781.     bit    0,c        ; true to decrement
  1782.     jr    z,sc_f_4
  1783.     sub    d        ; no actually decrement
  1784.     sub    d
  1785. sc_f_4:
  1786.     and    (ix+1)
  1787.     ld    c,a
  1788.     ld    a,(ix+0)    ; 0Fh, 1Fh
  1789.     jr    sc_f_2
  1790.  
  1791. sc_f_w_fore:
  1792.     ld    a,c        ; true to decrement
  1793.     ld    hl,def_bios_start+status_colour
  1794.     ld    b,(hl)
  1795.     ld    c,b
  1796.     inc    c        ; increment
  1797.     or    a
  1798.     jr    z,sc_f_6
  1799.     dec    c        ; no actually decrement
  1800.     dec    c
  1801. sc_f_6:
  1802.     ld    a,(ix+0)
  1803.     and    c
  1804.     ld    c,a
  1805.     ld    a,(ix+1)
  1806. sc_f_7:
  1807.     and    b
  1808.     add    a,c
  1809.     ld    (hl),a
  1810.     ld    c,a
  1811.     ld    a,40h
  1812.     out    (8),a
  1813.     ld    hl,8800h+24*80
  1814.     ld    (hl),c
  1815.     ld    a,c
  1816.     ld    de,8801h+24*80
  1817.     ld    bc,80-1
  1818.     ldir
  1819.     ld    b,num_lines
  1820.     ld    hl,window_start+800h
  1821.     ld    de,80-num_cols
  1822. sc_f_10:
  1823.     push    bc
  1824.     ld    b,num_cols
  1825. sc_f_9:
  1826.     ld    (hl),a
  1827.     inc    hl
  1828.     djnz    sc_f_9
  1829.     add    hl,de
  1830.     pop    bc
  1831.     djnz    sc_f_10
  1832.     xor    a
  1833.     out    (8),a
  1834.     jp    sc_f_1
  1835.  
  1836. sc_f_w_back:
  1837.     ld    hl,def_bios_start+status_colour
  1838.     ld    b,(hl)
  1839.     ld    a,b
  1840.     ld    d,(ix+2)    ; 10h / 20h
  1841.     add    a,d        ; increment
  1842.     bit    0,c        ; true to decrement
  1843.     jr    z,sc_f_8
  1844.     sub    d        ; no actually decrement
  1845.     sub    d
  1846. sc_f_8:
  1847.     and    (ix+1)
  1848.     ld    c,a
  1849.     ld    a,(ix+0)
  1850.     jr    sc_f_7
  1851.  
  1852. sc_f_w_toggle:
  1853.     ld    hl,def_bios_start+3Ah
  1854.     ld    a,(hl)
  1855.     xor    1
  1856.     ld    (hl),a
  1857.     ld    b,a
  1858.     ld    a,6
  1859.     out    (12),a
  1860.     ld    a,b
  1861.     out    (13),a
  1862.     jp    sc_f_1
  1863.  
  1864. premium_col_masks:
  1865.     db    0Fh,0F0h,10h
  1866. standard_col_masks:
  1867.     db    1Fh,0E0h,20h
  1868.  
  1869. ;    
  1870. ; start of house keeping routines etc.
  1871. ;
  1872.  
  1873. ; convert BCD to binary for calculations
  1874. conv_bin:
  1875.     push    bc
  1876.     ld    b,a
  1877.     and    0Fh
  1878.     ld    c,a
  1879.     ld    a,b
  1880.     and    0F0h
  1881.     rra
  1882.     rra
  1883.     rra
  1884.     rra
  1885.     ld    b,a
  1886.     ld    a,c
  1887.     jr    z,c_b_2
  1888.     ld    c,10
  1889. c_b_1:
  1890.     add    a,c
  1891.     djnz    c_b_1
  1892. c_b_2:
  1893.     pop    bc
  1894.     ret
  1895.  
  1896. ; get address contained at (bios_start+DE)
  1897. get_address:
  1898.     ld    hl,def_bios_start
  1899.     add    hl,de
  1900.     ld    e,(hl)
  1901.     inc    hl
  1902.     ld    h,(hl)
  1903.     ld    l,e
  1904.     ret
  1905.  
  1906. ; get a key from keyboard (bypasses function keys)
  1907. ; also updates clock display
  1908. ; returns Z if key pressed
  1909. get_a_key:
  1910.     push    hl
  1911.     push    de
  1912.     call    get_key_1
  1913.     pop    de
  1914.     pop    hl
  1915.     ret
  1916.  
  1917. ; as above but convert cursor code to control code, ignore window key etc.
  1918. get_a_key_c:
  1919.     push    hl
  1920.     push    de
  1921.     call    get_key_1
  1922.     jr    nz,g_k_1
  1923.     cp    fn_key_1_us
  1924.     jr    nc,got_a_key
  1925.     cp    window_key
  1926.     jr    nc,not_a_key
  1927.     cp    curs_key
  1928.     jr    c,got_a_key
  1929. ;    cp    curs_key+16
  1930. ;    jr    nc,got_a_key
  1931.     and    0Fh
  1932.     ld    hl,def_bios_start+curs_key_tab
  1933.     ld    e,a
  1934.     ld    d,0
  1935.     add    hl,de
  1936.     ld    a,(hl)
  1937. got_a_key:
  1938.     cp    a
  1939.     jr    g_k_1
  1940. not_a_key:
  1941.     or    -1
  1942. g_k_1:
  1943.     pop    de
  1944.     pop    hl
  1945.     ret
  1946.  
  1947. get_key_1:
  1948.     push    ix
  1949.     push    bc
  1950.     ld    a,(def_bios_start+status_on)
  1951.     cp    25
  1952.     call    z,print_s_line
  1953.     call    read_time
  1954.     ld    ix,time
  1955.     ld    hl,window_start+(80*2)+7
  1956.     call    z,display_time
  1957.     ld    de,get_char
  1958.     call    get_address
  1959.     ld    (call_kbd_i+1),hl
  1960. call_kbd_i:
  1961.     call    0
  1962.     pop    bc
  1963.     pop    ix
  1964.     ret
  1965.  
  1966. ; convert char in A to upper case
  1967. conv_upper:
  1968.     cp    'a'
  1969.     ret    c
  1970.     cp    'z'+1
  1971.     ret    nc    
  1972.     sub    'a'-'A'
  1973.     ret
  1974.  
  1975. ; read time from RTC and return z if changed from last time
  1976. read_time:
  1977. ; but first, is it there ?
  1978.     ld    a,(no_clock)
  1979.     or    a
  1980.     ret    nz    ; no it wasn't there - make sure no display occurs
  1981.     ld    de,get_rtc
  1982.     call    get_address
  1983.     ld    (c_r1+1),hl
  1984.     ld    hl,new_time
  1985.     ld    e,0        ; read from reg 0
  1986.     ld    b,10        ; 10 regs
  1987. c_r1:
  1988.     call    0
  1989. ; update main time regs and check if any change has occurred
  1990.     ld    bc,10*256    ; b with 10, c with false
  1991.     ld    de,new_time
  1992.     ld    hl,time
  1993. r_t1:
  1994.     ld    a,(de)
  1995.     cp    (hl)
  1996.     ld    (hl),a
  1997.     jr    z,r_t2
  1998.     ld    c,true        ; a value has changed
  1999. r_t2:
  2000.     inc    de
  2001.     inc    hl
  2002.     djnz    r_t1
  2003.     ld    a,true
  2004.     cp    c        ; z if changed
  2005.     ret
  2006.  
  2007. ; print time from (ix) to (hl)
  2008. display_time:
  2009.     ld    a,(ix+4)    ; hours
  2010.     ld    c,'P'
  2011.     sub    12h
  2012.     daa
  2013.     jr    nc,dt_1
  2014.     add    a,12h
  2015.     daa
  2016.     ld    c,'A'
  2017. dt_1:
  2018.     or    a
  2019.     jr    nz,dt_2
  2020.     ld    a,12h
  2021. dt_2:
  2022.     cp    10h
  2023.     jr    nc,dt_3
  2024.     ld    (hl),' '
  2025.     inc    hl
  2026. dt_3:
  2027.     call    print_bcd_1
  2028.     ld    (hl),':'
  2029.     inc    hl
  2030.     ld    a,(ix+5)    ; min
  2031.     call    print_bcd
  2032.     ld    (hl),':'
  2033.     inc    hl
  2034.     ld    a,(ix+6)    ; sec
  2035.     call    print_bcd
  2036.     inc    hl
  2037.     ld    (hl),c
  2038.     inc    hl
  2039.     ld    (hl),'M'
  2040.     inc    hl
  2041.     inc    hl
  2042.     ld    c,(ix+3)    ; day
  2043.     dec    c
  2044.     ld    a,c
  2045.     add    a,c        ; *2
  2046.     add    a,c        ; *3
  2047.     ld    c,a
  2048.     ld    b,0
  2049.     ex    de,hl
  2050.     ld    hl,day_1    ; --> day name
  2051.     add    hl,bc
  2052.     ld    c,3
  2053.     ldir
  2054.     ex    de,hl
  2055.     ld    (hl),','
  2056.     inc    hl
  2057.     inc    hl
  2058.     ld    a,(ix+2)    ; date
  2059.     call    print_bcd
  2060.     ld    (hl),'-'
  2061.     inc    hl
  2062.     ld    a,(ix+1)    ; month
  2063.     call    conv_bin
  2064.     dec    a
  2065.     ld    c,a
  2066.     add    a,a        ; *2
  2067.     add    a,c        ; *3
  2068.     ld    c,a
  2069.     ex    de,hl
  2070.     ld    hl,month_1
  2071.     add    hl,bc
  2072.     ld    c,3
  2073.     ldir
  2074.     ex    de,hl
  2075.     ld    (hl),'-'
  2076.     inc    hl
  2077.     ld    a,(ix+0)    ; year
  2078.     call    print_bcd
  2079.     ret
  2080.  
  2081. ; print bcd num in a to (hl)
  2082. print_bcd:
  2083.     push    de
  2084.     ld    e,a
  2085.     rra
  2086.     rra
  2087.     rra
  2088.     rra
  2089.     and    0Fh
  2090.     add    a,'0'
  2091.     ld    (hl),a
  2092.     inc    hl
  2093.     ld    a,e
  2094.     and    0Fh
  2095.     add    a,'0'
  2096.     ld    (hl),a
  2097.     inc    hl
  2098.     pop    de
  2099.     ret
  2100.  
  2101. ; print bcd with leading zero blanking
  2102. print_bcd_1:
  2103.     cp    10h
  2104.     jr    nc,print_bcd
  2105.     add    a,'0'
  2106.     ld    (hl),a
  2107.     inc    hl
  2108.     ret
  2109.  
  2110. ; subroutine to check for premium, colour and clock
  2111. do_checks:
  2112. ; standard BIOS location has is_premium flag
  2113.     ld    ix,def_bios_start+is_premium
  2114.     bit    0,(ix)
  2115.     jr    z,d_c_1
  2116. ; is premium so get old value of vml and must have colour
  2117.     in    a,(vml)        ; premium - VML latch, standard - same as 0Ch
  2118.     ld    (old_vml),a
  2119.     ld    a,true
  2120.     ld    (colour_fitted),a
  2121.     jr    d_c_2
  2122. ; now check for colour
  2123. d_c_1:
  2124.     ld    hl,8800h
  2125.     ld    b,(hl)
  2126.     ld    a,40h
  2127.     out    (8),a
  2128.     ld    c,(hl)
  2129.     ld    a,b
  2130.     cpl
  2131.     ld    d,a
  2132.     ld    (hl),a
  2133.     xor    a
  2134.     out    (8),a
  2135.     ld    a,(hl)
  2136.     cp    d
  2137.     ld    a,false
  2138.     jr    z,no_colour
  2139.     ld    a,true
  2140. no_colour:
  2141.     ld    (colour_fitted),a
  2142.     ld    (hl),b
  2143.     ld    a,40h
  2144.     out    (8),a
  2145.     ld    (hl),c
  2146.     xor    a
  2147.     out    (8),a
  2148. d_c_2:
  2149. ; now check for clock
  2150.     ld    c,7
  2151.     ld    a,14
  2152.     out    (4),a
  2153.     in    b,(c)
  2154.     ld    a,14
  2155.     out    (4),a
  2156.     ld    a,85
  2157.     out    (6),a
  2158.     ld    a,14
  2159.     out    (4),a
  2160.     in    d,(c)
  2161.     ld    a,14
  2162.     out    (4),a
  2163.     ld    a,b
  2164.     out    (6),a
  2165.     ld    a,d
  2166.     sub    85
  2167.     ld    (no_clock),a    ; nz if no rtc present
  2168.     ret
  2169.  
  2170. ; save contents of screen, PCG, colour and attribute RAM as necessary
  2171. ; and set up for window
  2172. save_screen:
  2173. ; colour first
  2174.     ld    a,(colour_fitted)
  2175.     or    a
  2176.     jr    z,s_sc8
  2177.     call    window_colour
  2178. s_sc8:
  2179. ; now attribute
  2180.     bit    0,(ix)
  2181.     jr    z,s_sc9
  2182.     ld    a,90h
  2183.     out    (vml),a
  2184.     ld    a,window_attr
  2185.     ld    hl,window_start
  2186.     ld    de,temp_attr
  2187.     call    save_block
  2188.     ld    a,80h
  2189.     out    (vml),a
  2190. s_sc9:
  2191. ; now screen
  2192.     ld    hl,window_start
  2193.     ld    de,temp_screen
  2194.     ld    a,' '
  2195.     call    save_block
  2196. ; now inverse
  2197.     bit    0,(ix)
  2198.     jr    z,s_sc10
  2199.     ld    a,80h+(window_attr and 0Fh)    ; select PCG 1 if premium
  2200.     out    (vml),a
  2201. s_sc10:
  2202.     ld    hl,first_char
  2203.     ld    de,temp_inverse
  2204.     ld    bc,num_pcg*16
  2205.     ldir
  2206.     ld    hl,inv_chars
  2207.     ld    de,first_char
  2208.     ld    bc,num_pcg*16
  2209.     ldir
  2210. ; now set up window on screen
  2211.     ld    hl,window_start
  2212.     ld    de,80-num_cols+1
  2213.     ld    (hl),' '
  2214.     inc    hl
  2215.     ld    (hl),char_tl
  2216.     inc    hl
  2217.     ld    b,num_cols-4
  2218. s_sc1:
  2219.     ld    (hl),char_t
  2220.     inc    hl
  2221.     djnz    s_sc1
  2222.     ld    (hl),char_tr
  2223.     inc    hl
  2224.     ld    (hl),' '
  2225.     add    hl,de
  2226.     call    clear_a_line
  2227.     call    clear_a_line
  2228.     ld    (hl),' '
  2229.     inc    hl
  2230.     ld    (hl),char_lm
  2231.     inc    hl
  2232.     ld    b,num_cols-4
  2233. s_sc2:
  2234.     ld    (hl),char_t
  2235.     inc    hl
  2236.     djnz    s_sc2
  2237.     ld    (hl),char_rm
  2238.     inc    hl
  2239.     ld    (hl),' '
  2240.     add    hl,de
  2241.     ld    bc,80*(num_lines-6)
  2242.     add    hl,bc
  2243.     call    clear_a_line
  2244.     ld    (hl),' '
  2245.     inc    hl
  2246.     ld    (hl),char_bl
  2247.     inc    hl
  2248.     ld    b,num_cols-4
  2249. s_sc4:
  2250.     ld    (hl),char_t
  2251.     inc    hl
  2252.     djnz    s_sc4
  2253.     ld    (hl),char_br
  2254.     inc    hl
  2255.     ld    (hl),' '
  2256.     ld    hl,top_line
  2257.     call    print_string
  2258.     ld    hl,esc_exit_1
  2259.     call    print_string
  2260.     ret
  2261.  
  2262. window_colour:
  2263.     ld    hl,def_bios_start+228h
  2264.     ld    c,(hl)
  2265.     ld    a,40h
  2266.     out    (8),a
  2267.     ld    a,c
  2268.     ld    hl,window_start+800h
  2269.     ld    de,temp_col
  2270.     call    save_block
  2271.     xor    a
  2272.     out    (8),a
  2273.     ret
  2274.  
  2275. ; save screen section from any bank of RAM
  2276. ; and fill with value in A
  2277. save_block:
  2278.     ld    b,num_lines
  2279. s_b2:
  2280.     push    bc
  2281.     ld    bc,num_cols
  2282.     push    hl
  2283.     ldir
  2284.     pop    hl
  2285.     ld    b,num_cols
  2286. s_b1:
  2287.     ld    (hl),a
  2288.     inc    hl
  2289.     djnz    s_b1
  2290.     ld    c,80-num_cols
  2291.     add    hl,bc
  2292.     pop    bc
  2293.     djnz    s_b2
  2294.     ret
  2295.  
  2296. ; restore screen, colour, attribute and inverse
  2297. restore_screen:
  2298. ; colour..
  2299.     ld    a,(colour_fitted)
  2300.     or    a
  2301.     jr    z,r_sc1
  2302.     ld    a,40h
  2303.     out    (8),a
  2304.     ld    hl,temp_col
  2305.     ld    de,window_start+800h
  2306.     call    restore_block
  2307.     xor    a
  2308.     out    (8),a
  2309. r_sc1:
  2310. ; screen..
  2311.     ld    hl,temp_screen
  2312.     ld    de,window_start
  2313.     call    restore_block
  2314. ; inverse..
  2315.     ld    hl,temp_inverse
  2316.     ld    de,first_char
  2317.     ld    bc,num_pcg*16
  2318.     ldir
  2319. ; attribute..
  2320.     ld    a,(def_bios_start+is_premium)
  2321.     or    a
  2322.     ret    z
  2323.     ld    a,90h
  2324.     out    (vml),a
  2325.     ld    hl,temp_attr
  2326.     ld    de,window_start
  2327.     call    restore_block
  2328.     ld    a,(old_vml)
  2329.     out    (vml),a
  2330.     ret
  2331.  
  2332. restore_block:
  2333.     ld    b,num_lines
  2334. r_b1:
  2335.     push    bc
  2336.     ld    bc,num_cols
  2337.     ldir
  2338.     ld    c,80-num_cols
  2339.     ex    de,hl
  2340.     add    hl,bc
  2341.     ex    de,hl
  2342.     pop    bc
  2343.     djnz    r_b1
  2344.     ret
  2345.  
  2346.  
  2347. clear_lower:
  2348.     ld    hl,window_start+(80*4)
  2349.     ld    b,num_lines-6
  2350. cl_low1:
  2351.     call    clear_a_line
  2352.     djnz    cl_low1
  2353.     ret
  2354.  
  2355. clear_p_lower:
  2356.     ld    hl,window_start+(80*5)
  2357.     ld    b,num_lines-7
  2358.     jr    cl_low1
  2359.  
  2360. clear_a_line:
  2361.     push    bc
  2362.     ld    (hl),' '
  2363.     inc    hl
  2364.     ld    (hl),char_l
  2365.     inc    hl
  2366.     ld    b,num_cols-4
  2367. cl_line1:
  2368.     ld    (hl),' '
  2369.     inc    hl
  2370.     djnz    cl_line1
  2371.     ld    (hl),char_l
  2372.     inc    hl
  2373.     ld    (hl),' '
  2374.     ld    de,80-num_cols+1
  2375.     add    hl,de
  2376.     pop    bc
  2377.     ret
  2378.  
  2379. clear_screen:
  2380.     ld    hl,8000h
  2381.     ld    de,8001h
  2382.     ld    bc,7FEh
  2383.     ld    (hl),' '
  2384.     ldir
  2385.     ld    a,(is_premium)
  2386.     or    a
  2387.     jr    z,cl_s1
  2388.     xor    a
  2389.     out    (vml),a
  2390. cl_s1:
  2391. ; must set cursor address to 8000h
  2392.     ld    hl,def_bios_start+286h
  2393.     ld    (hl),0
  2394.     inc    hl
  2395.     ld    (hl),0
  2396.     inc    hl
  2397.     ld    (hl),0
  2398.     inc    hl
  2399.     ld    (hl),80h
  2400.     ret
  2401.  
  2402. ; print string pointed to by HL, starts with screen address, ends with 0FFh
  2403. print_string:
  2404.     push    de
  2405.     ld    e,(hl)
  2406.     inc    hl
  2407.     ld    d,(hl)
  2408.     inc    hl
  2409. prt_st1:
  2410.     ld    a,(hl)
  2411.     cp    0FFh
  2412.     jr    z,prt_exit
  2413.     ld    (de),a
  2414.     inc    hl
  2415.     inc    de
  2416.     jr    prt_st1
  2417. prt_exit:
  2418.     pop    de
  2419.     ret
  2420.  
  2421.  
  2422. top_line:
  2423.     dw    window_start+80+((40-(t_l2-t_l1))/2)
  2424. t_l1:    db    'SYSTEM SETUP WINDOW'
  2425. t_l2:    db    255
  2426.  
  2427. esc_exit_1:
  2428.     dw    window_start+(80*(num_lines-2))+5
  2429.     db    '<ESC> to exit.',255
  2430. main_menu_3:
  2431.     dw    window_start+(80*9)+5
  2432.     db    '<W> to Warm Boot,',255
  2433. main_menu_4:
  2434.     dw    window_start+(80*4)+5
  2435.     db    '<F> to set Function Keys,',255
  2436. main_menu_5:
  2437.     dw    window_start+(80*5)+5
  2438.     db    '<C> to set Cursor Keys,',255
  2439. main_menu_6:
  2440.     dw    window_start+(80*6)+5
  2441.     db    '<K> to set Key Click,',255
  2442. main_menu_7:
  2443.     dw    window_start+(80*8)+5
  2444.     db    '<T> for Clock Functions,',255
  2445. main_menu_8:
  2446.     dw    window_start+(80*7)+5
  2447.     db    '<S> for Screen Functions,',255
  2448. main_menu_9:
  2449.     dw    window_start+(80*10)+5
  2450.     db    '<M> for Miscellaneous.',255
  2451.  
  2452. day_1:    
  2453.     db    'SunMonTueWedThuFriSat'
  2454. month_1:
  2455.     db    'JanFebMarAprMayJunJulAugSepOctNovDec'
  2456.  
  2457. misc_fn_1:
  2458.     dw    window_start+(80*4)+5
  2459.     db    '<F> for Fast CPU (6.75 MHz),',255
  2460. misc_fn_2:
  2461.     dw    window_start+(80*5)+5
  2462.     db    '<S> for Slow CPU (3.375 MHz).',255
  2463.  
  2464. click_1:
  2465.     dw    window_start+(80*4)+5
  2466.     db    '1..9 to set click pitch,',255
  2467. click_2:
  2468.     dw    window_start+(80*5)+5
  2469.     db    '<L> 0..9 to set length.',255
  2470.  
  2471. click_tones:
  2472.     db    11,15,23,33,51,75,111,171,255    ; Odd
  2473. click_lengths:
  2474.     db    0,1,3,5,7,11,15,21,31,45
  2475.  
  2476. set_fn_1:
  2477.     dw    window_start+(80*4)+5
  2478.     db    'Select function ',char_fn,'1..',char_fn,'12,',255
  2479. set_fn_2:
  2480.     dw    window_start+(80*5)+5
  2481.     db    '<O> to toggle on/off (',255
  2482. set_fn_on:
  2483.     dw    window_start+(80*5)+5+22
  2484.     db    'ON), ',255
  2485. set_fn_off:
  2486.     dw    window_start+(80*5)+5+22
  2487.     db    'OFF),',255
  2488. set_fn_3:
  2489.     dw    window_start+(80*6)+5
  2490.     db    '<N> assign numbers to ',char_fn,'1..',char_fn,'8.',255
  2491.  
  2492. fn_num_1:
  2493.     dw    window_start+(80*8)+5
  2494.     db    'Erases ',char_fn,'1..',char_fn,'8 !! Sure ?',255
  2495.  
  2496. ent_str_1:
  2497.     dw    window_start+(80*6)+5
  2498.     db    '<RETURN> to save line,',255
  2499. ent_str_2:
  2500.     dw    window_start+(80*7)+5
  2501.     db    '<^> to enter CTRL key,',255
  2502. ent_str_3:
  2503.     dw    window_start+(80*8)+5
  2504.     db    '^P to enter pause (',char_pause,'),',255
  2505. ent_str_4:
  2506.     dw    window_start+(80*9)+5
  2507.     db    '^W to enter wait (',char_wait,').',255
  2508.  
  2509. w_boot_1:
  2510.     dw    window_start+(80*4)+5
  2511.     db    '<B> to warm boot,',255
  2512. w_boot_2:
  2513.     dw    window_start+(80*5)+5
  2514.     db    '<S> to boot to Shell,',255
  2515. w_boot_3:
  2516.     dw    window_start+(80*6)+5
  2517.     db    '<C> to boot to CCP,',255
  2518. w_boot_4:
  2519.     dw    window_start+(80*7)+5
  2520.     db    '<E> to edit command line.',255
  2521.  
  2522. set_curs_1:
  2523.     dw    window_start+(80*4)+5
  2524.     db    'Press cursor key to change.',255
  2525. set_curs_2:
  2526.     dw    window_start+(80*6)+10
  2527.     db    'Currently - ',255
  2528. set_curs_3:
  2529.     dw    window_start+(80*8)+10
  2530.     db    'Change to ?',255
  2531.  
  2532. time_1:
  2533.     dw    window_start+(80*4)+5
  2534.     db    '<S> Set time/date,',255
  2535. time_2:
  2536.     dw    window_start+(80*5)+5
  2537.     db    '<1> Date - 20th Dec., 1987,',255
  2538. time_3:
  2539.     dw    window_start+(80*6)+5
  2540.     db    '<2> Date - Dec. 20th, 1987,',255
  2541. time_4:
  2542.     dw    window_start+(80*7)+5
  2543.     db    '<3> Date - 20/12/87,',255
  2544. time_5:
  2545.     dw    window_start+(80*8)+5
  2546.     db    '<4> Date - 12/20/87 (U.S.),',255
  2547. time_6:
  2548.     dw    window_start+(80*9)+5
  2549.     db    '<T> Time stamp.',255
  2550.  
  2551. set_time_1:
  2552.     dw    window_start+(80*6)+5
  2553.     db    'Use cursor keys to set,',255
  2554. set_time_▓:
  2555.     dw    window_start+(80*7)+5
  2556.     db    '^Z to zero digits,',255
  2557. set_time_3:
  2558.     dw    window_start+(80*8)+5
  2559.     db    '<RETURN> to save new time,',255
  2560. set_time_4:
  2561.     dw    window_start+(80*9)+5
  2562.     db    '<D> to save date only.',255
  2563.  
  2564. screen_1:
  2565.     dw    window_start+(80*4)+5
  2566.     db    'Use cursor keys to move screen,',255
  2567. screen_2:
  2568.     dw    window_start+(80*5)+5
  2569.     db    '<F> foreground colour,',255
  2570. screen_3:
  2571.     dw    window_start+(80*6)+5
  2572.     db    '<B> background colour,',255
  2573. screen_4:
  2574.     dw    window_start+(80*7)+5
  2575.     db    '<C> window foreground,',255
  2576. screen_5:
  2577.     dw    window_start+(80*8)+5
  2578.     db    '<V> window background,',255
  2579. screen_6:
  2580.     dw    window_start+(80*9)+7
  2581.     db    '( <SHIFT> to reverse )',255
  2582. screen_7:
  2583.     dw    window_start+(80*10)+5
  2584.     db    '<L> status line on/off.',255
  2585.  
  2586.  
  2587. inv_chars:
  2588. ;; top left
  2589. ;    db    000h,000h,000h,000h,00Fh,01Fh,01Ch,01Ch,01Ch,01Ch,01Ch
  2590. ;    db     01Ch,01Ch,01Ch,01Ch,01Ch
  2591. ;; top, bottom
  2592. ;    db    000h,000h,000h,000h,0FFh,0FFh,000h,000h,000h,000h,000h
  2593. ;    db     000h,000h,000h,000h,000h
  2594. ;; top right
  2595. ;    db    000h,000h,000h,000h,0F8h,0FCh,01Ch,01Ch,01Ch,01Ch,01Ch
  2596. ;    db     01Ch,01Ch,01Ch,01Ch,01Ch
  2597. ;; left, right
  2598. ;    db    01Ch,01Ch,01Ch,01Ch,01Ch,01Ch,01Ch,01Ch,01Ch,01Ch,01Ch
  2599. ;    db     01Ch,01Ch,01Ch,01Ch,01Ch
  2600. ;; bottom left
  2601. ;    db    01Ch,01Ch,01Ch,01Ch,01Fh,00Fh,000h,000h,000h,000h,000h
  2602. ;    db     000h,000h,000h,000h,000h
  2603. ;; bottom right
  2604. ;    db    01Ch,01Ch,01Ch,01Ch,0FCh,0F8h,000h,000h,000h,000h,000h
  2605. ;    db     000h,000h,000h,000h,000h
  2606. ;; middle left
  2607. ;    db    01Ch,01Ch,01Ch,01Ch,01Fh,01Fh,01Ch,01Ch,01Ch,01Ch,01Ch
  2608. ;    db     01Ch,01Ch,01Ch,01Ch,01Ch
  2609. ;; middle right
  2610. ;    db    01Ch,01Ch,01Ch,01Ch,0FCh,0FCh,01Ch,01Ch,01Ch,01Ch,01Ch
  2611. ;    db     01Ch,01Ch,01Ch,01Ch,01Ch
  2612.  
  2613. ; Alternate set with two lines ...
  2614. ; top left
  2615.     db    000h,000h,000h,000h,00Fh,010h,021h,022h,024h,024h,024h
  2616.     db     024h,024h,024h,024h,024h
  2617. ; top, bottom
  2618.     db    000h,000h,000h,000h,0FFh,000h,0FFh,000h,000h,000h,000h
  2619.     db     000h,000h,000h,000h,000h
  2620. ; top right
  2621.     db    000h,000h,000h,000h,0F0h,008h,084h,044h,024h,024h,024h
  2622.     db     024h,024h,024h,024h,024h
  2623. ; left, right
  2624.     db    024h,024h,024h,024h,024h,024h,024h,024h,024h,024h,024h
  2625.     db     024h,024h,024h,024h,024h
  2626. ; bottom left
  2627.     db    024h,024h,024h,022h,021h,010h,00Fh,000h,000h,000h,000h
  2628.     db     000h,000h,000h,000h,000h
  2629. ; bottom right
  2630.     db    024h,024h,024h,044h,084h,008h,0F0h,000h,000h,000h,000h
  2631.     db     000h,000h,000h,000h,000h
  2632. ; middle left
  2633.     db    024h,024h,024h,022h,021h,020h,021h,022h,024h,024h,024h
  2634.     db     024h,024h,024h,024h,024h
  2635. ; middle right
  2636.     db    024h,024h,024h,044h,084h,004h,084h,044h,024h,024h,024h
  2637.     db     024h,024h,024h,024h,024h
  2638.  
  2639.  
  2640. ; cursor for entering strings, time
  2641.     db    0FFh,0FFh,000h,000h,000h,000h,000h,000h,000h,000h,000h
  2642.     db     000h,000h,000h,000h,000h
  2643.  
  2644. ; pause
  2645. ;    db    000h,000h,000h,000h,008h,014h,008h,000h,000h,000h,000h
  2646.     db    000h,000h,000h,000h,03Ch,008h,01Eh,000h,000h,000h,000h
  2647.     db     000h,000h,000h,000h,000h
  2648. ; control code
  2649.     db    000h,000h,008h,01Ch,036h,022h,000h,000h,000h,000h,000h
  2650.     db     000h,000h,000h,000h,000h
  2651. ; chain function
  2652.     db    000h,03Eh,030h,030h,03Eh,030h,030h,030h,000h,000h,000h
  2653.     db     000h,000h,000h,000h,000h
  2654. ; wait
  2655.     db    000h,000h,000h,03Eh,030h,03Eh,030h,030h,000h,000h,000h
  2656.     db     000h,000h,000h,000h,000h
  2657.  
  2658.  
  2659. end_code    equ    $
  2660.  
  2661. ; zero fill to end of CP/M record (128 bytes)
  2662.     if    ($ and 127) ne 0
  2663.      ds    128-($ and 127)
  2664.     endif
  2665.  
  2666. ; start of uninitialised storage
  2667.  
  2668. save_sp        equ    end_code
  2669.  
  2670. stack        equ    save_sp+64+2
  2671.  
  2672. temp_screen    equ    stack
  2673.  
  2674. temp_inverse    equ    temp_screen+(num_lines*num_cols)
  2675.  
  2676. temp_col    equ    temp_inverse+(num_pcg*16)
  2677.  
  2678. temp_attr    equ    temp_col+(num_lines*num_cols)
  2679.  
  2680. time        equ    temp_attr+(num_lines*num_cols)
  2681.  
  2682. new_time    equ    time+10
  2683.  
  2684. entered_time    equ    new_time+10
  2685.  
  2686. no_clock    equ    entered_time+10
  2687.  
  2688. prog_fn_addr    equ    no_clock+1
  2689.  
  2690. temp_string    equ    prog_fn_addr+2
  2691.  
  2692. pointer        equ    temp_string+128
  2693.  
  2694. line_length    equ    pointer+1
  2695.  
  2696. fn_flag        equ    line_length+1
  2697.  
  2698. colour_fitted    equ    fn_flag+1
  2699.  
  2700. old_vml        equ    colour_fitted+1
  2701.  
  2702. last_key    equ    old_vml+1
  2703.  
  2704. last_addr    equ    last_key+1
  2705.     if    (last_addr gt spare_fn_str)
  2706. error     equ     code gone too far !!!
  2707.      dw     last_addr-spare_fn_str+zero
  2708.     endif
  2709.  
  2710.     end
  2711.