Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add port to original Xbox using nxdk #1

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,8 @@ build
hode
hode.ini
setup.cfg
*.obj
*.exe
*.lib
*.iso
bin/
31 changes: 31 additions & 0 deletions Makefile.nxdk
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
NXDK_DIR = /home/fox/Data/Projects/XboxDev/nxdk

XBE_TITLE = "Heart of Darkness"
GEN_XISO = Heart_of_Darkness-Original_Xbox.iso

CXXFLAGS = -Wall -Wpedantic

SRCS += andy.cpp benchmark.cpp fileio.cpp fs_win32.cpp game.cpp \
level1_rock.cpp level2_fort.cpp level3_pwr1.cpp level4_isld.cpp \
level5_lava.cpp level6_pwr2.cpp level7_lar1.cpp level8_lar2.cpp level9_dark.cpp \
lzw.cpp main.cpp mdec.cpp menu.cpp mixer.cpp monsters.cpp paf.cpp random.cpp \
resource.cpp screenshot.cpp sound.cpp staticres.cpp system_sdl2.cpp \
util.cpp video.cpp

SCALERS := scaler_nearest.cpp #FIXME: scaler_xbr.cpp is broken in nxdk
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: The XBR scaler is broken; the linker will throw a warning and the result XBE will not launch. I assume cxbe can't handle files with dllexports?


SRCS += $(SCALERS)

SRCS += 3p/libxbr-standalone/xbr.c 3p/inih/ini.c

all_local: data all

include $(NXDK_DIR)/Makefile

data:
@mkdir -p $(OUTPUT_DIR)
cp README.txt $(OUTPUT_DIR)/
cp RELEASES.yaml $(OUTPUT_DIR)/

NXDK_SDL = y
include $(NXDK_DIR)/Makefile
1 change: 0 additions & 1 deletion fileio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
* Copyright (C) 2009-2011 Gregory Montoir ([email protected])
*/

#include <sys/param.h>
#include "fileio.h"
#include "util.h"

Expand Down
101 changes: 101 additions & 0 deletions fs_win32.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@

#include <assert.h>
#include <windows.h>
#ifndef NXDK
#include <stdlib.h>
#else
#define _MAX_PATH 200 //FIXME: Get real value for Xbox?
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: This should be fixed upstream so we no longer need this different code-path

#endif
#include "fs.h"
#include "util.h"

static const char *_suffixes[] = {
"setup.dat",
"setup.dax",
".paf",
"_hod.lvl",
"_hod.sss",
"_hod.mst",
0
};

static bool matchGameData(const char *path) {
const int len = strlen(path);
for (int i = 0; _suffixes[i]; ++i) {
const int suffixLen = strlen(_suffixes[i]);
if (len >= suffixLen && strcasecmp(path + len - suffixLen, _suffixes[i]) == 0) {
return true;
}
}
return false;
}

FileSystem::FileSystem(const char *dataPath, const char *savePath)
: _dataPath(dataPath), _savePath(savePath), _filesCount(0), _filesList(0) {
listFiles(dataPath);
}

FileSystem::~FileSystem() {
for (int i = 0; i < _filesCount; ++i) {
free(_filesList[i]);
}
free(_filesList);
}

FILE *FileSystem::openAssetFile(const char *name) {
FILE *fp = 0;
for (int i = 0; i < _filesCount; ++i) {
const char *p = strrchr(_filesList[i], '\\');
assert(p);
if (strcasecmp(name, p + 1) == 0) {
fp = fopen(_filesList[i], "rb");
break;
}
}
return fp;
}

FILE *FileSystem::openSaveFile(const char *filename, bool write) {
char path[_MAX_PATH];
snprintf(path, sizeof(path), "%s\\%s", _savePath, filename);
return fopen(path, write ? "wb" : "rb");
}

int FileSystem::closeFile(FILE *fp) {
const int err = ferror(fp);
fclose(fp);
return err;
}

void FileSystem::addFilePath(const char *path) {
_filesList = (char **)realloc(_filesList, (_filesCount + 1) * sizeof(char *));
if (_filesList) {
_filesList[_filesCount] = strdup(path);
++_filesCount;
}
}

void FileSystem::listFiles(const char *dir) {
char filePath[_MAX_PATH];
WIN32_FIND_DATAA de;
snprintf(filePath, sizeof(filePath), "%s\\*", dir);
HANDLE d = FindFirstFileA(filePath, &de);
if (d != INVALID_HANDLE_VALUE) {
BOOL found = TRUE;
while (1) {
if (de.cFileName[0] == '.') {
continue;
}
snprintf(filePath, sizeof(filePath), "%s\\%s", dir, de.cFileName);
if (de.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
listFiles(filePath);
} else if (matchGameData(filePath)) {
addFilePath(filePath);
}
if(!FindNextFileA(d, &de)) {
break;
}
}
CloseHandle(d);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bug; from MSDN:

When the search handle is no longer needed, close it by using the FindClose function, not CloseHandle.

CC @tuxuser

}
}
71 changes: 70 additions & 1 deletion main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@
*/

