;CD-Player, der kein MSCDEX braucht! Nur den Hardwaredevicedriver!
include prolog.asm
include "sound.asm"
mov al,0 ;Nummer des gewünschten CDROMs
call OpenCD ;ein paar Parameter einsammeln
jc errm
mov si,ofs MediaCKdo
call myIOCTL
mov di,81h
scancl: mov al,[di]
inc di
call Upcase
cmp al,' '
jz scancl
cmp al,'-'
jz scancl
cmp al,'/'
jz scancl
cmp al,'H'
jz help
cmp al,'?'
jz help
cmp al,'O'
mov si,ofs EjectKdo
jz Kdo
cmp al,'E'
jz Kdo
cmp al,'L'
mov si,ofs LockKdo
jz Kdo
cmp al,'U'
mov si,ofs UnlockKdo
jz Kdo
cmp al,'C'
mov si,ofs CloseKdo
jz Kdo
cmp al,'S'
jz KdoStop
cmp al,'P'
jz KdoPlay ;Ganze Disk abspielen
cmp al,'A' ;stAtus
jz KdoState
cmp al,'I' ;Kurzinfo
jn z,KdoInfo
cmp al,13
jnz scancl
exi: call CloseCD
DOS 4c00h
errm: mov cx,3
call PRINTF
DOS 4c01h
Help: mov cx,2
call PRINTF
jr exi
Kdo: call myIOCTL
jr scancl
KdoStop:
mov ax,850dh ;Länge und Kommando
call myCmd2CD
mov ax,850dh ;Länge und Kommando
call myCmd2CD
jmp scancl
KdoPlay:
mov si,ofs VolsizeKdo
call myIOCTL
jnc kpl1
mov al,18*7 ;7 Sekunden warten (???)
call wait8
mov si,ofs MediaCKdo
call myIOCTL
mov si,ofs VolsizeKdo
call myIOCTL
jnc kpl1
cmp al,0fh ;Disk change?
jz KdoPlay
call axhx ;Fehlernummer zur Diagnose
jmp scancl
kpl1: mov ax,[wo LOW Volsize]
mov [wo LOW ReqHdr.sectors],ax
mov ax,[wo HIGH Volsize]
mov [wo HIGH ReqHdr.sectors],ax
mov ax,132*256+13+9 ;Länge und Kommando
call myCmd2CD
scan01: jmp scancl
KdoState:
call DevStat
jc scan01
mov cx,0
call PRINTF
mov ax,[wo LOW status]
call axhx
mov cx,1
call PRINTF
mov dx,[wo LOW status]
mov cl,3
shl dx,cl
mov cx,13 ;13 Wörter
loo: shl dx,1
sbb ax,ax ;0 oder -1
push ax
loop loo ;13mal
mov cx,5 ;Superstring
call printf ;Nu schaufel mal!
add sp,13*2
jr scan01
KdoInfo:
call DevStat
jc scan01
mov dx,[wo LOW status]
test dh,8 ;CD eingelegt?
call pushnz
test dl,2
call pushnz
test dl,1
call pushnz
mov cx,4 ;String-No.
call PRINTF
add sp,6
jr scan01
pushnz: pop cx
mov ax,0
jz pu1
inc ax
pu1: push ax
jmp cx ;zurück
struc tReqHdr
len db ? ;User-schreibbar
subno db ? ;!!System-Eintrag!!
cmd db ? ;User-schreibbar
stat dw ? ;!!nur zum Rücklesen!!
res db 8 dup (?) ;!!System-reserviert!!
;ab hier zum Manipulieren durch den Anwender
mode db ? ;meist: Adressiermodus
pointer dd ? ;meist ein Zeiger
sectors dd ? ;meist irgendwelche Sektoren
volume dd ? ;ein Volume??
ILS db ? ;Interleave Skip (Maximallänge)
reserve db ? ;für besseres Alignment
ends
alignv 2
DevStrt dd ?
DevIntr dd ?
ReqHdr tReqHdr <>
StatKdo db 5,3,6
Status dd ?
VolsizeKdo db 5,3,8
Volsize dd ?
MediaCKdo db 2,3,9
MediaC db ?
EjectKdo db 1,12,0
LockKdo db 2,12,1,1
UnlockKdo db 2,12,1,0
CloseKdo db 1,12,5
printf: mov bx,1 ;Standardausgabe für 99% der Fälle
proc fprintf ;cx=String-Nummer in String-Ressource
cld ;durchweg
push ax bx cx dx si bx
mov bx,sp
add bx,14 ;wenn NEAR
call iprintf
pop si dx cx bx ax
ret
endp fprintf
proc iprintf ;Innere PRINTF-Routine für Rekursionen
;bx=Stackzeiger (Parameterliste)
;cx=Stringnummer (auf Stack?)
;auf Stack: const Handle
@hand equ <wo bp+4>
entr 20 ;20 Bytes lokale Variablen
@flag equ <by bp-1>
@fill equ <by bp-2>
@case equ <wo bp-4>
@zahl equ <wo bp-6>
@buff equ <bp-20> ;14 Bytes Zahlenpuffer o.ä.
mov [@flag],0 ;rücksetzen
mov si,[StrC] ;Adresse der Kollekion holen (globaler Pointer)
jcxz @@o2
@@l3: lodsb ;String mit Nummer suchen
or al,al
jnz @@l3
loop @@l3
@@o2: mov ah,'%' ;Extra-Terminator
call strout ;liefert al=0, wenn ok beendet.
jc @@e ;bei Fehler
or al,al
jnz @@2 ;wenn '%'
@@e: leav
ret 2 ;Ende mit Allende
@@casz: ;CASE-Anweisung
mov al,[@flag]
test al,80h ;Case-Mode aktiv?
jnz @@c1
mov dx,[ss:bx] ;niemals LONG
inc bx
inc bx
mov [@case],dx
or al,80h
@@c1: or al,40h ;HIDE setzen
mov dx,[@zahl] ;die vorher eingelesene
cmp [@case],dx
@@el: jnz @@c2 ;wenn ungleich (bzw. Bit gesetzt)
and al,not 40h ;HIDE löschen
or al,20h ;ELSE totlegen
@@c2: mov [@flag],al
jmp @@o2 ;weiter im Text
@@else: ;ELSE-Zweig
mov al,[@flag] ;kein Test auf vorangegangenes Case!
or al,40h ;HIDE setzen
test al,20h ;ELSE erlaubt?
jr @@el ;...!!!
@@endc: ;Ende der Case-Anweisung
mov al,0
jr @@c2 ;Flags nullsetzen
@@nums: mov ax,[ss:bx] ;vom Stack!
inc bx
inc bx
@@num1: mov [@zahl],ax
jr @@2a
@@lng: or [@flag],2
jr @@2a
@@nul: mov [@fill],'0'
jr @@2a
@@min: or [@flag],1 ;Minus-Bit setzen
jr @@2a
@@2: ;%-Jokerzeichen
and [@flag],not 0fh ;Joker-Lokal-Flags löschen
mov [@fill],' ' ;Standardfüllzeichen
mov [@zahl],0 ;Standardzahl
@@2a: lodsb ;nächstas Zeichen
cmp al,'-'
jz @@min
cmp al,'0'
jz @@nul
cmp al,'l'
jz @@lng
cmp al,'z' ;num. Parameter auf Stack
jz @@nums
cmp al,'C'
jz @@casz
cmp al,'e'
jz @@else
cmp al,'E'
jz @@endc
test [@flag],40h ;hidden?
jnz @@3
cmp al,'Z' ;Keine anderen Parameter auswerten!
jz @@wech
cmp al,'s'
jz @@str
cmp al,'S'
jz @@nest
cmp al,'c'
jz @@char
cmp al,'i'
; jz @@int
cmp al,'u'
; jz @@unsi
cmp al,'x'
; jz @@hex
cmp al,'X'
; jz @@hex
@@3: dec si
push bx
mov bl,10
call inw2
pop bx
jnc @@num1 ;die Zahl eintragen
jmp @@o2 ;sonst Ausgabe fortsetzen (z.B. %%->%)
@@str: ;normaler String NEAR, ls=String FAR
push ds si
mov si,[ss:bx]
test [@flag],2 ;Long?
jz @@str1 ;Nein.
mov ds,[ss:bx+2] ;ja.
@@str1: ;DS:SI=Stringadresse
call fstrout
pop si ds
jc @@e1 ;Bei Fehler sofort raus!
@@wech: ;hau wech den Parameter
inc bx
inc bx
test [@flag],2 ;Long Parameter?
jz @@w1
inc bx
inc bx
@@w1: jmp @@o2 ;zurück zur Hauptschleife
@@char: ;1 Zeichen ausgeben
mov al,[ss:bx]
mov ah,0
push ds si
LD ds,ss
lea si,[@buff]
mov [si],ax
call fstrout ;Dieses eine Zeichen als String betrachten
pop si ds
jc @@e1
jr @@wech ;Parameter abräumen
@@nest: ;Nested String (Verschachtelt)
mov cx,[@Zahl]
push si
push [@hand]
call iprintf ;Fertig!!
pop si
jnc @@w1 ;von vorn. (KEINE REKURSIONEN BITTE!!)
@@e1: jmp @@e
proc mchars ;Gib [@zahl] Zeichen [@fill] aus!
push ds si
LD ds,ss
lea dx,[@fill] ;DS:SI=SS:BP+??
mov cx,1 ;je 1 Zeichen
@@l: call DOSwrite ;schreiben
jc @@e ;Fehler!
dec [@zahl]
jnz @@l
@@e: pop si ds
ret
endp mchars
proc fstrout ;Formatierte Stringausgabe
;PE: DS:SI=String
; [@zahl]=Anzahl der Zeichen mindestens
; [@fill]=Füllzeichen
; 0[@flag]=Linksbündige Ausgabe
;PA: CY=1: DOS-Fehler, AX=Fehlernummer
xor ah,ah
push si
call strlen ;Länge kalkulieren (nur bis 0 oder lf)
pop si
sub [@zahl],cx
jbe strout0
test [@flag],1 ;Minus=linksbündig?
jz @@right
or al,al ;0 als Abbruch?
jnz strout0
call strout0
jc @@e
call mchars
@@e: ret
@@right: call mchars ;Füllzeichen ausgeben
jc @@e
;ret absichtlich vergessen!
endp fstrout
strout0: mov ah,0
proc strout ;Stringausgabe
;PE: DS:SI: Stringzeiger
; AH: Extra-Terminator ('%' oder 0)
;PA: AL=0: Normaler Terminator
; CY=1: Fehler beim Schreiben, dann AX=DOS-Fehlernummer
; SI zeigt HINTER den Terminator!
;VR: AX SI
;Bem.: Diese Funktion wandelt 0ah in 0dh-0ah
push cx dx
@@o: mov dx,si ;Anfangsadresse
call strlen ;SI ist danach hinter dem Endezeichen
push ax ;Abbruchzeichen merken
call DOSwrite
jc @@e ;zum Fehler-Ende
pop ax
cmp al,0ah
clc
jnz @@e
;DOS-Newline
ifdef olines ;Wenn Zeilenzähler definiert
inc [olines] ;Zeilennummer erhöhen
endif ;!!Probleme mit DS!! Woher denn nehmen??
mov cl,[by nl$] ;im Datensegment wie auch StrC (Resourcezeiger)
mov dx,ofs nl$+1 ;PASCAL-String des Zeilentrenners (kann ja auch 0 sein!)
xor ch,ch ;<=255 Zeichen
push ax ;AH retten
call DOSwrite
jc @@er ;und weiter gehts! (wenn kein DOSenfehler)
pop ax
jr @@o
@@er: pop cx
@@e: pop dx cx
ret
proc DOSwrite ;Schreiben auf BX, wenn BX=0 (stdin) dann in Speicher!
test [@flag],40h ;Hidden? (Unterdrückte Case-Zweige)
jnz @@x
push bx
mov bx,[@hand] ;Handle vom Stack besorgen
;PE: Handle, CX=Länge, Quelladresse DS:DX, ggf. Zieladresse ES:DI
;PA: CY=1: Fehler, dann AX=Fehlernummer (DOS)
ifdef UseMemW
or bx,bx
jz @@mem
endif
DOS 40h ;Schreiben! (gleich ganzen Block)
jc @@e ;DOS-Fehler
cmp ax,cx
mov ax,1 ;Disk full-Fehler (da "unbek. FktNr" Quatsch)
ifdef UseMemW
jr @@e
@@mem:
push si cx
mov si,dx
rep movsb ;Speicherschreiben
pop cx si
endif
@@e: pop bx
@@x: ret
endp DOSwrite
endp strout
proc strlen ;PE: DS:SI=String
;PA: CX=Länge, SI zeigt HINTER den Terminator
mov cx,-1
@@l: lodsb
inc cx
or al,al
jz @@e
cmp al,0ah
jz @@e
cmp al,ah
jnz @@l
@@e: ret
endp strlen
endp iprintf
StrC dw ofs exampl$
nl$: dps 13,10
exampl$:
dz 'Status: ' ;0 ..%X',10
dz 10 ;1
db 'Mini-CD-Ansteuerung (haftmann#software): TESTVERSION, benötigt KEIN MSCDEX',10
db 'Parameter: - h oder ? Diese Hilfe',10
db ' - o oder e CD-Fach öffnen',10
db ' - c CD-Fach schließen',10
db ' - l Fach verriegeln',10
db ' - u Verriegelung aufheben',10
db ' - p Ganze CD abspielen',10
db ' - s Abspiel stoppen',10
db ' - a Komplett-Statusanzeige',10
db ' - i Kurzinfo',10
db 'z.B. CDPL clp = CD einfahren, verriegeln und komplett abspielen',10
db 'oder CDPL suo = (das Gegenteil), CDPL uocococococl = Leute ärgern',10
dz ;2
db 'Kein Hardwaretreiber für CD-Laufwerk %u gefunden',10
dz ;3
db '%11S, %12S, %13S.',10
dz ;4
db '%11S',10
db '%6S%12S',10
db '%10S%0Cnur %7S%e%7S und raw%E',10
db '%0C%8S%9S%e%9S und Schreiben%E',10
db '%0C%8SDaten%eDaten, Audio und Video%E',10
db '%0CKein Interleave%eISO-9660-konform%E',10
db '%Z'
db '%0C%eKein %EKommando-Prefetching',10
db '%0C%eKeine %EAudio-Kanal-Manipulation',10
db 'HSG%0C-%e und Red Book %EAdressierung',10
db '%Z'
db '%13S',10
db '%10S%0C%ekeine %ER-W-Sub-Kanäle',10,10
dz ;5
dz 'Tür ' ;6
dz 'cooked' ;7
dz 'Nur ' ;8
dz 'Lesen' ;9
dz 'unterstützt ' ;10
dz '%6S%0Cgeschloss%eoff%Een' ;11
dz '%0C%eun%Everriegelt' ;12
dz 'CD %0C%enicht %Eeingelegt' ;13
_UPCASE
_AXHX
_WAIT8
_INW2
;CD-Unit, erfordert Variablen im Datensegment namens ReqHdr, DevStrt, DevIntr
DevStat: ;Get Device Status (dword)
mov si,ofs StatKdo
myIOCTL:lodsw
IOCTLIO: ;IOCTL Input/Output
;PE: si: Tabelle, DS im Datensegment, al=Bytes im Puffer
;ah=3 für Input, 12 (dez) für Output
SDS [ReqHdr.pointer],si
mov [by LOW wo LOW ReqHdr.sectors],al ;Länge
mov al,13+13 ;AH ist bereits das Kommando
jr myCmd2CD
CloseCD: ;PE:-
mov ax,14*256+13
proc myCmd2CD ;PE: AL=Länge, AH=Kommando
;oder AX= MEIN Kommandoword
;PA: AX=Return-Code
;Löscht nach Ausführung alle Folgefelder; müssen
;beim nächsten Mal nicht initialisiert werden!
push es bx
mov bx,ofs ReqHdr
mov [bx+tReqHdr.len],al
mov [bx+tReqHdr.cmd],ah
LD es,ds
push cx dx ;sicherheitshalber!!
call [DevStrt]
call [DevIntr]
pop dx cx
mov bx,ofs ReqHdr.stat
mov ax,[bx]
push cx
mov cx,size tReqHdr-3 ;!!Tja, wie berechnet man eine Länge?
@@l: mov [by bx],0 ;Requestheader löschen
inc bx
loop @@l
pop cx bx es
cmp ah,80h
cmc ;CY aus Bit15 ziehen
ret
endp
proc OpenCD ;PE: AL=Nummer; patcht in ReqHdr den Eintrag "sub"
;PA: CY=1: Kein CD-ROM Nummer AL gefunden!
push es bx
DOS 52h ;gültig ab DOS 3.1!!!
add bx,22h ;NUL Device Header
@@l: les bx,[es:bx] ;nächster Devicedriver
cmp bx,0ffffh
jnc @@e ;Ende der Kette! (noch CY=0)
cmp [wo es:bx+10],'SM'
jnz @@l
cmp [wo es:bx+12],'DC'
jnz @@l
mov ah,[by es:bx+15h];Anzahl Devices im Treiber
sub al,ah
jnc @@l ;noch nicht genug
add al,ah ;CY immer 1
mov [ReqHdr.subno],al;Nummer speichern
mov [wo HIGH DevStrt],es
mov [wo HIGH DevIntr],es
mov ax,[es:bx+6]
mov [wo LOW DevStrt],ax
mov ax,[es:bx+8]
mov [wo LOW DevIntr],ax
mov ax,0d0dh
call myCmd2CD ;CD öffnen
stc
@@e: cmc
pop bx es
ret
endp
endc
Detected encoding: OEM (CP437) | 1
|
|