retroarch.c 241 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334
  1. /* RetroArch - A frontend for libretro.
  2. * Copyright (C) 2010-2014 - Hans-Kristian Arntzen
  3. * Copyright (C) 2011-2021 - Daniel De Matteis
  4. * Copyright (C) 2012-2015 - Michael Lelli
  5. * Copyright (C) 2014-2017 - Jean-Andr� Santoni
  6. * Copyright (C) 2016-2019 - Brad Parker
  7. *
  8. * RetroArch is free software: you can redistribute it and/or modify it under the terms
  9. * of the GNU General Public License as published by the Free Software Found-
  10. * ation, either version 3 of the License, or (at your option) any later version.
  11. *
  12. * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
  13. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  14. * PURPOSE. See the GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License along with RetroArch.
  17. * If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. #ifdef _WIN32
  20. #ifdef _XBOX
  21. #include <xtl.h>
  22. #else
  23. #define WIN32_LEAN_AND_MEAN
  24. #include <windows.h>
  25. #endif
  26. #if defined(DEBUG) && defined(HAVE_DRMINGW)
  27. #include "exchndl.h"
  28. #endif
  29. #endif
  30. #if defined(DINGUX)
  31. #include <sys/types.h>
  32. #include <unistd.h>
  33. #endif
  34. #if (defined(__linux__) || defined(__unix__) || defined(DINGUX)) && !defined(EMSCRIPTEN)
  35. #include <signal.h>
  36. #endif
  37. #if defined(_WIN32_WINNT) && _WIN32_WINNT < 0x0500 || defined(_XBOX)
  38. #ifndef LEGACY_WIN32
  39. #define LEGACY_WIN32
  40. #endif
  41. #endif
  42. #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
  43. #include <objbase.h>
  44. #include <process.h>
  45. #endif
  46. #include <stdio.h>
  47. #include <stdlib.h>
  48. #include <stdarg.h>
  49. #include <stdint.h>
  50. #include <string.h>
  51. #include <ctype.h>
  52. #include <math.h>
  53. #include <locale.h>
  54. #include <boolean.h>
  55. #include <clamping.h>
  56. #include <string/stdstring.h>
  57. #include <dynamic/dylib.h>
  58. #include <file/config_file.h>
  59. #include <lists/string_list.h>
  60. #include <memalign.h>
  61. #include <retro_math.h>
  62. #include <retro_timers.h>
  63. #include <encodings/utf.h>
  64. #include <time/rtime.h>
  65. #include <libretro.h>
  66. #define VFS_FRONTEND
  67. #include <vfs/vfs_implementation.h>
  68. #include <features/features_cpu.h>
  69. #include <compat/strl.h>
  70. #include <compat/strcasestr.h>
  71. #include <compat/getopt.h>
  72. #include <compat/posix_string.h>
  73. #include <file/file_path.h>
  74. #include <retro_miscellaneous.h>
  75. #include <lists/dir_list.h>
  76. #ifdef EMSCRIPTEN
  77. #include <emscripten/emscripten.h>
  78. #endif
  79. #ifdef HAVE_LIBNX
  80. #include <switch.h>
  81. #endif
  82. #if defined(HAVE_LAKKA) || defined(HAVE_LIBNX)
  83. #include "switch_performance_profiles.h"
  84. #endif
  85. #if defined(ANDROID)
  86. #include "play_feature_delivery/play_feature_delivery.h"
  87. #endif
  88. #ifdef HAVE_PRESENCE
  89. #include "network/presence.h"
  90. #endif
  91. #ifdef HAVE_DISCORD
  92. #include "network/discord.h"
  93. #endif
  94. #ifdef HAVE_MIST
  95. #include "steam/steam.h"
  96. #endif
  97. #include "config.def.h"
  98. #ifdef HAVE_MENU
  99. #include "menu/menu_driver.h"
  100. #endif
  101. #include "runloop.h"
  102. #include "camera/camera_driver.h"
  103. #include "location_driver.h"
  104. #include "record/record_driver.h"
  105. #ifdef HAVE_CONFIG_H
  106. #include "config.h"
  107. #endif
  108. #ifdef HAVE_NETWORKING
  109. #include <net/net_compat.h>
  110. #include <net/net_socket.h>
  111. #endif
  112. #include <audio/audio_resampler.h>
  113. #include "audio/audio_driver.h"
  114. #ifdef HAVE_GFX_WIDGETS
  115. #include "gfx/gfx_widgets.h"
  116. #endif
  117. #include "input/input_remapping.h"
  118. #ifdef HAVE_CHEEVOS
  119. #include "cheevos/cheevos.h"
  120. #include "cheevos/cheevos_menu.h"
  121. #endif
  122. #ifdef HAVE_TRANSLATE
  123. #include <encodings/base64.h>
  124. #include <formats/rbmp.h>
  125. #include <formats/rpng.h>
  126. #include <formats/rjson.h>
  127. #include "translation_defines.h"
  128. #endif
  129. #ifdef HAVE_NETWORKING
  130. #include "network/netplay/netplay.h"
  131. #include "network/netplay/netplay_private.h"
  132. #ifdef HAVE_WIFI
  133. #include "network/wifi_driver.h"
  134. #endif
  135. #endif
  136. #ifdef HAVE_THREADS
  137. #include <rthreads/rthreads.h>
  138. #endif
  139. #include "autosave.h"
  140. #include "config.features.h"
  141. #include "content.h"
  142. #include "core_info.h"
  143. #include "dynamic.h"
  144. #include "defaults.h"
  145. #include "driver.h"
  146. #include "msg_hash.h"
  147. #include "paths.h"
  148. #include "file_path_special.h"
  149. #include "ui/ui_companion_driver.h"
  150. #include "verbosity.h"
  151. #include "gfx/video_driver.h"
  152. #include "gfx/video_display_server.h"
  153. #ifdef HAVE_BLUETOOTH
  154. #include "bluetooth/bluetooth_driver.h"
  155. #endif
  156. #include "misc/cpufreq/cpufreq.h"
  157. #include "led/led_driver.h"
  158. #include "midi_driver.h"
  159. #include "core.h"
  160. #include "configuration.h"
  161. #include "list_special.h"
  162. #ifdef HAVE_CHEATS
  163. #include "cheat_manager.h"
  164. #endif
  165. #include "tasks/task_content.h"
  166. #include "tasks/tasks_internal.h"
  167. #include "version.h"
  168. #include "version_git.h"
  169. #include "retroarch.h"
  170. #include "accessibility.h"
  171. #if defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL_DINGUX)
  172. #include "SDL.h"
  173. #endif
  174. #ifdef HAVE_LAKKA
  175. #include "lakka.h"
  176. #endif
  177. #define _PSUPP(var, name, desc) printf(" %s:\n\t\t%s: %s\n", name, desc, var ? "yes" : "no")
  178. #define FAIL_CPU(simd_type) do { \
  179. RARCH_ERR(simd_type " code is compiled in, but CPU does not support this feature. Cannot continue.\n"); \
  180. retroarch_fail(1, "validate_cpu_features()"); \
  181. } while (0)
  182. #define FFMPEG_RECORD_ARG "r:"
  183. #ifdef HAVE_DYNAMIC
  184. #define DYNAMIC_ARG "L:"
  185. #else
  186. #define DYNAMIC_ARG
  187. #endif
  188. #ifdef HAVE_NETWORKING
  189. #define NETPLAY_ARG "HC:F:"
  190. #else
  191. #define NETPLAY_ARG
  192. #endif
  193. #ifdef HAVE_CONFIGFILE
  194. #define CONFIG_FILE_ARG "c:"
  195. #else
  196. #define CONFIG_FILE_ARG
  197. #endif
  198. #ifdef HAVE_BSV_MOVIE
  199. #define BSV_MOVIE_ARG "P:R:M:"
  200. #else
  201. #define BSV_MOVIE_ARG
  202. #endif
  203. #define _PSUPP_BUF(buf, var, name, desc) \
  204. strlcat(buf, " ", sizeof(buf)); \
  205. snprintf(buf + strlen(buf), sizeof(buf), "%-15s", name); \
  206. strlcat(buf, " - ", sizeof(buf)); \
  207. strlcat(buf, desc, sizeof(buf)); \
  208. strlcat(buf, ": ", sizeof(buf)); \
  209. strlcat(buf, var ? "yes\n" : "no\n", sizeof(buf))
  210. /* Griffin hack */
  211. #ifdef HAVE_QT
  212. #ifndef HAVE_MAIN
  213. #define HAVE_MAIN
  214. #endif
  215. #endif
  216. /* Descriptive names for options without short variant.
  217. *
  218. * Please keep the name in sync with the option name.
  219. * Order does not matter. */
  220. enum
  221. {
  222. RA_OPT_MENU = 256, /* must be outside the range of a char */
  223. RA_OPT_CHECK_FRAMES,
  224. RA_OPT_PORT,
  225. RA_OPT_SPECTATE,
  226. RA_OPT_NICK,
  227. RA_OPT_COMMAND,
  228. RA_OPT_APPENDCONFIG,
  229. RA_OPT_BPS,
  230. RA_OPT_IPS,
  231. RA_OPT_NO_PATCH,
  232. RA_OPT_RECORDCONFIG,
  233. RA_OPT_SUBSYSTEM,
  234. RA_OPT_SIZE,
  235. RA_OPT_FEATURES,
  236. RA_OPT_VERSION,
  237. RA_OPT_EOF_EXIT,
  238. RA_OPT_LOG_FILE,
  239. RA_OPT_MAX_FRAMES,
  240. RA_OPT_MAX_FRAMES_SCREENSHOT,
  241. RA_OPT_MAX_FRAMES_SCREENSHOT_PATH,
  242. RA_OPT_SET_SHADER,
  243. RA_OPT_DATABASE_SCAN,
  244. RA_OPT_ACCESSIBILITY,
  245. RA_OPT_LOAD_MENU_ON_ERROR
  246. };
  247. /* DRIVERS */
  248. #ifdef HAVE_BLUETOOTH
  249. extern const bluetooth_driver_t *bluetooth_drivers[];
  250. #endif
  251. /* MAIN GLOBAL VARIABLES */
  252. struct rarch_state
  253. {
  254. char *connect_host; /* Netplay hostname passed from CLI */
  255. struct retro_perf_counter *perf_counters_rarch[MAX_COUNTERS];
  256. #ifdef HAVE_THREAD_STORAGE
  257. sthread_tls_t rarch_tls; /* unsigned alignment */
  258. #endif
  259. unsigned perf_ptr_rarch;
  260. uint16_t flags;
  261. char launch_arguments[4096];
  262. char path_default_shader_preset[PATH_MAX_LENGTH];
  263. char path_content[PATH_MAX_LENGTH];
  264. char path_libretro[PATH_MAX_LENGTH];
  265. char path_config_file[PATH_MAX_LENGTH];
  266. char path_config_append_file[PATH_MAX_LENGTH];
  267. char path_config_override_file[PATH_MAX_LENGTH];
  268. char path_core_options_file[PATH_MAX_LENGTH];
  269. char dir_system[PATH_MAX_LENGTH];
  270. char dir_savefile[PATH_MAX_LENGTH];
  271. char dir_savestate[PATH_MAX_LENGTH];
  272. };
  273. /* Forward declarations */
  274. #ifdef HAVE_LIBNX
  275. void libnx_apply_overclock(void);
  276. #endif
  277. static struct rarch_state rarch_st = {0};
  278. #ifdef HAVE_THREAD_STORAGE
  279. static const void *MAGIC_POINTER = (void*)(uintptr_t)0x0DEFACED;
  280. #endif
  281. static access_state_t access_state_st = {0};
  282. static struct global global_driver_st = {}; /* retro_time_t alignment */
  283. static void retro_frame_null(const void *data, unsigned width,
  284. unsigned height, size_t pitch) { }
  285. void retro_input_poll_null(void) { }
  286. /**
  287. * find_driver_nonempty:
  288. * @label : string of driver type to be found.
  289. * @i : index of driver.
  290. * @str : identifier name of the found driver
  291. * gets written to this string.
  292. * @len : size of @str.
  293. *
  294. * Find driver based on @label.
  295. *
  296. * Returns: NULL if no driver based on @label found, otherwise
  297. * pointer to driver.
  298. **/
  299. static const void *find_driver_nonempty(
  300. const char *label, int i,
  301. char *s, size_t len)
  302. {
  303. if (string_is_equal(label, "camera_driver"))
  304. {
  305. if (camera_drivers[i])
  306. {
  307. const char *ident = camera_drivers[i]->ident;
  308. strlcpy(s, ident, len);
  309. return camera_drivers[i];
  310. }
  311. }
  312. else if (string_is_equal(label, "location_driver"))
  313. {
  314. if (location_drivers[i])
  315. {
  316. const char *ident = location_drivers[i]->ident;
  317. strlcpy(s, ident, len);
  318. return location_drivers[i];
  319. }
  320. }
  321. #ifdef HAVE_MENU
  322. else if (string_is_equal(label, "menu_driver"))
  323. {
  324. if (menu_ctx_drivers[i])
  325. {
  326. const char *ident = menu_ctx_drivers[i]->ident;
  327. strlcpy(s, ident, len);
  328. return menu_ctx_drivers[i];
  329. }
  330. }
  331. #endif
  332. else if (string_is_equal(label, "input_driver"))
  333. {
  334. if (input_drivers[i])
  335. {
  336. const char *ident = input_drivers[i]->ident;
  337. strlcpy(s, ident, len);
  338. return input_drivers[i];
  339. }
  340. }
  341. else if (string_is_equal(label, "input_joypad_driver"))
  342. {
  343. if (joypad_drivers[i])
  344. {
  345. const char *ident = joypad_drivers[i]->ident;
  346. strlcpy(s, ident, len);
  347. return joypad_drivers[i];
  348. }
  349. }
  350. else if (string_is_equal(label, "video_driver"))
  351. {
  352. if (video_drivers[i])
  353. {
  354. const char *ident = video_drivers[i]->ident;
  355. strlcpy(s, ident, len);
  356. return video_drivers[i];
  357. }
  358. }
  359. else if (string_is_equal(label, "audio_driver"))
  360. {
  361. if (audio_drivers[i])
  362. {
  363. const char *ident = audio_drivers[i]->ident;
  364. strlcpy(s, ident, len);
  365. return audio_drivers[i];
  366. }
  367. }
  368. else if (string_is_equal(label, "record_driver"))
  369. {
  370. if (record_drivers[i])
  371. {
  372. const char *ident = record_drivers[i]->ident;
  373. strlcpy(s, ident, len);
  374. return record_drivers[i];
  375. }
  376. }
  377. else if (string_is_equal(label, "midi_driver"))
  378. {
  379. if (midi_driver_find_handle(i))
  380. {
  381. const char *ident = midi_drivers[i]->ident;
  382. strlcpy(s, ident, len);
  383. return midi_drivers[i];
  384. }
  385. }
  386. else if (string_is_equal(label, "audio_resampler_driver"))
  387. {
  388. if (audio_resampler_driver_find_handle(i))
  389. {
  390. const char *ident = audio_resampler_driver_find_ident(i);
  391. strlcpy(s, ident, len);
  392. return audio_resampler_driver_find_handle(i);
  393. }
  394. }
  395. #ifdef HAVE_BLUETOOTH
  396. else if (string_is_equal(label, "bluetooth_driver"))
  397. {
  398. if (bluetooth_drivers[i])
  399. {
  400. const char *ident = bluetooth_drivers[i]->ident;
  401. strlcpy(s, ident, len);
  402. return bluetooth_drivers[i];
  403. }
  404. }
  405. #endif
  406. #ifdef HAVE_WIFI
  407. else if (string_is_equal(label, "wifi_driver"))
  408. {
  409. if (wifi_drivers[i])
  410. {
  411. const char *ident = wifi_drivers[i]->ident;
  412. strlcpy(s, ident, len);
  413. return wifi_drivers[i];
  414. }
  415. }
  416. #endif
  417. return NULL;
  418. }
  419. int driver_find_index(const char *label, const char *drv)
  420. {
  421. unsigned i;
  422. char str[NAME_MAX_LENGTH];
  423. str[0] = '\0';
  424. for (i = 0;
  425. find_driver_nonempty(label, i, str, sizeof(str)) != NULL; i++)
  426. {
  427. if (string_is_empty(str))
  428. break;
  429. if (string_is_equal_noncase(drv, str))
  430. return i;
  431. }
  432. return -1;
  433. }
  434. /**
  435. * driver_find_last:
  436. * @label : string of driver type to be found.
  437. * @s : identifier of driver to be found.
  438. * @len : size of @s.
  439. *
  440. * Find last driver in driver array.
  441. **/
  442. static void driver_find_last(const char *label, char *s, size_t len)
  443. {
  444. unsigned i;
  445. for (i = 0;
  446. find_driver_nonempty(label, i, s, len) != NULL; i++) { }
  447. if (i)
  448. i = i - 1;
  449. else
  450. i = 0;
  451. find_driver_nonempty(label, i, s, len);
  452. }
  453. /**
  454. * driver_find_prev:
  455. * @label : string of driver type to be found.
  456. * @s : identifier of driver to be found.
  457. * @len : size of @s.
  458. *
  459. * Find previous driver in driver array.
  460. **/
  461. static bool driver_find_prev(const char *label, char *s, size_t len)
  462. {
  463. int i = driver_find_index(label, s);
  464. if (i > 0)
  465. {
  466. find_driver_nonempty(label, i - 1, s, len);
  467. return true;
  468. }
  469. RARCH_WARN(
  470. "Couldn't find any previous driver (current one: \"%s\").\n", s);
  471. return false;
  472. }
  473. /**
  474. * driver_find_next:
  475. * @label : string of driver type to be found.
  476. * @s : identifier of driver to be found.
  477. * @len : size of @s.
  478. *
  479. * Find next driver in driver array.
  480. **/
  481. static bool driver_find_next(const char *label, char *s, size_t len)
  482. {
  483. int i = driver_find_index(label, s);
  484. if (i >= 0 && string_is_not_equal(s, "null"))
  485. {
  486. find_driver_nonempty(label, i + 1, s, len);
  487. return true;
  488. }
  489. RARCH_WARN("%s (current one: \"%s\").\n",
  490. msg_hash_to_str(MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER),
  491. s);
  492. return false;
  493. }
  494. static void driver_adjust_system_rates(
  495. bool vrr_runloop_enable,
  496. float video_refresh_rate,
  497. float audio_max_timing_skew,
  498. bool video_adaptive_vsync,
  499. unsigned video_swap_interval)
  500. {
  501. runloop_state_t *runloop_st = runloop_state_get_ptr();
  502. video_driver_state_t *video_st = video_state_get_ptr();
  503. struct retro_system_av_info *av_info = &video_st->av_info;
  504. const struct retro_system_timing *info =
  505. (const struct retro_system_timing*)&av_info->timing;
  506. double input_sample_rate = info->sample_rate;
  507. double input_fps = info->fps;
  508. /* Update video swap interval if automatic
  509. * switching is enabled */
  510. runloop_set_video_swap_interval(
  511. vrr_runloop_enable,
  512. video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE,
  513. video_swap_interval,
  514. audio_max_timing_skew,
  515. video_refresh_rate,
  516. input_fps);
  517. video_swap_interval = runloop_get_video_swap_interval(
  518. video_swap_interval);
  519. if (input_sample_rate > 0.0)
  520. {
  521. audio_driver_state_t *audio_st = audio_state_get_ptr();
  522. if (vrr_runloop_enable)
  523. audio_st->input = input_sample_rate;
  524. else
  525. audio_st->input =
  526. audio_driver_monitor_adjust_system_rates(
  527. input_sample_rate,
  528. input_fps,
  529. video_refresh_rate,
  530. video_swap_interval,
  531. audio_max_timing_skew);
  532. RARCH_LOG("[Audio]: Set audio input rate to: %.2f Hz.\n",
  533. audio_st->input);
  534. }
  535. runloop_st->flags &= ~RUNLOOP_FLAG_FORCE_NONBLOCK;
  536. if (input_fps > 0.0)
  537. {
  538. float timing_skew_hz = video_refresh_rate;
  539. if (video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE)
  540. timing_skew_hz = input_fps;
  541. video_st->core_hz = input_fps;
  542. if (!video_driver_monitor_adjust_system_rates(
  543. timing_skew_hz,
  544. video_refresh_rate,
  545. vrr_runloop_enable,
  546. audio_max_timing_skew,
  547. video_swap_interval,
  548. input_fps))
  549. {
  550. /* We won't be able to do VSync reliably
  551. when game FPS > monitor FPS. */
  552. runloop_st->flags |= RUNLOOP_FLAG_FORCE_NONBLOCK;
  553. RARCH_LOG("[Video]: Game FPS > Monitor FPS. Cannot rely on VSync.\n");
  554. if (VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
  555. {
  556. if (video_st->current_video->set_nonblock_state)
  557. video_st->current_video->set_nonblock_state(
  558. video_st->data, true,
  559. video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC)
  560. && video_adaptive_vsync,
  561. video_swap_interval);
  562. }
  563. return;
  564. }
  565. }
  566. if (VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
  567. driver_set_nonblock_state();
  568. }
  569. /**
  570. * driver_set_nonblock_state:
  571. *
  572. * Sets audio and video drivers to nonblock state (if enabled).
  573. *
  574. * If nonblock state is false, sets
  575. * blocking state for both audio and video drivers instead.
  576. **/
  577. void driver_set_nonblock_state(void)
  578. {
  579. runloop_state_t *runloop_st = runloop_state_get_ptr();
  580. input_driver_state_t
  581. *input_st = input_state_get_ptr();
  582. audio_driver_state_t
  583. *audio_st = audio_state_get_ptr();
  584. video_driver_state_t
  585. *video_st = video_state_get_ptr();
  586. bool enable = input_st ?
  587. (input_st->flags & INP_FLAG_NONBLOCKING) : false;
  588. settings_t *settings = config_get_ptr();
  589. bool audio_sync = settings->bools.audio_sync;
  590. bool video_vsync = settings->bools.video_vsync;
  591. bool adaptive_vsync = settings->bools.video_adaptive_vsync;
  592. unsigned swap_interval = runloop_get_video_swap_interval(
  593. settings->uints.video_swap_interval);
  594. bool video_driver_active = video_st->flags & VIDEO_FLAG_ACTIVE;
  595. bool audio_driver_active = audio_st->flags & AUDIO_FLAG_ACTIVE;
  596. bool runloop_force_nonblock = runloop_st->flags & RUNLOOP_FLAG_FORCE_NONBLOCK;
  597. /* Only apply non-block-state for video if we're using vsync. */
  598. if (video_driver_active && VIDEO_DRIVER_GET_PTR_INTERNAL(video_st))
  599. {
  600. if (video_st->current_video->set_nonblock_state)
  601. {
  602. bool video_nonblock = enable;
  603. if (!video_vsync || runloop_force_nonblock)
  604. video_nonblock = true;
  605. video_st->current_video->set_nonblock_state(video_st->data,
  606. video_nonblock,
  607. video_driver_test_all_flags(GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
  608. adaptive_vsync, swap_interval);
  609. }
  610. }
  611. if (audio_driver_active && audio_st->context_audio_data)
  612. audio_st->current_audio->set_nonblock_state(
  613. audio_st->context_audio_data,
  614. audio_sync ? enable : true);
  615. audio_st->chunk_size = enable
  616. ? audio_st->chunk_nonblock_size
  617. : audio_st->chunk_block_size;
  618. }
  619. #ifndef HAVE_MENU
  620. /* This function gets called at first startup on Android/iOS
  621. * when we need to extract the APK contents/zip file. This
  622. * file contains assets which then get extracted to the
  623. * user's asset directories. */
  624. static void bundle_decompressed(retro_task_t *task,
  625. void *task_data,
  626. void *user_data, const char *err)
  627. {
  628. settings_t *settings = config_get_ptr();
  629. decompress_task_data_t *dec = (decompress_task_data_t*)task_data;
  630. if (err)
  631. RARCH_ERR("%s", err);
  632. if (dec)
  633. {
  634. if (!err)
  635. command_event(CMD_EVENT_REINIT, NULL);
  636. /* delete bundle? */
  637. free(dec->source_file);
  638. free(dec);
  639. }
  640. configuration_set_uint(settings,
  641. settings->uints.bundle_assets_extract_last_version,
  642. settings->uints.bundle_assets_extract_version_current);
  643. configuration_set_bool(settings, settings->bools.bundle_finished, true);
  644. command_event(CMD_EVENT_MENU_SAVE_CURRENT_CONFIG, NULL);
  645. }
  646. #endif
  647. void drivers_init(
  648. settings_t *settings,
  649. int flags,
  650. bool verbosity_enabled)
  651. {
  652. runloop_state_t *runloop_st = runloop_state_get_ptr();
  653. audio_driver_state_t *audio_st = audio_state_get_ptr();
  654. input_driver_state_t *input_st = input_state_get_ptr();
  655. video_driver_state_t *video_st = video_state_get_ptr();
  656. #ifdef HAVE_MENU
  657. struct menu_state *menu_st = menu_state_get_ptr();
  658. #endif
  659. camera_driver_state_t
  660. *camera_st = camera_state_get_ptr();
  661. location_driver_state_t
  662. *location_st = location_state_get_ptr();
  663. bool video_is_threaded = VIDEO_DRIVER_IS_THREADED_INTERNAL(video_st);
  664. gfx_display_t *p_disp = disp_get_ptr();
  665. #if defined(HAVE_GFX_WIDGETS)
  666. bool video_font_enable = settings->bools.video_font_enable;
  667. bool menu_enable_widgets = settings->bools.menu_enable_widgets;
  668. dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr();
  669. /* By default, we want display widgets to persist through driver reinits. */
  670. p_dispwidget->flags |= DISPGFX_WIDGET_FLAG_PERSISTING;
  671. #endif
  672. #ifdef HAVE_MENU
  673. /* By default, we want the menu to persist through driver reinits. */
  674. if (menu_st)
  675. menu_st->flags |= MENU_ST_FLAG_DATA_OWN;
  676. #endif
  677. if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
  678. driver_adjust_system_rates(
  679. settings->bools.vrr_runloop_enable,
  680. settings->floats.video_refresh_rate,
  681. settings->floats.audio_max_timing_skew,
  682. settings->bools.video_adaptive_vsync,
  683. settings->uints.video_swap_interval
  684. );
  685. /* Initialize video driver */
  686. if (flags & DRIVER_VIDEO_MASK)
  687. {
  688. struct retro_hw_render_callback *hwr =
  689. VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st);
  690. video_st->frame_time_count = 0;
  691. video_driver_lock_new();
  692. #ifdef HAVE_VIDEO_FILTER
  693. video_driver_filter_free();
  694. #endif
  695. video_driver_set_cached_frame_ptr(NULL);
  696. if (!video_driver_init_internal(&video_is_threaded,
  697. verbosity_enabled))
  698. retroarch_fail(1, "video_driver_init_internal()");
  699. if ( !(video_st->flags & VIDEO_FLAG_CACHE_CONTEXT_ACK)
  700. && hwr->context_reset)
  701. hwr->context_reset();
  702. video_st->flags &= ~VIDEO_FLAG_CACHE_CONTEXT_ACK;
  703. runloop_st->frame_time_last = 0;
  704. }
  705. /* Initialize audio driver */
  706. if (flags & DRIVER_AUDIO_MASK)
  707. {
  708. audio_driver_init_internal(
  709. settings,
  710. audio_st->callback.callback != NULL);
  711. if ( audio_st->current_audio
  712. && audio_st->current_audio->device_list_new
  713. && audio_st->context_audio_data)
  714. audio_st->devices_list = (struct string_list*)
  715. audio_st->current_audio->device_list_new(
  716. audio_st->context_audio_data);
  717. }
  718. /* Regular display refresh rate startup autoswitch based on content av_info */
  719. if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
  720. {
  721. struct retro_system_av_info *av_info = &video_st->av_info;
  722. float refresh_rate = av_info->timing.fps;
  723. unsigned autoswitch_refresh_rate = settings->uints.video_autoswitch_refresh_rate;
  724. bool exclusive_fullscreen = settings->bools.video_fullscreen && !settings->bools.video_windowed_fullscreen;
  725. bool windowed_fullscreen = settings->bools.video_fullscreen && settings->bools.video_windowed_fullscreen;
  726. bool all_fullscreen = settings->bools.video_fullscreen || settings->bools.video_windowed_fullscreen;
  727. /* Making a switch from PC standard 60 Hz to NTSC 59.94 is excluded by the last condition. */
  728. if ( refresh_rate > 0.0
  729. && !settings->uints.crt_switch_resolution
  730. && !settings->bools.vrr_runloop_enable
  731. && video_display_server_has_resolution_list()
  732. && (autoswitch_refresh_rate != AUTOSWITCH_REFRESH_RATE_OFF)
  733. && (fabs(settings->floats.video_refresh_rate - refresh_rate) > 1))
  734. {
  735. if (((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_EXCLUSIVE_FULLSCREEN) && exclusive_fullscreen) ||
  736. ((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_WINDOWED_FULLSCREEN) && windowed_fullscreen) ||
  737. ((autoswitch_refresh_rate == AUTOSWITCH_REFRESH_RATE_ALL_FULLSCREEN) && all_fullscreen))
  738. {
  739. bool video_switch_refresh_rate = false;
  740. video_switch_refresh_rate_maybe(&refresh_rate, &video_switch_refresh_rate);
  741. if (video_switch_refresh_rate && video_display_server_set_refresh_rate(refresh_rate))
  742. {
  743. int reinit_flags = DRIVER_AUDIO_MASK;
  744. video_monitor_set_refresh_rate(refresh_rate);
  745. /* Audio must reinit after successful rate switch */
  746. command_event(CMD_EVENT_REINIT, &reinit_flags);
  747. }
  748. }
  749. }
  750. }
  751. if (flags & DRIVER_CAMERA_MASK)
  752. {
  753. /* Only initialize camera driver if we're ever going to use it. */
  754. if (camera_st->active)
  755. {
  756. /* Resource leaks will follow if camera is initialized twice. */
  757. if (!camera_st->data)
  758. {
  759. if (!camera_driver_find_driver("camera driver",
  760. verbosity_enabled))
  761. retroarch_fail(1, "find_camera_driver()");
  762. if (camera_st->driver)
  763. {
  764. camera_st->data = camera_st->driver->init(
  765. *settings->arrays.camera_device ?
  766. settings->arrays.camera_device : NULL,
  767. camera_st->cb.caps,
  768. settings->uints.camera_width ?
  769. settings->uints.camera_width : camera_st->cb.width,
  770. settings->uints.camera_height ?
  771. settings->uints.camera_height : camera_st->cb.height);
  772. if (!camera_st->data)
  773. {
  774. RARCH_ERR("Failed to initialize camera driver. Will continue without camera.\n");
  775. camera_st->active = false;
  776. }
  777. if (camera_st->cb.initialized)
  778. camera_st->cb.initialized();
  779. }
  780. }
  781. }
  782. }
  783. #ifdef HAVE_BLUETOOTH
  784. if (flags & DRIVER_BLUETOOTH_MASK)
  785. bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_INIT, NULL);
  786. #endif
  787. #ifdef HAVE_WIFI
  788. if ((flags & DRIVER_WIFI_MASK))
  789. wifi_driver_ctl(RARCH_WIFI_CTL_INIT, NULL);
  790. #endif
  791. if (flags & DRIVER_LOCATION_MASK)
  792. {
  793. /* Only initialize location driver if we're ever going to use it. */
  794. if (location_st->active)
  795. if (!init_location(&runloop_state_get_ptr()->system,
  796. settings, verbosity_is_enabled()))
  797. location_st->active = false;
  798. }
  799. core_info_init_current_core();
  800. #if defined(HAVE_GFX_WIDGETS)
  801. /* Note that we only enable widgets if 'video_font_enable'
  802. * is true. 'video_font_enable' corresponds to the generic
  803. * 'On-Screen Notifications' setting, which should serve as
  804. * a global notifications on/off toggle switch */
  805. if ( video_font_enable
  806. && menu_enable_widgets
  807. && video_driver_has_widgets())
  808. {
  809. bool rarch_force_fullscreen = video_st->flags &
  810. VIDEO_FLAG_FORCE_FULLSCREEN;
  811. bool video_is_fullscreen = settings->bools.video_fullscreen ||
  812. rarch_force_fullscreen;
  813. p_dispwidget->active= gfx_widgets_init(
  814. p_disp,
  815. anim_get_ptr(),
  816. settings,
  817. (uintptr_t)&p_dispwidget->active,
  818. video_is_threaded,
  819. video_st->width,
  820. video_st->height,
  821. video_is_fullscreen,
  822. settings->paths.directory_assets,
  823. settings->paths.path_font);
  824. }
  825. else
  826. #endif
  827. {
  828. gfx_display_init_first_driver(p_disp, video_is_threaded);
  829. }
  830. #ifdef HAVE_MENU
  831. if (flags & DRIVER_VIDEO_MASK)
  832. {
  833. /* Initialize menu driver */
  834. if (flags & DRIVER_MENU_MASK)
  835. {
  836. if (!menu_driver_init(video_is_threaded))
  837. RARCH_ERR("Unable to init menu driver.\n");
  838. #ifdef HAVE_LIBRETRODB
  839. menu_explore_context_init();
  840. #endif
  841. menu_contentless_cores_context_init();
  842. }
  843. }
  844. /* Initialising the menu driver will also initialise
  845. * core info - if we are not initialising the menu
  846. * driver, must initialise core info 'by hand' */
  847. if (!(flags & DRIVER_VIDEO_MASK) ||
  848. !(flags & DRIVER_MENU_MASK))
  849. {
  850. command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
  851. command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
  852. }
  853. #else
  854. if ( settings->bools.bundle_assets_extract_enable
  855. && !string_is_empty(settings->paths.bundle_assets_src)
  856. && !string_is_empty(settings->paths.bundle_assets_dst)
  857. && (settings->uints.bundle_assets_extract_version_current
  858. != settings->uints.bundle_assets_extract_last_version)
  859. )
  860. {
  861. task_push_decompress(
  862. settings->paths.bundle_assets_src,
  863. settings->paths.bundle_assets_dst,
  864. NULL,
  865. settings->paths.bundle_assets_dst_subdir,
  866. NULL,
  867. bundle_decompressed,
  868. NULL,
  869. NULL,
  870. false);
  871. /* Support only 1 version - setting this would prevent the assets from being extracted every time */
  872. configuration_set_int(settings,
  873. settings->uints.bundle_assets_extract_last_version, 1);
  874. }
  875. /* Qt uses core info, even if the menu is disabled */
  876. command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
  877. command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
  878. #endif
  879. /* Keep non-throttled state as good as possible. */
  880. if (flags & (DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK))
  881. if (input_st && (input_st->flags & INP_FLAG_NONBLOCKING))
  882. driver_set_nonblock_state();
  883. /* Initialize LED driver */
  884. if (flags & DRIVER_LED_MASK)
  885. led_driver_init(settings->arrays.led_driver);
  886. /* Initialize MIDI driver */
  887. if (flags & DRIVER_MIDI_MASK)
  888. midi_driver_init(settings);
  889. #ifndef HAVE_LAKKA_SWITCH
  890. #ifdef HAVE_LAKKA
  891. cpu_scaling_driver_init();
  892. #endif
  893. #endif /* #ifndef HAVE_LAKKA_SWITCH */
  894. }
  895. void driver_uninit(int flags)
  896. {
  897. runloop_state_t *runloop_st = runloop_state_get_ptr();
  898. video_driver_state_t *video_st = video_state_get_ptr();
  899. camera_driver_state_t *camera_st = camera_state_get_ptr();
  900. #if defined(HAVE_GFX_WIDGETS)
  901. dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr();
  902. #endif
  903. core_info_deinit_list();
  904. core_info_free_current_core();
  905. #if defined(HAVE_GFX_WIDGETS)
  906. /* This absolutely has to be done before video_driver_free_internal()
  907. * is called/completes, otherwise certain menu drivers
  908. * (e.g. Vulkan) will segfault */
  909. if (p_dispwidget->flags & DISPGFX_WIDGET_FLAG_INITED)
  910. {
  911. gfx_widgets_deinit(p_dispwidget->flags & DISPGFX_WIDGET_FLAG_PERSISTING);
  912. p_dispwidget->active = false;
  913. }
  914. #endif
  915. #ifdef HAVE_MENU
  916. if (flags & DRIVER_MENU_MASK)
  917. {
  918. #ifdef HAVE_LIBRETRODB
  919. menu_explore_context_deinit();
  920. #endif
  921. menu_contentless_cores_context_deinit();
  922. #ifdef HAVE_CHEEVOS
  923. rcheevos_menu_reset_badges();
  924. #endif
  925. menu_driver_ctl(RARCH_MENU_CTL_DEINIT, NULL);
  926. }
  927. #endif
  928. if ((flags & DRIVER_LOCATION_MASK))
  929. uninit_location(&runloop_st->system);
  930. if ((flags & DRIVER_CAMERA_MASK))
  931. {
  932. if (camera_st->data && camera_st->driver)
  933. {
  934. if (camera_st->cb.deinitialized)
  935. camera_st->cb.deinitialized();
  936. if (camera_st->driver->free)
  937. camera_st->driver->free(camera_st->data);
  938. }
  939. camera_st->data = NULL;
  940. }
  941. #ifdef HAVE_BLUETOOTH
  942. if ((flags & DRIVER_BLUETOOTH_MASK))
  943. bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DEINIT, NULL);
  944. #endif
  945. #ifdef HAVE_WIFI
  946. if ((flags & DRIVER_WIFI_MASK))
  947. wifi_driver_ctl(RARCH_WIFI_CTL_DEINIT, NULL);
  948. #endif
  949. if (flags & DRIVER_LED)
  950. led_driver_free();
  951. if (flags & DRIVERS_VIDEO_INPUT)
  952. {
  953. video_driver_free_internal();
  954. VIDEO_DRIVER_LOCK_FREE(video_st);
  955. video_st->data = NULL;
  956. video_driver_set_cached_frame_ptr(NULL);
  957. }
  958. if (flags & DRIVER_AUDIO_MASK)
  959. audio_driver_deinit();
  960. if ((flags & DRIVER_VIDEO_MASK))
  961. video_st->data = NULL;
  962. if ((flags & DRIVER_INPUT_MASK))
  963. input_state_get_ptr()->current_data = NULL;
  964. if ((flags & DRIVER_AUDIO_MASK))
  965. audio_state_get_ptr()->context_audio_data = NULL;
  966. if (flags & DRIVER_MIDI_MASK)
  967. midi_driver_free();
  968. #ifndef HAVE_LAKKA_SWITCH
  969. #ifdef HAVE_LAKKA
  970. cpu_scaling_driver_free();
  971. #endif
  972. #endif /* #ifndef HAVE_LAKKA_SWITCH */
  973. }
  974. static void retroarch_deinit_drivers(struct retro_callbacks *cbs)
  975. {
  976. input_driver_state_t *input_st = input_state_get_ptr();
  977. video_driver_state_t *video_st = video_state_get_ptr();
  978. camera_driver_state_t *camera_st= camera_state_get_ptr();
  979. location_driver_state_t
  980. *location_st = location_state_get_ptr();
  981. runloop_state_t *runloop_st = runloop_state_get_ptr();
  982. #if defined(HAVE_GFX_WIDGETS)
  983. /* Tear down display widgets no matter what
  984. * in case the handle is lost in the threaded
  985. * video driver in the meantime
  986. * (breaking video_driver_has_widgets) */
  987. dispgfx_widget_t *p_dispwidget = dispwidget_get_ptr();
  988. if (p_dispwidget->flags & DISPGFX_WIDGET_FLAG_INITED)
  989. {
  990. gfx_widgets_deinit(
  991. p_dispwidget->flags & DISPGFX_WIDGET_FLAG_PERSISTING);
  992. p_dispwidget->active = false;
  993. }
  994. #endif
  995. #if defined(HAVE_CRTSWITCHRES)
  996. /* Switchres deinit */
  997. if (video_st->flags & VIDEO_FLAG_CRT_SWITCHING_ACTIVE)
  998. crt_destroy_modes(&video_st->crt_switch_st);
  999. #endif
  1000. /* Video */
  1001. video_display_server_destroy();
  1002. video_st->flags &= ~(VIDEO_FLAG_ACTIVE | VIDEO_FLAG_USE_RGBA |
  1003. VIDEO_FLAG_HDR_SUPPORT | VIDEO_FLAG_CACHE_CONTEXT |
  1004. VIDEO_FLAG_CACHE_CONTEXT_ACK
  1005. );
  1006. video_st->record_gpu_buffer = NULL;
  1007. video_st->current_video = NULL;
  1008. video_driver_set_cached_frame_ptr(NULL);
  1009. /* Audio */
  1010. audio_state_get_ptr()->flags &= ~AUDIO_FLAG_ACTIVE;
  1011. audio_state_get_ptr()->current_audio = NULL;
  1012. if (input_st)
  1013. {
  1014. /* Input */
  1015. input_st->flags &= ~(INP_FLAG_KB_LINEFEED_ENABLE
  1016. | INP_FLAG_BLOCK_HOTKEY
  1017. | INP_FLAG_BLOCK_LIBRETRO_INPUT
  1018. | INP_FLAG_NONBLOCKING);
  1019. memset(&input_st->turbo_btns, 0, sizeof(turbo_buttons_t));
  1020. memset(&input_st->analog_requested, 0,
  1021. sizeof(input_st->analog_requested));
  1022. input_st->current_driver = NULL;
  1023. }
  1024. #ifdef HAVE_MENU
  1025. menu_driver_destroy(
  1026. menu_state_get_ptr());
  1027. #endif
  1028. location_st->active = false;
  1029. destroy_location();
  1030. /* Camera */
  1031. camera_st->active = false;
  1032. camera_st->driver = NULL;
  1033. camera_st->data = NULL;
  1034. #ifdef HAVE_BLUETOOTH
  1035. bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_DESTROY, NULL);
  1036. #endif
  1037. #ifdef HAVE_WIFI
  1038. wifi_driver_ctl(RARCH_WIFI_CTL_DESTROY, NULL);
  1039. #endif
  1040. cbs->frame_cb = retro_frame_null;
  1041. cbs->poll_cb = retro_input_poll_null;
  1042. cbs->sample_cb = NULL;
  1043. cbs->sample_batch_cb = NULL;
  1044. cbs->state_cb = NULL;
  1045. runloop_st->current_core.flags &= ~RETRO_CORE_FLAG_INITED;
  1046. }
  1047. bool driver_ctl(enum driver_ctl_state state, void *data)
  1048. {
  1049. driver_ctx_info_t *drv = (driver_ctx_info_t*)data;
  1050. switch (state)
  1051. {
  1052. case RARCH_DRIVER_CTL_SET_REFRESH_RATE:
  1053. {
  1054. float *hz = (float*)data;
  1055. audio_driver_state_t
  1056. *audio_st = audio_state_get_ptr();
  1057. settings_t *settings = config_get_ptr();
  1058. unsigned
  1059. audio_output_sample_rate = settings->uints.audio_output_sample_rate;
  1060. bool vrr_runloop_enable = settings->bools.vrr_runloop_enable;
  1061. float video_refresh_rate = settings->floats.video_refresh_rate;
  1062. float audio_max_timing_skew = settings->floats.audio_max_timing_skew;
  1063. bool video_adaptive_vsync = settings->bools.video_adaptive_vsync;
  1064. unsigned video_swap_interval = settings->uints.video_swap_interval;
  1065. video_monitor_set_refresh_rate(*hz);
  1066. /* Sets audio monitor rate to new value. */
  1067. audio_st->source_ratio_original =
  1068. audio_st->source_ratio_current =
  1069. (double)audio_output_sample_rate / audio_st->input;
  1070. driver_adjust_system_rates(
  1071. vrr_runloop_enable,
  1072. video_refresh_rate,
  1073. audio_max_timing_skew,
  1074. video_adaptive_vsync,
  1075. video_swap_interval
  1076. );
  1077. }
  1078. break;
  1079. case RARCH_DRIVER_CTL_FIND_FIRST:
  1080. if (!drv)
  1081. return false;
  1082. find_driver_nonempty(drv->label, 0, drv->s, drv->len);
  1083. break;
  1084. case RARCH_DRIVER_CTL_FIND_LAST:
  1085. if (!drv)
  1086. return false;
  1087. driver_find_last(drv->label, drv->s, drv->len);
  1088. break;
  1089. case RARCH_DRIVER_CTL_FIND_PREV:
  1090. if (!drv)
  1091. return false;
  1092. return driver_find_prev(drv->label, drv->s, drv->len);
  1093. case RARCH_DRIVER_CTL_FIND_NEXT:
  1094. if (!drv)
  1095. return false;
  1096. return driver_find_next(drv->label, drv->s, drv->len);
  1097. case RARCH_DRIVER_CTL_NONE:
  1098. default:
  1099. break;
  1100. }
  1101. return true;
  1102. }
  1103. access_state_t *access_state_get_ptr(void)
  1104. {
  1105. return &access_state_st;
  1106. }
  1107. /* GLOBAL POINTER GETTERS */
  1108. global_t *global_get_ptr(void)
  1109. {
  1110. return &global_driver_st;
  1111. }
  1112. uint16_t retroarch_get_flags(void)
  1113. {
  1114. struct rarch_state *p_rarch = &rarch_st;
  1115. return p_rarch->flags;
  1116. }
  1117. struct retro_perf_counter **retro_get_perf_counter_rarch(void)
  1118. {
  1119. struct rarch_state *p_rarch = &rarch_st;
  1120. return p_rarch->perf_counters_rarch;
  1121. }
  1122. unsigned retro_get_perf_count_rarch(void)
  1123. {
  1124. struct rarch_state *p_rarch = &rarch_st;
  1125. return p_rarch->perf_ptr_rarch;
  1126. }
  1127. void rarch_perf_register(struct retro_perf_counter *perf)
  1128. {
  1129. struct rarch_state *p_rarch = &rarch_st;
  1130. runloop_state_t *runloop_st = runloop_state_get_ptr();
  1131. if (
  1132. !runloop_st->perfcnt_enable
  1133. || perf->registered
  1134. || p_rarch->perf_ptr_rarch >= MAX_COUNTERS
  1135. )
  1136. return;
  1137. p_rarch->perf_counters_rarch[p_rarch->perf_ptr_rarch++] = perf;
  1138. perf->registered = true;
  1139. }
  1140. struct string_list *dir_list_new_special(const char *input_dir,
  1141. enum dir_list_type type, const char *filter,
  1142. bool show_hidden_files)
  1143. {
  1144. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  1145. char ext_shaders[255];
  1146. #endif
  1147. char ext_name[255];
  1148. const char *exts = NULL;
  1149. bool recursive = false;
  1150. switch (type)
  1151. {
  1152. case DIR_LIST_AUTOCONFIG:
  1153. exts = filter;
  1154. break;
  1155. case DIR_LIST_CORES:
  1156. ext_name[0] = '\0';
  1157. if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name)))
  1158. return NULL;
  1159. exts = ext_name;
  1160. break;
  1161. case DIR_LIST_RECURSIVE:
  1162. recursive = true;
  1163. /* fall-through */
  1164. case DIR_LIST_CORE_INFO:
  1165. {
  1166. core_info_list_t *list = NULL;
  1167. core_info_get_list(&list);
  1168. if (list)
  1169. exts = list->all_ext;
  1170. }
  1171. break;
  1172. case DIR_LIST_SHADERS:
  1173. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  1174. {
  1175. union string_list_elem_attr attr;
  1176. struct string_list str_list;
  1177. if (!string_list_initialize(&str_list))
  1178. return NULL;
  1179. ext_shaders[0] = '\0';
  1180. attr.i = 0;
  1181. if (video_shader_is_supported(RARCH_SHADER_CG))
  1182. {
  1183. string_list_append(&str_list, "cgp", attr);
  1184. string_list_append(&str_list, "cg", attr);
  1185. }
  1186. if (video_shader_is_supported(RARCH_SHADER_GLSL))
  1187. {
  1188. string_list_append(&str_list, "glslp", attr);
  1189. string_list_append(&str_list, "glsl", attr);
  1190. }
  1191. if (video_shader_is_supported(RARCH_SHADER_SLANG))
  1192. {
  1193. string_list_append(&str_list, "slangp", attr);
  1194. string_list_append(&str_list, "slang", attr);
  1195. }
  1196. string_list_join_concat(ext_shaders, sizeof(ext_shaders), &str_list, "|");
  1197. string_list_deinitialize(&str_list);
  1198. exts = ext_shaders;
  1199. }
  1200. break;
  1201. #else
  1202. return NULL;
  1203. #endif
  1204. case DIR_LIST_COLLECTIONS:
  1205. exts = "lpl";
  1206. break;
  1207. case DIR_LIST_DATABASES:
  1208. exts = "rdb";
  1209. break;
  1210. case DIR_LIST_PLAIN:
  1211. exts = filter;
  1212. break;
  1213. case DIR_LIST_NONE:
  1214. default:
  1215. return NULL;
  1216. }
  1217. return dir_list_new(input_dir, exts, false,
  1218. show_hidden_files,
  1219. type == DIR_LIST_CORE_INFO, recursive);
  1220. }
  1221. struct string_list *string_list_new_special(enum string_list_type type,
  1222. void *data, unsigned *len, size_t *list_size)
  1223. {
  1224. union string_list_elem_attr attr;
  1225. unsigned i;
  1226. struct string_list *s = string_list_new();
  1227. if (!s || !len)
  1228. goto error;
  1229. attr.i = 0;
  1230. *len = 0;
  1231. switch (type)
  1232. {
  1233. case STRING_LIST_MENU_DRIVERS:
  1234. #ifdef HAVE_MENU
  1235. for (i = 0; menu_ctx_drivers[i]; i++)
  1236. {
  1237. const char *opt = menu_ctx_drivers[i]->ident;
  1238. *len += strlen(opt) + 1;
  1239. /* Don't allow the user to set menu driver to "null" using the UI.
  1240. * Can prevent the user from locking him/herself out of the program. */
  1241. if (string_is_not_equal(opt, "null"))
  1242. string_list_append(s, opt, attr);
  1243. }
  1244. break;
  1245. #endif
  1246. case STRING_LIST_CAMERA_DRIVERS:
  1247. for (i = 0; camera_drivers[i]; i++)
  1248. {
  1249. const char *opt = camera_drivers[i]->ident;
  1250. *len += strlen(opt) + 1;
  1251. string_list_append(s, opt, attr);
  1252. }
  1253. break;
  1254. case STRING_LIST_BLUETOOTH_DRIVERS:
  1255. #ifdef HAVE_BLUETOOTH
  1256. for (i = 0; bluetooth_drivers[i]; i++)
  1257. {
  1258. const char *opt = bluetooth_drivers[i]->ident;
  1259. *len += strlen(opt) + 1;
  1260. string_list_append(s, opt, attr);
  1261. }
  1262. break;
  1263. #endif
  1264. case STRING_LIST_WIFI_DRIVERS:
  1265. #ifdef HAVE_WIFI
  1266. for (i = 0; wifi_drivers[i]; i++)
  1267. {
  1268. const char *opt = wifi_drivers[i]->ident;
  1269. *len += strlen(opt) + 1;
  1270. string_list_append(s, opt, attr);
  1271. }
  1272. break;
  1273. #endif
  1274. case STRING_LIST_LOCATION_DRIVERS:
  1275. for (i = 0; location_drivers[i]; i++)
  1276. {
  1277. const char *opt = location_drivers[i]->ident;
  1278. *len += strlen(opt) + 1;
  1279. string_list_append(s, opt, attr);
  1280. }
  1281. break;
  1282. case STRING_LIST_AUDIO_DRIVERS:
  1283. for (i = 0; audio_drivers[i]; i++)
  1284. {
  1285. const char *opt = audio_drivers[i]->ident;
  1286. *len += strlen(opt) + 1;
  1287. string_list_append(s, opt, attr);
  1288. }
  1289. break;
  1290. case STRING_LIST_AUDIO_RESAMPLER_DRIVERS:
  1291. for (i = 0; audio_resampler_driver_find_handle(i); i++)
  1292. {
  1293. const char *opt = audio_resampler_driver_find_ident(i);
  1294. *len += strlen(opt) + 1;
  1295. string_list_append(s, opt, attr);
  1296. }
  1297. break;
  1298. case STRING_LIST_VIDEO_DRIVERS:
  1299. for (i = 0; video_drivers[i]; i++)
  1300. {
  1301. const char *opt = video_drivers[i]->ident;
  1302. *len += strlen(opt) + 1;
  1303. /* Don't allow the user to set video driver to "null" using the UI.
  1304. * Can prevent the user from locking him/herself out of the program. */
  1305. if (string_is_not_equal(opt, "null"))
  1306. string_list_append(s, opt, attr);
  1307. }
  1308. break;
  1309. case STRING_LIST_INPUT_DRIVERS:
  1310. for (i = 0; input_drivers[i]; i++)
  1311. {
  1312. const char *opt = input_drivers[i]->ident;
  1313. *len += strlen(opt) + 1;
  1314. /* Don't allow the user to set input driver to "null" using the UI.
  1315. * Can prevent the user from locking him/herself out of the program. */
  1316. if (string_is_not_equal(opt, "null"))
  1317. string_list_append(s, opt, attr);
  1318. }
  1319. break;
  1320. case STRING_LIST_INPUT_HID_DRIVERS:
  1321. #ifdef HAVE_HID
  1322. for (i = 0; hid_drivers[i]; i++)
  1323. {
  1324. const char *opt = hid_drivers[i]->ident;
  1325. *len += strlen(opt) + 1;
  1326. /* Don't allow the user to set input HID driver to "null" using the UI.
  1327. * Can prevent the user from locking him/herself out of the program. */
  1328. if (string_is_not_equal(opt, "null"))
  1329. string_list_append(s, opt, attr);
  1330. }
  1331. #endif
  1332. break;
  1333. case STRING_LIST_INPUT_JOYPAD_DRIVERS:
  1334. for (i = 0; joypad_drivers[i]; i++)
  1335. {
  1336. const char *opt = joypad_drivers[i]->ident;
  1337. *len += strlen(opt) + 1;
  1338. /* Don't allow the user to set input joypad driver to "null" using the UI.
  1339. * Can prevent the user from locking him/herself out of the program. */
  1340. if (string_is_not_equal(opt, "null"))
  1341. string_list_append(s, opt, attr);
  1342. }
  1343. break;
  1344. case STRING_LIST_RECORD_DRIVERS:
  1345. for (i = 0; record_drivers[i]; i++)
  1346. {
  1347. const char *opt = record_drivers[i]->ident;
  1348. *len += strlen(opt) + 1;
  1349. string_list_append(s, opt, attr);
  1350. }
  1351. break;
  1352. case STRING_LIST_MIDI_DRIVERS:
  1353. for (i = 0; midi_driver_find_handle(i); i++)
  1354. {
  1355. const char *opt = midi_drivers[i]->ident;
  1356. *len += strlen(opt) + 1;
  1357. string_list_append(s, opt, attr);
  1358. }
  1359. break;
  1360. #ifdef HAVE_LAKKA
  1361. case STRING_LIST_TIMEZONES:
  1362. {
  1363. const char *opt = DEFAULT_TIMEZONE;
  1364. *len += strlen(opt) + 1;
  1365. string_list_append(s, opt, attr);
  1366. FILE *zones_file = popen("grep -v ^# /usr/share/zoneinfo/zone.tab | "
  1367. "cut -f3 | "
  1368. "sort", "r");
  1369. if (zones_file)
  1370. {
  1371. char zone_desc[TIMEZONE_LENGTH];
  1372. while (fgets(zone_desc, TIMEZONE_LENGTH, zones_file))
  1373. {
  1374. size_t zone_desc_len = strlen(zone_desc);
  1375. if (zone_desc_len > 0)
  1376. if (zone_desc[--zone_desc_len] == '\n')
  1377. zone_desc[zone_desc_len] = '\0';
  1378. if (zone_desc && zone_desc[0] != '\0')
  1379. {
  1380. const char *opt = zone_desc;
  1381. *len += strlen(opt) + 1;
  1382. string_list_append(s, opt, attr);
  1383. }
  1384. }
  1385. pclose(zones_file);
  1386. }
  1387. }
  1388. break;
  1389. #endif
  1390. case STRING_LIST_NONE:
  1391. default:
  1392. goto error;
  1393. }
  1394. return s;
  1395. error:
  1396. string_list_free(s);
  1397. s = NULL;
  1398. return NULL;
  1399. }
  1400. const char *char_list_new_special(enum string_list_type type, void *data)
  1401. {
  1402. unsigned len = 0;
  1403. size_t list_size;
  1404. struct string_list *s = string_list_new_special(type, data, &len, &list_size);
  1405. char *options = (len > 0) ? (char*)calloc(len, sizeof(char)): NULL;
  1406. if (options && s)
  1407. string_list_join_concat(options, len, s, "|");
  1408. string_list_free(s);
  1409. s = NULL;
  1410. return options;
  1411. }
  1412. char *path_get_ptr(enum rarch_path_type type)
  1413. {
  1414. struct rarch_state *p_rarch = &rarch_st;
  1415. runloop_state_t *runloop_st = runloop_state_get_ptr();
  1416. switch (type)
  1417. {
  1418. case RARCH_PATH_CONTENT:
  1419. return p_rarch->path_content;
  1420. case RARCH_PATH_DEFAULT_SHADER_PRESET:
  1421. return p_rarch->path_default_shader_preset;
  1422. case RARCH_PATH_BASENAME:
  1423. return runloop_st->runtime_content_path_basename;
  1424. case RARCH_PATH_CORE_OPTIONS:
  1425. if (!path_is_empty(RARCH_PATH_CORE_OPTIONS))
  1426. return p_rarch->path_core_options_file;
  1427. break;
  1428. case RARCH_PATH_SUBSYSTEM:
  1429. return runloop_st->subsystem_path;
  1430. case RARCH_PATH_CONFIG:
  1431. if (!path_is_empty(RARCH_PATH_CONFIG))
  1432. return p_rarch->path_config_file;
  1433. break;
  1434. case RARCH_PATH_CONFIG_APPEND:
  1435. if (!path_is_empty(RARCH_PATH_CONFIG_APPEND))
  1436. return p_rarch->path_config_append_file;
  1437. break;
  1438. case RARCH_PATH_CONFIG_OVERRIDE:
  1439. if (!path_is_empty(RARCH_PATH_CONFIG_OVERRIDE))
  1440. return p_rarch->path_config_override_file;
  1441. break;
  1442. case RARCH_PATH_CORE:
  1443. return p_rarch->path_libretro;
  1444. case RARCH_PATH_NONE:
  1445. case RARCH_PATH_NAMES:
  1446. break;
  1447. }
  1448. return NULL;
  1449. }
  1450. const char *path_get(enum rarch_path_type type)
  1451. {
  1452. struct rarch_state *p_rarch = &rarch_st;
  1453. runloop_state_t *runloop_st = runloop_state_get_ptr();
  1454. switch (type)
  1455. {
  1456. case RARCH_PATH_CONTENT:
  1457. return p_rarch->path_content;
  1458. case RARCH_PATH_DEFAULT_SHADER_PRESET:
  1459. return p_rarch->path_default_shader_preset;
  1460. case RARCH_PATH_BASENAME:
  1461. return runloop_st->runtime_content_path_basename;
  1462. case RARCH_PATH_CORE_OPTIONS:
  1463. if (!path_is_empty(RARCH_PATH_CORE_OPTIONS))
  1464. return p_rarch->path_core_options_file;
  1465. break;
  1466. case RARCH_PATH_SUBSYSTEM:
  1467. return runloop_st->subsystem_path;
  1468. case RARCH_PATH_CONFIG:
  1469. if (!path_is_empty(RARCH_PATH_CONFIG))
  1470. return p_rarch->path_config_file;
  1471. break;
  1472. case RARCH_PATH_CONFIG_APPEND:
  1473. if (!path_is_empty(RARCH_PATH_CONFIG_APPEND))
  1474. return p_rarch->path_config_append_file;
  1475. break;
  1476. case RARCH_PATH_CONFIG_OVERRIDE:
  1477. if (!path_is_empty(RARCH_PATH_CONFIG_OVERRIDE))
  1478. return p_rarch->path_config_override_file;
  1479. break;
  1480. case RARCH_PATH_CORE:
  1481. return p_rarch->path_libretro;
  1482. case RARCH_PATH_NONE:
  1483. case RARCH_PATH_NAMES:
  1484. break;
  1485. }
  1486. return NULL;
  1487. }
  1488. size_t path_get_realsize(enum rarch_path_type type)
  1489. {
  1490. struct rarch_state *p_rarch = &rarch_st;
  1491. switch (type)
  1492. {
  1493. case RARCH_PATH_CONTENT:
  1494. return sizeof(p_rarch->path_content);
  1495. case RARCH_PATH_DEFAULT_SHADER_PRESET:
  1496. return sizeof(p_rarch->path_default_shader_preset);
  1497. case RARCH_PATH_BASENAME:
  1498. return sizeof(runloop_state_get_ptr()->runtime_content_path_basename);
  1499. case RARCH_PATH_CORE_OPTIONS:
  1500. return sizeof(p_rarch->path_core_options_file);
  1501. case RARCH_PATH_SUBSYSTEM:
  1502. return sizeof(runloop_state_get_ptr()->subsystem_path);
  1503. case RARCH_PATH_CONFIG:
  1504. return sizeof(p_rarch->path_config_file);
  1505. case RARCH_PATH_CONFIG_APPEND:
  1506. return sizeof(p_rarch->path_config_append_file);
  1507. case RARCH_PATH_CONFIG_OVERRIDE:
  1508. return sizeof(p_rarch->path_config_override_file);
  1509. case RARCH_PATH_CORE:
  1510. return sizeof(p_rarch->path_libretro);
  1511. case RARCH_PATH_NONE:
  1512. case RARCH_PATH_NAMES:
  1513. break;
  1514. }
  1515. return 0;
  1516. }
  1517. bool path_set(enum rarch_path_type type, const char *path)
  1518. {
  1519. struct rarch_state *p_rarch = &rarch_st;
  1520. runloop_state_t *runloop_st = NULL;
  1521. if (!path)
  1522. return false;
  1523. switch (type)
  1524. {
  1525. case RARCH_PATH_NAMES:
  1526. runloop_path_set_basename(path);
  1527. runloop_path_set_names();
  1528. runloop_path_set_redirect(config_get_ptr(), p_rarch->dir_savefile,
  1529. p_rarch->dir_savestate);
  1530. break;
  1531. case RARCH_PATH_CORE:
  1532. strlcpy(p_rarch->path_libretro, path,
  1533. sizeof(p_rarch->path_libretro));
  1534. break;
  1535. case RARCH_PATH_DEFAULT_SHADER_PRESET:
  1536. strlcpy(p_rarch->path_default_shader_preset, path,
  1537. sizeof(p_rarch->path_default_shader_preset));
  1538. break;
  1539. case RARCH_PATH_CONFIG_APPEND:
  1540. strlcpy(p_rarch->path_config_append_file, path,
  1541. sizeof(p_rarch->path_config_append_file));
  1542. break;
  1543. case RARCH_PATH_CONFIG:
  1544. strlcpy(p_rarch->path_config_file, path,
  1545. sizeof(p_rarch->path_config_file));
  1546. break;
  1547. case RARCH_PATH_CONFIG_OVERRIDE:
  1548. strlcpy(p_rarch->path_config_override_file, path,
  1549. sizeof(p_rarch->path_config_override_file));
  1550. break;
  1551. case RARCH_PATH_CORE_OPTIONS:
  1552. strlcpy(p_rarch->path_core_options_file, path,
  1553. sizeof(p_rarch->path_core_options_file));
  1554. break;
  1555. case RARCH_PATH_CONTENT:
  1556. strlcpy(p_rarch->path_content, path,
  1557. sizeof(p_rarch->path_content));
  1558. break;
  1559. case RARCH_PATH_BASENAME:
  1560. runloop_st = runloop_state_get_ptr();
  1561. strlcpy(runloop_st->runtime_content_path_basename, path,
  1562. sizeof(runloop_st->runtime_content_path_basename));
  1563. break;
  1564. case RARCH_PATH_SUBSYSTEM:
  1565. runloop_st = runloop_state_get_ptr();
  1566. strlcpy(runloop_st->subsystem_path, path,
  1567. sizeof(runloop_st->subsystem_path));
  1568. break;
  1569. case RARCH_PATH_NONE:
  1570. break;
  1571. }
  1572. return true;
  1573. }
  1574. bool path_is_empty(enum rarch_path_type type)
  1575. {
  1576. struct rarch_state *p_rarch = &rarch_st;
  1577. switch (type)
  1578. {
  1579. case RARCH_PATH_DEFAULT_SHADER_PRESET:
  1580. if (string_is_empty(p_rarch->path_default_shader_preset))
  1581. return true;
  1582. break;
  1583. case RARCH_PATH_CONFIG:
  1584. if (string_is_empty(p_rarch->path_config_file))
  1585. return true;
  1586. break;
  1587. case RARCH_PATH_CONFIG_APPEND:
  1588. if (string_is_empty(p_rarch->path_config_append_file))
  1589. return true;
  1590. break;
  1591. case RARCH_PATH_CONFIG_OVERRIDE:
  1592. if (string_is_empty(p_rarch->path_config_override_file))
  1593. return true;
  1594. break;
  1595. case RARCH_PATH_CORE_OPTIONS:
  1596. if (string_is_empty(p_rarch->path_core_options_file))
  1597. return true;
  1598. break;
  1599. case RARCH_PATH_CONTENT:
  1600. if (string_is_empty(p_rarch->path_content))
  1601. return true;
  1602. break;
  1603. case RARCH_PATH_CORE:
  1604. if (string_is_empty(p_rarch->path_libretro))
  1605. return true;
  1606. break;
  1607. case RARCH_PATH_BASENAME:
  1608. if (string_is_empty(runloop_state_get_ptr()->runtime_content_path_basename))
  1609. return true;
  1610. break;
  1611. case RARCH_PATH_SUBSYSTEM:
  1612. if (string_is_empty(runloop_state_get_ptr()->subsystem_path))
  1613. return true;
  1614. break;
  1615. case RARCH_PATH_NONE:
  1616. case RARCH_PATH_NAMES:
  1617. break;
  1618. }
  1619. return false;
  1620. }
  1621. void path_clear(enum rarch_path_type type)
  1622. {
  1623. struct rarch_state *p_rarch = &rarch_st;
  1624. runloop_state_t *runloop_st = NULL;
  1625. switch (type)
  1626. {
  1627. case RARCH_PATH_CORE:
  1628. *p_rarch->path_libretro = '\0';
  1629. break;
  1630. case RARCH_PATH_CONFIG:
  1631. *p_rarch->path_config_file = '\0';
  1632. break;
  1633. case RARCH_PATH_CONTENT:
  1634. *p_rarch->path_content = '\0';
  1635. break;
  1636. case RARCH_PATH_CORE_OPTIONS:
  1637. *p_rarch->path_core_options_file = '\0';
  1638. break;
  1639. case RARCH_PATH_DEFAULT_SHADER_PRESET:
  1640. *p_rarch->path_default_shader_preset = '\0';
  1641. break;
  1642. case RARCH_PATH_CONFIG_APPEND:
  1643. *p_rarch->path_config_append_file = '\0';
  1644. break;
  1645. case RARCH_PATH_CONFIG_OVERRIDE:
  1646. *p_rarch->path_config_override_file = '\0';
  1647. break;
  1648. case RARCH_PATH_NONE:
  1649. case RARCH_PATH_NAMES:
  1650. break;
  1651. case RARCH_PATH_BASENAME:
  1652. runloop_st = runloop_state_get_ptr();
  1653. *runloop_st->runtime_content_path_basename = '\0';
  1654. break;
  1655. case RARCH_PATH_SUBSYSTEM:
  1656. runloop_st = runloop_state_get_ptr();
  1657. *runloop_st->subsystem_path = '\0';
  1658. break;
  1659. }
  1660. }
  1661. static void path_clear_all(void)
  1662. {
  1663. path_clear(RARCH_PATH_CONTENT);
  1664. path_clear(RARCH_PATH_CONFIG);
  1665. path_clear(RARCH_PATH_CONFIG_APPEND);
  1666. path_clear(RARCH_PATH_CONFIG_OVERRIDE);
  1667. path_clear(RARCH_PATH_CORE_OPTIONS);
  1668. path_clear(RARCH_PATH_BASENAME);
  1669. }
  1670. static void ram_state_to_file(void)
  1671. {
  1672. char state_path[PATH_MAX_LENGTH];
  1673. if (!content_ram_state_pending())
  1674. return;
  1675. state_path[0] = '\0';
  1676. if (runloop_get_current_savestate_path(state_path, sizeof(state_path)))
  1677. command_event(CMD_EVENT_RAM_STATE_TO_FILE, state_path);
  1678. }
  1679. enum rarch_content_type path_is_media_type(const char *path)
  1680. {
  1681. char ext_lower[128];
  1682. strlcpy(ext_lower, path_get_extension(path), sizeof(ext_lower));
  1683. string_to_lower(ext_lower);
  1684. /* hack, to detect livestreams so the ffmpeg core can be started */
  1685. if (string_starts_with_size(path, "udp://", STRLEN_CONST("udp://")) ||
  1686. string_starts_with_size(path, "http://", STRLEN_CONST("http://")) ||
  1687. string_starts_with_size(path, "https://", STRLEN_CONST("https://")) ||
  1688. string_starts_with_size(path, "tcp://", STRLEN_CONST("tcp://")) ||
  1689. string_starts_with_size(path, "rtmp://", STRLEN_CONST("rtmp://")) ||
  1690. string_starts_with_size(path, "rtp://", STRLEN_CONST("rtp://")))
  1691. return RARCH_CONTENT_MOVIE;
  1692. switch (msg_hash_to_file_type(msg_hash_calculate(ext_lower)))
  1693. {
  1694. #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
  1695. case FILE_TYPE_OGM:
  1696. case FILE_TYPE_MKV:
  1697. case FILE_TYPE_AVI:
  1698. case FILE_TYPE_MP4:
  1699. case FILE_TYPE_FLV:
  1700. case FILE_TYPE_WEBM:
  1701. case FILE_TYPE_3GP:
  1702. case FILE_TYPE_3G2:
  1703. case FILE_TYPE_F4F:
  1704. case FILE_TYPE_F4V:
  1705. case FILE_TYPE_MOV:
  1706. case FILE_TYPE_WMV:
  1707. case FILE_TYPE_MPG:
  1708. case FILE_TYPE_MPEG:
  1709. case FILE_TYPE_VOB:
  1710. case FILE_TYPE_ASF:
  1711. case FILE_TYPE_DIVX:
  1712. case FILE_TYPE_M2P:
  1713. case FILE_TYPE_M2TS:
  1714. case FILE_TYPE_PS:
  1715. case FILE_TYPE_TS:
  1716. case FILE_TYPE_MXF:
  1717. return RARCH_CONTENT_MOVIE;
  1718. case FILE_TYPE_WMA:
  1719. case FILE_TYPE_OGG:
  1720. case FILE_TYPE_MP3:
  1721. case FILE_TYPE_M4A:
  1722. case FILE_TYPE_FLAC:
  1723. case FILE_TYPE_WAV:
  1724. return RARCH_CONTENT_MUSIC;
  1725. #endif
  1726. #ifdef HAVE_IMAGEVIEWER
  1727. case FILE_TYPE_JPEG:
  1728. case FILE_TYPE_PNG:
  1729. case FILE_TYPE_TGA:
  1730. case FILE_TYPE_BMP:
  1731. return RARCH_CONTENT_IMAGE;
  1732. #endif
  1733. #ifdef HAVE_IBXM
  1734. case FILE_TYPE_MOD:
  1735. case FILE_TYPE_S3M:
  1736. case FILE_TYPE_XM:
  1737. return RARCH_CONTENT_MUSIC;
  1738. #endif
  1739. case FILE_TYPE_NONE:
  1740. default:
  1741. break;
  1742. }
  1743. return RARCH_CONTENT_NONE;
  1744. }
  1745. /* get size functions */
  1746. size_t dir_get_size(enum rarch_dir_type type)
  1747. {
  1748. struct rarch_state *p_rarch = &rarch_st;
  1749. switch (type)
  1750. {
  1751. case RARCH_DIR_SYSTEM:
  1752. return sizeof(p_rarch->dir_system);
  1753. case RARCH_DIR_SAVESTATE:
  1754. return sizeof(p_rarch->dir_savestate);
  1755. case RARCH_DIR_CURRENT_SAVESTATE:
  1756. return sizeof(runloop_state_get_ptr()->savestate_dir);
  1757. case RARCH_DIR_SAVEFILE:
  1758. return sizeof(p_rarch->dir_savefile);
  1759. case RARCH_DIR_CURRENT_SAVEFILE:
  1760. return sizeof(runloop_state_get_ptr()->savefile_dir);
  1761. case RARCH_DIR_NONE:
  1762. break;
  1763. }
  1764. return 0;
  1765. }
  1766. /* clear functions */
  1767. void dir_clear(enum rarch_dir_type type)
  1768. {
  1769. struct rarch_state *p_rarch = &rarch_st;
  1770. runloop_state_t *runloop_st = NULL;
  1771. switch (type)
  1772. {
  1773. case RARCH_DIR_SAVEFILE:
  1774. *p_rarch->dir_savefile = '\0';
  1775. break;
  1776. case RARCH_DIR_SAVESTATE:
  1777. *p_rarch->dir_savestate = '\0';
  1778. break;
  1779. case RARCH_DIR_SYSTEM:
  1780. *p_rarch->dir_system = '\0';
  1781. break;
  1782. case RARCH_DIR_NONE:
  1783. break;
  1784. case RARCH_DIR_CURRENT_SAVEFILE:
  1785. runloop_st = runloop_state_get_ptr();
  1786. *runloop_st->savefile_dir = '\0';
  1787. break;
  1788. case RARCH_DIR_CURRENT_SAVESTATE:
  1789. runloop_st = runloop_state_get_ptr();
  1790. *runloop_st->savestate_dir = '\0';
  1791. break;
  1792. }
  1793. }
  1794. static void dir_clear_all(void)
  1795. {
  1796. dir_clear(RARCH_DIR_SYSTEM);
  1797. dir_clear(RARCH_DIR_SAVEFILE);
  1798. dir_clear(RARCH_DIR_SAVESTATE);
  1799. }
  1800. /* get ptr functions */
  1801. char *dir_get_ptr(enum rarch_dir_type type)
  1802. {
  1803. struct rarch_state *p_rarch = &rarch_st;
  1804. switch (type)
  1805. {
  1806. case RARCH_DIR_SAVEFILE:
  1807. return p_rarch->dir_savefile;
  1808. case RARCH_DIR_CURRENT_SAVEFILE:
  1809. return runloop_state_get_ptr()->savefile_dir;
  1810. case RARCH_DIR_SAVESTATE:
  1811. return p_rarch->dir_savestate;
  1812. case RARCH_DIR_CURRENT_SAVESTATE:
  1813. return runloop_state_get_ptr()->savestate_dir;
  1814. case RARCH_DIR_SYSTEM:
  1815. return p_rarch->dir_system;
  1816. case RARCH_DIR_NONE:
  1817. break;
  1818. }
  1819. return NULL;
  1820. }
  1821. void dir_set(enum rarch_dir_type type, const char *path)
  1822. {
  1823. struct rarch_state *p_rarch = &rarch_st;
  1824. runloop_state_t *runloop_st = NULL;
  1825. switch (type)
  1826. {
  1827. case RARCH_DIR_SAVEFILE:
  1828. strlcpy(p_rarch->dir_savefile, path,
  1829. sizeof(p_rarch->dir_savefile));
  1830. break;
  1831. case RARCH_DIR_SAVESTATE:
  1832. strlcpy(p_rarch->dir_savestate, path,
  1833. sizeof(p_rarch->dir_savestate));
  1834. break;
  1835. case RARCH_DIR_SYSTEM:
  1836. strlcpy(p_rarch->dir_system, path,
  1837. sizeof(p_rarch->dir_system));
  1838. break;
  1839. case RARCH_DIR_NONE:
  1840. break;
  1841. case RARCH_DIR_CURRENT_SAVEFILE:
  1842. runloop_st = runloop_state_get_ptr();
  1843. strlcpy(runloop_st->savefile_dir, path,
  1844. sizeof(runloop_st->savefile_dir));
  1845. break;
  1846. case RARCH_DIR_CURRENT_SAVESTATE:
  1847. runloop_st = runloop_state_get_ptr();
  1848. strlcpy(runloop_st->savestate_dir, path,
  1849. sizeof(runloop_st->savestate_dir));
  1850. break;
  1851. }
  1852. }
  1853. void dir_check_defaults(const char *custom_ini_path)
  1854. {
  1855. size_t i;
  1856. /* Early return for people with a custom folder setup
  1857. * so it doesn't create unnecessary directories */
  1858. if (!string_is_empty(custom_ini_path) &&
  1859. path_is_valid(custom_ini_path))
  1860. return;
  1861. for (i = 0; i < DEFAULT_DIR_LAST; i++)
  1862. {
  1863. const char *dir_path = g_defaults.dirs[i];
  1864. char new_path[PATH_MAX_LENGTH];
  1865. if (string_is_empty(dir_path))
  1866. continue;
  1867. fill_pathname_expand_special(new_path,
  1868. dir_path, sizeof(new_path));
  1869. if (!path_is_directory(new_path))
  1870. path_mkdir(new_path);
  1871. }
  1872. }
  1873. #ifdef HAVE_ACCESSIBILITY
  1874. bool is_accessibility_enabled(bool accessibility_enable, bool accessibility_enabled)
  1875. {
  1876. return accessibility_enabled || accessibility_enable;
  1877. }
  1878. #endif
  1879. /**
  1880. * command_event:
  1881. * @cmd : Event command index.
  1882. *
  1883. * Performs program event command with index @cmd.
  1884. *
  1885. * Returns: true (1) on success, otherwise false (0).
  1886. **/
  1887. bool command_event(enum event_command cmd, void *data)
  1888. {
  1889. struct rarch_state *p_rarch = &rarch_st;
  1890. runloop_state_t *runloop_st = runloop_state_get_ptr();
  1891. uico_driver_state_t *uico_st = uico_state_get_ptr();
  1892. #if defined(HAVE_ACCESSIBILITY) || defined(HAVE_TRANSLATE)
  1893. access_state_t *access_st = access_state_get_ptr();
  1894. #endif
  1895. #ifdef HAVE_MENU
  1896. struct menu_state *menu_st = menu_state_get_ptr();
  1897. #endif
  1898. video_driver_state_t *video_st = video_state_get_ptr();
  1899. settings_t *settings = config_get_ptr();
  1900. recording_state_t *recording_st = recording_state_get_ptr();
  1901. switch (cmd)
  1902. {
  1903. case CMD_EVENT_SAVE_FILES:
  1904. event_save_files(runloop_st->flags & RUNLOOP_FLAG_USE_SRAM);
  1905. break;
  1906. case CMD_EVENT_OVERLAY_DEINIT:
  1907. #ifdef HAVE_OVERLAY
  1908. input_overlay_deinit();
  1909. #endif
  1910. #if defined(HAVE_TRANSLATE) && defined(HAVE_GFX_WIDGETS)
  1911. /* Because the overlay is a display widget,
  1912. * it's going to be written
  1913. * over the menu, so we unset it here. */
  1914. if (dispwidget_get_ptr()->ai_service_overlay_state != 0)
  1915. gfx_widgets_ai_service_overlay_unload();
  1916. #endif
  1917. break;
  1918. case CMD_EVENT_OVERLAY_INIT:
  1919. #ifdef HAVE_OVERLAY
  1920. input_overlay_init();
  1921. #endif
  1922. break;
  1923. case CMD_EVENT_CHEAT_INDEX_PLUS:
  1924. #ifdef HAVE_CHEATS
  1925. cheat_manager_index_next();
  1926. #endif
  1927. break;
  1928. case CMD_EVENT_CHEAT_INDEX_MINUS:
  1929. #ifdef HAVE_CHEATS
  1930. cheat_manager_index_prev();
  1931. #endif
  1932. break;
  1933. case CMD_EVENT_CHEAT_TOGGLE:
  1934. #ifdef HAVE_CHEATS
  1935. cheat_manager_toggle();
  1936. #endif
  1937. break;
  1938. case CMD_EVENT_SHADER_NEXT:
  1939. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  1940. #ifdef HAVE_MENU
  1941. video_shader_dir_check_shader(menu_st->driver_data, settings,
  1942. &video_st->dir_shader_list, true, false);
  1943. #else
  1944. video_shader_dir_check_shader(NULL, settings,
  1945. &video_st->dir_shader_list, true, false);
  1946. #endif
  1947. #endif
  1948. break;
  1949. case CMD_EVENT_SHADER_PREV:
  1950. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  1951. #ifdef HAVE_MENU
  1952. video_shader_dir_check_shader(menu_st->driver_data, settings,
  1953. &video_st->dir_shader_list, false, true);
  1954. #else
  1955. video_shader_dir_check_shader(NULL, settings,
  1956. &video_st->dir_shader_list, false, true);
  1957. #endif
  1958. #endif
  1959. break;
  1960. case CMD_EVENT_SHADER_TOGGLE:
  1961. #ifdef HAVE_MENU
  1962. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  1963. video_shader_toggle(settings);
  1964. #endif
  1965. #endif
  1966. break;
  1967. case CMD_EVENT_AI_SERVICE_TOGGLE:
  1968. {
  1969. #ifdef HAVE_TRANSLATE
  1970. bool ai_service_pause = settings->bools.ai_service_pause;
  1971. if (!settings->bools.ai_service_enable)
  1972. break;
  1973. if (ai_service_pause)
  1974. {
  1975. /* Unpause on second press */
  1976. if (runloop_st->flags & RUNLOOP_FLAG_PAUSED)
  1977. {
  1978. #ifdef HAVE_ACCESSIBILITY
  1979. bool accessibility_enable = settings->bools.accessibility_enable;
  1980. unsigned accessibility_narrator_speech_speed = settings->uints.accessibility_narrator_speech_speed;
  1981. if (is_accessibility_enabled(
  1982. accessibility_enable,
  1983. access_st->enabled))
  1984. accessibility_speak_priority(
  1985. accessibility_enable,
  1986. accessibility_narrator_speech_speed,
  1987. (char*)msg_hash_to_str(MSG_UNPAUSED), 10);
  1988. #endif
  1989. command_event(CMD_EVENT_UNPAUSE, NULL);
  1990. }
  1991. else /* Pause on call */
  1992. {
  1993. command_event(CMD_EVENT_PAUSE, NULL);
  1994. command_event(CMD_EVENT_AI_SERVICE_CALL, NULL);
  1995. }
  1996. }
  1997. else
  1998. {
  1999. /* Don't pause - useful for Text-To-Speech since
  2000. * the audio can't currently play while paused.
  2001. * Also useful for cases when users don't want the
  2002. * core's sound to stop while translating.
  2003. *
  2004. * Also, this mode is required for "auto" translation
  2005. * packages, since you don't want to pause for that.
  2006. */
  2007. if (access_st->ai_service_auto == 2)
  2008. {
  2009. /* Auto mode was turned on, but we pressed the
  2010. * toggle button, so turn it off now. */
  2011. access_st->ai_service_auto = 0;
  2012. #ifdef HAVE_MENU_WIDGETS
  2013. gfx_widgets_ai_service_overlay_unload();
  2014. #endif
  2015. }
  2016. else
  2017. command_event(CMD_EVENT_AI_SERVICE_CALL, NULL);
  2018. }
  2019. #endif
  2020. break;
  2021. }
  2022. case CMD_EVENT_STREAMING_TOGGLE:
  2023. if (recording_st->streaming_enable)
  2024. command_event(CMD_EVENT_RECORD_DEINIT, NULL);
  2025. else
  2026. {
  2027. streaming_set_state(true);
  2028. command_event(CMD_EVENT_RECORD_INIT, NULL);
  2029. }
  2030. break;
  2031. case CMD_EVENT_RUNAHEAD_TOGGLE:
  2032. #if HAVE_RUNAHEAD
  2033. {
  2034. if (!core_info_current_supports_runahead())
  2035. {
  2036. runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_RUNAHEAD),
  2037. 1, 100, false,
  2038. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2039. break;
  2040. }
  2041. settings->bools.run_ahead_enabled =
  2042. !(settings->bools.run_ahead_enabled);
  2043. if (settings->bools.run_ahead_enabled)
  2044. {
  2045. char msg[256];
  2046. if (settings->bools.run_ahead_secondary_instance)
  2047. snprintf(msg, sizeof(msg),
  2048. msg_hash_to_str(MSG_RUNAHEAD_ENABLED_WITH_SECOND_INSTANCE),
  2049. settings->uints.run_ahead_frames);
  2050. else
  2051. snprintf(msg, sizeof(msg),
  2052. msg_hash_to_str(MSG_RUNAHEAD_ENABLED),
  2053. settings->uints.run_ahead_frames);
  2054. runloop_msg_queue_push(msg, 1, 100, false,
  2055. NULL, MESSAGE_QUEUE_ICON_DEFAULT,
  2056. MESSAGE_QUEUE_CATEGORY_INFO);
  2057. /* Disable preemptive frames */
  2058. settings->bools.preemptive_frames_enable = false;
  2059. preempt_deinit(runloop_st);
  2060. }
  2061. else
  2062. runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_DISABLED),
  2063. 1, 100, false,
  2064. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2065. }
  2066. #endif
  2067. break;
  2068. case CMD_EVENT_PREEMPT_TOGGLE:
  2069. #if HAVE_RUNAHEAD
  2070. {
  2071. bool old_warn = settings->bools.preemptive_frames_hide_warnings;
  2072. bool old_inited = runloop_st->preempt_data != NULL;
  2073. /* Toggle with warnings shown */
  2074. settings->bools.preemptive_frames_hide_warnings = false;
  2075. settings->bools.preemptive_frames_enable =
  2076. !(settings->bools.preemptive_frames_enable);
  2077. command_event(CMD_EVENT_PREEMPT_UPDATE, NULL);
  2078. settings->bools.preemptive_frames_hide_warnings = old_warn;
  2079. if (old_inited && !runloop_st->preempt_data)
  2080. runloop_msg_queue_push(msg_hash_to_str(MSG_PREEMPT_DISABLED),
  2081. 1, 100, false,
  2082. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2083. else if (runloop_st->preempt_data)
  2084. {
  2085. char msg[256];
  2086. snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_PREEMPT_ENABLED),
  2087. settings->uints.run_ahead_frames);
  2088. runloop_msg_queue_push(
  2089. msg, 1, 100, false,
  2090. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2091. /* Disable runahead */
  2092. settings->bools.run_ahead_enabled = false;
  2093. }
  2094. else /* Failed to init */
  2095. settings->bools.preemptive_frames_enable = false;
  2096. }
  2097. #endif
  2098. break;
  2099. case CMD_EVENT_PREEMPT_UPDATE:
  2100. #if HAVE_RUNAHEAD
  2101. preempt_deinit(runloop_st);
  2102. preempt_init(runloop_st);
  2103. #endif
  2104. break;
  2105. case CMD_EVENT_PREEMPT_RESET_BUFFER:
  2106. #if HAVE_RUNAHEAD
  2107. if (runloop_st->preempt_data)
  2108. runloop_st->preempt_data->frame_count = 0;
  2109. #endif
  2110. break;
  2111. case CMD_EVENT_RECORDING_TOGGLE:
  2112. if (recording_st->enable)
  2113. command_event(CMD_EVENT_RECORD_DEINIT, NULL);
  2114. else
  2115. command_event(CMD_EVENT_RECORD_INIT, NULL);
  2116. break;
  2117. case CMD_EVENT_SET_PER_GAME_RESOLUTION:
  2118. #if defined(GEKKO)
  2119. {
  2120. unsigned width = 0, height = 0;
  2121. char desc[64] = {0};
  2122. command_event(CMD_EVENT_VIDEO_SET_ASPECT_RATIO, NULL);
  2123. if (video_driver_get_video_output_size(&width, &height, desc, sizeof(desc)))
  2124. {
  2125. char msg[128];
  2126. video_driver_set_video_mode(width, height, true);
  2127. if (width == 0 || height == 0)
  2128. strlcpy(msg, msg_hash_to_str(MSG_SCREEN_RESOLUTION_DEFAULT), sizeof(msg));
  2129. else
  2130. {
  2131. msg[0] = '\0';
  2132. if (!string_is_empty(desc))
  2133. snprintf(msg, sizeof(msg),
  2134. msg_hash_to_str(MSG_SCREEN_RESOLUTION_DESC),
  2135. width, height, desc);
  2136. else
  2137. snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_SCREEN_RESOLUTION_NO_DESC),
  2138. width, height);
  2139. }
  2140. runloop_msg_queue_push(msg, 1, 100, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2141. }
  2142. }
  2143. #endif
  2144. break;
  2145. case CMD_EVENT_LOAD_CORE_PERSIST:
  2146. {
  2147. rarch_system_info_t *system_info = &runloop_st->system;
  2148. struct retro_system_info *system = &system_info->info;
  2149. const char *core_path = path_get(RARCH_PATH_CORE);
  2150. #if defined(HAVE_DYNAMIC)
  2151. if (string_is_empty(core_path))
  2152. return false;
  2153. #endif
  2154. if (!libretro_get_system_info(
  2155. core_path,
  2156. system,
  2157. &system_info->load_no_content))
  2158. return false;
  2159. if (!core_info_load(core_path))
  2160. {
  2161. #ifdef HAVE_DYNAMIC
  2162. return false;
  2163. #endif
  2164. }
  2165. }
  2166. break;
  2167. case CMD_EVENT_LOAD_CORE:
  2168. runloop_st->subsystem_current_count = 0;
  2169. content_clear_subsystem();
  2170. #ifdef HAVE_DYNAMIC
  2171. if (!(command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL)))
  2172. return false;
  2173. #else
  2174. command_event(CMD_EVENT_LOAD_CORE_PERSIST, NULL);
  2175. command_event(CMD_EVENT_QUIT, NULL);
  2176. #endif
  2177. break;
  2178. #if defined(HAVE_RUNAHEAD) && (defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB))
  2179. case CMD_EVENT_LOAD_SECOND_CORE:
  2180. if ( !(runloop_st->flags & RUNLOOP_FLAG_CORE_RUNNING)
  2181. || !(runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE))
  2182. return false;
  2183. if (!runloop_st->secondary_lib_handle)
  2184. {
  2185. if (!secondary_core_ensure_exists(runloop_st, settings))
  2186. {
  2187. runahead_secondary_core_destroy(runloop_st);
  2188. runloop_st->flags &=
  2189. ~RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE;
  2190. return false;
  2191. }
  2192. }
  2193. break;
  2194. #endif
  2195. case CMD_EVENT_LOAD_STATE:
  2196. {
  2197. #ifdef HAVE_CHEEVOS
  2198. if (rcheevos_hardcore_active())
  2199. {
  2200. runloop_msg_queue_push(msg_hash_to_str(MSG_CHEEVOS_LOAD_STATE_PREVENTED_BY_HARDCORE_MODE), 0, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_WARNING);
  2201. return false;
  2202. }
  2203. #endif
  2204. if (!command_event_main_state(cmd))
  2205. return false;
  2206. /* Run next frame to see the core output while paused */
  2207. else if (runloop_st->flags & RUNLOOP_FLAG_PAUSED)
  2208. {
  2209. runloop_st->flags &= ~RUNLOOP_FLAG_PAUSED;
  2210. runloop_st->run_frames_and_pause = 1;
  2211. }
  2212. #if HAVE_RUNAHEAD
  2213. command_event(CMD_EVENT_PREEMPT_RESET_BUFFER, NULL);
  2214. #endif
  2215. }
  2216. break;
  2217. case CMD_EVENT_UNDO_LOAD_STATE:
  2218. case CMD_EVENT_UNDO_SAVE_STATE:
  2219. case CMD_EVENT_LOAD_STATE_FROM_RAM:
  2220. if (!command_event_main_state(cmd))
  2221. return false;
  2222. break;
  2223. case CMD_EVENT_RAM_STATE_TO_FILE:
  2224. if (!content_ram_state_to_file((char *) data))
  2225. return false;
  2226. break;
  2227. case CMD_EVENT_RESIZE_WINDOWED_SCALE:
  2228. if
  2229. (!command_event_resize_windowed_scale
  2230. (settings,
  2231. runloop_st->pending_windowed_scale))
  2232. return false;
  2233. break;
  2234. case CMD_EVENT_MENU_TOGGLE:
  2235. #ifdef HAVE_MENU
  2236. if (menu_st->flags & MENU_ST_FLAG_ALIVE)
  2237. retroarch_menu_running_finished(false);
  2238. else
  2239. retroarch_menu_running();
  2240. #endif
  2241. break;
  2242. case CMD_EVENT_RESET:
  2243. RARCH_LOG("[Core]: %s.\n", msg_hash_to_str(MSG_RESET));
  2244. runloop_msg_queue_push(msg_hash_to_str(MSG_RESET), 1, 120, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2245. core_reset();
  2246. #ifdef HAVE_CHEEVOS
  2247. #ifdef HAVE_GFX_WIDGETS
  2248. rcheevos_reset_game(dispwidget_get_ptr()->active);
  2249. #else
  2250. rcheevos_reset_game(false);
  2251. #endif
  2252. #endif
  2253. #ifdef HAVE_NETWORKING
  2254. netplay_driver_ctl(RARCH_NETPLAY_CTL_RESET, NULL);
  2255. #endif
  2256. /* Recalibrate frame delay target */
  2257. if (settings->bools.video_frame_delay_auto)
  2258. video_st->frame_delay_target = 0;
  2259. /* Run a few frames to blank core output while paused */
  2260. if (runloop_st->flags & RUNLOOP_FLAG_PAUSED)
  2261. {
  2262. runloop_st->flags &= ~RUNLOOP_FLAG_PAUSED;
  2263. runloop_st->run_frames_and_pause = 8;
  2264. }
  2265. #if HAVE_RUNAHEAD
  2266. command_event(CMD_EVENT_PREEMPT_RESET_BUFFER, NULL);
  2267. #endif
  2268. return false;
  2269. case CMD_EVENT_PLAY_REPLAY:
  2270. {
  2271. #ifdef HAVE_BSV_MOVIE
  2272. input_driver_state_t *input_st = input_state_get_ptr();
  2273. char replay_path[PATH_MAX_LENGTH];
  2274. bool res = true;
  2275. /* TODO: Consider extending the current replay if we start recording during a playback */
  2276. if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING)
  2277. res = false;
  2278. else if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_PLAYBACK)
  2279. res = movie_stop(input_st);
  2280. if (!runloop_get_current_replay_path(replay_path, sizeof(replay_path)))
  2281. res = false;
  2282. if (res)
  2283. res = movie_start_playback(input_st, replay_path);
  2284. if (!res)
  2285. {
  2286. const char *movie_fail_str =
  2287. msg_hash_to_str(MSG_FAILED_TO_LOAD_MOVIE_FILE);
  2288. runloop_msg_queue_push(movie_fail_str,
  2289. 1, 180, true,
  2290. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2291. RARCH_ERR("%s.\n", movie_fail_str);
  2292. }
  2293. return res;
  2294. #else
  2295. return false;
  2296. #endif
  2297. }
  2298. case CMD_EVENT_RECORD_REPLAY:
  2299. {
  2300. #ifdef HAVE_BSV_MOVIE
  2301. char replay_path[PATH_MAX_LENGTH];
  2302. bool res = true;
  2303. input_driver_state_t *input_st = input_state_get_ptr();
  2304. int replay_slot = settings->ints.replay_slot;
  2305. if (settings->bools.replay_auto_index)
  2306. replay_slot += 1;
  2307. /* TODO: Consider cloning and extending the current replay if we start recording during a recording */
  2308. if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_RECORDING)
  2309. res = false;
  2310. else if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_PLAYBACK)
  2311. res = movie_stop(input_st);
  2312. if (!runloop_get_replay_path(replay_path, sizeof(replay_path), replay_slot))
  2313. res = false;
  2314. if (res)
  2315. res = movie_start_record(input_st, replay_path);
  2316. if (res && settings->bools.replay_auto_index)
  2317. configuration_set_int(settings, settings->ints.replay_slot, replay_slot);
  2318. if (!res)
  2319. {
  2320. const char *movie_rec_fail_str =
  2321. msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD);
  2322. runloop_msg_queue_push(movie_rec_fail_str,
  2323. 1, 180, true,
  2324. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2325. RARCH_ERR("%s.\n", movie_rec_fail_str);
  2326. }
  2327. return res;
  2328. #else
  2329. break;
  2330. #endif
  2331. }
  2332. case CMD_EVENT_HALT_REPLAY:
  2333. #ifdef HAVE_BSV_MOVIE
  2334. movie_stop(input_state_get_ptr());
  2335. #endif
  2336. break;
  2337. case CMD_EVENT_SAVE_STATE:
  2338. case CMD_EVENT_SAVE_STATE_TO_RAM:
  2339. {
  2340. int state_slot = settings->ints.state_slot;
  2341. if (settings->bools.savestate_auto_index)
  2342. {
  2343. int new_state_slot = state_slot + 1;
  2344. configuration_set_int(settings, settings->ints.state_slot, new_state_slot);
  2345. }
  2346. }
  2347. if (!command_event_main_state(cmd))
  2348. return false;
  2349. break;
  2350. case CMD_EVENT_SAVE_STATE_DECREMENT:
  2351. {
  2352. int state_slot = settings->ints.state_slot;
  2353. /* Slot -1 is (auto) slot. */
  2354. if (state_slot >= 0)
  2355. {
  2356. int new_state_slot = state_slot - 1;
  2357. configuration_set_int(settings, settings->ints.state_slot, new_state_slot);
  2358. }
  2359. }
  2360. break;
  2361. case CMD_EVENT_SAVE_STATE_INCREMENT:
  2362. {
  2363. int new_state_slot = settings->ints.state_slot + 1;
  2364. configuration_set_int(settings, settings->ints.state_slot, new_state_slot);
  2365. }
  2366. break;
  2367. case CMD_EVENT_REPLAY_DECREMENT:
  2368. #ifdef HAVE_BSV_MOVIE
  2369. {
  2370. int slot = settings->ints.replay_slot;
  2371. /* Slot -1 is (auto) slot. */
  2372. if (slot >= 0)
  2373. {
  2374. int new_slot = slot - 1;
  2375. configuration_set_int(settings, settings->ints.replay_slot, new_slot);
  2376. }
  2377. }
  2378. #endif
  2379. break;
  2380. case CMD_EVENT_REPLAY_INCREMENT:
  2381. #ifdef HAVE_BSV_MOVIE
  2382. {
  2383. int new_slot = settings->ints.replay_slot + 1;
  2384. configuration_set_int(settings, settings->ints.replay_slot, new_slot);
  2385. }
  2386. #endif
  2387. break;
  2388. case CMD_EVENT_TAKE_SCREENSHOT:
  2389. #ifdef HAVE_SCREENSHOTS
  2390. {
  2391. const char *dir_screenshot = settings->paths.directory_screenshot;
  2392. if (!take_screenshot(dir_screenshot,
  2393. path_get(RARCH_PATH_BASENAME), false,
  2394. video_driver_cached_frame_has_valid_framebuffer(), false, true))
  2395. return false;
  2396. }
  2397. #endif
  2398. break;
  2399. case CMD_EVENT_UNLOAD_CORE:
  2400. {
  2401. bool load_dummy_core = data ? *(bool*)data : true;
  2402. content_ctx_info_t content_info = {0};
  2403. global_t *global = global_get_ptr();
  2404. rarch_system_info_t *sys_info = &runloop_st->system;
  2405. uint8_t flags = content_get_flags();
  2406. runloop_st->flags &= ~RUNLOOP_FLAG_CORE_RUNNING;
  2407. /* The platform that uses ram_state_save calls it when the content
  2408. * ends and writes it to a file */
  2409. ram_state_to_file();
  2410. /* Save last selected disk index, if required */
  2411. if (sys_info)
  2412. disk_control_save_image_index(&sys_info->disk_control);
  2413. runloop_runtime_log_deinit(runloop_st,
  2414. settings->bools.content_runtime_log,
  2415. settings->bools.content_runtime_log_aggregate,
  2416. settings->paths.directory_runtime_log,
  2417. settings->paths.directory_playlist);
  2418. command_event_save_auto_state(
  2419. settings->bools.savestate_auto_save,
  2420. runloop_st->current_core_type);
  2421. if ( (runloop_st->flags & RUNLOOP_FLAG_REMAPS_CORE_ACTIVE)
  2422. || (runloop_st->flags & RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE)
  2423. || (runloop_st->flags & RUNLOOP_FLAG_REMAPS_GAME_ACTIVE)
  2424. || !string_is_empty(runloop_st->name.remapfile)
  2425. )
  2426. {
  2427. input_remapping_deinit(settings->bools.remap_save_on_exit);
  2428. input_remapping_set_defaults(true);
  2429. }
  2430. else
  2431. input_remapping_restore_global_config(true);
  2432. #ifdef HAVE_CONFIGFILE
  2433. if (runloop_st->flags & RUNLOOP_FLAG_OVERRIDES_ACTIVE)
  2434. {
  2435. /* Reload the original config */
  2436. config_unload_override();
  2437. if (!settings->bools.video_fullscreen)
  2438. {
  2439. input_driver_state_t *input_st = input_state_get_ptr();
  2440. video_driver_show_mouse();
  2441. if (input_driver_ungrab_mouse())
  2442. input_st->flags &= ~INP_FLAG_GRAB_MOUSE_STATE;
  2443. }
  2444. }
  2445. #endif
  2446. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  2447. runloop_st->runtime_shader_preset_path[0] = '\0';
  2448. #endif
  2449. video_driver_restore_cached(settings);
  2450. if ( (flags & CONTENT_ST_FLAG_IS_INITED)
  2451. && load_dummy_core)
  2452. {
  2453. #ifdef HAVE_MENU
  2454. if ( ((settings->uints.quit_on_close_content ==
  2455. QUIT_ON_CLOSE_CONTENT_CLI)
  2456. && global->launched_from_cli)
  2457. || (settings->uints.quit_on_close_content ==
  2458. QUIT_ON_CLOSE_CONTENT_ENABLED)
  2459. )
  2460. command_event(CMD_EVENT_QUIT, NULL);
  2461. #endif
  2462. if (!task_push_start_dummy_core(&content_info))
  2463. return false;
  2464. }
  2465. #ifdef HAVE_PRESENCE
  2466. {
  2467. presence_userdata_t userdata;
  2468. userdata.status = PRESENCE_NETPLAY_NETPLAY_STOPPED;
  2469. command_event(CMD_EVENT_PRESENCE_UPDATE, &userdata);
  2470. userdata.status = PRESENCE_MENU;
  2471. command_event(CMD_EVENT_PRESENCE_UPDATE, &userdata);
  2472. }
  2473. #endif
  2474. #ifdef HAVE_DYNAMIC
  2475. path_clear(RARCH_PATH_CORE);
  2476. runloop_system_info_free();
  2477. #endif
  2478. {
  2479. audio_driver_state_t
  2480. *audio_st = audio_state_get_ptr();
  2481. audio_st->callback.callback = NULL;
  2482. audio_st->callback.set_state = NULL;
  2483. }
  2484. if (flags & CONTENT_ST_FLAG_IS_INITED)
  2485. {
  2486. runloop_st->subsystem_current_count = 0;
  2487. content_clear_subsystem();
  2488. }
  2489. }
  2490. break;
  2491. case CMD_EVENT_CLOSE_CONTENT:
  2492. #ifdef HAVE_MENU
  2493. /* Closing content via hotkey requires toggling menu
  2494. * and resetting the position later on to prevent
  2495. * going to empty Quick Menu */
  2496. if (!(menu_state_get_ptr()->flags & MENU_ST_FLAG_ALIVE))
  2497. {
  2498. menu_state_get_ptr()->flags |= MENU_ST_FLAG_PENDING_CLOSE_CONTENT;
  2499. command_event(CMD_EVENT_MENU_TOGGLE, NULL);
  2500. }
  2501. #else
  2502. command_event(CMD_EVENT_QUIT, NULL);
  2503. #endif
  2504. break;
  2505. case CMD_EVENT_QUIT:
  2506. if (!retroarch_main_quit())
  2507. return false;
  2508. break;
  2509. case CMD_EVENT_CHEEVOS_HARDCORE_MODE_TOGGLE:
  2510. #ifdef HAVE_CHEEVOS
  2511. rcheevos_toggle_hardcore_paused();
  2512. #endif
  2513. break;
  2514. case CMD_EVENT_REINIT_FROM_TOGGLE:
  2515. video_st->flags &= ~VIDEO_FLAG_FORCE_FULLSCREEN;
  2516. /* this fallthrough is on purpose, it should do
  2517. a CMD_EVENT_REINIT too */
  2518. case CMD_EVENT_REINIT:
  2519. command_event_reinit(
  2520. data ? *(const int*)data : DRIVERS_CMD_ALL);
  2521. /* Recalibrate frame delay target */
  2522. if (settings->bools.video_frame_delay_auto)
  2523. video_st->frame_delay_target = 0;
  2524. break;
  2525. case CMD_EVENT_CHEATS_APPLY:
  2526. #ifdef HAVE_CHEATS
  2527. cheat_manager_apply_cheats();
  2528. #endif
  2529. break;
  2530. case CMD_EVENT_REWIND_DEINIT:
  2531. #ifdef HAVE_REWIND
  2532. {
  2533. bool core_type_is_dummy = runloop_st->current_core_type == CORE_TYPE_DUMMY;
  2534. if (core_type_is_dummy)
  2535. return false;
  2536. state_manager_event_deinit(&runloop_st->rewind_st,
  2537. &runloop_st->current_core);
  2538. }
  2539. #endif
  2540. break;
  2541. case CMD_EVENT_REWIND_INIT:
  2542. #ifdef HAVE_REWIND
  2543. {
  2544. bool rewind_enable = settings->bools.rewind_enable;
  2545. size_t rewind_buf_size = settings->sizes.rewind_buffer_size;
  2546. bool core_type_is_dummy = runloop_st->current_core_type == CORE_TYPE_DUMMY;
  2547. if (core_type_is_dummy)
  2548. return false;
  2549. #ifdef HAVE_CHEEVOS
  2550. if (rcheevos_hardcore_active())
  2551. return false;
  2552. #endif
  2553. if (rewind_enable)
  2554. {
  2555. #ifdef HAVE_NETWORKING
  2556. /* Only enable state manager if netplay is not underway
  2557. TODO/FIXME: Add a setting for these tweaks */
  2558. if (!netplay_driver_ctl(
  2559. RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
  2560. #endif
  2561. {
  2562. state_manager_event_init(&runloop_st->rewind_st,
  2563. (unsigned)rewind_buf_size);
  2564. }
  2565. }
  2566. }
  2567. #endif
  2568. break;
  2569. case CMD_EVENT_REWIND_TOGGLE:
  2570. #ifdef HAVE_REWIND
  2571. {
  2572. bool rewind_enable = settings->bools.rewind_enable;
  2573. if (rewind_enable)
  2574. command_event(CMD_EVENT_REWIND_INIT, NULL);
  2575. else
  2576. command_event(CMD_EVENT_REWIND_DEINIT, NULL);
  2577. }
  2578. #endif
  2579. break;
  2580. case CMD_EVENT_AUTOSAVE_INIT:
  2581. #ifdef HAVE_THREADS
  2582. if (runloop_st->flags & RUNLOOP_FLAG_USE_SRAM)
  2583. autosave_deinit();
  2584. {
  2585. #ifdef HAVE_NETWORKING
  2586. unsigned autosave_interval =
  2587. settings->uints.autosave_interval;
  2588. /* Only enable state manager if netplay is not underway
  2589. TODO/FIXME: Add a setting for these tweaks */
  2590. if ( (autosave_interval != 0)
  2591. && !netplay_driver_ctl(
  2592. RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
  2593. #endif
  2594. {
  2595. if (autosave_init())
  2596. runloop_st->flags |= RUNLOOP_FLAG_AUTOSAVE;
  2597. else
  2598. runloop_st->flags &= ~RUNLOOP_FLAG_AUTOSAVE;
  2599. }
  2600. }
  2601. #endif
  2602. break;
  2603. case CMD_EVENT_AUDIO_STOP:
  2604. midi_driver_set_all_sounds_off();
  2605. if (!audio_driver_stop())
  2606. return false;
  2607. break;
  2608. case CMD_EVENT_AUDIO_START:
  2609. if (!audio_driver_start(runloop_st->flags &
  2610. RUNLOOP_FLAG_SHUTDOWN_INITIATED))
  2611. return false;
  2612. break;
  2613. case CMD_EVENT_AUDIO_MUTE_TOGGLE:
  2614. {
  2615. audio_driver_state_t
  2616. *audio_st = audio_state_get_ptr();
  2617. bool audio_mute_enable =
  2618. *(audio_get_bool_ptr(AUDIO_ACTION_MUTE_ENABLE));
  2619. const char *msg = !audio_mute_enable ?
  2620. msg_hash_to_str(MSG_AUDIO_MUTED):
  2621. msg_hash_to_str(MSG_AUDIO_UNMUTED);
  2622. audio_st->mute_enable =
  2623. !audio_st->mute_enable;
  2624. #if defined(HAVE_GFX_WIDGETS)
  2625. if (dispwidget_get_ptr()->active)
  2626. gfx_widget_volume_update_and_show(
  2627. settings->floats.audio_volume,
  2628. audio_st->mute_enable);
  2629. else
  2630. #endif
  2631. runloop_msg_queue_push(msg, 1, 180, true, NULL,
  2632. MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2633. }
  2634. break;
  2635. case CMD_EVENT_FPS_TOGGLE:
  2636. settings->bools.video_fps_show = !(settings->bools.video_fps_show);
  2637. break;
  2638. case CMD_EVENT_STATISTICS_TOGGLE:
  2639. settings->bools.video_statistics_show = !(settings->bools.video_statistics_show);
  2640. break;
  2641. case CMD_EVENT_OVERLAY_NEXT:
  2642. /* Switch to the next available overlay screen. */
  2643. #ifdef HAVE_OVERLAY
  2644. {
  2645. bool *check_rotation = (bool*)data;
  2646. video_driver_state_t
  2647. *video_st = video_state_get_ptr();
  2648. input_driver_state_t *input_st = input_state_get_ptr();
  2649. bool inp_overlay_auto_rotate = settings->bools.input_overlay_auto_rotate;
  2650. float input_overlay_opacity = settings->floats.input_overlay_opacity;
  2651. if (!input_st->overlay_ptr)
  2652. return false;
  2653. input_st->overlay_ptr->index = input_st->overlay_ptr->next_index;
  2654. input_st->overlay_ptr->active = &input_st->overlay_ptr->overlays[
  2655. input_st->overlay_ptr->index];
  2656. input_overlay_load_active(input_st->overlay_visibility,
  2657. input_st->overlay_ptr, input_overlay_opacity);
  2658. input_st->overlay_ptr->flags |= INPUT_OVERLAY_BLOCKED;
  2659. input_st->overlay_ptr->next_index = (unsigned)((input_st->overlay_ptr->index + 1) % input_st->overlay_ptr->size);
  2660. /* Check orientation, if required */
  2661. if (inp_overlay_auto_rotate)
  2662. if (check_rotation)
  2663. if (*check_rotation)
  2664. input_overlay_auto_rotate_(
  2665. video_st->width,
  2666. video_st->height,
  2667. settings->bools.input_overlay_enable,
  2668. input_st->overlay_ptr);
  2669. }
  2670. #endif
  2671. break;
  2672. case CMD_EVENT_OSK_TOGGLE:
  2673. {
  2674. input_driver_state_t *input_st = input_state_get_ptr();
  2675. if (input_st->flags & INP_FLAG_KB_LINEFEED_ENABLE)
  2676. input_st->flags &= ~INP_FLAG_KB_LINEFEED_ENABLE;
  2677. else
  2678. input_st->flags |= INP_FLAG_KB_LINEFEED_ENABLE;
  2679. }
  2680. break;
  2681. case CMD_EVENT_DSP_FILTER_INIT:
  2682. #ifdef HAVE_DSP_FILTER
  2683. {
  2684. const char *path_audio_dsp_plugin = settings->paths.path_audio_dsp_plugin;
  2685. audio_driver_dsp_filter_free();
  2686. if (string_is_empty(path_audio_dsp_plugin))
  2687. break;
  2688. if (!audio_driver_dsp_filter_init(path_audio_dsp_plugin))
  2689. {
  2690. RARCH_ERR("[DSP]: Failed to initialize DSP filter \"%s\".\n",
  2691. path_audio_dsp_plugin);
  2692. }
  2693. }
  2694. #endif
  2695. break;
  2696. case CMD_EVENT_RECORD_DEINIT:
  2697. recording_st->enable = false;
  2698. streaming_set_state(false);
  2699. if (!recording_deinit())
  2700. return false;
  2701. break;
  2702. case CMD_EVENT_RECORD_INIT:
  2703. recording_st->enable = true;
  2704. if (!recording_init())
  2705. {
  2706. command_event(CMD_EVENT_RECORD_DEINIT, NULL);
  2707. return false;
  2708. }
  2709. break;
  2710. case CMD_EVENT_HISTORY_DEINIT:
  2711. if (g_defaults.content_history)
  2712. {
  2713. playlist_write_file(g_defaults.content_history);
  2714. playlist_free(g_defaults.content_history);
  2715. }
  2716. g_defaults.content_history = NULL;
  2717. if (g_defaults.music_history)
  2718. {
  2719. playlist_write_file(g_defaults.music_history);
  2720. playlist_free(g_defaults.music_history);
  2721. }
  2722. g_defaults.music_history = NULL;
  2723. #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
  2724. if (g_defaults.video_history)
  2725. {
  2726. playlist_write_file(g_defaults.video_history);
  2727. playlist_free(g_defaults.video_history);
  2728. }
  2729. g_defaults.video_history = NULL;
  2730. #endif
  2731. #ifdef HAVE_IMAGEVIEWER
  2732. if (g_defaults.image_history)
  2733. {
  2734. playlist_write_file(g_defaults.image_history);
  2735. playlist_free(g_defaults.image_history);
  2736. }
  2737. g_defaults.image_history = NULL;
  2738. #endif
  2739. break;
  2740. case CMD_EVENT_HISTORY_INIT:
  2741. {
  2742. playlist_config_t playlist_config;
  2743. const char *_msg = NULL;
  2744. bool history_list_enable = settings->bools.history_list_enable;
  2745. const char *path_content_history = settings->paths.path_content_history;
  2746. const char *path_content_music_history = settings->paths.path_content_music_history;
  2747. #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
  2748. const char *path_content_video_history = settings->paths.path_content_video_history;
  2749. #endif
  2750. #ifdef HAVE_IMAGEVIEWER
  2751. const char *path_content_image_history = settings->paths.path_content_image_history;
  2752. #endif
  2753. playlist_config.capacity = settings->uints.content_history_size;
  2754. playlist_config.old_format = settings->bools.playlist_use_old_format;
  2755. playlist_config.compress = settings->bools.playlist_compression;
  2756. playlist_config.fuzzy_archive_match = settings->bools.playlist_fuzzy_archive_match;
  2757. /* don't use relative paths for content, music, video, and image histories */
  2758. playlist_config_set_base_content_directory(&playlist_config, NULL);
  2759. command_event(CMD_EVENT_HISTORY_DEINIT, NULL);
  2760. if (!history_list_enable)
  2761. return false;
  2762. _msg = msg_hash_to_str(MSG_LOADING_HISTORY_FILE);
  2763. /* Note: Sorting is disabled by default for
  2764. * all content history playlists */
  2765. RARCH_LOG("[Playlist]: %s: \"%s\".\n", _msg,
  2766. path_content_history);
  2767. playlist_config_set_path(&playlist_config, path_content_history);
  2768. g_defaults.content_history = playlist_init(&playlist_config);
  2769. playlist_set_sort_mode(
  2770. g_defaults.content_history, PLAYLIST_SORT_MODE_OFF);
  2771. RARCH_LOG("[Playlist]: %s: \"%s\".\n", _msg,
  2772. path_content_music_history);
  2773. playlist_config_set_path(&playlist_config, path_content_music_history);
  2774. g_defaults.music_history = playlist_init(&playlist_config);
  2775. playlist_set_sort_mode(
  2776. g_defaults.music_history, PLAYLIST_SORT_MODE_OFF);
  2777. #if defined(HAVE_FFMPEG) || defined(HAVE_MPV)
  2778. RARCH_LOG("[Playlist]: %s: \"%s\".\n", _msg,
  2779. path_content_video_history);
  2780. playlist_config_set_path(&playlist_config, path_content_video_history);
  2781. g_defaults.video_history = playlist_init(&playlist_config);
  2782. playlist_set_sort_mode(
  2783. g_defaults.video_history, PLAYLIST_SORT_MODE_OFF);
  2784. #endif
  2785. #ifdef HAVE_IMAGEVIEWER
  2786. RARCH_LOG("[Playlist]: %s: \"%s\".\n", _msg,
  2787. path_content_image_history);
  2788. playlist_config_set_path(&playlist_config, path_content_image_history);
  2789. g_defaults.image_history = playlist_init(&playlist_config);
  2790. playlist_set_sort_mode(
  2791. g_defaults.image_history, PLAYLIST_SORT_MODE_OFF);
  2792. #endif
  2793. }
  2794. break;
  2795. case CMD_EVENT_CORE_INFO_DEINIT:
  2796. core_info_deinit_list();
  2797. core_info_free_current_core();
  2798. break;
  2799. case CMD_EVENT_CORE_INFO_INIT:
  2800. {
  2801. char ext_name[255];
  2802. const char *dir_libretro = settings->paths.directory_libretro;
  2803. const char *path_libretro_info = settings->paths.path_libretro_info;
  2804. bool show_hidden_files = settings->bools.show_hidden_files;
  2805. bool core_info_cache_enable = settings->bools.core_info_cache_enable;
  2806. ext_name[0] = '\0';
  2807. command_event(CMD_EVENT_CORE_INFO_DEINIT, NULL);
  2808. if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name)))
  2809. return false;
  2810. if (!string_is_empty(dir_libretro))
  2811. {
  2812. bool cache_supported = false;
  2813. core_info_init_list(path_libretro_info,
  2814. dir_libretro,
  2815. ext_name,
  2816. show_hidden_files,
  2817. core_info_cache_enable,
  2818. &cache_supported);
  2819. /* If core info cache is enabled but cache
  2820. * functionality is unsupported (i.e. because
  2821. * the core info directory is on read-only
  2822. * storage), force-disable the setting to
  2823. * avoid repeated failures */
  2824. if (core_info_cache_enable && !cache_supported)
  2825. configuration_set_bool(settings,
  2826. settings->bools.core_info_cache_enable, false);
  2827. }
  2828. }
  2829. break;
  2830. case CMD_EVENT_CORE_DEINIT:
  2831. {
  2832. struct retro_hw_render_callback *hwr = NULL;
  2833. video_driver_state_t
  2834. *video_st = video_state_get_ptr();
  2835. rarch_system_info_t *sys_info = &runloop_st->system;
  2836. /* The platform that uses ram_state_save calls it when the content
  2837. * ends and writes it to a file */
  2838. ram_state_to_file();
  2839. /* Save last selected disk index, if required */
  2840. if (sys_info)
  2841. disk_control_save_image_index(&sys_info->disk_control);
  2842. runloop_runtime_log_deinit(runloop_st,
  2843. settings->bools.content_runtime_log,
  2844. settings->bools.content_runtime_log_aggregate,
  2845. settings->paths.directory_runtime_log,
  2846. settings->paths.directory_playlist);
  2847. content_reset_savestate_backups();
  2848. hwr = VIDEO_DRIVER_GET_HW_CONTEXT_INTERNAL(video_st);
  2849. #ifdef HAVE_CHEEVOS
  2850. rcheevos_unload();
  2851. #endif
  2852. runloop_event_deinit_core();
  2853. #ifdef HAVE_RUNAHEAD
  2854. /* If 'runahead_available' is false, then
  2855. * runahead is enabled by the user but an
  2856. * error occurred while the core was running
  2857. * (typically a save state issue). In this
  2858. * case we have to 'manually' reset the runahead
  2859. * runtime variables, otherwise runahead will
  2860. * remain disabled until the user restarts
  2861. * RetroArch */
  2862. if (!(runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_AVAILABLE))
  2863. runahead_clear_variables(runloop_st);
  2864. /* Deallocate preemptive frames */
  2865. preempt_deinit(runloop_st);
  2866. #endif
  2867. if (hwr)
  2868. memset(hwr, 0, sizeof(*hwr));
  2869. break;
  2870. }
  2871. case CMD_EVENT_CORE_INIT:
  2872. {
  2873. enum rarch_core_type *type = (enum rarch_core_type*)data;
  2874. rarch_system_info_t *sys_info = &runloop_st->system;
  2875. input_driver_state_t *input_st = input_state_get_ptr();
  2876. audio_driver_state_t *audio_st = audio_state_get_ptr();
  2877. content_reset_savestate_backups();
  2878. /* Ensure that disk control interface is reset */
  2879. if (sys_info)
  2880. disk_control_set_ext_callback(&sys_info->disk_control, NULL);
  2881. /* Ensure that audio callback interface is reset */
  2882. audio_st->callback.callback = NULL;
  2883. audio_st->callback.set_state = NULL;
  2884. if (!type || !runloop_event_init_core(settings, input_st, *type,
  2885. p_rarch->dir_savefile, p_rarch->dir_savestate))
  2886. {
  2887. /* If core failed to initialise, audio callback
  2888. * interface may be assigned invalid function
  2889. * pointers -> ensure it is reset */
  2890. audio_st->callback.callback = NULL;
  2891. audio_st->callback.set_state = NULL;
  2892. return false;
  2893. }
  2894. }
  2895. break;
  2896. case CMD_EVENT_VIDEO_APPLY_STATE_CHANGES:
  2897. video_driver_apply_state_changes();
  2898. break;
  2899. case CMD_EVENT_VIDEO_SET_BLOCKING_STATE:
  2900. {
  2901. bool adaptive_vsync = settings->bools.video_adaptive_vsync;
  2902. unsigned swap_interval = runloop_get_video_swap_interval(
  2903. settings->uints.video_swap_interval);
  2904. video_driver_state_t
  2905. *video_st = video_state_get_ptr();
  2906. if (video_st->current_video->set_nonblock_state)
  2907. video_st->current_video->set_nonblock_state(
  2908. video_st->data, false,
  2909. video_driver_test_all_flags(
  2910. GFX_CTX_FLAGS_ADAPTIVE_VSYNC) &&
  2911. adaptive_vsync, swap_interval);
  2912. }
  2913. break;
  2914. case CMD_EVENT_VIDEO_SET_ASPECT_RATIO:
  2915. video_driver_set_aspect_ratio();
  2916. break;
  2917. case CMD_EVENT_OVERLAY_SET_SCALE_FACTOR:
  2918. #ifdef HAVE_OVERLAY
  2919. {
  2920. overlay_layout_desc_t layout_desc;
  2921. video_driver_state_t
  2922. *video_st = video_state_get_ptr();
  2923. input_driver_state_t *input_st = input_state_get_ptr();
  2924. layout_desc.scale_landscape = settings->floats.input_overlay_scale_landscape;
  2925. layout_desc.aspect_adjust_landscape = settings->floats.input_overlay_aspect_adjust_landscape;
  2926. layout_desc.x_separation_landscape = settings->floats.input_overlay_x_separation_landscape;
  2927. layout_desc.y_separation_landscape = settings->floats.input_overlay_y_separation_landscape;
  2928. layout_desc.x_offset_landscape = settings->floats.input_overlay_x_offset_landscape;
  2929. layout_desc.y_offset_landscape = settings->floats.input_overlay_y_offset_landscape;
  2930. layout_desc.scale_portrait = settings->floats.input_overlay_scale_portrait;
  2931. layout_desc.aspect_adjust_portrait = settings->floats.input_overlay_aspect_adjust_portrait;
  2932. layout_desc.x_separation_portrait = settings->floats.input_overlay_x_separation_portrait;
  2933. layout_desc.y_separation_portrait = settings->floats.input_overlay_y_separation_portrait;
  2934. layout_desc.x_offset_portrait = settings->floats.input_overlay_x_offset_portrait;
  2935. layout_desc.y_offset_portrait = settings->floats.input_overlay_y_offset_portrait;
  2936. layout_desc.touch_scale = (float)settings->uints.input_touch_scale;
  2937. layout_desc.auto_scale = settings->bools.input_overlay_auto_scale;
  2938. input_overlay_set_scale_factor(input_st->overlay_ptr,
  2939. &layout_desc,
  2940. video_st->width,
  2941. video_st->height);
  2942. }
  2943. #endif
  2944. break;
  2945. case CMD_EVENT_OVERLAY_SET_ALPHA_MOD:
  2946. /* Sets a modulating factor for alpha channel. Default is 1.0.
  2947. * The alpha factor is applied for all overlays. */
  2948. #ifdef HAVE_OVERLAY
  2949. {
  2950. float input_overlay_opacity = settings->floats.input_overlay_opacity;
  2951. input_driver_state_t *input_st = input_state_get_ptr();
  2952. input_overlay_set_alpha_mod(input_st->overlay_visibility,
  2953. input_st->overlay_ptr, input_overlay_opacity);
  2954. }
  2955. #endif
  2956. break;
  2957. case CMD_EVENT_OVERLAY_SET_EIGHTWAY_DIAGONAL_SENSITIVITY:
  2958. #ifdef HAVE_OVERLAY
  2959. input_overlay_set_eightway_diagonal_sensitivity();
  2960. #endif
  2961. break;
  2962. case CMD_EVENT_AUDIO_REINIT:
  2963. driver_uninit(DRIVER_AUDIO_MASK);
  2964. drivers_init(settings, DRIVER_AUDIO_MASK, verbosity_is_enabled());
  2965. #if defined(HAVE_AUDIOMIXER)
  2966. audio_driver_load_system_sounds();
  2967. #endif
  2968. break;
  2969. case CMD_EVENT_SHUTDOWN:
  2970. #if defined(__linux__) && !defined(ANDROID)
  2971. if (settings->bools.config_save_on_exit)
  2972. {
  2973. runloop_msg_queue_push(msg_hash_to_str(MSG_VALUE_SHUTTING_DOWN), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2974. command_event(CMD_EVENT_MENU_SAVE_CURRENT_CONFIG, NULL);
  2975. }
  2976. #ifdef HAVE_LAKKA
  2977. system("(sleep 1 && shutdown -P now) & disown");
  2978. #else
  2979. command_event(CMD_EVENT_QUIT, NULL);
  2980. system("shutdown -P now");
  2981. #endif /* HAVE_LAKKA */
  2982. #endif
  2983. break;
  2984. case CMD_EVENT_REBOOT:
  2985. #if defined(__linux__) && !defined(ANDROID)
  2986. if (settings->bools.config_save_on_exit)
  2987. {
  2988. runloop_msg_queue_push(msg_hash_to_str(MSG_VALUE_REBOOTING), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  2989. command_event(CMD_EVENT_MENU_SAVE_CURRENT_CONFIG, NULL);
  2990. }
  2991. #ifdef HAVE_LAKKA
  2992. system("(sleep 1 && shutdown -r now) & disown");
  2993. #else
  2994. command_event(CMD_EVENT_QUIT, NULL);
  2995. system("shutdown -r now");
  2996. #endif /* HAVE_LAKKA */
  2997. #endif
  2998. break;
  2999. case CMD_EVENT_RESUME:
  3000. #ifdef HAVE_MENU
  3001. retroarch_menu_running_finished(false);
  3002. #endif
  3003. if (uico_st->flags & UICO_ST_FLAG_IS_ON_FOREGROUND)
  3004. {
  3005. #ifdef HAVE_QT
  3006. bool desktop_menu_enable = settings->bools.desktop_menu_enable;
  3007. bool ui_companion_toggle = settings->bools.ui_companion_toggle;
  3008. #else
  3009. bool desktop_menu_enable = false;
  3010. bool ui_companion_toggle = false;
  3011. #endif
  3012. ui_companion_driver_toggle(desktop_menu_enable,
  3013. ui_companion_toggle, false);
  3014. }
  3015. break;
  3016. case CMD_EVENT_ADD_TO_FAVORITES:
  3017. {
  3018. struct string_list *str_list = (struct string_list*)data;
  3019. /* Check whether favourties playlist is at capacity */
  3020. if (playlist_size(g_defaults.content_favorites) >=
  3021. playlist_capacity(g_defaults.content_favorites))
  3022. {
  3023. runloop_msg_queue_push(
  3024. msg_hash_to_str(MSG_ADD_TO_FAVORITES_FAILED), 1, 180, true, NULL,
  3025. MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_ERROR);
  3026. return false;
  3027. }
  3028. if (str_list)
  3029. {
  3030. if (str_list->size >= 6)
  3031. {
  3032. struct playlist_entry entry = {0};
  3033. bool playlist_sort_alphabetical = settings->bools.playlist_sort_alphabetical;
  3034. entry.path = str_list->elems[0].data; /* content_path */
  3035. entry.label = str_list->elems[1].data; /* content_label */
  3036. entry.core_path = str_list->elems[2].data; /* core_path */
  3037. entry.core_name = str_list->elems[3].data; /* core_name */
  3038. entry.crc32 = str_list->elems[4].data; /* crc32 */
  3039. entry.db_name = str_list->elems[5].data; /* db_name */
  3040. /* Write playlist entry */
  3041. if (playlist_push(g_defaults.content_favorites, &entry))
  3042. {
  3043. enum playlist_sort_mode current_sort_mode =
  3044. playlist_get_sort_mode(g_defaults.content_favorites);
  3045. /* New addition - need to resort if option is enabled */
  3046. if ((playlist_sort_alphabetical && (current_sort_mode == PLAYLIST_SORT_MODE_DEFAULT)) ||
  3047. (current_sort_mode == PLAYLIST_SORT_MODE_ALPHABETICAL))
  3048. playlist_qsort(g_defaults.content_favorites);
  3049. playlist_write_file(g_defaults.content_favorites);
  3050. runloop_msg_queue_push(msg_hash_to_str(MSG_ADDED_TO_FAVORITES), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3051. }
  3052. }
  3053. }
  3054. break;
  3055. }
  3056. case CMD_EVENT_RESET_CORE_ASSOCIATION:
  3057. {
  3058. const char *core_name = "DETECT";
  3059. const char *core_path = "DETECT";
  3060. size_t *playlist_index = (size_t*)data;
  3061. struct playlist_entry entry = {0};
  3062. unsigned i = 0;
  3063. #ifdef HAVE_MENU
  3064. struct menu_state *menu_st = menu_state_get_ptr();
  3065. #endif
  3066. /* the update function reads our entry as const,
  3067. * so these casts are safe */
  3068. entry.core_path = (char*)core_path;
  3069. entry.core_name = (char*)core_name;
  3070. command_playlist_update_write(
  3071. NULL, *playlist_index, &entry);
  3072. #ifdef HAVE_MENU
  3073. /* Update playlist metadata */
  3074. if ( menu_st->driver_ctx
  3075. && menu_st->driver_ctx->refresh_thumbnail_image)
  3076. menu_st->driver_ctx->refresh_thumbnail_image(
  3077. menu_st->userdata, i);
  3078. #endif
  3079. runloop_msg_queue_push(msg_hash_to_str(MSG_RESET_CORE_ASSOCIATION), 1, 180, true, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3080. break;
  3081. }
  3082. case CMD_EVENT_RESTART_RETROARCH:
  3083. if (!frontend_driver_set_fork(FRONTEND_FORK_RESTART))
  3084. return false;
  3085. #ifndef HAVE_DYNAMIC
  3086. command_event(CMD_EVENT_QUIT, NULL);
  3087. #endif
  3088. break;
  3089. case CMD_EVENT_MENU_RESET_TO_DEFAULT_CONFIG:
  3090. config_set_defaults(global_get_ptr());
  3091. break;
  3092. case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG:
  3093. #if !defined(HAVE_DYNAMIC)
  3094. config_save_file_salamander();
  3095. #endif
  3096. #ifdef HAVE_CONFIGFILE
  3097. command_event_save_current_config(OVERRIDE_NONE);
  3098. #endif
  3099. break;
  3100. case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_CORE:
  3101. #ifdef HAVE_CONFIGFILE
  3102. command_event_save_current_config(OVERRIDE_CORE);
  3103. #endif
  3104. break;
  3105. case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR:
  3106. #ifdef HAVE_CONFIGFILE
  3107. command_event_save_current_config(OVERRIDE_CONTENT_DIR);
  3108. #endif
  3109. break;
  3110. case CMD_EVENT_MENU_SAVE_CURRENT_CONFIG_OVERRIDE_GAME:
  3111. #ifdef HAVE_CONFIGFILE
  3112. command_event_save_current_config(OVERRIDE_GAME);
  3113. #endif
  3114. break;
  3115. case CMD_EVENT_MENU_REMOVE_CURRENT_CONFIG_OVERRIDE_CORE:
  3116. #ifdef HAVE_CONFIGFILE
  3117. command_event_remove_current_config(OVERRIDE_CORE);
  3118. #endif
  3119. break;
  3120. case CMD_EVENT_MENU_REMOVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR:
  3121. #ifdef HAVE_CONFIGFILE
  3122. command_event_remove_current_config(OVERRIDE_CONTENT_DIR);
  3123. #endif
  3124. break;
  3125. case CMD_EVENT_MENU_REMOVE_CURRENT_CONFIG_OVERRIDE_GAME:
  3126. #ifdef HAVE_CONFIGFILE
  3127. command_event_remove_current_config(OVERRIDE_GAME);
  3128. #endif
  3129. break;
  3130. case CMD_EVENT_MENU_SAVE_CONFIG:
  3131. #ifdef HAVE_CONFIGFILE
  3132. if (!command_event_save_core_config(
  3133. settings->paths.directory_menu_config,
  3134. path_get(RARCH_PATH_CONFIG)))
  3135. return false;
  3136. #endif
  3137. break;
  3138. case CMD_EVENT_SHADER_PRESET_LOADED:
  3139. ui_companion_event_command(cmd);
  3140. break;
  3141. case CMD_EVENT_SHADERS_APPLY_CHANGES:
  3142. #ifdef HAVE_MENU
  3143. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  3144. menu_shader_manager_apply_changes(menu_shader_get(),
  3145. settings->paths.directory_video_shader,
  3146. settings->paths.directory_menu_config
  3147. );
  3148. #endif
  3149. #endif
  3150. ui_companion_event_command(cmd);
  3151. break;
  3152. case CMD_EVENT_PAUSE_TOGGLE:
  3153. {
  3154. bool paused = runloop_st->flags & RUNLOOP_FLAG_PAUSED;
  3155. #ifdef HAVE_ACCESSIBILITY
  3156. bool accessibility_enable
  3157. = settings->bools.accessibility_enable;
  3158. unsigned accessibility_narrator_speech_speed
  3159. = settings->uints.accessibility_narrator_speech_speed;
  3160. #endif
  3161. #ifdef HAVE_NETWORKING
  3162. if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL))
  3163. break;
  3164. #endif
  3165. paused = !paused;
  3166. #ifdef HAVE_ACCESSIBILITY
  3167. if (is_accessibility_enabled(
  3168. accessibility_enable,
  3169. access_st->enabled))
  3170. {
  3171. if (paused)
  3172. accessibility_speak_priority(
  3173. accessibility_enable,
  3174. accessibility_narrator_speech_speed,
  3175. (char*)msg_hash_to_str(MSG_PAUSED), 10);
  3176. else
  3177. accessibility_speak_priority(
  3178. accessibility_enable,
  3179. accessibility_narrator_speech_speed,
  3180. (char*)msg_hash_to_str(MSG_UNPAUSED), 10);
  3181. }
  3182. #endif
  3183. if (paused)
  3184. runloop_st->flags |= RUNLOOP_FLAG_PAUSED;
  3185. else
  3186. runloop_st->flags &= ~RUNLOOP_FLAG_PAUSED;
  3187. runloop_pause_checks();
  3188. }
  3189. break;
  3190. case CMD_EVENT_UNPAUSE:
  3191. #ifdef HAVE_NETWORKING
  3192. if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL))
  3193. break;
  3194. #endif
  3195. runloop_st->flags &= ~RUNLOOP_FLAG_PAUSED;
  3196. runloop_pause_checks();
  3197. break;
  3198. case CMD_EVENT_PAUSE:
  3199. #ifdef HAVE_NETWORKING
  3200. if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL))
  3201. break;
  3202. #endif
  3203. runloop_st->flags |= RUNLOOP_FLAG_PAUSED;
  3204. runloop_pause_checks();
  3205. break;
  3206. case CMD_EVENT_MENU_PAUSE_LIBRETRO:
  3207. #ifdef HAVE_MENU
  3208. if (menu_st->flags & MENU_ST_FLAG_ALIVE)
  3209. {
  3210. #ifdef HAVE_NETWORKING
  3211. bool menu_pause_libretro = settings->bools.menu_pause_libretro &&
  3212. netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL);
  3213. #else
  3214. bool menu_pause_libretro = settings->bools.menu_pause_libretro;
  3215. #endif
  3216. if (menu_pause_libretro)
  3217. command_event(CMD_EVENT_AUDIO_STOP, NULL);
  3218. else
  3219. command_event(CMD_EVENT_AUDIO_START, NULL);
  3220. }
  3221. else
  3222. {
  3223. #ifdef HAVE_NETWORKING
  3224. bool menu_pause_libretro = settings->bools.menu_pause_libretro &&
  3225. netplay_driver_ctl(RARCH_NETPLAY_CTL_ALLOW_PAUSE, NULL);
  3226. #else
  3227. bool menu_pause_libretro = settings->bools.menu_pause_libretro;
  3228. #endif
  3229. if (menu_pause_libretro)
  3230. command_event(CMD_EVENT_AUDIO_START, NULL);
  3231. }
  3232. #endif
  3233. break;
  3234. #ifdef HAVE_NETWORKING
  3235. case CMD_EVENT_NETPLAY_PING_TOGGLE:
  3236. settings->bools.netplay_ping_show =
  3237. !settings->bools.netplay_ping_show;
  3238. break;
  3239. case CMD_EVENT_NETPLAY_GAME_WATCH:
  3240. netplay_driver_ctl(RARCH_NETPLAY_CTL_GAME_WATCH, NULL);
  3241. break;
  3242. case CMD_EVENT_NETPLAY_PLAYER_CHAT:
  3243. netplay_driver_ctl(RARCH_NETPLAY_CTL_PLAYER_CHAT, NULL);
  3244. break;
  3245. case CMD_EVENT_NETPLAY_FADE_CHAT_TOGGLE:
  3246. settings->bools.netplay_fade_chat =
  3247. !settings->bools.netplay_fade_chat;
  3248. break;
  3249. case CMD_EVENT_NETPLAY_DEINIT:
  3250. deinit_netplay();
  3251. break;
  3252. case CMD_EVENT_NETWORK_INIT:
  3253. network_init();
  3254. break;
  3255. /* init netplay manually */
  3256. case CMD_EVENT_NETPLAY_INIT:
  3257. {
  3258. char tmp_netplay_server[256];
  3259. char tmp_netplay_session[sizeof(tmp_netplay_server)];
  3260. char *netplay_server = NULL;
  3261. char *netplay_session = NULL;
  3262. unsigned netplay_port = 0;
  3263. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3264. tmp_netplay_server[0] = '\0';
  3265. tmp_netplay_session[0] = '\0';
  3266. if (netplay_decode_hostname(p_rarch->connect_host,
  3267. tmp_netplay_server, &netplay_port, tmp_netplay_session,
  3268. sizeof(tmp_netplay_server)))
  3269. {
  3270. netplay_server = tmp_netplay_server;
  3271. netplay_session = tmp_netplay_session;
  3272. }
  3273. if (p_rarch->connect_host)
  3274. {
  3275. free(p_rarch->connect_host);
  3276. p_rarch->connect_host = NULL;
  3277. }
  3278. if (string_is_empty(netplay_server))
  3279. netplay_server = settings->paths.netplay_server;
  3280. if (!netplay_port)
  3281. netplay_port = settings->uints.netplay_port;
  3282. if (!init_netplay(netplay_server, netplay_port, netplay_session))
  3283. {
  3284. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3285. return false;
  3286. }
  3287. /* Disable rewind & SRAM autosave if it was enabled
  3288. * TODO/FIXME: Add a setting for these tweaks */
  3289. #ifdef HAVE_REWIND
  3290. state_manager_event_deinit(&runloop_st->rewind_st,
  3291. &runloop_st->current_core);
  3292. #endif
  3293. #ifdef HAVE_THREADS
  3294. autosave_deinit();
  3295. #endif
  3296. }
  3297. break;
  3298. /* Initialize netplay via lobby when content is loaded */
  3299. case CMD_EVENT_NETPLAY_INIT_DIRECT:
  3300. {
  3301. char netplay_server[256];
  3302. char netplay_session[sizeof(netplay_server)];
  3303. unsigned netplay_port = 0;
  3304. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3305. netplay_server[0] = '\0';
  3306. netplay_session[0] = '\0';
  3307. netplay_decode_hostname((char*) data, netplay_server,
  3308. &netplay_port, netplay_session, sizeof(netplay_server));
  3309. if (!netplay_port)
  3310. netplay_port = settings->uints.netplay_port;
  3311. RARCH_LOG("[Netplay]: Connecting to %s|%d (direct)\n",
  3312. netplay_server, netplay_port);
  3313. if (!init_netplay(netplay_server, netplay_port, netplay_session))
  3314. {
  3315. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3316. return false;
  3317. }
  3318. /* Disable rewind if it was enabled
  3319. TODO/FIXME: Add a setting for these tweaks */
  3320. #ifdef HAVE_REWIND
  3321. state_manager_event_deinit(&runloop_st->rewind_st,
  3322. &runloop_st->current_core);
  3323. #endif
  3324. #ifdef HAVE_THREADS
  3325. autosave_deinit();
  3326. #endif
  3327. }
  3328. break;
  3329. /* init netplay via lobby when content is not loaded */
  3330. case CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED:
  3331. {
  3332. char netplay_server[256];
  3333. char netplay_session[sizeof(netplay_server)];
  3334. unsigned netplay_port = 0;
  3335. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3336. netplay_server[0] = '\0';
  3337. netplay_session[0] = '\0';
  3338. netplay_decode_hostname((char*) data, netplay_server,
  3339. &netplay_port, netplay_session, sizeof(netplay_server));
  3340. if (!netplay_port)
  3341. netplay_port = settings->uints.netplay_port;
  3342. RARCH_LOG("[Netplay]: Connecting to %s|%d (deferred)\n",
  3343. netplay_server, netplay_port);
  3344. if (!init_netplay_deferred(netplay_server, netplay_port, netplay_session))
  3345. {
  3346. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3347. return false;
  3348. }
  3349. /* Disable rewind if it was enabled
  3350. * TODO/FIXME: Add a setting for these tweaks */
  3351. #ifdef HAVE_REWIND
  3352. state_manager_event_deinit(&runloop_st->rewind_st,
  3353. &runloop_st->current_core);
  3354. #endif
  3355. #ifdef HAVE_THREADS
  3356. autosave_deinit();
  3357. #endif
  3358. }
  3359. break;
  3360. case CMD_EVENT_NETPLAY_ENABLE_HOST:
  3361. {
  3362. if (!task_push_netplay_content_reload(NULL))
  3363. {
  3364. #ifdef HAVE_DYNAMIC
  3365. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  3366. netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL);
  3367. runloop_msg_queue_push(
  3368. msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NETPLAY_START_WHEN_LOADED),
  3369. 1, 480, true, NULL,
  3370. MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3371. #else
  3372. runloop_msg_queue_push(
  3373. msg_hash_to_str(MSG_NETPLAY_NEED_CONTENT_LOADED),
  3374. 1, 480, true, NULL,
  3375. MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3376. #endif
  3377. return false;
  3378. }
  3379. #if HAVE_RUNAHEAD
  3380. /* Deinit preemptive frames; not compatible with netplay */
  3381. preempt_deinit(runloop_st);
  3382. #endif
  3383. }
  3384. break;
  3385. case CMD_EVENT_NETPLAY_DISCONNECT:
  3386. {
  3387. bool rewind_enable = settings->bools.rewind_enable;
  3388. unsigned autosave_interval = settings->uints.autosave_interval;
  3389. netplay_driver_ctl(RARCH_NETPLAY_CTL_DISCONNECT, NULL);
  3390. netplay_driver_ctl(RARCH_NETPLAY_CTL_DISABLE, NULL);
  3391. #ifdef HAVE_REWIND
  3392. /* Re-enable rewind if it was enabled
  3393. * TODO/FIXME: Add a setting for these tweaks */
  3394. if (rewind_enable)
  3395. command_event(CMD_EVENT_REWIND_INIT, NULL);
  3396. #endif
  3397. if (autosave_interval != 0)
  3398. command_event(CMD_EVENT_AUTOSAVE_INIT, NULL);
  3399. }
  3400. break;
  3401. case CMD_EVENT_NETPLAY_HOST_TOGGLE:
  3402. if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
  3403. {
  3404. if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_SERVER, NULL) ||
  3405. netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_CONNECTED, NULL))
  3406. command_event(CMD_EVENT_NETPLAY_DISCONNECT, NULL);
  3407. }
  3408. else
  3409. command_event(CMD_EVENT_NETPLAY_ENABLE_HOST, NULL);
  3410. break;
  3411. #else
  3412. case CMD_EVENT_NETPLAY_DEINIT:
  3413. case CMD_EVENT_NETWORK_INIT:
  3414. case CMD_EVENT_NETPLAY_INIT:
  3415. case CMD_EVENT_NETPLAY_INIT_DIRECT:
  3416. case CMD_EVENT_NETPLAY_INIT_DIRECT_DEFERRED:
  3417. case CMD_EVENT_NETPLAY_HOST_TOGGLE:
  3418. case CMD_EVENT_NETPLAY_DISCONNECT:
  3419. case CMD_EVENT_NETPLAY_ENABLE_HOST:
  3420. case CMD_EVENT_NETPLAY_PING_TOGGLE:
  3421. case CMD_EVENT_NETPLAY_GAME_WATCH:
  3422. case CMD_EVENT_NETPLAY_PLAYER_CHAT:
  3423. case CMD_EVENT_NETPLAY_FADE_CHAT_TOGGLE:
  3424. return false;
  3425. #endif
  3426. case CMD_EVENT_FULLSCREEN_TOGGLE:
  3427. {
  3428. audio_driver_state_t
  3429. *audio_st = audio_state_get_ptr();
  3430. input_driver_state_t
  3431. *input_st = input_state_get_ptr();
  3432. bool *userdata = (bool*)data;
  3433. bool video_fullscreen = settings->bools.video_fullscreen;
  3434. bool ra_is_forced_fs = video_st->flags &
  3435. VIDEO_FLAG_FORCE_FULLSCREEN;
  3436. bool new_fullscreen_state = !video_fullscreen && !ra_is_forced_fs;
  3437. if (!video_driver_has_windowed())
  3438. return false;
  3439. audio_st->flags |= AUDIO_FLAG_SUSPENDED;
  3440. video_st->flags |= VIDEO_FLAG_IS_SWITCHING_DISPLAY_MODE;
  3441. /* we toggled manually, write the new value to settings */
  3442. configuration_set_bool(settings, settings->bools.video_fullscreen,
  3443. new_fullscreen_state);
  3444. /* Need to grab this setting's value again */
  3445. video_fullscreen = new_fullscreen_state;
  3446. /* we toggled manually, the CLI arg is irrelevant now */
  3447. if (ra_is_forced_fs)
  3448. video_st->flags &= ~VIDEO_FLAG_FORCE_FULLSCREEN;
  3449. /* If we go fullscreen we drop all drivers and
  3450. * reinitialize to be safe. */
  3451. command_event(CMD_EVENT_REINIT, NULL);
  3452. if (video_fullscreen)
  3453. {
  3454. video_driver_hide_mouse();
  3455. if (!settings->bools.video_windowed_fullscreen)
  3456. if (input_driver_grab_mouse())
  3457. input_st->flags |= INP_FLAG_GRAB_MOUSE_STATE;
  3458. }
  3459. else
  3460. {
  3461. video_driver_show_mouse();
  3462. if (!settings->bools.video_windowed_fullscreen)
  3463. if (input_driver_ungrab_mouse())
  3464. input_st->flags &= ~INP_FLAG_GRAB_MOUSE_STATE;
  3465. }
  3466. video_st->flags &= ~VIDEO_FLAG_IS_SWITCHING_DISPLAY_MODE;
  3467. audio_st->flags &= ~AUDIO_FLAG_SUSPENDED;
  3468. if (userdata && *userdata == true)
  3469. video_driver_cached_frame();
  3470. }
  3471. break;
  3472. case CMD_EVENT_DISK_APPEND_IMAGE:
  3473. {
  3474. const char *path = (const char*)data;
  3475. rarch_system_info_t *sys_info = &runloop_st->system;
  3476. if (string_is_empty(path) || !sys_info)
  3477. return false;
  3478. if (disk_control_enabled(&sys_info->disk_control))
  3479. {
  3480. #if defined(HAVE_MENU)
  3481. struct menu_state *menu_st = menu_state_get_ptr();
  3482. /* Get initial disk eject state */
  3483. bool initial_disk_ejected = disk_control_get_eject_state(&sys_info->disk_control);
  3484. #endif
  3485. /* Append disk image */
  3486. bool success =
  3487. command_event_disk_control_append_image(path);
  3488. #if defined(HAVE_MENU)
  3489. /* Appending a disk image may or may not affect
  3490. * the disk tray eject status. If status has changed,
  3491. * must refresh the disk options menu */
  3492. if (initial_disk_ejected != disk_control_get_eject_state(
  3493. &sys_info->disk_control))
  3494. menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH
  3495. | MENU_ST_FLAG_PREVENT_POPULATE;
  3496. #endif
  3497. return success;
  3498. }
  3499. else
  3500. runloop_msg_queue_push(
  3501. msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
  3502. 1, 120, true,
  3503. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3504. }
  3505. break;
  3506. case CMD_EVENT_DISK_EJECT_TOGGLE:
  3507. {
  3508. rarch_system_info_t *sys_info = &runloop_st->system;
  3509. if (!sys_info)
  3510. return false;
  3511. if (disk_control_enabled(&sys_info->disk_control))
  3512. {
  3513. bool *show_msg = (bool*)data;
  3514. bool eject = !disk_control_get_eject_state(
  3515. &sys_info->disk_control);
  3516. bool verbose = true;
  3517. #if defined(HAVE_MENU)
  3518. struct menu_state *menu_st = menu_state_get_ptr();
  3519. #endif
  3520. if (show_msg)
  3521. verbose = *show_msg;
  3522. disk_control_set_eject_state(
  3523. &sys_info->disk_control, eject, verbose);
  3524. #if defined(HAVE_MENU)
  3525. /* It is necessary to refresh the disk options
  3526. * menu when toggling the tray state */
  3527. menu_st->flags |= MENU_ST_FLAG_ENTRIES_NEED_REFRESH
  3528. | MENU_ST_FLAG_PREVENT_POPULATE;
  3529. #endif
  3530. }
  3531. else
  3532. runloop_msg_queue_push(
  3533. msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
  3534. 1, 120, true,
  3535. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3536. }
  3537. break;
  3538. case CMD_EVENT_DISK_NEXT:
  3539. {
  3540. rarch_system_info_t *sys_info = &runloop_st->system;
  3541. if (!sys_info)
  3542. return false;
  3543. if (disk_control_enabled(&sys_info->disk_control))
  3544. {
  3545. bool *show_msg = (bool*)data;
  3546. bool verbose = true;
  3547. if (show_msg)
  3548. verbose = *show_msg;
  3549. disk_control_set_index_next(&sys_info->disk_control, verbose);
  3550. }
  3551. else
  3552. runloop_msg_queue_push(
  3553. msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
  3554. 1, 120, true,
  3555. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3556. }
  3557. break;
  3558. case CMD_EVENT_DISK_PREV:
  3559. {
  3560. rarch_system_info_t *sys_info = &runloop_st->system;
  3561. if (!sys_info)
  3562. return false;
  3563. if (disk_control_enabled(&sys_info->disk_control))
  3564. {
  3565. bool *show_msg = (bool*)data;
  3566. bool verbose = true;
  3567. if (show_msg)
  3568. verbose = *show_msg;
  3569. disk_control_set_index_prev(&sys_info->disk_control, verbose);
  3570. }
  3571. else
  3572. runloop_msg_queue_push(
  3573. msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
  3574. 1, 120, true,
  3575. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3576. }
  3577. break;
  3578. case CMD_EVENT_DISK_INDEX:
  3579. {
  3580. rarch_system_info_t *sys_info = &runloop_st->system;
  3581. unsigned *index = (unsigned*)data;
  3582. if (!sys_info || !index)
  3583. return false;
  3584. /* Note: Menu itself provides visual feedback - no
  3585. * need to print info message to screen */
  3586. if (disk_control_enabled(&sys_info->disk_control))
  3587. disk_control_set_index(&sys_info->disk_control, *index, false);
  3588. else
  3589. runloop_msg_queue_push(
  3590. msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
  3591. 1, 120, true,
  3592. NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3593. }
  3594. break;
  3595. case CMD_EVENT_RUMBLE_STOP:
  3596. {
  3597. unsigned i;
  3598. for (i = 0; i < MAX_USERS; i++)
  3599. {
  3600. unsigned joy_idx = settings->uints.input_joypad_index[i];
  3601. input_driver_set_rumble(i, joy_idx, RETRO_RUMBLE_STRONG, 0);
  3602. input_driver_set_rumble(i, joy_idx, RETRO_RUMBLE_WEAK, 0);
  3603. }
  3604. }
  3605. break;
  3606. case CMD_EVENT_GRAB_MOUSE_TOGGLE:
  3607. {
  3608. bool ret = false;
  3609. input_driver_state_t
  3610. *input_st = input_state_get_ptr();
  3611. bool grab_mouse_state = !(input_st->flags &
  3612. INP_FLAG_GRAB_MOUSE_STATE);
  3613. if (grab_mouse_state)
  3614. {
  3615. if ((ret = input_driver_grab_mouse()))
  3616. input_st->flags |= INP_FLAG_GRAB_MOUSE_STATE;
  3617. }
  3618. else
  3619. {
  3620. if ((ret = input_driver_ungrab_mouse()))
  3621. input_st->flags &= ~INP_FLAG_GRAB_MOUSE_STATE;
  3622. }
  3623. if (!ret)
  3624. return false;
  3625. RARCH_LOG("[Input]: %s => %s\n",
  3626. msg_hash_to_str(MSG_GRAB_MOUSE_STATE),
  3627. grab_mouse_state ? "ON" : "OFF");
  3628. if (grab_mouse_state)
  3629. video_driver_hide_mouse();
  3630. else
  3631. video_driver_show_mouse();
  3632. }
  3633. break;
  3634. case CMD_EVENT_UI_COMPANION_TOGGLE:
  3635. {
  3636. #ifdef HAVE_QT
  3637. bool desktop_menu_enable = settings->bools.desktop_menu_enable;
  3638. bool ui_companion_toggle = settings->bools.ui_companion_toggle;
  3639. #else
  3640. bool desktop_menu_enable = false;
  3641. bool ui_companion_toggle = false;
  3642. #endif
  3643. ui_companion_driver_toggle(desktop_menu_enable,
  3644. ui_companion_toggle, true);
  3645. }
  3646. break;
  3647. case CMD_EVENT_GAME_FOCUS_TOGGLE:
  3648. {
  3649. bool video_fullscreen =
  3650. settings->bools.video_fullscreen
  3651. || (video_st->flags & VIDEO_FLAG_FORCE_FULLSCREEN);
  3652. enum input_game_focus_cmd_type game_focus_cmd = GAME_FOCUS_CMD_TOGGLE;
  3653. input_driver_state_t
  3654. *input_st = input_state_get_ptr();
  3655. bool current_enable_state = input_st->game_focus_state.enabled;
  3656. bool apply_update = false;
  3657. bool show_message = false;
  3658. if (data)
  3659. game_focus_cmd = *((enum input_game_focus_cmd_type*)data);
  3660. switch (game_focus_cmd)
  3661. {
  3662. case GAME_FOCUS_CMD_OFF:
  3663. /* Force game focus off */
  3664. input_st->game_focus_state.enabled = false;
  3665. if (input_st->game_focus_state.enabled != current_enable_state)
  3666. {
  3667. apply_update = true;
  3668. show_message = true;
  3669. }
  3670. break;
  3671. case GAME_FOCUS_CMD_ON:
  3672. /* Force game focus on */
  3673. input_st->game_focus_state.enabled = true;
  3674. if (input_st->game_focus_state.enabled != current_enable_state)
  3675. {
  3676. apply_update = true;
  3677. show_message = true;
  3678. }
  3679. break;
  3680. case GAME_FOCUS_CMD_TOGGLE:
  3681. /* Invert current game focus state */
  3682. input_st->game_focus_state.enabled = !input_st->game_focus_state.enabled;
  3683. #ifdef HAVE_MENU
  3684. /* If menu is currently active, disable
  3685. * 'toggle on' functionality */
  3686. if (menu_st->flags & MENU_ST_FLAG_ALIVE)
  3687. input_st->game_focus_state.enabled = false;
  3688. #endif
  3689. if (input_st->game_focus_state.enabled != current_enable_state)
  3690. {
  3691. apply_update = true;
  3692. show_message = true;
  3693. }
  3694. break;
  3695. case GAME_FOCUS_CMD_REAPPLY:
  3696. /* Reapply current game focus state */
  3697. apply_update = true;
  3698. show_message = false;
  3699. break;
  3700. default:
  3701. break;
  3702. }
  3703. if (apply_update)
  3704. {
  3705. input_driver_state_t
  3706. *input_st = input_state_get_ptr();
  3707. if (input_st->game_focus_state.enabled)
  3708. {
  3709. if (input_driver_grab_mouse())
  3710. input_st->flags |= INP_FLAG_GRAB_MOUSE_STATE;
  3711. video_driver_hide_mouse();
  3712. }
  3713. /* Ungrab only if windowed and auto mouse grab is disabled */
  3714. else if (!video_fullscreen &&
  3715. !settings->bools.input_auto_mouse_grab)
  3716. {
  3717. if (input_driver_ungrab_mouse())
  3718. input_st->flags &= ~INP_FLAG_GRAB_MOUSE_STATE;
  3719. video_driver_show_mouse();
  3720. }
  3721. if (input_st->game_focus_state.enabled)
  3722. input_st->flags |= INP_FLAG_BLOCK_HOTKEY
  3723. | INP_FLAG_KB_MAPPING_BLOCKED;
  3724. else
  3725. input_st->flags &= ~(INP_FLAG_BLOCK_HOTKEY
  3726. | INP_FLAG_KB_MAPPING_BLOCKED);
  3727. if (show_message)
  3728. runloop_msg_queue_push(
  3729. input_st->game_focus_state.enabled ?
  3730. msg_hash_to_str(MSG_GAME_FOCUS_ON) :
  3731. msg_hash_to_str(MSG_GAME_FOCUS_OFF),
  3732. 1, 60, true,
  3733. NULL, MESSAGE_QUEUE_ICON_DEFAULT,
  3734. MESSAGE_QUEUE_CATEGORY_INFO);
  3735. RARCH_LOG("[Input]: %s => %s\n",
  3736. "Game Focus",
  3737. input_st->game_focus_state.enabled ? "ON" : "OFF");
  3738. }
  3739. }
  3740. break;
  3741. case CMD_EVENT_VOLUME_UP:
  3742. {
  3743. audio_driver_state_t
  3744. *audio_st = audio_state_get_ptr();
  3745. command_event_set_volume(settings, 0.5f,
  3746. #if defined(HAVE_GFX_WIDGETS)
  3747. dispwidget_get_ptr()->active,
  3748. #else
  3749. false,
  3750. #endif
  3751. audio_st->mute_enable);
  3752. }
  3753. break;
  3754. case CMD_EVENT_VOLUME_DOWN:
  3755. command_event_set_volume(settings, -0.5f,
  3756. #if defined(HAVE_GFX_WIDGETS)
  3757. dispwidget_get_ptr()->active,
  3758. #else
  3759. false,
  3760. #endif
  3761. audio_state_get_ptr()->mute_enable
  3762. );
  3763. break;
  3764. case CMD_EVENT_MIXER_VOLUME_UP:
  3765. command_event_set_mixer_volume(settings, 0.5f);
  3766. break;
  3767. case CMD_EVENT_MIXER_VOLUME_DOWN:
  3768. command_event_set_mixer_volume(settings, -0.5f);
  3769. break;
  3770. case CMD_EVENT_SET_FRAME_LIMIT:
  3771. {
  3772. video_driver_state_t
  3773. *video_st = video_state_get_ptr();
  3774. runloop_set_frame_limit(&video_st->av_info,
  3775. runloop_get_fastforward_ratio(
  3776. settings,
  3777. &runloop_st->fastmotion_override.current));
  3778. }
  3779. break;
  3780. case CMD_EVENT_DISCORD_INIT:
  3781. #ifdef HAVE_DISCORD
  3782. {
  3783. bool discord_enable = settings ? settings->bools.discord_enable : false;
  3784. const char *discord_app_id = settings ? settings->arrays.discord_app_id : NULL;
  3785. discord_state_t *discord_st = discord_state_get_ptr();
  3786. if (!settings)
  3787. return false;
  3788. if (!discord_enable)
  3789. return false;
  3790. if (!discord_st->ready)
  3791. discord_init(discord_app_id, p_rarch->launch_arguments);
  3792. }
  3793. #endif
  3794. break;
  3795. case CMD_EVENT_PRESENCE_UPDATE:
  3796. {
  3797. #ifdef HAVE_PRESENCE
  3798. presence_userdata_t *userdata = NULL;
  3799. if (!data)
  3800. return false;
  3801. userdata = (presence_userdata_t*)data;
  3802. presence_update(userdata->status);
  3803. #endif
  3804. }
  3805. break;
  3806. case CMD_EVENT_AI_SERVICE_CALL:
  3807. {
  3808. #ifdef HAVE_TRANSLATE
  3809. #ifdef HAVE_ACCESSIBILITY
  3810. bool accessibility_enable = settings->bools.accessibility_enable;
  3811. unsigned accessibility_narrator_speech_speed = settings->uints.accessibility_narrator_speech_speed;
  3812. #endif
  3813. unsigned ai_service_mode = settings->uints.ai_service_mode;
  3814. #ifdef HAVE_AUDIOMIXER
  3815. if (ai_service_mode == 1 && audio_driver_is_ai_service_speech_running())
  3816. {
  3817. audio_driver_mixer_stop_stream(10);
  3818. audio_driver_mixer_remove_stream(10);
  3819. #ifdef HAVE_ACCESSIBILITY
  3820. if (is_accessibility_enabled(
  3821. accessibility_enable,
  3822. access_st->enabled))
  3823. accessibility_speak_priority(
  3824. accessibility_enable,
  3825. accessibility_narrator_speech_speed,
  3826. "stopped.", 10);
  3827. #endif
  3828. }
  3829. else
  3830. #endif
  3831. #ifdef HAVE_ACCESSIBILITY
  3832. if (is_accessibility_enabled(
  3833. accessibility_enable,
  3834. access_st->enabled)
  3835. && ai_service_mode == 2
  3836. && is_narrator_running(accessibility_enable))
  3837. accessibility_speak_priority(
  3838. accessibility_enable,
  3839. accessibility_narrator_speech_speed,
  3840. "stopped.", 10);
  3841. else
  3842. #endif
  3843. {
  3844. bool paused = runloop_st->flags & RUNLOOP_FLAG_PAUSED;
  3845. if (data)
  3846. paused = *((bool*)data);
  3847. if ( access_st->ai_service_auto == 0
  3848. && !settings->bools.ai_service_pause)
  3849. access_st->ai_service_auto = 1;
  3850. run_translation_service(settings, paused);
  3851. }
  3852. #endif
  3853. break;
  3854. }
  3855. case CMD_EVENT_CONTROLLER_INIT:
  3856. {
  3857. rarch_system_info_t *info = &runloop_st->system;
  3858. if (info)
  3859. command_event_init_controllers(info, settings,
  3860. settings->uints.input_max_users);
  3861. }
  3862. break;
  3863. case CMD_EVENT_VRR_RUNLOOP_TOGGLE:
  3864. settings->bools.vrr_runloop_enable = !(settings->bools.vrr_runloop_enable);
  3865. runloop_msg_queue_push(
  3866. msg_hash_to_str(
  3867. settings->bools.vrr_runloop_enable ? MSG_VRR_RUNLOOP_ENABLED
  3868. : MSG_VRR_RUNLOOP_DISABLED),
  3869. 1, 100, false, NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
  3870. break;
  3871. case CMD_EVENT_NONE:
  3872. return false;
  3873. /* Deprecated */
  3874. case CMD_EVENT_SEND_DEBUG_INFO:
  3875. break;
  3876. }
  3877. return true;
  3878. }
  3879. /* FRONTEND */
  3880. void retroarch_override_setting_set(
  3881. enum rarch_override_setting enum_idx, void *data)
  3882. {
  3883. struct rarch_state *p_rarch = &rarch_st;
  3884. #ifdef HAVE_NETWORKING
  3885. net_driver_state_t *net_st = networking_state_get_ptr();
  3886. #endif
  3887. switch (enum_idx)
  3888. {
  3889. case RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE:
  3890. {
  3891. unsigned *val = (unsigned*)data;
  3892. if (val)
  3893. {
  3894. unsigned bit = *val;
  3895. runloop_state_t *runloop_st = runloop_state_get_ptr();
  3896. BIT256_SET(runloop_st->has_set_libretro_device, bit);
  3897. }
  3898. }
  3899. break;
  3900. case RARCH_OVERRIDE_SETTING_VERBOSITY:
  3901. p_rarch->flags |= RARCH_FLAGS_HAS_SET_VERBOSITY;
  3902. break;
  3903. case RARCH_OVERRIDE_SETTING_LIBRETRO:
  3904. p_rarch->flags |= RARCH_FLAGS_HAS_SET_LIBRETRO;
  3905. break;
  3906. case RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY:
  3907. p_rarch->flags |= RARCH_FLAGS_HAS_SET_LIBRETRO_DIRECTORY;
  3908. break;
  3909. case RARCH_OVERRIDE_SETTING_SAVE_PATH:
  3910. p_rarch->flags |= RARCH_FLAGS_HAS_SET_SAVE_PATH;
  3911. break;
  3912. case RARCH_OVERRIDE_SETTING_STATE_PATH:
  3913. p_rarch->flags |= RARCH_FLAGS_HAS_SET_STATE_PATH;
  3914. break;
  3915. #ifdef HAVE_NETWORKING
  3916. case RARCH_OVERRIDE_SETTING_NETPLAY_MODE:
  3917. net_st->flags |= NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_MODE;
  3918. break;
  3919. case RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS:
  3920. net_st->flags |= NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_ADDRESS;
  3921. break;
  3922. case RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT:
  3923. net_st->flags |= NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_PORT;
  3924. break;
  3925. case RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES:
  3926. net_st->flags |= NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_CHECK_FRAMES;
  3927. break;
  3928. #endif
  3929. case RARCH_OVERRIDE_SETTING_UPS_PREF:
  3930. #ifdef HAVE_PATCH
  3931. p_rarch->flags |= RARCH_FLAGS_HAS_SET_UPS_PREF;
  3932. #endif
  3933. break;
  3934. case RARCH_OVERRIDE_SETTING_BPS_PREF:
  3935. #ifdef HAVE_PATCH
  3936. p_rarch->flags |= RARCH_FLAGS_HAS_SET_BPS_PREF;
  3937. #endif
  3938. break;
  3939. case RARCH_OVERRIDE_SETTING_IPS_PREF:
  3940. #ifdef HAVE_PATCH
  3941. p_rarch->flags |= RARCH_FLAGS_HAS_SET_IPS_PREF;
  3942. #endif
  3943. break;
  3944. case RARCH_OVERRIDE_SETTING_LOG_TO_FILE:
  3945. p_rarch->flags |= RARCH_FLAGS_HAS_SET_LOG_TO_FILE;
  3946. break;
  3947. case RARCH_OVERRIDE_SETTING_DATABASE_SCAN:
  3948. p_rarch->flags |= RARCH_FLAGS_CLI_DATABASE_SCAN;
  3949. break;
  3950. case RARCH_OVERRIDE_SETTING_NONE:
  3951. default:
  3952. break;
  3953. }
  3954. }
  3955. void retroarch_override_setting_unset(
  3956. enum rarch_override_setting enum_idx, void *data)
  3957. {
  3958. struct rarch_state *p_rarch = &rarch_st;
  3959. #ifdef HAVE_NETWORKING
  3960. net_driver_state_t *net_st = networking_state_get_ptr();
  3961. #endif
  3962. switch (enum_idx)
  3963. {
  3964. case RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE:
  3965. {
  3966. unsigned *val = (unsigned*)data;
  3967. if (val)
  3968. {
  3969. unsigned bit = *val;
  3970. runloop_state_t *runloop_st = runloop_state_get_ptr();
  3971. BIT256_CLEAR(runloop_st->has_set_libretro_device, bit);
  3972. }
  3973. }
  3974. break;
  3975. case RARCH_OVERRIDE_SETTING_VERBOSITY:
  3976. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_VERBOSITY;
  3977. break;
  3978. case RARCH_OVERRIDE_SETTING_LIBRETRO:
  3979. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_LIBRETRO;
  3980. break;
  3981. case RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY:
  3982. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_LIBRETRO_DIRECTORY;
  3983. break;
  3984. case RARCH_OVERRIDE_SETTING_SAVE_PATH:
  3985. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_SAVE_PATH;
  3986. break;
  3987. case RARCH_OVERRIDE_SETTING_STATE_PATH:
  3988. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_STATE_PATH;
  3989. break;
  3990. #ifdef HAVE_NETWORKING
  3991. case RARCH_OVERRIDE_SETTING_NETPLAY_MODE:
  3992. net_st->flags &= ~NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_MODE;
  3993. break;
  3994. case RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS:
  3995. net_st->flags &= ~NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_ADDRESS;
  3996. break;
  3997. case RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT:
  3998. net_st->flags &= ~NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_PORT;
  3999. break;
  4000. case RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES:
  4001. net_st->flags &= ~NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_CHECK_FRAMES;
  4002. break;
  4003. #endif
  4004. case RARCH_OVERRIDE_SETTING_UPS_PREF:
  4005. #ifdef HAVE_PATCH
  4006. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_UPS_PREF;
  4007. #endif
  4008. break;
  4009. case RARCH_OVERRIDE_SETTING_BPS_PREF:
  4010. #ifdef HAVE_PATCH
  4011. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_BPS_PREF;
  4012. #endif
  4013. break;
  4014. case RARCH_OVERRIDE_SETTING_IPS_PREF:
  4015. #ifdef HAVE_PATCH
  4016. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_IPS_PREF;
  4017. #endif
  4018. break;
  4019. case RARCH_OVERRIDE_SETTING_LOG_TO_FILE:
  4020. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_LOG_TO_FILE;
  4021. break;
  4022. case RARCH_OVERRIDE_SETTING_DATABASE_SCAN:
  4023. p_rarch->flags &= ~RARCH_FLAGS_CLI_DATABASE_SCAN;
  4024. break;
  4025. case RARCH_OVERRIDE_SETTING_NONE:
  4026. default:
  4027. break;
  4028. }
  4029. }
  4030. static void retroarch_override_setting_free_state(void)
  4031. {
  4032. unsigned i;
  4033. for (i = 0; i < RARCH_OVERRIDE_SETTING_LAST; i++)
  4034. {
  4035. if (i == RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE)
  4036. {
  4037. unsigned j;
  4038. for (j = 0; j < MAX_USERS; j++)
  4039. retroarch_override_setting_unset(
  4040. RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE, &j);
  4041. }
  4042. else
  4043. retroarch_override_setting_unset(
  4044. (enum rarch_override_setting)(i), NULL);
  4045. }
  4046. }
  4047. static void global_free(struct rarch_state *p_rarch)
  4048. {
  4049. global_t *global = NULL;
  4050. runloop_state_t *runloop_st = runloop_state_get_ptr();
  4051. content_deinit();
  4052. runloop_path_deinit_subsystem();
  4053. command_event(CMD_EVENT_RECORD_DEINIT, NULL);
  4054. retro_main_log_file_deinit();
  4055. runloop_st->flags &= ~(
  4056. RUNLOOP_FLAG_IS_SRAM_LOAD_DISABLED
  4057. | RUNLOOP_FLAG_IS_SRAM_SAVE_DISABLED
  4058. | RUNLOOP_FLAG_USE_SRAM);
  4059. #ifdef HAVE_PATCH
  4060. p_rarch->flags &= ~(
  4061. RARCH_FLAGS_BPS_PREF
  4062. | RARCH_FLAGS_IPS_PREF
  4063. | RARCH_FLAGS_UPS_PREF);
  4064. runloop_st->flags &= ~RUNLOOP_FLAG_PATCH_BLOCKED;
  4065. #endif
  4066. #ifdef HAVE_CONFIGFILE
  4067. p_rarch->flags &= ~RARCH_FLAGS_BLOCK_CONFIG_READ;
  4068. runloop_st->flags &= ~(RUNLOOP_FLAG_OVERRIDES_ACTIVE
  4069. | RUNLOOP_FLAG_REMAPS_CORE_ACTIVE
  4070. | RUNLOOP_FLAG_REMAPS_GAME_ACTIVE
  4071. | RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE);
  4072. #endif
  4073. runloop_st->current_core.flags &= ~(RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS
  4074. | RETRO_CORE_FLAG_HAS_SET_SUBSYSTEMS);
  4075. global = global_get_ptr();
  4076. path_clear_all();
  4077. dir_clear_all();
  4078. if (!string_is_empty(runloop_st->name.remapfile))
  4079. free(runloop_st->name.remapfile);
  4080. runloop_st->name.remapfile = NULL;
  4081. *runloop_st->name.ups = '\0';
  4082. *runloop_st->name.bps = '\0';
  4083. *runloop_st->name.ips = '\0';
  4084. *runloop_st->name.savefile = '\0';
  4085. *runloop_st->name.savestate = '\0';
  4086. *runloop_st->name.replay = '\0';
  4087. *runloop_st->name.cheatfile = '\0';
  4088. *runloop_st->name.label = '\0';
  4089. if (global)
  4090. memset(global, 0, sizeof(struct global));
  4091. retroarch_override_setting_free_state();
  4092. }
  4093. #if defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL_DINGUX)
  4094. static void sdl_exit(void)
  4095. {
  4096. /* Quit any SDL subsystems, then quit
  4097. * SDL itself */
  4098. uint32_t sdl_subsystem_flags = SDL_WasInit(0);
  4099. if (sdl_subsystem_flags != 0)
  4100. {
  4101. SDL_QuitSubSystem(sdl_subsystem_flags);
  4102. SDL_Quit();
  4103. }
  4104. }
  4105. #endif
  4106. /**
  4107. * main_exit:
  4108. *
  4109. * Cleanly exit RetroArch.
  4110. *
  4111. **/
  4112. void main_exit(void *args)
  4113. {
  4114. struct rarch_state *p_rarch = &rarch_st;
  4115. runloop_state_t *runloop_st = runloop_state_get_ptr();
  4116. #ifdef HAVE_MENU
  4117. struct menu_state *menu_st = menu_state_get_ptr();
  4118. #endif
  4119. settings_t *settings = config_get_ptr();
  4120. video_driver_restore_cached(settings);
  4121. #if defined(HAVE_GFX_WIDGETS)
  4122. /* Do not want display widgets to live any more. */
  4123. dispwidget_get_ptr()->flags &= ~DISPGFX_WIDGET_FLAG_PERSISTING;
  4124. #endif
  4125. #ifdef HAVE_MENU
  4126. /* Do not want menu context to live any more. */
  4127. if (menu_st)
  4128. menu_st->flags &= ~MENU_ST_FLAG_DATA_OWN;
  4129. #endif
  4130. retroarch_ctl(RARCH_CTL_MAIN_DEINIT, NULL);
  4131. if (runloop_st->perfcnt_enable)
  4132. {
  4133. RARCH_LOG("[PERF]: Performance counters (RetroArch):\n");
  4134. runloop_log_counters(p_rarch->perf_counters_rarch, p_rarch->perf_ptr_rarch);
  4135. }
  4136. #if defined(HAVE_LOGGER) && !defined(ANDROID)
  4137. logger_shutdown();
  4138. #endif
  4139. frontend_driver_deinit(args);
  4140. frontend_driver_exitspawn(
  4141. path_get_ptr(RARCH_PATH_CORE),
  4142. path_get_realsize(RARCH_PATH_CORE),
  4143. p_rarch->launch_arguments);
  4144. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_USERNAME;
  4145. runloop_st->flags &= ~RUNLOOP_FLAG_IS_INITED;
  4146. global_get_ptr()->error_on_init = false;
  4147. #ifdef HAVE_CONFIGFILE
  4148. p_rarch->flags &= ~RARCH_FLAGS_BLOCK_CONFIG_READ;
  4149. #endif
  4150. runloop_msg_queue_deinit();
  4151. driver_uninit(DRIVERS_CMD_ALL);
  4152. retro_main_log_file_deinit();
  4153. retroarch_ctl(RARCH_CTL_STATE_FREE, NULL);
  4154. global_free(p_rarch);
  4155. task_queue_deinit();
  4156. ui_companion_driver_deinit();
  4157. retroarch_config_deinit();
  4158. frontend_driver_shutdown(false);
  4159. retroarch_deinit_drivers(&runloop_st->retro_ctx);
  4160. uico_state_get_ptr()->drv = NULL;
  4161. frontend_driver_free();
  4162. rtime_deinit();
  4163. #if defined(ANDROID)
  4164. play_feature_delivery_deinit();
  4165. #endif
  4166. #if defined(HAVE_MIST)
  4167. steam_deinit();
  4168. #endif
  4169. #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
  4170. CoUninitialize();
  4171. #endif
  4172. #if defined(HAVE_SDL) || defined(HAVE_SDL2) || defined(HAVE_SDL_DINGUX)
  4173. sdl_exit();
  4174. #endif
  4175. }
  4176. /**
  4177. * main_entry:
  4178. *
  4179. * Main function of RetroArch.
  4180. *
  4181. * If HAVE_MAIN is not defined, will contain main loop and will not
  4182. * be exited from until we exit the program. Otherwise, will
  4183. * just do initialization.
  4184. *
  4185. * Returns: varies per platform.
  4186. **/
  4187. int rarch_main(int argc, char *argv[], void *data)
  4188. {
  4189. struct rarch_state *p_rarch = &rarch_st;
  4190. runloop_state_t *runloop_st = runloop_state_get_ptr();
  4191. video_driver_state_t *video_st = video_state_get_ptr();
  4192. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  4193. video_st->flags |= VIDEO_FLAG_SHADER_PRESETS_NEED_RELOAD;
  4194. #endif
  4195. #ifdef HAVE_RUNAHEAD
  4196. video_st->flags |= VIDEO_FLAG_RUNAHEAD_IS_ACTIVE;
  4197. runloop_st->flags |= (
  4198. RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE
  4199. | RUNLOOP_FLAG_RUNAHEAD_AVAILABLE
  4200. | RUNLOOP_FLAG_RUNAHEAD_FORCE_INPUT_DIRTY
  4201. );
  4202. #endif
  4203. #if defined(_WIN32) && !defined(_XBOX) && !defined(__WINRT__)
  4204. if (FAILED(CoInitialize(NULL)))
  4205. {
  4206. RARCH_ERR("FATAL: Failed to initialize the COM interface\n");
  4207. return 1;
  4208. }
  4209. #endif
  4210. rtime_init();
  4211. #if defined(ANDROID)
  4212. play_feature_delivery_init();
  4213. #endif
  4214. #if defined(HAVE_MIST)
  4215. steam_init();
  4216. #endif
  4217. libretro_free_system_info(&runloop_st->system.info);
  4218. command_event(CMD_EVENT_HISTORY_DEINIT, NULL);
  4219. retroarch_favorites_deinit();
  4220. retroarch_config_init();
  4221. retroarch_deinit_drivers(&runloop_st->retro_ctx);
  4222. retroarch_ctl(RARCH_CTL_STATE_FREE, NULL);
  4223. global_free(p_rarch);
  4224. frontend_driver_init_first(data);
  4225. if (runloop_st->flags & RUNLOOP_FLAG_IS_INITED)
  4226. driver_uninit(DRIVERS_CMD_ALL);
  4227. #ifdef HAVE_THREAD_STORAGE
  4228. sthread_tls_create(&p_rarch->rarch_tls);
  4229. sthread_tls_set(&p_rarch->rarch_tls, MAGIC_POINTER);
  4230. #endif
  4231. video_st->flags |= VIDEO_FLAG_ACTIVE;
  4232. audio_state_get_ptr()->flags |= AUDIO_FLAG_ACTIVE;
  4233. {
  4234. int i;
  4235. for (i = 0; i < MAX_USERS; i++)
  4236. input_config_set_device(i, RETRO_DEVICE_JOYPAD);
  4237. }
  4238. runloop_msg_queue_init();
  4239. if (frontend_state_get_ptr()->current_frontend_ctx)
  4240. {
  4241. content_ctx_info_t info;
  4242. info.argc = argc;
  4243. info.argv = argv;
  4244. info.args = data;
  4245. info.environ_get = frontend_state_get_ptr()->current_frontend_ctx->environment_get;
  4246. if (!task_push_load_content_from_cli(
  4247. NULL,
  4248. NULL,
  4249. &info,
  4250. CORE_TYPE_PLAIN,
  4251. NULL,
  4252. NULL))
  4253. return 1;
  4254. }
  4255. ui_companion_driver_init_first();
  4256. #if !defined(HAVE_MAIN) || defined(HAVE_QT)
  4257. for (;;)
  4258. {
  4259. int ret;
  4260. bool app_exit = false;
  4261. #ifdef HAVE_QT
  4262. ui_companion_qt.application->process_events();
  4263. #endif
  4264. ret = runloop_iterate();
  4265. task_queue_check();
  4266. #ifdef HAVE_MIST
  4267. steam_poll();
  4268. #endif
  4269. #ifdef HAVE_QT
  4270. app_exit = ui_companion_qt.application->exiting;
  4271. #endif
  4272. if (ret == -1 || app_exit)
  4273. {
  4274. #ifdef HAVE_QT
  4275. ui_companion_qt.application->quit();
  4276. #endif
  4277. break;
  4278. }
  4279. }
  4280. main_exit(data);
  4281. #endif
  4282. return 0;
  4283. }
  4284. #if defined(EMSCRIPTEN)
  4285. #include "gfx/common/gl_common.h"
  4286. void RWebAudioRecalibrateTime(void);
  4287. void emscripten_mainloop(void)
  4288. {
  4289. int ret;
  4290. static unsigned emscripten_frame_count = 0;
  4291. video_driver_state_t *video_st = video_state_get_ptr();
  4292. settings_t *settings = config_get_ptr();
  4293. input_driver_state_t *input_st = input_state_get_ptr();
  4294. bool black_frame_insertion = settings->uints.video_black_frame_insertion;
  4295. bool input_driver_nonblock_state = input_st ?
  4296. (input_st->flags & INP_FLAG_NONBLOCKING) : false;
  4297. uint32_t runloop_flags = runloop_get_flags();
  4298. bool runloop_is_slowmotion = runloop_flags & RUNLOOP_FLAG_SLOWMOTION;
  4299. bool runloop_is_paused = runloop_flags & RUNLOOP_FLAG_PAUSED;
  4300. RWebAudioRecalibrateTime();
  4301. emscripten_frame_count++;
  4302. /* Disable BFI during fast forward, slow-motion,
  4303. * and pause to prevent flicker. */
  4304. if (
  4305. black_frame_insertion
  4306. && !input_driver_nonblock_state
  4307. && !runloop_is_slowmotion
  4308. && !runloop_is_paused)
  4309. {
  4310. if ((emscripten_frame_count % (black_frame_insertion+1)) != 0)
  4311. {
  4312. gl_clear();
  4313. if (video_st->current_video_context.swap_buffers)
  4314. video_st->current_video_context.swap_buffers(
  4315. video_st->context_data);
  4316. return;
  4317. }
  4318. }
  4319. ret = runloop_iterate();
  4320. task_queue_check();
  4321. if (ret != -1)
  4322. return;
  4323. main_exit(NULL);
  4324. emscripten_force_exit(0);
  4325. }
  4326. #endif
  4327. #ifndef HAVE_MAIN
  4328. #ifdef __cplusplus
  4329. extern "C"
  4330. #endif
  4331. int main(int argc, char *argv[])
  4332. {
  4333. return rarch_main(argc, argv, NULL);
  4334. }
  4335. #endif
  4336. /* DYNAMIC LIBRETRO CORE */
  4337. const struct retro_subsystem_info *libretro_find_subsystem_info(
  4338. const struct retro_subsystem_info *info, unsigned num_info,
  4339. const char *ident)
  4340. {
  4341. unsigned i;
  4342. for (i = 0; i < num_info; i++)
  4343. {
  4344. if ( string_is_equal(info[i].ident, ident)
  4345. || string_is_equal(info[i].desc, ident)
  4346. )
  4347. return &info[i];
  4348. }
  4349. return NULL;
  4350. }
  4351. /**
  4352. * libretro_find_controller_description:
  4353. * @info : Pointer to controller info handle.
  4354. * @id : Identifier of controller to search
  4355. * for.
  4356. *
  4357. * Search for a controller of type @id in @info.
  4358. *
  4359. * Leaf function.
  4360. *
  4361. * @return controller description of found controller on success,
  4362. * otherwise NULL.
  4363. **/
  4364. const struct retro_controller_description *
  4365. libretro_find_controller_description(
  4366. const struct retro_controller_info *info, unsigned id)
  4367. {
  4368. unsigned i;
  4369. for (i = 0; i < info->num_types; i++)
  4370. {
  4371. if (info->types[i].id != id)
  4372. continue;
  4373. return &info->types[i];
  4374. }
  4375. return NULL;
  4376. }
  4377. /**
  4378. * libretro_free_system_info:
  4379. * @info : Pointer to system info information.
  4380. *
  4381. * Frees system information.
  4382. **/
  4383. void libretro_free_system_info(struct retro_system_info *info)
  4384. {
  4385. if (!info)
  4386. return;
  4387. free((void*)info->library_name);
  4388. free((void*)info->library_version);
  4389. free((void*)info->valid_extensions);
  4390. memset(info, 0, sizeof(*info));
  4391. }
  4392. static void retroarch_print_features(void)
  4393. {
  4394. char buf[4096];
  4395. buf[0] = '\0';
  4396. frontend_driver_attach_console();
  4397. strlcpy(buf, "Features:\n", sizeof(buf));
  4398. _PSUPP_BUF(buf, SUPPORTS_LIBRETRODB, "LibretroDB", "LibretroDB support");
  4399. _PSUPP_BUF(buf, SUPPORTS_COMMAND, "Command", "Command interface support");
  4400. _PSUPP_BUF(buf, SUPPORTS_NETWORK_COMMAND, "Network Command", "Network Command interface support");
  4401. _PSUPP_BUF(buf, SUPPORTS_SDL, "SDL", "SDL input/audio/video drivers");
  4402. _PSUPP_BUF(buf, SUPPORTS_SDL2, "SDL2", "SDL2 input/audio/video drivers");
  4403. _PSUPP_BUF(buf, SUPPORTS_X11, "X11", "X11 input/video drivers");
  4404. _PSUPP_BUF(buf, SUPPORTS_UDEV, "UDEV", "UDEV/EVDEV input driver");
  4405. _PSUPP_BUF(buf, SUPPORTS_WAYLAND, "Wayland", "Wayland input/video drivers");
  4406. _PSUPP_BUF(buf, SUPPORTS_THREAD, "Threads", "Threading support");
  4407. _PSUPP_BUF(buf, SUPPORTS_VULKAN, "Vulkan", "Video driver");
  4408. _PSUPP_BUF(buf, SUPPORTS_METAL, "Metal", "Video driver");
  4409. _PSUPP_BUF(buf, SUPPORTS_OPENGL, "OpenGL", "Video driver");
  4410. _PSUPP_BUF(buf, SUPPORTS_OPENGLES, "OpenGLES", "Video driver");
  4411. _PSUPP_BUF(buf, SUPPORTS_XVIDEO, "XVideo", "Video driver");
  4412. _PSUPP_BUF(buf, SUPPORTS_EGL, "EGL", "Video context driver");
  4413. _PSUPP_BUF(buf, SUPPORTS_KMS, "KMS", "Video context driver");
  4414. _PSUPP_BUF(buf, SUPPORTS_VG, "OpenVG", "Video context driver");
  4415. _PSUPP_BUF(buf, SUPPORTS_COREAUDIO, "CoreAudio", "Audio driver");
  4416. _PSUPP_BUF(buf, SUPPORTS_COREAUDIO3, "CoreAudioV3", "Audio driver");
  4417. _PSUPP_BUF(buf, SUPPORTS_ALSA, "ALSA", "Audio driver");
  4418. _PSUPP_BUF(buf, SUPPORTS_OSS, "OSS", "Audio driver");
  4419. _PSUPP_BUF(buf, SUPPORTS_JACK, "Jack", "Audio driver");
  4420. _PSUPP_BUF(buf, SUPPORTS_RSOUND, "RSound", "Audio driver");
  4421. _PSUPP_BUF(buf, SUPPORTS_ROAR, "RoarAudio", "Audio driver");
  4422. _PSUPP_BUF(buf, SUPPORTS_PULSE, "PulseAudio", "Audio driver");
  4423. _PSUPP_BUF(buf, SUPPORTS_DSOUND, "DirectSound", "Audio driver");
  4424. _PSUPP_BUF(buf, SUPPORTS_WASAPI, "WASAPI", "Audio driver");
  4425. _PSUPP_BUF(buf, SUPPORTS_XAUDIO, "XAudio2", "Audio driver");
  4426. _PSUPP_BUF(buf, SUPPORTS_AL, "OpenAL", "Audio driver");
  4427. _PSUPP_BUF(buf, SUPPORTS_SL, "OpenSL", "Audio driver");
  4428. _PSUPP_BUF(buf, SUPPORTS_7ZIP, "7zip", "7zip extraction support");
  4429. _PSUPP_BUF(buf, SUPPORTS_ZLIB, "zlib", "zip extraction support");
  4430. _PSUPP_BUF(buf, SUPPORTS_DYLIB, "External", "External filter and plugin support");
  4431. _PSUPP_BUF(buf, SUPPORTS_CG, "Cg", "Fragment/vertex shader driver");
  4432. _PSUPP_BUF(buf, SUPPORTS_GLSL, "GLSL", "Fragment/vertex shader driver");
  4433. _PSUPP_BUF(buf, SUPPORTS_HLSL, "HLSL", "Fragment/vertex shader driver");
  4434. _PSUPP_BUF(buf, SUPPORTS_SDL_IMAGE, "SDL_image", "SDL_image image loading");
  4435. _PSUPP_BUF(buf, SUPPORTS_RPNG, "rpng", "PNG image loading/encoding");
  4436. _PSUPP_BUF(buf, SUPPORTS_RJPEG, "rjpeg", "JPEG image loading");
  4437. _PSUPP_BUF(buf, SUPPORTS_DYNAMIC, "Dynamic", "Dynamic run-time loading of libretro library");
  4438. _PSUPP_BUF(buf, SUPPORTS_FFMPEG, "FFmpeg", "On-the-fly recording of gameplay with libavcodec");
  4439. _PSUPP_BUF(buf, SUPPORTS_FREETYPE, "FreeType", "TTF font rendering driver");
  4440. _PSUPP_BUF(buf, SUPPORTS_CORETEXT, "CoreText", "TTF font rendering driver");
  4441. _PSUPP_BUF(buf, SUPPORTS_NETPLAY, "Netplay", "Peer-to-peer netplay");
  4442. _PSUPP_BUF(buf, SUPPORTS_LIBUSB, "Libusb", "Libusb support");
  4443. _PSUPP_BUF(buf, SUPPORTS_COCOA, "Cocoa", "Cocoa UI companion support (for OSX and/or iOS)");
  4444. _PSUPP_BUF(buf, SUPPORTS_QT, "Qt", "Qt UI companion support");
  4445. _PSUPP_BUF(buf, SUPPORTS_V4L2, "Video4Linux2", "Camera driver");
  4446. fputs(buf, stdout);
  4447. }
  4448. static void retroarch_print_version(void)
  4449. {
  4450. char str[255];
  4451. str[0] = '\0';
  4452. frontend_driver_attach_console();
  4453. fprintf(stdout, "%s - %s\n",
  4454. msg_hash_to_str(MSG_PROGRAM),
  4455. msg_hash_to_str(MSG_LIBRETRO_FRONTEND));
  4456. fprintf(stdout, "Version: %s", PACKAGE_VERSION);
  4457. #ifdef HAVE_GIT_VERSION
  4458. fprintf(stdout, " (Git %s)", retroarch_git_version);
  4459. #endif
  4460. fprintf(stdout, " " __DATE__ "\n");
  4461. retroarch_get_capabilities(RARCH_CAPABILITIES_COMPILER, str, sizeof(str), 0);
  4462. fprintf(stdout, "%s\n", str);
  4463. }
  4464. /**
  4465. * retroarch_print_help:
  4466. *
  4467. * Prints help message explaining the program's commandline switches.
  4468. **/
  4469. static void retroarch_print_help(const char *arg0)
  4470. {
  4471. char buf[2048];
  4472. buf[0] = '\0';
  4473. frontend_driver_attach_console();
  4474. fputs("\n", stdout);
  4475. puts("===================================================================");
  4476. retroarch_print_version();
  4477. puts("===================================================================");
  4478. fputs("\n", stdout);
  4479. fprintf(stdout, "Usage: %s [OPTIONS]... [FILE]\n\n", arg0);
  4480. strlcat(buf,
  4481. " -h, --help "
  4482. "Show this help message.\n"
  4483. " -v, --verbose "
  4484. "Verbose logging.\n"
  4485. " --log-file=FILE "
  4486. "Log messages to FILE.\n"
  4487. " -V, --version "
  4488. "Show version.\n"
  4489. " --features "
  4490. "Print available features compiled into program.\n"
  4491. , sizeof(buf));
  4492. #ifdef HAVE_MENU
  4493. strlcat(buf,
  4494. " --menu "
  4495. "Do not require content or libretro core to be loaded,\n"
  4496. " "
  4497. " starts directly in menu. If no arguments are passed to\n"
  4498. " "
  4499. " the program, it is equivalent to using --menu as only argument.\n"
  4500. , sizeof(buf));
  4501. #endif
  4502. #ifdef HAVE_CONFIGFILE
  4503. strlcat(buf, " -c, --config=FILE "
  4504. "Path for config file.\n", sizeof(buf));
  4505. #ifdef _WIN32
  4506. strlcat(buf, " "
  4507. " Defaults to retroarch.cfg in same directory as retroarch.exe.\n"
  4508. " "
  4509. " If a default config is not found, the program will attempt to create one.\n"
  4510. , sizeof(buf));
  4511. #else
  4512. strlcat(buf,
  4513. " "
  4514. " By default looks for config in\n"
  4515. " "
  4516. " $XDG_CONFIG_HOME/retroarch/retroarch.cfg,\n"
  4517. " "
  4518. " $HOME/.config/retroarch/retroarch.cfg, and\n"
  4519. " "
  4520. " $HOME/.retroarch.cfg.\n"
  4521. " "
  4522. " If a default config is not found, the program will attempt to create one\n"
  4523. " "
  4524. " based on the skeleton config (" GLOBAL_CONFIG_DIR "/retroarch.cfg).\n"
  4525. , sizeof(buf));
  4526. #endif
  4527. strlcat(buf, " --appendconfig=FILE "
  4528. "Extra config files are loaded in, and take priority over\n"
  4529. " "
  4530. " config selected in -c (or default). Multiple configs are\n"
  4531. " "
  4532. " delimited by '|'.\n"
  4533. , sizeof(buf));
  4534. #endif
  4535. fputs(buf, stdout);
  4536. buf[0] = '\0';
  4537. #ifdef HAVE_DYNAMIC
  4538. strlcat(buf,
  4539. " -L, --libretro=FILE "
  4540. "Path to libretro implementation. Overrides any config setting.\n"
  4541. " "
  4542. " FILE may be one of the following:\n"
  4543. " "
  4544. " 1. The full path to a core shared object library: path/to/<core_name>_libretro.<lib_ext>\n"
  4545. " "
  4546. " 2. A core shared object library 'file name' (*): <core_name>_libretro.<lib_ext>\n"
  4547. , sizeof(buf));
  4548. strlcat(buf,
  4549. " "
  4550. " 3. A core 'short name' (*): <core_name>_libretro OR <core_name>\n"
  4551. " "
  4552. " (*) If 'file name' or 'short name' do not correspond to an existing full file path,\n"
  4553. " "
  4554. " the configured frontend 'cores' directory will be searched for a match.\n"
  4555. , sizeof(buf));
  4556. #endif
  4557. strlcat(buf,
  4558. " --subsystem=NAME "
  4559. "Use a subsystem of the libretro core. Multiple content\n"
  4560. " "
  4561. " files are loaded as multiple arguments. If a content\n"
  4562. " "
  4563. " file is skipped, use a blank (\"\") command line argument.\n"
  4564. , sizeof(buf));
  4565. strlcat(buf,
  4566. " "
  4567. " Content must be loaded in an order which depends on the\n"
  4568. " "
  4569. " particular subsystem used. See verbose log output to learn\n"
  4570. " "
  4571. " how a particular subsystem wants content to be loaded.\n"
  4572. , sizeof(buf));
  4573. #ifdef HAVE_LIBRETRODB
  4574. strlcat(buf,
  4575. " --scan=PATH|FILE "
  4576. "Import content from path.\n"
  4577. , sizeof(buf));
  4578. #endif
  4579. strlcat(buf,
  4580. " -f, --fullscreen "
  4581. "Start the program in fullscreen regardless of config setting.\n"
  4582. " --set-shader=PATH "
  4583. "Path to a shader (preset) that will be loaded each time content is loaded.\n"
  4584. " "
  4585. " Effectively overrides automatic shader presets.\n"
  4586. " "
  4587. " An empty argument \"\" will disable automatic shader presets.\n"
  4588. , sizeof(buf));
  4589. fputs(buf, stdout);
  4590. buf[0] = '\0';
  4591. printf( " -N, --nodevice=PORT "
  4592. "Disconnects controller device connected to PORT (1 to %d).\n", MAX_USERS);
  4593. printf( " -A, --dualanalog=PORT "
  4594. "Connect a DualAnalog controller to PORT (1 to %d).\n", MAX_USERS);
  4595. printf( " -d, --device=PORT:ID "
  4596. "Connect a generic device into PORT of the device (1 to %d).\n", MAX_USERS);
  4597. strlcat(buf,
  4598. " "
  4599. " Format is PORT:ID, where ID is a number corresponding to the particular device.\n"
  4600. " -M, --sram-mode=MODE "
  4601. "SRAM handling mode. MODE can be:\n"
  4602. " "
  4603. " 'noload-nosave', 'noload-save', 'load-nosave' or 'load-save'.\n"
  4604. " "
  4605. " Note: 'noload-save' implies that save files *WILL BE OVERWRITTEN*.\n"
  4606. , sizeof(buf));
  4607. #ifdef HAVE_NETWORKING
  4608. strlcat(buf,
  4609. " -H, --host "
  4610. "Host netplay as user 1.\n"
  4611. " -C, --connect=HOST "
  4612. "Connect to netplay server as user 2.\n"
  4613. " --port=PORT "
  4614. "Port used to netplay. Default is 55435.\n"
  4615. " --nick=NICK "
  4616. "Picks a username (for use with netplay). Not mandatory.\n"
  4617. " --check-frames=NUMBER "
  4618. "Check frames when using netplay.\n"
  4619. , sizeof(buf));
  4620. #ifdef HAVE_NETWORK_CMD
  4621. strlcat(buf,
  4622. " --command "
  4623. "Sends a command over UDP to an already running program process.\n"
  4624. " "
  4625. " Available commands are listed if command is invalid.\n"
  4626. , sizeof(buf));
  4627. #endif
  4628. #endif
  4629. #ifdef HAVE_BSV_MOVIE
  4630. strlcat(buf,
  4631. " -P, --play-replay=FILE "
  4632. "Playback a replay file.\n"
  4633. " -R, --record-replay=FILE "
  4634. "Start recording a replay file from the beginning.\n"
  4635. " --eof-exit "
  4636. "Exit upon reaching the end of the replay file.\n"
  4637. , sizeof(buf));
  4638. #endif
  4639. strlcat(buf,
  4640. " -r, --record=FILE "
  4641. "Path to record video file. Using mkv extension is recommended.\n"
  4642. " --recordconfig "
  4643. "Path to settings used during recording.\n"
  4644. " --size=WIDTHxHEIGHT "
  4645. "Overrides output video size when recording.\n"
  4646. , sizeof(buf));
  4647. fputs(buf, stdout);
  4648. buf[0] = '\0';
  4649. strlcat(buf,
  4650. " -D, --detach "
  4651. "Detach program from the running console. Not relevant for all platforms.\n"
  4652. " --max-frames=NUMBER "
  4653. "Runs for the specified number of frames, then exits.\n"
  4654. , sizeof(buf));
  4655. #ifdef HAVE_PATCH
  4656. strlcat(buf,
  4657. " -U, --ups=FILE "
  4658. "Specifies path for UPS patch that will be applied to content.\n"
  4659. " --bps=FILE "
  4660. "Specifies path for BPS patch that will be applied to content.\n"
  4661. " --ips=FILE "
  4662. "Specifies path for IPS patch that will be applied to content.\n"
  4663. " --no-patch "
  4664. "Disables all forms of content patching.\n"
  4665. , sizeof(buf));
  4666. #endif
  4667. #ifdef HAVE_SCREENSHOTS
  4668. strlcat(buf,
  4669. " --max-frames-ss "
  4670. "Takes a screenshot at the end of max-frames.\n"
  4671. " --max-frames-ss-path=FILE "
  4672. "Path to save the screenshot to at the end of max-frames.\n"
  4673. , sizeof(buf));
  4674. #endif
  4675. #ifdef HAVE_ACCESSIBILITY
  4676. strlcat(buf,
  4677. " --accessibility "
  4678. "Enables accessibilty for blind users using text-to-speech.\n"
  4679. , sizeof(buf));
  4680. #endif
  4681. strlcat(buf,
  4682. " --load-menu-on-error "
  4683. "Open menu instead of quitting if specified core or content fails to load.\n"
  4684. " -e, --entryslot=NUMBER "
  4685. "Slot from which to load an entry state.\n"
  4686. " -s, --save=PATH "
  4687. "Path for save files (*.srm). (DEPRECATED, use --appendconfig and savefile_directory)\n"
  4688. " -S, --savestate=PATH "
  4689. "Path for the save state files (*.state). (DEPRECATED, use --appendconfig and savestate_directory)\n"
  4690. , sizeof(buf));
  4691. fputs(buf, stdout);
  4692. }
  4693. #ifdef HAVE_DYNAMIC
  4694. static void retroarch_parse_input_libretro_path(const char *path)
  4695. {
  4696. settings_t *settings = config_get_ptr();
  4697. int path_stats = 0;
  4698. const char *path_ext = NULL;
  4699. core_info_t *core_info = NULL;
  4700. const char *core_path = NULL;
  4701. bool core_path_matched = false;
  4702. char tmp_path[PATH_MAX_LENGTH];
  4703. if (string_is_empty(path))
  4704. goto end;
  4705. /* Check if path refers to a built-in core */
  4706. if (string_ends_with_size(path, "builtin",
  4707. strlen(path), STRLEN_CONST("builtin")))
  4708. {
  4709. RARCH_LOG("--libretro argument \"%s\" is a built-in core. Ignoring.\n",
  4710. path);
  4711. return;
  4712. }
  4713. path_stats = path_stat(path);
  4714. /* Check if path is a directory */
  4715. if ((path_stats & RETRO_VFS_STAT_IS_DIRECTORY) != 0)
  4716. {
  4717. path_clear(RARCH_PATH_CORE);
  4718. configuration_set_string(settings,
  4719. settings->paths.directory_libretro, path);
  4720. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_LIBRETRO, NULL);
  4721. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY, NULL);
  4722. RARCH_WARN("Using old --libretro behavior. "
  4723. "Setting libretro_directory to \"%s\" instead.\n",
  4724. path);
  4725. return;
  4726. }
  4727. /* Check if path is a valid file */
  4728. if ((path_stats & RETRO_VFS_STAT_IS_VALID) != 0)
  4729. {
  4730. core_path = path;
  4731. goto end;
  4732. }
  4733. /* If path refers to a core file that does not exist,
  4734. * check for its presence in the user-defined cores
  4735. * directory */
  4736. path_ext = path_get_extension(path);
  4737. if (!string_is_empty(path_ext))
  4738. {
  4739. char core_ext[255];
  4740. core_ext[0] = '\0';
  4741. if (string_is_empty(settings->paths.directory_libretro) ||
  4742. !frontend_driver_get_core_extension(core_ext,
  4743. sizeof(core_ext)) ||
  4744. !string_is_equal(path_ext, core_ext))
  4745. goto end;
  4746. fill_pathname_join_special(tmp_path, settings->paths.directory_libretro,
  4747. path, sizeof(tmp_path));
  4748. if (string_is_empty(tmp_path))
  4749. goto end;
  4750. path_stats = path_stat(tmp_path);
  4751. if ((path_stats & RETRO_VFS_STAT_IS_VALID) != 0 &&
  4752. (path_stats & RETRO_VFS_STAT_IS_DIRECTORY) == 0)
  4753. {
  4754. core_path = tmp_path;
  4755. core_path_matched = true;
  4756. goto end;
  4757. }
  4758. }
  4759. else
  4760. {
  4761. size_t _len;
  4762. /* If path has no extension and contains no path
  4763. * delimiters, check if it is a core 'name', matching
  4764. * an existing file in the cores directory */
  4765. if (find_last_slash(path))
  4766. goto end;
  4767. command_event(CMD_EVENT_CORE_INFO_INIT, NULL);
  4768. _len = strlcpy(tmp_path, path, sizeof(tmp_path));
  4769. if (!string_ends_with_size(tmp_path, "_libretro",
  4770. strlen(tmp_path), STRLEN_CONST("_libretro")))
  4771. {
  4772. tmp_path[_len ] = '_';
  4773. tmp_path[_len+1] = 'l';
  4774. tmp_path[_len+2] = 'i';
  4775. tmp_path[_len+3] = 'b';
  4776. tmp_path[_len+4] = 'r';
  4777. tmp_path[_len+5] = 'e';
  4778. tmp_path[_len+6] = 't';
  4779. tmp_path[_len+7] = 'r';
  4780. tmp_path[_len+8] = 'o';
  4781. tmp_path[_len+9] = '\0';
  4782. }
  4783. if (!core_info_find(tmp_path, &core_info) ||
  4784. string_is_empty(core_info->path))
  4785. goto end;
  4786. core_path = core_info->path;
  4787. core_path_matched = true;
  4788. }
  4789. end:
  4790. if (!string_is_empty(core_path))
  4791. {
  4792. path_set(RARCH_PATH_CORE, core_path);
  4793. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_LIBRETRO, NULL);
  4794. /* We requested an explicit core, so use PLAIN core type. */
  4795. runloop_set_current_core_type(CORE_TYPE_PLAIN, false);
  4796. if (core_path_matched)
  4797. RARCH_LOG("--libretro argument \"%s\" matches core file \"%s\".\n",
  4798. path, core_path);
  4799. }
  4800. else
  4801. RARCH_WARN("--libretro argument \"%s\" is not a file, core name"
  4802. " or directory. Ignoring.\n",
  4803. path ? path : "");
  4804. }
  4805. #endif
  4806. #ifdef HAVE_MAEU
  4807. #ifdef HAVE_LIBRETRODB
  4808. void handle_dbscan_finished(retro_task_t *task,
  4809. void *task_data, void *user_data, const char *err);
  4810. #endif
  4811. #endif
  4812. /**
  4813. * retroarch_parse_input_and_config:
  4814. * @argc : Count of (commandline) arguments.
  4815. * @argv : (Commandline) arguments.
  4816. *
  4817. * Parses (commandline) arguments passed to program and loads the config file,
  4818. * with command line options overriding the config file.
  4819. *
  4820. **/
  4821. static bool retroarch_parse_input_and_config(
  4822. struct rarch_state *p_rarch,
  4823. global_t *global,
  4824. int argc, char *argv[])
  4825. {
  4826. unsigned i;
  4827. static bool first_run = true;
  4828. bool verbosity_enabled = false;
  4829. const char *optstring = NULL;
  4830. bool explicit_menu = false;
  4831. bool cli_active = false;
  4832. bool cli_core_set = false;
  4833. bool cli_content_set = false;
  4834. recording_state_t *recording_st = recording_state_get_ptr();
  4835. video_driver_state_t *video_st = video_state_get_ptr();
  4836. runloop_state_t *runloop_st = runloop_state_get_ptr();
  4837. settings_t *settings = config_get_ptr();
  4838. #ifdef HAVE_ACCESSIBILITY
  4839. access_state_t *access_st = access_state_get_ptr();
  4840. #endif
  4841. #ifdef HAVE_LIBRETRODB
  4842. retro_task_callback_t cb_task_dbscan
  4843. = NULL;
  4844. #endif
  4845. const struct option opts[] = {
  4846. #ifdef HAVE_DYNAMIC
  4847. { "libretro", 1, NULL, 'L' },
  4848. #endif
  4849. { "menu", 0, NULL, RA_OPT_MENU },
  4850. { "help", 0, NULL, 'h' },
  4851. { "save", 1, NULL, 's' },
  4852. { "fullscreen", 0, NULL, 'f' },
  4853. { "record", 1, NULL, 'r' },
  4854. { "recordconfig", 1, NULL, RA_OPT_RECORDCONFIG },
  4855. { "size", 1, NULL, RA_OPT_SIZE },
  4856. { "verbose", 0, NULL, 'v' },
  4857. #ifdef HAVE_CONFIGFILE
  4858. { "config", 1, NULL, 'c' },
  4859. { "appendconfig", 1, NULL, RA_OPT_APPENDCONFIG },
  4860. #endif
  4861. { "nodevice", 1, NULL, 'N' },
  4862. { "dualanalog", 1, NULL, 'A' },
  4863. { "device", 1, NULL, 'd' },
  4864. { "savestate", 1, NULL, 'S' },
  4865. { "set-shader", 1, NULL, RA_OPT_SET_SHADER },
  4866. #ifdef HAVE_BSV_MOVIE
  4867. { "play-replay", 1, NULL, 'P' },
  4868. { "record-replay", 1, NULL, 'R' },
  4869. #endif
  4870. { "sram-mode", 1, NULL, 'M' },
  4871. #ifdef HAVE_NETWORKING
  4872. { "host", 0, NULL, 'H' },
  4873. { "connect", 1, NULL, 'C' },
  4874. { "check-frames", 1, NULL, RA_OPT_CHECK_FRAMES },
  4875. { "port", 1, NULL, RA_OPT_PORT },
  4876. #ifdef HAVE_NETWORK_CMD
  4877. { "command", 1, NULL, RA_OPT_COMMAND },
  4878. #endif
  4879. #endif
  4880. { "nick", 1, NULL, RA_OPT_NICK },
  4881. #ifdef HAVE_PATCH
  4882. { "ups", 1, NULL, 'U' },
  4883. { "bps", 1, NULL, RA_OPT_BPS },
  4884. { "ips", 1, NULL, RA_OPT_IPS },
  4885. { "no-patch", 0, NULL, RA_OPT_NO_PATCH },
  4886. #endif
  4887. { "detach", 0, NULL, 'D' },
  4888. { "features", 0, NULL, RA_OPT_FEATURES },
  4889. { "subsystem", 1, NULL, RA_OPT_SUBSYSTEM },
  4890. { "max-frames", 1, NULL, RA_OPT_MAX_FRAMES },
  4891. { "max-frames-ss", 0, NULL, RA_OPT_MAX_FRAMES_SCREENSHOT },
  4892. { "max-frames-ss-path", 1, NULL, RA_OPT_MAX_FRAMES_SCREENSHOT_PATH },
  4893. { "eof-exit", 0, NULL, RA_OPT_EOF_EXIT },
  4894. { "version", 0, NULL, 'V' /* RA_OPT_VERSION */ },
  4895. { "log-file", 1, NULL, RA_OPT_LOG_FILE },
  4896. { "accessibility", 0, NULL, RA_OPT_ACCESSIBILITY},
  4897. { "load-menu-on-error", 0, NULL, RA_OPT_LOAD_MENU_ON_ERROR },
  4898. { "entryslot", 1, NULL, 'e' },
  4899. #ifdef HAVE_LIBRETRODB
  4900. { "scan", 1, NULL, RA_OPT_DATABASE_SCAN },
  4901. #endif
  4902. { NULL, 0, NULL, 0 }
  4903. };
  4904. if (first_run)
  4905. {
  4906. /* Copy the args into a buffer so launch arguments can be reused */
  4907. for (i = 0; i < (unsigned)argc; i++)
  4908. {
  4909. strlcat(p_rarch->launch_arguments,
  4910. argv[i], sizeof(p_rarch->launch_arguments));
  4911. strlcat(p_rarch->launch_arguments, " ",
  4912. sizeof(p_rarch->launch_arguments));
  4913. }
  4914. string_trim_whitespace_left(p_rarch->launch_arguments);
  4915. string_trim_whitespace_right(p_rarch->launch_arguments);
  4916. first_run = false;
  4917. /* Command line interface is only considered
  4918. * to be 'active' (i.e. used by a third party)
  4919. * if this is the first run (subsequent runs
  4920. * are triggered by RetroArch itself) */
  4921. cli_active = true;
  4922. }
  4923. /* Handling the core type is finicky. Based on the arguments we pass in,
  4924. * we handle it differently.
  4925. * Some current cases which track desired behavior and how it is supposed to work:
  4926. *
  4927. * Dynamically linked RA:
  4928. * ./retroarch -> CORE_TYPE_DUMMY
  4929. * ./retroarch -v -> CORE_TYPE_DUMMY + verbose
  4930. * ./retroarch --menu -> CORE_TYPE_DUMMY
  4931. * ./retroarch --menu -v -> CORE_TYPE_DUMMY + verbose
  4932. * ./retroarch -L contentless-core -> CORE_TYPE_PLAIN
  4933. * ./retroarch -L content-core -> CORE_TYPE_PLAIN + FAIL (This currently crashes)
  4934. * ./retroarch [-L content-core] ROM -> CORE_TYPE_PLAIN
  4935. * ./retroarch <-L or ROM> --menu -> FAIL
  4936. *
  4937. * The heuristic here seems to be that if we use the -L CLI option or
  4938. * optind < argc at the end we should set CORE_TYPE_PLAIN.
  4939. * To handle --menu, we should ensure that CORE_TYPE_DUMMY is still set
  4940. * otherwise, fail early, since the CLI options are non-sensical.
  4941. * We could also simply ignore --menu in this case to be more friendly with
  4942. * bogus arguments.
  4943. */
  4944. if (!(runloop_st->flags & RUNLOOP_FLAG_HAS_SET_CORE))
  4945. runloop_set_current_core_type(CORE_TYPE_DUMMY, false);
  4946. path_clear(RARCH_PATH_SUBSYSTEM);
  4947. retroarch_override_setting_free_state();
  4948. p_rarch->flags &= ~RARCH_FLAGS_HAS_SET_USERNAME;
  4949. #ifdef HAVE_PATCH
  4950. p_rarch->flags &= ~( RARCH_FLAGS_UPS_PREF | RARCH_FLAGS_IPS_PREF
  4951. | RARCH_FLAGS_BPS_PREF);
  4952. *runloop_st->name.ups = '\0';
  4953. *runloop_st->name.bps = '\0';
  4954. *runloop_st->name.ips = '\0';
  4955. #endif
  4956. #ifdef HAVE_CONFIGFILE
  4957. runloop_st->flags &= ~RUNLOOP_FLAG_OVERRIDES_ACTIVE;
  4958. #endif
  4959. global->cli_load_menu_on_error = false;
  4960. /* Make sure we can call retroarch_parse_input several times ... */
  4961. optind = 0;
  4962. optstring = "hs:fvVS:A:U:DN:d:e:"
  4963. BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG CONFIG_FILE_ARG;
  4964. #if defined(WEBOS)
  4965. argv = &(argv[1]);
  4966. argc = argc - 1;
  4967. #endif
  4968. #ifndef HAVE_MENU
  4969. if (argc == 1)
  4970. {
  4971. printf("%s\n", msg_hash_to_str(MSG_NO_ARGUMENTS_SUPPLIED_AND_NO_MENU_BUILTIN));
  4972. retroarch_print_help(argv[0]);
  4973. exit(0);
  4974. }
  4975. #endif
  4976. /* First pass: Read the config file path and any directory overrides, so
  4977. * they're in place when we load the config */
  4978. if (argc)
  4979. {
  4980. for (;;)
  4981. {
  4982. int c = getopt_long(argc, argv, optstring, opts, NULL);
  4983. #if 0
  4984. fprintf(stderr, "c is: %c (%d), optarg is: [%s]\n", c, c, string_is_empty(optarg) ? "" : optarg);
  4985. #endif
  4986. if (c == -1)
  4987. break;
  4988. /* Graceful failure with empty "-" parameter instead of allowing
  4989. * to continue to segmentation fault by trying to load content */
  4990. if (c == 0)
  4991. {
  4992. verbosity_enable();
  4993. fprintf(stderr, "%s\n", msg_hash_to_str(MSG_ERROR_PARSING_ARGUMENTS));
  4994. fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
  4995. exit(EXIT_FAILURE);
  4996. }
  4997. switch (c)
  4998. {
  4999. case 'h':
  5000. retroarch_print_help(argv[0]);
  5001. exit(0);
  5002. case 'V':
  5003. case RA_OPT_VERSION:
  5004. retroarch_print_version();
  5005. exit(0);
  5006. case RA_OPT_FEATURES:
  5007. retroarch_print_features();
  5008. exit(0);
  5009. #ifdef HAVE_CONFIGFILE
  5010. case 'c':
  5011. path_set(RARCH_PATH_CONFIG, optarg);
  5012. break;
  5013. case RA_OPT_APPENDCONFIG:
  5014. path_set(RARCH_PATH_CONFIG_APPEND, optarg);
  5015. break;
  5016. #endif
  5017. case 's':
  5018. strlcpy(runloop_st->name.savefile, optarg,
  5019. sizeof(runloop_st->name.savefile));
  5020. retroarch_override_setting_set(
  5021. RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL);
  5022. break;
  5023. case 'S':
  5024. strlcpy(runloop_st->name.savestate, optarg,
  5025. sizeof(runloop_st->name.savestate));
  5026. strlcpy(runloop_st->name.replay, optarg,
  5027. sizeof(runloop_st->name.replay));
  5028. retroarch_override_setting_set(
  5029. RARCH_OVERRIDE_SETTING_STATE_PATH, NULL);
  5030. break;
  5031. case 'v':
  5032. verbosity_enable();
  5033. retroarch_override_setting_set(
  5034. RARCH_OVERRIDE_SETTING_VERBOSITY, NULL);
  5035. break;
  5036. case RA_OPT_LOG_FILE:
  5037. /* Enable 'log to file' */
  5038. configuration_set_bool(settings,
  5039. settings->bools.log_to_file, true);
  5040. retroarch_override_setting_set(
  5041. RARCH_OVERRIDE_SETTING_LOG_TO_FILE, NULL);
  5042. /* Cache log file path override */
  5043. rarch_log_file_set_override(optarg);
  5044. break;
  5045. case RA_OPT_MENU:
  5046. explicit_menu = true;
  5047. break;
  5048. case RA_OPT_DATABASE_SCAN:
  5049. #ifdef HAVE_LIBRETRODB
  5050. verbosity_enable();
  5051. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_DATABASE_SCAN, NULL);
  5052. #endif
  5053. break;
  5054. /* Must handle '?' otherwise you get an infinite loop */
  5055. case '?':
  5056. frontend_driver_attach_console();
  5057. #ifdef _WIN32
  5058. fprintf(stderr, "\n%s: unrecognized option '%s'\n", argv[0], argv[optind]);
  5059. #endif
  5060. fprintf(stderr, "Try '%s --help' for more information\n", argv[0]);
  5061. exit(EXIT_FAILURE);
  5062. break;
  5063. /* All other arguments are handled in the second pass */
  5064. }
  5065. }
  5066. }
  5067. verbosity_enabled = verbosity_is_enabled();
  5068. /* Enable logging to file if verbosity and log-file arguments were passed.
  5069. * RARCH_OVERRIDE_SETTING_LOG_TO_FILE is set by the RA_OPT_LOG_FILE case above
  5070. * The parameters passed to rarch_log_file_init are hardcoded as the config
  5071. * has not yet been initialized at this point. */
  5072. if (verbosity_enabled && retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_LOG_TO_FILE, NULL))
  5073. rarch_log_file_init(true, false, NULL);
  5074. /* Flush out some states that could have been set
  5075. * by core environment variables. */
  5076. runloop_st->current_core.flags &= ~(RETRO_CORE_FLAG_HAS_SET_INPUT_DESCRIPTORS
  5077. | RETRO_CORE_FLAG_HAS_SET_SUBSYSTEMS);
  5078. /* Load the config file now that we know what it is */
  5079. #ifdef HAVE_CONFIGFILE
  5080. if (!(p_rarch->flags & RARCH_FLAGS_BLOCK_CONFIG_READ))
  5081. #endif
  5082. {
  5083. /* If this is a static build, load salamander
  5084. * config file first (sets RARCH_PATH_CORE) */
  5085. #if !defined(HAVE_DYNAMIC)
  5086. config_load_file_salamander();
  5087. #endif
  5088. config_load(global_get_ptr());
  5089. }
  5090. verbosity_enabled = verbosity_is_enabled();
  5091. /* Init logging after config load only if not overridden by command line argument.
  5092. * This handles when logging is set in the config but not via the --log-file option. */
  5093. if (verbosity_enabled && !retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_LOG_TO_FILE, NULL))
  5094. rarch_log_file_init(
  5095. settings->bools.log_to_file,
  5096. settings->bools.log_to_file_timestamp,
  5097. settings->paths.log_dir);
  5098. /* Second pass: All other arguments override the config file */
  5099. optind = 1;
  5100. if (argc)
  5101. {
  5102. for (;;)
  5103. {
  5104. int c = getopt_long(argc, argv, optstring, opts, NULL);
  5105. if (c == -1)
  5106. break;
  5107. switch (c)
  5108. {
  5109. case 'd':
  5110. {
  5111. unsigned new_port;
  5112. unsigned id = 0;
  5113. struct string_list *list = string_split(optarg, ":");
  5114. int port = 0;
  5115. if (list && list->size == 2)
  5116. {
  5117. port = (int)strtol(list->elems[0].data, NULL, 0);
  5118. id = (unsigned)strtoul(list->elems[1].data, NULL, 0);
  5119. }
  5120. string_list_free(list);
  5121. if (port < 1 || port > MAX_USERS)
  5122. {
  5123. RARCH_ERR("%s\n", msg_hash_to_str(MSG_VALUE_CONNECT_DEVICE_FROM_A_VALID_PORT));
  5124. retroarch_print_help(argv[0]);
  5125. retroarch_fail(1, "retroarch_parse_input()");
  5126. }
  5127. new_port = port - 1;
  5128. input_config_set_device(new_port, id);
  5129. retroarch_override_setting_set(
  5130. RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE, &new_port);
  5131. }
  5132. break;
  5133. case 'A':
  5134. {
  5135. unsigned new_port;
  5136. int port = (int)strtol(optarg, NULL, 0);
  5137. if (port < 1 || port > MAX_USERS)
  5138. {
  5139. RARCH_ERR("Connect dualanalog to a valid port.\n");
  5140. retroarch_print_help(argv[0]);
  5141. retroarch_fail(1, "retroarch_parse_input()");
  5142. }
  5143. new_port = port - 1;
  5144. input_config_set_device(new_port, RETRO_DEVICE_ANALOG);
  5145. retroarch_override_setting_set(
  5146. RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE, &new_port);
  5147. }
  5148. break;
  5149. case 'f':
  5150. video_st->flags |= VIDEO_FLAG_FORCE_FULLSCREEN;
  5151. break;
  5152. case 'N':
  5153. {
  5154. unsigned new_port;
  5155. int port = (int)strtol(optarg, NULL, 0);
  5156. if (port < 1 || port > MAX_USERS)
  5157. {
  5158. RARCH_ERR("%s\n",
  5159. msg_hash_to_str(MSG_DISCONNECT_DEVICE_FROM_A_VALID_PORT));
  5160. retroarch_print_help(argv[0]);
  5161. retroarch_fail(1, "retroarch_parse_input()");
  5162. }
  5163. new_port = port - 1;
  5164. input_config_set_device(new_port, RETRO_DEVICE_NONE);
  5165. retroarch_override_setting_set(
  5166. RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE, &new_port);
  5167. }
  5168. break;
  5169. case 'r':
  5170. strlcpy(recording_st->path, optarg,
  5171. sizeof(recording_st->path));
  5172. if (recording_st->enable)
  5173. recording_st->enable = true;
  5174. break;
  5175. case RA_OPT_SET_SHADER:
  5176. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  5177. /* disable auto-shaders */
  5178. if (string_is_empty(optarg))
  5179. {
  5180. video_st->flags |= VIDEO_FLAG_CLI_SHADER_DISABLE;
  5181. break;
  5182. }
  5183. /* rebase on shader directory */
  5184. if (path_is_absolute(optarg))
  5185. strlcpy(video_st->cli_shader_path, optarg,
  5186. sizeof(video_st->cli_shader_path));
  5187. else
  5188. fill_pathname_join_special(video_st->cli_shader_path,
  5189. settings->paths.directory_video_shader,
  5190. optarg, sizeof(video_st->cli_shader_path));
  5191. #endif
  5192. break;
  5193. #ifdef HAVE_DYNAMIC
  5194. case 'L':
  5195. retroarch_parse_input_libretro_path(optarg);
  5196. break;
  5197. #endif
  5198. case 'P':
  5199. #ifdef HAVE_BSV_MOVIE
  5200. {
  5201. input_driver_state_t *input_st = input_state_get_ptr();
  5202. strlcpy(input_st->bsv_movie_state.movie_start_path, optarg,
  5203. sizeof(input_st->bsv_movie_state.movie_start_path));
  5204. input_st->bsv_movie_state.flags |=
  5205. BSV_FLAG_MOVIE_START_PLAYBACK;
  5206. input_st->bsv_movie_state.flags &=
  5207. ~BSV_FLAG_MOVIE_START_RECORDING;
  5208. }
  5209. #endif
  5210. break;
  5211. case 'R':
  5212. #ifdef HAVE_BSV_MOVIE
  5213. {
  5214. input_driver_state_t *input_st = input_state_get_ptr();
  5215. strlcpy(input_st->bsv_movie_state.movie_start_path, optarg,
  5216. sizeof(input_st->bsv_movie_state.movie_start_path));
  5217. input_st->bsv_movie_state.flags &=
  5218. ~BSV_FLAG_MOVIE_START_PLAYBACK;
  5219. input_st->bsv_movie_state.flags |=
  5220. BSV_FLAG_MOVIE_START_RECORDING;
  5221. }
  5222. #endif
  5223. break;
  5224. case 'M':
  5225. if (string_is_equal(optarg, "noload-nosave"))
  5226. runloop_st->flags |= RUNLOOP_FLAG_IS_SRAM_LOAD_DISABLED
  5227. | RUNLOOP_FLAG_IS_SRAM_SAVE_DISABLED;
  5228. else if (string_is_equal(optarg, "noload-save"))
  5229. runloop_st->flags |= RUNLOOP_FLAG_IS_SRAM_LOAD_DISABLED;
  5230. else if (string_is_equal(optarg, "load-nosave"))
  5231. runloop_st->flags |= RUNLOOP_FLAG_IS_SRAM_SAVE_DISABLED;
  5232. else if (string_is_not_equal(optarg, "load-save"))
  5233. {
  5234. RARCH_ERR("Invalid argument in --sram-mode.\n");
  5235. retroarch_print_help(argv[0]);
  5236. retroarch_fail(1, "retroarch_parse_input()");
  5237. }
  5238. break;
  5239. #ifdef HAVE_NETWORKING
  5240. case 'H':
  5241. retroarch_override_setting_set(
  5242. RARCH_OVERRIDE_SETTING_NETPLAY_MODE, NULL);
  5243. netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_SERVER, NULL);
  5244. break;
  5245. case 'C':
  5246. retroarch_override_setting_set(
  5247. RARCH_OVERRIDE_SETTING_NETPLAY_MODE, NULL);
  5248. netplay_driver_ctl(RARCH_NETPLAY_CTL_ENABLE_CLIENT, NULL);
  5249. p_rarch->connect_host = strdup(optarg);
  5250. break;
  5251. case RA_OPT_CHECK_FRAMES:
  5252. retroarch_override_setting_set(
  5253. RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES, NULL);
  5254. configuration_set_int(settings,
  5255. settings->ints.netplay_check_frames,
  5256. (int)strtoul(optarg, NULL, 0));
  5257. break;
  5258. case RA_OPT_PORT:
  5259. retroarch_override_setting_set(
  5260. RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT, NULL);
  5261. configuration_set_uint(settings,
  5262. settings->uints.netplay_port,
  5263. (int)strtoul(optarg, NULL, 0));
  5264. break;
  5265. #ifdef HAVE_NETWORK_CMD
  5266. case RA_OPT_COMMAND:
  5267. #ifdef HAVE_COMMAND
  5268. if (command_network_send((const char*)optarg))
  5269. exit(0);
  5270. else
  5271. retroarch_fail(1, "network_cmd_send()");
  5272. #endif
  5273. break;
  5274. #endif
  5275. #endif
  5276. case RA_OPT_BPS:
  5277. #ifdef HAVE_PATCH
  5278. strlcpy(runloop_st->name.bps, optarg,
  5279. sizeof(runloop_st->name.bps));
  5280. p_rarch->flags |= RARCH_FLAGS_BPS_PREF;
  5281. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_BPS_PREF, NULL);
  5282. #endif
  5283. break;
  5284. case 'U':
  5285. #ifdef HAVE_PATCH
  5286. strlcpy(runloop_st->name.ups, optarg,
  5287. sizeof(runloop_st->name.ups));
  5288. p_rarch->flags |= RARCH_FLAGS_UPS_PREF;
  5289. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_UPS_PREF, NULL);
  5290. #endif
  5291. break;
  5292. case RA_OPT_IPS:
  5293. #ifdef HAVE_PATCH
  5294. strlcpy(runloop_st->name.ips, optarg,
  5295. sizeof(runloop_st->name.ips));
  5296. p_rarch->flags |= RARCH_FLAGS_IPS_PREF;
  5297. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_IPS_PREF, NULL);
  5298. #endif
  5299. break;
  5300. case RA_OPT_NO_PATCH:
  5301. #ifdef HAVE_PATCH
  5302. runloop_st->flags |= RUNLOOP_FLAG_PATCH_BLOCKED;
  5303. #endif
  5304. break;
  5305. case 'D':
  5306. frontend_driver_detach_console();
  5307. break;
  5308. case RA_OPT_MENU:
  5309. explicit_menu = true;
  5310. break;
  5311. case RA_OPT_NICK:
  5312. p_rarch->flags |= RARCH_FLAGS_HAS_SET_USERNAME;
  5313. configuration_set_string(settings,
  5314. settings->paths.username, optarg);
  5315. break;
  5316. case RA_OPT_SIZE:
  5317. if (sscanf(optarg, "%ux%u",
  5318. &recording_st->width,
  5319. &recording_st->height) != 2)
  5320. {
  5321. RARCH_ERR("Wrong format for --size.\n");
  5322. retroarch_print_help(argv[0]);
  5323. retroarch_fail(1, "retroarch_parse_input()");
  5324. }
  5325. break;
  5326. case RA_OPT_RECORDCONFIG:
  5327. strlcpy(recording_st->config, optarg,
  5328. sizeof(recording_st->config));
  5329. break;
  5330. case RA_OPT_MAX_FRAMES:
  5331. runloop_st->max_frames = (unsigned)strtoul(optarg, NULL, 10);
  5332. break;
  5333. case RA_OPT_MAX_FRAMES_SCREENSHOT:
  5334. #ifdef HAVE_SCREENSHOTS
  5335. runloop_st->flags |= RUNLOOP_FLAG_MAX_FRAMES_SCREENSHOT;
  5336. #endif
  5337. break;
  5338. case RA_OPT_MAX_FRAMES_SCREENSHOT_PATH:
  5339. #ifdef HAVE_SCREENSHOTS
  5340. strlcpy(runloop_st->max_frames_screenshot_path,
  5341. optarg,
  5342. sizeof(runloop_st->max_frames_screenshot_path));
  5343. #endif
  5344. break;
  5345. case RA_OPT_SUBSYSTEM:
  5346. path_set(RARCH_PATH_SUBSYSTEM, optarg);
  5347. break;
  5348. case RA_OPT_EOF_EXIT:
  5349. #ifdef HAVE_BSV_MOVIE
  5350. {
  5351. input_driver_state_t *input_st = input_state_get_ptr();
  5352. input_st->bsv_movie_state.flags |= BSV_FLAG_MOVIE_EOF_EXIT;
  5353. }
  5354. #endif
  5355. break;
  5356. case 'h':
  5357. case 'V':
  5358. case RA_OPT_VERSION:
  5359. case RA_OPT_FEATURES:
  5360. #ifdef HAVE_CONFIGFILE
  5361. case 'c':
  5362. case RA_OPT_APPENDCONFIG:
  5363. #endif
  5364. case 's':
  5365. case 'S':
  5366. case 'v':
  5367. case RA_OPT_LOG_FILE:
  5368. break; /* Handled in the first pass */
  5369. case '?':
  5370. retroarch_print_help(argv[0]);
  5371. retroarch_fail(1, "retroarch_parse_input()");
  5372. case RA_OPT_ACCESSIBILITY:
  5373. #ifdef HAVE_ACCESSIBILITY
  5374. access_st->enabled = true;
  5375. #endif
  5376. break;
  5377. case RA_OPT_LOAD_MENU_ON_ERROR:
  5378. global->cli_load_menu_on_error = true;
  5379. break;
  5380. case 'e':
  5381. {
  5382. unsigned entry_state_slot = (unsigned)strtoul(optarg, NULL, 0);
  5383. if (entry_state_slot)
  5384. runloop_st->entry_state_slot = entry_state_slot;
  5385. else
  5386. RARCH_WARN("--entryslot argument \"%s\" is not a valid "
  5387. "entry state slot index. Ignoring.\n", optarg);
  5388. }
  5389. break;
  5390. case RA_OPT_DATABASE_SCAN:
  5391. #ifdef HAVE_LIBRETRODB
  5392. {
  5393. settings_t *settings = config_get_ptr();
  5394. bool show_hidden_files = settings->bools.show_hidden_files;
  5395. const char *directory_playlist = settings->paths.directory_playlist;
  5396. const char *path_content_db = settings->paths.path_content_database;
  5397. int reinit_flags = DRIVERS_CMD_ALL &
  5398. ~(DRIVER_VIDEO_MASK | DRIVER_AUDIO_MASK | DRIVER_INPUT_MASK | DRIVER_MIDI_MASK);
  5399. drivers_init(settings, reinit_flags, false);
  5400. retroarch_init_task_queue();
  5401. #ifdef HAVE_MAEU
  5402. if (explicit_menu)
  5403. cb_task_dbscan = handle_dbscan_finished;
  5404. #else
  5405. if (explicit_menu)
  5406. cb_task_dbscan = NULL;
  5407. #endif
  5408. task_push_dbscan(
  5409. directory_playlist,
  5410. path_content_db,
  5411. optarg, path_is_directory(optarg),
  5412. show_hidden_files,
  5413. cb_task_dbscan);
  5414. if (!explicit_menu)
  5415. {
  5416. task_queue_wait(NULL, NULL);
  5417. driver_uninit(DRIVERS_CMD_ALL);
  5418. exit(0);
  5419. }
  5420. }
  5421. #endif
  5422. break;
  5423. default:
  5424. RARCH_ERR("%s\n", msg_hash_to_str(MSG_ERROR_PARSING_ARGUMENTS));
  5425. retroarch_fail(1, "retroarch_parse_input()");
  5426. }
  5427. }
  5428. }
  5429. #ifdef HAVE_GIT_VERSION
  5430. RARCH_LOG("RetroArch %s (Git %s)\n",
  5431. PACKAGE_VERSION, retroarch_git_version);
  5432. #endif
  5433. if (explicit_menu)
  5434. {
  5435. if (optind < argc)
  5436. {
  5437. RARCH_ERR("--menu was used, but content file was passed as well.\n");
  5438. retroarch_fail(1, "retroarch_parse_input()");
  5439. }
  5440. #ifdef HAVE_DYNAMIC
  5441. else
  5442. {
  5443. /* Allow stray -L arguments to go through to workaround cases
  5444. * where it's used as "config file".
  5445. *
  5446. * This seems to still be the case for Android, which
  5447. * should be properly fixed. */
  5448. runloop_set_current_core_type(CORE_TYPE_DUMMY, false);
  5449. }
  5450. #endif
  5451. }
  5452. if (optind < argc)
  5453. {
  5454. bool subsystem_path_is_empty = path_is_empty(RARCH_PATH_SUBSYSTEM);
  5455. /* We requested explicit ROM, so use PLAIN core type. */
  5456. runloop_set_current_core_type(CORE_TYPE_PLAIN, false);
  5457. if (subsystem_path_is_empty)
  5458. path_set(RARCH_PATH_NAMES, (const char*)argv[optind]);
  5459. else
  5460. runloop_path_set_special(argv + optind, argc - optind);
  5461. /* Register that content has been set via the
  5462. * command line interface */
  5463. cli_content_set = true;
  5464. }
  5465. else if (runloop_st->entry_state_slot)
  5466. {
  5467. runloop_st->entry_state_slot = 0;
  5468. RARCH_WARN("Trying to load entry state without content. Ignoring.\n");
  5469. }
  5470. #ifdef HAVE_BSV_MOVIE
  5471. if (runloop_st->entry_state_slot)
  5472. {
  5473. input_driver_state_t *input_st = input_state_get_ptr();
  5474. if (input_st->bsv_movie_state.flags & BSV_FLAG_MOVIE_START_PLAYBACK)
  5475. {
  5476. runloop_st->entry_state_slot = 0;
  5477. RARCH_WARN("Trying to load entry state while replay playback is active. Ignoring entry state.\n");
  5478. }
  5479. }
  5480. #endif
  5481. /* Check whether a core has been set via the
  5482. * command line interface */
  5483. cli_core_set = (runloop_st->current_core_type != CORE_TYPE_DUMMY);
  5484. /* Update global 'content launched from command
  5485. * line' status flag */
  5486. global->launched_from_cli = cli_active && (cli_core_set || cli_content_set);
  5487. /* Copy SRM/state dirs used, so they can be reused on reentrancy. */
  5488. if (retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH, NULL) &&
  5489. path_is_directory(runloop_st->name.savefile))
  5490. dir_set(RARCH_DIR_SAVEFILE, runloop_st->name.savefile);
  5491. if (retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH, NULL) &&
  5492. path_is_directory(runloop_st->name.savestate))
  5493. dir_set(RARCH_DIR_SAVESTATE, runloop_st->name.savestate);
  5494. return verbosity_enabled;
  5495. }
  5496. /**
  5497. * retroarch_validate_cpu_features:
  5498. *
  5499. * Validates CPU features for given processor architecture.
  5500. * Make sure we haven't compiled for something we cannot run.
  5501. * Ideally, code would get swapped out depending on CPU support,
  5502. * but this will do for now.
  5503. **/
  5504. static void retroarch_validate_cpu_features(void)
  5505. {
  5506. uint64_t cpu = cpu_features_get();
  5507. (void)cpu;
  5508. #ifdef __MMX__
  5509. if (!(cpu & RETRO_SIMD_MMX))
  5510. FAIL_CPU("MMX");
  5511. #endif
  5512. #ifdef __SSE__
  5513. if (!(cpu & RETRO_SIMD_SSE))
  5514. FAIL_CPU("SSE");
  5515. #endif
  5516. #ifdef __SSE2__
  5517. if (!(cpu & RETRO_SIMD_SSE2))
  5518. FAIL_CPU("SSE2");
  5519. #endif
  5520. #ifdef __AVX__
  5521. if (!(cpu & RETRO_SIMD_AVX))
  5522. FAIL_CPU("AVX");
  5523. #endif
  5524. }
  5525. /**
  5526. * retroarch_main_init:
  5527. * @argc : Count of (commandline) arguments.
  5528. * @argv : (Commandline) arguments.
  5529. *
  5530. * Initializes the program.
  5531. *
  5532. * @return true on success, otherwise false if there was an error.
  5533. **/
  5534. bool retroarch_main_init(int argc, char *argv[])
  5535. {
  5536. #if defined(DEBUG) && defined(HAVE_DRMINGW)
  5537. char log_file_name[128];
  5538. #endif
  5539. bool verbosity_enabled = false;
  5540. bool init_failed = false;
  5541. struct rarch_state *p_rarch = &rarch_st;
  5542. runloop_state_t *runloop_st = runloop_state_get_ptr();
  5543. input_driver_state_t
  5544. *input_st = input_state_get_ptr();
  5545. video_driver_state_t*video_st = video_state_get_ptr();
  5546. settings_t *settings = config_get_ptr();
  5547. recording_state_t
  5548. *recording_st = recording_state_get_ptr();
  5549. global_t *global = global_get_ptr();
  5550. #ifdef HAVE_ACCESSIBILITY
  5551. access_state_t *access_st = access_state_get_ptr();
  5552. bool accessibility_enable = false;
  5553. unsigned accessibility_narrator_speech_speed = 0;
  5554. #endif
  5555. #ifdef HAVE_MENU
  5556. struct menu_state *menu_st = menu_state_get_ptr();
  5557. #endif
  5558. input_st->osk_idx = OSK_LOWERCASE_LATIN;
  5559. video_st->flags |= VIDEO_FLAG_ACTIVE;
  5560. audio_state_get_ptr()->flags |= AUDIO_FLAG_ACTIVE;
  5561. if (setjmp(global->error_sjlj_context) > 0)
  5562. {
  5563. RARCH_ERR("%s: \"%s\"\n",
  5564. msg_hash_to_str(MSG_FATAL_ERROR_RECEIVED_IN),
  5565. global->error_string);
  5566. goto error;
  5567. }
  5568. global->error_on_init = true;
  5569. /* Have to initialise non-file logging once at the start... */
  5570. retro_main_log_file_init(NULL, false);
  5571. verbosity_enabled = retroarch_parse_input_and_config(p_rarch,
  5572. global_get_ptr(), argc, argv);
  5573. #ifdef HAVE_ACCESSIBILITY
  5574. accessibility_enable = settings->bools.accessibility_enable;
  5575. accessibility_narrator_speech_speed = settings->uints.accessibility_narrator_speech_speed;
  5576. /* State that the narrator is on, and also include the first menu
  5577. item we're on at startup. */
  5578. if (is_accessibility_enabled(
  5579. accessibility_enable,
  5580. access_st->enabled))
  5581. accessibility_speak_priority(
  5582. accessibility_enable,
  5583. accessibility_narrator_speech_speed,
  5584. "RetroArch accessibility on. Main Menu Load Core.",
  5585. 10);
  5586. #endif
  5587. if (verbosity_enabled)
  5588. {
  5589. {
  5590. char str_output[256];
  5591. const char *cpu_model = NULL;
  5592. str_output[0] = '\0';
  5593. cpu_model = frontend_driver_get_cpu_model_name();
  5594. strlcpy(str_output,
  5595. "=== Build =======================================\n",
  5596. sizeof(str_output));
  5597. if (!string_is_empty(cpu_model))
  5598. {
  5599. size_t _len;
  5600. strlcat(str_output, FILE_PATH_LOG_INFO " CPU Model Name: ",
  5601. sizeof(str_output));
  5602. _len = strlcat(str_output, cpu_model, sizeof(str_output));
  5603. str_output[_len ] = '\n';
  5604. str_output[_len+1] = '\0';
  5605. }
  5606. RARCH_LOG_OUTPUT("%s", str_output);
  5607. }
  5608. {
  5609. char str_output[256];
  5610. char str[128];
  5611. retroarch_get_capabilities(RARCH_CAPABILITIES_CPU, str, sizeof(str), 0);
  5612. #ifdef HAVE_GIT_VERSION
  5613. snprintf(str_output, sizeof(str_output),
  5614. "%s: %s" "\n"
  5615. FILE_PATH_LOG_INFO " Version: " PACKAGE_VERSION "\n"
  5616. FILE_PATH_LOG_INFO " Git: %s" "\n"
  5617. FILE_PATH_LOG_INFO " Built: " __DATE__ "\n"
  5618. FILE_PATH_LOG_INFO " =================================================\n",
  5619. msg_hash_to_str(MSG_CAPABILITIES),
  5620. str,
  5621. retroarch_git_version
  5622. );
  5623. #else
  5624. snprintf(str_output, sizeof(str_output),
  5625. "%s: %s" "\n"
  5626. FILE_PATH_LOG_INFO " Version: " PACKAGE_VERSION "\n"
  5627. FILE_PATH_LOG_INFO " Built: " __DATE__ "\n"
  5628. FILE_PATH_LOG_INFO " =================================================\n",
  5629. msg_hash_to_str(MSG_CAPABILITIES),
  5630. str);
  5631. #endif
  5632. RARCH_LOG_OUTPUT("%s", str_output);
  5633. }
  5634. }
  5635. #if defined(DEBUG) && defined(HAVE_DRMINGW)
  5636. RARCH_LOG_OUTPUT("Initializing Dr.MingW Exception handler\n");
  5637. fill_str_dated_filename(log_file_name, "crash",
  5638. "log", sizeof(log_file_name));
  5639. ExcHndlInit();
  5640. ExcHndlSetLogFileNameA(log_file_name);
  5641. #endif
  5642. retroarch_validate_cpu_features();
  5643. retroarch_init_task_queue();
  5644. {
  5645. const char *fullpath = path_get(RARCH_PATH_CONTENT);
  5646. if (!string_is_empty(fullpath))
  5647. {
  5648. enum rarch_content_type cont_type = path_is_media_type(fullpath);
  5649. #ifdef HAVE_IMAGEVIEWER
  5650. bool builtin_imageviewer = settings->bools.multimedia_builtin_imageviewer_enable;
  5651. #endif
  5652. bool builtin_mediaplayer = settings->bools.multimedia_builtin_mediaplayer_enable;
  5653. switch (cont_type)
  5654. {
  5655. case RARCH_CONTENT_MOVIE:
  5656. case RARCH_CONTENT_MUSIC:
  5657. if (builtin_mediaplayer)
  5658. {
  5659. /* TODO/FIXME - it needs to become possible to
  5660. * switch between FFmpeg and MPV at runtime */
  5661. #if defined(HAVE_MPV)
  5662. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_LIBRETRO, NULL);
  5663. runloop_set_current_core_type(CORE_TYPE_MPV, false);
  5664. #elif defined(HAVE_FFMPEG)
  5665. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_LIBRETRO, NULL);
  5666. runloop_set_current_core_type(CORE_TYPE_FFMPEG, false);
  5667. #endif
  5668. }
  5669. break;
  5670. #ifdef HAVE_IMAGEVIEWER
  5671. case RARCH_CONTENT_IMAGE:
  5672. if (builtin_imageviewer)
  5673. {
  5674. retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_LIBRETRO, NULL);
  5675. runloop_set_current_core_type(CORE_TYPE_IMAGEVIEWER, false);
  5676. }
  5677. break;
  5678. #endif
  5679. default:
  5680. break;
  5681. }
  5682. }
  5683. }
  5684. /* Pre-initialize all drivers
  5685. * Attempts to find a default driver for
  5686. * all driver types.
  5687. */
  5688. if (!(audio_driver_find_driver(settings,
  5689. "audio driver", verbosity_enabled)))
  5690. retroarch_fail(1, "audio_driver_find()");
  5691. if (!video_driver_find_driver(settings,
  5692. "video driver", verbosity_enabled))
  5693. retroarch_fail(1, "video_driver_find_driver()");
  5694. if (!input_driver_find_driver(settings,
  5695. "input driver", verbosity_enabled))
  5696. retroarch_fail(1, "input_driver_find_driver()");
  5697. if (!camera_driver_find_driver("camera driver", verbosity_enabled))
  5698. retroarch_fail(1, "find_camera_driver()");
  5699. #ifdef HAVE_BLUETOOTH
  5700. bluetooth_driver_ctl(RARCH_BLUETOOTH_CTL_FIND_DRIVER, NULL);
  5701. #endif
  5702. #ifdef HAVE_WIFI
  5703. wifi_driver_ctl(RARCH_WIFI_CTL_FIND_DRIVER, NULL);
  5704. #endif
  5705. location_driver_find_driver(settings,
  5706. "location driver", verbosity_enabled);
  5707. #ifdef HAVE_MENU
  5708. {
  5709. if (!(menu_st->driver_ctx = menu_driver_find_driver(settings,
  5710. "menu driver", verbosity_enabled)))
  5711. retroarch_fail(1, "menu_driver_find_driver()");
  5712. }
  5713. #endif
  5714. /* Enforce stored brightness if needed */
  5715. if (frontend_driver_can_set_screen_brightness())
  5716. frontend_driver_set_screen_brightness(settings->uints.screen_brightness);
  5717. /* Attempt to initialize core */
  5718. if (runloop_st->flags & RUNLOOP_FLAG_HAS_SET_CORE)
  5719. {
  5720. runloop_st->flags &= ~RUNLOOP_FLAG_HAS_SET_CORE;
  5721. if (!command_event(CMD_EVENT_CORE_INIT,
  5722. &runloop_st->explicit_current_core_type))
  5723. init_failed = true;
  5724. }
  5725. else if (!command_event(CMD_EVENT_CORE_INIT,
  5726. &runloop_st->current_core_type))
  5727. init_failed = true;
  5728. /* Handle core initialization failure */
  5729. if (init_failed)
  5730. {
  5731. #ifdef HAVE_DYNAMIC
  5732. /* Check if menu was active prior to core initialization */
  5733. if ( !global->launched_from_cli
  5734. || global->cli_load_menu_on_error
  5735. #ifdef HAVE_MENU
  5736. || (menu_st->flags & MENU_ST_FLAG_ALIVE)
  5737. #endif
  5738. )
  5739. #endif
  5740. {
  5741. /* Before initialising the dummy core, ensure
  5742. * that we:
  5743. * - Unload any active input remaps
  5744. * - Disable any active config overrides */
  5745. if ( (runloop_st->flags & RUNLOOP_FLAG_REMAPS_CORE_ACTIVE)
  5746. || (runloop_st->flags & RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE)
  5747. || (runloop_st->flags & RUNLOOP_FLAG_REMAPS_GAME_ACTIVE)
  5748. || !string_is_empty(runloop_st->name.remapfile)
  5749. )
  5750. {
  5751. input_remapping_deinit(false);
  5752. input_remapping_set_defaults(true);
  5753. }
  5754. else
  5755. input_remapping_restore_global_config(true);
  5756. #ifdef HAVE_CONFIGFILE
  5757. if (runloop_st->flags & RUNLOOP_FLAG_OVERRIDES_ACTIVE)
  5758. {
  5759. /* Reload the original config */
  5760. config_unload_override();
  5761. }
  5762. #endif
  5763. #ifdef HAVE_DYNAMIC
  5764. /* Ensure that currently loaded core is properly
  5765. * deinitialised */
  5766. if (runloop_st->current_core_type != CORE_TYPE_DUMMY)
  5767. command_event(CMD_EVENT_CORE_DEINIT, NULL);
  5768. #endif
  5769. /* Attempt initializing dummy core */
  5770. runloop_st->current_core_type = CORE_TYPE_DUMMY;
  5771. if (!command_event(CMD_EVENT_CORE_INIT, &runloop_st->current_core_type))
  5772. goto error;
  5773. }
  5774. #ifdef HAVE_DYNAMIC
  5775. else /* Fall back to regular error handling */
  5776. goto error;
  5777. #endif
  5778. }
  5779. #ifdef HAVE_CHEATS
  5780. cheat_manager_state_free();
  5781. command_event_init_cheats(
  5782. settings->bools.apply_cheats_after_load,
  5783. settings->paths.path_cheat_database,
  5784. #ifdef HAVE_BSV_MOVIE
  5785. input_st->bsv_movie_state_handle
  5786. #else
  5787. NULL
  5788. #endif
  5789. );
  5790. #endif
  5791. drivers_init(settings, DRIVERS_CMD_ALL, verbosity_enabled);
  5792. #ifdef HAVE_COMMAND
  5793. input_driver_deinit_command(input_st);
  5794. input_driver_init_command(input_st, settings);
  5795. #endif
  5796. #ifdef HAVE_NETWORKGAMEPAD
  5797. if (input_st->remote)
  5798. input_remote_free(input_st->remote,
  5799. settings->uints.input_max_users);
  5800. input_st->remote = NULL;
  5801. if (settings->bools.network_remote_enable)
  5802. input_st->remote = input_driver_init_remote(
  5803. settings,
  5804. settings->uints.input_max_users);
  5805. #endif
  5806. input_mapper_reset(&input_st->mapper);
  5807. #ifdef HAVE_REWIND
  5808. command_event(CMD_EVENT_REWIND_INIT, NULL);
  5809. #endif
  5810. command_event(CMD_EVENT_CONTROLLER_INIT, NULL);
  5811. if (!string_is_empty(recording_st->path))
  5812. command_event(CMD_EVENT_RECORD_INIT, NULL);
  5813. command_event(CMD_EVENT_SET_PER_GAME_RESOLUTION, NULL);
  5814. global->error_on_init = false;
  5815. runloop_st->flags |= RUNLOOP_FLAG_IS_INITED;
  5816. #ifdef HAVE_DISCORD
  5817. {
  5818. discord_state_t *discord_st = discord_state_get_ptr();
  5819. if (command_event(CMD_EVENT_DISCORD_INIT, NULL))
  5820. discord_st->inited = true;
  5821. }
  5822. #endif
  5823. #ifdef HAVE_PRESENCE
  5824. {
  5825. presence_userdata_t userdata;
  5826. userdata.status = PRESENCE_MENU;
  5827. command_event(CMD_EVENT_PRESENCE_UPDATE, &userdata);
  5828. }
  5829. #endif
  5830. #if defined(HAVE_AUDIOMIXER)
  5831. audio_driver_load_system_sounds();
  5832. #endif
  5833. #ifdef HAVE_RUNAHEAD
  5834. #ifdef HAVE_NETWORKING
  5835. if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_ENABLED, NULL))
  5836. #endif
  5837. preempt_init(runloop_st);
  5838. #endif
  5839. return true;
  5840. error:
  5841. command_event(CMD_EVENT_CORE_DEINIT, NULL);
  5842. runloop_st->flags &= ~RUNLOOP_FLAG_IS_INITED;
  5843. return false;
  5844. }
  5845. void retroarch_init_task_queue(void)
  5846. {
  5847. #ifdef HAVE_THREADS
  5848. settings_t *settings = config_get_ptr();
  5849. bool threaded_enable = settings->bools.threaded_data_runloop_enable;
  5850. #else
  5851. bool threaded_enable = false;
  5852. #endif
  5853. task_queue_deinit();
  5854. task_queue_init(threaded_enable, runloop_task_msg_queue_push);
  5855. }
  5856. bool retroarch_ctl(enum rarch_ctl_state state, void *data)
  5857. {
  5858. struct rarch_state *p_rarch = &rarch_st;
  5859. runloop_state_t *runloop_st = runloop_state_get_ptr();
  5860. switch(state)
  5861. {
  5862. case RARCH_CTL_HAS_SET_SUBSYSTEMS:
  5863. return ((runloop_st->current_core.flags &
  5864. RETRO_CORE_FLAG_HAS_SET_SUBSYSTEMS) > 0);
  5865. #ifdef HAVE_BSV_MOVIE
  5866. case RARCH_CTL_BSV_MOVIE_IS_INITED:
  5867. return (input_state_get_ptr()->bsv_movie_state_handle != NULL);
  5868. #endif
  5869. #ifdef HAVE_PATCH
  5870. case RARCH_CTL_UNSET_BPS_PREF:
  5871. p_rarch->flags &= ~RARCH_FLAGS_BPS_PREF;
  5872. break;
  5873. case RARCH_CTL_UNSET_UPS_PREF:
  5874. p_rarch->flags &= ~RARCH_FLAGS_UPS_PREF;
  5875. break;
  5876. case RARCH_CTL_UNSET_IPS_PREF:
  5877. p_rarch->flags &= ~RARCH_FLAGS_IPS_PREF;
  5878. break;
  5879. #endif
  5880. case RARCH_CTL_IS_DUMMY_CORE:
  5881. return runloop_st->current_core_type == CORE_TYPE_DUMMY;
  5882. case RARCH_CTL_IS_CORE_LOADED:
  5883. {
  5884. const char *core_path = (const char*)data;
  5885. const char *core_file = path_basename_nocompression(core_path);
  5886. if (!string_is_empty(core_file))
  5887. {
  5888. /* Get loaded core file name */
  5889. const char *loaded_core_file = path_basename_nocompression(
  5890. path_get(RARCH_PATH_CORE));
  5891. /* Check whether specified core and currently
  5892. * loaded core are the same */
  5893. if (!string_is_empty(loaded_core_file))
  5894. if (string_is_equal(core_file, loaded_core_file))
  5895. return true;
  5896. }
  5897. }
  5898. return false;
  5899. #if defined(HAVE_RUNAHEAD) && (defined(HAVE_DYNAMIC) || defined(HAVE_DYLIB))
  5900. case RARCH_CTL_IS_SECOND_CORE_AVAILABLE:
  5901. return
  5902. (runloop_st->flags & RUNLOOP_FLAG_CORE_RUNNING)
  5903. && (runloop_st->flags & RUNLOOP_FLAG_RUNAHEAD_SECONDARY_CORE_AVAILABLE);
  5904. case RARCH_CTL_IS_SECOND_CORE_LOADED:
  5905. return
  5906. (runloop_st->flags & RUNLOOP_FLAG_CORE_RUNNING)
  5907. && (runloop_st->secondary_lib_handle != NULL);
  5908. #endif
  5909. case RARCH_CTL_MAIN_DEINIT:
  5910. {
  5911. input_driver_state_t *input_st = input_state_get_ptr();
  5912. if (!(runloop_st->flags & RUNLOOP_FLAG_IS_INITED))
  5913. return false;
  5914. command_event(CMD_EVENT_NETPLAY_DEINIT, NULL);
  5915. #ifdef HAVE_COMMAND
  5916. input_driver_deinit_command(input_st);
  5917. #endif
  5918. #ifdef HAVE_NETWORKGAMEPAD
  5919. if (input_st->remote)
  5920. input_remote_free(input_st->remote,
  5921. config_get_ptr()->uints.input_max_users);
  5922. input_st->remote = NULL;
  5923. #endif
  5924. input_mapper_reset(&input_st->mapper);
  5925. #ifdef HAVE_THREADS
  5926. if (runloop_st->flags & RUNLOOP_FLAG_USE_SRAM)
  5927. autosave_deinit();
  5928. #endif
  5929. command_event(CMD_EVENT_RECORD_DEINIT, NULL);
  5930. command_event(CMD_EVENT_SAVE_FILES, NULL);
  5931. #ifdef HAVE_REWIND
  5932. command_event(CMD_EVENT_REWIND_DEINIT, NULL);
  5933. #endif
  5934. #ifdef HAVE_CHEATS
  5935. cheat_manager_state_free();
  5936. #endif
  5937. #ifdef HAVE_BSV_MOVIE
  5938. movie_stop(input_st);
  5939. #endif
  5940. command_event(CMD_EVENT_CORE_DEINIT, NULL);
  5941. content_deinit();
  5942. runloop_path_deinit_subsystem();
  5943. path_deinit_savefile();
  5944. runloop_st->flags &= ~RUNLOOP_FLAG_IS_INITED;
  5945. #ifdef HAVE_THREAD_STORAGE
  5946. sthread_tls_delete(&p_rarch->rarch_tls);
  5947. #endif
  5948. }
  5949. break;
  5950. #ifdef HAVE_CONFIGFILE
  5951. case RARCH_CTL_SET_BLOCK_CONFIG_READ:
  5952. p_rarch->flags |= RARCH_FLAGS_BLOCK_CONFIG_READ;
  5953. break;
  5954. case RARCH_CTL_UNSET_BLOCK_CONFIG_READ:
  5955. p_rarch->flags &= ~RARCH_FLAGS_BLOCK_CONFIG_READ;
  5956. break;
  5957. #endif
  5958. case RARCH_CTL_CORE_OPTIONS_LIST_GET:
  5959. {
  5960. core_option_manager_t **coreopts = (core_option_manager_t**)data;
  5961. if (!coreopts || !runloop_st->core_options)
  5962. return false;
  5963. *coreopts = runloop_st->core_options;
  5964. }
  5965. break;
  5966. case RARCH_CTL_CORE_OPTION_UPDATE_DISPLAY:
  5967. if ( runloop_st->core_options
  5968. && runloop_st->core_options_callback.update_display)
  5969. {
  5970. /* Note: The update_display() callback may read
  5971. * core option values via RETRO_ENVIRONMENT_GET_VARIABLE.
  5972. * This will reset the 'options updated' flag.
  5973. * We therefore have to cache the current 'options updated'
  5974. * state and restore it after the update_display() function
  5975. * returns */
  5976. bool values_updated = runloop_st->core_options->updated;
  5977. bool display_updated = runloop_st->core_options_callback.update_display();
  5978. runloop_st->core_options->updated = values_updated;
  5979. return display_updated;
  5980. }
  5981. return false;
  5982. #ifdef HAVE_CONFIGFILE
  5983. case RARCH_CTL_SET_REMAPS_CORE_ACTIVE:
  5984. /* Only one type of remap can be active
  5985. * at any one time */
  5986. runloop_st->flags &= ~(RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE
  5987. | RUNLOOP_FLAG_REMAPS_GAME_ACTIVE);
  5988. runloop_st->flags |= RUNLOOP_FLAG_REMAPS_CORE_ACTIVE;
  5989. break;
  5990. case RARCH_CTL_SET_REMAPS_GAME_ACTIVE:
  5991. runloop_st->flags &= ~(RUNLOOP_FLAG_REMAPS_CORE_ACTIVE
  5992. | RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE);
  5993. runloop_st->flags |= RUNLOOP_FLAG_REMAPS_GAME_ACTIVE;
  5994. break;
  5995. case RARCH_CTL_SET_REMAPS_CONTENT_DIR_ACTIVE:
  5996. runloop_st->flags &= ~(RUNLOOP_FLAG_REMAPS_CORE_ACTIVE
  5997. | RUNLOOP_FLAG_REMAPS_GAME_ACTIVE);
  5998. runloop_st->flags |= RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE;
  5999. break;
  6000. #endif
  6001. case RARCH_CTL_GET_PERFCNT:
  6002. {
  6003. bool **perfcnt = (bool**)data;
  6004. if (!perfcnt)
  6005. return false;
  6006. *perfcnt = &runloop_st->perfcnt_enable;
  6007. }
  6008. break;
  6009. case RARCH_CTL_SET_PERFCNT_ENABLE:
  6010. runloop_st->perfcnt_enable = true;
  6011. break;
  6012. case RARCH_CTL_UNSET_PERFCNT_ENABLE:
  6013. runloop_st->perfcnt_enable = false;
  6014. break;
  6015. case RARCH_CTL_IS_PERFCNT_ENABLE:
  6016. return runloop_st->perfcnt_enable;
  6017. case RARCH_CTL_SET_WINDOWED_SCALE:
  6018. {
  6019. unsigned *idx = (unsigned*)data;
  6020. if (!idx)
  6021. return false;
  6022. runloop_st->pending_windowed_scale = *idx;
  6023. }
  6024. break;
  6025. case RARCH_CTL_STATE_FREE:
  6026. {
  6027. input_driver_state_t *input_st = input_state_get_ptr();
  6028. runloop_st->perfcnt_enable = false;
  6029. #ifdef HAVE_CONFIGFILE
  6030. runloop_st->flags &= ~RUNLOOP_FLAG_OVERRIDES_ACTIVE;
  6031. #endif
  6032. runloop_st->flags &= ~(RUNLOOP_FLAG_AUTOSAVE
  6033. | RUNLOOP_FLAG_SLOWMOTION
  6034. | RUNLOOP_FLAG_IDLE
  6035. | RUNLOOP_FLAG_PAUSED
  6036. );
  6037. runloop_state_free(runloop_st);
  6038. memset(&input_st->analog_requested, 0,
  6039. sizeof(input_st->analog_requested));
  6040. }
  6041. break;
  6042. case RARCH_CTL_SET_SHUTDOWN:
  6043. runloop_st->flags |= RUNLOOP_FLAG_SHUTDOWN_INITIATED;
  6044. break;
  6045. case RARCH_CTL_CORE_OPTION_PREV:
  6046. /*
  6047. * Get previous value for core option specified by @idx.
  6048. * Options wrap around.
  6049. */
  6050. {
  6051. unsigned *idx = (unsigned*)data;
  6052. if (!idx || !runloop_st->core_options)
  6053. return false;
  6054. core_option_manager_adjust_val(runloop_st->core_options,
  6055. *idx, -1, true);
  6056. }
  6057. break;
  6058. case RARCH_CTL_CORE_OPTION_NEXT:
  6059. /*
  6060. * Get next value for core option specified by @idx.
  6061. * Options wrap around.
  6062. */
  6063. {
  6064. unsigned* idx = (unsigned*)data;
  6065. if (!idx || !runloop_st->core_options)
  6066. return false;
  6067. core_option_manager_adjust_val(runloop_st->core_options,
  6068. *idx, 1, true);
  6069. }
  6070. break;
  6071. case RARCH_CTL_NONE:
  6072. default:
  6073. return false;
  6074. }
  6075. return true;
  6076. }
  6077. bool retroarch_override_setting_is_set(
  6078. enum rarch_override_setting enum_idx, void *data)
  6079. {
  6080. struct rarch_state *p_rarch = &rarch_st;
  6081. #ifdef HAVE_NETWORKING
  6082. net_driver_state_t *net_st = networking_state_get_ptr();
  6083. #endif
  6084. switch (enum_idx)
  6085. {
  6086. case RARCH_OVERRIDE_SETTING_LIBRETRO_DEVICE:
  6087. {
  6088. unsigned *val = (unsigned*)data;
  6089. if (val)
  6090. {
  6091. unsigned bit = *val;
  6092. runloop_state_t *runloop_st = runloop_state_get_ptr();
  6093. return BIT256_GET(runloop_st->has_set_libretro_device, bit);
  6094. }
  6095. }
  6096. break;
  6097. case RARCH_OVERRIDE_SETTING_VERBOSITY:
  6098. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_VERBOSITY) > 0);
  6099. case RARCH_OVERRIDE_SETTING_LIBRETRO:
  6100. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_LIBRETRO) > 0);
  6101. case RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY:
  6102. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_LIBRETRO_DIRECTORY) > 0);
  6103. case RARCH_OVERRIDE_SETTING_SAVE_PATH:
  6104. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_SAVE_PATH) > 0);
  6105. case RARCH_OVERRIDE_SETTING_STATE_PATH:
  6106. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_STATE_PATH) > 0);
  6107. #ifdef HAVE_NETWORKING
  6108. case RARCH_OVERRIDE_SETTING_NETPLAY_MODE:
  6109. return ((net_st->flags & NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_MODE) > 0);
  6110. case RARCH_OVERRIDE_SETTING_NETPLAY_IP_ADDRESS:
  6111. return ((net_st->flags & NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_ADDRESS) > 0);
  6112. case RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT:
  6113. return ((net_st->flags & NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_IP_PORT) > 0);
  6114. case RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES:
  6115. return ((net_st->flags & NET_DRIVER_ST_FLAG_HAS_SET_NETPLAY_CHECK_FRAMES) > 0);
  6116. #endif
  6117. #ifdef HAVE_PATCH
  6118. case RARCH_OVERRIDE_SETTING_UPS_PREF:
  6119. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_UPS_PREF) > 0);
  6120. case RARCH_OVERRIDE_SETTING_BPS_PREF:
  6121. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_BPS_PREF) > 0);
  6122. case RARCH_OVERRIDE_SETTING_IPS_PREF:
  6123. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_IPS_PREF) > 0);
  6124. #endif
  6125. case RARCH_OVERRIDE_SETTING_LOG_TO_FILE:
  6126. return ((p_rarch->flags & RARCH_FLAGS_HAS_SET_LOG_TO_FILE) > 0);
  6127. case RARCH_OVERRIDE_SETTING_DATABASE_SCAN:
  6128. return ((p_rarch->flags & RARCH_FLAGS_CLI_DATABASE_SCAN) > 0);
  6129. case RARCH_OVERRIDE_SETTING_NONE:
  6130. default:
  6131. break;
  6132. }
  6133. return false;
  6134. }
  6135. int retroarch_get_capabilities(enum rarch_capabilities type,
  6136. char *s, size_t len, size_t _len)
  6137. {
  6138. switch (type)
  6139. {
  6140. case RARCH_CAPABILITIES_CPU:
  6141. {
  6142. uint64_t cpu = cpu_features_get();
  6143. if (cpu & RETRO_SIMD_MMX)
  6144. {
  6145. s[_len++] = 'M';
  6146. s[_len++] = 'M';
  6147. s[_len++] = 'X';
  6148. s[_len++] = ' ';
  6149. s[_len+1] = '\0';
  6150. }
  6151. if (cpu & RETRO_SIMD_MMXEXT)
  6152. {
  6153. s[_len++] = 'M';
  6154. s[_len++] = 'M';
  6155. s[_len++] = 'X';
  6156. s[_len++] = 'E';
  6157. s[_len++] = 'X';
  6158. s[_len++] = 'T';
  6159. s[_len++] = ' ';
  6160. s[_len+1] = '\0';
  6161. }
  6162. if (cpu & RETRO_SIMD_SSE)
  6163. {
  6164. s[_len++] = 'S';
  6165. s[_len++] = 'S';
  6166. s[_len++] = 'E';
  6167. s[_len++] = ' ';
  6168. s[_len+1] = '\0';
  6169. }
  6170. if (cpu & RETRO_SIMD_SSE2)
  6171. {
  6172. s[_len++] = 'S';
  6173. s[_len++] = 'S';
  6174. s[_len++] = 'E';
  6175. s[_len++] = '2';
  6176. s[_len++] = ' ';
  6177. s[_len+1] = '\0';
  6178. }
  6179. if (cpu & RETRO_SIMD_SSE3)
  6180. {
  6181. s[_len++] = 'S';
  6182. s[_len++] = 'S';
  6183. s[_len++] = 'E';
  6184. s[_len++] = '3';
  6185. s[_len++] = ' ';
  6186. s[_len+1] = '\0';
  6187. }
  6188. if (cpu & RETRO_SIMD_SSE4)
  6189. {
  6190. s[_len++] = 'S';
  6191. s[_len++] = 'S';
  6192. s[_len++] = 'E';
  6193. s[_len++] = '4';
  6194. s[_len++] = ' ';
  6195. s[_len+1] = '\0';
  6196. }
  6197. if (cpu & RETRO_SIMD_SSE42)
  6198. {
  6199. s[_len++] = 'S';
  6200. s[_len++] = 'S';
  6201. s[_len++] = 'E';
  6202. s[_len++] = '4';
  6203. s[_len++] = '.';
  6204. s[_len++] = '2';
  6205. s[_len++] = ' ';
  6206. s[_len+1] = '\0';
  6207. }
  6208. if (cpu & RETRO_SIMD_AES)
  6209. {
  6210. s[_len++] = 'A';
  6211. s[_len++] = 'E';
  6212. s[_len++] = 'S';
  6213. s[_len++] = ' ';
  6214. s[_len+1] = '\0';
  6215. }
  6216. if (cpu & RETRO_SIMD_AVX)
  6217. {
  6218. s[_len++] = 'A';
  6219. s[_len++] = 'V';
  6220. s[_len++] = 'X';
  6221. s[_len++] = ' ';
  6222. s[_len+1] = '\0';
  6223. }
  6224. if (cpu & RETRO_SIMD_AVX2)
  6225. {
  6226. s[_len++] = 'A';
  6227. s[_len++] = 'V';
  6228. s[_len++] = 'X';
  6229. s[_len++] = '2';
  6230. s[_len++] = ' ';
  6231. s[_len+1] = '\0';
  6232. }
  6233. if (cpu & RETRO_SIMD_NEON)
  6234. {
  6235. s[_len++] = 'N';
  6236. s[_len++] = 'E';
  6237. s[_len++] = 'O';
  6238. s[_len++] = 'N';
  6239. s[_len++] = ' ';
  6240. s[_len+1] = '\0';
  6241. }
  6242. if (cpu & RETRO_SIMD_VFPV3)
  6243. {
  6244. s[_len++] = 'V';
  6245. s[_len++] = 'F';
  6246. s[_len++] = 'P';
  6247. s[_len++] = 'v';
  6248. s[_len++] = '3';
  6249. s[_len++] = ' ';
  6250. s[_len+1] = '\0';
  6251. }
  6252. if (cpu & RETRO_SIMD_VFPV4)
  6253. {
  6254. s[_len++] = 'V';
  6255. s[_len++] = 'F';
  6256. s[_len++] = 'P';
  6257. s[_len++] = 'v';
  6258. s[_len++] = '4';
  6259. s[_len++] = ' ';
  6260. s[_len+1] = '\0';
  6261. }
  6262. if (cpu & RETRO_SIMD_VMX)
  6263. {
  6264. s[_len++] = 'V';
  6265. s[_len++] = 'M';
  6266. s[_len++] = 'X';
  6267. s[_len++] = ' ';
  6268. s[_len+1] = '\0';
  6269. }
  6270. if (cpu & RETRO_SIMD_VMX128)
  6271. {
  6272. s[_len++] = 'V';
  6273. s[_len++] = 'M';
  6274. s[_len++] = 'X';
  6275. s[_len++] = '1';
  6276. s[_len++] = '2';
  6277. s[_len++] = '8';
  6278. s[_len++] = ' ';
  6279. s[_len+1] = '\0';
  6280. }
  6281. if (cpu & RETRO_SIMD_VFPU)
  6282. {
  6283. s[_len++] = 'V';
  6284. s[_len++] = 'F';
  6285. s[_len++] = 'P';
  6286. s[_len++] = 'U';
  6287. s[_len++] = ' ';
  6288. s[_len+1] = '\0';
  6289. }
  6290. if (cpu & RETRO_SIMD_PS)
  6291. {
  6292. s[_len++] = 'P';
  6293. s[_len++] = 'S';
  6294. s[_len++] = ' ';
  6295. s[_len+1] = '\0';
  6296. }
  6297. if (cpu & RETRO_SIMD_ASIMD)
  6298. {
  6299. s[_len++] = 'A';
  6300. s[_len++] = 'S';
  6301. s[_len++] = 'I';
  6302. s[_len++] = 'M';
  6303. s[_len++] = 'D';
  6304. s[_len++] = ' ';
  6305. s[_len+1] = '\0';
  6306. }
  6307. s[_len-1] = '\0';
  6308. }
  6309. break;
  6310. case RARCH_CAPABILITIES_COMPILER:
  6311. #if defined(_MSC_VER)
  6312. snprintf(s, len, "%s: MSVC (%d) %u-bit",
  6313. msg_hash_to_str(MSG_COMPILER),
  6314. _MSC_VER, (unsigned)
  6315. (CHAR_BIT * sizeof(size_t)));
  6316. #elif defined(__SNC__)
  6317. snprintf(s, len, "%s: SNC (%d) %u-bit",
  6318. msg_hash_to_str(MSG_COMPILER),
  6319. __SN_VER__, (unsigned)(CHAR_BIT * sizeof(size_t)));
  6320. #elif defined(_WIN32) && defined(__GNUC__)
  6321. snprintf(s, len, "%s: MinGW (%d.%d.%d) %u-bit",
  6322. msg_hash_to_str(MSG_COMPILER),
  6323. __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__, (unsigned)
  6324. (CHAR_BIT * sizeof(size_t)));
  6325. #elif defined(__clang__)
  6326. snprintf(s, len, "%s: Clang/LLVM (%s) %u-bit",
  6327. msg_hash_to_str(MSG_COMPILER),
  6328. __clang_version__, (unsigned)(CHAR_BIT * sizeof(size_t)));
  6329. #elif defined(__GNUC__)
  6330. snprintf(s, len, "%s: GCC (%d.%d.%d) %u-bit",
  6331. msg_hash_to_str(MSG_COMPILER),
  6332. __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__, (unsigned)
  6333. (CHAR_BIT * sizeof(size_t)));
  6334. #else
  6335. snprintf(s, len, "%s %u-bit",
  6336. msg_hash_to_str(MSG_UNKNOWN_COMPILER),
  6337. (unsigned)(CHAR_BIT * sizeof(size_t)));
  6338. #endif
  6339. break;
  6340. default:
  6341. case RARCH_CAPABILITIES_NONE:
  6342. break;
  6343. }
  6344. return 0;
  6345. }
  6346. void retroarch_fail(int error_code, const char *error)
  6347. {
  6348. global_t *global = global_get_ptr();
  6349. /* We cannot longjmp unless we're in retroarch_main_init().
  6350. * If not, something went very wrong, and we should
  6351. * just exit right away. */
  6352. strlcpy(global->error_string,
  6353. error, sizeof(global->error_string));
  6354. longjmp(global->error_sjlj_context, error_code);
  6355. }
  6356. /*
  6357. * Also saves configuration files to disk,
  6358. * and (optionally) autosave state.
  6359. */
  6360. bool retroarch_main_quit(void)
  6361. {
  6362. runloop_state_t *runloop_st = runloop_state_get_ptr();
  6363. video_driver_state_t*video_st = video_state_get_ptr();
  6364. settings_t *settings = config_get_ptr();
  6365. bool config_save_on_exit = settings->bools.config_save_on_exit;
  6366. struct retro_system_av_info *av_info = &video_st->av_info;
  6367. /* Restore video driver before saving */
  6368. video_driver_restore_cached(settings);
  6369. #if !defined(HAVE_DYNAMIC)
  6370. {
  6371. /* Salamander sets RUNLOOP_FLAG_SHUTDOWN_INITIATED prior, so we need to handle it seperately */
  6372. /* config_save_file_salamander() must be called independent of config_save_on_exit */
  6373. config_save_file_salamander();
  6374. if (config_save_on_exit)
  6375. command_event(CMD_EVENT_MENU_SAVE_CURRENT_CONFIG, NULL);
  6376. }
  6377. #endif
  6378. #ifdef HAVE_PRESENCE
  6379. {
  6380. presence_userdata_t userdata;
  6381. userdata.status = PRESENCE_SHUTDOWN;
  6382. command_event(CMD_EVENT_PRESENCE_UPDATE, &userdata);
  6383. }
  6384. #endif
  6385. #ifdef HAVE_DISCORD
  6386. {
  6387. discord_state_t *discord_st = discord_state_get_ptr();
  6388. if (discord_st->ready)
  6389. {
  6390. Discord_ClearPresence();
  6391. #ifdef DISCORD_DISABLE_IO_THREAD
  6392. Discord_UpdateConnection();
  6393. #endif
  6394. Discord_Shutdown();
  6395. discord_st->ready = false;
  6396. }
  6397. discord_st->inited = false;
  6398. }
  6399. #endif
  6400. /* Restore original refresh rate, if it has been changed
  6401. * automatically in SET_SYSTEM_AV_INFO */
  6402. if (video_st->video_refresh_rate_original)
  6403. {
  6404. RARCH_DBG("[Video]: Restoring original refresh rate: %f Hz\n", video_st->video_refresh_rate_original);
  6405. /* Set the av_info fps also to the original refresh rate */
  6406. /* to avoid re-initialization problems */
  6407. av_info->timing.fps = video_st->video_refresh_rate_original;
  6408. video_display_server_restore_refresh_rate();
  6409. }
  6410. if (!(runloop_st->flags & RUNLOOP_FLAG_SHUTDOWN_INITIATED))
  6411. {
  6412. /* Save configs before quitting
  6413. * as for UWP depending on `OnSuspending` is not important as we can call it directly here
  6414. * specifically we need to get width,height which requires UI thread and it will not be available on exit
  6415. */
  6416. #if defined(HAVE_DYNAMIC)
  6417. if (config_save_on_exit)
  6418. command_event(CMD_EVENT_MENU_SAVE_CURRENT_CONFIG, NULL);
  6419. #endif
  6420. command_event_save_auto_state(
  6421. settings->bools.savestate_auto_save,
  6422. runloop_st->current_core_type);
  6423. /* If any save states are in progress, wait
  6424. * until all tasks are complete (otherwise
  6425. * save state file may be truncated) */
  6426. content_wait_for_save_state_task();
  6427. if ( (runloop_st->flags & RUNLOOP_FLAG_REMAPS_CORE_ACTIVE)
  6428. || (runloop_st->flags & RUNLOOP_FLAG_REMAPS_CONTENT_DIR_ACTIVE)
  6429. || (runloop_st->flags & RUNLOOP_FLAG_REMAPS_GAME_ACTIVE)
  6430. || !string_is_empty(runloop_st->name.remapfile)
  6431. )
  6432. {
  6433. input_remapping_deinit(settings->bools.remap_save_on_exit);
  6434. input_remapping_set_defaults(true);
  6435. }
  6436. else
  6437. input_remapping_restore_global_config(true);
  6438. #ifdef HAVE_CONFIGFILE
  6439. if (runloop_st->flags & RUNLOOP_FLAG_OVERRIDES_ACTIVE)
  6440. {
  6441. /* Reload the original config */
  6442. config_unload_override();
  6443. }
  6444. #endif
  6445. #if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
  6446. runloop_st->runtime_shader_preset_path[0] = '\0';
  6447. #endif
  6448. }
  6449. runloop_st->flags |= RUNLOOP_FLAG_SHUTDOWN_INITIATED;
  6450. #ifdef HAVE_MENU
  6451. retroarch_menu_running_finished(true);
  6452. #endif
  6453. return true;
  6454. }
  6455. enum retro_language retroarch_get_language_from_iso(const char *iso639)
  6456. {
  6457. unsigned i;
  6458. enum retro_language lang = RETRO_LANGUAGE_ENGLISH;
  6459. struct lang_pair
  6460. {
  6461. const char *iso639;
  6462. enum retro_language lang;
  6463. };
  6464. const struct lang_pair pairs[] =
  6465. {
  6466. {"ja", RETRO_LANGUAGE_JAPANESE},
  6467. {"fr", RETRO_LANGUAGE_FRENCH},
  6468. {"es", RETRO_LANGUAGE_SPANISH},
  6469. {"de", RETRO_LANGUAGE_GERMAN},
  6470. {"it", RETRO_LANGUAGE_ITALIAN},
  6471. {"nl", RETRO_LANGUAGE_DUTCH},
  6472. {"pt_BR", RETRO_LANGUAGE_PORTUGUESE_BRAZIL},
  6473. {"pt_PT", RETRO_LANGUAGE_PORTUGUESE_PORTUGAL},
  6474. {"pt", RETRO_LANGUAGE_PORTUGUESE_PORTUGAL},
  6475. {"ru", RETRO_LANGUAGE_RUSSIAN},
  6476. {"ko", RETRO_LANGUAGE_KOREAN},
  6477. {"zh_CN", RETRO_LANGUAGE_CHINESE_SIMPLIFIED},
  6478. {"zh_SG", RETRO_LANGUAGE_CHINESE_SIMPLIFIED},
  6479. {"zh_HK", RETRO_LANGUAGE_CHINESE_TRADITIONAL},
  6480. {"zh_TW", RETRO_LANGUAGE_CHINESE_TRADITIONAL},
  6481. {"zh", RETRO_LANGUAGE_CHINESE_SIMPLIFIED},
  6482. {"eo", RETRO_LANGUAGE_ESPERANTO},
  6483. {"pl", RETRO_LANGUAGE_POLISH},
  6484. {"vi", RETRO_LANGUAGE_VIETNAMESE},
  6485. {"ar", RETRO_LANGUAGE_ARABIC},
  6486. {"el", RETRO_LANGUAGE_GREEK},
  6487. {"tr", RETRO_LANGUAGE_TURKISH},
  6488. {"sk", RETRO_LANGUAGE_SLOVAK},
  6489. {"fa", RETRO_LANGUAGE_PERSIAN},
  6490. {"he", RETRO_LANGUAGE_HEBREW},
  6491. {"ast", RETRO_LANGUAGE_ASTURIAN},
  6492. {"fi", RETRO_LANGUAGE_FINNISH},
  6493. {"id", RETRO_LANGUAGE_INDONESIAN},
  6494. {"sv", RETRO_LANGUAGE_SWEDISH},
  6495. {"uk", RETRO_LANGUAGE_UKRAINIAN},
  6496. {"cs", RETRO_LANGUAGE_CZECH},
  6497. {"ca_ES@valencia", RETRO_LANGUAGE_CATALAN_VALENCIA},
  6498. {"ca", RETRO_LANGUAGE_CATALAN},
  6499. {"en_GB", RETRO_LANGUAGE_BRITISH_ENGLISH},
  6500. {"en", RETRO_LANGUAGE_ENGLISH},
  6501. {"hu", RETRO_LANGUAGE_HUNGARIAN},
  6502. };
  6503. if (string_is_empty(iso639))
  6504. return lang;
  6505. for (i = 0; i < ARRAY_SIZE(pairs); i++)
  6506. {
  6507. if (strcasestr(iso639, pairs[i].iso639))
  6508. {
  6509. lang = pairs[i].lang;
  6510. break;
  6511. }
  6512. }
  6513. return lang;
  6514. }
  6515. void retroarch_favorites_init(void)
  6516. {
  6517. settings_t *settings = config_get_ptr();
  6518. int content_favorites_size = settings ? settings->ints.content_favorites_size : 0;
  6519. const char *path_content_favorites = settings ? settings->paths.path_content_favorites : NULL;
  6520. bool playlist_sort_alphabetical = settings ? settings->bools.playlist_sort_alphabetical : false;
  6521. playlist_config_t playlist_config;
  6522. enum playlist_sort_mode current_sort_mode;
  6523. playlist_config.capacity = COLLECTION_SIZE;
  6524. playlist_config.old_format = settings ? settings->bools.playlist_use_old_format : false;
  6525. playlist_config.compress = settings ? settings->bools.playlist_compression : false;
  6526. playlist_config.fuzzy_archive_match = settings ? settings->bools.playlist_fuzzy_archive_match : false;
  6527. playlist_config_set_base_content_directory(&playlist_config, NULL);
  6528. if (!settings)
  6529. return;
  6530. if (content_favorites_size >= 0)
  6531. playlist_config.capacity = (size_t)content_favorites_size;
  6532. retroarch_favorites_deinit();
  6533. RARCH_LOG("[Playlist]: %s: \"%s\".\n",
  6534. msg_hash_to_str(MSG_LOADING_FAVORITES_FILE),
  6535. path_content_favorites);
  6536. playlist_config_set_path(&playlist_config, path_content_favorites);
  6537. g_defaults.content_favorites = playlist_init(&playlist_config);
  6538. /* Get current per-playlist sort mode */
  6539. current_sort_mode = playlist_get_sort_mode(g_defaults.content_favorites);
  6540. /* Ensure that playlist is sorted alphabetically,
  6541. * if required */
  6542. if ((playlist_sort_alphabetical && (current_sort_mode == PLAYLIST_SORT_MODE_DEFAULT)) ||
  6543. (current_sort_mode == PLAYLIST_SORT_MODE_ALPHABETICAL))
  6544. playlist_qsort(g_defaults.content_favorites);
  6545. }
  6546. void retroarch_favorites_deinit(void)
  6547. {
  6548. if (!g_defaults.content_favorites)
  6549. return;
  6550. playlist_write_file(g_defaults.content_favorites);
  6551. playlist_free(g_defaults.content_favorites);
  6552. g_defaults.content_favorites = NULL;
  6553. }
  6554. #ifdef HAVE_ACCESSIBILITY
  6555. bool accessibility_speak_priority(
  6556. bool accessibility_enable,
  6557. unsigned accessibility_narrator_speech_speed,
  6558. const char* speak_text, int priority)
  6559. {
  6560. access_state_t *access_st = access_state_get_ptr();
  6561. if (is_accessibility_enabled(
  6562. accessibility_enable,
  6563. access_st->enabled))
  6564. {
  6565. frontend_ctx_driver_t *frontend =
  6566. frontend_state_get_ptr()->current_frontend_ctx;
  6567. RARCH_LOG("Spoke: %s\n", speak_text);
  6568. if (frontend && frontend->accessibility_speak)
  6569. return frontend->accessibility_speak(accessibility_narrator_speech_speed, speak_text,
  6570. priority);
  6571. RARCH_LOG("Platform not supported for accessibility.\n");
  6572. /* The following method is a fallback for other platforms to use the
  6573. AI Service url to do the TTS. However, since the playback is done
  6574. via the audio mixer, which only processes the audio while the
  6575. core is running, this playback method won't work. When the audio
  6576. mixer can handle playing streams while the core is paused, then
  6577. we can use this. */
  6578. #if 0
  6579. #if defined(HAVE_NETWORKING)
  6580. return accessibility_speak_ai_service(speak_text, voice, priority);
  6581. #endif
  6582. #endif
  6583. }
  6584. return true;
  6585. }
  6586. #endif