1
0
mirror of https://github.com/djhackersdev/bemanitools.git synced 2025-01-31 20:15:20 +01:00

feat(iidx 20-26): New up-/downscaling gfx module, old one doesn't work

This replaces the scaling feature of iidxhook-util/d3d9 as the
game engine changed significantly that the old one is incompatible.

Create a new module because the logic to implement a scaling
feature is very different now. This also avoids further cluttering
the already badly overloaded old module.

The new module is light weight and "plugable" on a hooking
level. Further modules will follow to de-clutter the
iidxhook-util/d3d9 module
This commit is contained in:
icex2 2023-04-15 15:49:43 +02:00 committed by icex2
parent 6ea099fd9e
commit 782a23db74
5 changed files with 207 additions and 0 deletions

View File

@ -134,6 +134,7 @@ include src/main/iidx-bio2-exit-hook/Module.mk
include src/main/iidx-ezusb-exit-hook/Module.mk
include src/main/iidx-ezusb2-exit-hook/Module.mk
include src/main/iidx-irbeat-patch/Module.mk
include src/main/iidxhook-d3d9/Module.mk
include src/main/iidxhook-util/Module.mk
include src/main/iidxhook1/Module.mk
include src/main/iidxhook2/Module.mk

View File

@ -0,0 +1,8 @@
libs += iidxhook-d3d9
libs_iidxhook-d3d9 := \
util \
d3d9-util \
src_iidxhook-d3d9 := \
bb-scale-hd.c \

View File

@ -0,0 +1,163 @@
#define LOG_MODULE "iidxhook-d3d9-bb-scale-hd"
#include <windows.h>
#include "d3d9-util/vertex.h"
#include "bb-scale-hd.h"
#include "util.h"
#include "util/log.h"
static bool iidxhook_d3d9_bb_scale_initialized;
static uint16_t iidxhook_d3d9_bb_scale_hd_width;
static uint16_t iidxhook_d3d9_bb_scale_hd_height;
void iidxhook_d3d9_bb_scale_hd_init(uint16_t width, uint16_t height)
{
iidxhook_d3d9_bb_scale_hd_width = width;
iidxhook_d3d9_bb_scale_hd_height = height;
iidxhook_d3d9_bb_scale_initialized = true;
log_info("Initialized, width %d, height %d", width, height);
}
static bool iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
struct d3d9_util_vertex *vertex, float x, float y, float error_margin)
{
return vertex->x >= x - error_margin && vertex->x <= x + error_margin &&
vertex->y >= y - error_margin && vertex->y <= y + error_margin;
}
static bool iidxhook_d3d9_bb_scale_hd_match_2d_plane(
struct d3d9_util_vertex *vertices,
float origin_x,
float origin_y,
float size_x,
float size_y,
float error_margin)
{
return
// top left
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[0], origin_x, origin_y, error_margin) &&
// top right
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[1], origin_x + size_x, origin_y, error_margin) &&
// bottom right
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[2], origin_x + size_x, origin_y + size_y, error_margin) &&
// bottom left
iidxhook_d3d9_bb_scale_hd_in_range_of_2d_coords(
&vertices[3], origin_x, origin_y + size_y, error_margin);
}
static void iidxhook_d3d9_bb_scale_hd_set_plane(
struct d3d9_util_vertex *vertices,
float origin_x,
float origin_y,
float size_x,
float size_y)
{
// top left
vertices[0].x = origin_x;
vertices[0].y = origin_y;
// top right
vertices[1].x = origin_x + size_x;
vertices[1].y = origin_y;
// bottom right
vertices[2].x = origin_x + size_x;
vertices[2].y = origin_y + size_y;
// bottom left
vertices[3].x = origin_x;
vertices[3].y = origin_y + size_y;
}
HRESULT iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler(struct hook_d3d9_irp *irp)
{
log_assert(irp);
if (!iidxhook_d3d9_bb_scale_initialized) {
return hook_d3d9_irp_invoke_next(irp);
}
if (irp->op == HOOK_D3D9_IRP_OP_CTX_CREATE_DEVICE) {
// Scale the backbuffer accordingly
// The game renders to an intermediate texture by default to provide the
// SD vs. HD feature already
irp->args.ctx_create_device.pp->BackBufferWidth =
iidxhook_d3d9_bb_scale_hd_width;
irp->args.ctx_create_device.pp->BackBufferHeight =
iidxhook_d3d9_bb_scale_hd_height;
return hook_d3d9_irp_invoke_next(irp);
} else if (irp->op == HOOK_D3D9_IRP_OP_DEV_DRAW_PRIMITIVE_UP) {
if (irp->args.dev_draw_primitive_up.primitive_type ==
D3DPT_TRIANGLEFAN &&
irp->args.dev_draw_primitive_up.primitive_count == 2 &&
irp->args.dev_draw_primitive_up.stride == 28) {
struct d3d9_util_vertex *vertices =
(struct d3d9_util_vertex *)
irp->args.dev_draw_primitive_up.data;
// The engine draws everything to a separate texture as the primary
// render target Depending on the game mode selected, SD vs. HD/HD*,
// the texture's size is either 640x480 or 1280x720 After drawing
// the scene is finished (after EndScene), the game blends the
// texture with the game's rendered output to the actual frame
// buffer
if (iidxhook_d3d9_bb_scale_hd_match_2d_plane(
vertices, 0, 0, 640, 480, 1.0) ||
iidxhook_d3d9_bb_scale_hd_match_2d_plane(
vertices, 0, 0, 1280, 720, 1.0)) {
// Note: Original plane is not at origin 0.0/0.0?
// Example for SD plane:
// -0.500000/-0.500000 639.500000/-0.500000
// 639.500000/479.500000 -0.500000/479.500000 Patch to set it to
// 0.0/0.0
// Scale the 2D output plane primitive to the right resolution
// (upscale or downscale) The render parameter for the blending
// operation will automatically scale the selected source
// texture, the intermediate render buffer with the game's final
// frame, to the actual frame buffer once the DrawPrimitiveUP
// call completed
iidxhook_d3d9_bb_scale_hd_set_plane(
vertices,
0.0,
0.0,
iidxhook_d3d9_bb_scale_hd_width,
iidxhook_d3d9_bb_scale_hd_height);
}
}
return hook_d3d9_irp_invoke_next(irp);
} else if (irp->op == HOOK_D3D9_IRP_OP_DEV_RESET) {
// Gets called when changing the "definition type" in the operator
// menu. needs to be patched to keep the right back buffer size
irp->args.dev_reset.pp->BackBufferWidth =
iidxhook_d3d9_bb_scale_hd_width;
irp->args.dev_reset.pp->BackBufferHeight =
iidxhook_d3d9_bb_scale_hd_height;
return hook_d3d9_irp_invoke_next(irp);
} else if (irp->op == HOOK_D3D9_IRP_OP_DEV_SET_SCISSOR_RECT) {
// Blending to the frame buffer applies scissors which needs to be
// patched to match the final frame buffer's size
RECT *rect = (RECT *) irp->args.dev_set_scissor_rect.pRect;
// Only adjust scissoring when applied to full frame
// Otherwise, this also scissors various UI elements
if (rect->left == 0 && rect->left == 0 && rect->right == 1280 &&
rect->bottom == 720) {
rect->right = iidxhook_d3d9_bb_scale_hd_width;
rect->bottom = iidxhook_d3d9_bb_scale_hd_height;
}
return hook_d3d9_irp_invoke_next(irp);
} else {
return hook_d3d9_irp_invoke_next(irp);
}
}

View File

@ -0,0 +1,13 @@
#ifndef IIDXHOOK_D3D9_HD_H
#define IIDXHOOK_D3D9_HD_H
#include <stdbool.h>
#include <stdint.h>
#include "hook/d3d9.h"
void iidxhook_d3d9_bb_scale_hd_init(uint16_t width, uint16_t height);
HRESULT iidxhook_d3d9_bb_scale_hd_d3d9_irp_handler(struct hook_d3d9_irp *irp);
#endif

View File

@ -0,0 +1,22 @@
#ifndef IIDXHOOK_D3D9_UTIL_H
#define IIDXHOOK_D3D9_UTIL_H
#include <windows.h>
#include "d3d9-util/dxerr9.h"
#include "util/log.h"
inline void
iidxhook_d3d9_util_check_and_handle_failure(HRESULT hr, const char *msg)
{
if (FAILED(hr)) {
log_fatal(
"%s\nDX error: %s, DX error description: %s",
msg,
DXGetErrorString9(hr),
DXGetErrorDescription9(hr));
}
}
#endif