Subversion Repositories NedoOS

Rev

Rev 775 | Rev 854 | 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. textcuraddr     WORD ;адрес курсора на экране
  160. curcolor        BYTE ;текущий атрибут при печати
  161. dta             WORD ;data transfer address
  162. vol             BYTE ;текущий драйв (volume)
  163. dircluster      DWORD ;текущая директория
  164. dir             BLOCK DIR_sz ;временный буфер для чтения каталога
  165. bdosstack       BLOCK bdosstack_sz ;стек при вызове BDOS
  166. pal             BLOCK 32
  167. ;safestack       BLOCK safestack_sz ;de,hl,af',af,ix,hl',de',bc',iy
  168.         ENDS
  169.  
  170.         display "apps start=",/h,$
  171. safestack
  172.         ds safestack_sz
  173. app1    app
  174. app_sz=$-safestack
  175.  
  176.         ds (MAXAPPS-1)*app_sz
  177.         display "MAXAPPS=",/h,MAXAPPS
  178.  
  179. app_afterlast=$+safestack_sz
  180. app_last=app_afterlast-app_sz
  181.         display "app1=",/h,app1
  182.         display "app_last=",/h,app_last
  183.  
  184. sys_intgo
  185.         ex de,hl
  186.         ld hl,0
  187.         add hl,sp
  188. appaddr=$+1
  189.         ld sp,app1 ;safestack_end
  190.         push hl ;"sp"
  191.         push de ;"hl"
  192.         push iy
  193.         exx
  194.         push bc
  195.         push de
  196.         push hl
  197.         push ix
  198.         ex af,af' ;'
  199.         push af
  200.  
  201.         ld bc,memport4000
  202.         ld a,pgtrdosfs;pagexor-5
  203.         out (c),a ;там INTSTACK
  204.         ld sp,INTSTACK2
  205.         call setgfxpal_focus
  206.         call on_int ;тикает таймер
  207.         call schedule ;out: iy=app
  208.         ld a,pgkillable
  209.         ld bc,memport4000
  210.         ld (sys_curpg4000),a ;не надо? (если di)
  211.         out (c),a
  212.  
  213. sys_int_popregs ;только для выхода из yield
  214. ;iy=app
  215.         ld de,-(safestack_sz-2) ;2 на запарывание прерыванием
  216.         add iy,de
  217.         ld sp,iy ;di!!!
  218.  
  219.         pop af
  220.         ex af,af' ;'
  221.         pop ix
  222.         pop hl
  223.         pop de
  224.         pop bc
  225.         exx
  226.         ld d,(iy+app.mainpg+safestack_sz-2) ;2 на запарывание прерыванием
  227.         ld iy,(focusappaddr)
  228.         ld a,(iy+app.screen)
  229.         pop iy
  230.         pop bc ;"hl"
  231.         pop hl ;"sp"
  232.         ld sp,hl
  233.         ld h,b
  234.         ld l,c
  235.         ld bc,memport0000
  236.         ;TODO освободить мьютекс, можно включить прерывания
  237.         jp sys_intq ;out (0xfd),a ;дальше попадаем в init_resident
  238.  
  239. schedule
  240. ;find next app, set iy
  241. ;out: iy=app, ix=(focusappaddr)
  242.         ld iy,(appaddr)
  243.         ld bc,-app_last;app_afterlast
  244.         ld de,app_last+app_sz;app_sz
  245.          ld a,(sys_timer) ;ok
  246.         ld l,MAXAPPS
  247. findnextapp0
  248.         add iy,bc
  249.         jr nc,$+6
  250.         ld iy,app1 -(app_last+app_sz)
  251.         add iy,de
  252.          cp (iy+app.lasttime)
  253.          jr z,findnextappskip
  254.          ;bit fyield,(iy)
  255.          ;jr nz,findnextappq
  256.         bit factive,(iy)
  257.         jr nz,findnextappq
  258. findnextappskip
  259.         dec l
  260.         jr nz,findnextapp0
  261. ;no active apps (или каждая в данном фрейме уже вызывалась)
  262.         ld iy,app1 ;idle
  263. findnextappq
  264.         ld (appaddr),iy
  265.          ld (iy+app.lasttime),a
  266.           ;ld iy,(appaddr)
  267.           ld a,(iy+app.mainpg)
  268.           ld bc,memport4000
  269.           ld (sys_curpg4000),a ;нужно (могут вызвать из yield - в любой момент)
  270.           out (c),a
  271.           ld ix,(focusappaddr)
  272.           ld a,(ix+app.screen)
  273.           or fd_system
  274.           ;ld (user_fdvalue1+0x4000),a ;for QUIT, мешает делать многозадачность с 0xffff: jp nn
  275.           ld (user_fdvalue2+0x4000),a
  276.           ld (user_fdvalue3+0x4000),a
  277.           ld (user_fdvalue4+0x4000),a
  278.           ;ld (user_fdvalue5+0x4000),a ;not supported yet
  279.           ld (user_fdvalue6+0x4000),a
  280.           ld a,pgtrdosfs
  281.           ;ld (sys_curpg4000),a ;нужно (могут вызвать из yield - в любой момент - но там не важно, там стек в нулях, а потом само ввключает pgkillable)
  282.           out (c),a ;там INTSTACK
  283.         ;ld iy,(appaddr)
  284.         ret
  285.  
  286. setgfxpal_focus
  287. ;если в yield не поставить палитру второй задаче, то она никогда не поставится, если первая задача в цикле делает yield
  288. ;потому что все прерывания будут ставить первую задачу
  289. ;если же палитру ставить в самом yield, то могут быть проблемы с выставлением палитры, если yield вызывать в случайных местах или если все задачи неактивны
  290. ;поэтому обработчик прерываний должен выставлять палитру и видеорежим задачи, которая в фокусе, независимо от её активности
  291. ;менять палитру только после смены фокуса или записи палитры
  292.                 display "setgfxpal_focus ",setgfxpal_focus
  293. palettechanged=$
  294.         or a
  295.         jp c,focusappborder
  296.         ld a,55 ;"scf"
  297.         ld (palettechanged),a
  298.        ifndef NOPAL
  299.         ld hl,(focusappaddr)
  300.         ld bc,app.pal+31 ;-app.gfxmode
  301.         add hl,bc
  302.         if atm==1
  303.                 ld bc,0x07ff
  304.                 dup 8
  305.                 ld a,b
  306.                 out (0xf6),a
  307.                 outd
  308.                 dec hl
  309.                 edup
  310.                 ld b,0x07
  311.                 dup 7
  312.                 ld a,b
  313.                 out (0xfe),a
  314.                 outd
  315.                 dec hl
  316.                 edup
  317.                 ld a,b
  318.                 out (0xfe),a
  319.                 outd
  320.         else
  321.  
  322.         ld c,0xff
  323.         ld a,7
  324.         dup 8
  325.         OUT (0xF6),A
  326.         ld d,(hl)
  327.         dec hl
  328.         ld b,(hl) ;DDp palette low bits
  329.         OUT (c),d;(0xFF),A
  330.         dec hl
  331.         dec a
  332.         edup
  333.         ld a,7
  334.         dup 7
  335.         OUT (0xFE),A
  336.         ld d,(hl)
  337.         dec hl
  338.         ld b,(hl) ;DDp palette low bits
  339.         OUT (c),d;(0xFF),A
  340.         dec hl
  341.         dec a
  342.         edup
  343.         OUT (0xFE),A ;0
  344.         ld d,(hl)
  345.         dec hl
  346.         ld b,(hl) ;DDp palette low bits
  347.         OUT (c),d;(0xFF),A
  348.         endif
  349.        endif
  350. focusappborder
  351.          ld ix,(focusappaddr)
  352.        ifndef NOPAL
  353.          ld a,(ix+app.border)
  354.          cp 8
  355.          res 3,a ;tapeout sound
  356.          out (0xfe),a
  357.          ret c
  358.          out (0xf6),a
  359.        endif
  360.         ret
  361.  
  362. sys_sysint
  363. ;TODO schedule (для RTOS), но тогда надо реентерабельность всех процедур BDOS (даже без этого шедулинга они всё равно не должны иметь состояния!)
  364. ;как шедулить, когда мы в kernelspace???
  365. ;TODO проверка критической секции (в обычном прерывании не нужно)
  366.         ex de,hl
  367.         ex (sp),hl ;восстановили стек из de
  368.         ld (sys_sysint_jp),hl
  369.         ld (sys_sysint_sp),sp
  370.         ld sp,INTSTACK1
  371.         push af
  372.         push bc
  373.         push de ;"hl"
  374.         ;push hl
  375.         exx
  376.         ex af,af' ;'
  377.         push af
  378.         push bc
  379.         push de
  380.         push hl
  381.         push ix
  382.         push iy
  383.         ld sp,INTSTACK2
  384.  
  385.         ld bc,memport4000
  386.         ld a,pgtrdosfs;pagexor-5 ;там INTSTACK
  387.         out (c),a
  388.  
  389.         call setgfxpal_focus
  390.  
  391.         call on_int
  392. sys_curpg4000=$+1
  393.         ld a,pgkillable
  394.         ld bc,memport4000
  395.         out (c),a
  396.  
  397.         ld sp,INTSTACK1-18
  398.         pop iy
  399.         pop ix
  400.         pop hl
  401.         pop de
  402.         pop bc
  403.         pop af
  404.         ex af,af' ;'
  405.         exx
  406.         pop hl ;"hl"
  407.         ;pop de
  408.         pop bc
  409.         pop af
  410. sys_sysint_sp=$+1
  411.         ld sp,0
  412.         pop de
  413.         ei
  414.         ;ret
  415. sys_sysint_jp=$+1
  416.         jp 0
  417.        
  418. on_int
  419. ;в 0x4000 сейчас pg5, там стек
  420. focusappaddr=$+1
  421.         ld hl,app1
  422.         ld bc,app.gfxmode
  423.         add hl,bc
  424.         ld e,(hl)
  425. ;sys_curgfxmode=$+1
  426.         ;ld e,%10101000 ;320x200 mode
  427.                 if atm==1
  428.                         ld bc,0xfadf ;buttons
  429.                         in a,(c)
  430.                         ld (sys_mousebuttons),a
  431.                         inc b ;ld bc,0xfbdf ;x
  432.                         in l,(c)
  433.                         ld b,0xff ;y
  434.                         in h,(c)
  435.                 else
  436.                         ifdef NOMOUSE
  437.                         ld hl,0
  438.                         ld d,0x0f
  439.                         else
  440.                         call readmouse ;resident >=0x4000
  441.                         endif
  442.         ld a,d
  443.         ld (sys_mousebuttons),a
  444.                 endif
  445.         ld (sys_mousecoords),hl
  446.                 if atm != 1
  447.                         ld a,(sys_timer) ;ok
  448.                         and 7
  449.                         jr nz,on_int_noreadtime
  450.                         ifdef NOCMOS
  451.                         else
  452.                         call readtime ;hl=date, de=time
  453.                         ld (sys_time_date),de
  454.                         ld (sys_time_date+2),hl
  455.                         endif
  456. on_int_noreadtime
  457.                 endif
  458.         ld hl,sys_timer
  459.         inc (hl)
  460.         inc hl
  461.         jr nz,on_int_timerq
  462.         inc (hl)
  463.         inc hl
  464.         jr nz,on_int_timerq
  465.         inc (hl)
  466.         inc hl
  467.         jr nz,on_int_timerq
  468.         inc (hl)
  469. on_int_timerq
  470.        
  471.                 if PS2KBD==0
  472.                         ld a,pgtrdosfs
  473.                         ld bc,memport4000
  474.                         out (c),a ;don't keep in sys_curpg4000!
  475.                         call KEYSCAN
  476.                 else
  477. KEYSCAN
  478. .rep_wait=$+1
  479.                         ld a,0
  480.                         dec a
  481.                         jp m,.end_keyscan
  482.                         ld (.rep_wait),a
  483. .end_keyscan                   
  484.                 endif
  485.  
  486.         ;call PEEKKEY ;ld a,(curkey)
  487.         ;cp ssEnter
  488.        
  489.         ld a,0x7f
  490.         in a,(0xfe)
  491.         rra
  492.         ld c,a ;c0=ss
  493.         ld a,0xbf
  494.         in a,(0xfe)
  495.         or c
  496.         cpl
  497.         ld c,a
  498.         cpl
  499.         ;a0=c0=0: ssEnter pressed
  500. on_int_oldssEnter=$+1
  501.         or 0 ;=0: ssEnter was released
  502.         rra
  503.         ld a,c
  504.         ld (on_int_oldssEnter),a
  505.         jr c,sys_int_noselectapp
  506.          call KEY_PUTREDRAW
  507.  
  508.         if 1==1
  509.         ld iy,(focusappaddr)
  510.         call disablescrpgs_setc000
  511.         ld bc,-app_last;app_afterlast
  512.         ld de,app_last+app_sz;app_sz
  513.         ld l,MAXAPPS
  514. findnextgfxapp0
  515.         add iy,bc
  516.         jr nc,$+6
  517.         ld iy,app1 -(app_last+app_sz)
  518.         add iy,de
  519.         ld a,(iy+app.flags)
  520.         bit fgfx,a
  521.         jr z,findnextgfxappskip
  522.          bit fwaiting,a
  523.          jr z,findnextgfxappq
  524. findnextgfxappskip
  525.         dec l
  526.         jr nz,findnextgfxapp0
  527. ;no active apps (или каждая в данном фрейме уже вызывалась)
  528.         ld iy,app1 ;idle
  529. findnextgfxappq
  530.         ld (focusappaddr),iy
  531.         call setpalettechanged
  532.  
  533.         else
  534.        
  535.         ld hl,(focusappaddr)
  536.         ;отключить страницы экрана этой задаче и выключить их в памяти задачи
  537.         push hl
  538.         pop iy
  539.         call disablescrpgs_setc000
  540.         ld bc,-app_last;app_afterlast
  541.         ld de,app_last+app_sz;app_sz
  542.         ld a,MAXAPPS
  543. findnextgfxapp0
  544.         ;add hl,de
  545.         ;sbc hl,bc
  546.         ;add hl,bc
  547.         ;jr nz,$+5
  548.         ;ld hl,app1
  549.         add hl,bc
  550.         jr nc,$+5 ;hl < app_last
  551.         ld hl,app1 -(app_last+app_sz)
  552.         add hl,de
  553.         bit fgfx,(hl)
  554.         jr z,findnextgfxappskip
  555.          bit fwaiting,(hl)
  556.          jr z,findnextgfxappq
  557. findnextgfxappskip
  558.         dec a
  559.         jr nz,findnextgfxapp0
  560.         ld hl,app1
  561. findnextgfxappq
  562.         ld (focusappaddr),hl
  563.         call setpalettechanged
  564.         ;включить страницы экрана этой задаче
  565.         ;push iy
  566.         push hl
  567.         pop iy
  568.         endif
  569.        
  570.         call enablescreeninapp_setc000
  571.        
  572.         ;pop iy
  573.        
  574. sys_int_noselectapp
  575. muzpg=$+1
  576.         ld a,pgkillable
  577.         ld bc,memport4000
  578.         out (c),a
  579. muzpg8000=$+1
  580.          ld a,pgkillable
  581.          ld b,memport8000_hi
  582.          out (c),a
  583. muzpgc000=$+1
  584.          ld a,pgkillable
  585.          ld b,memportc000_hi
  586.          out (c),a
  587.  
  588.         ;jr $
  589.         ld sp,INTMUZSTACK
  590.  
  591.          ld e,pgsys
  592.         ld ix,(focusappaddr)
  593.         ld a,(ix+app.gfxmode)
  594. muzcall=$+1
  595.         call sys_reter;pt3player.PLAY ;TODO call drivers
  596.        
  597.         ld sp,INTSTACK2-2
  598.  
  599.         ld ix,(focusappaddr)
  600.         ld a,(ix+app.gfxmode)
  601.         ld bc,0xbd77
  602.         out (c),a ;set gfx mode
  603.        
  604.         ld a,pgtrdosfs;pagexor-5
  605.         ld bc,memport4000
  606.         out (c),a ;там INTSTACK
  607. sys_curpg8000=$+1
  608.          ld a,pgkillable
  609.          ld b,memport8000_hi
  610.          out (c),a
  611. sys_curpgc000=$+1
  612.          ld a,pgkillable
  613.          ld b,memportc000_hi
  614.          out (c),a
  615.         ret
  616.  
  617. copypage_a_to_e
  618.         call sys_setpg8000
  619.         ld a,e
  620.         call sys_setpgc000
  621.         ld hl,0x8000
  622.         ld de,0xc000
  623.         ld bc,0x4000
  624.         ldir
  625.         ret
  626.  
  627. disablescrpgs_setc000
  628.         bit 7,(iy+app.gfxkeep)
  629.         jr z,disablescrpgs_nokeep
  630.         ld a,pgscr0_0
  631.         ld e,(iy+app.scr0low)
  632.         call copypage_a_to_e
  633.         ld a,pgscr0_1
  634.         ld e,(iy+app.scr0high)
  635.         call copypage_a_to_e
  636.         ld a,pgscr1_0
  637.         ld e,(iy+app.scr1low)
  638.         call copypage_a_to_e
  639.         ld a,pgscr1_1
  640.         ld e,(iy+app.scr1high)
  641.         call copypage_a_to_e
  642. disablescrpgs_nokeep
  643.         call disablescreeninapp_setc000
  644.         ld de,curpg16k+0xc000
  645.         call disablescrpg
  646.         ld  e,0xff&(curpg32klow+0xc000)
  647.         call disablescrpg
  648.         ld  e,0xff&(curpg32khigh+0xc000)
  649.         ;call disablescrpg
  650. disablescrpg
  651. ;de=page keeping addr
  652.         ld a,(de)
  653.         or 7&(pgscr0_0|pgscr0_1|pgscr1_0|pgscr1_1)
  654.         cp pgscr0_0
  655.         ret nz;jr z,disablescrpg_ok
  656. disablescrpg_ok        
  657.         ld a,pgkillable
  658.         ld (de),a
  659.         ret
  660.  
  661. sys_getchar
  662. ;out: de=mouse yx, l=buttons, A=key, H=high bits of key, nz=no focus (mouse position=0, ignore it!)
  663.         ;call checkfocus_getkbdmouse
  664. ;checkfocus_getkbdmouse
  665. ;out: nz=fail
  666.         ld de,(focusappaddr)
  667.         ld hl,(appaddr)
  668.         xor a
  669.         sbc hl,de
  670.         jr nz,sys_getchar_fail ;nz
  671. ;sys_oldmousecoords=$+1
  672. ;        ld de,0
  673. ;        ld (sys_oldmousecoords),hl
  674. ;        ld a,l
  675. ;        sub e ;a=dx
  676. ;        ld e,a ;e=dx
  677. ;        ld a,d
  678. ;        sub h ;a=dy
  679. ;        ld d,a ;d=dy
  680.                 if PS2KBD==1
  681.                         display "ps2_sp ",$
  682.                         ld (ps2_sp),sp
  683.                         ld sp,BDOSSTACK ;это может затереть стек возврата! поэтому возвращаемся через jp
  684.                         call BDOS_setpgtrdosfs
  685.                         call GETKEY ;A=key, H=high bits of key, BC=keynolang
  686.                         ld e,a
  687.                         push bc ;ld (ps2_bc),bc
  688.                         ld a,pgkillable
  689.                         ld bc,memport4000
  690.                         ld (sys_curpg4000),a
  691.                         out (c),a
  692.                         pop bc
  693. ps2_sp=$+1
  694.                         ld sp,0
  695. ;ps2_bc=$+1
  696. ;                       ld bc,0
  697.                         ld a,e
  698.                 else
  699.                         call GETKEY ;A=key, H=high bits of key, BC=keynolang
  700.                 endif
  701.         cp a ;z
  702. sys_mousecoords=$+1
  703.         ld de,0;hl,0
  704. sys_mousebuttons=$+1
  705.         ld l,0xff
  706.         ;ret ;z
  707.         ;jp endsys_result_a
  708. endsys_result_a
  709.          ld iy,(focusappaddr)
  710.         ex af,af' ;'
  711.         ld a,(iy+app.screen)
  712.         ;ld iy,(appaddr)
  713.         jp endsys_result_aq
  714.  
  715. ;TODO брать номер экрана у задачи с фокусом и при шедулинге ставить этот номер в userkernel новой задачи
  716.        
  717. sys_getchar_fail
  718. ;a=0, nz
  719.         ;ld a,NOKEY ;no key
  720.          ;ld h,a
  721.          ;ld b,a
  722.          ld c,a ;no keynolang
  723.         ld d,a;0
  724.         ld e,a;0 ;no mouse movement
  725.         ld l,0xff ;no buttons
  726.         jr endsys_result_a ;ret ;nz ;jp endsys_result_a
  727.  
  728. callbdos
  729. ;при вызове bdos надо включить:
  730. ;0x0000 - syscode (уже включено)
  731. ;[0x4000 - pgfatfs или bdospg2]
  732. ;защита от одновременного доступа двум задачам
  733. ;занято a,bc,de,hl
  734. ;свободно iy
  735.         if bdosstack_sz==0
  736.  
  737.         ld (callbdos_sp),sp
  738.         ld sp,BDOSSTACK ;до этого момента прерывание может запороть любое место памяти (user sp >=0x3b00) ;это может затереть стек возврата! поэтому возвращаемся через jp
  739.  
  740.         else
  741.        
  742.         exx
  743. callbdos_lock        
  744.         ld hl,callbdos_mutex ;изначально 0xc0
  745.         sla (hl)
  746.         jr z,callbdos_lock ;был занят
  747.        
  748.         ld hl,0
  749.         add hl,sp
  750.         ld iy,(appaddr)
  751.         ;ld (iy+app.callbdos_sp),l
  752.         ;ld (iy+app.callbdos_sp+1),h
  753.         ld bc,app.bdosstack+bdosstack_sz
  754.         add iy,bc
  755.         ld sp,iy ;до этого момента прерывание может запороть любое место памяти (user sp >=0x3b00)
  756.         push hl
  757.         exx
  758.        
  759.         endif
  760.        
  761.             ;ld iy,(focusappaddr)
  762.             ;ld a,(iy+app.screen)
  763.             ;xor 0x10 ;fd_user^fd_system
  764.             ;out (0xfd),a
  765.         ld iy,(appaddr)
  766.         call BDOShandler
  767.          push af
  768.          push bc
  769.          call setpgs_killable
  770.         if bdosstack_sz !=0
  771.         ld a,0xc0
  772.         ld (callbdos_mutex),a ;то же самое делают те функции BDOS, которые не собираются возвращаться
  773.         endif
  774.          pop bc
  775.          pop af
  776.          
  777.         if bdosstack_sz==0
  778. callbdos_sp=$+1
  779.         ld sp,0
  780.         else
  781.         exx
  782.         pop hl
  783.         ld iy,(appaddr)
  784.         ;ld l,(iy+app.callbdos_sp)
  785.         ;ld h,(iy+app.callbdos_sp+1)
  786.         ld sp,hl
  787.         exx
  788.         endif
  789.         jp endsys_result_a
  790.  
  791. sys_quit
  792. ;снять текущую задачу
  793.         ld sp,QUITSTACK ;если не сделать, то всё ещё стек задачи, и мы не вернёмся из schedule
  794.         ld iy,(appaddr)
  795.         ld e,(iy+app.id)
  796.         push de
  797.         push iy
  798.         call BDOS_freezeapp
  799.         pop iy
  800. ;если установлен muzcall в пространстве задачи, снимаем его
  801.         ld a,(muzpg)
  802.         call addrpage
  803.         pop de
  804.         ld a,(hl)
  805.         cp e
  806.         jr nz,sys_quit_nomuzcall
  807.        ld hl,sys_reter
  808.        ld (muzcall),hl ;есть в delapppages тоже!!! TODO выбросить?
  809. sys_quit_nomuzcall
  810.         call BDOS_delapppages ;глушит сокеты и музыку
  811.         jp BDOS_yield_q ;переходим на какую-нибудь задачу (там же ставим pgkillable в 4000,8000,c000)
  812.        
  813. setkernelpages_go
  814. ;di!!!
  815. ;sp=0x3ffx
  816. ;сейчас включена 5-я страница
  817.         BDOSSETPGTRDOSFS
  818.         call makeidle
  819. ;setkernelpages_go_iy
  820.         ;ld sp,BDOSSTACK
  821.         call setpgs_killable
  822.         ld sp,-8
  823.  
  824.         ;ld iy,(appaddr)
  825.         ld d,(iy+app.mainpg)
  826. ;d=pgmain
  827. ;[e=значение для аккумулятора]
  828.         ld bc,memport0000
  829.         ld a,(iy+app.screen)
  830.         jp sys_intq ;там ei
  831.  
  832.  
  833. sys_findfreeappstruct
  834. ;out: nz=error, iy=free struct
  835.         ld iy,app1
  836.         ld de,app_sz
  837.         ld b,MAXAPPS
  838.         xor a
  839. sys_findfreeappstruct0
  840.         cp (iy+app.id)
  841.         ret z ;iy = free app struct
  842.         add iy,de
  843.         djnz sys_findfreeappstruct0
  844. ;too many apps!!!
  845.         ret ;nz
  846.        
  847. sys_findfreeid
  848.         xor a
  849. sys_findfreeid_next
  850.         inc a ;a!=0 (0 и 0xff нельзя - см. BDOS_newpage)
  851.         ld iy,app1
  852.         ld de,app_sz
  853.         ld b,MAXAPPS
  854. sys_findfreeid0
  855.         cp (iy+app.id)
  856.         jr z,sys_findfreeid_next
  857.         add iy,de
  858.         djnz sys_findfreeid0
  859. ;a=free id
  860.         ret
  861.                
  862.                 if atm==1
  863. NVRAM_REG=0xde
  864. NVRAM_VAL=0xbe
  865. readtime
  866. ;sp=0x7fxx
  867. ;e=gfxmode
  868. ;out: hl=date, de=time
  869. ;TODO атомарно
  870.                 ld bc,0xf7 + (NVRAM_REG<<8)
  871.                 ld a,0x0b
  872.                 out (c),a
  873.                 ld b,NVRAM_VAL
  874.                 in a,(c)
  875.                 or 0x04
  876.                 out (c),a
  877.                 xor a           ;sec
  878.                 call bcd2bin
  879.                 srl a
  880.                 ld l,a
  881.                
  882.                 ld a,2          ;min
  883.                 call bcd2bin
  884.                 call minmes
  885.                 add a,l
  886.                 ld (sys_time_date),a    ;ld e,a
  887.                 ld l,h
  888.                
  889.                 ld a,4          ;h
  890.                 call bcd2bin
  891.                 add a,a
  892.                 add a,a
  893.                 add a,a
  894.                 add a,l
  895.                 ld (sys_time_date+1),a  ;ld d,a
  896.                
  897.                 ld a,7          ;day
  898.                 call bcd2bin
  899.                 ld l,a
  900.                
  901.                 ld a,8          ;mes
  902.                 call bcd2bin
  903.                 call minmes
  904.                 add a,l
  905.                 ld (sys_time_date+2),a  ;ld l,a
  906.                
  907.                 ld a,9          ;god
  908.                 call bcd2bin
  909.                 add a,20
  910.                 add a,a
  911.                 add a,h
  912.                 ld (sys_time_date+3),a  ;ld h,a
  913.                 ret
  914. minmes
  915.                 ld h,a
  916.                 xor a
  917.                 srl h
  918.                 rra
  919.                 srl h
  920.                 rra
  921.                 srl h
  922.                 rra
  923.                 ret
  924.  
  925. bcd2bin
  926.                 ld b,NVRAM_REG
  927.                 out (c),a
  928.                 ld b,NVRAM_VAL
  929.                 in a,(c)
  930.                 ret
  931.    
  932.                 endif
  933.  
  934.  
  935.                 if PS2KBD==1
  936. KEY_PUTREDRAW
  937.                 ld bc,0xdef7
  938.                 out (c),c
  939.                 ld b,0xbe
  940.                 in a,(c)
  941.                 jr nz,KEY_PUTREDRAW
  942.                 xor a
  943.                 ld (KEYSCAN.rep_wait),a
  944.                 ld b,a
  945.                 ld c,a
  946.                 ld (.rep_key),bc
  947.                 ld bc,key_redraw
  948.                 ld (.redrawkey),bc
  949.                 ret
  950. .rep_key
  951.                 defw 0x0000
  952. .redrawkey
  953.                 defw 0x0000
  954.                 else
  955.                         include "syskey1.asm"
  956.                 endif
  957.                
  958.         ds 50  
  959. INTSTACK1;!=0x3f00 ;kernelspace (для входа в обработчик без порчи стека) (не пересекается с возможным стеком задачи!!!)
  960.  
  961.         include "fatfsdrv.asm"
  962.         include "sysbdos.asm" ;в конце есть align 256
  963.         ent
  964. syscodesz=$-wassyscode
  965.         display "syscodesz=",/h,syscodesz," < minstack=",/h,SYSMINSTACK
  966.