Initial commit
This commit is contained in:
commit
92936a6e11
9 changed files with 462 additions and 0 deletions
11
.project
Normal file
11
.project
Normal 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
13
Makefile
Normal 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
4
make.sh
Executable 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
BIN
pandash
Executable file
Binary file not shown.
45
src/CommandLine/CommandLineArguments.cpp
Normal file
45
src/CommandLine/CommandLineArguments.cpp
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
19
src/CommandLine/CommandLineArguments.h
Normal file
19
src/CommandLine/CommandLineArguments.h
Normal 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
8
src/Fs/Fs.cpp
Normal 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
12
src/Fs/Fs.h
Normal 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
350
src/main.cpp
Normal 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;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue