Rev 25 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
9 | daniel-mar | 1 | |
2 | ; Aysalia DOS Launcher |
||
3 | ; Launches aydos1.gam and aydos2.gam |
||
22 | daniel-mar | 4 | ; Revision 2018-12-07 |
9 | daniel-mar | 5 | ; (C) 2018 Daniel Marschall, ViaThinkSoft |
6 | |||
7 | .model small |
||
27 | daniel-mar | 8 | .stack 100h |
11 | daniel-mar | 9 | |
10 | ; ------------------------------------------------------- |
||
11 | |||
9 | daniel-mar | 12 | .data |
13 | |||
22 | daniel-mar | 14 | exename1 db "AYDOS1.GAM", 0 |
15 | exename2 db "AYDOS2.GAM", 0 |
||
16 | cmdargs db 0, '', 0Dh |
||
9 | daniel-mar | 17 | |
18 | dummy_fcb db 36 dup(0) |
||
19 | |||
20 | paramblk dw 0 ; use environment of parent |
||
21 | dw cmdargs ; command line arguments |
||
22 | dw 0 ; cmdargs_seg |
||
23 | dw dummy_fcb ; fcb1 |
||
24 | dw 0 ; fcb1_seg |
||
25 | dw dummy_fcb ; fcb2 |
||
26 | dw 0 ; fcb2_seg |
||
27 | |||
22 | daniel-mar | 28 | menu1 db 13, 10, \ |
29 | 13, 10, \ |
||
30 | 13, 10, \ |
||
31 | 13, 10, \ |
||
32 | ' Aysalia DOS', 13, 10, \ |
||
33 | 13, 10, \ |
||
34 | 13, 10, \ |
||
35 | ' Welches Spiel soll gestartet werden?', 13, 10, \ |
||
36 | 13, 10, \ |
||
37 | ' Dr', 81h, 'cke eine der folgenden Tasten:', 13, 10, \ |
||
38 | 13, 10, \ |
||
39 | ' 1 Aysalia DOS I', 13, 10, \ |
||
40 | ' 2 Aysalia DOS II', 13, 10, \ |
||
41 | 13, 10, \ |
||
42 | ' 9 Beenden', 13, 10, \ |
||
43 | 13, 10, \ |
||
44 | 13, 10, \ |
||
45 | 13, 10, 0 |
||
17 | daniel-mar | 46 | |
22 | daniel-mar | 47 | error1 db 13, 10, \ |
48 | 'Fehler: Spiel kann nicht gestartet werden. Fehlt eine Datei?', 13, 10, \ |
||
49 | 13, 10, 0 |
||
9 | daniel-mar | 50 | |
22 | daniel-mar | 51 | gameover1 db 13, 10, \ |
52 | 'Spiel zu Ende!', 13, 10, \ |
||
53 | 13, 10, 0 |
||
9 | daniel-mar | 54 | |
11 | daniel-mar | 55 | ; ------------------------------------------------------- |
56 | |||
9 | daniel-mar | 57 | .code |
58 | |||
59 | clear_vga PROC |
||
22 | daniel-mar | 60 | mov ax, 0A000h |
9 | daniel-mar | 61 | mov es, ax |
62 | xor di, di |
||
63 | mov ax, 0 |
||
64 | mov cx, 64000 |
||
65 | rep stosb |
||
66 | ret |
||
67 | clear_vga ENDP |
||
68 | |||
11 | daniel-mar | 69 | set_screen12 PROC |
70 | mov ah, 0 ; set screen mode |
||
71 | mov al, 12h ; graphic mode, 640x480 pixel, 16 colors (VGA) |
||
72 | int 10h |
||
73 | ret |
||
74 | set_screen12 ENDP |
||
75 | |||
9 | daniel-mar | 76 | setup_paramblk PROC |
77 | mov ax, cs |
||
78 | mov [paramblk + 4], ax ; cmdargs_seg |
||
79 | mov [paramblk + 8], ax ; fcb1_seg |
||
80 | mov [paramblk + 12], ax ; fcb2_seg |
||
81 | ret |
||
82 | setup_paramblk ENDP |
||
83 | |||
11 | daniel-mar | 84 | set_numlock_on PROC |
27 | daniel-mar | 85 | push es |
86 | |||
87 | ; In Windows 98+, we cannot access the BIOS Data Area, |
||
88 | ; so we use this technique to check if we are inside Windows. |
||
89 | ; This code was taken from http://www.fysnet.net/chkwin.htm |
||
90 | xor ax,ax ; point es:di to 0000:0000h |
||
91 | mov es,ax ; |
||
92 | mov di,ax ; |
||
93 | mov ax,1602h ; Get API entry point |
||
94 | int 2Fh ; call to multiplex interrupt |
||
95 | mov ax,es ; |
||
96 | or ax,ax ; if es:di doesn't point to 0000:0000h |
||
97 | jnz short is_win ; then Windows is running a DOS box |
||
98 | or di,di ; else |
||
99 | jnz short is_win ; we are in True DOS |
||
100 | |||
101 | ; Now the actual code that sets numlock on |
||
11 | daniel-mar | 102 | push ds |
103 | mov ax, 40h |
||
22 | daniel-mar | 104 | mov ds, ax ; Go to BIOS Data Area ( http://stanislavs.org/helppc/bios_data_area.html ) |
11 | daniel-mar | 105 | mov bx, 17h ; Load Keyboard flag byte 0 |
22 | daniel-mar | 106 | mov al, [bx] ; Read |
107 | or al, 20h ; Set bit 5 (numlock) to 1 |
||
108 | mov [bx], al ; Write |
||
11 | daniel-mar | 109 | pop ds |
27 | daniel-mar | 110 | |
111 | is_win: |
||
112 | pop es |
||
11 | daniel-mar | 113 | ret |
114 | set_numlock_on ENDP |
||
9 | daniel-mar | 115 | |
11 | daniel-mar | 116 | flush_keyb_buf PROC |
117 | mov ah, 0Ch ; Flush input buffer and input |
||
118 | mov al, 0 |
||
9 | daniel-mar | 119 | int 21h |
11 | daniel-mar | 120 | ret |
121 | flush_keyb_buf ENDP |
||
9 | daniel-mar | 122 | |
11 | daniel-mar | 123 | exit_to_dos PROC |
22 | daniel-mar | 124 | mov ah, 4Ch |
11 | daniel-mar | 125 | mov al, 00h |
126 | int 21h |
||
127 | ret |
||
128 | exit_to_dos ENDP |
||
9 | daniel-mar | 129 | |
11 | daniel-mar | 130 | sleep_5 PROC |
21 | daniel-mar | 131 | mov ah, 00h |
17 | daniel-mar | 132 | int 1Ah |
21 | daniel-mar | 133 | cmp dx, 7FFFh |
22 | daniel-mar | 134 | jg sleep_5_upperhalf |
135 | sleep_5_lowerhalf: |
||
21 | daniel-mar | 136 | mov bx, dx |
22 | daniel-mar | 137 | add bx, 91 ; 18.2 = 1 sec (therefore 91 = 5 sec) |
138 | sleep_5_lowerhalf_again: |
||
21 | daniel-mar | 139 | int 1Ah |
17 | daniel-mar | 140 | cmp dx, bx |
22 | daniel-mar | 141 | jl sleep_5_lowerhalf_again |
11 | daniel-mar | 142 | ret |
22 | daniel-mar | 143 | sleep_5_upperhalf: |
21 | daniel-mar | 144 | mov bx, dx |
145 | sub bx, 7FFFh |
||
22 | daniel-mar | 146 | add bx, 91 ; 18.2 = 1 sec (therefore 91 = 5 sec) |
147 | sleep_5_upperhalf_again: |
||
21 | daniel-mar | 148 | int 1Ah |
149 | sub dx, 7FFFh |
||
150 | cmp dx, bx |
||
22 | daniel-mar | 151 | jl sleep_5_upperhalf_again |
21 | daniel-mar | 152 | ret |
11 | daniel-mar | 153 | sleep_5 ENDP |
9 | daniel-mar | 154 | |
22 | daniel-mar | 155 | print_color_string PROC |
156 | ; This function requires: |
||
157 | ; dx = Pointer to zero terminated string |
||
158 | ; cl = Color |
||
159 | mov ah, 0Eh |
||
160 | print_color_string_again: |
||
161 | mov bx, dx |
||
25 | daniel-mar | 162 | mov al, [bx] |
27 | daniel-mar | 163 | test al, al ; is the character zero? then we are done |
164 | jz print_color_string_end |
||
22 | daniel-mar | 165 | mov bl, cl |
166 | int 10h |
||
25 | daniel-mar | 167 | add dx, 1 ; go to next character |
22 | daniel-mar | 168 | jmp print_color_string_again |
169 | print_color_string_end: |
||
170 | ret |
||
171 | print_color_string ENDP |
||
172 | |||
173 | set_bg_color PROC |
||
174 | ; This function requires: |
||
175 | ; bl = Color |
||
21 | daniel-mar | 176 | mov ah, 0Bh |
177 | mov bh, 00h |
||
178 | int 10h |
||
22 | daniel-mar | 179 | ret |
180 | set_bg_color ENDP |
||
21 | daniel-mar | 181 | |
22 | daniel-mar | 182 | print_menu_screen PROC |
23 | daniel-mar | 183 | ; Clear screen |
184 | call clear_vga |
||
22 | daniel-mar | 185 | |
186 | ; Set background color |
||
187 | mov bl, 8 ; dark green background |
||
188 | call set_bg_color |
||
189 | |||
190 | ; Set text color |
||
191 | mov cl, 0Fh ; white font |
||
9 | daniel-mar | 192 | lea dx, menu1 |
22 | daniel-mar | 193 | call print_color_string |
194 | |||
11 | daniel-mar | 195 | ret |
196 | print_menu_screen ENDP |
||
197 | |||
17 | daniel-mar | 198 | print_error_screen PROC |
23 | daniel-mar | 199 | ; Clear screen |
200 | call clear_vga |
||
21 | daniel-mar | 201 | |
22 | daniel-mar | 202 | ; Set background color |
203 | mov bl, 4 ; dark red background |
||
204 | call set_bg_color |
||
205 | |||
206 | ; Set text color |
||
207 | mov cl, 0Fh ; white font |
||
17 | daniel-mar | 208 | lea dx, error1 |
22 | daniel-mar | 209 | call print_color_string |
210 | |||
17 | daniel-mar | 211 | ret |
212 | print_error_screen ENDP |
||
213 | |||
23 | daniel-mar | 214 | print_gameover_message PROC |
22 | daniel-mar | 215 | ; Keep cursor position |
21 | daniel-mar | 216 | |
22 | daniel-mar | 217 | ; Set background color |
27 | daniel-mar | 218 | mov bl, 4 ; dark red background |
22 | daniel-mar | 219 | call set_bg_color |
220 | |||
221 | ; Set text color |
||
27 | daniel-mar | 222 | mov cl, 0Fh ; white font |
11 | daniel-mar | 223 | lea dx, gameover1 |
22 | daniel-mar | 224 | call print_color_string |
225 | |||
11 | daniel-mar | 226 | ret |
23 | daniel-mar | 227 | print_gameover_message ENDP |
11 | daniel-mar | 228 | |
229 | ; ------------------------------------------------------- |
||
230 | |||
231 | start: |
||
232 | ; Setup data segment |
||
233 | mov ax, @data ; moving base address of data to ax |
||
234 | mov ds, ax ; moving contents of ax into ds |
||
235 | ; data section now gets initialized |
||
236 | |||
237 | ; Preserve the original screen mode |
||
238 | mov ah, 0Fh ; Query screen mode |
||
239 | int 10h |
||
240 | push ax ; actually, we are only interested in register al (screen mode), not in ah (column count) |
||
9 | daniel-mar | 241 | |
11 | daniel-mar | 242 | ; Change numlock to ON |
243 | ; DOSBox has a bug where the NumLock is not correctly set to the setting of the host system, |
||
244 | ; so you have to press the NumLock key twice so that DOSBox recognizes the status. |
||
245 | ; see: https://sourceforge.net/p/dosbox/bugs/71/ |
||
246 | ; https://superuser.com/questions/255102/is-there-a-way-to-use-the-numeric-keypad-in-dosbox/1146986 |
||
247 | ; Since the game uses number keys very often, we set NumLock to ON |
||
248 | call set_numlock_on |
||
249 | |||
250 | ; Reduce size of own application to give the called applications more space |
||
251 | ; see https://stackoverflow.com/a/10067627 |
||
252 | mov ah, 4Ah |
||
14 | daniel-mar | 253 | mov bx, 100 ; 100 paragraphs a 16 bytes = 1600 bytes |
11 | daniel-mar | 254 | int 21h |
255 | |||
256 | menu: |
||
257 | ; Video Mode VGA 12 |
||
258 | call set_screen12 |
||
259 | |||
260 | ; Flush keyboard buffer |
||
261 | call flush_keyb_buf |
||
262 | |||
263 | ; Print menu screen |
||
264 | call print_menu_screen |
||
265 | |||
9 | daniel-mar | 266 | retry: |
267 | ; Query keyboard input |
||
11 | daniel-mar | 268 | mov ah, 07h ; Direct character input, without echo |
9 | daniel-mar | 269 | int 21h |
270 | cmp al, '1' |
||
271 | je prog1 |
||
272 | cmp al, '2' |
||
273 | je prog2 |
||
274 | cmp al, '9' |
||
11 | daniel-mar | 275 | je exit |
9 | daniel-mar | 276 | |
277 | ; Invalid input |
||
278 | jmp retry |
||
279 | |||
280 | prog1: |
||
281 | ; Clear screen |
||
282 | call clear_vga |
||
283 | |||
284 | ; Setup parameter block for the EXEC command |
||
285 | call setup_paramblk |
||
286 | |||
287 | ; Start game 1 |
||
27 | daniel-mar | 288 | mov ax, @data ; ds:dx = ASCIZ program name (must include extension) |
289 | mov ds, ax |
||
290 | lea dx, exename1 |
||
291 | mov ax, @data ; es:bx = Parameter block |
||
292 | mov es, ax |
||
9 | daniel-mar | 293 | mov bx, paramblk |
27 | daniel-mar | 294 | mov ah, 4Bh ; execute |
295 | mov al, 00h ; load and execute |
||
296 | int 21h ; DOS API |
||
9 | daniel-mar | 297 | |
17 | daniel-mar | 298 | ; Is everything OK? Or is the GAM file missing? |
299 | jc error |
||
300 | |||
11 | daniel-mar | 301 | ; Notify the player that the game has finished |
9 | daniel-mar | 302 | jmp gameover |
303 | |||
304 | prog2: |
||
305 | ; Clear screen |
||
306 | call clear_vga |
||
307 | |||
308 | ; Setup parameter block for the EXEC command |
||
309 | call setup_paramblk |
||
310 | |||
311 | ; Start game 2 |
||
27 | daniel-mar | 312 | mov ax, @data ; ds:dx = ASCIZ program name (must include extension) |
313 | mov ds, ax |
||
314 | lea dx, exename2 |
||
315 | mov ax, @data ; es:bx = Parameter block |
||
316 | mov es, ax |
||
9 | daniel-mar | 317 | mov bx, paramblk |
27 | daniel-mar | 318 | mov ah, 4Bh ; execute |
319 | mov al, 00h ; load and execute |
||
320 | int 21h ; DOS API |
||
17 | daniel-mar | 321 | |
322 | ; Is everything OK? Or is the GAM file missing? |
||
323 | jc error |
||
9 | daniel-mar | 324 | |
11 | daniel-mar | 325 | ; Notify the player that the game has finished |
9 | daniel-mar | 326 | jmp gameover |
11 | daniel-mar | 327 | |
17 | daniel-mar | 328 | error: |
329 | ; Video Mode VGA 12 |
||
330 | call set_screen12 |
||
331 | |||
332 | ; Print error |
||
333 | call print_error_screen |
||
334 | |||
335 | ; Give the player time to read the error message (approx 5 seconds) |
||
336 | call sleep_5 |
||
337 | |||
338 | ; Go back to the menu |
||
339 | jmp menu |
||
340 | |||
9 | daniel-mar | 341 | gameover: |
23 | daniel-mar | 342 | ; Print gameover message |
343 | call print_gameover_message |
||
9 | daniel-mar | 344 | |
11 | daniel-mar | 345 | ; Give the player time to read the game over message (approx 5 seconds) |
346 | call sleep_5 |
||
9 | daniel-mar | 347 | |
11 | daniel-mar | 348 | ; Go back to the menu |
9 | daniel-mar | 349 | jmp menu |
350 | |||
11 | daniel-mar | 351 | exit: |
9 | daniel-mar | 352 | ; Reset video mode to DOS default |
11 | daniel-mar | 353 | pop ax ; the video mode we have preserved at program start |
354 | mov ah, 0 ; set screen mode |
||
9 | daniel-mar | 355 | int 10h |
356 | |||
357 | ; Return to DOS |
||
11 | daniel-mar | 358 | call exit_to_dos |
9 | daniel-mar | 359 | |
11 | daniel-mar | 360 | ; ------------------------------------------------------- |
361 | |||
9 | daniel-mar | 362 | end start |