\documentclass[20pt]{article}

\usepackage{hyperref}
\hypersetup{
    colorlinks=true,
    linkcolor=blue,
    filecolor=magenta,
    urlcolor=cyan,
    pdftitle={Dreamcast},
    pdfpagemode=FullScreen,
    }

\usepackage{graphicx}
\graphicspath{ {./images/} }

\title{Dreamcast JVM}
\date{}

\setcounter{secnumdepth}{0}

\begin{document}

\maketitle
%\href{images/revision-1-inserted.png}{\includegraphics{images/revision-1-inserted.png}}

\tableofcontents
\section{Introduction}

This is a from-scratch JVM implementation for Sega Dreamcast, from zero to
3D spinning translucent textured cubes in 14 days.

This is not a port of the JVM from the OpenJDK project, but instead a completely
separate and independent implementation that follows the same specification.

My time on this project was split roughly 3 ways:

\begin{itemize}
\item 30\% of my time was spent writing the actual JVM itself

\item 30\% on writing new Java libraries for manipulating the Dreamcast hardware

\item 30\% on writing a "load Java classes the Dreamcast GDROM drive" loader.

\item 10\% on designing Java APIs, (and reviewing existing APIs, e.g:
  \texttt{java.nio}/\texttt{sun.misc}), particularly related to giving Java code
  direct and arbitrary access to Dreamcast memory/registers
\end{itemize}

\section{Demo download}

There are three different versions of my demo, depending on how/where you'd like
to run this:

