hello everyone and welcome to my talk
state of retrogaming and Emacs
[Music]
first of all a little bit about myself
my name is neilman I'm 28 years old
I work as a cyber security consultant
msg systems and
test other people's web applications and
review the source code for security
problems
you can reach me by email I have my own
self-hosted git repositories
and I have a blog where you can
occasionally find new posts by me on all
kinds of things not just emix things
so but the motivation about this one I
found that Emacs is the ultimate
procrastination machine and there are
lots of fun demonstrations I'll go over
a few of them
for example someone made a thing to
order sell it for himself online so it
doesn't have to walk over to the shop
there's plenty rc bots there's some game
things
there's an emulator for the z machine
which you can use to play zorg
and so I asked myself at this point can
you actually emulate retro games at
60fps and it looked around a bit
and found some projects but none that
were actually able to
do it at 60fps so I set out to do my own
one
and looked out for a console that you
can actually emulate at that speed
using emax with its very very limited
rendering
[Music]
and here's the project chip8.el it's
pretty much finished
it clocks into under 1000 sourced lines
of code
it supports the superchip 8 extensions
it runs at full speed all games behave
okay as far as I'm concerned and
yeah I'm pretty happy with it it's very
much the hell world of emulation
and I might maybe do some other
emulation projects in the future
now for the section which is the longest
bunch of fun facts about ship a dot el
which I've learned
during this project so
what the hell is debate anyway first of
all unlike many other emulation game
things it's not a console but a vm
it was designed for easy parting of home
computer games
it wasn't terribly successful and but
there's still a small community of
enthusiasts
writing games for it and there are even
a few demos
this vm has system specs it has a very
very simple 8-bit cpu with 16 registers
and
36 fixed size instructions you have a
whole
4 kilobyte of ram you have a stack with
16 return addresses
the resolution is 64 by 32 black white
pixels
rendering is done by drawing sprites
these are drawn in excel mode meaning
that if you
draw a sprite and set a bit it just
flips over from black to white or white
to black
first one you have a modern buzz that
can just beep at one
frequency and most unusually there's a
hexadecimal keypad as input
so the keys are basically zero to nine
and a to f
so how does this whole thing work it
runs an unspecified speed
you'll probably have to do some fine
tune you find the speed you're happy
with
sound and delay timers exist they count
down at 60fps down to zero
this is done so that you can play a
sound at some specific time
the game itself is loaded with a fixed
offset into ram the program account is
set to exactly that offset
and from there it enters the game loop
where decodes and instruction executes
it for the side effects and just
loops and does this at infinitum
[Music]
so the game was the first thing where
into problems the usual game approach is
to
do stuff figure out how long to eight
wait for exactly that much and
repeat this doesn't work well in imax at
all because well
user input basically and
Emacs is designed to just do whatever it
needs to do whenever you enter use input
instead of
doing things at one specific time if you
try to do
interruptable sleep well you get
unpredictable behavior
for example can be the timer doesn't run
at all at next time because you've
accidentally cancelled it
if you do uninterruptable sleep it's
freezes instead which isn't what you
want either
so I went for timers which forced me to
do inversion of control
meaning that I have to write code in the
style where it's just call it
time and this allows this input to
happen and to
for things to progress at roughly the
speed I want to
so there's the skydiver function which
is called a 60fps
and I have to be very careful to not do
too much in it
and say this function execute cpu cycles
decrypt the sound delay registers and
redraw
the screen so to map this whole system
to mx lisp
I've used just integers and vectors
which contain even more integers
this is used for the ram registers
return stack key state screen and so on
and so forth basically
what you would do if you were writing c
all of this is stored in global
variables I'm not using any
lists at all and as a side effect
there's no constant going on at all
there are no extra objects created which
would trigger
garbage collection pulses this getting
this red was rather tricky actually and
there were some
in garbage collection problems which I
had to resolve over time
so the coding instructions for this you
have to know that all instructions are
two bytes long
and the arguments encoded inside them
for example the jump to address
instruction
is encoded as one and three hex digits
the type is extracted masking with f000
and then shifting it by 12 bits mask
means the hd
performance binary end you can do the
same with the argument basement with
zero fff
and no shift if you do this long enough
you'll find common patterns for example
addresses are always encoded like this
using the last three nibbles in the code
you'll find a big count which dispatches
on the type and executes it for the side
effects
[Music]
for testing I've initially just accused
the rom until I fit ctrl g
and then use the debug command to run
the screen to a buffer
later on I found tiny roms that just
display a static
test screen for example logo and looked
whether it looked right
I added instructions as needed and went
through more and more and more roms and
later I wrote in unit test suite as a
safety net and this unit test suite it
just
sets up an empty emulator state executes
some instructions and then looks whether
the
expected side effects have happened
for debugging I usually use e-debug but
this was super ineffective because well
you don't really want to step through
big cons doing side effects for every
single cycle when it can take like 100
cycles for things to happen
therefore I've set up logging and
whenever I locked something
and couldn't figure out the error I
compared my lock output with
instrumented version of another emulator
and if the locks diverge then I have
figured out where the bug lies and could
look deeper into it
future project idea might be a chip 8
debugger but I doubt I'll ever
go into it for analysis I initially
wrote a disassembler which is a very
simple thing but super tedious
especially if you wanted to add advanced
functionality for example analysis or
thinking of what part is data what had
this code
and I had this great idea for using the
radari 2 framework
and adding analysis and disassembly
plug-in for it
so I looked into this found okay here
where you can write plugins in c
but also in python so I wrote one in
python and then the scout there's
actually existing one in core which you
have to enable explicitly by passing its
argument so I've tried it and found it's
not exactly as good as my own one so
improved this one and submitted pull
requests until it was at the same level
[Music]
rendering was the trickiest part of this
whole thing because
well I decided against using a library
not like there would have been any
usable library for this
my usual approach of accelerating svg
file was too expensive it just created
too much garbage and took too long time
I then tried creating mutating strings
this was either either too expensive
just like svgs or too complicated I
tried changing svg tiles which created
gaps between the lines
then I tried to create an xpm file which
was backed by a bull vector
administrating this bull vector
but the image caching effect made it
just every nth frame to appear which
wasn't good either then I had the idea
to just use plain text
and paint the individual characters with
a different background color this
this had perfect perfect performance
there were many optimization attempts
until I got there and it was
very very stressful I wasn't sure
whether I would ever get to accept the
performance at all
for sound you only need to a single beep
so technically it shouldn't be difficult
to emulate it
however doing this is hard because Emacs
officially only supports synchronous
playback of sounds
but there's also emax process which you
can launch in asynchronous way
so I looked into it and found that
employee has a slave mode and mpv
supports listing on the
fifo for commands so I've created a pipe
started a past mpv in loop mode and
always send in pause and pause command
to the fifo and that way I could control
when to start beeping and stop beeping
so yeah that's it so far was a very
educational experience
I have tried out a bunch of games which
were
well I almost say the worst ports of
classic games I've ever tried
it wasn't terribly fun to play them but
was fun to improve the emulator until
well things worked good enough
and I've learned a lot about how
computers work at this level
so maybe maybe I'll in the future make
another emulator
but uh I'm not sure whether anything
more advanced like intel 8080 emulator
will actually run mix fast enough
but it's still an interesting idea
because then you could actually have an
os
inside Emacs and fulfill that one
specific meme
but if I try to do most serious stuff
I'll probably use chicken scheme which
is my
preferred language for serious projects
and writing neso gamer emulator
and that's it thank you