mirror of https://github.com/OpenRCT2/OpenRCT2.git
Linux platform file
Add bulk of the platform file for linux, change the compilation target from shared library to executable for linux, provide necessary changes to make it compile & load the stub of a process. Make sure functions are marked as stubs where needed, and implementation is expected.
This commit is contained in:
parent
46a4b47715
commit
4ce0e3a8b2
|
@ -36,8 +36,8 @@ if (DISABLE_NETWORK)
|
|||
add_definitions(-DDISABLE_NETWORK)
|
||||
endif (DISABLE_NETWORK)
|
||||
|
||||
set(ORCTLIBS_INCLUDE /usr/local/cross-tools/orctlibs/include)
|
||||
set(JANSSON_INCLUDE /usr/local/cross-tools/orctlibs/include/jansson)
|
||||
set(ORCTLIBS_INCLUDE /usr/local/cross-tools/orctlibs/include)
|
||||
set(JANSSON_INCLUDE /usr/local/cross-tools/orctlibs/include/jansson)
|
||||
set(ORCTLIBS_LIB_DIR /usr/local/cross-tools/orctlibs/lib)
|
||||
set(ORCTLIBS_LIB jansson curl ssl crypto)
|
||||
|
||||
|
@ -50,8 +50,8 @@ file(GLOB_RECURSE ORCT2_SOURCES "src/*.c" "src/*.cpp" "lib/*.c")
|
|||
|
||||
if (UNIX)
|
||||
# force 32bit build for now and set necessary flags to compile code as is
|
||||
set(CMAKE_C_FLAGS "-m32 -masm=intel -std=gnu99")
|
||||
set(CMAKE_CXX_FLAGS "-m32 -std=gnu++11 -masm=intel")
|
||||
set(CMAKE_C_FLAGS "-m32 -masm=intel -fvar-tracking-assignments -std=gnu99")
|
||||
set(CMAKE_CXX_FLAGS "-m32 -std=gnu++11 -fvar-tracking-assignments -masm=intel")
|
||||
set(LIB32 /usr/lib32)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "-m32 -Wl,-melf_i386 -L${LIB32} -lSDL2_ttf")
|
||||
set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS})
|
||||
|
@ -62,11 +62,15 @@ if (UNIX)
|
|||
INCLUDE_DIRECTORIES(${SDL2_INCLUDE_DIRS})
|
||||
endif (UNIX)
|
||||
|
||||
INCLUDE_DIRECTORIES(${ORCTLIBS_INCLUDE} ${JANSSON_INCLUDE})
|
||||
LINK_DIRECTORIES(${SDL2_LIBRARY_DIRS} ${ORCTLIBS_LIB_DIR})
|
||||
if (WIN32)
|
||||
# build as library for now, replace with add_executable
|
||||
add_library(${PROJECT} SHARED ${ORCT2_SOURCES})
|
||||
else (WIN32)
|
||||
add_executable(${PROJECT} ${ORCT2_SOURCES})
|
||||
endif (WIN32)
|
||||
|
||||
# build as library for now, replace with add_executable
|
||||
add_library(${PROJECT} SHARED ${ORCT2_SOURCES})
|
||||
INCLUDE_DIRECTORIES(${ORCTLIBS_INCLUDE} ${JANSSON_INCLUDE})
|
||||
LINK_DIRECTORIES(${LINK_DIRECTORIES} ${LIB32} ${SDL2_LIBRARY_DIRS} ${ORCTLIBS_LIB_DIR})
|
||||
|
||||
# install into ${CMAKE_INSTALL_PREFIX}/bin/
|
||||
#install (TARGETS ${PROJECT} DESTINATION bin)
|
||||
|
@ -79,4 +83,3 @@ TARGET_LINK_LIBRARIES(${PROJECT} ${SDL2_LIBRARIES} ${ORCTLIBS_LIB})
|
|||
if (WIN32)
|
||||
target_link_libraries(${PROJECT} winmm.lib -limm32 -lversion -ldsound ws2_32)
|
||||
endif (WIN32)
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ elif [[ `uname` == "Linux" ]]; then
|
|||
apt-cache search libsdl2
|
||||
apt-cache policy libsdl2-dev:i386
|
||||
apt-cache policy libsdl2-dev
|
||||
sudo apt-get install -y --force-yes binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686 cmake libsdl2-dev:i386 libsdl2-ttf-dev:i386 gcc-4.8 pkg-config:i386 g++-4.8-multilib gcc-4.8-multilib libjansson-dev:i386 libspeex-dev:i386 libspeexdsp-dev:i386
|
||||
sudo apt-get install -y --force-yes binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686 cmake libsdl2-dev:i386 libsdl2-ttf-dev:i386 gcc-4.8 pkg-config:i386 g++-4.8-multilib gcc-4.8-multilib libjansson-dev:i386 libspeex-dev:i386 libspeexdsp-dev:i386 libcurl4-openssl-dev:i386 libcrypto++-dev:i386
|
||||
export CC=gcc-4.8
|
||||
export CXX=g++-4.8
|
||||
fi
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
@ -556,7 +556,8 @@ int sound_channel_load_file2(int channel, const char* filename, int offset)
|
|||
if (sound_channel_is_playing(channel)) {
|
||||
sound_channel_stop(channel);
|
||||
}
|
||||
if (SUCCEEDED(sound_channel_load_file(channel, filename, offset))) {
|
||||
int load_result = sound_channel_load_file(channel, filename, offset);
|
||||
if (load_result >= 0) {
|
||||
RCT2_ADDRESS(RCT2_ADDRESS_SOUND_CHANNEL_LIST, rct_sound_channel)[channel].var_4 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
@ -961,7 +962,7 @@ int sound_play(rct_sound* sound, int looping, int volume, int pan, int frequency
|
|||
} else {
|
||||
playflags = 0;
|
||||
}
|
||||
if (SUCCEEDED(sound->dsbuffer->lpVtbl->Play(sound->dsbuffer, 0, 0, playflags)))
|
||||
if (SUCCEEDED(sound->dsbuffer->lpVtbl->Play(sound->dsbuffer, 0, 0, playflags)))
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
@ -1497,7 +1498,7 @@ int dsound_create_primary_buffer(int a, int device, int channels, int samples, i
|
|||
if (FAILED(DirectSoundCreate(&dsdevice->guid, &RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), 0))) {
|
||||
return 0;
|
||||
}
|
||||
if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), windows_get_window_handle(), DSSCL_NORMAL)) ||
|
||||
if (FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->SetCooperativeLevel(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), windows_get_window_handle(), DSSCL_NORMAL)) ||
|
||||
FAILED(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->CreateSoundBuffer(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND), &bufferdesc, &RCT2_GLOBAL(0x009E2BA8, LPDIRECTSOUNDBUFFER), 0))) {
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND)->lpVtbl->Release(RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND));
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_DIRECTSOUND, LPDIRECTSOUND) = 0;
|
||||
|
|
|
@ -79,4 +79,4 @@ void diagnostic_log_with_location(int diagnosticLevel, const char *file, const c
|
|||
|
||||
// Line terminator
|
||||
fprintf(stream, "\n");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,4 +57,4 @@ void diagnostic_log_with_location(int diagnosticLevel, const char *file, const c
|
|||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
@ -22,6 +22,7 @@
|
|||
#include "../localisation/localisation.h"
|
||||
#include "../sprites.h"
|
||||
#include "../world/map.h"
|
||||
#include "../platform/platform.h"
|
||||
#include "drawing.h"
|
||||
|
||||
static int ttf_get_string_width(const utf8 *text);
|
||||
|
@ -353,7 +354,7 @@ void gfx_draw_string_centred(rct_drawpixelinfo *dpi, int format, int x, int y, i
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006C1E53
|
||||
* dpi (edi)
|
||||
* args (esi)
|
||||
|
@ -407,7 +408,7 @@ int gfx_draw_string_centred_wrapped(rct_drawpixelinfo *dpi, void *args, int x, i
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006C2105
|
||||
* dpi (edi)
|
||||
* args (esi)
|
||||
|
@ -441,7 +442,7 @@ int gfx_draw_string_left_wrapped(rct_drawpixelinfo *dpi, void *args, int x, int
|
|||
gfx_draw_string(dpi, buffer, 0xFE, x, lineY);
|
||||
buffer = get_string_end(buffer) + 1;
|
||||
lineY += lineHeight;
|
||||
}
|
||||
}
|
||||
return lineY - y;
|
||||
}
|
||||
|
||||
|
@ -492,7 +493,7 @@ void colour_char(uint8 colour, uint16* current_font_flags, uint8* palette_pointe
|
|||
if (!(*current_font_flags & 2)) {
|
||||
eax = eax & 0x0FF0000FF;
|
||||
}
|
||||
// Adjust text palette. Store current colour?
|
||||
// Adjust text palette. Store current colour?
|
||||
palette_pointer[1] = eax & 0xFF;
|
||||
palette_pointer[2] = (eax >> 8) & 0xFF;
|
||||
palette_pointer[3] = (eax >> 16) & 0xFF;
|
||||
|
@ -512,7 +513,7 @@ void colour_char_window(uint8 colour, uint16* current_font_flags,uint8* palette_
|
|||
if (*current_font_flags & 2) {
|
||||
eax |= 0x0A0A00;
|
||||
}
|
||||
//Adjust text palette. Store current colour?
|
||||
//Adjust text palette. Store current colour?
|
||||
palette_pointer[1] = eax & 0xFF;
|
||||
palette_pointer[2] = (eax >> 8) & 0xFF;
|
||||
palette_pointer[3] = (eax >> 16) & 0xFF;
|
||||
|
@ -521,7 +522,7 @@ void colour_char_window(uint8 colour, uint16* current_font_flags,uint8* palette_
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x00682702
|
||||
* dpi (edi)
|
||||
* buffer (esi)
|
||||
|
@ -712,7 +713,7 @@ void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int
|
|||
lineY = y - ((numLines * lineHeight) / 2);
|
||||
for (int line = 0; line <= numLines; line++) {
|
||||
int halfWidth = gfx_get_string_width(buffer) / 2;
|
||||
|
||||
|
||||
utf8 *ch = buffer;
|
||||
utf8 *nextCh;
|
||||
int codepoint;
|
||||
|
@ -735,7 +736,7 @@ void gfx_draw_string_centred_wrapped_partial(rct_drawpixelinfo *dpi, int x, int
|
|||
|
||||
buffer = get_string_end(buffer) + 1;
|
||||
lineY += lineHeight;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32 _ttf_surface_cache_hash(TTF_Font *font, const utf8 *text)
|
||||
|
@ -884,7 +885,7 @@ bool ttf_initialise()
|
|||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
TTFFontDescriptor *fontDesc = &(gCurrentTTFFontSet->size[i]);
|
||||
|
||||
|
||||
utf8 fontPath[MAX_PATH] = "C:\\Windows\\Fonts\\";
|
||||
strcat(fontPath, fontDesc->filename);
|
||||
|
||||
|
@ -1000,7 +1001,7 @@ static void ttf_draw_string_raw_ttf(rct_drawpixelinfo *dpi, const utf8 *text, te
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int fontSize = font_get_size_from_sprite_base(info->font_sprite_base);
|
||||
int drawX = info->x + fontDesc->offset_x;
|
||||
int drawY = info->y + fontDesc->offset_y;
|
||||
|
|
|
@ -856,7 +856,12 @@ int win1252_to_utf8(utf8string dst, const char *src, int maxBufferLength)
|
|||
int result = WideCharToMultiByte(CP_UTF8, 0, intermediateBuffer, -1, dst, maxBufferLength, NULL, NULL);
|
||||
#else
|
||||
STUB();
|
||||
int result = 0;
|
||||
// we cannot walk past maxBufferLength, but in case we have still space left
|
||||
// we need one byte for null terminator
|
||||
int result = strnlen(src, maxBufferLength) + 1;
|
||||
result = min(result, maxBufferLength);
|
||||
strncpy(dst, src, maxBufferLength);
|
||||
dst[maxBufferLength - 1] = '\0';
|
||||
#endif // _WIN32
|
||||
|
||||
if (heapBuffer != NULL) {
|
||||
|
|
24
src/object.c
24
src/object.c
|
@ -56,7 +56,7 @@ int object_load_file(int groupIndex, const rct_object_entry *entry, int* chunkSi
|
|||
{
|
||||
uint8 objectType;
|
||||
rct_object_entry openedEntry;
|
||||
char path[260];
|
||||
char path[MAX_PATH];
|
||||
SDL_RWops* rw;
|
||||
|
||||
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), (char*)installedObject + 16);
|
||||
|
@ -259,7 +259,7 @@ int object_load_packed(SDL_RWops* rw)
|
|||
}
|
||||
|
||||
if (entryGroupIndex == object_entry_group_counts[type]){
|
||||
// This should never occur. Objects are not loaded before installing a
|
||||
// This should never occur. Objects are not loaded before installing a
|
||||
// packed object. So there is only one object loaded at this point.
|
||||
log_error("Too many objects of the same type loaded.");
|
||||
rct2_free(chunk);
|
||||
|
@ -285,7 +285,7 @@ int object_load_packed(SDL_RWops* rw)
|
|||
}
|
||||
|
||||
// Convert the entry name to a upper case path name
|
||||
char path[260];
|
||||
char path[MAX_PATH];
|
||||
char objectPath[9] = { 0 };
|
||||
for (int i = 0; i < 8; ++i){
|
||||
if (entry.name[i] != ' ')
|
||||
|
@ -400,7 +400,7 @@ int object_calculate_checksum(const rct_object_entry *entry, const char *data, i
|
|||
int object_chunk_load_image_directory(uint8_t** chunk)
|
||||
{
|
||||
int image_start_no = RCT2_GLOBAL(RCT2_ADDRESS_TOTAL_NO_IMAGES, uint32_t);
|
||||
|
||||
|
||||
// First dword of chunk is no_images
|
||||
int no_images = *((uint32_t*)(*chunk));
|
||||
*chunk += 4;
|
||||
|
@ -754,7 +754,7 @@ int paint_ride_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* dp
|
|||
return flags;
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
rct_window* w = (rct_window*)esi;
|
||||
int width = w->x + w->width - x - 4;
|
||||
|
||||
|
@ -1415,7 +1415,7 @@ int paint_water_entry(int flags, int ebx, int ecx, int edx, rct_drawpixelinfo* d
|
|||
return 0;
|
||||
}
|
||||
else if ((flags & 0xFF) == 3){
|
||||
if (!((flags >> 8) & 0xFF))
|
||||
if (!((flags >> 8) & 0xFF))
|
||||
gfx_draw_string_centred(dpi, 3326, ecx, edx, 0, (void*)esi);
|
||||
}
|
||||
return flags;
|
||||
|
@ -1467,7 +1467,7 @@ int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi,
|
|||
switch (type)
|
||||
{
|
||||
case OBJECT_TYPE_RIDE:
|
||||
return paint_ride_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
return paint_ride_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
case OBJECT_TYPE_SMALL_SCENERY:
|
||||
return paint_small_scenery(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
case OBJECT_TYPE_LARGE_SCENERY:
|
||||
|
@ -1477,7 +1477,7 @@ int object_paint(int type, int eax, int ebx, int ecx, int edx, int esi, int edi,
|
|||
case OBJECT_TYPE_BANNERS:
|
||||
return paint_banner(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
case OBJECT_TYPE_PATHS:
|
||||
return paint_path_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
return paint_path_entry(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
case OBJECT_TYPE_PATH_BITS:
|
||||
return paint_path_bit(eax, ebx, ecx, edx, (rct_drawpixelinfo*)edi, esi, ebp);
|
||||
case OBJECT_TYPE_SCENERY_SETS:
|
||||
|
@ -1503,14 +1503,14 @@ int object_get_scenario_text(rct_object_entry *entry)
|
|||
rct_object_entry *installedObject = RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
|
||||
|
||||
installedObject = object_list_find(entry);
|
||||
|
||||
|
||||
if (installedObject == NULL){
|
||||
log_error("Object not found: %.8s", entry->name);
|
||||
RCT2_GLOBAL(0x00F42BD9, uint8) = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
char path[260];
|
||||
char path[MAX_PATH];
|
||||
char *objectPath = (char*)installedObject + 16;
|
||||
subsitute_path(path, RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char), objectPath);
|
||||
|
||||
|
@ -1571,7 +1571,7 @@ int object_get_scenario_text(rct_object_entry *entry)
|
|||
memcpy(gTempObjectLoadName, openedEntry.name, 8);
|
||||
// Not used??
|
||||
RCT2_GLOBAL(0x009ADAFD, uint8) = 1;
|
||||
object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0);
|
||||
object_paint(openedEntry.flags & 0x0F, 0, 0, 0, 0, (int)chunk, 0, 0);
|
||||
// Tell text to be loaded into normal address
|
||||
RCT2_GLOBAL(0x009ADAFC, uint8) = 0;
|
||||
// Not used??
|
||||
|
@ -1630,7 +1630,7 @@ rct_object_entry *object_get_next(rct_object_entry *entry)
|
|||
// Skip theme objects
|
||||
pos += *pos * 16 + 1;
|
||||
|
||||
// Skip
|
||||
// Skip
|
||||
pos += 4;
|
||||
|
||||
return (rct_object_entry*)pos;
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
@ -75,7 +75,7 @@ extern int object_entry_group_counts[];
|
|||
extern int object_entry_group_encoding[];
|
||||
|
||||
typedef struct {
|
||||
uint8 **chunks;
|
||||
uint8 **chunks;
|
||||
rct_object_entry_extended *entries;
|
||||
} rct_object_entry_group;
|
||||
|
||||
|
@ -122,4 +122,4 @@ char *object_get_name(rct_object_entry *entry);
|
|||
|
||||
rct_object_filters *get_object_filter(int index);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
@ -115,7 +115,7 @@ static void object_list_sort()
|
|||
objectBuffer = &RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, rct_object_entry*);
|
||||
numObjects = RCT2_GLOBAL(RCT2_ADDRESS_OBJECT_LIST_NO_ITEMS, sint32);
|
||||
copied = calloc(numObjects, sizeof(uint8));
|
||||
|
||||
|
||||
// Get buffer size
|
||||
entry = *objectBuffer;
|
||||
for (i = 0; i < numObjects; i++)
|
||||
|
@ -166,7 +166,7 @@ static void object_list_sort()
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006A93CD
|
||||
*/
|
||||
static void object_list_examine()
|
||||
|
@ -237,7 +237,7 @@ static int object_list_query_directory(int *outTotalFiles, uint64 *outTotalFileS
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006A8B40
|
||||
*/
|
||||
void object_list_load()
|
||||
|
@ -291,17 +291,17 @@ void object_list_load()
|
|||
free(_installedObjectFilters);
|
||||
_installedObjectFilters = NULL;
|
||||
}
|
||||
|
||||
|
||||
enumFileHandle = platform_enumerate_files_begin(RCT2_ADDRESS(RCT2_ADDRESS_OBJECT_DATA_PATH, char));
|
||||
if (enumFileHandle != INVALID_HANDLE) {
|
||||
uint32 installed_buffer_size = 0x1000;
|
||||
|
||||
|
||||
while (platform_enumerate_files_next(enumFileHandle, &enumFileInfo)) {
|
||||
fileCount++;
|
||||
|
||||
if ((installed_buffer_size - current_item_offset) <= 2842){
|
||||
installed_buffer_size += 0x1000;
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size);
|
||||
RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*) = rct2_realloc(RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, void*), installed_buffer_size);
|
||||
if (RCT2_GLOBAL(RCT2_ADDRESS_INSTALLED_OBJECT_LIST, int) == -1){
|
||||
log_error("Failed to allocate memory for object list");
|
||||
rct2_exit_reason(835, 3162);
|
||||
|
@ -355,6 +355,11 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file
|
|||
rct_plugin_header pluginHeader;
|
||||
uint32 filterVersion = 0;
|
||||
|
||||
#ifndef _WIN32
|
||||
// TODO: remove me!
|
||||
log_error("this is to be removed after testing/implementation is done");
|
||||
return 0;
|
||||
#endif
|
||||
log_verbose("loading object list cache (plugin.dat)");
|
||||
|
||||
get_plugin_path(path);
|
||||
|
@ -391,7 +396,7 @@ static int object_list_cache_load(int totalFiles, uint64 totalFileSize, int file
|
|||
free(_installedObjectFilters);
|
||||
_installedObjectFilters = malloc(sizeof(rct_object_filters) * pluginHeader.object_list_no_items);
|
||||
if (SDL_RWread(file, _installedObjectFilters, sizeof(rct_object_filters) * pluginHeader.object_list_no_items, 1) == 1) {
|
||||
|
||||
|
||||
SDL_RWclose(file);
|
||||
reset_loaded_objects();
|
||||
object_list_examine();
|
||||
|
@ -431,7 +436,7 @@ static int object_list_cache_save(int fileCount, uint64 totalFileSize, int fileD
|
|||
SDL_RWops *file;
|
||||
rct_plugin_header pluginHeader;
|
||||
uint32 filterVersion = FILTER_VERSION;
|
||||
|
||||
|
||||
log_verbose("saving object list cache (plugin.dat)");
|
||||
|
||||
pluginHeader.total_files = fileCount | 0x01000000;
|
||||
|
@ -519,7 +524,7 @@ void set_load_objects_fail_reason(){
|
|||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006AA0C6
|
||||
*/
|
||||
int object_read_and_load_entries(SDL_RWops* rw)
|
||||
|
@ -557,7 +562,7 @@ int object_read_and_load_entries(SDL_RWops* rw)
|
|||
}
|
||||
}
|
||||
|
||||
free(entries);
|
||||
free(entries);
|
||||
if (load_fail){
|
||||
object_unload_all();
|
||||
RCT2_GLOBAL(0x14241BC, uint32) = 0;
|
||||
|
@ -571,7 +576,7 @@ int object_read_and_load_entries(SDL_RWops* rw)
|
|||
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* rct2: 0x006A9CE8
|
||||
*/
|
||||
void object_unload_all()
|
||||
|
@ -631,7 +636,7 @@ void object_list_create_hash_table()
|
|||
|
||||
// Set hash table slot
|
||||
_installedObjectHashTable[index] = installedObject;
|
||||
|
||||
|
||||
// Next installed object
|
||||
installedObject = object_get_next(installedObject);
|
||||
}
|
||||
|
@ -645,8 +650,8 @@ int find_object_in_entry_group(rct_object_entry* entry, uint8* entry_type, uint8
|
|||
*entry_type = entry->flags & 0xF;
|
||||
|
||||
rct_object_entry_group entry_group = object_entry_groups[*entry_type];
|
||||
for (*entry_index = 0;
|
||||
*entry_index < object_entry_group_counts[*entry_type];
|
||||
for (*entry_index = 0;
|
||||
*entry_index < object_entry_group_counts[*entry_type];
|
||||
++(*entry_index),
|
||||
entry_group.chunks++,
|
||||
entry_group.entries++){
|
||||
|
|
|
@ -135,8 +135,19 @@ static void openrct2_set_exe_path()
|
|||
if (bytesRead == -1) {
|
||||
log_fatal("failed to read /proc/self/exe");
|
||||
}
|
||||
exePath[MAX_PATH - 1] = '\0';
|
||||
strncpy(gExePath, exePath, MAX_PATH);
|
||||
exePath[bytesRead] = '\0';
|
||||
log_verbose("######################################## Setting exe path to %s", exePath);
|
||||
char *exeDelimiter = strrchr(exePath, platform_get_path_separator());
|
||||
if (exeDelimiter == NULL)
|
||||
{
|
||||
log_error("should never happen here");
|
||||
gExePath[0] = '\0';
|
||||
return;
|
||||
}
|
||||
int exeDelimiterIndex = (int)(exeDelimiter - exePath);
|
||||
|
||||
strncpy(gExePath, exePath, exeDelimiterIndex + 1);
|
||||
gExePath[exeDelimiterIndex] = '\0';
|
||||
#endif // _WIN32
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,759 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef __linux
|
||||
|
||||
#include <libgen.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include "../addresses.h"
|
||||
#include "../cmdline.h"
|
||||
#include "../openrct2.h"
|
||||
#include "../localisation/language.h"
|
||||
#include "../localisation/currency.h"
|
||||
#include "../config.h"
|
||||
#include "platform.h"
|
||||
#include <dirent.h>
|
||||
|
||||
// The name of the mutex used to prevent multiple instances of the game from running
|
||||
#define SINGLE_INSTANCE_MUTEX_NAME "RollerCoaster Tycoon 2_GSKMUTEX"
|
||||
|
||||
/**
|
||||
* The function that is called directly from the host application (rct2.exe)'s WinMain. This will be removed when OpenRCT2 can
|
||||
* be built as a stand alone application.
|
||||
*/
|
||||
int main(int argc, const char **argv)
|
||||
{
|
||||
//RCT2_GLOBAL(RCT2_ADDRESS_HINSTANCE, HINSTANCE) = hInstance;
|
||||
//RCT2_GLOBAL(RCT2_ADDRESS_CMDLINE, LPSTR) = lpCmdLine;
|
||||
|
||||
STUB();
|
||||
int run_game = cmdline_run(argv, argc);
|
||||
if (run_game == 1)
|
||||
{
|
||||
openrct2_launch();
|
||||
}
|
||||
|
||||
exit(gExitCode);
|
||||
return gExitCode;
|
||||
}
|
||||
|
||||
char platform_get_path_separator()
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
|
||||
bool platform_file_exists(const utf8 *path)
|
||||
{
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
int len = min(MAX_PATH, utf8_length(path));
|
||||
char buffer[MAX_PATH];
|
||||
wcstombs(buffer, wPath, len);
|
||||
buffer[len] = '\0';
|
||||
free(wPath);
|
||||
int exists = access(buffer, F_OK) != -1;
|
||||
log_warning("file '%s' exists = %i", buffer, exists);
|
||||
return exists;
|
||||
}
|
||||
|
||||
bool platform_directory_exists(const utf8 *path)
|
||||
{
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
int len = min(MAX_PATH, utf8_length(path));
|
||||
char buffer[MAX_PATH];
|
||||
wcstombs(buffer, wPath, len);
|
||||
buffer[len] = '\0';
|
||||
free(wPath);
|
||||
struct stat dirinfo;
|
||||
int result = stat(buffer, &dirinfo);
|
||||
log_verbose("checking dir %s, result = %d, is_dir = %d", buffer, result, S_ISDIR(dirinfo.st_mode));
|
||||
if ((result != 0) || !S_ISDIR(dirinfo.st_mode))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool platform_original_game_data_exists(const utf8 *path)
|
||||
{
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
int len = min(MAX_PATH, utf8_length(path));
|
||||
char buffer[MAX_PATH];
|
||||
wcstombs(buffer, wPath, len);
|
||||
buffer[len] = '\0';
|
||||
free(wPath);
|
||||
char checkPath[MAX_PATH];
|
||||
sprintf(checkPath, "%s%c%s%c%s", buffer, platform_get_path_separator(), "data", platform_get_path_separator(), "g1.dat");
|
||||
return platform_file_exists(checkPath);
|
||||
}
|
||||
|
||||
mode_t getumask()
|
||||
{
|
||||
mode_t mask = umask(0);
|
||||
umask(mask);
|
||||
return 0777 & ~mask; // Keep in mind 0777 is octal
|
||||
}
|
||||
|
||||
bool platform_ensure_directory_exists(const utf8 *path)
|
||||
{
|
||||
mode_t mask = getumask();
|
||||
|
||||
wchar_t *wPath = utf8_to_widechar(path);
|
||||
int len = min(MAX_PATH, utf8_length(path));
|
||||
char buffer[MAX_PATH];
|
||||
wcstombs(buffer, wPath, len);
|
||||
buffer[len - 1] = '\0';
|
||||
free(wPath);
|
||||
log_verbose("%s", buffer);
|
||||
const int result = mkdir(buffer, mask);
|
||||
if (result == 0 || (result == -1 && errno == EEXIST))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool platform_directory_delete(const utf8 *path)
|
||||
{
|
||||
STUB();
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool platform_lock_single_instance()
|
||||
{
|
||||
STUB();
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
char active;
|
||||
char pattern[MAX_PATH];
|
||||
struct dirent **fileListTemp;
|
||||
char **paths;
|
||||
int cnt;
|
||||
int handle;
|
||||
void* data;
|
||||
} enumerate_file_info;
|
||||
static enumerate_file_info _enumerateFileInfoList[8] = { 0 };
|
||||
|
||||
char *g_file_pattern;
|
||||
|
||||
static int winfilter(const struct dirent *d)
|
||||
{
|
||||
int entry_length = strnlen(d->d_name, MAX_PATH);
|
||||
char *name_upper = malloc(entry_length + 1);
|
||||
if (name_upper == NULL)
|
||||
{
|
||||
log_error("out of memory");
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < entry_length; i++)
|
||||
{
|
||||
name_upper[i] = (char)toupper(d->d_name[i]);
|
||||
}
|
||||
name_upper[entry_length] = '\0';
|
||||
bool match = strstr(name_upper, g_file_pattern) != NULL;
|
||||
//log_warning("trying matching filename %s, result = %d", name_upper, match);
|
||||
free(name_upper);
|
||||
return match;
|
||||
}
|
||||
|
||||
int platform_enumerate_files_begin(const utf8 *pattern)
|
||||
{
|
||||
int i;
|
||||
enumerate_file_info *enumFileInfo;
|
||||
wchar_t *wpattern = utf8_to_widechar(pattern);
|
||||
int length = min(utf8_length(pattern), MAX_PATH);
|
||||
char *npattern = malloc(length);
|
||||
int converted;
|
||||
converted = wcstombs(npattern, wpattern, length);
|
||||
npattern[length - 1] = '\0';
|
||||
if (converted == MAX_PATH) {
|
||||
log_warning("truncated string %s", npattern);
|
||||
}
|
||||
log_warning("begin file search, pattern: %s", npattern);
|
||||
|
||||
char *file_name = strrchr(npattern, platform_get_path_separator());
|
||||
char *dir_name;
|
||||
if (file_name != NULL)
|
||||
{
|
||||
dir_name = strndup(npattern, file_name - npattern);
|
||||
file_name = &file_name[1];
|
||||
} else {
|
||||
file_name = npattern;
|
||||
dir_name = strdup(".");
|
||||
}
|
||||
|
||||
char *smatch = strchr(file_name, '*');
|
||||
if ((smatch != file_name) && (smatch != NULL))
|
||||
{
|
||||
log_error("Sorry, can only match '*' at start of filename.");
|
||||
return -1;
|
||||
} else {
|
||||
// '*' found
|
||||
if (smatch != NULL)
|
||||
{
|
||||
// some boundary checking needed
|
||||
// skip the '*'
|
||||
smatch = &smatch[1];
|
||||
char *match2 = strchr(&smatch[1], '*');
|
||||
if (match2 != NULL)
|
||||
{
|
||||
log_error("Sorry, can only match one '*' wildcard.");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
// '*' not found
|
||||
smatch = file_name;
|
||||
}
|
||||
}
|
||||
char *qmatch = strchr(file_name, '?');
|
||||
if ((qmatch != &npattern[length - 1]) && (qmatch != NULL))
|
||||
{
|
||||
log_error("Sorry, can only match '?' at end of filename.");
|
||||
return -1;
|
||||
} else {
|
||||
qmatch = &npattern[length];
|
||||
}
|
||||
int pattern_length = qmatch - smatch;
|
||||
g_file_pattern = strndup(smatch, pattern_length);
|
||||
for (int j = 0; j < pattern_length; j++)
|
||||
{
|
||||
g_file_pattern[j] = (char)toupper(g_file_pattern[j]);
|
||||
}
|
||||
log_warning("looking for file matching %s", g_file_pattern);
|
||||
int cnt;
|
||||
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
|
||||
enumFileInfo = &_enumerateFileInfoList[i];
|
||||
if (!enumFileInfo->active) {
|
||||
strncpy(enumFileInfo->pattern, npattern, length);
|
||||
cnt = scandir(dir_name, &enumFileInfo->fileListTemp, winfilter, alphasort);
|
||||
if (cnt < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
log_warning("found %d files matching in dir '%s'", cnt, dir_name);
|
||||
enumFileInfo->cnt = cnt;
|
||||
enumFileInfo->paths = malloc(cnt * sizeof(char *));
|
||||
char **paths = enumFileInfo->paths;
|
||||
// 256 is size of dirent.d_name
|
||||
const int buf_len = min(MAX_PATH, 256);
|
||||
const int dir_name_len = strnlen(dir_name, MAX_PATH);
|
||||
char separator[] = {platform_get_path_separator(), 0};
|
||||
for (int idx = 0; idx < cnt; idx++)
|
||||
{
|
||||
struct dirent *d = enumFileInfo->fileListTemp[idx];
|
||||
const int entry_len = strnlen(d->d_name, MAX_PATH);
|
||||
// 1 for separator, 1 for trailing null
|
||||
paths[idx] = malloc(sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2));
|
||||
paths[idx][0] = '\0';
|
||||
log_verbose("dir_name: %s", dir_name);
|
||||
strncat(paths[idx], dir_name, MAX_PATH);
|
||||
strncat(paths[idx], separator, MAX_PATH);
|
||||
strncat(paths[idx], d->d_name, MAX_PATH);
|
||||
log_verbose("paths[%d] = %s", idx, paths[idx]);
|
||||
}
|
||||
enumFileInfo->handle = 0;
|
||||
enumFileInfo->active = 1;
|
||||
free(dir_name);
|
||||
free(g_file_pattern);
|
||||
g_file_pattern = NULL;
|
||||
free(wpattern);
|
||||
free(npattern);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
free(dir_name);
|
||||
free(g_file_pattern);
|
||||
g_file_pattern = NULL;
|
||||
free(wpattern);
|
||||
free(npattern);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool platform_enumerate_files_next(int handle, file_info *outFileInfo)
|
||||
{
|
||||
bool result;
|
||||
enumerate_file_info *enumFileInfo;
|
||||
|
||||
enumFileInfo = &_enumerateFileInfoList[handle];
|
||||
|
||||
log_verbose("handle = %d", handle);
|
||||
if (enumFileInfo->handle < enumFileInfo->cnt) {
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
int entryIdx = enumFileInfo->handle++;
|
||||
struct stat fileInfo;
|
||||
log_verbose("trying handle %d", entryIdx);
|
||||
char *fileName = enumFileInfo->paths[entryIdx];
|
||||
int statRes;
|
||||
statRes = stat(fileName, &fileInfo);
|
||||
if (statRes == -1) {
|
||||
log_error("failed to stat file '%s'! errno = %i", fileName, errno);
|
||||
return 0;
|
||||
}
|
||||
outFileInfo->path = basename(fileName);
|
||||
outFileInfo->size = fileInfo.st_size;
|
||||
outFileInfo->last_modified = fileInfo.st_mtime;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void platform_enumerate_files_end(int handle)
|
||||
{
|
||||
int i;
|
||||
enumerate_file_info *enumFileInfo;
|
||||
|
||||
enumFileInfo = &_enumerateFileInfoList[handle];
|
||||
int cnt = enumFileInfo->cnt;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
free(enumFileInfo->fileListTemp[i]);
|
||||
free(enumFileInfo->paths[i]);
|
||||
}
|
||||
free(enumFileInfo->fileListTemp);
|
||||
free(enumFileInfo->paths);
|
||||
// FIXME: this here could have a bug
|
||||
enumFileInfo->fileListTemp = NULL;
|
||||
enumFileInfo->handle = 0;
|
||||
enumFileInfo->active = 0;
|
||||
}
|
||||
|
||||
static int dirfilter(const struct dirent *d)
|
||||
{
|
||||
#ifdef _DIRENT_HAVE_D_TYPE
|
||||
if (d->d_type != DT_DIR)
|
||||
{
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
#error implement dirfilter!
|
||||
#endif // _DIRENT_HAVE_D_TYPE
|
||||
}
|
||||
|
||||
int platform_enumerate_directories_begin(const utf8 *directory)
|
||||
{
|
||||
int i;
|
||||
enumerate_file_info *enumFileInfo;
|
||||
wchar_t *wpattern = utf8_to_widechar(directory);
|
||||
int length = min(utf8_length(directory), MAX_PATH);
|
||||
char *npattern = malloc(length);
|
||||
int converted;
|
||||
converted = wcstombs(npattern, wpattern, length);
|
||||
npattern[length - 1] = '\0';
|
||||
if (converted == MAX_PATH) {
|
||||
log_warning("truncated string %s", npattern);
|
||||
}
|
||||
log_warning("begin directory listing, path: %s", npattern);
|
||||
|
||||
// TODO: add some checking for stringness and directoryness
|
||||
|
||||
int cnt;
|
||||
for (i = 0; i < countof(_enumerateFileInfoList); i++) {
|
||||
enumFileInfo = &_enumerateFileInfoList[i];
|
||||
if (!enumFileInfo->active) {
|
||||
strncpy(enumFileInfo->pattern, npattern, length);
|
||||
cnt = scandir(npattern, &enumFileInfo->fileListTemp, dirfilter, alphasort);
|
||||
if (cnt < 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
log_warning("found %d files in dir '%s'", cnt, npattern);
|
||||
enumFileInfo->cnt = cnt;
|
||||
enumFileInfo->paths = malloc(cnt * sizeof(char *));
|
||||
char **paths = enumFileInfo->paths;
|
||||
// 256 is size of dirent.d_name
|
||||
const int buf_len = min(MAX_PATH, 256);
|
||||
const int dir_name_len = strnlen(npattern, MAX_PATH);
|
||||
char separator[] = {platform_get_path_separator(), 0};
|
||||
for (int idx = 0; idx < cnt; idx++)
|
||||
{
|
||||
struct dirent *d = enumFileInfo->fileListTemp[idx];
|
||||
const int entry_len = strnlen(d->d_name, MAX_PATH);
|
||||
// 1 for separator, 1 for trailing null
|
||||
paths[idx] = malloc(sizeof(char) * min(MAX_PATH, entry_len + dir_name_len + 2));
|
||||
paths[idx][0] = '\0';
|
||||
log_verbose("dir_name: %s", npattern);
|
||||
strncat(paths[idx], npattern, MAX_PATH);
|
||||
strncat(paths[idx], separator, MAX_PATH);
|
||||
strncat(paths[idx], d->d_name, MAX_PATH);
|
||||
log_verbose("paths[%d] = %s", idx, paths[idx]);
|
||||
}
|
||||
enumFileInfo->handle = 0;
|
||||
enumFileInfo->active = 1;
|
||||
free(wpattern);
|
||||
free(npattern);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
free(wpattern);
|
||||
free(npattern);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool platform_enumerate_directories_next(int handle, utf8 *path)
|
||||
{
|
||||
bool result;
|
||||
enumerate_file_info *enumFileInfo;
|
||||
|
||||
enumFileInfo = &_enumerateFileInfoList[handle];
|
||||
|
||||
log_verbose("handle = %d", handle);
|
||||
if (enumFileInfo->handle < enumFileInfo->cnt) {
|
||||
result = true;
|
||||
} else {
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
int entryIdx = enumFileInfo->handle++;
|
||||
struct stat fileInfo;
|
||||
log_verbose("trying handle %d", entryIdx);
|
||||
char *fileName = enumFileInfo->paths[entryIdx];
|
||||
int statRes;
|
||||
statRes = stat(fileName, &fileInfo);
|
||||
if (statRes == -1) {
|
||||
log_error("failed to stat file '%s'! errno = %i", fileName, errno);
|
||||
return 0;
|
||||
}
|
||||
// so very, very wrong…
|
||||
strncpy(path, basename(fileName), MAX_PATH);
|
||||
strncat(path, "/", MAX_PATH);
|
||||
path[MAX_PATH - 1] = '\0';
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void platform_enumerate_directories_end(int handle)
|
||||
{
|
||||
int i;
|
||||
enumerate_file_info *enumFileInfo;
|
||||
|
||||
enumFileInfo = &_enumerateFileInfoList[handle];
|
||||
int cnt = enumFileInfo->cnt;
|
||||
for (i = 0; i < cnt; i++) {
|
||||
free(enumFileInfo->fileListTemp[i]);
|
||||
free(enumFileInfo->paths[i]);
|
||||
}
|
||||
free(enumFileInfo->fileListTemp);
|
||||
free(enumFileInfo->paths);
|
||||
// FIXME: this here could have a bug
|
||||
enumFileInfo->fileListTemp = NULL;
|
||||
enumFileInfo->handle = 0;
|
||||
enumFileInfo->active = 0;
|
||||
}
|
||||
|
||||
int platform_get_drives(){
|
||||
/*
|
||||
return GetLogicalDrives();
|
||||
*/
|
||||
STUB();
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
bool platform_file_copy(const utf8 *srcPath, const utf8 *dstPath, bool overwrite)
|
||||
{
|
||||
STUB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool platform_file_move(const utf8 *srcPath, const utf8 *dstPath)
|
||||
{
|
||||
STUB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool platform_file_delete(const utf8 *path)
|
||||
{
|
||||
STUB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void platform_hide_cursor()
|
||||
{
|
||||
STUB();
|
||||
}
|
||||
|
||||
void platform_show_cursor()
|
||||
{
|
||||
STUB();
|
||||
}
|
||||
|
||||
void platform_get_cursor_position(int *x, int *y)
|
||||
{
|
||||
|
||||
STUB();
|
||||
}
|
||||
|
||||
void platform_set_cursor_position(int x, int y)
|
||||
{
|
||||
STUB();
|
||||
}
|
||||
|
||||
unsigned int platform_get_ticks()
|
||||
{
|
||||
STUB();
|
||||
return 100;
|
||||
}
|
||||
|
||||
wchar_t *regular_to_wchar(const char* src)
|
||||
{
|
||||
int len = strnlen(src, MAX_PATH);
|
||||
wchar_t *w_buffer = malloc((len + 1) * sizeof(wchar_t));
|
||||
mbtowc (NULL, NULL, 0); /* reset mbtowc */
|
||||
|
||||
int max = len;
|
||||
int i = 0;
|
||||
while (max > 0)
|
||||
{
|
||||
int length;
|
||||
length = mbtowc(&w_buffer[i], &src[i], max);
|
||||
if (length < 1)
|
||||
{
|
||||
w_buffer[i + 1] = '\0';
|
||||
break;
|
||||
}
|
||||
i += length;
|
||||
max -= length;
|
||||
}
|
||||
return w_buffer;
|
||||
}
|
||||
|
||||
void platform_get_user_directory(utf8 *outPath, const utf8 *subDirectory)
|
||||
{
|
||||
char buffer[MAX_PATH];
|
||||
buffer[0] = '\0';
|
||||
log_verbose("buffer = '%s'", buffer);
|
||||
const char *homedir = getenv("XDG_CONFIG_HOME");
|
||||
log_verbose("homedir = '%s'", homedir);
|
||||
if (homedir == NULL)
|
||||
{
|
||||
homedir = getpwuid(getuid())->pw_dir;
|
||||
log_verbose("homedir was null, used getuid, now is = '%s'", homedir);
|
||||
if (homedir == NULL)
|
||||
{
|
||||
log_error("Couldn't find user home directory");
|
||||
return;
|
||||
}
|
||||
}
|
||||
char separator[2] = { platform_get_path_separator(), 0 };
|
||||
strncat(buffer, homedir, MAX_PATH);
|
||||
strncat(buffer, separator, MAX_PATH);
|
||||
strncat(buffer, "OpenRCT2", MAX_PATH);
|
||||
strncat(buffer, separator, MAX_PATH);
|
||||
log_verbose("outPath + OpenRCT2 = '%s'", buffer);
|
||||
if (subDirectory != NULL && subDirectory[0] != 0) {
|
||||
log_verbose("adding subDirectory '%s'", subDirectory);
|
||||
strcat(buffer, subDirectory);
|
||||
strcat(buffer, separator);
|
||||
}
|
||||
int len = strnlen(buffer, MAX_PATH);
|
||||
wchar_t *w_buffer = regular_to_wchar(buffer);
|
||||
w_buffer[len] = '\0';
|
||||
utf8 *path = widechar_to_utf8(w_buffer);
|
||||
free(w_buffer);
|
||||
strcpy(outPath, path);
|
||||
free(path);
|
||||
log_verbose("outPath + subDirectory = '%s'", buffer);
|
||||
}
|
||||
|
||||
void platform_show_messagebox(char *message)
|
||||
{
|
||||
STUB();
|
||||
log_warning(message);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* rct2: 0x004080EA
|
||||
*/
|
||||
int platform_open_common_file_dialog(int type, utf8 *title, utf8 *filename, utf8 *filterPattern, utf8 *filterName)
|
||||
{
|
||||
STUB();
|
||||
return 0;
|
||||
}
|
||||
|
||||
utf8 *platform_open_directory_browser(utf8 *title)
|
||||
{
|
||||
STUB();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16 platform_get_locale_language(){
|
||||
/*
|
||||
CHAR langCode[4];
|
||||
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_SABBREVLANGNAME,
|
||||
(LPSTR)&langCode,
|
||||
sizeof(langCode)) == 0){
|
||||
return LANGUAGE_UNDEFINED;
|
||||
}
|
||||
|
||||
if (strcmp(langCode, "ENG") == 0){
|
||||
return LANGUAGE_ENGLISH_UK;
|
||||
}
|
||||
else if (strcmp(langCode, "ENU") == 0){
|
||||
return LANGUAGE_ENGLISH_US;
|
||||
}
|
||||
else if (strcmp(langCode, "DEU") == 0){
|
||||
return LANGUAGE_GERMAN;
|
||||
}
|
||||
else if (strcmp(langCode, "NLD") == 0){
|
||||
return LANGUAGE_DUTCH;
|
||||
}
|
||||
else if (strcmp(langCode, "FRA") == 0){
|
||||
return LANGUAGE_FRENCH;
|
||||
}
|
||||
else if (strcmp(langCode, "HUN") == 0){
|
||||
return LANGUAGE_HUNGARIAN;
|
||||
}
|
||||
else if (strcmp(langCode, "PLK") == 0){
|
||||
return LANGUAGE_POLISH;
|
||||
}
|
||||
else if (strcmp(langCode, "ESP") == 0){
|
||||
return LANGUAGE_SPANISH;
|
||||
}
|
||||
else if (strcmp(langCode, "SVE") == 0){
|
||||
return LANGUAGE_SWEDISH;
|
||||
}
|
||||
else if (strcmp(langCode, "ITA") == 0){
|
||||
return LANGUAGE_ITALIAN;
|
||||
}
|
||||
else if (strcmp(langCode, "POR") == 0){
|
||||
return LANGUAGE_PORTUGUESE_BR;
|
||||
}
|
||||
*/
|
||||
STUB();
|
||||
return LANGUAGE_ENGLISH_UK;
|
||||
}
|
||||
|
||||
time_t platform_file_get_modified_time(const utf8* path){
|
||||
/*
|
||||
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||
if (!GetFileAttributesEx(path, GetFileExInfoStandard, &data))
|
||||
return 0;
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = data.ftLastWriteTime.dwLowDateTime;
|
||||
ull.HighPart = data.ftLastWriteTime.dwHighDateTime;
|
||||
return ull.QuadPart / 10000000ULL - 11644473600ULL;
|
||||
*/
|
||||
STUB();
|
||||
return 100;
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_currency(){
|
||||
/*
|
||||
CHAR currCode[4];
|
||||
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_SINTLSYMBOL,
|
||||
(LPSTR)&currCode,
|
||||
sizeof(currCode)) == 0){
|
||||
return CURRENCY_POUNDS;
|
||||
}
|
||||
if (strcmp(currCode, "GBP") == 0){
|
||||
return CURRENCY_POUNDS;
|
||||
}
|
||||
else if (strcmp(currCode, "USD") == 0){
|
||||
return CURRENCY_DOLLARS;
|
||||
}
|
||||
else if (strcmp(currCode, "EUR") == 0){
|
||||
return CURRENCY_EUROS;
|
||||
}
|
||||
else if (strcmp(currCode, "SEK") == 0){
|
||||
return CURRENCY_KRONA;
|
||||
}
|
||||
else if (strcmp(currCode, "DEM") == 0){
|
||||
return CURRENCY_DEUTSCHMARK;
|
||||
}
|
||||
else if (strcmp(currCode, "ITL") == 0){
|
||||
return CURRENCY_LIRA;
|
||||
}
|
||||
else if (strcmp(currCode, "JPY") == 0){
|
||||
return CURRENCY_YEN;
|
||||
}
|
||||
else if (strcmp(currCode, "ESP") == 0){
|
||||
return CURRENCY_PESETA;
|
||||
}
|
||||
else if (strcmp(currCode, "FRF") == 0){
|
||||
return CURRENCY_FRANC;
|
||||
}
|
||||
else if (strcmp(currCode, "NLG") == 0){
|
||||
return CURRENCY_GUILDERS;
|
||||
}
|
||||
*/
|
||||
STUB();
|
||||
return CURRENCY_POUNDS;
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_measurement_format(){
|
||||
/*
|
||||
UINT measurement_system;
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
|
||||
(LPSTR)&measurement_system,
|
||||
sizeof(measurement_system)) == 0){
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
}
|
||||
switch (measurement_system){
|
||||
case 0:
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
case 1:
|
||||
default:
|
||||
return MEASUREMENT_FORMAT_IMPERIAL;
|
||||
}*/
|
||||
STUB();
|
||||
return MEASUREMENT_FORMAT_METRIC;
|
||||
}
|
||||
|
||||
uint8 platform_get_locale_temperature_format(){
|
||||
/*
|
||||
// There does not seem to be a function to obtain this, just check the countries
|
||||
UINT country;
|
||||
if (GetLocaleInfo(LOCALE_USER_DEFAULT,
|
||||
LOCALE_IMEASURE | LOCALE_RETURN_NUMBER,
|
||||
(LPSTR)&country,
|
||||
sizeof(country)) == 0){
|
||||
return TEMPERATURE_FORMAT_C;
|
||||
}
|
||||
switch (country){
|
||||
case CTRY_UNITED_STATES:
|
||||
case CTRY_BELIZE:
|
||||
return TEMPERATURE_FORMAT_F;
|
||||
default:
|
||||
return TEMPERATURE_FORMAT_C;
|
||||
}
|
||||
*/
|
||||
STUB();
|
||||
return TEMPERATURE_FORMAT_C;
|
||||
}
|
||||
#endif // __linux
|
|
@ -147,6 +147,7 @@ uint8 platform_get_locale_temperature_format();
|
|||
#define _strcmpi _stricmp
|
||||
#define _stricmp(x, y) strcasecmp((x), (y))
|
||||
#define _strnicmp(x, y, n) strncasecmp((x), (y), (n))
|
||||
#define _strdup(x) strdup((x))
|
||||
|
||||
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define RCT2_ENDIANESS __ORDER_LITTLE_ENDIAN__
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
|
@ -31,14 +31,16 @@
|
|||
// {
|
||||
// if (cmdline_run(argv, argc))
|
||||
// openrct2_launch();
|
||||
//
|
||||
//
|
||||
// return gExitCode;
|
||||
// }
|
||||
|
||||
/*
|
||||
char platform_get_path_separator()
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
*/
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
|
12
src/rct2.h
12
src/rct2.h
|
@ -1,9 +1,9 @@
|
|||
/*****************************************************************************
|
||||
* Copyright (c) 2014 Ted John
|
||||
* OpenRCT2, an open source clone of Roller Coaster Tycoon 2.
|
||||
*
|
||||
*
|
||||
* This file is part of OpenRCT2.
|
||||
*
|
||||
*
|
||||
* OpenRCT2 is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
|
@ -17,7 +17,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*****************************************************************************/
|
||||
|
||||
|
||||
#ifndef _RCT2_H_
|
||||
#define _RCT2_H_
|
||||
|
||||
|
@ -206,7 +206,11 @@ enum {
|
|||
// rct2 @ 0x0097F67C
|
||||
static const char * const file_paths[] =
|
||||
{
|
||||
"Data\\G1.DAT",
|
||||
#ifdef _WIN32
|
||||
"data\\g1.dat",
|
||||
#else
|
||||
"data/g1.dat",
|
||||
#endif // _WIN32
|
||||
"Data\\PLUGIN.DAT",
|
||||
"Data\\CSS1.DAT",
|
||||
"Data\\CSS2.DAT",
|
||||
|
|
Loading…
Reference in New Issue