Hello, Guest the thread was called1.2k times and contains 24 replays

last post from zrs1 at the

mkd64 - Weiterentwicklung

  • Hallo zusammen,


    ich habe mir vorgenommen, nach mehreren Jahren Pause endlich mkd64 weiterzuentwickeln. Wer jetzt nicht weiß, was das ist: Es handelt sich um ein Tool, um .D64 disk images zu erstellen, vor allem dafür gedacht, direkt in einem cross-build Prozess eingesetzt zu werden, so dass die selbst entwickelte C64 Software direkt auf einem disk image landet. Die bisher aktuelle Version 1.4b findet ihr auf Github, in der CSDb gibt es nur die etwas ältere 1.3b.


    Bevor ich aber wieder in den Code einsteige wollte ich das Projekt erst einmal neu strukturieren, so wie es mir heute "in den Kram passt" (wer mag schon den Krempel, den er vor Jahren gebaut hat). Ich möchte es a) einfacher haben und b) bei Gelegenheit den Code modernisieren (Richtung C11, eventuell C18). Deshalb habe ich als ersten kleinen Schritt das Buildsystem umgestellt. Bisher konnte mkd64 auf zwei verschiedene Arten gebaut werden:

    • mit GNU make (dafür waren handgeschriebene Makefiles drin)
    • mit Visual Studio (dafür waren .sln / .vcproj Files drin)

    Letzteres fällt komplett weg, schon allein, weil Microsofts C-Compiler einfach nicht mehr zeitgemäß ist -- Microsoft hat wohl entschieden, dass C nicht mehr interessiert sondern nur noch C++. Auf Windows muss in Zukunft mit mingw gebaut werden, ich empfehle dazu die Installation von MSYS2. Ersteres habe ich jetzt ersetzt durch ein ebenfalls selbst geschriebenes Build-System, das nur GNU make verwendet; es nennt sich zimk.


    Ein erstes Resultat dieser Umstellung ist seit heute eingecheckt, und es würde mich freuen, wenn jemand den Build testen könnte. Bisher ist es nur möglich, das Tool selbst (und die 3 bisher existierenden Plugins) zu bauen und zu installieren, am Code hat sich noch nichts geändert (gebaut wird Version 1.4b), Dokumentation und SDK für Plugins kann noch gar nicht gebaut werden. Das kommt hoffentlich noch ;)


    Wer es testen will bekommt den Source mit
    git clone --recursive https://github.com/Zirias/c64_tool_mkd64 mkd64


    danach lässt es sich mit make oder make strip (für "gestrippte" executables, also ohne unnötige symbole) bauen. make install installiert (auf Windows per default ins Unterverzeichnis dist, auf POSIX-Systemen wie Linux oder *BSD in den Verzeichnisbaum unter /usr/local). Das Build-System versteht viele übliche Variablen, wie z.B. prefix und DESTDIR.


    Auf Systemen, auf denen GNU make nicht das standard "make" ist (z.B. alle BSDs), muss statt make gmake geschrieben werden.


    Würde mich über etwas Feedback zum neuen Buildsystem freuen, vor allem um Bugs zu finden und zu beheben.


    Wenn das alles rund läuft wäre mein nächster Plan, ein neues Plugin zu schreiben, damit mkd64 auch bitfire Files schreiben kann :)

  • Habe noch ein bisschen gebastelt, unter anderem hat "zimk" (mein kleines Buildsystem) jetzt eine Option PORTABLE -- wenn die aktiv ist wird alles in ein Verzeichnis gebaut (die ganzen Verzeichnisvariablen sind leer), andernfalls in einen Unix Verzeichnisbaum. Auf Windows ist PORTABLE per default an, auf anderen Plattformen aus. Für eine kurze Anleitung gibt es auf der Seite von zimk ein README.


    Außerdem sind schon ein paar Build-Probleme gefixt, die ich selbst gefunden habe.


    Wer schon den Source per git geholt hat kann einfach mit git pull aktualisieren. Zimk sorgt dann selbst davon, dass es als submodule auch aktualisiert wird.

  • Ich habe mal versucht mit Cygwin32 zu übersetzen. Bricht leider ab:


    Code
    1. $ make
    2. [CFG] [release]
    3. [CCLD] lib/i686-pc-cygwin/release/cbmdos.so
    4. obj/i686-pc-cygwin/release/src/lib/mkd64/cbmdos/module_s.o:module.c:(.text+0xbb): undefined reference to `DiskFile_data'
    5. obj/i686-pc-cygwin/release/src/lib/mkd64/cbmdos/module_s.o:module.c:(.text+0xdb): undefined reference to `Block_rawData'
    6. ...
    7. obj/i686-pc-cygwin/release/src/lib/mkd64/cbmdos/alloc_s.o:alloc.c:(.text+0x39b): undefined reference to `mkd64Alloc'
    8. obj/i686-pc-cygwin/release/src/lib/mkd64/cbmdos/alloc_s.o:alloc.c:(.text+0x111): undefined reference to `Track_block'
    9. collect2: error: ld returned 1 exit status
    10. make: *** [src/lib/mkd64/cbmdos/cbmdos.mk:7: lib/i686-pc-cygwin/release/cbmdos.so] Error 1
  • Hui! @ogd, erstmal vielen Dank fürs testen :) cygwin hatte ich in der Tat GAR nicht auf dem Schirm, ist ja auch eigentlich unnötig, da mkd64 "native" win32 unterstützt. Aber gibt auf der anderen Seite auch keinen Grund, warum es NICHT gehen sollte, cygwin ist ja "einfach nur" POSIX auf Windows.


    Anhand der Fehlermeldung weiß ich auch schon, was genau schiefgeht. Das ist in der Tat mein eigenes Buildsystem "zimk", das da auf cygwin die falschen Entscheidungen trifft, wie ein Plugin zu linken ist. Hintergrund: Auf fast allen Plattformen sind "unresolved Symbols" in einem shared object völlig ok, der dynamic Linker löst diese dann zur Laufzeit auf. Nicht so auf Windows, da braucht es für alle extern referenzierten Symbole eine "import lib", also im Fall eines Plugins eine, die zum Hauptprogramm passt. Sieht jetzt so aus als würde zimk unter cygwin eine "posix" Plattform detecten und entsprechend alles auf die posix Art machen, was dann beim Linken eines Plugins schiefgeht, da hier auch unter cygwin das "normale" Windows DLL-Schema verwendet wird.


    Ich grüble mal ein wenig über einer Lösung, danke für den Hinweis ;)


    Edit: Örks! Gerade das Log nochmal genauer angeschaut -- da stimmt ja noch mehr nicht, z.B. wird das Plugin auch als "cbmdos.so" gebaut (statt "cbmdos.dll") -- cygwin ist hier ein seltsamer Zwitter aus der posix und der win32 Welt, das muss ich mir wohl selbst erstmal installieren, um eine Lösung finden zu können. Oder ich definiere es als "unsupported" ;) Mal sehen...

  • So, jetzt lässt es sich auch mit cygwin bauen und sogar installieren. Empfehlen würde ich das zwar nicht (zieht ohne Not die Abhängigkeit zur cygwin DLL rein), aber egal, ist jedenfalls ein kleiner Fortschritt für "zimk", dass cygwin unterstützt wird :)

  • Achso, verstehe :) ich habe Cygwin eben immer nur als (durchaus gut gelungene) Krücke gesehen für Software, die POSIX hart voraussetzt. "Krücke" schreibe ich, weil sich manches aus der POSIX Welt auf win32 nur mit dreckigen Tricks hässlich implementieren lässt, z.B. fork() -- soll also keine Kritik an Cygwin sein :)


    Aber wenn es jemand nützlich findet, mkd64 für Cygwin bauen zu können, dann hat sich die Arbeit ja gelohnt!


    Sobald ich es geschafft habe, ein neues Feature einzubauen, wird es auch wieder einen offiziellen Windows-Build geben -- der dann allerdings mit mingw. Bisher war es MSVC, aber Support für diesen Compiler fliegt definitiv raus :)

  • Sobald ich es geschafft habe, ein neues Feature einzubauen, wird es auch wieder einen offiziellen Windows-Build geben -- der dann allerdings mit mingw. Bisher war es MSVC, aber Support für diesen Compiler fliegt definitiv raus :)

    Ja, ein offizielles Windows-Build sollte natürlich keine Abhängigkeit zu Cygwin haben!

  • Bisher war es MSVC, aber Support für diesen Compiler fliegt definitiv raus

    Ich weiß ja, dass alte MSVC-Versionen grausig waren, aber was spricht denn gegen die aktuellen? Ich dachte, die haben einen kompletten Rewrite hingelegt und jetzt wäre alles ganz toll standardkonform etc? Oder stimmt das gar nicht?


    Was ich aus eigener Erfahrung weiß, ist dass der Compiler mittlerweile verflixt schnellen Code erzeugt, der mit dem Intel Compiler mithält. Außerdem arbeitet wohl die Mehrzahl von Windowsentwicklern unter Visual Studio, daher fände ich es generell schade, wenn Support dafür rausfliegt...

  • https://stackoverflow.com/ques…io-2017-fully-support-c99


    Kurz: Nichtmal C99 wird vollständig unterstützt, C11/C18 kannst du komplett vergessen. Microsofts Compiler ist für C und C++, aber nur letztere Sprache bekommt da wirklich Aufmerksamkeit.


    Da das Tool portierbar ist und bleiben soll und ich sowieso lieber mit make und einem gescheiten Texteditor arbeite habe ich keine Lust mehr, mich im Code auf "altes" C zu beschränken und dazu auch noch Files für Visual Studio zu pflegen, die nur die Funktion der Makefiles "doppeln", und das nur für eine Zielplattform. Wer auf Windows selbst compilieren will kann MSYS2 installieren, das ist keine große Schwierigkeit. Auch IDEs, die mit Makefiles klarkommen und ein Frontend zum GDB haben gibt es ;)

  • Ach, ich hatte in Erinnerung dass mkd64 in C++ geschrieben sei, da täuscht mich dann wohl mein Gedächtnis. Dann bin ich ganz bei Dir, weitermachen ^^

  • Das Projekt ist vorerst auf Eis. Es wird allerdings ein "mkd64 v2" kommen, ich kann nur nicht sagen ob in ein paar Monaten oder in ein paar Jahren ;)


    Der Grund: Ich habe mich für einen kompletten Rewrite mit anderer Architektur entschieden. Plugins gibt es (vielleicht auch vorerst?) nicht mehr, dafür steckt alle Funktionalität, die sich auf D64 images, CBM Dos, usw bezieht, in einer library. Die Library ist zwar objektorientiert, aber reines C -- das neue mkd64 wird sie verwenden (ebenfalls reines C).


    Status der Library ist aktuell: Kann das meiste, was ich gerne hätte (es fehlt noch Support für REL files und für G64 images). Hat aber auch noch Bugs.


    Aktuell arbeite ich an einem GUI (!) in C++ mit Qt. Das ist recht nervig, aber auf die Art findet man viele Bugs in der Lib :)


    Im Gegensatz zum alten mkd64 unterstützt die Library auch editieren existierender Disks. Das ist aber auch sehr viel komplexer, daher werde ich wohl noch längere Zeit mit dem fixen von Bugs und der gleichzeitigen Weiterentwicklung der GUI beschäftigt sein. Wenn das mal stabil ist kommt "mkd64 v2" wie gehabt als Kommandozeilentool um disk images zu erzeugen :)

  • - Weil C++ Schrott ist (aber die Qualitäten von Qt für cross-platform GUIs sind die Schmerzen wert)

    - Weil die Library möglichst eigenständig sein soll, Basis für potentiell viele Tools wie eben "mkd64 v2" -- und das möchte ich maximal portierbar haben.

  • Habe das im Halbschlaf gepostet -- ich führe den Grund mal ein bisschen aus.


    • "C++ ist Schrott" -- das ist sehr plakativ, und natürlich kann man C++ sinnvoll einsetzen, und es hat auch seinen Grund, dass Qt sich für C++ und gegen C entschieden hat -- GUI-Anwendungen sind geradezu prädestiniert für OOP, und obwohl das auch in C geht (siehe GTK), ist es ab einer gewissen Komplexität der Klassenstruktur in C++ doch übersichtlicher, z.B. sobald man an einigen Stellen Polymorphie braucht. C++ hat aber diverse Designprobleme, die mir wirklich auf den Keks gehen, deshalb nutze ich im Zweifel lieber C. Einige davon kommen daher, dass C++ zwar jede Menge neue Features wollte, aber trotzdem zu C kompatibel sein wollte, daraus ist unter anderem folgendes entstanden:
      • Referenzen als "Alternative" zu Pointern. In der Regel kennen Sprachen entweder das eine Konzept oder das andere. Intern steckt das gleiche dahinter, statt Objekte an Funktionen zu übergeben usw, wird nur ein Zeiger übergeben, über den sich das Objekt finden lässt. Bei Pointern ist dieser Zeiger explizit vorhanden, man muss ihn explizit "dereferenzieren" um auf das Objekt zuzugreifen, man kann aber auch mit dem Zeiger selbst arbeiten. Bei Referenzen passiert alles implizit, der Zeiger ist für den Programmierer unsichtbar und wird automatisch dereferenziert. C hat Pointer, C++ wollte Referenzen, also hat C++ beides.
      • Eigentlich "falsche" empfohlene Schreibweise. Klassisches Beispiel einer Pointer-Deklaration in C: int *a;. C++ empfiehlt, mit der (durchaus sinnvollen) Begründung, dass "Pointer" Teil des Typs ist, folgende Schreibweise: int* a;. Trotzdem ist C++ auch hier voll kompatibel zu C geblieben -- bei C war die Idee, dass die Deklaration immer genau so aussehen soll wie die Verwendung (deshalb "klebt" der Stern am Bezeichner und nicht am Typ). Das fällt bei Mehrfachdeklarationen auf: int* a, b; deklariert nicht etwa zwei Pointer sondern einen Pointer und ein Integer, in beiden Sprachen. Die Empfehlung für C++: Mehrfachdeklarationen meiden. Kann man machen (finde ich auch sinnvoll), löst aber nicht alle Probleme dieser Art. Eigentlich müsste man dann ja ein Array auch so deklarieren: int[5] a; (denn auch "Array" ist ja Teil des Typs). Das geht aber auch in C++ nicht, eben wegen Kompatibilität zu C.
      • Schlechteres "information hiding" als in C. In C werden Schnittstellen von Modulen nicht automatisch generiert, wie in manchen moderneren Sprachen (Java, C#, ...). Stattdessen werden sie vom Programmierer explizit in "header files" geschrieben. In C ist die Sache einfach, alles was "privat" ist, wird im Header schlicht nicht erwähnt. Wenn man in C eine "Klasse" schreibt, landen die Daten in einer "struct", die muss im Header aber nur erwähnt sein, den Inhalt kann man geheim halten. In C++ wurde das Konzept mit den Headern natürlich beibehalten (kompatibel zu C!), allerdings wenn man eine class deklarieren will, die aus einem anderen Modul genutzt werden kann, muss diese im Header stehen. Das beinhaltet alle privaten Felder und Methoden. Die Folge: Bei einer normalen C++-Klasse ist auch alles private Teil der Schnittstelle -- wenn sich Interna ändern, müssen alle Verwender neu compiliert werden. Es gibt eine Krücke, um dieses Problem zu umgehen, das "pimpl-Idiom". Verwende ich selbst häufig...
    • Dazu kommt das Thema "Exceptions". Dazu muss ich sagen, ich bin überhaupt kein Freund von Exceptions, weil sie einen versteckten Ablaufpfad einführen und die Wahrscheinlichkeit für Bugs steigern. Neuerdings gibt es durchaus Strömungen (Stichwort z.B. Railway-Programming), die das genauso sehen. Allerdings existiert entsprechende Kritik an Exceptions schon sehr viel länger, siehe z.B. Exception Handling Considered Harmful. Bei C++ ist es jetzt besonders schlimm, da man hier Exceptions mit explizitem Resource-Management kombiniert hat, was eine besonders unschöne Kombination ist. Der Programmierer muss peinlich genau darauf achten, dass durch Exceptions keine Resourcen "leaken" (z.B. Speicher nicht freigegeben wird). Hier kommt z.B. das C++-Prinzip RAII ins Spiel, um das zu vermeiden -- auf jeden Fall ist es eine weitere Komplexität. Zum Glück kann man mit Qt auch komplett auf Exeptions verzichten ;)
    • Stichwort Portierbarkeit der Library: Neben der Tatsache, dass es funktionierende C-Umgebungen immer noch für mehr Systeme gibt als funktionierende C++-Umgebungen finde ich hier noch eine Sache wirklich wichtig: Eine C-Library lässt sich in der Regel problemlos in C++ direkt verwenden (wenn der Programmierer hier nicht böswillig stört indem z.B. C++ keywords verwendet werden) -- wenn man den Header sinnvoll schreibt sieht es auch alles sauber aus. Der umgekehrte Weg ist unmöglich, da muss man schon einen "Adapter" vor die Lib setzen. Dazu kommt, dass C++-APIs nicht unbedingt zwischen verschiedenen Compilern binärkompatibel sind -- das bei C++ notwendige name mangling ist nämlich nicht standardisiert.
  • Moin,


    ich hatte vor Jahren auch mal etwas in dieser Richtung gebastelt, aber auch irgendwann aufgehört und heute würde ich den Code wahrscheinlich heute auch anders schreiben ;-)

    Meine Idee war damals auch eine Library zu bauen und passend dazu eine Konsolentool und ggf. später eine GUI Variante.


    Da es damals für meine Testzweck gereicht hatte, habe ich auch nicht weitergemacht. Auch mein Zeug ist auf Github (https://github.com/thecky/libcdim und https://github.com/thecky/cdim).


    Du hast geschrieben, das Du jetzt auf eine andere Architektur wechseln möchtest - welche denn?


    Gruß

    Thomas

  • Auch mein Zeug ist auf Github

    Mein aktuelles ist es (noch!) nicht, da es diesmal bei Erfolg eventuell ein "Scene release" werden könnte ;) Danach wird es aber auf jeden Fall "opensourced".

    Du hast geschrieben, das Du jetzt auf eine andere Architektur wechseln möchtest - welche denn?

    Die einfache, die auch du verfolgt hast: Alle Funktionalität zu den Images in einer shared library, "mkd64 v2" wird nur ein Frontend dieser Library werden. Dazu dann auch ein GUI Tool.


    Das bisherige mkd64 hatte eine Plugin-Architektur -- das Handling der rohen Disk-Images war direkt im Konsolen-Tool, alles andere (wie ein Cbmdos-Filesystem) war als ladbares Plugin implementiert. Ich sehe darin aber keinen Vorteil mehr, die Plugins bringen nur Komplexität ohne echten Nutzen. Die Idee war mal, dass es für den User leicht erweiterbar ist, aber das ist wohl eher Utopie.


    Hier mal ein Screenshot der aktuellen Entwicklungsversion des GUI: