?login_element?

Subversion Repositories NedoOS

Rev

Rev 1323 | Rev 1665 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download

  1. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; KERNEL (system side) ;;;;;;;;;;;;;;;;;;;;;;;        
  2. ;при вызове 0x0005 в системе включены страницы: pgsystem, pgkillable, pgkillable, pgkillable (на случай порчи стеком)
  3.  
  4. MAXAPPS=16
  5. bdosstack_sz=0;150 ;80 мало для загрузки файла, 110 мало для fopen (даже с INTSTACK2), 140 мало для чтения каталога (даже с INTSTACK2) ;0=отключить мьютекс BDOS
  6.  
  7. QUITSTACK=0x4000 ;<=0x4000
  8.  
  9.         macro BDOSSETPGSSCR
  10.         call sys_setpgsscr
  11.         endm
  12.  
  13.         macro BDOSSETPGFATFS
  14.         call BDOS_setpgfatfs
  15.         endm
  16.  
  17.         macro BDOSSETPGTRDOSFS
  18.         call BDOS_setpgtrdosfs
  19.         endm
  20.  
  21.         macro BDOSSETPGW5300
  22.         call BDOS_setpgtrdosfs
  23.         endm
  24.  
  25.  
  26. fatfs.tabl=0x4000
  27.         include "fatfs_h.asm"
  28.        
  29. wassyscode
  30.         disp 0x0000
  31. syscode
  32. sys_time_date
  33.         ds 4
  34.  
  35.         ds 0x0000+4-$
  36.         jp sys_quit
  37.  
  38. sys_reter
  39.         ret
  40.  
  41. callbdos_mutex
  42.         db 0xc0
  43.         ds 0x0005+4-$
  44.         jp callbdos
  45.  
  46.         ds 0x0009+4-$
  47.         jp sys_getchar
  48.  
  49. sys_farcall
  50.         jp endsys_result_a
  51.  
  52.         ds 0x0015-2-$
  53. endsys_result_aq
  54.         out (0xfd),a
  55.         display "kernel_result_a=",$
  56.         ds 0x0010+5-$
  57.         jp fastprchar
  58.  
  59.         ds 0x0018-$
  60. ;setpg4000=0x0018
  61.         ld bc,memport4000
  62.         out (c),a
  63.         ret
  64.  
  65.         ds 0x0020-$
  66. ;setpg8000=0x0020
  67.         ld bc,memport8000
  68.         out (c),a
  69.         ret
  70.  
  71.         ds 0x0028-$
  72. ;setpgc000=0x0028
  73.         ld bc,memportc000
  74.         out (c),a
  75.         ret
  76.  
  77. sys_timer
  78.         ds 4
  79.  
  80.         ds 0x0030+4-$
  81.         jp sys_farcall
  82.  
  83.         ds 0x0038-$
  84.         jp sys_sysint
  85.  
  86.         ds 0x0038+7-$ -3
  87. sys_intq
  88. ;bc=memport0000
  89. ;d=pgmain
  90. ;a=screenpg
  91.        di ;на время до включения нужной pg0000, чтобы не запороть чужой стек
  92.         out (0xfd),a ;дальше попадаем в init_resident
  93. ;выход в конец юзерского обработчика прерываний
  94.  
  95. ;вход из начала юзерского обработчика прерываний
  96.         ;ds 0x0038+14-$ -4
  97.         ;TODO захватить мьютекс (прерывание внутри прерывания должно попасть в простой обработчик без шедулера)
  98.         jp sys_intgo ;нужно, чтобы можно было ставить точку останова на 0x0100
  99.  
  100. fastprchar
  101. ;e=char
  102.         if bdosstack_sz==0
  103.         ld (sys_prchar_sp),sp
  104.         ld sp,BDOSSTACK ;до этого момента прерывание может запороть любое место памяти (user sp >=0x3b00)
  105.         else
  106.         exx
  107.         ld hl,0
  108.         add hl,sp
  109.         ld iy,(appaddr)
  110.         ;ld (iy+app.callbdos_sp),l
  111.         ;ld (iy+app.callbdos_sp+1),h
  112.         ld bc,app.bdosstack+bdosstack_sz
  113.         add iy,bc
  114.         ld sp,iy ;до этого момента прерывание может запороть любое место памяти (user sp >=0x3b00)
  115.         exx
  116.         endif
  117.        
  118.         ld iy,(appaddr)
  119.         call BDOS_prchar ;портит только 0xc000+, но сама восстанавливает pgkillable
  120.         if bdosstack_sz==0
  121. sys_prchar_sp=$+1
  122.         ld sp,0
  123.         else
  124.         exx
  125.         ;ld iy,(appaddr)
  126.         ;ld l,(iy+app.callbdos_sp)
  127.         ;ld h,(iy+app.callbdos_sp+1)
  128.         ld sp,hl
  129.         exx
  130.         endif
  131.         jp endsys_result_a
  132.  
  133.         ds 0x0100-$ ;stack for CP/M programs
  134.        
  135. safestack_sz=16 +2 ;на запарывание прерыванием
  136.         STRUCT app
  137. flags           BYTE ;флаги (всегда в начале структуры)
  138. ;priority        BYTE ;TODO приоритет (0=конец списка)
  139. id              BYTE ;номер задачи (0=свободно)
  140. parentid        BYTE ;номер родительской задачи
  141. mainpg          BYTE ;главная страница задачи (там userkernel)
  142. ;callbdos_sp     WORD ;сюда сохраняется стек при вызове BDOS
  143. ;curmsg          WORD ;TODO адрес текущего сообщения этой задаче
  144. ;endmsg          WORD ;TODO адрес конца очереди сообщений этой задаче
  145. ;sp              WORD ;текущий адрес стека (лежит в mainpg:intsp)
  146. ;next            WORD ;TODO указатель на следущую задачу (следующая за выполняемой внутри того же приоритета)
  147. stdin           BYTE
  148. stdout          BYTE
  149. stderr          BYTE ;TODO не нужен?
  150. lasttime        BYTE
  151. border          BYTE ;текущий цвет бордера 0..15
  152. screen          BYTE ;текущий номер экрана ;fd_user + 8*screen
  153. gfxmode         BYTE ;текущий видеорежим ;значение для 0xbd77
  154. gfxkeep         BYTE ;b7 = keep gfx pages
  155. scr0low         BYTE ;pages
  156. scr0high        BYTE ;pages
  157. scr1low         BYTE ;pages
  158. scr1high        BYTE ;pages
  159. childresult     WORD ;filled by closed child
  160. textcuraddr     WORD ;адрес курсора на экране
  161. curcolor        BYTE ;текущий атрибут при печати
  162. dta             WORD ;data transfer address
  163. vol             BYTE ;текущий драйв (volume)
  164. dircluster      DWORD ;текущая директория
  165. dir             BLOCK DIR_sz ;временный буфер для чтения каталога
  166. bdosstack       BLOCK bdosstack_sz ;стек при вызове BDOS
  167. pal             BLOCK 32
  168. ;safestack       BLOCK safestack_sz ;de,hl,af',af,ix,hl',de',bc',iy
  169.         ENDS
  170.  
  171.         display "apps start=",/h,$
  172. safestack
  173.         ds safestack_sz
  174. app1    app
  175. app_sz=$-safestack
  176.  
  177.         ds (MAXAPPS-1)*app_sz
  178.         display "MAXAPPS=",/h,MAXAPPS
  179.  
  180. app_afterlast=$+safestack_sz
  181. app_last=app_afterlast-app_sz
  182.         display "app1=",/h,app1
  183.         display "app_last=",/h,app_last
  184.  
  185. sys_intgo
  186.         ex de,hl
  187.         ld hl,0
  188.         add hl,sp
  189. appaddr=$+1
  190.         ld sp,app1 ;safestack_end
  191.         push hl ;"sp"
  192.         push de ;"hl"
  193.         push iy
  194.         exx
  195.         push bc
  196.         push de
  197.         push hl
  198.         push ix
  199.         ex af,af' ;'
  200.         push af
  201.  
  202.         ld bc,memport4000
  203.         ld a,pgtrdosfs;pagexor-5
  204.         out (c),a ;там INTSTACK
  205.         ld sp,INTSTACK2
  206.         call setgfxpal_focus
  207.         call on_int ;тикает таймер
  208.         call schedule ;out: iy=app
  209.         ld a,pgkillable
  210.         ld bc,memport4000
  211.         ld (sys_curpg4000),a ;не надо? (если di)
  212.         out (c),a
  213.  
  214. sys_int_popregs ;только для выхода из yield
  215. ;iy=app
  216.         ld de,-(safestack_sz-2) ;2 на запарывание прерыванием
  217.         add iy,de
  218.         ld sp,iy ;di!!!
  219.  
  220.         pop af
  221.         ex af,af' ;'
  222.         pop ix
  223.         pop hl
  224.         pop de
  225.         pop bc
  226.         exx
  227.         ld d,(iy+app.mainpg+safestack_sz-2) ;2 на запарывание прерыванием
  228.         ld iy,(focusappaddr)
  229.         ld a,(iy+app.screen)
  230.         pop iy
  231.         pop bc ;"hl"
  232.         pop hl ;"sp"
  233.         ld sp,hl
  234.         ld h,b
  235.         ld l,c
  236.         ld bc,memport0000
  237.         ;TODO освободить мьютекс, можно включить прерывания
  238.         jp sys_intq ;out (0xfd),a ;дальше попадаем в init_resident
  239.  
  240. schedule
  241. ;find next app, set iy
  242. ;out: iy=app, ix=(focusappaddr)
  243.         ld iy,(appaddr)
  244.         ld bc,-app_last;app_afterlast
  245.         ld de,app_last+app_sz;app_sz
  246.          ld a,(sys_timer) ;ok
  247.         ld l,MAXAPPS
  248. findnextapp0
  249.         add iy,bc
  250.         jr nc,$+6
  251.         ld iy,app1 -(app_last+app_sz)
  252.         add iy,de
  253.          cp (iy+app.lasttime)
  254.          jr z,findnextappskip
  255.          ;bit fyield,(iy)
  256.          ;jr nz,findnextappq
  257.         bit factive,(iy)
  258.         jr nz,findnextappq
  259. findnextappskip
  260.         dec l
  261.         jr nz,findnextapp0
  262. ;no active apps (или каждая в данном фрейме уже вызывалась)
  263.         ld iy,app1 ;idle
  264. findnextappq
  265. ;TODO при fwaitfocus пропускать app, если у него нет фокуса
  266. ;или пусть term (хозяин пайпа) получает factive только после появления чего-то в пайпе или при нажатии клавиши (когда он в фокусе)
  267.         ld (appaddr),iy
  268.          ld (iy+app.lasttime),a
  269.           ;ld iy,(appaddr)
  270.           ld a,(iy+app.mainpg)
  271.           ld bc,memport4000
  272.           ld (sys_curpg4000),a ;нужно (могут вызвать из yield - в любой момент)
  273.           out (c),a
  274.           ld ix,(focusappaddr)
  275.           ld a,(ix+app.screen)
  276.           or fd_system
  277.           ;ld (user_fdvalue1+0x4000),a ;for QUIT, мешает делать многозадачность с 0xffff: jp nn
  278.           ld (user_fdvalue2+0x4000),a
  279.           ld (user_fdvalue3+0x4000),a
  280.           ld (user_fdvalue4+0x4000),a
  281.           ;ld (user_fdvalue5+0x4000),a ;not supported yet
  282.           ld (user_fdvalue6+0x4000),a
  283.           ld a,pgtrdosfs
  284.           ;ld (sys_curpg4000),a ;нужно (могут вызвать из yield - в любой момент - но там не важно, там стек в нулях, а потом само ввключает pgkillable)
  285.           out (c),a ;там INTSTACK
  286.         ;ld iy,(appaddr)
  287.         ret
  288.  
  289. setgfxpal_focus
  290. ;если в yield не поставить палитру второй задаче, то она никогда не поставится, если первая задача в цикле делает yield
  291. ;потому что все прерывания будут ставить первую задачу
  292. ;если же палитру ставить в самом yield, то могут быть проблемы с выставлением палитры, если yield вызывать в случайных местах или если все задачи неактивны
  293. ;поэтому обработчик прерываний должен выставлять палитру и видеорежим задачи, которая в фокусе, независимо от её активности
  294. ;менять палитру только после смены фокуса или записи палитры
  295.                 display "setgfxpal_focus ",setgfxpal_focus
  296. palettechanged=$
  297.         or a
  298.         jp c,focusappborder
  299.         ld a,55 ;"scf"
  300.         ld (palettechanged),a
  301.        ifndef NOPAL
  302.         ld hl,(focusappaddr)
  303.         ld bc,app.pal+31 ;-app.gfxmode
  304.         add hl,bc
  305.         if 0;atm==1
  306.                 ld bc,0x07ff
  307.                 dup 8
  308.                 ld a,b
  309.                 out (0xf6),a
  310.                 outd
  311.                 dec hl
  312.                 edup
  313.                 ld b,0x07
  314.                 dup 7
  315.                 ld a,b
  316.                 out (0xfe),a
  317.                 outd
  318.                 dec hl
  319.                 edup
  320.                 ld a,b
  321.                 out (0xfe),a
  322.                 outd
  323.         else
  324.  
  325.         ld c,0xff
  326.         ld a,7
  327.         dup 8
  328.         OUT (0xF6),A
  329.         ld d,(hl)
  330.         dec hl
  331.         ld b,(hl) ;DDp palette low bits
  332.         OUT (c),d;(0xFF),A
  333.         dec hl
  334.         dec a
  335.         edup
  336.         ld a,7
  337.         dup 7
  338.         OUT (0xFE),A
  339.         ld d,(hl)
  340.         dec hl
  341.         ld b,(hl) ;DDp palette low bits
  342.         OUT (c),d;(0xFF),A
  343.         dec hl
  344.         dec a
  345.         edup
  346.         OUT (0xFE),A ;0
  347.         ld d,(hl)
  348.         dec hl
  349.         ld b,(hl) ;DDp palette low bits
  350.         OUT (c),d;(0xFF),A
  351.         endif
  352.        endif
  353. focusappborder
  354.          ld ix,(focusappaddr)
  355.        ifndef NOPAL
  356.          ld a,(ix+app.border)
  357.          cp 8
  358.          res 3,a ;tapeout sound
  359.          out (0xfe),a
  360.          ret c
  361.          out (0xf6),a
  362.        endif
  363.         ret
  364.  
  365. sys_sysint
  366. ;TODO schedule (для RTOS), но тогда надо реентерабельность всех процедур BDOS (даже без этого шедулинга они всё равно не должны иметь состояния!)
  367. ;как шедулить, когда мы в kernelspace???
  368. ;TODO проверка критической секции (в обычном прерывании не нужно)
  369.         ex de,hl
  370.         ex (sp),hl ;восстановили стек из de
  371.         ld (sys_sysint_jp),hl
  372.         ld (sys_sysint_sp),sp
  373.         ld sp,INTSTACK1
  374.         push af
  375.         push bc
  376.         push de ;"hl"
  377.         ;push hl
  378.         exx
  379.         ex af,af' ;'
  380.         push af
  381.         push bc
  382.         push de
  383.         push hl
  384.         push ix
  385.         push iy
  386.         ld sp,INTSTACK2
  387.  
  388.         ld bc,memport4000
  389.         ld a,pgtrdosfs;pagexor-5 ;там INTSTACK
  390.         out (c),a
  391.  
  392.         call setgfxpal_focus
  393.  
  394.         call on_int
  395. sys_curpg4000=$+1
  396.         ld a,pgkillable
  397.         ld bc,memport4000
  398.         out (c),a
  399.  
  400.         ld sp,INTSTACK1-18
  401.         pop iy
  402.         pop ix
  403.         pop hl
  404.         pop de
  405.         pop bc
  406.         pop af
  407.         ex af,af' ;'
  408.         exx
  409.         pop hl ;"hl"
  410.         ;pop de
  411.         pop bc
  412.         pop af
  413. sys_sysint_sp=$+1
  414.         ld sp,0
  415.         pop de
  416.         ei
  417.         ;ret
  418. sys_sysint_jp=$+1
  419.         jp 0
  420.        
  421. on_int
  422. ;в 0x4000 сейчас pg5, там стек
  423. focusappaddr=$+1
  424.         ld hl,app1
  425.         ld bc,app.gfxmode
  426.         add hl,bc
  427.         ld e,(hl)
  428. ;sys_curgfxmode=$+1
  429.         ;ld e,%10101000 ;320x200 mode
  430.                 if atm==1
  431.                         ld bc,0xfadf ;buttons
  432.                         in a,(c)
  433.                         ld (sys_mousebuttons),a
  434.                         inc b ;ld bc,0xfbdf ;x
  435.                         in l,(c)
  436.                         ld b,0xff ;y
  437.                         in h,(c)
  438.                          ld bc,0xff77   ;shadow ports and palette off
  439.                          out (c),e
  440.                         in a,(0x1f)
  441.                         ld (sys_kempstonbuttons),a
  442.                          ld bc,0x01bf
  443.                          out (c),b
  444.                          ld bc,0xbd77   ;shadow ports and palette remain on
  445.                          out (c),e
  446.                          ld a,32 ;xor a ;D5=444 palette
  447.                          out (0xbf),a
  448.                 else
  449.                         push de ;e=gfxmode
  450.                         ifdef NOMOUSE
  451.                         ld hl,0
  452.                         ld de,0x0f00
  453.                         else
  454.                         call readmouse ;resident >=0x4000
  455.                         endif
  456.                         ld a,d
  457.                         ld (sys_mousebuttons),a
  458.                         ld a,e
  459.                         ld (sys_kempstonbuttons),a
  460.                         pop de ;e=gfxmode
  461.                 endif
  462.         ld (sys_mousecoords),hl
  463.                 if atm != 1
  464.                         ld a,(sys_timer) ;ok
  465.                         and 7
  466.                         jr nz,on_int_noreadtime
  467.                         ifdef NOCMOS
  468.                         else
  469.                         call readtime ;in: e=gfxmode, out: hl=date, de=time
  470.                         ld (sys_time_date),de
  471.                         ld (sys_time_date+2),hl
  472.                         endif
  473. on_int_noreadtime
  474.                 endif
  475.         ld hl,sys_timer
  476.         inc (hl)
  477.         inc hl
  478.         jr nz,on_int_timerq
  479.         inc (hl)
  480.         inc hl
  481.         jr nz,on_int_timerq
  482.         inc (hl)
  483.         inc hl
  484.         jr nz,on_int_timerq
  485.         inc (hl)
  486. on_int_timerq
  487.        
  488.                 if PS2KBD==0
  489.                         ld a,pgtrdosfs
  490.                         ld bc,memport4000
  491.                         out (c),a ;don't keep in sys_curpg4000!
  492.                         call KEYSCAN
  493.                 else
  494. KEYSCAN
  495. .rep_wait=$+1
  496.                         ld a,0
  497.                         dec a
  498.                         jp m,.end_keyscan
  499.                         ld (.rep_wait),a
  500. .end_keyscan                   
  501.                 endif
  502. ;TODO при наличии клавиши или события мышки поставить factive для задачи в фокусе
  503. ;пока что просто ставим factive для задачи в фокусе, если у неё есть fgfx (т.е. это не idle) - этого достаточно для ускорения игр
  504.         ld iy,(focusappaddr)
  505.         bit fgfx,(iy+app.flags)
  506.         jr z,keyscan_nosetactive
  507.         set factive,(iy+app.flags)
  508. keyscan_nosetactive
  509.  
  510.         ;call PEEKKEY ;ld a,(curkey)
  511.         ;cp ssEnter
  512.        
  513.         ld a,0x7f
  514.         in a,(0xfe)
  515.         rra
  516.         ld c,a ;c0=ss
  517.         ld a,0xbf
  518.         in a,(0xfe)
  519.         or c
  520.         cpl
  521.         ld c,a
  522.         cpl
  523.         ;a0=c0=0: ssEnter pressed
  524. on_int_oldssEnter=$+1
  525.         or 0 ;=0: ssEnter was released
  526.         rra
  527.         ld a,c
  528.         ld (on_int_oldssEnter),a
  529.         jr c,sys_int_noselectapp
  530.          call KEY_PUTREDRAW
  531.  
  532.         if 1==1
  533.         ld iy,(focusappaddr)
  534.         call disablescrpgs_setc000
  535.         ld bc,-app_last;app_afterlast
  536.         ld de,app_last+app_sz;app_sz
  537.         ld l,MAXAPPS
  538. findnextgfxapp0
  539.         add iy,bc
  540.         jr nc,$+6
  541.         ld iy,app1 -(app_last+app_sz)
  542.         add iy,de
  543.         ld a,(iy+app.flags)
  544.         bit fgfx,a
  545.         jr z,findnextgfxappskip
  546.          bit fwaiting,a
  547.          jr z,findnextgfxappq
  548. findnextgfxappskip
  549.         dec l
  550.         jr nz,findnextgfxapp0
  551. ;no active apps (или каждая в данном фрейме уже вызывалась)
  552.         ld iy,app1 ;idle
  553. findnextgfxappq
  554.         ld (focusappaddr),iy
  555.         call setpalettechanged
  556.  
  557.         else
  558.        
  559.         ld hl,(focusappaddr)
  560.         ;отключить страницы экрана этой задаче и выключить их в памяти задачи
  561.         push hl
  562.         pop iy
  563.         call disablescrpgs_setc000
  564.         ld bc,-app_last;app_afterlast
  565.         ld de,app_last+app_sz;app_sz
  566.         ld a,MAXAPPS
  567. findnextgfxapp0
  568.         ;add hl,de
  569.         ;sbc hl,bc
  570.         ;add hl,bc
  571.         ;jr nz,$+5
  572.         ;ld hl,app1
  573.         add hl,bc
  574.         jr nc,$+5 ;hl < app_last
  575.         ld hl,app1 -(app_last+app_sz)
  576.         add hl,de
  577.         bit fgfx,(hl)
  578.         jr z,findnextgfxappskip
  579.          bit fwaiting,(hl)
  580.          jr z,findnextgfxappq
  581. findnextgfxappskip
  582.         dec a
  583.         jr nz,findnextgfxapp0
  584.         ld hl,app1
  585. findnextgfxappq
  586.         ld (focusappaddr),hl
  587.         call setpalettechanged
  588.         ;включить страницы экрана этой задаче
  589.         ;push iy
  590.         push hl
  591.         pop iy
  592.         endif
  593.        
  594.         call enablescreeninapp_setc000
  595.        
  596.         ;pop iy
  597.        
  598. sys_int_noselectapp
  599. muzpg=$+1
  600.         ld a,pgkillable
  601.         ld bc,memport4000
  602.         out (c),a
  603. muzpg8000=$+1
  604.          ld a,pgkillable
  605.          ld b,memport8000_hi
  606.          out (c),a
  607. muzpgc000=$+1
  608.          ld a,pgkillable
  609.          ld b,memportc000_hi
  610.          out (c),a
  611.  
  612.         ;jr $
  613.         ld sp,INTMUZSTACK
  614.  
  615.          ld e,pgsys
  616.         ld ix,(focusappaddr)
  617.         ld a,(ix+app.gfxmode)
  618. muzcall=$+1
  619.         call sys_reter;pt3player.PLAY ;TODO call drivers
  620.        
  621.         ld sp,INTSTACK2-2
  622.  
  623.         ld ix,(focusappaddr)
  624.         ld a,(ix+app.gfxmode)
  625.         ld bc,0xbd77
  626.         out (c),a ;set gfx mode
  627.        
  628.         ld a,pgtrdosfs;pagexor-5
  629.         ld bc,memport4000
  630.         out (c),a ;там INTSTACK
  631. sys_curpg8000=$+1
  632.          ld a,pgkillable
  633.          ld b,memport8000_hi
  634.          out (c),a
  635. sys_curpgc000=$+1
  636.          ld a,pgkillable
  637.          ld b,memportc000_hi
  638.          out (c),a
  639.         ret
  640.  
  641. copypage_a_to_e
  642.         call sys_setpg8000
  643.         ld a,e
  644.         call sys_setpgc000
  645.         ld hl,0x8000
  646.         ld de,0xc000
  647.         ld bc,0x4000
  648.         ldir
  649.         ret
  650.  
  651. disablescrpgs_setc000
  652.         bit 7,(iy+app.gfxkeep)
  653.         jr z,disablescrpgs_nokeep
  654.         ld a,pgscr0_0
  655.         ld e,(iy+app.scr0low)
  656.         call copypage_a_to_e
  657.         ld a,pgscr0_1
  658.         ld e,(iy+app.scr0high)
  659.         call copypage_a_to_e
  660.         ld a,pgscr1_0
  661.         ld e,(iy+app.scr1low)
  662.         call copypage_a_to_e
  663.         ld a,pgscr1_1
  664.         ld e,(iy+app.scr1high)
  665.         call copypage_a_to_e
  666.         call setmainpg_c000
  667.         if 1==0
  668.         ds 6*4
  669.         else
  670.        display "===",$
  671.         ld a,(iy+app.scr0low)
  672.         ld (0xc000+user_scr0_low),a
  673.         ld a,(iy+app.scr0high)
  674.         ld (0xc000+user_scr0_high),a
  675.         ld a,(iy+app.scr1low)
  676.         ld (0xc000+user_scr1_low),a
  677.         ld a,(iy+app.scr1high)
  678.         ld (0xc000+user_scr1_high),a
  679.         endif
  680.         jr disablescrpgs_keepok
  681. disablescrpgs_nokeep
  682.         call setmainpg_c000
  683.         call disablescreeninapp ;set user_scr0_low etc to pgkillable
  684. disablescrpgs_keepok
  685.         ld de,curpg16k+0xc000
  686.         call disablescrpg
  687.         ld  e,0xff&(curpg32klow+0xc000)
  688.         call disablescrpg
  689.         ld  e,0xff&(curpg32khigh+0xc000)
  690.         ;call disablescrpg
  691. disablescrpg
  692. ;de=page keeping addr
  693.         ld a,(de)
  694.         ;or 7&(pgscr0_0|pgscr0_1|pgscr1_0|pgscr1_1)
  695.         ;cp pgscr0_0
  696.         ;ret nz;jr z,disablescrpg_ok
  697. ;disablescrpg_ok
  698.         ;ld a,pgkillable
  699.         ld c,(iy+app.scr0low)
  700.         cp pgscr0_0
  701.         jr z,disablescrpg_ok
  702.         ld c,(iy+app.scr0high)
  703.         cp pgscr0_1
  704.         jr z,disablescrpg_ok
  705.         ld c,(iy+app.scr1low)
  706.         cp pgscr1_0
  707.         jr z,disablescrpg_ok
  708.         ld c,(iy+app.scr1high)
  709.         cp pgscr1_1
  710.         ret nz;jr z,disablescrpg_ok
  711. disablescrpg_ok
  712.         ld a,c
  713.         ld (de),a
  714.         ret
  715. enablescrpg
  716. ;de=page keeping addr
  717.         ld a,(de)
  718.         cp (iy+app.scr0low)
  719.         ld c,pgscr0_0
  720.         jr z,disablescrpg_ok
  721.         cp (iy+app.scr0high)
  722.         ld c,pgscr0_1
  723.         jr z,disablescrpg_ok
  724.         cp (iy+app.scr1low)
  725.         ld c,pgscr1_0
  726.         jr z,disablescrpg_ok
  727.         cp (iy+app.scr1high)
  728.         ld c,pgscr1_1
  729.         ret nz;jr z,enablescrpg_ok
  730. enablescrpg_ok
  731.         ld a,c
  732.         ld (de),a
  733.         ret
  734.  
  735. sys_getchar
  736. ;out:
  737. ;de=mouse yx, l=buttons, A=key, H=high bits of key, bc=keynolang, lx=joystick 0bP2JFUDLR, nz=no focus (mouse position=0, ignore it!)
  738.         ;call checkfocus_getkbdmouse
  739. ;checkfocus_getkbdmouse
  740. ;out: nz=fail
  741.         ld de,(focusappaddr)
  742.         ld hl,(appaddr)
  743.         xor a
  744.         sbc hl,de
  745.         jr nz,sys_getchar_fail ;nz
  746. ;sys_oldmousecoords=$+1
  747. ;        ld de,0
  748. ;        ld (sys_oldmousecoords),hl
  749. ;        ld a,l
  750. ;        sub e ;a=dx
  751. ;        ld e,a ;e=dx
  752. ;        ld a,d
  753. ;        sub h ;a=dy
  754. ;        ld d,a ;d=dy
  755.                 if PS2KBD==1
  756.                         display "ps2_sp ",$
  757.                         ld (ps2_sp),sp
  758.                         ld sp,BDOSSTACK ;это может затереть стек возврата! поэтому возвращаемся через jp
  759.                         call BDOS_setpgtrdosfs
  760.                         call GETKEY ;A=key, H=high bits of key, BC=keynolang
  761.                         ld e,a
  762.                         push bc ;ld (ps2_bc),bc
  763.                         ld a,pgkillable
  764.                         ld bc,memport4000
  765.                         ld (sys_curpg4000),a
  766.                         out (c),a
  767.                         pop bc
  768. ps2_sp=$+1
  769.                         ld sp,0
  770. ;ps2_bc=$+1
  771. ;                       ld bc,0
  772.                         ld a,e
  773.                 else
  774.                         call GETKEY ;A=key, H=high bits of key, BC=keynolang
  775.                 endif
  776.         cp a ;z
  777. sys_mousecoords=$+1
  778.         ld de,0;hl,0
  779. sys_mousebuttons=$+1
  780.         ld l,0xff
  781. sys_kempstonbuttons=$+2
  782.         ld lx,0
  783.         ;ret ;z
  784.         ;jp endsys_result_a
  785. endsys_result_a
  786.          ld iy,(focusappaddr)
  787.         ex af,af' ;'
  788.         ld a,(iy+app.screen)
  789.         ;ld iy,(appaddr)
  790.         jp endsys_result_aq
  791.  
  792. ;TODO брать номер экрана у задачи с фокусом и при шедулинге ставить этот номер в userkernel новой задачи
  793.        
  794. sys_getchar_fail
  795. ;a=0, nz
  796.         ;ld a,NOKEY ;no key
  797.          ;ld h,a
  798.          ;ld b,a
  799.          ld c,a ;no keynolang
  800.         ld d,a;0
  801.         ld e,a;0 ;no mouse movement
  802.          ld lx,a ;no joystick buttons
  803.         ld l,0xff ;no buttons
  804.         jr endsys_result_a ;ret ;nz ;jp endsys_result_a
  805.  
  806. callbdos
  807. ;при вызове bdos надо включить:
  808. ;0x0000 - syscode (уже включено)
  809. ;[0x4000 - pgfatfs или bdospg2]
  810. ;защита от одновременного доступа двум задачам
  811. ;занято a,bc,de,hl
  812. ;свободно iy
  813.         if bdosstack_sz==0
  814.  
  815.         ld (callbdos_sp),sp
  816.         ld sp,BDOSSTACK ;до этого момента прерывание может запороть любое место памяти (user sp >=0x3b00) ;это может затереть стек возврата! поэтому возвращаемся через jp
  817.  
  818.         else
  819.        
  820.         exx
  821. callbdos_lock        
  822.         ld hl,callbdos_mutex ;изначально 0xc0
  823.         sla (hl)
  824.         jr z,callbdos_lock ;был занят
  825.        
  826.         ld hl,0
  827.         add hl,sp
  828.         ld iy,(appaddr)
  829.         ;ld (iy+app.callbdos_sp),l
  830.         ;ld (iy+app.callbdos_sp+1),h
  831.         ld bc,app.bdosstack+bdosstack_sz
  832.         add iy,bc
  833.         ld sp,iy ;до этого момента прерывание может запороть любое место памяти (user sp >=0x3b00)
  834.         push hl
  835.         exx
  836.        
  837.         endif
  838.        
  839.             ;ld iy,(focusappaddr)
  840.             ;ld a,(iy+app.screen)
  841.             ;xor 0x10 ;fd_user^fd_system
  842.             ;out (0xfd),a
  843.         ld iy,(appaddr)
  844.        if 1
  845.         ;push hl
  846.         ;ld l,c
  847.         ;ld h,tbdoscmds/256
  848.         ;ld a,(hl)
  849.         ;inc h
  850.         ;ld h,(hl)
  851.         ;ld l,a
  852.         ;ex (sp),hl
  853.         ;ret ;73t+call ;TODO jp (hl)..pop hl..jp NN ;58t, no call
  854.         push hl
  855.         ld l,c
  856.         ld h,tbdoscmds/256
  857.         ld a,(hl)
  858.         inc h
  859.         ld h,(hl)
  860.         ld l,a
  861.         ld ($+3+1+1),hl
  862.         pop hl ;70t+call
  863.         call 0
  864.        else
  865.         call BDOShandler
  866.        endif
  867.          push af
  868.          push bc
  869.          call setpgs_killable
  870.         if bdosstack_sz !=0
  871.         ld a,0xc0
  872.         ld (callbdos_mutex),a ;то же самое делают те функции BDOS, которые не собираются возвращаться
  873.         endif
  874.          pop bc
  875.          pop af
  876.          
  877.         if bdosstack_sz==0
  878. callbdos_sp=$+1
  879.         ld sp,0
  880.         else
  881.         exx
  882.         pop hl
  883.         ld iy,(appaddr)
  884.         ;ld l,(iy+app.callbdos_sp)
  885.         ;ld h,(iy+app.callbdos_sp+1)
  886.         ld sp,hl
  887.         exx
  888.         endif
  889.         jp endsys_result_a
  890.  
  891.        if 0
  892. BDOShandler
  893.         push hl
  894.         ld a,c
  895.         ld hl,tbdoscmds
  896.         push bc
  897.         ld bc,nbdoscmds
  898.         cpir
  899.         jp nz,BDOS_pop2fail
  900. ;bc=nbdoscmds-(cmdnumber+1) = 0..(nbdoscmds-1)
  901.         add hl,bc
  902. ;hl=tbdoscmds+nbdoscmds
  903.         add hl,bc
  904.         add hl,bc
  905. ;hl=tbdoscmds+nbdoscmds+ 2*(nbdoscmds-(cmdnumber+1))
  906.         pop bc
  907.         ld a,(hl)
  908.         inc hl
  909.         ld h,(hl)
  910.         ld l,a
  911.         ;hl=jump addr
  912.         ex (sp),hl
  913.         ret
  914.        endif
  915.  
  916. sys_quit
  917. ;снять текущую задачу
  918. ;hl=result
  919.         ld sp,QUITSTACK ;если не сделать, то всё ещё стек задачи, и мы не вернёмся из schedule
  920.         ld iy,(appaddr)
  921.         ld e,(iy+app.id)
  922.        if 1==0
  923.         push de
  924.         push iy
  925.         call BDOS_freezeapp
  926.         pop iy
  927. ;если установлен muzcall в пространстве задачи, снимаем его
  928.         ld a,(muzpg)
  929.         call addrpage
  930.         pop de
  931.         ld a,(hl)
  932.         cp e
  933.         jr nz,sys_quit_nomuzcall
  934.        ld hl,sys_reter
  935.        ld (muzcall),hl ;есть в delapppages тоже!!! TODO выбросить?
  936. sys_quit_nomuzcall
  937.         call BDOS_delapppages ;глушит сокеты и музыку, удаляет страницы
  938.        endif
  939. ;hl=result
  940.        call BDOS_dropapp ;будит родителя, глушит сокеты и музыку, удаляет страницы
  941.         jp BDOS_yield_q ;переходим на какую-нибудь задачу (там же ставим pgkillable в 4000,8000,c000)
  942.        
  943. setkernelpages_go
  944. ;di!!!
  945. ;sp=0x3ffx
  946. ;сейчас включена 5-я страница
  947.         BDOSSETPGTRDOSFS
  948.         call makeidle
  949. ;setkernelpages_go_iy
  950.         ;ld sp,BDOSSTACK
  951.         call setpgs_killable
  952.         ld sp,-8
  953.  
  954.         ;ld iy,(appaddr)
  955.         ld d,(iy+app.mainpg)
  956. ;d=pgmain
  957. ;[e=значение для аккумулятора]
  958.         ld bc,memport0000
  959.         ld a,(iy+app.screen)
  960.         jp sys_intq ;там ei
  961.  
  962.  
  963. sys_findfreeappstruct
  964. ;out: nz=error, iy=free struct
  965.         ld iy,app1
  966.         ld de,app_sz
  967.         ld b,MAXAPPS
  968.         xor a
  969. sys_findfreeappstruct0
  970.         cp (iy+app.id)
  971.         ret z ;iy = free app struct
  972.         add iy,de
  973.         djnz sys_findfreeappstruct0
  974. ;too many apps!!!
  975.         ret ;nz
  976.        
  977. sys_findfreeid
  978.         xor a
  979. sys_findfreeid_next
  980.         inc a ;a!=0 (0 и 0xff нельзя - см. BDOS_newpage)
  981.         ld iy,app1
  982.         ld de,app_sz
  983.         ld b,MAXAPPS
  984. sys_findfreeid0
  985.         cp (iy+app.id)
  986.         jr z,sys_findfreeid_next
  987.         add iy,de
  988.         djnz sys_findfreeid0
  989. ;a=free id
  990.         ret
  991.  
  992. f_clos_curdrv_pp
  993. ;de=fil !=0
  994.         push de
  995.         call BDOS_setpgstructs
  996.         inc de
  997.         inc de
  998.         inc de
  999.         inc de
  1000.         inc de
  1001.         xor a
  1002.         ld (de),a
  1003.         pop de
  1004.         ld hl,ffsfunc.f_close
  1005.         jp call_ffs_curvol
  1006.                
  1007.                 if atm==1
  1008. NVRAM_REG=0xde
  1009. NVRAM_VAL=0xbe
  1010. readtime
  1011. ;sp=0x7fxx
  1012. ;e=gfxmode
  1013. ;out: hl=date, de=time
  1014. ;TODO атомарно
  1015.                 ld bc,0xf7 + (NVRAM_REG<<8)
  1016.                 ld a,0x0b
  1017.                 out (c),a
  1018.                 ld b,NVRAM_VAL
  1019.                 in a,(c)
  1020.                 or 0x04
  1021.                 out (c),a
  1022.                 xor a           ;sec
  1023.                 call bcd2bin
  1024.                 srl a
  1025.                 ld l,a
  1026.                
  1027.                 ld a,2          ;min
  1028.                 call bcd2bin
  1029.                 call minmes
  1030.                 add a,l
  1031.                 ld (sys_time_date),a    ;ld e,a
  1032.                 ld l,h
  1033.                
  1034.                 ld a,4          ;h
  1035.                 call bcd2bin
  1036.                 add a,a
  1037.                 add a,a
  1038.                 add a,a
  1039.                 add a,l
  1040.                 ld (sys_time_date+1),a  ;ld d,a
  1041.                
  1042.                 ld a,7          ;day
  1043.                 call bcd2bin
  1044.                 ld l,a
  1045.                
  1046.                 ld a,8          ;mes
  1047.                 call bcd2bin
  1048.                 call minmes
  1049.                 add a,l
  1050.                 ld (sys_time_date+2),a  ;ld l,a
  1051.                
  1052.                 ld a,9          ;god
  1053.                 call bcd2bin
  1054.                 add a,20
  1055.                 add a,a
  1056.                 add a,h
  1057.                 ld (sys_time_date+3),a  ;ld h,a
  1058.                 ret
  1059. minmes
  1060.                 ld h,a
  1061.                 xor a
  1062.                 srl h
  1063.                 rra
  1064.                 srl h
  1065.                 rra
  1066.                 srl h
  1067.                 rra
  1068.                 ret
  1069.  
  1070. bcd2bin
  1071.                 ld b,NVRAM_REG
  1072.                 out (c),a
  1073.                 ld b,NVRAM_VAL
  1074.                 in a,(c)
  1075.                 ret
  1076.    
  1077.                 endif
  1078.  
  1079.  
  1080.                 if PS2KBD==1
  1081. KEY_PUTREDRAW
  1082.                 ld bc,0xdef7
  1083.                 out (c),c
  1084.                 ld b,0xbe
  1085.         ld a,2
  1086.         out (c),a
  1087.                 in a,(c)
  1088.                 jr z,.buf_empty
  1089.                 inc a
  1090.                 jr nz,KEY_PUTREDRAW
  1091.                 ld b,0xde               ;переполнено
  1092.                 ld a,0x0c               ;сбросить буфер
  1093.                 out (c),a
  1094.                 ld b,0xbe
  1095.                 ld a,1
  1096.                 out (c),a
  1097. .buf_empty             
  1098.                 xor a
  1099.                 ld (KEYSCAN.rep_wait),a
  1100.                 ld b,a
  1101.                 ld c,a
  1102.                 ld (.rep_key),bc
  1103.                 ld bc,key_redraw
  1104.                 ld (.redrawkey),bc
  1105.                 ret
  1106. .rep_key
  1107.                 defw 0x0000
  1108. .redrawkey
  1109.                 defw 0x0000
  1110.                 else
  1111.                         include "syskey1.asm"
  1112.                 endif
  1113.                
  1114.         ds 50  
  1115. INTSTACK1;!=0x3f00 ;kernelspace (для входа в обработчик без порчи стека) (не пересекается с возможным стеком задачи!!!)
  1116.  
  1117.         include "fatfsdrv.asm"
  1118.         include "sysbdos.asm" ;в конце есть align 256
  1119. syskrnl_end=$
  1120.         ent
  1121.