/* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #include #include #include #include #include #include /* Global variables */ #define ds _my_ds() int __bss_count = 1; char **environ; int _crt0_startup_flags; /* default to zero unless app overrides them */ int __crt0_argc; char **__crt0_argv; /* Local variables */ static void setup_core_selector(void) { int c = __dpmi_allocate_ldt_descriptors(1); if (c == -1) { _dos_ds = 0; return; } _dos_ds = c; __dpmi_set_segment_limit(_dos_ds, 16 * 1024 * 1024 - 1); } static void setup_screens(void) { if(_farpeekw(_dos_ds, 0xffff3) == 0xfd80) /* NEC PC98 ? */ { ScreenPrimary = ScreenSecondary = 0xa0000; } else if (_farpeekb(_dos_ds, 0x449) == 7) { ScreenPrimary = 0xb0000; ScreenSecondary = 0xb8000; } else { ScreenPrimary = 0xb8000; ScreenSecondary = 0xb0000; } } static void setup_go32_info_block(void) { __dpmi_version_ret ver; __dpmi_get_version(&ver); _go32_info_block.size_of_this_structure_in_bytes = sizeof(_go32_info_block); __tb = _stubinfo->ds_segment * 16; _go32_info_block.size_of_transfer_buffer = _stubinfo->minkeep; _go32_info_block.pid = _stubinfo->psp_selector; _go32_info_block.master_interrupt_controller_base = ver.master_pic; _go32_info_block.slave_interrupt_controller_base = ver.slave_pic; _go32_info_block.linear_address_of_stub_info_structure = 0xffffffffU; /* force error */ __dpmi_get_segment_base_address(_stubinfo->psp_selector, &_go32_info_block.linear_address_of_original_psp); _go32_info_block.run_mode = _GO32_RUN_MODE_DPMI; _go32_info_block.run_mode_info = (ver.major << 8) | (ver.minor); } char *__dos_argv0; static void setup_environment(void) { char *dos_environ = alloca(_stubinfo->env_size), *cp; short env_selector; int env_count=0; movedata(_stubinfo->psp_selector, 0x2c, ds, (int)&env_selector, 2); movedata(env_selector, 0, ds, (int)dos_environ, _stubinfo->env_size); cp = dos_environ; do { env_count++; while (*cp) cp++; /* skip to NUL */ cp++; /* skip to next character */ } while (*cp); /* repeat until two NULs */ environ = (char **)malloc((env_count+1) * sizeof(char *)); if (environ == 0) return; cp = dos_environ; env_count = 0; do { /* putenv assumes each string is malloc'd */ environ[env_count] = (char *)malloc(strlen(cp)+1); strcpy(environ[env_count], cp); env_count++; while (*cp) cp++; /* skip to NUL */ cp++; /* skip to next character */ } while (*cp); /* repeat until two NULs */ environ[env_count] = 0; __dos_argv0 = (char *)malloc(strlen(cp + 3)+1); if (__dos_argv0 == 0) abort(); strcpy(__dos_argv0, cp+3); } extern void __main(void); extern int main(int, char **, char **); extern void _crt0_init_mcount(void); /* For profiling */ void __crt1_startup(void) { char *pn; __bss_count ++; __crt0_argv = 0; setup_core_selector(); setup_screens(); setup_go32_info_block(); __djgpp_exception_setup(); setup_environment(); __crt0_setup_arguments(); pn = __crt0_argv ? __crt0_argv[0] : __dos_argv0; __crt0_load_environment_file(pn); _npxsetup(pn); _crt0_init_mcount(); __main(); exit(main(__crt0_argc, __crt0_argv, environ)); }