home *** CD-ROM | disk | FTP | other *** search
-
- ;
- ; BIOS FUER DEN CP/M EMULATOR
- ;
- ;
- ; (C) 1990,1991,1992 by Jürgen Weber
- ;
- ; Version: 1.0
- ; 1.1 Disparameter laden/speichern
- ; 1.11 bios read zeigt Dos File Ende an
- ; 1.2 conin übersetzt CsrTasten nach WS
- ; ergänzte time fkt und Blink Attribut
-
- INCLUDE Z80EMU.INC
-
- EXTRN conout:near,conin:near,reset_conout:near,sel_scr_page:near
- EXTRN cursor_off:near,cursor_on:near
-
- PUBLIC prg_exit,bios88
- PUBLIC breakflag
-
-
- %nosyms ; keine symbols im listing
- warn ; alle warnings an
-
- DOSSEG ; UNBEDINGT notwendig, da fuer Speicherverwaltung des Z80 Segments
- ; und der Ramdisk Stacksegment als letztes kommen muss
- ; auch mussen Stack- und Codesegment Klassen 'STACK' bzw.
- ; 'CODE'bekommen
-
- LOCALS ; fuer locale Labels in Prozeduren
-
- JUMPS ; automatische Sprunglaengenanpassung
-
- CALLZ macro label ; Call if zero
- local exit
- jnz short exit
- call label
- exit:
- endm
-
- CALLNZ macro label ; Call if not zero
- local exit
- jz short exit
- call label
- exit:
- endm
-
- CALLC macro label ; Call if carry
- local exit
- jnc short exit
- call label
- exit:
- endm
-
-
- ;
- ; segmente des emulators:
- ;
-
- ; emulator_seg : emulator und bios code
- ; emudata_seg : emulator data und z80 bios code
- ; stack_seg : emulator und bios stack
- ; z80cpu_seg : Segment des emulierten z80, 64k, dummy at 0 (in z80seg_adr)
- ; ramdisc_seg : ramdisc fuer cp/m
- ;
-
-
- include dos.inc ; dos functionen
-
- ;
- ; ******* KONSTANTEN ********
- ;
-
- DEFAULT_DMA EQU 80H
- RECORD_LEN EQU 80H
-
-
-
- ZBIOSLEN equ (zbiosend-zbiosbeg)
- ZBIOSDISPL equ (0ffffh-ZBIOSLEN) and 0ff00h
- ; dies bewirkt Start auf neuer Seite, damit Bios auf XX00 anfaengt
- ZBIOS equ offset zbiosbeg+ZBIOSDISPL
-
- CTRL_BREAK_INT EQU 1BH
-
- ESC_KEY EQU 27
-
- EMU_SCR_PAGE EQU 0
- DOS_SCR_PAGE EQU 1
-
- ; folgende Konstanten werden als Flags zur Addressberechnung
- ; im Sektorbuffer benoetigt
-
- READ_OP EQU 0
- WRITE_OP EQU 0FFH
-
- PHYSDSK EQU 0
-
-
- BDOSLEN equ 1600h ; Laenge ccp+bdos cp/m 2.2
- BDOS_CHK_SUM equ 2d88h ; Checksumme ueber Bdos Copyright Meldung
-
- SYS_FRST_SEC EQU 28
- ; erster absoluter Sektor, den Bdos auf SysSpuren belegt
-
- SYS_SECS EQU BDOSLEN/RECORD_LEN ; Anzahl Sektoren, die System belegt
-
- TRACK_BUF_LEN EQU 10*512
-
- CPM_EOF EQU 26
-
- PHYS_DRV EQU 0 ; # diskettenlaufwerk
- RMD equ 1 ; # ramdisk
-
-
- PHYS_SEKLEN equ 512
- NSECTS equ 2
- NDISKS equ 2 ; last disk # +1
- BPS equ 2
-
- ; -------------------------------------
- ;
- ; emulator data segment
- ;
- ; --------------------------------------
-
-
- emudata_seg segment para public 'DATA'
-
- include zbios.inc
-
- dpb_cpc dpb <SPTC,BSHC,BLMC,EXMC,DSMC,DRMC,AL0C,AL1C,CKSC,OFFC>
- dpb_dta dpb <SPTD,BSHD,BLMD,EXMD,DSMD,DRMD,AL0D,AL1D,CKSD,OFFD>
- dpb_eig dpb <SPTD,BSHD,BLMD,EXMD,DSMD,DRMD,AL0D,AL1D,CKSD,OFFD>
- dpb_cpm86SS dpb <SPT0,BSH0,BLM0,EXM0,DSM0,DRM0,AL00,AL10,CKS0,OFF0>
- dpb_cpm86DS dpb <SPT1,BSH1,BLM1,EXM1,DSM1,DRM1,AL01,AL11,CKS1,OFF1>
-
- ramdisklen dw (?)
- lasttrack_rd db (?) ; 0..127 (512K)
-
- PUNCH_BUF_SIZE equ 512
- READER_BUF_SIZE equ 256
-
- start_string db 27,'E',27,'Y',32+8,32+24,27,'p'
- db 'ZSIM',27,'q'
- db 27,'Y',32+10,32+18
- db 'Free for personal use'
- db 27,'Y',32+12,32+18
- db 27,'p','USE AT YOUR OWN RISC !',27,'q'
- db 27,'Y',32+15,32+18
- db '(C) 1990,1992 by '
- db 27,'Y',32+17,32+18
- db 'Jürgen G. Weber'
- db 27,'Y',32+18,32+18
- db 'Wiesentalstr. 1'
- db 27,'Y',32+19,32+18
- db 'W-7170 Schwäbisch Hall'
- db 27,'Y',32+20,32+18
- db 'Federal Republic of Germany'
- db 27,'Y',32+24,32+17,27,'p'
- db 'Insert a CP/M disk then press any key'
- db 27,'q'
- db 0
-
-
- db 'ZSIM looks for the fellowing string: '
-
- bdos_str db ' COPYRIGHT (C) 1979, DIGITAL RESEARCH '
- bdos_str_end equ this byte
-
- cpmsys_fileName db 'CPMSYS.CPM',0
- ramdisc_fname db 'RAMDISC.CPM',0
- punch_fileName db 'PUNCH.CPM',0
- reader_fileName db 'READER.CPM',0
- temp_fname db '\EMUCPM.OVL',0
-
- fmt_file_flg db FALSE
- fmt_file_name db 80 dup (?)
- file_promt_str db 'Enter Disk Parameter filename: ',0
- file_promt_str_end equ $
-
-
- menutab label word
-
- dw m_esc
-
- dw m_continue
- dw m_save_rd_quit
- dw m_quit
- dw m_save_rd
- dw m_del_pf
- dw m_init_rdr
- dw m_shell
- dw m_edit_disk_parm
- dw m_save_d_parm
- dw m_load_d_parm
- dw m_w_boot
- dw m_info
-
- menu_strs db '\Continue','|'
- db 'Save \Ramdisc/Quit','|'
- db '\Quit','|'
- db '\Save Ramdisc','|'
- db '\Delete Punch File','|'
- db '\Init Reader','|'
- db '\OS Shell','|'
- db 'Disk \Parameters','|'
- db 'Sa\ve Parameters','|'
- db '\Load Parameters','|'
- db '\Warm Boot','|'
- db '\About','|'
- db 0
- menu_strs_end equ this byte
-
- MESG_ESC equ 0
-
- LONGEST_MESSAGE=20
- MESSAGE_COUNT=12
-
- prg_ext_box_res dw 0ffffh
-
- ins_cpm_disk_txt db 'Insert CP/M disk and press ENTER|',0
- ins_cpm_disk_txt_end equ this byte
-
- ins_dos_disk_txt db 'Insert MS-DOS disk and press ENTER|',0
- ins_dos_disk_txt_end equ this byte
-
- disk_err_txt db 'Disk Error. Press ESC|',0
- disk_err_txt_end equ this byte
-
- disk_ful_txt db 'Disk full. Press ESC|',0
- disk_ful_txt_end equ this byte
-
- f_not_found_txt db 'File not found. Press ESC|',0
- f_not_found_txt_end equ this byte
-
- on_sign_string equ this byte
- db 27,'E',27,'H'
- db 'jgw 64K cp/m 80 bios ver 1.2 -- '
- db ??date
- db ' (C) 1990,1992 by Jürgen G. Weber'
- db 13,10,10
- db 'BDOS: ',27,'j',0
- bad_format db 13,10
- db 'Unknown disc format. Insert new disc and press any key'
- db 13,10,0
- no_sys db 13,10
- db 'Could not read System sectors. Insert'
- db ' new disc and press any key'
- cr_lf_txt db 13,10,0
- control_c_txt db '^C...',0
-
- mfulstr db 13,10,'Not enough memory',13,10
- mfsend equ this byte
-
- illparm_str db 13,10,'Illegal Command Line Parameter',13,10
- illparm_strend equ this byte
-
- dma_txt db 13,10
- db 'Fatal: DMA Boundary Crossing'
- db 13,10
- dma_txt_end equ this byte
-
- exit_str db 'Type EXIT to return to CP/M Emulator ...',13,10
- exit_str_end equ this byte
-
-
- exec_par_block equ this word
- dw 0
- dw offset exec_cmd_line
- dw seg exec_cmd_line
- dd 0
- dd 0
- exec_cmd_line equ this word
- db ec_str_end-ec_str
- ec_str db ''
- ec_str_end equ this byte
- db 13
-
- no_cc_str db 13,10,'COMMAND.COM not found. Press ESC.',13,10
- no_cc_str_end equ this byte
-
- exec_fname db '\COMMAND.COM',0
-
-
- good_dpb_edit db (?)
- db 2 dup (?)
-
- breakflag db FALSE
-
- old_int1b dd (?)
- stackpoi dw (?)
-
- sp_save dw (?)
- ss_save dw (?)
-
- z80seg_adr dw (?)
- rdseg_adr dw (?)
- rdlen dw (?)
- exec_mem_start dw (?)
-
- psp_adr dw (?)
- prog_len dw (?)
- mem_end dw (?)
- ovl_base dw (?)
- hd_drive_flag db (?)
- ms_current_drive db (?)
-
- tmp_word dw (?)
-
- z80_pc dw ?
- ccp_adr dw ?
- bdos_adr dw ?
- bios_adr dw ?
-
- month_tab db 31,28,31,30,31,30,31,31,30,31,30,31
-
- ; flag, dass im Speicher noch ein nicht auf disk geschriebener
- ; nicht-dir Track ist
- write_flag db FALSE
-
- in_boot_flag db FALSE
-
- home_flag db FALSE
- last_track_written db 0,0
- dirtrack db 0,0
- r_track db 0,0
- w_track db 0,0
-
- track db 0,0
- sector db 0,0
- last_track_read db 0ffh ; default unmoeglich, noch nicht gelesen
-
- ms_phys_sec_len db (?)
- pspt_last db 9
- phys_tracks_last db 40
- frstps_last db 041h
- dirtr_last db 2
- dpb_last dw offset dpb_cpc
-
- cpm86dd_flag db FALSE
-
- ; ACHTUNG: die Reihenfolge der folgenden Vars nicht
- ; verändern, da sie so ans Modula UP übergeben werden
-
- cpm_drive db PHYS_DRV
- first_phys_sec db 41h
- phys_tracks db (?)
- phys_sec_pt db (?)
- cpm_phys_sec_len db 2
- autologin_flag db TRUE
-
- ; end Reihenfolge wichtig
-
-
- retry_count db 5
- side db 0
-
- dmaad dw ? ;direct memory address
- diskno db ? ;disk number 0-15
-
-
- punch_buf_entries dw (?)
- punch_buf_ptr dw (?)
-
- reader_empty_flag db TRUE
- reader_buf_entries dw (?)
- reader_buf_ptr dw (?)
- reader_file_pointer dw 0,0
-
-
- ; zeigt auf Bufferadresse des Tracks, der geschrieben werden soll
- outbuf_ptr dw (?)
-
- cpm_bdos_buf db BDOSLEN dup (?)
-
- dirtrbuf db TRACK_BUF_LEN dup (?)
- secbuf db TRACK_BUF_LEN dup (?)
- wrtbuf db TRACK_BUF_LEN dup (?)
-
- punch_buf db PUNCH_BUF_SIZE dup (?)
- reader_buf db READER_BUF_SIZE dup (?)
-
- ; dass die Buffer in der EXE-Datei erscheinen, laesst sich
- ; durch die Verwendung einer Gruppe mit den Buffern als
- ; Extra Segment umgehen
- ; jedoch muss dann bei jedem offset der Gruppenname angegeben werden
-
- emudata_seg ends
-
- ; ------------------------
-
- DATA segment para public 'DATA'
- ; Dummysegment zur Kombinierung mit Modula 2
- DATA ends
-
- STACK_SIZE EQU 1000H
-
- stack_seg segment para stack 'STACK'
- dw STACK_SIZE dup (?) ; Stack ist recht gross
- ; wegen Modula 2 UPs
- stack_seg ends
-
- z80cpu_seg segment at 0 ; dummy
- z80cpu_seg ends
-
- ; -------------------------------------
- ; emulator und bios segment start
- ; -------------------------------------
-
- emulator_seg segment para public 'CODE'
-
- assume cs:emulator_seg,ds:emudata_seg,es:z80cpu_seg,ss:stack_seg
-
- m2_ds dw (?) ; fmodula routinen erwarten
- ; bei cs:0 ihr DS
-
- init proc ; emulator start
-
- mov ax,emudata_seg
-
- mov ds,ax ; damit Vars angesprochen werden koennen
-
- mov stackpoi,sp
-
- mov bx,ss ; finde Programmende
- mov ax,sp
- mov cl,4
- shr ax,cl ; ax:=4
- add bx,ax ; bx=>programm ende
- inc bx ; vorsichtshalber
-
- push bx
- mov ax,es ; es:0 => PSP
- mov psp_adr,ax
- mov bx,ax
-
- mov si,0
- mov ax,[es:si+2] ; ax=> mem end
- mov mem_end,ax
- push ax
- sub ax,1000h
- mov ovl_base,ax
- pop ax
- push ax
- sub ax,bx ; mem end - prg start
- mov prog_len,ax
- pop ax ; mem end
- pop bx ; prg end
-
-
- sub ax,bx ; ax:=free mem
- mov z80seg_adr,bx
-
- mov cx,10000h / 16
- add bx,cx
-
- mov rdseg_adr,bx
-
- sub ax,cx
- jc short @@memful
-
- mov ramdisklen,ax
-
- call parse_cmd_line
- mov dx,offset illparm_str
- mov cx,illparm_strend-illparm_str
- jc short abort ; Fehler: falscher Parameter
-
- mov bx,offset start_string
- call puts
- call conin ; wait for keypressed
-
- call patch_int
-
- DOS GET_DISK_DRIVE
- mov ms_current_drive,al
-
- mov ax,z80seg_adr
- call clearz80 ; loesche z80 mem
-
- call init_ramdisc
-
- call patch_box
-
- ; physikalische Sektorlaenge merken
-
- push es
- mov ax,0
- mov es,ax
- les di,[es:78h]
- mov al,es:[di+3]
- pop es
- mov ms_phys_sec_len,al
-
-
- ;
- ; offset z80 bios start merken
- ;
- mov bios_adr,ZBIOSDISPL ; bios Sprungleiste einrichten
-
- call z80ini ; reset z80 cpu
-
- mov ax,z80seg_adr
- mov es,ax
- mov ds,ax
- ;
- ; weiter mit cp/m cold boot
- ;
- mov al,0
- jmp bios88
-
- @@memful:
- mov cx,mfsend-mfulstr
- mov dx,offset mfulstr
- abort:
- mov bx,STDERR
- DOS WRITE_TO_HANDLE
- mov al,1
- DOS TERMINATE_EXE
- init endp
-
- parse_cmd_line proc
- PUSHR <ax,bx,cx,di,si,ds,es>
- mov ax,ds
- mov es,ax ; es:=prog vars
- mov ax,psp_adr
- mov ds,ax
- mov di,offset fmt_file_name
- mov si,80h ; si => Commandozeilenparam
- lodsb ; count
- mov ch,0
- mov cl,al
- or al,al
- mov al,FALSE
- jz short @@no_parm
- @@findslash:
- lodsb
- cmp al," "
- loopz @@findslash ; +DEC CX
- cmp al,"/"
- jnz short @@parm_err
- lodsb
- dec cx
- and al,not ('a'-'A') ; toupper
- cmp al,'F'
- jnz short @@parm_err
- mov di,offset fmt_file_name
- @@SKIP_BLN:
- lodsb
- cmp al," "
- loopz @@SKIP_BLN; +DEC CX
- stosb ; 1. non-blank
-
- rep movsb
- mov al,0
- stosb ; Filename Endzeichen
- mov al,TRUE
- @@no_parm:
- POPR <es,ds,si,di,cx,bx>
- mov fmt_file_flg,al
- pop ax
- clc
- ret
- @@parm_err:
- POPR <es,ds,si,di,cx,bx,ax>
- stc
- ret
- parse_cmd_line endp
-
- tst_hd_drive proc
- PUSHR <ax,dx>
- mov hd_drive_flag,FALSE
- mov dl,cpm_drive
- mov ah,15h ; Laufwerktyp ?
- int 13h
- jc short @@exit ; PC,XT
- cmp ah,2 ; erkennt DiskWechsel
- jnz short @@exit
- mov hd_drive_flag,TRUE
- @@exit:
- POPR <dx,ax>
- ret
- tst_hd_drive endp
-
- ;
- ; der Interupt 1bH (Control-Break Interupt) muß auf eine Routine
- ; gelegt werden, die ein Abbruch Flag setzt
- ; Dieses wird dann bei jedem Bios Aufruf ausgewertet
- ;
- patch_int proc
- PUSHR <ds,es,ax,bx,dx>
- mov al,CTRL_BREAK_INT
- DOS GET_VECTOR
- mov word ptr old_int1b,bx
- mov bx,es
- mov word ptr old_int1b+2,bx
- mov dx,offset new_int1b
- push cs
- pop ds
- mov al,CTRL_BREAK_INT
- DOS SET_VECTOR
- POPR <dx,bx,ax,es,ds>
- ret
- patch_int endp
-
- restore_int proc
- push ds
- lds dx,old_int1b
- mov al,CTRL_BREAK_INT
- DOS SET_VECTOR
- pop ds
- ret
- restore_int endp
-
- new_int1b proc
- push ax
- push ds
- mov ax,emudata_seg
- mov ds,ax
- mov breakflag,TRUE
- pop ds
- pop ax
- iret
- new_int1b endp
-
- ; wird auch von Z80EMU.OP76 HALT aufgerufen
-
- prg_exit proc FAR
- PUSHR <ds,es,ax>
- PUSHR <bx,cx,dx,si>
- mov ax,emudata_seg
- mov ds,ax
- mov ax,z80seg_adr
- mov es,ax
- call restore_int
- mov breakflag,FALSE
-
- call wrt_out_punch
-
- mov cx,menu_strs_end-menu_strs ; high(messages)
- mov si,offset menu_strs ; offs(messages)
-
- call box_call
- sal ax,1
- mov di,ax
- call menutab[di]
-
- call patch_int
- POPR <si,dx,cx,bx>
- POPR <ax,es,ds>
- ret
- prg_exit endp
-
-
- ; Menü durch ESC abgebrochen
- m_esc proc
- ret
- m_esc endp
-
- ; Menüpunkt Emulation fortfahren
- m_continue proc
- ret
- m_continue endp
-
- ; Menüpunkt Ramdisk speichern
- m_save_rd proc
- call save_ramdisc
- ret
- m_save_rd endp
-
- ; Menüpunkt Quit
- m_quit proc
- ; etwaige Zeichen im Punch Buffer noch ausschreiben
- call wrt_out_punch
-
- mov cl,31 ; GotoXY(1,25)
- call conout
- mov cl,1
- call conout
- mov cl,25
- call conout
- mov al,0
- ABORT_EMU:
- push ax
- call ins_dos_disk
- pop ax
- DOS TERMINATE_EXE
- m_quit endp
-
- ; Menüpunkt Ramdisk speichern + Quit
- m_save_rd_quit proc
- call save_ramdisc
- jmp short m_quit
- m_save_rd_quit endp
-
- ; Menüpunkt Punch buffer file löschen
- m_del_pf proc
- call del_punch_file
- ret
- m_del_pf endp
- ; Menüpunkt Reader initialisieren
- m_init_rdr proc
- call reset_reader_buf
- ret
- m_init_rdr endp
-
- ; Menüpunkt OS Shell
- m_shell proc
- call dos_shell
- ret
- m_shell endp
-
- ; Menüpunkt Diskettenparameter editieren
- m_edit_disk_parm proc
- call edit_disk_pars
- cmp good_dpb_edit,1
- jnz short @@exit
- mov cpm86dd_flag,FALSE
- mov ah,0
- mov al,dpb0.off-dpb0.spt ; off
- call get_dpb_entrie ; nach bx
- mov dirtrack,bl
-
- cmp in_boot_flag,TRUE
- jz short @@exit ; mit boot weitermachen
- call m_w_boot
- @@exit:
- ret
- m_edit_disk_parm endp
-
- prepare_fname proc
- mov di,offset fmt_file_name
- push di
- mov cx,80
- mov si,offset file_promt_str
- mov bx,file_promt_str_end-file_promt_str
- call input_string
- pop bx
- or byte ptr [bx],0 ; Test ob was eingegeben, nein => Z
- ret
- prepare_fname endp
-
- ; Menüpunkt Diskettenparameter speichern
- m_save_d_parm proc
- call prepare_fname
- jz short @@exit
- call save_disk_pars
- @@exit:
- ret
- m_save_d_parm endp
-
- ; Menüpunkt Diskettenparameter laden
- m_load_d_parm proc
- call prepare_fname
- jz short @@exit
- call load_disk_pars
- jmp short m_w_boot
- @@exit:
- ret
- m_load_d_parm endp
-
- ; Menüpunkt CP/M warm boot durchführen
- m_w_boot proc
- mov sp,stackpoi
- call patch_int
- mov al,1
- jmp bios88
- m_w_boot endp
-
- ; Menüpunkt About Author
- m_info proc
- call about_author
- ret
- m_info endp
-
-
-
- ; Fehler durch Ueberschreiten der DMA Segment Grenze
- ; siehe c't 4/90 S.412
-
- dma_bound proc
- mov bx,STDERR
- mov cx,dma_txt_end-dma_txt
- mov dx,offset dma_txt
- DOS WRITE_TO_HANDLE
- mov al,1
- jmp ABORT_EMU
- dma_bound endp
-
- ; out: ax=result
- ins_dos_disk proc
- mov al,ms_current_drive
- cmp al,cpm_drive
- jnz short @@exit
- mov si,offset ins_dos_disk_txt
- mov cx,ins_dos_disk_txt_end-ins_dos_disk_txt
- call box_call
- @@exit:
- ret
- ins_dos_disk endp
-
- ; out: ax=result
- ins_cpm_disk proc
- mov al,ms_current_drive
- cmp al,cpm_drive
- jnz short @@exit
- mov si,offset ins_cpm_disk_txt
- mov cx,ins_cpm_disk_txt_end-ins_cpm_disk_txt
- call box_call
- @@exit:
- ret
- ins_cpm_disk endp
-
-
- disp_disk_err proc
- PUSHR <si,cx>
- pushf ; cy aufheben
- mov si,offset disk_err_txt
- mov cx,disk_err_txt_end-disk_err_txt
- call box_call
- POPR <cx,si>
- popf
- ret
- disp_disk_err endp
-
-
- disp_f_not_found proc
- pushf ; cy aufheben
- PUSHR <si,cx>
- mov si,offset f_not_found_txt
- mov cx,f_not_found_txt_end-f_not_found_txt
- call box_call
- POPR <cx,si>
- popf
- ret
- disp_f_not_found endp
-
- disp_disk_ful proc
- PUSHR <si,cx>
- mov si,offset disk_ful_txt
- mov cx,disk_ful_txt_end-disk_ful_txt
- call box_call
- POPR <cx,si>
- ret
- disp_disk_ful endp
-
-
- EXTRN EmuMenu_DoMenue:far,EmuMenu_EditDPB:far
- EXTRN EmuMenu_InputString:far,EmuMenu_About:far,EmuMenu_init:far
-
- ; fmodula2 laedt merkwuerdigerweise am Anfang DS aus CS:0
- ; also muss man dort ds hinbringen
- ; Trotzdem sollte vor Aufruf einer Funktion DS richtig
- ; geladen sein.
-
- patch_box proc
- mov ax,DATA
- mov [cs:0],ax
- ret
- patch_box endp
-
- box_call proc ; um Modula 2 UPs aufzurufen
- ;
- ; in: ds:si => menuetext
- ; cx = len(menuetext)
- ; out: ax = result
- ;
- ; auf dem STACK muss GENUG FREI sein, um zu erzeugendes WINDOW
- ; ABZUSPEICHERN
- ;
- COMMENT @
-
- DEFINITION MODULE EmuM2;
-
- FROM SYSTEM IMPORT BYTE,WORD;
-
- TYPE PhysDiskPars = RECORD
- cpm_drive : BYTE;
- first_phys_sec : BYTE;
- phys_tracks : BYTE;
- phys_sec_pt : BYTE;
- bytes_per_sec : BYTE;
- autologin_flag : BYTE;
- END;
-
- dpb = RECORD
- spt : WORD;
- bsh : BYTE;
- blm : BYTE;
- exm : BYTE;
- dsm : WORD;
- drm : WORD;
- al0 : BYTE;
- al1 : BYTE;
- cks : WORD;
- off : WORD;
- END;
- DPBPtr = POINTER TO dpb;
- PDPPtr = POINTER TO PhysDiskPars;
-
-
- PROCEDURE DoMenue(x,y:CARDINAL;messages:ARRAY OF CHAR;
- VAR WinSave:ARRAY OF CHAR;VAR res:CARDINAL);
- (* Pop Up Menue, obere linke Ecke des Rahmens bei x,y.
- messages = String mit darzustellenden Menuepunkten; Stringende = 0C.
- Menuepunkte werden durch | getrennt, auch nach letztem Menuepunkt
- MUSS | stehen.
- Jeder Menuepunkt darf durch Druecken eines einzigen Zeichens angewaehlt
- werden, das hell dargestellt wird. Diesem Zeichen muss der Backslash \
- vorangestellt werden.
- Es duerfen maximal 20 Menuepunkte sein.
- WinSave muss genug Platz enthalten, um Hintergrund + dessen Attribute
- abzuspeichern, = (Laengster Menuepunkt+2)*2*(Menuepunkte+2)
- *)
-
- PROCEDURE EditDPB(p:DPBPtr;q:PDPPtr;
- VAR WinSave:ARRAY OF CHAR;VAR OK:BOOLEAN);
- (* Len WinSave=20*18*2=720 *)
-
- PROCEDURE InputString(VAR WinSave,s,p:ARRAY OF CHAR);
- (* Es wird vorrausgesetzt, daß prompt p < 30 und string s < 30 *)
-
-
- PROCEDURE About(VAR WinSave:ARRAY OF CHAR);
- (* Author ausgeben *)
-
-
- END EmuM2.
-
-
- @
-
- HIGH_WinSave=(LONGEST_MESSAGE+2)*2*(MESSAGE_COUNT+2)
-
- IF HIGH_WinSave gt 2*STACK_SIZE/3
- %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
- ENDIF
-
- PUSHR <bx,cx,dx,di,si,bp,ds,es>
- sub sp,HIGH_WinSave
- mov bx,sp
- mov ax,20
- push ax ; x
- mov ax,7
- push ax ; y
- push cx ; high(messages)
- push ds ; seg(messages)
- push si ; offs(messages)
- mov cx,HIGH_WinSave
- push cx ; high(WinSave)
- push ss ; seg(WinSave)
- push bx ; offs(WinSave)
- mov ax,seg prg_ext_box_res
- push ax ; seg(prg_ext_box_res)
- mov ax,offset prg_ext_box_res
- push ax ; offs(prg_ext_box_res)
- ;box_adr equ this byte
- mov ax,DATA
- mov ds,ax
- call EmuMenu_DoMenue
- add sp,HIGH_WinSave
- POPR <es,ds>
- mov ax,prg_ext_box_res
- POPR <bp,si,di,dx,cx,bx>
- ret
- box_call endp
-
-
- edit_disk_pars proc
-
- HIGH_WinSave=800
-
- IF HIGH_WinSave gt 2*STACK_SIZE/3
- %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
- ENDIF
- PUSHR <bx,cx,dx,di,si,bp,ds,es>
- sub sp,HIGH_WinSave
- mov bx,sp
- mov ax,z80seg_adr
- push ax ; seg(p) p:DPBPtr
- mov ax,offset dpb0+ZBIOSDISPL
- push ax ; offs(p)
- mov ax,seg cpm_drive
- push ax ; seg (q) q:PDPPtr;
- mov ax,offset cpm_drive
- push ax ; offs (q)
- mov cx,HIGH_WinSave
- push cx ; high(WinSave)
- push ss ; seg(WinSave)
- push bx ; offs(WinSave)
- mov ax,seg good_dpb_edit
- push ax ; seg(ok)
- mov ax,offset good_dpb_edit
- push ax ; offs(ok)
- mov ax,DATA
- mov ds,ax
- call EmuMenu_EditDPB
- add sp,HIGH_WinSave
- POPR <es,ds,bp,si,di,dx,cx,bx>
- ret
- edit_disk_pars endp
-
- ;PROCEDURE InputString(VAR WinSave,s,p:ARRAY OF CHAR);
-
- input_string proc ; ds:si = prompt, bx = len prompt
- ; ds:di = string cx = len string
- LOCAL prompt_str,lenpr,in_str,lenstr:WORD = AUTO_SIZE
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
- mov prompt_str,si
- mov in_str,di
- mov lenpr,bx
- mov lenstr,cx
- HIGH_WinSave=800
-
- IF HIGH_WinSave gt 2*STACK_SIZE/3
- %out WARNING: POPUP WINDOW REQUIRES MUCH OF STACK
- ENDIF
- PUSHR <bx,cx,dx,di,si,bp,ds,es>
- sub sp,HIGH_WinSave
- mov bx,sp
- mov ax,z80seg_adr
-
- mov cx,HIGH_WinSave
- push cx ; high(WinSave)
- push ss ; seg(WinSave)
- push bx ; offs(WinSave)
-
- push lenstr ; high(s)
- push ds ; seg(s)
- push in_str ; offs(s)
- push lenpr ; high(p)
- push ds ; seg(p)
- push prompt_str ; offs(p)
- mov ax,DATA
- mov ds,ax
- call EmuMenu_InputString
- add sp,HIGH_WinSave
- POPR <es,ds,bp,si,di,dx,cx,bx>
- mov sp,bp
- pop bp
- ret
- input_string endp
-
-
- load_disk_pars proc
- LOCAL handle:WORD = AUTO_SIZE
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
- call ins_dos_disk
- call @@fopen
- jnc short @@ok
- cmp ax,2
- CALLZ disp_f_not_found
- jc short @@exit ; nicht da
- @@ok:
- call @@fread
- call @@fclose
- mov autologin_flag,FALSE
- @@exit:
- call ins_cpm_disk
- mov sp,bp
- pop bp
- ret
-
- @@fopen:
- mov al,0
- mov dx,offset fmt_file_name
- DOS OPEN_FILE
- mov handle,ax
- ret
-
- @@fclose:
- mov bx,handle
- DOS CLOSE_FILE
- CALLC disp_disk_err
- ret
-
- @@fread:
- mov dx,offset tmp_word
- mov bx,handle
- mov cx,2
- DOS READ_FROM_HANDLE
- CALLC disp_disk_err
- mov bx,dx
- mov bx,[bx]
- cmp bx,'WJ'
- jnz short @@ldexit ; falscher Kenncode <> 'JW'
-
- ; cp/m Parameter laden
-
- mov dx,offset offset dpb0+ZBIOSDISPL
- mov bx,handle
- mov cx,size dpb
- push ds
- mov ax,z80seg_adr
- mov ds,ax
- DOS READ_FROM_HANDLE
- pop ds
- CALLC disp_disk_err
-
- ; physikalische Parameter laden
-
- mov dx,offset cpm_drive
- mov bx,handle
- mov cx,autologin_flag-cpm_drive
- DOS READ_FROM_HANDLE
- CALLC disp_disk_err
-
- @@ldexit:
- ret
- load_disk_pars endp
-
- save_disk_pars proc
- LOCAL handle:WORD = AUTO_SIZE
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
- call ins_dos_disk
- cmp ax,MESG_ESC
- jz short @@exit
- call @@fopen
- jc short @@exit
- call @@fwrite
- call @@fclose
- call ins_cpm_disk
- @@exit:
- mov sp,bp
- pop bp
- ret
-
-
- @@fopen:
- mov cx,0
- mov dx,offset fmt_file_name
- DOS CREATE_FILE
- CALLC disp_disk_err
- mov handle,ax
- ret
-
- @@fclose:
- mov bx,handle
- DOS CLOSE_FILE
- CALLC disp_disk_err
- ret
-
- @@fwrite:
-
- ; erst Kennung schreiben
-
- mov bx,offset tmp_word
- mov [bx],'WJ'
- mov dx,bx
- mov bx,handle
- mov cx,2
- DOS WRITE_TO_HANDLE
- CALLC disp_disk_ful
-
- ; cp/m Parameter schreiben
-
- mov dx,offset offset dpb0+ZBIOSDISPL
- mov bx,handle
- mov cx,size dpb
- push ds
- mov ax,z80seg_adr
- mov ds,ax
- DOS WRITE_TO_HANDLE
- pop ds
- CALLC disp_disk_err
-
- ; physikalische Parameter schreiben
-
- mov dx,offset cpm_drive
- mov bx,handle
- mov cx,autologin_flag-cpm_drive
- DOS WRITE_TO_HANDLE
- CALLC disp_disk_err
-
- ret
- save_disk_pars endp
-
- about_author proc
- PUSHR <bx,cx,dx,di,si,bp,ds,es>
- sub sp,HIGH_WinSave
- mov bx,sp
- mov cx,HIGH_WinSave
- push cx ; high(WinSave)
- push ss ; seg(WinSave)
- push bx ; offs(WinSave)
- mov ax,DATA
- mov ds,ax
- call EmuMenu_About
- add sp,HIGH_WinSave
- POPR <es,ds,bp,si,di,dx,cx,bx>
- ret
- about_author endp
-
- clearz80 proc ; loesche z80mem
- ;
- ; input: ax=seg z80 segment
- ; alle register ok
- ;
- push es
- PUSHR <ax,cx,di>
- mov es,ax
- mov cx,8000h ; 32k words
- mov di,0
- mov ax,0
- rep stosw ; es:di := 0000h
- POPR <di,cx,ax>
- pop es
- ret
- clearz80 endp
-
- dos_exec proc
- mov al,DOS_SCR_PAGE
- call sel_scr_page
- mov bx,STDOUT
- mov cx,exit_str_end-exit_str
- mov dx,offset exit_str
- DOS WRITE_TO_HANDLE
- PUSHR <bx,cx,dx,di,si,bp,es>
- mov sp_save,sp
- mov ss_save,ss
- mov bx,seg exec_par_block
- mov es,bx
- mov bx,offset exec_par_block
- mov dx,offset exec_fname
- mov ax,seg exec_fname
- mov ds,ax
- mov al,EMU_SCR_PAGE
- DOS EXEC ; ax:=error code
- mov bx,emudata_seg
- mov ds,bx
- cli
- mov ss,ss_save
- mov sp,sp_save
- sti
- POPR <es,bp,si,di,dx,cx,bx>
- cmp ax,2
- jnz short @@cc_found
- mov bx,STDERR
- mov cx,no_cc_str_end-no_cc_str
- mov dx,offset no_cc_str
- DOS WRITE_TO_HANDLE
- @@press_esc:
- call conin
- cmp al,ESC_KEY
- jnz short @@press_esc
- @@cc_found:
- mov al,0
- call sel_scr_page
- ret
- dos_exec endp
-
-
- dos_shell proc
- LOCAL handle:WORD,mem_adr:WORD = AUTO_SIZE
- PUSHR <ax,bx,cx,dx,si,di>
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
-
- call ins_dos_disk
- cmp ax,MESG_ESC
- jz short @@exit ; ESC
-
- call @@fcreate
- jc short @@exit
- call @@fwrite
- call @@fclose
- call @@set_free
- call dos_exec
- call @@get_mem
- call @@fopen
- call @@fread
- call @@fclose
- mov dx,offset temp_fname
- DOS DELETE_FILE
- CALLC disp_disk_err
- call ins_cpm_disk
- @@exit:
- mov sp,bp
- pop bp
- POPR <di,si,dx,cx,bx,ax>
- ret
-
- @@set_free:
- push es
- mov es,psp_adr
- mov bx,prog_len
- sub bx,1000h
- DOS MODIFY_MEMORY
- mov bx,mem_end
- sub bx,1000h
- mov ovl_base,bx
- pop es
- ret
-
- @@get_mem:
- push es
- mov es,psp_adr
- mov bx,prog_len
- DOS MODIFY_MEMORY
- pop es
- ret
-
- @@fcreate:
- mov cx,2 ; Hidden
- mov dx,offset temp_fname
- DOS CREATE_FILE
- CALLC disp_disk_err ; Abbruch nach Error in toplevel
- mov handle,ax
- ret
-
- @@fopen:
- mov al,0
- mov dx,offset temp_fname
- DOS OPEN_FILE
- CALLC disp_disk_err
- mov handle,ax
- ret
-
- @@fclose:
- mov bx,handle
- DOS CLOSE_FILE
- CALLC disp_disk_err
- ret
-
- @@fwrite:
- push ds
- mov bx,handle
- mov cx,0ffffh
- mov ds,ovl_base
- mov dx,0
- DOS WRITE_TO_HANDLE
- CALLC disp_disk_ful
- pop ds
- ret
- ; end fwrite
- @@fread:
- push ds
- mov bx,handle
- mov cx,0ffffh
- mov ds,ovl_base
- mov dx,0
- DOS READ_FROM_HANDLE
- CALLC disp_disk_err
- pop ds
- ret
- ; end fread
- dos_shell endp
-
-
- init_ramdisc proc
- push es
- PUSHR <ax,cx>
- mov ax,ramdisklen ; in paragraphen
- LOG2(64) ; nach cl (1024/16)
- shr ax,cl ; ax:=ramdisk len in KB
- and ax,0fff0h or 1100b ; um Vielfache von 4K zu bekommen
-
- push ax
- LOG2(4)
- shr ax,cl ; ax/=4
- mov lasttrack_rd,al ; Tracks zu 4 K
- pop ax
- ; dsm=ramdisklen in K/2 -1 , da bls=2k
- shr ax,1 ; geht klar, da sowieso vielfaches von 4
- dec ax
- cmp ax,255
- jna short @@nobig
- mov ax,255 ; mehr wie 510k geht im PC sowieso kaum
- @@nobig:
- mov dpb1.dsm,ax ; blockzahl
- inc ax ; da KB=(dsm+1)*2
- shl ax,1
- mov ramdisklen,ax ; KBzahl
- mov dpb1.bsh,4
- mov dpb1.blm,15
- mov dpb1.exm,1 ; blocksize=2048
- mov dpb1.drm,127 ; dir entries
- mov dpb1.al0,11000000b
-
- ; loesche ramdisc
- mov ax,rdseg_adr
- mov es,ax
- mov ax,ramdisklen
- @@clrloop:
- cmp ax,64 ; k
- jb short @@less64
- push ax
- mov cx,8000h ; do 32k words
- mov di,0
- mov ax,0e5e5h
- rep stosw ; es:di := E5E5
- mov ax,es
- add ax,1000h
- mov es,ax
- pop ax
- sub ax,64
- jmp @@clrloop
- @@less64:
- LOG2(512)
- shl ax,cl ; ax*=1024/2 (word)
- mov cx,ax
- mov di,0
- mov ax,0e5e5h
- rep stosw ; es:di := E5E5
- POPR <cx,ax>
- pop es
- call load_ramdisc
- ret
- init_ramdisc endp
-
- ; speichere Ramdisk auf Platte
- ;
- ; der LOCAL Befehl legt lokale Auto-Vars auf dem Stack an mit
- ; Laenge AUTO_SIZE
- ;
- save_ramdisc proc
- LOCAL handle:WORD = AUTO_SIZE
-
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
- call ins_dos_disk
- cmp ax,MESG_ESC
- jz short @@exit
- call @@fopen
- jc short @@exit
- call @@fwrite
- call @@fclose
- call ins_cpm_disk
- @@exit:
- mov sp,bp
- pop bp
- ret
-
-
- @@fopen:
- mov cx,0
- mov dx,offset ramdisc_fname
- DOS CREATE_FILE
- CALLC disp_disk_err
- mov handle,ax
- ret
-
- @@fclose:
- mov bx,handle
- DOS CLOSE_FILE
- CALLC disp_disk_err
- ret
-
- @@fwrite:
- ; erst mal Ramdiskgroesse schreiben, beim Laden muss sie stimmen
-
- mov bx,offset secbuf
- mov ax,ramdisklen
- mov [bx],ax
- mov dx,bx
- mov bx,handle
- mov cx,2
- DOS WRITE_TO_HANDLE
- CALLC disp_disk_ful
-
- mov bx,rdseg_adr
- mov ax,ramdisklen
- @@wrtloop:
- cmp ax,0 ; fertig ?
- ; 0 oder negativ = Abbruch
- jle short @@wrtexit
- push ax
- cmp ax,32 ; kilobyte
- mov cx,8000h ; 32k
- ja short @@more32
- LOG2(1024) ; nach cl
- shl ax,cl ; ax*=1024
- mov cx,ax ; cx = Laenge in Byte
- @@more32:
- push bx
- push ds
- push bx
- pop ds
- mov bx,handle ; klappt, da ueber SS:BP
- mov dx,0 ; offset
- DOS WRITE_TO_HANDLE
- CALLC disp_disk_ful
- pop ds
- pop bx
- pop ax
- add bx,800h ; segment um 32k weitersetzen
- sub ax,32 ; restlaenge -=32
- jmp @@wrtloop
- @@wrtexit:
- ret
- ; end fwrite
- save_ramdisc endp
-
-
- ; hole Ramdisk von Platte
- ;
- ; der LOCAL Befehl legt lokale Auto-Vars auf dem Stack an mit
- ; Laenge AUTO_SIZE
- ;
- load_ramdisc proc
- LOCAL handle:WORD = AUTO_SIZE
-
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
- call @@fopen
- jc short @@exit ; nicht da
-
- call @@fread
- call @@fclose
- @@exit:
- mov sp,bp
- pop bp
- ret
-
-
- @@fopen:
- mov al,0
- mov dx,offset ramdisc_fname
- DOS OPEN_FILE
- mov handle,ax
- ret
-
- @@fclose:
- mov bx,handle
- DOS CLOSE_FILE
- CALLC disp_disk_err
- ret
-
- @@fread:
- mov dx,offset secbuf
- mov bx,handle
- mov cx,2
- DOS READ_FROM_HANDLE
- CALLC disp_disk_err
- mov bx,dx
- mov bx,[bx]
- cmp bx,ramdisklen
- ja short @@rdexit ; ueberhaupt zu gross
-
- mov ax,bx ; Laenge Ramdisk auf Platte
- mov bx,rdseg_adr
- @@rdloop:
- cmp ax,0 ; fertig ?
- jle short @@rdexit
- push ax
- cmp ax,32
- mov cx,8000h ; 32k
- ja short @@more32
- LOG2(1024) ; nach cl
- shl ax,cl ; ax*=1024
- mov cx,ax ; cx = Laenge in Byte
- @@more32:
- push bx
- push ds
- push bx
- pop ds
- mov bx,handle ; klappt, da ueber SS:BP
- mov dx,0 ; offset
- DOS READ_FROM_HANDLE
- CALLC disp_disk_err
- pop ds
- pop bx
- pop ax
- add bx,800h ; segment um 32k weitersetzen
- sub ax,32 ; restlaenge -=32
- jmp short @@rdloop
- @@rdexit:
- ret
- ; end fread
- load_ramdisc endp
-
- bios88 proc
- ;
- ; bios88 ist handler fuer alle bios calls
- ; In: al=bios nummer (warm boot = 1)
- ; cx,bx,dx wie bei cp/m bios calls
- ; Out: di,ah zerstoert
- ; si kann veraendert sein, falls bios change_si_flag
- ; hat nach wboot
- ;
- ; waehrend aller bios routinen zeigt ds auf emudata_seg
- ; es z80cpu_seg
- mov di,emudata_seg
- mov ds,di
-
- mov z80_pc,si
-
- cmp breakflag,TRUE
-
- CALLZ prg_exit
-
- PUSHR <bp,dx>
- ; cx nicht pushen, da cl:=drive # bei wboot
-
- xor ah,ah ; bios # = index
- sal ax,1
- mov di,ax
- call cs:biostab[di]
- mov si,z80_pc
-
- POPR <dx,bp>
-
- cmp breakflag,TRUE
-
- CALLZ prg_exit
-
- mov di,z80seg_adr
- mov ds,di
- mov es,di
- jmp bios88ret
-
- bios88 endp
-
-
- biostab label word
- dw boot ; cold start
- dw wboot ; warm start
- dw constat ; console status
- dw conin ; console character in
- dw conout ; console character out
- dw list ; list character out
- dw punch ; punch character out
- dw reader ; reader character out
- dw home ; move head to home position
- dw seldsk ; select disk
- dw settrk ; set track number
- dw setsec ; set sector number
- dw setdma ; set dma address
- dw read ; read disk
- dw write ; write disk
- dw listst ; return list status
- dw sectran ; sector translate
- rept 25-16-1
- dw wboot
- endm
- dw cpm3_move ; move
- dw cpm_get_time ; time
-
-
- ;
- ;
- ; individuelle UPs um jede Funktion auszufuehren
- ;
- boot proc
-
- ;simplest case is to just perform parameter initialization
- mov in_boot_flag,TRUE
- mov bx,offset on_sign_string
- call puts
-
- call instzbios
-
- cmp fmt_file_flg,TRUE
- CALLZ load_disk_pars
-
-
- call read_sys ; lade bdos aus file CPMSYS.CPM
- pushf
- call ins_cpm_disk
- popf
- jnc short @@goodload ; laden aus File klappte
- call get_sys ; BDOS mit BIOS fkt von Diskette laden
- @@goodload:
-
- ; Copyright von dr ausgeben
-
- mov cl,27
- call conout
- mov cl,'k' ; pop cursor pos
- call conout
- mov cl,27
- call conout
- mov cl,'J' ; Rest vom Fenster loeschen
- call conout
-
- mov bx,offset cpm_bdos_buf+18h
- call puts
-
- mov bx,offset cr_lf_txt
- call puts
- ;
- ; berechne adresse von ccp,bdos und bios
- ; dabei wird die JMP CCPENTRY Anweisung bei CCP+0 benutzt
- ;
- mov di,offset cpm_bdos_buf+807h
- mov al,[di]
- cmp al,11h
- jnz short @@no_standard
- mov di,offset cpm_bdos_buf+1
- mov ax,[di]
- sub ax,35ch ; ax:=start ccp
- ; CP/M CCP? dann al jetzt 0
- or al,al
- jz short @@is_standard
- ; sonst defaultmaessig e400 annehmen
- @@no_standard:
- mov ax,0e400h
- @@is_standard:
- mov ccp_adr,ax
- add ax,806h
- mov bdos_adr,ax
- add ax,(BDOSLEN-806h)
- mov bios_adr,ax
-
- call reset_conout
-
- mov di,IOBYTE
- mov byte ptr es:[di],0 ; clear IOBYTE
- mov di,CDISK
- mov byte ptr es:[di],0 ; select disk zero
- call reset_punch_buf
- call reset_reader_buf
- mov in_boot_flag,FALSE
- jmp wboot
- boot endp
-
- ;
- ; setze Punch buffer auf leer
- ;
-
- reset_punch_buf proc
- mov punch_buf_entries,0
- mov punch_buf_ptr,offset punch_buf
- ret
- reset_punch_buf endp
-
-
- ;
- ; setze Reader buffer auf nicht belegt
- ;
-
- reset_reader_buf proc
- mov reader_empty_flag,FALSE ; noch nicht lesen versucht
- mov reader_buf_entries,0
- mov reader_buf_ptr,offset reader_buf
- mov reader_file_pointer,0
- mov reader_file_pointer+2,0
- ret
- reset_reader_buf endp
-
- ;
- ; Stringausgabe
- ; In: bx zeigt auf String, Stringende = \0
- ;
- puts proc
- @@loop:
- mov cl,[bx]
- or cl,cl
- jz short @@exit
- inc bx
- push bx
- call conout
- pop bx
- jmp short @@loop
- @@exit:ret
- puts endp
-
- instzbios proc
- ;
- ; installiere z80 bios
- ; und discparameter
- ;
-
- PUSHR <si,di,cx>
-
- mov si,offset zbiosbeg
- mov di,ZBIOS
- mov cx,zbiosend-zbiosbeg
- cld
- rep movsb ; es:di := ds:si
-
- POPR <cx,di,si>
- ret
- instzbios endp
-
-
- instjp proc
- ;
- ; installiere z80 bios Sprungleiste bei bios_adr
- ;
- ; register o.k.
- ;
- ; darf nicht aufgerufen werden, bevor bios_adr
- ; von boot aufgesetzt wurde
- ;
-
- PUSHR <si,di,cx>
-
- mov si,offset wboote-3
- mov di,bios_adr
- mov cx,zvecend-wboote+3
- cld
- rep movsb ; es:di := ds:si
-
- POPR <cx,di,si>
-
- ret
- instjp endp
-
-
- read_sys proc
- ;
- ; lade cp/m bdos aus file CPMSYS.CPM in buffer
- ; um es durch warm boot zu benutzen
- ;
- ; das File entspricht dem durch MOVCPM erzeugten Speicherauszug
- ; dabei beginnt das eingentlich System erst ab Offset 880h
-
- MOVCPM_OFFS = 880H
-
- PUSHR <ax,bx,cx,dx,si>
- mov al,0
- mov dx,offset cpmsys_fileName
- DOS OPEN_FILE
- jc short @@exit
- mov si,ax
- ; setze Filepointer auf CCP Anfang im File
- mov cx,0 ; cx:dx: offset
- mov dx,MOVCPM_OFFS
- mov al,0 ; offset from start
- mov bx,si
- DOS MOVE_FILE_POINTER
- ;
- ; emudata_seg:buffer := CPMSYS.CPM
- ;
- mov cx,BDOSLEN ; Laenge
- mov bx,si ; handle
- mov dx,offset cpm_bdos_buf
- DOS READ_FROM_HANDLE
- jc short @@exit
- mov bx,si
- DOS CLOSE_FILE
- CALLC disp_disk_err
- @@exit:
- POPR <si,dx,cx,bx,ax>
- ret
- read_sys endp
-
-
- ; System von SystemSpuren laden
-
- ; while sector in systemsectoren do
- ; lies sector
- ; if an Adresse String COPYRIGHT 1979 ..
- ; sys=naechste SYS_SECS sektoren
- ; lies sys
- ; exit
- ; mache Checksumme ueber sys
- ; if falsch
- ; "no sys"
- ; endif
- ; endif
- ; endwhile
- ; "no sys"
-
- get_sys proc
- LOCAL sys_recs,last_sys_rec:WORD = AUTO_SIZE
-
- push bp
- mov bp,sp
- sub sp,AUTO_SIZE
- @@get_sys_loop:
- call login_disc
- mov ah,0
- mov al,dpb0.off-dpb0.spt ; off
- call get_dpb_entrie ; nach bx
- push bx
- mov ah,0
- mov al,dpb0.spt-dpb0.spt ; spt
- call get_dpb_entrie ; nach bx
- pop ax
- mul bx ; ax:=system records
- mov sys_recs,ax
- mov cx,0
- ; im Systembereich nach String "COPYRIGHT (C) 1979 " suchen
- @@srch_loop:
- cmp cx,sys_recs
- jnc short @@read_err ; schon ausserhalb sys
- push cx ; sector
- push cx
- mov cx,DEFAULT_DMA
- call setdma
- pop cx
- mov ah,cpm_drive
- call set_abs_sect
- call read
- pop cx
- cmp al,1
- jz short @@read_err
- call @@compare
- jz short @@found
- inc cx
- jnz @@srch_loop
- @@found:
- mov bx,DEFAULT_DMA
- push cx
- add cx,SYS_SECS
- mov last_sys_rec,cx
- pop cx
- @@loop:
- push cx ; sector
- push bx ; dma
- push cx
- mov cx,bx
- call setdma
- pop cx
- mov ah,cpm_drive
- call set_abs_sect
- call read
- pop bx
- pop cx
- cmp al,1
- jz short @@read_err
- add bx,RECORD_LEN
- inc cx
- cmp cx,last_sys_rec
- jnz @@loop
-
- jmp short @@good_load
-
- @@read_err:
- mov bx,offset no_sys
- call puts
- call conin
- jmp @@get_sys_loop
-
- @@good_load:
-
- ; System aus CP/M Segment nach Datensegment uebertragen
-
- PUSHR <si,di,bx,cx,ax>
- push ds
- push es
- mov di,offset cpm_bdos_buf
- mov si,DEFAULT_DMA
- mov ax,z80seg_adr
- mov ds,ax
- mov ax,emudata_seg
- mov es,ax
- mov cx,BDOSLEN/2
- cld
- rep movsw ; es:di := ds:si
- pop es
- pop ds
- POPR <ax,cx,bx,di,si>
- mov sp,bp
- pop bp
- ret
- @@compare:
- PUSHR <si,di,cx,ax>
- mov si,offset bdos_str
- mov di,DEFAULT_DMA+10H
- mov cx,bdos_str_end-bdos_str
- @@cp_loop:
- mov al,[es:di]
- mov ah,[si]
- inc si
- inc di
- cmp al,ah
- jnz short @@cp_exit
- loop @@cp_loop
- @@cp_exit:
- POPR <ax,cx,di,si>
- ret
-
- get_sys endp
- ;
-
- set_abs_sect proc ; absoluten Sektor in cx, drive ah setzen
- push cx
- mov al,0 ; spt
- call get_dpb_entrie ; nach bx
- pop ax
- mov dx,0
- div bx
- push dx
- mov cx,ax
- call settrk
- pop cx
- call setsec
- ret
- set_abs_sect endp
-
-
- wboot proc
-
- push di
- call copy_bdos
- call instjp ; bios Sprungleiste installieren
- ;
- ; 0000h := JP WBOOT
- ; 0005h := JP BDOS
- ;
- mov di,0 ; start cp/m memory
- mov byte ptr es:[di+0],0c3h
- mov bx,bios_adr
- add bx,3 ; bx:=warmboot
- mov es:[di+1],bx ; set address field for jmp at 0
- ;
- mov byte ptr es:[di+5],0c3h
- mov bx,bdos_adr ; bdos entry point
- mov es:[di+6],bx ; address field of jump at 5 to bdos
- ;
- mov cx,DEFAULT_DMA ; default dma address is 80h
- call setdma
-
- call login_disc ; physikalisches Login
- ;
- mov ax,ccp_adr
- mov z80_pc,ax ; jp ccp
-
- mov di,CDISK
- mov cl,es:[di] ; get current disk number & send to ccp
- pop di
- ret ;go to cp/m for further processing
-
- copy_bdos:
- PUSHR <si,di,cx>
-
- mov di,ccp_adr
- mov si,offset cpm_bdos_buf
- mov cx,BDOSLEN/2
- rep movsw ; es:di := ds:si
-
- POPR <cx,di,si>
- ret
-
- wboot endp
- ;
-
- ;
- ;
- constat proc
- ;
- ; console status, return 0ffh if character ready, 00h,Z_flag if not
- ;
- ; Out: al=keyboard status
- ;
- push bx
- mov ah,1 ; keybord status
- int 16h
- mov al,0ffh
- jnz short @@exit
- mov al,0
- @@exit:
- pop bx
- ret
- constat endp
-
- ; conin im Modul CONOUT
-
- ;
- ; test auf ^C, wenn ja, warm boot
- ;
- tst_ctrl_c proc
- push ax
- call constat
- jz short @@exit
- call conin
- cmp al,3 ; ^C
- clc ; cy = no error
- jnz short @@exit
- mov bx,offset control_c_txt
- call puts
- stc
- @@exit:
- pop ax
- ret
- tst_ctrl_c endp
- ;
- ; list character in register c auf Drucker
- ;
- list proc
- call listst
- jnz short @@ok
- call tst_ctrl_c
- jnc short list
- mov z80_pc,0 ; Z80 macht ab Adresse 0 weiter
- ret
- @@ok:
- mov al,cl ; char nach register a
- xor dx,dx ; lpt 0
- xor ah,ah ; list character
- push bp
- int 17h
- pop bp
- cmp ah,10h ; ok
- jnz short list
- ret
- list endp
- ;
- ; return list status (0,Z_flag if not ready, 1 if ready)
- ;
- listst proc
- push dx
- xor dx,dx ; lpt 0
- mov ah,2 ; test printer
- int 17h
- mov al,1
- cmp ah,90h ; on line und not busy
- jz short @@lret
- dec al
- @@lret:
- or al,al
- pop dx
- ret
- listst endp
-
- date_dos_2_cpm proc ; out: AX=tage seit 1.Jan. 1978
- push bx
- push cx
- push dx
- DOS GET_DATE
- push dx
- mov bx,1978
- inc cx ; ein Jahr zuviel, für Test ob akt. Schaltjahr
- MOV AX,0
- @@add_loop:
- cmp bx,cx ; aktuelles Jahr erreicht ?
- jz short @@years_done
-
- mov dx,bx
- and dx,11b ; 0 => durch 4 teilbar
- sub dx,1 ; 0 => cy
- mov dx,365
- adc dx,0 ; wird unten zum abziehen gebraucht
- add ax,dx ; 0 => 366
-
- inc bx
- jmp @@add_loop
- @@years_done:
- sub ax,dx ; da ein Jahr oben zuviel, 365 oder 366 wieder weg
- pop dx ; mon/tag
- mov ch,0
- mov cl,dl
- add ax,cx ; tag
- mov cl,dh ; monat
- dec cl ; da aktueller Monat schon dran
- jz short @@is_jan
- mov bx,offset month_tab
- @@add_months:
- mov dl,[bx] ; verschieden lange monate
- inc bx
- mov dh,0
- add ax,dx
- loop @@add_months
- @@is_jan:
- pop dx
- pop cx
- pop bx
- ret
- date_dos_2_cpm endp
-
- cpm3_move proc ; move wie bei cpm plus bios
- push ds
- push es
- pop ds
- mov si,bx
- mov di,dx
- add bx,cx ; hl=blockende
- cmp bx,dx ; größer Ziel ?
- jnb short @@topdown
- cld
- rep movsb
- jmp short @@exit
- @@topdown:
- add si,cx
- add di,cx
- mov bx,si
- mov dx,di
- dec si
- dec di
- std
- rep movsb
- pop ds
- ret
- @@exit:
- mov bx,si
- mov dx,di
- pop ds
- ret
- cpm3_move endp
-
-
- cpm_get_time proc ; dos zeit nach cpm plus zeit
- PUSHR <AX,CX,DX>
- cmp cl,0
- jnz short @@exit ; set time ignorieren
- call date_dos_2_cpm
- push ds
- push es
- pop ds
- mov @date+ZBIOSDISPL,ax
- DOS GET_TIME
- mov dl,10
- mov al,cl
- mov ah,0 ; sonst divide overflow
- div dl
- mov cl,4
- shl al,cl
- or al,ah
- mov @min+ZBIOSDISPL,al
- mov al,ch
- mov ah,0
- div dl
- shl al,cl
- or al,ah
- mov @hour+ZBIOSDISPL,al
- mov al,dh
- mov ah,0
- div dl
- shl al,cl
- or al,ah
- mov @sec+ZBIOSDISPL,al
- pop ds
- mov bx,(offset @date)+ZBIOSDISPL
- @@exit:
- POPR <DX,CX,AX>
- ret
- cpm_get_time endp
-
- del_punch_file proc
- mov dx,offset punch_fileName
- DOS DELETE_FILE
- ret
- del_punch_file endp
-
- ;
- ; punch character in register c
- ; wird durch Output in File auf MsDos Disk ersetzt
- ; Buffer wird auf File geschrieben, falls er voll ist
- ; und auch am Ende des Emulator-
- ; laufs
- ;
- punch proc
- ;
- ; fill buffer until full or eof
- ; open file
- ; if not exist file
- ; create file
- ; endif
- ; go to end of file
- ; append character
- ; close file
- ; empty buffer
- ;
- ; falls punch von bios88 aufgerufen wurde, ist al<>0
- ; nach Aufruf von wrt_out_punch aber al=0
-
- PUSHR <ax,bx,cx,dx,si>
- cmp al,0
- jz short @@write_out
- mov bx,punch_buf_ptr
- mov [bx],cl ; buf:=character
- inc bx
- mov punch_buf_ptr,bx
- inc punch_buf_entries
- cmp punch_buf_entries,PUNCH_BUF_SIZE
- jnz short @@exit
- @@write_out:
- call ins_dos_disk
- cmp ax,MESG_ESC
- jz short @@exit
- mov al,1
- mov dx,offset punch_fileName
- DOS OPEN_FILE
- jnc short @@file_found
- mov cl,0 ; write only
- DOS CREATE_FILE
- CALLC disp_disk_err
- @@file_found:
-
- mov bx,ax ; handle
- mov cx,0
- mov dx,0
- mov al,2 ; offset from end
- DOS MOVE_FILE_POINTER
-
- mov cx,punch_buf_entries
- mov dx,offset punch_buf
- DOS WRITE_TO_HANDLE
- CALLC disp_disk_ful
-
- DOS CLOSE_FILE
-
- call reset_punch_buf
- call ins_cpm_disk
- @@exit:
- POPR <si,dx,cx,bx,ax>
- ret
- punch endp
-
- wrt_out_punch proc
- cmp punch_buf_entries,0
- jz short @@exit
- xor al,al
- call punch
- @@exit:
- ret
- wrt_out_punch endp
- ;
- ;
- reader proc ;read character into register a from reader device
-
- ; if buffer empty
- ; open file
- ; if file not present
- ; exit
- ; else
- ; fill buffer
- ; endif
- ; endif
- ; read char
-
- cmp reader_empty_flag,TRUE
- jz short @@empty
- cmp reader_buf_entries,0
- jnz short @@do_read
-
- ; Buffer fuellen
- mov al,0
- mov dx,offset reader_fileName
- DOS OPEN_FILE
- jc short @@empty
- push ax
- mov bx,ax
- mov dx,reader_file_pointer
- mov cx,reader_file_pointer+2
- PUSHR <dx,cx>
- add dx,READER_BUF_SIZE
- adc cx,0
- mov reader_file_pointer,dx
- mov reader_file_pointer+2,cx
- POPR <cx,dx>
- mov al,0 ; offset from start
- DOS MOVE_FILE_POINTER
- pop bx ; handle
- mov cx,READER_BUF_SIZE
- mov dx,offset reader_buf
- DOS READ_FROM_HANDLE
- push ax
- DOS CLOSE_FILE
- pop ax
- cmp ax,0
- jz short @@empty
-
- ; buffer erfolgreich gefuellt
- mov reader_empty_flag,FALSE
- mov reader_buf_entries,ax
- mov reader_buf_ptr,offset reader_buf
-
- @@do_read:
- mov bx,reader_buf_ptr
- mov al,[bx]
- inc bx
- mov reader_buf_ptr,bx
- dec reader_buf_entries
- jmp short @@exit
- @@empty:
- mov reader_empty_flag,TRUE
- mov al,CPM_EOF
- mov bx,0ffffh ; hl=FFFF == Dos File Ende
- ret
- @@exit:
- mov bx,0 ; a=hl=gelesenes byte
- mov bl,al
- ret
-
- reader endp
-
-
- ; In: ah=drive
- ; al=offset im dpb
- ; Out: bx=word dpb[al]
-
- get_dpb_entrie proc
- push si
- mov bl,ah
- call get_dph_adr ; bx:=dph
- xor ah,ah
- mov si,ax
- mov bx,[es:bx+10] ; bx:=dpb
- mov bx,[es:bx+si] ; bx:=dpb[ax]
- pop si
- ret
- get_dpb_entrie endp
-
- ;
- ; select disk in register c
- ;
- seldsk proc
- cmp cl,NDISKS-1
- mov bx,0000h ; 0 = Drive nicht existent
- ja short @@exit
- mov diskno,cl
- mov bl,cl
- call get_dph_adr
- @@exit:
- ret
- seldsk endp
-
- ; In: bl:=Drive #
- ; Out: bx:= disk parameter header address
- ;
- get_dph_adr proc
- mov bh,0 ; high order zero
- push cx
- LOG2(16) ; nach cl
- sal bx,cl ; bx*=16 (size of each header)
- pop cx
- add bx,offset dph_base+ZBIOSDISPL
- ret ;hl=.dph_base(diskno*16)
- get_dph_adr endp
-
- ;
- ; move to the track 00 position of current drive
- ; translate this call into a settrk call with parameter 00
- ;
- home proc
- mov cx,0 ; select track 0
- call settrk
- mov home_flag,TRUE ; zur Auswertung durch read_track
- ret
- home endp
-
- ;
- ; set track given by register bc
- ;
- settrk proc
- mov word ptr track,cx
- ret
- settrk endp
- ;
- ; set sector given by register bc
- ;
- setsec proc
- mov word ptr sector,cx
- ret
- setsec endp
-
- ;
- ;translate the sector given by bc using the
- ;translate table given by de
- ;
- sectran proc
-
- mov bx,cx
- or dx,dx ; table ptr == 0 ?
- jz short @@exit
- add cx,cx ; index *= 2
- mov bx,dx ; hl=trans
- add bx,cx
- mov bx,[es:bx] ;hl=trans[sector]
- @@exit:
- ret ;with value in hl
- sectran endp
- ;
- ; set dma address given by registers b und c
- ;
- setdma proc
- mov dmaad,cx
- ret
- setdma endp
-
-
- calcadr proc
- ;
- ; ax:bx := record adresse in Ramdisk
- ; illegal sec: cy
- ;
- ; 1. 64k track 0..15
- ; 2. 64k track 16..31
- ; ..
- mov al,track
- cmp al,lasttrack_rd
- ja short @@badrec
-
- mov al,sector
- cmp al,LAST_SEC1
- ja short @@badrec
-
- ; phys recordnum = track * spt + sector
-
- PUSHR <cx,dx>
- mov ah,RMD
- mov al,0 ; spt
- call get_dpb_entrie
- mov cx,bx ; cx:=spt B:
- mov ax,word ptr track
- mul cx
- add ax,word ptr sector ; ax:=phys record num
- mov cx,512 ; 64K = 512 records @ 128 Bytes
- mov dx,0
- div cx ; ax:= # of 64K, dx:=recordnum
- mov cx,1000h
- push dx
- mul cx
- pop dx
- mov bx,rdseg_adr
- add bx,ax
- mov ax,dx
- LOG2(RECORD_LEN)
- shl ax,cl
- xchg bx,ax
- POPR <dx,cx>
- clc
- @@exit:
- ret
- @@badrec:
- stc
- jmp short @@exit
- calcadr endp
-
- ;
- read proc
- ;
- ; lies einen record von 128 bytes
- ;
- cmp diskno,RMD
- jnz short @@rfdisc
- call calcadr ; ax:bx := record addresse
- jc short @@badsec
- call rdrec
- @@exit:xor al,al ; o.k.
- ret
- @@badsec:
- mov al,1
- ret
-
- @@rfdisc:
- call is_valid_rec ; ax=rec/sec
- jc short @@badsec
-
- call read_track
- jc short @@badsec
- ;
- ; record num ist in ah
- ; ax:bx := adresse Track Buffer
- ;
- mov al,READ_OP
- call get_adr_in_buf ; nach bx
- mov ax,ds ; ax := seg track buffer
- call rdrec
- jmp short @@exit
- read endp
-
- ; berechne Sektoradresse im Buffer
- ; a=sector*128+buf
- ; input: al=READ_OP / WRITE_OP
-
- get_adr_in_buf proc
- PUSHR <AX,CX>
- call is_dir_track
- mov bx,offset dirtrbuf
- jz short @@calc
- mov bx,offset secbuf
- cmp al,READ_OP
- jz short @@calc
- mov bx,offset wrtbuf
- @@calc:
- xor ax,ax
- mov al,sector
- LOG2(RECORD_LEN) ; nach cl
- shl ax,cl ; ax *= 128
- add bx,ax
- POPR <CX,AX>
- RET
- get_adr_in_buf endp
-
- is_dir_track proc
- push ax
- mov al,track
- cmp al,dirtrack
- pop ax
- ret
- is_dir_track endp
-
- ;
- ;
- ;
- is_valid_rec proc
- ; Out: cy sector illegal
- ;
- ; test auf gueltigen track/sector auf DISC
- ;
- COMMENT *
- mov al,track
- cmp al,LAST_TRCK0
- stc
- ja short @@exit
- mov al,sector
- cmp al,LAST_SEC0
- stc
- ja short @@exit
- ; ok, clear cy
- *
- clc
- @@exit:
- ret
- is_valid_rec endp
-
- ;
- ; lies ganzen Track, falls noch nicht im Speicher
- ;
- read_track proc
- ;
- ; Error: cy=1
- ;
- PUSHR <ax,bx,cx,dx>
-
- ; der DirTrack wird nur gelesen nach HOME
-
- mov al,track
- cmp al,dirtrack
- jnz short @@nodir
- cmp home_flag,TRUE
- mov home_flag,FALSE
- mov bx,offset dirtrbuf
- jz short @@read_dir_track
- clc
- jmp short @@exit
- @@nodir:
- cmp al,last_track_read
- jz short @@exit
-
- mov bx,offset secbuf
- mov last_track_read,al
- @@read_dir_track:
- mov r_track,al
-
- call read_phys_track
- ; ab jetzt CY nicht mehr veraendern !
-
- @@exit:
- POPR <dx,cx,bx,ax>
- ret
- read_track endp
-
- ;
- ; lies ganzen Track, in den geschrieben werden soll, ein,
- ; falls noch nicht im Speicher
- ;
- read_w_track proc
- ;
- ; Error: cy=1
- ;
- PUSHR <ax,bx,cx,dx>
- ; der DirTrack ist sowieso im Speicher und braucht
- ; nicht gelesen werden
- mov al,track
- cmp al,dirtrack
- jz short @@exit
-
- cmp al,last_track_written
- jz short @@exit
-
- ; falls noetig alten Track im WriteBuffer erst
- ; ausschreiben
- call write_out_old_track
-
- mov al,track
- mov bx,offset wrtbuf
- mov last_track_written,al
- mov r_track,al
- call read_phys_track
-
- ; ab jetzt CY nicht mehr veraendern !
-
- @@exit:
- POPR <dx,cx,bx,ax>
- ret
- read_w_track endp
-
- ; physikalische Sektorlaenge herstellen
- dos_phys_len proc
- PUSHR <es,ax,di>
- mov ax,0
- mov es,ax
- les di,[es:78h]
- mov al,ms_phys_sec_len
- mov es:[di+3],al
- POPR <di,ax,es>
- ret
- dos_phys_len endp
-
- ; physikalische Sektorlaenge herstellen
- cpm_phys_len proc
- PUSHR <es,ax,di>
- mov ax,0
- mov es,ax
- les di,[es:78h]
- mov al,cpm_phys_sec_len
- mov es:[di+3],al
- POPR <di,ax,es>
- ret
- cpm_phys_len endp
-
- normalize_pointer proc ; es:bx
- PUSHR <cx,ax>
- mov ch,bl
- and ch,0fh
- LOG2(16) ; NACH CL
- shr bx,cl ; bx:=16
- mov ax,es
- add ax,bx
- mov es,ax
- mov bx,0
- mov bl,ch
- POPR <ax,cx>
- ret
- normalize_pointer endp
-
- read_phys_track proc
- PUSHR <ax,bx,cx,dx>
-
- ; der naechste Test sollte eigentlich nicht noetig sein, aber
- ; mein 386 Ami Bios weigert sich sonst, den gleichen Track nochmal
- ; zu lesen; jedenfalls kann auch gleich ein Diskwechsel festgestellt
- ; werden
- call tst_disk_change
- jz short @@no_change
- mov last_track_read,0ffh
- @@no_change:
-
- mov cl,retry_count
- xor ch,ch
- @@tryread:
- call cpm_phys_len
- push es
- mov ax,emudata_seg
- mov es,ax ; ist sonst z80cpu_seg
- push cx
-
- mov dl,cpm_drive ; diskno
- mov dh,side
- mov ch,r_track
- call track_trans
- mov cl,first_phys_sec ; physical sector number
- mov al,phys_sec_pt ; lies ganzen Track auf einmal
- mov ah,2 ; read sector
- ; call normalize_pointer
- int 13h ; es:bx := track
- pop cx
- pop es
- call dos_phys_len
- jnc short @@exit
- cmp ah,9
- jz dma_bound
- ; Fehler, Disk Reset und nochmal versuchen
- mov ah,0
- mov dl,cpm_drive
- int 13h ; disk reset
- loop @@tryread
- stc ; Error, cy
- @@exit:
- POPR <dx,cx,bx,ax>
- ret
- read_phys_track endp
-
- ; Trackuebersetzung nur fuer CP/M 86 DS DD noetig
- ; muss vor phys. read/write Ops aufgerufen werden
- ;
- ; in: ch: zu uebersetzender Track
- ; dh: Disk Side
-
- track_trans proc
- cmp ch,phys_tracks
- jb short @@exit
- cmp cpm86dd_flag,TRUE
- jnz short @@nocpm86dd
- push ax
- mov al,ch
- mov ch,79
- sub ch,al
- pop ax
- inc dh ; Seite 1
- jmp short @@exit
- @@nocpm86dd:
- sub ch,40
- inc dh ; Seite 1
- @@exit:
- ret
- track_trans endp
-
- tst_disk_change proc
- cmp hd_drive_flag,FALSE
- jz short @@exit ; kein Diskwechsel => Z
- mov ah,16h
- mov dl,cpm_drive
- int 13h ; Test auf Wechsel
- cmp ah,0 ; kein Diskwechsel => Z
- @@exit:
- ret
- tst_disk_change endp
-
- ; falls noch nicht geschriebener Track im Speicher ist,
- ; der kein DirTrack ist, ausschreiben
-
- write_out_old_track proc
- cmp write_flag,TRUE
- jnz short @@exit
- mov al,last_track_written
- mov w_track,al
- mov outbuf_ptr,offset wrtbuf
- call write_phys_track
- mov write_flag,FALSE
- @@exit:
- ret
- write_out_old_track endp
-
- ;
- ; den Dir Track auf Disk schreiben
- ;
- write_out_dir proc
- call write_out_old_track ; falls noetig
- mov al,dirtrack
- mov w_track,al
- mov outbuf_ptr,offset dirtrbuf
- call write_phys_track
- ret
- write_out_dir endp
-
- write_phys_track proc
- PUSHR <ax,bx,cx,dx>
- mov cl,retry_count
- xor ch,ch
- @@trywrit:
- call cpm_phys_len
- push es
- mov ax,emudata_seg
- mov es,ax
- push cx
- mov dl,cpm_drive ; diskno
- mov dh,side
- mov ch,w_track
- call track_trans
- mov cl,first_phys_sec ; physical sector number
- mov bx,outbuf_ptr
- mov al,phys_sec_pt
- ; call normalize_pointer
- mov ah,3 ; read sector
- int 13h ; track := es:bx
- pop cx
- pop es
- call dos_phys_len
- jnc short @@exit
- cmp ah,9
- jz dma_bound
- mov ah,0
- mov dl,cpm_drive
- int 13h ; disk reset
- loop @@trywrit
- stc ; Error, cy
- @@exit:
- POPR <dx,cx,bx,ax>
- ret
- write_phys_track endp
-
- ;
- ; versuchen, richtiges physikalisches Format zu finden
- ; und disc parameter block herrichten
- ;
- ; falls autologin_flag = FALSE , kann das Zeitaufwendige login
- ; entfallen
-
- login_disc proc
- push bx
- call tst_hd_drive
- mov last_track_read,0ffh ; Track Buffer auf leer setzen
- ; damit bei read_track gelesen wird
- mov write_flag,FALSE ; sonst wird beim naechsten write
- ; erst alter Schrott ausgeschrieben
- cmp autologin_flag,TRUE
- jnz @@exit
- mov cpm_drive,PHYS_DRV
-
- mov cpm86dd_flag,FALSE
-
- mov retry_count,2 ; Leseversuche herabsetzen,
- ; damit bei falschem
- ; Format nicht zuviel Zeit verschwendet wird
-
- @@loop:
-
- cmp breakflag,TRUE
-
- CALLZ prg_exit
-
- ; erst mal mit dem zuletzt verwendeten Format versuchen
- ; aber nicht, wenn letztes CP/M 86 war, da sonst das
- ; aehnliche Format mit 9 Sektoren nicht erkannt wird
-
- cmp byte ptr phys_sec_pt,8
- jz short @@tst_cpm86
-
- mov al,pspt_last
- mov phys_sec_pt,al
- mov al,phys_tracks_last
- mov phys_tracks,al
- mov al,frstps_last
- mov first_phys_sec,al ; physical sector
- mov al,dirtr_last
- mov dirtrack,al
- inc al
- mov r_track,al
- mov bx,offset secbuf
- call read_phys_track
- mov bx,dpb_last
- jnc @@goodfmt
-
-
- ;
- ; CP/M 86 format ?
- ;
- ; Bedingungen: Seite 0 muss Sektoren 1-8 haben, aber nicht 1-9
- ; Seite 1 muss Sektoren 1-8 haben
-
- ; setze 9 Phys. Sektoren, bei cp/m 86 mit 8 Sektoren pro Track muss
- ; es einen Lesefehler geben
-
- @@tst_cpm86:
- mov phys_sec_pt,9
- mov phys_tracks,40
- mov first_phys_sec,1h
- mov r_track,1+1
- mov dirtrack,1
- mov bx,offset secbuf
- call read_phys_track
- jnc short @@nocpm86
-
- mov phys_sec_pt,8
- mov phys_tracks,40
- mov first_phys_sec,1h
- mov r_track,1+1
- mov dirtrack,1
- mov bx,offset secbuf
- call read_phys_track
- jc short @@nocpm86
-
-
- ; Teste noch Seite 2 mit SektorNummer > 39
-
- mov phys_sec_pt,8
- mov phys_tracks,40
- mov first_phys_sec,1h
-
- mov r_track,40
- mov dirtrack,1
- mov bx,offset secbuf
- call read_phys_track
- mov bx,offset dpb_cpm86DS
- mov cpm86dd_flag,TRUE
- jnc @@goodfmt
- mov cpm86dd_flag,FALSE
- mov bx,offset dpb_cpm86SS
- jmp @@goodfmt
-
- @@nocpm86:
-
- ;
- ; cpc system format ?
- ;
- mov phys_sec_pt,9
- mov phys_tracks,40
- mov first_phys_sec,41h
- mov r_track,2+1
- mov dirtrack,2
- mov bx,offset secbuf
- call read_phys_track
- mov bx,offset dpb_cpc
- jnc short @@goodfmt
- ;
- ; data format ?
- ;
- mov phys_sec_pt,9
- mov phys_tracks,40
- mov first_phys_sec,0c1h
- mov r_track,0+1
- mov dirtrack,0
- mov bx,offset secbuf
- call read_phys_track
- mov bx,offset dpb_dta
- jnc short @@goodfmt
-
- @@tsteigfrm:
- ;
- ; is it own format
- ;
- mov phys_sec_pt,9
- mov phys_tracks,40
- mov first_phys_sec,1
- mov r_track,0+1
- mov dirtrack,0
- mov bx,offset secbuf
- call read_phys_track
- mov bx,offset dpb_eig
- jnc short @@goodfmt
-
- @@badfmt:
- mov bx,offset bad_format
- call puts
- call conin
- cmp autologin_flag,TRUE ; waehrend conin kann Edit DPH gewes. sein
- jnz short @@exit
- jmp @@loop
-
- @@goodfmt:
-
- ; physikalisches Format merken
-
- mov al,phys_sec_pt
- mov pspt_last,al
- mov al,first_phys_sec
- mov frstps_last,al
- mov al,dirtrack
- mov dirtr_last,al
- mov dpb_last,bx
-
- mov si,bx
- mov di,offset dpb0+ZBIOSDISPL
- mov cx,size dpb
- cld
- rep movsb ; es:di := ds:si
-
- @@exit:
- pop bx
- mov retry_count,5
- ret
- login_disc endp
-
-
- write proc
- ;
- ; write a record of 128 bytes
- ;
- cmp diskno,RMD
- jnz short wtodisc
- call calcadr ; ax:bx := record adress
- jc short @@bad
- call wrtrec ; buffer := record
- jc short @@bad
- xor al,al ; write ok
- ret
- @@bad: mov al,1
- ret
- write endp
-
- wtodisc proc
- push cx
- call is_valid_rec ; ax=rec/sec
- pop cx
- jc short @@badsec
-
-
- ; if track noch nicht im Buffer
- ; if noch alter Track im Buffer
- ; alten Track ausschreiben
- ; endif
- ; lies neuen Track ein
- ; endif
- ; if track ist dirtrack
- ; if noch alter Track im Buffer
- ; alten Track ausschreiben
- ; endif
- ; dirtrack ausschreiben
- ; else
- ; Setze Flag, daß Sektor geschreiben wurde
- ; endif
- ;
-
- push cx ; bdos info, ob dirsectoren
- call read_w_track
- pop cx
- jc short @@badsec
- ;
- ; record # ist in ah
- ;
-
- push cx
- mov al,WRITE_OP
- call get_adr_in_buf
- mov ax,ds ; ax:= seg track buffer
- call wrtrec
- pop cx
- cmp cl,1
- jz short @@isdir1
- call is_dir_track
- jz short @@isdir1
-
- mov write_flag,TRUE
- mov al,track
- mov last_track_written,al
- mov al,0 ; o.k.
- jmp short @@exit
-
- @@isdir1:
- call write_out_dir
- jc short @@badsec
- mov al,0
- jmp short @@exit
- @@badsec:
- mov al,1
- @@exit:
- ret
- wtodisc endp
-
- ;
- ; In: ax:bx = source adr
- ;
- rdrec proc
- ;
- PUSHR <si,di,bx,cx,ax>
- push ds
- mov si,bx
- mov di,dmaad ; ds MUSS = emudata_seg sein
- mov ds,ax
- mov cx,RECORD_LEN/2 ; record laenge in words
- cld
- rep movsw ; es:di := ds:si
- pop ds
- POPR <ax,cx,bx,di,si>
- ret
- rdrec endp
- ;
- ; In: ax:bx=target adr
- ;
- wrtrec proc
- PUSHR <si,di,cx,ax>
- push es
- push ds
-
- mov si,dmaad ; ACHTUNG: der MOV muss
- ; vor DS Segmentwechsel sein
- mov di,bx
- mov bx,ax ; ramdisc
- mov ax,es ; cp/m
- mov es,bx
- mov ds,ax
-
- mov cx,RECORD_LEN/2 ; record laenge in words
- cld
- rep movsw ; es:di := ds:si
- pop ds
- pop es
- POPR <ax,cx,di,si>
- ret
- wrtrec endp
-
- emulator_seg ends
-
-
- end init
-
-
-
-