doc: add documentation
This commit is contained in:
parent
d101710e0f
commit
d515c544f5
1
.gitignore
vendored
1
.gitignore
vendored
@ -24,6 +24,7 @@ classes.txt
|
||||
doc/*.pdf
|
||||
doc/*.css
|
||||
doc/*.html
|
||||
doc/entry*.svg
|
||||
*.idv
|
||||
*.aux
|
||||
*.4tc
|
||||
|
64
doc/boot.dot
Normal file
64
doc/boot.dot
Normal file
@ -0,0 +1,64 @@
|
||||
digraph jvm_boot {
|
||||
|
||||
newrank=true;
|
||||
|
||||
|
||||
boot_rom [shape=box label="Dreamcast Boot ROM"]
|
||||
first_read [shape=box label="1ST_READ.BIN"]
|
||||
discarded [shape=ellipse label="(discarded/overwritten)"]
|
||||
ip_bin [shape=box label="gdrom_jvm_boot.bin (“ip.bin”)"]
|
||||
|
||||
boot_rom -> first_read -> discarded
|
||||
boot_rom -> ip_bin
|
||||
|
||||
subgraph cluster_jvm_bin {
|
||||
label=" boot class files (embedded inside jvm.bin)"
|
||||
|
||||
jvm_bin [shape=box label="jvm.bin"]
|
||||
|
||||
boot_class_files [shape=plaintext label=<
|
||||
<table align="center" border="0" cellborder="1" cellpadding="3" cellspacing="3">
|
||||
<tr><td align="left"> example/GdromClassLoader.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/gdrom/GdromExtentReader.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/gdrom/GdromProtocol.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/gdrom/GdromCommandPacketFormat.class </td></tr>
|
||||
<tr><td align="left"> filesystem/iso9660/VolumeParser.class</td></tr>
|
||||
<tr><td align="left"> jvm/internal/Loader.class</td></tr>
|
||||
</table>
|
||||
>]
|
||||
}
|
||||
|
||||
subgraph cluster_application {
|
||||
label=" application class files (files on the iso9660 filesystem)"
|
||||
|
||||
main [shape=box label="Main.class"]
|
||||
|
||||
class_files [shape=plaintext label=<
|
||||
<table align="left" border="0" cellborder="1" cellpadding="3" cellspacing="3">
|
||||
<tr><td align="left"> example/JavaCube.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/Core.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/VideoOutput.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/RegionArray.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/TAFIFOPolygonConverter.class </td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/TAGlobalParameter.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/TAVertexParameter.class</td></tr>
|
||||
<tr><td align="left"> sega/dreamcast/holly/TextureMemoryAllocation.class </td></tr>
|
||||
<tr><td align="left"> model/CubeModel.class</td></tr>
|
||||
</table>
|
||||
>]
|
||||
}
|
||||
|
||||
{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
|
||||
|
||||
}
|
151
doc/boot.svg
Normal file
151
doc/boot.svg
Normal file
@ -0,0 +1,151 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
|
||||
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Generated by graphviz version 12.1.1 (20240910.0053)
|
||||
-->
|
||||
<!-- Title: jvm_boot Pages: 1 -->
|
||||
<svg width="724pt" height="725pt"
|
||||
viewBox="0.00 0.00 723.66 724.60" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 720.6)">
|
||||
<title>jvm_boot</title>
|
||||
<polygon fill="white" stroke="none" points="-4,4 -4,-720.6 719.66,-720.6 719.66,4 -4,4"/>
|
||||
<g id="clust1" class="cluster">
|
||||
<title>cluster_jvm_bin</title>
|
||||
<polygon fill="none" stroke="black" points="237.66,-382 237.66,-600.6 707.66,-600.6 707.66,-382 237.66,-382"/>
|
||||
<text text-anchor="middle" x="472.66" y="-584" font-family="Times,serif" font-size="14.00">                    boot class files (embedded inside jvm.bin)</text>
|
||||
</g>
|
||||
<g id="clust2" class="cluster">
|
||||
<title>cluster_application</title>
|
||||
<polygon fill="none" stroke="black" points="229.66,-8 229.66,-310 687.66,-310 687.66,-8 229.66,-8"/>
|
||||
<text text-anchor="middle" x="458.66" y="-293.4" font-family="Times,serif" font-size="14.00">                             application class files (files on the iso9660 filesystem)</text>
|
||||
</g>
|
||||
<!-- boot_rom -->
|
||||
<g id="node1" class="node">
|
||||
<title>boot_rom</title>
|
||||
<polygon fill="none" stroke="black" points="259.65,-716.6 117.67,-716.6 117.67,-680.6 259.65,-680.6 259.65,-716.6"/>
|
||||
<text text-anchor="middle" x="188.66" y="-694.4" font-family="Times,serif" font-size="14.00">Dreamcast Boot ROM</text>
|
||||
</g>
|
||||
<!-- first_read -->
|
||||
<g id="node2" class="node">
|
||||
<title>first_read</title>
|
||||
<polygon fill="none" stroke="black" points="157.69,-644.6 45.64,-644.6 45.64,-608.6 157.69,-608.6 157.69,-644.6"/>
|
||||
<text text-anchor="middle" x="101.66" y="-622.4" font-family="Times,serif" font-size="14.00">1ST_READ.BIN</text>
|
||||
</g>
|
||||
<!-- boot_rom->first_read -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>boot_rom->first_read</title>
|
||||
<path fill="none" stroke="black" d="M167.16,-680.3C156.6,-671.8 143.69,-661.41 132.13,-652.11"/>
|
||||
<polygon fill="black" stroke="black" points="134.39,-649.44 124.4,-645.9 130,-654.89 134.39,-649.44"/>
|
||||
</g>
|
||||
<!-- ip_bin -->
|
||||
<g id="node4" class="node">
|
||||
<title>ip_bin</title>
|
||||
<polygon fill="none" stroke="black" points="376.02,-644.6 175.31,-644.6 175.31,-608.6 376.02,-608.6 376.02,-644.6"/>
|
||||
<text text-anchor="middle" x="275.66" y="-622.4" font-family="Times,serif" font-size="14.00">gdrom_jvm_boot.bin (“ip.bin”)</text>
|
||||
</g>
|
||||
<!-- boot_rom->ip_bin -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>boot_rom->ip_bin</title>
|
||||
<path fill="none" stroke="black" d="M210.17,-680.3C220.73,-671.8 233.64,-661.41 245.2,-652.11"/>
|
||||
<polygon fill="black" stroke="black" points="247.33,-654.89 252.93,-645.9 242.94,-649.44 247.33,-654.89"/>
|
||||
</g>
|
||||
<!-- discarded -->
|
||||
<g id="node3" class="node">
|
||||
<title>discarded</title>
|
||||
<ellipse fill="none" stroke="black" cx="101.66" cy="-478.9" rx="101.66" ry="18"/>
|
||||
<text text-anchor="middle" x="101.66" y="-474.7" font-family="Times,serif" font-size="14.00">(discarded/overwritten)</text>
|
||||
</g>
|
||||
<!-- first_read->discarded -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>first_read->discarded</title>
|
||||
<path fill="none" stroke="black" d="M101.66,-608.31C101.66,-583.67 101.66,-538.13 101.66,-508.44"/>
|
||||
<polygon fill="black" stroke="black" points="105.16,-508.68 101.66,-498.68 98.16,-508.68 105.16,-508.68"/>
|
||||
</g>
|
||||
<!-- jvm_bin -->
|
||||
<g id="node5" class="node">
|
||||
<title>jvm_bin</title>
|
||||
<polygon fill="none" stroke="black" points="305.25,-496.9 246.08,-496.9 246.08,-460.9 305.25,-460.9 305.25,-496.9"/>
|
||||
<text text-anchor="middle" x="275.66" y="-474.7" font-family="Times,serif" font-size="14.00">jvm.bin</text>
|
||||
</g>
|
||||
<!-- ip_bin->jvm_bin -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>ip_bin->jvm_bin</title>
|
||||
<path fill="none" stroke="black" d="M275.66,-608.31C275.66,-583.67 275.66,-538.13 275.66,-508.44"/>
|
||||
<polygon fill="black" stroke="black" points="279.16,-508.68 275.66,-498.68 272.16,-508.68 279.16,-508.68"/>
|
||||
</g>
|
||||
<!-- boot_class_files -->
|
||||
<g id="node6" class="node">
|
||||
<title>boot_class_files</title>
|
||||
<polygon fill="none" stroke="black" points="334.26,-536 334.26,-560.8 689.07,-560.8 689.07,-536 334.26,-536"/>
|
||||
<text text-anchor="start" x="338.26" y="-544.2" font-family="Times,serif" font-size="14.00">  example/GdromClassLoader.class</text>
|
||||
<polygon fill="none" stroke="black" points="334.26,-508.2 334.26,-533 689.07,-533 689.07,-508.2 334.26,-508.2"/>
|
||||
<text text-anchor="start" x="338.26" y="-516.4" font-family="Times,serif" font-size="14.00">  sega/dreamcast/gdrom/GdromExtentReader.class</text>
|
||||
<polygon fill="none" stroke="black" points="334.26,-480.4 334.26,-505.2 689.07,-505.2 689.07,-480.4 334.26,-480.4"/>
|
||||
<text text-anchor="start" x="338.26" y="-488.6" font-family="Times,serif" font-size="14.00">  sega/dreamcast/gdrom/GdromProtocol.class</text>
|
||||
<polygon fill="none" stroke="black" points="334.26,-452.6 334.26,-477.4 689.07,-477.4 689.07,-452.6 334.26,-452.6"/>
|
||||
<text text-anchor="start" x="338.26" y="-460.8" font-family="Times,serif" font-size="14.00">  sega/dreamcast/gdrom/GdromCommandPacketFormat.class </text>
|
||||
<polygon fill="none" stroke="black" points="334.26,-424.8 334.26,-449.6 689.07,-449.6 689.07,-424.8 334.26,-424.8"/>
|
||||
<text text-anchor="start" x="338.26" y="-433" font-family="Times,serif" font-size="14.00">  filesystem/iso9660/VolumeParser.class</text>
|
||||
<polygon fill="none" stroke="black" points="334.26,-397 334.26,-421.8 689.07,-421.8 689.07,-397 334.26,-397"/>
|
||||
<text text-anchor="start" x="338.26" y="-405.2" font-family="Times,serif" font-size="14.00">  jvm/internal/Loader.class</text>
|
||||
</g>
|
||||
<!-- jvm_bin->boot_class_files -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>jvm_bin->boot_class_files</title>
|
||||
<path fill="none" stroke="black" d="M305.63,-478.9C307.75,-478.9 309.87,-478.9 311.99,-478.9"/>
|
||||
<polygon fill="black" stroke="black" points="311.82,-482.4 321.82,-478.9 311.82,-475.4 311.82,-482.4"/>
|
||||
</g>
|
||||
<!-- GdromClassLoader -->
|
||||
<g id="node9" class="node">
|
||||
<title>GdromClassLoader</title>
|
||||
<polygon fill="none" stroke="black" points="353.84,-354 197.49,-354 197.49,-318 353.84,-318 353.84,-354"/>
|
||||
<text text-anchor="middle" x="275.66" y="-331.8" font-family="Times,serif" font-size="14.00">GdromClassLoader.class</text>
|
||||
</g>
|
||||
<!-- jvm_bin->GdromClassLoader -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>jvm_bin->GdromClassLoader</title>
|
||||
<path fill="none" stroke="black" d="M275.66,-460.62C275.66,-436.96 275.66,-394.17 275.66,-365.66"/>
|
||||
<polygon fill="black" stroke="black" points="279.16,-365.93 275.66,-355.93 272.16,-365.93 279.16,-365.93"/>
|
||||
</g>
|
||||
<!-- main -->
|
||||
<g id="node7" class="node">
|
||||
<title>main</title>
|
||||
<polygon fill="none" stroke="black" points="313.8,-164.6 237.53,-164.6 237.53,-128.6 313.8,-128.6 313.8,-164.6"/>
|
||||
<text text-anchor="middle" x="275.66" y="-142.4" font-family="Times,serif" font-size="14.00">Main.class</text>
|
||||
</g>
|
||||
<!-- class_files -->
|
||||
<g id="node8" class="node">
|
||||
<title>class_files</title>
|
||||
<polygon fill="none" stroke="black" points="342.85,-245.4 342.85,-270.2 668.48,-270.2 668.48,-245.4 342.85,-245.4"/>
|
||||
<text text-anchor="start" x="346.85" y="-253.6" font-family="Times,serif" font-size="14.00">  example/JavaCube.class</text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-217.6 342.85,-242.4 668.48,-242.4 668.48,-217.6 342.85,-217.6"/>
|
||||
<text text-anchor="start" x="346.85" y="-225.8" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/Core.class</text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-189.8 342.85,-214.6 668.48,-214.6 668.48,-189.8 342.85,-189.8"/>
|
||||
<text text-anchor="start" x="346.85" y="-198" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/VideoOutput.class</text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-162 342.85,-186.8 668.48,-186.8 668.48,-162 342.85,-162"/>
|
||||
<text text-anchor="start" x="346.85" y="-170.2" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/RegionArray.class</text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-134.2 342.85,-159 668.48,-159 668.48,-134.2 342.85,-134.2"/>
|
||||
<text text-anchor="start" x="346.85" y="-142.4" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/TAFIFOPolygonConverter.class </text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-106.4 342.85,-131.2 668.48,-131.2 668.48,-106.4 342.85,-106.4"/>
|
||||
<text text-anchor="start" x="346.85" y="-114.6" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/TAGlobalParameter.class</text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-78.6 342.85,-103.4 668.48,-103.4 668.48,-78.6 342.85,-78.6"/>
|
||||
<text text-anchor="start" x="346.85" y="-86.8" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/TAVertexParameter.class</text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-50.8 342.85,-75.6 668.48,-75.6 668.48,-50.8 342.85,-50.8"/>
|
||||
<text text-anchor="start" x="346.85" y="-59" font-family="Times,serif" font-size="14.00">  sega/dreamcast/holly/TextureMemoryAllocation.class  </text>
|
||||
<polygon fill="none" stroke="black" points="342.85,-23 342.85,-47.8 668.48,-47.8 668.48,-23 342.85,-23"/>
|
||||
<text text-anchor="start" x="346.85" y="-31.2" font-family="Times,serif" font-size="14.00">  model/CubeModel.class</text>
|
||||
</g>
|
||||
<!-- main->class_files -->
|
||||
<g id="edge8" class="edge">
|
||||
<title>main->class_files</title>
|
||||
<path fill="none" stroke="black" d="M314.3,-146.6C316.4,-146.6 318.51,-146.6 320.61,-146.6"/>
|
||||
<polygon fill="black" stroke="black" points="320.35,-150.1 330.35,-146.6 320.35,-143.1 320.35,-150.1"/>
|
||||
</g>
|
||||
<!-- GdromClassLoader->main -->
|
||||
<g id="edge7" class="edge">
|
||||
<title>GdromClassLoader->main</title>
|
||||
<path fill="none" stroke="black" d="M275.66,-317.71C275.66,-285.42 275.66,-215.7 275.66,-176.27"/>
|
||||
<polygon fill="black" stroke="black" points="279.16,-176.37 275.66,-166.37 272.16,-176.37 279.16,-176.37"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 10 KiB |
15
doc/build.sh
Normal file
15
doc/build.sh
Normal file
@ -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| </span>|</span> |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
|
1
doc/deploy.sh
Normal file
1
doc/deploy.sh
Normal file
@ -0,0 +1 @@
|
||||
rsync -arv * root@az1.idk.st:/var/www/dreamcast/jvm/
|
222
doc/entry.tex
Normal file
222
doc/entry.tex
Normal file
@ -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}
|
Loading…
x
Reference in New Issue
Block a user