{"id":1850,"date":"2013-03-06T16:58:55","date_gmt":"2013-03-06T14:58:55","guid":{"rendered":"http:\/\/www.tutego.de\/blog\/javainsel\/?p=1850"},"modified":"2014-12-20T14:36:26","modified_gmt":"2014-12-20T12:36:26","slug":"mit-java-fr-c64-entwickeln","status":"publish","type":"post","link":"https:\/\/www.tutego.de\/blog\/javainsel\/2013\/03\/mit-java-fr-c64-entwickeln\/","title":{"rendered":"Mit Java f&uuml;r C64 entwickeln"},"content":{"rendered":"<p>Knackige \u00dcberschrift, was steckt dahinter? Wir warten auf den Architekten f\u00fcr unser Restaurant hier in den Philippinen und so hatte ich etwas Leerlauf, um was total Unn\u00f6tiges zu programmieren.<\/p>\n<p>Um Java-Programme, beziehungsweise eine Teilmenge der Sprache\/Bibliothek, auf dem C64 (oder anderen 8-Bit-Computern) zum Laufen zu bringen, sind mehrere Ans\u00e4tze denkbar:<\/p>\n<ul>\n<li>Eine <strong>JVM <\/strong>auf dem Heimcomputer, die Bytecode interpretiert. Das w\u00fcrde im Prinzip gehen, es gibt auch Mini-Laufzeitumgebungen f\u00fcr so etwas. Auch Java Smart Card ist ein Stichwort.<\/li>\n<li><strong>Compiler<\/strong>, die entweder Bytecode oder Source-Code in ein Quellformat umsetzen, was der 65xx versteht.<\/li>\n<\/ul>\n<p>Ein JVM ist richtig viel Arbeit, und war in 2 Tagen nicht zu schaffen. Und mit <a title=\"http:\/\/sourceforge.net\/projects\/vm02\/\" href=\"http:\/\/sourceforge.net\/projects\/vm02\/\">http:\/\/sourceforge.net\/projects\/vm02\/<\/a> gibt es so etwas auch schon f\u00fcr Apple II Computer. Ein <a href=\"http:\/\/de.wikipedia.org\/wiki\/Cross-Compiler\">(Cross-)Compiler<\/a> ist deutlicher einfacher. Bytecode in 65xx-Assembler zu \u00fcbersetzen ist relativ einfach, doch dann m\u00fcsste ich wieder Assembler anfassen und damit das ganze schnell wird, m\u00fcsste ich auch einen Code-Optimierer schreiben, denn einfach die Stack-Maschine umzusetzen, f\u00fchrt auch zu keinen Performance-Wundern. Da es f\u00fcr den C64 auch Compiler gibt, etwa f\u00fcr PASCAL (auf der Maschine) oder C (als Cross-Compiler etwa mit CC65), kann man aus Bytecode auch dieses Format generieren. Aber dann h\u00e4tte ich wieder mit Java-Bytecode arbeiten m\u00fcssen, was mir auch keine Freunde macht. Am Schnellsten verspricht Resultate eine Code-Transformation von Java nach C. Das Resultat kann dann der <a title=\"http:\/\/www.cc65.org\/\" href=\"http:\/\/www.cc65.org\/\">http:\/\/www.cc65.org\/<\/a> in Maschinencode umsetzen, und dann bekommt man auch ein paar Optimierung geschenkt.<\/p>\n<p>Das JDK bringt alles mit, um an den AST des Compilers zu kommen, wie schon im Blog hier beschrieben: <a title=\"http:\/\/www.tutego.de\/blog\/javainsel\/2012\/07\/mit-der-internen-compiler-api-auf-den-ast-einer-klasse-zugreifen\/\" href=\"http:\/\/www.tutego.de\/blog\/javainsel\/2012\/07\/mit-der-internen-compiler-api-auf-den-ast-einer-klasse-zugreifen\/\">http:\/\/www.tutego.de\/blog\/javainsel\/2012\/07\/mit-der-internen-compiler-api-auf-den-ast-einer-klasse-zugreifen\/<\/a>. Von den erkannten Elementen (Ausdr\u00fccke, Variablenzugriff, Schleife, \u2026) muss man nur C-Code schreiben und fertig ist. Um mir die Sache einfach zu machen vereinfache ich Java jedoch massiv:<\/p>\n<ul>\n<li>kein float\/double\/long\/boolean<\/li>\n<li>kein new, keine Klassen, Stellen und sonstiges objektorientiertes \u201cZeugs\u201d, das dranh\u00e4ngt, wie enum, erweitertes for, nur statische Methoden, keine Ausnahmen, Keine String-Konkatenation<\/li>\n<li>String-Literale k\u00f6nnen verwendet werden, allerdings nur von 0x0000 \u2013 0x00FF (256) und eigentlich geht PETSCII nur von 0-191<\/li>\n<li>Nichts von der Java-Bibliothek<\/li>\n<\/ul>\n<p>Des weiteren muss sehr \u201cC\u201d-\u00e4hnlich programmiert werden:<\/p>\n<ul>\n<li>Alle lokale Variablen m\u00fcssen am Anfang einer Methode deklariert sein<\/li>\n<li>Alle Bezeichner m\u00fcssen f\u00fcr den C-Compiler g\u00fcltig sein, keine Unicodes<\/li>\n<li>Die Reihenfolge muss stimmen, der Umsetzer erzeugt keine Prototypen<\/li>\n<li>Eine main()-Methode muss etwas zur\u00fcckgeben in C99, Java macht das nicht, daher nutzt man System.exit(0).<\/li>\n<\/ul>\n<p>Das auf diese Weise kastrierte Java ist zwar im Prinzip f\u00fcr nix mehr zu gebrauchen, aber f\u00fcr Heimcomputer immer noch akzeptabel und eine nette Spielerei.<\/p>\n<p>Wer bis dahin noch nicht das Interesse verloren hat, kann ein wenig mit dem Compiler spielen; die Source liegen unter <a href=\"https:\/\/code.google.com\/p\/java2c-transcompiler\/\">https:\/\/code.google.com\/p\/java2c-transcompiler\/<\/a>.<\/p>\n<p>Jetzt brauchen wir Input:<\/p>\n<pre class=\"csharpcode\">import <span class=\"kwrd\">static<\/span> j2c.lib.Stdio.printf;\r\n\r\n<span class=\"rem\">\/\/ Source: http:\/\/skoe.de\/wiki\/doku.php?id=ckurs:04-abend4<\/span>\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> Application\r\n{\r\n  <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">char<\/span> istPrimzahl( <span class=\"kwrd\">int<\/span> n )\r\n  {\r\n    <span class=\"kwrd\">int<\/span> divisor;\r\n    <span class=\"kwrd\">int<\/span> testEnde = n \/ 2;\r\n\r\n    <span class=\"rem\">\/* Alle potentiellen Teiler bis zur Mitte testen *\/<\/span>\r\n    <span class=\"kwrd\">for<\/span> ( divisor = 3; divisor &lt; testEnde; divisor += 2 ) {\r\n      <span class=\"rem\">\/* Mit Rest 0 teilbar? *\/<\/span>\r\n      <span class=\"kwrd\">if<\/span> ( n % divisor == 0 ) {\r\n        <span class=\"rem\">\/* Ueberpr\u00fcfung abbrechen, keine Primzahl *\/<\/span>\r\n        <span class=\"kwrd\">return<\/span> 0;\r\n      }\r\n    }\r\n\r\n    <span class=\"rem\">\/* Kein Test durchgefallen, ist eine Primzahl *\/<\/span>\r\n    <span class=\"kwrd\">return<\/span> 1;\r\n  }\r\n\r\n  <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">void<\/span> main( String[] args )\r\n  {\r\n    <span class=\"kwrd\">int<\/span> zahl;\r\n\r\n    <span class=\"rem\">\/* Von 3 beginnend jede zweite Zahl testen, bis unter 1000 *\/<\/span>\r\n    <span class=\"kwrd\">for<\/span> ( zahl = 3; zahl &lt; 1000; zahl += 2 ) {\r\n      <span class=\"kwrd\">if<\/span> ( istPrimzahl( zahl ) != 0 ) {\r\n        printf( <span class=\"str\">\"Primzahl: %u\\n\"<\/span>, zahl );\r\n      }\r\n    }\r\n\r\n    System.exit( 0 );\r\n  }\r\n}<\/pre>\n<p>F\u00fcr die C-Funktionen (<a title=\"http:\/\/www.cc65.org\/doc\/funcref.html\" href=\"http:\/\/www.cc65.org\/doc\/funcref.html) gibt\">http:\/\/www.cc65.org\/doc\/funcref.html) gibt<\/a> es eine paar statische Imports und native Platzhalter:<\/p>\n<pre class=\"csharpcode\">package j2c.lib;\r\n\r\n<span class=\"rem\">\/\/ http:\/\/www.cplusplus.com\/reference\/cstdio\/<\/span>\r\n\r\n<span class=\"kwrd\">public<\/span> <span class=\"kwrd\">class<\/span> Stdio\r\n{\r\n  <span class=\"rem\">\/**<\/span>\r\n<span class=\"rem\">   * Print formatted data to stdout.<\/span>\r\n<span class=\"rem\">   * &lt;code&gt;int printf ( const char * format, ... );&lt;\/code&gt;<\/span>\r\n<span class=\"rem\">   * @param format<\/span>\r\n<span class=\"rem\">   * @param args<\/span>\r\n<span class=\"rem\">   * @return<\/span>\r\n<span class=\"rem\">   *\/<\/span>\r\n  native <span class=\"kwrd\">public<\/span> <span class=\"kwrd\">static<\/span> <span class=\"kwrd\">int<\/span> printf( String format, Object... args );\r\n}<\/pre>\n<p>Das setzt der Compiler im Grunde 1:1 so um. Es lohnt sich das Eclipse CDT unter <a href=\"http:\/\/download.eclipse.org\/tools\/cdt\/releases\/juno\">http:\/\/download.eclipse.org\/tools\/cdt\/releases\/juno<\/a> zu installieren, damit die syntaktische Hervorhebung funktioniert (den CC65 Compiler einbinden k\u00f6nnten wir hier NICHT). Nach einer CDT-Neuformatierung ergibt sich:<\/p>\n<pre class=\"csharpcode\">#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;peekpoke.h&gt;\r\n#include &lt;c64.h&gt;\r\n#include &lt;conio.h&gt;\r\n<span class=\"rem\">\/* CLASS Application { *\/<\/span>\r\n<span class=\"kwrd\">char<\/span> istPrimzahl(<span class=\"kwrd\">int<\/span> n) {\r\n    <span class=\"kwrd\">int<\/span> divisor;\r\n    <span class=\"kwrd\">int<\/span> testEnde = n \/ 2;\r\n    <span class=\"kwrd\">for<\/span> (divisor = 3; divisor &lt; testEnde; divisor += 2) {\r\n        <span class=\"kwrd\">if<\/span> (n % divisor == 0) {\r\n            <span class=\"kwrd\">return<\/span> 0;\r\n        }\r\n    }\r\n    <span class=\"kwrd\">return<\/span> 1;\r\n}\r\n<span class=\"kwrd\">int<\/span> main(<span class=\"kwrd\">void<\/span>) {\r\n    <span class=\"kwrd\">int<\/span> zahl;\r\n    <span class=\"kwrd\">for<\/span> (zahl = 3; zahl &lt; 1000; zahl += 2) {\r\n        <span class=\"kwrd\">if<\/span> (istPrimzahl(zahl) != 0) {\r\n            printf(<span class=\"str\">\"Primzahl: %u\\n\"<\/span>, zahl);\r\n        }\r\n    }\r\n    <span class=\"kwrd\">return<\/span> 0;\r\n}\r\n<span class=\"rem\">\/* END CLASS } *\/<\/span><\/pre>\n<p>Um das Compilat zu Erzeugen muss nun der cc65 installiert werden. Unter <a title=\"ftp:\/\/ftp.musoftware.de\/pub\/uz\/cc65\/\" href=\"ftp:\/\/ftp.musoftware.de\/pub\/uz\/cc65\/\">ftp:\/\/ftp.musoftware.de\/pub\/uz\/cc65\/<\/a> l\u00e4dt man die f\u00fcr Windows etwa die 1.3 MB gro\u00dfe EXE und installiert. Die Eintragungen in den Path kann man vornehmen, nach der Installation folgt dann mit dem kleinen Test:<\/p>\n<p>C:\\..&gt;cc65<\/p>\n<p>cc65.exe: No input files<\/p>\n<p>Kappt also.<\/p>\n<p>Das Ganze soll im Emulator laufen, hier ist WinVICE gut: <a title=\"http:\/\/www.viceteam.org\/#download\" href=\"http:\/\/www.viceteam.org\/#download\">http:\/\/www.viceteam.org\/#download<\/a>.<\/p>\n<p>Eine Batch-Datei bindet alles zusammen, also Java \u2013&gt; C, Compilieren und im VICE starten:<\/p>\n<pre class=\"csharpcode\">set JAVA_HOME=<span class=\"str\">\"C:\\Program Files\\Java\\jdk1.7.0\"<\/span>\r\n%JAVA_HOME%\\bin\\java -cp bin\/;%JAVA_HOME%\\lib\\tools.jar j2c.J2CC65 src\/java\/Application.java &gt; app.c\r\ndel app.prg\r\ncl65 -o app.prg app.c\r\n<span class=\"str\">\"C:\\Program Files\\WinVICE-2.2-x64\\x64.exe\"<\/span> app.prg<\/pre>\n<p>Und das Ergebnis sieht so aus:<\/p>\n<p><a href=\"http:\/\/www.tutego.com\/blog\/javainsel\/images\/Mit-Java-fr-C64-entwickeln_20A0\/image.png\"><img loading=\"lazy\" decoding=\"async\" style=\"background-image: none; padding-left: 0px; padding-right: 0px; display: inline; padding-top: 0px; border: 0px;\" title=\"image\" src=\"http:\/\/www.tutego.com\/blog\/javainsel\/images\/Mit-Java-fr-C64-entwickeln_20A0\/image_thumb.png\" alt=\"image\" width=\"644\" height=\"404\" border=\"0\" \/><\/a><\/p>\n<p>Hat jmd. Lust das weiter zu entwickeln? Schreibt mir eine E-Mail.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Knackige \u00dcberschrift, was steckt dahinter? Wir warten auf den Architekten f\u00fcr unser Restaurant hier in den Philippinen und so hatte ich etwas Leerlauf, um was total Unn\u00f6tiges zu programmieren. Um Java-Programme, beziehungsweise eine Teilmenge der Sprache\/Bibliothek, auf dem C64 (oder anderen 8-Bit-Computern) zum Laufen zu bringen, sind mehrere Ans\u00e4tze denkbar: Eine JVM auf dem Heimcomputer, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","_links_to":"","_links_to_target":""},"categories":[1],"tags":[],"class_list":["post-1850","post","type-post","status-publish","format-standard","hentry","category-allgemein"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1850","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/comments?post=1850"}],"version-history":[{"count":4,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1850\/revisions"}],"predecessor-version":[{"id":3012,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/posts\/1850\/revisions\/3012"}],"wp:attachment":[{"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/media?parent=1850"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/categories?post=1850"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tutego.de\/blog\/javainsel\/wp-json\/wp\/v2\/tags?post=1850"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}