Wednesday, 2 March 2016

Playstation emulation: pcsx-rearmed

When I started this project, I was far from imagining that I could even try to emulate the Playstation. But I gave a try at pcsx-rearmed, and I was astonished! Even without hardware acceleration, lots of games actually work quite smoothly!

The original code is available here:

I have modified it for my usage, but my version may not be up to date. My patches are:

  • Modification of the configure script to enable the right options for the BeagleBone Black platform with SDL
  • Made the base save/configuration path absolute (and hard-coded) rather than relative. I want the path to stay the same even when starting the application from a service (my launcher)
  • Removed the menu when setting the NO_MENU environment variable: the only menu I want is that of my launcher
  • Removed a few "if"s that were never used in my case (show fps etc.). That's a pathology some developers like me get when getting in other people's codes - they tend to leave their marks for the sake of "optimization" or any other stupid reason :-)
  • Modification of the internal libpicofe, so that the environment variable PCSX_WIDTH, when set, allows forcing a size for the display. Some games do not run smoothly full-screen, so I decided to be able to reduce their size rather than ditch them.
The source code for my fork is available here:

To compile:

And to run, for example:

 PCSX_WIDTH=600 NO_MENU=1 /media/BBB/sources/pcsx_rearmed/pcsx -cdfile /media/BBB/roms/psx/MyGame.cue  

Arcade emulation: AdvanceMame

This one will be very quick: just get AdvanceMame 1.2 and compile :-)

OK, I'll give more details! First of all, get the tarball right here:

Compilation is straightforward (when you're used to the Linux world), just check the configure options to activate the proper flags. We want to display on the frame buffer, and use SDL for the rest, so:
 ./configure --prefix=/media/BBB/ --enable-sdl --enable-fb  
 make install  

The "toughest" part is to configure Mame to run and display the way you want. This is done by experimenting with the $HOME/.advance/advmame.rc file: specify the paths to your roms, the input mapping, the display settings, etc.

Here is mine, for information:
 debug_crash no  
 debug_rawsound no  
 debug_speedmark no  
 device_color_bgr15 yes  
 device_color_bgr16 yes  
 device_color_bgr24 yes  
 device_color_bgr32 yes  
 device_color_bgr8 yes  
 device_color_palette8 yes  
 device_color_yuy2 yes  
 device_joystick none  
 device_keyboard sdl  
 device_mouse none  
 device_raw_firstkeyhack no  
 device_raw_mousedev[0] auto  
 device_raw_mousedev[1] auto  
 device_raw_mousedev[2] auto  
 device_raw_mousedev[3] auto  
 device_raw_mousetype[0] pnp  
 device_raw_mousetype[1] pnp  
 device_raw_mousetype[2] pnp  
 device_raw_mousetype[3] pnp  
 device_sdl_samples 512  
 device_sound oss  
 device_video sdl  
 device_video_cursor auto  
 device_video_doublescan yes  
 device_video_fastchange no  
 device_video_interlace yes  
 device_video_output auto  
 device_video_overlaysize auto  
 device_video_singlescan yes  
 dir_artwork /root/.advance/artwork:/media/BBB/share/advance/artwork  
 dir_diff /root/.advance/diff  
 dir_hi /root/.advance/hi  
 dir_image /root/.advance/image:/media/BBB/share/advance/image  
 dir_inp /root/.advance/inp  
 dir_memcard /root/.advance/memcard  
 dir_nvram /root/.advance/nvram  
 dir_rom /root/.advance/rom:/media/BBB/share/advance/rom  
 dir_sample /root/.advance/sample:/media/BBB/share/advance/sample  
 dir_snap /root/.advance/snap  
 dir_sta /root/.advance/sta  
 display_adjust none  
 display_antialias no  
 display_artwork_backdrop yes  
 display_artwork_bezel no  
 display_artwork_crop yes  
 display_artwork_overlay yes  
 display_aspectx 16  
 display_aspecty 9  
 display_beam 1  
 display_brightness 1  
 display_buffer no  
 display_color auto  
 display_expand 1  
 display_flicker 0  
 display_flipx no  
 display_flipy no  
 display_frameskip auto  
 display_gamma 1  
 display_intensity 1.5  
 display_interlaceeffect none  
 display_magnify 1  
 display_magnifysize 640  
 display_mode auto  
 display_pausebrightness 1  
 display_resize fractional  
 display_resizeeffect auto  
 display_restore yes  
 display_rgbeffect none  
 display_rol no  
 display_ror no  
 display_scanlines no  
 display_skipcolumns auto  
 display_skiplines auto  
 display_translucency yes  
 display_vsync yes  
 input_hotkey yes  
 input_idleexit 0  
 input_steadykey no  
 lcd_server none  
 lcd_speed 4  
 lcd_timeout 500  
 misc_bios default  
 misc_cheat no  
 misc_cheatfile cheat.dat  
 misc_difficulty none  
 misc_eventdebug no  
 misc_eventfile event.dat  
 misc_freeplay no  
 misc_hiscorefile hiscore.dat  
 misc_lang none  
 misc_languagefile english.lng  
 misc_mutedemo no  
 misc_quiet yes  
 misc_safequit no  
 misc_smp no  
 misc_timetorun 0  
 record_sound yes  
 record_sound_time 15  
 record_video yes  
 record_video_interleave 2  
 record_video_time 15  
 script_led1 on(kdb, 0b1); wait(!event()); off(kdb, 0b1);  
 script_led2 on(kdb, 0b10); wait(!event()); off(kdb, 0b10);  
 script_turbo while (event()) { toggle(kdb, 0b100); delay(100); } off(kdb, 0b100);  
 script_video wait(!event()); set(kdb, 0);  
 sound_adjust auto  
 sound_equalizer_highvolume 0  
 sound_equalizer_lowvolume 0  
 sound_equalizer_midvolume 0  
 sound_latency 0.05  
 sound_mode auto  
 sound_normalize yes  
 sound_samplerate 44100  
 sound_samples yes  
 sound_volume -3  
 sync_fps auto  
 sync_resample auto  
 sync_speed 1  
 sync_startuptime auto  
 sync_turbospeed 3  
 ui_color[help_other] 000000 808080  
 ui_color[help_p1] 000000 ffff00  
 ui_color[help_p2] 000000 00ff00  
 ui_color[help_p3] 000000 ff0000  
 ui_color[help_p4] 000000 00ffff  
 ui_color[interface] 000000 ffffff  
 ui_color[select] 000000 afffff  
 ui_color[tag] 247ef0 ffffff  
 ui_font auto  
 ui_fontsize auto  
 ui_helpimage auto  
 ui_translucency 0.8  
 input_map[p1_up] keyboard[0,up]  
 input_map[p1_left] keyboard[0,left]  
 input_map[p1_right] keyboard[0,right]  
 input_map[p1_down] keyboard[0,down]  
 input_map[p1_button1] keyboard[0,a]  
 input_map[p1_button2] keyboard[0,s]  
 input_map[p1_button3] keyboard[0,d]  
 input_map[p1_button4] keyboard[0,q]  
 input_map[p1_button5] keyboard[0,w]  
 input_map[p1_button6] keyboard[0,e]  
 input_map[p1_button7] keyboard[0,z]  
 input_map[p1_button8] keyboard[0,x]  
 input_map[p2_up] keyboard[0,i]  
 input_map[p2_left] keyboard[0,j]  
 input_map[p2_right] keyboard[0,l]  
 input_map[p2_down] keyboard[0,k]  
 input_map[p2_button1] keyboard[0,f]  
 input_map[p2_button2] keyboard[0,g]  
 input_map[p2_button3] keyboard[0,h]  
 input_map[p2_button4] keyboard[0,r]  
 input_map[p2_button5] keyboard[0,t]  
 input_map[p2_button6] keyboard[0,y]  
 input_map[p2_button7] keyboard[0,v]  
 input_map[p2_button8] keyboard[0,b]  

Starting a game is "easy" once your paths are properly configured:
 advmame game_name  

You just have to "guess" your game name, but it is generally the name of your ROM, or very close, and Mame offers you suggestions if it fails at recognizing the game.

Super NES emulation: snes9x-sdl

The SNES emulation on snes9x-sdl has been one of my disappointments on this project. Although some games are playable, I frequenty encounter huge slowdowns that I have not been able to fix. The strange thing is that, as the slowdowns appear suddenly in the middle of a game, they seem to be triggered by some event that I have not been able to identify.

You can find the original source code right here:

Anyway, I might take some time in the future to work on this, but in the meantime, you might be interested by some tweaks that I have done in snes9x-sdl.

  • I have made a minor optimization in the 2x upscale filter, and written a 3x upscale filter (file filter/blit.cpp). This enables quasi-fullscreen on a 720p display. The calls to this filter have been hard-coded, along with other optimizations, in sdl/sdlvideo.cpp
  • I have hard-coded my key setup in sdl/sdlinput.cpp. I've done that 2 years ago, so I don't remember exactly why this was needed, but it must have been convenient :-)
  • I have changed an audio rate setting in sdl/sdlmain.cpp. This one has been a pain to fix. I did not have sound at first, and through debugging, I noticed that this value was the culprit. Changing it made everything fine afterward.

My own version of the emulator is on my github page: The pixbox.patch file at the root lists all the changes I have made.

To compile, make sure the following environment variables are set, and gcc/g++ are the 4.9.1 versions (not sure this is very important in practice):
 CC = gcc  
 CXX = g++  
 AS = as  
 CFLAGS += -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=vfpv3-d16   

/media/BBB/lib is the path where the SDL libraries have been installed. And then, just compile, in the classical Linux way:
 ./configure --prefix=/media/BBB/bin --enable-mtune=cortex-a8 --disable-gamepad

You can now run the emulator as follows (adapt to your own path):
 /media/BBB/sources/snes9x-sdl-master-optim/sdl/snes9x-sdl -nomp5 -nojustifier -nomouse -nosuperscope -port1 pad1 -port2 pad2 -playbackrate 40960 /media/BBB/roms/snes/your_rom  

Tuesday, 1 March 2016

Megadrive/Genesis, Master System, MegaCD/SegaCD, 32x emulation: Picodrive

I love old Sega systems! I know, Nintendo had Mario, Zelda, etc. are awesome, but one cannot fight childhood memories!

Picodrive is an awesome emulator: it emulates the Megadrive ecosystem, and even the Master System (which can be considered as part of the Megadrive ecosystem, as there was actually a Master System in each Megadrive). 32x emulation is way too slow on my setup, but it works. I remember seeing people running it on other, roughly equivalent systems, so I may have missed something.

I have put on my github account my modified version of Picodrive. The "pixbox.patch" file at the root of the folder is the difference with the original repository. It has been a long time since I last checked it out, and there must have been some evolutions, but I do not want to risk breaking what works perfectly on my system.

So, here are my main changes anyway:

  • I have forced "6 button" input on all the controllers. This was to fix what I supposed was a bug (some buttons not working), but which was a wrong soldering of my buttons! I suppose you can feel free to ignore this patch. I recall that I did not intend to share my modifications at first!
  • I have hard-coded the path to the system roms to /root/.picodrive. Otherwise, it looked for them in the current directory, which made little sense for an application which I intended to start from a service.
  • The most important change: starting the application with the environment variable NO_MENU set removes the menu when quitting a game. Which allows returning to my custom launcher.
Make sure the following environment variables are set, and gcc/g++ are the 4.9.1 versions (not sure this is very important in practice):
 CC = gcc  
 CXX = g++  
 AS = as  
 CFLAGS += -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=vfpv3-d16   

/media/BBB/lib is the path where the SDL libraries have been installed. And then, just compile, in the classical Linux way:
 ./configure --sound-drivers=sdl  

Once compiled, you can move the executable wherever you want (I put mine in /media/BBB/bin and set my PATH environment variable accordingly).

My typical command line to start the emulator is:
 SDL_VIDEO_YUV_DIRECT=1 SDL_VIDEO_YUV_HWACCEL=1 SDL_ACCEL=1 LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:/media/BBB/lib NO_MENU=1 /media/BBB/sources/picodrive/picodrive/PicoDrive -config /root/.picodrive/config2.cfg   

Yes, that's a lot of environment variables! But this is necessary to have a proper display on SDL. Feel free to tweak your own config2.cfg file, it is quite self-explanatory (or you can start the emulator without NO_MENU set to configure it once and for all).

NeoGeo emulation: gngeo

I have very little to say about this emulator: it runs almost out-of-the-box on the BeagleBone Black. I use version 0.7 (unmodified), which you can get here:

Make sure the following environment variables are set, and gcc/g++ are the 4.9.1 versions (not sure this is very important in practice):
 CC = gcc  
 CXX = g++  
 AS = as  
 CFLAGS += -O3 -march=armv7-a -mtune=cortex-a8 -mfloat-abi=hard -mfpu=vfpv3-d16   
/media/BBB/lib is the path where the SDL libraries have been installed. And then, just compile, in the classical Linux way:
 ./configure --prefix=/media/BBB/ --program-suffix=-0.7 --disable-gui
make install

The only quirk with this library is that it sometimes fails at loading roms, as the romset names may not match what you have. I have edited my romset definitions to match those of the games I have. I made it public on my github repository, in case this can help: Not all games are covered, but this may help you discover Metal Slug, which is the essential part of any emulation system!

To start the emulator, here is the command line I use, which allows me to set the path to the roms, the path to my romset definitions, the scaling (3x, full height on a 720p display), and the key mapping:
 gngeo-0.7 --p1key=97,115,100,113,49,53,273,274,276,275 --p2key=102,103,104,98,50,116,105,107,106,108 --scale=3 --romrcdir=/media/BBB/sources/gngeo-0.7/romrc.d/ --rompath=/media/BBB/roms/neogeo/