;NVOLUMES=8
MAXFILES=16;8
vol_trdos=4 ;'A'..'D'
vol_pipe=25 ;'Z'
TRDOSADD40=0x40
PIPEADD80=0x80
MAXPIPES=8
PIPEBUF_SZ=255
PIPEDESC_SZ=PIPEBUF_SZ+1
;предполагается, что юзер не имеет стек ниже 0x3b00, иначе он затрёт систему
;FCB и имя можно передавать в любой области userspace
;DTA может быть в любой области userspace
fatfs_org=0x4000
;CurrVol=0X4000+26
;CurrDir=CurrVol+1
MACRO GETVOLUME
;ld a,(CurrVol)
;ld a,(iy+app.dir+DIR.ID)
ld a,(iy+app.vol)
ENDM
MACRO SETVOLUME
;ld a,(CurrVol)
;ld a,(iy+app.dir+DIR.ID)
ld (iy+app.vol),a
ENDM
MACRO CHECKVOLUMETRDOS
GETVOLUME
cp vol_trdos
ENDM
BDOS_setpgtrdosfs
ld a,pgtrdosfs
jr sys_setpg4000
;ld bc,memport4000
;ld (sys_curpg4000),a
;out (c),a
;ret
BDOS_setpgfatfs
ld a,pgfatfs
sys_setpg4000
ld bc,memport4000
ld (sys_curpg4000),a ;для sys_sysint
out (c),a
ret
blocksize=128 ;сколько байтов читать в CP/M операциях
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BDOS_wiznetopen
BDOSSETPGW5300 ;портит bc
jp wiznet_open
BDOS_wiznetclose
BDOSSETPGW5300 ;портит bc
jp wiznet_close
BDOS_wiznetread
;de=pointer, hl=buffer size
;out: hl=size
call BDOS_preparedepage
call BDOS_setdepage
;DE = Pointer to physical data
BDOSSETPGW5300
jp wiznet_read
BDOS_wiznetwrite
;de=pointer, hl=size
call BDOS_preparedepage
call BDOS_setdepage
;DE = Pointer to physical data
BDOSSETPGW5300
jp wiznet_write
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BDOS_setmusic
muzpid=$+1
ld a,0
or a
call z,killmuz
ex af,af' ;'
ld (muzpg),a
ld a,h
or l
ret z ;killmuz ставит sys_reter
ld (muzcall),hl
ld a,(iy+app.id)
ld (muzpid),a
;страницы для 8000, c000 берём из текущей юзерской карты памяти
ld a,(iy+app.mainpg)
call sys_setpg8000
ld a,(curpg32klow+0x8000)
ld (muzpg8000),a
ld a,(curpg32khigh+0x8000)
ld (muzpgc000),a
ret
killmuz
xor a
ld (muzpid),a
ld de,sys_reter
ld (muzcall),de
ld a,0xfe
call shut1ay
ld a,0xff
shut1ay
ld bc,0xfffd
out (c),a
ld de,0x0e00
shutay0
dec d
ld b,0xff
out (c),d
ld b,0xbf
out (c),e
jr nz,shutay0
ret
BDOS_setmainpage
;ld iy,(appaddr)
;e=page for 0x0000
ld (iy+app.mainpg),e
ret
BDOS_setborder
;ld iy,(appaddr)
;e=border=0..15
ld (iy+app.border),e
ret
BDOS_setscreen
;ld iy,(appaddr)
;e=screen=0..1
ld a,e
add a,a
add a,a
add a,a
ld d,a
or fd_user
ld (iy+app.screen),a
;xor a ;success
ret;jr rest_exit
BDOS_getappmainpages
;e=id
;out: d,e,h,l=pages in 0000,4000,8000,c000, c=flags, a=error
call BDOS_findapp
jp nz,BDOS_fail
BDOS_getmainpages
;ld iy,(appaddr)
;out: dehl=номера страниц в 0000,4000,8000,c000, c=flags, b=id
BDOS_getmainpages_iy
call setmainpg_c000
ld d,a
ld a,(curpg16k+0xc000)
ld e,a
ld a,(curpg32klow+0xc000)
ld hl,(curpg32khigh+0xc000)
ld h,a
ld c,(iy+app.flags)
ld b,(iy+app.id)
xor a
ret
BDOS_preparedepage
;de=userspace addr
;out: de>=0x8000, depage8000, depagec000
;ld iy,(appaddr)
ld a,(iy+app.mainpg)
call sys_setpg8000
bit 7,d
jr nz,BDOS_preparedepage8000_c000
bit 6,d
jr nz,BDOS_preparedepage4000_8000
set 7,d
ld (depage8000),a
ld a,(curpg4000+0x8000)
;ld bc,memportc000
;out (c),a
ld (depagec000),a
ret
BDOS_preparedepage4000_8000
ld a,d
add a,0x40
ld d,a
ld a,(curpg8000+0x8000)
;call sys_setpgc000
ld (depagec000),a
ld a,(curpg4000+0x8000)
;call sys_setpg8000
ld (depage8000),a
ret
BDOS_preparedepage8000_c000
ld a,(curpgc000+0x8000)
;call sys_setpgc000
ld (depagec000),a
ld a,(curpg8000+0x8000)
;call sys_setpg8000
ld (depage8000),a
ret
BDOS_setdepage
;keep de,hl
depagec000=$+1
ld a,pgkillable;0
call sys_setpgc000
depage8000=$+1
ld a,pgkillable;0
sys_setpg8000
ld (sys_curpg8000),a
ld bc,memport8000
out (c),a
ret
BDOS_setpal
call BDOS_preparedepage
call BDOS_setdepage
;de=палитра (выше 0xc000)
push iy
pop hl
ld bc,app.pal
add hl,bc
ex de,hl
ld bc,32
ldir
;call setpalettechanged
;xor a
;ret
setpalettechanged
ld a,55+128 ;"or a"
ld (palettechanged),a
ret
BDOS_getpal
call BDOS_preparedepage
call BDOS_setdepage
ld hl,(focusappaddr)
ld bc,app.pal ;-app.gfxmode
add hl,bc
ld bc,32
ldir
ret
BDOS_scroll_prepare
ld a,l
srl a
ld (BDOS_scrollpagelinelayer_wid),a
ld b,h
dec b
BDOS_countxy
;keeps bc
ld a,d ;y
sub -0x87&0xff ;0xe1c0*4=0x8700
rra
ld h,a
ld a,0;16
rra
sra h
rra
ld l,e ;x
srl l
jr c,$+4
res 5,h
add a,l
ld l,a
ret
BDOS_getxy
;out: de=yx ;GET CURSOR POSITION
;ld hl,(pr_textmode_curaddr)
ld l,(iy+app.textcuraddr)
ld h,(iy+app.textcuraddr+1)
ld a,h
rla
rla
rla ;bit5
ld a,l
rla
and 0x7f
ld e,a ;x
add hl,hl
add hl,hl ;h=y*4 + const + n*0x80
ld a,h
sub 0x87 ;0xe1c0*4=0x8700
and 0x1f
ld d,a ;y
xor a ;success
ret
BDOS_countattraddr
BDOSSETPGSSCR
;ld hl,(pr_textmode_curaddr)
ld l,(iy+app.textcuraddr)
ld h,(iy+app.textcuraddr+1)
ld a,h
xor 0x60 ;attr + 0x20
ld h,a
and 0x20
jr nz,$+3
inc l
ret
BDOS_prattr
;e=color byte
ld hl,(appaddr)
ld bc,(focusappaddr)
or a
sbc hl,bc
ret nz
call BDOS_countattraddr
ld (hl),e
ret
BDOS_getattr
;out: a=color byte
call BDOS_countattraddr
ld a,(hl)
ret
BDOS_setxy
;de=yx
call BDOS_countxy
BDOS_settextcuraddr
;ld (pr_textmode_curaddr),hl
ld (iy+app.textcuraddr),l
ld (iy+app.textcuraddr+1),h
xor a ;success
ret
BDOS_prchar_controlcode
cp 0x0a
jr z,BDOS_prchar_lf
cp 0x0d
jp nz,BDOS_prchar_nocontrolcode
;jr z,BDOS_prchar_cr
BDOS_prchar_cr
ld a,l
and 0xc0
ld l,a
res 5,h
jr BDOS_settextcuraddr
;jp BDOS_prchar_q
BDOS_prchar_lf
ld a,l
add a,0x40
ld l,a
jr nc,BDOS_settextcuraddr ;BDOS_prchar_q ;ret nc
jr BDOS_prchar_lf_q
BDOS_prchar
;e=char
ld a,e
BDOS_prchar_a
;портит только 0xc000+, но сама восстанавливает там pgkillable (для быстрого вызова через rst)
ld hl,(appaddr)
ld bc,(focusappaddr)
or a
sbc hl,bc
ret nz ;no focus - no print
ld h,trecode/256
ld l,a
ld a,(hl)
;pr_textmode_curaddr=$+1
;ld hl,0xc1c0
ld l,(iy+app.textcuraddr)
ld h,(iy+app.textcuraddr+1)
cp 0x0e
jr c,BDOS_prchar_controlcode
BDOS_prchar_nocontrolcode
;push hl
;ld hl,(appaddr)
;ld bc,(focusappaddr)
;or a
;sbc hl,bc
;pop hl
;jr nz,BDOS_prchar_skip
;ld de,pgscr0_1*256+pgscr0_0
;ld bc,memportc000
;out (c),d ;text
;ld (hl),a
;out (c),e ;attr
ld e,a
ld a,pgscr0_1
call sys_setpgc000
ld (hl),e
ld a,pgscr0_0
call sys_setpgc000
;BDOS_prchar_skip
;ld de,0x2000 + pgkillable
;push af
ld a,h
xor 0x20;d;0x20 ;attr + 0x20
ld h,a
and 0x20;d;0x20
jr nz,$+3
inc l
;pop af
;jr nz,BDOS_prchar_skipattr
;pr_textmode_curcolor=$+1
;ld (hl),7
ld a,(iy+app.curcolor)
ld (hl),a
;set 6,h ;attr -> next char
;;ld e,pgkillable
;out (c),e ;pgkillable
ld a,pgkillable
call sys_setpgc000
;BDOS_prchar_skipattr
ld a,l
and 0x3f
cp 80/2
;ld (pr_textmode_curaddr),hl
ld (iy+app.textcuraddr),l
ld (iy+app.textcuraddr+1),h
ret nz ;jr nz,BDOS_prchar_q ;ret nz ;нет переноса строки
ld a,l
and 0xc0
add a,0x40
ld l,a
jr nc,BDOS_settextcuraddr ;BDOS_prchar_q ;ret nc
BDOS_prchar_lf_q
inc h
bit 3,h
jr z,BDOS_settextcuraddr ;BDOS_prchar_q ;нет выхода за последнюю строку
BDOS_scrolllock0
ld a,0xfe
in a,(0xfe)
rra ;Caps Shift
jr nc,BDOS_scrolllock0
ld hl,(appaddr)
ld de,(focusappaddr)
or a
sbc hl,de
jr nz,BDOS_prchar_skipscroll
;scroll+clear bottom line
call BDOS_scrollpage ;attr
ld a,pgscr0_1 ;text
;ld bc,memportc000
;out (c),a
call sys_setpgc000
call BDOS_cllastline
ld a,pgscr0_0 ;attr
;ld bc,memportc000
;out (c),a
call sys_setpgc000
call BDOS_cllastline
ld a,pgkillable
;ld bc,memportc000
;out (c),a
call sys_setpgc000
BDOS_prchar_skipscroll
ld hl,0xc7c0
BDOS_prchar_q
jp BDOS_settextcuraddr
;;ld (pr_textmode_curaddr),hl
;ld (iy+app.textcuraddr),l
;ld (iy+app.textcuraddr+1),h
;ret
BDOS_scrollpage
ld a,40
ld (BDOS_scrollpagelinelayer_wid),a
ld hl,0xc1c0
ld b,24
BDOS_scrollpage0
push bc
ld d,h
ld e,l
ld bc,64
add hl,bc
call BDOS_scrollpageline
pop bc
djnz BDOS_scrollpage0
ret
BDOS_scrollpageline
ld a,pgscr0_1 ;text
or a
call BDOS_scrollpagelinelayers ;text
ld a,pgscr0_0 ;attr
scf
BDOS_scrollpagelinelayers
;ld bc,memportc000
;out (c),a
call sys_setpgc000
push af
push de
push hl
set 5,h
set 5,d
or a
call BDOS_scrollpagelinelayer
pop hl
pop de
pop af
BDOS_scrollpagelinelayer
push de
push hl
jr nc,$+4
inc hl
inc de
BDOS_scrollpagelinelayer_wid=$+1
ld bc,39;40
ldir
pop hl
pop de
ret
BDOS_scrolldown
;de=topyx, hl=hgt,wid
;x, wid even
;push hl
;ld hl,(appaddr)
;ld bc,(focusappaddr)
;or a
;sbc hl,bc
;pop hl
;ret nz
ld a,d
add a,h
dec a
ld d,a ;ybottom
call BDOS_scroll_prepare
BDOS_scrolldown0
push bc
ld d,h
ld e,l
ld bc,-64
add hl,bc
call BDOS_scrollpageline
pop bc
djnz BDOS_scrolldown0
ret
BDOS_scrollup
;de=topyx, hl=hgt,wid
;x, wid even
;push hl
;ld hl,(appaddr)
;ld bc,(focusappaddr)
;or a
;sbc hl,bc
;pop hl
;ret nz
call BDOS_scroll_prepare
jp BDOS_scrollpage0
BDOS_cllastline
ld hl,0xc7c0
call BDOS_scrollpage_clline
;ld de,0xc7c1
;ld bc,64-1
;ld (hl),b
;ldir
ld hl,0xe7c0
BDOS_scrollpage_clline
ld d,h
ld e,l
inc e
ld bc,64-1
ld (hl),b
ldir ;clear bottom line
ret
BDOS_setcolor
;e=color byte
;ld a,e
;ld (pr_textmode_curcolor),a
ld (iy+app.curcolor),e
ret
;BDOS_getcolor
; ld e,(iy+app.curcolor)
; ret
BDOS_cls
ld hl,(appaddr)
ld bc,(focusappaddr)
or a
sbc hl,bc
ret nz
;ld iy,(appaddr)
;e=color byte
BDOSSETPGSSCR
if 1==1
ld a,(iy+app.gfxmode)
and 7
;jr z,BDOS_cls_EGA(0)
sub 3 ;MC hires(2)
ld a,e ;attr byte
jr c,BDOS_cls_EGA ;TODO отдельную очистку для MC hires
;dec a ;6912(3)
;textmode (6)
ld hl,0xc000
ld bc,0x1aff
jr z,BDOS_cls_textmode_ldirbc ;6912(3)
ld h,0x81;c0
call BDOS_cls_textmode_ldir
ld h,0xa1;c0
call BDOS_cls_textmode_ldir
endif
;ld de,0
ld d,b
ld e,b ;0
call BDOS_setxy
if 1==1
xor a
ld h,0xc1;c0
call BDOS_cls_textmode_ldir
ld h,0xe1;c0
BDOS_cls_textmode_ldir
ld l,0xc0
ld bc,25*64-1
BDOS_cls_textmode_ldirbc
ld d,h
ld e,l
inc de
ld (hl),a
ldir
ret
BDOS_cls_EGA
endif
;ld a,e
scrbase=0x8000
;чистим через стек, кроме первых байтов (иначе прерывание может запортить два байта перед экраном)
ld (clssp),sp
ld hl,scrbase+(200*40) ;чистим с конца, потому что прерывание портит стек
ld b,200-1
scf
clsline0
ld d,a
ld e,a
;ld c,2
clsline1
ld sp,hl
dup 20
push de
edup
set 5,h
ld sp,hl
dup 20
push de
edup
res 5,h
set 6,h
;dec c
;jp nz,clsline1
ccf
jp nc,clsline1
;ld sp,hl
;dup 20
;push de
;edup
;res 5,h
;ld sp,hl
;dup 20
;push de
;edup
;res 6,h
ld de,-40-0x4000
add hl,de ;CY=1!!!
djnz clsline0
clssp=$+1
ld sp,0
ld hl,0x0000 + scrbase
call clslayer2
;ld hl,0x2000 + scrbase
;call clslayer
clslayer2
;ld hl,0x4000 + scrbase
call clslayer
;ld hl,0x6000 + scrbase
clslayer
ld d,h
ld e,l
inc de
ld c,40-1;8000-1
ld (hl),a
ldir
ld de,0x2000-(40-1)
add hl,de
ret
BDOS_playcovox
;hl=data (0xc000+), ends with 0x00
;de=pagetable (0x0000+)
;hx=delay
set 7,d ;de=pagetable (0x8000+)
ld a,(iy+app.mainpg)
call sys_setpg8000 ;pagetable in mainpg
di
ld a,(iy+app.gfxmode)
and 0xf7 ;noturbo
ld bc,0xbd77
out (c),a
push bc
;hx=delay
;hl=data
;de=pagetable (0x8000+)
ld bc,memportc000
ld a,(de)
out (c),a
BDOS_playcovox0
xor a ;4
BDOS_playcovox0_a0
or (hl) ;7
out (0xfb),a ;11
jr z,BDOS_playcovoxdone ;7/12
inc hl ;6
bit 6,h ;8
jr z,BDOS_playcovoxpage ;7/12
BDOS_playcovoxdelay
ld a,hx ;4+4
dec a ;4
jp nz,$-1 ;10
jp BDOS_playcovox0_a0 ;10=78t при d=1, шаг задержки 14 тактов
BDOS_playcovoxpage
;тут и раньше была неточная задержка
ld h,0xc0
inc de
ld a,(de)
out (c),a
jp BDOS_playcovoxdelay
BDOS_playcovoxdone
ld a,(iy+app.gfxmode) ;turbo
pop bc
out (c),a
ei
ret
BDOS_getchildresult
res fchildfinished,(iy+app.flags) ;устанавливался по завершении дочерней задачи (чтобы в этом случае проскочить SETWAITING)
ld l,(iy+app.childresult)
ld h,(iy+app.childresult+1)
ret
BDOS_hidefromparent
;просто разбудить родителя
activateparent
;hl=result
ld e,(iy+app.parentid)
ld a,e
dec a
ret z ;idle
push hl
ld (iy+app.parentid),1;idle ;чтобы после закрытия задачи не пришлось будить родителя (он может уже не существовать)
call BDOS_findapp ;iy=found app
pop hl
ret nz ;not found
set factive,(iy+app.flags)
ld (iy+app.childresult),l
ld (iy+app.childresult+1),h
ret
BDOS_setstdinout
;b=id, e=stdin, d=stdout, h=stderr
push de
ld e,b
call BDOS_findapp
pop de
ld (iy+app.stdin),e
ld (iy+app.stdout),d
ld (iy+app.stderr),h
ret
BDOS_getstdinout
;out: e=stdin, d=stdout, h=stderr, l=hgt of stdout
ld e,(iy+app.stdin)
ld d,(iy+app.stdout)
ld h,0
ld l,d ;stdout
ld bc,pipetypes-PIPEADD80
add hl,bc
ld l,(hl)
ld h,(iy+app.stderr)
ret
BDOS_getkeymatrix
;out: bcdehlix = полуряды cs...space
ld hl,(appaddr)
ld de,(focusappaddr)
or a
sbc hl,de
jr nz,BDOS_getkeymatrix_fail
ld bc,0x7ffe
in a,(c)
ld lx,a ;lx=%???bnmS_
ld b,0xbf
in a,(c)
ld hx,a ;hx=%???hjklE
ld b,0xdf
in l,(c) ;l=%???yuiop
ld b,0xef
in h,(c) ;h=%???67890
ld b,0xf7
in e,(c) ;e=%???54321
ld b,0xfb
in d,(c) ;d=%???trewq
ld a,0xfd
in a,(0xfe);c=%???gfdsa
ld b,c;0xfe
in b,(c) ;b=%???vcxzC
ld c,a
xor a ;z
ret
BDOS_getkeymatrix_fail
;nz
ld bc,0xffff
ld d,c
ld e,c
ld h,c
ld l,c
push bc
pop ix
ret
BDOS_gettimerX
BDOS_gettimer
ld de,(sys_timer+2) ;ok
ld hl,(sys_timer) ;ok
ld a,(sys_timer+2) ;ok
sub e
jr nz,BDOS_gettimerX ;для атомарности
ret ;a=0
;BDOS_yield
; ex af,af'
; or a
; jr z,BDOS_yieldnokeep
; ;dec (iy+app.lasttime)
BDOS_yieldkeep
ld a,(sys_timer) ;ok
dec a
jr BDOS_yieldgo
;ld (iy+app.lasttime),a
;BDOS_yieldnokeep
BDOS_yield
ld a,(sys_timer) ;ok
BDOS_yieldgo
ld (iy+app.lasttime),a
;регистры не сохраняем, т.к. нам не важно, что на выходе из yield
if 1==1
;но надо:
;взять адрес стека для выхода из CALLBDOS и записать его в ld sp на выходе из обработчика прерываний
;взять адрес возврата из CALLBDOS и записать его в jp на выходе из обработчика прерываний
;на выходе надо вручную выставить везде pgkillable!
;ld iy,(appaddr)
if bdosstack_sz==0
ld hl,(callbdos_sp)
else
;ld l,(iy+app.callbdos_sp)
;ld h,(iy+app.callbdos_sp+1)
exx
endif
;call setmainpg_c000
;halt ;проверка на вшивость
;ld (intsp+0xc000),hl
;ex de,hl
ld de,-6
add hl,de ;место в стеке под 3 рег.пары (а потом адрес возврата из bdos)
ld (iy-2),l
ld (iy-1),h ;sp в описателе текущей задачи
;call BDOS_preparedepage
;call BDOS_setdepage ;включается сразу 2 страницы на случай sp на границе страниц
;ex de,hl
;halt ;проверка на вшивость
;ld e,(hl)
;inc hl
;ld d,(hl) ;вместо адреса возврата из bdos
;call setmainpg_c000
;halt ;проверка на вшивость
;ld (intjp+0xc000),de ;TODO при многозадачности в кернале это надо делать атомарно вместе с записью sp!
endif
;ld a,pgkillable
;call sys_setpgc000
;call sys_setpg8000
;call setpgs_killable
if bdosstack_sz !=0
ld a,0xc0
ld (callbdos_mutex),a ;то же самое делают те функции BDOS, которые не собираются возвращаться
endif
;не выходим из CALLBDOS, взамен шедулим и выходим через конец обработчика прерываний
BDOS_yield_q
; push iy
call schedule ;out: iy=app ;можно с включенными прерываниями, пока системный обработчик не умеет шедулить
call setpgs_killable ;во всех случаях!
;halt ;проверка на вшивость
; pop de
; or a
; sbc hl,de
; jr nz,BDOS_yield_nosame
; ld iy,app1 ;idle (TODO вместо этого сделать полноценные приоритеты)
; ld (appaddr),iy
;BDOS_yield_nosame
;di ;TODO critical section
jp sys_int_popregs ;там ei
BDOS_newapp
;пока структура не заполнена до конца, нельзя делать runapp
;out: b=id, dehl=номера страниц в 0000,4000,8000,c000 нового приложения, a=error
BDOSSETPGTRDOSFS
jp sys_newapp_forBDOS
BDOS_findapp
;nz=error
ld iy,app1
ld a,e
ld de,app_sz
ld b,MAXAPPS
BDOS_findapp0
cp (iy+app.id)
ret z
add iy,de
djnz BDOS_findapp0
ret ;nz
BDOS_dropapp
;e=id
;hl=result
push hl
call BDOS_findapp
pop hl
jp nz,BDOS_fail ;BDOS_popfail
push iy
push hl
call BDOS_freezeapp_go
pop hl ;result
pop iy
;BDOS_delapppages
push iy
call activateparent ;in: hl=result
pop iy
ld a,(muzpid)
cp (iy+app.id)
call z,killmuz ;before killing pages!!!
ld hl,tsys_pages
ld a,(iy+app.id)
ld b,sys_npages&0xff
sys_quit_delpages0
cp (hl) ;id==снимаемая задача?
jr nz,$+4
ld (hl),0 ;освободили страницу
inc hl
djnz sys_quit_delpages0
if INETDRV
BDOSSETPGW5300
call w53_drop_socs
endif
if 1==1
call BDOS_setpgstructs
ld ix,ffilearray
ld b,MAXFILES
BDOS_dropapp_closefiles0
ld de,FIL_sz
ld a,(ix+FIL.PAD1)
cp (iy+app.id)
jr nz,BDOS_dropapp_closefiles_skip
push bc
push ix
pop de
push de
F_CLOS_CURDRV
pop ix
pop bc
BDOS_dropapp_closefiles_skip
add ix,de
djnz BDOS_dropapp_closefiles0
endif
;ld a,(muzpid)
;cp (iy+app.id)
;call z,killmuz
xor a ;ok
ld (iy+app.id),a ;b;0 ;освободили место
ret
open_keeppid
push af
push de
inc de
inc de
inc de
inc de
inc de
push bc
call BDOS_setpgstructs
pop bc
ld a,(iy+app.id)
ld (de),a
pop de
pop af
ret
BDOS_runapp
;e=id
;push iy
call BDOS_findapp
jp nz,BDOS_fail ;BDOS_popfail
set factive,(iy+app.flags)
;pop iy
xor a
ret
BDOS_setwaiting
;set fwaiting,(iy+app.flags)
bit fchildfinished,(iy+app.flags)
ret nz ;не замораживает, если дочерний процесс уже завершился
res factive,(iy+app.flags)
ret
BDOS_checkpid
;e=id
;check if this child(!) app exists, out: a!=0 => OK, or else a=0
push iy
;set fwaiting,(iy+app.flags)
ld c,(iy+app.id) ;my (parent's) id ;caller is the parent
push bc
call BDOS_findapp ;iy=found app
pop bc
ld a,(iy+app.parentid)
pop iy
jr nz,BDOS_checkpid_OK ;app doesn't exist = OK
cp c ;parent id
jp z,BDOS_fail ;existing app = fail
BDOS_checkpid_OK
;res fwaiting,(iy+app.flags)
xor a
ret
BDOS_setgfx
;ld iy,(appaddr)
;e=0:EGA, e=2:MC, e=3:6912, e=6:text ;+8 = noturbo ;+128=keep screen
;e=-1: disable gfx (out: e=old gfxmode)
push de
bit 7,(iy+app.gfxkeep)
jr z,BDOS_setgfx_nkept
ld e,(iy+app.scr0low)
call BDOS_delpage
ld e,(iy+app.scr0high)
call BDOS_delpage
ld e,(iy+app.scr1low)
call BDOS_delpage
ld e,(iy+app.scr1high)
call BDOS_delpage
BDOS_setgfx_nkept
pop de
ld a,e
cp -1
jr z,BDOS_setgfx_gfxoff;BDOS_gfxoff_givefocus
IFDEF NOTURBO
ELSE
xor 0x08;%00001000 ;+8 = noturbo
ENDIF
ld (iy+app.gfxkeep),a ;b7 = keep gfx pages
push af
rla
jr nc,BDOS_setgfx_nokeep
;TODO return error if error
call BDOS_newpage_iy ;out: a=0 (OK)/0xff (fail), e=page
ld (iy+app.scr0low),e
call BDOS_newpage_iy ;out: a=0 (OK)/0xff (fail), e=page
ld (iy+app.scr0high),e
call BDOS_newpage_iy ;out: a=0 (OK)/0xff (fail), e=page
ld (iy+app.scr1low),e
call BDOS_newpage_iy ;out: a=0 (OK)/0xff (fail), e=page
ld (iy+app.scr1high),e
BDOS_setgfx_nokeep
pop af
or 0xa0;%10100000
ld (iy+app.gfxmode),a
call enablescreeninapp_nokeep ;enablescreeninapp_setc000
;кладём фокус в стек, только если не два раза setgfx в одной задаче:
ld hl,(focusappaddr)
push iy
pop de
or a
sbc hl,de
jr z,BDOS_setgfx_nopushfocus ;not in focus
;jr $
add hl,de
push de;iy
push hl
pop iy
call disablescrpgs_setc000 ;у старой focusapp отключить экран в переменных и в памяти
pop iy
ld hl,(oldfocusappaddr)
ld (oldoldfocusappaddr),hl ;TODO стек фокусов (чтобы после закрытия задачи вернуть фокус вызвавшей)
ld hl,(focusappaddr)
ld (oldfocusappaddr),hl ;TODO стек фокусов (чтобы после закрытия задачи вернуть фокус вызвавшей)
ld (focusappaddr),iy
call setpalettechanged
BDOS_setgfx_nopushfocus
set fgfx,(iy+app.flags)
ld e,(iy+app.gfxmode)
;xor a ;success
ret
BDOS_setgfx_gfxoff
call disablescrpgs_setc000 ;у старой focusapp отключить экран в переменных и в памяти
ld e,(iy+app.gfxmode)
push de
call BDOS_gfxoff_givefocus ;spoils iy!
pop de
ret
;disablescreeninapp_setc000
;call setmainpg_c000
disablescreeninapp ;used in sys_newapp
ld a,pgkillable
ld (0xc000+user_scr0_low),a
ld (0xc000+user_scr0_high),a
ld (0xc000+user_scr1_low),a
ld (0xc000+user_scr1_high),a
ret
enablescreeninapp_setc000
bit 7,(iy+app.gfxkeep)
jr z,enablescreeninapp_nokeep
ld e,pgscr0_0
ld a,(iy+app.scr0low)
call copypage_a_to_e
ld e,pgscr0_1
ld a,(iy+app.scr0high)
call copypage_a_to_e
ld e,pgscr1_0
ld a,(iy+app.scr1low)
call copypage_a_to_e
ld e,pgscr1_1
ld a,(iy+app.scr1high)
call copypage_a_to_e
enablescreeninapp_nokeep
call setmainpg_c000
ld de,curpg16k+0xc000
call enablescrpg
ld e,0xff&(curpg32klow+0xc000)
call enablescrpg
ld e,0xff&(curpg32khigh+0xc000)
call enablescrpg
;enablescreeninapp_nokeep
call setmainpg_c000
ld a,pgscr0_0
ld (0xc000+user_scr0_low),a
ld a,pgscr0_1
ld (0xc000+user_scr0_high),a
ld a,pgscr1_0
ld (0xc000+user_scr1_low),a
ld a,pgscr1_1
ld (0xc000+user_scr1_high),a
ret
BDOS_freezeapp
;e=id
;push iy
call BDOS_findapp
jp nz,BDOS_fail ;BDOS_popfail
BDOS_freezeapp_go
;ld (iy+app.flags),0 ;пока тут 0, задачу никто не будет трогать
res factive,(iy+app.flags)
BDOS_gfxoff_givefocus
res fgfx,(iy+app.flags) ;если в конце, то по дороге могут вручную переключить фокус, а если в начале, то ...
;если фокус у этой задачи, то дать фокус какой-нибудь графической задаче
push iy
pop hl
ld de,(focusappaddr)
xor a
sbc hl,de
ret nz ;jr nz,sys_quit_findgfxapp_fail ;фокус не у этой задачи
oldfocusappaddr=$+1
ld hl,app1
oldoldfocusappaddr=$+1
ld de,app1
ld (oldfocusappaddr),de
bit fgfx,(hl)
jr nz,sys_quit_findgfxappq ;TODO стек фокусов (чтобы после закрытия задачи вернуть фокус вызвавшей)
ld hl,app1
ld bc,-app_last;app_afterlast
ld de,app_last+app_sz;app_sz
sys_quit_findgfxapp0
add hl,bc
jr c,sys_quit_findgfxapp_fail ;уже проверили app_last, у него нет фокуса - некому давать фокус
add hl,de
bit fgfx,(hl)
jr z,sys_quit_findgfxapp0
sys_quit_findgfxappq
ld (focusappaddr),hl
call setpalettechanged
push hl
pop iy
call enablescreeninapp_setc000 ;включить экран в переменные этой задачи
;ld a,key_redraw
;ld (curkey),a
;ld bc,key_redraw
; ld (keyqueueput_codenolang),bc
;call KEYQUEUEPUT
call KEY_PUTREDRAW
sys_quit_findgfxapp_fail
;pop iy
xor a
ret
BDOS_getpageowner
;e=page ;out: e=owner id (0=free, 0xff=system)
ld hl,tsys_pages
if sys_npages != 256
ld a,e
cp sys_npages
jr nc,BDOS_getpageowner_toobig
endif
ld d,0
add hl,de
ld e,(hl)
ret
if sys_npages != 256
BDOS_getpageowner_toobig
ld e,0xff
ret
endif
BDOS_newpage
;ld iy,(appaddr)
BDOS_newpage_iy
;out: a=0 (OK)/0xff (fail), e=page
if TOPDOWNMEM
ld hl,tsys_pages +sys_npages-1
ld bc,sys_npages
xor a
cpdr
jr nz,BDOS_fail
inc hl
ld a,(iy+app.id)
ld (hl),a
ld a,pagexor;0x7f
sub c ;c=0..sys_npages-1
else
ld hl,tsys_pages
;push hl
ld bc,sys_npages
xor a
cpir
;pop de
jr nz,BDOS_fail
dec hl
ld a,(iy+app.id)
ld (hl),a
;or a
;sbc hl,de ;hl=(0..sys_npages-1)
;ld a,pagexor;0x7f
;sub l ;l=0..sys_npages-1
ld a,0xff&(pagexor-(sys_npages-1))
add a,c
endif
ld e,a ;page
BDOS_OK
xor a
ret ;a=0 (OK), e=page
BDOS_pop2fail
pop af
BDOS_popfail
pop af
BDOS_fail
ld a,0xff
ret
BDOS_delpage
;e=page
;не портит de
;в конце A не гарантировано
ld a,e
;call addrpage ;a=0
xor pagexor;0x7f
ld c,a
ld hl,tsys_pages
xor a
ld b,a
add hl,bc
ld a,(hl)
inc a
ret z ;reserved page (for example pgkillable)
ld (hl),b ;id=0, т.е. у этой страницы нет хозяина
ret
if 1==0
addrpage
xor pagexor;0x7f
ld c,a
ld hl,tsys_pages
xor a
ld b,a
add hl,bc
ret ;a=0
endif
;DEPRECATED!!!!!
BDOS_fdel
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to unopened FCB
CHECKVOLUMETRDOS
jr c,BDOS_fdel_noFATFS
call get_name
ld de,mfil
F_UNLINK_CURDRV
;or a:jp z,fexit
;ld a,0xff
ret;jp fexit
BDOS_fdel_noFATFS
BDOSSETPGTRDOSFS
;DE = Pointer to unopened FCB
jp nfdel
BDOS_rndrdwrseek
;DE = Pointer to opened FCB
push de
ld hl,0x21 ;outsize FCB_sz!!!
add hl,de
ld c,(hl)
inc hl
ld b,(hl)
push bc ;record number BC
call getFILfromFCB ;hl=FIL
ex de,hl ;de=fil (2 words in stack = shift)
push de
call BDOS_getfilesize_filde
;dehl=filesize (no more than 8M in CP/M finction)
;highest record number = dehl/128???
add hl,hl
rl e
ld l,h
ld h,e
;highest record number = dehl/128-1??? wrong!
;add hl,hl
;rl e
;ld l,h
;ld h,e
; ld a,h
; or l
; jr z,$+3
; dec hl
;highest record number = (dehl-1)/128??? wrong!
;ld a,h
;or l
;dec hl
;jr nz,$+3
;dec de
;add hl,hl
;rl e
;ld l,h
;ld h,e
; ld a,h
; and l
; inc a
; jr nz,$+3
; inc hl
pop de
pop bc ;record number BC
call minhl_bc_tobc
ld l,b ;HSB from BC
ld h,0
srl l
push hl ;HSW
ld b,c
ld c,h;0
rr b
rr c
push bc ;LSW
F_LSEEK_CURDRV
pop bc
pop bc
pop de
ret
;TODO TR-DOS???
BDOS_rndrd
call BDOS_preparedepage
call BDOS_setdepage
;DE = Pointer to opened FCB
call BDOS_rndrdwrseek
call BDOS_setdepage
jr BDOS_fread_gofatfs
;TODO TR-DOS???
BDOS_rndwr
call BDOS_preparedepage
call BDOS_setdepage
;DE = Pointer to opened FCB
call BDOS_rndrdwrseek
call BDOS_setdepage
jr BDOS_fwrite_gofatfs
BDOS_fread
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to opened FCB
;CHECKVOLUMETRDOS
ld a,(de)
cp vol_trdos
jr c,BDOS_fread_noFATFS
BDOS_fread_gofatfs
;достать из него адрес ffile
call getFILfromFCB ;hl=FIL
call BDOS_getdta ;de = disk transfer address
push de
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
ld b,d
ld c,e
ld de,blocksize
push de ;blocksize
ld ix,fres
push ix ;fres
push de ;blocksize
ex de,hl;ld de,ffile
F_READ_CURDRV
BDOS_fread_fatfsq
pop bc
pop bc
ld a,(bc)
pop bc ;blocksize
pop de ;de = disk transfer address
;call movedma_addr ;+bc ;TODO remove!!!
xor 0x80 ;!=, если прочитали не 128 байт ;TODO remove!!!
;a=0: OK (прочитали 128 байт)
;a=128: fail (прочитали 0 байт)
;a=???: OK (последний блок файла меньше 128 байт)
ret z
cp 0x80
ret z ;fail
;for CP/M compatibility: fill unused part of sector with 0x1a
push af
;call BDOS_getdta ;de = disk transfer address
call BDOS_preparedepage
call BDOS_setdepage ;нельзя надеяться на включение выше, если будет убрано в драйвер (т.к. это могло быть не последнее включение страницы)
pop af
push af
;a=128+bytes loaded
neg
;a=128-bytes loaded
ld b,a
ld a,e
add a,127
ld e,a
adc a,d
sub e
ld d,a ;de= Point to buffer end
ld a,0x1a
ld (de),a
dec de
djnz $-2
pop af
ret;jp fexit
BDOS_fread_noFATFS
BDOSSETPGTRDOSFS
;DE = Pointer to opened FCB (0x8000+/0xc000+)
jp trdos_fread
BDOS_fwrite
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to opened FCB
;CHECKVOLUMETRDOS
ld a,(de)
cp vol_trdos
jr c,BDOS_fwrite_noFATFS
BDOS_fwrite_gofatfs
;достать из него адрес ffile
call getFILfromFCB ;hl=FIL
call BDOS_getdta ;de = disk transfer address
push de
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
ld b,d
ld c,e
ld de,blocksize
push de ;blocksize
ld ix,fres
push ix ;fres
push de ;blocksize
ex de,hl;ld de,ffile
F_WRITE_CURDRV
jr BDOS_fread_fatfsq
BDOS_fwrite_noFATFS
BDOSSETPGTRDOSFS
;DE = Pointer to opened FCB
jp trdos_fwrite
if 1==0
BDOS_fwrite_nbytes
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to opened FCB
;hl = bytes
;CHECKVOLUMETRDOS
ld a,(de)
cp vol_trdos
jr c,BDOS_fwrite_nbytes_noFATFS
;достать из него адрес ffile
push hl ;bytes
call getFILfromFCB ;hl=FIL
call BDOS_getdta ;de = disk transfer address
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
ld b,d
ld c,e
;ld de,blocksize
pop de ;bytes
push de ;blocksize
ld ix,fres
push ix ;fres
push de ;blocksize
ex de,hl;ld de,ffile
F_WRITE_CURDRV
jr BDOS_fread_fatfsq
BDOS_fwrite_nbytes_noFATFS
BDOSSETPGTRDOSFS
;DE = Pointer to opened FCB
;hl = bytes
ld b,h
ld c,l
jp trdos_fwrite_nbytes
endif
;de=path
;hl=FILINFO buffer
BDOS_getfilinfo
push hl ;FILINFO buffer
call BDOS_preparedepage
call BDOS_setdepage
call countfiledrive
pop bc
F_STAT
ret
count_fdir
push iy
pop de
ld hl,app.dir
add hl,de
ex de,hl
ret
;de=path
BDOS_opendir
call BDOS_preparedepage
call BDOS_setdepage
call countfiledrive
ld b,d
ld c,e
CHECKVOLUMETRDOS
jr c,BDOS_opendir_noFATFS
BDOS_opencurdir
call count_fdir ;LD de,fdir
F_OPDIR_CURDRV
ret
BDOS_opendir_noFATFS
push af
BDOSSETPGTRDOSFS
pop af
ld (trdoscurdrive),a
ld hl,trdos_catbuf
call writedircluster_hl
ld de,0x0000 ;track,sector
ld (hl),e;0
ld bc,0x0905 ;read 9 sectors
call iodos.
xor a ;no error
ret
;de=buf for FILINFO, 0x00 in FILINFO_FNAME = end dir
BDOS_readdir
call BDOS_preparedepage
call BDOS_setdepage
ld b,d
ld c,e
CHECKVOLUMETRDOS
jr c,BDOS_readdir_noFATFS
call count_fdir ;LD de,fdir
F_RDIR_CURDRV
ret
BDOS_readdir_noFATFS
;bc=addrto
push bc
BDOSSETPGTRDOSFS
ld l,(iy+app.dircluster)
ld h,(iy+app.dircluster+1)
ld de,fcb2+FCB_FNAME
call trdos_searchnext
jp z,BDOS_popfail ;fsearchnext_nofile;BDOS_fsearch_loadloop_noFATFS_empty
call writedircluster_hl
pop de
;de=addrto
ld hl,fcb2+FCB_FSIZE
ld bc,4
ldir
ld hl,fcb2+FCB_FDATE
ld c,2
ldir
ld hl,fcb2+FCB_FTIME
ld c,2
ldir
ld hl,fcb2+FCB_FATTRIB
ldi
ld hl,fcb2+FCB_FNAME
call get_name_hltode ;делает из имени без точки имя с точкой
ld h,d
ld l,e
ld bc,12
xor a ;no error
ld (hl),a
inc de
ldir ;независимо от длины короткого имени он длинное затирает
ret
;FILINFO_FSIZE=0; DWORD ;/* FILE SIZE */
;FILINFO_FDATE=4; WORD ;/* LAST MODIFIED DATE */
;FILINFO_FTIME=6; WORD ;/* LAST MODIFIED TIME */
;FILINFO_FATTRIB=8; BYTE ;/* ATTRIBUTE */
;FILINFO_FNAME=9; BLOCK 13,0 ;/* SHORT FILE NAME (8.3 FORMAT with dot and terminator) */
;FILINFO_LNAME=22; BLOCK DIRMAXFILENAME64,0 ;/* LONG FILE NAME (ASCIIZ) */
;FILINFO_sz=FILINFO_LNAME+DIRMAXFILENAME64
;SEARCH FOR FIRST [FCB] (11H)
; Parameters: C = 11H (_SFIRST)
; DE = Pointer to unopened FCB
; Results: L=A = 0FFH if file not found
; = 0 if file found.
;The filename may be ambiguous (containing "?" characters) in which case the first match will be found.
;The low byte of the extent field will be used, and a file will only be found if it is big enough
;to contain this extent number. Normally the extent field will be set to zero by the program before
;calling this function. System file and sub-directory entries will not be found.
;If a suitable match is found (A=0) then the directory entry will be copied to the DTA address,
;preceded by the drive number. This can be used directly as an FCB for an OPEN function call if desired.
;The extent number will be set to the low byte of the extent from the search FCB, and the record count
;will be initialized appropriately (as for OPEN). The attributes byte from the directory entry will be
;stored in the S1 byte position, since its normal position (immediately after the filename extension field)
;is used for the extent byte.
BDOS_fsearchfirst
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
push de ;DE = Pointer to unopened FCB (0x8000+/0xc000+)
CHECKVOLUMETRDOS
jr c,BDOS_fsearchfirst_noFATFS
ld bc,0 ; TCHAR *path /* Pointer to the directory path */
call BDOS_opencurdir
pop de ;DE = Pointer to unopened FCB (0x8000+/0xc000+)
or a
ret nz;jp nz,fexit
jr BDOS_fsearch_goloadloop
BDOS_fsearchfirst_noFATFS
;TR-DOS
push af
BDOSSETPGTRDOSFS
pop af
ld (trdoscurdrive),a
ld hl,trdos_catbuf
;ld (BDOS_fsearch_loadloop_trdosaddr),hl ;TODO где хранить для многозадачности? возвращать в FCB_DIRPOS?
call writedircluster_hl
ld de,0x0000 ;track,sector
ld (hl),e;0
ld bc,0x0905 ;read 9 sectors
call iodos.
pop de ;DE = Pointer to unopened FCB (0x8000+/0xc000+)
jr BDOS_fsearch_goloadloop
;SEARCH FOR NEXT [FCB] (12H)
; Parameters: C = 12H (_SNEXT)
; Results: L=A = 0FFH if file not found
; = 0 if file found.
BDOS_fsearchnext
;(not CP/M!!!) для многозадачности принимать тут de = Pointer to unopened FCB
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
BDOS_fsearch_goloadloop
inc de
ld (fsearchnext_filename),de
BDOS_fsearch_loadloop
ld iy,(appaddr) ;т.к. ffs портит iy
CHECKVOLUMETRDOS
jr c,BDOS_fsearch_loadloop_noFATFS
call count_fdir ;LD de,fdir
LD bc,mfilinfo
F_RDIR_CURDRV
or a
jp nz,BDOS_fail ;fsearchnext_nofile ;иначе после удаления файла каталог не заканчивается
;переделать структуру FILINFO (которую мы сейчас считали) в структуру FCB
ld de,mfilinfo+FILINFO_FNAME
ld a,(de)
or a
jp z,BDOS_fail ;fsearchnext_nofile
BDOSSETPGTRDOSFS
call trdosgetdirfcb
jr BDOS_fsearch_loadloop_FATFSq
BDOS_fsearch_loadloop_noFATFS
;TR-DOS
BDOSSETPGTRDOSFS
ld l,(iy+app.dircluster)
ld h,(iy+app.dircluster+1)
ld de,fcb2+FCB_FNAME
call trdos_searchnext
jp z,BDOS_fail ;fsearchnext_nofile;BDOS_fsearch_loadloop_noFATFS_empty
call writedircluster_hl
jr BDOS_fsearch_loadloop_FATFSq
BDOS_fsearch_loadloop_FATFSq
ld hl,fcb2+FCB_FNAME ;прочитанное имя
fsearchnext_filename=$+1
ld de,0 ;образец
;проверить имя файла hl == de (игнорировать (de)=='?')
ld bc,11*256;0x0a00 ;b=bytes to compare, c=errors
fsearchnext_cp00
ld a,[de]
cp '?'
jr z,fsearchnext_cpskip
sub [hl]
or c
ld c,a ;errors
fsearchnext_cpskip
inc hl
inc de
djnz fsearchnext_cp00
;если не совпало, зациклить
ld a,c
or a
jp nz,BDOS_fsearch_loadloop
fsearchnext_nofileq
;иначе записать в dma
ld iy,(appaddr)
ld hl,fcb2
call BDOS_getdta ;de = disk transfer address
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
ld bc,FCB_sz;32;16
push bc
ldir
pop bc
call movedma_addr ;+bc
xor a ;success
ret;jp rest_exit
BDOS_getfiletime
;de=Drive/path/file ASCIIZ string
;out: ix=date, hl=time
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
call countfiledrive ;a=volume, de=path without drive, c=1: drive in path, CY=TR-DOS
jr c,BDOS_getfiletime_zero
ld bc,fres
;de=name
;bc=pointer to time,date
F_GETUTIME
ld hl,(fres)
ld ix,(fres+2)
;xor a
ret
BDOS_getfiletime_zero
;display "BDOS_getfiletime_zero=",BDOS_getfiletime_zero
BDOSSETPGTRDOSFS
jp trdos_getfiletime
;xor a
;ld l,a
;ld h,a
;push hl
;pop ix
BDOS_gettime
;out: ix=date, hl=time
if atm==1
call readtime
endif
ld hl,(sys_time_date) ;ok
ld ix,(sys_time_date+2) ;ok
ret
BDOS_settime
;in: ix=date, hl=time
ld (sys_settime_time),hl
ld (sys_settime_date),ix
ld a,55
ld (sys_settime_do),a
ret
BDOS_setfiletime
;de=Drive/path/file ASCIIZ string, ix=date, hl=time
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
call countfiledrive ;a=volume, de=path without drive, c=1: drive in path, CY=TR-DOS
jr c,BDOS_getfiletime_zero
push hl ;time
push ix ;date
pop bc ;date
;de=name
;bc=date
;stack=time
F_UTIME_CURDRV
pop bc
ret
BDOS_seekhandle
; B = File handle
; [A = Method code: 0=begin,1=cur,2=end]
; DE:HL = Signed offset
; Results: A = Error
; DE:HL = New file pointer
bit 6,b
jr nz,BDOS_seekhandle_noFATFS
push de ;HSW
push hl ;LSW
call BDOS_number_to_fil ;de=fil
F_LSEEK_CURDRV
pop bc
pop bc
ret
BDOS_seekhandle_noFATFS
push bc
BDOSSETPGTRDOSFS
pop bc
jp trdos_seekhandle
BDOS_getfilesize
;b=handle
;out: dehl=filesize
bit 6,b
jr nz,BDOS_getfilesize_noFATFS
call BDOS_number_to_fil ;de=fil
BDOS_getfilesize_filde
ld hl,FIL.FSIZE
jr BDOS_tellhandleq
;add hl,de
;ld e,(hl)
;inc hl
;ld d,(hl)
;inc hl
;ld a,(hl)
;inc hl
;ld h,(hl)
;ld l,a
;ex de,hl
;xor a
;ret
BDOS_getfilesize_noFATFS
push bc
BDOSSETPGTRDOSFS
pop bc
jp trdos_getfilesize ;dehl=filesize
BDOS_tellhandle
;b=file handle, out: dehl=offset
;TODO TR-DOS
call BDOS_number_to_fil ;de=fil
ld hl,FIL.FPTR
BDOS_tellhandleq
call BDOS_setpgstructs
add hl,de
ld c,(hl)
inc hl
ld b,(hl)
inc hl
ld e,(hl)
inc hl
ld d,(hl)
ld h,b
ld l,c
xor a
ret
BDOS_createhandle
;DE = Drive/path/file ASCIIZ string
;A = Open mode. b0 set => no write, b1 set => no read, b2 set => inheritable, b3..b7 - must be clear
;B = b0..b6 = Required attributes, b7 = Create new flag
;out: B = new file handle, A=error
ld c,a
ld a,'w'
LD HL,FA_READ|FA_WRITE|FA_CREATE_ALWAYS
jr BDOS_openorcreatehandle
BDOS_openhandle
;DE = Drive/path/file ASCIIZ string
;[A = Open mode. b0 set => no write, b1 set => no read, b2 set => inheritable, b3..b7 - must be clear]
;out: B = new file handle, A=error
ld c,a
ld a,'r'
ld hl,FA_READ|FA_WRITE
BDOS_openorcreatehandle
ld (BDOS_openorcreatehandle_trdosmode),a
ld (.mode),hl
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Drive/path/file ASCIIZ string
call countfiledrive ;a=volume, de=path without drive, c=1: drive in path, CY=TR-DOS
jr c,BDOS_openhandle_noFATFS
cp vol_pipe
jr z,BDOS_openhandle_pipe
ld (.store_a),a
push de
;dec c ;was c=1: drive in path
;call z,BDOS_setvol_rootdir ;drive specified in path
call findfreeffile
jr nz,$ ;TODO error
push bc
call BDOS_setdepage ;TODO убрать в драйвер????
pop bc
ld a,b
ex de,hl ;a=fil number, de=poi to FIL
pop bc
push af
.mode=$+1
LD HL,FA_READ|FA_WRITE
.store_a=$+1
ld a,0
F_OP
pop bc ;b=fil number=new file handle
ret
BDOS_openhandle_noFATFS
;a=drive
;recode file name
;pop af ;z=drive in path
push af ;drive
BDOSSETPGTRDOSFS
ex de,hl ;hl=path
call findlastslash. ;de=after last slash or beginning of path
ld hl,BDOS_parse_filename_cpmnamebuf
push hl
call dotname_to_cpmname ;de -> hl ;out: de=pointer to termination character, hl=buffer filled in
;BDOSSETPGTRDOSFS
pop de
BDOS_openorcreatehandle_trdosmode=$+1
ld c,'r'
pop af ;drive
call nfopen ;hl=trdosfcb
ld b,h ;new file handle
ret
BDOS_openhandle_pipe
;find free pipe
ld hl,freepipes
xor a
ld bc,MAXPIPES
cpir
jp nz,BDOS_fail
dec hl
inc (hl)
inc (hl) ;opened once, used as stdin and as stdout, closed twice
ld a,l
add a,0xff&(-freepipes+PIPEADD80)
push af ;a=handle
;a = PIPEADD80+pipeindex
call findpipe_byhandle ;out: hl=pipebuf, a=pipe#
ld bc,pipeowners
add a,c
ld c,a
jr nc,$+3
inc b
ld a,(iy+app.id)
ld (bc),a ;pipe owner (потом переназначится тому, кто читает)
xor a
ld (hl),a ;size=0
ld hl,pipetypes-pipeowners
add hl,bc
inc de
inc de ;de=path without drive, skip slash and first letter (for unique names in the future)
ld a,(de)
sub '0'
ld c,a
add a,a
add a,a
add a,c
add a,a ;*10
ld c,a
inc de
ld a,(de)
sub '0'
add a,c
ld (hl),a ;размер терминала в строках (делается из имени пайпа типа "a33")
pop bc ;b=handle
;b=new pipe handle
ret
BDOS_number_to_fil
;b = file handle = 0..
;out: de=fil
inc b
ld hl,ffilearray-FIL_sz
ld de,FIL_sz
BDOS_number_to_fil0
add hl,de
djnz BDOS_number_to_fil0
ex de,hl
ret
BDOS_closehandle
;B = file handle
;out: A=error
bit 7,b
jr nz,BDOS_closehandle_pipe
bit 6,b
jr nz,BDOS_closehandle_noFATFS
call BDOS_number_to_fil
;de=fil
F_CLOS_CURDRV
ret
BDOS_closehandle_noFATFS
ld h,b
ld l,0
BDOSSETPGTRDOSFS
jp trdos_fclose_hl
BDOS_closehandle_pipe
;B = file handle
inc b
ret z ;0xff=rnd
ld hl,freepipes-1-PIPEADD80
ld c,b
xor a
ld b,a
add hl,bc
dec (hl)
ret p
inc (hl) ;чтобы терминал не думал, а закрывал оба пайпа дважды
ret
freepipes
ds MAXPIPES
pipeowners
ds MAXPIPES
pipetypes ;пока тут размер терминала в строках, делается из имени пайпа
ds MAXPIPES
BDOS_readwritehandleprepare
;b=handle, hl=number of bytes, de=addr
;out: hl=fil, de=number of bytes, bc=addr(0x8000+)
push hl ;Number of bytes to read
push de ;Buffer address
call BDOS_number_to_fil ;de=fil
ex de,hl ;hl=FIL
pop de ;Buffer address
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер (или уже убрано?)
ld b,d
ld c,e
pop de ;Number of bytes to read
ret
BDOS_readhandle
;B = file handle
;DE = Buffer address
;HL = Number of bytes to read
;out: HL = Number of bytes actually read, A=error
dec hl
ld a,h
inc hl
cp 0x40
jr c,BDOS_readhandlego
push hl
ld hl,BDOS_readhandlego
BDOS_readwritehandle
ld (BDOS_readwritehandle_proc),hl
pop hl
ld (BDOS_readwritehandle_oldaddr),de
BDOS_readwritehandle0
push bc
push hl
push de ;addr
dec hl
ld a,h
inc hl
cp 0x40
jr c,$+5 ;<=0x4000
ld hl,0x4000
push hl ;bytes to process
;call BDOS_readwritehandlego ;hl=processed bytes
BDOS_readwritehandle_proc=$+1
call BDOS_readhandlego
;TODO что делать, если возвратилось hl==0 или a!=0?
;ex af,af' ;error
pop bc ;bytes to process
or a
sbc hl,bc
ld a,h
or l
add hl,bc ;z=all bytes were processed
ld b,h
ld c,l
pop hl ;addr
add hl,bc ;+processed bytes
ex de,hl ;de = new addr
pop hl
or a
sbc hl,bc ;-processed bytes
pop bc
jr z,BDOS_readwritehandleq ;0 bytes remain
jr c,BDOS_readwritehandleq ;less than 0 bytes remain
;jr nc,BDOS_readwritehandle0 ;no less than 0 bytes remain
or a
jr z,BDOS_readwritehandle0 ;all bytes were processed
BDOS_readwritehandleq
;0 bytes remain
;de=end address
ld h,d
ld l,e
BDOS_readwritehandle_oldaddr=$+1
ld bc,0
xor a ;no error
sbc hl,bc ;hl=processed bytes
;ex af,af' ;error
jr BDOS_readhandle_errorfromEOF ;ret
;BDOS_readwritehandlego
;BDOS_readwritehandle_proc=$+1
; jp BDOS_readhandlego
BDOS_readhandlego
;b=handle
bit 7,b
jr nz,BDOS_readhandle_pipe
bit 6,b
jr nz,BDOS_readhandle_noFATFS
call BDOS_readwritehandleprepare
;hl=fil, de=number of bytes, bc=addr(0x8000+)
ld ix,fres
push ix ;fres
push de ;blocksize
ex de,hl;ld de,ffile
F_READ_CURDRV
pop bc
pop bc ;fres
ld hl,(fres) ;hl=total processed bytes
BDOS_readhandle_errorfromEOF
;xor a ;no error
ld a,h
or l
ld a,0
ret nz
dec a
ret
BDOS_readhandle_noFATFS
push bc
BDOSSETPGTRDOSFS
pop bc
jp trdos_fread_b ;hl=total processed bytes, A=error
BDOS_writehandle
;B = file handle
;DE = Buffer address
;HL = Number of bytes to write
;out: HL = Number of bytes actually written, A=error
ld a,h
cp 0x40
jr c,BDOS_writehandlego
push hl
ld hl,BDOS_writehandlego
jr BDOS_readwritehandle
BDOS_writehandlego
;B = file handle
;DE = Buffer address
;HL = Number of bytes to write <= 0x4000
;out: HL = Number of bytes actually written, A=error
bit 7,b
jp nz,BDOS_writehandle_pipe
bit 6,b
jr nz,BDOS_writehandle_noFATFS
call BDOS_readwritehandleprepare
ld ix,fres
push ix ;fres
push de ;blocksize
ex de,hl;ld de,ffile
F_WRITE_CURDRV
pop bc
pop bc ;fres
ld hl,(fres) ;hl=total processed bytes
xor a ;a=0: no error
ret
BDOS_writehandle_noFATFS
push bc
BDOSSETPGTRDOSFS
pop bc
jp trdos_fwrite_b ;hl=total processed bytes, a=0: no error
BDOS_readhandle_pipe
;B = file handle
;DE = Buffer address
;HL = Number of bytes to write <= 0x4000
;out: HL = Number of bytes actually written, A=error
;TODO check EOF (input closed)
push bc
call BDOS_preparedepage
call BDOS_setdepage
pop af ;a=handle
cp 0xff
jr nz,BDOS_readhandle_pipe_nrnd
ld a,r
ld (de),a
ld hl,1
xor a ;no error
ret
BDOS_readhandle_pipe_nrnd
;a = PIPEADD80+pipeindex
ld (BDOS_readhandle_pipe_handle),a
call findpipe_byhandle ;out: hl=pipebuf, a=pipe# ;bc=number of bytes
ld bc,pipeowners
add a,c
ld c,a
jr nc,$+3
inc b
ld a,(iy+app.id)
ld (bc),a ;pipe owner - это адресат (чтобы его будить)
;читаем из текущей головы столько байт, сколько есть, но не больше number of bytes
;пока делаем, что вся очередь лежит в начале (не атомарно)
ld (BDOS_readhandle_pipe_addr),hl
ld a,(hl) ;cur_size
inc hl
push hl ;buf start
ld l,a
ld h,0
call minhl_bc_tobc ;to_user_size=bc<=hl
pop hl ;buf start
;
ex af,af' ;'
ld a,b
or c
jr z,BDOS_readhandle_pipe_empty
ex af,af' ;'
push bc ;to_user_size
ldir ;to user
pop bc ;to_user_size
ex de,hl
ld l,a
xor a
ld h,a
push bc ;to_user_size
;bc=cur_size-to_user_size
sbc hl,bc
ld b,h
ld c,l
ex de,hl
BDOS_readhandle_pipe_addr=$+1
ld de,0
ld a,c
ld (de),a
inc de
jr z,$+4
ldir ;на начало очереди
pop hl ;to_user_size ;возвращаем, сколько реально прочитано
xor a ;no error
ret
BDOS_readhandle_pipe_empty
;проверяем, что нет EOF (т.е. не закрыла пишущая сторона)
ld hl,freepipes-PIPEADD80
BDOS_readhandle_pipe_handle=$+1
ld bc,0 ;PIPEADD80+pipeindex
add hl,bc
ld a,(hl) ;2=both sides open, 1=one side closed
sub 2 ;a=error
ld h,b
ld l,b ;0 ;возвращаем, сколько реально прочитано
ret
findpipe_byhandle
;hl=number of bytes
;out: hl=pipebuf, a=pipe#, bc=oldhl
sub PIPEADD80
ld b,a
inc b
push hl ;number of bytes
push de ;user space
ld de,PIPEDESC_SZ
ld hl,pipebufs-PIPEDESC_SZ
add hl,de
djnz $-1
pop de ;user space
pop bc ;bc=number of bytes
ret
BDOS_writehandle_pipe
;b=handle, hl=number of bytes, de=addr
push bc
call BDOS_preparedepage
call BDOS_setdepage
pop af ;a=handle
cp 0xff
ret z ;rnd - fail
;a = PIPEADD80+pipeindex
ld (BDOS_writehandle_pipe_handle),a
call findpipe_byhandle ;out: hl=pipebuf, a=pipe# ;bc=number of bytes ;keep de
;включить адресату пайпа (он крутится в YIELD) возможность принять сообщение сразу
push bc
push de
ld bc,pipeowners
add a,c
ld c,a
jr nc,$+3
inc b
ld a,(bc)
ld e,a ;pipe owner
call BDOS_findapp ;iy=found app ;keep hl
pop de
pop bc
jp nz,BDOS_fail ;иначе виснет при нажатии кнопки во время закрытия программы ;FIXME почему пайп в какой-то момент без хозяина?
;set factive,(iy+app.flags)
ld a,(sys_timer) ;ok
dec a
ld (iy+app.lasttime),a
;добавляем в текущий хвост столько байт, сколько есть, но чтобы не превысило размер буфера
;пока делаем, что вся очередь лежит в начале (не атомарно)
ld (BDOS_writehandle_pipe_addr),hl
ld a,(hl) ;cur_size
inc hl
push af
add a,l
ld l,a
jr nc,$+3
inc h
pop af
push hl ;tail
ld hl,PIPEBUF_SZ
push bc ;bc=number of bytes
ld c,a
xor a
ld b,a
sbc hl,bc ;оставшееся место в буфере
pop bc ;bc=number of bytes
call minhl_bc_tobc ;from_user_size=bc<=hl
BDOS_writehandle_pipe_addr=$+1
ld hl,0
ld a,(hl) ;cur_size
add a,c ;from_user_size
ld (hl),a ;cur_size
ex de,hl ;hl=user space
pop de ;tail
ld a,b
or c
jr z,BDOS_readhandle_pipe_full
push bc ;from_user_size
ldir ;from user
pop hl ;from_user_size ;возвращаем, сколько реально записано
xor a ;no error
ret
BDOS_readhandle_pipe_full
;проверяем, что не закрыла читающая сторона
ld hl,freepipes-PIPEADD80
BDOS_writehandle_pipe_handle=$+1
ld bc,0 ;PIPEADD80+pipeindex
add hl,bc
ld a,(hl) ;2=both sides open, 1=one side closed
sub 2 ;a=error
ld h,b
ld l,b ;0 ;возвращаем, сколько реально записано
ret
minhl_bc_tobc
or a
sbc hl,bc
add hl,bc
ret nc ;bc<=hl
ld b,h
ld c,l
ret
BDOS_fopen_getname_fil
;out: de=poi to FIL, bc=mfil
push de
call get_name ;->mfil
pop de
call findfreeffile
jr nz,$ ;TODO error
ex de,hl ;de=poi to FIL
LD bc,mfil
jp nz,BDOS_pop2fail ;снимаем адрес возврата и FCB
ret
BDOS_fopen
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;de = pointer to unopened FCB
GETVOLUME
ld (de),a ;volume
cp vol_trdos ;CHECKVOLUMETRDOS
jr c,BDOS_fopen_noFATFS
push de ;FCB
call BDOS_fopen_getname_fil ;de=poi to FIL, bc=mfil
LD HL,FA_READ|FA_WRITE
jr BDOS_fopen_go
BDOS_fopen_noFATFS
;a=drive
push af
BDOSSETPGTRDOSFS
pop af
jp trdos_fopen
BDOS_fcreate
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to unopened FCB
GETVOLUME
ld (de),a ;volume
cp vol_trdos ;CHECKVOLUMETRDOS
jr c,BDOS_fcreate_noFATFS
push de ;FCB
call BDOS_fopen_getname_fil ;de=poi to FIL, bc=mfil
LD HL,FA_READ|FA_WRITE|FA_CREATE_ALWAYS
BDOS_fopen_go
;F_OPEN ffile,mfil,FA_READ|FA_WRITE|FA_CREATE_ALWAYS
;LD de,ffile
push de ;FIL
F_OPEN_CURDRV
pop de ;FIL
pop bc ;FCB
or a
ret nz ;error
;BDOS_fopen_OK
;de=ffile (FIL)
;bc=FCB
;ld iy,(appaddr)
;GETVOLUME
;ld (bc),a ;volume
ld hl,FCB_FFSFCB
add hl,bc
push af
call BDOS_setdepage
pop af
ld (hl),e
inc hl
ld (hl),d
ret
BDOS_fcreate_noFATFS
push af
BDOSSETPGTRDOSFS
pop af
jp trdos_fcreate
getFILfromFCB
;de=FCB (страницы уже включены)
;out: hl=FIL
ld hl,FCB_FFSFCB
add hl,de
ld a,(hl)
inc hl
ld h,(hl)
ld l,a ;hl = poi to FIL
ret
BDOS_fclose
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to opened FCB (для FATFS придётся игнорировать, брать текущий ffile - TODO искать подходящий ffile)
;CHECKVOLUMETRDOS
ld a,(de)
cp vol_trdos
jr c,BDOS_fclose_noFATFS
;F_CLOSE ffile ;сам освобождает FIL
call getFILfromFCB
ex de,hl
F_CLOS_CURDRV
;TODO убрать poi to FIL из FCB?
;or a:jp z,fexit
;ld a,0xff
ret;jp fexit
BDOS_fclose_noFATFS
BDOSSETPGTRDOSFS
jp trdos_fclose
call_ffs_curvol
GETVOLUME
call_ffs ;A=логический раздел, HL=функция
;портит iy! но нельзя двигать стек! в нём параметры!
push hl
push bc
ld hl,fatfsarray ;вычисляем указатель на структуру fatfs
sub vol_trdos
;or a
jr z,.fix_vol_dir
ld bc,FATFS_sz
.calcfatfs
add hl,bc
dec a
jr nz,.calcfatfs
.fix_vol_dir ;устанавливаем текущие fatfs и директорию
BDOSSETPGFATFS
ld (fatfs_org+FFS_DRV.curr_fatfs),hl
ld l,(iy+app.dircluster)
ld h,(iy+app.dircluster+1)
ld (fatfs_org+FFS_DRV.curr_dir0),hl
ld l,(iy+app.dircluster+2)
ld h,(iy+app.dircluster+3)
ld (fatfs_org+FFS_DRV.curr_dir2),hl
call BDOS_setpgstructs
pop bc
ret ;уходим в фатфс
BDOS_mount
;e=logical volume(char A-Z)
;out: a!=0 => not mounted
ld a,e
and 0xdf
sub 'A'
ret c
cp 26
ret nc
sub vol_trdos
jr c,.noFATFS
ld e,a
BDOSSETPGFATFS
call BDOS_setpgstructs
ld hl,fatfsarray ;вычисляем указатель на структуру fatfs
ld a,e
or a
jr z,.fix_ffs
ld bc,FATFS_sz
.calcfatfs
add hl,bc
dec a
jr nz,.calcfatfs
.fix_ffs
ld (fatfs_org+FFS_DRV.curr_fatfs),hl ;l
inc hl
ld a,e
cp 8
jr c,.isHDD
sub 6
ld (hl),a ;номер драйва
xor a
jr .f_mnt
.isHDD
srl e
srl e
ld (hl),e ;номер драйва
and %00000011
.f_mnt
inc hl
ld (hl),a ;номер раздела
F_MNT
ret
.noFATFS
xor a ;xor a ;NC:success, CY:fail
ret;jr rest_exit
BDOS_setsysdrv
SYSDRV_VAL=$+1
ld e,SYSDRV
call BDOS_setdrv
ld de,syspath
jp setpath ;NB! uses strcpy_usp2lib -> BDOS_setdepage without BDOS_preparedepage
BDOS_preparereadwritesectors_FATFS
sub vol_trdos ;получаем физический номер устройства (HDD master, HDD slave, SD...)
push af
BDOSSETPGFATFS
call BDOS_setdepage
pop af
push ix
pop bc
ex de,hl ;bcde=sector number, hl=buffer
;hl=buffer
;a=drive
;bcde=sector
;a'=count
ret
BDOS_preparereadwritesectors_TRDOSFS
push af
BDOSSETPGTRDOSFS
pop af
ld (trdoscurdrive),a
ld a,l
add hl,hl
add hl,hl
add hl,hl
add hl,hl
ex de,hl ;hl=buffer, d=track
and 0x0f
ld e,a ;e=sector
ex af,af' ;'
ld b,a ;count
;hl=buffer
;d=track
;e=sector
;b=count
ret
BDOS_readsectors
;b=drive(0..), de=buffer, ixhl=sector number, a'=count
;передавать логический volume (букву) и пересчитать в номер драйвера (в смещение раздела, наверно, бессмысленно)?
push bc
call BDOS_preparedepage
call BDOS_setdepage
pop af
cp vol_trdos
jr c,BDOS_readsectors_TRDOS
call BDOS_preparereadwritesectors_FATFS
jp devices_read_go_regs
BDOS_readsectors_TRDOS
call BDOS_preparereadwritesectors_TRDOSFS
jp rdsectors. ;out: a=error?
BDOS_writesectors
;b=drive(0..), de=buffer, ixhl=sector number, a'=count
;передавать логический volume (букву) и пересчитать в номер драйвера (в смещение раздела, наверно, бессмысленно)?
push bc
call BDOS_preparedepage
call BDOS_setdepage
pop af
cp vol_trdos
jr c,BDOS_writesectors_TRDOS
call BDOS_preparereadwritesectors_FATFS
jp devices_write_go_regs
BDOS_writesectors_TRDOS
call BDOS_preparereadwritesectors_TRDOSFS
jp wrsectors. ;out: a=error?
BDOS_setdrv
;e=volume
;out: a!=0 => not mounted (TODO), [l=number of volumes]
;мы не должны монтировать, просто должны указать volume, текущий для данной задачи, и сбросить path, текущий для данной задачи
ld a,e
;call BDOS_setvol_rootdir
;call BDOS_opencurdir ;эта операция нужна для определения смонтированности (F_MNT всегда возвращает 0)
;or a
;jr nc,BDOS_setdrvnfail
; ld (iy+app.vol),d
;BDOS_setdrvnfail
;ld l,NVOLUMES ;доступно 8 драйвов???
;xor a ;success
;ret;jr rest_exit
;BDOS_setvol_rootdir
;установлена страница PGFATFS
ld d,(iy+app.vol)
ld (iy+app.vol),a
;BDOS_setrootdir
;не установлена страница PGFATFS
;CY=error (при NC a=0) - TODO убрать?
xor a
ld h,a
ld l,a
call writedircluster_hl
;ld (iy+app.dircluster),a
;ld (iy+app.dircluster+1),a
ld (iy+app.dircluster+2),a
ld (iy+app.dircluster+3),a
CHECKVOLUMETRDOS
push de
;sbc a,a; ld a,0
jr c,BDOS_setrootdir_trdos ;ret c ;NC=no error, A=0
ld bc,0 ; TCHAR *path /* Pointer to the directory path */
call BDOS_opencurdir ;эта операция нужна для определения смонтированности (F_MNT всегда возвращает 0)
BDOS_setrootdir_q
pop de
or a
ret z ;NC=no error, A=0
ld (iy+app.vol),d
scf
ret ;CY=error
BDOS_setrootdir_trdos
push af
BDOSSETPGTRDOSFS
pop af
call iodos_setdrive
;ld a,(eRR2) ;0=OK, 0xff=Abort
jr BDOS_setrootdir_q
BDOS_delete
;DE = Drive/path/file ASCIIZ string
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to ASCIIZ string
call countfiledrive ;a=volume, de=path without drive, c=1: drive in path, CY=TR-DOS
;call eatdrive ;TODO keep and restore curdrv,curdir!!!
jr c,BDOS_delete_nofatfs
;call keepvoldir
; dec c ;was c=1: drive in path
; push de
; call z,BDOS_setvol_rootdir ;drive specified in path
; pop de
F_UNLINK
ret
BDOS_delete_nofatfs
push af ;drive
BDOSSETPGTRDOSFS
pop af
jp trdos_delete
BDOS_rename
;DE = Drive/path/file ASCIIZ string, HL = New filename ASCIIZ string (can contain drive/path! NOT MSXDOS)
ex de,hl
call BDOS_preparedepage ;TODO разные страницы hl,de (т.е. надо копировать отсюда в буфер)
call BDOS_setdepage ;TODO убрать в драйвер
ex de,hl
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
CHECKVOLUMETRDOS
jr c,BDOS_rename_nofatfs
ld b,h
ld c,l
;DE = Drive/path/file ASCIIZ string, BC = New filename ASCIIZ string
F_RENAME
ret
BDOS_rename_nofatfs
push af ;drive
BDOSSETPGTRDOSFS
pop af
jp trdos_rename
countfiledrive
;DE = Drive/path/file ASCIIZ string
;out: a=volume, de=path without drive, c=1: drive in path, CY=TR-DOS
inc de
ld a,(de)
cp ':'
dec de
ld c,0
;push af ;z=drive in path
GETVOLUME
jr nz,BDOS_openhandle_nodriveinpath ;drive not specified in path
ld a,(de)
and 0xdf
sub 'A'
inc de
inc de
;cp a ;z
inc c
BDOS_openhandle_nodriveinpath
;a=volume, de=path without drive, c=1: drive in path
cp vol_trdos
ret
BDOS_mkdir
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to ASCIIZ string
call countfiledrive ;call eatdrive
jp c,BDOS_fail
;DE = Pointer to ASCIIZ string
;call keepvoldir
; dec c ;was c=1: drive in path
; push de
; call z,BDOS_setvol_rootdir ;drive specified in path
; pop de
F_MKDIR
ret
BDOS_chdir
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
;DE = Pointer to ASCIIZ string
setpath
;установлена страница PGFATFS
;DE = Pointer to ASCIIZ string
call countfiledrive ;call eatdrive
jr c,BDOS_chdir_trdos
push af
; dec c ;was c=1: drive in path
; call z,BDOS_setvol_rootdir ;drive specified in path
F_CHDIR
pop hl
or a
ret nz
ld (iy+app.vol),h
ld hl,(fatfs_org+FFS_DRV.curr_dir2)
ld (iy+app.dircluster+2),l
ld (iy+app.dircluster+3),h
;xor a
ld hl,(fatfs_org+FFS_DRV.curr_dir0)
;ld (iy+app.dircluster),l
;ld (iy+app.dircluster+1),h
;ret
writedircluster_hl
ld (iy+app.dircluster),l
ld (iy+app.dircluster+1),h
ret
BDOS_chdir_trdos
ld (iy+app.vol),a
xor a
;ld a,(de) ;путь пустой?
;or a
;jp nz,BDOS_fail ;непустой
ret
if 1==0
strlen
;hl=str
;out: hl=length
xor a
ld b,a
ld c,a ;bc=0 ;чтобы точно найти терминатор
cpir ;найдём обязательно, если длина=0, то bc=-1 и т.д.
ld hl,-1
;or a
sbc hl,bc
ret
endif
;GET WHOLE PATH STRING (5EH)
; Parameters: C = 5EH (_WPATH)
; DE = Pointer to 64 byte (MAXPATH_sz!) buffer
; Results: A = Error
; DE = Filled in with whole path string
; HL = Pointer to start of last item
;This function simply copies an ASCIIZ path string from an internal buffer into the user's buffer. The string represents the whole path and filename, from the root ;directory, of a file or sub-directory located by a previous "find first entry" or "find new entry" function. [MSXDOS: The returned string will not include a drive, or an; ;initial "\" character.] Register HL will point at the first character of the last item on the string, exactly as for the "parse path" function (function 5Bh).
;in NedoOS: DRIVE:/PATH/ !!!
BDOS_getpath
push de ;нельзя после BDOS_preparedepage
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
push de ;DE = Pointer to 64 byte (MAXPATH_sz!) buffer (0x8000+/0xc000+!)
push de ;Pointer to 64 byte (MAXPATH_sz!) buffer (0x8000+/0xc000+!)
GETVOLUME
add a,'A'
ex de,hl
ld (hl),a
inc hl
ld (hl),':'
inc hl
ld (hl),'/'
inc hl
ld (hl),0
cp vol_trdos+'A'
jr c,BDOS_getpath_FATq
ex de,hl
BDOS_getpath_FAT
;DE=TCHAR *path, /* Pointer to the directory path */ буфер
ld bc,MAXPATH_sz;64 ;BC=UINT sz_path /* Size of path */) размер буфера
F_GETCWD_CURDRV
BDOS_getpath_FATq
pop hl ;Pointer to 64 byte (MAXPATH_sz!) buffer (0x8000+/0xc000+!)
call findlastslash. ;NC!!!
ex de,hl ;HL = Pointer to start of last item (0x8000+/0xc000+!)
pop de ;DE = Pointer to 64 byte (MAXPATH_sz!) buffer (0x8000+/0xc000+!)
;or a
sbc hl,de ;hl=расстояние до последнего слэша
pop de ;DE = Pointer to 64 byte (MAXPATH_sz!) buffer
add hl,de ;HL = Pointer to start of last item
ret
;hl = poi to filename in string
findlastslash.
;hl=path string
;out: de = after last slash (or start of path) ;NC!!!
nfopenfnslash.
ld d,h
ld e,l ;de = after last slash
;find last slash
nfopenfnslash0.
ld a,[hl]
inc hl
or a
ret z;jr z,nfopenfnslashq. ;NC!!!
cp '/'
jr nz,nfopenfnslash0.
jr nfopenfnslash.
;PARSE FILENAME (5CH) - MSX-DOS
; Parameters: C = 5CH (_PFILE)
; DE = ASCIIZ string for parsing
; HL = Pointer to 11 byte buffer
; Results: A = Error (always zero)
; DE = Pointer to termination character
; HL = Preserved, buffer filled in
; B = Parse flags (TODO)
;b0 - set if any characters parsed other than drive name
;b1 - set if any directory path specified
;b2 - set if drive name specified
;b3 - set if main filename specified in last item
;b4 - set if filename extension specified in last item
;b5 - set if last item is ambiguous
;b6 - set if last item is "." or ".."
;b7 - set if last item is ".."
BDOS_parse_filename
BDOSSETPGTRDOSFS
;делает из имени с точкой имя без точки (для CP/M)
push hl ;Pointer to 11 byte buffer
push de ;ASCIIZ string for parsing
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
push de ;ASCIIZ string for parsing (0x8000+/0xc000+)
ld hl,BDOS_parse_filename_cpmnamebuf
call dotname_to_cpmname ;de -> hl
ex de,hl ;de=Pointer to termination character (0x8000+/0xc000+)
pop bc ;ASCIIZ string for parsing (0x8000+/0xc000+)
or a
sbc hl,bc ;hl=расстояние до терминатора
pop bc ;ASCIIZ string for parsing
add hl,bc ;Pointer to termination character
pop de ;Pointer to 11 byte buffer
push hl ;Pointer to termination character
push de ;Pointer to 11 byte buffer
call BDOS_preparedepage
call BDOS_setdepage ;TODO убрать в драйвер
ld hl,BDOS_parse_filename_cpmnamebuf
ld bc,11
ldir
pop hl ;HL = Pointer to 11 byte buffer
pop de ;DE = Pointer to termination character
xor a
ret
get_name
;делает из имени без точки имя с точкой (для FATFS и для печати)
;de(FCB)->hl
inc de
ex hl,de
ld de,mfil
get_name_hltode
ld b,7
ld a,' '
get_name1
ldi
cp (hl)
jr z,get_name_skipspaces
djnz get_name1
ldi
jr get_name_findext ;скопировали 8 символов, пробел не нашли
get_name_skipspaces
inc hl
djnz $-1;1b ;пропускаем оставшиеся пробелы
get_name_findext
cp (hl)
jr z,get_name1f ;на месте расширения пробел - не ставим точку
ex hl,de
ld (hl),'.'
inc hl
ex hl,de
ldi
cp (hl)
jr z,get_name1f
ldi
cp (hl)
jr z,get_name1f
ldi
get_name1f
xor a
ld (de),a
ret
findfreeffile
;out: nz=fail, hl=FIL, b=fil number
call BDOS_setpgstructs
ld hl,ffilearray
ld de,FIL_sz
ld b,0
findfreeffile0
inc hl
ld a,(hl) ;FS(HSB)
dec hl
or a
ret z ;OK
add hl,de
inc b
;ld a,b
;cp MAXFILES
;jr nz,findfreeffile0
;or a ;nz
ld a,MAXFILES-1
cp b
jr nc,findfreeffile0
;or a ;nz
ret
movedma_addr
ld iy,(appaddr)
;ld hl,(dma_addr) ;оригинальный, не пересчитанный адрес
call BDOS_getdta
ex de,hl
add hl,bc
ex de,hl
;ld (dma_addr),hl
;ret
BDOS_setdta
ld (iy+app.dta),e
ld (iy+app.dta+1),d
;ret
BDOS_getdta
ld e,(iy+app.dta)
ld d,(iy+app.dta+1)
ret
;получить конфиг железа
BDOS_get_config
ld a,(SYSDRV_VAL)
ld h,a
ifdef KOE
ld l,0x06
else
ld l,atm
endif
ld a,(sys_pgdos)
ld d,a
ld e,pgsys
ifdef SVNREVISION
ld ix,((SVNREVISION+1) >> 16) & 0xffff
ld bc,(SVNREVISION+1) & 0xffff
else
ld ix,0
ld bc,0
endif
;H=system drive, L= 1-Evo 2-ATM2 3-ATM3 6-p2.666
;E=pgsys(system page) D= TR-DOS page
ret
BDOS_getmemports
ld ix,memport0000
ld bc,memport4000
ld de,memport8000
ld hl,memportc000
ret
;*****************НЕДОКУМЕНТИРОВАННЫЕ*********************
;вызов функции DE с картой керналя.
BDOS_reserv_1
di
call BDOS_preparedepage
call BDOS_setdepage
ex de,hl
ld a,pgsys
jp (hl)
;***********************ЗАГЛУШКИ**************************
;копирование строки из\в юзерспейса в\из либу фатфс
strcpy_lib2usp ;DE - dst, BC - src
strcpy_usp2lib
push bc
call BDOS_setdepage
pop bc
strcpy_lib2usp0
ld a,(bc)
ld (de),a
inc de
inc bc
or a
jr nz,strcpy_lib2usp0
;BDOSSETPGFATFS
;jp BDOS_setpgstructs
BDOS_setpgstructs
ld a,pgfatfs2
jr sys_setpgc000
setmainpg_c000
ld a,(iy+app.mainpg)
jr sys_setpgc000
sys_setpgsscr
ld a,(iy+app.screen)
bit 3,a
ld a,pgscr0_0
jr z,$+4
ld a,pgscr1_0
;ld bc,memport8000
;out (c),a
call sys_setpg8000
xor pgscr0_1^pgscr0_0 ;ld a,pgscr0_1
;ld b,memportc000_hi;0xff
;out (c),a
jr sys_setpgc000
setpgs_killable
ld a,pgkillable
ld bc,memport4000
ld (sys_curpg4000),a
out (c),a
;ld b,memport8000_hi;0xbf
;out (c),a
;ld b,memportc000_hi;0xff
;out (c),a
;ret
call sys_setpg8000
sys_setpgc000
ld (sys_curpgc000),a
ld bc,memportc000
out (c),a
ret
;копирование в\из юзерспейса в\из структуру
memcpy_buf2usp ;DE - dst, BC - src, на стеке count
res 7,b ;src=buf
jr memcpy_buf_go
memcpy_usp2buf
res 7,d ;dst=buf
memcpy_buf_go
push bc
ld a,pgfatfs2;=pgstructs
call sys_setpg4000
pop bc
jr memcpy_loop
;копирование в\из юзерспейса в\из либу фатфс
memcpy_lib2usp ;DE - dst, BC - src, на стеке count
memcpy_usp2lib
memcpy_loop
push bc
call BDOS_setdepage
pop hl;bc
;ld h,b
;ld l,c
pop af
pop bc
push bc
push af
ldir
BDOSSETPGFATFS ;4000
jp BDOS_setpgstructs
;по числу драйвов FatFS (для TR-DOS не надо)
fatfsarray=0xc000
;display "fatfsarray=",fatfsarray
;ds 4*FATFS_sz
ffilearray=fatfsarray+(13*FATFS_sz)
display "ffilearray_end=",ffilearray+(MAXFILES*FIL_sz)
;ds MAXFILES*FIL_sz
;dw 0x100 ;признак конца ffilearray
mfil db "12345678.123",0 ;нужно только на время операции, которая принимает имя файла (может быть с путём?)
mfilinfo ds FILINFO_sz ;FILINFO ;нужно только на время findnext
fcb2 ds FCB_sz ;нужно только на время findnext
fres dw 0 ;структура для возврата результата FatFS (число прочитанных/записанных байт)
dw 0 ;для возврата даты
syspath
db "bin",0
;для TASiS: не используются страницы ОЗУ 0x00, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F
;для избежания гибернации: не используются страницы ОЗУ 128K
tsys_pages
ifdef FREEPG0
db 0
else
db 0xff ;pg0 reserved
endif
db 0xff ;pg1 reserved (screen)
ifdef FREEPG2
db 0
else
db 0xff ;pg2 reserved
endif
db 0xff ;pg3 reserved (screen)
;ifdef FREEPG4
;db 0
;else
db 0xff ;pg4 reserved (killable)
;endif
db 0xff ;pg5 reserved (screen)
ifdef FREEPG6
db 0
else
db 0xff ;pg6 reserved
endif
db 0xff ;pg7 reserved (screen)
;;;;;;;;;;
if TOPDOWNMEM
db 0,0,0,0
else
db 0xff,0xff,0xff,0xff ;системные страницы
endif
db 0,0,0,0 ;0x08..0x0f
db 0,0,0,0,0,0,0,0 ;0x10..0x17
db 0,0,0 ;0x18..0x1a
ifdef ATMRESIDENT
db 0xff,0xff,0xff,0xff,0xff ;0x1b..0x1f for resident
else
db 0,0,0,0,0 ;0x1b..0x1f
endif
dup sys_npages-32-4
_=$-tsys_pages
_wrongpg=0
ifdef KEEPPG38
if (_ == 0x38)
_wrongpg=0xff
endif
endif
ifdef KOE
if (_ >= (64+8)) && (_ <= (64+12)) ;TODO ramdisk тоже?
_wrongpg=0xff
endif
endif
db _wrongpg ;0 ;0=empty, or else process number
edup
if TOPDOWNMEM
db 0xff,0xff,0xff,0xff ;системные страницы
else
db 0,0,0,0
endif
pipebufs
ds PIPEDESC_SZ*MAXPIPES