static bool wiiu_gfx_frame(void* data, const void* frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char* msg) { (void)msg; int i; wiiu_video_t* wiiu = (wiiu_video_t*) data; if (!width || !height) { GX2WaitForVsync(); return true; } if(wiiu->vsync) { uint32_t swap_count; uint32_t flip_count; OSTime last_flip; OSTime last_vsync; GX2GetSwapStatus(&swap_count, &flip_count, &last_flip, &last_vsync); if(wiiu->last_vsync >= last_vsync) { GX2WaitForVsync(); wiiu->last_vsync = last_vsync + ms_to_ticks(17); } else wiiu->last_vsync = last_vsync; } GX2WaitForFlip(); static u32 lastTick , currentTick; currentTick = OSGetSystemTick(); u32 diff = currentTick - lastTick; static float fps; static u32 frames; frames++; if(diff > wiiu_timer_clock) { fps = (float)frames * ((float) wiiu_timer_clock / (float) diff); lastTick = currentTick; frames = 0; } #if 0 static u32 last_frame_tick; if (!(wiiu->menu.enable)) printf("\r frame time : %10.6f ms \n", (float)(currentTick - last_frame_tick) * 1000.0f / (float)wiiu_timer_clock); last_frame_tick = currentTick; #endif printf("\rfps: %8.8f frames : %5i", fps, wiiu->frames++); fflush(stdout); static struct retro_perf_counter gfx_frame_perf = {0}; performance_counter_init(&gfx_frame_perf, "gfx_frame"); performance_counter_start(&gfx_frame_perf); if (wiiu->should_resize) wiiu_gfx_update_viewport(wiiu); GX2ClearColor(&wiiu->color_buffer, 0.0f, 0.0f, 0.0f, 1.0f); /* can't call GX2ClearColor after GX2SetContextState for whatever reason */ GX2SetContextState(wiiu->ctx_state); if(frame) { if (width > wiiu->texture.surface.width) width = wiiu->texture.surface.width; if (height > wiiu->texture.surface.height) height = wiiu->texture.surface.height; wiiu->width = width; wiiu->height = height; if(wiiu->rgb32) { const uint32_t* src = frame; uint32_t* dst = (uint32_t*)wiiu->texture.surface.image; for (i = 0; i < height; i++) { int j; for(j = 0; j < width; j++) dst[j] = src[j]; dst += wiiu->texture.surface.pitch; src += pitch / 4; } } else { const uint16_t* src = frame; uint16_t* dst = (uint16_t*)wiiu->texture.surface.image; for (i = 0; i < height; i++) { int j; for(j = 0; j < width; j++) dst[j] = __builtin_bswap16(src[j]); dst += wiiu->texture.surface.pitch; src += pitch / 2; } } GX2Invalidate(GX2_INVALIDATE_MODE_CPU_TEXTURE, wiiu->texture.surface.image, wiiu->texture.surface.imageSize); wiiu_set_tex_coords(wiiu->tex_coord, &wiiu->texture, 0, 0, width, height); } GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->position), sizeof(*wiiu->position), wiiu->position); GX2SetAttribBuffer(1, 4 * sizeof(*wiiu->tex_coord), sizeof(*wiiu->tex_coord), wiiu->tex_coord); GX2SetPixelTexture(&wiiu->texture, wiiu->shader->sampler.location); GX2SetPixelSampler(wiiu->smooth? &wiiu->sampler_linear : &wiiu->sampler_nearest, wiiu->shader->sampler.location); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); if (wiiu->menu.enable) { GX2SetAttribBuffer(0, 4 * sizeof(*wiiu->menu.position), sizeof(*wiiu->menu.position), wiiu->menu.position); GX2SetAttribBuffer(1, 4 * sizeof(*wiiu->menu.tex_coord), sizeof(*wiiu->menu.tex_coord), wiiu->menu.tex_coord); GX2SetPixelTexture(&wiiu->menu.texture, wiiu->shader->sampler.location); GX2SetPixelSampler(&wiiu->sampler_linear, wiiu->shader->sampler.location); GX2DrawEx(GX2_PRIMITIVE_MODE_QUADS, 4, 0, 1); GX2DrawDone(); } GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_DRC); GX2CopyColorBufferToScanBuffer(&wiiu->color_buffer, GX2_SCAN_TARGET_TV); GX2SwapScanBuffers(); GX2Flush(); performance_counter_stop(&gfx_frame_perf); return true; }
static bool cg_d3d9_renderchain_read_viewport(void *data, uint8_t *buffer) { unsigned width, height; D3DLOCKED_RECT rect; LPDIRECT3DSURFACE target = NULL; LPDIRECT3DSURFACE dest = NULL; bool ret = true; d3d_video_t *d3d = (d3d_video_t*)data; LPDIRECT3DDEVICE d3dr = (LPDIRECT3DDEVICE)d3d->dev; static struct retro_perf_counter d3d_read_viewport = {0}; video_driver_get_size(&width, &height); performance_counter_init(&d3d_read_viewport, "d3d_read_viewport"); performance_counter_start(&d3d_read_viewport); (void)data; (void)buffer; if (FAILED(d3d->d3d_err = d3dr->GetRenderTarget(0, &target))) { ret = false; goto end; } if (FAILED(d3d->d3d_err = d3dr->CreateOffscreenPlainSurface( width, height, D3DFMT_X8R8G8B8, D3DPOOL_SYSTEMMEM, &dest, NULL))) { ret = false; goto end; } if (FAILED(d3d->d3d_err = d3dr->GetRenderTargetData(target, dest))) { ret = false; goto end; } if (SUCCEEDED(dest->LockRect(&rect, NULL, D3DLOCK_READONLY))) { unsigned x, y; unsigned pitchpix = rect.Pitch / 4; const uint32_t *pixels = (const uint32_t*)rect.pBits; pixels += d3d->final_viewport.X; pixels += (d3d->final_viewport.Height - 1) * pitchpix; pixels -= d3d->final_viewport.Y * pitchpix; for (y = 0; y < d3d->final_viewport.Height; y++, pixels -= pitchpix) { for (x = 0; x < d3d->final_viewport.Width; x++) { *buffer++ = (pixels[x] >> 0) & 0xff; *buffer++ = (pixels[x] >> 8) & 0xff; *buffer++ = (pixels[x] >> 16) & 0xff; } } dest->UnlockRect(); }
static bool video_thread_frame(void *data, const void *frame_, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char *msg) { unsigned copy_stride; static struct retro_perf_counter thr_frame = {0}; const uint8_t *src = NULL; uint8_t *dst = NULL; thread_video_t *thr = (thread_video_t*)data; /* If called from within read_viewport, we're actually in the * driver thread, so just render directly. */ if (thr->frame.within_thread) { thread_update_driver_state(thr); if (thr->driver && thr->driver->frame) return thr->driver->frame(thr->driver_data, frame_, width, height, frame_count, pitch, msg); return false; } performance_counter_init(&thr_frame, "thr_frame"); performance_counter_start(&thr_frame); copy_stride = width * (thr->info.rgb32 ? sizeof(uint32_t) : sizeof(uint16_t)); src = (const uint8_t*)frame_; dst = thr->frame.buffer; slock_lock(thr->lock); if (!thr->nonblock) { settings_t *settings = config_get_ptr(); retro_time_t target_frame_time = (retro_time_t) roundf(1000000 / settings->video.refresh_rate); retro_time_t target = thr->last_time + target_frame_time; /* Ideally, use absolute time, but that is only a good idea on POSIX. */ while (thr->frame.updated) { retro_time_t current = cpu_features_get_time_usec(); retro_time_t delta = target - current; if (delta <= 0) break; if (!scond_wait_timeout(thr->cond_cmd, thr->lock, delta)) break; } } /* Drop frame if updated flag is still set, as thread is * still working on last frame. */ if (!thr->frame.updated) { if (src) { unsigned h; for (h = 0; h < height; h++, src += pitch, dst += copy_stride) memcpy(dst, src, copy_stride); } thr->frame.updated = true; thr->frame.width = width; thr->frame.height = height; thr->frame.count = frame_count; thr->frame.pitch = copy_stride; if (msg) strlcpy(thr->frame.msg, msg, sizeof(thr->frame.msg)); else *thr->frame.msg = '\0'; scond_signal(thr->cond_thread); #if defined(HAVE_MENU) if (thr->texture.enable) { while (thr->frame.updated) scond_wait(thr->cond_cmd, thr->lock); } #endif thr->hit_count++; } else thr->miss_count++; slock_unlock(thr->lock); performance_counter_stop(&thr_frame); thr->last_time = cpu_features_get_time_usec(); return true; }
static bool ctr_frame(void* data, const void* frame, unsigned width, unsigned height, uint64_t frame_count, unsigned pitch, const char* msg) { uint32_t diff; static uint64_t currentTick,lastTick; ctr_video_t *ctr = (ctr_video_t*)data; settings_t *settings = config_get_ptr(); static float fps = 0.0; static int total_frames = 0; static int frames = 0; static struct retro_perf_counter ctrframe_f = {0}; uint32_t state_tmp; touchPosition state_tmp_touch; extern bool select_pressed; if (!width || !height) { gspWaitForEvent(GSPGPU_EVENT_VBlank0, true); return true; } if(!aptMainLoop()) { command_event(CMD_EVENT_QUIT, NULL); return true; } if (select_pressed) { command_event(CMD_EVENT_QUIT, NULL); return true; } state_tmp = hidKeysDown(); hidTouchRead(&state_tmp_touch); if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120)) { Handle lcd_handle; u8 not_2DS; extern PrintConsole* currentConsole; gfxBottomFramebuffers[0] = ctr->lcd_buttom_on ? (u8*)ctr->empty_framebuffer: (u8*)currentConsole->frameBuffer; CFGU_GetModelNintendo2DS(¬_2DS); if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0) { u32 *cmdbuf = getThreadCommandBuffer(); cmdbuf[0] = ctr->lcd_buttom_on? 0x00120040: 0x00110040; cmdbuf[1] = 2; svcSendSyncRequest(lcd_handle); svcCloseHandle(lcd_handle); } ctr->lcd_buttom_on = !ctr->lcd_buttom_on; } svcWaitSynchronization(gspEvents[GSPGPU_EVENT_P3D], 20000000); svcClearEvent(gspEvents[GSPGPU_EVENT_P3D]); svcWaitSynchronization(gspEvents[GSPGPU_EVENT_PPF], 20000000); svcClearEvent(gspEvents[GSPGPU_EVENT_PPF]); frames++; if (ctr->vsync) svcWaitSynchronization(gspEvents[GSPGPU_EVENT_VBlank0], U64_MAX); svcClearEvent(gspEvents[GSPGPU_EVENT_VBlank0]); currentTick = svcGetSystemTick(); diff = currentTick - lastTick; if(diff > CTR_CPU_TICKS_PER_SECOND) { fps = (float)frames * ((float) CTR_CPU_TICKS_PER_SECOND / (float) diff); lastTick = currentTick; frames = 0; } //#define CTR_INSPECT_MEMORY_USAGE #ifdef CTR_INSPECT_MEMORY_USAGE uint32_t ctr_get_stack_usage(void); void ctr_linear_get_stats(void); extern u32 __linear_heap_size; extern u32 __heap_size; MemInfo mem_info; PageInfo page_info; u32 query_addr = 0x08000000; printf(PRINTFPOS(0,0)); while (query_addr < 0x40000000) { svcQueryMemory(&mem_info, &page_info, query_addr); printf("0x%08X --> 0x%08X (0x%08X) \n", mem_info.base_addr, mem_info.base_addr + mem_info.size, mem_info.size); query_addr = mem_info.base_addr + mem_info.size; if(query_addr == 0x1F000000) query_addr = 0x30000000; } // static u32* dummy_pointer; // if(total_frames == 500) // dummy_pointer = malloc(0x2000000); // if(total_frames == 1000) // free(dummy_pointer); printf("========================================"); printf("0x%08X 0x%08X 0x%08X\n", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree())); printf("fps: %8.4f frames: %i (%X)\n", fps, total_frames++, (__linear_heap_size - linearSpaceFree())); printf("========================================"); u32 app_memory = *((u32*)0x1FF80040); u64 mem_used; svcGetSystemInfo(&mem_used, 0, 1); printf("total mem : 0x%08X \n", app_memory); printf("used: 0x%08X free: 0x%08X \n", (u32)mem_used, app_memory - (u32)mem_used); static u32 stack_usage = 0; extern u32 __stack_bottom; if(!(total_frames & 0x3F)) stack_usage = ctr_get_stack_usage(); printf("stack total:0x%08X used: 0x%08X\n", 0x10000000 - __stack_bottom, stack_usage); printf("========================================"); ctr_linear_get_stats(); printf("========================================"); #else printf(PRINTFPOS(29,0)"fps: %8.4f frames: %i\r", fps, total_frames++); #endif fflush(stdout); performance_counter_init(&ctrframe_f, "ctrframe_f"); performance_counter_start(&ctrframe_f); if (ctr->should_resize) ctr_update_viewport(ctr); ctrGuSetMemoryFill(true, (u32*)CTR_TOP_FRAMEBUFFER, 0x00000000, (u32*)(CTR_TOP_FRAMEBUFFER + 2 * CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000, (u32*)(CTR_GPU_DEPTHBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)), 0x201); GPUCMD_SetBufferOffset(0); if (width > ctr->texture_width) width = ctr->texture_width; if (height > ctr->texture_height) height = ctr->texture_height; if(frame) { if(((((u32)(frame)) >= 0x14000000 && ((u32)(frame)) < 0x40000000)) /* frame in linear memory */ && !((u32)frame & 0x7F) /* 128-byte aligned */ && !(pitch & 0xF) /* 16-byte aligned */ && (pitch > 0x40)) { /* can copy the buffer directly with the GPU */ // GSPGPU_FlushDataCache(frame, pitch * height); ctrGuSetCommandList_First(true,(void*)frame, pitch * height,0,0,0,0); ctrGuCopyImage(true, frame, pitch / (ctr->rgb32? 4: 2), height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, true); } else { int i; uint8_t *dst = (uint8_t*)ctr->texture_linear; const uint8_t *src = frame; for (i = 0; i < height; i++) { memcpy(dst, src, width * (ctr->rgb32? 4: 2)); dst += ctr->texture_width * (ctr->rgb32? 4: 2); src += pitch; } GSPGPU_FlushDataCache(ctr->texture_linear, ctr->texture_width * ctr->texture_height * (ctr->rgb32? 4: 2)); ctrGuCopyImage(false, ctr->texture_linear, ctr->texture_width, ctr->texture_height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false, ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, true); } ctr->frame_coords->u0 = 0; ctr->frame_coords->v0 = 0; ctr->frame_coords->u1 = width; ctr->frame_coords->v1 = height; GSPGPU_FlushDataCache(ctr->frame_coords, sizeof(ctr_vertex_t)); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->scale_vector, 1); } ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height, (ctr->smooth? GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) : GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST)) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), ctr->rgb32 ? GPU_RGBA8: GPU_RGB565); ctr_check_3D_slider(ctr); /* ARGB --> RGBA */ if (ctr->rgb32) { GPU_SetTexEnv(0, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0), GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_G, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MODULATE, GPU_MODULATE, 0x0000FF); GPU_SetTexEnv(1, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS), GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_B, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MULTIPLY_ADD, GPU_MODULATE, 0x00FF00); GPU_SetTexEnv(2, GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS), GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0), GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_ALPHA, 0, 0), GPU_TEVOPERANDS(0, 0, 0), GPU_MULTIPLY_ADD, GPU_MODULATE, 0xFF0000); } GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); if (ctr->video_mode == CTR_VIDEO_MODE_3D) { if (ctr->menu_texture_enable) { ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(&ctr->frame_coords[1])); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(&ctr->frame_coords[2])); } else { ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords)); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER_RIGHT), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, CTR_TOP_FRAMEBUFFER_WIDTH); } else ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords)); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); /* restore */ if (ctr->rgb32) { GPU_SetTexEnv(0, GPU_TEXTURE0, GPU_TEXTURE0, 0, 0, GPU_REPLACE, GPU_REPLACE, 0); GPU_SetTexEnv(1, GPU_PREVIOUS, GPU_PREVIOUS, 0, 0, 0, 0, 0); GPU_SetTexEnv(2, GPU_PREVIOUS, GPU_PREVIOUS, 0, 0, 0, 0, 0); } if (ctr->menu_texture_enable) { GSPGPU_FlushDataCache(ctr->menu.texture_linear, ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t)); ctrGuCopyImage(false, ctr->menu.texture_linear, ctr->menu.texture_width, ctr->menu.texture_height, CTRGU_RGBA4444,false, ctr->menu.texture_swizzled, ctr->menu.texture_width, CTRGU_RGBA4444, true); ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->menu.texture_swizzled), ctr->menu.texture_width, ctr->menu.texture_height, GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) | GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE), GPU_RGBA4); ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->menu.scale_vector, 1); GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? CTR_TOP_FRAMEBUFFER_WIDTH * 2 : CTR_TOP_FRAMEBUFFER_WIDTH); ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->menu.frame_coords)); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); if (ctr->video_mode == CTR_VIDEO_MODE_3D) { GPU_SetViewport(VIRT_TO_PHYS(CTR_GPU_DEPTHBUFFER), VIRT_TO_PHYS(CTR_TOP_FRAMEBUFFER_RIGHT), 0, 0, CTR_TOP_FRAMEBUFFER_HEIGHT, CTR_TOP_FRAMEBUFFER_WIDTH); GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1); } } GPU_FinishDrawing(); GPUCMD_Finalize(); ctrGuFlushAndRun(true); ctrGuDisplayTransfer(true, CTR_TOP_FRAMEBUFFER, 240, ctr->video_mode == CTR_VIDEO_MODE_800x240 ? 800 : 400, CTRGU_RGBA8, gfxTopLeftFramebuffers[ctr->current_buffer_top], 240,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE); if ((ctr->video_mode == CTR_VIDEO_MODE_400x240) || (ctr->video_mode == CTR_VIDEO_MODE_3D)) ctrGuDisplayTransfer(true, CTR_TOP_FRAMEBUFFER_RIGHT, 240, 400, CTRGU_RGBA8, gfxTopRightFramebuffers[ctr->current_buffer_top], 240,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE); // Swap buffers : ctr->current_buffer_top ^= 1; extern GSPGPU_FramebufferInfo topFramebufferInfo; extern u8* gfxSharedMemory; extern u8 gfxThreadID; topFramebufferInfo.active_framebuf=ctr->current_buffer_top; topFramebufferInfo.framebuf0_vaddr=(u32*)gfxTopLeftFramebuffers[ctr->current_buffer_top]; if(ctr->video_mode == CTR_VIDEO_MODE_800x240) { topFramebufferInfo.framebuf1_vaddr=(u32*)(gfxTopLeftFramebuffers[ctr->current_buffer_top] + 240 * 3); topFramebufferInfo.framebuf_widthbytesize = 240 * 3 * 2; } else { topFramebufferInfo.framebuf1_vaddr=(u32*)gfxTopRightFramebuffers[ctr->current_buffer_top]; topFramebufferInfo.framebuf_widthbytesize = 240 * 3; } topFramebufferInfo.format=(1<<8)|(1<<5)|GSP_BGR8_OES; topFramebufferInfo.framebuf_dispselect=ctr->current_buffer_top; topFramebufferInfo.unk=0x00000000; u8* framebufferInfoHeader=gfxSharedMemory+0x200+gfxThreadID*0x80; GSPGPU_FramebufferInfo* framebufferInfo=(GSPGPU_FramebufferInfo*)&framebufferInfoHeader[0x4]; framebufferInfoHeader[0x0] ^= 1; framebufferInfo[framebufferInfoHeader[0x0]] = topFramebufferInfo; framebufferInfoHeader[0x1]=1; performance_counter_stop(&ctrframe_f); return true; }
/** * check_rewind: * @pressed : was rewind key pressed or held? * * Checks if rewind toggle/hold was being pressed and/or held. **/ void state_manager_check_rewind(bool pressed) { static bool first = true; settings_t *settings = config_get_ptr(); if (state_manager_frame_is_reversed()) { audio_driver_frame_is_reverse(); state_manager_set_frame_is_reversed(false); } if (first) { first = false; return; } if (!rewind_state.state) return; if (pressed) { const void *buf = NULL; if (state_manager_pop(rewind_state.state, &buf)) { retro_ctx_serialize_info_t serial_info; state_manager_set_frame_is_reversed(true); audio_driver_setup_rewind(); runloop_msg_queue_push( msg_hash_to_str(MSG_REWINDING), 0, runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL) ? 1 : 30, true); serial_info.data_const = buf; serial_info.size = rewind_state.size; core_unserialize(&serial_info); if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) bsv_movie_ctl(BSV_MOVIE_CTL_FRAME_REWIND, NULL); } else runloop_msg_queue_push( msg_hash_to_str(MSG_REWIND_REACHED_END), 0, 30, true); } else { static unsigned cnt = 0; cnt = (cnt + 1) % (settings->rewind_granularity ? settings->rewind_granularity : 1); /* Avoid possible SIGFPE. */ if ((cnt == 0) || bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL)) { retro_ctx_serialize_info_t serial_info; static struct retro_perf_counter rewind_serialize = {0}; void *state = NULL; state_manager_push_where(rewind_state.state, &state); performance_counter_init(&rewind_serialize, "rewind_serialize"); performance_counter_start(&rewind_serialize); serial_info.data = state; serial_info.size = rewind_state.size; core_serialize(&serial_info); performance_counter_stop(&rewind_serialize); state_manager_push_do(rewind_state.state); } } core_set_rewind_callbacks(); }
static void state_manager_push_do(state_manager_t *state) { #if STRICT_BUF_SIZE memcpy(state->nextblock, state->debugblock, state->debugsize); #endif static struct retro_perf_counter gen_deltas = {0}; uint8_t *swap = NULL; if (state->thisblock_valid) { const uint8_t *oldb, *newb; uint8_t *compressed; size_t headpos, tailpos, remaining; if (state->capacity < sizeof(size_t) + state->maxcompsize) return; recheckcapacity:; headpos = state->head - state->data; tailpos = state->tail - state->data; remaining = (tailpos + state->capacity - sizeof(size_t) - headpos - 1) % state->capacity + 1; if (remaining <= state->maxcompsize) { state->tail = state->data + read_size_t(state->tail); state->entries--; goto recheckcapacity; } performance_counter_init(&gen_deltas, "gen_deltas"); performance_counter_start(&gen_deltas); oldb = state->thisblock; newb = state->nextblock; compressed = state->head + sizeof(size_t); compressed += state_manager_raw_compress(oldb, newb, state->blocksize, compressed); if (compressed - state->data + state->maxcompsize > state->capacity) { compressed = state->data; if (state->tail == state->data + sizeof(size_t)) state->tail = state->data + read_size_t(state->tail); } write_size_t(compressed, state->head-state->data); compressed += sizeof(size_t); write_size_t(state->head, compressed-state->data); state->head = compressed; performance_counter_stop(&gen_deltas); } else state->thisblock_valid = true; swap = state->thisblock; state->thisblock = state->nextblock; state->nextblock = swap; state->entries++; }