mirror of
https://github.com/sfall-team/sfall.git
synced 2026-07-27 16:52:34 -07:00
Updated map view code
This commit is contained in:
@@ -155,9 +155,18 @@ void __declspec(naked) interpretError(const char* fmt, ...) {
|
||||
}
|
||||
|
||||
long __fastcall tile_num(long x, long y) {
|
||||
__asm push ebx; // don't delete (bug in tile_num_)
|
||||
__asm xor ebx, ebx; // don't delete (bug in tile_num_)
|
||||
WRAP_WATCOM_FCALL2(tile_num_, x, y);
|
||||
__asm pop ebx;
|
||||
}
|
||||
|
||||
void __fastcall square_xy(long x, long y, long* outSX, long* outSY) {
|
||||
__asm {
|
||||
xor ebx, ebx; // don't delete (bug in square_xy_)
|
||||
mov eax, ecx;
|
||||
push outSY;
|
||||
mov ecx, outSX;
|
||||
call fo::funcoffs::square_xy_;
|
||||
}
|
||||
}
|
||||
|
||||
GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWORD elevation, void* func) {
|
||||
|
||||
@@ -54,6 +54,8 @@ void __declspec() interpretError(const char* fmt, ...);
|
||||
|
||||
long __fastcall tile_num(long x, long y);
|
||||
|
||||
void __fastcall square_xy(long x, long y, long* outSX, long* outSY);
|
||||
|
||||
GameObject* __fastcall obj_blocking_at_wrapper(GameObject* obj, DWORD tile, DWORD elevation, void* func);
|
||||
|
||||
// Creates a button on a given window
|
||||
|
||||
@@ -60,6 +60,7 @@ WRAP_WATCOM_FFUNC4(long, register_object_run_to_object, fo::GameObject*, source,
|
||||
WRAP_WATCOM_FFUNC3(long, register_object_play_sfx, fo::GameObject*, object, const char*, sfxName, long, delay)
|
||||
WRAP_WATCOM_FFUNC3(long, scr_get_local_var, long, sid, long, varId, long*, value)
|
||||
WRAP_WATCOM_FFUNC3(long, scr_set_local_var, long, sid, long, varId, long, value)
|
||||
WRAP_WATCOM_FFUNC3(long, square_coord, long, square, long*, outX, long*, outY)
|
||||
WRAP_WATCOM_FFUNC6(long, text_object_create, fo::GameObject*, object, const char*, text, long, font, long, colorText, long, colorOutline, fo::BoundRect*, rect)
|
||||
WRAP_WATCOM_FFUNC3(long, tile_coord, long, tile, long*, outX, long*, outY) // the fourth argument of the function is not used
|
||||
WRAP_WATCOM_FFUNC3(long, tile_num_in_direction, long, tile, long, rotation, long, distance)
|
||||
|
||||
+12
-3
@@ -57,6 +57,8 @@ bool HRP::CheckExternalPatch() {
|
||||
}
|
||||
|
||||
void HRP::init() {
|
||||
//SafeWrite16(0x4B2EA8, 0x9090); // _show_grid
|
||||
|
||||
if (!hrpIsEnabled && IniReader::GetIntDefaultConfig("Main", "HiResMode", 1) == 0) return; // vanilla game mode
|
||||
|
||||
SCR_WIDTH = IniReader::GetInt("Main", "SCR_WIDTH", 640, f2ResIni);
|
||||
@@ -93,8 +95,8 @@ void HRP::init() {
|
||||
|
||||
std::string x = trim(IniReader::GetString("MAPS", "SCROLL_DIST_X", "480", 16, f2ResIni));
|
||||
std::string y = trim(IniReader::GetString("MAPS", "SCROLL_DIST_Y", "400", 16, f2ResIni));
|
||||
ViewMap::SCROLL_DIST_X = (x == "HALF_SCRN") ? (SCR_WIDTH / 2) + 32 : std::atol(x.c_str());
|
||||
ViewMap::SCROLL_DIST_Y = (y == "HALF_SCRN") ? (SCR_HEIGHT / 2) + 24 : std::atol(y.c_str());
|
||||
ViewMap::SCROLL_DIST_X = (!x.compare(0, 9, "HALF_SCRN")) ? (SCR_WIDTH / 2) + 32 : std::atol(x.c_str());
|
||||
ViewMap::SCROLL_DIST_Y = (!y.compare(0, 9, "HALF_SCRN")) ? (SCR_HEIGHT / 2) + 24 : std::atol(y.c_str());
|
||||
|
||||
ViewMap::IGNORE_PLAYER_SCROLL_LIMITS = (IniReader::GetInt("MAPS", "IGNORE_PLAYER_SCROLL_LIMITS", 0, f2ResIni) != 0);
|
||||
ViewMap::IGNORE_MAP_EDGES = (IniReader::GetInt("MAPS", "IGNORE_MAP_EDGES", 0, f2ResIni) != 0);
|
||||
@@ -106,9 +108,10 @@ void HRP::init() {
|
||||
IniReader::GetString("Main", "f2_res_patches", "data", MAX_PATH, f2ResIni)
|
||||
);
|
||||
|
||||
// Inject hacks
|
||||
/* Inject hacks */
|
||||
SafeWrite32(0x482E30, FO_VAR_mapEntranceTileNum); // map_load_file_ (_tile_center_tile to _mapEntranceTileNum)
|
||||
|
||||
if (SCR_WIDTH != 640 || SCR_HEIGHT != 480) {
|
||||
// Set the resolution for GNW95_init_mode_ex_
|
||||
SafeWrite32(0x4CAD6B, SCR_WIDTH); // 640
|
||||
SafeWrite32(0x4CAD66, SCR_HEIGHT); // 480
|
||||
@@ -120,6 +123,12 @@ void HRP::init() {
|
||||
// gnw_main_
|
||||
SafeWrite32(0x480AFA, SCR_HEIGHT); // -100 for ifacebar?
|
||||
SafeWrite32(0x480B04, SCR_WIDTH);
|
||||
// LoadGame_
|
||||
SafeWrite32(0x47C6E0, SCR_HEIGHT);
|
||||
SafeWrite32(0x47C6E5, SCR_WIDTH);
|
||||
SafeWrite32(0x47C703, SCR_WIDTH);
|
||||
SafeWrite32(0x47C70D, SCR_HEIGHT);
|
||||
}
|
||||
|
||||
// Inits
|
||||
SplashScreen::init();
|
||||
|
||||
@@ -16,15 +16,15 @@ namespace sfall
|
||||
{
|
||||
|
||||
static EdgeBorder::Edge* MapEdgeData;
|
||||
|
||||
// reference
|
||||
EdgeBorder::Edge* currentMapEdge;
|
||||
|
||||
EdgeBorder::Edge* EdgeBorder::CurrentMapEdge() { return currentMapEdge; }
|
||||
static EdgeBorder::Edge* currentMapEdge; // reference
|
||||
|
||||
static long edgeVersion; // 0 - version 1 (obsolete), 1 - version 2 (current)
|
||||
bool isLoadingMapEdge;
|
||||
bool isDefaultSetEdge;
|
||||
static bool isDefaultSetEdge;
|
||||
//bool isLoadingMapEdge;
|
||||
|
||||
long EdgeBorder::EdgeVersion() { return edgeVersion; }
|
||||
|
||||
EdgeBorder::Edge* EdgeBorder::CurrentMapEdge() { return currentMapEdge; }
|
||||
|
||||
// Implementation from HRP by Mash
|
||||
static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
|
||||
@@ -67,7 +67,7 @@ static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
|
||||
long rectH = (edgeData->borderRect.bottom - edgeData->borderRect.top) / 2;
|
||||
long _rectH = rectH;
|
||||
if (rectH % 24) {
|
||||
rectH -= rectH % 24; // truncate
|
||||
rectH -= rectH % 24;
|
||||
_rectH = rectH + 24;
|
||||
}
|
||||
if (rectH < h) {
|
||||
@@ -78,7 +78,6 @@ static void CalcEdgeData(EdgeBorder::Edge* edgeData, long w, long h) {
|
||||
edgeData->borderRect.bottom -= h;
|
||||
}
|
||||
|
||||
// borderRect: right is less than left
|
||||
if ((edgeData->borderRect.left < edgeData->borderRect.right) || (edgeData->borderRect.left - edgeData->borderRect.right) == 32) {
|
||||
edgeData->borderRect.left = edgeData->borderRect.right;
|
||||
}
|
||||
@@ -197,6 +196,7 @@ static fo::DbFile* LoadMapEdgeFileSub(char* mapName) {
|
||||
if (getValue != mapLevel) break; // next level
|
||||
|
||||
EdgeBorder::Edge *edge = new EdgeBorder::Edge;
|
||||
edge->prevEdgeData = edgeData;
|
||||
edge->nextEdgeData = nullptr;
|
||||
edge->squareRect = edgeData->squareRect; // rect copy
|
||||
edgeData->nextEdgeData = edge;
|
||||
@@ -304,7 +304,7 @@ long EdgeBorder::CheckBorder(long tile) {
|
||||
ViewMap::GetTileCoordOffset(tile, x, y);
|
||||
|
||||
if (x > currentMapEdge->borderRect.left || x < currentMapEdge->borderRect.right ||
|
||||
y > currentMapEdge->borderRect.bottom || y < currentMapEdge->borderRect.top)
|
||||
y < currentMapEdge->borderRect.top || y > currentMapEdge->borderRect.bottom)
|
||||
{
|
||||
return 0; // block
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ class EdgeBorder {
|
||||
public:
|
||||
struct Edge {
|
||||
POINT center; // x/y center of current map screen?
|
||||
RECT borderRect;
|
||||
RECT borderRect; // right is less than left
|
||||
RECT rect_2;
|
||||
RECT tileRect;
|
||||
RECT squareRect;
|
||||
@@ -36,7 +36,10 @@ public:
|
||||
};
|
||||
|
||||
static void init();
|
||||
|
||||
static Edge* CurrentMapEdge();
|
||||
static long EdgeVersion();
|
||||
|
||||
static long GetCenterTile(long tile, long mapLevel);
|
||||
static long CheckBorder(long tile);
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ static RECT mapVisibleArea;
|
||||
|
||||
// Returns -1 if the scrRect is not in the rectangle of inRect (same as rect_inside_bound_)
|
||||
static __inline long rect_inside_bound(RECT* srcRect, RECT* inRect, RECT* outRect) {
|
||||
*outRect = *srcRect; // srcRect copy to outRect
|
||||
if (srcRect != outRect) *outRect = *srcRect; // srcRect copy to outRect
|
||||
|
||||
if (inRect->right < srcRect->left ||
|
||||
inRect->left > srcRect->right ||
|
||||
@@ -111,7 +111,7 @@ static long __fastcall rect_inside_bound_clip(RECT* srcRect, RECT* inRect, RECT*
|
||||
|
||||
if (ViewMap::EDGE_CLIPPING_ON) {
|
||||
if (CheckRect(outRect)) { // when do you need the fill below?
|
||||
long height = outRect->bottom - outRect->top + 1;
|
||||
long height = (outRect->bottom - outRect->top) + 1;
|
||||
if (height > 0) {
|
||||
long width = (outRect->right - outRect->left) + 1;
|
||||
if (width > 0) {
|
||||
@@ -139,7 +139,7 @@ static void __declspec(naked) refresh_game_hook_rect_inside_bound() {
|
||||
static long __fastcall rect_inside_bound_scroll_clip(RECT* srcRect, RECT* inRect, RECT* outRect) {
|
||||
long height = (srcRect->bottom - srcRect->top) + 1;
|
||||
if (height > 0) {
|
||||
long width = srcRect->right - srcRect->left + 1;
|
||||
long width = (srcRect->right - srcRect->left) + 1;
|
||||
if (width > 0) {
|
||||
ClearRect(width, height, srcRect);
|
||||
}
|
||||
@@ -159,9 +159,10 @@ static void __declspec(naked) map_scroll_refresh_game_hook_rect_inside_bound() {
|
||||
}
|
||||
|
||||
static long __fastcall MouseCheckArea(long x, long y) {
|
||||
if (x < (mapVisibleArea.left) || x > (mapVisibleArea.right) || y < mapVisibleArea.top || y >= mapVisibleArea.bottom) {
|
||||
if (!ViewMap::EDGE_CLIPPING_ON) return 0;
|
||||
if (x < mapVisibleArea.left || x > mapVisibleArea.right || y < mapVisibleArea.top || y >= mapVisibleArea.bottom) {
|
||||
if (fo::func::win_get_top_win(x, y) == fo::var::getInt(FO_VAR_display_win)) {
|
||||
return -7;
|
||||
return 40000;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@@ -186,7 +187,8 @@ check:
|
||||
jnz set;
|
||||
retn;
|
||||
set:
|
||||
mov ebx, eax;
|
||||
mov ebx, -7;
|
||||
//mov ecx, 3;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
namespace sfall
|
||||
{
|
||||
|
||||
const long grid_width = 200; // _grid_width
|
||||
const long square_width = 100;
|
||||
const long square_length = 100;
|
||||
|
||||
static Rectangle obj_on_screen_rect;
|
||||
|
||||
long ViewMap::SCROLL_DIST_X;
|
||||
@@ -39,15 +43,15 @@ void ViewMap::GetCoordFromOffset(long &inOutX, long &inOutY) {
|
||||
}
|
||||
|
||||
void ViewMap::GetTileCoord(long tile, long &outX, long &outY) {
|
||||
int x = tile % 200; // tile % _grid_width // 20100%200 = 100
|
||||
int y = (tile / 200) + (x / 2); // tile / _grid_width + x / 2 // 20100/200 = 100+(100/2) = y:150 ???
|
||||
int x = tile % grid_width; // 20100%200 = 100
|
||||
int y = (tile / grid_width) + (x / 2); // 20100/200 = 100+(100/2) = y:150 ???
|
||||
outY = y;
|
||||
outX = (2 * x) - y; // 2*100 = 200-150 = x:50 ???
|
||||
}
|
||||
|
||||
void ViewMap::GetTileCoordOffset(long tile, long &outX, long &outY) {
|
||||
int x = tile % 200; // tile % _grid_width // 20100%200 = 100
|
||||
int y = (tile / 200) + (x / 2); // tile / _grid_width + x / 2 // 20100/200 = 100+(100/2) = y:150 ???
|
||||
int x = tile % grid_width; // 20100%200 = 100
|
||||
int y = (tile / grid_width) + (x / 2); // 20100/200 = 100+(100/2) = y:150 ???
|
||||
y &= 0xFFFFFFFE; // even to down
|
||||
x = (2 * x) + 200 - y; // 2*100 = 200+200-150 = x:250 ???
|
||||
|
||||
@@ -112,8 +116,8 @@ static long __fastcall tile_set_center(long tile, long modeFlags) {
|
||||
|
||||
fo::var::setInt(FO_VAR_tile_center_tile) = tile;
|
||||
|
||||
long tile_y = tile / 200; // _grid_width
|
||||
long tile_x = 200 - (tile % 200) - 1;
|
||||
long tile_y = tile / grid_width;
|
||||
long tile_x = 200 - (tile % grid_width) - 1;
|
||||
|
||||
if (tile_x & 1) {
|
||||
tile_x--;
|
||||
@@ -155,11 +159,178 @@ static void __declspec(naked) tile_set_center_hack_replacement() {
|
||||
|
||||
static void __declspec(naked) tile_scroll_to_hack_replacement() {
|
||||
__asm {
|
||||
//mov edx, 3; // modeFlags is always 2
|
||||
mov edx, 3; // modeFlags is always 2
|
||||
jmp tile_set_center_hack_replacement;
|
||||
}
|
||||
}
|
||||
|
||||
static long __fastcall square_rect_render_floor(long y, long id, long x) {
|
||||
if (x < 0 || x >= square_width || y < 0 || y >= square_length) return -1;
|
||||
|
||||
auto edge = EdgeBorder::CurrentMapEdge();
|
||||
if (EdgeBorder::EdgeVersion() && (x > edge->squareRect.left || x < edge->squareRect.right || y > edge->squareRect.bottom || y < edge->squareRect.top)) {
|
||||
return 1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static void __declspec(naked) square_render_floor_hook_art_id() {
|
||||
__asm {
|
||||
mov ecx, [esp + 0x24 + 4];
|
||||
push esi;
|
||||
call square_rect_render_floor;
|
||||
test eax, eax;
|
||||
js skipDraw; // -1
|
||||
mov edx, eax;
|
||||
xor ecx, ecx;
|
||||
mov eax, 4;
|
||||
jmp fo::funcoffs::art_id_;
|
||||
|
||||
skipDraw:
|
||||
mov [esp], 0x4B2AD4;
|
||||
retn 4;
|
||||
}
|
||||
}
|
||||
|
||||
static long __fastcall square_rect_render_roof(long y, long id, long x) {
|
||||
if (x < 0 || x >= square_width || y < 0 || y >= square_length) return -1;
|
||||
|
||||
auto edge = EdgeBorder::CurrentMapEdge();
|
||||
if (EdgeBorder::EdgeVersion() && (x > (edge->squareRect.left + 2) || x < (edge->squareRect.right + 2) ||
|
||||
y > (edge->squareRect.bottom + 3) || y < (edge->squareRect.top + 3)))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static void __declspec(naked) square_render_roof_hook_art_id() {
|
||||
using namespace fo;
|
||||
__asm {
|
||||
mov ecx, [esp + 0x20 + 4];
|
||||
push edi;
|
||||
call square_rect_render_roof;
|
||||
test eax, eax;
|
||||
js skipDraw; // -1
|
||||
mov edx, eax;
|
||||
xor ecx, ecx;
|
||||
mov eax, OBJ_TYPE_TILE;
|
||||
jmp fo::funcoffs::art_id_;
|
||||
|
||||
skipDraw:
|
||||
mov eax, esi;
|
||||
retn 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) square_roof_intersect_hook_art_id() {
|
||||
using namespace fo;
|
||||
__asm {
|
||||
mov ecx, [esp + 0x8 + 4];
|
||||
push [esp + 0x4 + 4];
|
||||
call square_rect_render_roof;
|
||||
test eax, eax;
|
||||
js skipDraw; // -1
|
||||
mov edx, eax;
|
||||
xor ecx, ecx;
|
||||
mov eax, OBJ_TYPE_TILE;
|
||||
jmp fo::funcoffs::art_id_;
|
||||
|
||||
skipDraw:
|
||||
xor eax, eax;
|
||||
mov [esp], 0x4B2C05;
|
||||
retn 4;
|
||||
}
|
||||
}
|
||||
|
||||
static void __fastcall square_obj_render(fo::BoundRect* rect, long tag) {
|
||||
if (EdgeBorder::EdgeVersion() == 0) return;
|
||||
|
||||
long x0, y0, x1, y1, x2, y2, x3, y3;
|
||||
|
||||
fo::func::square_xy(rect->x, rect->offy, &x0, &y0);
|
||||
fo::func::square_xy(rect->x, rect->y, &x1, &y1);
|
||||
fo::func::square_xy(rect->offx, rect->y, &x2, &y2);
|
||||
fo::func::square_xy(rect->offx, rect->offy, &x3, &y3);
|
||||
|
||||
if (++x0 > square_width) x0 = square_width - 1;
|
||||
if (--x2 < 0) x2 = 0;
|
||||
if (--y1 < 0) y1 = 0;
|
||||
if (++y3 > square_length) y3 = square_length - 1;
|
||||
|
||||
if (y1 >= y3 || x2 >= x0) return; // top >= bottom / left >= right
|
||||
|
||||
long Y = y1;
|
||||
long sY = square_width * Y;
|
||||
|
||||
auto edge = EdgeBorder::CurrentMapEdge();
|
||||
do {
|
||||
long X = x2;
|
||||
do {
|
||||
if (X > edge->squareRect.left && ((edge->field_48 >> 24) & 1) == tag ||
|
||||
Y < edge->squareRect.top && ((edge->field_48 >> 16) & 1) == tag ||
|
||||
X < edge->squareRect.right && ((edge->field_48 >> 8) & 1) == tag ||
|
||||
Y > edge->squareRect.bottom && (edge->field_48 & 1) == tag)
|
||||
{
|
||||
long s_x, s_y;
|
||||
fo::func::square_coord(X + sY, &s_x, &s_y);
|
||||
__asm {
|
||||
mov ecx, rect;
|
||||
mov ebx, s_y;
|
||||
mov edx, s_x;
|
||||
mov eax, 0x4000001; // tile fid
|
||||
call fo::funcoffs::floor_draw_;
|
||||
}
|
||||
}
|
||||
} while (++X < x0);
|
||||
|
||||
sY += square_width;
|
||||
} while (++Y < y3); // y < bottom
|
||||
}
|
||||
|
||||
static void __declspec(naked) obj_render_pre_roof_hack_0() {
|
||||
__asm {
|
||||
lea ecx, [esp + 4];
|
||||
mov edx, 0;
|
||||
call square_obj_render;
|
||||
mov edi, [esp + 0x2C + 4];
|
||||
test edi, edi;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
static void __declspec(naked) obj_render_pre_roof_hack_1() {
|
||||
__asm {
|
||||
lea ecx, [esp + 4];
|
||||
mov edx, 1;
|
||||
call square_obj_render;
|
||||
pop eax; // ret addr
|
||||
add esp, 0x44;
|
||||
pop ebp;
|
||||
pop edi;
|
||||
jmp eax;
|
||||
}
|
||||
}
|
||||
|
||||
// An odd solution to the problem from HRP 3.06 (4.1.8 uses a different solution)
|
||||
static void __declspec(naked) obj_render_pre_roof_hack() {
|
||||
__asm {
|
||||
mov ebx, [eax];
|
||||
lea eax, [edx + ebx];
|
||||
cmp eax, 40000; // _grid_size
|
||||
jge capMax;
|
||||
cmp eax, 0;
|
||||
jl capMin;
|
||||
retn;
|
||||
capMax:
|
||||
mov eax, 39999;
|
||||
retn;
|
||||
capMin:
|
||||
xor eax, eax;
|
||||
retn;
|
||||
}
|
||||
}
|
||||
|
||||
void ViewMap::init() {
|
||||
if (SCROLL_DIST_X <= 0) SCROLL_DIST_X = 480;
|
||||
else if (SCROLL_DIST_X < 320) SCROLL_DIST_X = 320;
|
||||
@@ -170,6 +341,15 @@ void ViewMap::init() {
|
||||
MakeJump(fo::funcoffs::tile_set_center_, tile_set_center_hack_replacement); // 0x4B12F8
|
||||
MakeJump(fo::funcoffs::tile_scroll_to_, tile_scroll_to_hack_replacement); // 0x4B3924
|
||||
|
||||
HookCall(0x4B2AC0, square_render_floor_hook_art_id);
|
||||
HookCall(0x4B2261, square_render_roof_hook_art_id);
|
||||
HookCall(0x4B2BF7, square_roof_intersect_hook_art_id); // need to test object_under_mouse_
|
||||
MakeCall(0x489730, obj_render_pre_roof_hack_0, 1);
|
||||
MakeCall(0x4897E3, obj_render_pre_roof_hack_1);
|
||||
|
||||
// Fix
|
||||
MakeCall(0x489665, obj_render_pre_roof_hack); // find the bug
|
||||
|
||||
obj_on_screen_rect.width = HRP::ScreenWidth();
|
||||
obj_on_screen_rect.height = HRP::ScreenHeight(); // maybe take into account the interface bar and be: height - 100?
|
||||
SafeWrite32(0x45C886, (DWORD)&obj_on_screen_rect); // replace rectangle in op_obj_on_screen_
|
||||
|
||||
Reference in New Issue
Block a user