Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion resources/unix/easyrpg-player.6.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,20 @@ NOTE: For games that only use ASCII (English games) use '1252'.
Enable limited support for the DynRPG patch from Cherry. The patches are not
loaded from DLL files, but re-implemented by the engine.

*--patch-easyrpg*::
Enable EasyRPG extensions such as support for 32 bit images and large charsets.

*--patch-key-patch*::
Enable support for the Key Patch by Ineluki.

*--patch-maniac*::
*--patch-maniac*:: _[N]_
Enable support for the Maniac Patch by BingShan.
Values for N:
- 1: Enable the patch (default)
- 2: Enable the patch but do not adjust variable ranges to 32 bit.

Not adjusting the variable ranges is useful if you are adding the patch to an
existing game, as this reduces the likelihood that the game will stop working.

*--patch-pic-unlock*::
Picture movement is not interrupted by messages in any version of the engine.
Expand Down
2 changes: 1 addition & 1 deletion src/battle_animation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ void BattleAnimationMap::DrawSingle(Bitmap& dst) {
}
const int character_height = 24;
int x_off = target.GetScreenX();
int y_off = target.GetScreenY(false, false);
int y_off = target.GetScreenY(false);
if (Scene::instance->type == Scene::Map) {
x_off += static_cast<Scene_Map*>(Scene::instance.get())->spriteset->GetRenderOx();
y_off += static_cast<Scene_Map*>(Scene::instance.get())->spriteset->GetRenderOy();
Expand Down
47 changes: 23 additions & 24 deletions src/bitmap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,67 +99,66 @@ Bitmap::Bitmap(Filesystem_Stream::InputStream stream, bool transparent, uint32_t
return;
}

int w = 0;
int h = 0;
void* pixels = nullptr;
ImageOut image_out;

uint8_t data[4] = {};
size_t bytes = stream.read(reinterpret_cast<char*>(data), 4).gcount();
stream.seekg(0, std::ios::ios_base::beg);

bool img_okay = false;

if (bytes >= 4 && strncmp((char*)data, "XYZ1", 4) == 0)
img_okay = ImageXYZ::ReadXYZ(stream, transparent, w, h, pixels);
else if (bytes > 2 && strncmp((char*)data, "BM", 2) == 0)
img_okay = ImageBMP::ReadBMP(stream, transparent, w, h, pixels);
else if (bytes >= 4 && strncmp((char*)(data + 1), "PNG", 3) == 0)
img_okay = ImagePNG::ReadPNG(stream, transparent, w, h, pixels);
else
if (bytes >= 4 && strncmp((char*)data, "XYZ1", 4) == 0) {
img_okay = ImageXYZ::Read(stream, transparent, image_out);
} else if (bytes > 2 && strncmp((char*)data, "BM", 2) == 0) {
img_okay = ImageBMP::Read(stream, transparent, image_out);
} else if (bytes >= 4 && strncmp((char*)(data + 1), "PNG", 3) == 0) {
img_okay = ImagePNG::Read(stream, transparent, image_out);
} else
Output::Warning("Unsupported image file {} (Magic: {:02X})", stream.GetName(), *reinterpret_cast<uint32_t*>(data));

if (!img_okay) {
free(pixels);
pixels = nullptr;
free(image_out.pixels);
return;
}

Init(w, h, nullptr);
Init(image_out.width, image_out.height, nullptr);

ConvertImage(w, h, pixels, transparent);
ConvertImage(image_out.width, image_out.height, image_out.pixels, transparent);

CheckPixels(flags);

original_bpp = image_out.bpp;

filename = ToString(stream.GetName());
}

Bitmap::Bitmap(const uint8_t* data, unsigned bytes, bool transparent, uint32_t flags) {
format = (transparent ? pixel_format : opaque_pixel_format);
pixman_format = find_format(format);

int w = 0, h = 0;
void* pixels = nullptr;
ImageOut image_out;

bool img_okay = false;

if (bytes > 4 && strncmp((char*) data, "XYZ1", 4) == 0)
img_okay = ImageXYZ::ReadXYZ(data, bytes, transparent, w, h, pixels);
img_okay = ImageXYZ::Read(data, bytes, transparent, image_out);
else if (bytes > 2 && strncmp((char*) data, "BM", 2) == 0)
img_okay = ImageBMP::ReadBMP(data, bytes, transparent, w, h, pixels);
img_okay = ImageBMP::Read(data, bytes, transparent, image_out);
else if (bytes > 4 && strncmp((char*)(data + 1), "PNG", 3) == 0)
img_okay = ImagePNG::ReadPNG((const void*) data, transparent, w, h, pixels);
img_okay = ImagePNG::Read((const void*) data, transparent, image_out);
else
Output::Warning("Unsupported image (Magic: {:02X})", bytes >= 4 ? *reinterpret_cast<const uint32_t*>(data) : 0);

if (!img_okay) {
free(pixels);
pixels = nullptr;
free(image_out.pixels);
return;
}

Init(w, h, nullptr);
Init(image_out.width, image_out.height, nullptr);

ConvertImage(image_out.width, image_out.height, image_out.pixels, transparent);

ConvertImage(w, h, pixels, transparent);
original_bpp = image_out.bpp;

CheckPixels(flags);
}
Expand All @@ -183,7 +182,7 @@ bool Bitmap::WritePNG(std::ostream& os) const {
pixman_image_composite32(PIXMAN_OP_SRC, bitmap.get(), NULL, dst.get(),
0, 0, 0, 0, 0, 0, width, height);

return ImagePNG::WritePNG(os, width, height, &data.front());
return ImagePNG::Write(os, width, height, &data.front());
}

size_t Bitmap::GetSize() const {
Expand Down
21 changes: 21 additions & 0 deletions src/bitmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ class Bitmap {
*/
StringView GetFilename() const;

/**
* Gets bpp of the source image.
*
* @return Bpp
*/
int GetOriginalBpp() const;

void CheckPixels(uint32_t flags);

/**
Expand Down Expand Up @@ -599,6 +606,9 @@ class Bitmap {

std::string filename;

/** Bpp of the source image */
int original_bpp;

/** Bitmap data. */
PixmanImagePtr bitmap;
pixman_format_code_t pixman_format;
Expand Down Expand Up @@ -636,6 +646,13 @@ class Bitmap {
bool read_only = false;
};

struct ImageOut {
int width = 0;
int height = 0;
void* pixels = nullptr;
int bpp = 0;
};

inline ImageOpacity Bitmap::GetImageOpacity() const {
return image_opacity;
}
Expand Down Expand Up @@ -672,4 +689,8 @@ inline StringView Bitmap::GetFilename() const {
return filename;
}

inline int Bitmap::GetOriginalBpp() const {
return original_bpp;
}

#endif
9 changes: 9 additions & 0 deletions src/cache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "player.h"
#include <lcf/data.h>
#include "game_clock.h"
#include "translation.h"

using namespace std::chrono_literals;

Expand Down Expand Up @@ -272,6 +273,14 @@ namespace {
bmp = Bitmap::Create(std::move(is), transparent, flags);
if (!bmp) {
Output::Warning("Invalid image: {}/{}", s.directory, filename);
} else {
if (bmp->GetOriginalBpp() > 8) {
if (!Player::HasEasyRpgExtensions() && !Player::IsPatchManiac() && !Tr::HasActiveTranslation()) {
Output::Warning("Image {}/{} has a bit depth of {} that is not supported by RPG_RT. Enable EasyRPG Extensions or Maniac Patch to load such images.", s.directory, filename, bmp->GetOriginalBpp());
}

bmp.reset();
}
}
}
}
Expand Down
18 changes: 5 additions & 13 deletions src/game_character.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,22 +71,18 @@ int Game_Character::GetJumpHeight() const {
return 0;
}

int Game_Character::GetScreenX(bool apply_shift) const {
int Game_Character::GetScreenX() const {
int x = GetSpriteX() / TILE_SIZE - Game_Map::GetDisplayX() / TILE_SIZE + TILE_SIZE;

if (Game_Map::LoopHorizontal()) {
x = Utils::PositiveModulo(x, Game_Map::GetTilesX() * TILE_SIZE);
}
x -= TILE_SIZE / 2;

if (apply_shift) {
x += Game_Map::GetTilesX() * TILE_SIZE;
}

return x;
}

int Game_Character::GetScreenY(bool apply_shift, bool apply_jump) const {
int Game_Character::GetScreenY(bool apply_jump) const {
int y = GetSpriteY() / TILE_SIZE - Game_Map::GetDisplayY() / TILE_SIZE + TILE_SIZE;

if (apply_jump) {
Expand All @@ -97,14 +93,10 @@ int Game_Character::GetScreenY(bool apply_shift, bool apply_jump) const {
y = Utils::PositiveModulo(y, Game_Map::GetTilesY() * TILE_SIZE);
}

if (apply_shift) {
y += Game_Map::GetTilesY() * TILE_SIZE;
}

return y;
}

Drawable::Z_t Game_Character::GetScreenZ(bool apply_shift) const {
Drawable::Z_t Game_Character::GetScreenZ(int x_offset, int y_offset) const {
Drawable::Z_t z = 0;

if (IsFlying()) {
Expand All @@ -118,8 +110,8 @@ Drawable::Z_t Game_Character::GetScreenZ(bool apply_shift) const {
}

// 0x8000 (32768) is added to shift negative numbers into the positive range
Drawable::Z_t y = static_cast<Drawable::Z_t>(GetScreenY(apply_shift, false) + 0x8000);
Drawable::Z_t x = static_cast<Drawable::Z_t>(GetScreenX(apply_shift) + 0x8000);
Drawable::Z_t y = static_cast<Drawable::Z_t>(GetScreenY(false) + y_offset + 0x8000);
Drawable::Z_t x = static_cast<Drawable::Z_t>(GetScreenX() + x_offset + 0x8000);

// The rendering order of characters is: Highest Y-coordinate, Highest X-coordinate, Highest ID
// To encode this behaviour all of them get 16 Bit in the Z value
Expand Down
11 changes: 5 additions & 6 deletions src/game_character.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,27 +693,26 @@ class Game_Character {
/**
* Gets sprite x coordinate transformed to screen coordinate in pixels.
*
* @param apply_shift When true the coordinate is shifted by the map width (for looping maps)
* @return screen x coordinate in pixels.
*/
virtual int GetScreenX(bool apply_shift = false) const;
virtual int GetScreenX() const;

/**
* Gets sprite y coordinate transformed to screen coordinate in pixels.
*
* @param apply_shift When true the coordinate is shifted by the map height (for looping maps)
* @param apply_jump Apply jump height modifier if character is jumping
* @return screen y coordinate in pixels.
*/
virtual int GetScreenY(bool apply_shift = false, bool apply_jump = true) const;
virtual int GetScreenY(bool apply_jump = true) const;

/**
* Gets screen z coordinate
*
* @param apply_shift Forwarded to GetScreenY
* @param x_offset Offset to apply to the X coordinate
* @param y_offset Offset to apply to the Y coordinate
* @return screen z coordinate
*/
virtual Drawable::Z_t GetScreenZ(bool apply_shift = false) const;
virtual Drawable::Z_t GetScreenZ(int x_offset, int y_offset) const;

/**
* Gets tile graphic ID.
Expand Down
16 changes: 15 additions & 1 deletion src/game_config_game.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,13 +89,23 @@ void Game_ConfigGame::LoadFromArgs(CmdlineParser& cp) {
patch_override = true;
continue;
}
if (cp.ParseNext(arg, 0, {"--patch-easyrpg", "--no-patch-easyrpg"})) {
patch_easyrpg.Set(arg.ArgIsOn());
patch_override = true;
continue;
}
if (cp.ParseNext(arg, 0, {"--patch-dynrpg", "--no-patch-dynrpg"})) {
patch_dynrpg.Set(arg.ArgIsOn());
patch_override = true;
continue;
}
if (cp.ParseNext(arg, 0, {"--patch-maniac", "--no-patch-maniac"})) {
if (cp.ParseNext(arg, 1, {"--patch-maniac", "--no-patch-maniac"})) {
patch_maniac.Set(arg.ArgIsOn());

if (arg.ArgIsOn() && arg.ParseValue(0, li_value)) {
patch_maniac.Set(li_value);
}

patch_override = true;
continue;
}
Expand Down Expand Up @@ -170,6 +180,10 @@ void Game_ConfigGame::LoadFromStream(Filesystem_Stream::InputStream& is) {
engine_str.FromIni(ini);
fake_resolution.FromIni(ini);

if (patch_easyrpg.FromIni(ini)) {
patch_override = true;
}

if (patch_dynrpg.FromIni(ini)) {
patch_override = true;
}
Expand Down
3 changes: 2 additions & 1 deletion src/game_config_game.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ struct Game_ConfigGame {
BoolConfigParam new_game{ "Start new game", "Skips the title screen and starts a new game directly", "Game", "NewGame", false };
StringConfigParam engine_str{ "Engine", "", "Game", "Engine", std::string() };
BoolConfigParam fake_resolution{ "Fake Metrics", "Makes games run on higher resolutions (with some success)", "Game", "FakeResolution", false };
BoolConfigParam patch_easyrpg{ "EasyRPG", "EasyRPG Engine Extensions", "Patch", "EasyRPG", false };
BoolConfigParam patch_dynrpg{ "DynRPG", "", "Patch", "DynRPG", false };
BoolConfigParam patch_maniac{ "Maniac Patch", "", "Patch", "Maniac", false };
ConfigParam<int> patch_maniac{ "Maniac Patch", "", "Patch", "Maniac", 0 };
BoolConfigParam patch_common_this_event{ "Common This Event", "Support \"This Event\" in Common Events", "Patch", "CommonThisEvent", false };
BoolConfigParam patch_unlock_pics{ "Unlock Pictures", "Allow picture commands while a message is shown", "Patch", "PicUnlock", false };
BoolConfigParam patch_key_patch{ "Ineluki Key Patch", "Support \"Ineluki Key Patch\"", "Patch", "KeyPatch", false };
Expand Down
4 changes: 2 additions & 2 deletions src/game_event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,10 @@ lcf::rpg::SaveMapEvent Game_Event::GetSaveData() const {
return save;
}

Drawable::Z_t Game_Event::GetScreenZ(bool apply_shift) const {
Drawable::Z_t Game_Event::GetScreenZ(int x_offset, int y_offset) const {
// Lowest 16 bit are reserved for the ID
// See base function for full explanation
return Game_Character::GetScreenZ(apply_shift) + GetId();
return Game_Character::GetScreenZ(x_offset, y_offset) + GetId();
}

int Game_Event::GetOriginalMoveRouteIndex() const {
Expand Down
2 changes: 1 addition & 1 deletion src/game_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class Game_Event : public Game_EventBase {
* Implementation of abstract methods
*/
/** @{ */
Drawable::Z_t GetScreenZ(bool apply_shift = false) const override;
Drawable::Z_t GetScreenZ(int x_offset, int y_offset) const override;
bool Move(int dir) override;
void UpdateNextMovementAction() override;
bool IsVisible() const override;
Expand Down
4 changes: 4 additions & 0 deletions src/game_interpreter_map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,10 @@ bool Game_Interpreter_Map::CommandToggleAtbMode(lcf::rpg::EventCommand const& /*
}

bool Game_Interpreter_Map::CommandEasyRpgTriggerEventAt(lcf::rpg::EventCommand const& com) {
if (!Player::HasEasyRpgExtensions()) {
return true;
}

int x = ValueOrVariable(com.parameters[0], com.parameters[1]);
int y = ValueOrVariable(com.parameters[2], com.parameters[3]);

Expand Down
4 changes: 2 additions & 2 deletions src/game_player.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,13 @@ lcf::rpg::SavePartyLocation Game_Player::GetSaveData() const {
return *data();
}

Drawable::Z_t Game_Player::GetScreenZ(bool apply_shift) const {
Drawable::Z_t Game_Player::GetScreenZ(int x_offset, int y_offset) const {
// Player is always "same layer as hero".
// When the Player is on the same Y-coordinate as an event the Player is always rendered first.
// This is different to events where, when Y is the same, the highest X-coordinate is rendered first.
// To ensure this, fake a very high X-coordinate of 65535 (all bits set)
// See base function for full explanation of the bitmask
return Game_Character::GetScreenZ(apply_shift) | (0xFFFFu << 16u);
return Game_Character::GetScreenZ(x_offset, y_offset) | (0xFFFFu << 16u);
}

void Game_Player::ReserveTeleport(int map_id, int x, int y, int direction, TeleportTarget::Type tt) {
Expand Down
2 changes: 1 addition & 1 deletion src/game_player.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class Game_Player : public Game_PlayerBase {
* Implementation of abstract methods
*/
/** @{ */
Drawable::Z_t GetScreenZ(bool apply_shift = false) const override;
Drawable::Z_t GetScreenZ(int x_offset, int y_offset) const override;
bool IsVisible() const override;
bool MakeWay(int from_x, int from_y, int to_x, int to_y) override;
void UpdateNextMovementAction() override;
Expand Down
Loading