Beispiel #1
0
void AutoexecObject::InstallBefore(const std::string &in) {
	if(GCC_UNLIKELY(installed)) E_Exit("autoexec: already created %s",buf.c_str());
	installed = true;
	buf = in;
	autoexec_strings.push_front(buf);
	this->CreateAutoexec();
}
Beispiel #2
0
static void AddEntry(PICEntry * entry) {
	PICEntry * find_entry=pic_queue.next_entry;
	if (GCC_UNLIKELY(find_entry ==0)) {
		entry->next=0;
		pic_queue.next_entry=entry;
	} else if (find_entry->index>entry->index) {
		pic_queue.next_entry=entry;
		entry->next=find_entry;
	} else while (find_entry) {
		if (find_entry->next) {
			/* See if the next index comes later than this one */
			if (find_entry->next->index > entry->index) {
				entry->next=find_entry->next;
				find_entry->next=entry;
				break;
			} else {
				find_entry=find_entry->next;
			}
		} else {
			entry->next=find_entry->next;
			find_entry->next=entry;
			break;
		}
	}
	Bits cycles=PIC_MakeCycles(pic_queue.next_entry->index-PIC_TickIndex());
	if (cycles<CPU_Cycles) {
		CPU_CycleLeft+=CPU_Cycles;
		CPU_Cycles=0;
	}
}
Beispiel #3
0
Bitu DOS_Drive_Cache::CreateShortNameID(CFileInfo* curDir, const char* name) {
	std::vector<CFileInfo*>::size_type filelist_size = curDir->longNameList.size();
	if (GCC_UNLIKELY(filelist_size<=0)) return 1;	// shortener IDs start with 1

	Bitu foundNr	= 0;	
	Bits low		= 0;
	Bits high		= (Bits)(filelist_size-1);
	Bits mid, res;

	while (low<=high) {
		mid = (low+high)/2;
		res = CompareShortname(name,curDir->longNameList[mid]->shortname);
		
		if (res>0)	low  = mid+1; else
		if (res<0)	high = mid-1; 
		else {
			// any more same x chars in next entries ?	
			do {
				foundNr = curDir->longNameList[mid]->shortNr;
				mid++;
			} while((Bitu)mid<curDir->longNameList.size() && (CompareShortname(name,curDir->longNameList[mid]->shortname)==0));
			break;
		};
	}
	return foundNr+1;
}
Beispiel #4
0
void AutoexecObject::Install(const std::string &in) {
    if(GCC_UNLIKELY(installed)) E_Exit("autoexec: already created %s",buf.c_str());
    installed = true;
    buf = in;
    autoexec_strings.push_back(buf);
    this->CreateAutoexec();

    //autoexec.bat is normally created AUTOEXEC_Init.
    //But if we are already running (first_shell)
    //we have to update the envirionment to display changes

    if(first_shell)	{
        //create a copy as the string will be modified
        std::string::size_type n = buf.size();
        char* buf2 = new char[n + 1];
        safe_strncpy(buf2, buf.c_str(), n + 1);
        if((strncasecmp(buf2,"set ",4) == 0) && (strlen(buf2) > 4)) {
            char* after_set = buf2 + 4;//move to variable that is being set
            char* test = strpbrk(after_set,"=");
            if(!test) {
                first_shell->SetEnv(after_set,"");
                return;
            }
            *test++ = 0;
            //If the shell is running/exists update the environment
            first_shell->SetEnv(after_set,test);
        }
        delete [] buf2;
    }
}
Beispiel #5
0
void PIC_Controller::start_irq(Bit8u val){
	irr&=~(1<<(val));
	if (!auto_eoi) {
		active_irq = val;
		isr |= 1<<(val);
		isrr = ~isr;
	} else if (GCC_UNLIKELY(rotate_on_auto_eoi)) {
		E_Exit("rotate on auto EOI not handled");
	}
}
Beispiel #6
0
static void RENDER_StartLineHandler(const void * s) {
	if (s) {
		const Bitu *src = (Bitu*)s;
		Bitu *cache = (Bitu*)(render.scale.cacheRead);
		Bits count = render.src.start;
#if defined(__SSE__)
		if(sse2_available) {
#if defined (_MSC_VER)
#define SIZEOF_INT_P 4
#endif
			static const Bitu simd_inc = 16/SIZEOF_INT_P;
			while (count >= (Bits)simd_inc) {
				__m128i v = _mm_loadu_si128((const __m128i*)src);
				__m128i c = _mm_loadu_si128((const __m128i*)cache);
				__m128i cmp = _mm_cmpeq_epi32(v, c);
				if (GCC_UNLIKELY(_mm_movemask_epi8(cmp) != 0xFFFF))
					goto cacheMiss;
				count-=simd_inc; src+=simd_inc; cache+=simd_inc;
			}
		}
#endif
		while (count) {
			if (GCC_UNLIKELY(src[0] != cache[0]))
				goto cacheMiss;
			count--; src++; cache++;
		}
	}
/* cacheHit */
	render.scale.cacheRead += render.scale.cachePitch;
	Scaler_ChangedLines[0] += Scaler_Aspect[ render.scale.inLine ];
	render.scale.inLine++;
	render.scale.outLine++;
	return;
cacheMiss:
	if (!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )) {
		RENDER_DrawLine = RENDER_EmptyLineHandler;
		return;
	}
	render.scale.outWrite += render.scale.outPitch * Scaler_ChangedLines[0];
	RENDER_DrawLine = render.scale.lineHandler;
	RENDER_DrawLine( s );
}
Beispiel #7
0
void PIC_runIRQs(void) {
	if (!GETFLAG(IF)) return;
	if (GCC_UNLIKELY(!PIC_IRQCheck)) return;
	if (GCC_UNLIKELY(cpudecoder==CPU_Core_Normal_Trap_Run)) return;

	const Bit8u p = (master.irr & master.imrr)&master.isrr;
	const Bit8u max = master.special?8:master.active_irq;
	for(Bit8u i = 0,s = 1;i < max;i++, s<<=1){
		if (p&s){
			if (i==2) { //second pic
				slave_startIRQ();
			} else {
				master_startIRQ(i);
			}
			break;
		}
	}
	//Disable check variable.
	PIC_IRQCheck = 0;
}
Beispiel #8
0
void RENDER_EndUpdate( bool abort ) {
	if (GCC_UNLIKELY(!render.updating))
		return;
	RENDER_DrawLine = RENDER_EmptyLineHandler;
	if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO))) {
		Bitu pitch, flags;
		flags = 0;
		if (render.src.dblw != render.src.dblh) {
			if (render.src.dblw) flags|=CAPTURE_FLAG_DBLW;
			if (render.src.dblh) flags|=CAPTURE_FLAG_DBLH;
		}
		float fps = render.src.fps;
		pitch = render.scale.cachePitch;
		if (render.frameskip.max)
			fps /= 1+render.frameskip.max;
		CAPTURE_AddImage( render.src.width, render.src.height, render.src.bpp, pitch,
			flags, fps, (Bit8u *)&scalerSourceCache, (Bit8u*)&render.pal.rgb );
	}
	if ( render.scale.outWrite ) {
		GFX_EndUpdate( abort? NULL : Scaler_ChangedLines );
		render.frameskip.hadSkip[render.frameskip.index] = 0;
	} else {
#if 0
		Bitu total = 0, i;
		render.frameskip.hadSkip[render.frameskip.index] = 1;
		for (i = 0;i<RENDER_SKIP_CACHE;i++) 
			total += render.frameskip.hadSkip[i];
		LOG_MSG( "Skipped frame %d %d", PIC_Ticks, (total * 100) / RENDER_SKIP_CACHE );
#endif
		// Force output to update the screen even if nothing changed...
		// works only with Direct3D output (GFX_StartUpdate() was probably not even called)
		if (render.forceUpdate) GFX_EndUpdate( 0 );
	}
	render.frameskip.index = (render.frameskip.index + 1) & (RENDER_SKIP_CACHE - 1);
	render.updating=false;

	if (pause_on_vsync) {
		pause_on_vsync = false;
		PauseDOSBox(true);
	}
}
Beispiel #9
0
void PIC_Controller::set_imr(Bit8u val) {
	if (GCC_UNLIKELY(machine==MCH_PCJR)) {
		//irq 6 is a NMI on the PCJR
		if (this == &master) val &= ~(1 <<(6));
	}
	Bit8u change = (imr) ^ (val); //Bits that have changed become 1.
	imr  =  val;
	imrr = ~val;

	//Test if changed bits are set in irr and are not being served at the moment
	//Those bits have impact on whether the cpu emulation should be paused or not.
	if((irr & change)&isrr) check_for_irq();
}
Beispiel #10
0
void PIC_AddEvent(PIC_EventHandler handler,float delay,Bitu val) {
	if (GCC_UNLIKELY(!pic_queue.free_entry)) {
		LOG(LOG_PIC,LOG_ERROR)("Event queue full");
		return;
	}
	PICEntry * entry=pic_queue.free_entry;
	if(InEventService) entry->index = delay + srv_lag;
	else entry->index = delay + PIC_TickIndex();

	entry->pic_event=handler;
	entry->value=val;
	pic_queue.free_entry=pic_queue.free_entry->next;
	AddEntry(entry);
}
Beispiel #11
0
static void slave_startIRQ(){
	Bit8u pic1_irq = 8;
	const Bit8u p = (slave.irr & slave.imrr)&slave.isrr;
	const Bit8u max = slave.special?8:slave.active_irq;
	for(Bit8u i = 0,s = 1;i < max;i++, s<<=1){
		if (p&s){
			pic1_irq = i;
			break;
		}
	}
	// Maybe change the E_Exit to a return
	if (GCC_UNLIKELY(pic1_irq == 8)) E_Exit("irq 2 is active, but no irq active on the slave PIC.");

	slave.start_irq(pic1_irq);
	master.start_irq(2);
	CPU_HW_Interrupt(slave.vector_base + pic1_irq);
}
Beispiel #12
0
static void DOS_CompressMemory(void) {
	Bit16u mcb_segment=dos.firstMCB;
	DOS_MCB mcb(mcb_segment);
	DOS_MCB mcb_next(0);

	while (mcb.GetType()!=0x5a) {
		mcb_next.SetPt((Bit16u)(mcb_segment+mcb.GetSize()+1));
		if (GCC_UNLIKELY((mcb_next.GetType()!=0x4d) && (mcb_next.GetType()!=0x5a))) E_Exit("Corrupt MCB chain");
		if ((mcb.GetPSPSeg()==MCB_FREE) && (mcb_next.GetPSPSeg()==MCB_FREE)) {
			mcb.SetSize(mcb.GetSize()+mcb_next.GetSize()+1);
			mcb.SetType(mcb_next.GetType());
		} else {
			mcb_segment+=mcb.GetSize()+1;
			mcb.SetPt(mcb_segment);
		}
	}
}
Beispiel #13
0
bool RENDER_StartUpdate(void) {
	if (GCC_UNLIKELY(render.updating))
		return false;
	if (GCC_UNLIKELY(!render.active))
		return false;
	if (GCC_UNLIKELY(render.frameskip.count<render.frameskip.max)) {
		render.frameskip.count++;
		return false;
	}
	render.frameskip.count=0;
	if (render.scale.inMode == scalerMode8) {
		Check_Palette();
	}
	render.scale.inLine = 0;
	render.scale.outLine = 0;
	render.scale.cacheRead = (Bit8u*)&scalerSourceCache;
	render.scale.outWrite = 0;
	render.scale.outPitch = 0;
	Scaler_ChangedLines[0] = 0;
	Scaler_ChangedLineIndex = 0;
	/* Clearing the cache will first process the line to make sure it's never the same */
	if (GCC_UNLIKELY( render.scale.clearCache) ) {
//		LOG_MSG("Clearing cache");
		//Will always have to update the screen with this one anyway, so let's update already
		if (GCC_UNLIKELY(!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )))
			return false;
		render.fullFrame = true;
		render.scale.clearCache = false;
		RENDER_DrawLine = RENDER_ClearCacheHandler;
	} else {
		if (render.pal.changed) {
			/* Assume pal changes always do a full screen update anyway */
			if (GCC_UNLIKELY(!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )))
				return false;
			RENDER_DrawLine = render.scale.linePalHandler;
			render.fullFrame = true;
		} else {
			RENDER_DrawLine = RENDER_StartLineHandler;
			if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO))) 
				render.fullFrame = true;
			else
				render.fullFrame = false;
		}
	}
	render.updating = true;
	return true;
}
void VGA_ATTR_SetPalette(Bit8u index,Bit8u val) {
	vga.attr.palette[index] = val;
	if (vga.attr.mode_control & 0x80) val = (val&0xf) | (vga.attr.color_select << 4);
	val &= 63;
	val |= (vga.attr.color_select & 0xc) << 4;
	if (GCC_UNLIKELY(machine==MCH_EGA)) {
		if ((vga.crtc.vertical_total | ((vga.crtc.overflow & 1) << 8)) == 260) {
			// check for intensity bit
			if (val&0x10) val|=0x38;
			else {
				val&=0x7;
				// check for special brown
				if (val==6) val=0x14;
			}
		}
	}
	VGA_DAC_CombineColor(index,val);
}
Beispiel #15
0
void PIC_ActivateIRQ(Bitu irq) {
	Bitu t = irq>7 ? (irq - 8): irq;
	PIC_Controller * pic=&pics[irq>7 ? 1 : 0];

	Bit32s OldCycles = CPU_Cycles;
	pic->raise_irq(t); //Will set the CPU_Cycles to zero if this IRQ will be handled directly

	if (GCC_UNLIKELY(OldCycles != CPU_Cycles)) {
		// if CPU_Cycles have changed, this means that the interrupt was triggered by an I/O
		// register write rather than an event.
		// Real hardware executes 0 to ~13 NOPs or comparable instructions
		// before the processor picks up the interrupt. Let's try with 2
		// cycles here.
		// Required by Panic demo (irq0), It came from the desert (MPU401)
		// Does it matter if CPU_CycleLeft becomes negative?

		// It might be an idea to do this always in order to simulate this
		// So on write mask and EOI as well. (so inside the activate function)
//		CPU_CycleLeft += (CPU_Cycles-2);
		CPU_CycleLeft -= 2;
		CPU_Cycles = 2;
	}
}
Beispiel #16
0
static void RENDER_StartLineHandler(const void * s) {
	if (s) {
		const Bitu *src = (Bitu*)s;
		Bitu *cache = (Bitu*)(render.scale.cacheRead);
		for (Bits x=render.src.start;x>0;) {
			if (GCC_UNLIKELY(src[0] != cache[0])) {
				if (!GFX_StartUpdate( render.scale.outWrite, render.scale.outPitch )) {
					RENDER_DrawLine = RENDER_EmptyLineHandler;
					return;
				}
				render.scale.outWrite += render.scale.outPitch * Scaler_ChangedLines[0];
				RENDER_DrawLine = render.scale.lineHandler;
				RENDER_DrawLine( s );
				return;
			}
			x--; src++; cache++;
		}
	}
	render.scale.cacheRead += render.scale.cachePitch;
	Scaler_ChangedLines[0] += Scaler_Aspect[ render.scale.inLine ];
	render.scale.inLine++;
	render.scale.outLine++;
}
Beispiel #17
0
Bits DOS_Drive_Cache::GetLongName(CFileInfo* curDir, char* shortName) {
	std::vector<CFileInfo*>::size_type filelist_size = curDir->fileList.size();
	if (GCC_UNLIKELY(filelist_size<=0)) return -1;

	// Remove dot, if no extension...
	RemoveTrailingDot(shortName);
	// Search long name and return array number of element
	Bits low	= 0;
	Bits high	= (Bits)(filelist_size-1);
	Bits mid,res;
	while (low<=high) {
		mid = (low+high)/2;
		res = strcmp(shortName,curDir->fileList[mid]->shortname);
		if (res>0)	low  = mid+1; else
		if (res<0)	high = mid-1; else
		{	// Found
			strcpy(shortName,curDir->fileList[mid]->orgname);
			return mid;
		};
	}
	// not available
	return -1;
}
Beispiel #18
0
void RENDER_EndUpdate( bool abort ) {
	if (GCC_UNLIKELY(!render.updating))
		return;
	RENDER_DrawLine = RENDER_EmptyLineHandler;
	GFX_EndUpdate(NULL);
	/*
	if (GCC_UNLIKELY(CaptureState & (CAPTURE_IMAGE|CAPTURE_VIDEO))) {
		Bitu pitch, flags;
		flags = 0;
		if (render.src.dblw != render.src.dblh) {
			if (render.src.dblw) flags|=CAPTURE_FLAG_DBLW;
			if (render.src.dblh) flags|=CAPTURE_FLAG_DBLH;
		}
		float fps = render.src.fps;
		pitch = render.scale.cachePitch;
		if (render.frameskip.max)
			fps /= 1+render.frameskip.max;
		CAPTURE_AddImage( render.src.width, render.src.height, render.src.bpp, pitch,
			flags, fps, (Bit8u *)&scalerSourceCache, (Bit8u*)&render.pal.rgb );
	}
	*/
	render.updating=false;
}
Beispiel #19
0
bool PIC_RunQueue(void) {
	/* Check to see if a new millisecond needs to be started */
	CPU_CycleLeft+=CPU_Cycles;
	CPU_Cycles=0;
	if (CPU_CycleLeft<=0) {
		return false;
	}
	/* Check the queue for an entry */
	Bits index_nd=PIC_TickIndexND();
	InEventService = true;
	while (pic_queue.next_entry && (pic_queue.next_entry->index*CPU_CycleMax<=index_nd)) {
		PICEntry * entry=pic_queue.next_entry;
		pic_queue.next_entry=entry->next;

		srv_lag = entry->index;
		(entry->pic_event)(entry->value); // call the event handler

		/* Put the entry in the free list */
		entry->next=pic_queue.free_entry;
		pic_queue.free_entry=entry;
	}
	InEventService = false;

	/* Check when to set the new cycle end */
	if (pic_queue.next_entry) {
		Bits cycles=(Bits)(pic_queue.next_entry->index*CPU_CycleMax-index_nd);
		if (GCC_UNLIKELY(!cycles)) cycles=1;
		if (cycles<CPU_CycleLeft) {
			CPU_Cycles=cycles;
		} else {
			CPU_Cycles=CPU_CycleLeft;
		}
	} else CPU_Cycles=CPU_CycleLeft;
	CPU_CycleLeft-=CPU_Cycles;
	if 	(PIC_IRQCheck)	PIC_runIRQs();
	return true;
}
Beispiel #20
0
bool DOS_Drive_Cache::GetShortName(const char* fullname, char* shortname) {
	// Get Dir Info
	char expand[CROSS_LEN] = {0};
	CFileInfo* curDir = FindDirInfo(fullname,expand);

	std::vector<CFileInfo*>::size_type filelist_size = curDir->longNameList.size();
	if (GCC_UNLIKELY(filelist_size<=0)) return false;

	Bits low		= 0;
	Bits high		= (Bits)(filelist_size-1);
	Bits mid, res;

	while (low<=high) {
		mid = (low+high)/2;
		res = strcmp(fullname,curDir->longNameList[mid]->orgname);
		if (res>0)	low  = mid+1; else
		if (res<0)	high = mid-1; 
		else {
			strcpy(shortname,curDir->longNameList[mid]->shortname);
			return true;
		};
	}
	return false;
}
Beispiel #21
0
void PIC_RemoveEvents(PIC_EventHandler handler) {
	PICEntry * entry=pic_queue.next_entry;
	PICEntry * prev_entry;
	prev_entry=0;
	while (entry) {
		if (GCC_UNLIKELY(entry->pic_event==handler)) {
			if (prev_entry) {
				prev_entry->next=entry->next;
				entry->next=pic_queue.free_entry;
				pic_queue.free_entry=entry;
				entry=prev_entry->next;
				continue;
			} else {
				pic_queue.next_entry=entry->next;
				entry->next=pic_queue.free_entry;
				pic_queue.free_entry=entry;
				entry=pic_queue.next_entry;
				continue;
			}
		}
		prev_entry=entry;
		entry=entry->next;
	}	
}
Beispiel #22
0
bool DOS_ResizeMemory(Bit16u segment,Bit16u * blocks) {
	if (segment < DOS_MEM_START+1) {
		LOG(LOG_DOSMISC,LOG_ERROR)("Program resizes %X, take care",segment);
	}
      
	DOS_MCB mcb(segment-1);
	if ((mcb.GetType()!=0x4d) && (mcb.GetType()!=0x5a)) {
		DOS_SetError(DOSERR_MCB_DESTROYED);
		return false;
	}

	DOS_CompressMemory();
	Bit16u total=mcb.GetSize();
	DOS_MCB	mcb_next(segment+total);
	if (*blocks<=total) {
		if (GCC_UNLIKELY(*blocks==total)) {
			/* Nothing to do */
			return true;
		}
		/* Shrinking MCB */
		DOS_MCB	mcb_new_next(segment+(*blocks));
		mcb.SetSize(*blocks);
		mcb_new_next.SetType(mcb.GetType());
		if (mcb.GetType()==0x5a) {
			/* Further blocks follow */
			mcb.SetType(0x4d);
		}

		mcb_new_next.SetSize(total-*blocks-1);
		mcb_new_next.SetPSPSeg(MCB_FREE);
		mcb.SetPSPSeg(dos.psp());
		DOS_CompressMemory();
		return true;
	}
	/* MCB will grow, try to join with following MCB */
	if (mcb.GetType()!=0x5a) {
		if (mcb_next.GetPSPSeg()==MCB_FREE) {
			total+=mcb_next.GetSize()+1;
		}
	}
	if (*blocks<total) {
		if (mcb.GetType()!=0x5a) {
			/* save type of following MCB */
			mcb.SetType(mcb_next.GetType());
		}
		mcb.SetSize(*blocks);
		mcb_next.SetPt((Bit16u)(segment+*blocks));
		mcb_next.SetSize(total-*blocks-1);
		mcb_next.SetType(mcb.GetType());
		mcb_next.SetPSPSeg(MCB_FREE);
		mcb.SetType(0x4d);
		mcb.SetPSPSeg(dos.psp());
		return true;
	}

	/* at this point: *blocks==total (fits) or *blocks>total,
	   in the second case resize block to maximum */

	if ((mcb_next.GetPSPSeg()==MCB_FREE) && (mcb.GetType()!=0x5a)) {
		/* adjust type of joined MCB */
		mcb.SetType(mcb_next.GetType());
	}
	mcb.SetSize(total);
	mcb.SetPSPSeg(dos.psp());
	if (*blocks==total) return true;	/* block fit exactly */

	*blocks=total;	/* return maximum */
	DOS_SetError(DOSERR_INSUFFICIENT_MEMORY);
	return false;
}
Beispiel #23
0
inline void IO_USEC_write_delay() {
	Bits delaycyc = CPU_CycleMax/IODELAY_WRITE_MICROSk;
	if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc=0;
	CPU_Cycles -= delaycyc;
	CPU_IODelayRemoved += delaycyc;
}
Beispiel #24
0
inline void IO_USEC_read_delay() {
	Bits delaycyc = CPU_CycleMax/IODELAY_READ_MICROSk;
	if(GCC_UNLIKELY(CPU_Cycles < 3*delaycyc)) delaycyc = 0; //Else port acces will set cycles to 0. which might trigger problem with games which read 16 bit values
	CPU_Cycles -= delaycyc;
	CPU_IODelayRemoved += delaycyc;
}
Beispiel #25
0
// Draw a textured quad on the back-buffer
bool CDirect3D::D3DSwapBuffers(void)
{
    HRESULT hr;
    UINT uPasses;

	if (backbuffer_clear_countdown > 0) {
		backbuffer_clear_countdown--;
		pD3DDevice9->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);
	}