#include <SDL.h>
#if !defined(NXDK)
#include <getopt.h>
#include <sys/stat.h>
#endif
#include <stdlib.h>

#include "3p/inih/ini.h"

Expand All @@ -21,11 +24,34 @@
#ifdef __SWITCH__
#include <switch.h>
#endif
#if defined(NXDK)
#include <windows.h>
#include <nxdk/mount.h>
#include <hal/video.h>
#include <hal/debug.h>

extern "C" {
extern uint8_t* _fb;
}
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: This works around a bug in nxdk video.h


void * __cdecl operator new(unsigned int size) {
void *ptr = malloc(size);
memset(ptr, 0x00, size);
return ptr;
}

void __cdecl operator delete(void *ptr) {
free(ptr);
}
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: new and delete should be from libcxx. Why don't we seem to have those?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requires NXDK_CXX = y in Makefile. Not fixed yet.

#endif


static const char *_title = "Heart of Darkness";

#ifdef __vita__
static const char *_configIni = "ux0:data/hode/hode.ini";
#elif defined(NXDK)
static const char *_configIni = "D:\\hode.ini";
#else
static const char *_configIni = "hode.ini";
#endif
Expand Down Expand Up @@ -116,8 +142,10 @@ static int handleConfigIni(void *userdata, const char *section, const char *name
g_system->setScaler(0, scale);
} else if (strcmp(name, "scale_algorithm") == 0) {
g_system->setScaler(value, 0);
#if !defined(NXDK)
} else if (strcmp(name, "gamma") == 0) {
g_system->setGamma(atof(value));
#endif
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: nxdk lacks atof

} else if (strcmp(name, "fullscreen") == 0) {
_fullscreen = configBool(value);
} else if (strcmp(name, "widescreen") == 0) {
Expand All @@ -127,14 +155,46 @@ static int handleConfigIni(void *userdata, const char *section, const char *name
return 0;
}


int main(int argc, char *argv[]) {
#ifdef __SWITCH__
socketInitializeDefault();
nxlinkStdio();
#endif
#if defined(NXDK)
// set display mode
XVideoSetMode(640, 480, 32, REFRESH_DEFAULT);
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: Check wether game works on all refresh rates? Also switch to 16bpp mode?


#if 1
// we consume a lot of memory, so we need to claim the framebuffer
size_t fb_size = 640 * 480 * 4;
_fb = (uint8_t*)MmAllocateContiguousMemoryEx(fb_size, 0, 0xFFFFFFFF, 0x1000, PAGE_READWRITE | PAGE_WRITECOMBINE);
memset(_fb, 0x00, fb_size);
#define _PCRTC_START 0xFD600800
*(unsigned int*)(_PCRTC_START) = (unsigned int)_fb & 0x03FFFFFF;
#endif
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME: This works around a bug in nxdk video.h


// nxdk needs this hint to work around bugs
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");

#endif
#ifdef __vita__
const char *dataPath = "ux0:data/hode";
const char *savePath = "ux0:data/hode";
#elif defined(NXDK)
const char *dataPath = "D:";
const char *savePath = "E:\\UDATA\\hode";

// mount save partition
BOOL mounted = nxMountDrive('E', "\\Device\\Harddisk0\\Partition1\\");
assert(mounted);

// create save directory with metadata
if (CreateDirectoryA(savePath, NULL)) {
FILE* titleMetaFile = fopen("E:\\UDATA\\hode\\TitleMeta.xbx", "wb");
fprintf(titleMetaFile, "TitleName=Heart of Darkness\r\n");
fclose(titleMetaFile);
}
#else
char *dataPath = 0;
char *savePath = 0;
Expand All @@ -146,6 +206,7 @@ int main(int argc, char *argv[]) {
g_debugMask = 0; //kDebug_GAME | kDebug_RESOURCE | kDebug_SOUND | kDebug_MONSTER;
int cheats = 0;

#if !defined(NXDK)
if (argc == 2) {
// data path as the only command line argument
struct stat st;
Expand Down Expand Up @@ -203,6 +264,7 @@ int main(int argc, char *argv[]) {
return -1;
}
}
#endif
Game *g = new Game(dataPath ? dataPath : _defaultDataPath, savePath ? savePath : _defaultSavePath, cheats);
ini_parse(_configIni, handleConfigIni, g);
if (_runBenchmark) {
Expand Down Expand Up @@ -238,12 +300,19 @@ int main(int argc, char *argv[]) {
g->_mix.fini();
g_system->destroy();
delete g;
#ifndef __vita__
#if !defined(__vita__) && !defined(NXDK)
free(dataPath);
free(savePath);
#endif
#ifdef __SWITCH__
socketExit();
#endif
#if defined(NXDK)
// turn screen black (disable DACs instead?)
memset(_fb, 0x00, fb_size);

// we will reboot to menu
HalReturnToFirmware(HalQuickRebootRoutine);
#endif
return 0;
}
Loading