7 changed files with 456 additions and 0 deletions
@ -0,0 +1,27 @@ |
|||||||
|
set(NONET ON) |
||||||
|
set(PREFILL_PLAYER_NAME ON) |
||||||
|
set(HAS_KBCTRL 1) |
||||||
|
set(BINARY_RELEASE ON) |
||||||
|
set(LTO ON) |
||||||
|
set(DIST ON) |
||||||
|
set(DEBUG OFF) |
||||||
|
set(ASAN OFF) |
||||||
|
set(UBSAN OFF) |
||||||
|
set(KBCTRL_BUTTON_DPAD_LEFT SDLK_LEFT) |
||||||
|
set(KBCTRL_BUTTON_DPAD_RIGHT SDLK_RIGHT) |
||||||
|
set(KBCTRL_BUTTON_DPAD_UP SDLK_UP) |
||||||
|
set(KBCTRL_BUTTON_DPAD_DOWN SDLK_DOWN) |
||||||
|
set(KBCTRL_BUTTON_X SDLK_i) |
||||||
|
set(KBCTRL_BUTTON_Y SDLK_u) |
||||||
|
set(KBCTRL_BUTTON_B SDLK_k) |
||||||
|
set(KBCTRL_BUTTON_A SDLK_j) |
||||||
|
set(KBCTRL_BUTTON_RIGHTSHOULDER SDLK_l) |
||||||
|
set(KBCTRL_BUTTON_LEFTSHOULDER SDLK_h) |
||||||
|
set(KBCTRL_BUTTON_AXIS_TRIGGERLEFT SDLK_y) |
||||||
|
set(KBCTRL_BUTTON_AXIS_TRIGGERRIGHT SDLK_o) |
||||||
|
set(KBCTRL_BUTTON_LEFTSTICK SDLK_PAGEUP) |
||||||
|
set(KBCTRL_BUTTON_RIGHTSTICK SDLK_PAGEDOWN) |
||||||
|
set(KBCTRL_BUTTON_START SDLK_RETURN) |
||||||
|
set(KBCTRL_BUTTON_BACK SDLK_SPACE) |
||||||
|
|
||||||
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O3") |
||||||
|
After Width: | Height: | Size: 4.1 KiB |
@ -0,0 +1,291 @@ |
|||||||
|
|
||||||
|
import pygame |
||||||
|
import validators |
||||||
|
import commands |
||||||
|
from UI.constants import Width,Height,ICON_TYPES,RUNSYS |
||||||
|
from UI.simple_name_space import SimpleNamespace |
||||||
|
from UI.page import Page |
||||||
|
from UI.label import Label |
||||||
|
from UI.icon_item import IconItem |
||||||
|
from UI.keys_def import CurKeys, IsKeyMenuOrB, IsKeyStartOrA |
||||||
|
from UI.skin_manager import MySkinManager |
||||||
|
from UI.lang_manager import MyLangManager |
||||||
|
|
||||||
|
from libs.DBUS import is_wifi_connected_now,get_wifi_ip |
||||||
|
from collections import deque |
||||||
|
from enum import Enum |
||||||
|
import os |
||||||
|
import subprocess |
||||||
|
import pipes |
||||||
|
|
||||||
|
class DevilutionPage(Page): |
||||||
|
_FootMsg = ["Nav","Check","Upgrade","Back","Play"] |
||||||
|
|
||||||
|
_GameName = "devilutionX" |
||||||
|
_GamePath = "/home/cpi/games/devilutionX" |
||||||
|
_GameExecutable = _GamePath + "/bin/devilutionx" |
||||||
|
_GameExecutableRevision = _GameExecutable + ".rev" |
||||||
|
_GameBuildScript = _GamePath + "/Packaging/cpi-gamesh/build.sh -t " + pipes.quote(os.path.dirname(os.path.abspath( __file__ ))) |
||||||
|
_GamePNG = _GamePath + "/Packaging/cpi-gamesh/Devilution.png" |
||||||
|
_DevilutionDiabdatmpq = "/home/cpi/.local/share/diasurgical/devilution/diabdat.mpq" |
||||||
|
_DevilutionDiabdatmpqPresent = False |
||||||
|
_GameInstalled = False |
||||||
|
|
||||||
|
_CiteNewUpdate = "Ahh... fresh meat!" |
||||||
|
_CiteCheckUpdate = "Lets search the books..." |
||||||
|
_CiteWelcome = "Well, what can I do for ya?" |
||||||
|
_CiteCompiling = "Stay awhile and listen." |
||||||
|
_CiteDone = "You must venture through the portal..." |
||||||
|
_CiteFailed = "Game Over. Better luck next time!" |
||||||
|
|
||||||
|
_GitURL = "https://github.com/danie1kr/devilutionX.git" |
||||||
|
_GitBranch = "gameshell" |
||||||
|
_GitRevision = "" |
||||||
|
|
||||||
|
_GameIcon = None |
||||||
|
|
||||||
|
_Process = None |
||||||
|
_Labels = {} |
||||||
|
_Coords = {} |
||||||
|
|
||||||
|
_ListFontObj = MyLangManager.TrFont("varela13") |
||||||
|
_URLColor = MySkinManager.GiveColor('URL') |
||||||
|
_TextColor = MySkinManager.GiveColor('Text') |
||||||
|
|
||||||
|
def __init__(self): |
||||||
|
Page.__init__(self) |
||||||
|
|
||||||
|
def InitLabels(self): |
||||||
|
|
||||||
|
y = 15 |
||||||
|
x = 11 |
||||||
|
yInc = 19 |
||||||
|
xGitRefLabelWidth = 48 |
||||||
|
|
||||||
|
labels = \ |
||||||
|
[["greeting",self._CiteWelcome, self._TextColor, x, y], |
||||||
|
["status", "", self._URLColor, x, y + 72-yInc], |
||||||
|
["comment", "", self._TextColor, x, y + 72], |
||||||
|
["console_out","",self._URLColor, x, y + 72 + yInc], |
||||||
|
["label_rev","GIT Revisions: ", self._TextColor, x, 132], |
||||||
|
["label_git_rev","Source: ", self._TextColor, x, 151], |
||||||
|
["content_git_rev","", self._URLColor, x + xGitRefLabelWidth, 151], |
||||||
|
["label_bin_rev","Bin: ", self._TextColor, x, 170], |
||||||
|
["content_bin_rev","", self._URLColor, x + xGitRefLabelWidth, 170] |
||||||
|
] |
||||||
|
|
||||||
|
for i in labels: |
||||||
|
l = Label() |
||||||
|
l.SetCanvasHWND(self._CanvasHWND) |
||||||
|
l.Init(i[1],self._ListFontObj) |
||||||
|
l.SetColor(i[2]) |
||||||
|
self._Labels[ i[0] ] = l |
||||||
|
|
||||||
|
c = SimpleNamespace() |
||||||
|
c.x = i[3] |
||||||
|
c.y = i[4] |
||||||
|
self._Coords[ i[0] ] = c |
||||||
|
|
||||||
|
def GitGetRevision(self): |
||||||
|
if not os.path.exists(self._GamePath): |
||||||
|
return "game not installed" |
||||||
|
process = subprocess.Popen("cd " + pipes.quote(self._GamePath) + "; git rev-parse HEAD",stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True) |
||||||
|
self._GitRevision = process.communicate()[0].strip() |
||||||
|
process.wait() |
||||||
|
return self._GitRevision |
||||||
|
|
||||||
|
def ExectuableGetRevision(self): |
||||||
|
try: |
||||||
|
with open(self._GameExecutableRevision, 'r') as file: |
||||||
|
executableRevsion = file.read().replace('\n', '') |
||||||
|
return executableRevsion |
||||||
|
except: |
||||||
|
return "unknown" |
||||||
|
|
||||||
|
def InitGameDirectory(self): |
||||||
|
try: |
||||||
|
os.makedirs(self._GamePath) |
||||||
|
except: |
||||||
|
pass |
||||||
|
self.StartShellProcess("cd " + pipes.quote(self._GamePath) + "; git clone --single-branch --branch " + pipes.quote(self._GitBranch) + " " + pipes.quote(self._GitURL) + " .") |
||||||
|
|
||||||
|
def CheckDevilutionMPQ(self): |
||||||
|
self._DevilutionDiabdatmpqPresent = os.path.isfile(self._DevilutionDiabdatmpq) |
||||||
|
|
||||||
|
def CheckGameInstalled(self): |
||||||
|
self._GameInstalled = os.path.isfile(self._GameExecutable) |
||||||
|
|
||||||
|
def UpdateFootMsg(self): |
||||||
|
if not self._GameInstalled: |
||||||
|
self._FootMsg = ["Nav","","Install","Back",""] |
||||||
|
self.UpdateLabel("status", "GIT Upgrade") |
||||||
|
self.UpdateLabel("comment", "Press X to install") |
||||||
|
elif not self._DevilutionDiabdatmpqPresent: |
||||||
|
self._FootMsg = ["Nav","","Upgrade","Back","Re-check"] |
||||||
|
self.UpdateLabel("status", "Gamefile diabdat.mpq missing") |
||||||
|
self.UpdateLabel("comment", "see readme") |
||||||
|
else: |
||||||
|
self._FootMsg = ["Nav","","Upgrade","Back","Play"] |
||||||
|
self.UpdateLabel("status", "Ready") |
||||||
|
self.UpdateLabel("comment", self._CiteDone) |
||||||
|
|
||||||
|
def Init(self): |
||||||
|
Page.Init(self) |
||||||
|
|
||||||
|
if self._Screen != None: |
||||||
|
if self._Screen._CanvasHWND != None and self._CanvasHWND == None: |
||||||
|
self._HWND = self._Screen._CanvasHWND |
||||||
|
self._CanvasHWND = pygame.Surface( (self._Screen._Width,self._Screen._Height) ) |
||||||
|
|
||||||
|
if os.path.isfile(self._GamePNG): |
||||||
|
self._GameIcon = IconItem() |
||||||
|
self._GameIcon._ImageName = self._GamePNG |
||||||
|
self._GameIcon._MyType = ICON_TYPES["STAT"] |
||||||
|
self._GameIcon._Parent = self |
||||||
|
self._GameIcon.Adjust(290,70,128,128,0) |
||||||
|
|
||||||
|
self.InitLabels() |
||||||
|
self.CheckDevilutionMPQ() |
||||||
|
self.CheckGameInstalled() |
||||||
|
self.UpdateFootMsg() |
||||||
|
|
||||||
|
self.UpdateLabel("content_git_rev", self.GitGetRevision(), 24) |
||||||
|
self.UpdateLabel("content_bin_rev", self.ExectuableGetRevision(), 24) |
||||||
|
|
||||||
|
def UpdateLabel(self, label, msg, maxLen=38): |
||||||
|
print(label + ": " + msg) |
||||||
|
if len(msg) > maxLen: |
||||||
|
m = msg[:maxLen] + "..." |
||||||
|
else: |
||||||
|
m = msg |
||||||
|
self._Labels[label].SetText(m) |
||||||
|
|
||||||
|
def StartShellProcess(self, cmd): |
||||||
|
print("StartShellProcess " + cmd) |
||||||
|
proc = subprocess.Popen(cmd,stdout=subprocess.PIPE,stderr=subprocess.STDOUT, shell=True) |
||||||
|
while(True): |
||||||
|
line = proc.stdout.readline() |
||||||
|
if line: |
||||||
|
self.UpdateLabel("console_out", line.strip(), 48) |
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
if line == '' and proc.poll() is not None: |
||||||
|
break |
||||||
|
self.UpdateLabel("console_out", "") |
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
|
||||||
|
def GitUpgrade(self): |
||||||
|
self.UpdateLabel("status", "GIT Upgrade") |
||||||
|
self.UpdateLabel("comment", self._CiteCheckUpdate) |
||||||
|
|
||||||
|
curRev = "unset" |
||||||
|
if not os.path.exists(self._GamePath): |
||||||
|
self.InitGameDirectory() |
||||||
|
else: |
||||||
|
curRev = self.GitGetRevision() |
||||||
|
self.StartShellProcess("cd " + pipes.quote(self._GamePath) + "; git pull") |
||||||
|
|
||||||
|
self._GitRevision = self.GitGetRevision() |
||||||
|
self.UpdateLabel("content_git_rev", self._GitRevision, 24) |
||||||
|
|
||||||
|
if curRev != self._GitRevision: |
||||||
|
self.UpdateLabel("comment", self._CiteNewUpdate) |
||||||
|
else: |
||||||
|
self.UpdateLabel("comment", self._CiteDone) |
||||||
|
|
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
|
||||||
|
def GitExectuableIsGitRevision(self): |
||||||
|
return self.GitGetRevision() == self.ExectuableGetRevision() |
||||||
|
|
||||||
|
def Build(self): |
||||||
|
self.UpdateLabel("status", "Building") |
||||||
|
self.StartShellProcess(self._GameBuildScript) |
||||||
|
|
||||||
|
def UpgradeAndBuild(self): |
||||||
|
self.GitUpgrade() |
||||||
|
self.UpdateLabel("comment", self._CiteCompiling) |
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
if not self.GitExectuableIsGitRevision(): |
||||||
|
self.Build() |
||||||
|
|
||||||
|
self.UpdateLabel("content_git_rev", self.GitGetRevision(), 24) |
||||||
|
self.UpdateLabel("content_bin_rev", self.ExectuableGetRevision(), 24) |
||||||
|
|
||||||
|
self.UpdateLabel("status", "Done") |
||||||
|
if self.GitExectuableIsGitRevision(): |
||||||
|
self.UpdateLabel("comment", self._CiteDone) |
||||||
|
else: |
||||||
|
self.UpdateLabel("comment", self._CiteFailed) |
||||||
|
|
||||||
|
self.CheckDevilutionMPQ() |
||||||
|
self.CheckGameInstalled() |
||||||
|
self.UpdateFootMsg() |
||||||
|
|
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
|
||||||
|
def KeyDown(self,event): |
||||||
|
|
||||||
|
if IsKeyMenuOrB(event.key): |
||||||
|
self.ReturnToUpLevelPage() |
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
|
||||||
|
if self._DevilutionDiabdatmpqPresent and self._GameInstalled: |
||||||
|
if IsKeyStartOrA(event.key): |
||||||
|
pygame.event.post( pygame.event.Event(RUNSYS, message=self._GameExecutable)) |
||||||
|
if event.key == CurKeys["X"]: |
||||||
|
self.UpgradeAndBuild() |
||||||
|
elif not self._GameInstalled: |
||||||
|
if event.key == CurKeys["X"]: |
||||||
|
self.UpgradeAndBuild() |
||||||
|
elif not self._DevilutionDiabdatmpqPresent: |
||||||
|
if IsKeyStartOrA(event.key): |
||||||
|
self.CheckDevilutionMPQ() |
||||||
|
self.CheckGameInstalled() |
||||||
|
self.UpdateFootMsg() |
||||||
|
self._Screen.Draw() |
||||||
|
self._Screen.SwapAndShow() |
||||||
|
|
||||||
|
def Draw(self): |
||||||
|
self.ClearCanvas() |
||||||
|
|
||||||
|
if self._GameIcon != None: |
||||||
|
self._GameIcon.Draw() |
||||||
|
|
||||||
|
for i in self._Labels: |
||||||
|
if i in self._Coords: |
||||||
|
self._Labels[i].NewCoord( self._Coords[i].x, self._Coords[i].y) |
||||||
|
self._Labels[i].Draw() |
||||||
|
|
||||||
|
if self._HWND != None: |
||||||
|
self._HWND.fill(MySkinManager.GiveColor('White')) |
||||||
|
self._HWND.blit(self._CanvasHWND,(self._PosX,self._PosY,self._Width, self._Height ) ) |
||||||
|
|
||||||
|
|
||||||
|
class APIOBJ(object): |
||||||
|
|
||||||
|
_Page = None |
||||||
|
def __init__(self): |
||||||
|
pass |
||||||
|
def Init(self,main_screen): |
||||||
|
self._Page = DevilutionPage() |
||||||
|
self._Page._Screen = main_screen |
||||||
|
self._Page._Name ="devilutionX" |
||||||
|
self._Page.Init() |
||||||
|
|
||||||
|
def API(self,main_screen): |
||||||
|
if main_screen !=None: |
||||||
|
main_screen.PushPage(self._Page) |
||||||
|
main_screen.Draw() |
||||||
|
main_screen.SwapAndShow() |
||||||
|
|
||||||
|
OBJ = APIOBJ() |
||||||
|
def Init(main_screen): |
||||||
|
OBJ.Init(main_screen) |
||||||
|
def API(main_screen): |
||||||
|
OBJ.API(main_screen) |
||||||
@ -0,0 +1,91 @@ |
|||||||
|
#!/usr/bin/env bash |
||||||
|
|
||||||
|
set -euo pipefail |
||||||
|
|
||||||
|
echo "Building for target: clockwork pi GameSH" |
||||||
|
|
||||||
|
declare -r DIR="$(dirname "${BASH_SOURCE[0]}")" |
||||||
|
cd "$DIR" |
||||||
|
declare -r ABSDIR="$(pwd)" |
||||||
|
|
||||||
|
usage() { |
||||||
|
echo "${BASH_SOURCE[0]} [--target /path/to/devliution/in/gameshell/menu] [--usage]" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
POSITIONAL=() |
||||||
|
while [[ $# -gt 0 ]] |
||||||
|
do |
||||||
|
key="$1" |
||||||
|
|
||||||
|
case $key in |
||||||
|
-t|--target) |
||||||
|
TARGET="$2" |
||||||
|
shift # past argument |
||||||
|
shift # past value |
||||||
|
;; |
||||||
|
--help|-h|--usage|-u) |
||||||
|
usage |
||||||
|
shift # past argument |
||||||
|
;; |
||||||
|
*) # unknown option |
||||||
|
POSITIONAL+=("$1") # save it in an array for later |
||||||
|
shift # past argument |
||||||
|
;; |
||||||
|
esac |
||||||
|
done |
||||||
|
set -- "${POSITIONAL[@]}" # restore positional parameters |
||||||
|
|
||||||
|
install_deps() { |
||||||
|
sudo apt install -y cmake libsdl2-ttf-dev libsdl2-mixer-dev |
||||||
|
} |
||||||
|
|
||||||
|
main() { |
||||||
|
install_deps |
||||||
|
build |
||||||
|
install |
||||||
|
} |
||||||
|
|
||||||
|
build() { |
||||||
|
mkdir -p ../../build |
||||||
|
cd ../../build |
||||||
|
rm -f CMakeCache.txt |
||||||
|
|
||||||
|
local -a defs=(-DCPIGAMESH=ON) |
||||||
|
cmake .. ${defs[@]} |
||||||
|
make -j $(getconf _NPROCESSORS_ONLN) |
||||||
|
cd - |
||||||
|
} |
||||||
|
|
||||||
|
install() { |
||||||
|
mkdir -p /home/cpi/games/devilutionX/bin |
||||||
|
cp /home/cpi/games/devilutionX/build/devilutionx /home/cpi/games/devilutionX/bin |
||||||
|
git rev-parse HEAD > /home/cpi/games/devilutionX/bin/devilutionx.rev |
||||||
|
|
||||||
|
if [ -z ${TARGET+x} ]; then |
||||||
|
local target_dir="25_devilutionX" |
||||||
|
else |
||||||
|
local target_dir=${TARGET#"/home/cpi/apps/Menu/"} |
||||||
|
fi |
||||||
|
|
||||||
|
local script_dir="/home/cpi/apps/Menu/$target_dir" |
||||||
|
|
||||||
|
local target_dir_base=`basename "$target_dir"` |
||||||
|
local target_dir_dir=`dirname "$target_dir"` |
||||||
|
local icon_name="${target_dir_dir}/${target_dir_base#*_}" |
||||||
|
|
||||||
|
local icon_dir="/home/cpi/launcher/skin/default/Menu/GameShell/${icon_name}.png" |
||||||
|
|
||||||
|
echo $target_dir |
||||||
|
echo $script_dir |
||||||
|
echo $target_dir_base |
||||||
|
echo $target_dir_dir |
||||||
|
echo $icon_name |
||||||
|
echo $icon_dir |
||||||
|
|
||||||
|
mkdir -p $script_dir |
||||||
|
cp __init__.py $script_dir |
||||||
|
cp Devilution.png $icon_dir |
||||||
|
} |
||||||
|
|
||||||
|
main |
||||||
@ -0,0 +1,42 @@ |
|||||||
|
|
||||||
|
### devilutionX package for ClockworkPi GameShell |
||||||
|
For more information about this device see [here](https://www.clockworkpi.com/gameshell). |
||||||
|
|
||||||
|
## Install devilutionX on the CPi GameShell |
||||||
|
|
||||||
|
To install devilutionX, just copy the [\_\_init__.py](https://raw.githubusercontent.com/danie1kr/devilutionX/gameshell/Packaging/cpi-gamesh/__init__.py) to a newly created folder under /home/cpi/apps/Menu and run it from the menu. The folder then symbolizes the devilutionX icon. |
||||||
|
From this menu, you can press 'X' to clone the git repository for devilutionX and compile the code. Dependencies are installed automatically (cmake and SDL development packages). |
||||||
|
Once installed, 'X' pulls the updated code and does the compiling. Note that any changes made locally to the source are reverted before pulling. |
||||||
|
|
||||||
|
Currently, the code is cloned from [a fork](https://github.com/danie1kr/devilutionX.git), branch "gameshell". |
||||||
|
|
||||||
|
When the compile is finished and the diabdat.mpq is in place at '/home/cpi/.local/share/diasurgical/devilution/', you can play the game. Enjoy! |
||||||
|
|
||||||
|
## Play devilutionX on the CPi GameShell |
||||||
|
|
||||||
|
When the game is compiled and the diabdat.mpq is in place, you can press "A" in the devilutionX menu to play. |
||||||
|
|
||||||
|
The following key mapping is in place. |
||||||
|
Unfortunately, the mapping is not trivial as devilutionX and GameShell use their own not(yet) compatible shift mechanism. |
||||||
|
The mapping is based on the standard GameShell keyboard layout, devilutionX uses the Nintento mapping. |
||||||
|
|
||||||
|
| GameShell Key | Keyboard Key | devilutionX Key | devilutionX Action | |
||||||
|
| --------------------- | --------------- | ------------------------- | ------------------ | |
||||||
|
| D-Pad | Arrows | D-Pad | move hero | |
||||||
|
| Select + D-Pad | Space + Arrows | Back + D-Pad | simulate mouse | |
||||||
|
| B | K | A | attack nearby enemies, talk to townspeople and merchants, pickup/place items in the inventory, OK while in main menu | |
||||||
|
| A | J | B | select spell, back while in menus | |
||||||
|
| Y | I | X | pickup items, open nearby chests and doors, use item in the inventory | |
||||||
|
| X | U | Y | cast spell, delete character while in main menu | |
||||||
|
| Select | Space | Select | Select | |
||||||
|
| Start | Enter | Start | game menu, skip movie | |
||||||
|
| LK1 | H | L1 | use health item from belt | |
||||||
|
| Start + Left | Enter + Left | Start + Left | character sheet | |
||||||
|
| Start + Right | Enter + Right | Start + Right | inventory | |
||||||
|
| LK5 | L | R1 | use mana item from belt | |
||||||
|
| Start + Down | Enter + Down | Start + Down | automap | |
||||||
|
| Select + LK1 | Space + H | Select + L1 | left mouse click | |
||||||
|
| Start + X | Enter + U | Start + Y | quest log | |
||||||
|
| Start + A | Enter + J | Start + B | spell book | |
||||||
|
| Select + LK5 | Space + L | Select + R1 | right mouse click | |
||||||
|
| Select + A/B/X/Y | Space + J/K/U/I | Select + A/B/X/Y | hot spell | |
||||||
Loading…
Reference in new issue