;
; CDP - CD-Player for DOS
;
; (C) 1994 by Henrik Drewelow
; (c) 1996,97 haftmann#software
include prolog.asm
P186
jumps
include "instchk.asm" ;Installations-Check über Int 2F
;Das Programm ist dadurch prinzipiell mehrfach installierbar
BiosKey equ 1
macro CallRet lbl
call lbl
ret
endm
ComEntry: jmp Main ;JMP to Main at bottom of seg
;****************************************
;** Residente Daten für TSR-Verwaltung **
;****************************************
;Festlegungen für INSTCHK.ASM
MUXI db 0 ;Autodetect
AnsCode equ '#P' ;Antwortcode für Int2F
VerCode equ 101h ;Versionsnummer
IntTab: IntEntry 08 ;Interrupttabelle für instchk
IntEntry 09 ;Definiert Nummer, OldIntXX und NewIntXX,
IntEntry 13 ;dadurch problemlose Deinstallation
IntEntry 28 ;auch bei verschobenen Routinen,
IntEntry 2F ;nur die Nummern müssen stimmen
db 0 ;Ende der Liste
; Residenter Code ******************************************************
InDosClr = bit 0 ;InDos=0 at popup time
InInt2F = bit 1 ;MSCDEX wurde gerufen
InInt13 = bit 2 ;BIOS disk I/O
InInt28 = bit 3 ;INT28 handler
In28Call = bit 4 ;we have issued INT28
iPopupRequest = bit 5 ;inverse popup-Anforderung
PoppedUp = bit 6 ;popup routine activated
BPActive = bit 7 ;Hintergrundprozeß aktiv
BitsUnsafe = InInt13 or In28Call or InInt2F or PoppedUp or BPActive
TsrMode db iPopupRequest ;bits for various modes
KeyMode db 0 ;bits for hotkey status
HotKeyOn = bit 2 ;full hotkey pressed
;Bit 3: CDP-Hauptschleife aktiv, Timer darf keine Treiberfunktionen rufen
;Bit 4: Wird vom Int09 bei Break-Codes gelöscht, um Loslassen der
; Spultaste zu erfassen (temporär?)
;Bit 6: BIOS-Tastenauswertung lahmlegen, stattdessen LastScancode benutzen
LastScancode db 0 ;1-Byte-Puffer reicht für CDP!
InDosPtr dd ? ;seg:off of InDos flag
CritErrPtr dd ? ;seg:off of CritErr flag
;==============================================================================
; DATA FOR INT09H HANDLER TO CHECK FOR HOTKEY COMBINATION
;==============================================================================
HotKeyShift db bit 2 + bit 3 ;shift state for popup
HotKey db 19h ;hot key for popup ('P')
;==============================================================================
; DATA FOR INT08H HANDLER TO CHECK FOR POPUP
;==============================================================================
SafeWait db 0 ;count-down for safe popup
MaxWait equ 8 ;wait no more 8/18 sec
;==============================================================================
; PROCESS & SYSTEM DATA
;==============================================================================
OldSP dw 0 ;old stack off
OldSS dw 0 ;old stack seg
;************************************
;** Residente Daten für CD-Spieler **
;************************************
; CD-Device-Driver Request Header Struct
struc tReqHdr
hdrlen db 13 ; Length of request header
subunit db 0 ; Subunit code for minor devices
command db ? ; Command code field
status dw ? ; Status
dum db 8 dup (?) ; Reserved
data db 15 dup (?) ; additional data
ends tReqHdr
; CD-Device-Driver IOCRTL Read/Write Request Header Struct
struc tIOCTRL
hdrlen db 13 ; Length of request header
subunit db 0 ; Subunit code for minor devices
command db 3 ; Command code field
status dw ? ; Status
dum db 8 dup (?) ; Reserved
media db 0 ; Media descriptor byte from BPB
bufptr dd ? ; Pointer to data buffer
buflen dw 16 ; Length of data buffer
dum1 db 6 dup (?) ; Reserved
ends tIOCTRL
; CD-Device IOCRTL Read Request Buffer Struct
struc tIOBuf
Request db ? ; Request code
Data db 15 dup (?) ; additional data
ends tIOBuf
struc tMSF ;Minuten-Sekunden-Frame
f db ?
union
time dw ?
struc
s db ?
m db ?
ends
ends
ends tMSF
; CD-Track Buffer
struc tTrackBuf
nr db ? ; Track number on CD
start tMSF <> ; Start sector
len tMSF <> ; Track sectors
ctrladr db ? ;CTRL+ADR-Byte (auf 8-Byte-Grenze bringen)
ends tTrackBuf
; variables ==========================================================
cddrive dw 0 ; CDROM Drive letter
reqhdr tReqHdr <> ; Request Header
IOCtrl tIOCTRL <> ; IOCRTL Buffer
IOBuf tIOBuf <> ;IOCTRL Data Buffer
tracks tTrackBuf 27 dup (<>) ; CD Audio-Track Buffer
nPlaylist db 27 dup (?) ;normale Playliste
sPlaylist db 27 dup (?) ;gesicherte Originalliste bei Random
ST_WaitDisk equ 0 ;Keine CD im Laufwerk
ST_WaitChange equ 1 ;CD im Laufwerk, aber keine Audiospuren
ST_Ready equ 2 ;CD im Laufwerk mit Audiospuren, eingelesen
ST_Playing equ 3 ; 3 -> playing
ST_NextTrack equ 4 ; 4 -> next track
ST_Pausing equ 5 ; 5 -> pausing
CDPStat db ST_WaitDisk ; CDP Status
QTrack db ? ;Q-Tracknummer
QTimeTrack TMSF <> ;Q-Zeit bezogen auf Spuranfang
QTimeDisk TMSF <> ;Q-Zeit bezogen auf Disk-Anfang
maxdtime TMSF <> ;Zeit aller Titel in der nPlaylist
CurTnoIdx db 0 ;Tracknummer-Index in nPlaylist (0=nichts)
keymodus db 0 ;Bedien- (0) oder Spurtaster (1) fokussiert
KeyFocused db 0 ;Fokussierter Bedientaster
TrackFocused db 1 ;Fokussierte Spur 1-basiert!
k_Play equ 0
k_Pause equ 1
k_Stop equ 2
k_Prev equ 3
k_Succ equ 4
k_Eject equ 5
k_PlayMode equ 6
k_Random equ 7
k_TimeMode equ 8
;LED-Zustände usw. für die einzelnen Tasten (für SetXxxFocus)
KeyLights dw 0 ;Bedientasten-LED's
playmode db 0 ; Mode of playing
;Zufallsgenerator (ist nicht gerade mein Liebling)
RandSeed dd ? ; Random Number
Factor dw 8405h ; Factor for random
;Bildschirm
label CdpScr dword ;Zeiger
dw ofs SCR_MAIN
dw 0 ;Segment (DS) wird vom Hauptprogramm gesetzt
LineIncr db SCR_MAIN_WIDTH ;Zeichen pro Zeile (im Puffer oder auf Schirm)
vid_CurPage db 0 ;aktuelle Bildschirmseite
vid_LeftTop dw 5*256+5 ;Cursorposition linke obere Ecke des Fensters
vid_WidthHeight dw ? ;Größe Bildschirm (für Dragging)
vid_CursS dw 1*256+0 ;Cursorform (shape)
vid_CursP dw 0 ;Cursorposition
vid_graph db 0 ;Grafikmode-Flag sowie Maus
;Bit 0: 1=Grafikmodus, 0=Textmodus
;Bit 1: 0=16 Farben, 1=256 und mehr Farben im Grafikmodus
;Bit 4: 1=Maus vorhanden (bei Installation)
;Sonstiges
timercnt db 0 ; Counter for timer int
wasplaying db 0 ; Key pressed during playing
canedit db 1 ; Set if can add to edit list
locked db 0 ; Flag for locked tray
Strat dd ?
Inter dd ? ;Strategie- und Interrupt-Eintrittspunkt des Treibers
; constants ==========================================================
include "cdpscr.asm"
scr_nodisk: dz 'no disk inserted'
scr_noaudiodisk: dz 'no audio tracks found'
scr_locked: dz 'disk tray is locked'
scr_clear: dz ' '
scr_mode: dz 'cont '
dz 'edit '
dz 'scan '
dz 'single'
scr_help: dz 'start play '
dz 'pause play '
dz 'stop play '
dz 'prev. track'
dz 'next track '
dz 'eject/close'
dz 'play mode '
dz 'random play'
dz 'time format'
dz 'resume play'
dz 'cont. play '
dz 'play track '
dz 'sel. track '
;Farbtabelle (12 verwendete Farben)
Colors db 01h ;Rand blau auf schwarz
db 1Bh ;Rahmen helltürkis auf blau
db 00h ;Unsichtbare Zahlen schwarz auf schwarz
db 0Bh ;Betriebsart, aktuelle Spur und Zeitangaben
;---
db 01h ;Sichtbare Zahlen
db 10h ;Fokussierte Zahlen
db 03h ;Hervorgehobene (ausgewählte) Zahlen (normal!)
db 30h ;Hervorgehoben und fokussiert
;---
db 70h ;Taste schwarz auf weiß
db 30h ;Fokussierte Taste
db 7Ah ;Hervorgehobene Taste
db 3Ah ;Hervorgehobene und fokussierte Taste
;***************************************
;** TSR-Verwaltungsroutinen, resident **
;***************************************
;==============================================================================
; TestSafe - CHECK IF THIS IS A SAFE TIME TO DO A POP UP
;
; RETURN CLC IF SAFE TO POP UP, CY IF NOT SAFE.
;
; CHECK IF WE ARE IN AN OUR OWN INT28 CALL (In28Call)
; CHECK 8259A PIC ISR REGISTER FOR MISSING EOIs
; CHECK IF DOS IS STABLE FOR POP UP
; CHECK IF A PRINT SCREEN IS IN PROGRESS
;==============================================================================
; DS muß aufs Datensegment zeigen!
;VR: AX,BX,Flags
proc TestSafe near
; ------------ CHECK THE 8259A PIC ISR REGISTER FOR NON-EOIed HW INTs
mov al,00001011b ;tell 8259A we want the ISR
out 20h,al ;8259A command reg
jmp $+2 ;now, ISR should be ready
in al,20h ;AL=mask of active INTs
or al,al ;test all (IRQ0 *did* EOI)
jnz @@NotSafe ;jump if active INTs
; ------------ NOW, ENSURE THAT DOS WAS NOT INTERRUPTED
push ds
lds bx,[InDosPtr] ;now, DS:BX=InDos
mov al,[by bx] ;get InDos to AL
lds bx,[cs:CritErrPtr] ;now, DS:BX=CritErr
or al,[by bx] ;both flags zero?
pop ds
jz @@Safe? ;YES - DOS is really idle
BTST [TsrMode],InInt28 ;is this an INT28h
jz @@NotSafe ;NO - not safe, should be idle
cmp al,1 ;YES - one InDos entry only?
ja @@NotSafe ;NO - jump if more than one
@@Safe?:
; ------------ CHECK TO SEE IF A PRINT SCREEN IS IN PROGRESS
push ds
LD ds,50h
cmp [by 0],1 ;print screen in progress?
pop ds
je @@NotSafe ;YES - jump if prtsc
; ------------ SEEMS TO BE A SAFE TIME FOR POPUP
clc ;CLC=safe to popup
jr @@e ;end this then
; ------------ APPARENTLY THIS IS JUST NOT THE TIME TO DO A POPUP
@@NotSafe: stc ;CY=don't popup now
; ------------ RETURN TO CALLER WITH CARRY SET/CLEAR
@@e: ret
endp TestSafe
;Testet, ob Fenster erscheinen soll, und läßt es ggf. erscheinen.
;Testet dabei das Bit PopupRequest, und setzt bei Stackumschaltung PoppedUp
;VR: Flags
proc CheckRequest
BTST [cs:TSRMode],iPopupRequest or BitsUnsafe
jnz @@e ;weder Anforderung noch Erlaubnis
sti
push ax bx ds
LD ds,cs
call TestSafe ;InDOS usw. sagt OK?
jc @@e1 ;nein, nicht aufpoppen!
BSET [TSRMode],PoppedUp or iPopupRequest
mov bx,ofs Popup ;Popup-Routine soll angesprungen werden
call InitPopup
mov [TimerCnt],0 ;Nicht gleich anschließend Hintergrundprozeß
BRES [TSRMode],PoppedUp
@@e1: pop ds bx ax
@@e: ret
endp
;Testet, ob Hintergrundarbeit gestartet werden kann. Das erfolgt
;etwa halbsekündlich, um Rechenleistung zu schonen
;VR: Flags
proc CheckBackground
inc [cs:TimerCnt]
cmp [cs:TimerCnt],9
jc @@e ;raus, zu wenig Zeit ist vergangen
BTST [cs:TSRMode],BitsUnsafe
jnz @@e ;keine Erlaubnis
sti
push ax bx ds
LD ds,cs
call TestSafe ;InDOS usw. sagt OK?
jc @@e1 ;nein, nicht aufpoppen!
BSET [TSRMode],BPActive
mov bx,ofs CDPTimer ;Timer-Routine soll angesprungen werden
call InitPopup
mov [TimerCnt],0 ;hier erst zurücksetzen
BRES [TSRMode],BPActive
@@e1: pop ds bx ax
@@e: ret
endp
ret
;==============================================================================
; OurInt08 - TSR INT08H HANDLER TO WATCH FOR HOTKEY AND SAFE POPUP TIMES
;
; CALL OldInt08
; CHECK FOR RE-ENTRANCE INTO CRITICAL INT08 CODE
; SET InInt08 FLAG
; CHECK IF HOTKEY WAS PRESSED
; CHECK IF ALREADY InPopup OR InInt28
; CHECK IF SAFE TIME FOR SYSTEM TO POPUP
; UPDATE FLAGS AND CALL POPUP IF SAFE
; GIVE ERROR BEEP IF POPUP WAS UNSAFE FOR A LONG TIME
; RESET InInt08 FLAG
; DO IRET
;==============================================================================
proc NewInt08 far
pushf ;simulate INT08
call [cs:OldInt08] ;call TSRs loaded before us
call CheckRequest ;Popup-Fenster aufrufen, wenn erforderlich
call CheckBackground ;Hintergrund-Routine starten, wenn Zeit um
iret
endp
;==============================================================================
; OurInt09 - TSR INT09H HANDLER TO WATCH FOR HOTKEY
;
; COMPARE FOR KEY MATCH
; SET HotKeyOn IF HOTKEY PRESSED
; Tastendruck selbst verschlucken
; DO IRET
; else JMP OldInt09
;==============================================================================
proc ClearKey
in al,61h ;Zeichen abholen (!!)
; mov ah,al
BSET al,bit 7
out 61h,al ;Bit 7[61h] setzen
; xchg al,ah
BRES al,bit 7
out 61h,al ;auf alten Wert zurück
mov al,61h ;EOI spezifisch IRQ1
out 20h,al
ret
endp
proc NewInt09 far
push ds ax ;save regs used
LD ds,40h ;BIOS-Datensegment
mov al,[17h] ;Shift-Byte
LD ds,cs
BTST [KeyMode],bit 6 ;Kein BIOS-Zugriff?
jnz @@nobios
BTST [TSRMode],PoppedUp ;Sichtbar oder im Aufbau?
jnz @@ToOld ;ja, nicht noch einmal aufpoppen!
BTST al,bit 0 ;RightShift gedrückt?
jz @@1
BSET al,bit 1 ;LeftShift drücken (keine Unterschiede machen)
@@1: not al ;Bits drehen
and al,[HotKeyShift]
jnz @@ToOld ;und wegspringen
in al,60h
cmp al,[HotKey] ;Unsere heiße Taste?
jnz @@ToOld
call ClearKey ;Tastaturpuffer leeren
BRES [TSRMode],iPopupRequest ;aufpoppen?
pop ax ds
call CheckRequest ;sollte kein Register ändern...
iret ;zurück
@@nobios:
in al,60h ;Al=key, preserved by BIOS
cmp al,0E0h ;Präfix-Code erweiterte Taste?
jz @@3 ;gleich "wegwerfen"
BTST al,bit 7 ;Loslaß-Code?
jz @@2
BRES [KeyMode],bit 4 ;Flag löschen für Spulknöpfe
jr @@3 ;und Loslaß-Code nicht speichern
@@2: mov [LastScancode],al
@@3:
ifndef BIOSKEY
call ClearKey
pop ax ds
iret
endif
@@ToOld:
pop ax ds
jmp [cs:OldInt09] ;weiter mit altem Handler
endp NewInt09
proc NewInt13 far
pushf ;save flags we use
BSET [cs:TsrMode],InInt13 ;remember we are in BIOS now
popf ;restore flags
pushf ;simulate INT13
call [cs:OldInt13] ;let BIOS handle it all
pushf ;BIOS uses flag return
BRES [cs:TsrMode],InInt13 ;tell people we left INT13h
call CheckRequest ;aufpoppen, wenn möglich
popf
sti
retf 2 ;throw flags off stack
endp NewInt13
proc NewInt28 far
BSET [cs:TSRMode],In28Call or InInt28;tell'em we are here
pushf
call [cs:OldInt28] ;call TSRs loaded before this
BRES [cs:TSRMode],In28Call
call CheckRequest
BRES [cs:TSRMode],InInt28
iret ;we have nothing more to say
endp
proc NewInt2F far
pushf
cmp ah,15h ;MSCDEX/NWCDEX-Funktion wird gerufen
je @@a ;ja, Semaphor aufbauen
cmp ah,[cs:MUXI] ;Installationstest-Funktion?
je @@t ;ja
popf
jmp [cs:OldInt2F] ;Nur anspringen, da einige andere Int2F-
;Funktionen Stack-Parameterübergabe praktizieren
@@t:
popf
or al,al
jnz @@e
MuxResponse ;Makro aus INSTCHK.ASM, Antwort-Code erzeugen
@@e: iret
@@a:
BSET [cs:TSRMode],InInt2F
popf
pushf
call [cs:OldInt2F] ;MSCDEX rufen
pushf
BRES [cs:TSRMode],InInt2F
call CheckRequest ;Prüfen, ob nicht etwas zu tun ist
popf
sti
retf 2
endp
;Aufruf mit DS=CS; AX und Flags gerettet, BX=Ansprungadresse, Interrupt frei
;Routine darf niemals verschachtelt gerufen werden, da Benutzung desselben
;Stacks. Die Prüfung geschieht außerhalb.
proc InitPopup
mov [OldSS],ss ;save current stack frame
mov [OldSP],sp
LD ss,ds
mov sp,102h ;Kommandozeile muß als Stack herhalten
; ------------ SAVE ALL REGS
pusha
push es
; ------------ TAG VALUE OF InDos FLAG AT TIME OF POPUP
les si,[InDosPtr] ;now, ES:[SI]=InDos
cmp [by es:si],1 ;InDos set? (>2 impossible)
jnc @@1 ;NO - jump if all clear DOS
BSET [TsrMode],InDosClr ;InDos war 0
@@1:
cld ;!! Klare Verhältnisse !!
LD es,ds
call bx ;Aufruf!
BRES [TsrMode],InDosClr
; ------------ RESTORE USER REGS
pop es
popa
mov ss,[OldSS] ;restore SS
mov sp,[OldSP] ;restore SP
ret
endp InitPopup
;***********************************
;***********************************
;** Residente CD-Spieler-Routinen **
;***********************************
;***********************************
; library procedures -------------------------------------------------
_ANUM
_OCHR
_ALDEZ
_CASE
macro PrintXY x:req,y:req,str:rest
ifnb <str>
lea si,[str]
endif
mov dx,y*256+x
call PrintScr
endm
tick dw 0
proc ErrBeep
push es
ld es,40h
mov ax,[es:6Ch]
S1: cmp [es:6Ch],ax
je S1 ;wait till clock tick changes
inc ax
mov [tick],ax
mov al,0B6h
out 43h,al ;get timer ready
mov ax,0C00h
out 42h,al
mov al,ah
out 42h,al ;set freq
in al,61h
or al,3
out 61h,al ;turn speaker on
mov ax,[tick]
S2: cmp ax,[es:6Ch]
je S2 ;do for one clock tick
in al,61h ;turn off speaker
and al,11111100b
out 61h,al
pop es
ret
endp ErrBeep
;*******************************
;** Aufruf des Gerätetreibers **
;*******************************
RequestLux: ;Luxusvariante mit AH=Code und AL=Kopflänge
mov [ReqHdr.hdrlen],al
mov [ReqHdr.command],ah
; Performs a driver request
;
; Return : al -> 0 - ok
; 1 - busy
; 2 - error ah -> error code
;Puffer ist fest auf ReqHdr gestellt!
proc Request
push es bx ;Verwendete Register retten
lea bx,[ReqHdr]
DoRequest:
LD es,ds
call [Strat]
call [Inter]
; push cx
; mov cx,[cddrive]
; MUX 1510h ; Pass to mscdex
; pop cx
pop bx es
;läuft durch zu CheckReturn!
endp Request
; Checks Driver request return code
;
; Return : al -> 0 - ok CY=0
; 1 - busy CY=0
; 2 - error ah -> error code CY=1
proc CheckReturn
mov ax,[IOCTRL.status]
BTST ax,bit 15
jnz @@error
BTST ax,bit 9
jnz @@busy
xor ax,ax
ret
@@busy:
mov ax,1
ret
@@error:
mov ah,al
BRES ah,bit 7
mov al,2
stc
ret
endp CheckReturn
IOCTRLReadLux: ;Luxusvariante mit AH=Code und AL=Pufferlänge
mov [by LOW IOCTRL.buflen],al ;Hi-Word ist sowieso immer 0
mov [IOBuf.request],ah
; Performs a IOCTRL Read request
;
; Return : al -> 0 - ok
; 1 - busy
; 2 - error ah -> error code
;Puffer sind fest auf IOCtrl und IOBuf gestellt
proc IOCTRLRead
push es bx
lea bx,[IOCTRL]
mov [(TIOCTRL bx).command],3 ; Set up for read
jmp DoRequest
endp IOCTRLRead
IOCTRLWriteLux: ;Luxusvariante mit AH=Code und AL=Pufferlänge
mov [by LOW IOCTRL.buflen],al ;Hi-Word ist sowieso immer 0
mov [IOBuf.request],ah
; Performs a IOCTRL Write request
;
; Return : al -> 0 - ok
; 1 - busy
; 2 - error ah -> error code
;Puffer sind fest auf IOCtrl und IOBuf gestellt
proc IOCTRLWrite
push es bx
lea bx,[IOCTRL]
mov [(TIOCTRL bx).command],12 ;Schreiben
jmp DoRequest
endp IOCTRLWrite
;******************************************
;** Einfache CDROM-Gerätetreiberzugriffe **
;** (ohne Zugriff auf CD-Tabellen) **
;******************************************
; Gets the device status
;
; Return : dx:cx -> Status
proc getdevicestatus
mov ax,0605h
call IOCTRLReadLux
lea si,[IOBuf.data]
mov cx,[si]
mov dx,[si+2]
ret
endp getdevicestatus
; Eject tray
;
proc Eject
mov ax,0*256+1
CallRet IOCTRLWriteLux
endp Eject
; Close tray
;
proc CloseTray
mov ax,5*256+1
CallRet IOCTRLWriteLux
endp CloseTray
; Checks if media was changed ( not if drive busy !!! )
;
; Return : carry set -> media changed
; carry not set -> media not changed
proc mediachanged
mov ax,0902h
call IOCTRLReadLux
mov al,[IOBuf.Data]
add al,1
ret
endp mediachanged
; Checks if a CD is inserted
;CY=1: keine CD im Laufwerk, dann CDPStat:=0
proc checkdisk
call getdevicestatus ; Get drive status
BTST cx,bit 11
jz @@DiskInserted
mov [CDPStat],0
stc
@@DiskInserted:
ret
endp checkdisk
; Checks if the tray is locked
;
; Return : carry set -> tray locked
; carry not set -> tray not locked
proc checktray
call getdevicestatus ; Get drive status
BTST cx,bit 1
jnz @@notl
stc
@@notl:
ret
endp checktray
; Stop playing
;
proc Stop
mov ax,133*256+13
CallRet RequestLux
endp Stop
; Continue playing
;
proc Continue
mov ax,136*256+13
CallRet RequestLux
endp Continue
;Ein "Stückchen" CD abspielen (zum CUE-Spulen wichtig)
;PE: AH:AL:DL=Startposition
; CH:CL:DH=Länge
;VR: ziemlich alle
;Vorher wird immer ein Stop-Kommando abgesetzt.
proc PlayPiece
LD es,ds
push cx ax ;CX bewußt ganz unten
call Stop ;erforderlich, falls CD gerade spielt
lea di,[reqhdr.data]
xor al,al
stosb ;Adressiermodus LBN (High Sierra)
pop ax
push dx ;DH retten
call lbn ;in LBN (High Sierra) umrechnen
sub ax,150 ;2 Sekunden abziehen
stosw ;LBN Lo-Word
xchg ax,dx
sbb ax,0 ;abziehen lt. Gleichung
stosw ;LBN Hi-Word
pop dx
xchg dl,dh
pop ax ;...was vorher CX war
call lbn ;in LBN (High Sierra) umrechnen
stosw ;LBN Lo-Word
xchg ax,dx
stosw ;LBN Hi-Word
mov ax,132*256+22
call RequestLux ;PLAY-Request
ret
endp
;***************************
;** (Um)Rechnungsroutinen **
;***************************
;Zeitdifferenz berechnen
;PE: AH:AL:DL: MSF Minuend, CH:CL:DH: MSF Subtrahend
;PA: AH:AL:DL: MSF Differenz, CY=1: Negatives Ergebnis
proc Diff
sub dl,dh
jnc @@1
add dl,75 ;Rahmen pro Sekunde
@@1: sbb al,cl
jnc @@2
add al,60 ;Sekunden pro Minute
@@2: sbb ah,ch
jnc @@3
add ah,60 ;Carry bleibt i.d.R.
@@3: ret
endp
;Zeitsumme berechnen
;PE: AH:AL:DL: MSF Akku, CH:CL:DH: MSF Summand
;PA: AH:AL:DL: MSF Akku
proc Sum
add dl,dh
cmp dl,75 ;Rahmen pro Sekunde
jc @@1 ;Wenn kleiner, dann KEIN Übertrag
sub dl,75 ;(Carry unverändert)
@@1: cmc ;Carry ist immer verkehrtherum, daher drehen!
adc al,cl
cmp al,60
jc @@2
sub al,60 ;Sekunden pro Minute
@@2: cmc
adc ah,ch
ret
endp
;Zeitangaben von MSF (Red Book) nach LBN (High Sierra) umrechnen
;PE: AH:AL:DL: Angabe in MSF
;PA: DX:AX: Angabe als LBN (Futter für PlayAudio-Funktion)
;VR: AX,DX,Flags
;Es erfolgt hier keine Korrektur auf Diskanfang (sub 150)!
proc lbn
push cx
mov cl,dl ;Rahmen retten
xor ch,ch ;auf 16 bit erweitern, später verwenden
mov dh,al ;Low-Teil retten
mov al,60 ;Multiplikation vorbereiten
mul ah ;AX=Sekunden der Minutenangabe
add al,dh ;Sekunden dazu
adc ah,0 ;AX=volle Sekunden
mov dx,75 ;Rahmen pro Sekunde
mul dx ;DX:AX=Rahmen der Minuten- und Sekundenangabe
add ax,cx ;Rahmen dazu
adc dx,0 ;LBN ist fertig.
pop cx
ret
endp
;Luxusvariante - bei EDIT-Modus erfolgt nur eine Indirektion!
;(wichtig für die korrekte Anzeige)
proc GetAdrOfIdxLux
cmp [PlayMode],1
je @@1
;PE: AL=Track-Index
;PA: AX=Zeiger in tracks-Liste (doppelte Indirektion!)
;Kein Gültigkeitstest, außer AL=0 liefert [tracks]
GetAdrOfIdx:
or al,al
jz @@1 ;Nicht umrechnen (das Längenbyte ist kein Index)
push bx
lea bx,[nPlaylist]
xlatb ;Index verrechnen
pop bx
@@1: mov ah,size TTrackBuf ;Einzelelement
mul ah ;AX=Differenz zum Anfang
add ax,ofs tracks
ret
endp
;PA: AL=Höchste angezeigte Display-Tracknummer (je nach Edit-Modus)
proc GetMaxDisplayTrack
mov al,[nPlaylist]
cmp [PlayMode],1
jne @@e
mov al,[tracks.nr]
@@e: ret
endp
;Zeit von Trackindex BL bis (einschließlich) BH berechnen
;BL und BH müssen gültig sein, es erfolgt kein Test!
;(jedoch bei BL>BH kommt die Zeit 0 heraus)
;PE: BL: Trackindex "von", BH: Trackindex "bis"
;PA: AH:AL:DL: Zeitsumme
;VR: AX,DL,BL,CX,SI
;Bem.: AH:AL:DL enthält in der Schleife die zu summierende Zeit
proc CalcTimeFromTo
xor ax,ax
mov dl,al ;Zeit-Akku nullsetzen
jr @@foot
@@l:
xchg si,ax ;AX retten
mov al,bl
call GetAdrOfIdx
xchg ax,si ;AX holen und Indexregister benutzen
mov dh,[(TTrackBuf si).len.f]
mov cx,[(TTrackBuf si).len.time]
call Sum
inc bl
@@foot:
cmp bh,bl ;BL größer?
jnc @@l ;nein, Schleifenrunde drehen
ret
endp
; Calculates time of all tracks in play list
;
; * Setzt MaxDTime auf die Zeitsumme
proc CalcTLTime
mov bl,1 ;von Spur 1
mov bh,[nPlaylist] ;bis zur letzten
call CalcTimeFromTo
mov [maxdtime.f],dl
mov [maxdtime.time],ax
ret
endp CalcTLTime
;********************************
;** High-Level-Treiberzugriffe **
;** (mit Zugriff auf Tabellen) **
;********************************
; Get the q-channel info
;PA: AX: Returncode von IOCTLRead (also 1 für "busy", sonst andere Werte)
proc GetQChannel
mov [IOBuf.data],1 ;Binär bitte!
mov ax,12*256+11
call IOCTRLReadLux
push ax
mov si,ofs IOBuf.data+1
lodsb ;Achtung! - immer BCD!
mov ah,al
shr ah,4
and al,0fh
aad ;deshalb binär wandeln (mit AAD!)
mov [QTrack],al
lodsw ;al verwerfen
mov [QTimeTrack.m],ah ;Minute
lodsw
mov [QTimeTrack.s],al ;Sekunde
mov [QTimeTrack.f],ah ;Rahmen
lodsw
mov [QTimeDisk.m],ah
lodsw
mov [QTimeDisk.s],al
mov [QTimeDisk.f],ah ;Alles einzeln, weil Bytes verdreht
pop ax
ret
endp GetQChannel
; Read in track data
;PA: CY=1: IOCTL-Fehler
;Das Feld "tacks" beinhaltet im Element 0 Startzeit und Länge der CD
;sowie die Anzahl der vorhandenen Audiospuren;
;die übrigen Elemente enthalten die tatsächliche Spurnummmer sowie
;Startzeit und Länge der Spur
;Alle Angaben im binärkodierten MSF (Red Book) Format
;Besseres Vorgehen:
;* Disk-Info einlesen, Disklänge merken
;* Datenspur-Flag:=TRUE
;a Spur-Info lesen
;* Datenspur-Flag=TRUE ? goto b
;* Differenz zum Anfang der vorhergehenden Spur berechnen
;* Errechnete Differenz bei vorhergehender Spur speichern
;b aktuell Datenspur ? Datenspur-Flag:=TRUE; goto c
;* Aktuellen Spur-Anfang eintragen
;* Datenspur-Flag:=FALSE
;c Noch nicht letzte Spur ? goto a (Schleife)
;* Datenspur-Flag=TRUE ? goto d
;* Differenz Disklänge zu Anfang vorhergehender Spur berechnen
;d
;Also keine ganz einfache Sache
; (deswegen war das Ursprungsprogramm hier verwirrend programmiert)
proc ReadInTrackData
mov ax,10*256+7 ;Disk-Info einlesen
call IOCTRLReadLux
jc @@e1 ;Fehler!
lea si,[IOBuf.data]
lodsb ;Kleinste Tracknummer
mov bl,al
lodsb ;Größte Tracknummer
mov [tracks.start.f],al ;als Puffer mißbrauchen!
mov [tracks.nr],0 ;Anzahl Audiospuren mitzählen
lodsb ;Lead-Out-Track (Erster Nicht-mehr-Track) LOW
mov [tracks.len.f],al
lodsw ;-"- HIGH
mov [tracks.len.time],ax
mov bh,40h ;Datenspur-Flag in BH setzen
lea di,[tracks+size TTrackBuf]
jr @@foot ;WHILE-Schleife realisieren
@@everytrack:
mov [IOBuf.data],bl ;aktuelle Spur-Nummer
mov ax,11*256+7 ;Spur-Info einlesen
call IOCTRLReadLux
@@e1: jc @@e ;Fehler!
test bh,40h ;Letzte Spur war Datenspur?
jnz @@1 ;ja, Sprung
cmp [tracks.nr],26 ;26 Audiospuren bereits gefunden?
jae @@4 ;Nur noch Länge zum Ende berechnen
;Schluß machen, die übrigen Spuren werden auf Nr. 26 zusammengefaßt
;in der Hoffnung, daß es alles (abspielbare) Audiospuren sind.
mov dl,[(by IOBuf.data)+1] ;Zeitdifferenz berechnen
mov ax,[(wo IOBuf.data)+2] ;AH:AL:DL = Minuend
call Diff ;AH:AL:DL := AH:AL:DL - CH:CL:DH
mov [(TTrackBuf di).len.f],dl
mov [(TTrackBuf di).len.time],ax
add di,size TTrackBuf ;müßten 7 Bytes sein
@@1:
mov dh,[(by IOBuf.data)+1]
mov cx,[(wo IOBuf.data)+2] ;CH:CL:DH = Startpukt neue Spur
mov bh,[(by IOBuf.data)+5] ;neues CTRL+ADR-Byte
test bh,40h
jnz @@2
inc [tracks.nr] ;Noch eine Audiospur!
mov [(TTrackBuf di).nr],bl ;Wahre Tracknummer aufheben
mov [(TTrackBuf di).start.f],dh
mov [(TTrackBuf di).start.time],cx
mov [(TTrackBuf di).ctrladr],bh ;für später zur Anzeige aufheben
@@2:
inc bl
@@foot:
cmp bl,[tracks.start.f] ;Merker für letzte Spur
jbe @@everytrack ;bis kleiner/gleich
;Ende der Schleife
test bh,40h ;Letzte Spur war Datenspur?
jnz @@3 ;ja, Sprung
@@4:
mov dl,[tracks.len.f] ;nein: Zeitdifferenz berechnen!
mov ax,[tracks.len.time] ;AH:AL:DL = Minuend
call Diff ;AH:AL:DL := AH:AL:DL - CH:CL:DH
mov [(TTrackBuf di).len.f],dl
mov [(TTrackBuf di).len.time],ax
@@3:
mov dl,[tracks.len.f]
mov ax,[tracks.len.time]
mov cx,2 ;die übliche CD-Startzeitangabe
mov dh,ch ;(immer 00:02:00)
call Diff ;AH:AL:DL := AH:AL:DL - CH:CL:DH
mov [tracks.start.f],dh
mov [tracks.start.time],cx
mov [tracks.len.f],dl
mov [tracks.len.time],ax
@@e: ret
endp
;Universelle Routine "PlayPieceOfCurTrack" muß her!
;PE: AH:AL:DL=Startzeit relativ zum aktuellen Track
; CH:CL:DH=Länge höchstens zu spielen
;PA: CY=1: Startzeit zu hoch
; Play a track
;
; Input : bl -> index in tracks
;BL=0 spielt die ganze CD ab (nur OK, wenn keine Datenspuren drauf sind)
;BH=1: Nur "scannen" (die ersten 10 Sekunden anspielen)
proc PlayScan
mov bh,1
jr PlayScan1
endp
proc Play
xor bh,bh
PlayScan1:
lea si,[tracks]
mov al,size tTrackBuf
mul bl
add si,ax ;Adresse im Feld ermittelt
mov dl,[(TTrackBuf si).start.f]
mov ax,[(TTrackBuf si).start.time]
mov dh,[(TTrackBuf si).len.f]
mov cx,[(TTrackBuf si).len.time]
or bh,bh
jz @@1 ;Ganz spielen
cmp cx,10 ;10 Sekunden (und keine Minuten)?
jc @@1 ;Titel ist kürzer, nichts tun
mov cx,10
mov dh,ch ;nur 10 Sekunden ansetzen
@@1:
call PlayPiece
mov [CDPStat],3
ret
endp Play
;***************************
;** Bildschirm-Funktionen **
;***************************
proc SwapCursor
mov bh,[vid_CurPage]
VID 3 ;Cursor ermitteln
xchg [vid_CursS],cx
xchg [vid_CursP],dx
VID 1 ;Cursorform setzen
VID 2 ;Cursorposition setzen
ret
endp
; Swap the main screen of CDP and the old data
;
proc SwapMainScreen
push es
lea si,[SCR_MAIN]
mov dx,0*256+0
@@l1:
call CalcAdr
mov cx,SCR_MAIN_WIDTH ; Cols
@@l2:
lodsw
xchg [es:di],ax
mov [si-2],ax
add di,2
loop @@l2
inc dh ;nächste Zeile
cmp dh,SCR_MAIN_DEPTH
jnz @@l1
pop es
ret
endp SwapMainScreen
proc CalcAdr ;Adresse ES:DI aus Cursorposition DX berechnen
;PE: DX=Cursorposition
;PA: ES:DI=Adresse
; zeigt entweder im das Programm-Image (wenn nicht aufgepopt oder
; Grafikmodus, also ES=DS und DI=offset TheDrawImage)
; oder in den Video-Speicher (aufgepopt im Textmodus)
;VR: ES,DI,Flags
push ax
mov al,dh
mul [LineIncr] ;AX=Zeile mal Zeichen/Zeile
add al,dl ;Spalte dazu
adc ah,0
add ax,ax ;Verdoppeln
les di,[CdpScr] ;Anfangsadresse
add di,ax ;Jetzt wirkliche Adresse
pop ax
ret
endp CalcAdr
proc PrintScr ;Zeichenkette ausgeben, Farbbytes bleiben
;PE: SI: (Nullterminierter) String
; DX: Cursorposition DH=Zeile, DL=Spalte
push es di cx
call CalcAdr
xor cl,cl
jr @@1
@@l: stosb
inc cl
inc di
@@1: lodsb
or al,al
jnz @@l ;Nächstes Zeichen
call Redraw
pop cx di es
ret
endp
;Ab Cursorposition vorhandene Zeichen mit neuer Farbe versehen
;PE: DX: Cursorposition
; CL: Anzahl Zeichen
; CH: neues Farbbyte
proc TouchColor
push es di ax cx
mov al,ch
xor ch,ch
jcxz @@e
call CalcAdr
mov ah,cl
@@l:
inc di
stosb
loop @@l
mov cl,ah ;Anzahl herstellen
call Redraw
@@e: pop cx ax di es
ret
endp
;So simpel diese Routine auch klingt, so kompliziert ist sie.
;PE: DX: Cursorposition Zeile (DH) und Spalte (DL)
; AX: Zeichen (AL) und Attribut (AH)
;Es erfolgt keine Ausgabe, wenn das Zeichen außerhalb liegt
proc PutChar
cmp dl,[by LOW vid_WidthHeight]
jnc @@e
cmp dh,[by HIGH vid_WidthHeight]
jnc @@e
push cx bx
mov bh,[vid_CurPage]
mov bl,ah ;Farbbyte retten
VID 2 ;Cursor positionieren
mov cx,1 ;Nur 1 Zeichen!
BTST [vid_Graph],bit 1 ;256-Farben-Flag?
jnz @@256
BTST [vid_Graph],bit 2 ;40-Spalten-Text-Flag?
jnz @@16 ;Einfach Zeichen ausgeben
mov ah,bl ;Farbbyte zurück
push ax
shr bl,4 ;Hintergrundfarbe als Vordergrundfarbe anbieten
VID 9,'█' ;Vollcursor in Hintergrundfarbe (Codepage 437 und 850)
pop ax
xor bl,ah ;Vordergrundfarbe als XOR-Wert
and bl,0fh ;Hintergrndfarbe ausmaskieren
or bl,80h ;XOR-Bit setzen
jr @@16
@@256: mov bh,bl
shr bh,4 ;Hintergrundfarbe nach BH
and bl,0fh
@@16: VID 9 ;1 Zeichen mit V-Farbe (und Anzahl) schreiben
pop bx cx
@@e: ret
endp
;Grafikbildschirm aktualisieren (ab CGA)
;Diese Routine tut bei gelöschtem Grafikflag nichts
;PE: DX: Cursorposition
; CL: Zeichenzahl
;VR: ES(=DS),DI
proc Redraw
push cx
BTST [vid_Graph],bit 0
jz @@e
xor ch,ch
jcxz @@e
push bx dx si
call CalcAdr ;haben wir ES:DI als Quelladresse(!)
xchg si,di
add dl,[by LOW vid_LeftTop] ;Linke obere Ecke des Fensters
add dh,[by HIGH vid_LeftTop]
@@l:
lodsw
call PutChar
inc dl ;Nächste Spalte
loop @@l
pop si dx bx
@@e: pop cx
ret
endp Redraw
;Grafikfenster löschen (beim Drücken von ESC schwarzes Loch hinterlassen)
;VR: ES,DI,si
proc RemoveWindow
push bx cx dx
mov bh,[vid_CurPage]
xor bl,bl ;Farbe schwarz
mov dx,[vid_LeftTop] ;globale Koordinaten!
mov cx,SCR_MAIN_DEPTH ;Zeilenzahl
mov si,SCR_MAIN_WIDTH
cmp dl,-3 ;Sonderfall, Extrawurst
jnz @@l
mov dl,0
mov si,[vid_WidthHeight] ;wirkliche Breite nehmen
and si,0ffh ;nur Low-Teil
@@l: push cx
VID 2 ;Cursorposition setzen
mov cx,si ;selten: sinnvolle Verwendung für CX
VID 9,' ' ;Zeile löschen
pop cx
inc dh
loop @@l
pop dx cx bx
ret
endp RemoveWindow
;Anzeige des CDP-Fensters. LineIncr sowie der CdpScr-Zeiger müssen stimmen.
;(Ausnahme Textmodus: Offsetanteil von CdpScr wird anhand der Cursorposition
;(vid_LeftTop) neu berechnet). Fürs Dragging vorgesehen.
proc ShowWindow
BTST [vid_Graph],bit 0
jnz @@noswap1
mov dx,[vid_LeftTop]
mov al,[LineIncr]
mul dh ;AX=Zeile mal Zeichen/Zeile
xor dh,dh
add ax,dx ;Spalte dazu
add ax,ax ;Verdoppeln wegen Attributbyte
push es
LD es,40h
add ax,[es:4eh] ;Startoffset aktive Seite noch dazu
pop es
mov [wo LOW CdpScr],ax ;wirklicher bzw. neuer Anfang
jmp swapmainscreen ;PopUp CDP !!!
@@noswap1:
xor dx,dx
@@g4: mov cl,SCR_MAIN_WIDTH
call Redraw ;Jede Zeile einzeln auf Schirm bringen
inc dh
cmp dh,SCR_MAIN_DEPTH
jnz @@g4
ret
endp
;Verschwindenlassen des CDP-Fensters. LineIncr und CdpScr werden NICHT
;zurückgesetzt - das muß nachgeholt werden, wenn Bildschirmzugriffe
;erwünscht sind. Für Dragging, ShowWindow kann unmittelbar folgen
;(nach Änderung von vid_LeftTop)
proc HideWindow
BTST [vid_Graph],bit 0
jz swapmainscreen ;Textmodus-Lösung
jmp RemoveWindow ;Grafikmodus-Lösung
endp
;********************************************
;** Routinen für die Oberflächengestaltung **
;********************************************
;Track-(Slot)-Nummer zu Cursorposition wandeln
;PE: CL: Track-Nummer 0=aktuell 1..26: in Liste
;PA: DX: Cursorposition linke Ziffer
;VR: DX,Flags
proc Tno2Cursor
push cx
mov dx,3*256+24 ;Position 3/24
or cl,cl
jz @@e
mov dx,1*256+1 ;Position 1/1
cmp cl,13
jbe @@s1
sub cl,13
inc dh ;Zeile 2
@@s1: add dl,cl
add dl,cl
add dl,cl ;Spalte cl*3+1
@@e: pop cx
ret
endp
;Aus Tastennummer Cursorposition (Links) ermitteln
;PE: BL=Tastennummer
;PA: DX=Cursorposition
;VR: DX, Flags
proc Key2Cursor
push bx
mov dx,5*256+3
cmp bl,2
jbe @@n
inc dl
@@n: cmp bl,4
jbe @@n2
inc dl
inc dl
@@n2: cmp bl,5
jbe @@n3
inc dl
inc dl
@@n3: shl bl,2
add dl,bl
pop bx
ret
endp Key2Cursor
;Anzahl Tracks in nPlaylist anzeigen
ShowTrackCount:
mov al,[nPlayList]
ShowTrackNumber0:
mov bl,[Colors+3]
xor cl,cl
; Show a track number
;
; Input : al -> Track number
; bl -> Screen attribute
; cl -> Slot position
; 0 = Track number at status line
; 1 - 26 = Track number at track info display
;VR: AX,DX,ES,DI,Flags
proc ShowTrackNumber
push es di
call Tno2Cursor ;Cursorposition aus CL ermittlen
call CalcAdr
call ALDEZ
stosb
mov al,bl ;Attribut
stosb
mov al,ah ;2. Zeichen
stosb
mov al,bl ;Noch ein Attribut
stosb
push cx
mov cl,2 ;2 Zeichen
call Redraw
pop cx
pop di es
ret
endp ShowTrackNumber
; Show a time
;
; Input : bx -> time BH: Minuten, BL: Sekunden
; carry -> position
; 0 = Time at current counter
; 1 = Time at overall counter
;neu:
;PE: AX=Zeit (auch bei dem alten ShowTime)
proc ShowTime
push es
mov dx,3*256+28
jnc @@1 ;Zeitangabe links
add dl,8 ;8 Zeichen weiter rechts
@@1: call CalcAdr
xchg bx,ax
mov al,'-'
cmp [KeyLights],bit k_Play
jz @@pos ;Nur während Abspiels negativ!
@@check:
BTST [KeyLights],bit k_TimeMode
jnz @@n
@@pos: mov al,' '
@@n: call @@outc
mov al,bh
call @@outd
mov al,':'
call @@outc
mov al,bl
call @@outd
mov cl,6 ;6 Zeichen aktualisieren
pop es
Callret Redraw
@@outd: call ALDEZ
stosb
inc di
mov al,ah
@@outc: stosb
inc di
ret
endp ShowTime
; Clear the display
;
proc ClearDisplay ; Clear track display
push es di dx
mov dx,1*256+4 ;ab Position 1/4
mov ch,[Colors+2] ;Anzeigetext verborgen (00)
mov cl,38
call TouchColor
inc dh ;Zeile 2
call TouchColor
mov dx,3*256+16 ;Zeile 3
call CalcAdr ;ES:DI ermitteln
mov al,' '
mov cx,27
rep stosw
mov ch,[Colors+3] ;Zeit-Anzeige (0B)
mov cl,27
call TouchColor
pop dx di es
ret
endp ClearDisplay
; Show the play list
;Es werden alle Positionen der Playlist angezeigt, in der dort vorliegenden
;Reihenfolge und unter Beachtung der "wahren" Spur-Nummer auf der CD
proc ShowPlayList
call ClearDisplay
lea si,[nPlayList]
lodsb
mov ch,al ;Anzahl
xor cl,cl
jr @@foot
@@l:
inc cl ;mit Platz 1 beginnen
lodsb ;Track-Nummer
mov ah,size TTrackBuf
mul ah
xchg bx,ax
mov al,[(tracks+bx).nr] ;wahre Tracknummer
mov bl,[Colors+6] ;Farbe (03)
call ShowTrackNumber
@@foot: cmp cl,ch
jc @@l
ret
endp ShowPlayList
; Show the edit list
;Es werden alle Spuren des "tracks"-Inhaltsverzeichnisses angezeigt.
;Spurnummern, die auch in der Playlist enthalten sind, werden hervorgehoben
proc ShowEditList
lea si,[tracks]
mov ch,[(TTrackBuf si).nr] ;Anzahl Spuren
xor cl,cl
jr @@foot
@@l:
inc cl ;Mit Slot 1 beginnen
add si,size TTrackBuf
mov al,cl
call InPlaylist ;In Spiel-Liste enthalten?
mov bl,[Colors+4] ;Farbe (01)
jnz @@1 ;Nicht in Liste
mov bl,[Colors+6] ;Farbe (01)
@@1: mov al,[(TTrackBuf si).nr] ;wahre Nummer (meist gleich!)
call ShowTrackNumber
@@foot:
cmp cl,ch
jc @@l
ret
endp ShowEditList
proc readtrackdata
mov [CurTnoIdx],0 ;Auf jeden Fall aktuelle Spur zurücksetzen
call ReadInTrackData
jc @@e
cmp [tracks.nr],0
jz @@noaudiodisk
mov [CDPStat],2
call setcontinuous ; Set continous mode
mov ah,1
call DrawCurPKey ;??
mov al,[tracks.nr] ; Show track count at status line
call showtracknumber0 ;an Position 0
mov ax,[tracks.len.time] ; Show disk time at status line
stc
call showtime
clc ; Ok
ret
@@noaudiodisk:
call cleardisplay
PRINTXY 17,3,scr_noaudiodisk
mov [CDPStat],1 ; Wait for disk change
mov ah,1
call DrawCurPKey ;??
stc ; No audio disk
@@e: ret
endp readtrackdata
;*****************************
;** Verwaltung der PlayList **
;*****************************
InPlaylist:
xor ah,ah ;Nur testen
proc AppendRemovePlaylist
;PE: AL: einzufügende oder (falls vorhanden) zu löschende Nummer
; AH: Modus (was zu tun ist)
; Bit 0 =1: Anhängen erlaubt (z.B. AH=1: anhängen, falls nicht vorhanden)
; Bit 1 =1: Löschen erlaubt (z.B. AH=0: nur testen)
;PA: Z=1: War enthalten (also ggf. NICHT MEHR enthalten)
; Z=0: War nicht enthalten (also ggf. JETZT ENTHALTEN)
;VR: Flags
push es di cx
LD es,ds
lea di,[nPlayList+1]
mov cl,[di-1]
xor ch,ch
or di,di ;Z-Flag löschen (wichtig für CX=0!)
repne scasb
;Z=1: Enthalten, dann: DI zeigt auf Folgenummer, CX=Anzahl Folgezeichen
;Z=0: Nicht enthalten, dann DI zeigt hinter das Listenende, CX=0
pushf ;Flags in jedem Falle dem Anwenderprogramm!
jz @@remove
BTST ah,bit 0 ;Anhängen erlaubt?
jz @@e
mov [di],al
inc [nPlayList] ;Stringlänge erhöhen
jr @@calc
@@remove:
BTST ah,bit 1 ;Löschen erlaubt?
jz @@e
push si
mov si,di
dec di ;Zeichenkettenrest nach vorn schaufeln
rep movsb
pop si
dec [nPlayList] ;Stringlänge erniedrigen
@@calc: pusha
call CalcTlTime ;Zeitänderung neu berechnen
popa
@@e: popf
pop cx di es
ret
endp
;nPlaylist nach sPlaylist kopieren
proc CopyPlaylist
LD es,ds ;da war noch ein Problem!
lea si,[nPlaylist]
lea di,[sPlaylist]
mov cx,27
rep movsb ;Kopieren
ret
endp
;* Kopie von nPlayList in sPlayList anlegen (zum Beenden von RANDOM)
;* nPlaylist leeren
;* zufälliges Element aud sPlaylist holen und - wenn nicht bereits vor-
; handen, nach nPlaylist anhängen
;* Wiederholen, bis alle Elemente erwischt worden.
proc MakeRandomPlaylist
call CopyPlaylist
mov [nPlaylist],0 ;kein Element zunächst
jmp @@foot ;WHILE-Schleife...
@@l:
MOV AX,[wo LOW RandSeed]
MOV BX,[wo HIGH RandSeed]
MOV CX,AX
MUL [FACTOR]
SHL CX,3
ADD CH,CL
ADD DX,CX
ADD DX,BX
SHL BX,2
ADD DX,BX
ADD DH,BL
MOV CL,5
SHL BX,CL
ADD DH,BL
ADD AX,1
ADC DX,0
MOV [wo LOW RandSeed],AX
MOV [wo HIGH RandSeed],DX
mov ax,[wo RandSeed+1]
xor dx,dx
mov bx,26 ;Listen-Länge
div bx ;Zufall bleibt Zufall
mov al,dl ;Auf den Rest bin ich scharf
lea bx,[sPlaylist+1] ;Vorbereiten für starkes XLAT
xlatb ;Zugriff (XLAT ist immer wieder schön!)
mov ah,1 ;Einfügen, nie löschen
call AppendRemovePlaylist ;einsortieren!?
jz @@l ;war schon einsortiert, neue Zufallszahl
@@foot:
mov al,[sPlaylist]
cmp [nPlaylist],al ;Liste voll?
jne @@l ;nein, neue Runde
ret
endp
;sPlaylist (Sicherungskopie) zurückspulen
proc ClearRandomPlaylist
LD es,ds ;da war noch ein Problem!
lea si,[sPlaylist]
lea di,[nPlaylist]
mov cx,27
rep movsb ;Rückschaufeln
ret
endp
;nPlayList wird mit allen verfügbaren Spuren in normaler Reihenfolge geladen
proc FillPlaylist
mov cl,[tracks.nr] ;Vorhandene Track-Anzahl
LD es,ds
lea di,[nPlayList]
xor ch,ch
mov al,cl
stosb ;Anzahl speichern
mov al,0
jcxz @@skip ;Anzahl 0 (ist sowieso fatal)
@@listloop:
inc al ;mit Nummer 1 beginnen
stosb
loop @@listloop
@@skip: CallRet CalcTlTime ;Zeit berechnen
endp
;nPlayList wird gelöscht (kein Titel mehr in der Liste)
proc ClearPlaylist
mov [nPlayList],0
CallRet CalcTlTime ;Zeit "berechnen"
endp
;********************************
;** Tasten-Wiedergabe-Routinen **
;********************************
DrawCurTKey: ;hier nur noch AH=0 oder AH=1 übergeben!
mov al,[TrackFocused]
;wie unten, mit automatischem Setzen des Bit 1 von AH
proc MarkTKeyLux
cmp [PlayMode],1 ;edit?
jne @@set
push ax ;Fokussierungs-Flag
xor ah,ah
call InPlaylist
pop ax
jnz @@w
@@set: BSET ah,bit 1 ;Hervorgehoben darstellen
@@w:
;Track-Anzeige aktualisieren
;PE: al: Positions-Nummer 1-basiert
; Bit0(ah): Schalter fokussiert
; Bit1(ah): Schalter aktiviert (leuchtend)
; Alle anderen Bits müssen 0 sein!
MarkTKey:
push dx cx bx
mov cl,al
call Tno2Cursor
mov al,ah
lea bx,[Colors+4]
xlatb ;passendes Farbbyte
mov ch,al ;nach CH
mov cl,2 ;2 Zeichen
call TouchColor ;Farbe setzen!
pop bx cx dx
ret
endp MarkTKeyLux
DrawCurPKey:
mov al,[KeyFocused]
proc MarkPKeyLux
push cx dx
mov cl,al
mov dx,1
shl dx,cl
BTST [KeyLights],dx
jz @@w
BSET ah,bit 1
@@w: pop dx cx
;Knopf neu zeichnen (neue Farbe)
;PE: AL=Knopf-Nummer (0-basiert)
; Bit0(AH): Knopf ist fokussiert
; Bit1(AH): Knopf-LED leuchtet
MarkPKey:
push bx cx dx
mov bl,al ;AL-->DX
call Key2Cursor
mov al,ah
lea bx,[Colors+8]
xlatb
mov ch,al ;Farbbyte
mov cl,3
call TouchColor ;Taste mit neuer Farbe
pop dx cx bx
ret
endp MarkPKeyLux
;Nichts fokussieren!
proc RemoveCurFocus
push ax
xor ah,ah
BTST [keymodus],bit 0 ;Bedientaste oder Spur?
jnz @@1 ;Spur!
call DrawCurPKey
jr @@e
@@1:
call DrawCurTKey
@@e: pop ax
ret
endp
proc SetKeyFocus
;PE: BL: Neue fokusierte Taste
;PA: -
;VR: ??
;Falls gerade ein Track fokussiert ist, wird die Fokkusierung dort entfernt
call RemoveCurFocus
BRES [keymodus],bit 0
mov [KeyFocused],bl
mov ah,1
call DrawCurPKey
callret showhelp ;Gleich noch Hilfe zeigen
endp
proc SetTrackFocus
;PE: BL: Neue fokusierte Spur (1-basiert)
;PA: -
;VR: ??
call RemoveCurFocus
BSET [keymodus],bit 0
call GetMaxDisplayTrack
MIN bl,al ;begrenzen !!!
mov [TrackFocused],bl
mov ah,1
call DrawCurTKey
callret ShowTrackLen
endp
; Shows the current modus display
;
proc ShowModus
mov al,7 ;Länge der Einzelstrings
mul [playmode]
lea si,[scr_mode]
add si,ax
mov dx,3*256+17
CallRet PrintScr
endp ShowModus
; Shows the help for a key
; BL=Tastennummer, BH=Fokussierungs-Flag
proc ShowHelp
cmp [locked],1
jne @@n4
PRINTXY 17,3,scr_clear
call showmodus
call ShowTrackCount
mov ax,[maxdtime.time]
stc
call showtime
mov [locked],0
ret
@@n4:
mov si,offset scr_help
BTST [KeyModus],bit 0
jne @@nkeys ;Track-Auswahl aktiv!
mov al,12 ;Länge der Hilfestrings
mul bl ;mal Tastennummer
add si,ax ;SI=Adresse Hilfestring
cmp bl,1 ;Pausentaste?
jne @@n3 ;nein
BTST [KeyLights],bit k_Pause
jz @@n3
add si,8*12 ;8 Strings weiter (brrr!)
jr @@n1
@@n3:
cmp bl,7 ;Taste "R"?
jne @@n1
BTST [KeyLights],bit k_Random
jz @@n1
add si,3*12
jr @@n1
@@nkeys:
cmp [playmode],1
je @@n2
BTST [KeyLights],bit k_Play
jz @@n2
sub si,1*12
@@n2:
add si,12*12
@@n1:
mov dx,3*256+4
call PrintScr
ret
endp ShowHelp
;Taste hervorheben oder zurückstellen (Status aktiv oder inaktiv)
;
; Input : bl -> Key number
;NEU (temp) BL=Nummer, Status aus KeyLights (nicht BH)
HiliteCurKey: ;auf aktuell fokussierte Taste bezogen
mov bl,[KeyFocused]
proc HilitePKey
xor ah,ah
mov al,bl
BTST [keymodus],bit 0
jnz @@w
cmp [KeyFocused],al
jnz @@w
BSET ah,bit 0 ;Fokussiert darstellen
@@w: jmp MarkPKeyLux
endp HilitePKey
;*****************************************
;** Funktionalität der Bedienoberfläche **
;*****************************************
; Shuffles the playlist
proc SetRandom
call MakeRandomPlaylist
jr ResetRandom1
endp SetRandom
; Restores playlist
;
proc ResetRandom
call ClearRandomPlaylist
jr ResetRandom1
endp ResetRandom
; Fills playlist with all tracks
;
proc SetContinuous
mov [playmode],0 ;"cont"
call FillPlaylist ;berechnet auch Zeitsumme
BTST [KeyLights],bit k_Random
jnz SetRandom ;Zufällig machen, falls Random-Knopf leuchtet
ResetRandom1:
call showplaylist ;Normale Anzeige
callret showmodus
endp SetContinuous
; Fills playlist with all tracks
;
proc SetScan
mov [playmode],2 ;"scan"
call FillPlayList
call CopyPlaylist
jr ResetRandom1 ;Random-Flag hierbei ignorieren
endp SetScan
;************************************
;** Bedientasten-Aktionsfunktionen **
;************************************
; Procedure for play key
;CY=1 wenn CurTnoIdx mit Bereichsüberlauf
;Setzt CurTnoIdx auf 1, wenn es 0 enthielt
proc KeyPlay
mov [QTimeTrack.time],0
mov al,[CurTnoIdx]
or al,al
jnz @@n
inc al
mov [CurTnoIdx],al
@@n:
lea bx,[nPlayList]
cmp [bx],al ;Kein Überlauf?
jc @@e
xlatb ;Indizierter Zugriff
mov bl,al
cmp [playmode],2
jne @@play
call playscan
jr @@cont
@@play:
call play
@@cont:
BSET [KeyLights],bit k_Play
mov bl,k_Play
call HilitePKey
BRES [KeyLights],bit k_Pause
mov bl,k_Pause
call HilitePKey
clc
@@e: ret
endp KeyPlay
; Procedure for stop key
;
proc KeyStop
cmp [playmode],3
jne @@norm
call setcontinuous
@@norm:
mov [CDPStat],2
BSET [KeyLights],bit k_Stop
mov bl,k_Stop
call HilitePKey
call stop
call stop
BRES [KeyLights],bit k_Stop + bit k_Pause + bit k_Play
mov bl,k_Stop
call HilitePKey
mov bx,k_Pause
call HilitePKey
mov bx,k_Play
call HilitePKey
call showplaylist
call showmodus
call ShowTrackCount
mov ax,[maxdtime.time]
stc
call showtime
mov ah,1
call DrawCurPKey ;??
ret
endp KeyStop
; Procedure for eject key
;(sie schließt den Laden gegebenfalls wieder)
proc KeyEject
call checktray
jnc @@n1
PRINTXY 17,3,scr_clear
PRINTXY 20,3,scr_locked
mov [locked],1
ret
@@n1:
push cx ;Statusbit von checktray
BSET [KeyLights],bit k_Eject
call HiliteCurKey
pop cx
BTST cx,bit 0 ;Tür auf oder zu?
jnz @@c ;auf, also zumachen!
call keystop
call eject
jr @@o
@@c: call closetray
@@o: BRES [KeyLights],bit k_Eject
call HiliteCurKey
ret
endp KeyEject
; Procedure for pause key
;
proc KeyPause
BTST [KeyLights],bit k_Play
jz @@e ;Wenn kein PLAY, dann kein PAUSE
BTST [KeyLights],bit k_Pause
jz @@pause
call continue
BRES [KeyLights],bit k_Pause
call HiliteCurKey
mov [CDPStat],3
mov bh,0
jr @@exit
@@pause:
call stop
mov [CDPStat],5
BSET [KeyLights],bit k_Pause
@@exit:
call HiliteCurKey
mov ah,1
call DrawCurPKey ;??
@@e: ret
endp KeyPause
; Procedure for random key
;
proc KeyRandom
BTST [KeyLights],bit k_Play
jz @@start
call keystop
mov [wasplaying],1
@@start:
mov [canedit],0
BTST [KeyLights],bit k_Random
je @@random
call ResetRandom
jmp @@rmn1
@@random:
call SetRandom
@@rmn1:
BTOG [KeyLights],bit k_Random
call HiliteCurKey
call showtrackCount
mov ax,[maxdtime.time]
stc
mov [CDPStat],2
call showtime
cmp [wasplaying],1
jne @@exit
mov [wasplaying],0
call keyplay
@@exit:
ret
endp KeyRandom
; Procedure for mode key
;
proc KeyPlayMode
BTST [KeyLights],bit k_Play
jz @@start
call keystop
mov [wasplaying],1
@@start:
mov [canedit],1
mov al,[playmode]
inc al
cmp al,3
jc @@n1
xor al,al ;nur 0, 1 oder 2; Modus "3" gibt's hier nicht
@@n1: mov [playmode],al
or al,al ;"cont"
jne @@m1
call setcontinuous ;Playliste füllen
jr @@exit
@@m1:
dec al
jnz @@m2
call ClearPlaylist ;Playliste leeren
call showeditlist ; Show tracks at display
call showmodus ;"edit"
jr @@exit
@@m2:
call setscan
@@exit:
call ShowTrackCount ;Anzahl anzeigen
mov ax,[maxdtime.time]
stc
call showtime
cmp [wasplaying],1
jne @@ex
mov [wasplaying],0
call keyplay
@@ex: ret
endp KeyPlayMode
;Zeigt die Länge der gerade fokussierten Spur an. Man beachte die
;Fallunterscheidung beim Edit-Mode; hier nur eine Indirektion!
;PE: keine, PA: keine
;Keine Anzeige, wenn Play-Knopf leuchtet
proc ShowTracklen
BTST [KeyLights],bit k_Play
jnz @@e
mov al,[TrackFocused]
cmp [PlayMode],1 ;edit
je @@1
lea bx,[nPlaylist]
xlatb
@@1: mov ah,size TTrackBuf
mul ah
add ax,ofs tracks
mov bx,ax
mov ax,[(TTrackBuf bx).len.time]
; clc
call ShowTime
@@e: ret
endp
;Wartet, bis Tastenrepeat einsetzt oder Taste losgelassen wird
;liefert in AX ASCII- und Scancode sowie AX=0, wenn Taste losgelassen
proc GetKey
@@l:
ifdef BIOSKEY
KBD 1
jz @@f
KBD 0
jr @@l
@@f:
endif
xor ax,ax
BTST [KeyMode],bit 4
jz @@e ;Losgelassen!
xor al,al
xchg [LastScancode],al
or al,al
jz @@l ;Kein Repeat
mov ah,al ;Erstmal kompatibel bleiben
@@e: ret
endp
proc KeyPrev
BTST [KeyLights],bit k_Play
jz @@e
BSET [KeyMode],bit 4 ;Loslaßcode einfangen
BSET [KeyLights],bit k_Prev
call HiliteCurKey
call GetKey
or ax,ax ;Losgelassen?
jz @@WholeTrack
;hier Rückspulroutine einbauen:
;* auf QTimeDisk einige Sekunden subtrahieren
;* Test, ob Zeit im tracks-Verzeichnis enthalten ist, und wo (Nummer!)
;* Wenn nicht enthalten, dann ganzer Titel zurück
;* Wenn kein vorhergehender Titel, dann von hinten (?)
;* Restspielzeit des Titels ermitteln
;* Losspielen
;* Anzeigen aktualisieren
;* Das ganze solange, bis GetKey einen Loslaßcode liefert
@@loop:
mov dl,[QTimeTrack.f]
mov ax,[QTimeTrack.time]
mov cx,10 ;10 Sekunden rückspulen
mov dh,ch
call Diff
pushf
push ax dx
mov cx,ax
mov dh,dl
mov al,[CurTnoIdx]
call GetAdrOfIdx
mov si,ax
pop bx cx ;Neue Position im Track
popf
mov dh,bl
jnc @@NoPrevTrack ;kein Überlauf bei Subtraktion
mov al,[CurTnoIdx]
dec al
jz @@r ;Bereits vorn!
mov [CurTnoIdx],al
call GetAdrOfIdx
mov si,ax
mov dl,[(TTrackBuf si).len.f]
mov ax,[(TTrackBuf si).len.time]
xor cx,cx
mov dh,ch ;Null Sekunden
@@NoPrevTrack:
push ax dx
mov dl,[(TTrackBuf si).start.f]
mov ax,[(TTrackBuf si).start.time]
call Sum
pop bx cx ;Länge
mov dh,bl
call PlayPiece
call PeriodicAction
;call WaitTick ;Etwas ausharren
call GetKey
or ax,ax
jnz @@loop ;Der User hält die Taste immer noch gebannt
mov [LastScancode],0 ;Wiederauslösung verhindern
jmp @@r
@@WholeTrack:
mov al,[CurTnoIdx]
@@l: or al,al
jz @@a ;bei Null lassen (nicht zirkular)
dec al
@@a: mov [CurTnoIdx],al
; mov [QTimeTrack],0
call stop
call keyplay
@@r: BRES [KeyLights],bit k_Prev
call HiliteCurKey
@@e: ret
endp
proc KeySucc
BTST [KeyLights],bit k_Play
jz @@e
BSET [KeyMode],bit 4 ;Loslaßcode einfangen
BSET [KeyLights],bit k_Succ
call HiliteCurKey
call GetKey
or ax,ax ;Losgelassen?
jz @@WholeTrack
;hier Vorspulroutine einbauen:
;* auf QTimeDisk einige Sekunden addieren
;* Test, ob Zeit im tracks-Verzeichnis enthalten ist, und wo (Nummer!)
;* Wenn nicht enthalten, dann ganzer Titel vorwärts
;* Wenn kein Folgetitel, dann von vorn (?)
;* Restspielzeit des Titels ermitteln
;* Losspielen
;* Anzeigen aktualisieren
;* Das ganze solange, bis GetKey einen Loslaßcode liefert
@@loop:
mov dl,[QTimeTrack.f]
mov ax,[QTimeTrack.time]
mov cx,10 ;10 Sekunden vorspulen
mov dh,ch
call Sum
push ax dx
mov cx,ax
mov dh,dl
mov al,[CurTnoIdx]
call GetAdrOfIdx
mov si,ax
mov dl,[(TTrackBuf si).len.f]
mov ax,[(TTrackBuf si).len.time]
call Diff ;Rest des Titels nach AH:AL:DL
pop bx cx ;Neue Position im Track
mov dh,bl
jnc @@NoNextTrack ;Überlauf bei Subtraktion!
mov al,[CurTnoIdx]
inc al
cmp [nPlayList],al
jc @@r
mov [CurTnoIdx],al
call GetAdrOfIdx
mov si,ax
mov dl,[(TTrackBuf si).len.f]
mov ax,[(TTrackBuf si).len.time]
xor cx,cx
mov dh,ch ;Null Sekunden
@@NoNextTrack:
push ax dx
mov dl,[(TTrackBuf si).start.f]
mov ax,[(TTrackBuf si).start.time]
call Sum
pop bx cx ;Länge
mov dh,bl
call PlayPiece
call PeriodicAction
;call WaitTick ;Etwas ausharren
call GetKey
or ax,ax
jnz @@loop ;Der User hält die Taste immer noch gebannt
mov [LastScancode],0 ;Wiederauslösung verhindern
jmp @@r
@@WholeTrack:
mov al,[CurTnoIdx]
inc al
cmp [nPlayList],al
jnc @@a
xor al,al ;Nach letzten Titel nichts auswählen
@@a: mov [CurTnoIdx],al
; mov [QTimeTrack],0
call stop
call keyplay
@@r: BRES [KeyLights],bit k_Succ
call HiliteCurKey
@@e: ret
endp
proc KeyTimeMode
BTOG [KeyLights],bit k_TimeMode ;XOR - Bit "verdrehen"
CallRet HiliteCurKey
endp
KeyActions: ;Adressen der Handler-Routinen
dw ofs KeyPlay ;0: >
dw ofs KeyPause ;1: ║
dw ofs KeyStop ;2: ■
dw ofs KeyPrev ;3: <<
dw ofs KeySucc ;4: >>
dw ofs KeyEject ;5: ^
dw ofs KeyPlaymode ;6: M
dw ofs KeyRandom ;7: R
dw ofs KeyTimeMode ;8: T
; Handle pressed key
;
keyEnter:
keySpace: ;tun dasselbe wie...
proc KeyAction
BTST [KeyModus],bit 0
jne @@trackkeys ;Kompizierte Behandlung!
mov bl,[KeyFocused]
xor bh,bh
shl bx,1
jmp [wo KeyActions+bx] ;Programmverteiler: Fokussierte Taste
@@trackkeys: ; Track key pressed
cmp [playmode],0 ;"cont": Einzelstück auswählen?
jne @@setedit ;nein
call ClearPlaylist ;ist zwar simpel...
mov al,[TrackFocused]
mov ah,3 ;Einfüge-Bit gesetzt
call AppendRemovePlaylist ;Das eine Element an die leere Liste
mov [playmode],3 ;"single"
mov bl,[TrackFocused] ; Play track
call play
mov bl,[KeyFocused]
call SetKeyFocus ;Fokus springt herunter
call showplaylist ;hier: die eine Zahl
call showmodus ;"single"
BSET [KeyLights],bit k_Play
mov bl,k_Play
CallRet HilitePKey
@@setedit: ;alle anderen Fälle...
mov al,[TrackFocused] ;aktuelle Nummer...
mov ah,3 ;Einfügen oder Löschen
push ax
call AppendRemovePlaylist ;speichen oder löschen, je nachdem
pop ax
mov ah,1 ;Fokussiert
CallRet marktkeyLux
endp KeyAction
;************************************************
;** Hauptschleife von CDP und Tastenfunktionen **
;************************************************
KeyDispatch:
DVT 77,keyCursorRight
DVT 75,keyCursorLeft
DVT 72,keyCursorUp
DVT 80,keyCursorDown
DVT 57,keySpace
DVT 28,keyEnter
DVT 15,keyTab
DVT 71,keyDragLeft ;HOME-Taste
DVT 73,keyDragUp ;PgUp-Taste
DVT 79,keyDragRight ;END-Taste
DVT 81,keyDragDown ;PgDn-Taste
DVT 0,keyElse
proc mainl
@@l: ;call WaitTick ;Etwas warten
int 28h ;Etwas idlen
MainLoop:
call PeriodicAction ;Alles auf dem laufenden halten
ifdef BIOSKEY
@@l0: KBD 1
jz @@f0
KBD 0 ;BIOS-Tastaturpuffer leeren
jr @@l0
@@f0:
endif
xor al,al
xchg [LastScancode],al
or al,al
jz @@l ;Schleifen-Durchlauf mit etwas Warten
cmp al,1 ; ESC ?
je @@e
;Unterprogramme verteilen!
LD es,ds
lea di,[KeyDispatch]
call case
call [wo di]
jmp MainLoop
keyElse:
@@e: ret
endp
keyTab: ;macht dasselbe wie...
proc keyCursorRight
cmp [CDPStat],2
jc @@e
BTST [KeyModus],bit 0
je @@pkeys1
mov bl,[TrackFocused]
inc bl
call GetMaxDisplayTrack
cmp al,bl ;Zu groß?
jnc @@nt1
mov bl,1 ;Von vorn!
@@nt1: callret SetTrackFocus
@@pkeys1:
mov bl,[KeyFocused]
inc bl
cmp bl,9
jc @@nn1
xor bl,bl ;modulo 9
@@nn1:
call SetKeyFocus
@@e: ret
endp
proc keyCursorLeft
cmp [CDPStat],2 ;Keine Tasten bei 0 oder 1
jc @@e
BTST [KeyModus],bit 0
je @@pkeys2
mov bl,[TrackFocused]
dec bl
jnz @@nt2
mov bl,[tracks.nr]
@@nt2: callret SetTrackFocus
@@pkeys2:
mov bl,[KeyFocused]
dec bl
cmp bl,-1
jnz @@nn2
mov bl,8 ;modulo 9
@@nn2: call SetKeyFocus
@@e: ret
endp
proc keyCursorUp
BTST [KeyModus],bit 0 ;Schon oben?
jne @@e ;ja, nichtstun (Anschlag)
; cmp [CDPStat],2 ;bereit? (kein PLAY)
; jne @@e ;nein, keine Tastenfunktion!
cmp [playmode],2 ;"scan"?
je @@e ;nichtstun
cmp [canedit],1
jne @@e
cmp [playmode],1 ;"edit"?
jne @@nn8 ;nein
call showeditlist ;ja, Edit-Liste anzeigen
call showtrackCount ;und die Anzahl gerade ausgewählter Elemente
mov ax,[maxdtime.time]
stc
call showtime
@@nn8:
mov bl,[TrackFocused]
call SetTrackFocus ;Fokus hoch!
@@e: ret
endp
proc keyCursorDown
BTST [KeyModus],bit 0 ;Schon unten?
je @@e ;ja, nichtstun (Anschlag)
; cmp [CDPStat],2 ;bereit?
; jne @@e ;nein, nichtstun
cmp [playmode],2 ;"scan"?
je @@e ;nichtstun
cmp [canedit],1
jne @@e
mov bl,[KeyFocused]
call SetKeyFocus ;Fokus 'runter!
cmp [playmode],1 ;"edit"?
jne @@e
call showplaylist ;Die ausgewählten Elemente nun anzeigen
call showmodus ;"edit"
call showtrackCount ;die Anzahl (bereit zum PLAY drücken)
mov ax,[maxdtime.time]
stc
call showtime
@@e: ret
endp
proc keyDragLeft ;HOME-Taste
cmp [by LOW vid_LeftTop],-3
jz @@e ;bei "Extrawurst" Links/Rechts
cmp [by LOW vid_LeftTop],0 ;Schon links?
jz @@e ;nichts tun
call HideWindow
dec [by LOW vid_LeftTop]
call ShowWindow
@@e: ret
endp
proc keyDragUp ;PgUp-Taste
cmp [by HIGH vid_LeftTop],0 ;Schon oben?
jz @@e ;nichts tun
call HideWindow
dec [by HIGH vid_LeftTop]
call ShowWindow
@@e: ret
endp
proc keyDragRight ;END-Taste
cmp [by LOW vid_LeftTop],-3
jz @@e ;bei "Extrawurst" Links/Rechts
mov al,[by LOW vid_LeftTop] ;Linke Kante
add al,SCR_MAIN_WIDTH ;Breite des Fensters dazu
cmp [by LOW vid_WidthHeight],al ;Schon rechts oder rechtsheraus?
jbe @@e ;nichts tun
call HideWindow
inc [by LOW vid_LeftTop]
call ShowWindow
@@e: ret
endp
proc keyDragDown ;PgDn-Taste
mov al,[by HIGH vid_LeftTop] ;Obere Kante
add al,SCR_MAIN_DEPTH ;Höhe des Fensters dazu
cmp [by HIGH vid_WidthHeight],al ;Schon unten oder untenheraus?
jbe @@e ;nichts tun
call HideWindow
inc [by HIGH vid_LeftTop]
call ShowWindow
@@e: ret
endp
;***************************************
;** Periodisch aufgerufene Funktionen **
;***************************************
; Wait for a disk inserted and read it in
;
proc PollDisk
cmp [CDPStat],0
je @@g ;Da ist keine drin gewesen
call checkdisk
jc @@f ;Fehler: ausgeben
call mediachanged
jnc @@e ;Kein sicherer Wechsel
mov [CDPStat],0
@@f:
call cleardisplay
PrintXY 21,3,scr_nodisk
BRES [KeyLights],bit k_Play + bit k_Pause
mov bl,k_Pause ;Lichter löschen
call HilitePKey
mov bx,k_Play
call HilitePKey
mov bl,k_Eject
call SetKeyFocus
@@g:
InitDisk: ;Ansprung beim Aufpoppen
call CheckDisk
jc @@e ;Fehler belassen
call ReadTrackData ;meldet von selber NoAudioDisk
@@e: ret
endp
;Q-Channel abfragen (wenn CDPStat=3 (abspielend))
proc TestQ
cmp [CDPStat],2
jc @@exit ;Zustände 0 und 1: Keine Tests!
BTST [KeyLights],bit k_Play
jz @@NotPlaying
BTST [KeyLights],bit k_Pause
jnz @@NotPlaying
call GetQChannel
or ax,ax ;Fehlercode
jz @@endplay
;Entspricht aktueller Track dem erwarteten?
;(QTrack==tracks[nPlaylist[CurTnoIdx]].nr)
@@FindTrack:
mov al,[CurTnoIdx]
call GetAdrOfIdx
mov bx,ax
mov al,[(TTrackBuf bx).nr]
cmp [QTrack],al ;Gleich
je @@IsOK ;ja, niemand pfuschte dazwischen
;Hier noch einbauen:
call SetContinuous ;Anzeige umschalten
;Welche Titel-Nummer ist es? Liste absuchen...
xor ah,ah
lea bx,[tracks]
mov al,[QTrack] ;Zu suchende Nummer
mov cl,[(TTrackBuf bx).nr] ;Anzahl
xor ch,ch
jcxz @@notfound ;Anzahl=0
@@l:
inc ah ;Track-Index-Nummer
add bx,size TTrackBuf
cmp [(TTrackBuf bx).nr],al
je @@found ;Hurra, gefunden
loop @@l ;nicht gefunden, weitersuchen
@@notfound: ;Problem, was nun? Disk einlesen!
call ReadInTrackData
call FillPlaylist
mov ah,0 ;Ärger für nächste Runde aufheben
@@found:
mov [CurTnoIdx],ah ;Neue Index-Nummer eintragen (nachführen)
@@IsOK:
BTST [KeyLights],bit k_TimeMode
jnz @@negtime
mov ax,[QTimeTrack.time]
clc
call showtime ;Track-Zeit direkt anzeigen
mov bl,1 ;von 1
mov bh,[CurTnoIdx]
or bh,bh ;Null?
jz @@fromQ ;Q-Channel-Wert ausgeben
dec bh ;bis zur aktuellen Spur
call CalcTimeFromTo ;Zeiten zusammenrechnen
mov dh,[QTimeTrack.f]
mov cx,[QTimeTrack.time]
call Sum
jr @@a1
@@fromQ:
mov ax,[QTimeDisk.time]
jr @@a1
@@negtime:
mov al,[CurTnoIdx]
call GetAdrOfIdx ;nach AX, notfalls (AL=0) bzgl. Gesamt-CD
mov bx,ax
mov dl,[(TTrackBuf bx).len.f]
mov ax,[(TTrackBuf bx).len.time]
mov dh,[QTimeTrack.f]
mov cx,[QTimeTrack.time]
call Diff
push cx dx ;brauche ich noch
clc
call showtime
pop dx ;DH zurück
mov bl,[CurTnoIdx] ;Erster Index
mov bh,[nPlaylist] ;letzter Index
call CalcTimeFromTo ;zusammenzählen, DH bleibt
pop cx ;CX zurück
call Diff ;Dasselbe für Gesamtrestspielzeit
@@a1: stc
call showtime
@@show:
mov al,[QTrack] ;vom Q-Channel
call showtracknumber0
jr @@exit
@@NotPlaying:
call GetQChannel ;Prüfen, ob Laufwerk noch steht
;Eventuelles Problem, wenn MSCDEX gerade eine Datenspur liest...
or ax,ax
jz @@exit
BSET [KeyLights],bit k_Play
mov bl,k_Play
call HilitePKey ;Es wird gerade gespielt, Knopf leuchte!
BRES [KeyLights],bit k_Pause
mov bl,k_Pause
call HilitePKey ;Es wird gerade gespielt, Pause AUS
jmp @@FindTrack
@@endplay:
cmp [playmode],3 ;"single"?
je @@stop ;stehenbleiben
mov al,[CurTnoIdx]
cmp [nPlaylist],al ;Ende erreicht?
je @@stop
inc [CurTnoIdx]
call keyplay ;testet auch CurTnoIdx
jnc @@exit
@@stop:
call keystop
mov [CDPStat],2
@@exit: ret
endp
; CDP Timer Int process
CDPTimer:
; ret ;TEST
proc PeriodicAction
; ret ;TEST+++TEST
call PollDisk ;überprüft, ob alles noch rechtens ist
jc @@e ;Fehler - kein TestQ
call TestQ ;Q-Kanal prüfen und ggf. nächsten Track spielen
@@e: ret
endp
proc Popup
VID 0fh ; Check current video mode
mov [vid_CurPage],bh ;angezeigte Seite
push es
LD es,40h
mov bl,[es:84h] ;Letzte Zeile (EGA/VGA)
pop es
MAX bl,24 ;Mindestens 24 muß AL sein
inc bl
mov [by HIGH vid_WidthHeight],bl ;Höhe
mov [by LOW vid_WidthHeight],ah ;Breite
mov bx,0b800h
BRES al,bit 7 ;ausmaskieren!
cmp al,3 ;CO80
je @@textmode
cmp al,2 ;BW80
je @@textmode
cmp ah,132 ;132 Spalten gibt's in keinem Grafikmodus
je @@textmode
mov bh,0b0h
cmp al,7 ;MONO
je @@textmode
BSET [vid_Graph],bit 0 ;Grafikmodus annehmen
mov [LineIncr],SCR_MAIN_WIDTH
SDS [CdpScr],ofs SCR_MAIN ;Zeiger ins eigene Programm hinein
cmp al,2 ;40spaltiger Textmodus?
jnc @@gt
BSET [vid_Graph],bit 2 ;Textmodus als Grafik
@@gt: cmp al,13h ;256-Farben-Modus?
jnz @@g1
BSET [vid_Graph],bit 1
jr @@g1 ;gemeinsam weiter
@@textmode:
BRES [vid_Graph],bit 0 ;Textmodus annehmen
mov [LineIncr],ah ;Zeichen pro Zeile
mov [wo HIGH CdpScr],bx
@@g1:
;Prüfen, ob nicht das Darstellungsfenster zu klein ist
mov ax,[vid_LeftTop];Fensterecke
add ax,SCR_MAIN_DEPTH*256+SCR_MAIN_WIDTH ;Größe des Fensters
cmp [by LOW vid_WidthHeight],al
jnc @@fx
mov [by LOW vid_LeftTop],0
@@fx: cmp [by HIGH vid_WidthHeight],ah
jnc @@fy
mov [by HIGH vid_LeftTop],0
@@fy: ;Spezialfall weniger als 46 Zeichen pro Zeile
cmp [by LOW vid_WidthHeight],SCR_MAIN_WIDTH
jnc @@fz
push [vid_LeftTop]
mov [by LOW vid_LeftTop],-3 ;Mittig postieren (bei 40 Zeichen)
@@fz: ;Cursor(en) verschwinden lassen
BTST [vid_Graph],bit 4 ; Mouse off if installed
jz @@nomouse1
mov ax,2 ;Maus AUS
int 33h
@@nomouse1:
call SwapCursor
;Fenster anzeigen
call ShowWindow ;bei Position vid_LeftTop
BSET [KeyMode],bit 6 ;Verbot für Tastatur-BIOS
call mainloop ;Tastatur-Abfrageschleife
BRES [KeyMode],bit 6 ;Erlaubnis für Tastatur-BIOS
call HideWindow ;Fenster zurücknehmen
mov [LineIncr],SCR_MAIN_WIDTH
SDS [CdpScr],ofs SCR_MAIN ;Zeiger ins eigene Programm hinein
BRES [vid_Graph],0fh ;Kein Grafikmodus, keine Grafik-Flags mehr
;Cursor(en) wieder erscheinen lassen
call SwapCursor
BTST [vid_Graph],bit 4 ; Mouse on if installed
jz @@nomouse2
mov ax,1
int 33h
@@nomouse2:
cmp [by LOW vid_LeftTop],-3 ;Mittig postiert?
jnz @@v1
pop ax ;alte Position
mov [by LOW vid_LeftTop],al ;an ehemalige X-Stelle zurück
@@v1:
ret
endp Popup
;==============================================================================
; TSR IRON CURTAIN - HE WHO CROSSES THIS CURTAIN WILL BE GONE AFTER TSR!
;==============================================================================
ResEnd:
TsrCurtain: ;TSR memory break
DATASEG
; Transient code *****************************************************
Mscdex$ db 'MSCDEX $'
drive$ db 'drive $'
found$ db ': found, $'
msg_installed db '_',8,'■ installed, $'
HotkeyIs$ db 'Hotkey is $'
Shift$ db 'Shift+$' ;hier: links ODER rechts - egal!
Ctrl$ db 'Ctrl+$'
Alt$ db 'Alt+$'
PointNL$ db '".',nl,'$'
NoMscdex$ db "seems to be not loaded. ",7,"Try /D switch",nl,'$'
WrongVersion$ db 'version 2.10+ required ',7,'(or use /D workaround)',nl,'$'
NoAudio$ db 'CD drive is not capable of playing audio',7,nl,'$'
NoDrive$ db "CD drive letter given doesn't exist",7,nl,'$'
NoDriver$ db "CDROM low-level driver given doesn't exist ",7,"(error opening)",nl,'$'
DriverErr$ db "Low-level driver given exist, but won't work properly",7,nl,'$'
NoChange$ db "It's not possible to change CD drive ",7,"while CDP is resident",nl,'$'
CmdLineError$ db "Command line error ",7,"(unknown option or syntax error, try /?)",nl,'$'
No286$ db "This program doesn't run on 8086/88 (PC/XT) machines",7,nl,'$'
NoFreeMux$ db "No free MUX available",7,nl,'$'
msg_alreadyinst db 'CDP already resident. $'
msg_status1 db 'Last status: $'
msg_status2 db 'no disk inserted.',nl,'$'
msg_status3 db 'no audio disk.',nl,'$'
msg_status4 db 'ready to play.',nl,'$'
msg_status5 db 'playing.',nl,'$'
msg_status6 db 'pausing.',nl,'$'
msg_notinstalled db 'CDP is not ',7,'resident',nl,'$'
msg_cannotuninst db "Can not uninstall ",7,"the resident CDP. Remove other TSR first",nl,'$'
msg_uninstalled db 'uninstalled and removed from memory.',nl,'$'
msg_copyright db 'C',8,'CD',8,'DP',8,'P 1.1 (h#s): $'
;Mit LESS (NROFF)-Sequenzen für den Einsatz mit geladenem ANSI.COM
msg_help1 db "haftmann#software CD player - freeware",nl
db "CDP - a resident popup music CD player - even for graphics mode.",nl
db "Default action is to load the player or to show a status if loaded.",nl
db 'Command line options: (the switch char can be "-", "/" or omitted,',nl
db 'a delimiter ":","=" or omitted).',nl
db nl
db " /H or /? -> show this help on usage",nl
db " /U -> tries to uninstall the resident CDP",nl
db " /K:{CSA}key -> changes the hotkey for popup",nl
db " /D:drivername -> use CDROM driver instead of MSCDEX",nl
db " /L:drive{:} -> use CDROM on specific drive letter",nl
;db " /V -> verbose info",nl
;db " /S -> status info only",nl
db nl
db "CDP is based on XCD v1.0ß by Henrik Drewelow, 1994.",nl
db '$'
; variables ----------------------------------------------------------
resseg dw ? ; Segment of the resident CDP
command db 0 ; Commands in command line
; 1 -> Uninstall CDP
; 2 -> Help on Usage
; 4 -> Hotkey selection
; 8 -> Ungültige Option
; 16 -> Treiber gewählt
; 32 -> MSCDEX gewählt
tsrstat db 0 ;Statusbits von InstChk
PDriverName dw 0 ;zeigt in die Kommandozeile
CODESEG
; library procedures -------------------------------------------------
include "asc2scan.asm"
_SCANTAB
_SCAN2ASC
_ASC2SCAN
_UPCASE
_INSTCHK
; misc. procedures ---------------------------------------------------
; Sets up data for the IOCTRL requests
;
proc setupIOCTRL
SCS [IOCTRL.bufptr],offset IOBuf
mov [IoCtrl.buflen],size IOBuf
ret
endp setupIOCTRL
proc DetectMscdex
;CY=1: Kein MSCDEX
xor bx,bx
MUX 1500h
cmp bx,1
ret
endp
proc CheckVersion
;CY=1: Version zu klein
xor bx,bx
MUX 150Ch
cmp bx,20ah
ret
endp
proc GetSysEntry
;CY=1: Fehler (kein Laufwerk auf Buchstabe)
mov cx,[CDDrive]
push es
ld es,cs
mov bx,offset IoCtrl
mov [(TIoCtrl bx).hdrlen],1Ah ;Länge
mov [(TIoCtrl bx).command],3 ;IOCTL Read
mov [IOBuf.request],0 ;Adresse Gerätekopf
mov ax,1510h
int 2fh ; Pass to mscdex
jc @@e
les bx,[dword IoBuf.data] ;Adresse
mov ax,[(TDevHdr es:bx).pStrat]
SES [Strat],ax
mov ax,[(TDevHdr es:bx).pIntr]
SES [Inter],ax
@@e: pop es
ret
endp
; Checks the Drive capabilities
;PA: CY=1 wenn Laufwerk meint, kein Audio zu unterstützen
proc checkdrive
call getdevicestatus ; Get drive status
BTST cx,bit 4 ;Dieses Bit muß gesetzt sein!
jnz @@e ;okay (CY ist 0)
stc
@@e: ret
endp checkdrive
;textuelle Ausgabe des ausgewählten Hotkeys
;(z.B. 'Hotkey is Ctrl+Alt+"K".'
proc WriteHotKey
print HotkeyIs$
mov cl,[es:hotkeyshift]
test cl,bit 1
jz @@n1
print Shift$
@@n1: test cl,bit 2
jz @@n3
print Ctrl$
@@n3: test cl,bit 3
jz @@n4
print Alt$
@@n4: mov al,'"' ;wegen 1 Zeichen nicht gleich PRINT!
call ochr
mov al,[es:hotkey]
call scan2asc
call ochr
print PointNL$
ret
endp WriteHotKey
; Writes the last Status
;
proc WriteStatus
print msg_status1
cmp [es:CDPStat],0
lea dx,[msg_status2]
je @@we
cmp [es:CDPStat],1
lea dx,[msg_status3]
je @@we
BTST [es:KeyLights],bit k_Pause
lea dx,[msg_status6]
jnz @@we
BTST [es:KeyLights],bit k_Play
lea dx,[msg_status5]
jnz @@we
lea dx,[msg_status4]
@@we: DOS 9
ret
endp WriteStatus
;Übergehe Doppelpunkt (colon) oder Gleichheitszeichen (equal sign)
proc OverCE
lodsb
cmp al,':' ;optionaler Doppelpunkt?
jz @@over
cmp al,'=' ;oder Gleichheitszeichen?
jz @@over
dec si ;Hier beginnen!
@@over: ret
endp
upvt: ;Unterprogrammverteilertabelle für Kommandozeilenoptionen
DVT 'U',cmdUninstall
DVT '?',cmdHelp
DVT 'H',cmdHelp
DVT 'K',cmdHotKey
DVT 'L',cmdMSCDEX
DVT 'D',cmdDriver
DVT 0, cmdError ;Else-Zweig: Ganz einfach: Fehler
; Parse the command line
;ES zeigt auf residente Kopie
proc ParseCommandLine
mov si,81h ; read cmdline len
@@read:
lodsb ; read char
@@next:
cmp al,0dh
je @@exit
cmp al,' '
jbe @@read ;nächstes Zeichen bei Weißraum
cmp al,'-'
je @@read ;Optionszeichen übergehen (alles ist mit Option!)
cmp al,'/'
je @@read
@@option:
call upcase
push es
LD es,ds
lea di,[upvt] ;Unterprogrammverteilertabelle
call case
pop es
jmp [wo di]
@@exit:
ret
cmdUninstall:
or [command],1 ; Uninstall switch
jr @@read
cmdHelp:
or [command],2 ; Help switch
jr @@read
cmdHotKey:
or [command],4 ; Hotkey selection
xor bx,bx ;keine Shift-Tasten-Modifikation annehmen
call OverCE
@@kl: lodsb
cmp [by si],21h ;Folgt Weißraum?
jc @@k1 ;ja, Tasten-Bezeichner (keine Shifttasten)
call Upcase ;nein - Shift-Bezeichner in AL
cmp al,'S'
mov ah,bit 1 ;Shift-Bit
jz @@ks
cmp al,'C'
mov ah,bit 2 ;Control-Bit
jz @@ks
cmp al,'A'
mov ah,bit 3 ;Alt-Bit
jz @@ks
@@ke: jmp CmdError ;Fehler (vielleicht später Extra-Meldung)
@@ks:
BTST bh,ah ;Bit bereits gesetzt?
jnz @@ke ;Doppelt angeben gibt's nicht!
or bh,ah ;Shift-Tasten-Bitmaske: Bit setzen
inc bl ;Shift-Tasten-Zähler: erhöhen
jr @@kl
@@k1:
cmp bl,1 ;Nur eine Shift-Taste angegeben?
je @@ke ;Fehler!
call asc2scan ;muß Zahl oder Buchstabe sein
jc @@ke ;Fehler
mov [es:HotKey],al ;Taste auf jeden Fall ändern
or bl,bl ;Shift-Tasten angegeben?
jz @@read ;nein
mov [es:HotkeyShift],bh ;ja, auch ändern
jr @@read
cmdMSCDEX:
BSET [command],bit 5
call OverCE
lodsb
call anum ;in Ziffer wandeln
cmp al,0ah ;war Ziffer?
jc @@grr ;Laufwerksbuchstabe muß ermittelt werden!
sub al,0ah
cmp al,26
jnc cmdError ;Kommandozeilen-Fehler
cbw
mov [CDDrive],ax
lodsb
cmp al,':' ;Laufwerks-Doppelpunkt?
jnz @@next ;nein, Zeichen anderweitig interpretieren!
@@grr: jmp @@read
cmdDriver:
BSET [command],bit 4
call OverCE
mov [PDriverName],si ;merken
@@l: lodsb
cmp al,' ' ;Weißraum?
ja @@l
mov [by si-1],0 ;nullterminieren!
jmp @@next ;!! Nicht noch einmal lesen (könnte 0Dh sein) !!
cmdError:
or [command],8 ;Ungültige Option!
jmp @@read
endp ParseCommandLine
; program entry point ************************************************
proc Main
print msg_copyright ;Display Copyright
IS286
lea dx,[No286$]
jc MsgExit
call InstChk
mov [resseg],es ;save resident segment
mov [tsrstat],ch
call parsecommandline ;Check program parameter
test [command],bit 1 ;Help request
lea dx,[msg_help1]
jnz MsgExit
test [command],bit 3 ;Kommandozeilen-Fehler
lea dx,[CmdLineError$]
jnz MsgExit
BTST [tsrstat],bit 7
jnz @@notinstalled
; ============ TSR ALREADY INSTALLED, CHECK OPTIONS
test [command],bit 4 + bit 5 ;Treiber oder Laufwerk angegeben?
lea dx,[NoChange$]
jnz MsgExit ;ist auch ein Fehler (z.Z.)
test [command],1 ;uninstall request
jnz @@uninstall
; ------------ SHOW HOTKEY AND STATUS, EXIT CDP
print msg_alreadyinst ;display alr installed msg
ld es,[resseg]
call writehotkey ;shot the hotkey
call writestatus ;show last status
OKExit: DOS 4c00h ;error level in AL
; ------------ UNINSTALL RESIDENT CDP, CHECK VECTORS FOR UNINSTALLING
@@uninstall:
BTST [tsrstat],0fh ;Anzahl verbogener Vektoren
jnz @@cannot
mov ah,[MUXI]
xor al,al
MUX ;SI besorgen
call Unhook
PRINT msg_uninstalled
jmp OKExit
@@cannot:
lea dx,[msg_cannotuninst]
jmp MsgExit
@@notinstalled:
BTST [command],1 ;uninstall request
lea dx,[msg_notinstalled]
jnz MsgExit
call SetupIOCTRL ;erforderliche Datenstrukturen initialisieren
test [command],bit 4 ;mit Gerätetreiber verlangt?
jnz ConnectToSysDrv
PRINT mscdex$
call detectmscdex ; Check for MSCDEX
lea dx,[NoMscdex$]
jc @@MX
BTST [command],bit 5 ;Laufwerksvorgabe auf Kommandozeile?
jnz @@a1 ;ja, [CDDrive] belassen
mov [cddrive],cx ;1. Laufwerk einschreiben
@@a1: call CheckVersion
lea dx,[WrongVersion$]
jc @@MX
call GetSysEntry
lea dx,[NoDrive$]
jc @@MX
PRINT Drive$
mov al,[by CDDrive]
add al,'A' ; Display drive letter
call OCHR
PRINT Found$
ContDrv: ;hier weiter im Falle eines Gerätetreibers
call CheckDrive ; Check drive capabilities
lea dx,[NoAudio$]
@@MX: jc MsgExit
xor ax,ax
int 1ah ;BIOS-Uhrzeit nach CX:DX
mov [wo LOW RandSeed],dx
mov [wo HIGH RandSeed],cx
DOS 3533h ;Interruptvektor Maus besorgen
mov ax,es ;liefert NIL-Pointer?
or bx,ax
jz @@nomouse ;dann keine Maus
xor ax,ax ; Check for mouse
int 33h
or ax,ax
jz @@nomouse
BSET [vid_Graph],bit 4
@@nomouse:
call FindFreeMux
lea dx,[NoFreeMux$]
jc MsgExit
push ds es
DOS 3400h
SES [InDosPtr],bx
DOS 5d06h
SDS [cs:CritErrPtr],si
pop es ds
mov [word HIGH CdpScr],ds ;Segment einsetzen
call HookAll
print msg_installed
LD es,ds
call writehotkey
BSET [TSRMode],BPActive
call cdptimer
BRES [TSRMode],BPActive
mov es,[2ch] ;ES=our environment copy
DOS 49h ;to let DOS free block
mov dx,ParaRes ;Gleichung residente Paragrafen
DOS 3100h ;TSR, AL=err level
ConnectToSysDrv:
mov dx,[PDriverName]
DOS 3D00h ;Gerät zum Lesen öffnen
lea dx,[NoDriver$]
jc MsgExit ;Fehler!
xchg bx,ax ;Handle
lea dx,[IOBuf] ;Puffer für IOCTL
mov [IOBuf.request],0 ;Funktion 0: Gerätetreiberkopfadr.
mov cx,5
DOS 4402h ;IOCTL Read
jc @@nodriver1 ;Noch ein Fehler
push es bx
les bx,[dword IoBuf.data] ;Adresse
mov ax,[(TDevHdr es:bx).pStrat]
SES [Strat],ax
mov ax,[(TDevHdr es:bx).pIntr]
SES [Inter],ax
pop bx es
DOS 3eh ;Gerät schließen
jmp ContDrv
; ------------ MESSAGES FOR NOT INSTALLING RESIDENT
@@nodriver1:
DOS 3eh ;Datei schließen
lea dx,[DriverErr$]
MsgExit:
DOS 9
exit: DOS 4c01h
endp Main
endc
Detected encoding: OEM (CP437) | 1
|
|