#if DOSBOXMENU_TYPE == DOSBOXMENU_SDLDRAW
    // If the SDL drawn menus are visible, copy the SDL surface to the Direct3D surface to keep them visible on-screen
    if (mainMenu.isVisible() && mainMenu.menuBox.h != 0 && dwY >= mainMenu.menuBox.h)
	UpdateRectFromSDLSurface(0, 0, mainMenu.menuBox.w, mainMenu.menuBox.h);
#endif

    // begin rendering
    pD3DDevice9->BeginScene();

#if C_D3DSHADERS
    /* PS 2.0 path */
    if(psActive) {

	if(preProcess) {

	    // Set preprocess matrices
	    if(FAILED(psEffect->SetMatrices(m_matPreProj, m_matPreView, m_matPreWorld))) {
		LOG_MSG("D3D:Set matrices failed.");
		return false;
	    }

	    // Save render target
	    LPDIRECT3DSURFACE9 lpRenderTarget;
	    pD3DDevice9->GetRenderTarget(0, &lpRenderTarget);
	    LPDIRECT3DTEXTURE9 lpWorkTexture = lpWorkTexture1;
pass2:
	    // Change the render target
	    LPDIRECT3DSURFACE9 lpNewRenderTarget;
	    lpWorkTexture->GetSurfaceLevel(0, &lpNewRenderTarget);

	    if(FAILED(pD3DDevice9->SetRenderTarget(0, lpNewRenderTarget))) {
		LOG_MSG("D3D:Failed to set render target");
		return false;
	    }

	    SAFE_RELEASE(lpNewRenderTarget);

	    uPasses = 0;
	    if(FAILED(psEffect->Begin((lpWorkTexture==lpWorkTexture1) ?
		    (ScalingEffect::Preprocess1):(ScalingEffect::Preprocess2), &uPasses))) {
		LOG_MSG("D3D:Failed to begin PS");
		return false;
	    }

	    for(UINT uPass=0;uPass<uPasses;uPass++) {
		hr=psEffect->BeginPass(uPass);
		if(FAILED(hr)) {
		    LOG_MSG("D3D:Failed to begin pass %d", uPass);
		    return false;
		}

		// Render the vertex buffer contents
		pD3DDevice9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 4, 2);
		psEffect->EndPass();
	    }

	    if(FAILED(psEffect->End())) {
		LOG_MSG("D3D:Failed to end effect");
		return false;
	    }

#if DEBUG_PS
	    // Save rendertarget data
	    LPDIRECT3DSURFACE9 lpTexRenderTarget;
	    lpWorkTexture->GetSurfaceLevel(0, &lpTexRenderTarget);
	    lpDebugTexture->GetSurfaceLevel(0, &lpNewRenderTarget);
	    if(FAILED(hr=pD3DDevice9->GetRenderTargetData(lpTexRenderTarget, lpNewRenderTarget))) {
		LOG_MSG("D3D:Unable to get render target data: 0x%x", hr);
		SAFE_RELEASE(lpTexRenderTarget);
		SAFE_RELEASE(lpNewRenderTarget);
	    } else {
		SAFE_RELEASE(lpTexRenderTarget);
		SAFE_RELEASE(lpNewRenderTarget);
		LOG_MSG("D3D:Got render target data, writing debug file (%dx%d)", dwTexWidth, dwTexHeight);
		if(lpDebugTexture->LockRect(0, &d3dlr, NULL, D3DLOCK_READONLY) == D3D_OK) {
		    FILE * debug = fopen(((lpWorkTexture==lpWorkTexture1)?"pass1.raw":"pass2.raw"), "wb");
		    if(debug == NULL) {
			LOG_MSG("D3D:Unable to create file!");
		    } else {
			for(int i = 0; i < dwTexHeight; i++) {
			    Bit8u * ptr = (Bit8u*)d3dlr.pBits;
			    for(int j = 0; j < dwTexWidth; j++) {
				fwrite(ptr, 3, sizeof(char), debug);
				ptr += 4;
			    }
			    d3dlr.pBits = (Bit8u*)d3dlr.pBits + d3dlr.Pitch;
			}
			fclose(debug);
		    }
		    lpDebugTexture->UnlockRect(0);
		}
		d3dlr.pBits = NULL;
	    }
#endif

	    if((psEffect->hasPreprocess2()) && (lpWorkTexture == lpWorkTexture1)) {
		lpWorkTexture = lpWorkTexture2;
		goto pass2;
	    }

	    // Reset the rendertarget
	    pD3DDevice9->SetRenderTarget(0, lpRenderTarget);
	    SAFE_RELEASE(lpRenderTarget);

	    // Set matrices for final pass
	    if(FAILED(psEffect->SetMatrices(m_matProj, m_matView, m_matWorld))) {
		LOG_MSG("D3D:Set matrices failed.");
		return false;
	    }
	}

	uPasses = 0;

	if(FAILED(psEffect->Begin(ScalingEffect::Combine, &uPasses))) {
	    LOG_MSG("D3D:Failed to begin PS");
	    return false;
	}

	for(UINT uPass=0;uPass<uPasses;uPass++) {
	    hr=psEffect->BeginPass(uPass);
	    if(FAILED(hr)) {
		LOG_MSG("D3D:Failed to begin pass %d", uPass);
		return false;
	    }

	    // Render the vertex buffer contents
	    pD3DDevice9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
	    psEffect->EndPass();
	}

	if(FAILED(psEffect->End())) {
	    LOG_MSG("D3D:Failed to end effect");
	    return false;
	}

    } else
#endif
    {
	// Normal path
	pD3DDevice9->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
    }

    // end rendering
    pD3DDevice9->EndScene();

    if(GCC_UNLIKELY(hr=pD3DDevice9->Present(NULL, NULL, NULL, NULL)) != D3D_OK) {
	switch(hr) {
	    case D3DERR_DEVICELOST:
        LOG_MSG("D3D:Driver device lost");
        if (!deviceLost) {
            deviceLost = true;
            void RENDER_CallBack(GFX_CallBackFunctions_t f);
            RENDER_CallBack(GFX_CallBackRedraw);
        }
		return false;
		break;
	    case D3DERR_DRIVERINTERNALERROR:
		LOG_MSG("D3D:Driver internal error");
		return false;
		break;
	    case D3DERR_INVALIDCALL:
	    default:
		LOG_MSG("D3D:Invalid call");
		return false;
		break;
	}
    }

    return true;
}
Beispiel #26
0
Bits CPU_Core_Dynrec_Run(void) {
	for (;;) {
		// Determine the linear address of CS:EIP
		PhysPt ip_point=SegPhys(cs)+reg_eip;
		#if C_HEAVY_DEBUG
			if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
		#endif

		CodePageHandlerDynRec * chandler=0;
		// see if the current page is present and contains code
		if (GCC_UNLIKELY(MakeCodePage(ip_point,chandler))) {
			// page not present, throw the exception
			CPU_Exception(cpu.exception.which,cpu.exception.error);
			continue;
		}

		// page doesn't contain code or is special
		if (GCC_UNLIKELY(!chandler)) return CPU_Core_Normal_Run();

		// find correct Dynamic Block to run
		CacheBlockDynRec * block=chandler->FindCacheBlock(ip_point&4095);
		if (!block) {
			// no block found, thus translate the instruction stream
			// unless the instruction is known to be modified
			if (!chandler->invalidation_map || (chandler->invalidation_map[ip_point&4095]<4)) {
				// translate up to 32 instructions
				block=CreateCacheBlock(chandler,ip_point,32);
			} else {
				// let the normal core handle this instruction to avoid zero-sized blocks
				Bitu old_cycles=CPU_Cycles;
				CPU_Cycles=1;
				Bits nc_retcode=CPU_Core_Normal_Run();
				if (!nc_retcode) {
					CPU_Cycles=old_cycles-1;
					continue;
				}
				CPU_CycleLeft+=old_cycles;
				return nc_retcode; 
			}
		}

run_block:
		cache.block.running=0;
		// now we're ready to run the dynamic code block
//		BlockReturn ret=((BlockReturn (*)(void))(block->cache.start))();
		BlockReturn ret=core_dynrec.runcode(block->cache.start);

		switch (ret) {
		case BR_Iret:
#if C_HEAVY_DEBUG
			if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
			if (!GETFLAG(TF)) {
				if (GETFLAG(IF) && PIC_IRQCheck) return CBRET_NONE;
				break;
			}
			// trapflag is set, switch to the trap-aware decoder
			cpudecoder=CPU_Core_Dynrec_Trap_Run;
			return CBRET_NONE;

		case BR_Normal:
			// the block was exited due to a non-predictable control flow
			// modifying instruction (like ret) or some nontrivial cpu state
			// changing instruction (for example switch to/from pmode),
			// or the maximal number of instructions to translate was reached
#if C_HEAVY_DEBUG
			if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
			break;

		case BR_Cycles:
			// cycles went negative, return from the core to handle
			// external events, schedule the pic...
#if C_HEAVY_DEBUG			
			if (DEBUG_HeavyIsBreakpoint()) return debugCallback;
#endif
			return CBRET_NONE;

		case BR_CallBack:
			// the callback code is executed in dosbox.conf, return the callback number
			FillFlags();
			return core_dynrec.callback;

		case BR_SMCBlock:
//			LOG_MSG("selfmodification of running block at %x:%x",SegValue(cs),reg_eip);
			cpu.exception.which=0;
			// fallthrough, let the normal core handle the block-modifying instruction
		case BR_Opcode:
			// some instruction has been encountered that could not be translated
			// (thus it is not part of the code block), the normal core will
			// handle this instruction
			CPU_CycleLeft+=CPU_Cycles;
			CPU_Cycles=1;
			return CPU_Core_Normal_Run();

#if (C_DEBUG)
		case BR_OpcodeFull:
			CPU_CycleLeft+=CPU_Cycles;
			CPU_Cycles=1;
			return CPU_Core_Full_Run();
#endif

		case BR_Link1:
		case BR_Link2:
			block=LinkBlocks(ret);
			if (block) goto run_block;
			break;

		default:
			E_Exit("Invalid return code %d", ret);
		}
	}
	return CBRET_NONE;
}
Beispiel #27
0
void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) {
//	if((crtc(index)!=0xe)&&(crtc(index)!=0xf)) 
//		LOG_MSG("CRTC w #%2x val %2x",crtc(index),val);
	switch(crtc(index)) {
	case 0x00:	/* Horizontal Total Register */
		if (crtc(read_only)) break;
		crtc(horizontal_total)=val;
		/* 	0-7  Horizontal Total Character Clocks-5 */
		break;
	case 0x01:	/* Horizontal Display End Register */
		if (crtc(read_only)) break;
		if (val != crtc(horizontal_display_end)) {
			crtc(horizontal_display_end)=val;
			VGA_StartResize();
		}
		/* 	0-7  Number of Character Clocks Displayed -1 */
		break;
	case 0x02:	/* Start Horizontal Blanking Register */
		if (crtc(read_only)) break;
		crtc(start_horizontal_blanking)=val;
		/*	0-7  The count at which Horizontal Blanking starts */
		break;
	case 0x03:	/* End Horizontal Blanking Register */
		if (crtc(read_only)) break;
		crtc(end_horizontal_blanking)=val;
		/*
			0-4	Horizontal Blanking ends when the last 6 bits of the character
				counter equals this field. Bit 5 is at 3d4h index 5 bit 7.
			5-6	Number of character clocks to delay start of display after Horizontal
				Total has been reached.
			7	Access to Vertical Retrace registers if set. If clear reads to 3d4h
				index 10h and 11h access the Lightpen read back registers ??
		*/
		break;
	case 0x04:	/* Start Horizontal Retrace Register */
		if (crtc(read_only)) break;
		crtc(start_horizontal_retrace)=val;
		/*	0-7  Horizontal Retrace starts when the Character Counter reaches this value. */
		break;
	case 0x05:	/* End Horizontal Retrace Register */
		if (crtc(read_only)) break;
		crtc(end_horizontal_retrace)=val;
		/*
			0-4	Horizontal Retrace ends when the last 5 bits of the character counter
				equals this value.
			5-6	Number of character clocks to delay start of display after Horizontal
				Retrace.
			7	bit 5 of the End Horizontal Blanking count (See 3d4h index 3 bit 0-4)
		*/	
		break;
	case 0x06: /* Vertical Total Register */
		if (crtc(read_only)) break;
		if (val != crtc(vertical_total)) {
			crtc(vertical_total)=val;	
			VGA_StartResize();
		}
		/*	0-7	Lower 8 bits of the Vertical Total. Bit 8 is found in 3d4h index 7
				bit 0. Bit 9 is found in 3d4h index 7 bit 5.
			Note: For the VGA this value is the number of scan lines in the display -2.
		*/
		break;
	case 0x07:	/* Overflow Register */
		//Line compare bit ignores read only */
		vga.config.line_compare=(vga.config.line_compare & 0x6ff) | (val & 0x10) << 4;
		if (crtc(read_only)) break;
		if ((vga.crtc.overflow ^ val) & 0xd6) {
			crtc(overflow)=val;
			VGA_StartResize();
		} else crtc(overflow)=val;
		/*
			0  Bit 8 of Vertical Total (3d4h index 6)
			1  Bit 8 of Vertical Display End (3d4h index 12h)
			2  Bit 8 of Vertical Retrace Start (3d4h index 10h)
			3  Bit 8 of Start Vertical Blanking (3d4h index 15h)
			4  Bit 8 of Line Compare Register (3d4h index 18h)
			5  Bit 9 of Vertical Total (3d4h index 6)
			6  Bit 9 of Vertical Display End (3d4h index 12h)
			7  Bit 9 of Vertical Retrace Start (3d4h index 10h)
		*/
		break;
	case 0x08:	/* Preset Row Scan Register */
		crtc(preset_row_scan)=val;
		vga.config.hlines_skip=val&31;
		if (IS_VGA_ARCH) vga.config.bytes_skip=(val>>5)&3;
		else vga.config.bytes_skip=0;
//		LOG_DEBUG("Skip lines %d bytes %d",vga.config.hlines_skip,vga.config.bytes_skip);
		/*
			0-4	Number of lines we have scrolled down in the first character row.
				Provides Smooth Vertical Scrolling.b
			5-6	Number of bytes to skip at the start of scanline. Provides Smooth
				Horizontal Scrolling together with the Horizontal Panning Register
				(3C0h index 13h).
		*/
		break;
	case 0x09: /* Maximum Scan Line Register */
	{
		if (IS_VGA_ARCH) {
			vga.config.line_compare &= 0x5ff;
			vga.config.line_compare |= (val&0x40)<<3;
		} else if(machine==MCH_EGA) {
			val &= 0x7f; // EGA ignores the doublescan bit
			}
		Bit8u old = crtc(maximum_scan_line);
		crtc(maximum_scan_line) = val;

		if(!vga.draw.doublescan_merging) {
			if ((old ^ val) & 0x20) VGA_StartResize();
			vga.draw.address_line_total = (val &0x1F) + 1;
			if (val&0x80) vga.draw.address_line_total*=2;
		} else if ((old ^ val) & 0xbf)
				VGA_StartResize();
		/*
			0-4	Number of scan lines in a character row -1. In graphics modes this is
				the number of times (-1) the line is displayed before passing on to
				the next line (0: normal, 1: double, 2: triple...).
				This is independent of bit 7, except in CGA modes which seems to
				require this field to be 1 and bit 7 to be set to work.
			5	Bit 9 of Start Vertical Blanking
			6	Bit 9 of Line Compare Register
			7	Doubles each scan line if set. I.e. displays 200 lines on a 400 display.
		*/
		break;
	}
	case 0x0A:	/* Cursor Start Register */
		crtc(cursor_start)=val;
		vga.draw.cursor.sline=val&0x1f;
		if (IS_VGA_ARCH) vga.draw.cursor.enabled=!(val&0x20);
		else vga.draw.cursor.enabled=true;
		/*
			0-4	First scanline of cursor within character.
			5	Turns Cursor off if set
		*/
		break;
	case 0x0B:	/* Cursor End Register */
		crtc(cursor_end)=val;
		vga.draw.cursor.eline=val&0x1f;
		vga.draw.cursor.delay=(val>>5)&0x3;

		/* 
			0-4	Last scanline of cursor within character
			5-6	Delay of cursor data in character clocks.
		*/
		break;
	case 0x0C:	/* Start Address High Register */
		crtc(start_address_high)=val;
		vga.config.display_start=(vga.config.display_start & 0xFF00FF)| (val << 8);
		/* 0-7  Upper 8 bits of the start address of the display buffer */
		page_flip_debug_notify();
		break;
	case 0x0D:	/* Start Address Low Register */
		crtc(start_address_low)=val;
		vga.config.display_start=(vga.config.display_start & 0xFFFF00)| val;
		/*	0-7	Lower 8 bits of the start address of the display buffer */
		page_flip_debug_notify();
		break;
	case 0x0E:	/*Cursor Location High Register */
		crtc(cursor_location_high)=val;
		vga.config.cursor_start&=0xff00ff;
		vga.config.cursor_start|=val << 8;
		/*	0-7  Upper 8 bits of the address of the cursor */
		break;
	case 0x0F:	/* Cursor Location Low Register */
//TODO update cursor on screen
		crtc(cursor_location_low)=val;
		vga.config.cursor_start&=0xffff00;
		vga.config.cursor_start|=val;
		/*	0-7  Lower 8 bits of the address of the cursor */
		break;
	case 0x10:	/* Vertical Retrace Start Register */
		crtc(vertical_retrace_start)=val;
		/*	
			0-7	Lower 8 bits of Vertical Retrace Start. Vertical Retrace starts when
			the line counter reaches this value. Bit 8 is found in 3d4h index 7
			bit 2. Bit 9 is found in 3d4h index 7 bit 7.
		*/
		break;
	case 0x11:	/* Vertical Retrace End Register */
		crtc(vertical_retrace_end)=val;
		
		if (IS_EGAVGA_ARCH && !(val & 0x10)) {
			vga.draw.vret_triggered=false;
			if (GCC_UNLIKELY(machine==MCH_EGA)) PIC_DeActivateIRQ(9);
		}
		if (IS_VGA_ARCH) crtc(read_only)=(val & 128)>0;
		else crtc(read_only)=false;
		/*
			0-3	Vertical Retrace ends when the last 4 bits of the line counter equals
				this value.
			4	if clear Clears pending Vertical Interrupts.
			5	Vertical Interrupts (IRQ 2) disabled if set. Can usually be left
				disabled, but some systems (including PS/2) require it to be enabled.
			6	If set selects 5 refresh cycles per scanline rather than 3.
			7	Disables writing to registers 0-7 if set 3d4h index 7 bit 4 is not
				affected by this bit.
		*/
		break;
	case 0x12:	/* Vertical Display End Register */
		if (val!=crtc(vertical_display_end)) {
			if (abs((Bits)val-(Bits)crtc(vertical_display_end))<3) {
				// delay small vde changes a bit to avoid screen resizing
				// if they are reverted in a short timeframe
				PIC_RemoveEvents(VGA_SetupDrawing);
				vga.draw.resizing=false;
				crtc(vertical_display_end)=val;
				VGA_StartResize(150);
			} else {
				crtc(vertical_display_end)=val;
				VGA_StartResize();
			}
		}
		/*
			0-7	Lower 8 bits of Vertical Display End. The display ends when the line
				counter reaches this value. Bit 8 is found in 3d4h index 7 bit 1.
			Bit 9 is found in 3d4h index 7 bit 6.
		*/
		break;
	case 0x13:	/* Offset register */
		crtc(offset)=val;
		vga.config.scan_len&=0x300;
		vga.config.scan_len|=val;
		VGA_CheckScanLength();
		/*
			0-7	Number of bytes in a scanline / K. Where K is 2 for byte mode, 4 for
				word mode and 8 for Double Word mode.
		*/
		break;
	case 0x14:	/* Underline Location Register */
		crtc(underline_location)=val;
		if (IS_VGA_ARCH) {
			//Byte,word,dword mode
			if ( crtc(underline_location) & 0x40 )
				vga.config.addr_shift = 2;
			else if ( crtc( mode_control) & 0x40 )
				vga.config.addr_shift = 0;
			else
				vga.config.addr_shift = 1;
		} else {
			vga.config.addr_shift = 1;
		}

		VGA_CheckScanLength();
		/*
			0-4	Position of underline within Character cell.
			5	If set memory address is only changed every fourth character clock.
			6	Double Word mode addressing if set
		*/
		break;
	case 0x15:	/* Start Vertical Blank Register */
		if (val!=crtc(start_vertical_blanking)) {
			crtc(start_vertical_blanking)=val;
			VGA_StartResize();
		}
		/* 
			0-7	Lower 8 bits of Vertical Blank Start. Vertical blanking starts when
				the line counter reaches this value. Bit 8 is found in 3d4h index 7
				bit 3.
		*/
		break;
	case 0x16:	/*  End Vertical Blank Register */
		if (val!=crtc(end_vertical_blanking)) {
			crtc(end_vertical_blanking)=val;
			VGA_StartResize();
		}
		/*
			0-6	Vertical blanking stops when the lower 7 bits of the line counter
				equals this field. Some SVGA chips uses all 8 bits!
				IBM actually says bits 0-7.
		*/
		break;
	case 0x17:	/* Mode Control Register */
		crtc(mode_control)=val;
		vga.tandy.line_mask = (~val) & 3;
		//Byte,word,dword mode
		if ( crtc(underline_location) & 0x40 )
			vga.config.addr_shift = 2;
		else if ( crtc( mode_control) & 0x40 )
			vga.config.addr_shift = 0;
		else
			vga.config.addr_shift = 1;

		if ( vga.tandy.line_mask ) {
			vga.tandy.line_shift = 13;
			vga.tandy.addr_mask = (1 << 13) - 1;
		} else {
			vga.tandy.addr_mask = ~0;
			vga.tandy.line_shift = 0;
		}
		VGA_CheckScanLength();

		//Should we really need to do a determinemode here?
//		VGA_DetermineMode();
		/*
			0	If clear use CGA compatible memory addressing system
				by substituting character row scan counter bit 0 for address bit 13,
				thus creating 2 banks for even and odd scan lines.
			1	If clear use Hercules compatible memory addressing system by
				substituting character row scan counter bit 1 for address bit 14,
				thus creating 4 banks.
			2	If set increase scan line counter only every second line.
			3	If set increase memory address counter only every other character clock.
			5	When in Word Mode bit 15 is rotated to bit 0 if this bit is set else
				bit 13 is rotated into bit 0.
			6	If clear system is in word mode. Addresses are rotated 1 position up
				bringing either bit 13 or 15 into bit 0.
			7	Clearing this bit will reset the display system until the bit is set again.
		*/
		break;
	case 0x18:	/* Line Compare Register */
		crtc(line_compare)=val;
		vga.config.line_compare=(vga.config.line_compare & 0x700) | val;
		/*
			0-7	Lower 8 bits of the Line Compare. When the Line counter reaches this
				value, the display address wraps to 0. Provides Split Screen
				facilities. Bit 8 is found in 3d4h index 7 bit 4.
				Bit 9 is found in 3d4h index 9 bit 6.
		*/
		break;
	default:
		if (svga.write_p3d5) {
			svga.write_p3d5(crtc(index), val, iolen);
		} else {
			LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:CRTC:Write to unknown index %X",crtc(index));
		}
		break;
	}