mirror of https://github.com/decompals/wibo.git
3 funcs needed for some mwcc compilers (#22)
* 3 funcs needed for some mwcc compilers * some PR feedback * lots more via pair programming with Simon * cleanup, add test dir as an include dir for tests * bugfix
This commit is contained in:
parent
ffe30a626b
commit
6de4e9a163
|
@ -23,7 +23,7 @@ jobs:
|
||||||
run: |
|
run: |
|
||||||
wget https://cdn.discordapp.com/attachments/727918646525165659/917185027656286218/GC_WII_COMPILERS.zip
|
wget https://cdn.discordapp.com/attachments/727918646525165659/917185027656286218/GC_WII_COMPILERS.zip
|
||||||
unzip GC_WII_COMPILERS.zip
|
unzip GC_WII_COMPILERS.zip
|
||||||
MWCIncludes=. build/wibo GC/2.7/mwcceppc.exe -c test/test.c
|
MWCIncludes=. build/wibo GC/2.7/mwcceppc.exe -c test/test.c -Itest
|
||||||
file test.o
|
file test.o
|
||||||
|
|
||||||
- name: Upload build
|
- name: Upload build
|
||||||
|
|
|
@ -16,6 +16,7 @@ add_executable(wibo
|
||||||
dll/user32.cpp
|
dll/user32.cpp
|
||||||
dll/version.cpp
|
dll/version.cpp
|
||||||
files.cpp
|
files.cpp
|
||||||
|
handles.cpp
|
||||||
loader.cpp
|
loader.cpp
|
||||||
main.cpp
|
main.cpp
|
||||||
)
|
)
|
||||||
|
|
165
dll/kernel32.cpp
165
dll/kernel32.cpp
|
@ -1,12 +1,15 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "handles.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
|
#include <fnmatch.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
#include <sys/mman.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
|
||||||
namespace kernel32 {
|
namespace kernel32 {
|
||||||
|
@ -85,6 +88,17 @@ namespace kernel32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t getFileSize(void* hFile) {
|
||||||
|
FILE *fp = files::fpFromHandle(hFile);
|
||||||
|
struct stat64 st;
|
||||||
|
fflush(fp);
|
||||||
|
if (fstat64(fileno(fp), &st) == -1 || !S_ISREG(st.st_mode)) {
|
||||||
|
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND (?)
|
||||||
|
return -1; // INVALID_FILE_SIZE
|
||||||
|
}
|
||||||
|
return st.st_size;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t WIN_FUNC GetLastError() {
|
uint32_t WIN_FUNC GetLastError() {
|
||||||
return wibo::lastError;
|
return wibo::lastError;
|
||||||
}
|
}
|
||||||
|
@ -384,9 +398,14 @@ namespace kernel32 {
|
||||||
|
|
||||||
int WIN_FUNC CloseHandle(void *hObject) {
|
int WIN_FUNC CloseHandle(void *hObject) {
|
||||||
DEBUG_LOG("CloseHandle %p\n", hObject);
|
DEBUG_LOG("CloseHandle %p\n", hObject);
|
||||||
FILE *fp = files::fpFromHandle(hObject, true);
|
auto data = handles::dataFromHandle(hObject, true);
|
||||||
if (fp && fp != stdin && fp != stdout && fp != stderr) {
|
if (data.type == handles::TYPE_FILE) {
|
||||||
fclose(fp);
|
FILE *fp = (FILE *) data.ptr;
|
||||||
|
if (!(fp == stdin || fp == stdout || fp == stderr)) {
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
} else if (data.type == handles::TYPE_MAPPED) {
|
||||||
|
munmap(data.ptr, data.size);
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -442,6 +461,41 @@ namespace kernel32 {
|
||||||
CharType cAlternateFileName[14];
|
CharType cAlternateFileName[14];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct FindFirstFileHandle {
|
||||||
|
std::filesystem::directory_iterator it;
|
||||||
|
std::string pattern;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool findNextFile(FindFirstFileHandle *handle) {
|
||||||
|
while (handle->it != std::filesystem::directory_iterator()) {
|
||||||
|
std::filesystem::path path = *handle->it;
|
||||||
|
if (fnmatch(handle->pattern.c_str(), path.filename().c_str(), 0) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
handle->it++;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setFindFileDataFromPath(WIN32_FIND_DATA<char>* data, const std::filesystem::path &path) {
|
||||||
|
auto status = std::filesystem::status(path);
|
||||||
|
uint64_t fileSize = 0;
|
||||||
|
data->dwFileAttributes = 0;
|
||||||
|
if (std::filesystem::is_directory(status)) {
|
||||||
|
data->dwFileAttributes |= 0x10;
|
||||||
|
}
|
||||||
|
if (std::filesystem::is_regular_file(status)) {
|
||||||
|
data->dwFileAttributes |= 0x80;
|
||||||
|
fileSize = std::filesystem::file_size(path);
|
||||||
|
}
|
||||||
|
data->nFileSizeHigh = (uint32_t)(fileSize >> 32);
|
||||||
|
data->nFileSizeLow = (uint32_t)fileSize;
|
||||||
|
auto fileName = path.filename().string();
|
||||||
|
assert(fileName.size() < 260);
|
||||||
|
strcpy(data->cFileName, fileName.c_str());
|
||||||
|
strcpy(data->cAlternateFileName, "8P3FMTFN.BAD");
|
||||||
|
}
|
||||||
|
|
||||||
void *WIN_FUNC FindFirstFileA(const char *lpFileName, WIN32_FIND_DATA<char> *lpFindFileData) {
|
void *WIN_FUNC FindFirstFileA(const char *lpFileName, WIN32_FIND_DATA<char> *lpFindFileData) {
|
||||||
// This should handle wildcards too, but whatever.
|
// This should handle wildcards too, but whatever.
|
||||||
auto path = files::pathFromWindows(lpFileName);
|
auto path = files::pathFromWindows(lpFileName);
|
||||||
|
@ -453,23 +507,40 @@ namespace kernel32 {
|
||||||
|
|
||||||
auto status = std::filesystem::status(path);
|
auto status = std::filesystem::status(path);
|
||||||
if (status.type() == std::filesystem::file_type::regular) {
|
if (status.type() == std::filesystem::file_type::regular) {
|
||||||
lpFindFileData->dwFileAttributes = 0x80; // FILE_ATTRIBUTE_NORMAL
|
setFindFileDataFromPath(lpFindFileData, path);
|
||||||
auto fileSize = std::filesystem::file_size(path);
|
|
||||||
lpFindFileData->nFileSizeHigh = (uint32_t)(fileSize >> 32);
|
|
||||||
lpFindFileData->nFileSizeLow = (uint32_t)fileSize;
|
|
||||||
auto fileName = path.filename().string();
|
|
||||||
assert(fileName.size() < 260);
|
|
||||||
strcpy(lpFindFileData->cFileName, fileName.c_str());
|
|
||||||
strcpy(lpFindFileData->cAlternateFileName, "8P3FMTFN.BAD");
|
|
||||||
return (void *) 1;
|
return (void *) 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND
|
FindFirstFileHandle *handle = new FindFirstFileHandle();
|
||||||
return (void *) 0xFFFFFFFF;
|
std::filesystem::directory_iterator it(path.parent_path());
|
||||||
|
handle->it = it;
|
||||||
|
handle->pattern = path.filename().string();
|
||||||
|
|
||||||
|
if (!findNextFile(handle)) {
|
||||||
|
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND
|
||||||
|
delete handle;
|
||||||
|
return (void *) 0xFFFFFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFindFileDataFromPath(lpFindFileData, *handle->it++);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
int WIN_FUNC FindNextFileA(void *hFindFile, WIN32_FIND_DATA<char> *lpFindFileData) {
|
||||||
|
FindFirstFileHandle *handle = (FindFirstFileHandle *) hFindFile;
|
||||||
|
if (!findNextFile(handle)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
setFindFileDataFromPath(lpFindFileData, *handle->it++);
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int WIN_FUNC FindClose(void *hFindFile) {
|
int WIN_FUNC FindClose(void *hFindFile) {
|
||||||
DEBUG_LOG("FindClose\n");
|
DEBUG_LOG("FindClose\n");
|
||||||
|
if (hFindFile != (void *) 1) {
|
||||||
|
delete (FindFirstFileHandle *)hFindFile;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,6 +651,55 @@ namespace kernel32 {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *WIN_FUNC CreateFileMappingA(
|
||||||
|
void *hFile,
|
||||||
|
void *lpFileMappingAttributes,
|
||||||
|
unsigned int flProtect,
|
||||||
|
unsigned int dwMaximumSizeHigh,
|
||||||
|
unsigned int dwMaximumSizeLow,
|
||||||
|
const char *lpName) {
|
||||||
|
DEBUG_LOG("CreateFileMappingA(%p, %p, %u, %u, %u, %s)\n", hFile, lpFileMappingAttributes, flProtect, dwMaximumSizeHigh, dwMaximumSizeLow, lpName);
|
||||||
|
|
||||||
|
int64_t size = (int64_t) dwMaximumSizeHigh << 32 | dwMaximumSizeLow;
|
||||||
|
|
||||||
|
void* mmapped;
|
||||||
|
|
||||||
|
if (hFile == (void*) -1) { // INVALID_HANDLE_VALUE
|
||||||
|
mmapped = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
|
||||||
|
} else {
|
||||||
|
int fd = fileno(files::fpFromHandle(hFile));
|
||||||
|
|
||||||
|
if (size == 0) {
|
||||||
|
size = getFileSize(hFile);
|
||||||
|
if (size == -1) {
|
||||||
|
return (void*) -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mmapped = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(mmapped != MAP_FAILED);
|
||||||
|
return handles::allocDataHandle({handles::TYPE_MAPPED, mmapped, (unsigned int) size});
|
||||||
|
}
|
||||||
|
|
||||||
|
void *WIN_FUNC MapViewOfFile(
|
||||||
|
void *hFileMappingObject,
|
||||||
|
unsigned int dwDesiredAccess,
|
||||||
|
unsigned int dwFileOffsetHigh,
|
||||||
|
unsigned int dwFileOffsetLow,
|
||||||
|
unsigned int dwNumberOfBytesToMap) {
|
||||||
|
DEBUG_LOG("MapViewOfFile(%p, %u, %u, %u, %u)\n", hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, dwFileOffsetLow, dwNumberOfBytesToMap);
|
||||||
|
|
||||||
|
handles::Data data = handles::dataFromHandle(hFileMappingObject, false);
|
||||||
|
assert(data.type == handles::TYPE_MAPPED);
|
||||||
|
return (void*)((unsigned int) data.ptr + dwFileOffsetLow);
|
||||||
|
}
|
||||||
|
|
||||||
|
int WIN_FUNC UnmapViewOfFile(void *lpBaseAddress) {
|
||||||
|
DEBUG_LOG("UnmapViewOfFile(%p)\n", lpBaseAddress);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int WIN_FUNC DeleteFileA(const char* lpFileName) {
|
int WIN_FUNC DeleteFileA(const char* lpFileName) {
|
||||||
std::string path = files::pathFromWindows(lpFileName);
|
std::string path = files::pathFromWindows(lpFileName);
|
||||||
DEBUG_LOG("DeleteFileA %s (%s)\n", lpFileName, path.c_str());
|
DEBUG_LOG("DeleteFileA %s (%s)\n", lpFileName, path.c_str());
|
||||||
|
@ -637,18 +757,15 @@ namespace kernel32 {
|
||||||
|
|
||||||
unsigned int WIN_FUNC GetFileSize(void *hFile, unsigned int *lpFileSizeHigh) {
|
unsigned int WIN_FUNC GetFileSize(void *hFile, unsigned int *lpFileSizeHigh) {
|
||||||
DEBUG_LOG("GetFileSize\n");
|
DEBUG_LOG("GetFileSize\n");
|
||||||
struct stat64 st;
|
int64_t size = getFileSize(hFile);
|
||||||
FILE *fp = files::fpFromHandle(hFile);
|
if (size == -1) {
|
||||||
fflush(fp);
|
return 0xFFFFFFFF; // INVALID_FILE_SIZE
|
||||||
if (fstat64(fileno(fp), &st) == -1 || !S_ISREG(st.st_mode)) {
|
|
||||||
wibo::lastError = 2; // ERROR_FILE_NOT_FOUND (?)
|
|
||||||
return ~0u; // INVALID_FILE_SIZE
|
|
||||||
}
|
}
|
||||||
DEBUG_LOG("-> %ld\n", st.st_size);
|
DEBUG_LOG("-> %ld\n", size);
|
||||||
if (lpFileSizeHigh != nullptr) {
|
if (lpFileSizeHigh != nullptr) {
|
||||||
*lpFileSizeHigh = st.st_size >> 32;
|
*lpFileSizeHigh = size >> 32;
|
||||||
}
|
}
|
||||||
return st.st_size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1478,11 +1595,15 @@ void *wibo::resolveKernel32(const char *name) {
|
||||||
// fileapi.h
|
// fileapi.h
|
||||||
if (strcmp(name, "GetFullPathNameA") == 0) return (void *) kernel32::GetFullPathNameA;
|
if (strcmp(name, "GetFullPathNameA") == 0) return (void *) kernel32::GetFullPathNameA;
|
||||||
if (strcmp(name, "FindFirstFileA") == 0) return (void *) kernel32::FindFirstFileA;
|
if (strcmp(name, "FindFirstFileA") == 0) return (void *) kernel32::FindFirstFileA;
|
||||||
|
if (strcmp(name, "FindNextFileA") == 0) return (void *) kernel32::FindNextFileA;
|
||||||
if (strcmp(name, "FindClose") == 0) return (void *) kernel32::FindClose;
|
if (strcmp(name, "FindClose") == 0) return (void *) kernel32::FindClose;
|
||||||
if (strcmp(name, "GetFileAttributesA") == 0) return (void *) kernel32::GetFileAttributesA;
|
if (strcmp(name, "GetFileAttributesA") == 0) return (void *) kernel32::GetFileAttributesA;
|
||||||
if (strcmp(name, "WriteFile") == 0) return (void *) kernel32::WriteFile;
|
if (strcmp(name, "WriteFile") == 0) return (void *) kernel32::WriteFile;
|
||||||
if (strcmp(name, "ReadFile") == 0) return (void *) kernel32::ReadFile;
|
if (strcmp(name, "ReadFile") == 0) return (void *) kernel32::ReadFile;
|
||||||
if (strcmp(name, "CreateFileA") == 0) return (void *) kernel32::CreateFileA;
|
if (strcmp(name, "CreateFileA") == 0) return (void *) kernel32::CreateFileA;
|
||||||
|
if (strcmp(name, "CreateFileMappingA") == 0) return (void *) kernel32::CreateFileMappingA;
|
||||||
|
if (strcmp(name, "MapViewOfFile") == 0) return (void *) kernel32::MapViewOfFile;
|
||||||
|
if (strcmp(name, "UnmapViewOfFile") == 0) return (void *) kernel32::UnmapViewOfFile;
|
||||||
if (strcmp(name, "DeleteFileA") == 0) return (void *) kernel32::DeleteFileA;
|
if (strcmp(name, "DeleteFileA") == 0) return (void *) kernel32::DeleteFileA;
|
||||||
if (strcmp(name, "SetFilePointer") == 0) return (void *) kernel32::SetFilePointer;
|
if (strcmp(name, "SetFilePointer") == 0) return (void *) kernel32::SetFilePointer;
|
||||||
if (strcmp(name, "SetEndOfFile") == 0) return (void *) kernel32::SetEndOfFile;
|
if (strcmp(name, "SetEndOfFile") == 0) return (void *) kernel32::SetEndOfFile;
|
||||||
|
|
30
files.cpp
30
files.cpp
|
@ -1,9 +1,10 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
|
#include "handles.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
namespace files {
|
namespace files {
|
||||||
static FILE *handleFps[0x10000];
|
|
||||||
|
|
||||||
static void *stdinHandle;
|
static void *stdinHandle;
|
||||||
static void *stdoutHandle;
|
static void *stdoutHandle;
|
||||||
|
@ -68,28 +69,19 @@ namespace files {
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE *fpFromHandle(void *handle, bool pop) {
|
FILE *fpFromHandle(void *handle, bool pop) {
|
||||||
uintptr_t index = (uintptr_t)handle;
|
handles::Data data = handles::dataFromHandle(handle, pop);
|
||||||
if (index > 0 && index < 0x10000) {
|
if (data.type == handles::TYPE_FILE) {
|
||||||
FILE *ret = handleFps[index];
|
return (FILE*)data.ptr;
|
||||||
if (pop)
|
} else if (data.type == handles::TYPE_UNUSED && pop) {
|
||||||
handleFps[index] = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
if (pop)
|
|
||||||
return 0;
|
return 0;
|
||||||
printf("Invalid file handle %p\n", handle);
|
} else {
|
||||||
assert(0);
|
printf("Invalid file handle %p\n", handle);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void *allocFpHandle(FILE *fp) {
|
void *allocFpHandle(FILE *fp) {
|
||||||
for (int i = 1; i < 0x10000; i++) {
|
return handles::allocDataHandle(handles::Data{handles::TYPE_FILE, fp, 0});
|
||||||
if (!handleFps[i]) {
|
|
||||||
handleFps[i] = fp;
|
|
||||||
return (void*)i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
printf("Out of file handles\n");
|
|
||||||
assert(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *getStdHandle(uint32_t nStdHandle) {
|
void *getStdHandle(uint32_t nStdHandle) {
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include "common.h"
|
||||||
|
#include "handles.h"
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace handles {
|
||||||
|
static Data datas[0x10000];
|
||||||
|
|
||||||
|
Data dataFromHandle(void *handle, bool pop) {
|
||||||
|
uintptr_t index = (uintptr_t)handle;
|
||||||
|
if (index > 0 && index < 0x10000) {
|
||||||
|
Data ret = datas[index];
|
||||||
|
if (pop)
|
||||||
|
datas[index] = Data{};
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (pop)
|
||||||
|
return Data{};
|
||||||
|
printf("Invalid file handle %p\n", handle);
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *allocDataHandle(Data data) {
|
||||||
|
for (int i = 1; i < 0x10000; i++) {
|
||||||
|
if (datas[i].type == TYPE_UNUSED) {
|
||||||
|
datas[i] = data;
|
||||||
|
return (void*)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Out of handles\n");
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace handles {
|
||||||
|
enum Type {
|
||||||
|
TYPE_UNUSED,
|
||||||
|
TYPE_FILE,
|
||||||
|
TYPE_MAPPED,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
Type type = TYPE_UNUSED;
|
||||||
|
void *ptr;
|
||||||
|
size_t size;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data dataFromHandle(void *handle, bool pop);
|
||||||
|
void *allocDataHandle(Data data);
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
#define SOMETHING 3
|
|
@ -1,6 +1,8 @@
|
||||||
|
#include "another.inc.c"
|
||||||
|
|
||||||
float apple = 3.0f;
|
float apple = 3.0f;
|
||||||
float banana = 65.32f;
|
float banana = 65.32f;
|
||||||
|
|
||||||
int something(void) {
|
int something(void) {
|
||||||
return (int)(apple * banana) % 11;
|
return (int)(apple * banana) % 11 + SOMETHING;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue