static unsigned long depackedlen(const unsigned char *p, unsigned long plen) { if (p[0] == 'P' && p[1] == 'P' && p[2] == '2' && p[3] == '0') return val(p+plen-4); if (host_readd((Bit8u*)p) == plen) return val(p+plen-4); if (host_readd((Bit8u*)p) + 8 == plen) return val(p+plen-4); return 0; /* not a powerpacker file */ }
/** * menu_enter_delete() - selects a hero to enter / get deleted * @ptr: pointer * @entries: how many heros * @mode: 1 = enter / -1 = delete * * Returns: the number of the selected hero. * Used only in temples. */ signed short menu_enter_delete(RealPt ptr, signed short entries, signed short mode) { signed short i; signed short answer; signed short a; signed short l_di; answer = 0; l_di = 0; while (answer != -1) { a = (l_di + 10 < entries) ? 10 : entries - l_di; /* fill a pointer array with the pointer to the names */ for (i = 0; i < a; i++) { ds_writed(0xbf95 + 4 * i, (Bit32u)((i + l_di) * 32 + ptr + 0x10)); } i = a; if (entries > 10) { ds_writed(0xbf95 + 4 * i, host_readd(Real2Host((RealPt)ds_readd(TEXT_LTX) + 0x48c))); i++; } answer = GUI_radio( (mode == -1) ? get_ltx(0x8dc) : get_ltx(0x490), (signed char)i, Real2Host(ds_readd(0xbf95)), Real2Host(ds_readd(0xbf99)), Real2Host(ds_readd(0xbf9d)), Real2Host(ds_readd(0xbfa1)), Real2Host(ds_readd(0xbfa5)), Real2Host(ds_readd(0xbfa9)), Real2Host(ds_readd(0xbfad)), Real2Host(ds_readd(0xbfb1)), Real2Host(ds_readd(0xbfb5)), Real2Host(ds_readd(0xbfb9)), Real2Host(ds_readd(0xbfbd)), Real2Host(ds_readd(0xbfc1))); if ((entries > 10) && (answer == i)) { l_di += 10; if (l_di > entries) { l_di = 0; } } else { if (answer != -1) { return l_di + answer - 1; } } } return -1; }
static INLINE Bitu hostRead(HostPt off ) { if ( sizeof( Size ) == 1) return host_readb( off ); else if ( sizeof( Size ) == 2) return host_readw( off ); else if ( sizeof( Size ) == 4) return host_readd( off ); return 0; }
void copy_3d_to_screen(void) { Bit8u *src, *t_src; PhysPt dst, t_dst; signed short i, j; src = Real2Host(ds_readd(0xb128)); dst = PhysMake(0xa000, 0x28f); i = 134; do { t_src = src; t_dst = dst; for (j = 52; j > 0; j--) { mem_writed_inline(t_dst, host_readd(t_src)); t_dst+=4; t_src+=4; } src += 320; dst += 320; i--; } while (i != 0); }
bool DOS_Execute(char * name,PhysPt block_pt,Bit8u flags) { EXE_Header head;Bitu i; Bit16u fhandle;Bit16u len;Bit32u pos; Bit16u pspseg,envseg,loadseg,memsize,readsize; PhysPt loadaddress;RealPt relocpt; Bitu headersize,imagesize; DOS_ParamBlock block(block_pt); block.LoadData(); if (flags!=LOADNGO && flags!=OVERLAY && flags!=LOAD) { E_Exit("DOS:Not supported execute mode %d for file %s",flags,name); } /* Check for EXE or COM File */ bool iscom=false; if (!DOS_OpenFile(name,OPEN_READ,&fhandle)) return false; len=sizeof(EXE_Header); if (!DOS_ReadFile(fhandle,(Bit8u *)&head,&len)) { DOS_CloseFile(fhandle); return false; } if (len<sizeof(EXE_Header)) { if (len==0) { /* Prevent executing zero byte files */ DOS_SetError(DOSERR_ACCESS_DENIED); DOS_CloseFile(fhandle); return false; } /* Otherwise must be a .com file */ iscom=true; } else { /* Convert the header to correct endian, i hope this works */ HostPt endian=(HostPt)&head; for (i=0;i<sizeof(EXE_Header)/2;i++) { *((Bit16u *)endian)=host_readw(endian); endian+=2; } if ((head.signature!=MAGIC1) && (head.signature!=MAGIC2)) iscom=true; else { if(head.pages & ~0x07ff) /* 1 MB dos maximum address limit. Fixes TC3 IDE (kippesoep) */ LOG(LOG_EXEC,LOG_NORMAL)("Weird header: head.pages > 1 MB"); head.pages&=0x07ff; headersize = head.headersize*16; imagesize = head.pages*512-headersize; if (imagesize+headersize<512) imagesize = 512-headersize; } } Bit8u * loadbuf=(Bit8u *)new Bit8u[0x10000]; if (flags!=OVERLAY) { /* Create an environment block */ envseg=block.exec.envseg; if (!MakeEnv(name,&envseg)) { DOS_CloseFile(fhandle); return false; } /* Get Memory */ Bit16u minsize,maxsize;Bit16u maxfree=0xffff;DOS_AllocateMemory(&pspseg,&maxfree); if (iscom) { minsize=0x1000;maxsize=0xffff; if (machine==MCH_PCJR) { /* try to load file into memory below 96k */ pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); Bit16u dataread=0x1800; DOS_ReadFile(fhandle,loadbuf,&dataread); if (dataread<0x1800) maxsize=dataread; if (minsize>maxsize) minsize=maxsize; } } else { /* Exe size calculated from header */ minsize=long2para(imagesize+(head.minmemory<<4)+256); if (head.maxmemory!=0) maxsize=long2para(imagesize+(head.maxmemory<<4)+256); else maxsize=0xffff; } if (maxfree<minsize) { DOS_SetError(DOSERR_INSUFFICIENT_MEMORY); DOS_FreeMemory(envseg); return false; } if (maxfree<maxsize) memsize=maxfree; else memsize=maxsize; if (!DOS_AllocateMemory(&pspseg,&memsize)) E_Exit("DOS:Exec error in memory"); if (iscom && (machine==MCH_PCJR) && (pspseg<0x2000)) { maxsize=0xffff; /* resize to full extent of memory block */ DOS_ResizeMemory(pspseg,&maxsize); /* now try to lock out memory above segment 0x2000 */ if ((real_readb(0x2000,0)==0x5a) && (real_readw(0x2000,1)==0) && (real_readw(0x2000,3)==0x7ffe)) { /* MCB after PCJr graphics memory region is still free */ if (pspseg+maxsize==0x17ff) { DOS_MCB cmcb((Bit16u)(pspseg-1)); cmcb.SetType(0x5a); // last block } } } loadseg=pspseg+16; if (!iscom) { /* Check if requested to load program into upper part of allocated memory */ if ((head.minmemory == 0) && (head.maxmemory == 0)) loadseg = ((pspseg+memsize)*0x10-imagesize)/0x10; } } else loadseg=block.overlay.loadseg; /* Load the executable */ loadaddress=PhysMake(loadseg,0); if (iscom) { /* COM Load 64k - 256 bytes max */ pos=0;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); readsize=0xffff-256; DOS_ReadFile(fhandle,loadbuf,&readsize); MEM_BlockWrite(loadaddress,loadbuf,readsize); } else { /* EXE Load in 32kb blocks and then relocate */ pos=headersize;DOS_SeekFile(fhandle,&pos,DOS_SEEK_SET); while (imagesize>0x7FFF) { readsize=0x8000;DOS_ReadFile(fhandle,loadbuf,&readsize); MEM_BlockWrite(loadaddress,loadbuf,readsize); // if (readsize!=0x8000) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header"); loadaddress+=0x8000;imagesize-=0x8000; } if (imagesize>0) { readsize=(Bit16u)imagesize;DOS_ReadFile(fhandle,loadbuf,&readsize); MEM_BlockWrite(loadaddress,loadbuf,readsize); // if (readsize!=imagesize) LOG(LOG_EXEC,LOG_NORMAL)("Illegal header"); } /* Relocate the exe image */ Bit16u relocate; if (flags==OVERLAY) relocate=block.overlay.relocation; else relocate=loadseg; pos=head.reloctable;DOS_SeekFile(fhandle,&pos,0); for (i=0;i<head.relocations;i++) { readsize=4;DOS_ReadFile(fhandle,(Bit8u *)&relocpt,&readsize); relocpt=host_readd((HostPt)&relocpt); //Endianize PhysPt address=PhysMake(RealSeg(relocpt)+loadseg,RealOff(relocpt)); mem_writew(address,mem_readw(address)+relocate); } } delete[] loadbuf; DOS_CloseFile(fhandle); /* Setup a psp */ if (flags!=OVERLAY) { // Create psp after closing exe, to avoid dead file handle of exe in copied psp SetupPSP(pspseg,memsize,envseg); SetupCMDLine(pspseg,block); }; CALLBACK_SCF(false); /* Carry flag cleared for caller if successfull */ if (flags==OVERLAY) return true; /* Everything done for overlays */ RealPt csip,sssp; if (iscom) { csip=RealMake(pspseg,0x100); sssp=RealMake(pspseg,0xfffe); mem_writew(PhysMake(pspseg,0xfffe),0); } else { csip=RealMake(loadseg+head.initCS,head.initIP); sssp=RealMake(loadseg+head.initSS,head.initSP); } if (flags==LOAD) { DOS_PSP callpsp(dos.psp()); /* Save the SS:SP on the PSP of calling program */ callpsp.SetStack(RealMakeSeg(ss,reg_sp)); /* Switch the psp's */ dos.psp(pspseg); DOS_PSP newpsp(dos.psp()); dos.dta(RealMake(newpsp.GetSegment(),0x80)); block.exec.initsssp = sssp; block.exec.initcsip = csip; block.SaveData(); return true; } if (flags==LOADNGO) { /* Get Caller's program CS:IP of the stack and set termination address to that */ RealSetVec(0x22,RealMake(mem_readw(SegPhys(ss)+reg_sp+2),mem_readw(SegPhys(ss)+reg_sp))); SaveRegisters(); DOS_PSP callpsp(dos.psp()); /* Save the SS:SP on the PSP of calling program */ callpsp.SetStack(RealMakeSeg(ss,reg_sp)); /* Switch the psp's and set new DTA */ dos.psp(pspseg); DOS_PSP newpsp(dos.psp()); dos.dta(RealMake(newpsp.GetSegment(),0x80)); /* save vectors */ newpsp.SaveVectors(); /* copy fcbs */ newpsp.SetFCB1(block.exec.fcb1); newpsp.SetFCB2(block.exec.fcb2); /* Set the stack for new program */ SegSet16(ss,RealSeg(sssp));reg_sp=RealOff(sssp); /* Add some flags and CS:IP on the stack for the IRET */ reg_sp-=6; mem_writew(SegPhys(ss)+reg_sp+0,RealOff(csip)); mem_writew(SegPhys(ss)+reg_sp+2,RealSeg(csip)); /* DOS starts programs with a RETF, so our IRET should not modify critical flags (IOPL in v86 mode); interrupt flag is set explicitly, test flags cleared */ mem_writew(SegPhys(ss)+reg_sp+4,(reg_flags&(~FMASK_TEST))|FLAG_IF); /* Setup the rest of the registers */ reg_ax=reg_bx=0;reg_cx=0xff; reg_dx=pspseg; reg_si=RealOff(csip); reg_di=RealOff(sssp); reg_bp=0x91c; /* DOS internal stack begin relict */ SegSet16(ds,pspseg);SegSet16(es,pspseg); #if C_DEBUG /* Started from debug.com, then set breakpoint at start */ DEBUG_CheckExecuteBreakpoint(RealSeg(csip),RealOff(csip)); #endif /* Add the filename to PSP and environment MCB's */ char stripname[8];Bitu index=0; while (char chr=*name++) { switch (chr) { case ':':case '\\':case '/':index=0;break; default:if (index<8) stripname[index++]=toupper(chr); } } index=0; while (index<8) { if (stripname[index]=='.') break; if (!stripname[index]) break; index++; } memset(&stripname[index],0,8-index); DOS_MCB pspmcb(dos.psp()-1); pspmcb.SetFileName(stripname); DOS_UpdatePSPName(); return true; } return false; }
static INLINE Bit32u Fetchd() { Bit32u temp=host_readd(core.cseip); core.cseip+=4; return temp; }
//Initializer - is startet if executed file is SCHICKM.EXE/BLADEM.EXE or GEN.EXE //Returns true if the desired programm is started bool init_schick(char *name, unsigned short reloc, unsigned short _cs, unsigned short ip) { char borsig[] = "Borland C++ - Copyright 1991 Borland Intl."; char fname[81]; int ver; schick_get_fname(fname, name); if (strcmp(fname, "schickm.exe") && strcmp(fname, "bladem.exe") && strcmp(fname, "gen.exe")) return false; /* Check CS:IP in the EXE-Header are 0:0 * and the first executed instruction is mov dx,i16 */ if (_cs != 0 || ip != 0 || real_readb(reloc+_cs, ip) != 0xba) return false; /* Show CS:IP on the virtual machine and the pointer to 0:0 */ D1_TRAC("\n\nCS:IP 0x%x:0x%x\tMemBase: %p\n", reloc, ip, MemBase); /* Read and show the Datasegment */ datseg_bak = datseg; datseg = real_readw(reloc, ip+1); p_datseg_bak = p_datseg; p_datseg = MemBase + PhysMake(datseg, 0); D1_TRAC("Dseg: 0x%X\n", datseg); /* Check if the start of the Datasegment is Borland C++ */ if (host_readd(p_datseg) != 0 || strcmp((char*)MemBase+PhysMake(datseg, 4), borsig)) { D1_ERR("Kein Borland C++ Kompilat!\n"); return false; } /* check for the game program */ if (!strcmp(fname, "schickm.exe") || !strcmp(fname, "bladem.exe")) { reloc_game = reloc; ver = schick_get_version((char*)p_datseg); if (ver == 0) { D1_ERR("Unbekannte Version von DSA1\n"); return false; } D1_INFO("\nDSA1 Schicksalsklinge gefunden V%d.%02d_%s\n", ver / 100, ver % 100, schick_is_en() ? "en": "de"); /* enable profiler only on this version */ if (ver == 302 && !schick_is_en()) { D1_INFO("Starte Profiler\n"); /* enable status comperator */ schick_status_init(); schick_timer_enable(); schick++; } } /* check for the character generation program */ if (!strcmp(fname, "gen.exe")) { reloc_gen = reloc; ver = schick_gen_get_version((char*)p_datseg); if (ver == 0) { D1_ERR("Unbekannte Version von DSA1 Generierung\n"); return false; } D1_INFO("DSA1 Generierung gefunden V%d.%02d_%s\n", ver / 100, ver % 100, schick_gen_is_en() ? "en": "de"); /* This happens only gen is started from the game. We have to save some values. */ if (!fromgame && schick && !gen) { if (schick_get_version((char*)p_datseg_bak) == 302 && !schick_is_en()) { schick_status_disable(); schick_timer_disable(); } schick--; fromgame++; D1_INFO("Gen gestartet\nreloc (0x%x)\n", (unsigned int)reloc_gen); } /* enable profiler only on this version */ if (ver == 105 && !schick_is_en()) { D1_INFO("Starte Profiler\n"); gen++; } } return true; }