Mesen - Linux (preview)

This is an archive of a topic from NESdev BBS, taken in mid-October 2019 before a server upgrade.
View original topic
Mesen - Linux (preview)
by on (#184970)
I just finished making a build Mesen that runs under Linux and I was wondering if some people would be willing to test it on their end to see if it works (or crashes!).
It runs under Mono (only tested Mono 4.2.1 - I assume any recent version will work) and requires SDL2 to be installed.

Building requires clang or gcc, Mono/XBuild and SDL2. It comes with a very basic makefile - just run "make" and then "make run" to start the emulator.
There's also a prebuilt binary here: [linux preview download] (This was built on Ubuntu 16.04 - if you get a popup asking to download the microsoft C++ runtime, you are missing some dependencies)

The main issues remaining at the moment are:
-Gamepads aren't supported (yet)
-Automatic updates won't work
-Netplay doesn't automatically add port forwarding rules to the router (UPnP)
-Fullscreen mode doesn't hide the taskbar

Beyond that, everything else should work (including debugging, netplay (works cross-platform!), NSF player, etc.)
The code itself is almost identical between the Windows & Linux versions - the only portions that differ being the Video/Audio/Input handling (DirectX vs SDL), so most things should be ok.
There is a bunch of features I haven't had the time to test, so I definitely expect some things to be broken beyond what I just listed, though.

Also, for some reason, performance seems to be worse than the Windows build (e.g ~30% slower).
But I've only tested on a VM, so that may be part of the reason.

If you encounter any issue or crash with the Linux version, please let me know in this thread.
Re: Mesen - Linux (preview)
by on (#184973)
Building from source was super easy, with two small sticking points: for some reason std::sqrt needs #include <cmath> ... and the makefile accidentally uses clang instead of $(CC) to build SevenZip/obj/%.o


Debugger is quite nice, but again two small sticking points, both pertaining to fonts. One: the disassembly and memory viewer both seem to be using some random proportional font instead of a monospaced one, and two: the memory viewer is doing something very odd:
Attachment:
cpumemory.png
cpumemory.png [ 36.76 KiB | Viewed 3746 times ]
Re: Mesen - Linux (preview)
by on (#184976)
Thanks, I fixed the makefile & missing header in xBRZ's code.

Both of the debugger issues you mentionned are actually the same - it's because the display needs to use a monospaced font to work properly.
At the moment it's hardcoded to use "Ubuntu Mono" in BaseControl.cs since that's what I had available on the VM - if you change it to a font you have, it should work as expected.
Are there any "standard" monospaced fonts that I can reasonably expect all (or at least most) linux distros to have?
Re: Mesen - Linux (preview)
by on (#184979)
Sour wrote:
Are there any "standard" monospaced fonts that I can reasonably expect all (or at least most) linux distros to have?

I guess you could query fontconfig for the user's preferred monospace font. If all else fails, you could find a free font, like good old DSM, and bundle it. If that's too big, you could bundle a bitmap font.

I plan to try Mesen after I've upgraded my laptop to Xubuntu 16.04 "Xenial". It currently runs 14.04 "Trusty" because that was the newest when I began my last major paid project, and I didn't want to do a major upgrade right in the middle.
Re: Mesen - Linux (preview)
by on (#184985)
Thanks for the suggestion - I bundled DroidSansMono (it's pretty small) and automatically install it to ~/.fonts on startup, seems to work pretty well.
Also reduced the default font size for the debugger because DSM looked ridiculously big.

I'm not sure how hard it would be to build on Ubuntu 14, probably just depends on the compiler you have installed.
The code uses the C++17 filesystem api, which apparently is only available in GCC 5.3+ (Dec 2015).
Re: Mesen - Linux (preview)
by on (#184987)
Use the font "fixed" which should be included on all X window systems.
Re: Mesen - Linux (preview)
by on (#184988)
AIUI, the fonts infrastructure on any even remotely modern linux uses FontConfig, and that's by default configured to treat the special name "monospace" to mean 'some random installed monospaced font'


"fixed" will only DTRT if FontConfig is configured to use bitmap fonts, which it isn't by default.
Re: Mesen - Linux (preview)
by on (#184994)
Ok, another minor bug, having to do with partial screen redraws. The memory map visualization at the bottom of the debugger can give me some awfully weird results if I drag another window over it:
Attachment:
memory-map-weirdness.png
memory-map-weirdness.png [ 33.32 KiB | Viewed 3658 times ]



Oh, and, for hilarity's sake, the automatic subroutine finder gets awfully confused by the code that (my) NROM build of Driar puts into RAM.

edit: Another: if I go into the Audio configuration, change anything, quit, and restart, then audio doesn't work. For some reason, having any non-empty value in <AudioDevice> in the configuration file causes sound to stop working.
Re: Mesen - Linux (preview)
by on (#185023)
Thanks for testing! I'll try and fix these tomorrow.

For the audio issue, what does the "Device" dropdown contain in the audio config window?
I'm thinking it might have multiple devices with the same name and it doesn't pick the right one after you change any other setting.

A bit unrelated, but how is the audio latency? On my VM it's pretty terrible (e.g 300-400ms real latency with the latency set to 50ms), but I think that might just be due to the VM itself as I don't really see any reason why it would be so high based on the code.

Also, I just finished adding gamepad support if you feel like giving it a try.
Re: Mesen - Linux (preview)
by on (#185026)
Sour wrote:
For the audio issue, what does the "Device" dropdown contain in the audio config window?
"HDA Intel PCH, ALC1150 Analog" or the same but ending in "Digital"
Either choice causes no audio on the analog output.

Quote:
how is the audio latency?
31ms scheduled latency → ≈100ms real-world A-V latency but 15ms scheduled latency → ≈60ms real-world A-V latency??

Quote:
Also, I just finished adding gamepad support if you feel like giving it a try.
Only thing I have is a USB Gravis GamePad Pro, and it didn't work
Re: Mesen - Linux (preview)
by on (#185027)
lidnariq wrote:
"HDA Intel PCH, ALC1150 Analog" or the same but ending in "Digital"
Either choice causes no audio on the analog output.
Odd - it could potentially be a SDL bug (although it's more likely to be my own code's fault). I committed a patch/safety net that will ignore the device name if audio init fails because of it (and log a line in the "message log" with the string it tried to use to initialized the audio system - if it doesn't match the dropdown's content, that's probably what's causing the bug in the first place) - so at the very least you should be able to alter the audio config normally now.

Quote:
31ms scheduled latency → ≈100ms real-world A-V latency but 15ms scheduled latency → ≈60ms real-world A-V latency??
Not quite sure what's going on here :) I would have expected ~85ms, not 60ms. Either way, this is much better than what I am getting.

Quote:
Only thing I have is a USB Gravis GamePad Pro, and it didn't work
That sounds pretty old. Maybe it's not supported by the newer /dev/eventX api and only works via /dev/joyX?
Re: Mesen - Linux (preview)
by on (#185029)
Sour wrote:
I committed a patch/safety net that will ignore the device name if audio init fails because of it (and log a line in the "message log" with the string it tried to use to initialized the audio system - if it doesn't match the dropdown's content, that's probably what's causing the bug in the first place) - so at the very least you should be able to alter the audio config normally now.
Yup, that works, and yup, the error you'd expect to find shows up in the log ([Audio] Failed opening audio device 'HDA Intel PCH, ALC1150 Analog', will retry with default device.)

Quote:
[a USB Gravis GamePad Pro] sounds pretty old. Maybe it's not supported by the newer /dev/eventX api and only works via /dev/joyX?
No, I can read it both via /dev/input/js0 and /dev/input/event14

And if i install libevemu-tools and try running evemu-describe it certainly seems to find it.
Re: Mesen - Linux (preview)
by on (#185070)
lidnariq wrote:
And if i install libevemu-tools and try running evemu-describe it certainly seems to find it.
Could you send me the full output for that device when you use evemu-describe and enter the device's number?
e.g:
# EVEMU 1.2
# Input device name: "Microsoft X-Box 360 pad"
# Input device ID: bus 0x03 vendor 0x45e product 0x28e version 0x114
# Supported events:
# Event type 0 (EV_SYN)
# Event code 0 (SYN_REPORT)
# Event code 1 (SYN_CONFIG)
[...]

The supported events/codes, etc. should help me figure out why it's not working with the code I have.
Re: Mesen - Linux (preview)
by on (#185076)
lidnariq wrote:
Ok, another minor bug, having to do with partial screen redraws.
This should be fixed - I couldn't reproduce it on my end in Linux, but actually had some refresh issues visible in Windows under some circumstances, so I fixed those.

lidnariq wrote:
Oh, and, for hilarity's sake, the automatic subroutine finder gets awfully confused by the code that (my) NROM build of Driar puts into RAM.
I took a look and I can't see anything wrong - the function list can only detect functions from PRG ROM (since anything else could be erased at any time). As far as I can tell, it's working as I'd expect. What issue did you have with it?


Unrelated, but I also fixed the code window's mouse over tooltip in the debugger (the tooltip when you mouse over labels/addresses didn't show up correctly on my end - it was too small to fit the content)
Re: Mesen - Linux (preview)
by on (#185081)
This is what I see (on the left) with Driar—the code keeps moving the RTS around in RAM, so I assume that's why we end up with this fragmented thing:
Attachment:
unroller-blocks.png
unroller-blocks.png [ 2.76 KiB | Viewed 3488 times ]


Redraw issues are fixed.

Other things:
- The nametable portion of the PPU memory map seems to be a misleading with things that use ROM nametables?
(I was testing with my silly N163 demo here as well as After Burner)
- Trying to load a 7z file from the GoodMerged GoodNES distribution elicits some complicated crash
- (wishlist) please let me start Mesen with a path to a NES ROM as the first argument?
Re: Mesen - Linux (preview)
by on (#185086)
Today I reinstalled Xubuntu on my laptop for three reasons: upgrade to an SSD, retain support even after Canonical drops i686 in favor of amd64 sometime in 2018, and remove years of cruft accumulated in the transitions from GNOME 2 through Unity to Xfce.

In the process, I found Debian's page about fontconfig, which describes a shell command to list all available monospace fonts:
Code:
fc-list :spacing=mono


lidnariq wrote:
- (wishlist) please let me start Mesen with a path to a NES ROM as the first argument?

Seconded. If I adopt Mesen, I need this for my workflow where make run starts the emulator.
Re: Mesen - Linux (preview)
by on (#185089)
lidnariq wrote:
This is what I see (on the left) with Driar—the code keeps moving the RTS around in RAM, so I assume that's why we end up with this fragmented thing
Ah, I see what you meant now - thought you were talking about the function list. For code in ram, Mesen keeps a cache of what instructions were run, and then invalidates that cache on subsequent writes to RAM, which would result in this if you're constantly altering only portions of it (i.e replacing NOPs with RTS and the like). And unrelated, but I think the green background maybe actually be a bug in this case, will have to check that.


PPU/CPU memory map:
They are not perfectly accurate (i.e the "work ram" segment is hardcoded) and some mappers (which require "lower-level" functionalities in the code) do not play nice with it (MMC5 and N163 are good examples of this). Most common mappers (and the vast majority of supported mappers) do not use these though, and should display accurate info for the 0x8000-0xFFFF CPU banks and the entire PPU memory.

7zip crash: Thanks, this is fixed (I just learned the hard way that wchar_t is not 2-bytes in Linux!)

Loading from command line:
This is already supported - it's how the file associations options work. ("make run" is just an easy way to run it)
e.g from the bin/x64/Release folder:
./Mesen.exe ~/Desktop/DriarNROM\(UE\)2.7z
mono Mesen.exe ~/Desktop/DriarNROM\(UE\)2.7z

Both correctly load up Mesen w/ the ROM.


Edit: About fontconfig - I kinda feel like shipping a small default font (e.g DSM like is the case at the moment) might be a better option? It helps ensure that the controls display as I'd expect (they are all custom drawn controls) so it may reduce bugs. Arguably I could also allow the user to select a font, but that seems like going a bit too far on customizations (and again, adds the possibility of some fonts not working as expected, etc.)

Edit #2: About 32-bit support - do people actually still run Linux on 32-bits environments? At the moment Mesen ships with both 32-bit & 64-bit DLLs bundled for the Windows version since a lot of people still have 32-bit OSes (no thanks to Windows 10 still shipping with a 32-bit version - despite likely not supporting any 32-bit-only processors). I could do the same for Linux, but I was hoping x64 might be good enough for just about everybody.
Re: Mesen - Linux (preview)
by on (#185091)
Sour wrote:
Loading from command line:
This is already supported - it's how the file associations options work. ("make run" is just an easy way to run it)
e.g from the bin/x64/Release folder:
./Mesen.exe ~/Desktop/DriarNROM\(UE\)2.7z
mono Mesen.exe ~/Desktop/DriarNROM\(UE\)2.7z

Both correctly load up Mesen w/ the ROM.
... Ah-hah. It requires an absolute path, relative paths won't work.


Sour wrote:
For code in ram, Mesen keeps a cache of what instructions were run, and then invalidates that cache on subsequent writes to RAM, which would result in this if you're constantly altering only portions of it
It's been so long I'd forgotten, but the only thing I'm doing is changing the argument in LDA #imm. And alternating between whether the very first instruction in the unrolled loop (at $04E0) is LDA #imm or RTS ... no moving the RTS around.

Which would still explain what's happening.
Re: Mesen - Linux (preview)
by on (#185093)
lidnariq wrote:
... Ah-hah. It requires an absolute path, relative paths won't work.
Ah, nice catch. Actually, it does support relative paths, but since Mesen changes the working folder to ~/Mesen at startup, they're paths relative to that location (not very useful). It shouldn't be too hard to fix though.
Re: Mesen - Linux (preview)
by on (#185334)
Xubuntu 14.04.5 LTS (x86), lastest -master:

Code:
evgs@VirtualBox:~/Загрузки/Mesen-master$ make -j4
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zAlloc.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zArcIn.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zBuf.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zCrc.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zCrcOpt.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zDec.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zFile.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zMemBuffer.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../7zStream.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Bcj2.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Bra86.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Bra.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../BraIA64.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../CpuArch.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Delta.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Lzma2Dec.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../LzmaDec.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Ppmd7.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Ppmd7Dec.c
mkdir -p SevenZip/obj.x64 && cd SevenZip/obj.x64 && clang -fPIC -Wall -O3 -m64 -c  ../Precomp.c
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++14 -O3 -m64 -c  ../ArchiveReader.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++14 -O3 -m64 -c  ../AutoResetEvent.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++14 -O3 -m64 -c  ../blip_buf.cpp
error: invalid value 'c++14' in '--std=c++14'
make: *** [Utilities/obj.x64/ArchiveReader.o] Ошибка 1
make: *** Ожидание завершения заданий…
error: invalid value 'c++14' in '--std=c++14'
make: *** [Utilities/obj.x64/AutoResetEvent.o] Ошибка 1
error: invalid value 'c++14' in '--std=c++14'
make: *** [Utilities/obj.x64/blip_buf.o] Ошибка 1
evgs@VirtualBox:~/Загрузки/Mesen-master$


I tried to replace
GCCOPTIONS=-fPIC -Wall --std=c++14 -O3
to
GCCOPTIONS=-fPIC -Wall --std=c++11 -O3
in makefile and compile continues. But finally it doesn't help:

Code:
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../ArchiveReader.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../AutoResetEvent.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../blip_buf.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../CRC32.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../FolderUtilities.cpp
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../HexUtilities.cpp
../ArchiveReader.cpp:29:9: error: call to implicitly-deleted copy constructor of 'std::stringstream' (aka 'basic_stringstream<char>')
        return ss;
               ^~
/usr/include//c++/4.8/sstream:502:32: note: copy constructor of 'basic_stringstream<char, std::char_traits<char>, std::allocator<char> >' is implicitly
      deleted because base class 'basic_iostream<char, std::char_traits<char> >' has a deleted copy constructor
    class basic_stringstream : public basic_iostream<_CharT, _Traits>
                               ^
/usr/include//c++/4.8/istream:796:7: note: copy constructor of 'basic_iostream<char, std::char_traits<char> >' is implicitly deleted because base class
      'basic_istream<char, std::char_traits<char> >' has a deleted copy constructor
    : public basic_istream<_CharT, _Traits>,
      ^
/usr/include//c++/4.8/istream:58:27: note: copy constructor of 'basic_istream<char, std::char_traits<char> >' is implicitly deleted because base class
      'basic_ios<char, std::char_traits<char> >' has a deleted copy constructor
    class basic_istream : virtual public basic_ios<_CharT, _Traits>
                          ^
/usr/include//c++/4.8/bits/basic_ios.h:66:23: note: copy constructor of 'basic_ios<char, std::char_traits<char> >' is implicitly deleted because base class
      'std::ios_base' has an inaccessible copy constructor
    class basic_ios : public ios_base
                      ^
1 error generated.
mkdir -p Utilities/obj.x64 && cd Utilities/obj.x64 && clang++ -fPIC -Wall --std=c++11 -O3 -m64 -c  ../IpsPatcher.cpp
make: *** [Utilities/obj.x64/ArchiveReader.o] Ошибка 1
make: *** Ожидание завершения заданий…
../FolderUtilities.cpp:4:10: fatal error: 'experimental/filesystem' file not found
#include <experimental/filesystem>

Re: Mesen - Linux (preview)
by on (#185335)
Unfortunately, gcc ≥v5.3 (or whatever corresponding version of clang) is a firm requirement, due to using C++14 constructs.
Re: Mesen - Linux (preview)
by on (#185337)
Like lidnariq said, you'll need gcc 5.3+ (not sure about clang's version, but 3.8 works fine for me)
It actually also uses some features planned for C++17 (filesystem api) - I go for standard & cross-platform APIs whenever possible, since this reduces the odds of platform-specific bugs (at the cost of not working on older compilers)
Re: Mesen - Linux (preview)
by on (#185343)
On Xubuntu 14.04, sudo do-release-upgrade should give you Xubuntu 16.04, which has newer versions of GCC and pretty much everything else. For me it gives this:
Code:
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609