/* * This is file detect.h * Used for DOSEMU supplied DOS-tools to detect DOSEMU * For gas code also some rudimentary runtime system is supported * ( argc, argv, print, printnumber ..., exit ) * * Copyright (C) under GPL, The DOSEMU Team 1997-2001 * Author: Hans Lermen@fgan.de */ #ifndef DOSEMU_DETECT_H #define DOSEMU_DETECT_H #define DOSEMU_BIOS_DATE "02/25/93" #define DOSEMU_MAGIC "$DOSEMU$" #if defined(__GNUC__) && !defined(__ASSEMBLER__) #define DOSEMU_BIOS_DATE_LOCATION 0x000FFFF5 #define DOSEMU_MAGIC_LOCATION 0x000FFFE0 #define FAR #else #define DOSEMU_BIOS_DATE_LOCATION 0xF000FFF5 #define DOSEMU_MAGIC_LOCATION 0xF000FFE0 #define FAR far #endif #if defined(__ASSEMBLER__) /* this for assembler code */ # assuming we have a *.com file (CS=DS=SS=ES) # assuming we are included just at the start point of the program cld pushw %es les magicptr,%si lods %es:(%si),%eax cmpl exp_magic, %eax jne check_old lods %es:(%si),%eax cmpl exp_magic+4, %eax jne check_old lods %es:(%si),%eax movl %eax, real_version # save dosemu version popw %es jmp ok_start_label check_old: les dateptr,%si lods %es:(%si),%eax cmpl exp_date,%eax lods %es:(%si),%eax pop %es jne check_failed cmpl exp_date+4,%eax jne check_failed jmp ok_start_label check_failed: movw $2,std_handle # print to STDERR leaw exit1msg,%si print_and_exit: call print movb $1,%al exit: movb $0x4c,%ah int $0x21 printchar: pushw %ax pushw %bx #ifdef PRINT_USING_BIOS movb $0x0E,%ah xorw %bx,%bx int $0x10 #else pushw %cx pushw %dx movw %sp,%dx addw $6,%dx # pointing to AL on stack movb $0x40,%ah movw std_handle,%bx movw $1,%cx # count =1 int $0x21 popw %dx popw %cx #endif popw %bx popw %ax ret # Print an ASCIIZ string to console # DS:SI pointing to the string print: cld jmp print_entry print_loop: call printchar print_entry: lodsb orb %al,%al jnz print_loop ret hextable: .ascii "0123456789ABCDEF" printnibble: pushw %ax pushw %bx movw %ax,%bx andw $15,%bx movb hextable(%bx), %al call printchar popw %bx popw %ax ret # Converts AX to ASCII and prints it # AX=number # CX=base 2,8,10,16 (e.g =10 to print decimal, =16 for hex) # All registers preserved printnumber: orw %ax,%ax jnz printnumber_0 call printnibble ret printnumber_0: pushw %ax pushw %dx call printnumber_ popw %dx popw %ax ret printnumber_: orw %ax,%ax jz printnumber_1 xorw %dx,%dx divw %cx pushw %dx call printnumber_ popw %ax call printnibble printnumber_1: ret printdecimal: movw $10,%cx call printnumber ret printhex: movw $16,%cx call printnumber ret real_version: .long 0 # here we insert the DOSEMU version dateptr: .long DOSEMU_BIOS_DATE_LOCATION magicptr: .long DOSEMU_MAGIC_LOCATION exp_date: .ascii DOSEMU_BIOS_DATE exp_magic: .ascii DOSEMU_MAGIC exit1msg: .ascii "This program requires DOSEMU to run, aborting" .byte 13,10,0 std_handle: .word 1 #preset for STDOUT #ifdef NEED_ARGV ok_start_label: movzbw (0x80),%cx jcxz ok_start_label_1 movw $0x81,%si leaw argv,%di argvscan_0: lodsb orb %al,%al jz argvscan_finish cmpb $13,%al jz argvscan_finish cmpb $32,%al jz argvscan_skip leaw -1(%si),%ax stosw incw argc jmp argvscan_2 argvscan_skip: loop argvscan_0 argvscan_finish: movb $0,-1(%si) ok_start_label_1: jmp ok_start_label_2 argvscan_2: lodsb orb %al,%al jz argvscan_finish cmpb $13,%al jz argvscan_finish cmpb $32,%al jnz argvscan_2 movb $0,-1(%si) cmpw $16,argc jb argvscan_0 jmp ok_start_label_2 argc: .word 0 argv: .word 0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0,0,0,0 ,0 # Convert asciiz decimal pointed to by DS:SI int to binary # returns number in AX atoi: push %dx push %cx xor %dx,%dx cld atoi_loop: lodsb orb %al,%al jz atoi_ex andw $15,%ax movw %dx,%cx shlw $3,%dx addw %cx,%dx addw %cx,%dx addw %ax,%dx jmp atoi_loop atoi_ex: movw %dx,%ax popw %cx popw %dx ret ok_start_label_2: #else ok_start_label: #endif /* not NEED_ARGV */ # here normal program start happens #else struct dosemu_detect { union { char magic_[8]; unsigned long magic[2]; } u; unsigned long version; }; static int old_dosemu_compatibility(void) { static unsigned long FAR *given = (void FAR *) DOSEMU_BIOS_DATE_LOCATION; static unsigned long *expected = (unsigned long *)DOSEMU_BIOS_DATE; return (given[0] == expected[0] && given[1] == expected[1]); } static unsigned long is_dosemu(void) { static struct dosemu_detect FAR *given = (void FAR *) DOSEMU_MAGIC_LOCATION; static struct dosemu_detect expected = {DOSEMU_MAGIC}; if ( (expected.u.magic[0] == given->u.magic[0]) && (expected.u.magic[1] == given->u.magic[1]) ) return given->version; return old_dosemu_compatibility(); } #endif /* not __ASSEMBLER__ */ #endif /* DOSEMU_DETECT_H */