Subversion Repositories NedoOS

Rev

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