Compare commits

...

6 Commits

16 changed files with 320 additions and 37 deletions

50
README-OS4.md Normal file
View File

@ -0,0 +1,50 @@
# The Battle for the Solar System : The Pandoran War
This is the port of the "The Battle for the Solar System : The Pandoran War"
v1.50.1 for the AmigaOS 4.
The Pandoran War is a 2D mission-based space shooter based on the BATTLE FOR
THE SOLAR SYSTEM space opera and set between books two and three: THE THIRD
SIDE and THE ATTTRIBUTE OF THE STRONG. The game features many missions,
with many different objectives and craft.
It requires a fast system to play the game as fast as possible, and a
graphics card that supports either opengl/opengles2 with SDL2.
It is tested and runs well on X5000/40 with a RadeonRX 550.
This archive does not contain any data files. In order to play the game, you
need to download the data separately. From the following website download
the "tbftss-1.5.1.linux-x86_64.tar.gz" file.
https://www.battleforthesolarsystem.com/games/pw/#downloads
To install it, extract the data file anywhere at you hard disk
and copy over all the files from this archive. A requester will show up
to replace some files, which you need to confirm for all of them.
If you like the game and would like to support its developer, you can go and
buy it at:
https://parallelrealities.itch.io/tbftss-the-pandoran-war
### How to make it faster
The game should run in 60fps but on my test system I get around 30fps with all
the effects enabled. That's why I introduced an option at the Options screen,
named "Effects Reduction" with values from 0 to 3. With 0 you have full effects
everywhere, and with 3 you have less effects shown. That increases a lot the
speed, but you might still see slowdowns in situations where there is a lot of
action on the screen.
It is recommended to open the SDL2 prefs and set the Driver to opengl/opengl2
depending your gfx card and the drivers you have installed.
On my system "Batching Mode: enabled" leads to some crashes. I recommend you
to set this to default. But feel free to experiment with it, in case it
works better for you.
I'd love to hear how it works on your system.
### Changelog
1.50.1r1 (2022-08-22)
* First release

View File

@ -50,8 +50,11 @@ $(OUT)/%.o: %.c %.h $(DEPS)
$(CC) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
%.mo: %.po
ifneq ($(shell uname), AmigaOS)
msgfmt -c -o $@ $<
endif
# cleaning everything that can be automatically recreated with "make".
clean:
$(RM) $(OBJS) $(PROG) $(LOCALE_MO)

View File

@ -1,6 +1,7 @@
{
"winWidth" : 1280,
"winHeight" : 720,
"effects" : 0,
"fullscreen" : 0,
"musicVolume" : 8,
"soundVolume" : 10,
@ -41,3 +42,4 @@
"healthBars" : 1
}
}

View File

@ -10,6 +10,17 @@
"w" : 400,
"h": 34
},
{
"name" : "effects",
"group" : "options",
"type" : "WT_SELECT",
"text" : "Effects Reduction",
"options" : "0;1;2;3",
"x" : -1,
"y" : 225,
"w" : 400,
"h": 34
},
{
"name" : "soundVolume",
"group" : "options",
@ -17,7 +28,7 @@
"text" : "Sound Volume",
"options" : "0;1;2;3;4;5;6;7;8;9;10",
"x" : -1,
"y" : 250,
"y" : 275,
"w" : 400,
"h": 34
},
@ -64,3 +75,4 @@
"h": 34
}
]

BIN
icons/tbftss.info Normal file

Binary file not shown.

53
makefile.os4 Normal file
View File

