Commit c7099812 authored by mercury233's avatar mercury233

Merge branch 'fh' into patch-win64

parents daf3becf c3e25993
......@@ -333,9 +333,7 @@ jobs:
- name: Use premake to generate make files
run: |
./premake5 gmake \
--freetype-include-dir="/usr/include/freetype2" \
--opus-include-dir="/usr/include/opus"
./premake5 gmake
- name: Make
run: |
......@@ -426,31 +424,9 @@ jobs:
cp -r premake/* .
cp -r resource/* .
- name: Use premake to generate make files (Intel)
if: runner.arch == 'X64'
run: |
./premake5 gmake \
--cc=clang \
--freetype-include-dir="/usr/local/include/freetype2" \
--opus-include-dir="/usr/local/include/opus"
- name: Use premake to generate make files (ARM64)
if: runner.arch == 'ARM64'
run: |
./premake5 gmake \
--cc=clang \
--event-include-dir="/opt/homebrew/include" \
--event-lib-dir="/opt/homebrew/lib" \
--freetype-include-dir="/opt/homebrew/include/freetype2" \
--freetype-lib-dir="/opt/homebrew/lib" \
--sqlite-include-dir="/opt/homebrew/opt/sqlite/include" \
--sqlite-lib-dir="/opt/homebrew/opt/sqlite/lib" \
--miniaudio-include-dir="/opt/homebrew/include" \
--miniaudio-lib-dir="/opt/homebrew/lib" \
--opus-include-dir="/opt/homebrew/include/opus" \
--opus-lib-dir="/opt/homebrew/lib" \
--vorbis-include-dir="/opt/homebrew/include" \
--vorbis-lib-dir="/opt/homebrew/lib"
- name: Use premake to generate make files
run: |
DYLD_LIBRARY_PATH=$(brew --prefix)/lib ./premake5 gmake --cc=clang
- name: Make
run: |
......
......@@ -32,7 +32,7 @@ public:
* @brief Copy a C-style string to another C-style string.
* @param src The source wide string
* @param pstr The destination char string
* @param bufsize The size of the destination buffer
* @param bufsize The length of the destination buffer
* @return The length of the copied string
*/
template<typename T1, typename T2>
......@@ -62,13 +62,13 @@ public:
}
template<size_t N>
static void CopyString(const char* src, char(&dst)[N]) {
dst[0] = 0;
std::strncat(dst, src, N - 1);
std::strncpy(dst, src, N - 1);
dst[N - 1] = 0;
}
template<size_t N>
static void CopyWideString(const wchar_t* src, wchar_t(&dst)[N]) {
dst[0] = 0;
std::wcsncat(dst, src, N - 1);
std::wcsncpy(dst, src, N - 1);
dst[N - 1] = 0;
}
template<typename T>
static bool CheckUTF8Byte(const T* str, int len) {
......
......@@ -359,34 +359,21 @@ bool DeckManager::DeleteCategory(const wchar_t* name) {
return false;
return FileSystem::DeleteDir(localname);
}
bool DeckManager::SaveDeckBuffer(const int deckbuf[], const wchar_t* name) {
bool DeckManager::SaveDeckArray(const DeckArray& deck, const wchar_t* name) {
if (!FileSystem::IsDirExists(L"./deck") && !FileSystem::MakeDir(L"./deck"))
return false;
FILE* fp = OpenDeckFile(name, "w");
if (!fp)
return false;
int it = 0;
const int mainc = deckbuf[it];
++it;
std::fprintf(fp, "#created by ...\n#main\n");
for (int i = 0; i < mainc; ++i) {
std::fprintf(fp, "%d\n", deckbuf[it]);
++it;
}
const int extrac = deckbuf[it];
++it;
for (const auto& code : deck.main)
std::fprintf(fp, "%u\n", code);
std::fprintf(fp, "#extra\n");
for (int i = 0; i < extrac; ++i) {
std::fprintf(fp, "%d\n", deckbuf[it]);
++it;
}
const int sidec = deckbuf[it];
++it;
for (const auto& code : deck.extra)
std::fprintf(fp, "%u\n", code);
std::fprintf(fp, "!side\n");
for (int i = 0; i < sidec; ++i) {
std::fprintf(fp, "%d\n", deckbuf[it]);
++it;
}
for (const auto& code : deck.side)
std::fprintf(fp, "%u\n", code);
std::fclose(fp);
return true;
}
......
......@@ -35,6 +35,12 @@ struct Deck {
}
};
struct DeckArray {
std::vector<uint32_t> main;
std::vector<uint32_t> extra;
std::vector<uint32_t> side;
};
class DeckManager {
public:
Deck current_deck;
......@@ -49,7 +55,6 @@ public:
unsigned int CheckDeck(const Deck& deck, unsigned int lfhash, int rule);
bool LoadCurrentDeck(const wchar_t* file, bool is_packlist = false);
bool LoadCurrentDeck(int category_index, const wchar_t* category_name, const wchar_t* deckname);
bool SaveDeckBuffer(const int deckbuf[], const wchar_t* name);
static uint32_t LoadDeck(Deck& deck, uint32_t dbuf[], int mainc, int sidec, bool is_packlist = false);
static uint32_t LoadDeckFromStream(Deck& deck, std::istringstream& deckStream, bool is_packlist = false);
......@@ -63,6 +68,7 @@ public:
static bool CreateCategory(const wchar_t* name);
static bool RenameCategory(const wchar_t* oldname, const wchar_t* newname);
static bool DeleteCategory(const wchar_t* name);
static bool SaveDeckArray(const DeckArray& deck, const wchar_t* name);
};
extern DeckManager deckManager;
......
......@@ -1262,7 +1262,12 @@ void Game::DrawDeckBd() {
driver->draw2DRectangle(Resize(805, 160, 1020, 630), 0x400000ff, 0x400000ff, 0x40000000, 0x40000000);
driver->draw2DRectangleOutline(Resize(804, 159, 1020, 630));
}
for(int i = 0; i < 9 && i + scrFilter->getPos() < (int)deckBuilder.results.size(); ++i) {
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
constexpr int MAX_RESULT = 9;
#else
constexpr int MAX_RESULT = 7;
#endif
for(int i = 0; i < MAX_RESULT && i + scrFilter->getPos() < (int)deckBuilder.results.size(); ++i) {
code_pointer ptr = deckBuilder.results[i + scrFilter->getPos()];
if(i >= 7)
{
......
......@@ -1557,6 +1557,10 @@ void Game::ShowCardInfo(int code, bool resize) {
myswprintf(formatBuffer, L"%ls[%08d]", dataManager.GetName(code), code);
}
stName->setText(formatBuffer);
if((int)guiFont->getDimension(formatBuffer).Width > stName->getRelativePosition().getWidth() - gameConf.textfontsize)
stName->setToolTipText(formatBuffer);
else
stName->setToolTipText(nullptr);
int offset = 0;
if (is_valid && !gameConf.hide_setname) {
auto& cd = cit->second;
......@@ -2033,6 +2037,9 @@ void Game::OnResize() {
btnBigCardZoomIn->setRelativePosition(Resize(205, 140, 295, 175));
btnBigCardZoomOut->setRelativePosition(Resize(205, 180, 295, 215));
btnBigCardClose->setRelativePosition(Resize(205, 230, 295, 265));
irr::s32 barWidth = (xScale > 1) ? gameConf.textfontsize * xScale : gameConf.textfontsize;
env->getSkin()->setSize(irr::gui::EGDS_SCROLLBAR_SIZE, barWidth);
}
void Game::ResizeChatInputWindow() {
irr::s32 x = wInfos->getRelativePosition().LowerRightCorner.X + 6;
......
......@@ -33,11 +33,17 @@ int main(int argc, char* argv[]) {
#ifdef __APPLE__
CFURLRef bundle_url = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFURLRef bundle_base_url = CFURLCreateCopyDeletingLastPathComponent(nullptr, bundle_url);
CFStringRef bundle_ext = CFURLCopyPathExtension(bundle_url);
if (bundle_ext) {
char path[PATH_MAX];
if (CFStringCompare(bundle_ext, CFSTR("app"), kCFCompareCaseInsensitive) == kCFCompareEqualTo
&& CFURLGetFileSystemRepresentation(bundle_base_url, true, (UInt8*)path, PATH_MAX)) {
chdir(path);
}
CFRelease(bundle_ext);
}
CFRelease(bundle_url);
CFStringRef path = CFURLCopyFileSystemPath(bundle_base_url, kCFURLPOSIXPathStyle);
CFRelease(bundle_base_url);
chdir(CFStringGetCStringPtr(path, kCFStringEncodingUTF8));
CFRelease(path);
#endif //__APPLE__
#ifdef _WIN32
if (argc == 2 && (ygo::IsExtension(argv[1], ".ydk") || ygo::IsExtension(argv[1], ".yrp"))) { // open file from explorer
......
#include "image_manager.h"
#include "game.h"
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
#include <thread>
#endif
#ifdef _OPENMP
#include <omp.h>
#endif
namespace ygo {
......@@ -17,8 +22,10 @@ bool ImageManager::Initial() {
tUnknownFit = nullptr;
tUnknownThumb = nullptr;
tBigPicture = nullptr;
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
tLoading = nullptr;
tThumbLoadingThreadRunning = false;
#endif
tAct = driver->getTexture("textures/act.png");
tAttack = driver->getTexture("textures/attack.png");
tChain = driver->getTexture("textures/chain.png");
......@@ -59,7 +66,11 @@ void ImageManager::ClearTexture() {
driver->removeTexture(tit->second);
}
for(auto tit = tThumb.begin(); tit != tThumb.end(); ++tit) {
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
if(tit->second && tit->second != tLoading)
#else
if(tit->second)
#endif
driver->removeTexture(tit->second);
}
if(tBigPicture != nullptr) {
......@@ -69,12 +80,14 @@ void ImageManager::ClearTexture() {
tMap[0].clear();
tMap[1].clear();
tThumb.clear();
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
tThumbLoadingMutex.lock();
tThumbLoading.clear();
while(!tThumbLoadingCodes.empty())
tThumbLoadingCodes.pop();
tThumbLoadingThreadRunning = false;
tThumbLoadingMutex.unlock();
#endif
tFields.clear();
}
void ImageManager::RemoveTexture(int code) {
......@@ -110,11 +123,13 @@ void ImageManager::ResizeTexture() {
driver->removeTexture(tUnknown);
driver->removeTexture(tUnknownFit);
driver->removeTexture(tUnknownThumb);
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
driver->removeTexture(tLoading);
tLoading = GetTextureFromFile("textures/cover.jpg", imgWidthThumb, imgHeightThumb);
#endif
tUnknown = GetTextureFromFile("textures/unknown.jpg", CARD_IMG_WIDTH, CARD_IMG_HEIGHT);
tUnknownFit = GetTextureFromFile("textures/unknown.jpg", imgWidthFit, imgHeightFit);
tUnknownThumb = GetTextureFromFile("textures/unknown.jpg", imgWidthThumb, imgHeightThumb);
tLoading = GetTextureFromFile("textures/cover.jpg", imgWidthThumb, imgHeightThumb);
driver->removeTexture(tBackGround);
tBackGround = GetTextureFromFile("textures/bg.jpg", bgWidth, bgHeight);
driver->removeTexture(tBackGround_menu);
......@@ -128,25 +143,27 @@ void ImageManager::ResizeTexture() {
}
// function by Warr1024, from https://github.com/minetest/minetest/issues/2419 , modified
void imageScaleNNAA(irr::video::IImage *src, irr::video::IImage *dest) {
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
irr::u32 dy, dx;
irr::video::SColor pxl;
const irr::core::dimension2d<irr::u32> srcDim = src->getDimension();
const irr::core::dimension2d<irr::u32> destDim = dest->getDimension();
// Cache rectsngle boundaries.
double sw = src->getDimension().Width * 1.0;
double sh = src->getDimension().Height * 1.0;
// Cache scale ratios.
const double rx = (double)srcDim.Width / destDim.Width;
const double ry = (double)srcDim.Height / destDim.Height;
// Walk each destination image pixel.
// Note: loop y around x for better cache locality.
irr::core::dimension2d<irr::u32> dim = dest->getDimension();
for(dy = 0; dy < dim.Height; dy++)
for(dx = 0; dx < dim.Width; dx++) {
#pragma omp parallel
{
double sx, sy, minsx, maxsx, minsy, maxsy, area, ra, ga, ba, aa, pw, ph, pa;
irr::video::SColor pxl, npxl;
// Walk each destination image pixel.
#pragma omp for schedule(dynamic)
for(irr::s32 dy = 0; dy < destDim.Height; dy++) {
for(irr::s32 dx = 0; dx < destDim.Width; dx++) {
// Calculate floating-point source rectangle bounds.
minsx = dx * sw / dim.Width;
maxsx = minsx + sw / dim.Width;
minsy = dy * sh / dim.Height;
maxsy = minsy + sh / dim.Height;
minsx = dx * rx;
maxsx = minsx + rx;
minsy = dy * ry;
maxsy = minsy + ry;
// Total area, and integral of r, g, b values over that area,
// initialized to zero, to be summed up in next loops.
......@@ -157,9 +174,8 @@ void imageScaleNNAA(irr::video::IImage *src, irr::video::IImage *dest) {
aa = 0;
// Loop over the integral pixel positions described by those bounds.
for(sy = floor(minsy); sy < maxsy; sy++)
for(sy = floor(minsy); sy < maxsy; sy++) {
for(sx = floor(minsx); sx < maxsx; sx++) {
// Calculate width, height, then area of dest pixel
// that's covered by this source pixel.
pw = 1;
......@@ -183,21 +199,20 @@ void imageScaleNNAA(irr::video::IImage *src, irr::video::IImage *dest) {
ba += pa * pxl.getBlue();
aa += pa * pxl.getAlpha();
}
}
// Set the destination image pixel to the average color.
if(area > 0) {
pxl.setRed(ra / area + 0.5);
pxl.setGreen(ga / area + 0.5);
pxl.setBlue(ba / area + 0.5);
pxl.setAlpha(aa / area + 0.5);
npxl.set((irr::u32)(aa / area + 0.5),
(irr::u32)(ra / area + 0.5),
(irr::u32)(ga / area + 0.5),
(irr::u32)(ba / area + 0.5));
} else {
pxl.setRed(0);
pxl.setGreen(0);
pxl.setBlue(0);
pxl.setAlpha(0);
npxl.set(0);
}
dest->setPixel(dx, dy, pxl);
dest->setPixel(dx, dy, npxl);
}
}
} // end of parallel region
}
irr::video::ITexture* ImageManager::GetTextureFromFile(const char* file, irr::s32 width, irr::s32 height) {
if(mainGame->gameConf.use_image_scale) {
......@@ -283,6 +298,7 @@ irr::video::ITexture* ImageManager::GetBigPicture(int code, float zoom) {
tBigPicture = texture;
return texture;
}
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
int ImageManager::LoadThumbThread() {
while(true) {
imageManager.tThumbLoadingMutex.lock();
......@@ -338,9 +354,34 @@ int ImageManager::LoadThumbThread() {
imageManager.tThumbLoadingMutex.unlock();
return 0;
}
#endif // YGOPRO_USE_THUMB_LOAD_THREAD
irr::video::ITexture* ImageManager::GetTextureThumb(int code) {
if(code == 0)
return tUnknownThumb;
#ifndef YGOPRO_USE_THUMB_LOAD_THREAD
auto tit = tThumb.find(code);
if(tit == tThumb.end()) {
char file[256];
std::snprintf(file, sizeof file, "expansions/pics/thumbnail/%d.jpg", code);
int width = CARD_THUMB_WIDTH * mainGame->xScale;
int height = CARD_THUMB_HEIGHT * mainGame->yScale;
irr::video::ITexture* img = GetTextureFromFile(file, width, height);
if(img == NULL) {
std::snprintf(file, sizeof file, "pics/thumbnail/%d.jpg", code);
img = GetTextureFromFile(file, width, height);
}
if(img == NULL && mainGame->gameConf.use_image_scale) {
std::snprintf(file, sizeof file, "expansions/pics/%d.jpg", code);
img = GetTextureFromFile(file, width, height);
if(img == NULL) {
std::snprintf(file, sizeof file, "pics/%d.jpg", code);
img = GetTextureFromFile(file, width, height);
}
}
tThumb[code] = img;
return (img == NULL) ? tUnknownThumb : img;
}
#else // YGOPRO_USE_THUMB_LOAD_THREAD
imageManager.tThumbLoadingMutex.lock();
auto lit = tThumbLoading.find(code);
if(lit != tThumbLoading.end()) {
......@@ -368,6 +409,7 @@ irr::video::ITexture* ImageManager::GetTextureThumb(int code) {
imageManager.tThumbLoadingMutex.unlock();
return tLoading;
}
#endif // YGOPRO_USE_THUMB_LOAD_THREAD
if(tit->second)
return tit->second;
else
......
#ifndef IMAGEMANAGER_H
#define IMAGEMANAGER_H
#ifndef _OPENMP
#define YGOPRO_USE_THUMB_LOAD_THREAD
#endif
#include "config.h"
#include "data_manager.h"
#include <unordered_map>
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
#include <queue>
#include <mutex>
#endif
namespace ygo {
......@@ -21,15 +27,19 @@ public:
irr::video::ITexture* GetBigPicture(int code, float zoom);
irr::video::ITexture* GetTextureThumb(int code);
irr::video::ITexture* GetTextureField(int code);
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
static int LoadThumbThread();
#endif
std::unordered_map<int, irr::video::ITexture*> tMap[2];
std::unordered_map<int, irr::video::ITexture*> tThumb;
std::unordered_map<int, irr::video::ITexture*> tFields;
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
std::unordered_map<int, irr::video::IImage*> tThumbLoading;
std::queue<int> tThumbLoadingCodes;
std::mutex tThumbLoadingMutex;
bool tThumbLoadingThreadRunning;
#endif
irr::IrrlichtDevice* device;
irr::video::IVideoDriver* driver;
irr::video::ITexture* tCover[4];
......@@ -37,7 +47,9 @@ public:
irr::video::ITexture* tUnknownFit;
irr::video::ITexture* tUnknownThumb;
irr::video::ITexture* tBigPicture;
#ifdef YGOPRO_USE_THUMB_LOAD_THREAD
irr::video::ITexture* tLoading;
#endif
irr::video::ITexture* tAct;
irr::video::ITexture* tAttack;
irr::video::ITexture* tNegated;
......
......@@ -232,6 +232,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
break;
}
case BUTTON_LOAD_REPLAY: {
int start_turn = 1;
if(open_file) {
ReplayMode::cur_replay.OpenReplay(open_file_name);
open_file = false;
......@@ -243,6 +244,7 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
myswprintf(replay_path, L"./replay/%ls", mainGame->lstReplayList->getListItem(selected));
if (!ReplayMode::cur_replay.OpenReplay(replay_path))
break;
start_turn = std::wcstol(mainGame->ebRepStartTurn->getText(), nullptr, 10);
}
mainGame->ClearCardInfo();
mainGame->wCardImg->setVisible(true);
......@@ -257,7 +259,6 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
mainGame->dField.Clear();
mainGame->HideElement(mainGame->wReplay);
mainGame->device->setEventReceiver(&mainGame->dField);
unsigned int start_turn = std::wcstol(mainGame->ebRepStartTurn->getText(), nullptr, 10);
if(start_turn == 1)
start_turn = 0;
ReplayMode::StartReplay(start_turn);
......@@ -300,42 +301,23 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
if(selected == -1)
break;
Replay replay;
wchar_t ex_filename[256]{};
wchar_t replay_filename[256]{};
wchar_t namebuf[4][20]{};
wchar_t filename[256]{};
wchar_t replay_path[256]{};
BufferIO::CopyWideString(mainGame->lstReplayList->getListItem(selected), ex_filename);
myswprintf(replay_path, L"./replay/%ls", ex_filename);
BufferIO::CopyWideString(mainGame->lstReplayList->getListItem(selected), replay_filename);
myswprintf(replay_path, L"./replay/%ls", replay_filename);
if (!replay.OpenReplay(replay_path))
break;
const ReplayHeader& rh = replay.pheader;
if(rh.flag & REPLAY_SINGLE_MODE)
if (replay.pheader.flag & REPLAY_SINGLE_MODE)
break;
int player_count = (rh.flag & REPLAY_TAG) ? 4 : 2;
//player name
for(int i = 0; i < player_count; ++i)
replay.ReadName(namebuf[i]);
//skip pre infos
for(int i = 0; i < 4; ++i)
replay.ReadInt32();
//deck
std::vector<int> deckbuf;
for(int i = 0; i < player_count; ++i) {
deckbuf.clear();
int main = replay.ReadInt32();
deckbuf.push_back(main);
for (int j = 0; j < main; ++j) {
deckbuf.push_back(replay.ReadInt32());
}
int extra = replay.ReadInt32();
deckbuf.push_back(extra);
for (int j = 0; j < extra; ++j) {
deckbuf.push_back(replay.ReadInt32());
}
deckbuf.push_back(0);
for (size_t i = 0; i < replay.decks.size(); ++i) {
BufferIO::CopyWideString(replay.players[Replay::GetDeckPlayer(i)].c_str(), namebuf[i]);
FileSystem::SafeFileName(namebuf[i]);
myswprintf(filename, L"deck/%ls-%d %ls.ydk", ex_filename, i + 1, namebuf[i]);
deckManager.SaveDeckBuffer(deckbuf.data(), filename);
}
for (size_t i = 0; i < replay.decks.size(); ++i) {
myswprintf(filename, L"./deck/%ls-%d %ls.ydk", replay_filename, i + 1, namebuf[i]);
DeckManager::SaveDeckArray(replay.decks[i], filename);
}
mainGame->stACMessage->setText(dataManager.GetSysString(1335));
mainGame->PopupElement(mainGame->wACMessage, 20);
......@@ -545,30 +527,30 @@ bool MenuHandler::OnEvent(const irr::SEvent& event) {
break;
wchar_t replay_path[256]{};
myswprintf(replay_path, L"./replay/%ls", mainGame->lstReplayList->getListItem(sel));
if (!ReplayMode::cur_replay.OpenReplay(replay_path)) {
mainGame->stReplayInfo->setText(L"");
if (!temp_replay.OpenReplay(replay_path)) {
mainGame->stReplayInfo->setText(L"Error");
break;
}
wchar_t infobuf[256]{};
std::wstring repinfo;
time_t curtime;
if(ReplayMode::cur_replay.pheader.flag & REPLAY_UNIFORM)
curtime = ReplayMode::cur_replay.pheader.start_time;
if(temp_replay.pheader.flag & REPLAY_UNIFORM)
curtime = temp_replay.pheader.start_time;
else
curtime = ReplayMode::cur_replay.pheader.seed;
curtime = temp_replay.pheader.seed;
std::wcsftime(infobuf, sizeof infobuf / sizeof infobuf[0], L"%Y/%m/%d %H:%M:%S\n", std::localtime(&curtime));
repinfo.append(infobuf);
wchar_t namebuf[4][20]{};
ReplayMode::cur_replay.ReadName(namebuf[0]);
ReplayMode::cur_replay.ReadName(namebuf[1]);
if(ReplayMode::cur_replay.pheader.flag & REPLAY_TAG) {
ReplayMode::cur_replay.ReadName(namebuf[2]);
ReplayMode::cur_replay.ReadName(namebuf[3]);
if (temp_replay.pheader.flag & REPLAY_SINGLE_MODE) {
wchar_t path[256]{};
BufferIO::DecodeUTF8(temp_replay.script_name.c_str(), path);
repinfo.append(path);
repinfo.append(L"\n");
}
if(ReplayMode::cur_replay.pheader.flag & REPLAY_TAG)
myswprintf(infobuf, L"%ls\n%ls\n===VS===\n%ls\n%ls\n", namebuf[0], namebuf[1], namebuf[2], namebuf[3]);
const auto& player_names = temp_replay.players;
if(temp_replay.pheader.flag & REPLAY_TAG)
myswprintf(infobuf, L"%ls\n%ls\n===VS===\n%ls\n%ls\n", player_names[0].c_str(), player_names[1].c_str(), player_names[2].c_str(), player_names[3].c_str());
else
myswprintf(infobuf, L"%ls\n===VS===\n%ls\n", namebuf[0], namebuf[1]);
myswprintf(infobuf, L"%ls\n===VS===\n%ls\n", player_names[0].c_str(), player_names[1].c_str());
repinfo.append(infobuf);
mainGame->ebRepStartTurn->setText(L"1");
mainGame->SetStaticText(mainGame->stReplayInfo, 180, mainGame->guiFont, repinfo.c_str());
......
......@@ -2,6 +2,7 @@
#define MENU_HANDLER_H
#include <irrlicht.h>
#include "replay.h"
namespace ygo {
......@@ -10,7 +11,7 @@ public:
bool OnEvent(const irr::SEvent& event) override;
irr::s32 prev_operation{ 0 };
int prev_sel{ -1 };
Replay temp_replay;
};
}
......
......@@ -5,6 +5,7 @@ project "YGOPro"
kind "WindowedApp"
cppdialect "C++14"
rtti "Off"
openmp "On"
files { "*.cpp", "*.h" }
includedirs { "../ocgcore" }
......@@ -49,7 +50,7 @@ project "YGOPro"
includedirs { "../miniaudio/extras/decoders/libopus", "../miniaudio/extras/decoders/libvorbis" }
if not MINIAUDIO_BUILD_OPUS_VORBIS then
links { "opusfile", "vorbisfile", "opus", "vorbis", "ogg" }
libdirs { OPUS_LIB_DIR, VORBIS_LIB_DIR, OGG_LIBDIR }
libdirs { OPUS_LIB_DIR, OPUSFILE_LIB_DIR, VORBIS_LIB_DIR, OGG_LIB_DIR }
end
end
end
......@@ -83,6 +84,7 @@ project "YGOPro"
filter "not system:windows"
links { "event_pthreads", "dl", "pthread" }
filter "system:macosx"
openmp "Off"
links { "z" }
defines { "GL_SILENCE_DEPRECATION" }
if MAC_ARM then
......@@ -94,6 +96,7 @@ project "YGOPro"
end
filter "system:linux"
links { "GL", "X11", "Xxf86vm" }
linkoptions { "-fopenmp" }
if USE_AUDIO and AUDIO_LIB == "irrklang" then
links { "IrrKlang" }
linkoptions{ IRRKLANG_LINK_RPATH }
......
#include "replay.h"
#include "myfilesystem.h"
#include "network.h"
#include "lzma/LzmaLib.h"
namespace ygo {
......@@ -28,9 +29,7 @@ void Replay::BeginRecord() {
if(!fp)
return;
#endif
replay_size = 0;
comp_size = 0;
is_replaying = false;
Reset();
is_recording = true;
}
void Replay::WriteHeader(ReplayHeader& header) {
......@@ -111,11 +110,7 @@ bool Replay::OpenReplay(const wchar_t* name) {
if(!rfp)
return false;
data_position = 0;
is_recording = false;
is_replaying = false;
replay_size = 0;
comp_size = 0;
Reset();
if(std::fread(&pheader, sizeof pheader, 1, rfp) < 1) {
std::fclose(rfp);
return false;
......@@ -138,6 +133,13 @@ bool Replay::OpenReplay(const wchar_t* name) {
comp_size = 0;
}
is_replaying = true;
can_read = true;
if (!ReadInfo()) {
Reset();
return false;
}
info_offset = data_position;
data_position = 0;
return true;
}
bool Replay::CheckReplay(const wchar_t* name) {
......@@ -177,10 +179,6 @@ bool Replay::ReadNextResponse(unsigned char resp[]) {
unsigned char len{};
if (!ReadData(&len, sizeof len))
return false;
if (len > SIZE_RETURN_VALUE) {
is_replaying = false;
return false;
}
if (!ReadData(resp, len))
return false;
return true;
......@@ -197,10 +195,10 @@ void Replay::ReadHeader(ReplayHeader& header) {
header = pheader;
}
bool Replay::ReadData(void* data, size_t length) {
if(!is_replaying)
if (!is_replaying || !can_read)
return false;
if (data_position + length > replay_size) {
is_replaying = false;
can_read = false;
return false;
}
if (length)
......@@ -213,6 +211,77 @@ int32_t Replay::ReadInt32() {
}
void Replay::Rewind() {
data_position = 0;
can_read = true;
}
void Replay::Reset() {
is_recording = false;
is_replaying = false;
can_read = false;
replay_size = 0;
comp_size = 0;
data_position = 0;
info_offset = 0;
players.clear();
params = { 0 };
decks.clear();
script_name.clear();
}
void Replay::SkipInfo(){
if (data_position == 0)
data_position += info_offset;
}
bool Replay::IsReplaying() const {
return is_replaying;
}
bool Replay::ReadInfo() {
int player_count = (pheader.flag & REPLAY_TAG) ? 4 : 2;
for (int i = 0; i < player_count; ++i) {
wchar_t name[20]{};
if (!ReadName(name))
return false;
players.push_back(name);
}
if (!ReadData(&params, sizeof params))
return false;
bool is_tag1 = pheader.flag & REPLAY_TAG;
bool is_tag2 = params.duel_flag & DUEL_TAG_MODE;
if (is_tag1 != is_tag2)
return false;
if (pheader.flag & REPLAY_SINGLE_MODE) {
uint16_t slen = Read<uint16_t>();
char filename[256]{};
if (slen == 0 || slen > sizeof(filename) - 1)
return false;
if (!ReadData(filename, slen))
return false;
filename[slen] = 0;
if (std::strncmp(filename, "./single/", 9))
return false;
script_name = filename + 9;
if (script_name.find_first_of(R"(/\)") != std::string::npos)
return false;
}
else {
for (int p = 0; p < player_count; ++p) {
DeckArray deck;
uint32_t main = Read<uint32_t>();
if (main > MAINC_MAX)
return false;
if (main)
deck.main.resize(main);
if (!ReadData(deck.main.data(), main * sizeof(uint32_t)))
return false;
uint32_t extra = Read<uint32_t>();
if (extra > MAINC_MAX)
return false;
if (extra)
deck.extra.resize(extra);
if (!ReadData(deck.extra.data(), extra * sizeof(uint32_t)))
return false;
decks.push_back(deck);
}
}
return true;
}
}
......@@ -2,6 +2,7 @@
#define REPLAY_H
#include "config.h"
#include "deck_manager.h"
namespace ygo {
......@@ -13,7 +14,7 @@ namespace ygo {
#define REPLAY_UNIFORM 0x10
// max size
constexpr int MAX_REPLAY_SIZE = 0x20000;
constexpr int MAX_REPLAY_SIZE = 0x80000;
constexpr int MAX_COMP_SIZE = UINT16_MAX + 1;
struct ReplayHeader {
......@@ -26,6 +27,13 @@ struct ReplayHeader {
uint8_t props[8]{};
};
struct DuelParameters {
int32_t start_lp{};
int32_t start_hand{};
int32_t draw_count{};
uint32_t duel_flag{};
};
class Replay {
public:
Replay();
......@@ -45,10 +53,20 @@ public:
void SaveReplay(const wchar_t* name);
// play
bool OpenReplay(const wchar_t* name);
static bool CheckReplay(const wchar_t* name);
static bool DeleteReplay(const wchar_t* name);
static bool RenameReplay(const wchar_t* oldname, const wchar_t* newname);
static size_t GetDeckPlayer(size_t deck_index) {
switch (deck_index) {
case 2:
return 3;
case 3:
return 2;
default:
return deck_index;
}
}
bool OpenReplay(const wchar_t* name);
bool ReadNextResponse(unsigned char resp[]);
bool ReadName(wchar_t* data);
void ReadHeader(ReplayHeader& header);
......@@ -61,6 +79,9 @@ public:
}
int32_t ReadInt32();
void Rewind();
void Reset();
void SkipInfo();
bool IsReplaying() const;
FILE* fp{ nullptr };
#ifdef _WIN32
......@@ -71,12 +92,22 @@ public:
unsigned char* comp_data;
size_t comp_size{};
std::vector<std::wstring> players; // 80 or 160 bytes
DuelParameters params; // 16 bytes
std::vector<DeckArray> decks; // 4 bytes, main deck, 4 bytes, extra deck
std::string script_name; // 2 bytes, script name (max: 256 bytes)
private:
bool ReadInfo();
unsigned char* replay_data;
size_t replay_size{};
size_t data_position{};
size_t info_offset{};
bool is_recording{};
bool is_replaying{};
bool can_read{};
};
}
......
......@@ -158,89 +158,65 @@ bool ReplayMode::StartDuel() {
const ReplayHeader& rh = cur_replay.pheader;
unsigned int seed = rh.seed;
std::mt19937 rnd(seed);
if(mainGame->dInfo.isTag) {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.hostname_tag);
cur_replay.ReadName(mainGame->dInfo.clientname_tag);
cur_replay.ReadName(mainGame->dInfo.clientname);
cur_replay.SkipInfo();
if(rh.flag & REPLAY_TAG) {
BufferIO::CopyWideString(cur_replay.players[0].c_str(), mainGame->dInfo.hostname);
BufferIO::CopyWideString(cur_replay.players[1].c_str(), mainGame->dInfo.hostname_tag);
BufferIO::CopyWideString(cur_replay.players[2].c_str(), mainGame->dInfo.clientname_tag);
BufferIO::CopyWideString(cur_replay.players[3].c_str(), mainGame->dInfo.clientname);
} else {
cur_replay.ReadName(mainGame->dInfo.hostname);
cur_replay.ReadName(mainGame->dInfo.clientname);
BufferIO::CopyWideString(cur_replay.players[0].c_str(), mainGame->dInfo.hostname);
BufferIO::CopyWideString(cur_replay.players[1].c_str(), mainGame->dInfo.clientname);
}
pduel = create_duel(rnd());
int start_lp = cur_replay.ReadInt32();
int start_hand = cur_replay.ReadInt32();
int draw_count = cur_replay.ReadInt32();
int opt = cur_replay.ReadInt32();
int duel_rule = opt >> 16;
mainGame->dInfo.duel_rule = duel_rule;
set_player_info(pduel, 0, start_lp, start_hand, draw_count);
set_player_info(pduel, 1, start_lp, start_hand, draw_count);
mainGame->dInfo.lp[0] = start_lp;
mainGame->dInfo.lp[1] = start_lp;
mainGame->dInfo.start_lp = start_lp;
mainGame->dInfo.duel_rule = cur_replay.params.duel_flag >> 16;
set_player_info(pduel, 0, cur_replay.params.start_lp, cur_replay.params.start_hand, cur_replay.params.draw_count);
set_player_info(pduel, 1, cur_replay.params.start_lp, cur_replay.params.start_hand, cur_replay.params.draw_count);
mainGame->dInfo.lp[0] = cur_replay.params.start_lp;
mainGame->dInfo.lp[1] = cur_replay.params.start_lp;
mainGame->dInfo.start_lp = cur_replay.params.start_lp;
myswprintf(mainGame->dInfo.strLP[0], L"%d", mainGame->dInfo.lp[0]);
myswprintf(mainGame->dInfo.strLP[1], L"%d", mainGame->dInfo.lp[1]);
mainGame->dInfo.turn = 0;
if(!mainGame->dInfo.isSingleMode) {
if(!(opt & DUEL_TAG_MODE)) {
int main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
int extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(0), main, extra);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(1), main, extra);
if(!(rh.flag & REPLAY_SINGLE_MODE)) {
if(!(rh.flag & REPLAY_TAG)) {
for (int i = 0; i < 2; ++i) {
for (const auto& code : cur_replay.decks[i].main)
new_card(pduel, code, i, i, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
for (const auto& code : cur_replay.decks[i].extra)
new_card(pduel, code, i, i, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(i), cur_replay.decks[i].main.size(), cur_replay.decks[i].extra.size());
}
} else {
int main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
int extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(0), main, extra);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 0, LOCATION_DECK);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 0, LOCATION_EXTRA);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_card(pduel, cur_replay.ReadInt32(), 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(1), main, extra);
main = cur_replay.ReadInt32();
for(int i = 0; i < main; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 1, LOCATION_DECK);
extra = cur_replay.ReadInt32();
for(int i = 0; i < extra; ++i)
new_tag_card(pduel, cur_replay.ReadInt32(), 1, LOCATION_EXTRA);
for (const auto& code : cur_replay.decks[0].main)
new_card(pduel, code, 0, 0, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
for (const auto& code : cur_replay.decks[0].extra)
new_card(pduel, code, 0, 0, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(0), cur_replay.decks[0].main.size(), cur_replay.decks[0].extra.size());
for (const auto& code : cur_replay.decks[1].main)
new_tag_card(pduel, code, 0, LOCATION_DECK);
for (const auto& code : cur_replay.decks[1].extra)
new_tag_card(pduel, code, 0, LOCATION_EXTRA);
for (const auto& code : cur_replay.decks[2].main)
new_card(pduel, code, 1, 1, LOCATION_DECK, 0, POS_FACEDOWN_DEFENSE);
for (const auto& code : cur_replay.decks[2].extra)
new_card(pduel, code, 1, 1, LOCATION_EXTRA, 0, POS_FACEDOWN_DEFENSE);
mainGame->dField.Initial(mainGame->LocalPlayer(1), cur_replay.decks[2].main.size(), cur_replay.decks[2].extra.size());
for (const auto& code : cur_replay.decks[3].main)
new_tag_card(pduel, code, 1, LOCATION_DECK);
for (const auto& code : cur_replay.decks[3].extra)
new_tag_card(pduel, code, 1, LOCATION_EXTRA);
}
} else {
char filename[256];
auto slen = cur_replay.Read<uint16_t>();
if (slen > sizeof(filename) - 1) {
return false;
}
cur_replay.ReadData(filename, slen);
filename[slen] = 0;
char filename[256]{};
std::snprintf(filename, sizeof filename, "./single/%s", cur_replay.script_name.c_str());
if(!preload_script(pduel, filename)) {
return false;
}
}
if (!(rh.flag & REPLAY_UNIFORM))
opt |= DUEL_OLD_REPLAY;
start_duel(pduel, opt);
cur_replay.params.duel_flag |= DUEL_OLD_REPLAY;
start_duel(pduel, cur_replay.params.duel_flag);
return true;
}
void ReplayMode::EndDuel() {
......@@ -848,12 +824,12 @@ bool ReplayMode::ReplayAnalyze(unsigned char* msg, unsigned int len) {
break;
}
case MSG_AI_NAME: {
int len = BufferIO::ReadInt16(pbuf);
int len = buffer_read<uint16_t>(pbuf);
pbuf += len + 1;
break;
}
case MSG_SHOW_HINT: {
int len = BufferIO::ReadInt16(pbuf);
int len = buffer_read<uint16_t>(pbuf);
pbuf += len + 1;
break;
}
......
......@@ -25,7 +25,6 @@ private:
public:
static Replay cur_replay;
public:
static bool StartReplay(int skipturn);
static void StopReplay(bool is_exiting = false);
static void SwapField();
......
......@@ -749,21 +749,25 @@ bool SingleMode::SinglePlayAnalyze(unsigned char* msg, unsigned int len) {
case MSG_AI_NAME: {
char namebuf[128]{};
wchar_t wname[20]{};
int len = BufferIO::ReadInt16(pbuf);
auto begin = pbuf;
pbuf += len + 1;
std::memcpy(namebuf, begin, len + 1);
int name_len = buffer_read<uint16_t>(pbuf);
if (name_len + 1 <= (int)sizeof namebuf) {
std::memcpy(namebuf, pbuf, name_len);
namebuf[name_len] = 0;
}
pbuf += name_len + 1;
BufferIO::DecodeUTF8(namebuf, wname);
BufferIO::CopyCharArray(wname, mainGame->dInfo.clientname);
break;
}
case MSG_SHOW_HINT: {
char msgbuf[1024];
wchar_t msg[1024];
int len = BufferIO::ReadInt16(pbuf);
auto begin = pbuf;
pbuf += len + 1;
std::memcpy(msgbuf, begin, len + 1);
char msgbuf[1024]{};
wchar_t msg[1024]{};
int msg_len = buffer_read<uint16_t>(pbuf);
if (msg_len + 1 <= (int)sizeof msgbuf) {
std::memcpy(msgbuf, pbuf, msg_len);
msgbuf[msg_len] = 0;
}
pbuf += msg_len + 1;
BufferIO::DecodeUTF8(msgbuf, msg);
mainGame->gMutex.lock();
mainGame->SetStaticText(mainGame->stMessage, 310, mainGame->guiFont, msg);
......
......@@ -16,6 +16,7 @@ project "irrlicht"
"_IRR_STATIC_LIB_",
"NO_IRR_USE_NON_SYSTEM_BZLIB_",
"NO_IRR_COMPILE_WITH_BZIP2_",
"NO_IRR_COMPILE_WITH_LZMA_",
"NO_IRR_COMPILE_WITH_CONSOLE_DEVICE_",
"NO_IRR_COMPILE_WITH_DIRECT3D_8_",
"NO_IRR_COMPILE_WITH_DIRECTINPUT_JOYSTICK_",
......
......@@ -123,7 +123,7 @@ project "miniaudio"
"OPUS_HAVE_RTCD", "OPUS_X86_MAY_HAVE_SSE", "OPUS_X86_MAY_HAVE_SSE4_1", "OPUS_X86_MAY_HAVE_AVX2",
}
else
includedirs { OPUS_INCLUDE_DIR, VORBIS_INCLUDE_DIR, OGG_INCLUDE_DIR }
includedirs { OPUS_INCLUDE_DIR, OPUSFILE_INCLUDE_DIR, VORBIS_INCLUDE_DIR, OGG_INCLUDE_DIR }
end
end
......
......@@ -48,14 +48,14 @@ newoption { trigger = "no-dxsdk", category = "YGOPro - irrlicht", description =
newoption { trigger = "no-audio", category = "YGOPro", description = "" }
newoption { trigger = "audio-lib", category = "YGOPro", description = "", value = "miniaudio, irrklang", default = AUDIO_LIB }
newoption { trigger = "miniaudio-include-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "miniaudio-lib-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "miniaudio-support-opus-vorbis", category = "YGOPro - miniaudio", description = "" }
newoption { trigger = "no-miniaudio-support-opus-vorbis", category = "YGOPro - miniaudio", description = "" }
newoption { trigger = "build-opus-vorbis", category = "YGOPro - miniaudio", description = "" }
newoption { trigger = "no-build-opus-vorbis", category = "YGOPro - miniaudio", description = "" }
newoption { trigger = "opus-include-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "opus-lib-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "opusfile-include-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "opusfile-lib-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "vorbis-include-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "vorbis-lib-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
newoption { trigger = "ogg-include-dir", category = "YGOPro - miniaudio", description = "", value = "PATH" }
......@@ -79,6 +79,14 @@ function GetParam(param)
return _OPTIONS[param] or os.getenv(string.upper(string.gsub(param,"-","_")))
end
function FindHeaderWithSubDir(header, subdir)
local result = os.findheader(header)
if result and subdir then
result = path.join(result, subdir)
end
return result
end
if GetParam("build-lua") then
BUILD_LUA = true
elseif GetParam("no-build-lua") then
......@@ -88,7 +96,7 @@ if not BUILD_LUA then
-- at most times you need to change this if you change BUILD_LUA to false
-- make sure your lua lib is built with C++ and version >= 5.3
LUA_LIB_NAME = GetParam("lua-lib-name")
LUA_INCLUDE_DIR = GetParam("lua-include-dir") or os.findheader(LUA_LIB_NAME)
LUA_INCLUDE_DIR = GetParam("lua-include-dir") or os.findheader("lua.h")
LUA_LIB_DIR = GetParam("lua-lib-dir") or os.findlib(LUA_LIB_NAME)
end
......@@ -98,7 +106,7 @@ elseif GetParam("no-build-event") then
BUILD_EVENT = false
end
if not BUILD_EVENT then
EVENT_INCLUDE_DIR = GetParam("event-include-dir") or os.findheader("event")
EVENT_INCLUDE_DIR = GetParam("event-include-dir") or os.findheader("event2/event.h")
EVENT_LIB_DIR = GetParam("event-lib-dir") or os.findlib("event")
end
......@@ -108,7 +116,7 @@ elseif GetParam("no-build-freetype") then
BUILD_FREETYPE = false
end
if not BUILD_FREETYPE then
FREETYPE_INCLUDE_DIR = GetParam("freetype-include-dir") or os.findheader("freetype")
FREETYPE_INCLUDE_DIR = GetParam("freetype-include-dir") or FindHeaderWithSubDir("freetype2/ft2build.h", "freetype2")
FREETYPE_LIB_DIR = GetParam("freetype-lib-dir") or os.findlib("freetype")
end
......@@ -118,7 +126,7 @@ elseif GetParam("no-build-sqlite") then
BUILD_SQLITE = false
end
if not BUILD_SQLITE then
SQLITE_INCLUDE_DIR = GetParam("sqlite-include-dir") or os.findheader("sqlite3")
SQLITE_INCLUDE_DIR = GetParam("sqlite-include-dir") or os.findheader("sqlite3.h")
SQLITE_LIB_DIR = GetParam("sqlite-lib-dir") or os.findlib("sqlite3")
end
......@@ -128,7 +136,7 @@ elseif GetParam("no-build-irrlicht") then
BUILD_IRRLICHT = false
end
if not BUILD_IRRLICHT then
IRRLICHT_INCLUDE_DIR = GetParam("irrlicht-include-dir") or os.findheader("irrlicht")
IRRLICHT_INCLUDE_DIR = GetParam("irrlicht-include-dir") or os.findheader("irrlicht.h")
IRRLICHT_LIB_DIR = GetParam("irrlicht-lib-dir") or os.findlib("irrlicht")
end
......@@ -175,12 +183,14 @@ if USE_AUDIO then
MINIAUDIO_BUILD_OPUS_VORBIS = true
end
if not MINIAUDIO_BUILD_OPUS_VORBIS then
OPUS_INCLUDE_DIR = GetParam("opus-include-dir") or os.findheader("opus")
OPUS_LIB_DIR = GetParam("opus-lib-dir") or os.findlib("opusfile")
VORBIS_INCLUDE_DIR = GetParam("vorbis-include-dir") or os.findheader("vorbis")
OPUS_INCLUDE_DIR = GetParam("opus-include-dir") or FindHeaderWithSubDir("opus/opus.h", "opus")
OPUS_LIB_DIR = GetParam("opus-lib-dir") or os.findlib("opus")
OPUSFILE_INCLUDE_DIR = GetParam("opusfile-include-dir") or FindHeaderWithSubDir("opus/opusfile.h", "opus")
OPUSFILE_LIB_DIR = GetParam("opusfile-lib-dir") or os.findlib("opusfile")
VORBIS_INCLUDE_DIR = GetParam("vorbis-include-dir") or os.findheader("vorbis/vorbisfile.h")
VORBIS_LIB_DIR = GetParam("vorbis-lib-dir") or os.findlib("vorbis")
OGG_INCLUDE_DIR = GetParam("ogg-include-dir") or os.findheader("ogg")
OCG_LIB_DIR = GetParam("ogg-lib-dir") or os.findlib("ogg")
OGG_INCLUDE_DIR = GetParam("ogg-include-dir") or os.findheader("ogg/ogg.h")
OGG_LIB_DIR = GetParam("ogg-lib-dir") or os.findlib("ogg")
end
end
elseif AUDIO_LIB == "irrklang" then
......
......@@ -663,6 +663,7 @@
!counter 0x106b 狂爱指示物
!counter 0x6c 访问指示物
!counter 0x6d 祝台指示物
!counter 0x6e 四季指示物
#setnames, using tab for comment
!setname 0x1 正义盟军 AOJ
!setname 0x2 次世代 ジェネクス
......@@ -1245,7 +1246,7 @@
!setname 0x1c0 龙华 竜華
!setname 0x1c1 阿尔戈☆群星 ARGS
!setname 0x1c2 喷水引擎 アクア・ジェット
!setname 0x1c3 Mitsurugi
!setname 0x1c3 Mitsurugi
!setname 0x1c4 征龙 征竜
!setname 0x1c5 再世 再世
!setname 0x1c6 统王 ドミナス
......@@ -1254,3 +1255,6 @@
!setname 0x1c9 星辰 ドラゴンテイル
!setname 0x1ca 味美喵 ヤミー
!setname 0x1cb K9
!setname 0x1cc 瞬间移动 テレポート
!setname 0x1cd 神艺 アルトメギア
!setname 0x1ce 狱神 獄神
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment