.comment %

MEMTSR.MAC -- TSR afhandingsroutines

Deze module omvat alle routines die in het managersegment in pagina 1
geplaatst worden. Deze routines worden door L80 aan het einde van de
file MEMMAN.REL meegelinkt, en door de routine INSTALL (in de
file MEMINST.MAC) naar pagina 1 gecopieerd.

De volgende source-bestanden worden ingevoegd:

- MEMCONST -- Constanten definities
- MEMEXTSR -- MemMan functies
- MEMTL    -- CMD TL
- MEMTK    -- CMD TK
- MEMTV    -- CMD TV
- MEMFT    -- ATTR$ FT

%

	public mmSegLn	;Lengte van de pagina-1 code

	public statMapTab
	public tsrPntTab
	public getTsrID
	public f10Zoek
	public fnc31Ad
	public makeSegTab
	public fncFFSegTabAd
	public fncFFTab
	public hpSrt1
	public hpSrt2
	public hpSrt3
	public notTsr
	public fnc50Tab

	public callExFnc
	public fnc61Ad
	public exIniChk
	public getSegType
	public fnc61Cont
	public fnc63Ad
	public hookProces
	public callTsr


; Externals in MEMMAN.GEN
;
	external cur0Seg
	external cur2Seg
	external cur3Seg
	external callSP
	external saveSP
	external tsrFlags
	external callSeg
	external tempHookBuf
	external savTsrID
	external nowMapSeg
	external enaDiskRom
	external ramAd0
	external ramAd2
	external ramAd3
	external dos2FreSeg
	external tpaRam1
	external dos2AllSeg
	external connFlag
	external getTabWord
	external adUse0
	external adUse1
	external adUse2
	external tsrCall
	external basicCall
	external fastGetCur
	external memManEntry
	external xTsrCall
	external hookIn
	external tsrNameBuf


; Macro definities
;
defFnc	macro @fnc,@addr	;Functie tabel definitie macro
                defb @fnc              ;Functie nummer
                defw @addr             ;Uitvoer adres van de functie
              endm


; MemMan constanten definities (versienummer etc.)
;
	include memconst.mac


; Systeemadressen
;
expTbl	equ 0fcc1h	;Slot-expansietabel


; Pre-relocation naar adres 04000H
;
	.phase 04000h	;TsrMan code komt in pagine 1


; Het volgende komt in ieder tsr segment te staan
;
overheadStart equ $

	defw tsrPntTab	;Pointer naar de tabellen pointers

; callTsr
;
; Deze routine roept een tsr aan. Er wordt over overgeschakeld op de
; originele stack zoals die aktief was ten tijde van de hook-aanroep.
; Op die stack staat het startadres van de TSR, en ook het returnadres naar
; de routine `TsrRetAd'.
;
; In: AF,DE,HL,BC  = Registers voor de TSR
;     Interrupts disabled
;
; Stack: Huidige stack: Return adres naar hook-processor
;        (saveSP+0)   : Uitvoer adres van de TSR
;        (saveSP+2)   : Terugkeer adres naar de manager
;        (saveSP+4)   : Bij de aanroep vanaf een hook staat hier de stack
;	          zoals deze was toen de hook aangeroepen werd. Een
;	          TSR `ziet' dus alleen het terugkeer adres naar de
;	          manager nog op de originele stack. Naar dit adres
;	          moet altijd teruggesprongen worden!
;
; Op het moment dat de tsr aangeroepen wordt staat dus alleen het terugkeer
; adres naar de tsrManager nog op de stack. Dit adres kan de tsr er tijdelijk
; afhalen, waarna de originele stack gemanipuleerd kan worden.
;
; Dit stukje code behoort tot de TSR Page Header
;
callTsr:
r5TsrSP::	ld (callSP),sp	;Bewaar interne stack pointer
r6TsrSP::	ld sp,(saveSP)	;Herstel orig. stack
	ret	;Spring naar de tsr