@ -0,0 +1,53 @@
PROG = tbftss
CC = gcc-11
PREFIX ?= /usr
BIN_DIR ?= $(PREFIX)/bin
DATA_DIR ?= data
LOCALE_DIR = locale
ICON_DIR = $(PREFIX)/share/icons/hicolor
DESKTOP_DIR = $(PREFIX)/share/applications
DESTDIR ?=
INST_BIN_DIR = $(DESTDIR)$(BIN_DIR)
INST_DATA_DIR = $(DESTDIR)$(DATA_DIR)
INST_LOCALE_DIR = $(DESTDIR)$(LOCALE_DIR)
INST_ICON_DIR = $(DESTDIR)$(ICON_DIR)
INST_DESKTOP_DIR = $(DESTDIR)$(DESKTOP_DIR)
SEARCHPATH += src/plat/os4
_OBJS += os4Init.o
include common.mk
CXXFLAGS += -DVERSION=$(VERSION) -DREVISION=$(REVISION) -DDATA_DIR=\"$(DATA_DIR)\" -DLOCALE_DIR=\"$(LOCALE_DIR)\" -D__USE_INLINE__
CXXFLAGS += -pedantic
CXXFLAGS += -g -lefence
CXXFLAGS += -Wall -Wempty-body -Werror -Wstrict-prototypes -Werror=maybe-uninitialized -Warray-bounds
# CXXFLAGS += -gstabs
LDFLAGS += -lauto -lSDL2_image -lSDL2_ttf -lft2 -ltiff -lwebp -lpng -ljpeg -lz -lm
LDFLAGS += -lSDL2_mixer -lmikmod -lmodplug -lFLAC -lsmpeg2 -lvorbisfile -lvorbis -logg
LDFLAGS += -lSDL2 -lpthread -athread=native -lstdc++
# LDFLAGS += -gstabs
# linking the program.
$(PROG): $(OBJS)
$(CC) -o $@ $(OBJS) $(LDFLAGS)
# prepare an archive for the program
dist:
mkdir -p release/$(PROG)-$(VERSION).$(REVISION)/data/app
mkdir -p release/$(PROG)-$(VERSION).$(REVISION)/data/widgets
cp $(PROG) release/$(PROG)-$(VERSION).$(REVISION)/
strip release/$(PROG)-$(VERSION).$(REVISION)/$(PROG)
cp icons/tbftss.info release/$(PROG)-$(VERSION).$(REVISION)/$(PROG).info
cp data/app/config.json release/$(PROG)-$(VERSION).$(REVISION)/data/app/
cp data/widgets/options.json release/$(PROG)-$(VERSION).$(REVISION)/data/widgets/
cp LICENSE release/$(PROG)-$(VERSION).$(REVISION)/
cp README.md release/$(PROG)-$(VERSION).$(REVISION)/
cp README-OS4.md release/$(PROG)-$(VERSION).$(REVISION)/
lha -aeqr3 a $(PROG)-$(VERSION).$(REVISION).lha release/
.PHONY: dist

View File