\subsection{Dreamcast (for physical CD-R; may also work on GD-ROM drive emulators)}
\begin{itemize}
\item \href{https://dreamcast.idk.st/jvm/jvm-cube-dreamcast.cdi}{jvm-cube-dreamcast.cdi}
\end{itemize}

\subsection{Dreamcast (for loading via a Dreamcast USB-UART)}
\begin{itemize}
\item \href{https://dreamcast.idk.st/jvm/jvm-cube-usb-uart.bin}{jvm-cube-usb-uart.bin}
\end{itemize}

\subsection{Flycast}
\begin{itemize}
\item \href{https://dreamcast.idk.st/jvm/jvm-cube-flycast.cdi}{jvm-cube-flycast.cdi}
\end{itemize}

\section{Current status}

The current Dreamcast JVM implementation is fairly complete, and will correctly
interpret a wide range of Java code correctly.

However, the following JVM features are not supported:

\begin{itemize}
\item exceptions (\texttt{try}/\texttt{catch}/\texttt{finally} in Java)

\item separately from the above, \texttt{finally} clauses from Java versions <=1.4 (2002 or
  earlier)

\item \texttt{invokedynamic} (Java lambdas, Java string concatenation, etc...)

\item \texttt{synchronized} methods (Java threads are also not implemented)

\item runtime type checks (\texttt{instanceof}/\texttt{checkedcast}) on
  zero-length/null arrays of references

\item garbage collection and memory deallocation (technically not required of a
  JVM, but fair to expect of a JVM that this exists)
\end{itemize}

The above list is \textit{probably} exhaustive. An attempt to do any of these
will trigger a failed assertion, and JVM execution will halt.

Other than above list, generally speaking Java class files emitted by any Java
version from 6 through 23 inclusive should be compatible with the Dreamcast JVM.

\section{How much of this cube demo is written in Java?}

To the greatest extent that Java (a language that does not have memory address
dereferences as a built-in language construct) is able, all manipulations of
Dreamcast hardware and memory state are manipulated directly from Java
code. Memory access occurs either directly via the \texttt{Memory.getU4} and
\texttt{Memory.putU4} static methods, or indirectly via the Dreamcast DMA
controllers.

There are no “foreign calls” to C libraries whatsoever.

The cube demo is 100\% native Java.

\section{How does the demo work?}

I believe it could be interesting if it were possible to author code for the
Dreamcast without GCC/binutils. In service to this idea, I designed this
multi-stage “boot” process. The boot process allows Java class files to be
automatically loaded from iso9660 on a CD, rather than embedded in another
binary file via a specialized toolchain.

This means that anyone with a generic \texttt{javac}, \texttt{mkisofs}, and
copies of \texttt{jvm.bin} and \texttt{gdrom\_jvm\_boot.bin} can write code for
the Dreamcast.

\href{boot.svg}{\includegraphics{boot.svg}}

\section{Could the Dreamcast JVM also work on Sega Saturn?}

\textbf{Yes.}

Java float and double primitives are perhaps the only obstacle.

Though the JVM specification does clearly specify that float and double
\textbf{must} be in IEEE-754 format, I think it would be interesting to instead
implement float as 16.16 fixed-point, and double as 32.32 fixed-point on Saturn
in deliberate violation of the specification.

Implementing fixed-point operations as primitive types rather than as a
“FixedPoint” class in Java would also yield significantly better
performance---arithmetic opcode execution is practically "free" compared to the
expense of resolving and calling instance methods, not even considering the
additional pointer indirections.

\section{What about JVM languages other than Java?}

Kotlin “hello world” works in the current Dreamcast JVM implementation:

\begin{verbatim}
fun main() {
  println("Hello world!")
}
\end{verbatim}

I did not test beyond this.

The most probable issue with attempts to run Kotlin/Clojure/Jython, etc... (and
in particular their interpreters) on the Dreamcast JVM is most of the Java SE
class library is missing. This is not a hard issue to solve; perhaps just
slightly tedious at worst.

\section{Why can't you just use the Java SE libraries from OpenJDK with the Dreamcast JVM?}

The OpenJDK class libraries depend on the OpenJDK JVM's internals (for which
there is no formal specification).

\section{What about performance? Is the Dreamcast JVM fast?}

\textbf{Absolutely not.}

On the current JVM implementation, expect performance
somewhere on the order of \textbf{100x slower} than semantically-equivalent C
code as compiled by GCC.

The fact that my cube demo spins at all at relatively nice-looking framerates is
a testament to the brute speed of the SH7091 SH4 CPU in the Dreamcast.

\section{Could Dreamcast JVM performance improve?}

The Dreamcast JVM is a fairly naive bytecode interpreter, so there are myriad
ways to improve performance. For long sequences of arithmetic operations (e.g: a
vertex transformation function), it is fairly obvious that the solution should
be to JIT-compile the bytecodes to SH instructions. I think this should be
fairly easy to do.

While there have been several "JIT-compile SH to x86" projects (as in Dreamcast
emulators), I am not aware of any "JIT-compile [thing] to SH" projects. This
adds to the list of reasons why I think this would be interesting to pursue.

Indepent of bytecode execution: method lookups, and particularly instance method
lookups, are slower than they could be. Perhaps in parallel with the JIT effort,
with a more thorough “linking” process, method lookups could likely become about
as fast as calling a function pointer in C.

\section{Does this mean Java ME games for early 2000's mobile phones could be run on Dreamcast?}

I like this idea. Unlike Java SE, which is fairly huge, implementing the Java ME
class libraries feels closer to what could be a one-person initiative.

It could also be fun to implement the "Mobile 3D Graphics" Java ME profiles for
Dreamcast.

\section{What about .NET/CLR for Dreamcast/Saturn?}

The Dreamcast JVM project would not have been possible without the excellent and
freely-available specification:

\href{https://docs.oracle.com/javase/specs/jvms/se23/html/index.html}{https://docs.oracle.com/javase/specs/jvms/se23/html/index.html}

I am aware that a CLR/CLI/CIL specification exists as well:

\href{https://ecma-international.org/wp-content/uploads/ECMA-335_6th_edition_june_2012.pdf}{https://ecma-international.org/wp-content/uploads/ECMA-335\_6th\_edition\_june\_2012.pdf}

The ECMA-335 specification looks fairly complete/implementable, and I estimate
such a project would be roughly on the same level of effort as this JVM project.

I don't know. Maybe?

\section{Other possible future directions}

I am interested in hearing anyone's opinions on any topic even vaguely related
to any of the above.

\end{document}
