\documentclass[20pt]{article}

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

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

\title{Building and running the Dreamcast JVM}
\date{}

\setcounter{secnumdepth}{0}

\begin{document}

\maketitle

\tableofcontents
\section{Introduction}

The \texttt{jvm} project's Dreamcast build system depends on the
\texttt{dreamcast} project. This dependency is limited mostly to sharing Make
rules. Clone both of these as siblings of the same parent directory, as in:

\begin{verbatim}
git clone https://github.com/buhman/dreamcast

git clone https://github.com/buhman/jvm
\end{verbatim}

If you would like to use a \texttt{.cdi} image, the build process also depends
on \texttt{cdi4dc}. It is assumed that this tool exists in the same directory
that contains the \texttt{dreamcast} and \texttt{jvm} directories. On Linux, do:

\begin{verbatim}
curl -LO https://files.dcemulation.org/software/pctools/cdi4dc/cdi4dc_02b_linux.zip

unzip cdi4dc_02b_linux.zip

chmod +x cdi4dc
\end{verbatim}

To build everything, do the following:

\begin{verbatim}
cd jvm

sh generate_classpath.sh

rm -f main.bin main.elf jvm.iso

make -f Makefile.dreamcast.mk TARGET=sh-elf- jvm.iso

../cdi4dc jvm.iso jvm.cdi
\end{verbatim}

You should change the value of \texttt{TARGET=sh-elf-} to whatever matches your
GCC SH installation. If for example your GCC is named \texttt{sh4-none-elf-gcc}
then the correct \texttt{TARGET} value would be \texttt{TARGET=sh4-none-elf-}
(including the trailing hyphen).

You can then run the generated \texttt{jvm.cdi} on Dreamcast hardware or
emulators.

\section{Additional notes}

\subsection{Generate classpath}

The \texttt{generate\_classpath.sh} script is terrible. It is a ``quick hack''
to work around \hyperref[sec:unsolved]{multiple unsolved problems}.

If you wish to modify the build process to include newly-written classes, you
should append them to the \texttt{application\_classes} array in
\texttt{generate\_classpath.sh}.

\subsection{Flycast settings}

I recommend the following Flycast settings:

\begin{itemize}
\item Video → Transparent Sorting → Per Pixel (selected)
\item Video → Rendering Options → Full Framebuffer Emulation (checked)
\item Video → Advanced → Copy Rendered Textures to VRAM (checked)
\item Advanced → Other → Serial Console (checked)
\end{itemize}

\subsection{Run the Dreamcast JVM on Linux/Windows/macOS}

The Dreamcast JVM can also run as a application on a PC operating system. This
can be useful for testing general Java features independently of running on a
Dreamcast.

\begin{verbatim}
make clean

make main
\end{verbatim}

You should run \texttt{make clean} any time you wish to swap between the PC and
Dreamcast versions of the JVM.

Compile one of the tests as an example:

\begin{verbatim}
make classes/test/TestIntegerBitCount.class
\end{verbatim}

Run the Dreamcast JVM like this:

\begin{verbatim}
cd classes

# ../main [entry_class_name] [class_file...]

../main test/TestIntegerBitCount test/*.class java/lang/*.class java/io/*.class
\end{verbatim}

Note that for no specific reason, the Dreamcast JVM main method declaration is
\begin{verbatim}
public static void main()
\end{verbatim}
rather than the standard
\begin{verbatim}
public static void main(String[] args)
\end{verbatim}
I may change this in the future (it is not hard to support either, or even
both).

\subsection{JVM debug print}

\texttt{DEBUG\_PRINT} is \textbf{very slow} and unintelligibly verbose for
non-trivial programs. It is mostly useful for doing low-level debugging of the
JVM itself for very simple programs.

This can be disabled/enabled in either \texttt{Makefile} or
\texttt{Makefile.dreamcast.mk} by commenting/uncommenting the line
\begin{verbatim}
CFLAGS += -DDEBUG_PRINT
\end{verbatim}

When changing \texttt{CFLAGS}, remove all previously-built object files with the
command:

\begin{verbatim}
make clean
\end{verbatim}

\section{Unsolved problems}
\label{sec:unsolved}

There are a few issues that currently cause the build process to be uglier than
I'd like it to be. I welcome any suggestions regarding any of these topics:

\subsection{Boot class path}

The Dreamcast JVM includes its own versions the classes from
\texttt{java.lang}. The OpenJDK \texttt{javac}, however, will attempt to link
against OpenJDK's own version of \texttt{java.lang}.

In many cases, this will coincidentally not cause issues. However, it is better
to explicitly reference the Dreamcast JVM's version of \texttt{java.lang} to be
able to catch any linking errors as early as possible (\texttt{javac}'s error
messages are also much better than those you'd get from \texttt{jvm.bin}).

However, \texttt{javac} doesn't appear to support this in a convenient way. The
best invocation I've found so far is:

\begin{verbatim}
cd jvm/classes

javac -Xlint:-options --source 8 --target 8 --boot-class-path . path/to/YourClass.java
\end{verbatim}

This does limit you to Java 8 language features, but this appears to be the only
way to enable the \texttt{--boot-class-path} option, for which there is no clear
replacement in newer versions.

\subsection{Nested class filenames contain the dollar-sign character}

I have not managed to make my Make rules tolerant of \texttt{\$} characters in
filenames. This is the main reason why \texttt{generate\_classpath.sh} exists,
and it's also the reason why it's terrible.

\subsection{Unused class/method removal}

It would be nice to have a build process/tool that works like this:

\begin{itemize}
\item give the name of the ``main''/entrypoint class as a command-line argument
\item automatically/recursively calculate the minimum set of
  classes/methods/fields that ``main'' depends on
\item from the full library of available classes, emit a reduced/minimal set of
  (compiled) class files that only contain the methods and fields that are
  reachable via ``main''.
\end{itemize}

I will create this tool at some point.

\end{document}
