enables printf() logging over usb from homebrew games built using the n64 sdk, while running on an everdrive 64 device.
at a high level, the steps involved are:
- copy the code to your n64 game and add calls to the ed64log api
- install or build the logger client program on your computer
then to run your game with logging:
- connect to the everdrive via usb
- build and run your game on the everdrive
- run the logger client program on your computer
-
copy the sources from the n64 directory of this repo into your game's source, and add the .c files to your Makefile.
-
in the initialization of your game, include ed64io.h and call
evd_init()
to initialize the everdrive hardware for writing. see the example app. -
then add synchronous or asynchronous logging calls into your game code
- include ed64io.h in your source file and use
ed64PrintfSync()
as you would normally useprintf()
in other programs. note: this will block the thread (eg. temporarily freeze the game) until it finishes logging (including if the host is not connected). this is mainly useful to guarantee that the log message gets through, eg. before a crash/failed assertion, or to test that the logging functionality is working.
- in the main loop (or at some regular interval) include ed64io.h and call
ed64AsyncLoggerFlush()
to write pending logs to the computer via usb. - to use printf logging in your game, include ed64io.h in your source file and use
ed64Printf()
as you would normally useprintf()
in other programs. - up to 512 chars will be buffered. if you log more than that without calling
ed64AsyncLoggerFlush
, the output will be truncated. if you want to log a lot you wil need toed64AsyncLoggerFlush()
more frequently during a frame. you could even call it on a timer in a background thread. i haven't explored this fully.
you can see an example of implementing logging in a game in this commit to goose64.
you can override nintendo's implementation of osSyncPrintf
with an ed64log-based version by calling ed64ReplaceOSSyncPrintf()
once as part of your game's startup process. this will allow all osSyncPrintf()
calls to work, including debug error messages in libultra_d and libmus_d.
optionally, you can set up an exception handler thread to automatically log details when an exception occurs (eg. invalid memory access) by calling ed64StartFaultHandlerThread()
, passing the thread priority to run at (typically, the same as the main thread) like this. for usage details, see the example app readme.
optionally, you can override the default N64 OS error handler which prints errors in calls to libultra functions to osSyncPrintf
, with one that prints to ed64SyncPrintf
instead, by calling ed64RegisterOSErrorHandler()
once in the initialization of your progam.
note: this is not needed if you override osSyncPrintf()
as described above.
if you experience a freeze/hang in your game which doesn't produce any useful error message, you can create a watchdog timer to detect when the game has frozen and then print out useful information about the application state.
ed64StartWatchdogThread
takes a pointer to an integer value which should continually change while the program is working correctly (eg. a counter of the absolute frame number) and an interval in milliseconds at which the watchdog will check if the program is still running. when the watchdog timer interrupts the program it will check if the current value of the integer has changed since the last check. if the program has frozen (for example, having entered an infinite loop), the watchdog thread will print the current state of each thread, and a stacktrace of the thread's execution.
example:
ed64StartWatchdogThread(&intValueThatIncrements, 500);
on any OS, you can use the node.js-based client to receive logs
first install node and npm
then install ed64logjs:
npm install -g ed64logjs
then, after starting the game on the everdrive, run
ed64logjs
install required libraries from homebrew:
brew install libftdi libusb
-
in XCode, open xcode/ed64log.xcodeproj
-
by default, building will install ed64log to
/usr/local/bin
. If you want to change this, in the ed64log target's build phases tab, change the 'copy files' command output path to where you want the ed64log binary installed -
click 'run' to build and install the ed64log binary
then, after starting the game on the everdrive, run
./ed64log
this will output the logs as they are sent from the everdrive
install libftdi
from your package manager of choice (including headers). eg for ubuntu:
sudo apt-get install libftdi1 libftdi1-dev
compile the ed64log tool from source:
./make.sh
then, to start tailing the logs:
# needs sudo to access usb device
sudo ./ed64log
the source of the ed64log client is based on loader64 by saturnu tt@anpa.nl