home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 23 / IOPROG_23.ISO / SOFT / ASM / PMODN021.ZIP / PMODE.ASM < prev    next >
Encoding:
Assembly Source File  |  1999-01-19  |  83.2 KB  |  2,077 lines

  1. ; PMODE v2.51 raw, DPMI, VCPI, & XMS compliant protected mode header.
  2. ; By Tran (a.k.a. Thomas Pytel).
  3.  
  4. ; NASM (The Netwide Assembler) 0.95 port 0.1
  5. ; By Cyborg/Mistery <cyborg@otitsun.oulu.fi>
  6.  
  7. ; NASM 0.97 port 0.2
  8. ; by Ike (a.k.a. Ivan Tomac) <ike@technologist.com>
  9.  
  10. %include "nasmmac.inc"
  11.  
  12. global          v86r_eax                ; D
  13. global          v86r_ebx                ; D
  14. global          v86r_ecx                ; D
  15. global          v86r_edx                ; D
  16. global          v86r_esi                ; D
  17. global          v86r_edi                ; D
  18. global          v86r_ebp                ; D
  19. global          v86r_ah                 ; B
  20. global          v86r_al                 ; B
  21. global          v86r_bh                 ; B
  22. global          v86r_bl                 ; B
  23. global          v86r_ch                 ; B
  24. global          v86r_cl                 ; B
  25. global          v86r_dh                 ; B
  26. global          v86r_dl                 ; B
  27. global          v86r_ax                 ; W
  28. global          v86r_bx                 ; W
  29. global          v86r_cx                 ; W
  30. global          v86r_dx                 ; W
  31. global          v86r_si                 ; W
  32. global          v86r_di                 ; W
  33. global          v86r_bp                 ; W
  34. global          v86r_ds                 ; W
  35. global          v86r_es                 ; W
  36. global          v86r_fs                 ; W
  37. global          v86r_gs                 ; W
  38. global          _selcode                ; W
  39. global          _seldata                ; W
  40. global          _selzero                ; W
  41. global          _lomembase              ; D
  42. global          _lomemtop               ; D
  43. global          _himembase              ; D
  44. global          _himemtop               ; D
  45. global          _pspa                   ; D
  46. global          _code16a                ; D
  47. global          _code32a                ; D
  48. global          _getirqvect             ; D
  49. global          _setirqvect             ; D
  50. global          _sysbyte0               ; B
  51. global          _setselector            ; D
  52. global          _exitcode               ; B
  53.  
  54. global          _getmem                 ; near
  55. global          _getlomem               ; near
  56. global          _gethimem               ; near
  57. global          _lomemsize              ; near
  58. global          _himemsize              ; near
  59. global          _ret                    ; near
  60. global          _exit                   ; near
  61. global          _getirqmask             ; near
  62. global          _setirqmask             ; near
  63. global          _rmpmirqset             ; near
  64. global          _rmpmirqfree            ; near
  65. global          _getselector            ; near
  66. global          _freeselector           ; near
  67.  
  68. extern          _main
  69.  
  70. LOWMIN          equ 0           ; minimum free low memory (in K)
  71. EXTMIN          equ 0           ; minimum free extended memory (in K)
  72. SELECTORS       equ 8           ; extra selectors for allocation != 0
  73. STAKMAIN        equ 100h        ; main execution stream stack size (in para)
  74. STAKRMODE       equ 10h         ; real mode call stack size (in para)
  75. STAKPMODE       equ 20h         ; protected mode call stack size (in para)
  76. MODENESTING     equ 8           ; max number of nested mode switches
  77.  
  78. RMODENUM        equ (MODENESTING+1) >> 1
  79. PMODENUM        equ MODENESTING >> 1
  80. STAKSIZE        equ STAKMAIN+(PMODENUM*STAKPMODE)+(RMODENUM*STAKRMODE) ;<0fffh!
  81.  
  82. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  83. ; Real mode and 16bit code
  84. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  85.  
  86. section code
  87. bits 16
  88.  
  89. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  90. ; 16 bit common system data
  91. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  92.  
  93. errmsg0         db '386 or better not detected!!!',7,'$'
  94. errmsg1         db 'Not enough low memory!!!',7,'$'
  95. errmsg2         db 'System is already in V86 mode, and no VCPI or DPMI found!!!',7,'$'
  96. errmsg3         db 'Not enough extended memory!!!',7,'$'
  97. errmsg4         db 'Could not enable A20 gate!!!',7,'$'
  98. errmsg5         db 'Extended memory allocation failure. (weird eh???)',7,'$'
  99.  
  100. nullint         db 0CFh         ; IRET instruction
  101. exitrout        dw exit         ; exit routine, modified if XMS, VCPI
  102.  
  103. savedstakoff    dw ?            ; current saved stack offset
  104. savedstakseg    dw ?            ; current saved stack segment
  105.  
  106. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  107. ; 16 bit common system code
  108. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  109. ;═════════════════════════════════════════════════════════════════════════════
  110.  
  111. intreal:                                ; real mode int, load FS and GS here
  112.                 pushf
  113. ;-----------------------------------------------------------------------------
  114. callreal:                               ; real mode call, load FS and GS here
  115.                 push    cs
  116.                 push    W icreald
  117.                 mov     fs,[cs:v86r_fs]
  118.                 mov     gs,[cs:v86r_gs]
  119.                 mov     eax,[cs:v86r_eax]
  120.                 mov     ecx,[cs:v86r_ecx]
  121.                 mov     edx,[cs:v86r_edx]
  122.                 mov     ebx,[cs:v86r_ebx]
  123.                 mov     esi,[cs:v86r_esi]
  124.                 mov     edi,[cs:v86r_edi]
  125.                 mov     ebp,[cs:v86r_ebp]
  126. ;-----------------------------------------------------------------------------
  127. icreal:                                 ; real mode int, call, or IRQ
  128.                 db      66h,68h         ; PUSH destination addx
  129. icrealm1        dd      ?       ;
  130. icrealm0        db      ?       ; CLI or STI
  131.                 retf
  132. ;-----------------------------------------------------------------------------
  133. icreald:                                ; done with real int or call
  134.                 cli
  135.                 pushf
  136.                 pop     W[cs:v86r_flags]
  137.                 mov     [cs:v86r_eax],eax
  138.                 mov     [cs:v86r_ecx],ecx
  139.                 mov     [cs:v86r_edx],edx
  140.                 mov     [cs:v86r_ebx],ebx
  141.                 mov     [cs:v86r_esi],esi
  142.                 mov     [cs:v86r_edi],edi
  143.                 mov     [cs:v86r_ebp],ebp
  144.                 mov     [cs:v86r_ds],ds
  145.                 mov     [cs:v86r_es],es
  146.                 mov     [cs:v86r_fs],fs
  147.                 mov     [cs:v86r_gs],gs
  148. icreald2:
  149.                 mov     ax,cs
  150.                 mov     ds,ax
  151. icrealm2:                               ; return to pmode modifiable to JMP
  152. ;-----------------------------------------------------------------------------
  153.                 mov     ebx,[cp_savedstakoff]   ; DPMI return to pmode
  154.                 mov     dx,[dp_savedstaksel]
  155.                 mov     edi,dp_int3_d
  156.                 mov     si,[_selcode]
  157.                 mov     cx,dx
  158.                 mov     ax,[_seldata]
  159.                 jmp     far [d_switchaddx]
  160. ;-----------------------------------------------------------------------------
  161. VICREAL1D       equ (($-(icrealm2+2)) << 8) + 0EBh
  162. v_icreal1d:                             ; VCPI return to pmode from safe
  163.                 mov     edi,cp_int3_d
  164. ;-----------------------------------------------------------------------------
  165. ; EDI=offset to jump to in code32
  166. v_switchtopmode:                        ; VCPI switch to pmode
  167.                 mov     [v_ss_dest],edi
  168.                 mov     esi,v_ss_cr3
  169.                 add     esi,[_code16a]
  170.                 mov     ax,0DE0Ch
  171.                 int     67h
  172. ;-----------------------------------------------------------------------------
  173. CICREAL1D       equ (($-(icrealm2+2)) << 8) + 0EBh
  174. c_icreal1d:                             ; custom return to pmode from safe
  175.                 mov     edi,cp_int3_d
  176. ;-----------------------------------------------------------------------------
  177. ; EDI=offset in pmode to jump to
  178. c_retpmode:                             ; reenter 32bit pmode
  179.                 lgdt    [c_gdt32addx]           ; set up pmode GDT and IDT
  180.                 lidt    [c_idt32addx]
  181.                 mov     B[gdt32task+5],89h      ; set task as not busy
  182.                 mov     eax,cr0                 ; switch to pmode
  183.                 or      al,1
  184.                 mov     cr0,eax
  185.                 db      0EAh
  186.                 dw      $+4,20h
  187.                 mov     ax,30h                  ; load task register
  188.                 ltr     ax
  189.                 jmp     c_gotopmode
  190. ;═════════════════════════════════════════════════════════════════════════════
  191. int32:                                  ; real mode INT32: EDX=off
  192.                 pushad
  193.                 push    ds
  194.                 push    es
  195.                 push    fs
  196.                 push    gs
  197.                 cli
  198.                 mov     ax,cs
  199.                 mov     ds,ax
  200.                 mov     [p_cpmodem0],edx
  201.                 mov     al,[esp+45]
  202.                 shr     al,1
  203.                 and     al,1
  204.                 add     al,0FAh
  205.                 mov     [p_cpmodem1],al
  206.                 push    W[savedstakoff]
  207.                 push    W[savedstakseg]
  208.                 movzx   ebx,W[nextmodestack]
  209.                 lea     eax,[ebx-STAKPMODE*16]
  210.                 mov     [nextmodestack],ax
  211.                 add     ebx,[realstackbase]
  212.                 mov     [savedstakseg],ss
  213. int32m0:                                ; jump to pmode, modifiable
  214. ;-----------------------------------------------------------------------------
  215.                 sub     sp,[dp_savelen]
  216.                 mov     [savedstakoff],sp
  217.                 mov     ax,ss                       ; DPMI jump to pmode
  218.                 mov     es,ax
  219.                 mov     di,sp
  220.                 xor     al,al
  221.                 call    far [d_saveaddx]
  222.                 mov     ax,[_seldata]
  223.                 mov     cx,ax
  224.                 mov     dx,ax
  225.                 mov     edi,p_cpmode0
  226.                 mov     si,[_selcode]
  227.                 jmp     far [d_switchaddx]
  228. ;-----------------------------------------------------------------------------
  229. VINT32          equ (($-(int32m0+2)) << 8) + 0EBh       ; JMP short v_int32
  230. v_int32:                                ; VCPI call pmode
  231.                 push    W[p_cpmodem2]
  232.                 mov     W[p_cpmodem2],VCPMODED
  233.                 mov     [savedstakoff],sp
  234.                 mov     edi,p_cpmode1
  235.                 jmp     v_switchtopmode
  236. ;-----------------------------------------------------------------------------
  237. ; if ($-(int32m0+2)) gt 127 => error
  238. CINT32          equ (($-(int32m0+2)) << 8)+0EBh         ; JMP short c_int32
  239. c_int32:                                ; raw/XMS call pmode
  240.                 push    W[p_cpmodem2]
  241.                 mov     W[p_cpmodem2],CCPMODED
  242.                 mov     [savedstakoff],sp
  243.                 mov     edi,p_cpmode1
  244.                 jmp     c_retpmode
  245. ;═════════════════════════════════════════════════════════════════════════════
  246. int32d0:                                ; DPMI done with pmode call
  247.                 mov     di,sp
  248.                 mov     al,1
  249.                 call    far [d_saveaddx]
  250.                 add     sp,[dp_savelen]
  251. ;-----------------------------------------------------------------------------
  252. int32d2:                                ; done from all
  253.                 pop     W[savedstakseg]
  254.                 pop     W[savedstakoff]
  255.                 add     W[nextmodestack],STAKPMODE*16
  256.                 mov     bx,[v86r_flags]
  257.                 mov     ax,[esp+44]
  258.                 and     ax,~8D5h
  259.                 and     bx,8D5h
  260.                 or      ax,bx
  261.                 mov     [esp+44],ax
  262.                 pop     gs
  263.                 pop     fs
  264.                 pop     es
  265.                 pop     ds
  266.                 popad
  267.                 iret
  268. ;═════════════════════════════════════════════════════════════════════════════
  269. int32d1:                                ; VCPI done with pmode call
  270.                 mov     ss,[savedstakseg]
  271.                 pop     W[p_cpmodem2]
  272.                 jmp     int32d2
  273. ;═════════════════════════════════════════════════════════════════════════════
  274. int32d3:                                ; raw/XMS done with pmode call
  275.                 mov     W[c_retreal0m0],c_sicreal
  276.                 mov     ax,cs
  277.                 mov     ds,ax
  278.                 movzx   esp,W[savedstakoff]
  279.                 mov     ss,[savedstakseg]
  280.                 pop     W[p_cpmodem2]
  281.                 jmp     int32d2
  282. ;─────────────────────────────────────────────────────────────────────────────
  283. chek_VCPI:                              ; Chek for VCPI
  284.                 xor     ax,ax
  285.                 mov     gs,ax
  286.                 mov     ax,[gs:67h*4]
  287.                 or      ax,[gs:67h*4+2]
  288.                 jz      short chekVCPIa
  289.                 mov     ax,0DE00h
  290.                 int     67h
  291.                 or      ah,ah
  292.                 clc
  293.                 jz      short chekVCPId
  294. chekVCPIa:
  295.                 stc
  296. chekVCPId:
  297.                 ret
  298. ;─────────────────────────────────────────────────────────────────────────────
  299. chek_processor:                         ; Detect if current processor 386
  300.                 pushf
  301.                 xor     ah,ah
  302.                 push    ax
  303.                 popf
  304.                 pushf
  305.                 pop     ax
  306.                 and     ah,0F0h
  307.                 cmp     ah,0F0h
  308.                 je      short detectno386
  309.                 mov     ah,0F0h
  310.                 push    ax
  311.                 popf
  312.                 pushf
  313.                 pop     ax
  314.                 and     ah,0F0h
  315.                 jz      short detectno386
  316.                 popf
  317.                 ret
  318. detectno386:
  319.                 mov     dx,errmsg0
  320.                 jmp     short exit16err
  321. ;─────────────────────────────────────────────────────────────────────────────
  322. chek_V86:                               ; Chek if already in V86 mode
  323.                 smsw    ax
  324.                 test    al,1
  325.                 mov     dx,errmsg2
  326.                 jnz     short exit16err
  327.                 ret
  328. ;─────────────────────────────────────────────────────────────────────────────
  329. pregetlomem:                            ; Get low memory or abort
  330.                 add     eax,[_lomembase]
  331.                 mov     ebx,[_lomemtop]
  332.                 cmp     eax,ebx
  333.                 ja      short pregetlomema
  334.                 mov     ecx,eax
  335.                 xchg    eax,[_lomembase]
  336.                 sub     ebx,ecx
  337.                 cmp     ebx,LOWMIN*1024
  338.                 jb      short pregetlomema
  339.                 ret
  340. pregetlomema:
  341.                 mov     dx,errmsg1
  342. ;─────────────────────────────────────────────────────────────────────────────
  343. exit16err:                              ; Exit program with message
  344.                 mov     ah,9
  345.                 int     21h
  346.                 jmp     [exitrout]
  347. ;-----------------------------------------------------------------------------
  348. exit:                                   ; Guess what???
  349.                 movzx   esp,sp
  350.                 mov     ah,4Ch
  351.                 mov     al,[_exitcode]
  352.                 int     21h
  353. ;═════════════════════════════════════════════════════════════════════════════
  354. ..start:                                ; Program begins here
  355.                 cli
  356.                 mov     ax,stack
  357.                 mov     ss,ax
  358.                 mov     esp,STAKSIZE*16
  359.  
  360.                 cld
  361.                 push    cs
  362.                 pop     ds
  363.  
  364.                 call    chek_processor          ; is it at least a 386¿
  365.  
  366.                 mov     ax,es                   ; set up a bunch of pointers
  367.                 movzx   eax,ax
  368.                 shl     eax,4
  369.                 mov     [_pspa],eax
  370.                 mov     ax,cs
  371.                 movzx   eax,ax
  372.                 shl     eax,4
  373.                 mov     [_code16a],eax
  374.                 or      [gdt32code16+2],eax
  375.                 or      [gdt32data16+2],eax
  376.                 mov     bx,cs
  377.                 movzx   ebx,bx
  378.                 shl     ebx,4
  379.                 mov     [_code32a],ebx
  380.                 or      [gdt32code32+2],ebx
  381.                 or      [gdt32data32+2],ebx
  382.                 add     [c_gdt32addx+2],ebx
  383.                 mov     ax,ss
  384.                 movzx   eax,ax
  385.                 shl     eax,4
  386.                 sub     eax,ebx
  387.                 mov     [_lomembase],eax
  388.                 mov     [realstackbase],eax
  389.                 movzx   eax,W[es:2]
  390.                 shl     eax,4
  391.                 sub     eax,ebx
  392.                 mov     [_lomemtop],eax
  393.  
  394.                 mov     eax,STAKSIZE*16         ; get stack memory
  395.                 call    pregetlomem
  396.  
  397.                 push    es                      ; save PSP seg (DPMI chek kills ES)
  398.                 pop     fs
  399.  
  400.                 call    chek_VCPI               ; chek for VCPI
  401.                 jnc     near v_start
  402.  
  403.                 mov     ax,1687h                ; chek for DPMI
  404.                 int     2Fh
  405.                 or      ax,ax
  406.                 jz      near d_start
  407.  
  408.                 call    chek_V86                ; chek for V86 mode
  409.  
  410.                 mov     ax,4300h                ; chek for XMS
  411.                 int     2Fh
  412.                 cmp     al,80h
  413.                 je      near x_start
  414.  
  415.                 jmp     c_start                 ; custom system start
  416. ;─────────────────────────────────────────────────────────────────────────────
  417. enableA20:                              ; hardware enable gate A20
  418.                 xor     ax,ax
  419.                 mov     fs,ax
  420.                 dec     ax
  421.                 mov     gs,ax
  422.                 call    testA20
  423.                 je      short enableA20done
  424.                 in      al,92h                  ; PS/2 A20 enable
  425.                 or      al,2
  426.                 jmp     short $+2
  427.                 jmp     short $+2
  428.                 jmp     short $+2
  429.                 out     92h,al
  430.                 call    testA20
  431.                 je      short enableA20done
  432.                 call    enableA20o1             ; AT A20 enable
  433.                 jnz     short enableA20wait
  434.                 mov     al,0D1h
  435.                 out     64h,al
  436.                 call    enableA20o1
  437.                 jnz     short enableA20wait
  438.                 mov     al,0dfh
  439.                 out     60h,al
  440.                 push    W enableA20wait
  441. enableA20o1:
  442.                 mov     ecx,20000h
  443. enableA20o1l:
  444.                 jmp     short $+2
  445.                 jmp     short $+2
  446.                 jmp     short $+2
  447.                 in      al,64h
  448.                 test    al,2
  449.                 loopnz  enableA20o1l
  450. enableA20done:
  451.                 ret
  452. ;-----------------------------------------------------------------------------
  453. enableA20wait:                          ; wait for A20
  454.                 mov     al,36h
  455.                 out     43h,al
  456.                 xor     al,al
  457.                 out     40h,al
  458.                 out     40h,al
  459.                 mov     cx,800h
  460. enableA20waitl0:
  461.                 call    testA20
  462.                 je      enableA20done
  463.                 in      al,40h
  464.                 in      al,40h
  465.                 mov     ah,al
  466. enableA20waitl1:
  467.                 in      al,40h
  468.                 in      al,40h
  469.                 cmp     al,ah
  470.                 je      enableA20waitl1
  471.                 loop    enableA20waitl0
  472.                 mov     dx,errmsg4
  473.                 jmp     exit16err
  474. ;-----------------------------------------------------------------------------
  475. testA20:                                ; Test for enabled A20
  476.                 mov     al,[fs:0]
  477.                 mov     ah,al
  478.                 not     al
  479.                 mov     [gs:10h],al
  480.                 cmp     ah,[fs:0]
  481.                 mov     [fs:0],ah
  482.                 ret
  483. ;─────────────────────────────────────────────────────────────────────────────
  484. ; BL=low PIC val, BH=high PIC val
  485. setintslots:                            ; set int nums in table to PIC vals
  486.                 mov     edi,intslottbl
  487.                 mov     cl,8
  488. setintslotsl0:
  489.                 mov     [di],bl
  490.                 inc     di
  491.                 inc     bl
  492.                 dec     cl
  493.                 jnz     setintslotsl0
  494.                 mov     cl,8
  495. setintslotsl1:
  496.                 mov     [di],bh
  497.                 inc     di
  498.                 inc     bh
  499.                 dec     cl
  500.                 jnz     setintslotsl1
  501.                 ret
  502.  
  503. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  504. ; 16 bit DPMI system data
  505. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  506. d_errmsg0       db 'DPMI host is not 32bit!!!',7,'$'
  507. d_errmsg1       db 'Ran out of DPMI descriptors!!!',7,'$'
  508. d_errmsg2       db 'Could not set DPMI descriptors as needed!!!',7,'$'
  509. d_errmsg3       db 'Could not enter 32bit protected mode!!!',7,'$'
  510.  
  511. d_enterpmode    dw ?,?          ; DPMI switch to pmode addx
  512. d_pspsel        dw ?            ; stupid PSP selector
  513. d_oldenvsegsel  dw ?            ; stupid selector we dont want
  514.  
  515. d_switchaddx    dd ?            ; switch to pmode addx
  516. d_saveaddx      dd ?            ; save/restore state addx
  517.  
  518. d_nintoff       dd dp_irq0,  dp_irq1,  dp_irq2,  dp_irq3
  519.                 dd dp_irq4,  dp_irq5,  dp_irq6,  dp_irq7
  520.                 dd dp_irq8,  dp_irq9,  dp_irqa,  dp_irqb
  521.                 dd dp_irqc,  dp_irqd,  dp_irqe,  dp_irqf
  522.                 dd dp_int33, dp_int32
  523.  
  524. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  525. ; 16 bit DPMI system code
  526. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  527. ;═════════════════════════════════════════════════════════════════════════════
  528. d_retreal:                              ; Return to real mode
  529.                 mov     ax,0205h        ; restore all int vectors needed
  530.                 mov     edi,17
  531. d_retreall0:
  532.                 mov     bl,[intslottbl+edi]
  533.                 lea     ebp,[edi*3]
  534.                 mov     edx,D[ds:dp_ointbuf+ebp*2]
  535.                 mov     cx,W[ds:dp_ointbuf+ebp*2+4]
  536.                 int     31h
  537.                 sub     di,1
  538.                 jnc     d_retreall0
  539.                 jmp     short d_exit
  540. ;─────────────────────────────────────────────────────────────────────────────
  541. d_exit16err:                            ; DPMI Exit with error message
  542.                 mov     W[v86r_ds],code
  543.                 mov     B[v86r_ah],9
  544.                 mov     ax,0300h
  545.                 mov     bx,21h
  546.                 xor     cx,cx
  547.                 mov     edi,v86r_edi
  548.                 push    ds
  549.                 pop     es
  550.                 int     31h
  551. ;─────────────────────────────────────────────────────────────────────────────
  552. d_exit:                                 ; DPMI exit to real mode
  553.                 mov     es,[d_pspsel]           ; restore env selector
  554.                 mov     ax,[d_oldenvsegsel]
  555.                 mov     [es:2Ch],ax
  556.                 jmp     exit
  557. ;═════════════════════════════════════════════════════════════════════════════
  558. d_start:                                ; Start in a crappy DPMI system
  559.                 or      B[_sysbyte0],3          ; set system type DPMI byte
  560.  
  561.                 test    bl,1                    ; must be 32bit DPMI
  562.                 mov     dx,d_errmsg0
  563.                 jz      near exit16err
  564.  
  565.                 mov     [d_enterpmode+0],di     ; store enter addx
  566.                 mov     [d_enterpmode+2],es
  567.                 push    W[fs:2Ch]               ; preserve old env seg
  568.  
  569.                 movzx   eax,si                  ; get mem for DPMI blok
  570.                 shl     eax,4
  571.                 call    pregetlomem
  572.                 shr     eax,4
  573.                 add     ax,code
  574.                 mov     es,ax
  575.  
  576.                 mov     ax,1                    ; switch to pmode
  577.                 call    far [d_enterpmode]
  578.                 cli                             ; I don't trust DPMI
  579.                 mov     dx,d_errmsg3
  580.                 jc      near exit16err
  581.                 mov     W[v86r_dx],d_errmsg1    ; prepare for abort maybe
  582.                 pop     ax                      ; swap old env seg with selector
  583.                 xchg    ax,[es:2Ch]
  584.                 mov     [d_oldenvsegsel],ax
  585.                 mov     [d_pspsel],es           ; store stupid selectors
  586.                 mov     [data16sel],ds
  587.                 mov     [code16sel],cs
  588.                 mov     W[code16off],d_retreal   ; set return to real mode addx
  589.                 mov     D[_setirqvect],dp_setirqvect    ; modify some crap
  590.                 mov     D[_getirqvect],dp_getirqvect
  591.                 mov     D[_setselector],dp_setselector
  592.  
  593.                 push    ds                      ; no more need for PSP
  594.                 pop     es
  595.                 mov     ax,0003h                ; get selector increment value
  596.                 int     31h
  597.                 mov     bx,ax
  598.                 xor     ax,ax                   ; get needed selectors
  599.                 mov     cx,3+SELECTORS
  600.                 int     31h
  601.                 jc      near d_exit16err
  602.  
  603.                 mov     si,ax                   ; set up descriptors
  604.                 mov     [_selcode],ax
  605.                 lea     ecx,[eax+ebx]
  606.                 mov     [_seldata],cx
  607.                 lea     ebp,[ecx+ebx]
  608.                 mov     [_selzero],bp
  609.                 lea     eax,[ebp+ebx]
  610.  
  611.                 mov     [selectorbase],ax
  612.                 mov     [selectorinc],bx
  613.  
  614.                 mov     W[v86r_dx],d_errmsg2
  615.                 mov     ax,0Ch                  ; set descriptors from GDT
  616.                 mov     bx,si
  617.                 mov     edi,gdt32code32
  618.                 or      B[edi+5],01100000b      ; set DPL to 3
  619.                 int     31h
  620.                 jc      near d_exit16err
  621.                 mov     bx,cx
  622.                 mov     edi,gdt32data32
  623.                 or      B[edi+5],01100000b
  624.                 int     31h
  625.                 jc      near d_exit16err
  626.                 mov     bx,bp
  627.                 mov     edi,gdt32zero32
  628.                 or      B[edi+5],01100000b
  629.                 int     31h
  630.                 jc      near d_exit16err
  631.  
  632.                 mov     bx,[selectorbase]       ; set up extra allocatable selectors
  633.                 mov     dx,SELECTORS
  634. d_startl1:
  635.                 int     31h                     ; initialize them all as gdt32zero32
  636.                 jc      near d_exit16err
  637.                 add     bx,[selectorinc]
  638.                 dec     dx
  639.                 jnz     d_startl1
  640.  
  641.                 mov     es,cx                   ; ES, FS, and GS what they should be
  642.                 mov     fs,cx
  643.                 mov     gs,bp
  644.  
  645.                 mov     edi,[_lomembase]        ; chek and get extended memory
  646.                 mov     eax,[_lomemtop]
  647.                 sub     eax,edi
  648.                 cmp     eax,48                  ; 30h-byte buffer
  649.                 mov     W[v86r_dx],errmsg1
  650.                 jb      near d_exit16err
  651.                 mov     ax,0500h
  652.                 int     31h
  653.                 mov     edx,[es:edi]
  654.                 mov     W[v86r_dx],errmsg3
  655.                 jmp     short d_startf0
  656. d_startl2:
  657.                 sub     edx,4096
  658.                 jnc     short d_startf0
  659.                 xor     edx,edx
  660. d_startf0:
  661.                 mov     eax,edx
  662.                 shr     eax,10
  663.                 cmp     eax,EXTMIN
  664.                 jb      near d_exit16err
  665.                 or      edx,edx
  666.                 jz      short d_startf1
  667.                 mov     cx,dx
  668.                 shld    ebx,edx,16
  669.                 mov     ax,0501h
  670.                 int     31h
  671.                 jc      d_startl2
  672.                 shl     ebx,16
  673.                 mov     bx,cx
  674.                 sub     ebx,[_code32a]
  675.                 mov     [_himembase],ebx
  676.                 add     ebx,edx
  677.                 mov     [_himemtop],ebx
  678. d_startf1:
  679.  
  680.                 mov     ax,0305h                ; get save/restore state addxs
  681.                 int     31h
  682.                 mov     [dp_savelen],ax
  683.                 mov     [dp_saveaddx+0],edi
  684.                 mov     [dp_saveaddx+4],si
  685.                 mov     [d_saveaddx+0],cx
  686.                 mov     [d_saveaddx+2],bx
  687.                 mov     ax,0306h                ; get switch mode addxs
  688.                 int     31h
  689.                 mov     [dp_switchaddx+0],edi
  690.                 mov     [dp_switchaddx+4],si
  691.                 mov     [d_switchaddx+0],cx
  692.                 mov     [d_switchaddx+2],bx
  693.  
  694.                 mov     ax,0400h                ; set IRQ handlers to PIC values
  695.                 int     31h
  696.                 xchg    dl,dh
  697.                 mov     bx,dx
  698.                 call    setintslots
  699.  
  700.                 mov     ah,2                    ; backup and set all int vectors
  701.                 mov     si,[_selcode]
  702.                 mov     edi,17
  703. d_startl0:
  704.                 mov     bl,[intslottbl+edi]
  705.                 mov     al,4
  706.                 int     31h
  707.                 lea     ebp,[edi*3]
  708.                 mov     [ds:dp_ointbuf+ebp*2],edx
  709.                 mov     [ds:dp_ointbuf+ebp*2+4],cx
  710.                 mov     al,5
  711.                 mov     edx,[d_nintoff+edi*4]
  712.                 mov     cx,si
  713.                 int     31h
  714.                 sub     di,1
  715.                 jnc     d_startl0
  716.  
  717.                 mov     ax,es                   ; set up needed regs & go on to 32bit
  718.                 mov     ss,ax
  719.                 add     esp,[realstackbase]
  720.                 mov     ds,ax
  721.                 push    D[cs:_selcode]
  722.                 push    D p_start
  723.                 db      66h,0CBh                ; 32bit RETF
  724.  
  725. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  726. ; 16bit VCPI system data
  727. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  728. v_errmsg0       db 'Incompatible VCPI PIC mappings!!!',7,'$'
  729.  
  730. v_pagedirseg    dw ?               ; seg of page directory
  731. v_pagebase      dw 0               ; first page of himem (*4)+1000h
  732. v_pagetop       dw 0               ; top page of himem (*4)+1000h
  733.  
  734. v_ss_cr3        dd ?               ; new CR3 for pmode (physical)
  735. v_ss_gdtaddxptr dw c_gdt32addx,0   ; ptr to GDT data for pmode
  736. v_ss_idtaddxptr dw c_idt32addx,0   ; ptr to IDT data for pmode
  737. v_ss_ldtsel     dw 0               ; don't need no stinkin LDTs
  738. v_ss_trsel      dw 30h             ; task state segment selector
  739. v_ss_dest       dd ?               ; start in pmode EIP
  740.                 dw 20h             ; start in pmode CS
  741. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  742. ; 16bit VCPI system code
  743. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  744. ;═════════════════════════════════════════════════════════════════════════════
  745. v_retreal:                              ; VCPI return to real mode
  746.                 movzx   edi,W[exitrout]
  747.                 mov     esi,esp
  748.                 sub     esi,[realstackbase]
  749.                 mov     cx,code
  750. ;═════════════════════════════════════════════════════════════════════════════
  751. ; EDI=offset to jump to, ESI=real mode stack ptr, CX=real mode DS
  752. v_retreal0:                             ; VCPI go to real mode
  753.                 sub     esp,8
  754.                 push    ecx
  755.                 push    D[v86r_es]
  756.                 dw      06866h,stack,0          ; PUSH dword codeend
  757.                 push    esi
  758.                 pushfd
  759.                 dw      06866h,code,0           ; PUSH dword code16
  760.                 push    edi
  761.                 mov     ax,gs
  762.                 mov     ds,ax
  763.                 mov     ax,0DE0Ch
  764.                 call    D far [cs:vp_vcpipmentry]
  765. ;─────────────────────────────────────────────────────────────────────────────
  766. v_exit:                                 ; VCPI exit (clean up pages)
  767.                 mov     es,[v_pagedirseg]
  768.                 mov     si,[v_pagebase]
  769.                 mov     cx,[v_pagetop]
  770.                 sub     cx,si
  771.                 jbe     short v_exitf0
  772. v_exitl0:
  773.                 mov     edx,[es:si]
  774.                 and     dx,0F000h
  775.                 mov     ax,0DE05h
  776.                 int     67h
  777.                 add     si,4
  778.                 sub     cx,4
  779.                 jnz     v_exitl0
  780. v_exitf0:
  781.                 jmp     exit
  782. ;─────────────────────────────────────────────────────────────────────────────
  783. v_exiterr1:                             ; VCPI not enough low mem exit
  784.                 mov     dx,errmsg1
  785.                 jmp     exit16err
  786. ;═════════════════════════════════════════════════════════════════════════════
  787. v_start:                                ; start continues from VCPI
  788.                 or      B[_sysbyte0],2          ; set system type VCPI byte
  789.                 mov     W[code16off],v_retreal  ; VCPI return to real mode
  790.                 mov     D[c_idt32handler+40h],vp_int33  ; VCPI safe int handlers
  791.                 mov     D[c_idt32handler+44h],vp_int32
  792.                 mov     D[cp_v86irqintr],vp_int33f0     ; VCPI IRQ safe int routine
  793.                 mov     W[int32m0],VINT32               ; VCPI real INT32
  794.  
  795.                 mov     ax,0DE0Ah               ; get PIC mappings
  796.                 int     67h
  797.                 mov     bh,cl
  798.                 mov     dx,v_errmsg0            ; chek for compatible PIC mapping
  799.                 cmp     bl,bh
  800.                 je      near exit16err
  801.                 cmp     bl,30h
  802.                 je      near exit16err
  803.                 cmp     bh,30h
  804.                 je      near exit16err
  805.                 mov     ax,70h                  ; compatible, get highest needed num
  806.                 cmp     al,bl
  807.                 ja      short v_startf1
  808.                 mov     al,bl
  809. v_startf1:
  810.                 cmp     al,bh
  811.                 ja      short v_startf2
  812.                 mov     al,bh
  813. v_startf2:
  814.                 add     al,7
  815.                 mov     [c_numofintvects],al
  816.                 lea     eax,[eax*8+7]           ; set limit of IDT
  817.                 mov     [c_idt32addx],ax
  818.                 call    setintslots             ; set int slots needed
  819.                 movzx   eax,ax
  820.                 add     eax,2068h+1
  821.                 call    pregetlomem             ; allocate TSS, IO bitmap, and IDT
  822.                 mov     [cp_tssesp0ptr],eax
  823.                 mov     eax,[_code16a]          ; adjust mode switch structure
  824.                 add     [v_ss_gdtaddxptr],eax
  825.                 add     [v_ss_idtaddxptr],eax
  826.  
  827.                 mov     W[exitrout],v_exit      ; set VCPI cleanup exit
  828.  
  829.                 mov     eax,[_lomembase]        ; align lomem base on a page
  830.                 mov     ebx,[_code32a]
  831.                 add     ebx,eax
  832.                 lea     ecx,[ebx+0FFFh]
  833.                 and     ecx,0FFFFF000h
  834.                 sub     ebx,ecx
  835.                 sub     eax,ebx
  836.                 mov     [_lomembase],eax
  837.                 mov     ebp,[_lomemtop]         ; get available low memory
  838.                 sub     ebp,eax
  839.                 sub     ebp,LOWMIN*1024         ; die if not enough
  840.                 jc      near v_exiterr1
  841.                 cmp     ebp,8192
  842.                 jb      near v_exiterr1
  843.  
  844.                 shld    eax,ecx,28              ; get segment and clear all pages
  845.                 mov     [v_pagedirseg],ax
  846.                 mov     es,ax
  847.                 xor     di,di
  848.                 mov     cx,2048
  849.                 xor     eax,eax
  850.                 rep     stosd
  851.                 mov     di,1000h                ; get VCPI pmode interface
  852.                 mov     esi,gdt32vcpi
  853.                 mov     ax,0DE01h
  854.                 int     67h
  855.                 mov     [vp_vcpipmentry],ebx
  856.  
  857.                 mov     [v_pagebase],di         ; set up and go through allocation
  858.                 mov     [v_pagetop],di
  859.                 movzx   eax,di
  860.                 sub     eax,1000h
  861.                 shl     eax,10
  862.                 sub     eax,[_code32a]
  863.                 mov     [_himembase],eax
  864.                 mov     ebx,8192
  865. v_startl2:
  866.                 mov     ax,0DE04h
  867.                 int     67h
  868.                 or      ah,ah
  869.                 jnz     short v_startl2d
  870.                 test    di,0FFFh
  871.                 jnz     short v_startf4
  872.                 add     ebx,4096
  873.                 cmp     ebx,ebp
  874.                 jbe     short v_startf4
  875.                 mov     [v_pagetop],di
  876.                 mov     ax,0DE05h
  877.                 int     67h
  878.                 jmp     v_exiterr1
  879. v_startf4:
  880.                 and     dx,0F000h
  881.                 or      dl,7
  882.                 mov     [es:di],edx
  883.                 add     di,4
  884.                 jnc     v_startl2
  885. v_startl2d:
  886.                 mov     [v_pagetop],di
  887.                 lea     si,[di-1000h]
  888.                 movzx   eax,si
  889.                 shl     eax,10
  890.                 sub     eax,[_code32a]
  891.                 mov     [_himemtop],eax
  892.                 sub     di,[v_pagebase]
  893.                 cmp     di,EXTMIN
  894.                 mov     dx,errmsg3
  895.                 jb      near exit16err
  896.                 add     [_lomembase],ebx
  897.  
  898.                 movzx   ebx,W[v_pagedirseg]     ; set up physical addresses
  899.                 shr     ebx,8
  900.                 mov     eax,[es:ebx*4+1000h]
  901.                 mov     [v_ss_cr3],eax
  902.                 xor     di,di
  903. v_startl3:
  904.                 inc     ebx
  905.                 mov     eax,[es:ebx*4+1000h]
  906.                 and     ax,0F000h
  907.                 or      al,7
  908.                 stosd
  909.                 sub     si,1000h
  910.                 ja      v_startl3
  911.  
  912.                 mov     edi,c_startf1           ; offset to jump to in pmode
  913.                 mov     ebx,[cp_tssesp0ptr]
  914.                 jmp     v_switchtopmode         ; duh?
  915.  
  916. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  917. ; 16 bit XMS system data
  918. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  919. x_calladdx      dd ?                    ; XMS driver addx
  920. x_handle        dw 0FEDCh               ; XMS handle of extended memory
  921. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  922. ; 16 bit XMS system code
  923. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  924. ;─────────────────────────────────────────────────────────────────────────────
  925. x_exit:                                 ; XMS exit (clean up allocation)
  926.                 mov     ax,cs
  927.                 mov     ds,ax
  928.                 mov     dx,[x_handle]
  929.                 mov     ah,0Dh
  930.                 call    far [x_calladdx]
  931.                 mov     ah,0Ah
  932.                 call    far [x_calladdx]
  933.                 jmp     exit
  934. ;─────────────────────────────────────────────────────────────────────────────
  935. x_exiterr5:                             ; exit with error message 5
  936.                 mov     dx,errmsg5
  937.                 jmp     exit16err
  938. ;═════════════════════════════════════════════════════════════════════════════
  939. x_start:                                ; start in an XMS system
  940.                 or      B[_sysbyte0],1          ; set system type XMS byte
  941.  
  942.                 mov     ax,4310h                ; get XMS driver addx
  943.                 int     2Fh
  944.                 mov     [x_calladdx+0],bx
  945.                 mov     [x_calladdx+2],es
  946.  
  947.                 mov     ah,3                    ; XMS enable A20
  948.                 call    far [x_calladdx]
  949.                 or      ax,ax
  950.                 mov     dx,errmsg4
  951.                 jz      near exit16err
  952.  
  953.                 mov     ah,8                    ; chek and get extended memory
  954.                 call    far [x_calladdx]
  955.                 sub     ax,64
  956.                 jnc     short x_startf0
  957.                 xor     ax,ax
  958. x_startf0:
  959.                 cmp     ax,EXTMIN
  960.                 mov     dx,errmsg3
  961.                 jb      near exit16err
  962.                 mov     dx,ax
  963.                 movzx   ecx,ax
  964.                 shl     ecx,10
  965.                 mov     ah,9
  966.                 call    far [x_calladdx]
  967.                 or      ax,ax
  968.                 jz      x_exiterr5
  969.                 mov     [x_handle],dx
  970.                 mov     W[exitrout],x_exit
  971.                 mov     ah,0Ch
  972.                 call    far [x_calladdx]
  973.                 or      ax,ax
  974.                 jz      x_exiterr5
  975.                 shrd    eax,edx,16
  976.                 mov     ax,bx
  977.                 sub     eax,[_code32a]
  978.                 mov     [_himembase],eax
  979.                 add     eax,ecx
  980.                 mov     [_himemtop],eax
  981.  
  982.                 jmp     c_startf0               ; go on to custom start
  983.  
  984. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  985. ; 16 bit custom system data
  986. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  987. c_idt16addx     dw 3FFh, 0,0            ; default real mode IDT addx&limit
  988. c_idt32addx     dw 3BFh, ?,?            ; 32bit IDT addx&limit
  989. c_gdt32addx     dw 04Fh+SELECTORS*8     ; 32bit GDT addx&limit
  990.                 dd gdt32                ;
  991.  
  992. c_numofintvects db 77h                  ; number of int vects needed -1
  993. c_idt32handler  dd cp_irq0,  cp_irq1,  cp_irq2,  cp_irq3
  994.                 dd cp_irq4,  cp_irq5
  995.                 dd cp_irq6,  cp_irq7,  cp_irq8,  cp_irq9
  996.                 dd cp_irqa,  cp_irqb
  997.                 dd cp_irqc,  cp_irqd,  cp_irqe,  cp_irqf
  998.                 dd cp_int33, cp_int32, cp_int31
  999.                 dd cp_exc0,  cp_exc1,  cp_exc2,  cp_exc3
  1000.                 dd cp_exc4,  cp_exc5
  1001.                 dd cp_exc6,  cp_exc7
  1002. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1003. ; 16 bit custom system code
  1004. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1005. ;═════════════════════════════════════════════════════════════════════════════
  1006. c_irqreal:                              ; real mode IRQ
  1007.                 pushf
  1008.                 push    cs
  1009.                 push    W icreald2
  1010.                 jmp     icreal
  1011. ;-----------------------------------------------------------------------------
  1012. c_retreal1:                             ; load some real mode stuff & exit
  1013.                 mov     ax,stack
  1014.                 mov     ss,ax
  1015.                 mov     esp,STAKSIZE*10h
  1016.                 jmp     [exitrout]
  1017. ;═════════════════════════════════════════════════════════════════════════════
  1018. c_retreal0:                             ; load real mode IDT and set PE=0
  1019.                 mov     ax,28h
  1020.                 mov     ds,ax
  1021.                 mov     es,ax
  1022.                 mov     fs,ax
  1023.                 mov     gs,ax
  1024.                 mov     ss,ax
  1025.                 lidt    [c_idt16addx]
  1026.                 mov     eax,cr0
  1027.                 and     al,0FEh
  1028.                 mov     cr0,eax
  1029.                 db      0EAh            ; JMP FAR PTR c_retreal0m0
  1030. c_retreal0m0    dw      c_sicreal,code
  1031. ;-----------------------------------------------------------------------------
  1032. c_sicreal:                              ; safe real mode int or call
  1033.                 mov     ax,stack
  1034.                 mov     ss,ax
  1035.                 mov     ds,[cs:v86r_ds]
  1036.                 mov     es,[cs:v86r_es]
  1037.                 db      0EAh            ; JMP FAR PTR c_sicrealm0
  1038. c_sicrealm0     dw      ?,code
  1039. ;═════════════════════════════════════════════════════════════════════════════
  1040. c_retreal:                              ; return to real mode
  1041.                 mov     W[c_retreal0m0],c_retreal1
  1042.                 mov     esp,STAKSIZE*10h
  1043.                 jmp     c_retreal0
  1044. ;═════════════════════════════════════════════════════════════════════════════
  1045. c_start:                                ; custom only start
  1046.                 call    enableA20               ; enable that stupid A20 thingy
  1047.  
  1048.                 mov     ah,88h                  ; chek and get extended mem
  1049.                 int     15h
  1050.                 cmp     ax,EXTMIN
  1051.                 mov     dx,errmsg3
  1052.                 jb      near exit16err
  1053.                 movzx   eax,ax
  1054.                 shl     eax,10
  1055.                 mov     ebx,100000h
  1056.                 sub     ebx,[_code32a]
  1057.                 mov     [_himembase],ebx
  1058.                 add     eax,ebx
  1059.                 mov     [_himemtop],eax
  1060. ;═════════════════════════════════════════════════════════════════════════════
  1061. c_startf0:                              ; start continues from custom or XMS
  1062.                 mov     W[int32m0],CINT32       ; raw/XMS real INT32
  1063.                 mov     eax,2428h               ; allocate TSS, IO bitmap, and IDT
  1064.                 call    pregetlomem
  1065.                 mov     ebx,eax
  1066.  
  1067.                 lgdt    [c_gdt32addx]           ; switch to pmode
  1068.                 mov     eax,cr0
  1069.                 or      al,1
  1070.                 mov     cr0,eax
  1071.                 db      0EAh
  1072.                 dw      $+4,20h
  1073. ;-----------------------------------------------------------------------------
  1074. ; EBX->TSS
  1075. c_startf1:                              ; in 16bit pmode
  1076.                 mov     ax,28h                  ; set up segregs
  1077.                 mov     ds,ax
  1078.                 mov     al,18h
  1079.                 mov     gs,ax
  1080.                 mov     al,10h
  1081.                 mov     es,ax
  1082.                 mov     fs,ax
  1083.                 mov     ss,ax
  1084.                 mov     esp,STAKSIZE*16
  1085.                 add     esp,[realstackbase]
  1086.  
  1087.                 mov     W[v_ss_dest+4],8        ; VCPI enter 32bit pmode from now on
  1088.                 lea     eax,[ebx+4]             ; addx of ESP0 in TSS
  1089.                 mov     [cp_tssesp0ptr],eax
  1090.                 mov     ebp,[_code32a]          ; TSS location in mem to GDT
  1091.                 lea     eax,[ebx+ebp]
  1092.                 mov     ecx,gdt32task           ; set up task
  1093.                 or      [ecx+2],eax
  1094.                 mov     B[ecx+5],89h
  1095.                 mov     cx,30h
  1096.                 ltr     cx
  1097.                 add     eax,2068h               ; set up IDT
  1098.                 mov     ecx,c_idt32addx
  1099.                 mov     [ecx+2],eax
  1100.                 lidt    [ecx]
  1101.  
  1102.                 mov     D[es:ebx+8],10h         ; set up TSS stuff (EBX->TSS)
  1103.                 mov     edi,104
  1104.                 mov     [es:ebx+102],di
  1105.                 mov     W[es:ebx+100],0
  1106.                 add     edi,ebx                 ; fill IO bitmap with 0
  1107.                 xor     eax,eax
  1108.                 mov     ecx,800h
  1109.                 a32     rep stosd
  1110.  
  1111.                 mov     [cp_idt32ptr],edi       ; set up blank IDT entries
  1112.                 movzx   esi,B[c_numofintvects]
  1113. c_startl0:                                      ; set up interrupt gates
  1114.                 mov     D[es:edi+esi*8],80000h+cp_excf   ; offset, selector 8h
  1115.                 mov     D[es:edi+esi*8+4],(10001110b<<8) ; P=1, DPL=0
  1116.                 sub     si,1
  1117.                 jnc     c_startl0
  1118.                 mov     si,1Ah                  ; necessary IDT entries
  1119. c_startl1:
  1120.                 movzx   ebp,B[intslottbl+esi]
  1121.                 mov     eax,[c_idt32handler+esi*4]
  1122. c_startl1c:
  1123.                 mov     [es:edi+ebp*8],ax
  1124.                 sub     si,1
  1125.                 jnc     c_startl1
  1126.  
  1127.                 mov     edi,p_start             ; set up regs & go on to 32bit
  1128.                 mov     ax,10h
  1129.                 mov     ds,ax
  1130. ;-----------------------------------------------------------------------------
  1131. c_gotopmode:                            ; jump to 32bit pmode
  1132.                 pushfd                          ; set eflags: NT=0, IOPL=3
  1133.                 pop     eax
  1134.                 and     ah,10111111b            ; NT=0
  1135.                 or      ah,00110000b            ; IOPL=3
  1136.                 push    eax
  1137.                 popfd
  1138.                 dw      6866h,8,0               ; PUSH dword 8
  1139.                 push    edi
  1140.                 db      66h,0CBh                ; 32bit RETF
  1141.  
  1142. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1143. ; 32bit pmode code
  1144. ;▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  1145.  
  1146. bits 32
  1147.  
  1148. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1149. ; 32 bit common system data
  1150. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1151. _lomembase      dd ?                    ; low mem base for allocation
  1152. _lomemtop       dd ?                    ; top of low mem
  1153. _himembase      dd 0                    ; high mem base for allocation
  1154. _himemtop       dd 0                    ; top of high mem
  1155. _pspa           dd ?                    ; offset of start of PSP from 0
  1156. _code16a        dd ?                    ; offset of start of 16bit code from 0
  1157. _code32a        dd ?                    ; offset of start of 32bit code from 0
  1158. _selcode        dw 8                    ; code segment selector
  1159. _seldata        dw 10h                  ; data segment alias for code
  1160. _selzero        dw 18h                  ; data segment starting at 0:0
  1161. _sysbyte0       db 0                    ; system bits:
  1162.                                         ;  0-1: 0=raw, 1=XMS, 2=VCPI, 3=DPMI
  1163. _exitcode       db 0                    ; exit code for int21h ah=4ch
  1164.  
  1165. ALIGNZ(4)
  1166. _getirqvect     dd cp_getirqvect        ; get IRQ handler offset routine addx
  1167. _setirqvect     dd cp_setirqvect        ; set IRQ handler offset routine addx
  1168. _setselector    dd cp_setselector       ; set a selector addx offset addx
  1169.  
  1170.                 ;  /limit15-0\ /base23-0\   /G,X,O,AVL,limit19-16\ /base31-24\
  1171. gdt32           dd 0,0                ; /P,DPL,1,TYPE,A\                 ;  0h
  1172. gdt32code32     db 0FFh, 0FFh, 0, 0, 0,    10011010b,   11001111b,     0 ;  8h
  1173. gdt32data32     db 0FFh, 0FFh, 0, 0, 0,    10010010b,   11001111b,     0 ; 10h
  1174. gdt32zero32     db 0FFh, 0FFh, 0, 0, 0,    10010010b,   11001111b,     0 ; 18h
  1175. gdt32code16     db 0FFh, 0FFh, 0, 0, 0,    10011010b,          0,      0 ; 20h
  1176. gdt32data16     db 0FFh, 0FFh, 0, 0, 0,    10010010b,          0,      0 ; 28h
  1177. gdt32task       db 0FFh, 0FFh, 0, 0, 0,    10001001b,          0,      0 ; 30h
  1178. gdt32vcpi       dd ?,?                                                   ; 38h
  1179.                 dd ?,?                                                   ; 40h
  1180.                 dd ?,?                                                   ; 48h
  1181. gdt32free       times SELECTORS db 0FFh,0FFh, 0,0,0, 10010010b,11001111b, 0
  1182.  
  1183. v86r_edi:                               ; vregs for pmode<>real communication
  1184. v86r_di         dw ?, ?                 ;  needs to stay this way cuz its a
  1185. v86r_esi:                               ;  stupid DPMI structure thingy
  1186. v86r_si         dw ?, ?
  1187. v86r_ebp:
  1188. v86r_bp         dw ?, ?
  1189.                 dd 0
  1190. v86r_ebx:
  1191. v86r_bx:
  1192. v86r_bl         db ?
  1193. v86r_bh         db ?, ?,?
  1194. v86r_edx:
  1195. v86r_dx:
  1196. v86r_dl         db ?
  1197. v86r_dh         db ?, ?,?
  1198. v86r_ecx:
  1199. v86r_cx:
  1200. v86r_cl         db ?
  1201. v86r_ch         db ?, ?,?
  1202. v86r_eax:
  1203. v86r_ax:
  1204. v86r_al         db ?
  1205. v86r_ah         db ?, ?,?
  1206. v86r_flags      dw ?
  1207. v86r_es         dw ?
  1208. v86r_ds         dw ?
  1209. v86r_fs         dw ?
  1210. v86r_gs         dw ?
  1211.                 dd 0,0
  1212.  
  1213. oint1bvect      dd ?                    ; old real int 1Bh vector (ctrl+break)
  1214. oint32vect      dd ?                    ; old real int 32h vector
  1215. oirqmask        dw ?                    ; old port 21h and 0A1h masks
  1216. intslottbl      db 8,9,0Ah,0Bh,0Ch,0Dh,0Eh,0Fh,70h,71h,72h,73h,74h,75h,76h,77h
  1217.                 db 33h,32h,31h,0,1,2,3,4,5,6,7
  1218.  
  1219. selectorbase    dw 50h
  1220. selectorinc     dw 8
  1221. selectorfree    times SELECTORS db 0
  1222.  
  1223. code16off       dw c_retreal            ; offset in 16bit of exit function
  1224. code16sel       dw 20h                  ; 16bit pmode code selector
  1225. data16sel       dw 28h                  ; 16bit pmode data selector
  1226.  
  1227. nextmodestack   dw (STAKSIZE-STAKMAIN)*16       ; stack for next mode switch
  1228. realstackbase   dd ?                    ; linear ptr to beginning of codeend
  1229.  
  1230. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1231. ; 32 bit common system code
  1232. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1233. ;═════════════════════════════════════════════════════════════════════════════
  1234. p_cpmode2:                              ; call pmode from V86
  1235.                 mov     gs,cx
  1236.                 mov     cl,10h
  1237.                 mov     ds,cx
  1238.                 mov     es,cx
  1239.                 mov     fs,cx
  1240.                 sub     W[nextmodestack],STAKPMODE*16
  1241.                 push    W[p_cpmodem2]
  1242.                 mov     W[p_cpmodem2],V86CPMODED
  1243.                 mov     eax,[esp+22]
  1244.                 mov     [p_cpmodem0],eax
  1245.                 mov     al,[esp+43]
  1246.                 shr     al,1
  1247.                 and     al,1
  1248.                 add     al,0FAh
  1249.                 mov     [p_cpmodem1],al
  1250.                 jmp     short p_cpmode
  1251. ;═════════════════════════════════════════════════════════════════════════════
  1252. p_cpmode1:                              ; call pmode, load all
  1253.                 mov     esp,ebx
  1254.                 mov     ax,10h
  1255.                 mov     ds,ax
  1256.                 mov     es,ax
  1257.                 mov     ss,ax
  1258. ;-----------------------------------------------------------------------------
  1259. p_cpmode0:                              ; call pmode, load FS and GS
  1260.                 mov     fs,[_seldata]
  1261.                 mov     gs,[_selzero]
  1262. ;-----------------------------------------------------------------------------
  1263. p_cpmode:                               ; call pmode routine from real
  1264.                 push    D p_cpmoded
  1265.                 cld
  1266.                 mov     eax,[v86r_eax]
  1267.                 mov     ecx,[v86r_ecx]
  1268.                 mov     edx,[v86r_edx]
  1269.                 mov     ebx,[v86r_ebx]
  1270.                 mov     esi,[v86r_esi]
  1271.                 mov     edi,[v86r_edi]
  1272.                 mov     ebp,[v86r_ebp]
  1273.                 db      68h             ; PUSH destination address
  1274. p_cpmodem0      dd      ?               ;
  1275. p_cpmodem1      db      ?               ; CLI or STI
  1276.                 ret
  1277. ;-----------------------------------------------------------------------------
  1278. p_cpmoded:                              ; call to pmode done
  1279.                 cli
  1280.                 pushf
  1281.                 pop     W[v86r_flags]
  1282.                 mov     [v86r_eax],eax
  1283.                 mov     [v86r_ecx],ecx
  1284.                 mov     [v86r_edx],edx
  1285.                 mov     [v86r_ebx],ebx
  1286.                 mov     [v86r_esi],esi
  1287.                 mov     [v86r_edi],edi
  1288.                 mov     [v86r_ebp],ebp
  1289.                 mov     ecx,[_code16a]
  1290. p_cpmodem2:                             ; return to real, modifiable to JMP
  1291. ;-----------------------------------------------------------------------------
  1292.                 movzx   ebx,W[gs:savedstakoff+ecx]  ; DPMI return to real mode
  1293.                 mov     dx,[gs:savedstakseg+ecx]
  1294.                 mov     ax,code
  1295.                 mov     cx,dx
  1296.                 mov     si,ax
  1297.                 mov     edi,int32d0
  1298.                 jmp     D far [dp_switchaddx]
  1299. ;-----------------------------------------------------------------------------
  1300. VCPMODED        equ (($-(p_cpmodem2+2)) << 8) + 0EBh
  1301. p_cpmoded2:                                     ; VCPI done with pmode
  1302.                 movzx   esi,W[gs:savedstakoff+ecx]
  1303.                 mov     cx,code
  1304.                 mov     edi,int32d1
  1305.                 db      0EAh                    ; 16bit JMP FAR 20h:v_retreal0
  1306.                 dw      v_retreal0,0,20h        ;
  1307. ;-----------------------------------------------------------------------------
  1308. CCPMODED        equ (($-(p_cpmodem2+2)) << 8) + 0EBh
  1309. p_cpmoded3:                                     ; raw/XMS done with pmode
  1310.                 mov     W[gs:c_retreal0m0+ecx],int32d3
  1311.                 db      0EAh                    ; 16bit JMP FAR 20h:c_retreal0
  1312.                 dw      c_retreal0,0,20h        ;
  1313. ;-----------------------------------------------------------------------------
  1314. ; if ($-(p_cpmodem2+2)) gt 127 => error
  1315. V86CPMODED      equ (($-(p_cpmodem2+2)) << 8) + 0EBh
  1316. p_cpmoded4:                                     ; V86 done with pmode
  1317.                 pop     W[p_cpmodem2]
  1318.                 jmp     cp_int3_d3
  1319. ;═════════════════════════════════════════════════════════════════════════════
  1320. p_start:                                ; common 32bit start
  1321.                 mov     eax,[gs:1Bh*4]          ; neutralize crtl+break
  1322.                 mov     [oint1bvect],eax
  1323.                 db      65h,67h,0C7h,6  ; MOV DWORD PTR GS:[1bh*4],code16:nullint
  1324.                 dw      1Bh*4,nullint,code      ;
  1325.                 mov     eax,[gs:32h*4]          ; set up for new real mode INT32
  1326.                 mov     [oint32vect],eax
  1327.                 db      65h,67h,0C7h,6  ; MOV DWORD PTR GS:[32h*4],code16:int32
  1328.                 dw      32h*4,int32,code        ;
  1329.                 in      al,21h                  ; save old PIC masks
  1330.                 mov     ah,al
  1331.                 in      al,0A1h
  1332.                 mov     [oirqmask],ax
  1333.                 jmp     _main                   ; go to main code
  1334.  
  1335. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1336. ; Allocate any mem, (first cheks low, then high)
  1337. ; In:
  1338. ;   EAX - size requested
  1339. ; Out:
  1340. ;   CF=0 - memory allocated
  1341. ;   CF=1 - not enough mem
  1342. ;   EAX - linear pointer to mem or ?
  1343. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1344. _getmem:
  1345.                 push    eax
  1346.                 call    _getlomem
  1347.                 jnc     short getmemd
  1348.                 pop     eax
  1349.                 jmp     short _gethimem
  1350. getmemd:
  1351.                 add     esp,4
  1352. _ret:                                   ; generic RET instruction
  1353.                 ret
  1354. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1355. ; Allocate some low mem
  1356. ; In:
  1357. ;   EAX - size requested
  1358. ; Out:
  1359. ;   CF=0 - memory allocated
  1360. ;   CF=1 - not enough mem
  1361. ;   EAX - linear pointer to mem or ?
  1362. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1363. _getlomem:
  1364.                 add     eax,[_lomembase]
  1365.                 cmp     eax,[_lomemtop]
  1366.                 ja      short getmemerr
  1367.                 xchg    eax,[_lomembase]
  1368.                 clc
  1369.                 ret
  1370. getmemerr:
  1371.                 stc
  1372.                 ret
  1373. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1374. ; Allocate some high mem
  1375. ; In:
  1376. ;   EAX - size requested
  1377. ; Out:
  1378. ;   CF=0 - memory allocated
  1379. ;   CF=1 - not enough mem
  1380. ;   EAX - linear pointer to mem or ?
  1381. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1382. _gethimem:
  1383.                 add     eax,[_himembase]
  1384.                 cmp     eax,[_himemtop]
  1385.                 ja      short getmemerr
  1386.                 xchg    eax,[_himembase]
  1387.                 clc
  1388.                 ret
  1389. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1390. ; Get amount of free low mem
  1391. ; Out:
  1392. ;   EAX - number of bytes free
  1393. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1394. _lomemsize:
  1395.                 mov     eax,[_lomemtop]
  1396.                 sub     eax,[_lomembase]
  1397.                 ret
  1398. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1399. ; Get amount of free high mem
  1400. ; Out:
  1401. ;   EAX - number of bytes free
  1402. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1403. _himemsize:
  1404.                 mov     eax,[_himemtop]
  1405.                 sub     eax,[_himembase]
  1406.                 ret
  1407. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1408. ; Get status of IRQ mask bit
  1409. ; In:
  1410. ;   BL - IRQ num (0-15)
  1411. ; Out:
  1412. ;   AL - status: 0=enabled, 1=disabled
  1413. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1414. _getirqmask:
  1415.                 push    ax
  1416.                 in      al,0A1h
  1417.                 mov     ah,al
  1418.                 in      al,21h
  1419.                 xchg    cl,bl
  1420.                 shr     ax,cl
  1421.                 xchg    cl,bl
  1422.                 and     al,1
  1423.                 mov     [esp],al
  1424.                 pop     ax
  1425.                 ret
  1426. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1427. ; Set status of IRQ mask bit
  1428. ; In:
  1429. ;   BL - IRQ num (0-15)
  1430. ;   AL - status: 0=enabled, 1=disabled
  1431. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1432. _setirqmask:
  1433.                 push    ax
  1434.                 push    bx
  1435.                 push    cx
  1436.                 push    dx
  1437.                 mov     cl,bl
  1438.                 mov     bx,0FFFEh
  1439.                 movzx   dx,al
  1440.                 rol     bx,cl
  1441.                 shl     dx,cl
  1442.                 in      al,0A1h
  1443.                 mov     ah,al
  1444.                 in      al,21h
  1445.                 and     ax,bx
  1446.                 or      ax,dx
  1447.                 out     21h,al
  1448.                 mov     al,ah
  1449.                 out     0A1h,al
  1450.                 pop     dx
  1451.                 pop     cx
  1452.                 pop     bx
  1453.                 pop     ax
  1454.                 ret
  1455. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1456. ; Set a real mode IRQ vect to redirect to pmode
  1457. ; In:
  1458. ;   BL - IRQ number
  1459. ;   EDX - offset of IRQ handler
  1460. ;   EDI -> 21 byte buffer for code stub created
  1461. ; Out:
  1462. ;   EAX - old seg:off of real mode IRQ handler
  1463. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1464. rmpmirqsetd0:
  1465. db 66h,52h              ; PUSH EDX
  1466. db 66h,0BAh,?,?,?,?     ; MOV EDX,?
  1467. db 0CDh,32h             ; INT 32h
  1468. db 66h,5Ah              ; POP EDX
  1469. db 0CFh                 ; IRET
  1470. db 9Ch                  ; PUSHFD
  1471. db 0Eh                  ; PUSH CS
  1472. db 0E8h,?,?,?,?         ; CALL ?
  1473. db 0C3h                 ; RET
  1474. ;-----------------------------------------------------------------------------
  1475. _rmpmirqset:
  1476.                 push    esi
  1477.                 push    edi
  1478.                 mov     esi,rmpmirqsetd0
  1479.                 lea     eax,[edi+13]
  1480.                 mov     [esi+4],eax
  1481.                 add     eax,7
  1482.                 sub     eax,edx
  1483.                 neg     eax
  1484.                 mov     [esi+16],eax
  1485.                 mov     eax,edi
  1486.                 movsd
  1487.                 movsd
  1488.                 movsd
  1489.                 movsd
  1490.                 movsd
  1491.                 movsb
  1492.                 add     eax,[_code32a]
  1493.                 shl     eax,12
  1494.                 shr     ax,12
  1495.                 movzx   edi,bl
  1496.                 cmp     edi,8
  1497.                 jb      short rmpmirqsetf0
  1498.                 add     edi,60h
  1499. rmpmirqsetf0:
  1500.                 xchg    eax,[gs:edi*4+20h]
  1501.                 pop     edi
  1502.                 pop     esi
  1503.                 ret
  1504. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1505. ; Reset a real more IRQ vect back to normal (just sets real mode IRQ vect)
  1506. ; In:
  1507. ;   BL - IRQ number
  1508. ;   EAX - seg:off of real mode IRQ handler
  1509. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1510. _rmpmirqfree:
  1511.                 push    ebx
  1512.                 movzx   ebx,bl
  1513.                 cmp     bl,8
  1514.                 jb      short rmpmirqfreef0
  1515.                 add     bl,60h
  1516. rmpmirqfreef0:
  1517.                 mov     [gs:ebx*4+20h],eax
  1518.                 pop     ebx
  1519.                 ret
  1520. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1521. ; Allocate a selector
  1522. ; Out:
  1523. ;   CF=1 - selector not allocated
  1524. ;   CF=0 - selector allocated
  1525. ;   AX - 4G data selector or ?
  1526. ; Notes:
  1527. ;   The selector returned is for a 4G r/w data segment with an undefined base
  1528. ;    address.
  1529. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1530. _getselector:
  1531.                 push    ecx
  1532.                 push    edi
  1533.                 mov     edi,selectorfree
  1534.                 mov     ecx,SELECTORS
  1535.                 mov     al,0
  1536.                 repne   scasb
  1537.                 jne     short getselectorf0
  1538.                 mov     B[edi-1],1
  1539.                 sub     ecx,SELECTORS-1
  1540.                 neg     ecx
  1541.                 imul    cx,[selectorinc]
  1542.                 mov     ax,[selectorbase]
  1543.                 add     ax,cx
  1544.                 clc
  1545.                 jmp     short getselectorf1
  1546. getselectorf0:
  1547.                 stc
  1548. getselectorf1:
  1549.                 pop     edi
  1550.                 pop     ecx
  1551.                 ret
  1552. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1553. ; Free an allocated selector
  1554. ; In:
  1555. ;   AX - selector
  1556. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1557. _freeselector:
  1558.                 push    eax
  1559.                 push    dx
  1560.                 sub     ax,[selectorbase]
  1561.                 xor     dx,dx
  1562.                 div     W[selectorinc]
  1563.                 movzx   eax,ax
  1564.                 mov     B[selectorfree+eax],0
  1565.                 pop     dx
  1566.                 pop     eax
  1567.                 ret
  1568. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1569. ; Exit to real mode
  1570. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1571. _exit:
  1572.                 cli
  1573.                 mov     eax,[oint1bvect]        ; restore ctrl+break
  1574.                 mov     [gs:1Bh*4],eax
  1575.                 mov     eax,[oint32vect]        ; restore real mode int 32h vector
  1576.                 mov     [gs:32h*4],eax
  1577.                 mov     ax,[oirqmask]           ; restore PIC masks
  1578.                 out     0A1h,al
  1579.                 mov     al,ah
  1580.                 out     21h,al
  1581.                 push    W[code16sel]            ; go to 16bit pmode exit code
  1582.                 push    W[code16off]
  1583.                 mov     ds,[data16sel]
  1584.                 db      66h,0CBh        ; 16bit RETF
  1585.  
  1586. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1587. ; 32 bit DPMI system data
  1588. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1589. dp_switchaddx   dw ?,?,?                ; switch to real mode addx
  1590. dp_saveaddx     dw ?,?,?                ; save/restore state addx
  1591. dp_savelen      dw 0,0                  ; length of state buffer
  1592. dp_savedstaksel dw ?                    ; current saved stack selector
  1593.  
  1594. dp_ointbuf      times 18 dw ?,?,?       ; saved interrupt addx buffer
  1595. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1596. ; 32 bit DPMI system code
  1597. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1598. ;═════════════════════════════════════════════════════════════════════════════
  1599. dp_int32:                               ; DPMI INT32/34: CX:DX=seg:off
  1600.                 pushad
  1601.                 shl     ecx,16
  1602.                 mov     cx,dx
  1603.                 mov     bp,callreal
  1604.                 mov     dl,1
  1605.                 jmp     short dp_int3_
  1606. ;═════════════════════════════════════════════════════════════════════════════
  1607. dp_int33:                               ; DPMI INT33/35: AL=int num
  1608.                 pushad
  1609.                 movzx   eax,al
  1610.                 mov     ecx,[gs:eax*4]
  1611.                 mov     bp,intreal
  1612.                 xor     dl,dl
  1613. ;-----------------------------------------------------------------------------
  1614. dp_int3_:                               ; DPMI int or call to real mode
  1615.                 mov     ax,0900h
  1616.                 int     31h
  1617.                 push    ax
  1618.                 and     al,dl
  1619.                 add     al,0FAh
  1620.                 mov     ebx,[_code16a]
  1621.                 mov     [gs:icrealm0+ebx],al
  1622.                 mov     [gs:icrealm1+ebx],ecx
  1623.                 push    D[cp_savedstakoff]
  1624.                 push    W[dp_savedstaksel]
  1625.                 movzx   ebx,W[nextmodestack]
  1626.                 lea     eax,[ebx-STAKRMODE*16]
  1627.                 mov     [nextmodestack],ax
  1628.                 mov     ax,ss
  1629.                 mov     es,ax
  1630.                 sub     esp,[dp_savelen]
  1631.                 mov     edi,esp
  1632.                 xor     al,al
  1633.                 call    D far [dp_saveaddx]
  1634.                 mov     [cp_savedstakoff],esp
  1635.                 mov     [dp_savedstaksel],ss
  1636.                 mov     dx,stack
  1637.                 mov     ax,[v86r_ds]
  1638.                 mov     cx,[v86r_es]
  1639.                 movzx   edi,bp
  1640.                 mov     si,code
  1641.                 jmp     D far [dp_switchaddx]
  1642. ;-----------------------------------------------------------------------------
  1643. dp_int3_d:                              ; done with real mode int or call
  1644.                 mov     edi,esp
  1645.                 mov     al,1
  1646.                 call    D far [dp_saveaddx]
  1647.                 add     esp,[dp_savelen]
  1648.                 pop     W[dp_savedstaksel]
  1649.                 pop     D[cp_savedstakoff]
  1650.                 add     W[nextmodestack],STAKRMODE*16
  1651.                 mov     bx,[v86r_flags]
  1652.                 pop     ax
  1653.                 int     31h
  1654.                 mov     ax,ds
  1655.                 mov     es,ax
  1656.                 mov     fs,ax
  1657.                 mov     gs,[_selzero]
  1658.                 jmp     cp_int3_d2
  1659. ;═════════════════════════════════════════════════════════════════════════════
  1660. ; DPMI IRQ redirectors (needed to make all IRQ vector selectors = CS)
  1661. dp_irq0:        jmp     D far [cs:dp_ointbuf+0]
  1662. dp_irq1:        jmp     D far [cs:dp_ointbuf+6]
  1663. dp_irq2:        jmp     D far [cs:dp_ointbuf+12]
  1664. dp_irq3:        jmp     D far [cs:dp_ointbuf+18]
  1665. dp_irq4:        jmp     D far [cs:dp_ointbuf+24]
  1666. dp_irq5:        jmp     D far [cs:dp_ointbuf+30]
  1667. dp_irq6:        jmp     D far [cs:dp_ointbuf+36]
  1668. dp_irq7:        jmp     D far [cs:dp_ointbuf+42]
  1669. dp_irq8:        jmp     D far [cs:dp_ointbuf+48]
  1670. dp_irq9:        jmp     D far [cs:dp_ointbuf+54]
  1671. dp_irqa:        jmp     D far [cs:dp_ointbuf+60]
  1672. dp_irqb:        jmp     D far [cs:dp_ointbuf+66]
  1673. dp_irqc:        jmp     D far [cs:dp_ointbuf+72]
  1674. dp_irqd:        jmp     D far [cs:dp_ointbuf+78]
  1675. dp_irqe:        jmp     D far [cs:dp_ointbuf+84]
  1676. dp_irqf:        jmp     D far [cs:dp_ointbuf+90]
  1677.  
  1678. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1679. ; DPMI get IRQ handler offset
  1680. ; In:
  1681. ;   BL - IRQ num (0-0fh)
  1682. ; Out:
  1683. ;   EDX - offset of IRQ handler
  1684. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1685. dp_getirqvect:
  1686.                 push    ax
  1687.                 push    ebx
  1688.                 push    cx
  1689.                 movzx   ebx,bl
  1690.                 mov     bl,[intslottbl+ebx]
  1691.                 mov     ax,0204h
  1692.                 int     31h
  1693.                 pop     cx
  1694.                 pop     ebx
  1695.                 pop     ax
  1696.                 ret
  1697. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1698. ; DPMI set IRQ handler offset
  1699. ; In:
  1700. ;   BL - IRQ num (0-0fh)
  1701. ;   EDX - offset of IRQ handler
  1702. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1703. dp_setirqvect:
  1704.                 push    ax
  1705.                 push    ebx
  1706.                 push    cx
  1707.                 movzx   ebx,bl
  1708.                 mov     bl,[intslottbl+ebx]
  1709.                 mov     cx,cs
  1710.                 mov     ax,0205h
  1711.                 int     31h
  1712.                 pop     cx
  1713.                 pop     ebx
  1714.                 pop     ax
  1715.                 ret
  1716. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1717. ; Set the base addx for a selector
  1718. ; In:
  1719. ;   AX - selector
  1720. ;   EDX - linear base addx for selector
  1721. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  1722. dp_setselector:
  1723.                 push    ax
  1724.                 push    bx
  1725.                 push    ecx
  1726.                 shld    ecx,edx,16
  1727.                 mov     bx,ax
  1728.                 mov     ax,7
  1729.                 int     31h
  1730.                 pop     ecx
  1731.                 pop     bx
  1732.                 pop     ax
  1733.                 ret
  1734.  
  1735. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1736. ; 32 bit custom/XMS/VCPI system data
  1737. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1738. vp_vcpipmentry  dw 0,0,38h              ; VCPI entry point in pmode
  1739.  
  1740. cp_tssesp0ptr   dd 0                    ; ptr to ESP0 in TSS, or null in VCPI
  1741. cp_idt32ptr     dd ?                    ; ptr to 32bit IDT
  1742. cp_validexcdesp dd 0                    ; valid ESP value for exc 13
  1743.  
  1744. cp_v86irqintr   dd cp_int33f0
  1745. cp_v86irqnum    db ?                    ; IRQ num for V86 mode
  1746. cp_savedstakoff dd ?                    ; current saved stack offset
  1747. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1748. ; 32 bit custom/XMS/VCPI system code
  1749. ;▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
  1750. ;═════════════════════════════════════════════════════════════════════════════
  1751. cp_int31:                               ; INT 31h: AX=900h,901h,902h
  1752.                 cmp     al,1
  1753.                 mov     al,[esp+9]
  1754.                 jb      short cp_int31f0
  1755.                 ja      short cp_int31f1
  1756.                 or      B[esp+9],2
  1757.                 jmp     short cp_int31f1
  1758. cp_int31f0:
  1759.                 and     B[esp+9],0FDh
  1760. cp_int31f1:
  1761.                 shr     al,1
  1762.                 and     al,1
  1763.                 iretd
  1764. ;═════════════════════════════════════════════════════════════════════════════
  1765. vp_int32:                               ; VCPI INT 32h: safe CX:DX=seg:off
  1766.                 pushad
  1767.                 mov     ebp,callreal
  1768.                 mov     si,VICREAL1D
  1769.                 mov     bl,2
  1770.                 jmp     short cp_int34f0
  1771. ;═════════════════════════════════════════════════════════════════════════════
  1772. vp_int33:                               ; VCPI INT 33h: safe AL=int num
  1773.                 pushad
  1774.                 mov     ebp,intreal
  1775. ;-----------------------------------------------------------------------------
  1776. vp_int33f0:
  1777.                 mov     si,VICREAL1D
  1778.                 mov     bl,2
  1779.                 jmp     short cp_int35f0
  1780. ;═════════════════════════════════════════════════════════════════════════════
  1781. cp_int32:                               ; INT 32h: safe CX:DX=seg:off
  1782.                 pushad
  1783.                 mov     ebp,callreal
  1784.                 mov     si,CICREAL1D
  1785.                 mov     bl,1
  1786.                 jmp     short cp_int34f0
  1787. ;═════════════════════════════════════════════════════════════════════════════
  1788. cp_int33:                               ; INT 33h: safe AL=int num
  1789.                 pushad
  1790.                 mov     ebp,intreal
  1791. ;-----------------------------------------------------------------------------
  1792. cp_int33f0:
  1793.                 mov     si,CICREAL1D
  1794.                 mov     bl,1
  1795.                 jmp     short cp_int35f0
  1796. ;-----------------------------------------------------------------------------
  1797. cp_int34f0:                             ; relic from times past
  1798.                 shl     ecx,16
  1799.                 mov     cx,dx
  1800.                 mov     bh,1
  1801.                 jmp     short cp_int3_
  1802. ;-----------------------------------------------------------------------------
  1803. cp_int35f0:                             ; another one, but functional
  1804.                 movzx   eax,al
  1805.                 mov     ecx,[gs:eax*4]
  1806.                 xor     bh,bh
  1807. ;-----------------------------------------------------------------------------
  1808. cp_int3_:                               ; int or call to real mode
  1809.                 mov     edi,[esp+40]
  1810.                 shld    eax,edi,23
  1811.                 and     al,bh
  1812.                 add     al,0FAh
  1813.                 mov     edx,[_code16a]
  1814.                 mov     [gs:icrealm0+edx],al
  1815.                 mov     [gs:icrealm1+edx],ecx
  1816.                 xchg    [gs:icrealm2+edx],si
  1817.                 push    si
  1818.                 movzx   esi,W[nextmodestack]
  1819.                 lea     eax,[esi-STAKRMODE*16]
  1820.                 mov     [nextmodestack],ax
  1821.                 add     eax,[realstackbase]
  1822.                 mov     edx,[cp_tssesp0ptr]
  1823.                 push    D[edx]
  1824.                 mov     [edx],eax
  1825.                 sub     eax,40
  1826.                 push    D[cp_validexcdesp]
  1827.                 mov     [cp_validexcdesp],eax
  1828.                 push    D[cp_savedstakoff]
  1829.                 mov     [cp_savedstakoff],esp
  1830.                 cmp     bl,1
  1831.                 ja      short vp_int3_s
  1832. ;-----------------------------------------------------------------------------
  1833. cp_int3_s:                              ; safe real mode int or call
  1834.                 mov     edx,[_code16a]
  1835.                 mov     [gs:c_sicrealm0+edx],bp
  1836.                 mov     esp,esi
  1837.                 db      0EAh                    ; 16bit JMP FAR 20h:c_retreal0
  1838.                 dw      c_retreal0,0,20h        ;
  1839. ;-----------------------------------------------------------------------------
  1840. vp_int3_s:                              ; safe VCPI real mode int or call
  1841.                 mov     edi,ebp
  1842.                 mov     cx,[v86r_ds]
  1843.                 mov     ax,28h
  1844.                 mov     ds,ax
  1845.                 db      0EAh                    ; 16bit JMP FAR 20h:v_retreal0
  1846.                 dw      v_retreal0,0,20h        ;
  1847. ;-----------------------------------------------------------------------------
  1848. cp_int3_d:                              ; done with real mode int or call
  1849.                 mov     ax,18h
  1850.                 mov     gs,ax
  1851.                 mov     ax,10h
  1852.                 mov     ds,ax
  1853.                 mov     es,ax
  1854.                 mov     fs,ax
  1855.                 mov     ss,ax
  1856.                 mov     esp,[cp_savedstakoff]
  1857.                 pop     D[cp_savedstakoff]
  1858.                 pop     D[cp_validexcdesp]
  1859.                 mov     ebx,[cp_tssesp0ptr]
  1860.                 pop     D[ebx]
  1861.                 mov     ebx,[_code16a]
  1862.                 pop     W[gs:icrealm2+ebx]
  1863. ;-----------------------------------------------------------------------------
  1864. cp_int3_d3:                             ; done from real mode pmode call
  1865.                 add     W[nextmodestack],STAKRMODE*16
  1866.                 mov     bx,[v86r_flags]
  1867. ;-----------------------------------------------------------------------------
  1868. cp_int3_d2:                             ; done from DPMI also
  1869.                 mov     ax,[esp+40]
  1870.                 and     ax,~8D5h
  1871.                 and     bx,8D5h
  1872.                 or      ax,bx
  1873.                 mov     [esp+40],ax
  1874.                 popad
  1875.                 iretd
  1876. ;═════════════════════════════════════════════════════════════════════════════
  1877. ; low 8 exceptions and undefined interrupt.
  1878. cp_exc0:
  1879.                 push    eax
  1880.                 xor     al,al
  1881.                 jmp     cp_irq
  1882. cp_exc1:
  1883.                 push    eax
  1884.                 mov     al,1
  1885.                 jmp     cp_irq
  1886. cp_exc2:
  1887.                 push    eax
  1888.                 mov     al,2
  1889.                 jmp     cp_irq
  1890. cp_exc3:
  1891.                 push    eax
  1892.                 mov     al,3
  1893.                 jmp     cp_irq
  1894. cp_exc4:
  1895.                 push    eax
  1896.                 mov     al,4
  1897.                 jmp     cp_irq
  1898. cp_exc5:
  1899.                 push    eax
  1900.                 mov     al,5
  1901.                 jmp     cp_irq
  1902. cp_exc6:
  1903.                 pushad
  1904.                 mov     al,6
  1905.                 jmp     short cp_exc
  1906. cp_exc7:
  1907.                 push    eax
  1908.                 mov     al,7
  1909.                 jmp     cp_irq
  1910. cp_excf:
  1911.                 pushad
  1912.                 mov     al,0FFh
  1913. ;-----------------------------------------------------------------------------
  1914. cp_exc:                                 ; main exception handler
  1915.                 mov     bx,10h
  1916.                 mov     ds,bx
  1917.                 mov     es,bx
  1918.                 mov     fs,bx
  1919.                 mov     gs,[_selzero]
  1920.                 cld
  1921.                 jmp     _exit
  1922. ;═════════════════════════════════════════════════════════════════════════════
  1923. ; IRQ redirector between modes
  1924. cp_irq0:
  1925.                 push    eax
  1926.                 mov     al,08h
  1927.                 jmp     short cp_irq
  1928. cp_irq1:
  1929.                 push    eax
  1930.                 mov     al,09h
  1931.                 jmp     short cp_irq
  1932. cp_irq2:
  1933.                 push    eax
  1934.                 mov     al,0Ah
  1935.                 jmp     short cp_irq
  1936. cp_irq3:
  1937.                 push    eax
  1938.                 mov     al,0Bh
  1939.                 jmp     short cp_irq
  1940. cp_irq4:
  1941.                 push    eax
  1942.                 mov     al,0Ch
  1943.                 jmp     short cp_irq
  1944. cp_irq5:
  1945.                 push    eax
  1946.                 mov     al,0Dh
  1947.                 jmp     short cp_irq
  1948. cp_irq6:
  1949.                 push    eax
  1950.                 mov     al,0Eh
  1951.                 jmp     short cp_irq
  1952. cp_irq7:
  1953.                 push    eax
  1954.                 mov     al,0Fh
  1955.                 jmp     short cp_irq
  1956. cp_irq8:
  1957.                 push    eax
  1958.                 mov     al,70h
  1959.                 jmp     short cp_irq
  1960. cp_irq9:
  1961.                 push    eax
  1962.                 mov     al,71h
  1963.                 jmp     short cp_irq
  1964. cp_irqa:
  1965.                 push    eax
  1966.                 mov     al,72h
  1967.                 jmp     short cp_irq
  1968. cp_irqb:
  1969.                 push    eax
  1970.                 mov     al,73h
  1971.                 jmp     short cp_irq
  1972. cp_irqc:
  1973.                 push    eax
  1974.                 mov     al,74h
  1975.                 jmp     short cp_irq
  1976. cp_irqd:
  1977.                 push    eax
  1978.                 mov     al,75h
  1979.                 jmp     short cp_irq
  1980. cp_irqe:
  1981.                 push    eax
  1982.                 mov     al,76h
  1983.                 jmp     short cp_irq
  1984. cp_irqf:
  1985.                 push    eax
  1986.                 mov     al,77h
  1987. ;─────────────────────────────────────────────────────────────────────────────
  1988. cp_irq:                                 ; main IRQ handler thingy
  1989.                 mov     [ss:cp_v86irqnum],al
  1990.                 pop     eax
  1991.                 push    ds
  1992.                 push    es
  1993.                 push    fs
  1994.                 push    gs
  1995.                 pushfd
  1996.                 push    cs
  1997.                 push    D cp_irqpd
  1998.                 pushad
  1999.                 mov     ax,10h
  2000.                 mov     ds,ax
  2001.                 mov     al,18h
  2002.                 mov     gs,ax
  2003.                 mov     al,[cp_v86irqnum]
  2004.                 mov     ebp,c_irqreal
  2005.                 jmp     [cp_v86irqintr]
  2006. cp_irqpd:
  2007.                 pop     gs
  2008.                 pop     fs
  2009.                 pop     es
  2010.                 pop     ds
  2011.                 iretd
  2012.  
  2013. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2014. ; Custom get IRQ handler offset
  2015. ; In:
  2016. ;   BL - IRQ num (0-0fh)
  2017. ; Out:
  2018. ;   EDX - offset of IRQ handler
  2019. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2020. cp_getirqvect:
  2021.                 push    ebx
  2022.                 pushfd
  2023.                 cli
  2024.                 movzx   ebx,bl
  2025.                 mov     bl,[intslottbl+ebx]
  2026.                 lea     ebx,[ebx*8]
  2027.                 add     ebx,[cp_idt32ptr]
  2028.                 mov     dx,[ebx+6]
  2029.                 shl     edx,16
  2030.                 mov     dx,[ebx]
  2031.                 popfd
  2032.                 pop     ebx
  2033.                 ret
  2034. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2035. ; Custom set IRQ handler offset
  2036. ; In:
  2037. ;   BL - IRQ num (0-0fh)
  2038. ;   EDX - offset of IRQ handler
  2039. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2040. cp_setirqvect:
  2041.                 push    ebx
  2042.                 push    edx
  2043.                 pushfd
  2044.                 cli
  2045.                 movzx   ebx,bl
  2046.                 mov     bl,[intslottbl+ebx]
  2047.                 lea     ebx,[ebx*8]
  2048.                 add     ebx,[cp_idt32ptr]
  2049.                 mov     [ebx],dx
  2050.                 shr     edx,16
  2051.                 mov     [ebx+6],dx
  2052.                 popfd
  2053.                 pop     edx
  2054.                 pop     ebx
  2055.                 ret
  2056. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2057. ; Custom set the base addx for a selector
  2058. ; In:
  2059. ;   AX - selector
  2060. ;   EDX - linear base addx for selector
  2061. ;░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░
  2062. cp_setselector:
  2063.                 push    eax
  2064.                 push    edx
  2065.                 movzx   eax,ax
  2066.                 and     edx,0FFFFFFh
  2067.                 or      edx,92000000h
  2068.                 mov     [gdt32+eax+2],edx
  2069.                 mov     dl,[esp+3]
  2070.                 mov     [gdt32+eax+7],dl
  2071.                 pop     edx
  2072.                 pop     eax
  2073.                 ret
  2074.  
  2075. section stack stack align=16
  2076.         resb STAKSIZE*16
  2077.