@ -24,6 +24,7 @@ static void setRandomFlameHue(Effect *e);
static void setRandomShieldHue(Effect *e);
static void resizeDrawList(void);
static int pointOnScreen(float x, float y);
static float calculateEffectsValue(unsigned int);
static AtlasImage *explosionTexture;
static AtlasImage *shieldHitTexture;
@ -202,7 +203,7 @@ void addBulletHitEffect(int x, int y, int r, int g, int b)
e->type = EFFECT_TEXTURE;
e->texture = explosionTexture;
e->size = 16;
e->size = calculateEffectsValue(16);
e->x = x;
e->y = y;
@ -215,7 +216,7 @@ void addBulletHitEffect(int x, int y, int r, int g, int b)
e->g = g;
e->b = b;
e->a = 64;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
}
}
@ -233,12 +234,12 @@ void addSmallFighterExplosion(void)
e->x = self->x + (rand() % 16 - rand() % 16);
e->y = self->y + (rand() % 16 - rand() % 16);
e->texture = explosionTexture;
e->size = 32;
e->size = calculateEffectsValue(32);
setRandomFlameHue(e);
e->a = 128 + (rand() % 128);
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -258,12 +259,12 @@ void addDebrisFire(int x, int y)
e->x = x + (rand() % 8 - rand() % 8);
e->y = y + (rand() % 8 - rand() % 8);
e->texture = explosionTexture;
e->size = 4 + rand() % 12;
e->size = calculateEffectsValue(4 + rand() % 12);
setRandomFlameHue(e);
e->a = rand() % 256;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -290,13 +291,13 @@ void addSmallExplosion(void)
e->dy = (rand() % 25) - (rand() % 25);
e->dy *= 0.025;
e->texture = explosionTexture;
e->size = 32 + (rand() % 64);
e->size = calculateEffectsValue(32 + (rand() % 64));
e->r = 255;
setRandomFlameHue(e);
e->a = 128 + (rand() % 128);
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -318,7 +319,7 @@ void addSmallExplosion(void)
e->dy *= 0.1;
e->a = 128;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
setRandomFlameHue(e);
}
@ -341,13 +342,13 @@ void addMineExplosion(void)
e->x = self->x + rand() % 64 - rand() % 64;
e->y = self->y + rand() % 64 - rand() % 64;
e->texture = explosionTexture;
e->size = 64 + (rand() % 64);
e->size = calculateEffectsValue(64 + (rand() % 64));
e->r = 255;
setRandomFlameHue(e);
e->a = 32 + (rand() % 192);
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -362,7 +363,7 @@ void addMineExplosion(void)
e->type = EFFECT_HALO;
e->x = self->x;
e->y = self->y;
e->size = 64;
e->size = calculateEffectsValue(64);
e->scaleAmount = 6;
e->texture = haloTexture;
@ -371,7 +372,7 @@ void addMineExplosion(void)
e->b = 255;
e->a = 128;
e->health = 128;
e->health = calculateEffectsValue(128);
}
void addLargeExplosion(void)
@ -395,13 +396,13 @@ void addLargeExplosion(void)
e->dy = (rand() % 25) - (rand() % 25);
e->dy *= 0.01;
e->texture = explosionTexture;
e->size = 128 + (rand() % 512);
e->size = calculateEffectsValue(128 + (rand() % 512));
e->r = 255;
setRandomFlameHue(e);
e->a = 128 + (rand() % 128);
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -416,7 +417,7 @@ void addLargeExplosion(void)
e->type = EFFECT_HALO;
e->x = self->x;
e->y = self->y;
e->size = 256;
e->size = calculateEffectsValue(256);
e->scaleAmount = 4;
e->texture = haloTexture;
@ -425,7 +426,7 @@ void addLargeExplosion(void)
e->b = 255;
e->a = 255;
e->health = 255;
e->health = calculateEffectsValue(255);
}
void addMissileExplosion(Bullet *b)
@ -449,13 +450,13 @@ void addMissileExplosion(Bullet *b)
e->dy = (rand() % 25) - (rand() % 25);
e->dy *= 0.025;
e->texture = explosionTexture;
e->size = 32 + (rand() % 64);
e->size = calculateEffectsValue(32 + (rand() % 64));
e->r = 255;
setRandomFlameHue(e);
e->a = 128 + (rand() % 128);
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -477,7 +478,7 @@ void addMissileExplosion(Bullet *b)
e->dy *= 0.1;
e->a = 128;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
setRandomFlameHue(e);
}
@ -507,13 +508,13 @@ void addEngineEffect(void)
e->x += rand() % 4 - rand() % 4;
e->texture = explosionTexture;
e->size = 16;
e->size = calculateEffectsValue(16);
e->r = 128;
e->g = 128;
e->b = 255;
e->a = 64;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -540,13 +541,13 @@ void addLargeEngineEffect(void)
e->x -= rand() % 4;
e->texture = explosionTexture;
e->size = 64;
e->size = calculateEffectsValue(64);
e->r = 128;
e->g = 128;
e->b = 255;
e->a = 64;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -573,11 +574,11 @@ void addMissileEngineEffect(Bullet *b)
e->x -= rand() % 4;
e->texture = explosionTexture;
e->size = 12;
e->size = calculateEffectsValue(12);
setRandomFlameHue(e);
e->a = 128;
e->health = e->a;
e->health = calculateEffectsValue(e->a);
e->x -= e->size / 2;
e->y -= e->size / 2;
@ -695,3 +696,16 @@ void destroyEffects(void)
effectsToDraw = NULL;
}
static float calculateEffectsValue(unsigned int val)
{
#if defined(__amigaos4__)
if (app.effects)
{
return val / (app.effects * 2);
}
#endif
return (float)val;
}

View File

@ -80,7 +80,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#define NUM_ATLAS_BUCKETS 64
#define NUM_GLYPH_BUCKETS 128
#define MAX_STARS 500
#define MAX_STARS 100
#define MAX_CHALLENGES 3
@ -421,3 +421,4 @@ enum
TROPHY_UNEARNED,
TROPHY_MAX
};

View File

