diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.cpp b/game/graphics/opengl_renderer/OpenGLRenderer.cpp index e0d74609d0..bbeff3ea7d 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.cpp +++ b/game/graphics/opengl_renderer/OpenGLRenderer.cpp @@ -701,6 +701,38 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) { m_last_pmode_alp = settings.pmode_alp_register; + if (settings.save_screenshot) { + auto prof = m_profiler.root()->make_scoped_child("screenshot"); + int read_buffer; + int x, y, w, h, fbo_id; + + if (settings.internal_res_screenshot) { + Fbo* screenshot_src; + // can't screenshot from a multisampled buffer directly - + if (m_fbo_state.resources.resolve_buffer.valid) { + screenshot_src = &m_fbo_state.resources.resolve_buffer; + read_buffer = GL_COLOR_ATTACHMENT0; + } else { + screenshot_src = m_fbo_state.render_fbo; + read_buffer = GL_FRONT; + } + w = screenshot_src->width; + h = screenshot_src->height; + x = 0; + y = 0; + fbo_id = screenshot_src->fbo_id; + } else { + read_buffer = GL_FRONT; + w = settings.draw_region_width; + h = settings.draw_region_height; + x = m_render_state.draw_offset_x; + y = m_render_state.draw_offset_y; + fbo_id = 0; // window + } + finish_screenshot(settings.screenshot_path, w, h, x, y, fbo_id, read_buffer, + settings.quick_screenshot); + } + if (settings.draw_render_debug_window) { auto prof = m_profiler.root()->make_scoped_child("render-window"); draw_renderer_selection_window(); @@ -751,22 +783,6 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) { if (settings.draw_filters_window) { m_filters_menu.draw_window(); } - - if (settings.save_screenshot) { - Fbo* screenshot_src; - int read_buffer; - - // can't screenshot from a multisampled buffer directly - - if (m_fbo_state.resources.resolve_buffer.valid) { - screenshot_src = &m_fbo_state.resources.resolve_buffer; - read_buffer = GL_COLOR_ATTACHMENT0; - } else { - screenshot_src = m_fbo_state.render_fbo; - read_buffer = GL_FRONT; - } - finish_screenshot(settings.screenshot_path, screenshot_src->width, screenshot_src->height, 0, 0, - screenshot_src->fbo_id, read_buffer, settings.quick_screenshot); - } if (settings.gpu_sync) { glFinish(); } @@ -838,35 +854,24 @@ void OpenGLRenderer::setup_frame(const RenderOptions& settings) { m_fbo_state.resources.render_buffer.clear(); m_fbo_state.resources.resolve_buffer.clear(); - // first, see if we can just render straight to the display framebuffer. - // note: we always force a separate fbo on a screenshot so that it won't capture overlays. - // as an added bonus it also doesn't break the sprite distort buffer... - if (!settings.save_screenshot && - window_fb.matches(settings.game_res_w, settings.game_res_h, settings.msaa_samples)) { - // it matches - no need for extra framebuffers. - lg::info("FBO Setup: rendering directly to window framebuffer"); - m_fbo_state.render_fbo = &m_fbo_state.resources.window; + // NOTE: we will ALWAYS render the game to a separate framebuffer instead of directly to the + // window framebuffer. + + // create a fbo to render to, with the desired settings + m_fbo_state.resources.render_buffer = + make_fbo(settings.game_res_w, settings.game_res_h, settings.msaa_samples, true); + m_fbo_state.render_fbo = &m_fbo_state.resources.render_buffer; + + if (settings.msaa_samples != 1) { + lg::info("FBO Setup: using second temporary buffer: res: {}x{} {}x{}", window_fb.width, + window_fb.height, settings.game_res_w, settings.game_res_h); + + // we'll need a temporary fbo to do the msaa resolve step + // non-multisampled, and doesn't need z/stencil + m_fbo_state.resources.resolve_buffer = + make_fbo(settings.game_res_w, settings.game_res_h, 1, false); } else { - lg::info("FBO Setup: window didn't match: {} {}", window_fb.width, window_fb.height); - - // create a fbo to render to, with the desired settings - m_fbo_state.resources.render_buffer = - make_fbo(settings.game_res_w, settings.game_res_h, settings.msaa_samples, true); - m_fbo_state.render_fbo = &m_fbo_state.resources.render_buffer; - - bool msaa_matches = window_fb.multisample_count == settings.msaa_samples; - - if (!msaa_matches) { - lg::info("FBO Setup: using second temporary buffer: res: {}x{} {}x{}", window_fb.width, - window_fb.height, settings.game_res_w, settings.game_res_h); - - // we'll need a temporary fbo to do the msaa resolve step - // non-multisampled, and doesn't need z/stencil - m_fbo_state.resources.resolve_buffer = - make_fbo(settings.game_res_w, settings.game_res_h, 1, false); - } else { - lg::info("FBO Setup: not using second temporary buffer"); - } + lg::info("FBO Setup: not using second temporary buffer"); } } @@ -874,15 +879,15 @@ void OpenGLRenderer::setup_frame(const RenderOptions& settings) { fmt::format("Bad viewport size from game_res: {}x{}\n", settings.game_res_w, settings.game_res_h)); - if (!m_fbo_state.render_fbo->is_window) { - glBindFramebuffer(GL_FRAMEBUFFER, 0); - glViewport(0, 0, m_fbo_state.resources.window.width, m_fbo_state.resources.window.height); - glClearColor(0.0, 0.0, 0.0, 0.0); - glClearDepth(0.0); - glDepthMask(GL_TRUE); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - glDisable(GL_BLEND); - } + ASSERT_MSG(!m_fbo_state.render_fbo->is_window, "window fbo"); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glViewport(0, 0, m_fbo_state.resources.window.width, m_fbo_state.resources.window.height); + glClearColor(0.0, 0.0, 0.0, 0.0); + glClearDepth(0.0); + glDepthMask(GL_TRUE); + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + glDisable(GL_BLEND); glBindFramebuffer(GL_FRAMEBUFFER, m_fbo_state.render_fbo->fbo_id); glClearColor(0.0, 0.0, 0.0, 0.0); @@ -914,20 +919,11 @@ void OpenGLRenderer::setup_frame(const RenderOptions& settings) { m_render_state.draw_region_h = 240; } - if (m_fbo_state.render_fbo->is_window) { - m_render_state.render_fb_x = m_render_state.draw_offset_x; - m_render_state.render_fb_y = m_render_state.draw_offset_y; - m_render_state.render_fb_w = m_render_state.draw_region_w; - m_render_state.render_fb_h = m_render_state.draw_region_h; - glViewport(m_render_state.draw_offset_x, m_render_state.draw_offset_y, - m_render_state.draw_region_w, m_render_state.draw_region_h); - } else { - m_render_state.render_fb_x = 0; - m_render_state.render_fb_y = 0; - m_render_state.render_fb_w = settings.game_res_w; - m_render_state.render_fb_h = settings.game_res_h; - glViewport(0, 0, settings.game_res_w, settings.game_res_h); - } + m_render_state.render_fb_x = 0; + m_render_state.render_fb_y = 0; + m_render_state.render_fb_w = settings.game_res_w; + m_render_state.render_fb_h = settings.game_res_h; + glViewport(0, 0, settings.game_res_w, settings.game_res_h); } void OpenGLRenderer::dispatch_buckets_jak1(DmaFollower dma, @@ -1068,7 +1064,6 @@ void win_print_last_error(const std::string& msg) { lg::error("[OpenGLRenderer] {} Win Err: {}", msg, lpMsgBuf); } -HGLOBAL hClipboardData; void copy_texture_to_clipboard(int width, int height, const std::vector& texture_data) { std::vector data(texture_data); @@ -1112,7 +1107,7 @@ void copy_texture_to_clipboard(int width, int height, const std::vector& te } // Create a global memory object to hold the image data - hClipboardData = GlobalAlloc(GMEM_MOVEABLE, sizeof(header) + image_size); + HGLOBAL hClipboardData = GlobalAlloc(GMEM_MOVEABLE, sizeof(header) + image_size); if (hClipboardData == NULL) { win_print_last_error("Failed to allocate memory for clipboard data."); CloseClipboard(); @@ -1201,44 +1196,41 @@ void OpenGLRenderer::finish_screenshot(const std::string& output_name, void OpenGLRenderer::do_pcrtc_effects(float alp, SharedRenderState* render_state, ScopedProfilerNode& prof) { - if (m_fbo_state.render_fbo->is_window) { - // nothing to do! - } else { - Fbo* window_blit_src = nullptr; - if (m_fbo_state.resources.resolve_buffer.valid) { - glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_state.render_fbo->fbo_id); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_state.resources.resolve_buffer.fbo_id); - glBlitFramebuffer(0, // srcX0 - 0, // srcY0 - m_fbo_state.render_fbo->width, // srcX1 - m_fbo_state.render_fbo->height, // srcY1 - 0, // dstX0 - 0, // dstY0 - m_fbo_state.resources.resolve_buffer.width, // dstX1 - m_fbo_state.resources.resolve_buffer.height, // dstY1 - GL_COLOR_BUFFER_BIT, // mask - GL_LINEAR // filter - ); - window_blit_src = &m_fbo_state.resources.resolve_buffer; - } else { - window_blit_src = &m_fbo_state.resources.render_buffer; - } - - glBindFramebuffer(GL_READ_FRAMEBUFFER, window_blit_src->fbo_id); - glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); - glBlitFramebuffer(0, // srcX0 - 0, // srcY0 - window_blit_src->width, // srcX1 - window_blit_src->height, // srcY1 - render_state->draw_offset_x, // dstX0 - render_state->draw_offset_y, // dstY0 - render_state->draw_offset_x + render_state->draw_region_w, // dstX1 - render_state->draw_offset_y + render_state->draw_region_h, // dstY1 - GL_COLOR_BUFFER_BIT, // mask - GL_LINEAR // filter + Fbo* window_blit_src = nullptr; + if (m_fbo_state.resources.resolve_buffer.valid) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fbo_state.render_fbo->fbo_id); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo_state.resources.resolve_buffer.fbo_id); + glBlitFramebuffer(0, // srcX0 + 0, // srcY0 + m_fbo_state.render_fbo->width, // srcX1 + m_fbo_state.render_fbo->height, // srcY1 + 0, // dstX0 + 0, // dstY0 + m_fbo_state.resources.resolve_buffer.width, // dstX1 + m_fbo_state.resources.resolve_buffer.height, // dstY1 + GL_COLOR_BUFFER_BIT, // mask + GL_LINEAR // filter ); - glBindFramebuffer(GL_FRAMEBUFFER, 0); + window_blit_src = &m_fbo_state.resources.resolve_buffer; + } else { + window_blit_src = &m_fbo_state.resources.render_buffer; } + + glBindFramebuffer(GL_READ_FRAMEBUFFER, window_blit_src->fbo_id); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, // srcX0 + 0, // srcY0 + window_blit_src->width, // srcX1 + window_blit_src->height, // srcY1 + render_state->draw_offset_x, // dstX0 + render_state->draw_offset_y, // dstY0 + render_state->draw_offset_x + render_state->draw_region_w, // dstX1 + render_state->draw_offset_y + render_state->draw_region_h, // dstY1 + GL_COLOR_BUFFER_BIT, // mask + GL_LINEAR // filter + ); + glBindFramebuffer(GL_FRAMEBUFFER, 0); + if (alp < 1) { glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); diff --git a/game/graphics/opengl_renderer/OpenGLRenderer.h b/game/graphics/opengl_renderer/OpenGLRenderer.h index f1b5c1c86a..4cd8209ef2 100644 --- a/game/graphics/opengl_renderer/OpenGLRenderer.h +++ b/game/graphics/opengl_renderer/OpenGLRenderer.h @@ -43,6 +43,7 @@ struct RenderOptions { bool save_screenshot = false; bool quick_screenshot = false; + bool internal_res_screenshot = false; std::string screenshot_path; float pmode_alp_register = 0.f; diff --git a/game/graphics/opengl_renderer/Warp.cpp b/game/graphics/opengl_renderer/Warp.cpp index 15f2bccf72..7c4db32a51 100644 --- a/game/graphics/opengl_renderer/Warp.cpp +++ b/game/graphics/opengl_renderer/Warp.cpp @@ -8,8 +8,7 @@ void Warp::draw_debug_window() { } void Warp::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) { - m_fb_copier.copy_now(render_state->render_fb_w, render_state->render_fb_h, - render_state->render_fb_x, render_state->render_fb_y, + m_fb_copier.copy_now(render_state->render_fb_w, render_state->render_fb_h, 0, 0, render_state->render_fb); render_state->texture_pool->move_existing_to_vram(m_warp_src_tex, m_tbp); m_generic->render_in_mode(dma, render_state, prof, Generic2::Mode::WARP); diff --git a/game/graphics/opengl_renderer/opengl_utils.cpp b/game/graphics/opengl_renderer/opengl_utils.cpp index 8183bb7386..1dee050f3a 100644 --- a/game/graphics/opengl_renderer/opengl_utils.cpp +++ b/game/graphics/opengl_renderer/opengl_utils.cpp @@ -197,16 +197,16 @@ void FramebufferCopier::copy_now(int render_fb_w, glBindFramebuffer(GL_READ_FRAMEBUFFER, render_fb); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo); - glBlitFramebuffer(render_fb_x, // srcX0 - render_fb_y, // srcY0 - render_fb_x + render_fb_w, // srcX1 - render_fb_y + render_fb_h, // srcY1 - 0, // dstX0 - 0, // dstY0 - m_fbo_width, // dstX1 - m_fbo_height, // dstY1 - GL_COLOR_BUFFER_BIT, // mask - GL_NEAREST // filter + glBlitFramebuffer(0, // srcX0 + 0, // srcY0 + render_fb_w, // srcX1 + render_fb_h, // srcY1 + 0, // dstX0 + 0, // dstY0 + m_fbo_width, // dstX1 + m_fbo_height, // dstY1 + GL_COLOR_BUFFER_BIT, // mask + GL_NEAREST // filter ); glBindFramebuffer(GL_FRAMEBUFFER, render_fb); diff --git a/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp b/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp index 5caf1ed2d3..b5941beb05 100644 --- a/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp +++ b/game/graphics/opengl_renderer/sprite/GlowRenderer.cpp @@ -188,9 +188,8 @@ GlowRenderer::GlowRenderer() { GL_UNSIGNED_BYTE, nullptr); glGenRenderbuffers(1, &m_ogl.probe_fbo_zbuf_rb); glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_ogl.probe_fbo_w, - m_ogl.probe_fbo_h); - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_ogl.probe_fbo_rgba_tex, 0); @@ -469,23 +468,23 @@ void GlowRenderer::blit_depth(SharedRenderState* render_state) { glBindTexture(GL_TEXTURE_2D, 0); glBindRenderbuffer(GL_RENDERBUFFER, m_ogl.probe_fbo_zbuf_rb); - glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, m_ogl.probe_fbo_w, + glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, m_ogl.probe_fbo_w, m_ogl.probe_fbo_h); } glBindFramebuffer(GL_READ_FRAMEBUFFER, render_state->render_fb); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_ogl.probe_fbo); - glBlitFramebuffer(render_state->render_fb_x, // srcX0 - render_state->render_fb_y, // srcY0 - render_state->render_fb_x + render_state->render_fb_w, // srcX1 - render_state->render_fb_y + render_state->render_fb_h, // srcY1 - 0, // dstX0 - 0, // dstY0 - m_ogl.probe_fbo_w, // dstX1 - m_ogl.probe_fbo_h, // dstY1 - GL_DEPTH_BUFFER_BIT, // mask - GL_NEAREST // filter + glBlitFramebuffer(0, // srcX0 + 0, // srcY0 + render_state->render_fb_w, // srcX1 + render_state->render_fb_h, // srcY1 + 0, // dstX0 + 0, // dstY0 + m_ogl.probe_fbo_w, // dstX1 + m_ogl.probe_fbo_h, // dstY1 + GL_DEPTH_BUFFER_BIT, // mask + GL_NEAREST // filter ); } diff --git a/game/graphics/opengl_renderer/sprite/Sprite3_Distort.cpp b/game/graphics/opengl_renderer/sprite/Sprite3_Distort.cpp index bd8d4d7e7a..6d57b5304f 100644 --- a/game/graphics/opengl_renderer/sprite/Sprite3_Distort.cpp +++ b/game/graphics/opengl_renderer/sprite/Sprite3_Distort.cpp @@ -595,16 +595,16 @@ void Sprite3::distort_draw_common(SharedRenderState* render_state, ScopedProfile glBindFramebuffer(GL_READ_FRAMEBUFFER, render_state->render_fb); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_distort_ogl.fbo); - glBlitFramebuffer(render_state->render_fb_x, // srcX0 - render_state->render_fb_y, // srcY0 - render_state->render_fb_x + render_state->render_fb_w, // srcX1 - render_state->render_fb_y + render_state->render_fb_h, // srcY1 - 0, // dstX0 - 0, // dstY0 - m_distort_ogl.fbo_width, // dstX1 - m_distort_ogl.fbo_height, // dstY1 - GL_COLOR_BUFFER_BIT, // mask - GL_NEAREST // filter + glBlitFramebuffer(0, // srcX0 + 0, // srcY0 + render_state->render_fb_w, // srcX1 + render_state->render_fb_h, // srcY1 + 0, // dstX0 + 0, // dstY0 + m_distort_ogl.fbo_width, // dstX1 + m_distort_ogl.fbo_height, // dstY1 + GL_COLOR_BUFFER_BIT, // mask + GL_NEAREST // filter ); glBindFramebuffer(GL_FRAMEBUFFER, render_state->render_fb); diff --git a/game/graphics/pipelines/opengl.cpp b/game/graphics/pipelines/opengl.cpp index ac5454e432..8d07a2e0e7 100644 --- a/game/graphics/pipelines/opengl.cpp +++ b/game/graphics/pipelines/opengl.cpp @@ -340,9 +340,8 @@ void render_game_frame(int game_width, { auto p = scoped_prof("wait-for-dma"); std::unique_lock lock(g_gfx_data->dma_mutex); - // note: there's a timeout here. If the engine is messed up and not sending us frames, - // we still want to run the glfw loop. - got_chain = g_gfx_data->dma_cv.wait_for(lock, std::chrono::milliseconds(50), + // there's a timeout here, so imgui can still be responsive even if we don't render anything + got_chain = g_gfx_data->dma_cv.wait_for(lock, std::chrono::milliseconds(40), [=] { return g_gfx_data->has_data_to_render; }); } // render that chain. @@ -364,6 +363,7 @@ void render_game_frame(int game_width, options.draw_filters_window = g_gfx_data->debug_gui.should_draw_filters_menu(); options.save_screenshot = false; options.quick_screenshot = false; + options.internal_res_screenshot = false; options.gpu_sync = g_gfx_data->debug_gui.should_gl_finish(); if (take_screenshot) { diff --git a/goal_src/jak1/engine/gfx/math-camera.gc b/goal_src/jak1/engine/gfx/math-camera.gc index 11a776eacf..385c9cc559 100644 --- a/goal_src/jak1/engine/gfx/math-camera.gc +++ b/goal_src/jak1/engine/gfx/math-camera.gc @@ -69,8 +69,8 @@ ;; crops excess aspect ratio at the top and bottom ;(set! (-> math-cam y-ratio) (* (1/ (-> *pc-settings* aspect-ratio)) (-> math-cam x-ratio))) ) - ((-> *pc-settings* movie?) - ;; this mess is just so that we can force the original 16x9 cropping during cutscenes. + ((real-movie?) + ;; force the original 16x9 cropping during cutscenes. (if (<= (-> *pc-settings* aspect-ratio) ASPECT_16X9) (set! (-> math-cam y-ratio) (* (1/ (-> *pc-settings* aspect-ratio)) (-> math-cam x-ratio))) (begin diff --git a/goal_src/jak1/pc/features/autosplit.gc b/goal_src/jak1/pc/features/autosplit.gc index 4be7cf9613..40dc05ecd3 100644 --- a/goal_src/jak1/pc/features/autosplit.gc +++ b/goal_src/jak1/pc/features/autosplit.gc @@ -54,7 +54,7 @@ (set! (-> *autosplit-info-jak1* citadel-num-scout-flies) (buzzer-count *game-info* (-> *level-task-data* (level-task-data-index citadel) task-info (-> *level-task-data* (level-task-data-index citadel) buzzer-task-index) task-id))) ;; loading/cutscene related flags - (set! (-> *autosplit-info-jak1* in-cutscene?) (-> *pc-settings* movie?)) + (set! (-> *autosplit-info-jak1* in-cutscene?) (real-movie?)) ;; need resolution flags (autosplit-flag-task-complete! res-training-gimmie training-gimmie) diff --git a/goal_src/jak1/pc/pckernel-common.gc b/goal_src/jak1/pc/pckernel-common.gc index 7a1b6a8c32..7f5ea5e3b2 100644 --- a/goal_src/jak1/pc/pckernel-common.gc +++ b/goal_src/jak1/pc/pckernel-common.gc @@ -68,7 +68,7 @@ ;; if windowed mode, set the size properly (when (= (-> obj display-mode) 'windowed) ;; TODO - this means the user can never have a window smaller than MIN_WIDTH/HEIGHT - (pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height)))))) + (pc-set-window-size (max PC_MIN_WIDTH (-> obj window-width)) (max PC_MIN_HEIGHT (-> obj window-height)))))) 0) (defmethod set-size! pc-settings ((obj pc-settings) (width int) (height int) (call-handlers symbol)) @@ -76,10 +76,10 @@ (format 0 "Setting ~A size to ~D x ~D~%" (-> obj display-mode) width height) (cond ((= 'windowed (-> obj display-mode)) - (set! (-> obj win-width) width) - (set! (-> obj win-height) height) + (set! (-> obj window-width) width) + (set! (-> obj window-height) height) (if call-handlers - (pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height)))) + (pc-set-window-size (max PC_MIN_WIDTH (-> obj window-width)) (max PC_MIN_HEIGHT (-> obj window-height)))) ) (else (set! (-> obj width) width) @@ -151,7 +151,7 @@ (defmethod update-from-os pc-settings ((obj pc-settings)) "Update settings from the C kernel to GOAL." - (pc-get-window-size (&-> obj real-width) (&-> obj real-height)) + (pc-get-window-size (&-> obj framebuffer-width) (&-> obj framebuffer-height)) (pc-get-window-scale (&-> obj dpi-x) (&-> obj dpi-y)) (when (-> obj use-vis?) @@ -161,29 +161,29 @@ ) ) - (unless (or (zero? (-> obj real-width)) (zero? (-> obj real-height))) - (let ((win-aspect (/ (the float (-> obj real-width)) (the float (-> obj real-height))))) + (unless (or (zero? (-> obj framebuffer-width)) (zero? (-> obj framebuffer-height))) + (let ((win-aspect (/ (the float (-> obj framebuffer-width)) (the float (-> obj framebuffer-height))))) (cond ((and (not (-> obj use-vis?)) (-> obj aspect-ratio-auto?)) ;; the window determines the resolution (set-aspect-ratio! obj win-aspect) - (set! (-> obj lbox-width) (-> obj real-width)) - (set! (-> obj lbox-height) (-> obj real-height)) + (set! (-> obj framebuffer-scissor-width) (-> obj framebuffer-width)) + (set! (-> obj framebuffer-scissor-height) (-> obj framebuffer-height)) ) ((> win-aspect (-> obj aspect-ratio)) ;; too wide - (set! (-> obj lbox-width) (the int (* (the float (-> obj real-height)) (-> obj aspect-ratio)))) - (set! (-> obj lbox-height) (-> obj real-height)) + (set! (-> obj framebuffer-scissor-width) (the int (* (the float (-> obj framebuffer-height)) (-> obj aspect-ratio)))) + (set! (-> obj framebuffer-scissor-height) (-> obj framebuffer-height)) ) ((< win-aspect (-> obj aspect-ratio)) ;; too tall - (set! (-> obj lbox-width) (-> obj real-width)) - (set! (-> obj lbox-height) (the int (/ (the float (-> obj real-width)) (-> obj aspect-ratio)))) + (set! (-> obj framebuffer-scissor-width) (-> obj framebuffer-width)) + (set! (-> obj framebuffer-scissor-height) (the int (/ (the float (-> obj framebuffer-width)) (-> obj aspect-ratio)))) ) (else ;; just right - (set! (-> obj lbox-width) (-> obj real-width)) - (set! (-> obj lbox-height) (-> obj real-height)) + (set! (-> obj framebuffer-scissor-width) (-> obj framebuffer-width)) + (set! (-> obj framebuffer-scissor-height) (-> obj framebuffer-height)) ) ) )) @@ -197,10 +197,10 @@ ;; TODO - move the below out of this function that runs every frame (cond ((-> obj letterbox?) - (pc-set-letterbox (-> obj lbox-width) (-> obj lbox-height)) + (pc-set-letterbox (-> obj framebuffer-scissor-width) (-> obj framebuffer-scissor-height)) ) (else - (pc-set-letterbox (-> obj real-width) (-> obj real-height)) + (pc-set-letterbox (-> obj framebuffer-width) (-> obj framebuffer-height)) ) ) @@ -213,7 +213,7 @@ ;; do game resolution (if (= (-> obj display-mode) 'windowed) - (pc-set-game-resolution (-> obj real-width) (-> obj real-height)) + (pc-set-game-resolution (-> obj framebuffer-scissor-width) (-> obj framebuffer-scissor-height)) (pc-set-game-resolution (-> obj width) (-> obj height))) ;; set msaa sample rate. if invalid, just reset to 2. @@ -281,6 +281,10 @@ (+ (* (shr (logand bcd #xf0) 4) 10) (logand bcd #x0f)) ) +(defun real-movie? () + "are we in an actual cutscene and should letterbox the view?" + (and (nonzero? movie?) (movie?))) + (defmethod update pc-settings ((obj pc-settings)) "Update settings to/from PC kernel. Call this at the start of every frame. This will update things like the aspect-ratio, which will be used for graphics code later." @@ -288,8 +292,6 @@ (update-from-os obj) (update-to-os obj) - (set! (-> obj movie?) (movie?)) - (update-discord-rpc obj) ;; update auto-splitter info @@ -350,8 +352,8 @@ (cond ((= (-> obj display-mode) 'windowed) (if (-> obj letterbox?) - (-> obj lbox-width) - (-> obj real-width))) + (-> obj framebuffer-scissor-width) + (-> obj framebuffer-width))) (else (-> obj width)) ) @@ -362,8 +364,8 @@ (cond ((= (-> obj display-mode) 'windowed) (if (-> obj letterbox?) - (-> obj lbox-height) - (-> obj real-height))) + (-> obj framebuffer-scissor-height) + (-> obj framebuffer-height))) (else (-> obj height)) ) @@ -375,16 +377,15 @@ "debug draw some things on-screen" (when (-> obj debug?) + (format *stdcon* "fullscreen resolution: ~D x ~D~%" (-> obj width) (-> obj height)) + (format *stdcon* "window size: ~D x ~D @ ~,,1f x ~,,1f~%" (-> obj window-width) (-> obj window-height) (-> obj dpi-x) (-> obj dpi-y)) + (format *stdcon* "fb size: ~D x ~D (scissor: ~D x ~D)~%" (-> obj framebuffer-width) (-> obj framebuffer-height) (-> obj framebuffer-scissor-width) (-> obj framebuffer-scissor-height)) + (format *stdcon* "aspect: ~,,3f/~,,3f auto? ~A vis? ~A lbox? ~A~%" (-> obj aspect-ratio) (/ (the float (-> obj framebuffer-width)) (the float (-> obj framebuffer-height))) (-> obj aspect-ratio-auto?) (-> obj use-vis?) (-> obj letterbox?)) + (format *stdcon* "display-mode: ~A vsync? ~A~%" (-> obj display-mode) (-> obj vsync?)) (clear *pc-temp-string*) - (format *pc-temp-string* "game resolution: ~D x ~D~%" (-> obj width) (-> obj height)) - (format *pc-temp-string* "window size: ~D x ~D (~,,1f x ~,,1f)~%" (-> obj real-width) (-> obj real-height) (-> obj dpi-x) (-> obj dpi-y)) - (format *pc-temp-string* "target aspect: ~,,3f/~,,3f A: ~A/~A L: ~A~%" (-> obj aspect-ratio) (/ (the float (-> obj real-width)) (the float (-> obj real-height))) (-> obj aspect-ratio-auto?) (-> obj use-vis?) (-> obj letterbox?)) - (format *pc-temp-string* "display-type: ~A ~A~%" (-> obj display-mode) (-> obj vsync?)) - - (draw-string-xy *pc-temp-string* buf 0 (- 224 (* 8 4)) (font-color default) (font-flags shadow kerning)) ) (when *display-actor-bank* - (draw-string-xy (string-format "Actor Bank: ~,,1m/~,,1m (~D)" (-> *ACTOR-bank* pause-dist) (-> *ACTOR-bank* birth-dist) (-> *ACTOR-bank* birth-max)) buf 512 (- 224 8) (font-color default) (font-flags shadow kerning right)) + (draw-string-xy (string-format "Actor Bank: ~,,1m/~,,1m (~D)" (-> *ACTOR-bank* pause-dist) (-> *ACTOR-bank* birth-dist) (-> *ACTOR-bank* birth-max)) buf 512 0 (font-color default) (font-flags shadow kerning right)) ) ) @@ -619,7 +620,7 @@ ;; restore the windowed mode resolution properly (when (= (-> obj display-mode) 'windowed) - (pc-set-window-size (max PC_MIN_WIDTH (-> obj win-width)) (max PC_MIN_HEIGHT (-> obj win-height)))) + (pc-set-window-size (max PC_MIN_WIDTH (-> obj window-width)) (max PC_MIN_HEIGHT (-> obj window-height)))) #t ) @@ -630,8 +631,8 @@ (case-str *pc-temp-string* (("fps") (set-frame-rate! obj (file-stream-read-int file) #t)) (("window-size") - (set! (-> obj win-width) (file-stream-read-int file)) - (set! (-> obj win-height) (file-stream-read-int file)) + (set! (-> obj window-width) (file-stream-read-int file)) + (set! (-> obj window-height) (file-stream-read-int file)) ) (("game-size") (set! (-> obj width) (file-stream-read-int file)) @@ -731,7 +732,7 @@ (-> obj aspect-custom-x) (-> obj aspect-custom-y) (-> obj aspect-ratio-auto?)) (format file " (display-mode ~A)~%" (-> obj display-mode)) - (format file " (window-size ~D ~D)~%" (-> obj win-width) (-> obj win-height)) + (format file " (window-size ~D ~D)~%" (-> obj window-width) (-> obj window-height)) (format file " (game-size ~D ~D)~%" (-> obj width) (-> obj height)) (format file " (monitor ~D)~%" (-> obj monitor)) (format file " (letterbox ~A)~%" (-> obj letterbox?)) diff --git a/goal_src/jak1/pc/pckernel-h.gc b/goal_src/jak1/pc/pckernel-h.gc index 553691501f..147659796d 100644 --- a/goal_src/jak1/pc/pckernel-h.gc +++ b/goal_src/jak1/pc/pckernel-h.gc @@ -139,14 +139,14 @@ (width int32) (height int32) ;; window size. resolution = window size in windowed mode. - (win-width int32) - (win-height int32) - ;; real window size from OS - (real-width int32) - (real-height int32) - ;; letterboxed window size - (lbox-width int32) - (lbox-height int32) + (window-width int32) + (window-height int32) + ;; reported window framebuffer size from OS + (framebuffer-width int32) + (framebuffer-height int32) + ;; the region to draw in that framebuffer. rest is cleared to black. + (framebuffer-scissor-width int32) + (framebuffer-scissor-height int32) (dpi-x float) ;; DPI width scale (dpi-y float) ;; DPI height scale (aspect-ratio-auto? symbol) ;; if on, aspect ratio is calculated automatically based on game display size. @@ -165,7 +165,6 @@ (os symbol) ;; windows, linux, macos (user symbol) ;; username. not system username, just debug thing. (debug? symbol) ;; more debug stuff just in case. - (movie? symbol) ;; device settings (ignore-controller-win-unfocused? symbol) @@ -325,7 +324,6 @@ (set! (-> obj os) (pc-get-os)) (set! (-> obj user) #f) (set! (-> obj debug?) #f) - (set! (-> obj movie?) #f) (set! (-> obj font-scale) 1.0) (set! (-> obj aspect-custom-x) 4) (set! (-> obj aspect-custom-y) 3) @@ -455,6 +453,11 @@ )) ) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;; cheats +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (seval (define *pc-cheat-map* '((#\a (circle triangle)) (#\b (square x)) @@ -540,3 +543,6 @@ +(defun-extern real-movie? symbol) + + diff --git a/goal_src/jak1/pc/pckernel.gc b/goal_src/jak1/pc/pckernel.gc index d6e081a3e7..4d93c5a764 100644 --- a/goal_src/jak1/pc/pckernel.gc +++ b/goal_src/jak1/pc/pckernel.gc @@ -245,7 +245,7 @@ (set! (-> info deaths) (&-> *game-info* total-deaths)) (set! (-> info status) "Playing Jak and Daxter: The Precursor Legacy™") (set! (-> info level) (symbol->string (-> (level-get-target-inside *level*) name))) ;; grab the name of level we're in - (set! (-> info cutscene?) (-> obj movie?)) + (set! (-> info cutscene?) (real-movie?)) (set! (-> info ogreboss?) (aif (process-by-ename "ogreboss-1") (case (-> it next-state name) ( ('ogreboss-die 'ogreboss-idle diff --git a/goal_src/jak2/engine/draw/drawable.gc b/goal_src/jak2/engine/draw/drawable.gc index 8f98aa519f..1044f1d67e 100644 --- a/goal_src/jak2/engine/draw/drawable.gc +++ b/goal_src/jak2/engine/draw/drawable.gc @@ -1411,7 +1411,7 @@ (local-vars (a0-96 int) (a0-98 int)) (with-pp (when *slow-frame-rate* - (dotimes (v1-2 12800000) + (dotimes (v1-2 128000000) ;; was 12800000 (nop!) (nop!) (nop!) diff --git a/goal_src/jak2/engine/game/task/task-control.gc b/goal_src/jak2/engine/game/task/task-control.gc index e507916ad9..86c3f1e537 100644 --- a/goal_src/jak2/engine/game/task/task-control.gc +++ b/goal_src/jak2/engine/game/task/task-control.gc @@ -2218,7 +2218,7 @@ ;; PC port note : added this so we can see it during the code-hook :post (behavior () (if *debug-segment* - (format *stdcon* "task-manager: alive in code-hook task ~A~%" (game-task->string (-> self node-info task))) + (format *stdcon* "task-manager: alive in code task ~A~%" (game-task->string (-> self node-info task))) ) ) ) diff --git a/goal_src/jak2/engine/gfx/math-camera.gc b/goal_src/jak2/engine/gfx/math-camera.gc index 71ccd39aa4..ae172c583b 100644 --- a/goal_src/jak2/engine/gfx/math-camera.gc +++ b/goal_src/jak2/engine/gfx/math-camera.gc @@ -76,7 +76,7 @@ renderers that want a single matrix. ;; crops excess aspect ratio at the top and bottom ;(set! (-> arg0 y-ratio) (* (1/ (-> *pc-settings* aspect-ratio)) (-> arg0 x-ratio))) ) - ((-> *pc-settings* movie?) + ((real-movie?) ;; this mess is just so that we can force the original 16x9 cropping during cutscenes. (if (<= (-> *pc-settings* aspect-ratio) ASPECT_16X9) (set! (-> arg0 y-ratio) (* (1/ (-> *pc-settings* aspect-ratio)) (-> arg0 x-ratio))) diff --git a/goal_src/jak2/pc/pckernel.gc b/goal_src/jak2/pc/pckernel.gc index 42cca43e98..d1fe83168a 100644 --- a/goal_src/jak2/pc/pckernel.gc +++ b/goal_src/jak2/pc/pckernel.gc @@ -52,13 +52,9 @@ ) -(defmethod update pc-settings-jak2 ((obj pc-settings-jak2)) - "handle the text parsing input for the 'settings' group" - - ((method-of-type pc-settings update) obj) - - (set! (-> obj movie?) (and (!= #f *scene-player*) (movie?))) - (none)) +(defun real-movie? () + "are we in an actual cutscene and should letterbox the view?" + (and (!= #f *scene-player*) (nonzero? movie?) (movie?))) (defmethod update-discord-rpc pc-settings-jak2 ((obj pc-settings-jak2)) "update discord rpc module" @@ -79,7 +75,7 @@ (else (set! (-> info level) (aif (-> *load-state* vis-nick) (symbol->string it) "unknown"))) ) - (set! (-> info cutscene?) (-> *pc-settings* movie?)) + (set! (-> info cutscene?) (real-movie?)) (set! (-> info time-of-day) (-> *time-of-day-context* time)) (set! (-> info percent-complete) (calculate-percentage *game-info*)) (set! (-> info focus-status) (if *target* (-> *target* focus-status) 0)) @@ -91,7 +87,7 @@ (defmethod update-speedrun pc-settings-jak2 ((obj pc-settings-jak2)) "update speedrun module" (when (-> *pc-settings* speedrunner-mode?) - (speedrun-mode-update)) + (speedrun-mode-update)) (none)) (defmethod update-video-hacks pc-settings-jak2 ((obj pc-settings-jak2)) @@ -161,9 +157,9 @@ (bucket-id debug-no-zbuf1)) (draw-string-xy *pc-settings-built-sha* buf - 0 10 + 512 14 (font-color flat-yellow) - (font-flags shadow kerning)))) + (font-flags right shadow kerning)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;; process pools