Skip to content

Instantly share code, notes, and snippets.

@Gemba
Last active March 20, 2023 19:04
Show Gist options
  • Save Gemba/f2c541f6e027d7278e948f80e311e318 to your computer and use it in GitHub Desktop.
Save Gemba/f2c541f6e027d7278e948f80e311e318 to your computer and use it in GitHub Desktop.
RetroPie Scriptmodule for Head Over Heels (2022 enhanced remake) - https://github.com/dougmencken/HeadOverHeels

The scriptmodule installs the Head Over Heels game at ~/RetroPie/roms/ports

  1. Deploy the scriptmodule from below at ~/RetroPie-Setup/ext/<somefolder>/scriptmodules/ports/headoverheels.sh
  2. Deploy the patch from below at ~/RetroPie-Setup/ext/<somefolder>/scriptmodules/ports/hoh/01-menu-intro-outro.patch
  3. Run sudo ~/RetroPie-Setup/retropie_packages.sh hoh
  4. Find and start the entry "Head over Heels" in the "Ports" System in EmulationStation.
  5. Set in your Runcommand menu on first game start the video resolution to 640x480.

Note for Raspberry Pi3 users: The menu can be quite slow and may miss keypresses, the gameplay may have issues as the liballeg5 implementation is work-in-progress / not optimized yet.

