home *** CD-ROM | disk | FTP | other *** search
/ ftp.barnyard.co.uk / 2015.02.ftp.barnyard.co.uk.tar / ftp.barnyard.co.uk / cpm / walnut-creek-CDROM / ENTERPRS / CPM / UTILS / S / ZSIM12.ZIP / CPMBIOS.ASM < prev    next >
Assembly Source File  |  1992-01-12  |  73KB  |  3,167 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     Disparameter laden/speichern
  10. ;          1.11    bios read zeigt Dos File Ende an
  11. ;          1.2     conin übersetzt CsrTasten nach WS
  12. ;                  ergänzte time fkt und Blink Attribut
  13.  
  14. INCLUDE Z80EMU.INC
  15.  
  16. EXTRN conout:near,conin:near,reset_conout:near,sel_scr_page:near
  17. EXTRN cursor_off:near,cursor_on:near
  18.  
  19. PUBLIC prg_exit,bios88
  20. PUBLIC breakflag
  21.  
  22.  
  23. %nosyms        ; keine symbols im listing
  24. warn           ; alle warnings an
  25.  
  26. DOSSEG   ; UNBEDINGT notwendig, da fuer Speicherverwaltung des Z80 Segments
  27.          ; und der Ramdisk Stacksegment als letztes kommen muss
  28.          ; auch mussen Stack- und Codesegment Klassen 'STACK' bzw.
  29.          ; 'CODE'bekommen
  30.  
  31. LOCALS   ; fuer locale Labels in Prozeduren
  32.  
  33. JUMPS    ; automatische Sprunglaengenanpassung
  34.  
  35. CALLZ macro label ; Call if zero
  36. local exit
  37.       jnz short exit
  38.       call label
  39. exit:
  40. endm
  41.  
  42. CALLNZ macro label ; Call if not zero
  43. local exit
  44.       jz   short exit
  45.       call label
  46. exit:
  47. endm
  48.  
  49. CALLC macro label ; Call if carry
  50. local exit
  51.       jnc  short exit
  52.       call label
  53. exit:
  54. endm
  55.  
  56.  
  57. ;
  58. ; segmente des emulators:
  59. ;
  60.  
  61. ; emulator_seg   : emulator und bios code
  62. ; emudata_seg    : emulator data und z80 bios code
  63. ; stack_seg      : emulator und bios stack
  64. ; z80cpu_seg     : Segment des emulierten z80, 64k, dummy at 0 (in z80seg_adr)
  65. ; ramdisc_seg    : ramdisc fuer cp/m
  66. ;
  67.  
  68.  
  69. include dos.inc         ; dos functionen
  70.  
  71. ;
  72. ; ******* KONSTANTEN ********
  73. ;
  74.  
  75. DEFAULT_DMA        EQU 80H
  76. RECORD_LEN         EQU 80H
  77.  
  78.  
  79.  
  80. ZBIOSLEN           equ (zbiosend-zbiosbeg)
  81. ZBIOSDISPL         equ (0ffffh-ZBIOSLEN) and 0ff00h
  82. ; dies bewirkt Start auf neuer Seite, damit Bios auf XX00 anfaengt
  83. ZBIOS              equ offset zbiosbeg+ZBIOSDISPL
  84.  
  85. CTRL_BREAK_INT EQU 1BH
  86.  
  87. ESC_KEY            EQU 27
  88.  
  89. EMU_SCR_PAGE EQU 0
  90. DOS_SCR_PAGE EQU 1
  91.  
  92. ; folgende Konstanten werden als Flags zur Addressberechnung
  93. ; im Sektorbuffer benoetigt
  94.  
  95. READ_OP            EQU 0
  96. WRITE_OP           EQU 0FFH
  97.  
  98. PHYSDSK            EQU 0
  99.  
  100.  
  101. BDOSLEN            equ 1600h     ; Laenge ccp+bdos cp/m 2.2
  102. BDOS_CHK_SUM       equ 2d88h     ; Checksumme ueber Bdos Copyright Meldung
  103.  
  104. SYS_FRST_SEC       EQU 28
  105.          ; erster absoluter Sektor, den Bdos auf SysSpuren belegt
  106.  
  107. SYS_SECS           EQU BDOSLEN/RECORD_LEN ; Anzahl Sektoren, die System belegt
  108.  
  109. TRACK_BUF_LEN      EQU 10*512
  110.  
  111. CPM_EOF            EQU 26
  112.  
  113. PHYS_DRV           EQU 0   ; # diskettenlaufwerk
  114. RMD                equ 1   ; # ramdisk
  115.  
  116.  
  117. PHYS_SEKLEN        equ 512
  118. NSECTS             equ    2
  119. NDISKS             equ    2  ; last disk # +1
  120. BPS                equ    2
  121.  
  122. ; -------------------------------------
  123. ;
  124. ; emulator data segment
  125. ;
  126. ; --------------------------------------
  127.  
  128.  
  129. emudata_seg segment para public 'DATA'
  130.  
  131. include zbios.inc
  132.  
  133. dpb_cpc     dpb <SPTC,BSHC,BLMC,EXMC,DSMC,DRMC,AL0C,AL1C,CKSC,OFFC>
  134. dpb_dta     dpb <SPTD,BSHD,BLMD,EXMD,DSMD,DRMD,AL0D,AL1D,CKSD,OFFD>
  135. dpb_eig     dpb <SPTD,BSHD,BLMD,EXMD,DSMD,DRMD,AL0D,AL1D,CKSD,OFFD>
  136. dpb_cpm86SS dpb <SPT0,BSH0,BLM0,EXM0,DSM0,DRM0,AL00,AL10,CKS0,OFF0>
  137. dpb_cpm86DS dpb <SPT1,BSH1,BLM1,EXM1,DSM1,DRM1,AL01,AL11,CKS1,OFF1>
  138.  
  139. ramdisklen dw (?)
  140. lasttrack_rd db (?) ; 0..127  (512K)
  141.  
  142. PUNCH_BUF_SIZE  equ 512
  143. READER_BUF_SIZE equ 256
  144.  
  145. start_string db 27,'E',27,'Y',32+8,32+24,27,'p'
  146.              db 'ZSIM',27,'q'
  147.              db 27,'Y',32+10,32+18
  148.              db 'Free for personal use'
  149.              db 27,'Y',32+12,32+18
  150.              db 27,'p','USE AT YOUR OWN RISC !',27,'q'
  151.              db 27,'Y',32+15,32+18
  152.              db '(C) 1990,1992 by '
  153.              db 27,'Y',32+17,32+18
  154.              db 'Jürgen G. Weber'
  155.              db 27,'Y',32+18,32+18
  156.              db 'Wiesentalstr. 1'
  157.              db 27,'Y',32+19,32+18
  158.              db 'W-7170 Schwäbisch Hall'
  159.              db 27,'Y',32+20,32+18
  160.              db 'Federal Republic of Germany'
  161.              db 27,'Y',32+24,32+17,27,'p'
  162.              db 'Insert a CP/M disk then press any key'
  163.              db 27,'q'
  164.              db 0
  165.  
  166.  
  167. db 'ZSIM looks for the fellowing string: '
  168.  
  169. bdos_str db '        COPYRIGHT (C) 1979, DIGITAL RESEARCH  '
  170. bdos_str_end equ this byte
  171.  
  172. cpmsys_fileName  db 'CPMSYS.CPM',0
  173. ramdisc_fname    db 'RAMDISC.CPM',0
  174. punch_fileName   db 'PUNCH.CPM',0
  175. reader_fileName  db 'READER.CPM',0
  176. temp_fname       db '\EMUCPM.OVL',0
  177.  
  178. fmt_file_flg db FALSE
  179. fmt_file_name    db 80 dup (?)
  180. file_promt_str db 'Enter Disk Parameter filename: ',0
  181. file_promt_str_end equ $
  182.  
  183.  
  184. menutab label word
  185.  
  186.      dw m_esc
  187.  
  188.      dw m_continue
  189.      dw m_save_rd_quit
  190.      dw m_quit
  191.      dw m_save_rd
  192.      dw m_del_pf
  193.      dw m_init_rdr
  194.      dw m_shell
  195.      dw m_edit_disk_parm
  196.      dw m_save_d_parm
  197.      dw m_load_d_parm
  198.      dw m_w_boot
  199.      dw m_info
  200.  
  201. menu_strs    db '\Continue','|'
  202.              db 'Save \Ramdisc/Quit','|'
  203.              db '\Quit','|'
  204.              db '\Save Ramdisc','|'
  205.              db '\Delete Punch File','|'
  206.              db '\Init Reader','|'
  207.              db '\OS Shell','|'
  208.              db 'Disk \Parameters','|'
  209.              db 'Sa\ve Parameters','|'
  210.              db '\Load Parameters','|'
  211.              db '\Warm Boot','|'
  212.              db '\About','|'
  213.              db 0
  214. menu_strs_end equ this byte
  215.  
  216. MESG_ESC equ 0
  217.  
  218. LONGEST_MESSAGE=20
  219. MESSAGE_COUNT=12
  220.  
  221. prg_ext_box_res  dw 0ffffh
  222.  
  223. ins_cpm_disk_txt db 'Insert CP/M disk and press ENTER|',0
  224. ins_cpm_disk_txt_end equ this byte
  225.  
  226. ins_dos_disk_txt db 'Insert MS-DOS disk and press ENTER|',0
  227. ins_dos_disk_txt_end equ this byte
  228.  
  229. disk_err_txt db 'Disk Error. Press ESC|',0
  230. disk_err_txt_end equ this byte
  231.  
  232. disk_ful_txt db 'Disk full. Press ESC|',0
  233. disk_ful_txt_end equ this byte
  234.  
  235. f_not_found_txt db 'File not found. Press ESC|',0
  236. f_not_found_txt_end equ this byte
  237.  
  238. on_sign_string equ this byte
  239.                    db 27,'E',27,'H'
  240.                    db 'jgw 64K cp/m 80 bios ver 1.2 --  '
  241.                    db ??date
  242.                    db '  (C) 1990,1992 by Jürgen G. Weber'
  243.                    db 13,10,10
  244.                    db 'BDOS: ',27,'j',0
  245. bad_format         db 13,10
  246.                    db 'Unknown disc format. Insert new disc and press any key'
  247.                    db 13,10,0
  248. no_sys             db 13,10
  249.                    db 'Could not read System sectors. Insert'
  250.                    db ' new disc and press any key'
  251. cr_lf_txt          db 13,10,0
  252. control_c_txt      db '^C...',0
  253.  
  254. mfulstr db 13,10,'Not enough memory',13,10
  255. mfsend equ this byte
  256.  
  257. illparm_str db 13,10,'Illegal Command Line Parameter',13,10
  258. illparm_strend equ this byte
  259.  
  260. dma_txt db 13,10
  261.         db 'Fatal: DMA Boundary Crossing'
  262.         db 13,10
  263. dma_txt_end equ this byte
  264.  
  265. exit_str db 'Type EXIT to return to CP/M Emulator ...',13,10
  266. exit_str_end equ this byte
  267.  
  268.  
  269. exec_par_block equ this word
  270.        dw 0
  271.        dw offset exec_cmd_line
  272.        dw seg    exec_cmd_line
  273.        dd 0
  274.        dd 0
  275. exec_cmd_line equ this word
  276.        db ec_str_end-ec_str
  277. ec_str db ''
  278. ec_str_end equ this byte
  279.        db 13
  280.  
  281. no_cc_str  db 13,10,'COMMAND.COM not found. Press ESC.',13,10
  282. no_cc_str_end equ this byte
  283.  
  284. exec_fname db '\COMMAND.COM',0
  285.  
  286.  
  287. good_dpb_edit db (?)
  288. db 2 dup (?)
  289.  
  290. breakflag  db FALSE
  291.  
  292. old_int1b  dd (?)
  293. stackpoi   dw (?)
  294.  
  295. sp_save    dw (?)
  296. ss_save    dw (?)
  297.  
  298. z80seg_adr dw (?)
  299. rdseg_adr  dw (?)
  300. rdlen      dw (?)
  301. exec_mem_start dw (?)
  302.  
  303. psp_adr    dw (?)
  304. prog_len   dw (?)
  305. mem_end    dw (?)
  306. ovl_base   dw (?)
  307. hd_drive_flag db (?)
  308. ms_current_drive db (?)
  309.  
  310. tmp_word        dw (?)
  311.  
  312. z80_pc             dw ?
  313. ccp_adr            dw ?
  314. bdos_adr           dw ?
  315. bios_adr           dw ?
  316.  
  317. month_tab db 31,28,31,30,31,30,31,31,30,31,30,31
  318.  
  319. ; flag, dass im Speicher noch ein nicht auf disk geschriebener
  320. ; nicht-dir Track ist
  321. write_flag         db FALSE
  322.  
  323. in_boot_flag       db FALSE
  324.  
  325. home_flag          db FALSE
  326. last_track_written db 0,0
  327. dirtrack           db 0,0
  328. r_track            db 0,0
  329. w_track            db 0,0
  330.  
  331. track              db 0,0
  332. sector             db 0,0
  333. last_track_read    db 0ffh  ; default unmoeglich, noch nicht gelesen
  334.  
  335. ms_phys_sec_len    db (?)
  336. pspt_last          db 9
  337. phys_tracks_last   db 40
  338. frstps_last        db 041h
  339. dirtr_last         db 2
  340. dpb_last           dw offset dpb_cpc
  341.  
  342. cpm86dd_flag       db FALSE
  343.  
  344. ; ACHTUNG: die Reihenfolge der folgenden Vars nicht
  345. ;          verändern, da sie so ans Modula UP übergeben werden
  346.  
  347. cpm_drive          db PHYS_DRV
  348. first_phys_sec     db 41h
  349. phys_tracks        db (?)
  350. phys_sec_pt        db (?)
  351. cpm_phys_sec_len   db 2
  352. autologin_flag     db TRUE
  353.  
  354. ; end Reihenfolge wichtig
  355.  
  356.  
  357. retry_count        db 5
  358. side               db 0
  359.  
  360. dmaad              dw ?          ;direct memory address
  361. diskno             db ?          ;disk number 0-15
  362.  
  363.  
  364. punch_buf_entries  dw (?)
  365. punch_buf_ptr      dw (?)
  366.  
  367. reader_empty_flag  db TRUE
  368. reader_buf_entries dw (?)
  369. reader_buf_ptr     dw (?)
  370. reader_file_pointer dw 0,0
  371.  
  372.  
  373. ; zeigt auf Bufferadresse des Tracks, der geschrieben werden soll
  374. outbuf_ptr         dw (?)
  375.  
  376. cpm_bdos_buf db BDOSLEN dup (?)
  377.  
  378. dirtrbuf db TRACK_BUF_LEN dup (?)
  379. secbuf   db TRACK_BUF_LEN dup (?)
  380. wrtbuf   db TRACK_BUF_LEN dup (?)
  381.  
  382. punch_buf  db PUNCH_BUF_SIZE dup (?)
  383. reader_buf db READER_BUF_SIZE dup (?)
  384.  
  385. ; dass die Buffer in der EXE-Datei erscheinen, laesst sich
  386. ; durch die Verwendung einer Gruppe mit den Buffern als
  387. ; Extra Segment umgehen
  388. ; jedoch muss dann bei jedem offset der Gruppenname angegeben werden
  389.  
  390. emudata_seg ends
  391.  
  392. ; ------------------------
  393.  
  394. DATA segment para public 'DATA'
  395.      ; Dummysegment zur Kombinierung mit Modula 2
  396. DATA ends
  397.  
  398. STACK_SIZE EQU 1000H
  399.  
  400. stack_seg  segment para stack 'STACK'
  401.       dw STACK_SIZE dup (?)            ; Stack ist recht gross
  402.                                   ; wegen Modula 2 UPs
  403. stack_seg  ends
  404.  
  405. z80cpu_seg segment at 0 ; dummy
  406. z80cpu_seg ends
  407.  
  408. ; -------------------------------------
  409. ; emulator und bios segment start
  410. ; -------------------------------------
  411.  
  412. emulator_seg segment para public 'CODE'
  413.  
  414. assume  cs:emulator_seg,ds:emudata_seg,es:z80cpu_seg,ss:stack_seg
  415.  
  416. m2_ds  dw (?)                          ; fmodula routinen erwarten
  417.                                        ; bei cs:0 ihr DS
  418.  
  419. init proc                              ; emulator start
  420.  
  421.        mov  ax,emudata_seg
  422.  
  423.        mov  ds,ax            ; damit Vars angesprochen werden koennen
  424.  
  425.        mov  stackpoi,sp
  426.  
  427.        mov bx,ss             ; finde Programmende
  428.        mov ax,sp
  429.        mov cl,4
  430.        shr ax,cl             ; ax:=4
  431.        add bx,ax             ; bx=>programm ende
  432.        inc bx                ; vorsichtshalber
  433.  
  434.        push bx
  435.        mov  ax,es            ; es:0 => PSP
  436.        mov  psp_adr,ax
  437.        mov  bx,ax
  438.  
  439.        mov si,0
  440.        mov ax,[es:si+2]      ; ax=> mem end
  441.        mov  mem_end,ax
  442.        push ax
  443.        sub  ax,1000h
  444.        mov  ovl_base,ax
  445.        pop  ax
  446.        push ax
  447.        sub  ax,bx            ; mem end - prg start
  448.        mov  prog_len,ax
  449.        pop  ax               ; mem end
  450.        pop  bx               ; prg end
  451.  
  452.  
  453.        sub ax,bx             ; ax:=free mem
  454.        mov  z80seg_adr,bx
  455.  
  456.        mov  cx,10000h / 16
  457.        add  bx,cx
  458.  
  459.        mov  rdseg_adr,bx
  460.  
  461.        sub  ax,cx
  462.        jc   short @@memful
  463.  
  464.        mov  ramdisklen,ax
  465.  
  466.        call parse_cmd_line
  467.        mov dx,offset illparm_str
  468.        mov cx,illparm_strend-illparm_str
  469.        jc short abort              ; Fehler: falscher Parameter
  470.  
  471.        mov  bx,offset start_string
  472.        call puts
  473.        call conin            ; wait for keypressed
  474.  
  475.        call patch_int
  476.  
  477.        DOS  GET_DISK_DRIVE
  478.        mov  ms_current_drive,al
  479.  
  480.        mov  ax,z80seg_adr
  481.        call clearz80         ; loesche z80 mem
  482.  
  483.        call init_ramdisc
  484.  
  485.        call patch_box
  486.  
  487. ; physikalische Sektorlaenge merken
  488.  
  489.       push es
  490.       mov  ax,0
  491.       mov  es,ax
  492.       les  di,[es:78h]
  493.       mov  al,es:[di+3]
  494.       pop  es
  495.       mov  ms_phys_sec_len,al
  496.  
  497.  
  498. ;
  499. ; offset z80 bios start merken
  500. ;
  501.        mov bios_adr,ZBIOSDISPL          ; bios Sprungleiste einrichten
  502.  
  503.        call z80ini                      ; reset z80 cpu
  504.  
  505.        mov ax,z80seg_adr
  506.        mov es,ax
  507.        mov ds,ax
  508. ;
  509. ; weiter mit cp/m cold boot
  510. ;
  511.        mov al,0
  512.        jmp bios88
  513.  
  514. @@memful:
  515.        mov cx,mfsend-mfulstr
  516.        mov dx,offset mfulstr
  517. abort:
  518.        mov bx,STDERR
  519.        DOS WRITE_TO_HANDLE
  520.        mov al,1
  521.        DOS TERMINATE_EXE
  522. init   endp
  523.  
  524. parse_cmd_line proc
  525.        PUSHR <ax,bx,cx,di,si,ds,es>
  526.         mov ax,ds
  527.         mov es,ax             ; es:=prog vars
  528.         mov ax,psp_adr
  529.         mov ds,ax
  530.         mov di,offset fmt_file_name
  531.         mov si,80h            ; si => Commandozeilenparam
  532.         lodsb                 ; count
  533.         mov ch,0
  534.         mov cl,al
  535.         or  al,al
  536.         mov al,FALSE
  537.         jz  short @@no_parm
  538. @@findslash:
  539.         lodsb
  540.         cmp al," "
  541.         loopz @@findslash     ; +DEC CX
  542.         cmp al,"/"
  543.         jnz short @@parm_err
  544.         lodsb
  545.         dec cx
  546.         and al,not ('a'-'A')  ; toupper
  547.         cmp al,'F'
  548.         jnz short @@parm_err
  549.         mov di,offset fmt_file_name
  550. @@SKIP_BLN:
  551.         lodsb
  552.         cmp al," "
  553.         loopz @@SKIP_BLN; +DEC CX
  554.         stosb         ; 1. non-blank
  555.  
  556.         rep movsb
  557.         mov al,0
  558.         stosb         ; Filename Endzeichen
  559.         mov al,TRUE
  560. @@no_parm:
  561.        POPR <es,ds,si,di,cx,bx>
  562.        mov fmt_file_flg,al
  563.        pop ax
  564.        clc
  565.        ret
  566. @@parm_err:
  567.        POPR <es,ds,si,di,cx,bx,ax>
  568.        stc
  569.        ret
  570. parse_cmd_line endp
  571.  
  572. tst_hd_drive proc
  573.        PUSHR <ax,dx>
  574.        mov hd_drive_flag,FALSE
  575.        mov dl,cpm_drive
  576.        mov ah,15h                 ; Laufwerktyp ?
  577.        int 13h
  578.        jc  short @@exit           ; PC,XT
  579.        cmp ah,2                   ; erkennt DiskWechsel
  580.        jnz short @@exit
  581.        mov hd_drive_flag,TRUE
  582. @@exit:
  583.        POPR <dx,ax>
  584.        ret
  585. tst_hd_drive endp
  586.  
  587. ;
  588. ; der Interupt 1bH (Control-Break Interupt) muß auf eine Routine
  589. ; gelegt werden, die ein Abbruch Flag setzt
  590. ; Dieses wird dann bei jedem Bios Aufruf ausgewertet
  591. ;
  592. patch_int proc
  593.        PUSHR <ds,es,ax,bx,dx>
  594.        mov al,CTRL_BREAK_INT
  595.        DOS GET_VECTOR
  596.        mov word ptr old_int1b,bx
  597.        mov bx,es
  598.        mov word ptr old_int1b+2,bx
  599.        mov  dx,offset new_int1b
  600.        push cs
  601.        pop  ds
  602.        mov al,CTRL_BREAK_INT
  603.        DOS SET_VECTOR
  604.        POPR <dx,bx,ax,es,ds>
  605.        ret
  606. patch_int endp
  607.  
  608. restore_int proc
  609.        push ds
  610.        lds dx,old_int1b
  611.        mov al,CTRL_BREAK_INT
  612.        DOS SET_VECTOR
  613.        pop ds
  614.        ret
  615. restore_int endp
  616.  
  617. new_int1b proc
  618.        push ax
  619.        push ds
  620.        mov  ax,emudata_seg
  621.        mov  ds,ax
  622.        mov  breakflag,TRUE
  623.        pop  ds
  624.        pop  ax
  625.        iret
  626. new_int1b endp
  627.  
  628. ; wird auch von Z80EMU.OP76 HALT aufgerufen
  629.  
  630. prg_exit proc FAR
  631.        PUSHR <ds,es,ax>
  632.        PUSHR <bx,cx,dx,si>
  633.        mov  ax,emudata_seg
  634.        mov  ds,ax
  635.        mov  ax,z80seg_adr
  636.        mov  es,ax
  637.        call restore_int
  638.        mov  breakflag,FALSE
  639.  
  640.        call wrt_out_punch
  641.  
  642.        mov  cx,menu_strs_end-menu_strs   ; high(messages)
  643.        mov  si,offset menu_strs          ; offs(messages)
  644.  
  645.        call box_call
  646.        sal ax,1
  647.        mov di,ax
  648.        call menutab[di]
  649.  
  650.        call patch_int
  651.        POPR <si,dx,cx,bx>
  652.        POPR <ax,es,ds>
  653.        ret
  654. prg_exit endp
  655.  
  656.  
  657. ; Menü durch ESC abgebrochen
  658. m_esc proc
  659.        ret
  660. m_esc endp
  661.  
  662. ; Menüpunkt Emulation fortfahren
  663. m_continue proc
  664.       ret
  665. m_continue endp
  666.  
  667. ; Menüpunkt Ramdisk speichern
  668. m_save_rd proc
  669.       call save_ramdisc
  670.       ret
  671. m_save_rd endp
  672.  
  673. ; Menüpunkt Quit
  674. m_quit proc
  675. ; etwaige Zeichen im Punch Buffer noch ausschreiben
  676.        call wrt_out_punch
  677.  
  678.        mov cl,31                  ; GotoXY(1,25)
  679.        call conout
  680.        mov cl,1
  681.        call conout
  682.        mov cl,25
  683.        call conout
  684.        mov  al,0
  685. ABORT_EMU:
  686.        push ax
  687.        call ins_dos_disk
  688.        pop ax
  689.        DOS TERMINATE_EXE
  690. m_quit endp
  691.  
  692. ; Menüpunkt Ramdisk speichern + Quit
  693. m_save_rd_quit proc
  694.        call save_ramdisc
  695.        jmp short m_quit
  696. m_save_rd_quit endp
  697.  
  698. ; Menüpunkt Punch buffer file löschen
  699. m_del_pf proc
  700.      call del_punch_file
  701.      ret
  702. m_del_pf endp
  703. ; Menüpunkt Reader initialisieren
  704. m_init_rdr proc
  705.       call reset_reader_buf
  706.       ret
  707. m_init_rdr endp
  708.  
  709. ; Menüpunkt OS Shell
  710. m_shell proc
  711.        call dos_shell
  712.        ret
  713. m_shell endp
  714.  
  715. ; Menüpunkt Diskettenparameter editieren
  716. m_edit_disk_parm proc
  717.        call edit_disk_pars
  718.        cmp  good_dpb_edit,1
  719.        jnz  short @@exit
  720.        mov  cpm86dd_flag,FALSE
  721.        mov  ah,0
  722.        mov  al,dpb0.off-dpb0.spt  ; off
  723.        call get_dpb_entrie        ; nach bx
  724.        mov  dirtrack,bl
  725.  
  726.        cmp  in_boot_flag,TRUE
  727.        jz   short @@exit          ; mit boot weitermachen
  728.        call m_w_boot
  729. @@exit:
  730.        ret
  731. m_edit_disk_parm endp
  732.  
  733. prepare_fname proc
  734.        mov  di,offset fmt_file_name
  735.        push di
  736.        mov  cx,80
  737.        mov  si,offset file_promt_str
  738.        mov  bx,file_promt_str_end-file_promt_str
  739.        call input_string
  740.        pop  bx
  741.        or   byte ptr [bx],0          ; Test ob was eingegeben, nein => Z
  742.        ret
  743. prepare_fname endp
  744.  
  745. ; Menüpunkt Diskettenparameter speichern
  746. m_save_d_parm proc
  747.        call prepare_fname
  748.        jz short @@exit
  749.        call save_disk_pars
  750. @@exit:
  751.        ret
  752. m_save_d_parm endp
  753.  
  754. ; Menüpunkt Diskettenparameter laden
  755. m_load_d_parm proc
  756.        call prepare_fname
  757.        jz short @@exit
  758.        call load_disk_pars
  759.        jmp  short m_w_boot
  760. @@exit:
  761.        ret
  762. m_load_d_parm endp
  763.  
  764. ; Menüpunkt CP/M warm boot durchführen
  765. m_w_boot proc
  766.        mov sp,stackpoi
  767.        call patch_int
  768.        mov al,1
  769.        jmp bios88
  770. m_w_boot endp
  771.  
  772. ; Menüpunkt About Author
  773. m_info proc
  774.        call about_author
  775.        ret
  776. m_info endp
  777.  
  778.  
  779.  
  780. ; Fehler durch Ueberschreiten der DMA Segment Grenze
  781. ; siehe c't 4/90 S.412
  782.  
  783. dma_bound proc
  784.        mov bx,STDERR
  785.        mov cx,dma_txt_end-dma_txt
  786.        mov dx,offset dma_txt
  787.        DOS WRITE_TO_HANDLE
  788.        mov al,1
  789.        jmp ABORT_EMU
  790. dma_bound endp
  791.  
  792. ; out: ax=result
  793. ins_dos_disk proc
  794.        mov al,ms_current_drive
  795.        cmp al,cpm_drive
  796.        jnz short @@exit
  797.        mov si,offset ins_dos_disk_txt
  798.        mov cx,ins_dos_disk_txt_end-ins_dos_disk_txt
  799.        call box_call
  800. @@exit:
  801.        ret
  802. ins_dos_disk endp
  803.  
  804. ; out: ax=result
  805. ins_cpm_disk proc
  806.        mov al,ms_current_drive
  807.        cmp al,cpm_drive
  808.        jnz short @@exit
  809.        mov si,offset ins_cpm_disk_txt
  810.        mov cx,ins_cpm_disk_txt_end-ins_cpm_disk_txt
  811.        call box_call
  812. @@exit:
  813.        ret
  814. ins_cpm_disk endp
  815.  
  816.  
  817. disp_disk_err proc
  818.        PUSHR <si,cx>
  819.        pushf                      ; cy aufheben
  820.        mov si,offset disk_err_txt
  821.        mov cx,disk_err_txt_end-disk_err_txt
  822.        call box_call
  823.        POPR <cx,si>
  824.        popf
  825.        ret
  826. disp_disk_err endp
  827.  
  828.  
  829. disp_f_not_found proc
  830.        pushf                      ; cy aufheben
  831.        PUSHR <si,cx>
  832.        mov si,offset f_not_found_txt
  833.        mov cx,f_not_found_txt_end-f_not_found_txt
  834.        call box_call
  835.        POPR <cx,si>
  836.        popf
  837.        ret
  838. disp_f_not_found endp
  839.  
  840. disp_disk_ful proc
  841.        PUSHR <si,cx>
  842.        mov si,offset disk_ful_txt
  843.        mov cx,disk_ful_txt_end-disk_ful_txt
  844.        call box_call
  845.        POPR <cx,si>
  846.        ret
  847. disp_disk_ful endp
  848.  
  849.  
  850. EXTRN EmuMenu_DoMenue:far,EmuMenu_EditDPB:far
  851. EXTRN EmuMenu_InputString:far,EmuMenu_About:far,EmuMenu_init:far
  852.  
  853. ; fmodula2 laedt merkwuerdigerweise am Anfang DS aus CS:0
  854. ; also muss man dort ds hinbringen
  855. ; Trotzdem sollte vor Aufruf einer Funktion DS richtig
  856. ; geladen sein.
  857.  
  858. patch_box proc
  859.        mov  ax,DATA
  860.        mov  [cs:0],ax
  861.        ret
  862. patch_box endp
  863.  
  864. box_call proc                     ; um Modula 2 UPs aufzurufen
  865. ;
  866. ; in:  ds:si => menuetext
  867. ;      cx    =  len(menuetext)
  868. ; out: ax = result
  869. ;
  870. ; auf dem STACK muss GENUG FREI sein, um zu erzeugendes WINDOW
  871. ; ABZUSPEICHERN
  872. ;
  873. COMMENT @
  874.  
  875. DEFINITION MODULE EmuM2;
  876.  
  877. FROM SYSTEM IMPORT BYTE,WORD;
  878.  
  879. TYPE PhysDiskPars = RECORD
  880.            cpm_drive       : BYTE;
  881.                      first_phys_sec  : BYTE;
  882.                      phys_tracks     : BYTE;
  883.            phys_sec_pt     : BYTE;
  884.            bytes_per_sec   : BYTE;
  885.            autologin_flag  : BYTE;
  886.        END;
  887.  
  888. dpb = RECORD
  889.              spt  : WORD;
  890.              bsh  : BYTE;
  891.              blm  : BYTE;
  892.              exm  : BYTE;
  893.              dsm  : WORD;
  894.              drm  : WORD;
  895.              al0  : BYTE;
  896.              al1  : BYTE;
  897.              cks  : WORD;
  898.              off  : WORD;
  899.            END;
  900.      DPBPtr = POINTER TO dpb;
  901.      PDPPtr = POINTER TO PhysDiskPars;
  902.  
  903.  
  904. PROCEDURE DoMenue(x,y:CARDINAL;messages:ARRAY OF CHAR;
  905.                   VAR WinSave:ARRAY OF CHAR;VAR res:CARDINAL);
  906. (* Pop Up Menue, obere linke Ecke des Rahmens bei x,y.
  907.    messages = String mit darzustellenden Menuepunkten; Stringende = 0C.
  908.    Menuepunkte werden durch | getrennt, auch nach letztem Menuepunkt
  909.    MUSS | stehen.
  910.    Jeder Menuepunkt darf durch Druecken eines einzigen Zeichens angewaehlt
  911.    werden, das hell dargestellt wird. Diesem Zeichen muss der Backslash \
  912.    vorangestellt werden.
  913.    Es duerfen maximal 20 Menuepunkte sein.
  914.    WinSave muss genug Platz enthalten, um Hintergrund + dessen Attribute
  915.    abzuspeichern, = (Laengster Menuepunkt+2)*2*(Menuepunkte+2)
  916. *)
  917.  
  918. PROCEDURE EditDPB(p:DPBPtr;q:PDPPtr;
  919.                   VAR WinSave:ARRAY OF CHAR;VAR OK:BOOLEAN);
  920. (* Len WinSave=20*18*2=720 *)
  921.  
  922. PROCEDURE InputString(VAR WinSave,s,p:ARRAY OF CHAR);
  923. (* Es wird vorrausgesetzt, daß prompt p < 30 und string s < 30 *)
  924.  
  925.  
  926. PROCEDURE About(VAR WinSave:ARRAY OF CHAR);
  927. (* Author ausgeben *)
  928.  
  929.  
  930. END EmuM2.
  931.  
  932.  
  933. @
  934.  
  935. HIGH_WinSave=(LONGEST_MESSAGE+2)*2*(MESSAGE_COUNT+2)
  936.  
  937. IF HIGH_WinSave gt 2*STACK_SIZE/3
  938.    %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
  939. ENDIF
  940.  
  941.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  942.        sub  sp,HIGH_WinSave
  943.        mov  bx,sp
  944.        mov  ax,20
  945.        push ax                 ; x
  946.        mov  ax,7
  947.        push ax                 ; y
  948.        push cx                 ; high(messages)
  949.        push ds                 ; seg(messages)
  950.        push si                 ; offs(messages)
  951.        mov  cx,HIGH_WinSave
  952.        push cx                 ; high(WinSave)
  953.        push ss                 ; seg(WinSave)
  954.        push bx                 ; offs(WinSave)
  955.        mov  ax,seg prg_ext_box_res
  956.        push ax                 ; seg(prg_ext_box_res)
  957.        mov  ax,offset prg_ext_box_res
  958.        push ax                 ; offs(prg_ext_box_res)
  959. ;box_adr equ this byte
  960.        mov  ax,DATA
  961.        mov  ds,ax
  962.        call EmuMenu_DoMenue
  963.        add  sp,HIGH_WinSave
  964.        POPR <es,ds>
  965.        mov  ax,prg_ext_box_res
  966.        POPR <bp,si,di,dx,cx,bx>
  967.        ret
  968. box_call endp
  969.  
  970.  
  971. edit_disk_pars proc
  972.  
  973. HIGH_WinSave=800
  974.  
  975. IF HIGH_WinSave gt 2*STACK_SIZE/3
  976.    %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
  977. ENDIF
  978.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  979.        sub  sp,HIGH_WinSave
  980.        mov  bx,sp
  981.        mov  ax,z80seg_adr
  982.        push ax                 ; seg(p)  p:DPBPtr
  983.        mov  ax,offset dpb0+ZBIOSDISPL
  984.        push ax                 ; offs(p)
  985.        mov  ax,seg cpm_drive
  986.        push ax                 ; seg (q) q:PDPPtr;
  987.        mov  ax,offset cpm_drive
  988.        push ax                 ; offs (q)
  989.        mov  cx,HIGH_WinSave
  990.        push cx                 ; high(WinSave)
  991.        push ss                 ; seg(WinSave)
  992.        push bx                 ; offs(WinSave)
  993.        mov  ax,seg good_dpb_edit
  994.        push ax                 ; seg(ok)
  995.        mov  ax,offset good_dpb_edit
  996.        push ax                 ; offs(ok)
  997.        mov  ax,DATA
  998.        mov  ds,ax
  999.        call EmuMenu_EditDPB
  1000.        add  sp,HIGH_WinSave
  1001.        POPR <es,ds,bp,si,di,dx,cx,bx>
  1002.        ret
  1003. edit_disk_pars endp
  1004.  
  1005. ;PROCEDURE InputString(VAR WinSave,s,p:ARRAY OF CHAR);
  1006.  
  1007. input_string proc   ; ds:si = prompt, bx = len prompt
  1008.                     ; ds:di = string  cx = len string
  1009. LOCAL  prompt_str,lenpr,in_str,lenstr:WORD = AUTO_SIZE
  1010.        push bp
  1011.        mov  bp,sp
  1012.        sub  sp,AUTO_SIZE
  1013.        mov  prompt_str,si
  1014.        mov  in_str,di
  1015.        mov lenpr,bx
  1016.        mov lenstr,cx
  1017. HIGH_WinSave=800
  1018.  
  1019. IF HIGH_WinSave gt 2*STACK_SIZE/3
  1020.    %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
  1021. ENDIF
  1022.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  1023.        sub  sp,HIGH_WinSave
  1024.        mov  bx,sp
  1025.        mov  ax,z80seg_adr
  1026.  
  1027.        mov  cx,HIGH_WinSave
  1028.        push cx                 ; high(WinSave)
  1029.        push ss                 ; seg(WinSave)
  1030.        push bx                 ; offs(WinSave)
  1031.  
  1032.        push lenstr             ; high(s)
  1033.        push ds                 ; seg(s)
  1034.        push in_str             ; offs(s)
  1035.        push lenpr              ; high(p)
  1036.        push ds                 ; seg(p)
  1037.        push prompt_str         ; offs(p)
  1038.        mov  ax,DATA
  1039.        mov  ds,ax
  1040.        call EmuMenu_InputString
  1041.        add  sp,HIGH_WinSave
  1042.        POPR <es,ds,bp,si,di,dx,cx,bx>
  1043.        mov  sp,bp
  1044.        pop  bp
  1045.        ret
  1046. input_string endp
  1047.  
  1048.  
  1049. load_disk_pars proc
  1050. LOCAL  handle:WORD = AUTO_SIZE
  1051.        push bp
  1052.        mov  bp,sp
  1053.        sub  sp,AUTO_SIZE
  1054.        call ins_dos_disk
  1055.        call @@fopen
  1056.        jnc  short @@ok
  1057.        cmp  ax,2
  1058.        CALLZ disp_f_not_found
  1059.        jc  short @@exit           ; nicht da
  1060. @@ok:
  1061.        call @@fread
  1062.        call @@fclose
  1063.        mov  autologin_flag,FALSE
  1064. @@exit:
  1065.        call ins_cpm_disk
  1066.        mov  sp,bp
  1067.        pop  bp
  1068.        ret
  1069.  
  1070. @@fopen:
  1071.        mov al,0
  1072.        mov dx,offset fmt_file_name
  1073.        DOS OPEN_FILE
  1074.        mov handle,ax
  1075.        ret
  1076.  
  1077. @@fclose:
  1078.        mov bx,handle
  1079.        DOS CLOSE_FILE
  1080.        CALLC disp_disk_err
  1081.        ret
  1082.  
  1083. @@fread:
  1084.        mov dx,offset tmp_word
  1085.        mov bx,handle
  1086.        mov cx,2
  1087.        DOS READ_FROM_HANDLE
  1088.        CALLC disp_disk_err
  1089.        mov bx,dx
  1090.        mov bx,[bx]
  1091.        cmp bx,'WJ'
  1092.        jnz  short @@ldexit         ; falscher Kenncode <> 'JW'
  1093.  
  1094.        ; cp/m Parameter laden
  1095.  
  1096.        mov dx,offset offset dpb0+ZBIOSDISPL
  1097.        mov bx,handle
  1098.        mov cx,size dpb
  1099.        push ds
  1100.        mov ax,z80seg_adr
  1101.        mov ds,ax
  1102.        DOS READ_FROM_HANDLE
  1103.        pop ds
  1104.        CALLC disp_disk_err
  1105.  
  1106.        ; physikalische Parameter laden
  1107.  
  1108.        mov dx,offset cpm_drive
  1109.        mov bx,handle
  1110.        mov cx,autologin_flag-cpm_drive
  1111.        DOS READ_FROM_HANDLE
  1112.        CALLC disp_disk_err
  1113.  
  1114. @@ldexit:
  1115.      ret
  1116. load_disk_pars endp
  1117.  
  1118. save_disk_pars proc
  1119. LOCAL  handle:WORD = AUTO_SIZE
  1120.        push bp
  1121.        mov  bp,sp
  1122.        sub  sp,AUTO_SIZE
  1123.        call ins_dos_disk
  1124.        cmp  ax,MESG_ESC
  1125.        jz   short @@exit
  1126.        call @@fopen
  1127.             jc short @@exit
  1128.        call @@fwrite
  1129.        call @@fclose
  1130.        call ins_cpm_disk
  1131. @@exit:
  1132.        mov  sp,bp
  1133.        pop  bp
  1134.        ret
  1135.  
  1136.  
  1137. @@fopen:
  1138.        mov cx,0
  1139.        mov dx,offset fmt_file_name
  1140.        DOS CREATE_FILE
  1141.        CALLC disp_disk_err
  1142.        mov handle,ax
  1143.        ret
  1144.  
  1145. @@fclose:
  1146.        mov bx,handle
  1147.        DOS CLOSE_FILE
  1148.        CALLC disp_disk_err
  1149.        ret
  1150.  
  1151. @@fwrite:
  1152.  
  1153. ; erst Kennung schreiben
  1154.  
  1155.        mov bx,offset tmp_word
  1156.        mov [bx],'WJ'
  1157.        mov dx,bx
  1158.        mov bx,handle
  1159.        mov cx,2
  1160.        DOS WRITE_TO_HANDLE
  1161.        CALLC disp_disk_ful
  1162.  
  1163.       ; cp/m Parameter schreiben
  1164.  
  1165.        mov dx,offset offset dpb0+ZBIOSDISPL
  1166.        mov bx,handle
  1167.        mov cx,size dpb
  1168.        push ds
  1169.        mov ax,z80seg_adr
  1170.        mov ds,ax
  1171.        DOS WRITE_TO_HANDLE
  1172.        pop ds
  1173.        CALLC disp_disk_err
  1174.  
  1175.        ; physikalische Parameter schreiben
  1176.  
  1177.        mov dx,offset cpm_drive
  1178.        mov bx,handle
  1179.        mov cx,autologin_flag-cpm_drive
  1180.        DOS WRITE_TO_HANDLE
  1181.        CALLC disp_disk_err
  1182.  
  1183.      ret
  1184. save_disk_pars endp
  1185.  
  1186. about_author proc
  1187.        PUSHR <bx,cx,dx,di,si,bp,ds,es>
  1188.        sub  sp,HIGH_WinSave
  1189.        mov  bx,sp
  1190.        mov  cx,HIGH_WinSave
  1191.        push cx                 ; high(WinSave)
  1192.        push ss                 ; seg(WinSave)
  1193.        push bx                 ; offs(WinSave)
  1194.        mov  ax,DATA
  1195.        mov  ds,ax
  1196.        call EmuMenu_About
  1197.        add  sp,HIGH_WinSave
  1198.        POPR <es,ds,bp,si,di,dx,cx,bx>
  1199.        ret
  1200. about_author endp
  1201.  
  1202. clearz80 proc    ; loesche z80mem
  1203. ;
  1204. ; input: ax=seg z80 segment
  1205. ; alle  register ok
  1206. ;
  1207.        push es
  1208.        PUSHR <ax,cx,di>
  1209.        mov es,ax
  1210.        mov cx,8000h                      ; 32k words
  1211.        mov di,0
  1212.        mov ax,0
  1213.        rep stosw                         ; es:di := 0000h
  1214.        POPR <di,cx,ax>
  1215.        pop es
  1216.        ret
  1217. clearz80 endp
  1218.  
  1219. dos_exec proc
  1220.        mov   al,DOS_SCR_PAGE
  1221.        call  sel_scr_page
  1222.        mov bx,STDOUT
  1223.        mov cx,exit_str_end-exit_str
  1224.        mov dx,offset exit_str
  1225.        DOS WRITE_TO_HANDLE
  1226.        PUSHR <bx,cx,dx,di,si,bp,es>
  1227.        mov   sp_save,sp
  1228.        mov   ss_save,ss
  1229.        mov   bx,seg    exec_par_block
  1230.        mov   es,bx
  1231.        mov   bx,offset exec_par_block
  1232.        mov   dx,offset exec_fname
  1233.        mov   ax,seg    exec_fname
  1234.        mov   ds,ax
  1235.        mov   al,EMU_SCR_PAGE
  1236.        DOS   EXEC                 ; ax:=error code
  1237.        mov   bx,emudata_seg
  1238.        mov   ds,bx
  1239.        cli
  1240.        mov   ss,ss_save
  1241.        mov   sp,sp_save
  1242.        sti
  1243.        POPR  <es,bp,si,di,dx,cx,bx>
  1244.        cmp   ax,2
  1245.        jnz   short @@cc_found
  1246.        mov bx,STDERR
  1247.        mov cx,no_cc_str_end-no_cc_str
  1248.        mov dx,offset no_cc_str
  1249.        DOS WRITE_TO_HANDLE
  1250. @@press_esc:
  1251.        call conin
  1252.        cmp  al,ESC_KEY
  1253.        jnz  short @@press_esc
  1254. @@cc_found:
  1255.        mov   al,0
  1256.        call  sel_scr_page
  1257.        ret
  1258. dos_exec endp
  1259.  
  1260.  
  1261. dos_shell proc
  1262. LOCAL  handle:WORD,mem_adr:WORD = AUTO_SIZE
  1263.        PUSHR <ax,bx,cx,dx,si,di>
  1264.        push bp
  1265.        mov  bp,sp
  1266.        sub  sp,AUTO_SIZE
  1267.  
  1268.        call ins_dos_disk
  1269.        cmp  ax,MESG_ESC
  1270.        jz   short @@exit          ; ESC
  1271.  
  1272.        call @@fcreate
  1273.             jc short @@exit
  1274.        call @@fwrite
  1275.        call @@fclose
  1276.        call @@set_free
  1277.        call dos_exec
  1278.        call @@get_mem
  1279.        call @@fopen
  1280.        call @@fread
  1281.        call @@fclose
  1282.        mov  dx,offset temp_fname
  1283.        DOS  DELETE_FILE
  1284.        CALLC disp_disk_err
  1285.        call ins_cpm_disk
  1286. @@exit:
  1287.        mov  sp,bp
  1288.        pop  bp
  1289.        POPR <di,si,dx,cx,bx,ax>
  1290.        ret
  1291.  
  1292. @@set_free:
  1293.        push es
  1294.        mov  es,psp_adr
  1295.        mov  bx,prog_len
  1296.        sub  bx,1000h
  1297.        DOS  MODIFY_MEMORY
  1298.        mov  bx,mem_end
  1299.        sub  bx,1000h
  1300.        mov  ovl_base,bx
  1301.        pop  es
  1302.        ret
  1303.  
  1304. @@get_mem:
  1305.        push es
  1306.        mov  es,psp_adr
  1307.        mov  bx,prog_len
  1308.        DOS  MODIFY_MEMORY
  1309.        pop  es
  1310.        ret
  1311.  
  1312. @@fcreate:
  1313.        mov cx,2 ; Hidden
  1314.        mov dx,offset temp_fname
  1315.        DOS CREATE_FILE
  1316.        CALLC disp_disk_err        ; Abbruch nach Error in toplevel
  1317.        mov handle,ax
  1318.        ret
  1319.  
  1320. @@fopen:
  1321.        mov al,0
  1322.        mov  dx,offset temp_fname
  1323.        DOS OPEN_FILE
  1324.        CALLC disp_disk_err
  1325.        mov handle,ax
  1326.        ret
  1327.  
  1328. @@fclose:
  1329.        mov bx,handle
  1330.        DOS CLOSE_FILE
  1331.        CALLC disp_disk_err
  1332.        ret
  1333.  
  1334. @@fwrite:
  1335.        push ds
  1336.        mov  bx,handle
  1337.        mov  cx,0ffffh
  1338.        mov  ds,ovl_base
  1339.        mov  dx,0
  1340.        DOS WRITE_TO_HANDLE
  1341.        CALLC disp_disk_ful
  1342.        pop  ds
  1343.       ret
  1344. ; end fwrite
  1345. @@fread:
  1346.        push ds
  1347.        mov  bx,handle
  1348.        mov  cx,0ffffh
  1349.        mov  ds,ovl_base
  1350.        mov  dx,0
  1351.        DOS READ_FROM_HANDLE
  1352.        CALLC disp_disk_err
  1353.        pop  ds
  1354.       ret
  1355. ; end fread
  1356. dos_shell endp
  1357.  
  1358.  
  1359. init_ramdisc proc
  1360.        push es
  1361.        PUSHR <ax,cx>
  1362.        mov ax,ramdisklen          ; in paragraphen
  1363.        LOG2(64)                   ; nach cl (1024/16)
  1364.        shr ax,cl                  ; ax:=ramdisk len in KB
  1365.        and ax,0fff0h or 1100b     ; um Vielfache von 4K zu bekommen
  1366.  
  1367.        push ax
  1368.        LOG2(4)
  1369.        shr ax,cl                  ; ax/=4
  1370.        mov lasttrack_rd,al        ; Tracks zu 4 K
  1371.        pop ax
  1372.                                   ; dsm=ramdisklen in K/2 -1 , da bls=2k
  1373.        shr ax,1                   ; geht klar, da sowieso vielfaches von 4
  1374.        dec ax
  1375.        cmp ax,255
  1376.        jna short @@nobig
  1377.        mov ax,255                 ; mehr wie 510k geht im PC sowieso kaum
  1378.    @@nobig:
  1379.        mov dpb1.dsm,ax            ; blockzahl
  1380.        inc ax                     ; da KB=(dsm+1)*2
  1381.        shl ax,1
  1382.        mov ramdisklen,ax          ; KBzahl
  1383.        mov dpb1.bsh,4
  1384.        mov dpb1.blm,15
  1385.        mov dpb1.exm,1             ; blocksize=2048
  1386.        mov dpb1.drm,127           ; dir entries
  1387.        mov dpb1.al0,11000000b
  1388.  
  1389.                                   ; loesche ramdisc
  1390.        mov ax,rdseg_adr
  1391.        mov es,ax
  1392.        mov ax,ramdisklen
  1393. @@clrloop:
  1394.        cmp ax,64 ; k
  1395.        jb  short @@less64
  1396.        push ax
  1397.        mov cx,8000h               ; do 32k words
  1398.        mov di,0
  1399.        mov ax,0e5e5h
  1400.        rep stosw                  ; es:di := E5E5
  1401.        mov ax,es
  1402.        add ax,1000h
  1403.        mov es,ax
  1404.        pop ax
  1405.        sub ax,64
  1406.        jmp @@clrloop
  1407. @@less64:
  1408.        LOG2(512)
  1409.        shl ax,cl                  ; ax*=1024/2 (word)
  1410.        mov cx,ax
  1411.        mov di,0
  1412.        mov ax,0e5e5h
  1413.        rep stosw                  ; es:di := E5E5
  1414.        POPR <cx,ax>
  1415.        pop es
  1416.        call load_ramdisc
  1417.       ret
  1418. init_ramdisc endp
  1419.  
  1420. ; speichere Ramdisk auf Platte
  1421. ;
  1422. ; der LOCAL Befehl legt lokale Auto-Vars auf dem Stack an mit
  1423. ; Laenge AUTO_SIZE
  1424. ;
  1425. save_ramdisc proc
  1426. LOCAL  handle:WORD = AUTO_SIZE
  1427.  
  1428.        push bp
  1429.        mov  bp,sp
  1430.        sub  sp,AUTO_SIZE
  1431.        call ins_dos_disk
  1432.        cmp  ax,MESG_ESC
  1433.        jz   short @@exit
  1434.        call @@fopen
  1435.             jc short @@exit
  1436.        call @@fwrite
  1437.        call @@fclose
  1438.        call ins_cpm_disk
  1439. @@exit:
  1440.        mov  sp,bp
  1441.        pop  bp
  1442.        ret
  1443.  
  1444.  
  1445. @@fopen:
  1446.        mov cx,0
  1447.        mov dx,offset ramdisc_fname
  1448.        DOS CREATE_FILE
  1449.        CALLC disp_disk_err
  1450.        mov handle,ax
  1451.        ret
  1452.  
  1453. @@fclose:
  1454.        mov bx,handle
  1455.        DOS CLOSE_FILE
  1456.        CALLC disp_disk_err
  1457.        ret
  1458.  
  1459. @@fwrite:
  1460.        ; erst mal Ramdiskgroesse schreiben, beim Laden muss sie stimmen
  1461.  
  1462.        mov bx,offset secbuf
  1463.        mov ax,ramdisklen
  1464.        mov [bx],ax
  1465.        mov dx,bx
  1466.        mov bx,handle
  1467.        mov cx,2
  1468.        DOS WRITE_TO_HANDLE
  1469.        CALLC disp_disk_ful
  1470.  
  1471.        mov bx,rdseg_adr
  1472.        mov ax,ramdisklen
  1473. @@wrtloop:
  1474.        cmp  ax,0                  ; fertig ?
  1475.                                   ; 0 oder negativ = Abbruch
  1476.        jle short @@wrtexit
  1477.        push ax
  1478.        cmp ax,32                  ; kilobyte
  1479.        mov  cx,8000h ; 32k
  1480.        ja  short @@more32
  1481.        LOG2(1024)                 ; nach cl
  1482.        shl ax,cl                  ; ax*=1024
  1483.        mov cx,ax                  ; cx = Laenge in Byte
  1484. @@more32:
  1485.        push bx
  1486.          push ds
  1487.          push bx
  1488.          pop  ds
  1489.          mov  bx,handle           ; klappt, da ueber SS:BP
  1490.          mov  dx,0 ; offset
  1491.          DOS WRITE_TO_HANDLE
  1492.          CALLC disp_disk_ful
  1493.          pop  ds
  1494.        pop bx
  1495.        pop ax
  1496.        add bx,800h                ; segment um 32k weitersetzen
  1497.        sub ax,32                  ; restlaenge -=32
  1498.       jmp @@wrtloop
  1499. @@wrtexit:
  1500.       ret
  1501. ; end fwrite
  1502. save_ramdisc endp
  1503.  
  1504.  
  1505. ; hole Ramdisk von Platte
  1506. ;
  1507. ; der LOCAL Befehl legt lokale Auto-Vars auf dem Stack an mit
  1508. ; Laenge AUTO_SIZE
  1509. ;
  1510. load_ramdisc proc
  1511. LOCAL  handle:WORD = AUTO_SIZE
  1512.  
  1513.        push bp
  1514.        mov  bp,sp
  1515.        sub  sp,AUTO_SIZE
  1516.        call @@fopen
  1517.        jc   short @@exit           ; nicht da
  1518.  
  1519.        call @@fread
  1520.        call @@fclose
  1521. @@exit:
  1522.        mov  sp,bp
  1523.        pop  bp
  1524.        ret
  1525.  
  1526.  
  1527. @@fopen:
  1528.        mov al,0
  1529.        mov dx,offset ramdisc_fname
  1530.        DOS OPEN_FILE
  1531.        mov handle,ax
  1532.        ret
  1533.  
  1534. @@fclose:
  1535.        mov bx,handle
  1536.        DOS CLOSE_FILE
  1537.        CALLC disp_disk_err
  1538.        ret
  1539.  
  1540. @@fread:
  1541.        mov dx,offset secbuf
  1542.        mov bx,handle
  1543.        mov cx,2
  1544.        DOS READ_FROM_HANDLE
  1545.        CALLC disp_disk_err
  1546.        mov bx,dx
  1547.        mov bx,[bx]
  1548.        cmp bx,ramdisklen
  1549.        ja  short @@rdexit         ; ueberhaupt zu gross
  1550.  
  1551.        mov ax,bx                  ; Laenge Ramdisk auf Platte
  1552.        mov bx,rdseg_adr
  1553. @@rdloop:
  1554.        cmp  ax,0                  ; fertig ?
  1555.        jle short @@rdexit
  1556.        push ax
  1557.        cmp ax,32
  1558.        mov  cx,8000h              ; 32k
  1559.        ja  short @@more32
  1560.        LOG2(1024)                 ; nach cl
  1561.        shl ax,cl                  ; ax*=1024
  1562.        mov cx,ax                  ; cx = Laenge in Byte
  1563. @@more32:
  1564.        push bx
  1565.          push ds
  1566.          push bx
  1567.          pop  ds
  1568.          mov  bx,handle           ; klappt, da ueber SS:BP
  1569.          mov  dx,0                ; offset
  1570.          DOS READ_FROM_HANDLE
  1571.          CALLC disp_disk_err
  1572.          pop  ds
  1573.        pop bx
  1574.        pop ax
  1575.        add bx,800h                ; segment um 32k weitersetzen
  1576.        sub ax,32                  ; restlaenge -=32
  1577.       jmp short @@rdloop
  1578. @@rdexit:
  1579.       ret
  1580. ; end fread
  1581. load_ramdisc endp
  1582.  
  1583. bios88 proc
  1584. ;
  1585. ; bios88 ist handler fuer alle bios calls
  1586. ; In:  al=bios nummer (warm boot = 1)
  1587. ;      cx,bx,dx wie bei cp/m bios calls
  1588. ; Out: di,ah zerstoert
  1589. ;         si kann veraendert sein, falls bios change_si_flag
  1590. ;            hat nach wboot
  1591. ;
  1592. ; waehrend aller bios routinen zeigt ds auf emudata_seg
  1593. ;                                    es     z80cpu_seg
  1594.        mov di,emudata_seg
  1595.        mov ds,di
  1596.  
  1597.        mov z80_pc,si
  1598.  
  1599.        cmp breakflag,TRUE
  1600.  
  1601.        CALLZ prg_exit
  1602.  
  1603.        PUSHR <bp,dx>
  1604. ; cx nicht pushen, da cl:=drive # bei wboot
  1605.  
  1606.        xor ah,ah                  ; bios # = index
  1607.        sal ax,1
  1608.        mov di,ax
  1609.          call cs:biostab[di]
  1610.        mov     si,z80_pc
  1611.  
  1612.        POPR  <dx,bp>
  1613.  
  1614.        cmp breakflag,TRUE
  1615.  
  1616.        CALLZ  prg_exit
  1617.  
  1618.        mov di,z80seg_adr
  1619.        mov ds,di
  1620.        mov es,di
  1621.        jmp bios88ret
  1622.  
  1623. bios88 endp
  1624.  
  1625.  
  1626. biostab label word
  1627.         dw boot                   ; cold start
  1628.         dw wboot                  ; warm start
  1629.         dw constat                ; console status
  1630.         dw conin                  ; console character in
  1631.         dw conout                 ; console character out
  1632.         dw list                   ; list character out
  1633.         dw punch                  ; punch character out
  1634.         dw reader                 ; reader character out
  1635.         dw home                   ; move head to home position
  1636.         dw seldsk                 ; select disk
  1637.         dw settrk                 ; set track number
  1638.         dw setsec                 ; set sector number
  1639.         dw setdma                 ; set dma address
  1640.         dw read                   ; read disk
  1641.         dw write                  ; write disk
  1642.         dw listst                 ; return list status
  1643.         dw sectran                ; sector translate
  1644.         rept 25-16-1
  1645.           dw wboot
  1646.         endm
  1647.         dw cpm3_move              ; move
  1648.         dw cpm_get_time           ; time
  1649.  
  1650.  
  1651. ;
  1652. ;
  1653. ;  individuelle UPs um jede Funktion auszufuehren
  1654. ;
  1655. boot proc
  1656.  
  1657. ;simplest case is to just perform parameter initialization
  1658.        mov in_boot_flag,TRUE
  1659.        mov bx,offset on_sign_string
  1660.        call puts
  1661.  
  1662.        call instzbios
  1663.  
  1664.        cmp  fmt_file_flg,TRUE
  1665.        CALLZ load_disk_pars
  1666.  
  1667.  
  1668.        call read_sys  ; lade bdos aus file CPMSYS.CPM
  1669.        pushf
  1670.        call ins_cpm_disk
  1671.        popf
  1672.        jnc  short @@goodload ; laden aus File klappte
  1673.        call get_sys   ; BDOS mit BIOS fkt von Diskette laden
  1674. @@goodload:
  1675.  
  1676. ; Copyright von dr ausgeben
  1677.  
  1678.        mov cl,27
  1679.        call conout
  1680.        mov cl,'k'                 ; pop cursor pos
  1681.        call conout
  1682.        mov cl,27
  1683.        call conout
  1684.        mov cl,'J'                 ; Rest vom Fenster loeschen
  1685.        call conout
  1686.  
  1687.        mov bx,offset cpm_bdos_buf+18h
  1688.        call puts
  1689.  
  1690.        mov bx,offset cr_lf_txt
  1691.        call puts
  1692. ;
  1693. ; berechne adresse von ccp,bdos und bios
  1694. ; dabei wird die JMP CCPENTRY Anweisung bei CCP+0 benutzt
  1695. ;
  1696.        mov di,offset cpm_bdos_buf+807h
  1697.        mov al,[di]
  1698.        cmp al,11h
  1699.        jnz short @@no_standard
  1700.        mov di,offset cpm_bdos_buf+1
  1701.        mov ax,[di]
  1702.        sub ax,35ch                ; ax:=start ccp
  1703. ; CP/M CCP? dann al jetzt 0
  1704.        or al,al
  1705.        jz short @@is_standard
  1706. ; sonst defaultmaessig e400 annehmen
  1707. @@no_standard:
  1708.        mov ax,0e400h
  1709. @@is_standard:
  1710.        mov ccp_adr,ax
  1711.        add  ax,806h
  1712.        mov bdos_adr,ax
  1713.        add  ax,(BDOSLEN-806h)
  1714.        mov bios_adr,ax
  1715.  
  1716.        call reset_conout
  1717.  
  1718.        mov di,IOBYTE
  1719.        mov byte ptr es:[di],0     ; clear IOBYTE
  1720.        mov di,CDISK
  1721.        mov byte ptr es:[di],0     ; select disk zero
  1722.        call reset_punch_buf
  1723.        call reset_reader_buf
  1724.        mov in_boot_flag,FALSE
  1725.        jmp  wboot
  1726. boot endp
  1727.  
  1728. ;
  1729. ; setze Punch buffer auf leer
  1730. ;
  1731.  
  1732. reset_punch_buf proc
  1733.        mov punch_buf_entries,0
  1734.        mov punch_buf_ptr,offset punch_buf
  1735.        ret
  1736. reset_punch_buf endp
  1737.  
  1738.  
  1739. ;
  1740. ; setze Reader buffer auf nicht belegt
  1741. ;
  1742.  
  1743. reset_reader_buf proc
  1744.        mov reader_empty_flag,FALSE     ; noch nicht lesen versucht
  1745.        mov reader_buf_entries,0
  1746.        mov reader_buf_ptr,offset reader_buf
  1747.        mov reader_file_pointer,0
  1748.        mov reader_file_pointer+2,0
  1749.        ret
  1750. reset_reader_buf endp
  1751.  
  1752. ;
  1753. ; Stringausgabe
  1754. ; In: bx zeigt auf String, Stringende = \0
  1755. ;
  1756. puts proc
  1757. @@loop:
  1758.        mov cl,[bx]
  1759.        or  cl,cl
  1760.        jz  short @@exit
  1761.        inc bx
  1762.        push bx
  1763.        call conout
  1764.        pop  bx
  1765.        jmp short @@loop
  1766. @@exit:ret
  1767. puts endp
  1768.  
  1769. instzbios proc
  1770. ;
  1771. ; installiere z80 bios
  1772. ; und discparameter
  1773. ;
  1774.  
  1775.        PUSHR <si,di,cx>
  1776.  
  1777.          mov  si,offset zbiosbeg
  1778.          mov  di,ZBIOS
  1779.          mov  cx,zbiosend-zbiosbeg
  1780.          cld
  1781.          rep movsb                ; es:di := ds:si
  1782.  
  1783.        POPR <cx,di,si>
  1784.        ret
  1785. instzbios endp
  1786.  
  1787.  
  1788. instjp proc
  1789. ;
  1790. ; installiere z80 bios Sprungleiste bei bios_adr
  1791. ;
  1792. ; register o.k.
  1793. ;
  1794. ; darf nicht aufgerufen werden, bevor bios_adr
  1795. ; von boot aufgesetzt wurde
  1796. ;
  1797.  
  1798.        PUSHR <si,di,cx>
  1799.  
  1800.          mov  si,offset wboote-3
  1801.          mov  di,bios_adr
  1802.          mov  cx,zvecend-wboote+3
  1803.          cld
  1804.          rep movsb                ; es:di := ds:si
  1805.  
  1806.        POPR <cx,di,si>
  1807.  
  1808.        ret
  1809. instjp endp
  1810.  
  1811.  
  1812. read_sys  proc
  1813. ;
  1814. ; lade cp/m bdos aus file CPMSYS.CPM in buffer
  1815. ; um es durch warm boot zu benutzen
  1816. ;
  1817. ; das File entspricht dem durch MOVCPM erzeugten Speicherauszug
  1818. ; dabei beginnt das eingentlich System erst ab Offset 880h
  1819.  
  1820. MOVCPM_OFFS = 880H
  1821.  
  1822.      PUSHR <ax,bx,cx,dx,si>
  1823.        mov al,0
  1824.        mov dx,offset cpmsys_fileName
  1825.        DOS OPEN_FILE
  1826.        jc  short @@exit
  1827.        mov si,ax
  1828.        ; setze Filepointer auf CCP Anfang im File
  1829.        mov cx,0                   ; cx:dx: offset
  1830.        mov dx,MOVCPM_OFFS
  1831.        mov al,0                   ; offset from start
  1832.        mov bx,si
  1833.        DOS MOVE_FILE_POINTER
  1834. ;
  1835. ; emudata_seg:buffer := CPMSYS.CPM
  1836. ;
  1837.        mov cx,BDOSLEN             ; Laenge
  1838.        mov bx,si                  ; handle
  1839.        mov dx,offset cpm_bdos_buf
  1840.        DOS READ_FROM_HANDLE
  1841.        jc  short @@exit
  1842.        mov bx,si
  1843.        DOS CLOSE_FILE
  1844.        CALLC disp_disk_err
  1845. @@exit:
  1846.        POPR <si,dx,cx,bx,ax>
  1847.        ret
  1848. read_sys  endp
  1849.  
  1850.  
  1851. ; System von SystemSpuren laden
  1852.  
  1853. ; while sector in systemsectoren do
  1854. ;    lies sector
  1855. ;    if an Adresse     String COPYRIGHT 1979 ..
  1856. ;       sys=naechste SYS_SECS sektoren
  1857. ;       lies sys
  1858. ;       exit
  1859. ;       mache Checksumme ueber sys
  1860. ;       if falsch
  1861. ;          "no sys"
  1862. ;       endif
  1863. ;    endif
  1864. ; endwhile
  1865. ; "no sys"
  1866.  
  1867. get_sys proc
  1868. LOCAL  sys_recs,last_sys_rec:WORD = AUTO_SIZE
  1869.  
  1870.        push bp
  1871.        mov  bp,sp
  1872.        sub  sp,AUTO_SIZE
  1873. @@get_sys_loop:
  1874.        call login_disc
  1875.        mov  ah,0
  1876.        mov  al,dpb0.off-dpb0.spt  ; off
  1877.        call get_dpb_entrie        ; nach bx
  1878.        push bx
  1879.        mov  ah,0
  1880.        mov  al,dpb0.spt-dpb0.spt  ; spt
  1881.        call get_dpb_entrie        ; nach bx
  1882.        pop  ax
  1883.        mul  bx                    ; ax:=system records
  1884.        mov  sys_recs,ax
  1885.        mov  cx,0
  1886. ; im Systembereich nach String "COPYRIGHT (C) 1979 " suchen
  1887. @@srch_loop:
  1888.        cmp  cx,sys_recs
  1889.        jnc  short @@read_err      ; schon ausserhalb sys
  1890.        push cx  ; sector
  1891.        push cx
  1892.        mov  cx,DEFAULT_DMA
  1893.        call setdma
  1894.        pop  cx
  1895.        mov  ah,cpm_drive
  1896.        call set_abs_sect
  1897.        call read
  1898.        pop  cx
  1899.        cmp  al,1
  1900.        jz   short @@read_err
  1901.        call @@compare
  1902.        jz   short @@found
  1903.        inc  cx
  1904.        jnz  @@srch_loop
  1905. @@found:
  1906.        mov  bx,DEFAULT_DMA
  1907.        push cx
  1908.        add  cx,SYS_SECS
  1909.        mov  last_sys_rec,cx
  1910.        pop  cx
  1911. @@loop:
  1912.        push cx  ; sector
  1913.        push bx  ; dma
  1914.        push cx
  1915.        mov  cx,bx
  1916.        call setdma
  1917.        pop  cx
  1918.        mov  ah,cpm_drive
  1919.        call set_abs_sect
  1920.        call read
  1921.        pop  bx
  1922.        pop  cx
  1923.        cmp  al,1
  1924.        jz   short @@read_err
  1925.        add  bx,RECORD_LEN
  1926.        inc  cx
  1927.        cmp  cx,last_sys_rec
  1928.        jnz  @@loop
  1929.  
  1930.        jmp  short @@good_load
  1931.  
  1932. @@read_err:
  1933.        mov  bx,offset no_sys
  1934.        call puts
  1935.        call conin
  1936.        jmp  @@get_sys_loop
  1937.  
  1938. @@good_load:
  1939.  
  1940. ; System aus CP/M Segment nach Datensegment uebertragen
  1941.  
  1942.        PUSHR <si,di,bx,cx,ax>
  1943.        push ds
  1944.        push es
  1945.          mov di,offset cpm_bdos_buf
  1946.          mov si,DEFAULT_DMA
  1947.          mov ax,z80seg_adr
  1948.          mov ds,ax
  1949.          mov ax,emudata_seg
  1950.          mov es,ax
  1951.          mov cx,BDOSLEN/2
  1952.          cld
  1953.          rep movsw                ; es:di := ds:si
  1954.        pop es
  1955.        pop ds
  1956.        POPR <ax,cx,bx,di,si>
  1957.        mov  sp,bp
  1958.        pop  bp
  1959.        ret
  1960. @@compare:
  1961.        PUSHR <si,di,cx,ax>
  1962.        mov  si,offset bdos_str
  1963.        mov  di,DEFAULT_DMA+10H
  1964.        mov  cx,bdos_str_end-bdos_str
  1965. @@cp_loop:
  1966.        mov al,[es:di]
  1967.        mov ah,[si]
  1968.        inc si
  1969.        inc di
  1970.        cmp al,ah
  1971.        jnz  short @@cp_exit
  1972.        loop @@cp_loop
  1973. @@cp_exit:
  1974.        POPR <ax,cx,di,si>
  1975.        ret
  1976.  
  1977. get_sys endp
  1978. ;
  1979.  
  1980. set_abs_sect proc    ; absoluten Sektor in cx, drive ah setzen
  1981.        push cx
  1982.        mov  al,0                  ; spt
  1983.        call get_dpb_entrie        ; nach bx
  1984.        pop  ax
  1985.        mov  dx,0
  1986.        div  bx
  1987.        push dx
  1988.        mov  cx,ax
  1989.        call settrk
  1990.        pop  cx
  1991.        call setsec
  1992.        ret
  1993. set_abs_sect endp
  1994.  
  1995.  
  1996. wboot proc
  1997.  
  1998.      push   di
  1999.        call   copy_bdos
  2000.        call   instjp              ; bios Sprungleiste installieren
  2001. ;
  2002. ; 0000h := JP WBOOT
  2003. ; 0005h := JP BDOS
  2004. ;
  2005.        mov     di,0               ; start cp/m memory
  2006.        mov     byte ptr es:[di+0],0c3h
  2007.        mov     bx,bios_adr
  2008.        add     bx,3               ; bx:=warmboot
  2009.        mov     es:[di+1],bx       ; set address field for jmp at 0
  2010. ;
  2011.        mov     byte ptr es:[di+5],0c3h
  2012.        mov     bx,bdos_adr        ; bdos entry point
  2013.        mov     es:[di+6],bx       ; address field of jump at 5 to bdos 
  2014. ;
  2015.        mov     cx,DEFAULT_DMA     ; default dma address is 80h
  2016.        call   setdma
  2017.  
  2018.        call login_disc ; physikalisches Login
  2019. ;
  2020.        mov     ax,ccp_adr
  2021.        mov     z80_pc,ax          ; jp ccp
  2022.  
  2023.        mov     di,CDISK
  2024.        mov     cl,es:[di]         ; get current disk number & send to ccp 
  2025.      pop di
  2026.      ret                          ;go to cp/m for further processing
  2027.  
  2028. copy_bdos:
  2029.        PUSHR <si,di,cx>
  2030.  
  2031.          mov di,ccp_adr
  2032.          mov si,offset cpm_bdos_buf
  2033.          mov cx,BDOSLEN/2
  2034.          rep movsw                ; es:di := ds:si
  2035.  
  2036.        POPR <cx,di,si>
  2037.        ret
  2038.  
  2039. wboot  endp
  2040. ;
  2041.  
  2042. ;
  2043. ;
  2044. constat proc
  2045. ;
  2046. ; console status, return 0ffh if character ready, 00h,Z_flag if not
  2047. ;
  2048. ; Out: al=keyboard status
  2049. ;
  2050.         push bx
  2051.         mov ah,1                  ; keybord status
  2052.         int 16h
  2053.         mov al,0ffh
  2054.         jnz short @@exit
  2055.         mov al,0
  2056. @@exit:
  2057.         pop bx
  2058.         ret
  2059. constat endp
  2060.  
  2061. ; conin im Modul CONOUT
  2062.  
  2063. ;
  2064. ; test auf ^C, wenn ja, warm boot
  2065. ;
  2066. tst_ctrl_c proc
  2067.        push ax
  2068.        call constat
  2069.        jz   short @@exit
  2070.        call conin
  2071.        cmp  al,3                  ; ^C
  2072.        clc                        ; cy = no error
  2073.        jnz  short @@exit
  2074.        mov  bx,offset control_c_txt
  2075.        call puts
  2076.        stc
  2077. @@exit:
  2078.        pop ax
  2079.        ret
  2080. tst_ctrl_c endp
  2081. ;
  2082. ; list character in register c auf Drucker
  2083. ;
  2084. list proc
  2085.        call listst
  2086.        jnz  short @@ok
  2087.        call tst_ctrl_c
  2088.        jnc  short list
  2089.        mov  z80_pc,0              ; Z80 macht ab Adresse 0 weiter
  2090.        ret
  2091. @@ok:
  2092.        mov al,cl                  ; char nach register a
  2093.        xor dx,dx                  ; lpt 0
  2094.        xor ah,ah                  ; list character
  2095.        push bp
  2096.        int 17h
  2097.        pop bp
  2098.        cmp ah,10h                 ; ok
  2099.        jnz short list
  2100.        ret
  2101. list endp
  2102. ;
  2103. ; return list status (0,Z_flag if not ready, 1 if ready)
  2104. ;
  2105. listst proc
  2106.        push dx
  2107.        xor dx,dx                  ; lpt 0
  2108.        mov ah,2                   ; test printer
  2109.        int 17h
  2110.        mov al,1
  2111.        cmp ah,90h                 ; on line und not busy
  2112.        jz short @@lret
  2113.        dec al
  2114. @@lret:
  2115.        or  al,al
  2116.        pop dx
  2117.        ret
  2118. listst endp
  2119.  
  2120. date_dos_2_cpm proc  ; out: AX=tage seit 1.Jan. 1978
  2121.     push bx
  2122.     push cx
  2123.     push dx
  2124.     DOS GET_DATE
  2125.     push dx
  2126.     mov bx,1978
  2127.     inc cx      ; ein Jahr zuviel, für Test ob akt. Schaltjahr
  2128.     MOV AX,0
  2129. @@add_loop:
  2130.     cmp  bx,cx  ; aktuelles Jahr erreicht ?
  2131.     jz short @@years_done
  2132.  
  2133.     mov  dx,bx
  2134.     and  dx,11b ; 0 => durch 4 teilbar
  2135.     sub  dx,1   ; 0 => cy
  2136.     mov  dx,365
  2137.     adc  dx,0   ; wird unten zum abziehen gebraucht
  2138.     add  ax,dx  ; 0 => 366
  2139.  
  2140.     inc  bx
  2141.     jmp  @@add_loop
  2142. @@years_done:
  2143.     sub ax,dx  ; da ein Jahr oben zuviel, 365 oder 366 wieder weg
  2144.     pop dx   ; mon/tag
  2145.     mov ch,0
  2146.     mov cl,dl
  2147.     add ax,cx ; tag
  2148.     mov cl,dh ; monat
  2149.     dec cl    ; da aktueller Monat schon dran
  2150.     jz  short @@is_jan
  2151.     mov bx,offset month_tab
  2152. @@add_months:
  2153.     mov dl,[bx]    ; verschieden lange monate
  2154.     inc bx
  2155.     mov dh,0
  2156.     add ax,dx
  2157.     loop @@add_months
  2158. @@is_jan:
  2159.     pop dx
  2160.     pop cx
  2161.     pop bx
  2162.     ret
  2163. date_dos_2_cpm endp
  2164.  
  2165. cpm3_move proc   ; move wie bei cpm plus bios
  2166.     push ds
  2167.     push es
  2168.     pop  ds
  2169.     mov  si,bx
  2170.     mov  di,dx
  2171.     add  bx,cx      ; hl=blockende
  2172.     cmp  bx,dx      ; größer Ziel ?
  2173.     jnb   short @@topdown
  2174.     cld
  2175.     rep movsb
  2176.     jmp short @@exit
  2177. @@topdown:
  2178.     add si,cx
  2179.     add di,cx
  2180.     mov bx,si
  2181.     mov dx,di
  2182.     dec si
  2183.     dec di
  2184.     std
  2185.     rep movsb
  2186.     pop ds
  2187.     ret
  2188. @@exit:
  2189.     mov bx,si
  2190.     mov dx,di
  2191.     pop ds
  2192.    ret
  2193. cpm3_move endp
  2194.  
  2195.  
  2196. cpm_get_time proc   ; dos zeit nach cpm plus zeit
  2197.     PUSHR <AX,CX,DX>
  2198.     cmp cl,0
  2199.     jnz short @@exit ; set time ignorieren
  2200.     call date_dos_2_cpm
  2201.     push ds
  2202.     push es
  2203.     pop  ds
  2204.     mov @date+ZBIOSDISPL,ax
  2205.     DOS GET_TIME
  2206.     mov dl,10
  2207.     mov al,cl
  2208.     mov ah,0         ; sonst divide overflow
  2209.     div dl
  2210.     mov cl,4
  2211.     shl al,cl
  2212.     or  al,ah
  2213.     mov @min+ZBIOSDISPL,al
  2214.     mov al,ch
  2215.     mov ah,0
  2216.     div dl
  2217.     shl al,cl
  2218.     or  al,ah
  2219.     mov @hour+ZBIOSDISPL,al
  2220.     mov al,dh
  2221.     mov ah,0
  2222.     div dl
  2223.     shl al,cl
  2224.     or  al,ah
  2225.     mov @sec+ZBIOSDISPL,al
  2226.     pop ds
  2227.     mov bx,(offset @date)+ZBIOSDISPL
  2228. @@exit:
  2229.     POPR <DX,CX,AX>
  2230.     ret
  2231. cpm_get_time endp
  2232.         
  2233. del_punch_file proc
  2234.        mov dx,offset punch_fileName
  2235.        DOS DELETE_FILE
  2236.        ret
  2237. del_punch_file endp
  2238.  
  2239. ;
  2240. ; punch character in register c
  2241. ; wird durch Output in File auf MsDos Disk ersetzt
  2242. ; Buffer wird auf File geschrieben, falls er voll ist
  2243. ; und  auch am Ende des Emulator-
  2244. ; laufs
  2245. ;
  2246. punch proc
  2247. ;
  2248. ; fill buffer until full or eof
  2249. ; open file
  2250. ; if not exist file
  2251. ;    create file
  2252. ; endif
  2253. ; go to end of file
  2254. ; append character
  2255. ; close file
  2256. ; empty buffer
  2257. ;
  2258. ; falls punch von bios88 aufgerufen wurde, ist al<>0
  2259. ; nach Aufruf von wrt_out_punch aber al=0
  2260.  
  2261.      PUSHR <ax,bx,cx,dx,si>
  2262.        cmp al,0
  2263.        jz  short @@write_out
  2264.        mov bx,punch_buf_ptr
  2265.        mov [bx],cl                ; buf:=character
  2266.        inc bx
  2267.        mov punch_buf_ptr,bx
  2268.        inc punch_buf_entries
  2269.        cmp punch_buf_entries,PUNCH_BUF_SIZE
  2270.        jnz short @@exit
  2271. @@write_out:
  2272.        call ins_dos_disk
  2273.        cmp  ax,MESG_ESC
  2274.        jz   short @@exit
  2275.        mov al,1
  2276.        mov dx,offset punch_fileName
  2277.        DOS OPEN_FILE
  2278.        jnc short @@file_found
  2279.            mov cl,0 ; write only
  2280.            DOS CREATE_FILE
  2281.            CALLC disp_disk_err
  2282. @@file_found:
  2283.  
  2284.        mov bx,ax                  ; handle
  2285.        mov cx,0
  2286.        mov dx,0
  2287.        mov al,2                   ; offset from end
  2288.        DOS MOVE_FILE_POINTER
  2289.  
  2290.        mov cx,punch_buf_entries
  2291.        mov dx,offset punch_buf
  2292.        DOS WRITE_TO_HANDLE
  2293.        CALLC disp_disk_ful
  2294.  
  2295.        DOS CLOSE_FILE
  2296.  
  2297.        call reset_punch_buf
  2298.        call ins_cpm_disk
  2299. @@exit:
  2300.        POPR <si,dx,cx,bx,ax>
  2301.        ret
  2302. punch  endp
  2303.  
  2304. wrt_out_punch proc
  2305.        cmp punch_buf_entries,0
  2306.        jz  short @@exit
  2307.        xor  al,al
  2308.        call punch
  2309. @@exit:
  2310.        ret
  2311. wrt_out_punch endp
  2312. ;
  2313. ;
  2314. reader proc       ;read character into register a from reader device
  2315.  
  2316. ; if buffer empty
  2317. ;    open file
  2318. ;    if file not present
  2319. ;       exit
  2320. ;    else
  2321. ;       fill buffer
  2322. ;    endif
  2323. ; endif
  2324. ; read char
  2325.  
  2326.        cmp reader_empty_flag,TRUE
  2327.        jz  short @@empty
  2328.        cmp reader_buf_entries,0
  2329.        jnz short @@do_read
  2330.  
  2331. ; Buffer fuellen
  2332.          mov al,0
  2333.          mov dx,offset reader_fileName
  2334.          DOS OPEN_FILE
  2335.          jc  short @@empty
  2336.          push ax
  2337.          mov bx,ax
  2338.          mov dx,reader_file_pointer
  2339.          mov cx,reader_file_pointer+2
  2340.          PUSHR <dx,cx>
  2341.           add dx,READER_BUF_SIZE
  2342.           adc cx,0
  2343.           mov reader_file_pointer,dx
  2344.           mov reader_file_pointer+2,cx
  2345.          POPR  <cx,dx>
  2346.          mov al,0                   ; offset from start
  2347.          DOS MOVE_FILE_POINTER
  2348.          pop bx                     ; handle
  2349.          mov cx,READER_BUF_SIZE
  2350.          mov dx,offset reader_buf
  2351.          DOS READ_FROM_HANDLE
  2352.          push ax
  2353.          DOS CLOSE_FILE
  2354.          pop ax
  2355.          cmp ax,0
  2356.          jz  short @@empty
  2357.  
  2358.  ; buffer erfolgreich gefuellt
  2359.          mov reader_empty_flag,FALSE
  2360.          mov reader_buf_entries,ax
  2361.          mov reader_buf_ptr,offset reader_buf
  2362.  
  2363. @@do_read:
  2364.          mov bx,reader_buf_ptr
  2365.          mov al,[bx]
  2366.          inc bx
  2367.          mov reader_buf_ptr,bx
  2368.          dec reader_buf_entries
  2369.          jmp short @@exit
  2370. @@empty:
  2371.        mov reader_empty_flag,TRUE
  2372.        mov al,CPM_EOF
  2373.        mov bx,0ffffh       ; hl=FFFF  == Dos File Ende
  2374.        ret
  2375. @@exit:
  2376.        mov bx,0            ; a=hl=gelesenes byte
  2377.        mov bl,al
  2378.        ret
  2379.  
  2380. reader endp
  2381.  
  2382.  
  2383. ; In:  ah=drive
  2384. ;      al=offset im dpb
  2385. ; Out: bx=word dpb[al]
  2386.  
  2387. get_dpb_entrie proc
  2388.        push si
  2389.        mov  bl,ah
  2390.        call get_dph_adr           ; bx:=dph
  2391.        xor  ah,ah
  2392.        mov  si,ax
  2393.        mov  bx,[es:bx+10]         ; bx:=dpb
  2394.        mov  bx,[es:bx+si]         ; bx:=dpb[ax]
  2395.        pop  si
  2396.        ret
  2397. get_dpb_entrie endp
  2398.  
  2399. ;
  2400. ; select disk in register c
  2401. ;
  2402. seldsk proc
  2403.        cmp cl,NDISKS-1
  2404.        mov bx,0000h               ; 0 = Drive nicht existent
  2405.        ja  short @@exit
  2406.        mov diskno,cl
  2407.        mov bl,cl
  2408.        call get_dph_adr
  2409. @@exit:
  2410.        ret
  2411. seldsk endp
  2412.  
  2413. ;  In:  bl:=Drive #
  2414. ;  Out: bx:= disk parameter header address
  2415. ;
  2416. get_dph_adr proc
  2417.        mov bh,0                   ; high order zero
  2418.        push cx
  2419.        LOG2(16)                   ; nach cl
  2420.        sal bx,cl                  ; bx*=16 (size of each header)
  2421.        pop cx
  2422.        add bx,offset dph_base+ZBIOSDISPL
  2423.        ret                        ;hl=.dph_base(diskno*16)
  2424. get_dph_adr endp
  2425.  
  2426. ;
  2427. ;  move to the track 00 position of current drive
  2428. ;  translate this call into a settrk call with parameter 00
  2429. ;
  2430. home proc
  2431.        mov cx,0                   ; select track 0
  2432.        call settrk
  2433.        mov  home_flag,TRUE        ; zur Auswertung durch read_track
  2434.        ret
  2435. home endp
  2436.  
  2437. ;
  2438. ; set track given by register bc
  2439. ;
  2440. settrk proc
  2441.        mov word ptr track,cx
  2442.        ret
  2443. settrk endp
  2444. ;
  2445. ; set sector given by register bc
  2446. ;
  2447. setsec proc
  2448.        mov word ptr sector,cx
  2449.        ret
  2450. setsec endp
  2451.  
  2452. ;
  2453. ;translate the sector given by bc using the
  2454. ;translate table given by de
  2455. ;
  2456. sectran proc
  2457.  
  2458.        mov  bx,cx
  2459.        or   dx,dx                 ; table ptr == 0 ?
  2460.        jz   short @@exit
  2461.        add  cx,cx                 ; index *= 2
  2462.        mov  bx,dx                 ; hl=trans
  2463.        add  bx,cx
  2464.        mov  bx,[es:bx]            ;hl=trans[sector]
  2465. @@exit:
  2466.        ret                        ;with value in hl
  2467. sectran endp
  2468. ;
  2469. ; set dma address given by registers b und c
  2470. ;
  2471. setdma proc
  2472.        mov dmaad,cx
  2473.        ret
  2474. setdma endp
  2475.  
  2476.  
  2477. calcadr proc
  2478. ;
  2479. ; ax:bx := record adresse in Ramdisk
  2480. ; illegal sec: cy
  2481. ;
  2482. ; 1. 64k track  0..15
  2483. ; 2. 64k track 16..31
  2484. ; ..
  2485.        mov al,track
  2486.        cmp al,lasttrack_rd
  2487.        ja short @@badrec
  2488.  
  2489.        mov al,sector
  2490.        cmp al,LAST_SEC1
  2491.        ja short @@badrec
  2492.  
  2493. ; phys recordnum = track * spt + sector
  2494.  
  2495.        PUSHR <cx,dx>
  2496.        mov  ah,RMD
  2497.        mov  al,0                  ; spt
  2498.        call get_dpb_entrie
  2499.        mov  cx,bx                 ; cx:=spt B:
  2500.        mov  ax,word ptr track
  2501.        mul  cx
  2502.        add  ax,word ptr sector    ; ax:=phys record num
  2503.        mov  cx,512                ; 64K = 512 records @ 128 Bytes
  2504.        mov  dx,0
  2505.        div  cx                    ; ax:= # of 64K, dx:=recordnum
  2506.        mov  cx,1000h
  2507.        push dx
  2508.        mul  cx
  2509.        pop  dx
  2510.        mov  bx,rdseg_adr
  2511.        add  bx,ax
  2512.        mov  ax,dx
  2513.        LOG2(RECORD_LEN)
  2514.        shl  ax,cl
  2515.        xchg bx,ax
  2516.        POPR <dx,cx>
  2517.       clc
  2518. @@exit:
  2519.       ret
  2520. @@badrec:
  2521.       stc
  2522.       jmp short @@exit
  2523. calcadr endp
  2524.  
  2525. ;
  2526. read proc
  2527. ;
  2528. ; lies einen record von 128 bytes
  2529. ;
  2530.        cmp  diskno,RMD
  2531.        jnz  short @@rfdisc
  2532.        call calcadr               ; ax:bx := record addresse
  2533.        jc   short @@badsec
  2534.        call rdrec
  2535. @@exit:xor al,al                  ; o.k.
  2536.        ret
  2537. @@badsec:
  2538.        mov al,1
  2539.        ret
  2540.  
  2541. @@rfdisc:
  2542.        call is_valid_rec          ; ax=rec/sec
  2543.        jc   short @@badsec
  2544.  
  2545.        call read_track
  2546.        jc   short @@badsec
  2547. ;
  2548. ; record num ist in ah
  2549. ; ax:bx := adresse Track Buffer
  2550. ;
  2551.        mov  al,READ_OP
  2552.        call get_adr_in_buf        ; nach bx
  2553.        mov  ax,ds                 ; ax := seg track buffer
  2554.        call rdrec
  2555.        jmp  short @@exit
  2556. read endp
  2557.  
  2558. ; berechne Sektoradresse im Buffer
  2559. ; a=sector*128+buf
  2560. ; input: al=READ_OP / WRITE_OP
  2561.  
  2562. get_adr_in_buf proc
  2563.       PUSHR <AX,CX>
  2564.        call is_dir_track
  2565.        mov  bx,offset dirtrbuf
  2566.         jz  short @@calc
  2567.        mov  bx,offset secbuf
  2568.        cmp  al,READ_OP
  2569.         jz  short @@calc
  2570.        mov  bx,offset wrtbuf
  2571. @@calc:
  2572.        xor  ax,ax
  2573.        mov  al,sector
  2574.        LOG2(RECORD_LEN)                  ; nach cl
  2575.        shl  ax,cl                 ; ax *= 128
  2576.        add  bx,ax
  2577.       POPR <CX,AX>
  2578.       RET
  2579. get_adr_in_buf endp
  2580.  
  2581. is_dir_track proc
  2582.       push ax
  2583.        mov  al,track
  2584.        cmp  al,dirtrack
  2585.       pop  ax
  2586.       ret
  2587. is_dir_track endp
  2588.  
  2589. ;
  2590. ;
  2591. ;
  2592. is_valid_rec proc
  2593. ; Out:  cy   sector illegal
  2594. ;
  2595. ; test auf gueltigen track/sector auf DISC
  2596. ;
  2597. COMMENT *
  2598.       mov al,track
  2599.       cmp al,LAST_TRCK0
  2600.       stc
  2601.       ja  short @@exit
  2602.       mov al,sector
  2603.       cmp al,LAST_SEC0
  2604.       stc
  2605.       ja short @@exit
  2606. ; ok, clear cy
  2607. *
  2608.       clc
  2609. @@exit:
  2610.       ret
  2611. is_valid_rec endp
  2612.  
  2613. ;
  2614. ; lies ganzen Track, falls noch nicht im Speicher
  2615. ;
  2616. read_track proc
  2617. ;
  2618. ; Error: cy=1
  2619. ;
  2620.       PUSHR <ax,bx,cx,dx>
  2621.  
  2622. ; der DirTrack wird nur gelesen nach HOME
  2623.  
  2624.       mov  al,track
  2625.       cmp  al,dirtrack
  2626.       jnz  short @@nodir
  2627.       cmp  home_flag,TRUE
  2628.       mov  home_flag,FALSE
  2629.       mov  bx,offset dirtrbuf
  2630.       jz  short @@read_dir_track
  2631.       clc
  2632.       jmp short @@exit
  2633. @@nodir:
  2634.        cmp  al,last_track_read
  2635.        jz   short @@exit
  2636.  
  2637.            mov  bx,offset secbuf
  2638.            mov  last_track_read,al
  2639. @@read_dir_track:
  2640.            mov  r_track,al
  2641.  
  2642.            call read_phys_track
  2643.            ; ab jetzt CY nicht mehr veraendern !
  2644.  
  2645. @@exit:
  2646.       POPR <dx,cx,bx,ax>
  2647.       ret
  2648. read_track endp
  2649.  
  2650. ;
  2651. ; lies ganzen Track, in den geschrieben werden soll, ein,
  2652. ;  falls noch nicht im Speicher
  2653. ;
  2654. read_w_track proc
  2655. ;
  2656. ; Error: cy=1
  2657. ;
  2658.       PUSHR <ax,bx,cx,dx>
  2659.       ; der DirTrack ist sowieso im Speicher und braucht
  2660.       ; nicht gelesen werden
  2661.       mov  al,track
  2662.       cmp  al,dirtrack
  2663.       jz  short @@exit
  2664.  
  2665.       cmp  al,last_track_written
  2666.       jz   short @@exit
  2667.  
  2668.       ; falls noetig alten Track im WriteBuffer erst
  2669.       ; ausschreiben
  2670.       call write_out_old_track
  2671.  
  2672.       mov  al,track
  2673.       mov  bx,offset wrtbuf
  2674.       mov  last_track_written,al
  2675.       mov  r_track,al
  2676.       call read_phys_track
  2677.  
  2678.       ; ab jetzt CY nicht mehr veraendern !
  2679.  
  2680. @@exit:
  2681.       POPR <dx,cx,bx,ax>
  2682.       ret
  2683. read_w_track endp
  2684.  
  2685. ; physikalische Sektorlaenge herstellen
  2686. dos_phys_len proc
  2687.        PUSHR <es,ax,di>
  2688.        mov  ax,0
  2689.        mov  es,ax
  2690.        les  di,[es:78h]
  2691.        mov  al,ms_phys_sec_len
  2692.        mov  es:[di+3],al
  2693.        POPR <di,ax,es>
  2694.        ret
  2695. dos_phys_len endp
  2696.  
  2697. ; physikalische Sektorlaenge herstellen
  2698. cpm_phys_len proc
  2699.        PUSHR <es,ax,di>
  2700.        mov  ax,0
  2701.        mov  es,ax
  2702.        les  di,[es:78h]
  2703.        mov  al,cpm_phys_sec_len
  2704.        mov  es:[di+3],al
  2705.        POPR <di,ax,es>
  2706.        ret
  2707. cpm_phys_len endp
  2708.  
  2709. normalize_pointer proc ; es:bx
  2710.        PUSHR <cx,ax>
  2711.         mov ch,bl
  2712.         and ch,0fh
  2713.         LOG2(16)         ; NACH CL
  2714.         shr bx,cl        ; bx:=16
  2715.         mov ax,es
  2716.         add ax,bx
  2717.         mov es,ax
  2718.         mov bx,0
  2719.         mov bl,ch
  2720.        POPR <ax,cx>
  2721.        ret
  2722. normalize_pointer endp
  2723.  
  2724. read_phys_track proc
  2725.       PUSHR <ax,bx,cx,dx>
  2726.  
  2727. ; der naechste Test sollte eigentlich nicht noetig sein, aber
  2728. ; mein 386 Ami Bios weigert sich sonst, den gleichen Track nochmal
  2729. ; zu lesen; jedenfalls kann auch gleich ein Diskwechsel festgestellt
  2730. ; werden
  2731.       call tst_disk_change
  2732.       jz   short @@no_change
  2733.       mov  last_track_read,0ffh
  2734. @@no_change:
  2735.  
  2736.       mov  cl,retry_count
  2737.       xor  ch,ch
  2738. @@tryread:
  2739.         call cpm_phys_len
  2740.         push es
  2741.         mov  ax,emudata_seg
  2742.         mov  es,ax                ; ist sonst z80cpu_seg
  2743.         push cx
  2744.  
  2745.           mov  dl,cpm_drive       ; diskno
  2746.           mov  dh,side
  2747.           mov  ch,r_track
  2748.           call track_trans
  2749.           mov  cl,first_phys_sec  ; physical sector number
  2750.           mov  al,phys_sec_pt     ; lies ganzen Track auf einmal
  2751.           mov  ah,2               ; read sector
  2752. ;          call normalize_pointer
  2753.           int 13h                 ; es:bx := track
  2754.         pop cx
  2755.         pop es
  2756.         call dos_phys_len
  2757.         jnc  short @@exit
  2758.         cmp  ah,9
  2759.         jz   dma_bound
  2760. ; Fehler, Disk Reset und nochmal versuchen
  2761.         mov ah,0
  2762.         mov dl,cpm_drive
  2763.         int 13h                   ; disk reset
  2764.       loop  @@tryread
  2765.       stc                         ; Error, cy
  2766. @@exit:
  2767.       POPR <dx,cx,bx,ax>
  2768.       ret
  2769. read_phys_track endp
  2770.  
  2771. ; Trackuebersetzung nur fuer CP/M 86 DS DD noetig
  2772. ; muss vor phys. read/write Ops aufgerufen werden
  2773. ;
  2774. ; in: ch: zu uebersetzender Track
  2775. ;     dh: Disk Side
  2776.  
  2777. track_trans proc
  2778.           cmp  ch,phys_tracks
  2779.           jb  short @@exit
  2780.           cmp  cpm86dd_flag,TRUE
  2781.           jnz short @@nocpm86dd
  2782.           push ax
  2783.           mov  al,ch
  2784.           mov  ch,79
  2785.           sub  ch,al
  2786.           pop  ax
  2787.           inc  dh                 ; Seite 1
  2788.           jmp  short @@exit
  2789. @@nocpm86dd:
  2790.           sub ch,40
  2791.           inc  dh                 ; Seite 1
  2792. @@exit:
  2793.           ret
  2794. track_trans endp
  2795.  
  2796. tst_disk_change proc
  2797.           cmp hd_drive_flag,FALSE
  2798.           jz  short @@exit        ; kein Diskwechsel => Z
  2799.           mov ah,16h
  2800.           mov dl,cpm_drive
  2801.           int 13h  ; Test auf Wechsel
  2802.           cmp ah,0                ; kein Diskwechsel => Z
  2803. @@exit:
  2804.           ret
  2805. tst_disk_change endp
  2806.  
  2807. ; falls noch nicht geschriebener Track im Speicher ist,
  2808. ; der kein DirTrack ist, ausschreiben
  2809.  
  2810. write_out_old_track proc
  2811.       cmp  write_flag,TRUE
  2812.       jnz short @@exit
  2813.       mov  al,last_track_written
  2814.       mov  w_track,al
  2815.       mov  outbuf_ptr,offset wrtbuf
  2816.         call write_phys_track
  2817.       mov  write_flag,FALSE
  2818. @@exit:
  2819.       ret
  2820. write_out_old_track endp
  2821.  
  2822. ;
  2823. ; den Dir Track auf Disk schreiben
  2824. ;
  2825. write_out_dir proc
  2826.       call write_out_old_track    ; falls noetig
  2827.       mov  al,dirtrack
  2828.       mov  w_track,al
  2829.       mov  outbuf_ptr,offset dirtrbuf
  2830.           call write_phys_track
  2831.       ret
  2832. write_out_dir endp
  2833.  
  2834. write_phys_track proc
  2835.       PUSHR <ax,bx,cx,dx>
  2836.       mov  cl,retry_count
  2837.       xor  ch,ch
  2838. @@trywrit:
  2839.         call cpm_phys_len
  2840.         push es
  2841.         mov  ax,emudata_seg
  2842.         mov  es,ax
  2843.         push cx
  2844.           mov  dl,cpm_drive          ; diskno
  2845.           mov  dh,side
  2846.           mov  ch,w_track
  2847.           call track_trans
  2848.           mov  cl,first_phys_sec  ; physical sector number
  2849.           mov  bx,outbuf_ptr
  2850.           mov  al,phys_sec_pt
  2851. ;          call normalize_pointer
  2852.           mov  ah,3               ; read sector
  2853.           int 13h                 ; track := es:bx
  2854.         pop cx
  2855.         pop es
  2856.         call dos_phys_len
  2857.         jnc  short @@exit
  2858.         cmp  ah,9
  2859.         jz   dma_bound
  2860.         mov ah,0
  2861.         mov dl,cpm_drive
  2862.         int 13h                   ; disk reset
  2863.       loop  @@trywrit
  2864.       stc                         ; Error,  cy
  2865. @@exit:
  2866.       POPR <dx,cx,bx,ax>
  2867.       ret
  2868. write_phys_track endp
  2869.  
  2870. ;
  2871. ; versuchen, richtiges physikalisches Format zu finden
  2872. ; und disc parameter block herrichten
  2873. ;
  2874. ; falls autologin_flag = FALSE , kann das Zeitaufwendige login
  2875. ; entfallen
  2876.  
  2877. login_disc proc
  2878.       push bx
  2879.       call tst_hd_drive
  2880.       mov last_track_read,0ffh    ; Track Buffer auf leer setzen
  2881.                                   ; damit bei read_track gelesen wird
  2882.       mov write_flag,FALSE            ; sonst wird beim naechsten write
  2883.                                   ; erst alter Schrott ausgeschrieben
  2884.       cmp  autologin_flag,TRUE
  2885.       jnz  @@exit
  2886.       mov  cpm_drive,PHYS_DRV
  2887.  
  2888.       mov cpm86dd_flag,FALSE
  2889.  
  2890.       mov retry_count,2           ; Leseversuche herabsetzen,
  2891.                                   ; damit bei falschem
  2892.                                   ; Format nicht zuviel Zeit verschwendet wird
  2893.  
  2894. @@loop:
  2895.  
  2896.        cmp breakflag,TRUE
  2897.  
  2898.        CALLZ  prg_exit
  2899.  
  2900. ; erst mal mit dem zuletzt verwendeten Format versuchen
  2901. ; aber nicht, wenn letztes CP/M 86 war, da sonst das
  2902. ; aehnliche Format mit 9 Sektoren nicht erkannt wird
  2903.  
  2904.       cmp byte ptr phys_sec_pt,8
  2905.       jz  short @@tst_cpm86
  2906.  
  2907.       mov al,pspt_last
  2908.       mov phys_sec_pt,al
  2909.       mov al,phys_tracks_last
  2910.       mov phys_tracks,al
  2911.       mov al,frstps_last
  2912.       mov first_phys_sec,al       ; physical sector
  2913.       mov al,dirtr_last
  2914.       mov dirtrack,al
  2915.       inc al
  2916.       mov r_track,al
  2917.       mov bx,offset secbuf
  2918.       call read_phys_track
  2919.       mov  bx,dpb_last
  2920.       jnc  @@goodfmt
  2921.  
  2922.  
  2923. ;
  2924. ; CP/M 86 format ?
  2925. ;
  2926. ; Bedingungen: Seite 0 muss Sektoren 1-8 haben, aber nicht 1-9
  2927. ;              Seite 1 muss Sektoren 1-8 haben
  2928.  
  2929. ; setze 9 Phys. Sektoren, bei cp/m 86 mit 8 Sektoren pro Track muss
  2930. ; es einen Lesefehler geben
  2931.  
  2932. @@tst_cpm86:
  2933.       mov phys_sec_pt,9
  2934.       mov phys_tracks,40
  2935.       mov first_phys_sec,1h
  2936.       mov r_track,1+1
  2937.       mov dirtrack,1
  2938.       mov bx,offset secbuf
  2939.       call read_phys_track
  2940.       jnc  short @@nocpm86
  2941.  
  2942.       mov phys_sec_pt,8
  2943.       mov phys_tracks,40
  2944.       mov first_phys_sec,1h
  2945.       mov r_track,1+1
  2946.       mov dirtrack,1
  2947.       mov bx,offset secbuf
  2948.       call read_phys_track
  2949.       jc  short @@nocpm86
  2950.  
  2951.  
  2952.   ; Teste noch Seite 2 mit SektorNummer > 39
  2953.  
  2954.       mov phys_sec_pt,8
  2955.       mov phys_tracks,40
  2956.       mov first_phys_sec,1h
  2957.  
  2958.       mov r_track,40
  2959.       mov dirtrack,1
  2960.       mov bx,offset secbuf
  2961.       call read_phys_track
  2962.       mov  bx,offset dpb_cpm86DS
  2963.       mov  cpm86dd_flag,TRUE
  2964.       jnc  @@goodfmt
  2965.       mov  cpm86dd_flag,FALSE
  2966.       mov  bx,offset dpb_cpm86SS
  2967.       jmp  @@goodfmt
  2968.  
  2969. @@nocpm86:
  2970.  
  2971. ;
  2972. ; cpc system format ?
  2973. ;
  2974.       mov phys_sec_pt,9
  2975.       mov phys_tracks,40
  2976.       mov first_phys_sec,41h
  2977.       mov r_track,2+1
  2978.       mov dirtrack,2
  2979.       mov bx,offset secbuf
  2980.       call read_phys_track
  2981.       mov  bx,offset dpb_cpc
  2982.       jnc  short @@goodfmt
  2983. ;
  2984. ; data format ?
  2985. ;
  2986.       mov phys_sec_pt,9
  2987.       mov phys_tracks,40
  2988.       mov first_phys_sec,0c1h
  2989.       mov r_track,0+1
  2990.       mov dirtrack,0
  2991.       mov bx,offset secbuf
  2992.       call read_phys_track
  2993.       mov  bx,offset dpb_dta
  2994.       jnc  short @@goodfmt
  2995.  
  2996. @@tsteigfrm:
  2997. ;
  2998. ; is it own format
  2999. ;
  3000.       mov phys_sec_pt,9
  3001.       mov phys_tracks,40
  3002.       mov first_phys_sec,1
  3003.       mov r_track,0+1
  3004.       mov dirtrack,0
  3005.       mov bx,offset secbuf
  3006.       call read_phys_track
  3007.       mov  bx,offset dpb_eig
  3008.       jnc  short @@goodfmt
  3009.  
  3010. @@badfmt:
  3011.       mov  bx,offset bad_format
  3012.       call puts
  3013.       call conin
  3014.       cmp  autologin_flag,TRUE    ; waehrend conin kann Edit DPH gewes. sein
  3015.       jnz  short @@exit
  3016.       jmp  @@loop
  3017.  
  3018. @@goodfmt:
  3019.  
  3020. ; physikalisches Format merken
  3021.  
  3022.        mov al,phys_sec_pt
  3023.        mov pspt_last,al
  3024.        mov al,first_phys_sec
  3025.        mov frstps_last,al
  3026.        mov al,dirtrack
  3027.        mov dirtr_last,al
  3028.        mov dpb_last,bx
  3029.  
  3030.        mov  si,bx
  3031.        mov  di,offset dpb0+ZBIOSDISPL
  3032.        mov  cx,size dpb
  3033.        cld
  3034.        rep movsb                  ; es:di := ds:si
  3035.  
  3036. @@exit:
  3037.        pop bx
  3038.        mov retry_count,5
  3039.        ret
  3040. login_disc endp
  3041.  
  3042.  
  3043. write proc
  3044. ;
  3045. ; write a record of 128 bytes
  3046. ;
  3047.        cmp  diskno,RMD
  3048.        jnz  short wtodisc
  3049.        call calcadr               ; ax:bx := record adress
  3050.        jc   short @@bad
  3051.        call wrtrec                ; buffer := record
  3052.        jc   short @@bad
  3053.        xor  al,al                 ; write ok
  3054.        ret
  3055. @@bad: mov al,1
  3056.        ret
  3057. write endp
  3058.  
  3059. wtodisc proc
  3060.        push cx
  3061.        call is_valid_rec          ; ax=rec/sec
  3062.        pop  cx
  3063.        jc   short @@badsec
  3064.  
  3065.  
  3066. ; if track noch nicht im Buffer
  3067. ;    if noch alter Track im Buffer
  3068. ;       alten Track ausschreiben
  3069. ;    endif
  3070. ;    lies neuen Track ein
  3071. ; endif
  3072. ; if track ist dirtrack
  3073. ;    if noch alter Track im Buffer
  3074. ;       alten Track ausschreiben
  3075. ;    endif
  3076. ;    dirtrack ausschreiben
  3077. ; else
  3078. ;    Setze Flag, daß Sektor geschreiben wurde
  3079. ; endif
  3080. ;
  3081.  
  3082.        push cx                    ; bdos info, ob dirsectoren
  3083.        call read_w_track
  3084.        pop  cx
  3085.        jc   short @@badsec
  3086. ;
  3087. ; record # ist in ah
  3088. ;
  3089.  
  3090.        push cx
  3091.        mov  al,WRITE_OP
  3092.        call get_adr_in_buf
  3093.        mov  ax,ds                 ; ax:= seg track buffer
  3094.        call wrtrec
  3095.        pop  cx
  3096.        cmp  cl,1
  3097.        jz   short @@isdir1
  3098.        call is_dir_track
  3099.        jz   short @@isdir1
  3100.  
  3101.        mov  write_flag,TRUE
  3102.        mov  al,track
  3103.        mov  last_track_written,al
  3104.        mov  al,0                  ; o.k.
  3105.        jmp  short @@exit
  3106.  
  3107. @@isdir1:
  3108.        call write_out_dir
  3109.        jc short @@badsec
  3110.        mov  al,0
  3111.        jmp  short @@exit
  3112. @@badsec:
  3113.       mov al,1
  3114. @@exit:
  3115.       ret
  3116. wtodisc endp
  3117.  
  3118. ;
  3119. ; In: ax:bx = source adr
  3120. ;
  3121. rdrec proc
  3122. ;
  3123.        PUSHR <si,di,bx,cx,ax>
  3124.        push ds
  3125.          mov si,bx
  3126.          mov di,dmaad             ; ds MUSS =  emudata_seg sein
  3127.          mov ds,ax
  3128.          mov cx,RECORD_LEN/2             ; record laenge in words
  3129.          cld
  3130.          rep movsw                ; es:di := ds:si
  3131.        pop ds
  3132.        POPR <ax,cx,bx,di,si>
  3133.        ret
  3134. rdrec endp
  3135. ;
  3136. ; In: ax:bx=target adr
  3137. ;
  3138. wrtrec proc
  3139.        PUSHR <si,di,cx,ax>
  3140.        push es
  3141.        push ds
  3142.  
  3143.        mov si,dmaad               ; ACHTUNG: der MOV muss
  3144.                                   ; vor DS Segmentwechsel sein
  3145.        mov di,bx
  3146.        mov bx,ax                  ; ramdisc
  3147.        mov ax,es                  ; cp/m
  3148.        mov es,bx
  3149.        mov ds,ax
  3150.  
  3151.        mov cx,RECORD_LEN/2               ; record laenge in words
  3152.        cld
  3153.        rep movsw                  ; es:di := ds:si
  3154.        pop ds
  3155.        pop es
  3156.        POPR <ax,cx,di,si>
  3157.        ret
  3158. wrtrec endp
  3159.  
  3160. emulator_seg ends
  3161.  
  3162.  
  3163. end init
  3164.  
  3165.  
  3166.  
  3167.