@ -21,6 +21,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "options.h"
static void changeWindowSize(char *value);
static void changeEffectsReduction(char *value);
static void changeSoundVolume(char *value);
static void changeMusicVolume(char *value);
static void changeFullscreen(char *value);
@ -41,6 +42,7 @@ void initOptions(void (*rtn)(void))
selectWidget("windowSize", "options");
getWidget("windowSize", "options")->onChange = changeWindowSize;
getWidget("effects", "options")->onChange = changeEffectsReduction;
getWidget("soundVolume", "options")->onChange = changeSoundVolume;
getWidget("musicVolume", "options")->onChange = changeMusicVolume;
getWidget("fullscreen", "options")->onChange = changeFullscreen;
@ -51,6 +53,9 @@ void initOptions(void (*rtn)(void))
sprintf(optionStr, "%d x %d", app.winWidth, app.winHeight);
setWidgetOption("windowSize", "options", optionStr);
sprintf(optionStr, "%d", app.effects);
setWidgetOption("effects", "options", optionStr);
sprintf(optionStr, "%d", app.soundVolume);
setWidgetOption("soundVolume", "options", optionStr);
@ -116,9 +121,11 @@ static void drawMain(void)
drawWidgets("options");
app.textWidth = r.w - 100;
#if !defined(__amigaos4__)
drawText(UI_WIDTH / 2, r.y + r.h - 135, 16, TA_CENTER, colors.yellow, RESOLUTION_TEXT);
#endif
app.textWidth = 0;
SDL_SetRenderTarget(app.renderer, app.backBuffer);
@ -172,6 +179,11 @@ static void changeWindowSize(char *value)
initStars();
}
static void changeEffectsReduction(char *value)
{
app.effects = atoi(value);
}
static void changeSoundVolume(char *value)
{
app.soundVolume = atoi(value);
@ -204,3 +216,4 @@ static void controlsOK(void)
{
show = SHOW_MAIN;
}

View File

@ -426,7 +426,7 @@ void awardStatsTrophies(void)
void awardCampaignTrophies(void)
{
char trophyId[MAX_NAME_LENGTH];
char trophyId[MAX_NAME_LENGTH * 2];
char name[MAX_NAME_LENGTH];
int i, len;
StarSystem *starSystem;
@ -533,3 +533,4 @@ static void setSparkleColor(Trophy *t)
break;
}
}

101
src/plat/os4/os4Init.c Normal file
View File