diff --git a/src/gui/Screen.cpp b/src/gui/Screen.cpp
index 4de4a71..e8c4eee 100644
--- a/src/gui/Screen.cpp
+++ b/src/gui/Screen.cpp
@@ -11,6 +11,9 @@
#include "AnimatedPictureWidget.hpp"
#include "Color.hpp"
+#if defined( USE_ALLEGRO5 ) && USE_ALLEGRO5
+#include <allegro5/allegro.h>
+#endif
#include <iostream>
@@ -454,11 +457,16 @@ void Screen::barWipeHorizontally( const Screen& oldScreen, const Screen& newScre
if ( &oldScreen == &newScreen ||
oldScreen.imageOfScreen == nilPointer || newScreen.imageOfScreen == nilPointer ) return ;
- Picture buffer( * oldScreen.imageOfScreen );
+ Picture& buffer = *oldScreen.imageOfScreen;
newScreen.refresh ();
- Picture& newPicture = * newScreen.imageOfScreen ;
+ Picture& newPicture = *newScreen.imageOfScreen;
+ barWipeHorizontally( buffer, newPicture, rightToLeft );
+}
+/* static */
+void Screen::barWipeHorizontally( const Picture from, const Picture to, bool rightToLeft )
+{
unsigned int pieces = iso::ScreenWidth() >> 6 ;
unsigned int widthOfPiece = iso::ScreenWidth() / pieces ;
@@ -470,15 +478,15 @@ void Screen::barWipeHorizontally( const Screen& oldScreen, const Screen& newScre
{
if ( rightToLeft )
{
- allegro::bitBlit( newPicture.getAllegroPict(), buffer.getAllegroPict(), pieceX + widthOfPiece - x, 0, pieceX + widthOfPiece - x, 0, x, iso::ScreenHeight() );
+ allegro::bitBlit( to.getAllegroPict(), from.getAllegroPict(), pieceX + widthOfPiece - x, 0, pieceX + widthOfPiece - x, 0, x, iso::ScreenHeight() );
}
else
{
- allegro::bitBlit( newPicture.getAllegroPict(), buffer.getAllegroPict(), pieceX, 0, pieceX, 0, x, iso::ScreenHeight() );
+ allegro::bitBlit( to.getAllegroPict(), from.getAllegroPict(), pieceX, 0, pieceX, 0, x, iso::ScreenHeight() );
}
}
- allegro::bitBlit( buffer.getAllegroPict(), allegro::Pict::theScreen() );
+ allegro::bitBlit( from.getAllegroPict(), allegro::Pict::theScreen() );
allegro::update ();
milliSleep( 2 );
@@ -493,40 +501,16 @@ void Screen::randomPixelFade( bool fadeIn, const Screen& slide, const Color& col
// refresh screen before fading
slide.refresh();
- AllegroColor aColor = color.toAllegroColor() ;
-
- if ( fadeIn )
- {
+ Picture target = Picture( slide.imageOfScreen->getWidth(), slide.imageOfScreen->getHeight(), color );
+ if ( fadeIn ) {
+ barWipeHorizontally( target, *slide.imageOfScreen, !fadeIn );
+ } else {
+ barWipeHorizontally( *slide.imageOfScreen, target, !fadeIn );
+ AllegroColor aColor = color.toAllegroColor();
allegro::Pict::theScreen().clearToColor( aColor );
- allegro::update();
- }
-
- const unsigned int screenWidth = slide.imageOfScreen->getWidth() ;
- const unsigned int screenHeight = slide.imageOfScreen->getHeight() ;
-
- const size_t howManyPixels = screenWidth * screenHeight;
-
- std::vector< bool > bits( howManyPixels, false ); // bit map of howManyPixels bits
-
- unsigned int limit = ( howManyPixels >= 100000 ) ? ( howManyPixels / 50000 ) - 1 : 0 ;
-
- for ( size_t yet = 0 ; yet < howManyPixels - limit ; )
- {
- int x = rand() % screenWidth ; /* random between 0 and screenWidth - 1 */
- int y = rand() % screenHeight ; /* random between 0 and screenHeight - 1 */
-
- if ( ! bits[ x + y * screenWidth ] )
- {
- if ( fadeIn )
- allegro::Pict::theScreen().drawPixelAt( x, y, slide.imageOfScreen->getPixelAt( x, y ) );
- else
- allegro::Pict::theScreen().drawPixelAt( x, y, aColor );
-
- allegro::update();
-
- bits[ x + y * screenWidth ] = true;
- yet ++;
- }
+#if defined( USE_ALLEGRO5 ) && USE_ALLEGRO5
+ al_flip_display();
+#endif
}
}
diff --git a/src/gui/Screen.hpp b/src/gui/Screen.hpp
index a885789..1ebfc6d 100644
--- a/src/gui/Screen.hpp
+++ b/src/gui/Screen.hpp
@@ -124,6 +124,7 @@ private:
AnimatedPictureWidget * pictureOfHeels ;
static void randomPixelFade( bool fadeIn, const Screen & slide, const Color & color ) ;
+ static void barWipeHorizontally( const Picture from, const Picture to, bool rightToLeft );
protected:
#! /usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="hoh"
rp_module_desc="Open sourced and enhanced remake of 'Head over Heels'"
rp_module_licence="GPL3 https://github.com/dougmencken/HeadOverHeels/blob/master/LICENSE"
rp_module_repo="git https://github.com/dougmencken/HeadOverHeels.git"
rp_module_help="Batteries included: No extra gamefiles needed."
rp_module_section="exp"
rp_module_flags="!all arm rpi4"
_hoh_romdir="$romdir/ports/headoverheels"
_hoh_executable="bin/headoverheels"
function depends_hoh() {
local deb_pkgs=(
autoconf
cmake
liballegro-acodec5-dev
liballegro-audio5-dev
liballegro-image5-dev
liballegro5-dev
libpng-dev
libtinyxml2-dev
libtool
libvorbis-dev
rsync
xorg
)
getDepends ${deb_pkgs[*]}
}
function sources_hoh() {
gitPullOrClone
applyPatch "$md_data/01-menu-intro-outro.patch"
}
function build_hoh() {
mkdir -p m4
[ -f ./configure ] || autoreconf -f -i
local install_prefix="$md_build"/_rootdir
./configure --with-allegro5 --prefix="${install_prefix}" #--enable-debug=yes
make clean
make && make install
md_ret_require="$install_prefix/$_hoh_executable"
}
function install_hoh() {
for d in bin share ; do
mkUserDir "$_hoh_romdir/$d"
rsync --recursive --owner --group --chown="$user":"$user" \
"$md_build"/_rootdir/$d/* "$_hoh_romdir/$d"
done
cp -p "$md_build"/LICENSE "$_hoh_romdir"
chown "$user": "$_hoh_romdir"/LICENSE
}
function configure_hoh() {
local ports_cfg_dir="headoverheels"
local launcher="$md_inst/launcher.sh"
addPort "$md_id" "$ports_cfg_dir" "Head over Heels" "XINIT:$launcher"
[[ "$md_mode" != "install" ]] && return
local pref_dir="$home"/.headoverheels
local pref_file="$pref_dir"/preferences.xml
mkUserDir "$pref_dir"
moveConfigDir "$pref_dir" "$md_conf_root/$ports_cfg_dir"
if [[ ! -e "$pref_file" ]] ; then
cat >"$pref_file" << _EOF_
<preferences>
<language>en_US</language>
<keyboard>
<movenorth>Left</movenorth>
<movesouth>Right</movesouth>
<moveeast>Up</moveeast>
<movewest>Down</movewest>
<jump>Space</jump>
<take>c</take>
<takeandjump>b</takeandjump>
<doughnut>n</doughnut>
<swap>x</swap>
<pause>Esc</pause>
<automap>Tab</automap>
</keyboard>
<audio>
<fx>80</fx>
<music>75</music>
<roomtunes>true</roomtunes>
</audio>
<video>
<fullscreen>true</fullscreen>
<shadows>true</shadows>
<background>true</background>
<graphics>gfx</graphics>
</video>
</preferences>
_EOF_
chown "$user": "$pref_file"
fi
cat >"$launcher" << _EOF_
#! /usr/bin/env bash
xset -dpms s off s noblank
cd "$_hoh_romdir"
bin/headoverheels
killall xinit
_EOF_
chown "$user": "$launcher"
chmod a+x "$launcher"
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment