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.