+ >]
+ }
+
+ {rank=same; jvm_bin; boot_class_files}
+
+ {rank=same; main; class_files}
+
+ ip_bin -> jvm_bin
+ jvm_bin -> boot_class_files
+
+ GdromClassLoader [shape=box label="GdromClassLoader.class"]
+
+ jvm_bin -> GdromClassLoader -> main
+
+ main -> class_files
+
+}
\ No newline at end of file
diff --git a/doc/boot.svg b/doc/boot.svg
new file mode 100644
index 0000000..f3492a9
--- /dev/null
+++ b/doc/boot.svg
@@ -0,0 +1,151 @@
+
+
+
+
+
diff --git a/doc/build.sh b/doc/build.sh
new file mode 100644
index 0000000..59b2c05
--- /dev/null
+++ b/doc/build.sh
@@ -0,0 +1,15 @@
+make4ht entry.tex "pic-m,pic-equation,svg"
+
+mv entry.html index.html
+mv entry.css index.css
+
+echo 'img[alt="PIC"] { width: 100%; }' >> index.css
+echo '.cmtt-10 { font-size: 0.9em; }' >> index.css
+echo 'img[src="index3x.svg"] { height: 2.5em; }' >> index.css
+echo 'object[class="graphics"] { width: 100% }' >> index.css
+
+sed -i '/prefers-color-scheme/d' index.css
+sed -i 's| | |g' index.html
+sed -i 's/entry.css/index.css/g' index.html
+sed -i 's/1.5157em/1.3157em/g' index.css
+sed -i 's/1.3195em/1.0195em/g' index.css
diff --git a/doc/deploy.sh b/doc/deploy.sh
new file mode 100644
index 0000000..2ba9647
--- /dev/null
+++ b/doc/deploy.sh
@@ -0,0 +1 @@
+rsync -arv * root@az1.idk.st:/var/www/dreamcast/jvm/
diff --git a/doc/entry.tex b/doc/entry.tex
new file mode 100644
index 0000000..666ed63
--- /dev/null
+++ b/doc/entry.tex
@@ -0,0 +1,222 @@
+\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}