Máquina Arcade amb monedes i limitació de temps. MAME i neogeo

De wikijoan
Salta a la navegació Salta a la cerca

Introducció

Es tracta de fer una màquina (Vilanova i la Geltrú) en què les monedes donin crèdit de temps no de partides. Per exemple, una moneda són 10 minuts de joc. S'ha d'implementar els emuladors de mame i neogeo.

Les monedes es poden posar en qualsevol moment (en el frontend, en el mame, o en el neogeo), i s'haurà de comtpabilitzar el temps de forma seamless en qualsevol de les tres aplicacions.

El temps anirà corrent cap endarrera metre estigui jugant amb el mame o el neogeo, no quan estigui a dins del frontend.

Les primeres proves que vaig fer eren orientades a fer una aplicació amb SDL que coexistís amb els modes fullscreen del mame, però això va resultar impossible. Sembla ser que quan el mame està fullscreen, no hi pot haver cap altra aplicació ni sprite que pugui coexisitir en la pantalla.

Per tant, la única solució és hackejar el mame i el neogeo per mostrar per pantalla la informació del temps restant. Compartir la informació del temps restant entre les tres aplicacions, i incrementar 10 minuts quan posi una moneda és relativament fàcil. Sempre es farà mitjançant lectures/escriptures del fitxer comptador.txt que està a joanillo_arcade_frontend/resources/comptador.txt.

Sempre he associat la tecla 2 al COIN. Això continuarà sent cert, i serà la manera que pugui donar crèdits dins el MAME i dins el NeoGeo. Però ara el moneder real l'associaré a una altra tecla: el 6, i això ho hauré de tenir en compte en el front-end, en el MAME, i en el NeoGeo.

Per què el 6? Només tinc mame i neogeo. No tinc altres jocs que feia servir el 6 (SNES, GBA, Mega Drive). Per tant, el 6, 7 i 8 estan lliures. El 7 i el 8 es poden fer servir per controlar el volum per software. I el 8 es fa servir en el NeoGeo (botó D). Per tant el més lògic és fer servir el 6.

Per tant, tinc dos botons associats a la moneda: el 2 i el 6, però no s'han de confondre. El 2 és el que sempre he fet servir per donar crèdits dins de l'emulador. El 6 el que em dóna és temps de joc, i està associat al moneder real.

Projecte mame4allpi. Compilació des de les fonts

Es tracta de compilar des de 0 el mame4all-pi, que estic utiltizant des de fa temps, però mai he compilat.

$ git clone https://git.code.sf.net/p/mame4allpi/code mame4allpi-code

Es crea la carpeta mame4allpi-code, i aquest serà el punt de compilació.

Compila sense problemes:

$ cd /home/pi/mame4allpi-code
$ ./configure
$ make

L'exeuctable és:

  • /home/pi/mame4allpi-code/mame

No cal fer sudo make install. El que he de fer ara és recuperar la meva configuració. Concretament copiar el fitxer mame.cfg a /home/pi/mame4allpi-code, i crear la carpeta src/cfg/ (que no està creada, allà on hi ha les altres carpetes nvram,...), i copiar aquí dins tots els fitxers .cfg de les roms, i més important, el fitxer default.cfg, que és on estan definides les tecles que faig servir generals.

$ ./mame 1942

Quan faci canvis en el codi font, només caldrà fer el make per recompilar el projecte.

Hack de MAME. Gameplay del MAME orientat al temps

Introducció

Els fitxers que he canviat, amb les seves versions, estan a MAME/codisfont/mame4allpi-code/src/rpi/canvis.

Tots els canvis que he fet vénen precedits del comentari //canvi.

La idea és que en el mame puc fer F11 i em surt per pantalla informació del fps. He de fer servir aquesta funcionalitat per mostrar per pantalla la informació que m'interessa.

Desenvolupament

Les notes que a continuació vénen són sense estructurar, és fruit de la recerca que s'ha fet.

./rpi/input.cpp:    { "TAB",        KEY_TAB,            KEYCODE_TAB },
./rpi/input.cpp:    {    KEY_TAB,                    SDLK_TAB },

