The Mupen64+ emulator is one of the best open source emulators available for the Nintendo 64, so if you are interested in emulator development or how the Nintendo 64 works then this post should help.
This post will be a sort of Cliff Notes
to give an overview of how the emulators source code is laid out and should give you an idea on where to start looking for what you are interested in.
The first step is to compile the emulator on your system, this will allow you to experiment by changing variables and functions to help you better understand the emulator.
Building the emulator in MacOSX is fairly straightforward as long as you have all the dependencies installed.
brew install pkg-config libpng sdl freetype nasm binutils
This step is common among all the Operating systems, the DEBUGGER=1
parameter is used to enable debug mode so that you can step through the N64 MIPS assembly instructions one at a time and even supports creating basic breakpoints.
make all DEBUGGER=1
This section is a reference to be used only when you have a problem compiling the emulator, otherwise it can be ignored.
If you get this error you will need to modify the MakeFile and change -mmacosx-version-min= in both places to the version of your OS (e.g 10.14)
If you get the following error:
nasm: fatal: unrecognised output format `macho64' - use -hf for a list
Then make sure to install a new version of nasm, as it is most likely out-of-date:
brew install nasm
If you get an error about dis-asm.h
such as:
../../src/debugger/dbg_memory.c:37:10: fatal error: 'dis-asm.h' file not found
#include <dis-asm.h>
You need to install bin-utils
via brew and then you need to run the following in your current bash session:
export LDFLAGS="-L/usr/local/opt/binutils/lib"
export CPPFLAGS="-I/usr/local/opt/binutils/include"
So We get further but now an new error probably due to the version of binutils:
../../src/debugger/dbg_memory.c:113:19: error: use of undeclared identifier 'print_insn_i386'; did you mean
'print_insn_m32c'?
disassemble = print_insn_i386;
To fix this I simply added this to the top of the file called dbg_memory.c
:
#define USE_LIBOPCODES_GE_2_29 1
If you get lots of Undefined symbol linker errors such as the following:
Undefined symbols for architecture x86_64:
"_htab_hash_pointer", referenced from:
_xcoff_archive_info_hash in libbfd.a(xcofflink.o)
"_libintl_dngettext", referenced from:
_ppc64_elf_build_stubs in libbfd.a(elf64-ppc.o)
"_xexit", referenced from:
_spu_elf_final_link in libbfd.a(elf32-spu.o)
"_hex_init", referenced from:
_ihex_object_p in libbfd.a(ihex.o)
_srec_object_p in libbfd.a(srec.o)
_srec_mkobject in libbfd.a(srec.o)
_symbolsrec_object_p in libbfd.a(srec.o)
_tekhex_init in libbfd.a(tekhex.o)
_verilog_mkobject in libbfd.a(verilog.o)
"__hex_value", referenced from:
_ihex_object_p in libbfd.a(ihex.o)
_ihex_get_section_contents in libbfd.a(ihex.o)
_srec_object_p in libbfd.a(srec.o)
_srec_get_section_contents in libbfd.a(srec.o)
_srec_scan in libbfd.a(srec.o)
_tekhex_object_p in libbfd.a(tekhex.o)
_getvalue in libbfd.a(tekhex.o)
...
This is due to brew not installing libiberty.a library file. I found it quite difficult to fix using brew so I installed macports and ran:
sudo port install x86_64-elf-binutils
The look in the folder: /opt/local/x86_64-elf/host/lib
and you will find a libiberty.a file, copy this across to: /usr/local/opt/binutils/lib
cp /usr/local/opt/binutils/lib/libiberty.a /usr/local/opt/binutils/lib
Ok now we have a lot less linker errors we now just need to find libintl.
Now finally change the Makefile on line 643 to add -L/usr/local/opt/binutils/lib -liberty -lintl -liconv
so it should look like:
ifeq ($(DEBUGGER), 1)
SOURCE += \
$(SRCDIR)/debugger/dbg_debugger.c \
$(SRCDIR)/debugger/dbg_decoder.c \
$(SRCDIR)/debugger/dbg_memory.c \
$(SRCDIR)/debugger/dbg_breakpoints.c
LDLIBS += -lopcodes -lbfd -L/usr/local/opt/binutils/lib -liberty -lintl -liconv
if you get the following error:
ld: library not found for -lintl
Then run:
brew link gettext --force
So Finally we have a libmupen64plus.dylib
with the debugger enabled! Now what? How do we use it?! Well first we need a few plugins to be compiled to be able to render graphics.
In order to compile Glitch64 you will need to make sure you have boost installed, which you can do via brew like so:
brew install boost
Also I had to change line 137 of MakeFile to match the following:
CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -I../../src/Glitch64/inc -DGCC -I/usr/local/Cellar/boost/1.67.0_1/include
Now Glitch64 should be able to be compiled with make
.
Finally the Console Application is the last piece of the puzzle, this is what will actually execute the emulator, so when this is built we will be able to run games!
You will need to point APIDIR to the location of the core source code you checked out earlier.
make APIDIR=/../mupen64plus-core-master/src/api DEBUG=1 all
The console application is the simplest frontend for the emulator and it also has a very basic debugger in it.
Now copy over the plugins that you have built previously such as glide64
.
Now the run the emulator! The emulator comes with an example public domain rom file called example.v64
, this ROM only seems to work with glide64 graphics for me. You can run it like so:
./mupen64plus --emumode 0 --corelib ./libmupen64plus.dylib --gfx ./mupen64plus-video-glide64mk2.dylib ./example.v64
You can run the emulator with the debugger enabled by passing a few extra parameters like so:
./mupen64plus --corelib ./libmupen64plus.dylib --gfx ./mupen64plus-video-glide64mk2.dylib --emumode 0 --noosd --verbose --debug ./example.v64
In debugger mode PC starts at 0xA4000040 (2751463488) with:
mtc0 $zero,C0_CAUSE
GlideHQ is a texture upscale for the Glide graphics emulator plugin. This uses a number of different upscaling algorithms to make textures look higher quality than the what the original hardware supported.
GlideHq comes as part of the Mupen64+ Glide64 source code.
Contains most of the emulator logic for the N64.
The r4300 is the main CPU used in the Nintendo64, it is based on the R4200 by MIPS Technologies Inc. R4200 - Wikipedia
The main implementation of the cpu is contained in the r4300_core
folder along with implementations of the 3 co-processors (cp0, cp1 and cp2).
More information about the CPU can be found here: N64 Programming/CPU overview - Wikibooks, open books for an open world
IPL2 is the PIF ROM? IPL3 is the first 1MB of CART?