home *** CD-ROM | disk | FTP | other *** search
/ Large Pack of OldSkool DOS MOD Trackers / cdfm.zip / PMODE.ASM < prev    next >
Assembly Source File  |  1996-06-10  |  68KB  |  2,028 lines

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