./rpi/allegro.h:#define KEY_TAB            15

./input.h:    KEYCODE_TAB, KEYCODE_OPENBRACE, KEYCODE_CLOSEBRACE, KEYCODE_ENTER, KEYCODE_COLON,
./inptport.cpp:    { IPT_UI_CONFIGURE,         "Config Menu",       SEQ_DEF_1(KEYCODE_TAB) },
./legacy.h:    ver_567_KEYCODE_TAB, ver_567_KEYCODE_OPENBRACE, ver_567_KEYCODE_CLOSEBRACE, ver_567_KEYCODE_ENTER, ver_567_KEYCODE_COLON,
./legacy.h:    { ver_567_KEYCODE_TAB, KEYCODE_TAB },

./inptport.cpp:    if (input_ui_pressed(IPT_UI_CONFIGURE))

video.cpp
update_screen = blitscreen_dirty1_color8;

La idea és fer per exemple un showfps (associat a la tecla F11), i en comptes del fps, que m'aparegui el text i la info que jo vull.

              if (vector_game)
              {
                      sprintf(buf," %d vector updates",vups);
                      ui_text(bitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,Machine->uifontheight);
              }

ui_text és per escriure text per pantalla...

$ find /home/pi/mame4allpi-code/src -type f -print | xargs egrep -i showfps

$ find /home/pi/mame4allpi-code/src -type f -print | xargs egrep -i showfps
/home/pi/mame4allpi-code/src/rpi/video.cpp:	static int showfps,showfpstemp;
/home/pi/mame4allpi-code/src/rpi/video.cpp:		if (showfpstemp)
/home/pi/mame4allpi-code/src/rpi/video.cpp:			showfpstemp--;
/home/pi/mame4allpi-code/src/rpi/video.cpp:			if (showfps == 0 && showfpstemp == 0)
/home/pi/mame4allpi-code/src/rpi/video.cpp:			if (showfpstemp)
/home/pi/mame4allpi-code/src/rpi/video.cpp:				showfpstemp = 0;
/home/pi/mame4allpi-code/src/rpi/video.cpp:				showfps ^= 1;
/home/pi/mame4allpi-code/src/rpi/video.cpp:				if (showfps == 0)
/home/pi/mame4allpi-code/src/rpi/video.cpp:		if (showfps || showfpstemp)
/home/pi/mame4allpi-code/src/rpi/video.cpp:		if (showfps == 0)
/home/pi/mame4allpi-code/src/rpi/video.cpp:			showfpstemp = 2*video_fps;
/home/pi/mame4allpi-code/src/rpi/video.cpp:		if (showfps == 0)
/home/pi/mame4allpi-code/src/rpi/video.cpp:			showfpstemp = 2*video_fps;

$ find /home/pi/mame4allpi-code/src -type f -print | xargs egrep -i F11
/home/pi/mame4allpi-code/src/legacy.h:	ver_567_KEYCODE_F11, ver_567_KEYCODE_F12,
/home/pi/mame4allpi-code/src/legacy.h:	{ ver_567_KEYCODE_F11, KEYCODE_F11 },
/home/pi/mame4allpi-code/src/inptport.cpp:	{ IPT_UI_SHOW_FPS,          "Show FPS",          SEQ_DEF_5(KEYCODE_F11, CODE_NOT, KEYCODE_LCONTROL, CODE_NOT, KEYCODE_LSHIFT) },
/home/pi/mame4allpi-code/src/inptport.cpp:	{ IPT_UI_SHOW_PROFILER,     "Show Profiler",     SEQ_DEF_2(KEYCODE_F11, KEYCODE_LSHIFT) },

$ find /home/pi/mame4allpi-code/src -type f -print | xargs egrep -i IPT_UI_SHOW_FPS
/home/pi/mame4allpi-code/src/inptport.h:	IPT_UI_SHOW_FPS,
/home/pi/mame4allpi-code/src/inptport.cpp:	{ IPT_UI_SHOW_FPS,          "Show FPS",          SEQ_DEF_5(KEYCODE_F11, CODE_NOT, KEYCODE_LCONTROL, CODE_NOT, KEYCODE_LSHIFT) },
/home/pi/mame4allpi-code/src/rpi/video.cpp:		if (input_ui_pressed(IPT_UI_SHOW_FPS))

Veig que la funcionalitat important del showfps està en el fitxer video.cpp:

video.cpp, línia 808

		if (input_ui_pressed(IPT_UI_SHOW_FPS))
		{
			if (showfpstemp)
			{
				showfpstemp = 0;
				have_to_clear_bitmap = 1;
			}
			else
			{
				showfps ^= 1;
				if (showfps == 0)
				{
					have_to_clear_bitmap = 1;
				}
			}
		}

línia 877:

		if (showfps || showfpstemp)
		{
			int fps;
			char buf[30];
			int divdr;
			divdr = 100 * FRAMESKIP_LEVELS;
			fps = (video_fps * (FRAMESKIP_LEVELS - frameskip) * speed + (divdr / 2)) / divdr;
			sprintf(buf,"%s%2d%4d%%%4d/%d fps",autoframeskip?"auto":"fskp",frameskip,speed,fps,(int)(video_fps+0.5));
			ui_text(bitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,0);
			if (vector_game)
			{
				sprintf(buf," %d vector updates",vups);
				ui_text(bitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,Machine->uifontheight);
			}
		}

i aleshores ve la part més important, de fer el update_screen(). Si comentem la línia 972 ( // update_screen(bitmap) ), no es veu res per pantalla.

línia 972:
                /* copy the bitmap to screen memory */
                profiler_mark(PROFILER_BLIT);
                update_screen(bitmap);

A la línia 893 fico, i funciona:

$ cd ~/MAME/codis_font/mame4allpi-code/src/rpi/canvis
$ sshpass -p 'raspberry' scp video.cpp pi@192.168.1.38:/home/pi/mame4allpi-code/src/rpi
char buf[30];
sprintf(buf,"hola joan");   
ui_text(bitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,0);

Tot això era la versió 0, en què només he tocat l'arxiu video.cpp, i he vist com es mostra la informació del showfpw per pantalla, i on s'ha de posar perquè surti sempre, sense haver de clicar una tecla.

Tinc la variable temps_restant. El codi per convertir els segons a hora-minut-segons és:

//canvi
char buf[30];
end = clock();
time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
if (time_spent_temp != (int)time_spent) {
	temps_restant --;
	time_spent_temp = (int)time_spent;
}

temps_restant_temp = temps_restant;

for (i = 0; i < 3; ++i) {
	temps_hms[i] = temps_restant_temp / valors_hms[i];
	temps_restant_temp -= temps_hms[i] * valors_hms[i];
}

if (temps_hms[0] > 0) {
	sprintf(buf, "%dh%dm%ds", temps_hms[0], temps_hms[1], temps_hms[2]);
} else if (temps_hms[1] > 0) {
	sprintf(buf, "%dm%ds", temps_hms[1], temps_hms[2]);
} else {
	sprintf(buf, "%ds", temps_hms[2]);
}
ui_text(bitmap,buf,Machine->uiwidth-strlen(buf)*Machine->uifontwidth,Machine->uifontheight);

En la versió 1 em preocuparé del TIMING:

línia 72:
#define ticker() gp2x_timer_read() 

línia 783:
	if (prev_measure==0)
	{
		/* first time through, initialize timer */
		prev_measure = ticker() - FRAMESKIP_LEVELS * TICKS_PER_SEC/video_fps;
	}

Està clar que la meva aplicació és capaç de tenir una mesura exacta del temps, però hi ha altres maneres. Al final implemento:

Suposo que un bon lloc per obrir el fitxer és en la línia 279 de video.cpp, al final de la funció select_display_mode(), quan s'obre el display, abans de fer el begin = clock();:

suposo que un bon lloc per escriure en el fitxer és en la línia 493 de video.cpp:

/* shut up the display */

Un cop funcioni tot només havent tocat el fitxer video.cpp, el següent objectiu serà detectar quan fico un crèdit, i això farà que augmenti el número de segons disponibles.

La funció main() està en la línia 100 de rpi.cpp, i aquest serà el fitxer on hauré de ficar variables globals, i on hauria d'obrir i tancar el fitxer.

Efectivament, en el main.cpp ja tinc el #include <time.h>, i per tant no cal ficar-lo en el video.cpp.

$ find /home/joan/mame4allpi-code -type f -print | xargs egrep -i 'main\('
$ find /home/joan/mame4allpi-code -type f -print | xargs egrep -i 'main \('

C language extern variables:

En el fitxer rpi.cpp podem utilitzar variables externes, com a la línia 28:

extern fe_driver fe_drivers[NUMGAMES];

La manera com funciona és:

A rpi.cpp (ĺínia 31), puc declarar (que no definir) la variable externa:

extern int temps_restant;

i a la línia 106 (just al començament del main()):

	//canvi
	temps_restant = 3600;

En el video.cpp puc fer servir aquesta variable temps_restant, i efectivament, agafa el valor de 3600s. Per tant, ja tinc la variable temps_restant que puc utilitzar de forma global.

Aquesta és la manera que una variable la pugui declarar en un fitxer, i utilitzar-la en un altre fitxer. Per ex,

$ find /home/joan/mame4allpi-code -type f -print | xargs egrep -i fe_driver

La variable fe_driver es declara a rpi.cpp, però s'utilitza a gp2x_frontend.cpp

En el fitxer rpi.cpp, la definició del main() està a la línia 100, i el init_SDL() està dins del main a la línia 187, abans del bucle principal (etiqueta gui_loop: en la línia 194). Just abans del bucle principal obriré el meu fitxer comptador.txt (i ja no cal obrir-lo a video.cpp)

El fitxer el tancaré a la línia 445, després de deinit_SDL();

Jo sé que F11 està associat al showfps. Canviar F11 per la tecla que jo vull associar.

inptport.cpp:    { IPT_UI_SHOW_FPS,          "Show FPS",          SEQ_DEF_5(KEYCODE_F11, CODE_NOT, KEYCODE_LCONTROL, CODE_NOT, KEYCODE_LSHIFT) },

input.cpp:    { "F11",        KEY_F11,            KEYCODE_F11 },
input.cpp:    {    KEY_F11,                    SDLK_F11 },

video.cpp, línia 805

        if (input_ui_pressed(IPT_UI_SHOW_FPS))

$ find /home/joan/mame4allpi-code -type f -print | xargs egrep -i input_ui_pressed

  usrintrf.c:
 Functions used to handle MAME's crude user interface.

La crude user interface (fitxer usrintrf.c) fa referència a la interfície que accedeixo amb el TAB, i que puc canviar paràmetres.

Per ex en la línia 1235 tenim:

        if (input_ui_pressed(IPT_UI_SNAPSHOT))
            osd_save_snapshot(bitmap);

Per tant ja sé què passa i quina funció s'executa quan faig un snapshot.

Es tracta de definir una nova tecla per al snapshot, i definir una funció que actualitzarà el temps restant.

Amb TAB entro a la configuració de les tecles, i associo el snapshot a la tecla 6. Veig que el directori snap/ no està creat. El creo. Efectivament, aquí es guarden les captures de pantalla. Per tant, faig servir un petit truco, que és apropiar-me de la funcionalitat de fer un snapshot per incrementar el temps de joc.

fitxer usrintrf.cpp, línia 3440:

	/* if the user pressed F12, save the screen to a file */
	if (input_ui_pressed(IPT_UI_SNAPSHOT))
	{
		//osd_save_snapshot(bitmap);
		temps_restant+=900;
	}

Compte! que hi ha d'altres llocs on es crida la funció osd_save_snapshot(), per ex en la línia 1238

Hi ha hagut bastant d'embolic amb la variable global temps_restant. La manera com al final funciona s'explica a continuació.

El fitxer de capçalera driver.h és comú a tots els fitxers que he modificat: rpi/video.cpp, rpi/rpi.cp i usrintrf.cpp

  • driver.h: línia 498: extern int temps_restant;
  • usrintrf.cpp: aquí sí que he de declarar: int temps_restant;
  • rpi/video.cpp: no cal declarar!, comento la declaració //int temps_restant;
  • rpi/rpi.cp: no cal declarar!, comento la declaració //int temps_restant;

I finalment he aconseguit compilar sense errors sense haver d'utilitzar el fitxer driver.h:

  • usrintrf.cpp: línia 59: extern int temps_restant;
  • rpi/video.cpp: línia 90: int temps_restant;
  • rpi/rpi.cp: línia 31, l'he de tornar a definir com a extern: extern int temps_restant;

Realment no s'acaba d'entendre això de les variables externes.

Fins aquí la versió 1.

Ara el que falta és que quan estic jugant al 1942 i s'acaba el temps, aleshores he de sortir de MAME. Serà la versió 2.

rpi.cpp, línia 441:

	if(use_gui) goto gui_loop;

a usrintrf.cpp tenim (a varis llocs):

	if (input_ui_pressed(IPT_UI_CANCEL))
		sel = -1;

video.cpp, línia 912:

if (time_spent_temp != (int)time_spent) {
	temps_restant --;
	time_spent_temp = (int)time_spent;
	//if (temps_restant==0) input_ui_pressed(IPT_UI_CANCEL); -> no funciona
	if (temps_restant==0) exit(1); //funciona, però no és la manera correcta
}

Evidentment, fer un exit() així tal qual no és la manera correcta, com ja sabem. He de buscar una altra manera més correcta.

Dins de mame.cpp tinc int run_machine(void)

i aquí dins trobo la crida a l'execució de l'emulador: línia 634

cpu_run();      /* run the emulation! */

cpu_run() està definit a cpuintrf.cp, línia 584, i dins d'aquesta funció hi haurà el bucle principal.

cpuintrf.cpp:

línia 187:
//canvi
extern int temps_restant;

línia 696: (dins de la funció cpu_run() )
	/* loop until the user quits */
	usres = 0;
	while (usres == 0)
	{
		//canvi
		if(temps_restant==0) {
			usres=1;
		}

aquest seria el bucle ppal de l'emulació, i fico la condició de sortida. En principi, si surto de l'emulació aquí el programa ja s'encarregarà de sortir en tots els llocs adients. Efectivament, quan surto d'aquesta manera s'executa la gravació del fitxer comptador.txt (ficant un 0) que està en el fitxer rpi.cpp. Per tant, surto bé.

Per tant, en principi ja he acomplert tots els objectius proposats:

  • Quan entro al MAME, es llegeix el fitxer comptador.txt i comença a descomptar el temps, que està sempre visible
  • Quan fico una moneda, sumem el temps, i s'actualitza el comptador correctament
  • Quan cliclo ESC, sortim de l'emulador per tornar al frontend, actualitzant primer el fitxer comptador.txt (i es torna al frontend, que era el lloc d'on veníem).
  • Quan s'acaba el temps, se surt de l'emulador de forma correcta, actualitzant primer el fitxer comptador.txt (i es torna al frontend, que era el lloc d'on veníem).

Hack neogeo

Faig els canvis a codis_font/gngeo-pi-0.85/src/canvis

$ cd ~/MAME/codis_font/gngeo-pi-0.85/src/canvis/
$ sshpass -p 'raspberry' scp conf.c pi@192.168.1.38:/home/pi/gngeo-pi-0.85/src

Quan faci els canvis, he de tornar a compilar:

$ make

L'executable està a: /home/pi/gngeo-pi-0.85/src/gngeo i si faig

$ sudo make install

l'executable també el trobo a: /home/pi/gngeo-pi-0.85/installdir/bin/arm-linux-gngeo

conf.c, línia 114:

conf.show_fps = CF_BOOL(cf_get_item_by_name("showfps"));

Per tal de què surti el valor dels fps ( a dalt a l'esquerra), el més normal és entrar en el fitxer de configuració .gngeo/gngeorc i ficar showfps true. Ara bé, jo toco el codi i fico (així no m'hauré de preocupar de tocar el fitxer de configuració)

//conf.show_fps = CF_BOOL(cf_get_item_by_name("showfps"));
conf.show_fps = 1

la idea és tornar a utilitzar el showfps per mostrar informació per pantalla. el FPS s'escriu per pantalla a:

video.c, línia 662

    if (conf.show_fps)
        SDL_textout(buffer, visible_area.x+8, visible_area.y, fps_str);

just abans del

screen_update();

Puc canviar la línia 662 per:

	if (conf.show_fps)
		SDL_textout(buffer, visible_area.x+8, visible_area.y, "hola");
		//SDL_textout(buffer, visible_area.x+8, visible_area.y, fps_str);

El que es pot fer (TBD) és buscar una altra font per a les lletres.


Un bon lloc per obrir el fitxer comptador.txt és en el main.c, línia 107, abans del init_sdl();

I per tancar el comptador ho puc fer en el main.c, línia 170, després del close_game(); i abans del return 0.

He declarat la variable temps_restant, que llegeixo del fitxer, i gravo al fitxer quan acabo. Ara vull que aquesta variable (definida a main.c) estigui disponible en el label del fps, a video.c. Per tal de compartir la variable temps_restant entre els dos fitxers l'he de definir així:

  • main.c: extern int temps_restant;
  • video.c: int temps_restant;

En aquest punt ja visualitzo els segons (que he carrregat del fitxer) en el label que hi havia reservat per al fps.

Ara m'he d'encarregar de la part de comptar cap endarrere els segons. Igual que havia fet amb mame, faig servir la funció clock() de la llibreria time.h per fer la diferència edn-begin. El begin el fico quan arrenca el video, dins del init_video, al final de tot de video'c.

void init_video(void) {
	//canvi
	begin = clock();

La part del convertir els segons a h-m-s ja la tinc solucionada a MAME, i ho deixo pel final.

Associo la tecla 6 al moneder real, i he de sumar 15 minuts-900 segons. He de tocar el fitxer event.c. A la línia 16 redeclaro la variable:

//canvi
int temps_restant;

i a la línia 220:

	case SDL_KEYDOWN:
		switch (event->key.keysym.sym) {
		case SDLK_6: //canvi
			temps_restant+=900;
			break;

Finalment, quan s'acaba el temps s'ha de sortir de l'emulador.

Des de main.c es crida al main_loop() (línia 166), que està definit a emu.c (línia 297). Dins del main_loop tinc el while:

while (!neo_emu_done) {
...

i el que hauré de fer és

if (temps_restant <= 0) neo_emu_done=1;

i també redefinir al principi la variable:

int temps_restant

Converteixo els segons restants a h-m-s. video.c queda de la següent manera:

		//canvi
		char buf[30];
		end = clock();
		time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
		if (time_spent_temp != (int)time_spent) {
			temps_restant --;
			time_spent_temp = (int)time_spent;
		}

		temps_restant_temp = temps_restant;

		for (i = 0; i < 3; ++i) {
			temps_hms[i] = temps_restant_temp / valors_hms[i];
			temps_restant_temp -= temps_hms[i] * valors_hms[i];
		}

		if (temps_hms[0] > 0) {
			sprintf(buf, "%dh%dm%ds", temps_hms[0], temps_hms[1], temps_hms[2]);
		} else if (temps_hms[1] > 0) {
			sprintf(buf, "%dm%ds", temps_hms[1], temps_hms[2]);
		} else {
			sprintf(buf, "%ds", temps_hms[2]);
}

		sprintf(temps_restant_str, "%d", temps_restant);
		//SDL_textout(buffer, visible_area.x+8, visible_area.y, temps_restant_str);
		SDL_textout(buffer, visible_area.w-45, visible_area.y, buf);
		//SDL_textout(buffer, visible_area.x+8, visible_area.y, fps_str); //aquesta era la única línia original
	}

He substituït visible_area.x+8 per visible_area.w-45, i així el label queda a dalt a la dreta.

Modificació front-end joanillo_arcade_frontend

versió 1.0.16:

284:
int temps_restant;

337:
	temps_restant = 0;

He de pensar en el mode kiosk!

223:
#define KEY_MONEDER SDLK_6

1131:
	case KEY_MONEDER:
		if(key.state == SDL_PRESSED) {
			incrementa_temps_restant(900);
			break;
		}

235:
void mostra_temps_restant ();
void incrementa_temps_restant (int);

1662:
void mostra_temps_restant () {

	//llegim el temps_restant del fitxer comptador.txt
	string path;
	path = home_path;
	ifstream in_comptador;
	in_comptador.open(path.append("resources/comptador.txt").c_str());
	string s;
	getline(in_comptador, s);
	istringstream ( s ) >> temps_restant; //convertim el string a número
	in_comptador.close();

	string str_temps_restant;
	int valors_hms[3] = {3600, 60, 1};
	int temps_hms[3];
	int temps_restant_temp;
	temps_restant_temp = temps_restant;

	for (int i = 0; i < 3; ++i) {
		temps_hms[i] = temps_restant_temp / valors_hms[i];
		temps_restant_temp -= temps_hms[i] * valors_hms[i];
	}

	if (temps_restant == 0) {
		str_temps_restant = "Inserta moneda";
	} else {
		if (temps_hms[0] > 0) {
			str_temps_restant = IntToString(temps_hms[0]) + "h" + IntToString(temps_hms[1]) + "m" + IntToString(temps_hms[2]) + "s";
		} else if (temps_hms[1] > 0) {
			str_temps_restant = IntToString(temps_hms[1]) + "m" + IntToString(temps_hms[2]) + "s";
		} else {
			str_temps_restant = IntToString(temps_hms[2]) + "s";
		}
	}

	str_temps_restant += "                  ";
	srf_vol = TTF_RenderUTF8_Blended(font1, str_temps_restant.c_str(), fgcolor_negre );
	rect_vol.x = VOL_X;	
	rect_vol.y = CAPCALERA_Y;
	rect_vol.w = srf_vol->w;
	rect_vol.h = srf_vol->h;
	SDL_FillRect (screen, &rect_vol, color_fons_taronja);
	SDL_BlitSurface(srf_vol,NULL,screen,&rect_vol);
	SDL_FreeSurface(srf_vol);
}

void incrementa_temps_restant (int inc_segons) {
	
	string str_temps_restant;
	int valors_hms[3] = {3600, 60, 1};
	int temps_hms[3];
	int temps_restant_temp;

	temps_restant += inc_segons;
	temps_restant_temp = temps_restant;

	for (int i = 0; i < 3; ++i) {
		temps_hms[i] = temps_restant_temp / valors_hms[i];
		temps_restant_temp -= temps_hms[i] * valors_hms[i];
	}

	if (temps_restant == 0) {
		str_temps_restant = "Inserta moneda";
	} else {
		if (temps_hms[0] > 0) {
			str_temps_restant = IntToString(temps_hms[0]) + "h" + IntToString(temps_hms[1]) + "m" + IntToString(temps_hms[2]) + "s";
		} else if (temps_hms[1] > 0) {
			str_temps_restant = IntToString(temps_hms[1]) + "m" + IntToString(temps_hms[2]) + "s";
		} else {
			str_temps_restant = IntToString(temps_hms[2]) + "s";
		}
	}

	str_temps_restant += "                  ";
	srf_vol = TTF_RenderUTF8_Blended(font1, str_temps_restant.c_str(), fgcolor_negre );
	rect_vol.x = VOL_X;	
	rect_vol.y = CAPCALERA_Y;
	rect_vol.w = srf_vol->w;
	rect_vol.h = srf_vol->h;
	SDL_FillRect (screen, &rect_vol, color_fons_taronja);
	SDL_BlitSurface(srf_vol,NULL,screen,&rect_vol);
	SDL_UpdateRect(screen,0,0,0,0);
	SDL_FreeSurface(srf_vol);

	//guardem el temps_restant en el fitxer
	string path;
	path = home_path;
	ofstream out_comptador(path.append("resources/comptador.txt").c_str(), fstream::out);
	out_comptador << temps_restant << endl;
	out_comptador.close();
}

1186:
	mostra_temps_restant();
(abans de SDL_UpdateRect(screen,0,0,0,0);)

826:
mode kiosk:
abans d'entrar en el mode kiosk he d'incrementar el temps_restant, doncs si no el MAME o el NeoGeo et torna a expulsar. Hi ha la possibiltiat de què quedi temps restant a la màquina
			} else {
				//cout << "temps_restant: " << temps_restant << endl;
				if (temps_restant < 300) {
					//incrementem 10 minuts en el mode kiosk
					temps_restant += 600;
					//guardem el temps_restant en el fitxer
					string path;
					path = home_path;
					ofstream out_comptador(path.append("resources/comptador.txt").c_str(), fstream::out);
					out_comptador << temps_restant << endl;
					out_comptador.close();  			
	  			}		
			}

Sortir del front-end amb la combinació de pitjar dues tecles alhora (es tracta de clicar ESC al mateix temps que clico sobre P1, COIN o P2):

línia 1003

	case KEY_ENTRAR1: //SDLK_1
	case KEY_ENTRAR2: //SDLK_9
	case KEY_ENTRAR_COIN: //SDLK_2
		if(key.state == SDL_PRESSED) {
			Uint8 *keystate = SDL_GetKeyState(NULL);
			if ( keystate[SDLK_0] ) {
				SDL_Quit();
				//cout << "sudo /sbin/shutdown -h now" << endl;
				system("sudo /sbin/shutdown -h now"); 
			}

Resum. Posar-ho tot junt en una màquina

Coses a tenir en compte:

  • En el frontend, joanillo_arcade_frontend, he de tenir en compte que l'executable de mame estarà a /home/pi/mame4allpi-code/mame
  • En el frontend, joanillo_arcade_frontend, a resources, només ha d'haver-hi les romlist de mame4all i gngeo, doncs només per aquests dos emuladors tinc implementat el hack del countdown de temps.

Per aplicar els canvis:

A l'ordinador:
$ cd ~/MAME/codis_font/mame4allpi-code/src/rpi/canvis
$ scp rpi.cpp pi@192.168.1.37:/home/pi/mame4allpi-code/src/rpi
$ scp video.cpp pi@192.168.1.37:/home/pi/mame4allpi-code/src/rpi
$ scp usrintrf.cpp pi@192.168.1.37:/home/pi/mame4allpi-code/src
$ scp cpuintrf.cpp pi@192.168.1.37:/home/pi/mame4allpi-code/src

$ cd ~/MAME/codis_font/gngeo-pi-0.85/src/canvis
$ scp * pi@192.168.1.37:/home/pi/gngeo-pi-0.85/src/

A la RPi hem de compilar els canvis:
$ cd /home/pi/mame4allpi-code/
$ make

$ cd /home/pi/gngeo-pi-0.85/src
$ make
$ sudo make install

per al mame:

  • s'ha de copiar el mame.cfg
  • s'ha de crear la carpeta src/cfg/, i s'han de copiar aquí tots els arxius *.cfg, sobretot el default.cfg, que és el més important.
  • Recordar que la tecla 6 és l'associada al moneder, i que en el mame4all la funcionalitat del moneder s'activa amb el snapshot. És a dir, haurem d'entrar en la configuració (TAB, que escriu en el fitxer default.cfg), i associar al snapshot la tecla 6 (i mirar que el 6 no tingui associat res més).

El frontend s'ha de tornar a compilar. Els canvis s'han implementat en la versió 1.0.16.

En el mame4llpi-code, s'ha de crear el directori cfg

  • tornar a habilitar pikeyd
  • tornar a deshabilitar la xarxa
  • tocar el fitxer comptador.txt, per tal de que no tingui molt de temps

Per comprovar que tot funciona correctament, he d'entrar des del frontend a MAME i NeoGeo. He de poder inserir moneda en el front-end, MAME i NeoGeo. Veure que quan s'esgota el temps a MAME i NeoGeo em retorna al frontend. Veure que puc entrar en mode kiosk tant en MAME com en NeoGeo.

Enllaços


creat per Joan Quintana Compte, març 2017