|
Es ist unter Die Abteilungen des Betriebssystems: AmsdosAmsdos jedoch nicht möglich, zeichenweise geschriebene Dateien en Die Speicherkonfiguration im Schneider CPC: Blockblock zu laden!
Und versucht man, en Die Speicherkonfiguration im Schneider CPC: Blockblock geschriebene Dateien zeichenweise zu lesen, so gibt es Schwierigkeiten:
Das Zeichen 26 wird, wie das beim zeichenweisen Lesen einer Datei üblich ist, als EOF interpretiert. Dieser Code kann aber auch rein zufällig in der Datei vorkommen, vor allem, wenn sie eben keinen 'normalen' ASCII-Text enthält. Man kann dieses Zeichen aber auch ganz bewusst in eine Datei schreiben, z.LOW KERNEL JUMPBLOCK: 000B: LOW KL LOW PCHL LOW KERNEL JUMPBLOCK: 001B: LOW KL FAR PCHL LOW KERNEL JUMPBLOCK: 003B: LOW EXT INTERRUPTB. unter Einleitung: BASIC Anhang: BasicBasic in eine OPENOUT-Datei: PRINT#9,CHR$(26). Wird dieses Zeichen später eingelesen, so wird es als sogenanntes 'weiches' EOF (soft end) interpretiert, auch wenn danach noch 10 kByte Text folgen sollten!
Trotzdem kann man bei einer Datei mit Amsdos: HeaderHeader erkennen, dass ein CHR 26 kein EOF ist, weil im Amsdos: HeaderHeader ja steht, wieviele Datentypen: Bytes Datenbreite: BytesBytes die Datei umfasst. Bei einer ASCII-Datei dagegen könnte man nur dann ein EOF trotz gelesenem Zeichen 26 sicher ausschließen, wenn das Zeichen in einem anderen als dem letzten Datenspeicherung und Datenstrukturen: RecordsRecord gefunden wurde.
Soll ein Basic-Programm zu einem bereits bestehenden in den Speicher gemischt, also 'gemerget' werden, so muss der Basic-Interpreter das neue Programm zeichenweise einlesen, auch wenn es, wie üblich, en Die Speicherkonfiguration im Schneider CPC: Blockblock gespeichert wurde. Damit ist der kritische Fall da:
Wird jetzt das Zeichen 26 eingelesen, was sehr häufig vorkommen kann (nicht nur bei der Zeilennummer 26), so meldet Die Abteilungen des Betriebssystems: AmsdosAmsdos mitten in einer Basic-Zeile ein EOF und der Basic-Interpreter weiß sich in seiner Not nicht anders zu helfen, als das gesamte Programm zu löschen.
Der einfachste Trick ist, Programme, die später 'gemerget' werden sollen, als ASCII-Datei zu speichern:
SAVE "progname",Operationen: BD5B / 349A / 349A: FLO SUBa
Der von Schneider publizierte Trick besteht in einem Patch des Vektors CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR: Hier wird die Meldung "soft end" = CY=0, Z=0 und Operationen: BD5B / 349A / 349A: FLO SUBA=26 in "alles o.k." = CY=1 und Operationen: BD5B / 349A / 349A: FLO SUBA=26 umgewandelt. Damit klappt dann das Mergen von normalen Basic-Programmen.
Aber oh weh! Damit ist man bei Schneider voll über's Ziel hinausgeschossen, denn jetzt wird u. Operationen: BD5B / 349A / 349A: FLO SUBA. beim Mergen von ASCII-Programmdateien das Zeichen 26 nicht mehr als EOF erkannt, und Einleitung: BASIC Anhang: BasicBasic meldet nun mit schöner Regelmäßigkeit "Direct Befehls-Elemente: Commandscommand found". Auch INPUT und LINE INPUT aus OPENIN-Dateien schießen jetzt über das Datei-Ende hinaus, weil CHR 26 nicht mehr als File-Ende erkannt wird. Statt dessen lesen sie schön brav weiter, bis mit dem Record-Ende das sogenannte 'hard end' erreicht ist.
Trotzdem ist es sicher oft sinnvoll, diesen Vektor zu patchen. Das folgende Assembler-Programm vermeidet die Schwäche des Schneider-Patches, indem nur bei Header-Dateien der Vektor CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR gepatcht wird. Dateien ohne Amsdos: HeaderHeader werden nicht gepatcht und liefern deshalb beim CHR 26 auch weiterhin ein 'soft end'.
Dieses Beispiel zeigt auch, wie umständlich man die Amsdos-Vektoren patchen muss, weil diese nicht relocatibel sind.
Da die beiden RSX-Kommandos |DISC und |DISC.IN die betroffenen Vektoren wieder in den Original-Amsdos-Zustand versetzen, dürfen sie nicht benutzt werden! Man kann aber selbst zwei RSX-Kommandos mit diesen Namen zu definieren (die dann Priorität über die 'aelteren' Definitionen erlangen), die erst die Original-Routinen aufrufen, und danach den Patch sofort wieder restaurieren.
; Verbesserter CHAIN-MERGE / MERGE-Patch Erklärung zu den Anschlüssen: Vcc und Vss Erklärung zu den Anschluss-Bezeichnungen: Vcc und Vssvs. 25/26.5.86 (c) G.Woigk
; -------------------------------------- -------------- -----------
;
ORG 40000
;
INCHAR: EQU #BC80 ; CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR
OPENIN: EQU #BC77 ; CASSETTE MANAGER: BC77: CAS IN OPENCAS in OPEN
;
; Hier: Relocater einbinden.
;
INIT: LD HL,OPENIN ; Erstelle eine Kopie (1) des Vektors
LD DE,KOPIE1 ; CASSETTE MANAGER: BC77: CAS IN OPENCAS IN OPEN.
LD BC,3
LDIR
;
LD HL,INCHAR ; Erstelle eine Kopie (2) des Vektors
LD BC,3 ; CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR.
LDIR
;
; Hier evtl. noch eigene |DISC- und |DISC.IN-Befehle definieren.
;
INIT1: LD HL,OPEN ; Patche den Vektor CASSETTE MANAGER: BC77: CAS IN OPENCAS IN OPEN
LD (OPENIN+1),HL ; mit Sprung zur eigenen Routine OPEN.
LD HL,OPENIN
LD (HL),195 ; Opcode für 'JP'.
RET
;
KOPIE1: DEFS 3 ; Platz für Original von CASSETTE MANAGER: BC77: CAS IN OPENCAS IN OPEN.
KOPIE2: DEFS 3 ; Platz für Original von CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR.
;
; Ersatz-Routine für CASSETTE MANAGER: BC77: CAS IN OPENCAS IN OPEN
;
OPEN: PUSH HL
LD HL,(KOPIE1) ; Restauriere Vektor
LD (OPENIN),HL ; CASSETTE MANAGER: BC77: CAS IN OPENCAS IN OPEN.
LD Operationen: BD5B / 349A / 349A: FLO SUBA,(KOPIE1+2)
LD (OPENIN+2),Operationen: BD5B / 349A / 349A: FLO SUBA
POP HL
;
Maschinencode über HIMEM: CALLCALL OPENIN ; Rufe normale Die Fließkomma-Routinen: FunktionenFunktion auf.
;
PUSH HL
PUSH AF
Maschinencode über HIMEM: CALLCALL INIT1 ; und richte Patch wieder ein.
;
LD Operationen: BD5B / 349A / 349A: FLO SUBA,LOW KERNEL JUMPBLOCK: 000B: LOW KL LOW PCHL LOW KERNEL JUMPBLOCK: 001B: LOW KL FAR PCHL LOW KERNEL JUMPBLOCK: 003B: LOW EXT INTERRUPTB ; logische Datei-Länge = 0 ??
OR C
Maschinencode über HIMEM: CALLCALL NZ,OPEN1 ; Nein -> Datei hat Amsdos: HeaderHeader. Patche CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR
Maschinencode über HIMEM: CALLCALL Z,OPEN2 ; Ja -> Datei hat keinen Amsdos: HeaderHeader. Soft EOF darf
POP AF ; nicht abgefangen werden. --> CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR
POP HL ; restaurieren.
RET
;
; Patche CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR. (Nur HL benutzt wg. INCHR)
;
OPEN1: LD HL,INCHAR ; Opcode 'JP' in Vektor poken
LD (HL),195
LD HL,INCHR ; und Sprungadresse dahinter.
LD (INCHAR+1),HL
RET
;
; Versetze CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR in den Originalzustand:
;
OPEN2: LD HL,(KOPIE2) ; Vektor aus Kopie2
LD (INCHAR),HL ; an seine Position
LD Operationen: BD5B / 349A / 349A: FLO SUBA,(KOPIE2+2) ; im BCD1: KL LOG EXT: 1. JumpblockJumpblock
LD (INCHAR+2),Operationen: BD5B / 349A / 349A: FLO SUBA ; zurückkopieren.
RET
;
; Eigene Routine für CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR
;
INCHR: PUSH HL
Maschinencode über HIMEM: CALLCALL OPEN2 ; CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR restaurieren
Maschinencode über HIMEM: CALLCALL INCHAR ; CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR aufrufen
Maschinencode über HIMEM: CALLCALL OPEN1 ; CASSETTE MANAGER: BC80: CAS IN CHARCAS IN CHAR wieder patchen
POP HL
;
RET C ; CY=1 -> alles o.k.
RET Z ; Der Linien-Algorithmus: Fehler 3Fehler mit Z=1 -> kein 14/15/26-Der Linien-Algorithmus: Fehler 3Fehler
CP 26 ; Der Linien-Algorithmus: Fehler 3Fehler 26 = Soft EOF?
CCF
RET NC ; Der Linien-Algorithmus: Fehler 3Fehler < 26: Dann zurück mit CY=0 und Z=0
CP 27
RET C ; Der Linien-Algorithmus: Fehler 3Fehler = 26: Dann zurück mit CY=1 und Z=0
CP 26
RET ; Der Linien-Algorithmus: Fehler 3Fehler > 26: Dann zurück mit CY=0 und Z=0
| |