1#![deny(warnings)]
2#![doc(test(attr(deny(warnings))))]
3#![doc(test(attr(allow(dead_code))))]
4#![doc(test(attr(allow(unused_variables))))]
5#![allow(clippy::needless_pass_by_ref_mut)]
6
7#![no_std]
8
9#[cfg(target_os="dos")]
10use core::arch::asm;
11use core::mem::MaybeUninit;
12#[cfg(target_os="dos")]
13use core::mem::size_of;
14use core::num::NonZeroU8;
15#[cfg(target_os="dos")]
16use memoffset::offset_of;
17
18pub const DOS_ERR_FUNC_NUM_INVALID: u8 = 1;
19pub const DOS_ERR_FILE_NOT_FOUND: u8 = 2;
20pub const DOS_ERR_PATH_NOT_FOUND: u8 = 3;
21pub const DOS_ERR_TOO_MANY_OPEN_FILES: u8 = 4;
22pub const DOS_ERR_ACCESS_DENIED: u8 = 5;
23pub const DOS_ERR_INVALID_HANDLE: u8 = 6;
24pub const DOS_ERR_MCB_DESTROYED: u8 = 7;
25pub const DOS_ERR_INSUFFICIENT_MEMORY: u8 = 8;
26pub const DOS_ERR_MBA_INVALID: u8 = 9;
27pub const DOS_ERR_ENVIRONMENT_INVALID: u8 = 10;
28pub const DOS_ERR_FORMAT_INVALID: u8 = 11;
29pub const DOS_ERR_ACCESS_CODE_INVALID: u8 = 12;
30pub const DOS_ERR_DATA_INVALID: u8 = 13;
31pub const DOS_ERR_INVALID_DRIVE: u8 = 15;
32pub const DOS_ERR_ATTEMPT_RM_CUR_DIR: u8 = 16;
33pub const DOS_ERR_NOT_SAME_DEV: u8 = 17;
34pub const DOS_ERR_NO_MORE_TILES: u8 = 18;
35pub const DOS_ERR_DISK_WRITE_PROTECTED: u8 = 19;
36pub const DOS_ERR_UNKNOWN_UNIT: u8 = 20;
37pub const DOS_ERR_DRIVE_NOT_READY: u8 = 21;
38pub const DOS_ERR_UNKNOWN_CMD: u8 = 22;
39pub const DOS_ERR_DATA_ERROR: u8 = 23;
40pub const DOS_ERR_BAD_STRUCT_LEN: u8 = 24;
41pub const DOS_ERR_SEEK_ERROR: u8 = 25;
42pub const DOS_ERR_UNKNOWN_MEDIA_TYPE: u8 = 26;
43pub const DOS_ERR_SECTOR_NOT_FOUND: u8 = 27;
44pub const DOS_ERR_PRINTER_NO_PAPER: u8 = 28;
45pub const DOS_ERR_WRITE_FAULT: u8 = 29;
46pub const DOS_ERR_READ_FAULT: u8 = 30;
47pub const DOS_ERR_GENERAL_FAILURE: u8 = 31;
48pub const DOS_ERR_SHARING_VIOLATION: u8 = 32;
49pub const DOS_ERR_LOCK_VIOLATION: u8 = 33;
50pub const DOS_ERR_DISK_CHANGE_INVALID: u8 = 34;
51pub const DOS_ERR_FCB_UNAVAILABLE: u8 = 35;
52pub const DOS_ERR_SHARING_BUFFER_INVALID: u8 = 36;
53pub const DOS_ERR_CODE_PAGE_MISMATCH: u8 = 37;
54pub const DOS_ERR_OUT_OF_INPUT: u8 = 38;
55pub const DOS_ERR_INSUFFICIENT_DISK_SPACE: u8 = 39;
56pub const DOS_ERR_NET_REQUEST_NOT_SUPPORTED: u8 = 50;
57pub const DOS_ERR_NET_COMPUTER_NOT_LISTENING: u8 = 51;
58pub const DOS_ERR_NET_DUPLICATE_NAME: u8 = 52;
59pub const DOS_ERR_NET_NAME_NOT_FOUND_53: u8 = 53;
60pub const DOS_ERR_NET_BUSY: u8 = 54;
61pub const DOS_ERR_NET_DEV_NO_LONGER_EXISTS: u8 = 55;
62pub const DOS_ERR_NET_BIOS_CMD_LIMIT_EXCEEDED: u8 = 56;
63pub const DOS_ERR_NET_ADAPTER_HARDWARE_ERROR: u8 = 57;
64pub const DOS_ERR_NET_INCORRECT_RESPONSE: u8 = 58;
65pub const DOS_ERR_NET_UNEXPECTED_ERROR: u8 = 59;
66pub const DOS_ERR_NET_INCOMPATIBLE_ADAPTER: u8 = 60;
67pub const DOS_ERR_PRINT_QUEUE_FULL: u8 = 61;
68pub const DOS_ERR_QUEUE_NOT_FULL: u8 = 62;
69pub const DOS_ERR_NO_SPACE_TO_PRINT_FILE: u8 = 63;
70pub const DOS_ERR_NET_NAME_WAS_DELETED: u8 = 64;
71pub const DOS_ERR_NET_ACCESS_DENIED: u8 = 65;
72pub const DOS_ERR_NET_DEV_TYPE_INCORRECT: u8 = 66;
73pub const DOS_ERR_NET_NAME_NOT_FOUND_67: u8 = 67;
74pub const DOS_ERR_NET_NAME_LIMIT_EXCEEDED: u8 = 68;
75pub const DOS_ERR_NET_BIOS_SESSION_LIMIT_EXCEEDED: u8 = 69;
76pub const DOS_ERR_TEMPORARILY_PAUSED: u8 = 70;
77pub const DOS_ERR_NET_REQUEST_NOT_ACCEPTED: u8 = 71;
78pub const DOS_ERR_NET_REDIRECTION_PAUSED: u8 = 72;
79pub const DOS_ERR_NET_INVALID_VERSION: u8 = 73;
80pub const DOS_ERR_ACCOUNT_EXPIRED: u8 = 74;
81pub const DOS_ERR_PASSWORD_EXPIRED: u8 = 75;
82pub const DOS_ERR_LOGIN_ATTEMPTED_INVALID: u8 = 76;
83pub const DOS_ERR_NET_DISK_LIMIT_EXCEED: u8 = 77;
84pub const DOS_ERR_NET_NOT_LOGGED: u8 = 78;
85pub const DOS_ERR_FILE_EXISTS: u8 = 80;
86pub const DOS_ERR_CANNOT_MAKE_DIR: u8 = 82;
87pub const DOS_ERR_FAIL_ON_INT_24H: u8 = 83;
88pub const DOS_ERR_TOO_MANY_REDIRECTIONS: u8 = 84;
89pub const DOS_ERR_DUPLICATE_REDIRECTION: u8 = 85;
90pub const DOS_ERR_INVALID_PASSWORD: u8 = 86;
91pub const DOS_ERR_INVALID_PARAMETER: u8 = 87;
92pub const DOS_ERR_NET_WRITE_FAULT: u8 = 88;
93pub const DOS_ERR_NET_FUNC_NOT_SUPPORTED: u8 = 89;
94pub const DOS_ERR_SYS_COMPONENT_NOT_INSTALLED: u8 = 90;
95
96#[cfg(not(target_os="dos"))]
97#[allow(non_snake_case)]
98#[allow(unused_variables)]
99pub fn int_21h_ah_4Ch_exit(al_exit_code: u8) {
100 panic!("cfg(target_os=\"dos\")");
101}
102
103#[cfg(target_os="dos")]
104#[allow(non_snake_case)]
105#[inline]
106pub fn int_21h_ah_4Ch_exit(al_exit_code: u8) {
107 unsafe {
108 asm!(
109 "int 0x21",
110 in("ax") 0x4C00u16 | al_exit_code as u16,
111 );
112 }
113}
114
115#[derive(Debug, Clone)]
116pub struct DosVer {
117 pub ah_minor: u8,
118 pub al_major: u8,
119}
120
121#[cfg(not(target_os="dos"))]
122pub fn int_21h_ah_30h_dos_ver() -> DosVer {
123 panic!("cfg(target_os=\"dos\")");
124}
125
126#[cfg(target_os="dos")]
127#[inline]
128pub fn int_21h_ah_30h_dos_ver() -> DosVer {
129 let mut ax: u16;
130 unsafe {
131 asm!(
132 "int 0x21",
133 in("ax") 0x3000u16,
134 lateout("ax") ax,
135 lateout("cx") _,
136 lateout("bx") _,
137 );
138 }
139 DosVer { ah_minor: (ax >> 8) as u8, al_major: ax as u8 }
140}
141
142#[cfg(not(target_os="dos"))]
143pub fn int_21h_ah_33h_al_00h_get_ctrl_break_status() -> bool {
144 panic!("cfg(target_os=\"dos\")");
145}
146
147#[cfg(target_os="dos")]
148#[inline]
149pub fn int_21h_ah_33h_al_00h_get_ctrl_break_status() -> bool {
150 let mut dx: u16;
151 unsafe {
152 asm!(
153 "int 0x21",
154 in("ax") 0x3300u16,
155 lateout("dx") dx,
156 );
157 }
158 dx & 0xFF != 0
159}
160
161#[cfg(not(target_os="dos"))]
162#[allow(unused_variables)]
163pub fn int_21h_ah_33h_al_01h_set_ctrl_break_status(dl_ctrl_break_on: bool) {
164 panic!("cfg(target_os=\"dos\")");
165}
166
167#[cfg(target_os="dos")]
168#[inline]
169pub fn int_21h_ah_33h_al_01h_set_ctrl_break_status(dl_ctrl_break_on: bool) {
170 unsafe {
171 asm!(
172 "int 0x21",
173 in("ax") 0x3301u16,
174 in("dx") dl_ctrl_break_on as u8 as u16,
175 );
176 }
177}
178
179#[cfg(not(target_os="dos"))]
180#[allow(unused_variables)]
181pub fn int_10h_ah_02h_set_cursor_position(bh_video_page: u8, dh_row: u8, dl_column: u8) {
182 panic!("cfg(target_os=\"dos\")");
183}
184
185#[cfg(target_os="dos")]
186#[inline]
187pub fn int_10h_ah_02h_set_cursor_position(bh_video_page: u8, dh_row: u8, dl_column: u8) {
188 unsafe {
189 asm!(
190 "int 0x10",
191 in("ax") 0x0200u16,
192 in("bx") (bh_video_page as u16) << 8,
193 in("dx") ((dh_row as u16) << 8) | (dl_column as u16),
194 );
195 }
196}
197
198#[derive(Debug, Clone)]
199pub struct CodePage {
200 pub bx_active: u16,
201 pub dx_default: u16,
202}
203
204#[derive(Debug, Clone)]
205pub struct AxErr {
206 pub ax_err: u16,
207}
208
209#[cfg(target_os="dos")]
210const CF: u8 = 0x01;
211
212#[cfg(target_os="dos")]
213const ZF: u8 = 0x40;
214
215#[cfg(not(target_os="dos"))]
216pub fn int_21h_ax_6601h_code_page() -> Result<CodePage, AxErr> {
217 panic!("cfg(target_os=\"dos\")");
218}
219
220#[cfg(target_os="dos")]
221#[inline]
222pub fn int_21h_ax_6601h_code_page() -> Result<CodePage, AxErr> {
223 let mut bx_active: u16;
224 let mut dx_default: u16;
225 let mut flags: u16;
226 let mut ax_err: u16;
227 unsafe {
228 asm!(
229 "int 0x21",
230 "mov {ax_err:x}, ax",
231 "lahf",
232 ax_err = lateout(reg) ax_err,
233 in("ax") 0x6601u16,
234 lateout("ax") flags,
235 lateout("bx") bx_active,
236 lateout("dx") dx_default,
237 );
238 }
239 if ((flags >> 8) as u8) & CF == 0 {
240 Ok(CodePage { bx_active, dx_default })
241 } else {
242 Err(AxErr { ax_err })
243 }
244}
245
246#[cfg(target_os="dos")]
247#[inline]
248fn p32<T>(p: *const T) -> u32 {
249 assert!(size_of::<*const T>() == size_of::<u32>());
250 p as usize as u32
251}
252
253#[derive(Debug, Clone)]
254pub struct AlLastCh {
255 pub al_last_ch: u8,
256}
257
258#[cfg(not(target_os="dos"))]
259#[allow(unused_variables)]
260pub fn int_21h_ah_02h_out_ch(dl_ch: u8) -> AlLastCh {
261 panic!("cfg(target_os=\"dos\")");
262}
263
264#[cfg(target_os="dos")]
265#[inline]
266pub fn int_21h_ah_02h_out_ch(dl_ch: u8) -> AlLastCh {
267 let mut ax: u16;
268 unsafe {
269 asm!(
270 "int 0x21",
271 in("ax") 0x0200u16,
272 in("dx") dl_ch as u16,
273 lateout("ax") ax,
274 );
275 }
276 AlLastCh { al_last_ch: ax as u8 }
277}
278
279#[cfg(not(target_os="dos"))]
280#[allow(unused_variables)]
281pub fn int_21h_ah_09h_out_str(dx_str_24h: *const u8) {
282 panic!("cfg(target_os=\"dos\")");
283}
284
285#[cfg(target_os="dos")]
286#[inline]
287pub fn int_21h_ah_09h_out_str(dx_str_24h: *const u8) {
288 unsafe {
289 asm!(
290 "int 0x21",
291 in("ax") 0x0900u16,
292 in("edx") p32(dx_str_24h),
293 lateout("ax") _,
294 );
295 }
296}
297
298#[derive(Debug, Clone)]
299pub struct AxHandle {
300 pub ax_handle: u16,
301}
302
303#[cfg(not(target_os="dos"))]
304#[allow(non_snake_case)]
305#[allow(unused_variables)]
306pub fn int_21h_ah_3Dh_open(dx_path_z: *const u8, al_mode: u8) -> Result<AxHandle, AxErr> {
307 panic!("cfg(target_os=\"dos\")");
308}
309
310#[cfg(target_os="dos")]
311#[allow(non_snake_case)]
312#[inline]
313pub fn int_21h_ah_3Dh_open(dx_path_z: *const u8, al_mode: u8) -> Result<AxHandle, AxErr> {
314 let mut ax: u16;
315 let mut flags: u16;
316 unsafe {
317 asm!(
318 "int 0x21",
319 "mov {ax:x}, ax",
320 "lahf",
321 ax = lateout(reg) ax,
322 in("ax") 0x3d00u16 | al_mode as u16,
323 in("edx") p32(dx_path_z),
324 lateout("ax") flags,
325 );
326 }
327 if ((flags >> 8) as u8) & CF == 0 {
328 Ok(AxHandle { ax_handle: ax })
329 } else {
330 Err(AxErr { ax_err: ax })
331 }
332}
333
334#[cfg(not(target_os="dos"))]
335#[allow(non_snake_case)]
336#[allow(unused_variables)]
337pub fn int_21h_ah_3Eh_close(bx_handle: u16) -> Result<(), AxErr> {
338 panic!("cfg(target_os=\"dos\")");
339}
340
341#[cfg(target_os="dos")]
342#[allow(non_snake_case)]
343#[inline]
344pub fn int_21h_ah_3Eh_close(bx_handle: u16) -> Result<(), AxErr> {
345 let mut ax: u16;
346 let mut flags: u16;
347 unsafe {
348 asm!(
349 "int 0x21",
350 "mov {ax:x}, ax",
351 "lahf",
352 ax = lateout(reg) ax,
353 in("ax") 0x3e00u16,
354 in("bx") bx_handle,
355 lateout("ax") flags,
356 );
357 }
358 if ((flags >> 8) as u8) & CF == 0 {
359 Ok(())
360 } else {
361 Err(AxErr { ax_err: ax })
362 }
363}
364
365#[derive(Debug, Clone)]
366pub struct AxRead {
367 pub ax_read: u16,
368}
369
370#[cfg(not(target_os="dos"))]
371#[allow(non_snake_case)]
372#[allow(unused_variables)]
373pub fn int_21h_ah_3Fh_read(bx_handle: u16, dx_cx_buf: &mut [MaybeUninit<u8>]) -> Result<AxRead, AxErr> {
374 panic!("cfg(target_os=\"dos\")");
375}
376
377#[cfg(target_os="dos")]
378#[allow(non_snake_case)]
379#[inline]
380pub fn int_21h_ah_3Fh_read(bx_handle: u16, dx_cx_buf: &mut [MaybeUninit<u8>]) -> Result<AxRead, AxErr> {
381 let mut flags: u16;
382 let mut ax: u16;
383 unsafe {
384 asm!(
385 "int 0x21",
386 "mov {ax:x}, ax",
387 "lahf",
388 ax = lateout(reg) ax,
389 in("ax") 0x3F00u16,
390 in("bx") bx_handle,
391 in("ecx") u16::try_from(dx_cx_buf.len()).unwrap() as u32,
392 in("edx") p32(dx_cx_buf.as_mut_ptr()),
393 lateout("ax") flags
394 );
395 }
396 if ((flags >> 8) as u8) & CF == 0 {
397 Ok(AxRead { ax_read: ax })
398 } else {
399 Err(AxErr { ax_err: ax })
400 }
401}
402
403#[derive(Debug, Clone)]
404pub struct AxWritten {
405 pub ax_written: u16,
406}
407
408#[cfg(not(target_os="dos"))]
409#[allow(unused_variables)]
410pub fn int_21h_ah_40h_write(bx_handle: u16, dx_cx_buf: &[u8]) -> Result<AxWritten, AxErr> {
411 panic!("cfg(target_os=\"dos\")");
412}
413
414#[cfg(target_os="dos")]
415#[inline]
416pub fn int_21h_ah_40h_write(bx_handle: u16, dx_cx_buf: &[u8]) -> Result<AxWritten, AxErr> {
417 let mut flags: u16;
418 let mut ax: u16;
419 unsafe {
420 asm!(
421 "int 0x21",
422 "mov {ax:x}, ax",
423 "lahf",
424 ax = lateout(reg) ax,
425 in("ax") 0x4000u16,
426 in("bx") bx_handle,
427 in("ecx") u16::try_from(dx_cx_buf.len()).unwrap() as u32,
428 in("edx") p32(dx_cx_buf.as_ptr()),
429 lateout("ax") flags
430 );
431 }
432 if ((flags >> 8) as u8) & CF == 0 {
433 Ok(AxWritten { ax_written: ax })
434 } else {
435 Err(AxErr { ax_err: ax })
436 }
437}
438
439#[derive(Debug, Clone)]
440pub struct AxSegment {
441 pub ax_segment: u16,
442}
443
444#[derive(Debug, Clone)]
445pub struct AllocErr {
446 pub ax_err: u16,
447 pub bx_available_paragraphs: u16,
448}
449
450#[cfg(not(target_os="dos"))]
451#[allow(unused_variables)]
452pub fn int_21h_ah_48h_alloc(bx_paragraphs: u16) -> Result<AxSegment, AllocErr> {
453 panic!("cfg(target_os=\"dos\")");
454}
455
456#[cfg(target_os="dos")]
457#[inline]
458pub fn int_21h_ah_48h_alloc(bx_paragraphs: u16) -> Result<AxSegment, AllocErr> {
459 let mut ebx_paragraphs = bx_paragraphs as u32;
460 let mut ax: u16;
461 let mut flags: u16;
462 unsafe {
463 asm!(
464 "int 0x21",
465 "mov {ax:x}, ax",
466 "lahf",
467 ax = lateout(reg) ax,
468 in("ax") 0x4800u16,
469 inlateout("ebx") ebx_paragraphs => ebx_paragraphs,
470 lateout("ax") flags,
471 );
472 }
473 if ((flags >> 8) as u8) & CF == 0 {
474 Ok(AxSegment { ax_segment: ax })
475 } else {
476 Err(AllocErr { ax_err: ax, bx_available_paragraphs: ebx_paragraphs as u16 })
477 }
478}
479
480#[derive(Debug, Clone)]
481pub struct BxSegment {
482 pub bx_segment: u16,
483}
484
485#[cfg(not(target_os="dos"))]
486pub fn int_21h_ah_62h_psp_addr() -> BxSegment {
487 panic!("cfg(target_os=\"dos\")");
488}
489
490#[cfg(target_os="dos")]
491#[inline]
492pub fn int_21h_ah_62h_psp_addr() -> BxSegment {
493 let mut bx_segment: u16;
494 unsafe {
495 asm!(
496 "int 0x21",
497 in("ax") 0x6200u16,
498 lateout("bx") bx_segment,
499 );
500 }
501 BxSegment { bx_segment }
502}
503
504#[derive(Debug, Clone)]
505pub struct AlChar {
506 pub al_char: u8,
507}
508
509#[cfg(not(target_os="dos"))]
510#[allow(non_snake_case)]
511pub fn int_21h_ah_06h_dl_FFh_inkey() -> Result<Option<AlChar>, DpmiErr> {
512 panic!("cfg(target_os=\"dos\")");
513}
514
515#[cfg(target_os="dos")]
516#[repr(C)]
517struct RmRegs {
518 edi: u32,
519 esi: u32,
520 ebp: u32,
521 zero: u32,
522 ebx: u32,
523 edx: u32,
524 ecx: u32,
525 eax: u32,
526 flags: u16,
527 es: u16,
528 ds: u16,
529 fs: u16,
530 gs: u16,
531 ip: u16,
532 cs: u16,
533 sp: u16,
534 ss: u16,
535}
536
537pub struct DpmiErr(pub u16);
538
539#[cfg(target_os="dos")]
540#[allow(non_snake_case)]
541#[inline]
542pub fn int_21h_ah_06h_dl_FFh_inkey() -> Result<Option<AlChar>, DpmiErr> {
543 let mut regs = RmRegs {
544 es: 0, ds: 0, fs: 0, gs: 0, ip: 0, cs: 0, sp: 0, ss: 0,
545 edi: 0, esi: 0, ebp: 0, zero: 0, ebx: 0, ecx: 0, flags: 0,
546 edx: 0x00FF,
547 eax: 0x0600,
548 };
549 let regs = &mut regs;
550 let regs = regs as *mut _;
551 let mut regs = p32(regs);
552 let mut flags: u16;
553 let mut ax_err: u16;
554 unsafe {
555 asm!(
556 "int 0x31",
557 "mov {ax_err:x}, ax",
558 "lahf",
559 ax_err = lateout(reg) ax_err,
560 in("ax") 0x0300u16,
561 in("bx") 0x0021u16,
562 in("cx") 0x0000u16,
563 inlateout("edi") regs => regs,
564 lateout("ax") flags,
565 );
566 }
567 if ((flags >> 8) as u8) & CF == 0 {
568 let mut rm_flags: u16;
569 let mut rm_eax: u32;
570 unsafe {
571 asm!(
572 "mov {rm_flags:x}, [{regs:e} + {regs_flags_offset}]",
573 "mov {rm_eax:e}, [{regs:e} + {regs_eax_offset}]",
574 regs = in(reg) regs,
575 rm_flags = out(reg) rm_flags,
576 rm_eax = out(reg) rm_eax,
577 regs_flags_offset = const offset_of!(RmRegs, flags),
578 regs_eax_offset = const offset_of!(RmRegs, eax),
579 );
580 }
581 if rm_flags & u16::from(ZF) == 0 {
582 Ok(Some(AlChar { al_char: rm_eax as u8 }))
583 } else {
584 Ok(None)
585 }
586 } else {
587 Err(DpmiErr(ax_err))
588 }
589}
590
591#[derive(Debug, Clone)]
592pub struct CxDxAddr {
593 pub cx_segment: u16,
594 pub dx_offset: u16,
595}
596
597#[cfg(not(target_os="dos"))]
598#[allow(unused_variables)]
599pub fn int_31h_ax_0006h_segment_addr(bx_selector: u16) -> Result<CxDxAddr, AxErr> {
600 panic!("cfg(target_os=\"dos\")");
601}
602
603#[cfg(target_os="dos")]
604#[inline]
605pub fn int_31h_ax_0006h_segment_addr(bx_selector: u16) -> Result<CxDxAddr, AxErr> {
606 let mut flags: u16;
607 let mut ax_err: u16;
608 let mut cx: u16;
609 let mut dx: u16;
610 unsafe {
611 asm!(
612 "int 0x31",
613 "mov {ax_err:x}, ax",
614 "lahf",
615 ax_err = lateout(reg) ax_err,
616 in("ax") 0x0006u16,
617 in("bx") bx_selector,
618 lateout("ax") flags,
619 lateout("cx") cx,
620 lateout("dx") dx,
621 );
622 }
623 if ((flags >> 8) as u8) & CF == 0 {
624 Ok(CxDxAddr { cx_segment: cx, dx_offset: dx })
625 } else {
626 Err(AxErr { ax_err })
627 }
628}
629
630#[cfg(not(target_os="dos"))]
631#[allow(unused_variables)]
632pub fn int_31h_ax_0200h_get_rm_int(bl_vec_num: u8) -> CxDxAddr {
633 panic!("cfg(target_os=\"dos\")");
634}
635
636#[cfg(target_os="dos")]
637#[inline]
638pub fn int_31h_ax_0200h_get_rm_int(bl_vec_num: u8) -> CxDxAddr {
639 let mut cx: u16;
640 let mut dx: u16;
641 unsafe {
642 asm!(
643 "int 0x31",
644 in("ax") 0x0200u16,
645 in("bx") bl_vec_num as u16,
646 lateout("cx") cx,
647 lateout("dx") dx,
648 );
649 }
650 CxDxAddr { cx_segment: cx, dx_offset: dx }
651}
652
653#[cfg(not(target_os="dos"))]
654#[allow(unused_variables)]
655pub fn int_31h_ax_0201h_set_rm_int(bl_vec_num: u8, cx_int_handler_segment: u16, dx_int_handler_offset: u16) {
656 panic!("cfg(target_os=\"dos\")");
657}
658
659#[cfg(target_os="dos")]
660#[inline]
661pub fn int_31h_ax_0201h_set_rm_int(bl_vec_num: u8, cx_int_handler_segment: u16, dx_int_handler_offset: u16) {
662 unsafe {
663 asm!(
664 "int 0x31",
665 in("ax") 0x0201u16,
666 in("bx") bl_vec_num as u16,
667 in("cx") cx_int_handler_segment,
668 in("dx") dx_int_handler_offset,
669 );
670 }
671}
672
673#[derive(Debug, Clone)]
674pub struct RmAlloc {
675 pub ax_segment: u16,
676 pub dx_selector: u16,
677}
678
679#[cfg(not(target_os="dos"))]
680#[allow(unused_variables)]
681pub fn int_31h_ax_0100h_rm_alloc(bx_paragraphs: u16) -> Result<RmAlloc, AllocErr> {
682 panic!("cfg(target_os=\"dos\")");
683}
684
685#[cfg(target_os="dos")]
686#[inline]
687pub fn int_31h_ax_0100h_rm_alloc(mut bx_paragraphs: u16) -> Result<RmAlloc, AllocErr> {
688 let mut flags: u16;
689 let mut ax: u16;
690 let mut dx_selector: u16;
691 unsafe {
692 asm!(
693 "int 0x31",
694 "mov {ax:x}, ax",
695 "lahf",
696 ax = lateout(reg) ax,
697 in("ax") 0x0100u16,
698 inlateout("bx") bx_paragraphs => bx_paragraphs,
699 lateout("ax") flags,
700 lateout("dx") dx_selector,
701 );
702 }
703 if ((flags >> 8) as u8) & CF == 0 {
704 Ok(RmAlloc { ax_segment: ax, dx_selector })
705 } else {
706 Err(AllocErr { ax_err: ax, bx_available_paragraphs: bx_paragraphs })
707 }
708}
709
710#[cfg(not(target_os="dos"))]
711#[allow(unused_variables)]
712pub fn int_31h_ax_0101h_rm_free(dx_selector: u16) -> Result<(), AxErr> {
713 panic!("cfg(target_os=\"dos\")");
714}
715
716#[cfg(target_os="dos")]
717#[inline]
718pub fn int_31h_ax_0101h_rm_free(dx_selector: u16) -> Result<(), AxErr> {
719 let mut flags: u16;
720 let mut ax_err: u16;
721 unsafe {
722 asm!(
723 "int 0x31",
724 "mov {ax_err:x}, ax",
725 "lahf",
726 ax_err = lateout(reg) ax_err,
727 in("ax") 0x0101u16,
728 in("dx") dx_selector,
729 lateout("ax") flags,
730 );
731 }
732 if ((flags >> 8) as u8) & CF == 0 {
733 Ok(())
734 } else {
735 Err(AxErr { ax_err })
736 }
737}
738
739#[derive(Debug, Clone)]
740pub struct AlErr {
741 pub al_err: NonZeroU8,
742}
743
744#[cfg(not(target_os="dos"))]
745#[allow(unused_variables)]
746pub fn int_10h_ah_00h_set_video_mode(al_mode: u8) -> Result<(), AlErr> {
747 panic!("cfg(target_os=\"dos\")");
748}
749
750#[cfg(target_os="dos")]
751#[inline]
752pub fn int_10h_ah_00h_set_video_mode(al_mode: u8) -> Result<(), AlErr> {
753 let mut al_err: u16;
754 unsafe {
755 asm!(
756 "int 0x10",
757 in("ax") al_mode as u16,
758 lateout("ax") al_err,
759 );
760 }
761 NonZeroU8::new(al_err as u8).map(|al_err| AlErr { al_err }).map_or(Ok(()), Err)
762}
763
764#[cfg(not(target_os="dos"))]
765#[allow(unused_variables)]
766pub fn int_10h_ah_05h_set_video_active_page(al_active_page: u8) {
767 panic!("cfg(target_os=\"dos\")");
768}
769
770#[cfg(target_os="dos")]
771#[inline]
772pub fn int_10h_ah_05h_set_video_active_page(al_active_page: u8) {
773 unsafe {
774 asm!(
775 "int 0x10",
776 in("ax") 0x0500 | al_active_page as u16,
777 );
778 }
779}
780
781#[derive(Debug, Clone)]
782pub struct VideoMode {
783 pub al_mode: u8,
784 pub ah_cols: u8,
785 pub bh_active_page: u8,
786}
787
788#[cfg(not(target_os="dos"))]
789#[allow(non_snake_case)]
790#[allow(unused_variables)]
791pub fn int_10h_ah_0Fh_video_mode() -> VideoMode {
792 panic!("cfg(target_os=\"dos\")");
793}
794
795#[cfg(target_os="dos")]
796#[allow(non_snake_case)]
797#[inline]
798pub fn int_10h_ah_0Fh_video_mode() -> VideoMode {
799 let mut ax: u16;
800 let mut bx_active_page: u16;
801 unsafe {
802 asm!(
803 "int 0x10",
804 in("ax") 0x0F00u16,
805 lateout("ax") ax,
806 lateout("bx") bx_active_page,
807 );
808 }
809 VideoMode {
810 al_mode: ax as u8,
811 ah_cols: (ax >> 8) as u8,
812 bh_active_page: (bx_active_page >> 8) as u8,
813 }
814}
815
816pub struct IntHandler {
817 pub ebx_int_handler: u32,
818}
819
820#[cfg(not(target_os="dos"))]
821#[allow(unused_variables)]
822pub fn int_21h_ah_35h_get_int(al_vec_num: u8) -> IntHandler {
823 panic!("cfg(target_os=\"dos\")");
824}
825
826#[cfg(target_os="dos")]
827#[inline]
828pub fn int_21h_ah_35h_get_int(al_vec_num: u8) -> IntHandler {
829 let mut ebx_int_handler: u32;
830 unsafe {
831 asm!(
832 "int 0x21",
833 in("ax") 0x3500u16 | al_vec_num as u16,
834 lateout("ebx") ebx_int_handler,
835 );
836 }
837 IntHandler { ebx_int_handler }
838}
839
840#[cfg(not(target_os="dos"))]
841#[allow(unused_variables)]
842pub fn int_21h_ah_25h_set_int(al_vec_num: u8, edx_int_handler: u32) {
843 panic!("cfg(target_os=\"dos\")");
844}
845
846#[cfg(target_os="dos")]
847#[inline]
848pub fn int_21h_ah_25h_set_int(al_vec_num: u8, edx_int_handler: u32) {
849 unsafe {
850 asm!(
851 "int 0x21",
852 in("ax") 0x2500u16 | al_vec_num as u16,
853 in("edx") edx_int_handler,
854 );
855 }
856}