void COGLGraphicsContext::UpdateFrame(bool swapOnly) { status.gFrameCount++; glFlush(); OPENGL_CHECK_ERRORS; // if emulator defined a render callback function, call it before buffer swap if (renderCallback) (*renderCallback)(status.bScreenIsDrawn); retro_return(true); glDepthMask(GL_TRUE); OPENGL_CHECK_ERRORS; glClearDepth(1.0f); OPENGL_CHECK_ERRORS; if (!g_curRomInfo.bForceScreenClear) { glClear(GL_DEPTH_BUFFER_BIT); OPENGL_CHECK_ERRORS; } else { needCleanScene = true; } status.bScreenIsDrawn = false; }
void angrylionUpdateScreen(void) { static int counter; #ifdef HAVE_FRAMESKIP if (counter++ < skip) return; counter = 0; #endif rdp_update(); retro_return(true); #if 0 if (step != 0) MessageBox(NULL, "Updated screen.\nPaused.", "Frame Step", MB_OK); #endif return; }
void glide64UpdateScreen (void) { bool forced_update = false; uint32_t width = (*gfx_info.VI_WIDTH_REG) << 1; if (*gfx_info.VI_ORIGIN_REG > width) update_screen_count++; if ( (settings.frame_buffer & fb_cpu_write_hack) && (update_screen_count > ((settings.hacks&hack_Lego) ? 15U : 30U)) && (rdp.last_bg == 0) ) { //DirectCPUWrite hack update_screen_count = 0; no_dlist = true; ClearCache (); width = (*gfx_info.VI_WIDTH_REG) << 1; if (*gfx_info.VI_ORIGIN_REG > width) update_screen_count++; } if( no_dlist ) { if( *gfx_info.VI_ORIGIN_REG > width ) { ChangeSize(); LRDP("ChangeSize done\n"); if (rdp.vi_height != 0) drawViRegBG(); rdp.updatescreen = 1; forced_update = true; } else return; } if (settings.swapmode == 0 || forced_update) newSwapBuffers (); if (settings.swapmode_retro && BUFFERSWAP) retro_return(true); }
void COGLGraphicsContext::UpdateFrame(bool swapOnly) { status.gFrameCount++; glFlush(); OPENGL_CHECK_ERRORS; //glFinish(); //wglSwapIntervalEXT(0); /* if (debuggerPauseCount == countToPause) { static int iShotNum = 0; // get width, height, allocate buffer to store image int width = windowSetting.uDisplayWidth; int height = windowSetting.uDisplayHeight; printf("Saving debug images: width=%i height=%i\n", width, height); short *buffer = (short *) malloc(((width+3)&~3)*(height+1)*4); glReadBuffer( GL_FRONT ); // set up a BMGImage struct struct BMGImageStruct img; memset(&img, 0, sizeof(BMGImageStruct)); InitBMGImage(&img); img.bits = (unsigned char *) buffer; img.bits_per_pixel = 32; img.height = height; img.width = width; img.scan_width = width * 4; // store the RGB color image char chFilename[64]; sprintf(chFilename, "dbg_rgb_%03i.png", iShotNum); glReadPixels(0,0,width,height, GL_BGRA, GL_UNSIGNED_BYTE, buffer); WritePNG(chFilename, img); // store the Z buffer sprintf(chFilename, "dbg_Z_%03i.png", iShotNum); glReadPixels(0,0,width,height, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, buffer); //img.bits_per_pixel = 16; //img.scan_width = width * 2; WritePNG(chFilename, img); // dump a subset of the Z data for (int y = 0; y < 480; y += 16) { for (int x = 0; x < 640; x+= 16) printf("%4hx ", buffer[y*640 + x]); printf("\n"); } printf("\n"); // free memory and get out of here free(buffer); iShotNum++; } */ // if emulator defined a render callback function, call it before buffer swap if (renderCallback) (*renderCallback)(status.bScreenIsDrawn); retro_return(true); /*if (options.bShowFPS) { static unsigned int lastTick=0; static int frames=0; unsigned int nowTick = SDL_GetTicks(); frames++; if (lastTick + 5000 <= nowTick) { char caption[200]; sprintf(caption, "%s v%i.%i.%i - %.3f VI/S", PLUGIN_NAME, VERSION_PRINTF_SPLIT(PLUGIN_VERSION), frames/5.0); CoreVideo_SetCaption(caption); frames = 0; lastTick = nowTick; } }*/ glDepthMask(GL_TRUE); OPENGL_CHECK_ERRORS; glClearDepth(1.0f); OPENGL_CHECK_ERRORS; if (!g_curRomInfo.bForceScreenClear) { glClear(GL_DEPTH_BUFFER_BIT); OPENGL_CHECK_ERRORS; } else { needCleanScene = true; } status.bScreenIsDrawn = false; }
void gen_interrupt(void) { if (stop == 1) { g_gs_vi_counter = 0; /* debug */ dyna_stop(); } if (!interrupt_unsafe_state) { if (reset_hard_job) { reset_hard(); reset_hard_job = 0; return; } } if (skip_jump) { uint32_t dest = skip_jump; uint32_t count = g_cp0_regs[CP0_COUNT_REG]; skip_jump = 0; next_interrupt = (q.first->data.count > count || (count - q.first->data.count) < UINT32_C(0x80000000)) ? q.first->data.count : 0; last_addr = dest; generic_jump_to(dest); return; } switch(q.first->data.type) { case SPECIAL_INT: special_int_handler(); break; case VI_INT: remove_interrupt_event(); vi_vertical_interrupt_event(&g_dev.vi); retro_return(false); break; case COMPARE_INT: compare_int_handler(); break; case CHECK_INT: remove_interrupt_event(); wrapped_exception_general(); break; case SI_INT: remove_interrupt_event(); si_end_of_dma_event(&g_dev.si); break; case PI_INT: remove_interrupt_event(); pi_end_of_dma_event(&g_dev.pi); break; case AI_INT: remove_interrupt_event(); ai_end_of_dma_event(&g_dev.ai); break; case SP_INT: remove_interrupt_event(); rsp_interrupt_event(&g_dev.sp); break; case DP_INT: remove_interrupt_event(); rdp_interrupt_event(&g_dev.dp); break; case HW2_INT: hw2_int_handler(); break; case NMI_INT: nmi_int_handler(); break; case CART_INT: g_cp0_regs[CP0_CAUSE_REG] |= 0x00000800; /* set IP3 */ g_cp0_regs[CP0_CAUSE_REG] &= 0xFFFFFF83; /* mask out old exception code */ remove_interrupt_event(); #if 0 if (dd_end_of_dma_event(&g_dd) == 1) { remove_interrupt_event(); g_cp0_regs[CP0_CAUSE_REG] &= ~0x00000800; } #endif break; default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q.first->data.type); remove_interrupt_event(); wrapped_exception_general(); break; } }
EXPORT m64p_error CALL VidExt_GL_SwapBuffers(void) { retro_return(true); return M64ERR_SUCCESS; }
void parallelUpdateScreen(void) { VI::complete_frame(); retro_return(true); }
void gen_interupt(void) { if (stop == 1) { #ifndef SINGLE_THREAD g_gs_vi_counter = 0; /* debug */ #endif dyna_stop(); } if (!interupt_unsafe_state) { if (reset_hard_job) { reset_hard(); reset_hard_job = 0; return; } } if (skip_jump) { uint32_t dest = skip_jump; skip_jump = 0; next_interupt = (q.first->data.count > g_cp0_regs[CP0_COUNT_REG] || (g_cp0_regs[CP0_COUNT_REG] - q.first->data.count) < UINT32_C(0x80000000)) ? q.first->data.count : 0; last_addr = dest; generic_jump_to(dest); return; } switch(q.first->data.type) { case SPECIAL_INT: special_int_handler(); break; case VI_INT: remove_interupt_event(); vi_vertical_interrupt_event(&g_vi); #ifdef __LIBRETRO__ retro_return(false); #endif break; case COMPARE_INT: compare_int_handler(); break; case CHECK_INT: remove_interupt_event(); wrapped_exception_general(); break; case SI_INT: remove_interupt_event(); si_end_of_dma_event(&g_si); break; case PI_INT: remove_interupt_event(); pi_end_of_dma_event(&g_pi); break; case AI_INT: remove_interupt_event(); ai_end_of_dma_event(&g_ai); break; case SP_INT: remove_interupt_event(); rsp_interrupt_event(&g_sp); break; case DP_INT: remove_interupt_event(); rdp_interrupt_event(&g_dp); break; case HW2_INT: hw2_int_handler(); break; case NMI_INT: nmi_int_handler(); break; default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q.first->data.type); remove_interupt_event(); break; } }
void gen_interupt(void) { if (stop == 1) { vi_counter = 0; // debug dyna_stop(); } if (!interupt_unsafe_state) { if (reset_hard_job) { reset_hard(); reset_hard_job = 0; return; } } if (skip_jump) { unsigned int dest = skip_jump; skip_jump = 0; if (q->count > Count || (Count - q->count) < 0x80000000) next_interupt = q->count; else next_interupt = 0; last_addr = dest; generic_jump_to(dest); return; } switch(q->type) { case SPECIAL_INT: if (Count > 0x10000000) return; remove_interupt_event(); add_interupt_event_count(SPECIAL_INT, 0); return; break; case VI_INT: if (retro_return(false) != savestates_job_nothing) { gen_interupt(); return; } gfx.updateScreen(); refresh_stat(); if (vi_register.vi_v_sync == 0) vi_register.vi_delay = 500000; else vi_register.vi_delay = ((vi_register.vi_v_sync + 1)*1500); next_vi += vi_register.vi_delay; if (vi_register.vi_status&0x40) vi_field=1-vi_field; else vi_field=0; remove_interupt_event(); add_interupt_event_count(VI_INT, next_vi); MI_register.mi_intr_reg |= 0x08; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case COMPARE_INT: remove_interupt_event(); Count+=2; add_interupt_event_count(COMPARE_INT, Compare); Count-=2; Cause = (Cause | 0x8000) & 0xFFFFFF83; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case CHECK_INT: remove_interupt_event(); break; case SI_INT: PIF_RAMb[0x3F] = 0x0; remove_interupt_event(); MI_register.mi_intr_reg |= 0x02; si_register.si_stat |= 0x1000; //si_register.si_stat &= ~0x1; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case PI_INT: remove_interupt_event(); MI_register.mi_intr_reg |= 0x10; pi_register.read_pi_status_reg &= ~3; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case AI_INT: if (ai_register.ai_status & 0x80000000) // full { unsigned int ai_event = get_event(AI_INT); remove_interupt_event(); ai_register.ai_status &= ~0x80000000; ai_register.current_delay = ai_register.next_delay; ai_register.current_len = ai_register.next_len; add_interupt_event_count(AI_INT, ai_event+ai_register.next_delay); MI_register.mi_intr_reg |= 0x04; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; } else { remove_interupt_event(); ai_register.ai_status &= ~0x40000000; //------- MI_register.mi_intr_reg |= 0x04; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; } break; case SP_INT: remove_interupt_event(); sp_register.sp_status_reg |= 0x203; // sp_register.sp_status_reg |= 0x303; if (!(sp_register.sp_status_reg & 0x40)) return; // !intr_on_break MI_register.mi_intr_reg |= 0x01; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case DP_INT: remove_interupt_event(); dpc_register.dpc_status &= ~2; dpc_register.dpc_status |= 0x81; MI_register.mi_intr_reg |= 0x20; if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg) Cause = (Cause | 0x400) & 0xFFFFFF83; else return; if ((Status & 7) != 1) return; if (!(Status & Cause & 0xFF00)) return; break; case HW2_INT: // Hardware Interrupt 2 -- remove interrupt event from queue remove_interupt_event(); // setup r4300 Status flags: reset TS, and SR, set IM2 Status = (Status & ~0x00380000) | 0x1000; Cause = (Cause | 0x1000) & 0xFFFFFF83; /* the exception_general() call below will jump to the interrupt vector (0x80000180) and setup the * interpreter or dynarec */ break; case NMI_INT: // Non Maskable Interrupt -- remove interrupt event from queue remove_interupt_event(); // setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR Status = (Status & ~0x00380000) | 0x00500004; Cause = 0x00000000; // simulate the soft reset code which would run from the PIF ROM r4300_reset_soft(); // clear all interrupts, reset interrupt counters back to 0 Count = 0; vi_counter = 0; init_interupt(); // clear the audio status register so that subsequent write_ai() calls will work properly ai_register.ai_status = 0; // set ErrorEPC with the last instruction address ErrorEPC = PC->addr; // reset the r4300 internal state if (r4300emu != CORE_PURE_INTERPRETER) { // clear all the compiled instruction blocks and re-initialize free_blocks(); init_blocks(); } // adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags if(delay_slot==1 || delay_slot==3) { ErrorEPC-=4; } delay_slot = 0; dyna_interp = 0; // set next instruction address to reset vector last_addr = 0xa4000040; generic_jump_to(0xa4000040); return; default: DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q->type); remove_interupt_event(); break; } #ifdef NEW_DYNAREC if (r4300emu == CORE_DYNAREC) { EPC = pcaddr; pcaddr = 0x80000180; Status |= 2; Cause &= 0x7FFFFFFF; pending_exception=1; } else { exception_general(); } #else exception_general(); #endif }