@ -0,0 +1,101 @@
/*
Copyright (C) 2015-2019,2022 Parallel Realities
This program 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 2
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <errno.h>
#include <pwd.h>
#include <sys/stat.h>
#include <unistd.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include "../../common.h"
#include "os4Init.h"
#define VSTRING "tbftss 1.50.1r1 (22.08.2022)"
#define VERSTAG "\0$VER: " VSTRING
static CONST_STRPTR stack USED = "$STACK:102400";
static CONST_STRPTR version USED = VERSTAG;
extern App app;
extern Dev dev;
void createSaveFolder(void)
{
// char *dir;
// int i;
BPTR savesPathLock = Lock("PROGDIR:saves", SHARED_LOCK);
if (!savesPathLock)
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "Saves folder not found. I am going to create it.");
// mkpath("PROGDIR:saves");
if (mkdir("PROGDIR:saves", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0 && errno != EEXIST)
{
SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to create save dir.");
return;
}
}
else {
UnLock(savesPathLock);
}
// for (i = 0 ; i < MAX_SAVE_SLOTS ; i++)
// {
// dir = buildFormattedString("saves/%d", i);
// mkpath(dir);
// free(dir);
// }
// app.saveDir = "saves";
STRNCPY(app.saveDir, "saves", MAX_FILENAME_LENGTH);
// char *userHome;
// char dir[MAX_FILENAME_LENGTH];
// userHome = getenv("HOME");
// if (!userHome)
// {
// SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Unable to determine user save folder. Will save to current dir.");
// return;
// }
// SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_INFO, "User home = %s", userHome);
// sprintf(dir, "%s/.local/share/tbftss", userHome);
// if (mkdir(dir, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH) != 0 && errno != EEXIST)
// {
// SDL_LogMessage(SDL_LOG_CATEGORY_APPLICATION, SDL_LOG_PRIORITY_WARN, "Failed to create save dir '%s'. Will save to current dir.", dir);
// return;
// }
// STRNCPY(app.saveDir, dir, MAX_FILENAME_LENGTH);
}
void createScreenshotFolder(void)
{
mkdir("PROGDIR:screenshots", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
dev.screenshotFolder = "screenshots";
}

22
src/plat/os4/os4Init.h Executable file
View File

@ -0,0 +1,22 @@
/*
Copyright (C) 2015-2019,2022 Parallel Realities
This program 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 2
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
void createScreenshotFolder(void);
void createSaveFolder(void);

View File

@ -521,6 +521,7 @@ typedef struct {
int keyControls[CONTROL_MAX];
int mouseControls[CONTROL_MAX];
int textWidth;
int effects;
} App;
typedef struct {
@ -576,3 +577,4 @@ typedef struct {
typedef struct {
int32_t length, offset;
} MOEntry;

View File

@ -261,8 +261,8 @@ void saveScreenshot(void)
char filename[MAX_NAME_LENGTH];
SDL_Surface *sshot;
sprintf(filename, "/tmp/tbftss/%d.bmp", ++i);
sprintf(filename, "%s/%d.bmp", dev.screenshotFolder, ++i);
sshot = SDL_CreateRGBSurface(0, app.winWidth, app.winHeight, 32, 0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000);
SDL_RenderReadPixels(app.renderer, NULL, SDL_PIXELFORMAT_ARGB8888, sshot->pixels, sshot->pitch);
SDL_SaveBMP(sshot, filename);
@ -273,3 +273,4 @@ void saveScreenshot(void)
printf("Saved '%s'\n", filename);
}
}

View File

@ -229,6 +229,7 @@ static void loadConfigFile(char *filename)
app.winWidth = cJSON_GetObjectItem(root, "winWidth")->valueint;
app.winHeight = cJSON_GetObjectItem(root, "winHeight")->valueint;
app.effects = cJSON_GetObjectItem(root, "effects")->valueint;
app.fullscreen = cJSON_GetObjectItem(root, "fullscreen")->valueint;
app.musicVolume = cJSON_GetObjectItem(root, "musicVolume")->valueint;
app.soundVolume = cJSON_GetObjectItem(root, "soundVolume")->valueint;
@ -284,6 +285,7 @@ void saveConfig(void)
root = cJSON_CreateObject();
cJSON_AddNumberToObject(root, "winWidth", app.winWidth);
cJSON_AddNumberToObject(root, "winHeight", app.winHeight);
cJSON_AddNumberToObject(root, "effects", app.effects);
cJSON_AddNumberToObject(root, "fullscreen", app.fullscreen);
cJSON_AddNumberToObject(root, "musicVolume", app.musicVolume);
cJSON_AddNumberToObject(root, "soundVolume", app.soundVolume);
@ -383,3 +385,4 @@ void cleanup(void)
SDL_Quit();
}

View File

@ -59,7 +59,7 @@ void doWidgets(void)
if (drawingWidgets)
{
updateSelectWidgets();
handleMouse();
handleKeyboard();
@ -69,17 +69,21 @@ void doWidgets(void)
handleControlWidgets();
}
}
#if !defined(__amigaos4__)
if (hoverWidget != selectedWidget)
{
selectedWidget = NULL;
}
#endif
drawingWidgets = 0;
}
static void updateSelectWidgets(void)
{
#if !defined(__amigaos4__)
Widget *w;
for (w = head.next; w != NULL ; w = w->next)
@ -99,6 +103,7 @@ static void updateSelectWidgets(void)
}
}
}
#endif
}
Widget *getWidget(const char *name, const char *group)
@ -320,7 +325,6 @@ static void handleMouse(void)
static void handleKeyboard(void)
{
Widget *old;
if (selectedWidget != NULL)
{
if (selectedWidget->type == WT_BUTTON)
@ -357,7 +361,7 @@ static void handleControlWidgets(void)
}
else
{
if (app.lastKeyPressed != -1)
if (app.lastKeyPressed != -1 && selectedWidget->name)
{
updateControlKey(selectedWidget->name);
@ -601,3 +605,4 @@ void destroyWidgets(void)
head.next = NULL;
}