]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/flatreal/flatmode.asm
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / flatreal / flatmode.asm
1
2 ; NTS: We use NASM to achieve our goals here because WASM sucks donkey balls
3 ;      Maybe when they bother to implement a proper conditional macro system, I'll consider it...
4
5 %if TARGET_MSDOS == 16
6  %ifndef MMODE
7   %error You must specify MMODE variable (memory model) for 16-bit real mode code
8  %endif
9 %endif
10
11 %if TARGET_MSDOS == 16
12  %ifidni MMODE,l
13   %define retnative retf
14   %define cdecl_param_offset 6  ; RETF addr + PUSH BP
15  %else
16   %ifidni MMODE,m
17    %define retnative retf
18    %define cdecl_param_offset 6 ; RETF addr + PUSH BP
19   %else
20    %define retnative ret
21    %define cdecl_param_offset 4 ; RET addr + PUSH BP
22   %endif
23  %endif
24 %else
25  %define retnative ret
26  %define cdecl_param_offset 8   ; RET addr + PUSH EBP
27 %endif
28
29 ; NTS: Associate our data with Watcom's data segment
30 segment .data public align=4 class=data
31
32 ; NTS: Help NASM put the code segment in the right place for Watcom to link it in properly
33 segment text public align=1 class=code
34
35 %if TARGET_MSDOS == 16
36
37 ; int flatrealmode_test()
38 global flatrealmode_test_
39 flatrealmode_test_:
40                 pushf
41                 push            ds
42                 push            si
43                 push            cx
44
45                 ; clear interrupts, to ensure IRQ 5 is not mistaken for a GP fault
46                 cli
47
48                 ; set DS=0 to carry out the test, and zero AX
49                 xor             ax,ax
50                 mov             ds,ax
51
52                 ; hook interrupt 0x0D (general protection fault and IRQ 5)
53                 mov             si,0x0D * 4
54                 mov             cx,[si]                 ; offset
55                 mov             word [si],_flatrealmode_test_fail
56                 push            cx
57                 mov             cx,[si+2]
58                 mov             word [si+2],cs
59                 push            cx
60
61                 ; now try it. either we'll make it through unscathed or it will cause a GP fault and branch to our handler
62                 mov             esi,0xFFFFFFF8
63                 mov             esi,[esi]
64
65                 ; either nothing happened, or control jmp'd here from the exception handler (who also set AX=1)
66                 ; restore interrupt routine and clean up
67 _flatrealmode_test_conclude:
68                 mov             si,0x0D * 4
69                 pop             cx
70                 mov             word [si+2],cx
71                 pop             cx
72                 mov             word [si],cx
73
74                 pop             cx
75                 pop             si
76                 pop             ds
77                 popf
78                 retnative
79 _flatrealmode_test_fail:
80                 add             sp,6                    ; throw away IRETF address (IP+CS+FLAGS)
81                 inc             ax                      ; make AX nonzero
82                 jmp short       _flatrealmode_test_conclude
83
84 ; void __cdecl flatrealmode_force_datasel(void *ptr);
85 global _flatrealmode_force_datasel
86 _flatrealmode_force_datasel:
87                 push            bp
88                 mov             bp,sp
89                 pushf
90                 pusha
91
92                 mov             ax,cs
93                 mov             word [cs:_flatrealmode_force_datasel_j2_hackme+3],ax            ; overwrite segment portion of JMP FAR instruction
94
95 ; LARGE and COMPACT memory models: a far pointer is passed onto the stack
96 %ifidni MMODE,l
97 %define FARPTR_
98 %else
99  %ifidni MMODE,c
100  %define FARPTR_
101  %endif
102 %endif
103
104 %ifdef FARPTR_
105  %undef FARPTR_
106                 ; LARGE memory model version (we're given a FAR pointer)
107                 ; caller passes us the address of the constructed GDT (near ptr)
108                 xor             esi,esi
109                 mov             si,[bp+cdecl_param_offset]
110
111                 ; now convert to physical addr
112                 xor             eax,eax
113                 mov             ax,[bp+cdecl_param_offset+2]
114                 shl             eax,4
115                 add             eax,esi
116 %else           ; SMALL memory model version (we're given a NEAR pointer)
117                 ; caller passes us the address of the constructed GDT (near ptr)
118                 xor             esi,esi
119                 mov             si,[bp+cdecl_param_offset]
120
121                 ; now convert to physical addr
122                 xor             eax,eax
123                 mov             ax,ds
124                 shl             eax,4
125                 add             eax,esi
126 %endif
127
128                 ; disable interrupts, we're going to fuck with the CPU mode and thunk into protected mode
129                 cli
130
131                 ; allocate room on the stack for the GDT and store the original GDTR
132                 sub             sp,8
133                 mov             bx,sp
134                 sgdt            [bx]
135
136                 ; and another for the new GDT
137                 sub             sp,8
138                 mov             di,sp
139                 mov             word [di],0xFF
140                 mov             dword [di+2],eax
141
142                 ; load the new GDT
143                 lgdt            [di]
144
145                 ; save previous segment regs
146                 mov             bx,ds
147                 mov             cx,es
148
149                 ; enable protected mode
150                 mov             eax,cr0
151                 or              al,1
152                 mov             cr0,eax
153
154                 ; now load the segment registers
155                 mov             ax,8                    ; GDT selector value
156                 mov             ds,ax
157                 mov             es,ax
158
159                 ; force CPU to go into protected mode, clear cache
160                 jmp             16:word _flatrealmode_force_datasel_j1
161 _flatrealmode_force_datasel_j1:
162
163                 ; disable protected mode
164                 mov             eax,cr0
165                 and             al,~1
166                 mov             cr0,eax
167
168                 ; jump to force it
169                 ; opcode format: 0xEA <ofs> <seg>
170 _flatrealmode_force_datasel_j2_hackme:
171                 jmp             0:word _flatrealmode_force_datasel_j2
172 _flatrealmode_force_datasel_j2:
173
174                 ; reload sane realmode selectors
175                 mov             ds,bx
176                 mov             es,cx
177
178                 ; discard the new GDT
179                 add             sp,8
180
181                 ; restore old GDT
182                 mov             bx,sp
183                 lgdt            [bx]
184
185                 ; discard old GDT
186                 add             sp,8
187
188                 popa
189                 popf
190                 pop             bp
191                 retnative
192 %endif