#$K+ KC-Load – Kassetten-Transfer
KCLOAD.EXE – ein Hilfsprogramm nicht nur für KCEMU – überträgt Kassettendateien über eine geeignete Soundkarte in den PC. Dabei können verschiedene Speicherformate ausgewählt und bei Bedarf über eine externe DLL selbst programmiert werden.
Dieses Programm ist sicher nicht perfekt – Bug-Berichte bitte an henrik.haftmann@e-technik.tu-chemnitz.de.
Zum Programm
Vorwort
Funktionsprinzip
Erforderliche Hard- und Software
Bedienung
Hauptfenster
Datei-Dialog
Benutzerdefinierte Kodierung erstellen
Hilfe KC-Load © h#s (5/13)

+$#K Vorwort
Zu einem Emulator gehört sich eigentlich die Möglichkeit, Kassettendateien irgendwie in den PC zu bekommen. Für Disketten wird CDRIVE empfohlen. Bei Kassetten sieht das schon anders aus. Obwohl der Ur-PC auch ein Kassetten-Interface hatte, wurde das bei den „Kompatiblen“ später weggelassen. Erst seit sich Soundkarten in PCs allgemein durchgesetzt hatten, gibt es wieder eine Möglichkeit, Bandaufnahmen ohne Basteleien in den Computer zu lesen.
Außerdem ermöglicht KC-Load die umgekehrte Richtung: Daten auf Kassette speichern; das ist wohl eher für Nostalgiker oder zur Erinnerung, wie sich das damals so anhörte. (Für Programmierer auch zu Testzwecken.)

Die ursprüngliche Idee war, dass der emulierte Code im KCEMU die Kassettendateien einlesen könnte. Auf diese Weise könnte man jedes noch so exotische Format lesen. Das Problem ist jedoch, dass man dazu einen wirklich schnellen Computer braucht, und die Handhabung umständlich bleibt.

+$#K Funktionsprinzip
Die Kassettenaufzeichung erfolgt im FM-Verfahren, also Frequenzmodulation. Dabei ist die konstante Länge einer Bitzelle nicht von Belang, d. h. ein Block mit vielen Nullen ist kürzer als einer mit vielen Einsen. Die Möglichkeit der Amplitudenmodulation mit einer Soundkarte (z. B. Kantenglättung, Nulldurchgangsschätzung) wurde nicht vorgesehen; es wird einfach Rechtecksignal generiert bzw. erwartet.

Grundlegende Unterprogramme sind ReadSwing, Messen der Zeit (Samples) zwischen zwei Nulldurchgängen, und WriteSwing, Ausgabe einer Halbschwingung mit vorgegebener Anzahl von Samples. Diese beiden Unterprogramme überwachen den Samplepufferüberlauf und fordern ggf. von MMSystem den nächsten Puffer an.
Auf die beiden Unterprogramme kann jedes denkbare Kassettenformat aufgebaut werden, mit weiteren Unterprogrammen wie WriteByte, WriteBlock usw.

Weiterhin arbeitet das Programm mit einer Multimedia-Task, eine Art Multithreading unter 16-bit-Windows.
Als Folge können Sie während des Ladens/Speicherns unbekümmert das Fenster verschieben usw.
Für den kontinuierlichen Datenfluss ist es aber wichtig, dass keine „große“ Applikation gestartet wird; d. h. Rechenzeit muss dennoch laufend zur Verfügung stehen.

+$#K Hard- und Software-Erfordernisse
Dieses Programm benötigt:
{bmc bullet.shg}	Windows 3.1 (Standard-Modus) oder höher
{bmc bullet.shg}	eine Soundkarte o.ä. mit einer Samplerate von 22kHz

Dieses Programm benötigt mindestens Windows 3.1 im Standard-Modus – demzufolge einen AT286 oder besser. Es ist 16bittrig und arbeitet daher auch unter WinOS2 und (vielleicht) WINE.
Alle gängigen Soundkarten sind geeignet; sie muss 22 kHz (Mono, 8bit) bei Wiedergabe und 11 kHz oder 22 kHz bei Aufnahme bewältigen. Ein einfacher PC-Lautsprecher-Treiber (speaker.drv) ist zur Wiedergabe nicht geeignet.

Wie alle 16-Bit-Windows-Programme läuft dieses Programm nicht unter 64-Bit-Windows-Versionen! Es sei denn, man installiert „wine für Windows“, also den Windows-Emulator (ursprünglich) für Linux.

+$#K Hauptfenster
Das Programm präsentiert sich als Dialogfenster, welches sämtliche Einstellmöglichkeiten auf einen Blick serviert. Beim Draufziehen von Dateien (Drag'n'Drop) werden diese ausgegeben.

{bmc kcload.shg}
Klicke mit der Maus auf Dialogelemente, oder drücke TAB und ENTER, um detaillierte Hilfe zu erhalten.

+$#K Datei-Dialog
Das Laden und Speichern erfolgt generell netto, kein Hinzufügen oder Weglassen von Headern (Vorblöcken). Werden Extra-Header gewünscht, muss der Schalter {bmc checkbox.bmp} Mit Vorblock eingeschaltet werden. Die Wirkung dieses Schalters ist abhängig von der gewählten Kodierung.
(Hier fehlt dem Schreiberling noch Information!)

+$#K Laden von Kassette
Dieser voreingestellte Schalter (ENTER löst Knopfdruck aus) startet den Einlesevorgang. Es wird das ausgewählte Wave-In-Gerät verwendet und die Daten über die ausgewählte Kodierung dekodiert. Das Speichern der erfolgreich eingelesenen Datei erfolgt generell am Ende. Dabei „errät“ KC-Load einen geeigneten DOS-Dateinamen aus der vorhandenen Header-Information.
Hinweis: Das Speichern im Z80-Format ist nicht explizit implementiert.

Mit dem Laden werden die eingelesenen Blöcke wie am KC in der blauen Statuszeile gelistet. (Betrifft nur KC85/1..4 und Turbolader MPM).

Folgende Zeichen müssen beim Einlesen beachtet werden:
>	Block wurde fehlerfrei gelesen; Band weiterlaufen lassen
?	Block wurde falsch gelesen; bitte Band etwas zurückspulen
*	Nicht erwartete Blocknummer gelesen; bitte Band vor- oder zurückspulen (je nachdem, welcher Block erwartet wird), ggf. Band weiterlaufen lassen und abwarten.
!	Fehlerhafter Block wurde nach angebbarer Anzahl von Versuchen schließlich fehlerhaft eingelesen

Bei den anderen Formaten erfolgen die Meldungen anders; bei BASICODE erscheint der Text; bei Turbolader h#s ist die Fehlerprüfung systembedingt erst am Ende des gesamten Einlesevorgangs möglich.

Diese Seite ins Hauptfenster

+$#K Speichern auf Kassette
Mit diesem Schalter öffnet sofort der Dateiauswahl-Dialog, in dem Sie die zu speichernde Datei auswählen. Mit dem OK beginnt der Speichervorgang über das ausgewählte Wave-Out-Gerät und die Kodierung. Generell geht der Dateiname beim Speichervorgang verloren.
Hinweis: Das Laden im Z80-Format ist nicht explizit implementiert.

Mit dem Speichern werden die geschriebenen Blöcke wie am KC in der blauen Statuszeile gelistet. (Betrifft nur KC85/1..4 und Turbolader MPM).
Dabei gibt es nur ein Zeichen:
<	Block wurde fehlerfrei(?) geschrieben; Band weiterlaufen lassen

Die anderen Kodierungen machen sich anders bemerkbar; BASICODE schreibt den gespeicherten Text in die Statuszeile.

Diese Seite ins Hauptfenster

+$#K Lese-Versuche
Um den Benutzer nicht mit nervenden Messageboxen o. ä. bei fehlerhaften Blöcken zu quälen, wurde bereits am KC eine Möglichkeit geschaffen, nach einer gewissen Anzahl von Leseversuchen automatisch den Block fehlerhaft zu lesen. So konnte und kann sich der Bediener ausschließlich dem Kassettenrecorder widmen und muss nicht zweiarmig arbeiten. Die Anzahl der Versuche ist hiermit einstellbar von 0 (fehlerhaften Block sofort lesen) bis 7; auch mit Maus unter Verwendung des Mini-Rollbalkens rechts. Die Zahl der Versuche wird sofort wirksam, also auch während des Lesens.
Vorgabe: 4

+$#K Lautstärke
Bei der Wave-Ausgabe kann die Lautstärke graduell von 0 (Stille, UNSINN!) bis 7 (maximaler Hub, ‑98..98) eingestellt werden. Der Hub errechnet sich zu 2*Lautstärke².
Vorgabe: 4

+$#K Kodierung
Entsprechend der Vielzahl emulierter Computer mit verschiedenen Kassettenformaten unterstützt KC-Load folgende Kodierungen:
{bmc bullet.shg}	KC85/1..4, das Standardformat für die KC-Reihe. Jeder Block umfasst 1 Byte Blocknummer, 128 Byte Nutzdaten und 1 Byte Prüfsumme.
{bmc bullet.shg}	Turbolader MPM, ein von Mühlhausen(?) stammendes Format mit gleichem Blockaufbau, aber doppelt so schnell.
{bmc bullet.shg}	Turbolader h#s, ein von haftmann#software 1990/91 entwickelter Lader. Das Besondere: Der Code zum Turbo-Laden befindet sich im ersten Daten-Block (im gewohnten KC85/1..4-Format), so dass man keinen extra Lader braucht(e). Ist etwa dreimal so schnell; gravierender Nachteil ist, dass die Prüfsumme erst am Schluss kommt.
{bmc bullet.shg}	Z1013, dieser Computer verwendet als einziger Blöcke mit 32 Byte Nutzdaten. Dabei gibt es Dateien ohne und mit Header vom Extra-Programm HEADERSAVE. Meist kursieren Dateien mit Header, weil man sich ansonsten unbedingt Anfangs-, End- und Startadresse aufschreiben musste und die Dateien keinen Namen trugen. Etwa so schnell wie KC85/1..4
{bmc bullet.shg}	BASICODE, nicht nur ein BASIC-Dialekt, sondern auch ein gemeinsames Dateiformat, erschaffen von Radio Hilversum zur Vereinheitlichung der BASIC-Programme (besonders zwischen West-Computern). Sehr langsam. FSK-moduliertes RS-232 mit 1200 Baud, 8 Datenbits, 2 Stoppbits. Bit 7 invertiert. Trägerfrequenzen 2400 Hz (1-Bit), 1200 Hz (0-Bit). Keine Prüfsummen, nur für Text gedacht.
{bmc bullet.shg}	benutzerdefinierte Kodierungen; die Programme dazu befinden sich in DLLs mit der Endung .KCL, die sich im Startverzeichnis von KCLOAD.EXE befinden müssen. Wenn keine .KCL-Dateien gefunden wurden, erscheinen auch keine. Hinweise zum Schreiben solcher DLLs siehe Benutzerdefinierte Kodierung erstellen.

Vorgabe: KC85/1..4

Diese Seite ins Hauptfenster

+$#K Ende/Abbruch
Dieser Schalter beendet das Programm KC-Load. Er wechselt während der Wave- Ein/Ausgabe zu einem Abbruch-Schalter; damit wird der Wave-Vorgang beendet. Die Taste ESC funktioniert nur bei Beschriftung Abbruch; das Programmende kann mit Alt+E, Alt+F4, System-Menü oder Task-Manager erreicht werden.

+$#K Hilfe
Naja, muss ich den Schalter erklären?

+$#K Installieren
Was macht denn SO ein Schalter?
Zunächst wird KC-Load keinerlei Registry-Eintragungen vornehmen. Im Gegenzug „vergisst“ es alle Einstellungen beim Beenden.
Wollen Sie jedoch, dass KC-Load die Einstellungen (Lese-Versuche, Lautstärke, Kodierung und Wave-Geräte) sich merkt, drücken Sie diesen Knopf. Es wird sofort und ab jetzt auch bei jedem (normalen) Programmende gespeichert.

+$#K Wave-Geräte
Nur für den Fall, dass Sie mehrere Soundkarten verwenden, können Sie hiermit die gewünschte auswählen. Bei Wave-Mapper wählt Windows eine freie Soundkarte selbständig aus (siehe auch Win95-Systemsteuerung/Multimedia/Audio/Bevorzugtes Gerät).
Falls keine Soundkarte auftaucht, ist entweder keine installiert, oder das Format 22 kHz, Mono, 8 bit (11 kHz bei Aufnahme) wird nicht unterstützt. Falls Sie in diesem Falle Wave-Mapper auswählen, kann das Programm sehr hart abstürzen (Ursache noch ungeklärt).
Außerdem haben Sie die Möglichkeit, mit WAVE-Dateien zu arbeiten; KC-Load benutzt in diesem Fall immer eine Datei KCLOAD.WAV im aktuellen Verzeichnis (Name nicht änderbar).

+$#K Block (Status-Anzeige)
Hier können Sie KC-like den Lade- und Speicher-Vorgang verfolgen. Zur Erläuterung der angezeigten Symbole sehen Sie unter Laden von Kassette und Speichern auf Kassette nach.
Vielleicht erinnert Sie die weiße Schrift auf blauem Grund an den KC85…

#$K+ Benutzerdefinierte Kodierung erstellen
Die zu erstellende DLL muss (oder sollte mindestens einen der beiden) Eintrittspunkte mit folgenden Namen und Definitionen aufweisen:

procedure LOAD; export;
 {Laden von Kassette}
 ...

procedure SAVE; export;
 {Schreiben auf Kassette}
 ...

exports
 LOAD,
 SAVE;

Die Ordinalzahlen für den Export sind beliebig.
Der Kontext ist quasi ein Thread von MMTASK.TSK. (Ja, KCLOAD arbeitet multi-threaded!) Das reguläre Ende dieser Unterprogramme entspricht einem Aufruf von EndProcess(true), was den Thread beendet.

Diese beiden Routinen können sich zur Bewältigung ihrer Arbeit folgender Unterprogramme aus KCLOAD.EXE bedienen:

function ReadSwing:Integer; far; external 'KCLOAD' index 2;
 {Flusswechsel erkennen, LOAD}

procedure WriteSwing(Len:Integer); far; external 'KCLOAD' index 3;
 {Flusswechsel schreiben, SAVE}

procedure EndProcess(OK:Boolean); far; external 'KCLOAD' index 4;
 {Vorzeitig abbrechen, LOAD und SAVE}

procedure SetStatus(S:PChar); far; external 'KCLOAD' index 5;
 {Statuszeile setzen, LOAD und SAVE}

function GetSizeData:Longint; far; external 'KCLOAD' index 6;
 {Restliche Datei-Bytes ermitteln, SAVE}

function GetDataBlock(P:PChar; Size:Integer):Integer; far; external 'KCLOAD' index 7;
 {Datei-Bytes holen, SAVE}

procedure AddDataBlock(P:PChar; Size:Integer); far; external 'KCLOAD' index 8;
 {Datei-Bytes schreiben, LOAD}

procedure GetName(P:PChar; Size:Integer); far; external 'KCLOAD' index 9;
 {Dateiname beschaffen, SAVE}

procedure SetNameHint(P:PChar); far; external 'KCLOAD' index 10;
 {Dateiname vorgeben, LOAD}

Diese Programme sind weitestgehend selbsterklärend, hoffe ich. Das „Len“ bei WriteSwing bzw. das Ergebnis bei ReadSwing versteht sich als Sample-Zahl bei 22kHz.
Wie der Name EndProcess andeutet, kehrt diese Routine niemals zurück.
Das Ergebnis von GetDataBlock ist die Anzahl der in den Puffer kopierten Bytes. Falls dagegen AddDataBlock keine Bytes mehr schreiben kann, kehrt diese Prozedur nicht zurück; es erscheint eine Fehlermeldung.

Alternativ kann diese DLL in C oder Assembler(!) geschrieben werden; entsprechende Anweisungen müssen in die .DEF-Datei geschrieben werden. (Integer=int, PChar=LPSTR, Boolean=char.)
Ist diese DLL fertig, muss sie in *.KCL umbenannt werden, damit sie von KCLOAD.EXE erkannt wird.
Zum Testen der DLL ist es nützlich, einen Breakpoint (asm int 3 end) zu Beginn der Unterprogramme LOAD und SAVE zu setzen.

Hinweis: Eine solche DLL wurde noch nie geschrieben, wer's macht, ist der erste!