Initial commit

This commit is contained in:
dajoho 2023-12-10 21:17:35 +01:00
commit 92936a6e11
9 changed files with 462 additions and 0 deletions

11
.project Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>pandory500-pandash</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

13
Makefile Normal file
View file

@ -0,0 +1,13 @@
all: clean pandash
CXX = /opt/armv8-teampandory_a500mini_gcc12-linux-gnueabihf/bin/armv8-teampandory_a500mini_gcc12-linux-gnueabihf-g++
STRIP = /opt/armv8-teampandory_a500mini_gcc12-linux-gnueabihf/bin/armv8-teampandory_a500mini_gcc12-linux-gnueabihf-strip
INCLUDES = -Isrc
CFLAGS = -Os -s
pandash: $(OBJS)
$(CXX) $(CFLAGS) $(INCLUDES) src/main.cpp src/CommandLine/CommandLineArguments.cpp src/Fs/Fs.cpp -o $@
$(STRIP) pandash
upx -9 -f pandash
clean:
rm -f pandash 2>/dev/null || true

4
make.sh Executable file
View file

@ -0,0 +1,4 @@
#!/bin/bash
podman run -v "$(pwd):/pandash:Z" teampandory/teampandory-a500-private sh -c "cd /pandash; make"
cp -fv pandash ../pandory-packagebuilder/pandory500/root/bin/

BIN
pandash Executable file

Binary file not shown.

View file

@ -0,0 +1,45 @@
#include <string>
#include "CommandLineArguments.h"
CommandLineArguments::CommandLineArguments(int argc, char *argv[]) {
argumentCount = argc;
argumentPointers = argv;
}
int CommandLineArguments::getArgumentCount() {
return argumentCount;
}
std::string CommandLineArguments::getArgument(int n) {
for (int i = 0; i < argumentCount; ++i) {
if (i == n) {
return std::string(argumentPointers[i]);
}
}
return std::string();
}
std::string CommandLineArguments::getPathArgument(int n) {
std::string arg = getArgument(n);
if (!arg.empty()) {
int len = arg.length();
std::string end = arg.substr(len-1, 1);
if (end == ":") {
arg += "/";
}
return arg;
}
return std::string();
}
std::string CommandLineArguments::getAllAsString() {
std::string stringArgs;
for (int i = 0; i < argumentCount; ++i) {
stringArgs.append(std::string(argumentPointers[i])+" ");
}
return stringArgs;
}

View file

@ -0,0 +1,19 @@
#ifndef TESTC_COMMANDLINEARGUMENTS_H
#define TESTC_COMMANDLINEARGUMENTS_H
#include <string>
#include <iostream>
class CommandLineArguments {
protected:
int argumentCount;
char **argumentPointers;
public:
CommandLineArguments(int argc, char *argv[]);
int getArgumentCount();
std::string getArgument(int n);
std::string getAllAsString();
std::string getPathArgument(int n);
};
#endif //TESTC_COMMANDLINEARGUMENTS_H

8
src/Fs/Fs.cpp Normal file
View file

@ -0,0 +1,8 @@
#include <filesystem>
#include <iostream>
#include <algorithm>
#include "Fs.h"
bool Fs::exists(const std::string& file) {
return std::filesystem::exists(file.c_str());
}

12
src/Fs/Fs.h Normal file
View file

@ -0,0 +1,12 @@
#ifndef PANDORER_FILESYSTEM_H
#define PANDORER_FILESYSTEM_H
#include <experimental/filesystem>
#include <string>
class Fs {
public:
static bool exists(const std::string& file);
};
#endif //PANDORER_FILESYSTEM_H

350
src/main.cpp Normal file
View file

@ -0,0 +1,350 @@
#include <iostream>
#include <string>
#include <unistd.h>
#include <sys/stat.h>
#include "CommandLine/CommandLineArguments.h"
#include "Fs/Fs.h"
void pandoryExec(std::string const& cmd)
{
std::cout << "Executing shell: " << cmd << std::endl;
system(cmd.c_str());
}
void freezeProcess(const std::string &processName)
{
std::cout << "Freezing process: " << processName << std::endl;
std::string pauseCmd = "kill -STOP $(pidof "+ processName +") 2>/dev/null";
pandoryExec(pauseCmd);
}
void unfreezeProcess(const std::string &processName)
{
std::cout << "Unfreezing process: " << processName << std::endl;
std::string pauseCmd = "kill -CONT $(pidof "+ processName +") 2>/dev/null";
pandoryExec(pauseCmd);
}
void shuffleMusic()
{
pandoryExec("umount /tmp/pandory/share/retroarch/assets/sounds/bgm.mp3");
pandoryExec("cd /mnt/Pandory/.user/bgm && ls | sed -n \"$((RANDOM%$(ls | wc -l)+1))p\" > /tmp/pandory_track");
pandoryExec("busybox mount -o bind /mnt/Pandory/.user/bgm/$(cat /tmp/pandory_track) /tmp/pandory/share/retroarch/assets/sounds/bgm.mp3");
}
void forceKill(const std::string &processName)
{
std::cout << "Force killing process: " << processName << std::endl;
std::string cmd = "killall -9 " + processName + " 2>/dev/null";
pandoryExec(cmd.c_str());
}
void yaft()
{
pandoryExec("cp -fv /tmp/pandory/bin/shell /tmp/pandoryshell && chmod +x /tmp/pandoryshell");
pandoryExec("/tmp/pandory/bin/yaft < /dev/tty0");
}
void ppsspp()
{
pandoryExec("/tmp/pandory/bin/PPSSPPGold --fullscreen");
}
void retroarch()
{
// if mode == retroarch
shuffleMusic();
// TODO: just complain instead if at 60hz. autopatch retroarch.cfg for 50/60hz
system("busybox ash /tmp/pandory/bin/checkfreq.sh");
system("mount -o bind /mnt/Pandory/.user/.config/retroarch/thumbnails/ /tmp/pandory/share/retroarch/thumbnails");
system("mount -o loop,ro /mnt/Pandory/.pandorythumbs /tmp/pandory/share/retroarch/thumbnails");
system("mount -o bind /tmp/pandory/share/retroarch/thumbnails/Arcade '/tmp/pandory/share/retroarch/thumbnails/FBNeo - Arcade Games'");
system("mount -o bind /tmp/pandory/share/retroarch/thumbnails/Arcade '/tmp/pandory/share/retroarch/thumbnails/MAME'");
pandoryExec("/tmp/pandory/bin/retroarch -c /mnt/Pandory/.user/.config/retroarch/retroarch.cfg");
}
void spectrum()
{
pandoryExec("/tmp/pandory/bin/zesarux.sh");
}
void dosbox()
{
pandoryExec("/tmp/pandory/bin/dosbox -conf /mnt/Pandory/.user/config/dosbox/dosbox-staging.conf");
}
void openbor()
{
pandoryExec("cd /mnt/Pandory/.roms/OpenBOR && OpenBOR.elf");
}
void amiberry5(std::string const &executionMode, std::string const &romPath)
{
forceKill("amiberry5");
std::string cmd = "";
if (romPath != "") {
cmd = "cd /mnt/Pandory/.user/.config/amiberry/; amiberry5 -o default_fullscreen_mode=1 -o default_vkbd_enabled=yes -o default_vkbd_exit=yes -o default_vkbd_style=Cool --autoload \""+romPath+"\"";
} else {
cmd = "cd /mnt/Pandory/.user/.config/amiberry/; amiberry5 -o default_fullscreen_mode=1";
}
pandoryExec(cmd);
}
void scummvm()
{
pandoryExec("/tmp/pandory/bin/scummvm --config=/mnt/Pandory/.user/.config/scummvm/scummvm.ini");
}
void darkplaces()
{
pandoryExec("export LD_LIBRARY_PATH=\"/opt/gles/lib:$LD_LIBRARY_PATH\" && cd /mnt/Pandory/.roms/Quake/ && darkplaces-sdl");
//pandoryExec("export LD_LIBRARY_PATH=\"/opt/gles/lib:$LD_LIBRARY_PATH\" && darkplaces.sh");
}
void emulationStation()
{
pandoryExec("/tmp/pandory/bin/emulationstation");
}
void hatari()
{
pandoryExec("/tmp/pandory/bin/hatari");
}
void vanillaTD()
{
system("cd \"/mnt/Pandory/.roms/Vanilla Conquer/TD/\" && ./vanillatd");
}
void vanillaRA()
{
system("cd \"/mnt/Pandory/.roms/Vanilla Conquer/RA/\" && ./vanillara");
}
void loadKernelModule(const std::string &module)
{
std::string modulePath = "/tmp/pandory/lib/modules/";
std::string cmd = "insmod " + modulePath + module + ".ko";
system(cmd.c_str());
}
void enableNetwork()
{
loadKernelModule("ipv4");
loadKernelModule("af_packet");
loadKernelModule("mii");
loadKernelModule("rtl8150");
loadKernelModule("r8152");
loadKernelModule("tcp_cubic");
loadKernelModule("usbnet");
loadKernelModule("libphy");
loadKernelModule("asix");
//loadKernelModule("ax88179_178a");
loadKernelModule("catc");
loadKernelModule("cdc_ether");
loadKernelModule("ipheth");
loadKernelModule("kaweth");
loadKernelModule("pegasus");
loadKernelModule("squashfs");
// wait for interfaces and bring them up
system("sleep 5");
system("ifconfig eth0 up");
//dhcp
system("busybox udhcpc -s /tmp/pandory/etc/udhcpc.script &");
system("cd /mnt/Pandory/.webserver && php -S 0.0.0.0:80 &");
system("dropbear -r /mnt/Pandory/.user/.config/dropbear/dropbear_rsa_host_key -E -p 0.0.0.0:22 &");
}
void prepareBios()
{
// Make a virtual kickstarts folder in /tmp
mkdir("/tmp/bios/", 0750);
chdir("/tmp/bios/");
// Symlink all the nand-kickstarts to /tmp/bios/
system("find /usr/share/amiberry/kickstarts/ -type f -exec ash -c 'ln -sfv {} $(basename {})' \\;");
// Symlink all the libre amiberry-fallback-kickstarts to /tmp/bios/
system("find /mnt/Pandory/.user/.config/amiberry/kickstarts/ -type f -exec ash -c 'ln -sfv {} $(basename {})' \\;");
// Rsync the preferred kickstarts to their correct names in the amiberry kickstart folder
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick34005.A500 '/mnt/Pandory/.user/.config/amiberry/kickstarts/Kickstart v1.3 rev 34.5 (1987)(Commodore)(A500-A1000-A2000-CDTV).rom'");
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick37350.A600 '/mnt/Pandory/.user/.config/amiberry/kickstarts/Kickstart v2.05 rev 37.350 (1992)(Commodore)(A600HD)[!].rom'");
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick40068.A1200 '/mnt/Pandory/.user/.config/amiberry/kickstarts/Kickstart v3.1 rev 40.68 (1993)(Commodore)(A1200)[!].rom'");
// ..and to the whdload boot folder
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick34005.A500 /mnt/Pandory/.user/.config/amiberry/whdboot/save-data/Kickstarts/");
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick37350.A600 /mnt/Pandory/.user/.config/amiberry/whdboot/save-data/Kickstarts/");
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick40068.A1200 /mnt/Pandory/.user/.config/amiberry/whdboot/save-data/Kickstarts/");
// ..and the rtb files, because whdload. the a600 one doesn't exist.
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick34005.A500.RTB /mnt/Pandory/.user/.config/amiberry/whdboot/save-data/Kickstarts/");
system("rsync -av --size-only /usr/share/amiberry/kickstarts/kick40068.A1200.RTB /mnt/Pandory/.user/.config/amiberry/whdboot/save-data/Kickstarts/");
}
void parseAmiberryCommandLine(std::string const &name, std::string const &mode)
{
std::string cmd = "ps -oargs | grep -v grep | grep amiberry | grep \""+name+"\" && touch /tmp/pandory_mode_" + mode;
pandoryExec(cmd);
}
void clearCaches()
{
pandoryExec("busybox sysctl vm.drop_caches=3");
}
int main(int argc, char *argv[])
{
// init pandory libraries and paths
setenv("LD_LIBRARY_PATH", "/tmp/pandory/usr/lib:/tmp/pandory/lib64:/tmp/pandory/lib", 1);
setenv("PATH", "/mnt/Pandory/.bin:/tmp/pandory/usr/bin:/tmp/pandory/sbin:/tmp/pandory/bin:/usr/bin:/sbin:/bin", 1);
// empty caches
clearCaches();
CommandLineArguments args = CommandLineArguments(argc, argv);
std::string mode = args.getArgument(1);
std::string rom = args.getArgument(2);
std::string romExtra = args.getArgument(3);
if (mode == "network") {
enableNetwork();
return 0;
}
if (mode == "bios") {
prepareBios();
return 0;
}
if (mode == "amiberry5") {
std::string executionMode = args.getArgument(2);
std::string romPath = args.getArgument(3);
amiberry5(executionMode, romPath);
return 0;
}
if (mode == "quake") {
freezeProcess("amiberry5");
darkplaces();
unfreezeProcess("amiberry5");
return 0;
}
freezeProcess("manhattan");
freezeProcess("skyline");
freezeProcess("amiberry");
if (!Fs::exists("/tmp/pandory_original_amiberry")) {
pandoryExec("mkdir /tmp/dbus/");
pandoryExec("mount -o bind /mnt/Pandory/.user /root");
pandoryExec("cp -f /usr/bin/amiberry /tmp/pandory_original_amiberry");
pandoryExec("mount -o bind /tmp/pandory/bin/amiberry-proxy.sh /usr/bin/amiberry");
pandoryExec("mount -o bind /tmp/pandory/share/terminfo/ /usr/share/terminfo/");
// fork network in the background
pandoryExec("pandash network &");
// prepare bios in the background -> do it sync instead of async
pandoryExec("pandash bios");
// rsync /etc/ to /tmp/etc/ and bind mount it back so it's writable
system("mkdir /tmp/etc/ && rsync -av /etc/ /tmp/etc/");
system("mount -o bind /tmp/etc/ /etc/");
// make an empty mountpoint for dropbear and bind mount ssh configuration from usb stick
pandoryExec("mkdir /tmp/etc/dropbear/");
//pandoryExec("mount -o bind /mnt/Pandory/.user/.config/dropbear/ /etc/dropbear/");
pandoryExec("cp -fv /mnt/Pandory/.user/.config/dropbear/shadow /etc/shadow");
pandoryExec("cp -fv /mnt/Pandory/.user/.config/dropbear/passwd /etc/passwd");
}
system("rm -f /tmp/pandory_mode_*");
parseAmiberryCommandLine("Start AMiNIMiga", "aminimiga");
parseAmiberryCommandLine("Start AGS", "ags2");
parseAmiberryCommandLine("Get Pandory500", "upgrade");
parseAmiberryCommandLine("Start PPSSPP (PSP)", "ppsspp");
parseAmiberryCommandLine("Start Darkplaces (Quake)", "darkplaces");
parseAmiberryCommandLine("Start Hatari (Atari)", "hatari");
parseAmiberryCommandLine("Start Amiberry 5 (Amiga)", "amiberry5");
parseAmiberryCommandLine("Start OpenBor (Beat-em-ups)", "openbor");
parseAmiberryCommandLine("Start Terminal (Linux)", "terminal");
parseAmiberryCommandLine("Start ScummVM (Adventure Games)", "scummvm");
parseAmiberryCommandLine("Start Zesarux (Spectrum)", "spectrum");
parseAmiberryCommandLine("Start DOSBox Staging (IBM PC)", "dosbox");
parseAmiberryCommandLine("Start Tiberian Dawn (C&C)", "vanillatd");
parseAmiberryCommandLine("Start Red Alert (C&C)", "vanillara");
// free up memory
forceKill("amiberry");
// empty caches
clearCaches();
if (Fs::exists("/tmp/pandory_mode_ppsspp")) {
ppsspp();
} else if (Fs::exists("/tmp/pandory_mode_terminal")) {
system("cp -fv /tmp/pandory/bin/shell /tmp/pandoryshell");
yaft();
} else if (Fs::exists("/tmp/pandory_mode_darkplaces")) {
darkplaces();
} else if (Fs::exists("/tmp/pandory_mode_spectrum")) {
spectrum();
} else if (Fs::exists("/tmp/pandory_mode_dosbox")) {
dosbox();
} else if (Fs::exists("/tmp/pandory_mode_hatari")) {
hatari();
} else if (Fs::exists("/tmp/pandory_mode_amiberry5")) {
// start amiberry with no arguments
amiberry5("", "");
} else if (Fs::exists("/tmp/pandory_mode_scummvm")) {
scummvm();
} else if (Fs::exists("/tmp/pandory_mode_openbor")) {
openbor();
} else if (Fs::exists("/tmp/pandory_mode_vanillatd")) {
vanillaTD();
} else if (Fs::exists("/tmp/pandory_mode_vanillara")) {
vanillaRA();
} else if (Fs::exists("/tmp/pandory_mode_emulationstation")) {
emulationStation();
} else if (Fs::exists("/tmp/pandory_mode_aminimiga")) {
pandoryExec("/mnt/AMiNIMiga/.pandory/boot.sh");
pandoryExec("cd /mnt/Pandory/.user/.config/amiberry/; amiberry5 -o default_fullscreen_mode=1 -o config_path=/mnt/AMiNIMiga/.pandory/ --config /mnt/AMiNIMiga/.pandory/aminimiga.uae -s use_gui=no");
} else if (Fs::exists("/tmp/pandory_mode_ags2")) {
pandoryExec("/mnt/AGS/.pandory/boot.sh");
pandoryExec("cd /mnt/Pandory/.user/.config/amiberry/; amiberry5 -o default_fullscreen_mode=1 -o config_path=/mnt/AGS/.pandory/ --config /mnt/AGS/.pandory/ags.uae -s use_gui=no");
} else if (Fs::exists("/tmp/pandory_mode_upgrade")) {
//pandoryExec("echo 'echo Upgrade to the full Pandory500 to add many emulators and new features to your A500 Mini. https://go.teampandory.com/a500 && sleep 10 && exit' > /tmp/pandoryshell");
pandoryExec("mpv.sh /tmp/pandory/etc/pandory.mp4");
} else {
retroarch();
}
unfreezeProcess("manhattan");
unfreezeProcess("skyline");
// empty caches
clearCaches();
return 0;
}