; tsrRetAd
;
; Hier keert de tsr terug na een aanroep van de manager.
;
; In:  AF,DE,BC,HL = Data registers van de tsr
;      A'          = Vlaggenbyte van de tsr
;
; Uit: AF,DE,BC,HL = Data registers van de tsr
;      (tsrFlags)  = Vlaggenbyte van de tsr
;
; De interne stack van MemMan wordt weer actief gemaakt, en de routine
; springt terug naar de hook-processor.
;
; Dit stukje code behoort tot de TSR Page Header
;
tsrRetAd:	di	;Geen recursie vanwege `tsrFlags'
	ex af,af'                ;Haal vlaggenbyte uit de schaduw
r1TsrFlags::	ld (tsrFlags),a	;Bewaar het vlaggenbyte van de tsr
	ex af,af'                ;Databyte van TSR terug in AF
r7TsrSP::	ld (saveSP),sp	;Bewaar stack van de TSR
r8TsrSP::	ld sp,(callSP)	;Schakel over op interne stack
	ret	;Keer terug naar het manager-segment

overheadEnd	equ $	;Vrije ruimte start in tsr segmenten
overheadLn	equ $-overheadStart	;Lengte van de TSR Page Header


; getSlt2
;
; Bereken huidig slotbyte van pagina 2
; In:      Niets
; Uit:     A = slotbyte
; Wijzigt: HL, BC, AF
;
ppi_ar	equ 0a8h	;PPI port A

getSlt2:	in a,(ppi_ar)	;Deze routine werkt alleen op page2
	rrca	; en is dus redelijk snel
	rrca
	rrca
	rrca
	and 00000011B	;Prim. slot # in [A]
	ld h,high expTbl	;Hoog adres byte van tabel alvast in H
	add a,low expTbl	;Bereken low adres van expansion byte
	ld l,a	;Laag adresbyte in L
	sub low expTbl	;Herstel primair slot nummer
	or (hl)	;Set MSB indien ge‰xpandeerd
	ret p	;Not expanded, all done
	ld c,a	;Save primary slot number and exp-flag
	inc l	;Point to slttbl entry
	inc l	;     MSX Technical Data Book zegt
	inc l	;     inc hl i.p.v. inc l
	inc l	;     werkt allebei, inc l is sneller
	ld a,(hl)	;Get current contents of expansion
	rrca	; slotregister in bit 3,2
	rrca
	and 00001100B
	or c	;Expanded-flag en primslot in bit 7,1,0
	ret


; hookProces(sor)
;
; Deze routine zorgt ervoor dat een (eventueel meerdere keren) afgebogen hook
; bij de tsr('s) terecht komt.
;
; In: AF,HL,DE,BC = Data registes voor de tsr
;     SP	    = Call stack, originele stack pointer in saveSP
;     DI	    = Geen recursie, dan zou "saveSP" etc. overschreven worden
;
; Stack: Terugkeer adres naar de hook
;        Stack zoals bij aanroep van de hook
;        Interrupts Disabled
;
; Opm: Deze routine staat op een adres hoger dan 4025h, waardoor de ramdisk
;      versie 4.0 voor MemMan "veilig" inter-slot calls naar het adresgebied
;      tussen 4010h en 4025h kan afbuigen naar het ramdisk-segment. Indien
;      MemMan en de ramdisk beide in hetzelfde adresgebied zouden werken, zou
;      er geen onderscheid tussen calls naar MemMan en de Ramdisk gemaakt
;      kunnen worden.
;
hookProces:	exx	;Bewaar de dataregisters voor de tsr
	ex af,af'                ; in de schaduw

r1TsrCur::	ld hl,(cur2Seg)	;Haal segment-administratie van page 2
	push hl	;En bewaar die op de stack
	ld e,h	;Mapper page opslaan voor DOS1
	call getSlt2	;Bereken fysieke slotbyte van page 2
	ld l,a	;Naar register L
tc2ClGet::	db opcodeCALL	;Call opcode voor de dos2 getp2 call
tc2AdGet::	nop	;Opvullen voor DOS2 call adres
	ld a,e	;Mapper page voor DOS1 is cur2Seg
	ld h,a	;Mapperblok van DOS2 in register [H]
r2TsrCur::	ld (cur2Seg),hl	;Nu kunnen TSR's veilig USE2 gebruiken

r3TsrSP::	ld (callSP),sp	;Bewaar de interne stackpointer
r4TsrSP::	ld sp,(saveSP)	;Haal de originele stackpointer terug

	pop hl	;Adres van de CALL vanaf de hook

; tsrHookLoop
;
; Verwerkingslus voor de TSR's in de TSR-Tab
;
; In: HL=Pointer naar hookTab
;     TSR stack actief ("saveSP")
;
tsrHookLoop:	ld e,(hl)	;Haal de hookTab pointer op. Deze
	inc hl	; staat achter de call vanaf de
	ld d,(hl)	; hook opgeslagen.

	ex de,hl	;Poiner naar hookTab in HL halen
	ld c,(hl)	;Haal het aanroep adres van de tsr
	inc hl	; op uit de hookTab entry
	ld b,(hl)
	inc hl

	ld e,(hl)	;Haal de segmentcode op uit hookTab
	inc hl
	ld d,(hl)
	inc hl	;Pointer naar de oude hook data

	dec b	;Is de tsr DOOD?
	jp z,doPrevHook	; Ja, => vorige hook uitvoeren
	inc b	;Herstel het uitvoer adres

	ex de,hl	;Pointer in DE, segmentcode in HL

	push hl	;Bewaar de segmentcode even

	ld hl,tsrRetAd	;Terugkeer adres na uitvoer van de tsr
	ex (sp),hl	;Adres op de stack, segmentcode in HL

	push bc	;Uitvoer adres op de stack

r11TsrSP::	ld (saveSP),sp	;Bewaar orig. stack pnt.
r12TsrSP::	ld sp,(callSP)	;Naar interne stack

	push de	;Bewaar hooktab-pointer

r1CallSeg::	call callSeg	;Doe inter-segment/slot call naar TSR

	pop hl	;Herstel hooktab-pointer

r2TsrFlags::	ld a,(tsrFlags)	;Haal het vlaggen byte
	rrca	;Quithook vlag?
	jr c,hookReturn	; Ja, => keer terug

r9TsrSP::	ld (callSP),sp	;Bewaar interne stack
r10TsrSP::	ld sp,(saveSP)	;Schakel over op TSR stack

doPrevHook:	ld a,(hl)	;Eerste byte van de oude hook ophalen
	cp opcodeCALL	;Mogelijk door ons afgebogen?
	jr nz,notTsr	; Nee, => dit is niet een TSR

	push hl	;Bewaren voor alsnog oude hook uitvoer
	inc hl
	ld c,(hl)	;Haal het uitvoer adres van de call
	inc hl	; vanaf de hook op
	ld b,(hl)
	inc hl	;Wijst nu naar het hookTab word
	ex de,hl	;Sla dat adres op in DE
rMinHookIn::	ld hl,0	;'-HookIn' adres
	adc hl,bc	;Is het het hookIn adres? (NC door CP)
	pop hl	;Herstel de oude hookdata pointer
	jr nz,notTsr	;Klopt niet, oude hook uitvoeren

	ex de,hl	;HookTab pointer weer naar HL
	jp tsrHookLoop	;Volgende hook afwerken


; Hier komt de hook processor als de opgeslagen 'oude' hookdata van een door
; ons afgebogen hook niet OOK een door ons afgebogen hook is.
;
; De oude hookdata wordt naar pagina 3 gekopieerd om daar uitgevoerd te worden
; als de segmenten stand weer hersteld is.
;
notTsr:	ld de,tempHookBuf	;Op tempHook kan ie staan voor uitvoer
	push de	; in pagina 3, uitvoer ad op de stack
	ld bc,5	;Lengte van een hook
	ldir	;Kopieer de hookdata (int's zijn al uit)

r1TsrSP::	ld (saveSP),sp	;Bewaar de originele stackpointer
r2TsrSP::	ld sp,(callSP)	;De interne stackpointer ophalen


; Hier komt de hook processor als de quitHook vlag gezet is OF als er niet
; meer hooks in de chain zitten.
;
; De opgeslagen data registers worden weer teruggehaald en er wordt terug-
; gekeerd naar pagina 3 alwaar de slotstand hersteld wordt.
;
; Uit: AF,DE,BC,HL = Data registers van de tsr
;      SP	     = Call stack, originele stack pointer in saveSP
;
hookReturn:	pop hl	;Herstel Page 2 segment administratie
r3TsrCur::	ld (cur2Seg),hl	;Bewaren voor Use2 en getGur2
	exx	;Haal de dataregisters van de tsr
	ex af,af'                ; weer uit de schaduw
	ret	;Terug naar pagina 3 (hookIn routine)


; fnc61Cont, Vervolg van pagina 3 (MEMNWEX)
;
; Roep het interactie adres van een tsr aan.
;
; In:  AF,HL,DE,BC = Dataregisters voor de TSR
;       (savTsrID) = TSR-ID
;
; Uit: AF, HL, DE, BC = Dataregisters van de TSR
;
fnc61Cont:
r1XCall::	ld ix,(savTsrID)	;Haal TSR-ID uit systeemgeheugen
	jr doCallTsr	;Voer TSR-call uit


; tsrCall (63)
;
; Roep het interactie adres van een tsr aan.
;
; In:  AF,HL,DE = Dataregisters voor de TSR
;            BC = TSR-ID
;
; Uit: AF, HL, DE, BC = Dataregisters van de TSR
;
fnc63Ad:	push bc	;TSR-ID verplaatsen naar IX
	pop ix

	di	;Was aangezet door functionhandler

doCallTsr:	exx	;Bewaar de registers voor de tsr
	ex af,af'                ; in de schaduw

	ld hl,tsrRetAd	;Daar terugkeren na de aanroep
	push hl	;Adres naar de stack voor terugkeer

	ld l,(ix+9)	;Driver adres van de tsr uit de
	ld h,(ix+10)	; tsrTab halen
	push hl	;Adres naar de stack voor uitvoer

r13TsrSP::	ld (saveSP),sp	;Bewaar orig. stack pnt.
r14TsrSP::	ld sp,(callSP)	;Naar interne stack

	ld l,(ix+1)	;Haal de segmentcode op van het segment
	ld h,(ix+2)	; waarin de tsr zich bevindt

r2CallSeg::	call callSeg	;Roep de tsr aan

r15TsrSP::	ld (callSP),sp	;Bewaar interne stack pointer
r16TsrSP::	ld sp,(saveSP)	;Terug naar program stack

	exx	;Haal de dataregisters van de tsr
	ex af,af'                ; weer uit de schaduw

	ret	;Terug naar aanroepende programma


; extBioTsr
;
; Dit zijn de routines die bij memMan behoren, maar in het tsrMan segment
; geplaatst zijn om de grootte van de code onder highMem zo klein mogelijk
; te houden.
;
	include MEMEXTSR.MAC    ;ExtBios code in het tsrMan segment


; CMD TL
;
; TsrLoader. Deze routines handelen het commando CMD TL af. De code
; wordt als een gewone TSR geinstalleerd.
;
	include MEMTL.MAC


; CMD TK
;
; TsrKill. Deze routines handelen het commando CMD TK af. De code
; wordt gekoppeld aan die van CMD TL.
;
	include MEMTK.MAC

; CMD TV
;
; TsrView. Deze routines handelen het commando CMD TV af. De code
; wordt gekoppeld aan die van CMD TK.
;
	include MEMTV.MAC

; ATTR$ FT
;
; FindTsr. Deze routine zoekt een TSR.
;
	include MEMFT.MAC


; tsrPntTab
;
; Dit is een info tabel met pointers naar de verschillende tabellen die
; door de tsrManager beheert worden. Op adres 4000h in het tsrManager segment
; staat een pointer naar deze tabel.
;
; Indeling: +0 = tsrTab   -> tsr's administratie
;           +2 = hookTab  -> afgebogen hooks administratie
;
tsrPntTab:	defw 0	;Tsr's administratie tabel
	defw 0	;Afgebogen hooks administratie tabel

; tsrTab
;
; In deze tabel worden de tsr administratie gedaan.
; Iedere tsr heeft 1 entry in deze tabel, ongeacht het aantal hooks dat
; naar de tsr is afgebogen.
;
; tsrTab: +0	  Aantal entries in de tabel
;         +1..  Entries; Lengte = 23 bytes per entry
;
; Entry Structuur:
;
; +0      Entry status
; +1,2    Segmentcode van het blok geheugen
; +3,4    Startadres van het blok geheugen
; +5,6    Lengte van het blok geheugen
; +7,8    Destructie adres van de tsr
; +9,10   Driver (= interactie adres) van de tsr
; +11..22 Naam van de tsr (12 tekens)
;
; Over de Entry Status (+0):
;
; 00h = Ongebruikte entry
; 01h = Geheugen 'flard' registratie
; 02h = Systeem-TSR, niet verwijderbaar
; 80h = Actieve TSR entry, wel verwijderbaar
;
; Opm: Op de eerste entry van de tabel staat, na de installatie van memman,
;      altijd de 'rest' van het manager segment geregistreerd als vrij
;      geheugen.
;
; Deze tabel is van variabele grootte en daarom niet hier gedefinieerd

; hookTab
;
; In deze tabel wordt de afgebogen hooks administratie gedaan.
; Iedere tsr die een waar een hook naartoe gaat heeft 1 entry in
; de tabel. Meerdere entries kunnen dus naar elkaar verwijzen omdat
; meerdere tsr's ze afgebogen hebben.
;
; hookTab: +0    Aantal entries in de tabel
;          +1..  Entries; Lengte = 14
;
; Structuur:
;
; +0      Entry Status
; +1,2    Uitvoer adres in de tsr
; +3,4    Segmentcode waarin de tsr staat
; +5..9   Oude hook data
; +10,11  Adres van de tsr entry in tsrTab voor hook verwijdering
; +12,13  Adres waar de oude hookdata eerst stond
;
; Over de Entry Status (+0):
;
; 00h = Ongebruikte entry
; 01h = Dode doorverwijs hook
; 80h = Actieve TSR hook
;
; Deze tabel is van variabele grootte en daarom niet hier gedefinieerd

; neSegTab
;
; Dit is de in het tsrManager segment gekopieerde segmenten tabel
; De structuur staat beschreven aan het eind van memSrch.gen
;
; Deze tabel is van variabele grootte en daarom niet hier gedefinieerd

mmSegLn	equ $-4000h

	.dephase	;Herstel de .phase

	end
