Something went wrong. Try again.
A modern, network-enabled music player platform built on Rockbox technology. rockboxd.tsiry-sandratraina.com
rust deno navidrome airplay libadwaita zig mpris snapcast mpd rockbox audio subsonic
Something went wrong. Try again.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291/*************************************************************************** * __________ __ ___. * Open \______ \ ____ ____ | | _\_ |__ _______ ___ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ * \/ \/ \/ \/ \/ * * Copyright (C) 2004-2007 Antoine Cellerier <dionoea @t videolan d.t org> * * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * ****************************************************************************/
#include "plugin.h"#include "lib/playback_control.h"#include "lib/configfile.h"#include "lib/display_text.h"#include "button.h"#include "lcd.h"
#define min(a,b) (a<b?a:b)
/** * Key definitions */
#if (CONFIG_KEYPAD == IRIVER_H100_PAD) || \ (CONFIG_KEYPAD == IRIVER_H300_PAD)# define SOL_QUIT BUTTON_OFF# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MODE# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_ON)# define SOL_CUR2STACK_PRE BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_ON)# define SOL_REM BUTTON_REC# define SOL_RC_QUIT BUTTON_RC_STOP# define HK_MOVE "NAVI"# define HK_DRAW "A-B"# define HK_REM2CUR "PLAY+LEFT"# define HK_CUR2STACK "NAVI.."# define HK_REM2STACK "PLAY+RIGHT"
#elif (CONFIG_KEYPAD == IPOD_4G_PAD) || (CONFIG_KEYPAD == IPOD_3G_PAD) || \ (CONFIG_KEYPAD == IPOD_1G2G_PAD)# define SOL_QUIT (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_UP BUTTON_SCROLL_BACK# define SOL_DOWN BUTTON_SCROLL_FWD# define SOL_LEFT_PRE BUTTON_LEFT# define SOL_LEFT (BUTTON_LEFT | BUTTON_REL)# define SOL_RIGHT_PRE BUTTON_RIGHT# define SOL_RIGHT (BUTTON_RIGHT | BUTTON_REL)# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW_PRE BUTTON_MENU# define SOL_DRAW (BUTTON_MENU | BUTTON_REL)# define SOL_REM2CUR BUTTON_PLAY# define SOL_CUR2STACK_PRE BUTTON_MENU# define SOL_CUR2STACK (BUTTON_MENU | BUTTON_REPEAT)# define SOL_REM2STACK_PRE BUTTON_RIGHT# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_REPEAT)# define HK_UD "SCROLL U/D"# define HK_MOVE "SELECT"# define HK_DRAW "MENU"# define HK_REM2CUR "PLAY"# define HK_CUR2STACK "MENU.."# define HK_REM2STACK "RIGHT.."
#elif (CONFIG_KEYPAD == IAUDIO_X5M5_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW_PRE BUTTON_PLAY# define SOL_DRAW (BUTTON_PLAY | BUTTON_REL)# define SOL_REM2CUR_PRE BUTTON_PLAY# define SOL_REM2CUR (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_CUR2STACK_PRE BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_REC# define HK_MOVE "SELECT"# define HK_DRAW "PLAY"# define HK_REM2CUR "PLAY.."# define HK_CUR2STACK "SELECT.."# define HK_REM2STACK "REC"
#elif (CONFIG_KEYPAD == GIGABEAT_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_A)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_A)# define HK_MOVE "SELECT"# define HK_DRAW "MENU"# define HK_REM2CUR "A+LEFT"# define HK_CUR2STACK "SELECT.."# define HK_REM2STACK "A+RIGHT"
#elif (CONFIG_KEYPAD == SANSA_E200_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_SCROLL_BACK# define SOL_RIGHT BUTTON_SCROLL_FWD# define SOL_MOVE BUTTON_SELECT# define SOL_DRAW BUTTON_REC# define SOL_REM2CUR BUTTON_LEFT# define SOL_CUR2STACK_PRE BUTTON_REC# define SOL_CUR2STACK (BUTTON_REC | BUTTON_RIGHT)# define SOL_REM2STACK BUTTON_RIGHT# define HK_MOVE "SELECT"# define HK_DRAW "REC"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "DOUBLE SELECT"# define HK_REM2STACK "RIGHT"
#elif (CONFIG_KEYPAD == SANSA_FUZE_PAD)# define SOL_QUIT (BUTTON_HOME|BUTTON_REPEAT)# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_SCROLL_BACK# define SOL_RIGHT BUTTON_SCROLL_FWD# define SOL_MOVE (BUTTON_SELECT|BUTTON_REL)# define SOL_DRAW (BUTTON_HOME|BUTTON_REL)# define SOL_REM2CUR BUTTON_LEFT# define SOL_CUR2STACK_PRE (BUTTON_RIGHT | BUTTON_REPEAT)# define SOL_CUR2STACK BUTTON_RIGHT# define SOL_REM2STACK (BUTTON_LEFT|BUTTON_REPEAT)# define SOL_REM2STACK_PRE BUTTON_LEFT# define HK_MOVE "SHORT SELECT"# define HK_DRAW "SHORT HOME"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "DOUBLE SELECT"# define HK_REM2STACK "LEFT"
#elif (CONFIG_KEYPAD == SANSA_C200_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_VOL_DOWN# define SOL_REM2CUR BUTTON_REC# define SOL_CUR2STACK_PRE BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "SELECT"# define HK_DRAW "REC"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "DOUBLE SELECT"# define HK_REM2STACK "RIGHT"
#elif CONFIG_KEYPAD == SANSA_CLIP_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_HOME# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "SELECT"# define HK_DRAW "HOME"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "DOUBLE SELECT"# define HK_REM2STACK "RIGHT"
#elif CONFIG_KEYPAD == SANSA_M200_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW (BUTTON_SELECT | BUTTON_UP)# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "SELECT"# define HK_DRAW "SELECT + UP"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "DOUBLE SELECT"# define HK_REM2STACK "RIGHT"
#elif (CONFIG_KEYPAD == IRIVER_H10_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_SCROLL_UP# define SOL_DOWN BUTTON_SCROLL_DOWN# define SOL_LEFT_PRE BUTTON_LEFT# define SOL_LEFT (BUTTON_LEFT | BUTTON_REL)# define SOL_RIGHT_PRE BUTTON_RIGHT# define SOL_RIGHT (BUTTON_RIGHT | BUTTON_REL)# define SOL_MOVE BUTTON_PLAY# define SOL_DRAW_PRE BUTTON_LEFT# define SOL_DRAW (BUTTON_LEFT | BUTTON_REPEAT)# define SOL_REM2CUR BUTTON_FF# define SOL_CUR2STACK BUTTON_REW# define SOL_REM2STACK_PRE BUTTON_RIGHT# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_REPEAT)# define HK_MOVE "PLAY"# define HK_DRAW "LEFT.."# define HK_REM2CUR "FF"# define HK_CUR2STACK "REW"# define HK_REM2STACK "RIGHT.."
#elif (CONFIG_KEYPAD == GIGABEAT_S_PAD)# define SOL_QUIT BUTTON_BACK# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_SELECT)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_SELECT)# define HK_MOVE "SELECT"# define HK_DRAW "MENU"# define HK_REM2CUR "SELECT+LEFT"# define HK_CUR2STACK "SELECT.."# define HK_REM2STACK "SELECT+RIGHT"
#elif (CONFIG_KEYPAD == MROBE100_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_DISPLAY)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_DISPLAY)# define HK_MOVE "SELECT"# define HK_DRAW "MENU"# define HK_REM2CUR "DISPLAY+LEFT"# define HK_CUR2STACK "SELECT.."# define HK_REM2STACK "DISPLAY+RIGHT"
#elif CONFIG_KEYPAD == IAUDIO_M3_PAD# define SOL_QUIT BUTTON_RC_REC# define SOL_UP BUTTON_RC_VOL_UP# define SOL_DOWN BUTTON_RC_VOL_DOWN# define SOL_LEFT BUTTON_RC_REW# define SOL_RIGHT BUTTON_RC_FF# define SOL_MOVE BUTTON_RC_PLAY# define SOL_DRAW_PRE BUTTON_RC_MENU# define SOL_DRAW (BUTTON_RC_MENU | BUTTON_REL)# define SOL_REM2CUR_PRE BUTTON_RC_MENU# define SOL_REM2CUR (BUTTON_RC_MENU | BUTTON_REPEAT)# define SOL_CUR2STACK_PRE BUTTON_RC_MODE# define SOL_CUR2STACK (BUTTON_RC_MODE | BUTTON_REL)# define SOL_REM2STACK_PRE BUTTON_RC_MODE# define SOL_REM2STACK (BUTTON_RC_MODE | BUTTON_REPEAT)# define HK_LR "REW/FF"# define HK_UD "VOL UP/DOWN"# define HK_MOVE "PLAY"# define HK_DRAW "MENU"# define HK_REM2CUR "MENU.."# define HK_CUR2STACK "MODE"# define HK_REM2STACK "MODE.."
#elif (CONFIG_KEYPAD == COWON_D2_PAD)# define SOL_QUIT BUTTON_POWER
#elif (CONFIG_KEYPAD == CREATIVE_ZENXFI3_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_BACK# define SOL_RIGHT BUTTON_MENU# define SOL_MOVE (BUTTON_PLAY|BUTTON_REL)# define SOL_DRAW (BUTTON_PLAY|BUTTON_REPEAT)# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE (BUTTON_VOL_UP | BUTTON_REPEAT)# define SOL_CUR2STACK BUTTON_VOL_UP# define SOL_REM2STACK (BUTTON_VOL_DOWN|BUTTON_REPEAT)# define SOL_REM2STACK_PRE BUTTON_VOL_DOWN
# define HK_MOVE "SHORT PLAY"# define HK_DRAW "LONG PLAY"# define HK_REM2CUR "VOLUME-"# define HK_CUR2STACK "VOLUME+"# define HK_REM2STACK "LONG VOLUME-"
#elif CONFIG_KEYPAD == PHILIPS_HDD1630_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_LEFT | BUTTON_VIEW)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_RIGHT | BUTTON_VIEW)# define HK_MOVE "SELECT"# define HK_DRAW "MENU"# define HK_REM2CUR "VIEW+LEFT"# define HK_CUR2STACK "SELECT.."# define HK_REM2STACK "VIEW+RIGHT"
#elif CONFIG_KEYPAD == PHILIPS_HDD6330_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_PREV# define SOL_RIGHT BUTTON_NEXT# define SOL_MOVE_PRE BUTTON_PLAY# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR BUTTON_LEFT# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_RIGHT# define HK_MOVE "PLAY"# define HK_DRAW "MENU"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "PLAY.."# define HK_REM2STACK "RIGHT"
#elif CONFIG_KEYPAD == PHILIPS_SA9200_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_PREV# define SOL_RIGHT BUTTON_NEXT# define SOL_MOVE_PRE BUTTON_PLAY# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR BUTTON_LEFT# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_RIGHT# define HK_MOVE "PLAY"# define HK_DRAW "MENU"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "PLAY..."# define HK_REM2STACK "RIGHT"
#elif (CONFIG_KEYPAD == ONDAVX747_PAD) || \(CONFIG_KEYPAD == ONDAVX777_PAD) || \CONFIG_KEYPAD == MROBE500_PAD# define SOL_QUIT BUTTON_POWER
#elif CONFIG_KEYPAD == SAMSUNG_YH820_PAD# define SOL_QUIT BUTTON_REW# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE BUTTON_PLAY# define SOL_DRAW BUTTON_FFWD# define SOL_REM2CUR (BUTTON_REC | BUTTON_DOWN)# define SOL_CUR2STACK (BUTTON_REC | BUTTON_UP)# define SOL_REM2STACK (BUTTON_REC | BUTTON_RIGHT)# define HK_MOVE "PLAY"# define HK_DRAW "FFWD"# define HK_REM2CUR "REC+DOWN"# define HK_CUR2STACK "REC+UP"# define HK_REM2STACK "REC+RIGHT"
#elif CONFIG_KEYPAD == SAMSUNG_YH92X_PAD# define SOL_QUIT BUTTON_REW# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_PLAY# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW BUTTON_FFWD# define SOL_REM2CUR (BUTTON_PLAY | BUTTON_DOWN)# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_UP)# define SOL_REM2STACK (BUTTON_PLAY | BUTTON_RIGHT)# define HK_MOVE "PLAY"# define HK_DRAW "FFWD"# define HK_REM2CUR "PLAY+DOWN"# define HK_CUR2STACK "PLAY+UP"# define HK_REM2STACK "PLAY+RIGHT"
#elif CONFIG_KEYPAD == PBELL_VIBE500_PAD# define SOL_QUIT BUTTON_REC# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_PREV# define SOL_RIGHT BUTTON_NEXT# define SOL_MOVE_PRE BUTTON_OK# define SOL_MOVE (BUTTON_OK | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR BUTTON_CANCEL# define SOL_CUR2STACK BUTTON_PLAY# define SOL_REM2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define HK_MOVE "OK"# define HK_DRAW "MENU"# define HK_REM2CUR "CANCEL"# define HK_CUR2STACK "PLAY"# define HK_REM2STACK "PLAY..."
#elif CONFIG_KEYPAD == MPIO_HD200_PAD# define SOL_QUIT (BUTTON_REC | BUTTON_PLAY)# define SOL_UP BUTTON_REW# define SOL_DOWN BUTTON_FF# define SOL_LEFT BUTTON_VOL_DOWN# define SOL_RIGHT BUTTON_VOL_UP# define SOL_MOVE_PRE BUTTON_FUNC# define SOL_MOVE (BUTTON_FUNC | BUTTON_REL)# define SOL_DRAW BUTTON_REC# define SOL_REM2CUR (BUTTON_REC | BUTTON_REPEAT)# define SOL_CUR2STACK BUTTON_PLAY# define SOL_REM2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define HK_MOVE "FUNC"# define HK_DRAW "REC"# define HK_REM2CUR "REC.."# define HK_CUR2STACK "PLAY"# define HK_REM2STACK "PLAY...."
#elif CONFIG_KEYPAD == MPIO_HD300_PAD# define SOL_QUIT (BUTTON_MENU | BUTTON_REPEAT)# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_REW# define SOL_RIGHT BUTTON_FF# define SOL_MOVE_PRE BUTTON_ENTER# define SOL_MOVE (BUTTON_ENTER | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_PLAY | BUTTON_REL)# define SOL_CUR2STACK BUTTON_REC# define SOL_REM2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define HK_MOVE "ENTER"# define HK_DRAW "MENU"# define HK_REM2CUR "PLAY"# define HK_CUR2STACK "ENTER..."# define HK_REM2STACK "PLAY...."
#elif CONFIG_KEYPAD == SANSA_FUZEPLUS_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE BUTTON_SELECT# define SOL_DRAW BUTTON_BACK# define SOL_REM2CUR BUTTON_BOTTOMLEFT# define SOL_CUR2STACK BUTTON_PLAYPAUSE|BUTTON_REL# define SOL_REM2STACK BUTTON_PLAYPAUSE|BUTTON_REPEAT# define HK_MOVE "SELECT"# define HK_DRAW "BACK"# define HK_REM2CUR "BOTTOM-LEFT"# define HK_CUR2STACK "PLAY-PAUSE"# define HK_REM2STACK "BOTTOM-RIGHT"
#elif (CONFIG_KEYPAD == SANSA_CONNECT_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_SCROLL_BACK# define SOL_RIGHT BUTTON_SCROLL_FWD# define SOL_MOVE BUTTON_SELECT# define SOL_DRAW BUTTON_VOL_UP# define SOL_REM2CUR BUTTON_LEFT# define SOL_CUR2STACK_PRE BUTTON_VOL_DOWN# define SOL_CUR2STACK BUTTON_NEXT# define SOL_REM2STACK BUTTON_PREV# define HK_MOVE "SELECT"# define HK_DRAW "Vol+"# define HK_REM2CUR "LEFT"# define HK_CUR2STACK "NEXT"# define HK_REM2STACK "PREV"
#elif (CONFIG_KEYPAD == SAMSUNG_YPR0_PAD)# define SOL_QUIT BUTTON_BACK# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_USER | BUTTON_REPEAT)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_POWER# define HK_MOVE "Select"# define HK_DRAW "Menu"# define HK_REM2CUR "Long User"# define HK_CUR2STACK "Long Select.."# define HK_REM2STACK "Power"
#elif (CONFIG_KEYPAD == HM60X_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_POWER | BUTTON_SELECT)# define SOL_DRAW (BUTTON_POWER | BUTTON_UP)# define SOL_REM2CUR (BUTTON_POWER | BUTTON_DOWN)# define SOL_CUR2STACK (BUTTON_POWER | BUTTON_LEFT)# define SOL_REM2STACK (BUTTON_POWER | BUTTON_RIGHT)# define HK_MOVE "SELECT + POWER"# define HK_DRAW "UP + POWER"# define HK_REM2CUR "DOWN + POWER"# define HK_CUR2STACK "LEFT + POWER"# define HK_REM2STACK "RIGHT + POWER"
#elif (CONFIG_KEYPAD == HM801_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_PREV# define SOL_MOVE BUTTON_NEXT# define SOL_DRAW BUTTON_PLAY# define SOL_REM2CUR BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_POWER | BUTTON_LEFT)# define SOL_REM2STACK (BUTTON_POWER | BUTTON_RIGHT)# define HK_MOVE "PREV"# define HK_DRAW "PLAY"# define HK_REM2CUR "SELECT"# define HK_CUR2STACK "POWER + LEFT"# define HK_REM2STACK "POWER + RIGHT"
#elif (CONFIG_KEYPAD == SONY_NWZ_PAD)#define SOL_QUIT BUTTON_BACK#define SOL_UP BUTTON_UP#define SOL_DOWN BUTTON_DOWN#define SOL_LEFT BUTTON_LEFT#define SOL_RIGHT BUTTON_RIGHT#define SOL_MOVE BUTTON_PLAY#define SOL_DRAW (BUTTON_POWER|BUTTON_UP)#define SOL_REM2CUR (BUTTON_POWER|BUTTON_DOWN)#define SOL_CUR2STACK (BUTTON_POWER|BUTTON_LEFT)#define SOL_REM2STACK (BUTTON_POWER|BUTTON_RIGHT)#define HK_MOVE "Play"#define HK_DRAW "Option+Up"#define HK_REM2CUR "Option+Down"#define HK_CUR2STACK "Option+Left"#define HK_REM2STACK "Option+Right"
#elif (CONFIG_KEYPAD == AGPTEK_ROCKER_PAD)#define SOL_QUIT BUTTON_POWER#define SOL_UP BUTTON_UP#define SOL_DOWN BUTTON_DOWN#define SOL_LEFT BUTTON_LEFT#define SOL_RIGHT BUTTON_RIGHT#define SOL_MOVE BUTTON_SELECT#define SOL_DRAW (BUTTON_VOLUP|BUTTON_UP)#define SOL_REM2CUR (BUTTON_VOLUP|BUTTON_DOWN)#define SOL_CUR2STACK (BUTTON_VOLUP|BUTTON_LEFT)#define SOL_REM2STACK (BUTTON_VOLUP|BUTTON_RIGHT)#define HK_MOVE "Select"#define HK_DRAW "Option+Up"#define HK_REM2CUR "Option+Down"#define HK_CUR2STACK "Option+Left"#define HK_REM2STACK "Option+Right"
#elif (CONFIG_KEYPAD == CREATIVE_ZEN_PAD)#define SOL_QUIT BUTTON_POWER#define SOL_UP BUTTON_UP#define SOL_DOWN BUTTON_DOWN#define SOL_LEFT BUTTON_LEFT#define SOL_RIGHT BUTTON_RIGHT#define SOL_MOVE BUTTON_SELECT#define SOL_DRAW BUTTON_PLAYPAUSE#define SOL_REM2CUR BUTTON_BACK#define SOL_CUR2STACK BUTTON_MENU#define SOL_REM2STACK BUTTON_SHORTCUT#define HK_MOVE "Select"#define HK_DRAW "Play/pause"#define HK_REM2CUR "Back"#define HK_CUR2STACK "Menu"#define HK_REM2STACK "Shortcut"
#elif (CONFIG_KEYPAD == DX50_PAD)# define SOL_QUIT (BUTTON_POWER | BUTTON_REL)
#elif CONFIG_KEYPAD == CREATIVE_ZENXFI2_PAD# define SOL_QUIT BUTTON_POWER
#elif CONFIG_KEYPAD == XDUOO_X3_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_HOME# define SOL_DOWN BUTTON_OPTION# define SOL_LEFT BUTTON_PREV# define SOL_RIGHT BUTTON_NEXT# define SOL_MOVE_PRE BUTTON_PLAY# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW (BUTTON_POWER | BUTTON_REPEAT)# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE BUTTON_PLAY# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "PLAY"# define HK_DRAW "DBL HOME"# define HK_REM2CUR "PREV"# define HK_CUR2STACK "DBL PLAY"# define HK_REM2STACK "NEXT"
#elif CONFIG_KEYPAD == XDUOO_X3II_PAD || CONFIG_KEYPAD == XDUOO_X20_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_HOME# define SOL_DOWN BUTTON_OPTION# define SOL_LEFT BUTTON_PREV# define SOL_RIGHT BUTTON_NEXT# define SOL_MOVE_PRE BUTTON_PLAY# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW (BUTTON_POWER | BUTTON_REPEAT)# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE BUTTON_PLAY# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "PLAY"# define HK_DRAW "DBL HOME"# define HK_REM2CUR "PREV"# define HK_CUR2STACK "DBL PLAY"# define HK_REM2STACK "NEXT"
#elif CONFIG_KEYPAD == IHIFI_770_PAD || CONFIG_KEYPAD == IHIFI_800_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_PREV# define SOL_DOWN BUTTON_NEXT# define SOL_LEFT BUTTON_HOME# define SOL_RIGHT BUTTON_VOL_DOWN# define SOL_MOVE_PRE BUTTON_VOL_UP# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW (BUTTON_POWER | BUTTON_REPEAT)# define SOL_REM2CUR (BUTTON_POWER | BUTTON_VOL_DOWN)# define SOL_CUR2STACK_PRE BUTTON_PLAY# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_POWER | BUTTON_VOL_UP)# define HK_MOVE "PLAY"# define HK_DRAW "DBL POWER"# define HK_REM2CUR "POWER"# define HK_CUR2STACK "DBL PLAY"# define HK_REM2STACK "POWER+"
#elif CONFIG_KEYPAD == EROSQ_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_PREV# define SOL_DOWN BUTTON_NEXT# define SOL_LEFT BUTTON_SCROLL_BACK# define SOL_RIGHT BUTTON_SCROLL_FWD# define SOL_MOVE_PRE BUTTON_PLAY# define SOL_MOVE (BUTTON_PLAY | BUTTON_REL)# define SOL_DRAW (BUTTON_POWER | BUTTON_REPEAT)# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE BUTTON_PLAY# define SOL_CUR2STACK (BUTTON_PLAY | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "PLAY"# define HK_DRAW "DBL HOME"# define HK_REM2CUR "PREV"# define HK_CUR2STACK "DBL PLAY"# define HK_REM2STACK "NEXT"
#elif CONFIG_KEYPAD == FIIO_M3K_PAD# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT|BUTTON_REL)# define SOL_DRAW BUTTON_PLAY# define SOL_REM2CUR BUTTON_VOL_DOWN# define SOL_CUR2STACK_PRE BUTTON_SELECT# define SOL_CUR2STACK (BUTTON_SELECT|BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_VOL_UP# define HK_MOVE "SELECT"# define HK_DRAW "PLAY"# define HK_REM2CUR "VOL-"# define HK_CUR2STACK "HOLD SELECT"# define HK_REM2STACK "VOL+"
#elif CONFIG_KEYPAD == SHANLING_Q1_PAD || CONFIG_KEYPAD == HIBY_R3PROII_PAD || CONFIG_KEYPAD == HIDIZS_AP80MAX_PAD# define SOL_QUIT BUTTON_POWER
#elif CONFIG_PAD == SDL_APP# define SOL_QUIT (BUTTON_SELECT | BUTTON_MENU)# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT_PRE BUTTON_LEFT# define SOL_LEFT (BUTTON_LEFT | BUTTON_SELECT)# define SOL_RIGHT_PRE BUTTON_RIGHT# define SOL_RIGHT (BUTTON_RIGHT | BUTTON_SELECT)# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_UP)# define SOL_DRAW_PRE BUTTON_MENU# define HK_UD "SCROLL U/D"# define HK_MOVE "SELECT"# define HK_DRAW "MENU"# define HK_REM2CUR "PLAY"# define HK_CUR2STACK "MENU.."# define HK_REM2STACK "RIGHT.."#elif CONFIG_KEYPAD == RG_NANO_PAD# define SOL_QUIT BUTTON_START# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE BUTTON_A# define SOL_DRAW BUTTON_X# define SOL_REM2CUR BUTTON_L# define SOL_CUR2STACK BUTTON_B# define SOL_REM2STACK BUTTON_R# define HK_MOVE "A"# define HK_DRAW "X"# define HK_REM2CUR "L"# define HK_CUR2STACK "B"# define HK_REM2STACK "R"
#elif (CONFIG_KEYPAD == N3DS_PAD)# define SOL_QUIT BUTTON_BACK# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_USER | BUTTON_REPEAT)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_POWER# define HK_MOVE "A"# define HK_DRAW "X"# define HK_REM2CUR "Long Y"# define HK_CUR2STACK "Long A.."# define HK_REM2STACK "Start"
#elif CONFIG_KEYPAD == MA_PAD# define SOL_QUIT (BUTTON_LEFT|BUTTON_REPEAT)# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_MENU# define SOL_MOVE (BUTTON_MENU|BUTTON_REPEAT)# define SOL_DRAW BUTTON_PLAY# define SOL_REM2CUR (BUTTON_MENU|BUTTON_DOWN)# define SOL_CUR2STACK_PRE BUTTON_BACK# define SOL_CUR2STACK (BUTTON_BACK|BUTTON_REPEAT)# define SOL_REM2STACK (BUTTON_MENU|BUTTON_UP)# define HK_MOVE "MENU"# define HK_DRAW "PLAY"# define HK_REM2CUR "MENU+DOWN"# define HK_CUR2STACK "BACK"# define HK_REM2STACK "MENU+UP"
#elif (CONFIG_KEYPAD == ECHO_R1_PAD)# define SOL_QUIT BUTTON_POWER# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_A# define SOL_MOVE (BUTTON_A | BUTTON_REL)# define SOL_DRAW BUTTON_X# define SOL_REM2CUR (BUTTON_Y | BUTTON_REPEAT)# define SOL_CUR2STACK (BUTTON_A | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_START# define HK_MOVE "A"# define HK_DRAW "X"# define HK_REM2CUR "Long Y"# define HK_CUR2STACK "Long A.."# define HK_REM2STACK "Start"
#elif (CONFIG_KEYPAD == PSP_PAD)# define SOL_QUIT BUTTON_BACK# define SOL_UP BUTTON_UP# define SOL_DOWN BUTTON_DOWN# define SOL_LEFT BUTTON_LEFT# define SOL_RIGHT BUTTON_RIGHT# define SOL_MOVE_PRE BUTTON_SELECT# define SOL_MOVE (BUTTON_SELECT | BUTTON_REL)# define SOL_DRAW BUTTON_MENU# define SOL_REM2CUR (BUTTON_USER | BUTTON_REPEAT)# define SOL_CUR2STACK (BUTTON_SELECT | BUTTON_REPEAT)# define SOL_REM2STACK BUTTON_POWER# define HK_MOVE "Cross"# define HK_DRAW "Square"# define HK_REM2CUR "Long Triangle"# define HK_CUR2STACK "Long Cross.."# define HK_REM2STACK "Start"
#else#error No keymap defined!#endif
#ifdef HAVE_TOUCHSCREEN//#ifndef SOL_QUIT//# define SOL_QUIT BUTTON_TOPLEFT//endif#ifndef SOL_UP# define SOL_UP BUTTON_TOPMIDDLE#endif#ifndef SOL_DOWN# define SOL_DOWN BUTTON_BOTTOMMIDDLE#endif#ifndef SOL_LEFT# define SOL_LEFT BUTTON_MIDLEFT#endif#ifndef SOL_RIGHT# define SOL_RIGHT BUTTON_MIDRIGHT#endif#ifndef SOL_MOVE# define SOL_MOVE BUTTON_CENTER# define HK_MOVE "CENTRE"#endif#ifndef SOL_DRAW# define SOL_DRAW BUTTON_TOPLEFT# define HK_DRAW "TOPLEFT"#endif#ifndef SOL_REM2CUR# define SOL_REM2CUR BUTTON_TOPRIGHT# define HK_REM2CUR "TOPRIGHT"#endif#ifndef SOL_CUR2STACK# define SOL_CUR2STACK BUTTON_BOTTOMLEFT# define HK_CUR2STACK "BOTTOMLEFT"#endif#ifndef SOL_REM2STACK# define SOL_REM2STACK BUTTON_BOTTOMRIGHT# define HK_REM2STACK "BOTTOMRIGHT"#endif
#endif
#ifndef HK_LR# define HK_LR "LEFT/RIGHT"#endif#ifndef HK_UD# define HK_UD "UP/DOWN"#endif
/** * Misc constants, graphics and other defines */
#include "pluginbitmaps/card_back.h"#include "pluginbitmaps/card_deck.h"#include "pluginbitmaps/solitaire_suitsi.h"
#define CARD_GFX_WIDTH BMPWIDTH_card_back#define CARD_GFX_HEIGHT BMPHEIGHT_card_back#define CARD_WIDTH (BMPWIDTH_card_back+2)#define CARD_HEIGHT (BMPHEIGHT_card_back+2)
#if LCD_WIDTH >= 640# define MARGIN 4# define LARGE_CARD# define SYMBOL_HEIGHT 24
#elif LCD_WIDTH >= 320# define MARGIN 4# define LARGE_CARD# define SYMBOL_HEIGHT 12#elif LCD_WIDTH >= 220# define MARGIN 3# define LARGE_CARD# define SYMBOL_HEIGHT 12#elif LCD_WIDTH >= 160# define MARGIN 2# define SYMBOL_HEIGHT 11#elif LCD_WIDTH >= 128# define MARGIN 1# define SYMBOL_HEIGHT 10#else# define MARGIN 0# define SYMBOL_HEIGHT 8#endif
#define CARD_START (CARD_HEIGHT+2*MARGIN+1)
/* background color */#ifdef HAVE_LCD_COLOR# define BACKGROUND_COLOR LCD_RGBPACK(0,157,0)# define FRAME_COLOR LCD_RGBPACK(23,119,218)#elif LCD_DEPTH > 1# define BACKGROUND_COLOR LCD_WHITE# define FRAME_COLOR LCD_BLACK#endif
#define CONFIG_FILENAME "sol.cfg"
#define NOT_A_CARD -1
/* number of cards per suit */#define CARDS_PER_SUIT 13
/* number of suits */#define SUITS 4
#define NUM_CARDS ( CARDS_PER_SUIT * SUITS )
/* number of columns */#define COL_NUM 7
/* pseudo column numbers to be used for cursor coordinates *//* columns COL_NUM to COL_NUM + SUITS - 1 correspond to the final stacks */#define STACKS_COL COL_NUM/* column COL_NUM + SUITS corresponds to the remains' stack */#define REM_COL (STACKS_COL + SUITS)
#define NOT_A_COL -1
#if defined(SOL_LEFT_PRE) || defined(SOL_RIGHT_PRE) || \ defined(SOL_DOWN_PRE) || defined(SOL_UP_PRE) || \ defined(SOL_CUR2STACK_PRE) || defined(SOL_MOVE_PRE) || \ defined(SOL_REM2CUR_PRE) || defined(SOL_REM2STACK_PRE) || \ defined(SOL_DRAW_PRE)# define NEED_LASTBUTTON_VAR#endif
typedef struct{ signed char suit; signed char num; bool known : 1; bool used : 1; /* this is what is used when dealing cards */ signed char next;} card_t;
/** * LCD card drawing routines */
static void draw_cursor( int x, int y ){ rb->lcd_set_drawmode( DRMODE_COMPLEMENT ); rb->lcd_fillrect( x+1, y+1, CARD_GFX_WIDTH, CARD_GFX_HEIGHT );#ifdef LARGE_CARD rb->lcd_drawpixel( x+1, y+1 ); rb->lcd_drawpixel( x+1, y+CARD_HEIGHT-2 ); rb->lcd_drawpixel( x+CARD_WIDTH-2, y+1 ); rb->lcd_drawpixel( x+CARD_WIDTH-2, y+CARD_HEIGHT-2 );#endif rb->lcd_set_drawmode( DRMODE_SOLID );}
/* Draw a card's border, select it if it's selected and draw the cursor * if the cursor is currently over the card */static void draw_card_ext( int x, int y, bool selected, bool cursor ){#if LCD_DEPTH > 1 int oldfg = rb->lcd_get_foreground();
rb->lcd_set_foreground( LCD_BLACK );#endif#ifdef LARGE_CARD rb->lcd_hline( x+2, x+CARD_WIDTH-3, y ); rb->lcd_hline( x+2, x+CARD_WIDTH-3, y+CARD_HEIGHT-1 ); rb->lcd_vline( x, y+2, y+CARD_HEIGHT-3 ); rb->lcd_vline( x+CARD_WIDTH-1, y+2, y+CARD_HEIGHT-3 ); rb->lcd_drawpixel( x+1, y+1 ); rb->lcd_drawpixel( x+1, y+CARD_HEIGHT-2 ); rb->lcd_drawpixel( x+CARD_WIDTH-2, y+1 ); rb->lcd_drawpixel( x+CARD_WIDTH-2, y+CARD_HEIGHT-2 );#else rb->lcd_hline( x+1, x+CARD_WIDTH-2, y ); rb->lcd_hline( x+1, x+CARD_WIDTH-2, y+CARD_HEIGHT-1 ); rb->lcd_vline( x, y+1, y+CARD_HEIGHT-2 ); rb->lcd_vline( x+CARD_WIDTH-1, y+1, y+CARD_HEIGHT-2 );#endif
if( selected ) {#if LCD_DEPTH > 1 rb->lcd_set_foreground( FRAME_COLOR );#endif rb->lcd_drawrect( x+1, y+1, CARD_WIDTH-2, CARD_HEIGHT-2 );#ifdef LARGE_CARD rb->lcd_drawrect( x+2, y+2, CARD_WIDTH-4, CARD_HEIGHT-4 );#endif }#if LCD_DEPTH > 1 rb->lcd_set_foreground( oldfg );#endif
if( cursor ) { draw_cursor( x, y ); }}
/* Draw a card's inner graphics */static void draw_card( card_t *card, int x, int y, bool selected, bool cursor ){ if( card->known ) { rb->lcd_bitmap_part( card_deck, CARD_GFX_WIDTH * card->num, CARD_GFX_HEIGHT * card->suit, STRIDE(SCREEN_MAIN, BMPWIDTH_card_deck, BMPHEIGHT_card_deck), x+1, y+1, CARD_GFX_WIDTH, CARD_GFX_HEIGHT ); } else { rb->lcd_bitmap( card_back, x+1, y+1, CARD_GFX_WIDTH, CARD_GFX_HEIGHT ); } draw_card_ext( x, y, selected, cursor );}
/* Draw an empty stack */static void draw_empty_stack( int s, int x, int y, bool cursor ){ rb->lcd_bitmap_part( solitaire_suitsi, 0, CARD_GFX_HEIGHT * s, STRIDE( SCREEN_MAIN, BMPWIDTH_solitaire_suitsi, BMPHEIGHT_solitaire_suitsi), x+1, y+1, CARD_GFX_WIDTH, CARD_GFX_HEIGHT );
draw_card_ext( x, y, false, cursor );}
/* Help */static bool solitaire_help( void ){ static char* help_text[] = { "Solitaire", "", "Controls", "", HK_LR ":", "Move", "the", "cursor", "to", "the", "previous/", "next", "column.", "", HK_UD ":", "Move", "the", "cursor", "up/", "down", "in", "the", "column.", "", HK_MOVE ":", "Select", "cards,", "move", "cards...", "", HK_DRAW ":", "Deselect", "a", "card", "if", "it", "was", "selected.", "Else", "draw", "new", "card(s)", "from", "the", "remains", "stack.", "", "", "Shortcuts", "", HK_REM2CUR ":", "Put", "the", "card", "on", "top", "of", "the", "remains", "stack", "on", "top", "of", "the", "cursor.", "", HK_CUR2STACK ":", "Put", "the", "card", "under", "the", "cursor", "on", "one", "of", "the", "4", "final", "stacks.", "", HK_REM2STACK ":", "Put", "the", "card", "on", "top", "of", "the", "remains", "stack", "on", "one", "of", "the", "4", "final", "stacks." }; static struct style_text formation[]={ { 0, TEXT_CENTER|TEXT_UNDERLINE }, { 2, C_RED }, { 48, C_RED }, LAST_STYLE_ITEM }; if (display_text(ARRAYLEN(help_text), help_text, formation, NULL, true)) return true; return false;}
/** * Custom menu / options */
#define CFGFILE_VERSION 0
struct sol_config { int draw_type;};
struct sol_config sol_disk = {0};struct sol_config sol;
static struct configdata config[] = { { TYPE_INT, 0, 1, { .int_p = &sol_disk.draw_type }, "draw_type", NULL }};
static const struct opt_items drawcards[2] = { { "Draw Three Cards", -1 }, { "Draw One Card", -1 },};
void solitaire_init(void);
/* menu return codes */enum { MENU_RESUME, MENU_SAVE_AND_QUIT, MENU_QUIT, MENU_USB };
static bool _ingame;static int solitaire_menu_cb(int action, const struct menu_item_ex *this_item, struct gui_synclist *this_list){ (void)this_list; int i = (intptr_t)this_item; if( action == ACTION_REQUEST_MENUITEM ) { if((!_ingame && (i==0 || i==5)) || ( _ingame && i==2 )) return ACTION_EXIT_MENUITEM; } return action;}
static int solitaire_menu(bool in_game){ int selected = 0; int result = -1;
MENUITEM_STRINGLIST(menu, "Solitaire", solitaire_menu_cb, "Resume Game", "Start New Game", "Draw Cards Option", "Help", "Playback Control", "Quit without Saving", "Quit"); _ingame = in_game;
while (result < 0) { switch (rb->do_menu(&menu, &selected, NULL, false)) { default: result = MENU_RESUME; break;
case MENU_ATTACHED_USB: result = MENU_USB; break;
case 0: result = MENU_RESUME; break;
case 1: solitaire_init(); result = MENU_RESUME; break;
case 2: if (rb->set_option("Draw Cards Option", &sol.draw_type, RB_INT, drawcards, 2, NULL)) result = MENU_USB; break;
case 3: if (solitaire_help()) result = MENU_USB; break;
case 4: playback_control(NULL); break;
case 5: result = MENU_QUIT; break;
case 6: result = MENU_SAVE_AND_QUIT; break; } } return result;}
/** * Global variables */
/* player's cursor */int cur_card;/* player's cursor column num */int cur_col;
/* selected card */int sel_card;
/* the deck */card_t deck[ NUM_CARDS ];
/* the remaining cards *//* first card of the remains' stack */int rem;/* upper visible card from the remains' stack */int cur_rem;/* number of cards drawn from the remains stack - 1 */int count_rem;/* number of cards per draw of the remains' stack */int cards_per_draw;
/* the 7 game columns */int cols[COL_NUM];/* the 4 final stacks */int stacks[SUITS];
/** * Card handling routines */
static int next_random_card( card_t *deck ){ int i,r;
r = rb->rand()%(NUM_CARDS)+1; i = 0;
while( r>0 ) { i = (i + 1)%(NUM_CARDS); if( !deck[i].used ) r--; }
deck[i].used = true;
return i;}
/* initialize the game */void solitaire_init( void ){
int c; int i, j;
/* number of cards that are drawn on the remains' stack (by pressing F2) */ if( sol.draw_type == 0 ) { cards_per_draw = 3; } else { cards_per_draw = 1; }
/* init deck */ for( i=0; i<SUITS; i++ ) { for( j=0; j<CARDS_PER_SUIT; j++ ) {#define card deck[i*CARDS_PER_SUIT+j] card.suit = i; card.num = j; card.known = true; card.used = false; card.next = NOT_A_CARD;#undef card } }
/* deal the cards ... */ /* ... in the columns */ for( i=0; i<COL_NUM; i++ ) { c = NOT_A_CARD; for( j=0; j<=i; j++ ) { if( c == NOT_A_CARD ) { cols[i] = next_random_card( deck ); c = cols[i]; } else { deck[c].next = next_random_card( deck ); c = deck[c].next; } if( j < i ) deck[c].known = false; } }
/* ... shuffle what's left of the deck */ rem = next_random_card(deck); c = rem;
for( i=1; i < NUM_CARDS - COL_NUM * (COL_NUM + 1)/2; i++ ) { deck[c].next = next_random_card( deck ); c = deck[c].next; }
/* we now finished dealing the cards. The game can start ! (at last) */
/* init the stack */ for( i = 0; i<SUITS; i++ ) { stacks[i] = NOT_A_CARD; }
/* the cursor starts on upper left card */ cur_card = cols[0]; cur_col = 0;
/* no card is selected */ sel_card = NOT_A_CARD;
/* init the remainder */ cur_rem = NOT_A_CARD;
count_rem = -1;}
/* find the column number in which 'card' can be found */static int find_card_col( int card ){ int i; int c;
if( card == NOT_A_CARD ) return NOT_A_COL;
for( i=0; i<COL_NUM; i++ ) { c = cols[i]; while( c != NOT_A_CARD ) { if( c == card ) return i; c = deck[c].next; } }
for( i=0; i<SUITS; i++ ) { c = stacks[i]; while( c != NOT_A_CARD ) { if( c == card ) return STACKS_COL + i; c = deck[c].next; } }
return REM_COL;}
/* find the card preceding 'card' *//* if it doesn't exist, return NOT_A_CARD */static int find_prev_card( int card ){ int i;
for( i=0; i < NUM_CARDS; i++ ) { if( deck[i].next == card ) return i; }
return NOT_A_CARD;}
/* find the last card of a given column */static int find_last_card( int col ){ int c;
if( col < COL_NUM ) { c = cols[col]; } else if( col < REM_COL ) { c = stacks[col - STACKS_COL]; } else { c = cur_rem; }
if(c == NOT_A_CARD) return c; else { while(deck[c].next != NOT_A_CARD) c = deck[c].next; return c; }}
enum move { MOVE_OK, MOVE_NOT_OK };
static enum move move_card( int dest_col, int src_card ){ /* the column on which to take src_card */ int src_col;
/* the last card of dest_col */ int dest_card;
/* the card under src_card */ int src_card_prev;
/* you can't move no card (at least, it doesn't have any consequence) */ if( src_card == NOT_A_CARD ) return MOVE_NOT_OK; /* you can't put a card back on the remains' stack */ if( dest_col == REM_COL ) return MOVE_NOT_OK; /* you can't move an unknown card */ if( !deck[src_card].known ) return MOVE_NOT_OK;
src_col = find_card_col( src_card ); dest_card = find_last_card( dest_col ); src_card_prev = find_prev_card( src_card );
/* you can't move more than one card at a time from the final stack */ /* to the rest of the game */ if( src_col >= COL_NUM && src_col < REM_COL && deck[src_card].next != NOT_A_CARD ) { return MOVE_NOT_OK; }
/* if we (that means dest) are on one of the 7 columns ... */ if( dest_col < COL_NUM ) { /* ... check is we are on an empty color and that the src is a king */ if( dest_card == NOT_A_CARD && deck[src_card].num == CARDS_PER_SUIT - 1 ) { /* this is a winning combination */ cols[dest_col] = src_card; } /* ... or check if the cards follow one another and have * different colorsuit */ else if(( deck[dest_card].suit + deck[src_card].suit)%2==1 && deck[dest_card].num == deck[src_card].num + 1 ) { /* this is a winning combination */ deck[dest_card].next = src_card; } /* ... or, humpf, well that's not good news */ else { /* this is not a winning combination */ return MOVE_NOT_OK; } } /* if we are on one of the 4 final stacks ... */ else if( dest_col < REM_COL ) { /* ... check if we are on an empty stack... */ if( dest_card == NOT_A_CARD ) { /* ... and the src is an ace and this is the correct final stack */ if( deck[src_card].num == 0 && deck[src_card].suit == dest_col - STACKS_COL ) { /* this is a winning combination */ stacks[dest_col - STACKS_COL] = src_card; } else { /* this is not a winning combination */ return MOVE_NOT_OK; } } else /* non-empty stack */ { /* ...check if the cards follow one another, have the same suit and * {that src has no .next element or is from the remains' stack} */ if( deck[dest_card].suit == deck[src_card].suit && deck[dest_card].num + 1 == deck[src_card].num && (deck[src_card].next == NOT_A_CARD || src_col == REM_COL) ) { /* this is a winning combination */ deck[dest_card].next = src_card; } /* ... or, well that's not good news */ else { /* this is not a winning combination */ return MOVE_NOT_OK; } } } /* if we are on the remains' stack */ else { /* you can't move a card back to the remains' stack */ return MOVE_NOT_OK; }
/* if the src card is from the remains' stack, we don't want to take * the following cards */ if( src_col == REM_COL ) { /* if src card is the first card from the stack */ if( src_card_prev == NOT_A_CARD ) { rem = deck[src_card].next; } /* if src card is not the first card from the stack */ else { deck[src_card_prev].next = deck[src_card].next; } deck[src_card].next = NOT_A_CARD; cur_rem = src_card_prev; count_rem--; } /* if the src card is from somewhere else, just take everything */ else { if( src_card_prev == NOT_A_CARD ) { if( src_col < COL_NUM ) { cols[src_col] = NOT_A_CARD; } else { stacks[src_col - STACKS_COL] = NOT_A_CARD; } } else { deck[src_card_prev].next = NOT_A_CARD; deck[src_card_prev].known = true; } } sel_card = NOT_A_CARD; /* tada ! */ return MOVE_OK;}
enum { SOLITAIRE_WIN, SOLITAIRE_SAVE_AND_QUIT, SOLITAIRE_QUIT, SOLITAIRE_USB };
/** * Bouncing cards at the end of the game */
#define BC_ACCEL ((1<<16)*LCD_HEIGHT/128)#define BC_MYSPEED (6*BC_ACCEL)#define BC_MXSPEED (6*LCD_HEIGHT/128)
static int bouncing_cards( void ){ int i, j, x, vx, y, fp_y, fp_vy, button;
/* flush the button queue */ while( ( button = rb->button_get( false ) ) != BUTTON_NONE ) { if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) return SOLITAIRE_USB; }
/* fun stuff :) */ for( i = CARDS_PER_SUIT-1; i>=0; i-- ) { for( j = 0; j < SUITS; j++ ) { x = LCD_WIDTH-(CARD_WIDTH*4+4+MARGIN)+CARD_WIDTH*j+j+1; fp_y = MARGIN<<16;
#if LCD_WIDTH > 200 vx = rb->rand() % (4*BC_MXSPEED/3-2) - BC_MXSPEED; if( vx >= -1 ) vx += 3;#else vx = rb->rand() % (4*BC_MXSPEED/3) - BC_MXSPEED; if( vx >= 0 ) vx++;#endif
fp_vy = -rb->rand() % BC_MYSPEED;
while( x < LCD_WIDTH && x + CARD_WIDTH > 0 ) { fp_vy += BC_ACCEL; x += vx; fp_y += fp_vy; if( fp_y >= (LCD_HEIGHT-CARD_HEIGHT) << 16 ) { fp_vy = -fp_vy*4/5; fp_y = (LCD_HEIGHT-CARD_HEIGHT) << 16; } y = fp_y >> 16; draw_card( &deck[j*CARDS_PER_SUIT+i], x, y, false, false ); rb->lcd_update_rect( x<0?0:x, y<0?0:y, CARD_WIDTH, CARD_HEIGHT );
button = rb->button_get_w_tmo( 2 ); if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) return SOLITAIRE_USB; if( button == SOL_QUIT || button == SOL_MOVE ) return SOLITAIRE_WIN; } } } return SOLITAIRE_WIN;}
/** * Game save/load routines */static void get_save_filename( char *buf ){#ifdef APPLICATION rb->snprintf(buf, sizeof(buf), PLUGIN_DATA_DIR "/sol.save");#else char *s; rb->strcpy( buf, rb->plugin_get_current_filename() ); s = rb->strrchr( buf, '/' ) + 1; *s = '\0'; rb->strcat( s, "sol.save" );#endif}
static int open_save_file( int flags ){ char buf[MAX_PATH]; get_save_filename( buf ); return rb->open( buf, flags, 0666);}
static void delete_save_file( void ){ char buf[MAX_PATH]; get_save_filename( buf ); rb->remove( buf );}
#ifdef write# undef write#endifstatic int save_write( int fd, const void *buf, size_t count, int *checksum ){ size_t i; if( rb->write( fd, buf, count ) < (ssize_t)count ) return 1; for( i = 0; i < count; i++ ) *checksum += (int)(((const char *)buf)[i]); return 0;}
#ifdef read# undef read#endifstatic int save_read( int fd, void *buf, size_t count, int *checksum ){ size_t i; if( rb->read( fd, buf, count ) < (ssize_t)count ) return 1; for( i = 0; i < count; i++ ) *checksum -= (int)(((const char *)buf)[i]); return 0;}
static int save_game( void ){ int fd = open_save_file( O_CREAT|O_WRONLY|O_TRUNC ); int checksum = 42; if( fd < 0 ) return -1; if( save_write( fd, &cur_card, sizeof( int ), &checksum ) || save_write( fd, &cur_col, sizeof( int ), &checksum ) || save_write( fd, &sel_card, sizeof( int ), &checksum ) || save_write( fd, deck, NUM_CARDS * sizeof( card_t ), &checksum ) || save_write( fd, &rem, sizeof( int ), &checksum ) || save_write( fd, &cur_rem, sizeof( int ), &checksum ) || save_write( fd, &count_rem, sizeof( int ), &checksum ) || save_write( fd, &cards_per_draw, sizeof( int ), &checksum ) || save_write( fd, cols, COL_NUM * sizeof( int ), &checksum ) || save_write( fd, stacks, SUITS * sizeof( int ), &checksum ) || ( rb->write( fd, &checksum, sizeof( int ) ) < (ssize_t)(sizeof( int ) ) ) ) { rb->close( fd ); rb->splash( 2*HZ, "Error while saving game. Aborting." ); return -2; } rb->close( fd ); return 0;}
static int load_game( void ){ int checksum, retval;
int fd = open_save_file( O_RDONLY ); if( fd < 0 ) return -1;
retval = 0; /* Assume good case */ if( ( rb->lseek( fd, -(off_t)sizeof( int ), SEEK_END ) == -((ssize_t)sizeof( int ))-1 ) || ( rb->read( fd, &checksum, sizeof( int ) ) < ((ssize_t)sizeof( int )) ) || ( rb->lseek( fd, 0, SEEK_SET ) == -1 ) || save_read( fd, &cur_card, sizeof( int ), &checksum ) || save_read( fd, &cur_col, sizeof( int ), &checksum ) || save_read( fd, &sel_card, sizeof( int ), &checksum ) || save_read( fd, deck, NUM_CARDS * sizeof( card_t ), &checksum ) || save_read( fd, &rem, sizeof( int ), &checksum ) || save_read( fd, &cur_rem, sizeof( int ), &checksum ) || save_read( fd, &count_rem, sizeof( int ), &checksum ) || save_read( fd, &cards_per_draw, sizeof( int ), &checksum ) || save_read( fd, cols, COL_NUM * sizeof( int ), &checksum ) || save_read( fd, stacks, SUITS * sizeof( int ), &checksum ) ) { rb->splash( 2*HZ, "Error while loading saved game. Aborting." ); retval = -2; } else if( checksum != 42 ) { rb->splash( 2*HZ, "Save file was corrupted. Aborting." ); retval = -3; }
rb->close( fd ); delete_save_file(); return retval;}
/** * The main game loop * * If skipmenu is defined to SOLITAIRE_QUIT, the menu will be skipped and * game will resume. */
static int solitaire( int skipmenu ){
int i,j; int button;#ifdef NEED_LASTBUTTON_VAR int lastbutton = 0;#endif int c,h,prevcard; int biggest_col_length;
if( skipmenu != SOLITAIRE_QUIT ) { switch( solitaire_menu(false) ) { case MENU_SAVE_AND_QUIT: return SOLITAIRE_QUIT;
case MENU_USB: return SOLITAIRE_USB; } solitaire_init(); }
while( true ) { rb->lcd_clear_display();
/* get the biggest column length so that display can be "optimized" */ biggest_col_length = 0;
for(i=0;i<COL_NUM;i++) { j = 0; c = cols[i];
if( c != NOT_A_CARD ) { while( true ) { /* don't include the last card in the column length. */ if( deck[c].next == NOT_A_CARD ) { break; /* no successor: get outta here. */ } else { if( deck[c].known ) j += 2; else j++; } c = deck[c].next; } /* make column distinguishable from an empty column, * and avoid division by zero while displaying */ if( j == 0 ) j = 1; } if( j > biggest_col_length ) biggest_col_length = j; }
/* check if there are cards remaining in the game. */ /* if there aren't any, that means you won :) */ if( biggest_col_length == 0 && rem == NOT_A_CARD ) { rb->lcd_update(); rb->splash( HZ, "You Won :)" ); return bouncing_cards(); }
/* draw the columns */ for( i = 0; i < COL_NUM; i++ ) { c = cols[i]; j = CARD_START; while( true ) { if( c == NOT_A_CARD ) { /* draw the cursor on empty columns */ if( cur_col == i ) { draw_cursor( MARGIN + i * (CARD_WIDTH +(LCD_WIDTH-COL_NUM*CARD_WIDTH-2*MARGIN)/(COL_NUM-1)), j ); } break; }
draw_card( &deck[c], MARGIN + i * (CARD_WIDTH +(LCD_WIDTH-COL_NUM*CARD_WIDTH-2*MARGIN)/(COL_NUM-1)), j, c == sel_card, c == cur_card );
h = c; c = deck[c].next; if( c == NOT_A_CARD ) break;
/* This is where we change the spacing between cards so that * they don't overflow out of the LCD */ if( h == cur_card ) j += SYMBOL_HEIGHT; else if( deck[h].known ) j += min( SYMBOL_HEIGHT, 2 * (LCD_HEIGHT - CARD_START - CARD_HEIGHT - MARGIN) / biggest_col_length ); else j += min( SYMBOL_HEIGHT / 2, (LCD_HEIGHT - CARD_START - CARD_HEIGHT - MARGIN) / biggest_col_length ); } }
/* draw the stacks */ for( i=0; i<SUITS; i++ ) { c = find_last_card( STACKS_COL + i );
if( c != NOT_A_CARD ) { draw_card( &deck[c], LCD_WIDTH-(CARD_WIDTH*4+4+MARGIN)+CARD_WIDTH*i+i+1, MARGIN, c == sel_card, cur_col == STACKS_COL + i ); } else { draw_empty_stack( i, LCD_WIDTH-(CARD_WIDTH*4+4+MARGIN)+CARD_WIDTH*i+i+1, MARGIN, cur_col == STACKS_COL + i ); } }
/* draw the remains */ if( rem != NOT_A_CARD && ( cur_rem == NOT_A_CARD || deck[cur_rem].next != NOT_A_CARD ) ) { /* gruik ! (we want to display a card back) */ deck[rem].known = false; draw_card( &deck[rem], MARGIN, MARGIN, false, false ); deck[rem].known = true; }
if( rem != NOT_A_CARD && cur_rem != NOT_A_CARD ) { if( count_rem < 0 ) { prevcard = rem; count_rem = 0; while( prevcard != cur_rem && count_rem < cards_per_draw-1 ) { prevcard = deck[prevcard].next; count_rem++; } } prevcard = cur_rem; j = CARD_WIDTH+2*MARGIN+1; for( i = 0; i < count_rem; i++ ) prevcard = find_prev_card(prevcard); for( i = 0; i <= count_rem; i++ ) { draw_card( &deck[prevcard], j, MARGIN, sel_card == prevcard, cur_card == prevcard ); prevcard = deck[prevcard].next; j += CARD_WIDTH/2; } } if( ( cur_rem == NOT_A_CARD || rem == NOT_A_CARD ) && cur_col == REM_COL ) { draw_cursor( CARD_WIDTH+2*MARGIN+1, MARGIN ); }
rb->lcd_update();
/* what to do when a key is pressed ... */ button = rb->button_get( true );#if (CONFIG_KEYPAD == SANSA_E200_PAD) || (CONFIG_KEYPAD == SANSA_FUZE_PAD) if (button&(BUTTON_SCROLL_BACK|BUTTON_SCROLL_FWD)) button = button & (~BUTTON_REPEAT);#endif switch( button ) { /* move cursor to the last card of the previous column * or to the previous final stack * or to the remains stack */ case SOL_RIGHT:#ifdef SOL_RIGHT_PRE if( lastbutton != SOL_RIGHT_PRE ) break;#endif if( cur_col >= COL_NUM ) { cur_col = 0; } else if( cur_col == COL_NUM - 1 ) { cur_col = REM_COL; } else { cur_col = (cur_col+1)%(REM_COL+1); } if(cur_col == REM_COL) { cur_card = cur_rem; break; } cur_card = find_last_card( cur_col ); break;
/* move cursor to the last card of the next column * or to the next final stack * or to the remains stack */ case SOL_LEFT:#ifdef SOL_LEFT_PRE if( lastbutton != SOL_LEFT_PRE ) break;#endif if( cur_col == 0 ) { cur_col = REM_COL; } else if( cur_col >= COL_NUM ) { cur_col = COL_NUM - 1; } else { cur_col = (cur_col + REM_COL)%(REM_COL+1); } if( cur_col == REM_COL ) { cur_card = cur_rem; break; } cur_card = find_last_card( cur_col ); break;
/* move cursor to card that's bellow */ case SOL_DOWN:#ifdef SOL_DOWN_PRE if( lastbutton != SOL_DOWN_PRE ) break;#else case SOL_DOWN|BUTTON_REPEAT:#endif if( cur_col >= COL_NUM ) { cur_col = (cur_col - COL_NUM + 1)%(SUITS + 1) + COL_NUM; if( cur_col == REM_COL ) { cur_card = cur_rem; } else { cur_card = find_last_card( cur_col ); } break; } if( cur_card == NOT_A_CARD ) break; if( deck[cur_card].next != NOT_A_CARD ) { cur_card = deck[cur_card].next; } else { cur_card = cols[cur_col]; while( !deck[ cur_card].known && deck[cur_card].next != NOT_A_CARD ) { cur_card = deck[cur_card].next; } } break;
/* move cursor to card that's above */ case SOL_UP:#ifdef SOL_UP_PRE if( lastbutton != SOL_UP_PRE ) break;#else case SOL_UP|BUTTON_REPEAT:#endif if( cur_col >= COL_NUM ) { cur_col = (cur_col - COL_NUM + SUITS)%(SUITS + 1) + COL_NUM; if( cur_col == REM_COL ) { cur_card = cur_rem; } else { cur_card = find_last_card( cur_col ); } break; } if( cur_card == NOT_A_CARD ) break; do { cur_card = find_prev_card( cur_card ); if( cur_card == NOT_A_CARD ) { cur_card = find_last_card( cur_col ); } } while( deck[cur_card].next != NOT_A_CARD && !deck[cur_card].known ); break;
/* Try to put card under cursor on one of the stacks */ case SOL_CUR2STACK:#ifdef SOL_CUR2STACK_PRE if( lastbutton != SOL_CUR2STACK_PRE ) break;#endif move_card( deck[cur_card].suit + STACKS_COL, cur_card ); break;
/* Move cards arround, Uncover cards, ... */ case SOL_MOVE:#ifdef SOL_MOVE_PRE if( lastbutton != SOL_MOVE_PRE ) break;#endif
if( sel_card == NOT_A_CARD ) { if( cur_card != NOT_A_CARD ) { if( deck[cur_card].next == NOT_A_CARD && !deck[cur_card].known ) { /* reveal a hidden card */ deck[cur_card].known = true; } else if( cur_col == REM_COL && cur_rem == NOT_A_CARD ) { break; } else { /* select a card */ sel_card = cur_card; } } } else if( sel_card == cur_card ) { /* unselect card or try putting card on * one of the 4 stacks */ if( move_card( deck[sel_card].suit + COL_NUM, sel_card ) == MOVE_OK && cur_col == REM_COL ) { cur_card = cur_rem; } sel_card = NOT_A_CARD; } else { /* try moving cards */ /* The flexible move must not be used from the remains stack. */ if (find_card_col(sel_card) == REM_COL) { if (move_card( cur_col, sel_card ) == MOVE_NOT_OK) sel_card = NOT_A_CARD; } else { do { if (move_card( cur_col, sel_card) == MOVE_OK) break; sel_card = find_prev_card(sel_card); } while (sel_card != NOT_A_CARD); } } break;
/* If the card on the top of the remains can be put where * the cursor is, go ahead */ case SOL_REM2CUR:#ifdef SOL_REM2CUR_PRE if( lastbutton != SOL_REM2CUR_PRE ) break;#endif move_card( cur_col, cur_rem ); break;
/* If the card on top of the remains can be put on one * of the stacks, do so */ case SOL_REM2STACK:#ifdef SOL_REM2STACK_PRE if( lastbutton != SOL_REM2STACK_PRE ) break;#endif move_card( deck[cur_rem].suit + COL_NUM, cur_rem ); break;
#ifdef SOL_REM case SOL_REM: if( sel_card != NOT_A_CARD ) { /* unselect selected card */ sel_card = NOT_A_CARD; break; } if( rem != NOT_A_CARD && cur_rem != NOT_A_CARD ) { sel_card = cur_rem; break; } break;#endif
/* unselect selected card or ... * draw new cards from the remains of the deck */ case SOL_DRAW:#ifdef SOL_DRAW_PRE if( lastbutton != SOL_DRAW_PRE ) break;#endif if( sel_card != NOT_A_CARD ) { /* unselect selected card */ sel_card = NOT_A_CARD; break; } if( rem != NOT_A_CARD ) { int cur_rem_old = cur_rem; count_rem = -1; /* draw new cards form the remains of the deck */ if( cur_rem == NOT_A_CARD ) { /*if the cursor card is null*/ cur_rem = rem; i = cards_per_draw - 1; count_rem++; } else { i = cards_per_draw; }
while( i > 0 && deck[cur_rem].next != NOT_A_CARD ) { cur_rem = deck[cur_rem].next; i--; count_rem++; } /* test if any cards are really left on * the remains' stack */ if( i == cards_per_draw ) { cur_rem = NOT_A_CARD; count_rem = -1; } /* if cursor was on remains' stack when new cards were * drawn, put cursor on top of remains' stack */ if( cur_col == REM_COL && cur_card == cur_rem_old ) { cur_card = cur_rem; sel_card = NOT_A_CARD; } } break;
/* Show the menu */#ifdef SOL_RC_QUIT case SOL_RC_QUIT:#endif case SOL_QUIT: switch( solitaire_menu(true) ) { case MENU_SAVE_AND_QUIT: return SOLITAIRE_SAVE_AND_QUIT;
case MENU_QUIT: return SOLITAIRE_QUIT;
case MENU_USB: return SOLITAIRE_USB; } break;
case SYS_POWEROFF: case SYS_REBOOT: return SOLITAIRE_SAVE_AND_QUIT;
default: if( rb->default_event_handler( button ) == SYS_USB_CONNECTED ) return SOLITAIRE_USB; break; }
#ifdef NEED_LASTBUTTON_VAR if( button != BUTTON_NONE ) lastbutton = button;#endif
/* fix incoherences concerning cur_col and cur_card */ c = find_card_col( cur_card ); if( c != NOT_A_COL && c != cur_col ) cur_card = find_last_card( cur_col );
if( cur_card == NOT_A_CARD && find_last_card( cur_col ) != NOT_A_CARD ) cur_card = find_last_card( cur_col );
rb->yield(); }}
/** * Plugin entry point */
enum plugin_status plugin_start(const void* parameter ){ int result;
/* plugin init */ (void)parameter;
configfile_load(CONFIG_FILENAME, config, sizeof(config) / sizeof(config[0]), CFGFILE_VERSION); rb->memcpy(&sol, &sol_disk, sizeof(sol)); /* copy to running config */
if( load_game() == 0 ) { rb->splash( HZ, "Resuming saved game." ); result = SOLITAIRE_QUIT; } else result = SOLITAIRE_WIN;
/* play the game :) * Keep playing if a game was won (that means display the menu after * winning instead of quiting) */ while( ( result = solitaire( result ) ) == SOLITAIRE_WIN );
if( result != SOLITAIRE_QUIT ) /* result == SOLITAIRE_USB || result == SOLITAIRE_SAVE_AND_QUIT */ save_game();
if (rb->memcmp(&sol, &sol_disk, sizeof(sol))) /* save settings if changed */ { rb->memcpy(&sol_disk, &sol, sizeof(sol)); configfile_save(CONFIG_FILENAME, config, sizeof(config) / sizeof(config[0]), CFGFILE_VERSION); }
/* Exit the plugin */ return ( result == SOLITAIRE_USB ) ? PLUGIN_USB_CONNECTED : PLUGIN_OK;}