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(); }
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; } }
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; }
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; } }
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"); } }
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 ); }
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; }
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); } }
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(); }
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); }
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); }
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); } } }
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); }
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; } }
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++; }
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; }
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; }
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; }
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; }
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; } }
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; }
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; }
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; }
// 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; }
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; }
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; }