diff --git a/doc/build.sh b/doc/build.sh index 59b2c05..6df575d 100644 --- a/doc/build.sh +++ b/doc/build.sh @@ -1,7 +1,11 @@ -make4ht entry.tex "pic-m,pic-equation,svg" +set -eux -mv entry.html index.html -mv entry.css index.css +make4ht $1 "pic-m,pic-equation,svg" + +css="$(basename ${1%.tex}.css)" + +mv "$(basename ${1%.tex}.html)" index.html +mv "${css}" index.css echo 'img[alt="PIC"] { width: 100%; }' >> index.css echo '.cmtt-10 { font-size: 0.9em; }' >> index.css @@ -9,7 +13,8 @@ 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 + +sed -i 's| | |g' index.html +sed -i "s/${css}/index.css/g" index.html diff --git a/doc/howto/howto.tex b/doc/howto/howto.tex new file mode 100644 index 0000000..6fcc556 --- /dev/null +++ b/doc/howto/howto.tex @@ -0,0 +1,206 @@ +\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} diff --git a/doc/howto/howto0x.svg b/doc/howto/howto0x.svg new file mode 100644 index 0000000..b6b917e --- /dev/null +++ b/doc/howto/howto0x.svg @@ -0,0 +1,149 @@ + + + \ No newline at end of file diff --git a/doc/howto/index.css b/doc/howto/index.css new file mode 100644 index 0000000..f74efe5 --- /dev/null +++ b/doc/howto/index.css @@ -0,0 +1,146 @@ + +/* start css.sty */ +.cmr-17{font-size:170%;} +.cmtt-10{font-family: monospace,monospace;} +.cmbx-10{ font-weight: bold;} +.tctt-1000{font-family: monospace,monospace;} +p{margin-top:0;margin-bottom:0} +p.indent{text-indent:0;} +p + p{margin-top:1em;} +p + div, p + pre {margin-top:1em;} +div + p, pre + p {margin-top:1em;} +a { overflow-wrap: break-word; word-wrap: break-word; word-break: break-word; hyphens: auto; } +@media print {div.crosslinks {visibility:hidden;}} +table.tabular{border-collapse: collapse; border-spacing: 0;} +a img { border-top: 0; border-left: 0; border-right: 0; } +center { margin-top:1em; margin-bottom:1em; } +td center { margin-top:0em; margin-bottom:0em; } +.Canvas { position:relative; } +img.math{vertical-align:middle;} +div.par-math-display, div.math-display{text-align:center;} +body{ margin:1em auto; max-width:80ch; padding:0 .62em; } +h1,h2,h3,h4,h5 { line-height:1.2; } +@media print{ body{ max-width:none } } +.partHead, .likepartHead { font-size: 2em; } +.chapterHead, .likechapterHead { font-size: 1.7411em; } +.sectionHead, .likesectionHead { font-size: 1.3157em; } +.subsectionHead, .likesubsectionHead { font-size: 1.0195em; } +.subsubsectionHead, .likesubsubsectionHead { font-size: 1.1487em; } +li p.indent { text-indent: 0em } +li p:first-child{ margin-top:0em; } +li p:last-child, li div:last-child { margin-bottom:0.5em; } +li p:first-child{ margin-bottom:0; } +li p~ul:last-child, li p~ol:last-child{ margin-bottom:0.5em; } +.enumerate1 {list-style-type:decimal;} +.enumerate2 {list-style-type:lower-alpha;} +.enumerate3 {list-style-type:lower-roman;} +.enumerate4 {list-style-type:upper-alpha;} +div.newtheorem { margin-bottom: 2em; margin-top: 2em;} +div.newtheorem .head{font-weight: bold;} +.obeylines-h,.obeylines-v {white-space: nowrap; } +div.obeylines-v p { margin-top:0; margin-bottom:0; } +.overline{ text-decoration:overline; } +.overline img{ border-top: 1px solid black; } +td.displaylines {text-align:center; white-space:nowrap;} +.centerline {text-align:center;} +.rightline {text-align:right;} +pre.verbatim {font-family: monospace,monospace; text-align:left; clear:both; } +.fbox {padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +div.fbox {display:table} +div.center div.fbox {text-align:center; clear:both; padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +div.minipage{width:100%;} +div.center, div.center div.center {text-align: center; margin-left:1em; margin-right:1em;} +div.center div {text-align: left;} +div.flushright, div.flushright div.flushright {text-align: right;} +div.flushright div {text-align: left;} +div.flushleft {text-align: left;} +.underline{ text-decoration:underline; } +.underline img{ border-bottom: 1px solid black; margin-bottom:1pt; } +.framebox-c, .framebox-l, .framebox-r { padding-left:3.0pt; padding-right:3.0pt; text-indent:0pt; border:solid black 0.4pt; } +.framebox-c {text-align:center;} +.framebox-l {text-align:left;} +.framebox-r {text-align:right;} +span.thank-mark{ vertical-align: super } +span.footnote-mark sup.textsuperscript, span.footnote-mark a sup.textsuperscript{ font-size:80%; } +code.verb{font-family:monospace,monospace;} +div.tabular, div.center div.tabular {text-align: center; margin-top:0.5em; margin-bottom:0.5em; } +table.tabular td p{margin-top:0em;} +table.tabular {margin-left: auto; margin-right: auto;} +td p:first-child{ margin-top:0em; } +td p:last-child{ margin-bottom:0em; } +div.td00{ margin-left:0pt; margin-right:0pt; } +div.td01{ margin-left:0pt; margin-right:5pt; } +div.td10{ margin-left:5pt; margin-right:0pt; } +div.td11{ margin-left:5pt; margin-right:5pt; } +table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; } +td.td00{ padding-left:0pt; padding-right:0pt; } +td.td01{ padding-left:0pt; padding-right:5pt; } +td.td10{ padding-left:5pt; padding-right:0pt; } +td.td11{ padding-left:5pt; padding-right:5pt; } +table[rules] {border-left:solid black 0.4pt; border-right:solid black 0.4pt; } +.hline hr, .cline hr{ height : 0px; margin:0px; } +.hline td, .cline td{ padding: 0; } +.hline hr, .cline hr{border:none;border-top:1px solid black;} +.hline {border-top: 1px solid black;} +.hline + .vspace:last-child{display:none;} +.hline:first-child{border-bottom:1px solid black;border-top:none;} +.tabbing-right {text-align:right;} +div.float, div.figure {margin-left: auto; margin-right: auto;} +div.float img {text-align:center;} +div.figure img {text-align:center;} +.marginpar,.reversemarginpar {width:20%; float:right; text-align:left; margin-left:auto; margin-top:0.5em; font-size:85%; text-decoration:underline;} +.marginpar p,.reversemarginpar p{margin-top:0.4em; margin-bottom:0.4em;} +.reversemarginpar{float:left;} +table.equation {width:100%;} +.equation td{text-align:center; } +td.equation { margin-top:1em; margin-bottom:1em; } +td.equation-label { width:5%; text-align:center; } +td.eqnarray4 { width:5%; white-space: normal; } +td.eqnarray2 { width:5%; } +table.eqnarray-star, table.eqnarray {width:100%;} +div.eqnarray{text-align:center;} +div.array {text-align:center;} +div.pmatrix {text-align:center;} +table.pmatrix {width:100%;} +span.pmatrix img{vertical-align:middle;} +div.pmatrix {text-align:center;} +table.pmatrix {width:100%;} +span.bar-css {text-decoration:overline;} +img.cdots{vertical-align:middle;} +.partToc a, .partToc, .likepartToc a, .likepartToc {line-height: 200%; font-weight:bold; font-size:110%;} +.index-item, .index-subitem, .index-subsubitem {display:block} +div.caption {text-indent:-2em; margin-left:3em; margin-right:1em; text-align:left;} +div.caption span.id{font-weight: bold; white-space: nowrap; } +h1.partHead{text-align: center} +p.bibitem { text-indent: -2em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } +p.bibitem-p { text-indent: 0em; margin-left: 2em; margin-top:0.6em; margin-bottom:0.6em; } +.subsubsectionHead, .likesubsubsectionHead { font-size: 1em; } +.paragraphHead, .likeparagraphHead { margin-top:2em; font-weight: bold;} +.subparagraphHead, .likesubparagraphHead { font-weight: bold;} +.verse{white-space:nowrap; margin-left:2em} +div.maketitle {text-align:center;} +h2.titleHead{text-align:center;} +div.maketitle{ margin-bottom: 2em; } +div.author, div.date {text-align:center;} +div.thanks{text-align:left; margin-left:10%; font-size:85%; font-style:italic; } +div.author{white-space: nowrap;} +div.abstract p {margin-left:5%; margin-right:5%;} +div.abstract {width:100%;} +.abstracttitle{text-align:center;margin-bottom:1em;} +.subsectionToc, .likesubsectionToc {margin-left:1em;} +.subsubsectionToc, .likesubsubsectionToc {margin-left:2em;} +.paragraphToc, .likeparagraphToc {margin-left:3em;} +.subparagraphToc, .likesubparagraphToc {margin-left:4em;} +figure.float, div.figure {margin-left: auto; margin-right: auto;} +figure.figure {text-align:center;} +figcaption.caption {text-indent:-2em; margin-left:3em; margin-right:1em; text-align:center;} +figcaption.caption span.id{font-weight: bold; white-space: nowrap; } +p + figcaption, img + figcaption{margin-top: 1em;} +.abstract{margin:1em;} +.rotatebox{display: inline-block;} +/* end css.sty */ + +img[alt="PIC"] { width: 100%; } +.cmtt-10 { font-size: 0.9em; } +img[src="index3x.svg"] { height: 2.5em; } +object[class="graphics"] { width: 100% } diff --git a/doc/howto/index.html b/doc/howto/index.html new file mode 100644 index 0000000..d28ef79 --- /dev/null +++ b/doc/howto/index.html @@ -0,0 +1,253 @@ + + +
The jvm project’s Dreamcast build system depends on the dreamcast project. This +dependency is limited mostly to sharing Make rules. Clone both of these as siblings of +the same parent directory, as in: + + + +
++git clone https://github.com/buhman/dreamcast + +git clone https://github.com/buhman/jvm ++
+
If you would like to use a .cdi image, the build process also depends on cdi4dc. +It is assumed that this tool exists in the same directory that contains the dreamcast +and jvm directories. On Linux, do: + + + +
++curl -LO https://files.dcemulation.org/software/pctools/cdi4dc/cdi4dc_02b_linux.zip + +unzip cdi4dc_02b_linux.zip + +chmod +x cdi4dc ++
+
To build everything, do the following: + + + +
++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 ++
+
You should change the value of TARGET=sh-elf- to whatever matches your GCC +SH installation. If for example your GCC is named sh4-none-elf-gcc then the +correct TARGET value would be TARGET=sh4-none-elf- (including the trailing +hyphen). +
You can then run the generated jvm.cdi on Dreamcast hardware or +emulators. +
+
++
+The generate_classpath.sh script is terrible. It is a “quick hack” to work around +multiple unsolved problems. +
If you wish to modify the build process to include newly-written classes, you +should append them to the application_classes array in generate_classpath.sh. +
+
+I recommend the following Flycast settings: +
+ + + ++
+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. + + + +
++make clean + +make main ++
+
You should run 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: + + + +
++make classes/test/TestIntegerBitCount.class ++
+
Run the Dreamcast JVM like this: + + + +
++cd classes + +# ../main [entry_class_name] [class_file...] + +../main test/TestIntegerBitCount test/*.class java/lang/*.class java/io/*.class ++
+
Note that for no specific reason, the Dreamcast JVM main method declaration +is + + + +
++public static void main() ++
rather than the standard + + + +
++public static void main(String[] args) ++
I may change this in the future (it is not hard to support either, or even +both). +
+
+DEBUG_PRINT is 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 Makefile or Makefile.dreamcast.mk by +commenting/uncommenting the line + + + +
++CFLAGS += -DDEBUG_PRINT ++
+
When changing CFLAGS, remove all previously-built object files with the +command: + + + +
++make clean ++
+
+
+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: +
+
+The Dreamcast JVM includes its own versions the classes from java.lang. The +OpenJDK javac, however, will attempt to link against OpenJDK’s own version of +java.lang. +
In many cases, this will coincidentally not cause issues. However, it is better to +explicitly reference the Dreamcast JVM’s version of java.lang to be able to catch +any linking errors as early as possible (javac’s error messages are also much better +than those you’d get from jvm.bin). +
However, javac doesn’t appear to support this in a convenient way. The best +invocation I’ve found so far is: + + + +
++cd jvm/classes + +javac -Xlint:-options --source 8 --target 8 --boot-class-path . path/to/YourClass.java ++
+
This does limit you to Java 8 language features, but this appears to be the only +way to enable the --boot-class-path option, for which there is no clear +replacement in newer versions. +
+
+I have not managed to make my Make rules tolerant of $ characters in filenames. +This is the main reason why generate_classpath.sh exists, and it’s also the reason +why it’s terrible. +
+
+It would be nice to have a build process/tool that works like this: +
+I will create this tool at some point. +
+ + + \ No newline at end of file diff --git a/doc/boot.dot b/doc/index/boot.dot similarity index 100% rename from doc/boot.dot rename to doc/index/boot.dot diff --git a/doc/boot.svg b/doc/index/boot.svg similarity index 100% rename from doc/boot.svg rename to doc/index/boot.svg diff --git a/doc/entry.tex b/doc/index/index.tex similarity index 100% rename from doc/entry.tex rename to doc/index/index.tex