home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / z / zsim20.zip / CPMBIOS.ASM < prev    next >
Assembly Source File  |  1992-12-03  |  92KB  |  3,945 lines

  1.  
  2. ;
  3. ; BIOS FUER DEN CP/M EMULATOR
  4. ;
  5. ;
  6. ; (C) 1990,1991,1992 by Jürgen Weber
  7. ;
  8. ; Version: 1.0
  9. ;          1.1     Load/Save disparameters with  /F fname
  10. ;          1.11    bios read signals Dos File End
  11. ;          1.2     conin translates Csr keys to WS
  12. ;                  time functon and blink attribute
  13. ;          1.21    Option /Snnn to restrain ramdisc size
  14. ;          1.22    look first for `COMSPEC` then \COMMAND.COM
  15. ;                  free 128K mem for OS-Shell
  16. ;                  some bug fixes
  17. ;                  do not save cpm_drv to disc parameter file anymore
  18. ;          1.3     can be assembled with option to make an interrupt
  19. ;                  request with every timer tick
  20. ;          1.4     user bios call for file transfer to/from msdos
  21. ;                  menu option reset screen
  22. ;          1.5     select drive 0 after warm boot from ctrl-brk-menu
  23. ;                  menu option swap drives
  24. ;                  no longer swap to root dir at os shell
  25. ;          1.6     IOBYTE support:
  26. ;                    function 6 and 7 can be set to the serial port
  27. ;          1.7     option /D to set physical drive
  28. ;                  option /H to get option help
  29. ;          2.0     Z80 emulation is now 20% faster
  30.  
  31. .286
  32.  
  33.  
  34. DEFAULT_IOBYTE EQU   10000001b ; lpt0,,,video
  35.  
  36. VERSION equ '2.0'  ; to display on screen
  37. VERSNR  equ 20h    ; to return if requested
  38.  
  39. ; CHANGE THE FELLOWING TO THE PHYSICAL DISK
  40. ; YOU WANT TO USE FOR CPM
  41.  
  42. IFNDEF PHYS_DRV
  43.   PHYS_DRV EQU 0   ; phys number of pc drive to use as CP/M floppy
  44. ENDIF
  45.  
  46. IF PHYS_DRV GT 1
  47.    %OUT ERROR: PHYSICAL CP/M DRIVE SET TO ILLEGAL VALUE: VALID IS 0 OR 1
  48.    ERR
  49. ENDIF
  50.  
  51. ; IF TIMER_INTS THEN
  52. ;    at every PC Timertick a z80 interrupt request is made
  53. ; (if default int mode 0 is set execute DATABUS_BTE,
  54. ;  elseif int mode 1 do a RST 38H
  55. ;  else (int mode 2) call word ptr [I_Reg shl 8 + (DATABUS_BTE shl 1) )
  56. ; (Z80 emulator defaults to interrupt DISabled, IM 0)
  57.  
  58. TIMER_INTS EQU 0
  59. DATABUS_BTE EQU 0E7H   ; RST 20H
  60.  
  61. INCLUDE Z80EMU.INC
  62.  
  63. EXTRN crtout:near,crtin:near,crtinstat:near,reset_crt:near,sel_scr_page:near
  64. EXTRN cursor_off:near,cursor_on:near
  65.  
  66. PUBLIC prg_exit,bios88
  67.  
  68. PUBLIC breakflag
  69.  
  70.  
  71. %nosyms        ; keine symbols im listing
  72. warn           ; alle warnings an
  73.  
  74. DOSSEG   ; UNBEDINGT notwendig, da fuer Speicherverwaltung des Z80 Segments
  75.          ; und der Ramdisk Stacksegment als letztes kommen muss
  76.          ; auch mussen Stack- und Codesegment Klassen 'STACK' bzw.
  77.          ; 'CODE'bekommen
  78.  
  79. LOCALS   ; fuer locale Labels in Prozeduren
  80.  
  81. JUMPS    ; automatische Sprunglaengenanpassung
  82.  
  83. CALLZ macro label ; Call if zero
  84. local exit
  85.       jnz short exit
  86.       call label
  87. exit:
  88. endm
  89.  
  90. CALLNZ macro label ; Call if not zero
  91. local exit
  92.       jz   short exit
  93.       call label
  94. exit:
  95. endm
  96.  
  97. CALLC macro label ; Call if carry
  98. local exit
  99.       jnc  short exit
  100.       call label
  101. exit:
  102. endm
  103.  
  104.  
  105. TSTNCLR MACRO FLAG    ; Z-> war nicht gesetzt
  106.         CMP FLAG,FALSE
  107.         MOV FLAG,FALSE
  108. ENDM
  109.  
  110.  
  111. ;
  112. ; segmente des emulators:
  113. ;
  114.  
  115. ; emulator_seg   : emulator und bios code
  116. ; emudata_seg    : emulator data und z80 bios code
  117. ; stack_seg      : emulator und bios stack
  118. ; z80cpu_seg     : Segment des emulierten z80, 64k, dummy at 0 (in z80seg_adr)
  119. ; ramdisc_seg    : ramdisc fuer cp/m
  120. ;
  121.  
  122.  
  123. include dos.inc         ; dos functionen
  124.  
  125. ;
  126. ; ******* KONSTANTEN ********
  127. ;
  128.  
  129. DEFAULT_DMA        EQU 80H
  130. RECORD_LEN         EQU 80H
  131.  
  132.  
  133.  
  134. ZBIOSLEN           equ (zbiosend-zbiosbeg)
  135. ZBIOSDISPL         equ (0ffffh-ZBIOSLEN) and 0ff00h
  136. ; dies bewirkt Start auf neuer Seite, damit Bios auf XX00 anfaengt
  137. ZBIOS              equ offset zbiosbeg+ZBIOSDISPL
  138.  
  139. CTRL_BREAK_INT EQU 1BH
  140.  
  141. ESC_KEY            EQU 27
  142.  
  143. EMU_SCR_PAGE EQU 0
  144. DOS_SCR_PAGE EQU 1
  145.  
  146. ; folgende Konstanten werden als Flags zur Addressberechnung
  147. ; im Sektorbuffer benoetigt
  148.  
  149. READ_OP            EQU 0
  150. WRITE_OP           EQU 0FFH
  151.  
  152.  
  153.  
  154.  
  155. BDOSLEN            equ 1600h     ; Laenge ccp+bdos cp/m 2.2
  156. BDOS_CHK_SUM       equ 2d88h     ; Checksumme ueber Bdos Copyright Meldung
  157.  
  158. SYS_FRST_SEC       EQU 28
  159.          ; erster absoluter Sektor, den Bdos auf SysSpuren belegt
  160.  
  161. SYS_SECS           EQU BDOSLEN/RECORD_LEN ; Anzahl Sektoren, die System belegt
  162.  
  163. TRACK_BUF_LEN      EQU 10*512
  164.  
  165. CPM_EOF            EQU 26
  166.  
  167.  
  168. RMD                equ 1   ; phys Number of ramdisk IN CP/M
  169.  
  170.  
  171. PHYS_SEKLEN        equ 512
  172. NSECTS             equ    2
  173. NDISKS             equ    2  ; last disk # +1
  174. BPS                equ    2
  175.  
  176. ; -------------------------------------
  177. ;
  178. ; emulator data segment
  179. ;
  180. ; --------------------------------------
  181.  
  182.  
  183. emudata_seg segment para public 'DATA'
  184.  
  185. include zbios.inc
  186.  
  187. dpb_cpc     dpb <SPTC,BSHC,BLMC,EXMC,DSMC,DRMC,AL0C,AL1C,CKSC,OFFC>
  188. dpb_dta     dpb <SPTD,BSHD,BLMD,EXMD,DSMD,DRMD,AL0D,AL1D,CKSD,OFFD>
  189. dpb_eig     dpb <SPTD,BSHD,BLMD,EXMD,DSMD,DRMD,AL0D,AL1D,CKSD,OFFD>
  190. dpb_cpm86SS dpb <SPT0,BSH0,BLM0,EXM0,DSM0,DRM0,AL00,AL10,CKS0,OFF0>
  191. dpb_cpm86DS dpb <SPT1,BSH1,BLM1,EXM1,DSM1,DRM1,AL01,AL11,CKS1,OFF1>
  192.  
  193. ramdisklen dw (?)
  194. lasttrack_rd db (?) ; 0..127  (512K)
  195.  
  196. PUNCH_BUF_SIZE  equ 512
  197. READER_BUF_SIZE equ 256
  198.  
  199. start_string db 27,'E',27,'Y',32+8,32+24,27,'p'
  200.              db 'ZSIM',27,'q'
  201.              db 27,'Y',32+10,32+18
  202.              db 'Free for personal use'
  203.              db 27,'Y',32+12,32+18
  204.              db 27,'p','USE AT YOUR OWN RISC !',27,'q'
  205.              db 27,'Y',32+15,32+18
  206.              db '(C) 1990,1992 by '
  207.              db 27,'Y',32+17,32+18
  208.              db 'Jürgen G. Weber'
  209.              db 27,'Y',32+18,32+18
  210.              db 'Wiesentalstr. 1'
  211.              db 27,'Y',32+19,32+18
  212.              db 'W-7170 Schwäbisch Hall'
  213.              db 27,'Y',32+20,32+18
  214.              db 'Federal Republic of Germany'
  215.              db 27,'Y',32+24,32+17,27,'p'
  216.              db 'Insert a CP/M disk into drive '
  217. drv_letter   db 'A'
  218.              db ': then press any key'
  219.              db 27,'q'
  220.              db 0
  221.  
  222.  
  223. help_str     db 13,10
  224.              db 'ZSIM - Z80 EMULATOR + CP/M 80 BIOS'
  225.              db 13,10,10
  226.              db '(C) 1990,1992 by Jürgen Weber',13,10,10
  227.              db 'Options:',13,10,10
  228.              db '/Dn   n=0,1    Use PC disc drive n',13,10
  229.              db '/F <parmfile>  Use disc parameter file <parmfile>',13,10
  230.              db '/H or /?       Get this help',13,10
  231.              db '/Snnn          Restrain ramdisc size to nnn K',13,10,0
  232. help_str_end equ $
  233.  
  234. db 'ZSIM is copyrighted by Jürgen Weber but'
  235. db ' it looks for the fellowing string: '
  236.  
  237. bdos_str db '        COPYRIGHT (C) 1979, DIGITAL RESEARCH  '
  238. bdos_str_end equ this byte
  239.  
  240. cpmsys_fileName  db 'CPMSYS.CPM',0
  241. ramdisc_fname    db 'RAMDISC.CPM',0
  242. punch_fileName   db 'PUNCH.CPM',0
  243. reader_fileName  db 'READER.CPM',0
  244. temp_fname       db 'EMUOVL.$$$',0
  245.  
  246. fmt_file_flg db FALSE
  247. fmt_file_name    db 80 dup (?)
  248. file_promt_str db 'Enter Disk Parameter filename: ',0
  249. file_promt_str_end equ $
  250.  
  251.  
  252. menutab label word
  253.  
  254.      dw m_esc
  255.  
  256.      dw m_continue
  257.      dw m_save_rd_quit
  258.      dw m_quit
  259.      dw m_save_rd
  260.      dw m_del_pf
  261.      dw m_init_rdr
  262.      dw m_shell
  263.      dw m_edit_disk_parm
  264.      dw m_save_d_parm
  265.      dw m_load_d_parm
  266.      dw m_swap_drives
  267.      dw m_reset_scr
  268.      dw m_w_boot
  269.      dw m_info
  270.  
  271. menu_strs    db '\Continue','|'
  272.              db 'Save \Ramdisc/Quit','|'
  273.              db '\Quit','|'
  274.              db '\Save Ramdisc','|'
  275.              db '\Delete Punch File','|'
  276.              db '\Init Reader','|'
  277.              db '\OS Shell','|'
  278.              db 'Disk \Parameters','|'
  279.              db 'Sa\ve Parameters','|'
  280.              db '\Load Parameters','|'
  281.              db 'Swap Driv\es','|'
  282.              db 'Rese\t Screen','|'
  283.              db '\Warm Boot','|'
  284.              db '\About','|'
  285.              db 0
  286. menu_strs_end equ this byte
  287.  
  288. MESG_ESC equ 0
  289.  
  290. LONGEST_MESSAGE=20
  291. MESSAGE_COUNT=12
  292.  
  293. prg_ext_box_res  dw 0ffffh
  294.  
  295. ins_cpm_disk_txt db 'Insert CP/M disk and press ENTER|',0
  296. ins_cpm_disk_txt_end equ this byte
  297.  
  298. ins_dos_disk_txt db 'Insert MS-DOS disk and press ENTER|',0
  299. ins_dos_disk_txt_end equ this byte
  300.  
  301. disk_err_txt db 'Disk Error '
  302. disk_err_num db 2 dup (?)
  303.              db 'H, Class '
  304. disk_err_cls db 2 dup (?)
  305.              db 'H. Press ESC|',0
  306. disk_err_txt_end equ this byte
  307.  
  308.  
  309. f_not_found_txt db 'File not found. Press ESC|',0
  310. f_not_found_txt_end equ this byte
  311.  
  312. no_mem_txt db 'Not enough memory to shell. Press ESC|',0
  313. no_mem_txt_end equ this byte
  314.  
  315. on_sign_string equ this byte
  316.                    db 27,'E',27,'H'
  317.                    db 'jgw 64K cp/m 80 bios ver '
  318.                    db VERSION
  319.                    db ' --  '
  320.                    db ??date
  321.                    db '  (C) 1990,1992 by Jürgen G. Weber'
  322.                    db 13,10,10
  323.                    db 'BDOS: ',27,'j',0
  324. bad_format         db 13,10
  325.                    db 'Unknown disc format. Insert new disc and press any key'
  326.                    db 13,10,0
  327. no_sys             db 13,10
  328.                    db 'Could not read System sectors. Insert'
  329.                    db ' new disc and press any key'
  330. cr_lf_txt          db 13,10,0
  331. control_c_txt      db '^C...',0
  332. reset_scr_txt      db 27,'@',0
  333.  
  334. mfulstr db 13,10,'Not enough memory',13,10
  335. mfsend equ this byte
  336.  
  337. illparm_str db 13,10,'Illegal Command Line Parameter',13,10
  338. illparm_strend equ this byte
  339.  
  340. dma_txt db 13,10
  341.         db 'Fatal: DMA Boundary Crossing'
  342.         db 13,10
  343. dma_txt_end equ this byte
  344.  
  345. exit_str db 'Type EXIT to return to CP/M Emulator ...',13,10
  346. exit_str_end equ this byte
  347.  
  348.  
  349. exec_par_block equ this word
  350.        dw 0
  351.        dw offset exec_cmd_line
  352.        dw seg    exec_cmd_line
  353.        dd 0
  354.        dd 0
  355. exec_cmd_line equ this word
  356.        db ec_str_end-ec_str
  357. ec_str db ''
  358. ec_str_end equ this byte
  359.        db 13
  360.  
  361. exec_usr_flg db FALSE
  362.  
  363. exec_usr_lne equ $
  364. db 0
  365.  db '/C '
  366. usr_lne equ $
  367. db 80 dup (?)
  368.  
  369.  
  370. no_cc_str  db 13,10,'COMMAND.COM not found. Press ESC.',13,10
  371. no_cc_str_end equ this byte
  372.  
  373. exec_fname db '\COMMAND.COM',0
  374. comspec db 80 dup (?)
  375.  
  376. var_comspec db 'COMSPEC='
  377. var_comspec_len equ $-var_comspec
  378.  
  379. good_dpb_edit db (?)
  380. db 2 dup (?)
  381.  
  382. breakflag  db FALSE
  383.  
  384.  
  385.  
  386. old_int1b  dd (?)
  387. stackpoi   dw (?)
  388.  
  389. sp_save    dw (?)
  390. ss_save    dw (?)
  391.  
  392. z80seg_adr dw (?)
  393. rdseg_adr  dw (?)
  394. rdlen      dw (?)
  395. max_rd_size dw 1024   ; default auf maximal
  396. exec_mem_start dw (?)
  397.  
  398. default_dta dd (?)
  399. psp_adr    dw (?)
  400. prog_len   dw (?)
  401. mem_end    dw (?)
  402. ovl_base   dw (?)
  403. hd_drive_flag db (?)
  404. ms_current_drive db (?)
  405.  
  406. tmp_word        dw (?)
  407.  
  408. z80_pc             dw ?
  409. ccp_adr            dw ?
  410. bdos_adr           dw ?
  411. bios_adr           dw ?
  412.  
  413. month_tab db 31,28,31,30,31,30,31,31,30,31,30,31
  414.  
  415. ; flag, dass im Speicher noch ein nicht auf disk geschriebener
  416. ; nicht-dir Track ist
  417. write_flag         db FALSE
  418.  
  419. in_boot_flag       db FALSE
  420.  
  421. home_flag          db FALSE
  422. last_track_written db 0,0
  423. dirtrack           db 0,0
  424. r_track            db 0,0
  425. w_track            db 0,0
  426.  
  427. track              db 0,0
  428. sector             db 0,0
  429. last_track_read    db 0ffh  ; default unmoeglich, noch nicht gelesen
  430.  
  431. ms_phys_sec_len    db (?)
  432. pspt_last          db 9
  433. phys_tracks_last   db 40
  434. frstps_last        db 041h
  435. dirtr_last         db 2
  436. dpb_last           dw offset dpb_cpc
  437.  
  438. cpm86dd_flag       db FALSE
  439.  
  440. drv_swap_flag      db FALSE
  441.  
  442. ; ACHTUNG: die Reihenfolge der folgenden Vars nicht
  443. ;          verändern, da sie so ans Modula UP übergeben werden
  444.  
  445. cpmdrv_set_flg     db FALSE
  446. cpm_drive          db PHYS_DRV
  447. first_phys_sec     db 41h
  448. phys_tracks        db (?)
  449. phys_sec_pt        db (?)
  450. cpm_phys_sec_len   db 2
  451. autologin_flag     db TRUE
  452.  
  453. ; end Reihenfolge wichtig
  454.  
  455.  
  456. retry_count        db 5
  457. side               db 0
  458.  
  459. dmaad              dw ?          ;direct memory address
  460. diskno             db ?          ;disk number 0-15
  461.  
  462.  
  463. punch_buf_entries  dw (?)
  464. punch_buf_ptr      dw (?)
  465.  
  466. reader_empty_flag  db TRUE
  467. reader_buf_entries dw (?)
  468. reader_buf_ptr     dw (?)
  469. reader_file_pointer dw 0,0
  470.  
  471. new_dosfilespecflg db (?)
  472. openin_handle      dw 0
  473. openout_handle     dw (?)
  474. dosfilespec        db 80 dup (?)
  475. tmpstore           db '\'
  476.                    db 80 dup (?)
  477.  
  478. ; zeigt auf Bufferadresse des Tracks, der geschrieben werden soll
  479. outbuf_ptr         dw (?)
  480.  
  481. cpm_bdos_buf db BDOSLEN dup (?)
  482.  
  483. dirtrbuf db TRACK_BUF_LEN dup (?)
  484. secbuf   db TRACK_BUF_LEN dup (?)
  485. wrtbuf   db TRACK_BUF_LEN dup (?)
  486.  
  487. punch_buf  db PUNCH_BUF_SIZE dup (?)
  488. reader_buf db READER_BUF_SIZE dup (?)
  489.  
  490. ; dass die Buffer in der EXE-Datei erscheinen, laesst sich
  491. ; durch die Verwendung einer Gruppe mit den Buffern als
  492. ; Extra Segment umgehen
  493. ; jedoch muss dann bei jedem offset der Gruppenname angegeben werden
  494.  
  495. emudata_seg ends
  496.  
  497. ; ------------------------
  498.  
  499. DATA segment para public 'DATA'
  500.      ; Dummysegment zur Kombinierung mit Modula 2
  501. DATA ends
  502.  
  503. STACK_SIZE EQU 1000H
  504.  
  505. stack_seg  segment para stack 'STACK'
  506.       dw STACK_SIZE dup (?)            ; Stack ist recht gross
  507.                                   ; wegen Modula 2 UPs
  508. stack_seg  ends
  509.  
  510. z80cpu_seg segment at 0 ; dummy
  511. z80cpu_seg ends
  512.  
  513. ; -------------------------------------
  514. ; emulator und bios segment start
  515. ; -------------------------------------
  516.  
  517. emulator_seg segment para public 'CODE'
  518.  
  519. assume  cs:emulator_seg,ds:emudata_seg,es:z80cpu_seg,ss:stack_seg
  520.  
  521. m2_ds  dw (?)                          ; fmodula routinen erwarten
  522.                                        ; bei cs:0 ihr DS
  523.  
  524. init proc                              ; emulator start
  525.  
  526.        mov  ax,emudata_seg
  527.  
  528.        mov  ds,ax            ; damit Vars angesprochen werden koennen
  529.  
  530.        mov  stackpoi,sp
  531.  
  532.        mov bx,ss             ; finde Programmende
  533.        mov ax,sp
  534.        mov cl,4
  535.        shr ax,cl             ; ax:=4
  536.        add bx,ax             ; bx=>programm ende
  537.        inc bx                ; vorsichtshalber
  538.  
  539.        push bx
  540.        mov  ax,es            ; es:0 => PSP
  541.        mov  psp_adr,ax
  542.        mov  bx,ax
  543.  
  544.        mov si,0
  545.        mov ax,[es:si+2]      ; ax=> mem end
  546.        mov  mem_end,ax
  547.        push ax
  548.        sub  ax,2000h
  549.        mov  ovl_base,ax
  550.        pop  ax
  551.        push ax
  552.        sub  ax,bx            ; mem end - prg start
  553.        mov  prog_len,ax
  554.        pop  ax               ; mem end
  555.        pop  bx               ; prg end
  556.  
  557.  
  558.        sub ax,bx             ; ax:=free mem
  559.        mov  z80seg_adr,bx
  560.  
  561.        mov  cx,10000h / 16
  562.        add  bx,cx
  563.  
  564.        mov  rdseg_adr,bx
  565.  
  566.        sub  ax,cx
  567.        jc   short @@memful
  568.  
  569.        mov  ramdisklen,ax
  570.  
  571.        PUSHR <es,bx>
  572.        DOS GET_DTA
  573.        mov word ptr default_dta,bx
  574.        mov bx,es
  575.        mov word ptr default_dta+2,bx
  576.        POPR <bx,es>
  577.  
  578.        call parse_cmd_line
  579.        mov dx,offset illparm_str
  580.        mov cx,illparm_strend-illparm_str
  581.        jc short abort              ; Fehler: falscher Parameter
  582.  
  583.        mov al,cpm_drive
  584.        add al,'A'
  585.        mov drv_letter,al
  586.  
  587.        mov  bx,offset start_string
  588.        call puts
  589.        call crtin            ; wait for keypressed
  590.  
  591.        call patch_int
  592.  
  593.        DOS  GET_DISK_DRIVE
  594.        mov  ms_current_drive,al
  595.  
  596.        mov  ax,z80seg_adr
  597.        call clearz80         ; loesche z80 mem
  598.  
  599.        call init_ramdisc
  600.  
  601.        call patch_box
  602.  
  603. ; physikalische Sektorlaenge merken
  604.  
  605.       push es
  606.       mov  ax,0
  607.       mov  es,ax
  608.       les  di,[es:78h]
  609.       mov  al,es:[di+3]
  610.       pop  es
  611.       mov  ms_phys_sec_len,al
  612.  
  613.  
  614. ;
  615. ; offset z80 bios start merken
  616. ;
  617.        mov bios_adr,ZBIOSDISPL          ; bios Sprungleiste einrichten
  618.  
  619.        call z80ini                      ; reset z80 cpu
  620.  
  621.        mov ax,z80seg_adr
  622.        mov es,ax
  623.        mov ds,ax
  624. ;
  625. ; weiter mit cp/m cold boot
  626. ;
  627.        mov al,0
  628.        jmp bios88
  629.  
  630. @@memful:
  631.        mov cx,mfsend-mfulstr
  632.        mov dx,offset mfulstr
  633. abort:
  634.        mov bx,STDERR
  635.        DOS WRITE_TO_HANDLE
  636.        mov al,1
  637.        DOS TERMINATE_EXE
  638. init   endp
  639.  
  640. get_comspec proc
  641. ; on entry: ds->psp
  642. ; si=seg data !
  643.  
  644.         PUSHR <ds,es,si,di>
  645.         mov ax,[ds:2ch]
  646.         mov ds,ax
  647.         mov es,si
  648.         mov bx,0
  649. @@loop:
  650.         mov si,bx
  651.         inc bx
  652.         mov di,offset var_comspec
  653.         mov cx,var_comspec_len
  654.         repz cmpsb
  655.         jcxz short @@found
  656.         cmp word ptr [ds:si-1],0
  657.         jnz @@loop
  658. @@exit:
  659.         POPR <di,si,es,ds>
  660.        ret
  661. @@found:
  662.         mov di,offset comspec
  663. @@floop:
  664.         lodsb
  665.         stosb
  666.         cmp al,0
  667.         jnz @@floop
  668.         jmp @@exit
  669. get_comspec endp
  670.  
  671. parse_cmd_line proc
  672. LOCAL  dsseg:WORD = AUTO_SIZE
  673.        push bp
  674.        mov  bp,sp
  675.        sub  sp,AUTO_SIZE
  676.        PUSHR <ax,bx,cx,di,si,ds,es>
  677.  
  678.  
  679.         mov fmt_file_flg,FALSE
  680.         mov ax,ds
  681.         mov dsseg,ds
  682.         mov si,ax
  683.         mov es,ax             ; es:=prog vars
  684.         mov ax,psp_adr
  685.         mov ds,ax
  686.  
  687.         call get_comspec
  688.  
  689.         mov di,offset fmt_file_name
  690.         mov si,80h            ; si => Kommandozeilenparam
  691.         lodsb                 ; count
  692.         mov bh,0
  693.         mov bl,al
  694.         mov [si+bx],bh        ; 0
  695.         or  al,al
  696.         mov al,FALSE
  697.         jz  @@parm_done
  698. @@findslash:
  699. ; don't forget string help_str
  700.         lodsb
  701.         or al,al
  702.         jz  @@parm_done
  703.         cmp al," "
  704.         jz short @@findslash     ; +DEC CX
  705.         cmp al,"/"
  706.         jnz @@parm_err
  707.         lodsb
  708.         cmp al,'?'
  709.         jz helpnabort
  710.         and al,not ('a'-'A')  ; toupper
  711.         cmp al,'H'
  712.         jz helpnabort
  713.         cmp al,'F'
  714.         jz  short @@parm_file
  715.         cmp al,'D'
  716.         jz  short @@phys_drive
  717.         cmp al,'S'
  718.         jnz @@parm_err
  719.  
  720.         mov bx,10
  721.         mov ax,0
  722.         mov dh,0
  723. @@addloop:
  724.         mov dl,[si]
  725.         or dl,dl
  726.         jz  short @@done
  727.         inc si
  728.         sub dl,'0'
  729.         jc short @@done
  730.         cmp dl,9
  731.         ja short @@done
  732.         push dx
  733.         mul bx
  734.         pop dx
  735.         add ax,dx
  736.         jmp short @@addloop
  737. @@done:
  738.         cmp ax,640
  739.         ja short @@parm_err
  740.         cmp ax,64
  741.         jb short @@parm_err
  742.         mov bx,offset max_rd_size
  743.         mov [es:bx],ax
  744.         jmp @@findslash
  745. @@parm_file:
  746.         mov di,offset fmt_file_name
  747. @@SKIP_BLN:
  748.         lodsb
  749.         cmp al," "
  750.         jz @@SKIP_BLN; +DEC CX
  751.         stosb         ; 1. non-blank
  752. @@cp_loop:
  753.         lodsb
  754.         stosb
  755.         or al,al
  756.         jz  short @@name_done
  757.         cmp al,' '
  758.         jz  short @@name_done
  759.         cmp al,13
  760.         jz  short @@name_done
  761.         jmp @@cp_loop
  762. @@name_done:
  763.         dec si
  764.         mov al,0
  765.         stosb         ; Filename Endzeichen
  766.         mov di,offset fmt_file_flg
  767.         mov byte ptr es:[di],TRUE
  768.         jmp @@findslash
  769. @@phys_drive:
  770.         lodsb
  771.         cmp al," "
  772.         jz @@phys_drive ; +DEC CX
  773.         sub al,'0'
  774.         jc short @@parm_err
  775.         cmp al,1
  776.         ja short @@parm_err
  777.         push ds
  778.         mov  ds,dsseg
  779.         mov  cpm_drive,al
  780.         mov  cpmdrv_set_flg,TRUE
  781.         pop  ds
  782.         jmp @@findslash
  783.  
  784. @@parm_done:
  785.        POPR <es,ds,si,di,cx,bx,ax>
  786.        clc
  787.        add  sp,AUTO_SIZE
  788.        pop bp
  789.        ret
  790. @@parm_err:
  791.        POPR <es,ds,si,di,cx,bx,ax>
  792.        stc
  793.        add  sp,AUTO_SIZE
  794.        pop bp
  795.        ret
  796. parse_cmd_line endp
  797.  
  798. helpnabort proc
  799.        mov  ax,emudata_seg
  800.        mov  ds,ax
  801.        mov cx,help_str_end-help_str
  802.        mov dx,offset help_str
  803.        jmp abort
  804. helpnabort endp
  805.  
  806. tst_hd_drive proc
  807.        PUSHR <ax,dx>
  808.        mov hd_drive_flag,FALSE
  809.        mov dl,cpm_drive
  810.        mov ah,15h                 ; Laufwerktyp ?
  811.        int 13h
  812.        jc  short @@exit           ; PC,XT
  813.        cmp ah,2                   ; erkennt DiskWechsel
  814.        jnz short @@exit
  815.        mov hd_drive_flag,TRUE
  816. @@exit:
  817.        POPR <dx,ax>
  818.        ret
  819. tst_hd_drive endp
  820.  
  821. ;
  822. ; der Interupt 1bH (Control-Break Interupt) muß auf eine Routine
  823. ; gelegt werden, die ein Abbruch Flag setzt
  824. ; Dieses wird dann bei jedem Bios Aufruf ausgewertet
  825. ;
  826. patch_int proc
  827.        PUSHR <ds,es,ax,bx,dx>
  828.        mov al,CTRL_BREAK_INT
  829.        DOS GET_VECTOR
  830.        mov word ptr old_int1b,bx
  831.        mov bx,es
  832.        mov word ptr old_int1b+2,bx
  833.        mov  dx,offset new_int1b
  834.        push cs
  835.        pop  ds
  836.        mov al,CTRL_BREAK_INT
  837.        DOS SET_VECTOR
  838. if TIMER_INTS
  839.        mov al,1cH  ; timer
  840.        DOS GET_VECTOR
  841.        mov word ptr cs:old_int1C,bx
  842.        mov bx,es
  843.        mov word ptr cs:old_int1C+2,bx
  844.        mov  dx,offset new_int1C
  845.        push cs
  846.        pop  ds
  847.        mov al,1cH
  848.        DOS SET_VECTOR
  849. endif
  850.        POPR <dx,bx,ax,es,ds>
  851.        ret
  852. patch_int endp
  853.  
  854. restore_int proc
  855.        push ds
  856.        lds dx,old_int1b
  857.        mov al,CTRL_BREAK_INT
  858.        DOS SET_VECTOR
  859. if TIMER_INTS
  860.        lds dx,cs:old_int1C
  861.        mov al,1Ch
  862.        DOS SET_VECTOR
  863. endif
  864.        pop ds
  865.        ret
  866. restore_int endp
  867.  
  868. new_int1b proc
  869.        push ax
  870.        push ds
  871.        mov  ax,emudata_seg
  872.        mov  ds,ax
  873.        cmp byte ptr cs:in_emu_flg,TRUE
  874.        jnz short @@not_in_emu
  875.        call ctrl_break_req
  876.        jmp short @@exit
  877. @@not_in_emu:
  878.        mov  breakflag,TRUE   ; nur wenn gerade bios code abgearbeitet wird
  879. @@exit:
  880.        pop  ds
  881.        pop  ax
  882.        iret
  883. new_int1b endp
  884.  
  885. if TIMER_INTS
  886.  
  887. old_int1C  dd (?)
  888.  
  889. ; at every timer tick do an interrupt request
  890.  
  891. new_int1C proc
  892.        cmp byte ptr cs:in_emu_flg,TRUE
  893.        push ax
  894.        mov al,DATABUS_BTE
  895.        CALLZ interrupt_request    ; nur wenn gerade z80code laeuft
  896.        pop ax
  897.        jmp dword ptr cs:[old_int1C]
  898. new_int1C endp
  899.  
  900. endif ; TIMER_INTS
  901.  
  902. ; wird auch von Z80EMU.OP76 HALT aufgerufen
  903.  
  904. prg_exit proc FAR
  905.        PUSHR <ds,es,ax>
  906.        PUSHR <bx,cx,dx,si>
  907.        mov  ax,emudata_seg
  908.        mov  ds,ax
  909.        mov  ax,z80seg_adr
  910.        mov  es,ax
  911.        call restore_int
  912.        mov  breakflag,FALSE
  913.  
  914.        call wrt_out_punch
  915.  
  916.        mov  cx,menu_strs_end-menu_strs   ; high(messages)
  917.        mov  si,offset menu_strs          ; offs(messages)
  918.  
  919.        call box_call
  920.        sal ax,1
  921.        mov di,ax
  922.        call menutab[di]
  923.  
  924.        call patch_int
  925.        POPR <si,dx,cx,bx>
  926.        POPR <ax,es,ds>
  927.        ret
  928. prg_exit endp
  929.  
  930.  
  931. ; Menü durch ESC abgebrochen
  932. m_esc proc
  933.        ret
  934. m_esc endp
  935.  
  936. ; Menüpunkt Emulation fortfahren
  937. m_continue proc
  938.       ret
  939. m_continue endp
  940.  
  941. ; Menüpunkt Quit
  942. m_quit proc
  943. ; etwaige Zeichen im Punch Buffer noch ausschreiben
  944.        call wrt_out_punch
  945.  
  946.        mov cl,31                  ; GotoXY(1,25)
  947.        call crtout
  948.        mov cl,1
  949.        call crtout
  950.        mov cl,25
  951.        call crtout
  952.        mov  al,0
  953. ABORT_EMU:
  954.        push ax
  955.        call ins_dos_disk
  956.        pop ax
  957.        DOS TERMINATE_EXE
  958. m_quit endp
  959.  
  960. ; Menüpunkt Ramdisk speichern
  961. m_save_rd proc
  962.       call save_ramdisc
  963.       ret
  964. m_save_rd endp
  965.  
  966. ; Menüpunkt Ramdisk speichern + Quit
  967. m_save_rd_quit proc
  968.        call save_ramdisc
  969.        jmp short m_quit
  970. m_save_rd_quit endp
  971.  
  972. ; Menüpunkt Punch buffer file löschen
  973. m_del_pf proc
  974.      call del_punch_file
  975.      ret
  976. m_del_pf endp
  977. ; Menüpunkt Reader initialisieren
  978. m_init_rdr proc
  979.       call reset_reader_buf
  980.       ret
  981. m_init_rdr endp
  982.  
  983. ; Menüpunkt OS Shell
  984. m_shell proc
  985.        call dos_shell
  986.        ret
  987. m_shell endp
  988.  
  989. update_disk_pars proc
  990.       PUSHR <AX,BX>
  991.        mov  cpm86dd_flag,FALSE
  992.        mov  ah,0
  993.        mov  al,dpb0.off-dpb0.spt  ; off
  994.        call get_dpb_entrie        ; nach bx
  995.        mov  dirtrack,bl
  996.       POPR <BX,AX>
  997.       ret
  998. update_disk_pars endp
  999.  
  1000. ; Menüpunkt Diskettenparameter editieren
  1001. m_edit_disk_parm proc
  1002.        call edit_disk_pars
  1003.        cmp  good_dpb_edit,1
  1004.        jnz  short @@exit
  1005.        call update_disk_pars
  1006.  
  1007.        cmp  in_boot_flag,TRUE
  1008.        jz   short @@exit          ; mit boot weitermachen
  1009.        call m_w_boot
  1010. @@exit:
  1011.        ret
  1012. m_edit_disk_parm endp
  1013.  
  1014. prepare_fname proc
  1015.        mov  di,offset fmt_file_name
  1016.        push di
  1017.        mov  cx,80
  1018.        mov  si,offset file_promt_str
  1019.        mov  bx,file_promt_str_end-file_promt_str
  1020.        call input_string
  1021.        pop  bx
  1022.        or   byte ptr [bx],0          ; Test ob was eingegeben, nein => Z
  1023.        ret
  1024. prepare_fname endp
  1025.  
  1026. ; Menüpunkt Diskettenparameter speichern
  1027. m_save_d_parm proc
  1028.        call prepare_fname
  1029.        jz short @@exit
  1030.        call save_disk_pars
  1031. @@exit:
  1032.        ret
  1033. m_save_d_parm endp
  1034.  
  1035. ; Menüpunkt Diskettenparameter laden
  1036. m_load_d_parm proc
  1037.        call prepare_fname
  1038.        jz short @@exit
  1039.        call load_disk_pars
  1040.        jmp  short m_w_boot
  1041. @@exit:
  1042.        ret
  1043. m_load_d_parm endp
  1044.  
  1045. ; Menüpunkt CP/M warm boot durchführen
  1046. m_w_boot proc
  1047.        mov sp,stackpoi
  1048.        call patch_int
  1049.        mov ax,z80seg_adr
  1050.        mov es,ax
  1051.        mov di,CDISK
  1052.        mov byte ptr es:[di],0     ; select disk zero
  1053.        call init_iobyte
  1054.        mov al,1
  1055.        jmp bios88
  1056. m_w_boot endp
  1057.  
  1058. ; Menüpunkt About Author
  1059. m_info proc
  1060.        call about_author
  1061.        ret
  1062. m_info endp
  1063.  
  1064. m_swap_drives proc
  1065.         cmp drv_swap_flag,TRUE
  1066.         mov drv_swap_flag,FALSE
  1067.         jz short @@is_true
  1068.         mov drv_swap_flag,TRUE
  1069. @@is_true:
  1070.        jmp  short m_w_boot
  1071. m_swap_drives endp
  1072.  
  1073. ; Menüpunkt Reset Screen
  1074. m_reset_scr proc
  1075.         mov bx,offset reset_scr_txt
  1076.         call puts
  1077.         ret
  1078. m_reset_scr endp
  1079.  
  1080.  
  1081. ; Fehler durch Ueberschreiten der DMA Segment Grenze
  1082. ; siehe c't 4/90 S.412
  1083.  
  1084. dma_bound proc
  1085.        mov bx,STDERR
  1086.        mov cx,dma_txt_end-dma_txt
  1087.        mov dx,offset dma_txt
  1088.        DOS WRITE_TO_HANDLE
  1089.        mov al,1
  1090.        jmp ABORT_EMU
  1091. dma_bound endp
  1092.  
  1093. ; out: ax=result
  1094. ins_dos_disk proc
  1095.        mov al,ms_current_drive
  1096.        cmp al,cpm_drive
  1097.        jnz short @@exit
  1098.        mov si,offset ins_dos_disk_txt
  1099.        mov cx,ins_dos_disk_txt_end-ins_dos_disk_txt
  1100.        call box_call
  1101. @@exit:
  1102.        ret
  1103. ins_dos_disk endp
  1104.  
  1105. ; out: ax=result
  1106. ins_cpm_disk proc
  1107.        mov al,ms_current_drive
  1108.        cmp al,cpm_drive
  1109.        jnz short @@exit
  1110.        mov si,offset ins_cpm_disk_txt
  1111.        mov cx,ins_cpm_disk_txt_end-ins_cpm_disk_txt
  1112.        call box_call
  1113. @@exit:
  1114.        ret
  1115. ins_cpm_disk endp
  1116.  
  1117. disp_disk_err proc
  1118.        pushf                      ; cy aufheben
  1119.        PUSHR <si,cx,dx,bx>
  1120.         PUSHR <DI,BP,ES,DS>
  1121.         DOS GET_EXTENDED_ERRORS
  1122.         POPR <DS,ES,BP,DI>
  1123.         mov  bx,offset disk_err_num
  1124.         call hexbyte
  1125.         mov  al,bh
  1126.         mov  bx,offset disk_err_cls
  1127.         call hexbyte
  1128.        mov si,offset disk_err_txt
  1129.        mov cx,disk_err_txt_end-disk_err_txt
  1130.        call box_call
  1131.        POPR <bx,dx,cx,si>
  1132.        popf
  1133.        ret
  1134. disp_disk_err endp
  1135.  
  1136. disp_f_not_found proc
  1137.        pushf                      ; cy aufheben
  1138.        PUSHR <si,cx>
  1139.        mov si,offset f_not_found_txt
  1140.        mov cx,f_not_found_txt_end-f_not_found_txt
  1141.        call box_call
  1142.        POPR <cx,si>
  1143.        popf
  1144.        ret
  1145. disp_f_not_found endp
  1146.  
  1147. disp_no_mem proc
  1148.        PUSHR <si,cx>
  1149.        mov si,offset no_mem_txt
  1150.        mov cx,no_mem_txt_end-no_mem_txt
  1151.        call box_call
  1152.        POPR <cx,si>
  1153.        ret
  1154. disp_no_mem endp
  1155.  
  1156.  
  1157. hexbyte    PROC
  1158. ; in: bx-> store for hexbyte
  1159. ;     al=hexbyte
  1160.           push ax
  1161.           shr al,1                   ;extract high nibble
  1162.           shr al,1
  1163.           shr al,1
  1164.           shr al,1
  1165.           call nib
  1166.           pop ax
  1167.           and al,0fh
  1168. nib:
  1169.           add al,90h                 ;special hex conversion sequence
  1170.           daa                        ;using ADDs and DAA's
  1171.           adc al,40h
  1172.           daa                        ;nibble now converted to ASCII
  1173.           mov [bx],al
  1174.           inc bx
  1175.           ret
  1176. hexbyte ENDP
  1177.  
  1178.  
  1179. EXTRN EmuMenu_DoMenue:far,EmuMenu_EditDPB:far
  1180. EXTRN EmuMenu_InputString:far,EmuMenu_About:far,EmuMenu_init:far
  1181.  
  1182. ; fmodula2 laedt merkwuerdigerweise am Anfang DS aus CS:0
  1183. ; also muss man dort ds hinbringen
  1184. ; Trotzdem sollte vor Aufruf einer Funktion DS richtig
  1185. ; geladen sein.
  1186.  
  1187. patch_box proc
  1188.        mov  ax,DATA
  1189.        mov  [cs:0],ax
  1190.        ret
  1191. patch_box endp
  1192.  
  1193. box_call proc                     ; um Modula 2 UPs aufzurufen
  1194. ;
  1195. ; in:  ds:si => menuetext
  1196. ;      cx    =  len(menuetext)
  1197. ; out: ax = result
  1198. ;
  1199. ; auf dem STACK muss GENUG FREI sein, um zu erzeugendes WINDOW
  1200. ; ABZUSPEICHERN
  1201. ;
  1202. COMMENT @
  1203.  
  1204. DEFINITION MODULE EmuM2;
  1205.  
  1206. FROM SYSTEM IMPORT BYTE,WORD;
  1207.  
  1208. TYPE PhysDiskPars = RECORD
  1209.            cpm_drive       : BYTE;
  1210.            first_phys_sec  : BYTE;
  1211.            phys_tracks     : BYTE;
  1212.            phys_sec_pt     : BYTE;
  1213.            bytes_per_sec   : BYTE;
  1214.            autologin_flag  : BYTE;
  1215.        END;
  1216.  
  1217. dpb = RECORD
  1218.              spt  : WORD;
  1219.              bsh  : BYTE;
  1220.              blm  : BYTE;
  1221.              exm  : BYTE;
  1222.              dsm  : WORD;
  1223.              drm  : WORD;
  1224.              al0  : BYTE;
  1225.              al1  : BYTE;
  1226.              cks  : WORD;
  1227.              off  : WORD;
  1228.            END;
  1229.      DPBPtr = POINTER TO dpb;
  1230.      PDPPtr = POINTER TO PhysDiskPars;
  1231.  
  1232.  
  1233. PROCEDURE DoMenue(x,y:CARDINAL;messages:ARRAY OF CHAR;
  1234.                   VAR WinSave:ARRAY OF CHAR;VAR res:CARDINAL);
  1235. (* Pop Up Menue, obere linke Ecke des Rahmens bei x,y.
  1236.    messages = String mit darzustellenden Menuepunkten; Stringende = 0C.
  1237.    Menuepunkte werden durch | getrennt, auch nach letztem Menuepunkt
  1238.    MUSS | stehen.
  1239.    Jeder Menuepunkt darf durch Druecken eines einzigen Zeichens angewaehlt
  1240.    werden, das hell dargestellt wird. Diesem Zeichen muss der Backslash \
  1241.    vorangestellt werden.
  1242.    Es duerfen maximal 20 Menuepunkte sein.
  1243.    WinSave muss genug Platz enthalten, um Hintergrund + dessen Attribute
  1244.    abzuspeichern, = (Laengster Menuepunkt+2)*2*(Menuepunkte+2)
  1245. *)
  1246.  
  1247. PROCEDURE EditDPB(p:DPBPtr;q:PDPPtr;
  1248.                   VAR WinSave:ARRAY OF CHAR;VAR OK:BOOLEAN);
  1249. (* Len WinSave=20*18*2=720 *)
  1250.  
  1251. PROCEDURE InputString(VAR WinSave,s,p:ARRAY OF CHAR);
  1252. (* Es wird vorrausgesetzt, daß prompt p < 30 und string s < 30 *)
  1253.  
  1254.  
  1255. PROCEDURE About(VAR WinSave:ARRAY OF CHAR);
  1256. (* Author ausgeben *)
  1257.  
  1258.  
  1259. END EmuM2.
  1260.  
  1261.  
  1262. @
  1263.  
  1264. HIGH_WinSave=(LONGEST_MESSAGE+2)*2*(MESSAGE_COUNT+2)
  1265.  
  1266. IF HIGH_WinSave gt 2*STACK_SIZE/3
  1267.    %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
  1268. ENDIF
  1269.  
  1270.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  1271.        sub  sp,HIGH_WinSave
  1272.        mov  bx,sp
  1273.        mov  ax,20
  1274.        push ax                 ; x
  1275.        mov  ax,7
  1276.        push ax                 ; y
  1277.        push cx                 ; high(messages)
  1278.        push ds                 ; seg(messages)
  1279.        push si                 ; offs(messages)
  1280.        mov  cx,HIGH_WinSave
  1281.        push cx                 ; high(WinSave)
  1282.        push ss                 ; seg(WinSave)
  1283.        push bx                 ; offs(WinSave)
  1284.        mov  ax,seg prg_ext_box_res
  1285.        push ax                 ; seg(prg_ext_box_res)
  1286.        mov  ax,offset prg_ext_box_res
  1287.        push ax                 ; offs(prg_ext_box_res)
  1288. ;box_adr equ this byte
  1289.        mov  ax,DATA
  1290.        mov  ds,ax
  1291.        call EmuMenu_DoMenue
  1292.        add  sp,HIGH_WinSave
  1293.        POPR <es,ds>
  1294.        mov  ax,prg_ext_box_res
  1295.        POPR <bp,si,di,dx,cx,bx>
  1296.        ret
  1297. box_call endp
  1298.  
  1299.  
  1300. edit_disk_pars proc
  1301.  
  1302. HIGH_WinSave=800
  1303.  
  1304. IF HIGH_WinSave gt 2*STACK_SIZE/3
  1305.    %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
  1306. ENDIF
  1307.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  1308.        sub  sp,HIGH_WinSave
  1309.        mov  bx,sp
  1310.        mov  ax,z80seg_adr
  1311.        push ax                 ; seg(p)  p:DPBPtr
  1312.        mov  ax,offset dpb0+ZBIOSDISPL
  1313.        push ax                 ; offs(p)
  1314.        mov  ax,seg cpm_drive
  1315.        push ax                 ; seg (q) q:PDPPtr;
  1316.        mov  ax,offset cpm_drive
  1317.        push ax                 ; offs (q)
  1318.        mov  cx,HIGH_WinSave
  1319.        push cx                 ; high(WinSave)
  1320.        push ss                 ; seg(WinSave)
  1321.        push bx                 ; offs(WinSave)
  1322.        mov  ax,seg good_dpb_edit
  1323.        push ax                 ; seg(ok)
  1324.        mov  ax,offset good_dpb_edit
  1325.        push ax                 ; offs(ok)
  1326.        mov  ax,DATA
  1327.        mov  ds,ax
  1328.        call EmuMenu_EditDPB
  1329.        add  sp,HIGH_WinSave
  1330.        POPR <es,ds,bp,si,di,dx,cx,bx>
  1331.        ret
  1332. edit_disk_pars endp
  1333.  
  1334. ;PROCEDURE InputString(VAR WinSave,s,p:ARRAY OF CHAR);
  1335.  
  1336. input_string proc   ; ds:si = prompt, bx = len prompt
  1337.                     ; ds:di = string  cx = len string
  1338. LOCAL  prompt_str,lenpr,in_str,lenstr:WORD = AUTO_SIZE
  1339.        push bp
  1340.        mov  bp,sp
  1341.        sub  sp,AUTO_SIZE
  1342.        mov  prompt_str,si
  1343.        mov  in_str,di
  1344.        mov lenpr,bx
  1345.        mov lenstr,cx
  1346. HIGH_WinSave=800
  1347.  
  1348. IF HIGH_WinSave gt 2*STACK_SIZE/3
  1349.    %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
  1350. ENDIF
  1351.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  1352.        sub  sp,HIGH_WinSave
  1353.        mov  bx,sp
  1354.        mov  ax,z80seg_adr
  1355.  
  1356.        mov  cx,HIGH_WinSave
  1357.        push cx                 ; high(WinSave)
  1358.        push ss                 ; seg(WinSave)
  1359.        push bx                 ; offs(WinSave)
  1360.  
  1361.        push lenstr             ; high(s)
  1362.        push ds                 ; seg(s)
  1363.        push in_str             ; offs(s)
  1364.        push lenpr              ; high(p)
  1365.        push ds                 ; seg(p)
  1366.        push prompt_str         ; offs(p)
  1367.        mov  ax,DATA
  1368.        mov  ds,ax
  1369.        call EmuMenu_InputString
  1370.        add  sp,HIGH_WinSave
  1371.        POPR <es,ds,bp,si,di,dx,cx,bx>
  1372.        mov  sp,bp
  1373.        pop  bp
  1374.        ret
  1375. input_string endp
  1376.  
  1377.  
  1378. load_disk_pars proc
  1379. LOCAL  handle:WORD = AUTO_SIZE
  1380.        push bp
  1381.        mov  bp,sp
  1382.        sub  sp,AUTO_SIZE
  1383.        call ins_dos_disk
  1384.        call @@fopen
  1385.        jnc  short @@ok
  1386.        cmp  ax,2
  1387.        CALLZ disp_f_not_found
  1388.        jc  short @@exit           ; nicht da
  1389. @@ok:
  1390.        call @@fread
  1391.        call @@fclose
  1392.        call update_disk_pars
  1393.        mov  autologin_flag,FALSE
  1394. @@exit:
  1395.        call ins_cpm_disk
  1396.        mov  sp,bp
  1397.        pop  bp
  1398.        ret
  1399.  
  1400. @@fopen:
  1401.        mov al,0
  1402.        mov dx,offset fmt_file_name
  1403.        DOS OPEN_FILE
  1404.        mov handle,ax
  1405.        ret
  1406.  
  1407. @@fclose:
  1408.        mov bx,handle
  1409.        DOS CLOSE_FILE
  1410.        CALLC disp_disk_err
  1411.        ret
  1412.  
  1413. @@fread:
  1414.        mov dx,offset tmp_word
  1415.        mov bx,handle
  1416.        mov cx,2
  1417.        DOS READ_FROM_HANDLE
  1418.        CALLC disp_disk_err
  1419.        mov bx,dx
  1420.        mov bx,[bx]
  1421.        cmp bx,'WJ'
  1422.        jnz  short @@ldexit         ; falscher Kenncode <> 'JW'
  1423.  
  1424.        ; cp/m Parameter laden
  1425.  
  1426.        mov dx,offset offset dpb0+ZBIOSDISPL
  1427.        mov bx,handle
  1428.        mov cx,size dpb
  1429.        push ds
  1430.        mov ax,z80seg_adr
  1431.        mov ds,ax
  1432.        DOS READ_FROM_HANDLE
  1433.        pop ds
  1434.        CALLC disp_disk_err
  1435.  
  1436.        ; physikalische Parameter laden
  1437.  
  1438.        mov dx,offset first_phys_sec
  1439.        mov bx,handle
  1440.        mov cx,autologin_flag-first_phys_sec
  1441.        DOS READ_FROM_HANDLE
  1442.        CALLC disp_disk_err
  1443.  
  1444. @@ldexit:
  1445.      ret
  1446. load_disk_pars endp
  1447.  
  1448. save_disk_pars proc
  1449. LOCAL  handle:WORD = AUTO_SIZE
  1450.        push bp
  1451.        mov  bp,sp
  1452.        sub  sp,AUTO_SIZE
  1453.        call ins_dos_disk
  1454.        cmp  ax,MESG_ESC
  1455.        jz   short @@exit
  1456.        call @@fopen
  1457.             jc short @@exit
  1458.        call @@fwrite
  1459.        call @@fclose
  1460.        call ins_cpm_disk
  1461. @@exit:
  1462.        mov  sp,bp
  1463.        pop  bp
  1464.        ret
  1465.  
  1466.  
  1467. @@fopen:
  1468.        mov cx,0
  1469.        mov dx,offset fmt_file_name
  1470.        DOS CREATE_FILE
  1471.        CALLC disp_disk_err
  1472.        mov handle,ax
  1473.        ret
  1474.  
  1475. @@fclose:
  1476.        mov bx,handle
  1477.        DOS CLOSE_FILE
  1478.        CALLC disp_disk_err
  1479.        ret
  1480.  
  1481. @@fwrite:
  1482.  
  1483. ; erst Kennung schreiben
  1484.  
  1485.        mov bx,offset tmp_word
  1486.        mov [bx],'WJ'
  1487.        mov dx,bx
  1488.        mov bx,handle
  1489.        mov cx,2
  1490.        DOS WRITE_TO_HANDLE
  1491.        CALLC disp_disk_err
  1492.  
  1493.       ; cp/m Parameter schreiben
  1494.  
  1495.        mov dx,offset offset dpb0+ZBIOSDISPL
  1496.        mov bx,handle
  1497.        mov cx,size dpb
  1498.        push ds
  1499.        mov ax,z80seg_adr
  1500.        mov ds,ax
  1501.        DOS WRITE_TO_HANDLE
  1502.        pop ds
  1503.        CALLC disp_disk_err
  1504.  
  1505.        ; physikalische Parameter schreiben
  1506.  
  1507.        mov dx,offset first_phys_sec
  1508.        mov bx,handle
  1509.        mov cx,autologin_flag-first_phys_sec
  1510.        DOS WRITE_TO_HANDLE
  1511.        CALLC disp_disk_err
  1512.  
  1513.      ret
  1514. save_disk_pars endp
  1515.  
  1516. about_author proc
  1517.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  1518.        sub  sp,HIGH_WinSave
  1519.        mov  bx,sp
  1520.        mov  cx,HIGH_WinSave
  1521.        push cx                 ; high(WinSave)
  1522.        push ss                 ; seg(WinSave)
  1523.        push bx                 ; offs(WinSave)
  1524.        mov  ax,DATA
  1525.        mov  ds,ax
  1526.        call EmuMenu_About
  1527.        add  sp,HIGH_WinSave
  1528.        POPR <es,ds,bp,si,di,dx,cx,bx>
  1529.        ret
  1530. about_author endp
  1531.  
  1532. clearz80 proc    ; loesche z80mem
  1533. ;
  1534. ; input: ax=seg z80 segment
  1535. ; alle  register ok
  1536. ;
  1537.        push es
  1538.        PUSHR <ax,cx,di>
  1539.        mov es,ax
  1540.        mov cx,8000h                      ; 32k words
  1541.        mov di,0
  1542.        mov ax,0
  1543.        rep stosw                         ; es:di := 0000h
  1544.        POPR <di,cx,ax>
  1545.        pop es
  1546.        ret
  1547. clearz80 endp
  1548.  
  1549. dos_exec proc
  1550.        cmp  exec_usr_flg,TRUE
  1551.        jz short @@cont1
  1552.        mov   al,DOS_SCR_PAGE
  1553.        call  sel_scr_page
  1554.        mov bx,STDOUT
  1555.        mov cx,exit_str_end-exit_str
  1556.        mov dx,offset exit_str
  1557.        DOS WRITE_TO_HANDLE
  1558. @@cont1:
  1559.        PUSHR <bx,cx,dx,di,si,bp,es>
  1560. ; first try calling `COMSPEC`
  1561.        mov   sp_save,sp
  1562.        mov   ss_save,ss
  1563.        mov   bx,seg    exec_par_block
  1564.        mov   es,bx
  1565.        mov   bx,offset exec_par_block
  1566.        mov   dx,offset comspec
  1567.        mov   ax,seg    comspec
  1568.        mov   ds,ax
  1569.        mov   al,0                 ; exec
  1570.        DOS   EXEC                 ; ax:=error code
  1571.        jnc short @@done
  1572. ; if that failed try \COMMAND.COM
  1573.        mov   bx,seg    exec_par_block
  1574.        mov   es,bx
  1575.        mov   bx,offset exec_par_block
  1576.        mov   dx,offset exec_fname
  1577.        mov   ax,seg    exec_fname
  1578.        mov   ds,ax
  1579.        mov   al,0                 ; exec
  1580.        DOS   EXEC                 ; ax:=error code
  1581. @@done:
  1582.        mov   bx,emudata_seg
  1583.        mov   ds,bx
  1584.        cli
  1585.        mov   ss,ss_save
  1586.        mov   sp,sp_save
  1587.        sti
  1588.        POPR  <es,bp,si,di,dx,cx,bx>
  1589.        cmp   ax,2             ; file not found
  1590.        jnz   short @@cc_found
  1591.        mov bx,STDERR
  1592.        mov cx,no_cc_str_end-no_cc_str
  1593.        mov dx,offset no_cc_str
  1594.        DOS WRITE_TO_HANDLE
  1595. @@press_esc:
  1596.        call crtin
  1597.        cmp  al,ESC_KEY
  1598.        jnz  short @@press_esc
  1599. @@cc_found:
  1600.        cmp  exec_usr_flg,TRUE
  1601.        mov   al,0
  1602.        CALLNZ  sel_scr_page
  1603.        ret
  1604. dos_exec endp
  1605.  
  1606.  
  1607. dos_shell proc
  1608. LOCAL  handle:WORD,mem_adr:WORD = AUTO_SIZE
  1609.        PUSHR <ax,bx,cx,dx,si,di>
  1610.        push bp
  1611.        mov  bp,sp
  1612.        sub  sp,AUTO_SIZE
  1613.  
  1614.        mov  ax,ovl_base
  1615.        sub  ax,z80seg_adr
  1616.        jnc  short @@memok
  1617.        call disp_no_mem
  1618.        jmp  short @@exit
  1619. @@memok:
  1620.        call ins_dos_disk
  1621.        cmp  ax,MESG_ESC
  1622.        jz   short @@exit          ; ESC
  1623.  
  1624.        call @@fcreate
  1625.             jc short @@exit
  1626.        call @@fwrite
  1627.        call @@fclose
  1628.        call @@set_free
  1629.        call dos_exec
  1630.        call @@get_mem
  1631.        call @@fopen
  1632.        call @@fread
  1633.        call @@fclose
  1634.        mov  dx,offset temp_fname
  1635.        DOS  DELETE_FILE
  1636.        CALLC disp_disk_err
  1637.        call ins_cpm_disk
  1638. @@exit:
  1639.        mov  sp,bp
  1640.        pop  bp
  1641.        POPR <di,si,dx,cx,bx,ax>
  1642.        ret
  1643.  
  1644. @@set_free:
  1645.        push es
  1646.        mov  es,psp_adr
  1647.        mov  bx,prog_len
  1648.        sub  bx,2000h
  1649.        DOS  MODIFY_MEMORY
  1650.        mov  bx,mem_end
  1651.        sub  bx,2000h
  1652.        mov  ovl_base,bx
  1653.        pop  es
  1654.        ret
  1655.  
  1656. @@get_mem:
  1657.        push es
  1658.        mov  es,psp_adr
  1659.        mov  bx,prog_len
  1660.        DOS  MODIFY_MEMORY
  1661.        pop  es
  1662.        ret
  1663.  
  1664. @@fcreate:
  1665.        mov cx,2 ; Hidden
  1666.        mov dx,offset temp_fname
  1667.        DOS CREATE_FILE
  1668.        CALLC disp_disk_err        ; Abbruch nach Error in toplevel
  1669.        mov handle,ax
  1670.        ret
  1671.  
  1672. @@fopen:
  1673.        mov al,0
  1674.        mov  dx,offset temp_fname
  1675.        DOS OPEN_FILE
  1676.        CALLC disp_disk_err
  1677.        mov handle,ax
  1678.        ret
  1679.  
  1680. @@fclose:
  1681.        mov bx,handle
  1682.        DOS CLOSE_FILE
  1683.        CALLC disp_disk_err
  1684.        ret
  1685.  
  1686. @@fwrite:
  1687.        push ds
  1688.        mov  si,ovl_base
  1689.        mov  cx,4               ; do 4*32K
  1690. @@wlp:
  1691.        push cx
  1692.        mov  bx,handle
  1693.        mov  cx,8000h
  1694.        mov  ds,si
  1695.        mov  dx,0
  1696.        DOS WRITE_TO_HANDLE
  1697.        CALLC disp_disk_err
  1698.        add  si,800h
  1699.        pop  cx
  1700.        loop @@wlp
  1701.        pop  ds
  1702.       ret
  1703. ; end fwrite
  1704. @@fread:
  1705.        push ds
  1706.        mov  si,ovl_base
  1707.        mov  cx,4               ; do 4*32K
  1708. @@rlp:
  1709.        push cx
  1710.        mov  bx,handle
  1711.        mov  cx,8000h
  1712.        mov  ds,si
  1713.        mov  dx,0
  1714.        DOS  READ_FROM_HANDLE
  1715.        CALLC disp_disk_err
  1716.        add  si,800h
  1717.        pop  cx
  1718.        loop @@rlp
  1719.        pop  ds
  1720.       ret
  1721. ; end fread
  1722. dos_shell endp
  1723.  
  1724.  
  1725. init_ramdisc proc
  1726.        push es
  1727.        PUSHR <ax,cx>
  1728.        mov ax,ramdisklen          ; in paragraphen
  1729.        LOG2(64)                   ; nach cl (1024/16)
  1730.        shr ax,cl                  ; ax:=ramdisk len in KB
  1731.        and ax,0fff0h or 1100b     ; um Vielfache von 4K zu bekommen
  1732.        cmp ax,max_rd_size
  1733.        jna short @@rd_too_big
  1734.        mov ax,max_rd_size
  1735. @@rd_too_big:
  1736.        push ax
  1737.        LOG2(4)
  1738.        shr ax,cl                  ; ax/=4
  1739.        mov lasttrack_rd,al        ; Tracks zu 4 K
  1740.        pop ax
  1741.                                   ; dsm=ramdisklen in K/2 -1 , da bls=2k
  1742.        shr ax,1                   ; geht klar, da sowieso vielfaches von 4
  1743.        dec ax
  1744.        cmp ax,255
  1745.        jna short @@nobig
  1746.        mov ax,255                 ; mehr wie 510k geht im PC sowieso kaum
  1747.    @@nobig:
  1748.        mov dpb1.dsm,ax            ; blockzahl
  1749.        inc ax                     ; da KB=(dsm+1)*2
  1750.        shl ax,1
  1751.        mov ramdisklen,ax          ; KBzahl
  1752.        mov dpb1.bsh,4
  1753.        mov dpb1.blm,15
  1754.        mov dpb1.exm,1             ; blocksize=2048
  1755.        mov dpb1.drm,127           ; dir entries
  1756.        mov dpb1.al0,11000000b
  1757.  
  1758.                                   ; loesche ramdisc
  1759.        mov ax,rdseg_adr
  1760.        mov es,ax
  1761.        mov ax,ramdisklen
  1762. @@clrloop:
  1763.        cmp ax,64 ; k
  1764.        jb  short @@less64
  1765.        push ax
  1766.        mov cx,8000h               ; do 32k words
  1767.        mov di,0
  1768.        mov ax,0e5e5h
  1769.        rep stosw                  ; es:di := E5E5
  1770.        mov ax,es
  1771.        add ax,1000h
  1772.        mov es,ax
  1773.        pop ax
  1774.        sub ax,64
  1775.        jmp @@clrloop
  1776. @@less64:
  1777.        LOG2(512)
  1778.        shl ax,cl                  ; ax*=1024/2 (word)
  1779.        mov cx,ax
  1780.        mov di,0
  1781.        mov ax,0e5e5h
  1782.        rep stosw                  ; es:di := E5E5
  1783.        POPR <cx,ax>
  1784.        pop es
  1785.        call load_ramdisc
  1786.       ret
  1787. init_ramdisc endp
  1788.  
  1789. ; speichere Ramdisk auf Platte
  1790. ;
  1791. ; der LOCAL Befehl legt lokale Auto-Vars auf dem Stack an mit
  1792. ; Laenge AUTO_SIZE
  1793. ;
  1794. save_ramdisc proc
  1795. LOCAL  handle:WORD = AUTO_SIZE
  1796.  
  1797.        push bp
  1798.        mov  bp,sp
  1799.        sub  sp,AUTO_SIZE
  1800.        call ins_dos_disk
  1801.        cmp  ax,MESG_ESC
  1802.        jz   short @@exit
  1803.        call @@fopen
  1804.             jc short @@exit
  1805.        call @@fwrite
  1806.        call @@fclose
  1807.        call ins_cpm_disk
  1808. @@exit:
  1809.        mov  sp,bp
  1810.        pop  bp
  1811.        ret
  1812.  
  1813.  
  1814. @@fopen:
  1815.        mov cx,0
  1816.        mov dx,offset ramdisc_fname
  1817.        DOS CREATE_FILE
  1818.        CALLC disp_disk_err
  1819.        mov handle,ax
  1820.        ret
  1821.  
  1822. @@fclose:
  1823.        mov bx,handle
  1824.        DOS CLOSE_FILE
  1825.        CALLC disp_disk_err
  1826.        ret
  1827.  
  1828. @@fwrite:
  1829.        ; erst mal Ramdiskgroesse schreiben, beim Laden muss sie stimmen
  1830.  
  1831.        mov bx,offset secbuf
  1832.        mov ax,ramdisklen
  1833.        mov [bx],ax
  1834.        mov dx,bx
  1835.        mov bx,handle
  1836.        mov cx,2
  1837.        DOS WRITE_TO_HANDLE
  1838.        CALLC disp_disk_err
  1839.  
  1840.        mov bx,rdseg_adr
  1841.        mov ax,ramdisklen
  1842. @@wrtloop:
  1843.        cmp  ax,0                  ; fertig ?
  1844.                                   ; 0 oder negativ = Abbruch
  1845.        jle short @@wrtexit
  1846.        push ax
  1847.        cmp ax,32                  ; kilobyte
  1848.        mov  cx,8000h ; 32k
  1849.        ja  short @@more32
  1850.        LOG2(1024)                 ; nach cl
  1851.        shl ax,cl                  ; ax*=1024
  1852.        mov cx,ax                  ; cx = Laenge in Byte
  1853. @@more32:
  1854.        push bx
  1855.          push ds
  1856.          push bx
  1857.          pop  ds
  1858.          mov  bx,handle           ; klappt, da ueber SS:BP
  1859.          mov  dx,0 ; offset
  1860.          DOS WRITE_TO_HANDLE
  1861.          CALLC disp_disk_err
  1862.          pop  ds
  1863.        pop bx
  1864.        pop ax
  1865.        add bx,800h                ; segment um 32k weitersetzen
  1866.        sub ax,32                  ; restlaenge -=32
  1867.       jmp @@wrtloop
  1868. @@wrtexit:
  1869.       ret
  1870. ; end fwrite
  1871. save_ramdisc endp
  1872.  
  1873.  
  1874. ; hole Ramdisk von Platte
  1875. ;
  1876. ; der LOCAL Befehl legt lokale Auto-Vars auf dem Stack an mit
  1877. ; Laenge AUTO_SIZE
  1878. ;
  1879. load_ramdisc proc
  1880. LOCAL  handle:WORD = AUTO_SIZE
  1881.  
  1882.        push bp
  1883.        mov  bp,sp
  1884.        sub  sp,AUTO_SIZE
  1885.        call @@fopen
  1886.        jc   short @@exit           ; nicht da
  1887.  
  1888.        call @@fread
  1889.        call @@fclose
  1890. @@exit:
  1891.        mov  sp,bp
  1892.        pop  bp
  1893.        ret
  1894.  
  1895.  
  1896. @@fopen:
  1897.        mov al,0
  1898.        mov dx,offset ramdisc_fname
  1899.        DOS OPEN_FILE
  1900.        mov handle,ax
  1901.        ret
  1902.  
  1903. @@fclose:
  1904.        mov bx,handle
  1905.        DOS CLOSE_FILE
  1906.        CALLC disp_disk_err
  1907.        ret
  1908.  
  1909. @@fread:
  1910.        mov dx,offset secbuf
  1911.        mov bx,handle
  1912.        mov cx,2
  1913.        DOS READ_FROM_HANDLE
  1914.        CALLC disp_disk_err
  1915.        mov bx,dx
  1916.        mov bx,[bx]
  1917.        cmp bx,ramdisklen
  1918.        ja  short @@rdexit         ; ueberhaupt zu gross
  1919.  
  1920.        mov ax,bx                  ; Laenge Ramdisk auf Platte
  1921.        mov bx,rdseg_adr
  1922. @@rdloop:
  1923.        cmp  ax,0                  ; fertig ?
  1924.        jle short @@rdexit
  1925.        push ax
  1926.        cmp ax,32
  1927.        mov  cx,8000h              ; 32k
  1928.        ja  short @@more32
  1929.        LOG2(1024)                 ; nach cl
  1930.        shl ax,cl                  ; ax*=1024
  1931.        mov cx,ax                  ; cx = Laenge in Byte
  1932. @@more32:
  1933.        push bx
  1934.          push ds
  1935.          push bx
  1936.          pop  ds
  1937.          mov  bx,handle           ; klappt, da ueber SS:BP
  1938.          mov  dx,0                ; offset
  1939.          DOS READ_FROM_HANDLE
  1940.          CALLC disp_disk_err
  1941.          pop  ds
  1942.        pop bx
  1943.        pop ax
  1944.        add bx,800h                ; segment um 32k weitersetzen
  1945.        sub ax,32                  ; restlaenge -=32
  1946.       jmp short @@rdloop
  1947. @@rdexit:
  1948.       ret
  1949. ; end fread
  1950. load_ramdisc endp
  1951.  
  1952. in_emu_flg db FALSE
  1953. count1 db 0
  1954. count2 db 0
  1955. bios88 proc
  1956. ;
  1957. ; bios88 ist handler fuer alle bios calls
  1958. ; In:  al=bios nummer (warm boot = 1)
  1959. ;      cx,bx,dx wie bei cp/m bios calls
  1960. ; Out: di,ah zerstoert
  1961. ;         si kann veraendert sein, falls bios change_si_flag
  1962. ;            hat nach wboot
  1963. ;
  1964. ; waehrend aller bios routinen zeigt ds auf emudata_seg
  1965. ;                                    es     z80cpu_seg
  1966.  
  1967.        mov cs:in_emu_flg,FALSE
  1968.        mov di,emudata_seg
  1969.        mov ds,di
  1970.  
  1971.        mov z80_pc,si
  1972.  
  1973.        cmp breakflag,TRUE
  1974.  
  1975.        CALLZ prg_exit
  1976.  
  1977.        PUSHR <bp,dx>
  1978. ; cx nicht pushen, da cl:=drive # bei wboot
  1979.  
  1980.        cmp al,30
  1981.        jna short @@goodfn
  1982.        mov al,1                   ; illegal function -> warmboot
  1983. @@goodfn:
  1984.        xor ah,ah                  ; bios # = index
  1985.        sal ax,1
  1986.        mov di,ax
  1987.  
  1988. mov al,cs:count1
  1989. cmp al,cs:count2
  1990. jnz short @@xx0
  1991. mov al,ah
  1992. @@xx0:
  1993.          call cs:biostab[di]
  1994.        mov     si,z80_pc
  1995.  
  1996.        POPR  <dx,bp>
  1997.  
  1998.        cmp breakflag,TRUE
  1999.  
  2000.        CALLZ  prg_exit
  2001.  
  2002.        mov di,z80seg_adr
  2003.        mov ds,di
  2004.        mov es,di
  2005.        mov cs:in_emu_flg,TRUE
  2006.        jmp bios88ret
  2007.  
  2008. bios88 endp
  2009.  
  2010.  
  2011. biostab label word
  2012.         dw boot                   ; cold start
  2013.         dw wboot                  ; warm start
  2014.         dw constat                ; console status
  2015.         dw conin                  ; console character in
  2016.         dw conout                 ; console character out
  2017.         dw list                   ; list character out
  2018.         dw punch                  ; punch character out
  2019.         dw reader                 ; reader character out
  2020.         dw home                   ; move head to home position
  2021.         dw seldsk                 ; select disk
  2022.         dw settrk                 ; set track number
  2023.         dw setsec                 ; set sector number
  2024.         dw setdma                 ; set dma address
  2025.         dw read                   ; read disk
  2026.         dw write                  ; write disk
  2027.         dw listst                 ; return list status
  2028.         dw sectran                ; sector translate
  2029.         rept 25-16-1
  2030.           dw wboot                ; not used
  2031.         endm
  2032.         dw cpm3_move              ; move
  2033.         dw cpm_get_time           ; time
  2034.         rept 30-26-1
  2035.           dw wboot                ; not used
  2036.         endm
  2037.         dw userfn                 ; here: used for data transfer dos/cpm
  2038. ;
  2039. ;
  2040. ;  individuelle UPs um jede Funktion auszufuehren
  2041. ;
  2042. boot proc
  2043.  
  2044. ;simplest case is to just perform parameter initialization
  2045.        mov in_boot_flag,TRUE
  2046.        mov bx,offset on_sign_string
  2047.        call puts
  2048.  
  2049.        call instzbios
  2050.  
  2051.        cmp  fmt_file_flg,TRUE
  2052.        CALLZ load_disk_pars
  2053.  
  2054.  
  2055.        call read_sys  ; lade bdos aus file CPMSYS.CPM
  2056.        pushf
  2057.        call ins_cpm_disk
  2058.        popf
  2059.        jnc  short @@goodload ; laden aus File klappte
  2060.        call get_sys   ; BDOS mit BIOS fkt von Diskette laden
  2061. @@goodload:
  2062.  
  2063. ; Copyright von dr ausgeben
  2064.  
  2065.        mov cl,27
  2066.        call crtout
  2067.        mov cl,'k'                 ; pop cursor pos
  2068.        call crtout
  2069.        mov cl,27
  2070.        call crtout
  2071.        mov cl,'J'                 ; Rest vom Fenster loeschen
  2072.        call crtout
  2073.  
  2074.        mov bx,offset cpm_bdos_buf+18h
  2075.        call puts
  2076.  
  2077.        mov bx,offset cr_lf_txt
  2078.        call puts
  2079. ;
  2080. ; berechne adresse von ccp,bdos und bios
  2081. ; dabei wird die JMP CCPENTRY Anweisung bei CCP+0 benutzt
  2082. ;
  2083.        mov di,offset cpm_bdos_buf+807h
  2084.        mov al,[di]
  2085.        cmp al,11h
  2086.        jnz short @@no_standard
  2087.        mov di,offset cpm_bdos_buf+1
  2088.        mov ax,[di]
  2089.        sub ax,35ch                ; ax:=start ccp
  2090. ; CP/M CCP? dann al jetzt 0
  2091.        or al,al
  2092.        jz short @@is_standard
  2093. ; sonst defaultmaessig e400 annehmen
  2094. @@no_standard:
  2095.        mov ax,0e400h
  2096. @@is_standard:
  2097.        mov ccp_adr,ax
  2098.        add  ax,806h
  2099.        mov bdos_adr,ax
  2100.        add  ax,(BDOSLEN-806h)
  2101.        mov bios_adr,ax
  2102.  
  2103.        call reset_crt
  2104.  
  2105.        call init_iobyte
  2106.  
  2107.        mov di,CDISK
  2108.        mov byte ptr es:[di],0     ; select disk zero
  2109.        call reset_punch_buf
  2110.        call reset_reader_buf
  2111.        mov in_boot_flag,FALSE
  2112.        jmp  wboot
  2113. boot endp
  2114.  
  2115. init_iobyte proc
  2116.        mov di,IOBYTE
  2117.        mov byte ptr es:[di],DEFAULT_IOBYTE   
  2118.      ret
  2119. init_iobyte endp
  2120. ;
  2121. ; setze Punch buffer auf leer
  2122. ;
  2123.  
  2124. reset_punch_buf proc
  2125.        mov punch_buf_entries,0
  2126.        mov punch_buf_ptr,offset punch_buf
  2127.        ret
  2128. reset_punch_buf endp
  2129.  
  2130.  
  2131. ;
  2132. ; setze Reader buffer auf nicht belegt
  2133. ;
  2134.  
  2135. reset_reader_buf proc
  2136.        mov reader_empty_flag,FALSE     ; noch nicht lesen versucht
  2137.        mov reader_buf_entries,0
  2138.        mov reader_buf_ptr,offset reader_buf
  2139.        mov reader_file_pointer,0
  2140.        mov reader_file_pointer+2,0
  2141.        ret
  2142. reset_reader_buf endp
  2143.  
  2144. ;
  2145. ; Stringausgabe
  2146. ; In: bx zeigt auf String, Stringende = \0
  2147. ;
  2148. puts proc
  2149. @@loop:
  2150.        mov cl,[bx]
  2151.        or  cl,cl
  2152.        jz  short @@exit
  2153.        inc bx
  2154.        push bx
  2155.        call crtout
  2156.        pop  bx
  2157.        jmp short @@loop
  2158. @@exit:ret
  2159. puts endp
  2160.  
  2161. instzbios proc
  2162. ;
  2163. ; installiere z80 bios
  2164. ; und discparameter
  2165. ;
  2166.  
  2167.        PUSHR <si,di,cx>
  2168.  
  2169.          mov  si,offset zbiosbeg
  2170.          mov  di,ZBIOS
  2171.          mov  cx,zbiosend-zbiosbeg
  2172.          cld
  2173.          rep movsb                ; es:di := ds:si
  2174.  
  2175.        POPR <cx,di,si>
  2176.        ret
  2177. instzbios endp
  2178.  
  2179.  
  2180. instjp proc
  2181. ;
  2182. ; installiere z80 bios Sprungleiste bei bios_adr
  2183. ;
  2184. ; register o.k.
  2185. ;
  2186. ; darf nicht aufgerufen werden, bevor bios_adr
  2187. ; von boot aufgesetzt wurde
  2188. ;
  2189.  
  2190.        PUSHR <si,di,cx>
  2191.  
  2192.          mov  si,offset wboote-3
  2193.          mov  di,bios_adr
  2194.          mov  cx,zvecend-wboote+3
  2195.          cld
  2196.          rep movsb                ; es:di := ds:si
  2197.  
  2198.        POPR <cx,di,si>
  2199.  
  2200.        ret
  2201. instjp endp
  2202.  
  2203.  
  2204. read_sys  proc
  2205. ;
  2206. ; lade cp/m bdos aus file CPMSYS.CPM in buffer
  2207. ; um es durch warm boot zu benutzen
  2208. ;
  2209. ; das File entspricht dem durch MOVCPM erzeugten Speicherauszug
  2210. ; dabei beginnt das eingentlich System erst ab Offset 880h
  2211.  
  2212. MOVCPM_OFFS = 880H
  2213.  
  2214.      PUSHR <ax,bx,cx,dx,si>
  2215.        mov al,0
  2216.        mov dx,offset cpmsys_fileName
  2217.        DOS OPEN_FILE
  2218.        jc  short @@exit
  2219.        mov si,ax
  2220.        ; setze Filepointer auf CCP Anfang im File
  2221.        mov cx,0                   ; cx:dx: offset
  2222.        mov dx,MOVCPM_OFFS
  2223.        mov al,0                   ; offset from start
  2224.        mov bx,si
  2225.        DOS MOVE_FILE_POINTER
  2226. ;
  2227. ; emudata_seg:buffer := CPMSYS.CPM
  2228. ;
  2229.        mov cx,BDOSLEN             ; Laenge
  2230.        mov bx,si                  ; handle
  2231.        mov dx,offset cpm_bdos_buf
  2232.        DOS READ_FROM_HANDLE
  2233.        jc  short @@exit
  2234.        mov bx,si
  2235.        DOS CLOSE_FILE
  2236.        CALLC disp_disk_err
  2237. @@exit:
  2238.        POPR <si,dx,cx,bx,ax>
  2239.        ret
  2240. read_sys  endp
  2241.  
  2242.  
  2243. ; System von SystemSpuren laden
  2244.  
  2245. ; while sector in systemsectoren do
  2246. ;    lies sector
  2247. ;    if an Adresse     String COPYRIGHT 1979 ..
  2248. ;       sys=naechste SYS_SECS sektoren
  2249. ;       lies sys
  2250. ;       exit
  2251. ;       mache Checksumme ueber sys
  2252. ;       if falsch
  2253. ;          "no sys"
  2254. ;       endif
  2255. ;    endif
  2256. ; endwhile
  2257. ; "no sys"
  2258.  
  2259. get_sys proc
  2260. LOCAL  sys_recs,last_sys_rec:WORD = AUTO_SIZE
  2261.  
  2262.        push bp
  2263.        mov  bp,sp
  2264.        sub  sp,AUTO_SIZE
  2265. @@get_sys_loop:
  2266.        call login_disc
  2267.        call home                  ; else dir track will not be read
  2268.        mov  ah,0                  ; take drive A: = floppy disc
  2269.        mov  al,dpb0.off-dpb0.spt  ; off
  2270.        call get_dpb_entrie        ; nach bx
  2271.        push bx
  2272.        mov  ah,0                  ; A:
  2273.        mov  al,dpb0.spt-dpb0.spt  ; spt
  2274.        call get_dpb_entrie        ; nach bx
  2275.        pop  ax
  2276.        mul  bx                    ; ax:=system records
  2277.        mov  sys_recs,ax
  2278.        mov  cx,0
  2279. ; im Systembereich nach String "COPYRIGHT (C) 1979 " suchen
  2280. @@srch_loop:
  2281.        cmp  cx,sys_recs
  2282.        jnc  short @@read_err      ; schon ausserhalb sys
  2283.        push cx  ; sector
  2284.        push cx
  2285.        mov  cx,DEFAULT_DMA
  2286.        call setdma
  2287.        pop  cx
  2288.        mov  ah,0                  ; A:
  2289.        call set_abs_sect
  2290.        call read
  2291.        pop  cx
  2292.        cmp  al,1
  2293.        jz   short @@read_err
  2294.        call @@compare
  2295.        jz   short @@found
  2296.        inc  cx
  2297.        jnz  @@srch_loop
  2298. @@found:
  2299.        mov  bx,DEFAULT_DMA
  2300.        push cx
  2301.        add  cx,SYS_SECS
  2302.        mov  last_sys_rec,cx
  2303.        pop  cx
  2304. @@loop:
  2305.        push cx  ; sector
  2306.        push bx  ; dma
  2307.        push cx
  2308.        mov  cx,bx
  2309.        call setdma
  2310.        pop  cx
  2311.        mov  ah,0                  ; take drive A: = floppy disc
  2312.        call set_abs_sect
  2313.        call read
  2314.        pop  bx
  2315.        pop  cx
  2316.        cmp  al,1
  2317.        jz   short @@read_err
  2318.        add  bx,RECORD_LEN
  2319.        inc  cx
  2320.        cmp  cx,last_sys_rec
  2321.        jnz  @@loop
  2322.  
  2323.        jmp  short @@good_load
  2324.  
  2325. @@read_err:
  2326.        mov  bx,offset no_sys
  2327.        call puts
  2328.        call crtin
  2329.        jmp  @@get_sys_loop
  2330.  
  2331. @@good_load:
  2332.  
  2333. ; System aus CP/M Segment nach Datensegment uebertragen
  2334.  
  2335.        PUSHR <si,di,bx,cx,ax>
  2336.        push ds
  2337.        push es
  2338.          mov di,offset cpm_bdos_buf
  2339.          mov si,DEFAULT_DMA
  2340.          mov ax,z80seg_adr
  2341.          mov ds,ax
  2342.          mov ax,emudata_seg
  2343.          mov es,ax
  2344.          mov cx,BDOSLEN/2
  2345.          cld
  2346.          rep movsw                ; es:di := ds:si
  2347.        pop es
  2348.        pop ds
  2349.        POPR <ax,cx,bx,di,si>
  2350.        mov  sp,bp
  2351.        pop  bp
  2352.        ret
  2353. @@compare:
  2354.        PUSHR <si,di,cx,ax>
  2355.        mov  si,offset bdos_str
  2356.        mov  di,DEFAULT_DMA+10H
  2357.        mov  cx,bdos_str_end-bdos_str
  2358. @@cp_loop:
  2359.        mov al,[es:di]
  2360.        mov ah,[si]
  2361.        inc si
  2362.        inc di
  2363.        cmp al,ah
  2364.        jnz  short @@cp_exit
  2365.        loop @@cp_loop
  2366. @@cp_exit:
  2367.        POPR <ax,cx,di,si>
  2368.        ret
  2369.  
  2370. get_sys endp
  2371. ;
  2372.  
  2373. set_abs_sect proc    ; absoluten Sektor in cx, drive ah setzen
  2374.        push cx
  2375.        mov  al,0                  ; spt
  2376.        call get_dpb_entrie        ; nach bx
  2377.        pop  ax
  2378.        mov  dx,0
  2379.        div  bx
  2380.        push dx
  2381.        mov  cx,ax
  2382.        call settrk
  2383.        pop  cx
  2384.        call setsec
  2385.        ret
  2386. set_abs_sect endp
  2387.  
  2388.  
  2389. wboot proc
  2390.  
  2391.      push   di
  2392.        call   copy_bdos
  2393.        call   instjp              ; bios Sprungleiste installieren
  2394. ;
  2395. ; 0000h := JP WBOOT
  2396. ; 0005h := JP BDOS
  2397. ;
  2398.        mov     di,0               ; start cp/m memory
  2399.        mov     byte ptr es:[di+0],0c3h
  2400.        mov     bx,bios_adr
  2401.        add     bx,3               ; bx:=warmboot
  2402.        mov     es:[di+1],bx       ; set address field for jmp at 0
  2403. ;
  2404.        mov     byte ptr es:[di+5],0c3h
  2405.        mov     bx,bdos_adr        ; bdos entry point
  2406.        mov     es:[di+6],bx       ; address field of jump at 5 to bdos 
  2407. ;
  2408.        mov     cx,DEFAULT_DMA     ; default dma address is 80h
  2409.        call   setdma
  2410.  
  2411.        call login_disc ; physikalisches Login
  2412. ;
  2413.        mov     ax,ccp_adr
  2414.        mov     z80_pc,ax          ; jp ccp
  2415.  
  2416.        mov     di,CDISK
  2417.        mov     cl,es:[di]         ; get current disk number & send to ccp 
  2418.      pop di
  2419.      ret                          ;go to cp/m for further processing
  2420.  
  2421. copy_bdos:
  2422.        PUSHR <si,di,cx>
  2423.  
  2424.          mov di,ccp_adr
  2425.          mov si,offset cpm_bdos_buf
  2426.          mov cx,BDOSLEN/2
  2427.          rep movsw                ; es:di := ds:si
  2428.  
  2429.        POPR <cx,di,si>
  2430.        ret
  2431.  
  2432. wboot  endp
  2433. ;
  2434.  
  2435. ;
  2436. ;
  2437. constat proc
  2438. ;
  2439. ; console status, return 0ffh if character ready, 00h,Z_flag if not
  2440. ;
  2441. ; Out: al=status
  2442. ;
  2443.         mov bx,IOBYTE
  2444.         mov bl,es:[bx]
  2445.         and bx,11b
  2446.         add bx,bx
  2447.         jmp cs:consttab[bx]
  2448.  
  2449. consttab label word
  2450.        dw offset crtinstat
  2451.        dw offset crtinstat
  2452.        dw offset readstat
  2453.        dw offset crtinstat
  2454.  
  2455. constat endp
  2456.  
  2457. ;
  2458. ;
  2459. conin proc   ; CON:
  2460. ;
  2461. ; Out: al=char
  2462. ;
  2463.         mov bx,IOBYTE
  2464.         mov bl,es:[bx]
  2465.         and bx,11b
  2466.         add bx,bx
  2467.         jmp cs:conintab[bx]
  2468. conintab label word
  2469. ; -> consttab
  2470.        dw offset crtin      ;  TTY:
  2471.        dw offset crtin      ;  CRT:
  2472.        dw offset reader     ;  BAT:
  2473.        dw offset crtin      ;  UC1:
  2474. conin endp
  2475.  
  2476. conout proc  ; CON:
  2477. ;
  2478. ; In: c=char
  2479. ;
  2480.         mov bx,IOBYTE
  2481.         mov bl,es:[bx]
  2482.         and bx,11b
  2483.         add bx,bx
  2484.         mov al,1
  2485.         jmp cs:conouttab[bx]
  2486. conouttab label word
  2487.        dw offset crtout    ;  TTY:
  2488.        dw offset crtout    ;  CRT:
  2489.        dw offset punch     ;  BAT:
  2490.        dw offset crtout    ;  UC1:
  2491. conout endp
  2492.  
  2493.  
  2494. ;
  2495. ; test auf ^C, wenn ja, warm boot
  2496. ;
  2497. tst_ctrl_c proc
  2498.        push ax
  2499.        call constat
  2500.        jz   short @@exit
  2501.        call crtin
  2502.        cmp  al,3                  ; ^C
  2503.        clc                        ; cy = no error
  2504.        jnz  short @@exit
  2505.        mov  bx,offset control_c_txt
  2506.        call puts
  2507.        stc
  2508. @@exit:
  2509.        pop ax
  2510.        ret
  2511. tst_ctrl_c endp
  2512.  
  2513. list proc  ; LST:
  2514.     mov bx,IOBYTE
  2515.     mov bl,es:[bx]
  2516.     and bx,11000000b
  2517.     shr bx,6-1
  2518.     jmp cs:lsttab[bx]
  2519. lsttab label word
  2520.        dw offset crtout      ; TTY:
  2521.        dw offset crtout      ; CRT:
  2522.        dw offset lpt0list    ; LPT:
  2523.        dw offset lpt1list    ; UL1:
  2524. list endp
  2525.  
  2526. lpt0list proc
  2527.         xor dx,dx
  2528.         jmp short lptlist
  2529. lpt0list endp
  2530.  
  2531. lpt1list proc
  2532.         mov dx,1
  2533.         jmp short lptlist
  2534. lpt1list endp
  2535.  
  2536. ;
  2537. ; list character in register c auf Drucker
  2538. ;
  2539. lptlist proc
  2540.        call listst
  2541.        jnz  short @@ok
  2542.        call tst_ctrl_c
  2543.        jnc  short lptlist
  2544.        mov  z80_pc,0              ; Z80 macht ab Adresse 0 weiter
  2545.        ret
  2546. @@ok:
  2547.        mov al,cl                  ; char nach register a
  2548.        xor ah,ah                  ; list character
  2549.        push bp
  2550.        int 17h
  2551.        pop bp
  2552.        cmp ah,10h                 ; ok
  2553.        jnz short lptlist
  2554.        ret
  2555. lptlist endp
  2556. ;
  2557. ; return list status (0,Z_flag if not ready, 1 if ready)
  2558. ;
  2559. listst proc
  2560.        push dx
  2561.        mov ah,2                   ; test printer
  2562.        int 17h
  2563.        mov al,1
  2564.        cmp ah,90h                 ; on line und not busy
  2565.        jz short @@lret
  2566.        dec al
  2567. @@lret:
  2568.        or  al,al
  2569.        pop dx
  2570.        ret
  2571. listst endp
  2572.  
  2573.  
  2574. com0list proc
  2575.         xor dx,dx
  2576.         jmp short comlist
  2577. com0list endp
  2578.  
  2579. com1list proc
  2580.         mov dx,1
  2581.         jmp short comlist
  2582. com1list endp
  2583.  
  2584. comlist proc
  2585.         mov ah,1
  2586.         mov al,cl
  2587.         int 14h
  2588.         ret
  2589. comlist endp
  2590.  
  2591. com0read proc
  2592.         xor dx,dx
  2593.         jmp short comread
  2594. com0read endp
  2595.  
  2596. com1read proc
  2597.         mov dx,1
  2598.         jmp short comread
  2599. com1read endp
  2600.  
  2601. comread proc
  2602.         mov ah,2
  2603.         mov al,cl
  2604.         int 14h
  2605.         ret
  2606. comread endp
  2607.  
  2608. date_dos_2_cpm proc  ; out: AX=tage seit 1.Jan. 1978
  2609.     push bx
  2610.     push cx
  2611.     push dx
  2612.     DOS GET_DATE
  2613.     push dx
  2614.     mov bx,1978
  2615.     inc cx      ; ein Jahr zuviel, für Test ob akt. Schaltjahr
  2616.     MOV AX,0
  2617. @@add_loop:
  2618.     cmp  bx,cx  ; aktuelles Jahr erreicht ?
  2619.     jz short @@years_done
  2620.  
  2621.     mov  dx,bx
  2622.     and  dx,11b ; 0 => durch 4 teilbar
  2623.     sub  dx,1   ; 0 => cy
  2624.     mov  dx,365
  2625.     adc  dx,0   ; wird unten zum abziehen gebraucht
  2626.     add  ax,dx  ; 0 => 366
  2627.  
  2628.     inc  bx
  2629.     jmp  @@add_loop
  2630. @@years_done:
  2631.     sub ax,dx  ; da ein Jahr oben zuviel, 365 oder 366 wieder weg
  2632.     pop dx   ; mon/tag
  2633.     mov ch,0
  2634.     mov cl,dl
  2635.     add ax,cx ; tag
  2636.     mov cl,dh ; monat
  2637.     dec cl    ; da aktueller Monat schon dran
  2638.     jz  short @@is_jan
  2639.     mov bx,offset month_tab
  2640. @@add_months:
  2641.     mov dl,[bx]    ; verschieden lange monate
  2642.     inc bx
  2643.     mov dh,0
  2644.     add ax,dx
  2645.     loop @@add_months
  2646. @@is_jan:
  2647.     pop dx
  2648.     pop cx
  2649.     pop bx
  2650.     ret
  2651. date_dos_2_cpm endp
  2652.  
  2653. cpm3_move proc   ; move wie bei cpm plus bios
  2654.     push ds
  2655.     push es
  2656.     pop  ds
  2657.     mov  si,bx
  2658.     mov  di,dx
  2659.     add  bx,cx      ; hl=blockende
  2660.     cmp  bx,dx      ; größer Ziel ?
  2661.     jnb   short @@topdown
  2662.     cld
  2663.     rep movsb
  2664.     jmp short @@exit
  2665. @@topdown:
  2666.     add si,cx
  2667.     add di,cx
  2668.     mov bx,si
  2669.     mov dx,di
  2670.     dec si
  2671.     dec di
  2672.     std
  2673.     rep movsb
  2674.     pop ds
  2675.     ret
  2676. @@exit:
  2677.     mov bx,si
  2678.     mov dx,di
  2679.     pop ds
  2680.    ret
  2681. cpm3_move endp
  2682.  
  2683.  
  2684. cpm_get_time proc   ; dos zeit nach cpm plus zeit
  2685.     PUSHR <AX,CX,DX>
  2686.     cmp cl,0
  2687.     jnz short @@exit ; set time ignorieren
  2688.     call date_dos_2_cpm
  2689.     push ds
  2690.     push es
  2691.     pop  ds
  2692.     mov @date+ZBIOSDISPL,ax
  2693.     DOS GET_TIME
  2694.     mov dl,10
  2695.     mov al,cl
  2696.     mov ah,0         ; sonst divide overflow
  2697.     div dl
  2698.     mov cl,4
  2699.     shl al,cl
  2700.     or  al,ah
  2701.     mov @min+ZBIOSDISPL,al
  2702.     mov al,ch
  2703.     mov ah,0
  2704.     div dl
  2705.     shl al,cl
  2706.     or  al,ah
  2707.     mov @hour+ZBIOSDISPL,al
  2708.     mov al,dh
  2709.     mov ah,0
  2710.     div dl
  2711.     shl al,cl
  2712.     or  al,ah
  2713.     mov @sec+ZBIOSDISPL,al
  2714.     pop ds
  2715.     mov bx,(offset @date)+ZBIOSDISPL
  2716. @@exit:
  2717.     POPR <DX,CX,AX>
  2718.     ret
  2719. cpm_get_time endp
  2720.         
  2721. del_punch_file proc
  2722.        mov dx,offset punch_fileName
  2723.        DOS DELETE_FILE
  2724.        ret
  2725. del_punch_file endp
  2726.  
  2727. ; on entry to all userfunctions:
  2728. ;  c = proc number
  2729. ; de = entry data
  2730. ; hl = pointer to variable, where to store return value
  2731. userfn proc
  2732.         cmp cl,10
  2733.         ja wboot             ; illegal function
  2734.         mov ch,0
  2735.         mov si,cx
  2736.         add si,si
  2737.         push bx              ; hl
  2738.         call cs:userfntab[si]
  2739.         pop  di
  2740.         xchg ax,bx
  2741.         stosw                ; es:di:=ax
  2742.         mov  ax,bx
  2743.         ret
  2744.  
  2745. userfntab label word
  2746.         dw versionfn         ; return version NR
  2747.         dw openout           ; open out to dos
  2748.         dw closeout          ; close out to dos
  2749.         dw doswrite          ; write record to dos
  2750.         dw dosexec           ; execute dos command
  2751.         dw setfname          ; set filename for getnextname ("*.c")
  2752.         dw getnextname       ; return next suitable name
  2753.         dw openin            ; open in dosfile
  2754.         dw dosread           ; read next record from dos
  2755.         dw closein           ; abandon dos file
  2756.         dw get_phys_drv      ; return physical drive number
  2757. ; don't forget to adapt test at start of userfn
  2758.  
  2759. userfn endp
  2760.  
  2761. ; return physical drive number
  2762. ; out: al = physical drive number
  2763. get_phys_drv proc
  2764.         mov al,cpm_drive
  2765.         mov ah,0
  2766.         ret
  2767. get_phys_drv endp
  2768.  
  2769. ; execute dos command
  2770. ; in: DE-> zero terminated command line
  2771. ; out: -
  2772. dosexec proc
  2773.         mov si,dx
  2774.         mov di,offset usr_lne
  2775.         mov cx,80            ; in order not to copy too much
  2776. @@loop:
  2777.         mov al,es:[si]
  2778.         cmp al,0
  2779.         jz  short @@copied
  2780.         mov ds:[di],al
  2781.         inc si
  2782.         inc di
  2783.         loop @@loop
  2784. @@copied:
  2785.         mov byte ptr ds:[di],13
  2786.         mov al,83
  2787.         sub al,cl
  2788.         mov byte ptr exec_usr_lne,al
  2789.         mov exec_usr_flg,TRUE
  2790.         mov [exec_par_block+2],offset exec_usr_lne
  2791. mov di,offset exec_par_block
  2792.         call dos_shell
  2793.         mov [exec_par_block+2],offset exec_cmd_line
  2794.         mov exec_usr_flg,FALSE
  2795.         mov al,0
  2796.        ret
  2797. dosexec endp
  2798.  
  2799. ; return version NR
  2800. versionfn proc
  2801.         mov ax,41751         ; identification of ZSIM
  2802.         mov bx,VERSNR
  2803.         ret
  2804. versionfn endp
  2805.  
  2806. ; open out file to dos
  2807. ; in: DE-> zero terminated filename
  2808. ; out: if error A=1 else 0
  2809. ; first try to close an old file
  2810. openout proc
  2811.            push dx
  2812.            call closeout
  2813.            pop  dx
  2814.            push ds
  2815.            mov ax,es
  2816.            mov ds,ax         ; ds-> z80cpu seg
  2817.            mov cl,0 ; write only
  2818.            DOS CREATE_FILE
  2819.            CALLC disp_disk_err
  2820.            pop ds
  2821.            mov openout_handle,ax
  2822.            mov al,0
  2823.            adc al,0         ; error -> 1 else 0
  2824.           ret
  2825. openout endp
  2826.  
  2827. ; close outfile
  2828. ; in: -
  2829. ; out: if error A=1 else 0
  2830. closeout proc
  2831.         mov bx,openout_handle
  2832.         mov openout_handle,0
  2833.         cmp bx,0
  2834.         stc
  2835.         jz  short @@exit
  2836.         DOS CLOSE_FILE
  2837.         CALLC disp_disk_err
  2838. @@exit:
  2839.         mov al,0
  2840.         adc al,0
  2841.        ret
  2842. closeout endp
  2843.  
  2844. ; write 128 bytes to dos
  2845. ; in: DE -> data
  2846. ; out: if error A=1 else 0
  2847. doswrite proc
  2848.         push ds
  2849.         mov bx,openout_handle
  2850.         mov ax,es
  2851.         mov ds,ax         ; ds-> z80cpu seg
  2852.         mov cx,128
  2853.         DOS WRITE_TO_HANDLE
  2854.         CALLC disp_disk_err
  2855.         pop ds
  2856.         mov al,0
  2857.         adc al,0
  2858.        ret
  2859. doswrite endp
  2860.  
  2861. ; set filename for getnextname ("*.c\0")
  2862. ; in: DE -> fname
  2863. ; out: if error A=1 else 0
  2864. setfname proc
  2865.         mov cx,80
  2866.         mov di,offset dosfilespec
  2867.         mov si,dx
  2868. @@loop:
  2869.         mov al,es:[si]
  2870.         mov ds:[di],al
  2871.         or al,al
  2872.         jz short @@done
  2873.       
  2874.         inc si
  2875.         inc di
  2876.         loop @@loop
  2877.         mov al,1             ; Name is too long
  2878. @@done:                      ; A is 0
  2879.         mov new_dosfilespecflg,TRUE
  2880.         ret
  2881. setfname endp
  2882.  
  2883. ; return next suitable name
  2884. ; in: DE -> buffer to store filename
  2885. ; out: if error A=1 else 0
  2886. ; if found copy filename to buffer
  2887. getnextname proc
  2888.         push dx
  2889.  
  2890.         push ds
  2891.         lds dx,default_dta
  2892.         DOS SET_DTA
  2893.         pop ds
  2894.  
  2895.         TSTNCLR new_dosfilespecflg
  2896.         mov cx,0
  2897.         mov dx,offset dosfilespec
  2898.         jz short @@open_next
  2899.           DOS FIND_FIRST
  2900.           jmp short @@cont
  2901. @@open_next:
  2902.         DOS FIND_NEXT
  2903. @@cont:
  2904.         pop di
  2905.         mov al,1
  2906.         jc short @@exit
  2907.  
  2908.         push ds
  2909.         lds si,default_dta
  2910.         add si,1eh           ; si-> file name in dta returned
  2911. @@loop:
  2912.         lodsb                ; copy filename
  2913.         stosb
  2914.         or al,al             ; \0 ?
  2915.         jnz @@loop
  2916.         pop ds
  2917. @@exit:
  2918.         ret
  2919. getnextname endp
  2920.  
  2921. ; open in dosfile
  2922. ; in: DE -> filename\0
  2923. ; out: if error A=1 else 0
  2924. ; first try to close an old file
  2925. openin proc
  2926.         push dx
  2927.         call closein
  2928.         pop  dx
  2929.         push ds
  2930.         mov ax,es
  2931.         mov ds,ax
  2932.         mov al,0                                               
  2933.         DOS OPEN_FILE
  2934.         pop ds
  2935.         mov openin_handle,ax
  2936.         mov al,0
  2937.         adc al,0
  2938.         ret
  2939. openin endp
  2940.  
  2941. ; read next record from dos
  2942. ; in: DE -> buffer
  2943. ; out: if error A=1 else 0;HL=length (1..128)
  2944. dosread proc
  2945.         mov bx,openin_handle
  2946.         mov cx,128
  2947.         push ds
  2948.         mov ax,es
  2949.         mov ds,ax
  2950.         DOS READ_FROM_HANDLE
  2951.         pop ds
  2952.         mov bx,ax            ; length actually read
  2953.         mov al,0
  2954.         adc al,0
  2955.        ret
  2956. dosread endp
  2957.  
  2958. ; abandon dos file
  2959. ; in: -
  2960. ; out: if error A=1 else 0
  2961. ; is called before every openin
  2962. closein proc
  2963.         mov bx,openin_handle
  2964.         mov openin_handle,0
  2965.         cmp bx,0
  2966.         stc
  2967.         jz  short @@exit
  2968.         DOS CLOSE_FILE
  2969. @@exit:
  2970.         mov al,0
  2971.         adc al,0
  2972.        ret
  2973. closein endp
  2974.  
  2975. ;
  2976. ; punch character in register c
  2977. ; wird durch Output in File auf MsDos Disk ersetzt
  2978. ; Buffer wird auf File geschrieben, falls er voll ist
  2979. ; und  auch am Ende des Emulator-
  2980. ; laufs
  2981. ;
  2982. punch proc   ; PUN:
  2983.     mov bx,IOBYTE
  2984.     mov bl,es:[bx]
  2985.     and bx,110000b
  2986.     shr bx,4-1
  2987.     jmp cs:puntab[bx]
  2988. puntab label word
  2989.        dw offset filepunch   ; TTY:
  2990.        dw offset filepunch   ; PTP:
  2991.        dw offset com0list    ; UP1:
  2992.        dw offset com1list    ; UP2:
  2993. punch endp
  2994.  
  2995. filepunch proc
  2996. ;
  2997. ; fill buffer until full or eof
  2998. ; open file
  2999. ; if not exist file
  3000. ;    create file
  3001. ; endif
  3002. ; go to end of file
  3003. ; append character
  3004. ; close file
  3005. ; empty buffer
  3006. ;
  3007. ; falls punch von bios88 aufgerufen wurde, ist al<>0
  3008. ; nach Aufruf von wrt_out_punch aber al=0
  3009.  
  3010.      PUSHR <ax,bx,cx,dx,si>
  3011.        cmp al,0
  3012.        jz  short @@write_out
  3013.        mov bx,punch_buf_ptr
  3014.        mov [bx],cl                ; buf:=character
  3015.        inc bx
  3016.        mov punch_buf_ptr,bx
  3017.        inc punch_buf_entries
  3018.        cmp punch_buf_entries,PUNCH_BUF_SIZE
  3019.        jnz short @@exit
  3020. @@write_out:
  3021.        call ins_dos_disk
  3022.        cmp  ax,MESG_ESC
  3023.        jz   short @@exit
  3024.        mov al,1
  3025.        mov dx,offset punch_fileName
  3026.        DOS OPEN_FILE
  3027.        jnc short @@file_found
  3028.            mov cl,0 ; write only
  3029.            DOS CREATE_FILE
  3030.            CALLC disp_disk_err
  3031. @@file_found:
  3032.  
  3033.        mov bx,ax                  ; handle
  3034.        mov cx,0
  3035.        mov dx,0
  3036.        mov al,2                   ; offset from end
  3037.        DOS MOVE_FILE_POINTER
  3038.  
  3039.        mov cx,punch_buf_entries
  3040.        mov dx,offset punch_buf
  3041.        DOS WRITE_TO_HANDLE
  3042.        CALLC disp_disk_err
  3043.  
  3044.        DOS CLOSE_FILE
  3045.  
  3046.        call reset_punch_buf
  3047.        call ins_cpm_disk
  3048. @@exit:
  3049.        POPR <si,dx,cx,bx,ax>
  3050.        ret
  3051. filepunch endp
  3052.  
  3053. wrt_out_punch proc
  3054.        cmp punch_buf_entries,0
  3055.        jz  short @@exit
  3056.        xor  al,al
  3057.        call punch
  3058. @@exit:
  3059.        ret
  3060. wrt_out_punch endp
  3061. ;
  3062. ; RDR:
  3063. reader proc       ;read character into register a from reader device
  3064.         mov bx,IOBYTE
  3065.         mov bl,es:[bx]
  3066.         and bx,1100b
  3067.         shr bx,2-1
  3068.         jmp cs:rdrtab[bx]
  3069. rdrtab label word
  3070.        dw offset filereader  ; TTY:
  3071.        dw offset filereader  ; PTR:
  3072.        dw offset com0read    ; UR1:
  3073.        dw offset com1read    ; UR2:
  3074. reader endp
  3075.  
  3076. filereader proc
  3077. ; if buffer empty
  3078. ;    open file
  3079. ;    if file not present
  3080. ;       exit
  3081. ;    else
  3082. ;       fill buffer
  3083. ;    endif
  3084. ; endif
  3085. ; read char
  3086.  
  3087.        cmp reader_empty_flag,TRUE
  3088.        jz  short @@empty
  3089.        cmp reader_buf_entries,0
  3090.        jnz short @@do_read
  3091.  
  3092. ; Buffer fuellen
  3093.          mov al,0
  3094.          mov dx,offset reader_fileName
  3095.          DOS OPEN_FILE
  3096.          jc  short @@empty
  3097.          push ax
  3098.          mov bx,ax
  3099.          mov dx,reader_file_pointer
  3100.          mov cx,reader_file_pointer+2
  3101.          PUSHR <dx,cx>
  3102.           add dx,READER_BUF_SIZE
  3103.           adc cx,0
  3104.           mov reader_file_pointer,dx
  3105.           mov reader_file_pointer+2,cx
  3106.          POPR  <cx,dx>
  3107.          mov al,0                   ; offset from start
  3108.          DOS MOVE_FILE_POINTER
  3109.          pop bx                     ; handle
  3110.          mov cx,READER_BUF_SIZE
  3111.          mov dx,offset reader_buf
  3112.          DOS READ_FROM_HANDLE
  3113.          push ax
  3114.          DOS CLOSE_FILE
  3115.          pop ax
  3116.          cmp ax,0
  3117.          jz  short @@empty
  3118.  
  3119.  ; buffer erfolgreich gefuellt
  3120.          mov reader_empty_flag,FALSE
  3121.          mov reader_buf_entries,ax
  3122.          mov reader_buf_ptr,offset reader_buf
  3123.  
  3124. @@do_read:
  3125.          mov bx,reader_buf_ptr
  3126.          mov al,[bx]
  3127.          inc bx
  3128.          mov reader_buf_ptr,bx
  3129.          dec reader_buf_entries
  3130.          jmp short @@exit
  3131. @@empty:
  3132.        mov reader_empty_flag,TRUE
  3133.        mov al,CPM_EOF
  3134.        mov bx,0ffffh       ; hl=FFFF  == Dos File Ende
  3135.        ret
  3136. @@exit:
  3137.        mov bx,0            ; a=hl=gelesenes byte
  3138.        mov bl,al
  3139.        ret
  3140. filereader endp
  3141.  
  3142. readstat proc
  3143.        mov al,0
  3144. ; the following is commented out because else
  3145. ; ccp cancels operations if input is read from bat
  3146. ; and al=ff
  3147. ;       cmp reader_empty_flag,TRUE
  3148.  ;      jz short @@exit
  3149.   ;     dec al
  3150. @@exit:
  3151.        ret
  3152. readstat endp
  3153.  
  3154. ; In:  ah=drive
  3155. ;      al=offset im dpb
  3156. ; Out: bx=word dpb[al]
  3157.  
  3158. get_dpb_entrie proc
  3159.        push si
  3160.        mov  bl,ah
  3161.        call get_dph_adr           ; bx:=dph
  3162.        xor  ah,ah
  3163.        mov  si,ax
  3164.        mov  bx,[es:bx+10]         ; bx:=dpb
  3165.        mov  bx,[es:bx+si]         ; bx:=dpb[ax]
  3166.        pop  si
  3167.        ret
  3168. get_dpb_entrie endp
  3169.  
  3170. ;
  3171. ; select disk in register c
  3172. ;
  3173. seldsk proc
  3174.        cmp cl,NDISKS-1
  3175.        mov bx,0000h               ; 0 = Drive nicht existent
  3176.        ja  short @@exit
  3177.        cmp drv_swap_flag,TRUE
  3178.        jnz short @@noswp
  3179.        mov bl,cl
  3180.        mov cl,1
  3181.        sub cl,bl
  3182. @@noswp:
  3183.        mov diskno,cl
  3184.        mov bl,cl
  3185.        call get_dph_adr
  3186. @@exit:
  3187.        ret
  3188. seldsk endp
  3189.  
  3190. ;  In:  bl:=Drive #
  3191. ;  Out: bx:= disk parameter header address
  3192. ;
  3193. get_dph_adr proc
  3194.        mov bh,0                   ; high order zero
  3195.        push cx
  3196.        LOG2(16)                   ; nach cl
  3197.        sal bx,cl                  ; bx*=16 (size of each header)
  3198.        pop cx
  3199.        add bx,offset dph_base+ZBIOSDISPL
  3200.        ret                        ;hl=.dph_base(diskno*16)
  3201. get_dph_adr endp
  3202.  
  3203. ;
  3204. ;  move to the track 00 position of current drive
  3205. ;  translate this call into a settrk call with parameter 00
  3206. ;
  3207. home proc
  3208.        mov cx,0                   ; select track 0
  3209.        call settrk
  3210.        mov  home_flag,TRUE        ; zur Auswertung durch read_track
  3211.        ret
  3212. home endp
  3213.  
  3214. ;
  3215. ; set track given by register bc
  3216. ;
  3217. settrk proc
  3218.        mov word ptr track,cx
  3219.        ret
  3220. settrk endp
  3221. ;
  3222. ; set sector given by register bc
  3223. ;
  3224. setsec proc
  3225.        mov word ptr sector,cx
  3226.        ret
  3227. setsec endp
  3228.  
  3229. ;
  3230. ;translate the sector given by bc using the
  3231. ;translate table given by de
  3232. ;
  3233. sectran proc
  3234.  
  3235.        mov  bx,cx
  3236.        or   dx,dx                 ; table ptr == 0 ?
  3237.        jz   short @@exit
  3238.        add  cx,cx                 ; index *= 2
  3239.        mov  bx,dx                 ; hl=trans
  3240.        add  bx,cx
  3241.        mov  bx,[es:bx]            ;hl=trans[sector]
  3242. @@exit:
  3243.        ret                        ;with value in hl
  3244. sectran endp
  3245. ;
  3246. ; set dma address given by registers b und c
  3247. ;
  3248. setdma proc
  3249.        mov dmaad,cx
  3250.        ret
  3251. setdma endp
  3252.  
  3253.  
  3254. calcadr proc
  3255. ;
  3256. ; ax:bx := record adresse in Ramdisk
  3257. ; illegal sec: cy
  3258. ;
  3259. ; 1. 64k track  0..15
  3260. ; 2. 64k track 16..31
  3261. ; ..
  3262.        mov al,track
  3263.        cmp al,lasttrack_rd
  3264.        ja short @@badrec
  3265.  
  3266.        mov al,sector
  3267.        cmp al,LAST_SEC1
  3268.        ja short @@badrec
  3269.  
  3270. ; phys recordnum = track * spt + sector
  3271.  
  3272.        PUSHR <cx,dx>
  3273.        mov  ah,RMD
  3274.        mov  al,0                  ; spt
  3275.        call get_dpb_entrie
  3276.        mov  cx,bx                 ; cx:=spt B:
  3277.        mov  ax,word ptr track
  3278.        mul  cx
  3279.        add  ax,word ptr sector    ; ax:=phys record num
  3280.        mov  cx,512                ; 64K = 512 records @ 128 Bytes
  3281.        mov  dx,0
  3282.        div  cx                    ; ax:= # of 64K, dx:=recordnum
  3283.        mov  cx,1000h
  3284.        push dx
  3285.        mul  cx
  3286.        pop  dx
  3287.        mov  bx,rdseg_adr
  3288.        add  bx,ax
  3289.        mov  ax,dx
  3290.        LOG2(RECORD_LEN)
  3291.        shl  ax,cl
  3292.        xchg bx,ax
  3293.        POPR <dx,cx>
  3294.       clc
  3295. @@exit:
  3296.       ret
  3297. @@badrec:
  3298.       stc
  3299.       jmp short @@exit
  3300. calcadr endp
  3301.  
  3302. ;
  3303. read proc
  3304. ;
  3305. ; lies einen record von 128 bytes
  3306. ;
  3307.        cmp  diskno,RMD
  3308.        jnz  short @@rfdisc
  3309.        call calcadr               ; ax:bx := record addresse
  3310.        jc   short @@badsec
  3311.        call rdrec
  3312. @@exit:xor al,al                  ; o.k.
  3313.        ret
  3314. @@badsec:
  3315.        mov al,1
  3316.        ret
  3317.  
  3318. @@rfdisc:
  3319.        call is_valid_rec          ; ax=rec/sec
  3320.        jc   short @@badsec
  3321.  
  3322.        call read_track
  3323.        jc   short @@badsec
  3324. ;
  3325. ; record num ist in ah
  3326. ; ax:bx := adresse Track Buffer
  3327. ;
  3328.        mov  al,READ_OP
  3329.        call get_adr_in_buf        ; nach bx
  3330.        mov  ax,ds                 ; ax := seg track buffer
  3331.        call rdrec
  3332.        jmp  short @@exit
  3333. read endp
  3334.  
  3335. ; berechne Sektoradresse im Buffer
  3336. ; a=sector*128+buf
  3337. ; input: al=READ_OP / WRITE_OP
  3338.  
  3339. get_adr_in_buf proc
  3340.       PUSHR <AX,CX>
  3341.        call is_dir_track
  3342.        mov  bx,offset dirtrbuf
  3343.         jz  short @@calc
  3344.        mov  bx,offset secbuf
  3345.        cmp  al,READ_OP
  3346.         jz  short @@calc
  3347.        mov  bx,offset wrtbuf
  3348. @@calc:
  3349.        xor  ax,ax
  3350.        mov  al,sector
  3351.        LOG2(RECORD_LEN)                  ; nach cl
  3352.        shl  ax,cl                 ; ax *= 128
  3353.        add  bx,ax
  3354.       POPR <CX,AX>
  3355.       RET
  3356. get_adr_in_buf endp
  3357.  
  3358. is_dir_track proc
  3359.       push ax
  3360.        mov  al,track
  3361.        cmp  al,dirtrack
  3362.       pop  ax
  3363.       ret
  3364. is_dir_track endp
  3365.  
  3366. ;
  3367. ;
  3368. ;
  3369. is_valid_rec proc
  3370. ; Out:  cy   sector illegal
  3371. ;
  3372. ; test auf gueltigen track/sector auf DISC
  3373. ;
  3374. COMMENT *
  3375.       mov al,track
  3376.       cmp al,LAST_TRCK0
  3377.       stc
  3378.       ja  short @@exit
  3379.       mov al,sector
  3380.       cmp al,LAST_SEC0
  3381.       stc
  3382.       ja short @@exit
  3383. ; ok, clear cy
  3384. *
  3385.       clc
  3386. @@exit:
  3387.       ret
  3388. is_valid_rec endp
  3389.  
  3390. ;
  3391. ; lies ganzen Track, falls noch nicht im Speicher
  3392. ;
  3393. read_track proc
  3394. ;
  3395. ; Error: cy=1
  3396. ;
  3397.       PUSHR <ax,bx,cx,dx>
  3398.  
  3399. ; der DirTrack wird nur gelesen nach HOME
  3400.  
  3401.       mov  al,track
  3402.       cmp  al,dirtrack
  3403.       jnz  short @@nodir
  3404.       TSTNCLR home_flag
  3405.       mov  bx,offset dirtrbuf
  3406.       jnz  short @@read_dir_track
  3407.       clc
  3408.       jmp short @@exit
  3409. @@nodir:
  3410.        cmp  al,last_track_read
  3411.        jz   short @@exit
  3412.  
  3413.            mov  bx,offset secbuf
  3414.            mov  last_track_read,al
  3415. @@read_dir_track:
  3416.            mov  r_track,al
  3417.  
  3418.            call read_phys_track
  3419.            ; ab jetzt CY nicht mehr veraendern !
  3420.  
  3421. @@exit:
  3422.       POPR <dx,cx,bx,ax>
  3423.       ret
  3424. read_track endp
  3425.  
  3426. ;
  3427. ; lies ganzen Track, in den geschrieben werden soll, ein,
  3428. ;  falls noch nicht im Speicher
  3429. ;
  3430. read_w_track proc
  3431. ;
  3432. ; Error: cy=1
  3433. ;
  3434.       PUSHR <ax,bx,cx,dx>
  3435.       ; der DirTrack ist sowieso im Speicher und braucht
  3436.       ; nicht gelesen werden
  3437.       mov  al,track
  3438.       cmp  al,dirtrack
  3439.       jz  short @@exit
  3440.  
  3441.       cmp  al,last_track_written
  3442.       jz   short @@exit
  3443.  
  3444.       ; falls noetig alten Track im WriteBuffer erst
  3445.       ; ausschreiben
  3446.       call write_out_old_track
  3447.  
  3448.       mov  al,track
  3449.       mov  bx,offset wrtbuf
  3450.       mov  last_track_written,al
  3451.       mov  r_track,al
  3452.       call read_phys_track
  3453.  
  3454.       ; ab jetzt CY nicht mehr veraendern !
  3455.  
  3456. @@exit:
  3457.       POPR <dx,cx,bx,ax>
  3458.       ret
  3459. read_w_track endp
  3460.  
  3461. ; physikalische Sektorlaenge herstellen
  3462. dos_phys_len proc
  3463.        PUSHR <es,ax,di>
  3464.        mov  ax,0
  3465.        mov  es,ax
  3466.        les  di,[es:78h]
  3467.        mov  al,ms_phys_sec_len
  3468.        mov  es:[di+3],al
  3469.        POPR <di,ax,es>
  3470.        ret
  3471. dos_phys_len endp
  3472.  
  3473. ; physikalische Sektorlaenge herstellen
  3474. cpm_phys_len proc
  3475.        PUSHR <es,ax,di>
  3476.        mov  ax,0
  3477.        mov  es,ax
  3478.        les  di,[es:78h]
  3479.        mov  al,cpm_phys_sec_len
  3480.        mov  es:[di+3],al
  3481.        POPR <di,ax,es>
  3482.        ret
  3483. cpm_phys_len endp
  3484.  
  3485. normalize_pointer proc ; es:bx
  3486.        PUSHR <cx,ax>
  3487.         mov ch,bl
  3488.         and ch,0fh
  3489.         LOG2(16)         ; NACH CL
  3490.         shr bx,cl        ; bx:=16
  3491.         mov ax,es
  3492.         add ax,bx
  3493.         mov es,ax
  3494.         mov bx,0
  3495.         mov bl,ch
  3496.        POPR <ax,cx>
  3497.        ret
  3498. normalize_pointer endp
  3499.  
  3500. read_phys_track proc
  3501.       PUSHR <ax,bx,cx,dx>
  3502.  
  3503. ; der naechste Test sollte eigentlich nicht noetig sein, aber
  3504. ; mein 386 Ami Bios weigert sich sonst, den gleichen Track nochmal
  3505. ; zu lesen; jedenfalls kann auch gleich ein Diskwechsel festgestellt
  3506. ; werden
  3507.       call tst_disk_change
  3508.       jz   short @@no_change
  3509.       mov  last_track_read,0ffh
  3510. @@no_change:
  3511.  
  3512.       mov  cl,retry_count
  3513.       xor  ch,ch
  3514. @@tryread:
  3515.         call cpm_phys_len
  3516.         push es
  3517.         mov  ax,emudata_seg
  3518.         mov  es,ax                ; ist sonst z80cpu_seg
  3519.         push cx
  3520.  
  3521.           mov  dl,cpm_drive       ; diskno
  3522.           mov  dh,side
  3523.           mov  ch,r_track
  3524.           call track_trans
  3525.           mov  cl,first_phys_sec  ; physical sector number
  3526.           mov  al,phys_sec_pt     ; lies ganzen Track auf einmal
  3527.           mov  ah,2               ; read sector
  3528. ;          call normalize_pointer
  3529.           int 13h                 ; es:bx := track
  3530.         pop cx
  3531.         pop es
  3532.         call dos_phys_len
  3533.         jnc  short @@exit
  3534.         cmp  ah,9
  3535.         jz   dma_bound
  3536. ; Fehler, Disk Reset und nochmal versuchen
  3537.         mov ah,0
  3538.         mov dl,cpm_drive
  3539.         int 13h                   ; disk reset
  3540.       loop  @@tryread
  3541.       stc                         ; Error, cy
  3542. @@exit:
  3543.       POPR <dx,cx,bx,ax>
  3544.       ret
  3545. read_phys_track endp
  3546.  
  3547. ; Trackuebersetzung nur fuer CP/M 86 DS DD noetig
  3548. ; muss vor phys. read/write Ops aufgerufen werden
  3549. ;
  3550. ; in: ch: zu uebersetzender Track
  3551. ;     dh: Disk Side
  3552.  
  3553. track_trans proc
  3554.           cmp  ch,phys_tracks
  3555.           jb  short @@exit
  3556.           cmp  cpm86dd_flag,TRUE
  3557.           jnz short @@nocpm86dd
  3558.           push ax
  3559.           mov  al,ch
  3560.           mov  ch,79
  3561.           sub  ch,al
  3562.           pop  ax
  3563.           inc  dh                 ; Seite 1
  3564.           jmp  short @@exit
  3565. @@nocpm86dd:
  3566.           sub ch,40
  3567.           inc  dh                 ; Seite 1
  3568. @@exit:
  3569.           ret
  3570. track_trans endp
  3571.  
  3572. tst_disk_change proc
  3573.           cmp hd_drive_flag,FALSE
  3574.           jz  short @@exit        ; kein Diskwechsel => Z
  3575.           mov ah,16h
  3576.           mov dl,cpm_drive
  3577.           int 13h  ; Test auf Wechsel
  3578.           cmp ah,0                ; kein Diskwechsel => Z
  3579. @@exit:
  3580.           ret
  3581. tst_disk_change endp
  3582.  
  3583. ; falls noch nicht geschriebener Track im Speicher ist,
  3584. ; der kein DirTrack ist, ausschreiben
  3585.  
  3586. write_out_old_track proc
  3587.       cmp  write_flag,TRUE
  3588.       jnz short @@exit
  3589.       mov  al,last_track_written
  3590.       mov  w_track,al
  3591.       mov  outbuf_ptr,offset wrtbuf
  3592.         call write_phys_track
  3593.       mov  write_flag,FALSE
  3594. @@exit:
  3595.       ret
  3596. write_out_old_track endp
  3597.  
  3598. ;
  3599. ; den Dir Track auf Disk schreiben
  3600. ;
  3601. write_out_dir proc
  3602.       call write_out_old_track    ; falls noetig
  3603.       mov  al,dirtrack
  3604.       mov  w_track,al
  3605.       mov  outbuf_ptr,offset dirtrbuf
  3606.           call write_phys_track
  3607.       ret
  3608. write_out_dir endp
  3609.  
  3610. write_phys_track proc
  3611.       PUSHR <ax,bx,cx,dx>
  3612.       mov  cl,retry_count
  3613.       xor  ch,ch
  3614. @@trywrit:
  3615.         call cpm_phys_len
  3616.         push es
  3617.         mov  ax,emudata_seg
  3618.         mov  es,ax
  3619.         push cx
  3620.           mov  dl,cpm_drive          ; diskno
  3621.           mov  dh,side
  3622.           mov  ch,w_track
  3623.           call track_trans
  3624.           mov  cl,first_phys_sec  ; physical sector number
  3625.           mov  bx,outbuf_ptr
  3626.           mov  al,phys_sec_pt
  3627. ;          call normalize_pointer
  3628.           mov  ah,3               ; read sector
  3629.           int 13h                 ; track := es:bx
  3630.         pop cx
  3631.         pop es
  3632.         call dos_phys_len
  3633.         jnc  short @@exit
  3634.         cmp  ah,9
  3635.         jz   dma_bound
  3636.         mov ah,0
  3637.         mov dl,cpm_drive
  3638.         int 13h                   ; disk reset
  3639.       loop  @@trywrit
  3640.       stc                         ; Error,  cy
  3641. @@exit:
  3642.       POPR <dx,cx,bx,ax>
  3643.       ret
  3644. write_phys_track endp
  3645.  
  3646. ;
  3647. ; versuchen, richtiges physikalisches Format zu finden
  3648. ; und disc parameter block herrichten
  3649. ;
  3650. ; falls autologin_flag = FALSE , kann das Zeitaufwendige login
  3651. ; entfallen
  3652.  
  3653. login_disc proc
  3654.       push bx
  3655.       call tst_hd_drive
  3656.       mov last_track_read,0ffh    ; Track Buffer auf leer setzen
  3657.                                   ; damit bei read_track gelesen wird
  3658.       mov write_flag,FALSE        ; sonst wird beim naechsten write
  3659.                                   ; erst alter Schrott ausgeschrieben
  3660.       cmp  autologin_flag,TRUE
  3661.       jnz  @@exit
  3662.       cmp  cpmdrv_set_flg,TRUE
  3663.       jz short @@no_drset
  3664.       mov  cpm_drive,PHYS_DRV
  3665. @@no_drset:
  3666.       mov  al,ms_phys_sec_len
  3667.       mov  cpm_phys_sec_len,al
  3668.  
  3669.       mov cpm86dd_flag,FALSE
  3670.  
  3671.       mov retry_count,2           ; Leseversuche herabsetzen,
  3672.                                   ; damit bei falschem
  3673.                                   ; Format nicht zuviel Zeit verschwendet wird
  3674.  
  3675. @@loop:
  3676.  
  3677.        cmp breakflag,TRUE
  3678.  
  3679.        CALLZ  prg_exit
  3680.  
  3681. ; erst mal mit dem zuletzt verwendeten Format versuchen
  3682. ; aber nicht, wenn letztes CP/M 86 war, da sonst das
  3683. ; aehnliche Format mit 9 Sektoren nicht erkannt wird
  3684.  
  3685.       cmp byte ptr phys_sec_pt,8
  3686.       jz  short @@tst_cpm86
  3687.  
  3688.       mov al,pspt_last
  3689.       mov phys_sec_pt,al
  3690.       mov al,phys_tracks_last
  3691.       mov phys_tracks,al
  3692.       mov al,frstps_last
  3693.       mov first_phys_sec,al       ; physical sector
  3694.       mov al,dirtr_last
  3695.       mov dirtrack,al
  3696.       inc al
  3697.       mov r_track,al
  3698.       mov bx,offset secbuf
  3699.       call read_phys_track
  3700.       mov  bx,dpb_last
  3701.       jnc  @@goodfmt
  3702.  
  3703.  
  3704. ;
  3705. ; CP/M 86 format ?
  3706. ;
  3707. ; Bedingungen: Seite 0 muss Sektoren 1-8 haben, aber nicht 1-9
  3708. ;              Seite 1 muss Sektoren 1-8 haben
  3709.  
  3710. ; setze 9 Phys. Sektoren, bei cp/m 86 mit 8 Sektoren pro Track muss
  3711. ; es einen Lesefehler geben
  3712.  
  3713. @@tst_cpm86:
  3714.       mov phys_sec_pt,9
  3715.       mov phys_tracks,40
  3716.       mov first_phys_sec,1h
  3717.       mov r_track,1+1
  3718.       mov dirtrack,1
  3719.       mov bx,offset secbuf
  3720.       call read_phys_track
  3721.       jnc  short @@nocpm86
  3722.  
  3723.       mov phys_sec_pt,8
  3724.       mov phys_tracks,40
  3725.       mov first_phys_sec,1h
  3726.       mov r_track,1+1
  3727.       mov dirtrack,1
  3728.       mov bx,offset secbuf
  3729.       call read_phys_track
  3730.       jc  short @@nocpm86
  3731.  
  3732.  
  3733.   ; Teste noch Seite 2 mit SektorNummer > 39
  3734.  
  3735.       mov phys_sec_pt,8
  3736.       mov phys_tracks,40
  3737.       mov first_phys_sec,1h
  3738.  
  3739.       mov r_track,40
  3740.       mov dirtrack,1
  3741.       mov bx,offset secbuf
  3742.       call read_phys_track
  3743.       mov  bx,offset dpb_cpm86DS
  3744.       mov  cpm86dd_flag,TRUE
  3745.       jnc  @@goodfmt
  3746.       mov  cpm86dd_flag,FALSE
  3747.       mov  bx,offset dpb_cpm86SS
  3748.       jmp  @@goodfmt
  3749.  
  3750. @@nocpm86:
  3751.  
  3752. ;
  3753. ; cpc system format ?
  3754. ;
  3755.       mov phys_sec_pt,9
  3756.       mov phys_tracks,40
  3757.       mov first_phys_sec,41h
  3758.       mov r_track,2+1
  3759.       mov dirtrack,2
  3760.       mov bx,offset secbuf
  3761.       call read_phys_track
  3762.       mov  bx,offset dpb_cpc
  3763.       jnc  short @@goodfmt
  3764. ;
  3765. ; data format ?
  3766. ;
  3767.       mov phys_sec_pt,9
  3768.       mov phys_tracks,40
  3769.       mov first_phys_sec,0c1h
  3770.       mov r_track,0+1
  3771.       mov dirtrack,0
  3772.       mov bx,offset secbuf
  3773.       call read_phys_track
  3774.       mov  bx,offset dpb_dta
  3775.       jnc  short @@goodfmt
  3776.  
  3777. @@tsteigfrm:
  3778. ;
  3779. ; is it own format
  3780. ;
  3781.       mov phys_sec_pt,9
  3782.       mov phys_tracks,40
  3783.       mov first_phys_sec,1
  3784.       mov r_track,0+1
  3785.       mov dirtrack,0
  3786.       mov bx,offset secbuf
  3787.       call read_phys_track
  3788.       mov  bx,offset dpb_eig
  3789.       jnc  short @@goodfmt
  3790.  
  3791. @@badfmt:
  3792.       mov  bx,offset bad_format
  3793.       call puts
  3794.       call crtin
  3795.       cmp  autologin_flag,TRUE    ; waehrend conin kann Edit DPH gewes. sein
  3796.       jnz  short @@exit
  3797.       jmp  @@loop
  3798.  
  3799. @@goodfmt:
  3800.  
  3801. ; physikalisches Format merken
  3802.  
  3803.        mov al,phys_sec_pt
  3804.        mov pspt_last,al
  3805.        mov al,first_phys_sec
  3806.        mov frstps_last,al
  3807.        mov al,dirtrack
  3808.        mov dirtr_last,al
  3809.        mov dpb_last,bx
  3810.  
  3811.        mov  si,bx
  3812.        mov  di,offset dpb0+ZBIOSDISPL
  3813.        mov  cx,size dpb
  3814.        cld
  3815.        rep movsb                  ; es:di := ds:si
  3816.  
  3817. @@exit:
  3818.        pop bx
  3819.        mov retry_count,5
  3820.        ret
  3821. login_disc endp
  3822.  
  3823.  
  3824. write proc
  3825. ;
  3826. ; write a record of 128 bytes
  3827. ;
  3828.        cmp  diskno,RMD
  3829.        jnz  short wtodisc
  3830.        call calcadr               ; ax:bx := record adress
  3831.        jc   short @@bad
  3832.        call wrtrec                ; buffer := record
  3833.        jc   short @@bad
  3834.        xor  al,al                 ; write ok
  3835.        ret
  3836. @@bad: mov al,1
  3837.        ret
  3838. write endp
  3839.  
  3840. wtodisc proc
  3841.        push cx
  3842.        call is_valid_rec          ; ax=rec/sec
  3843.        pop  cx
  3844.        jc   short @@badsec
  3845.  
  3846.  
  3847. ; if track noch nicht im Buffer
  3848. ;    if noch alter Track im Buffer
  3849. ;       alten Track ausschreiben
  3850. ;    endif
  3851. ;    lies neuen Track ein
  3852. ; endif
  3853. ; if track ist dirtrack
  3854. ;    if noch alter Track im Buffer
  3855. ;       alten Track ausschreiben
  3856. ;    endif
  3857. ;    dirtrack ausschreiben
  3858. ; else
  3859. ;    Setze Flag, daß Sektor geschreiben wurde
  3860. ; endif
  3861. ;
  3862.  
  3863.        push cx                    ; bdos info, ob dirsectoren
  3864.        call read_w_track
  3865.        pop  cx
  3866.        jc   short @@badsec
  3867. ;
  3868. ; record # ist in ah
  3869. ;
  3870.  
  3871.        push cx
  3872.        mov  al,WRITE_OP
  3873.        call get_adr_in_buf
  3874.        mov  ax,ds                 ; ax:= seg track buffer
  3875.        call wrtrec
  3876.        pop  cx
  3877.        cmp  cl,1
  3878.        jz   short @@isdir1
  3879.        call is_dir_track
  3880.        jz   short @@isdir1
  3881.  
  3882.        mov  write_flag,TRUE
  3883.        mov  al,track
  3884.        mov  last_track_written,al
  3885.        mov  al,0                  ; o.k.
  3886.        jmp  short @@exit
  3887.  
  3888. @@isdir1:
  3889.        call write_out_dir
  3890.        jc short @@badsec
  3891.        mov  al,0
  3892.        jmp  short @@exit
  3893. @@badsec:
  3894.       mov al,1
  3895. @@exit:
  3896.       ret
  3897. wtodisc endp
  3898.  
  3899. ;
  3900. ; In: ax:bx = source adr
  3901. ;
  3902. rdrec proc
  3903. ;
  3904.        PUSHR <si,di,bx,cx,ax>
  3905.        push ds
  3906.          mov si,bx
  3907.          mov di,dmaad             ; ds MUSS =  emudata_seg sein
  3908.          mov ds,ax
  3909.          mov cx,RECORD_LEN/2             ; record laenge in words
  3910.          cld
  3911.          rep movsw                ; es:di := ds:si
  3912.        pop ds
  3913.        POPR <ax,cx,bx,di,si>
  3914.        ret
  3915. rdrec endp
  3916. ;
  3917. ; In: ax:bx=target adr
  3918. ;
  3919. wrtrec proc
  3920.        PUSHR <si,di,cx,ax>
  3921.        push es
  3922.        push ds
  3923.  
  3924.        mov si,dmaad               ; ACHTUNG: der MOV muss
  3925.                                   ; vor DS Segmentwechsel sein
  3926.        mov di,bx
  3927.        mov bx,ax                  ; ramdisc
  3928.        mov ax,es                  ; cp/m
  3929.        mov es,bx
  3930.        mov ds,ax
  3931.  
  3932.        mov cx,RECORD_LEN/2               ; record laenge in words
  3933.        cld
  3934.        rep movsw                  ; es:di := ds:si
  3935.        pop ds
  3936.        pop es
  3937.        POPR <ax,cx,di,si>
  3938.        ret
  3939. wrtrec endp
  3940.  
  3941. emulator_seg ends
  3942.  
  3943.  
  3944. end init
  3945.