home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ST-Computer Leser-CD 1999 January
/
STC_CD_01_1999.iso
/
base
/
pd_ph105
/
pd_lib.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-08
|
40KB
|
1,233 lines
/* V 1.05
(c) 1997,98 by Dimitri Junker
Adenauerallee 30
52066 Aachen */
/* Dies sind die C-Funktionen, die in PD eingefügt werden können*/
/* Zum Sprachgebrauch: Bei der 2 Monitorlösung unterscheide ich zwischen:
AES-Monitor: der über den das AES ausgibt, also der an der Grafikkarte
Bitmap-Monitor: der, der per Offscreen-Bitmap beschrieben wird
und am Original-Videoshifter hängt
Alle Routinennamen enden mit _1,_0,_2 oder _x, dabei bedeutet:
_1 : Routinen für den 1 Monitorbetrieb
_2 : Routinen für den 2 Monitorbetrieb
_x : Routinen für die implementierung von XBRA (unabhängig von der Anzahl Monitore)
_0 : alle anderen (unabhängig von der Anzahl Monitore)
*/
/* -------------------------------------------------------------------- */
/* Includes */
/* -------------------------------------------------------------------- */
#include <vdi.h>
#include <aes.h>
#include <stddef.h>
#include "patch.h"
#include "grafik.h"
/* -------------------------------------------------------------------- */
/* Makros. & Konstanten */
/* -------------------------------------------------------------------- */
#define min(a, b) ((a) < (b) ? (a) : (b))
#define _sysbase (0x4f2l)
#define EdDI_1_1 1
#define NOVA 2
/* Die 3 logischen Monitore */
#define BITMAP_MON1 0
#define BITMAP_MON2 1
#define AES_MON 2
/* Die folgenden Konstanten beschreiben die vorhandene Grafikhardware*/
#define ST_MOD 0
#define TT_MOD 2
/* -------------------------------------------------------------------- */
/* typedefs */
/* -------------------------------------------------------------------- */
typedef char BOOLEAN;
typedef struct BL
{ struct BL* bl_next;
unsigned long bl_len;
}BLOCK;
typedef struct XB
{
long xb_magic; /* "XBRA" = 0x58425241 */
long xb_id; /* ID aus vier ASCII-Zeichen */
struct XB *xb_oldvec; /* alter Wert des Vektors */
} XBRA;
/* -------------------------------------------------------------------- */
/* lokale Funktionsprototypen */
/* -------------------------------------------------------------------- */
void prg_reset_a(void);
void Set_Gd_trm(void);
long init_sup_0(void);
long init_sup_2(void);
long set_mon_2(void);
long get_cookie_jar_0();
BOOLEAN get_cookie_0(long cookie_name, LONG *cookie_value);
void draw_menu(void);
void v_opn_init_2( int *work_in_alt, int *handle,int *work_out );
long Supexec_0( long (*func)( ));
void vdi_2( VDIPB *vdipb );
BASPAG *get_act_pd_0(void);
void tst_sysv_x(BLOCK *mem);
void tst_1sysv_x(BLOCK *mem,int vec,XBRA **addr);
int mfree_l1_0(BLOCK *mem);
void mfree_a_sp_0(void);
void mfree_a_sp(void);
void res_sysv_x(void (*exchdlr)() ,int vec,XBRA **addr);
int memcpyx( void *dest, const void *src, size_t len );
/* -------------------------------------------------------------------- */
/* Globale Variablen */
/* -------------------------------------------------------------------- */
extern MFDB M_pd;
extern PDX X_pd;
extern int b_23E58;
extern void *Mem_l1,*Prg_a_sp;
extern void (*Ptr_Gemd)(),(*Ptr_term)(),(*Ptr_scrd)(),(*Ptr_vb)() ;
extern long My_id;
/* -------------------------------------------------------------------- */
/* Funktionen */
/* -------------------------------------------------------------------- */
/* -------------------------------------------------------------------- */
/* Routinen die sowohl für den 1 als auch den 2 Monitorbetrieb */
/* verwendet werden au₧er XBRA ( _0) */
/* -------------------------------------------------------------------- */
/*------------------------------------------------------------------*/
/* long init_sup_0(void) */
/* */
/* Der Teil der Initialisierung, der im Supervisormodus */
/* ausgeführt werden mu₧. Wird von v_opn_init_1 und _2 */
/* benutzt. */
/* Als long, damit es direkt von Supexec ausgeführt */
/* werden kann */
/* Parameter: keine */
/* Rückgabe : 0 als Dummy */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
long init_sup_0(void)
{
/* hier wird ermittelt, ob TRAP 6 oder 8 Byte auf den SSP legt.
Shortframe oder Longframe */
X_pd.p_frame=((*(int *)0x59EL) ? 8 : 6 );
/* Basepage ermitteln */
X_pd.p_bp=get_act_pd_0();
return(0);
}
/*------------------------------------------------------------------*/
/* BASPAG *get_act_pd_0(void) */
/* */
/* Basepage des aktuellen Proz. ermitteln */
/* nach Profibuch S.185 */
/* */
/* Parameter: keine */
/* Rückgabe : die Basepage */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
BASPAG * get_act_pd_0(void)
{ SYSHDR *os;
os=*(SYSHDR **)_sysbase;
os=os->os_base;
return((BASPAG *)*os->_run);
}
/*------------------------------------------------------------------*/
/* void reset_0(void ) */
/* */
/* fügt beim Programm-Reset auch noch ein Fclose aller */
/* offenen Dateien durch, ruft dann das Original auf */
/* */
/* Parameter: keine */
/* Rückgabe : keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void reset_0(void )
{ int i;
long tst;
tst=64l;
for(i=6;i<32;i++)
{ if((X_pd.p_flags[1]&tst)!=0l)
Fclose(i);
tst*=2l;
}
tst=1l;
for(i=32;i<64;i++)
{ if((X_pd.p_flags[0]&tst)!=0l)
Fclose(i);
tst*=2l;
}
/* Diese Abfrage ist eigentlich Teil des Original reset, wird aber
beim Patch überschrieben, s. Patch.C */
if(b_23E58!=-1)
prg_reset_a();
}
/*------------------------------------------------------------------*/
/* BOOLEAN get_cookie_0(long cookie_name, LONG *cookie_value) */
/* Ermittelt den Wert eines Cookies */
/* kommt auch in EASYFSEL.C vor */
/* Parameter: cookie_name: Name des zu suchenden Cookies */
/* *cookie_value: Pointer für die Rückgabe */
/* Rückgabe : 0,1: 1=erfolgreich */
/* falls 1: Wert des Cookies in cookie_value */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
BOOLEAN get_cookie_0(long cookie_name, LONG *cookie_value)
{
LONG *cookie;
int ret;
/* Zuerst einen Zeiger auf den Cookie holen */
if((cookie = (long *)Supexec_0(get_cookie_jar_0))==NULL)
ret=0;
else
{
do
{
/* Ist es unser Cookie ? */
if(*cookie== cookie_name)
break;
else
{
/* nächster Cookie aus Jar */
cookie = &(cookie[2]);
}
}
while(cookie[0]); /* solange nicht NULL-Cookie */
if(!cookie[0])
ret=0;
else
{ *cookie_value=cookie[1];
ret=1;
}
}
return(ret);
}
/*------------------------------------------------------------------*/
/* long get_cookie_jar_0() */
/* */
/* Ermittelt die Adresse des Cookie Jar. */
/* kommt auch in EASYFSEL.C vor */
/* */
/* Parameter:keine */
/* Rückgabe :Adresse, falls der Cookie Jar gefunden wurde, */
/* NULL falls kein Cookie-Jar */
/* Besonderheit: mu₧ per Supexec aufgerufen werden */
/* (c) by Dimitri Junker 1996 */
/*------------------------------------------------------------------*/
long get_cookie_jar_0()
{
LONG *cookiejar;
cookiejar = *((LONG **) 0x5a0L);
return((long)cookiejar);
}
/*------------------------------------------------------------------*/
/* void *malloc_high_0(unsigned long len) */
/* */
/* Diese Routine reserviert Speicher an möglichst hoher */
/* Stelle. Sie entstand aus der Originalroutine, die ich */
/* per Hand von Assembler nach C rückcompiliert habe. */
/* Ursprünglich nur um zu sehen was sie macht. Dabei */
/* fielen mir aber 2 Fehler auf, sie sind unten beschrieben*/
/* */
/* Parameter: Die Länge des gewünschten Speichers */
/* Rückgabe : Pointer auf den reservierten Speicher oder */
/* NULL falls nicht erfolgreich */
/* */
/* */
/*------------------------------------------------------------------*/
void *malloc_high_0(unsigned long len)
{ BLOCK *block,*h_block_1,*h_block_2;
unsigned long len_1;
len+=8;
len=(len+3)&0xfffffffcl;
h_block_1=NULL;
/* Solange grö₧te Speicherblöcke reservieren wie >8 Byte vorhanden
und verketten*/
while(1)
{ len_1=(long)Malloc(-1);
if(len_1<8)
break;
block=Malloc(len_1);
/* im Original wurde abgebrochen wenn Malloc erfolglos ist.
dies ist bei einem Multitasking-BS aber unsinnig */
if(block)
{ block->bl_next=h_block_1;
block->bl_len=len_1;
h_block_1=block;
}
}
h_block_2=NULL;
block=h_block_1; /* letzter erfolgreicher */
/* sucht genügend gro₧en Block mit höchster Addresse */
while(block)
{ if( block>h_block_2)
{ if(len <= block->bl_len)
h_block_2 = block;
}
block=block->bl_next;
}
/* Falls Block zu gro₧ nur oberen Teil reservieren */
if(h_block_2)
{ /* in den beiden nächsten Zeilen habe ich die '64' eingefügt.
Grund: MagiC hat pro Block einen Overhead von 32 Byte, aus
Sicherheitsgründen habe ich mal das doppelte genommen */
if(h_block_2->bl_len >= 8+len+64)
{ Mshrink(0,h_block_2,h_block_2->bl_len-len-64);
block=Malloc(len);
}
else
block=h_block_2;
}
/* alle anderen freigeben */
while(h_block_1)
{ h_block_2=h_block_1;
h_block_1=h_block_1->bl_next;
if(h_block_2!=block)
Mfree(h_block_2);
}
/* besser irgendwo als kein Speicher */
if(!block)
block=Malloc(len);
/* falls erfolgreich noch in Mem_l1 eintragen */
if(!block)
return(NULL);
else
{ block->bl_next=Mem_l1;
Mem_l1=block;
block->bl_len=len;
return(&block[1]);
}
}
/*------------------------------------------------------------------*/
/* int mfree_l1_0(BLOCK *mem) */
/* */
/* PD verwaltet den Speicherplatz in verschiefdenen */
/* verketteten Listen. Eine nenne ich Mem_l1. */
/* Das Original gibt einen Speicherblock aus dieser Liste */
/* frei. Da es sein könnte, da₧ dort Programmcode steht */
/* prüfe ich zusätzlich, ob ein Systemvektor hierhin zeigt */
/* Und entferne ihn ggf. */
/* */
/* Parameter: der freizugebende Speicher */
/* Rückgabe : 0: erfolgreich */
/* */
/* */
/*------------------------------------------------------------------*/
int mfree_l1_0(BLOCK *mem)
{ BLOCK *blk,*last;
int ret=-1;
mem--;
blk=Mem_l1;
last=(BLOCK *)&Mem_l1;
while(blk)
{ if(blk==mem)
{ last->bl_next=blk->bl_next; /* Aus Kette entfernen */
blk->bl_next=NULL; /*nur ein Block auf XBRA testen */
tst_sysv_x(blk);
ret=Mfree(blk);
break;
}
blk=blk->bl_next;
}
return(ret);
}
/*------------------------------------------------------------------*/
/* void mfree_a_sp_0(void) */
/* */
/* ähnlich wie die vorige Routine, allerdings wird hier der */
/* gesammte Speicher aus der Liste Prg_a_sp freigegeben */
/* dabei handelt es sich um den vom zu debuggenden Programm */
/* mit Malloc oder Mxalloc reservierten Speicher */
/* Parameter: keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void mfree_a_sp_0(void)
{ tst_sysv_x(Prg_a_sp);
mfree_a_sp(); /* die Originalroutine */
}
/* -------------------------------------------------------------------- */
/* Routinen die für den 1 Monitorbetrieb verwendet werden ( _1) */
/* -------------------------------------------------------------------- */
/*------------------------------------------------------------------*/
/* void v_opn_init_1( int *work_in, int *handle,int *work_out )*/
/* */
/* Im Einmonitorbetrieb ist zwar keine Alternative zu v_opnvwk */
/* nötig, aber da die Stelle gut für Initialisierung ist... */
/* Hier wird die Basepage ermittelt, Falls eine NOVA-Karte */
/* aktiv ist, wird der Mxalloc Modus auf 3 gesetzt, für andere */
/* Karten einfach selber testen */
/* */
/* Parameter: s. Original v_opnvwk */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void v_opn_init_1( int *work_in, int *handle,int *work_out )
{ ICB *icb;
Supexec_0(init_sup_0);
v_opnvwk(work_in,handle,work_out );
if (get_cookie_0('IMNE',(long *)&icb))
X_pd.p_bs_m=3;
X_pd.p_ms=-1;
}
/*------------------------------------------------------------------*/
/* void vq_mouse_1( int handle, int *pstatus, int *x,int *y ) */
/* */
/* Ersetzt vq_mouse */
/* Falls im 1-Monitorbetrieb in die Menüzeile geklickt */
/* wird, diese restaurieren falls die rechte Maustaste */
/* gedrückt wird: Mauszeiger aktivieren */
/* */
/* Parameter: s. vq_mouse */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void vq_mouse_1( int handle, int *pstatus, int *x,int *y )
{ vq_mouse(handle,pstatus,x,y );
if((*y<18 && *pstatus && !X_pd.p_ms)||X_pd.p_ms<0)
draw_menu();
if(*pstatus>1) /*Eine andere Maustaste als die linke gedrückt*/
{ v_show_c(handle,0);
*pstatus&=1; /*Vor PD verbergen */
}
X_pd.p_ms=*pstatus;
}
/*------------------------------------------------------------------*/
/* void Setscreen_1( void *laddr, void *paddr, int rez ) */
/* */
/* ersetzt Setscreen */
/* */
/* Aus mir noch unklaren Gründen gibt es teilweise */
/* Probleme mit Setscreen (Absturz). Wenn PD feststellt, */
/* da₧ Setscreen nicht funktioniert, arbeitet es ohne. */
/* Die einfachste Methode Setscreen nicht funktionieren zu */
/* lassen ist gar nichts zu tuen -> */
/* Parameter: s. Setscreen */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
#pragma warn -par
void Setscreen_1( void *laddr, void *paddr, int rez )
{ }
#pragma warn +par
/*------------------------------------------------------------------*/
/* void *Mxalloc_1( long amount, int mode ) */
/* ersetzt Mxalloc */
/* */
/* falls in v_opn_init_1 X_pd.p_bs_m umgesetzt wurde wird */
/* nicht mehr ST-RAM für den 2. Bildschirm verwendet */
/* Parameter: s.Mxalloc */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
#pragma warn -par
void *Mxalloc_1( long amount, int mode )
{ return(Mxalloc(amount,X_pd.p_bs_m ));
}
#pragma warn +par
/* -------------------------------------------------------------------- */
/* Routinen die für den 2 Monitorbetrieb verwendet werden ( _2) */
/* -------------------------------------------------------------------- */
/*------------------------------------------------------------------*/
/* void *Physbase_2(void) */
/* und void *Logbase_2(void) */
/* */
/* Im 2 Monitorbetrieb müssen PD teilweise andere Phys- bzw. */
/* Logbase Adressen gemeldet werden, als dies die */
/* Betriebssystemroutinen machen würden. */
/* */
/* Parameter: keine */
/* Rückgabe : Die vorzugaukelnde Adresse */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void *Physbase_2(void)
{ if(X_pd.p_phys==AES_MON)
return(Physbase());
else
return(X_pd.p_baddr[X_pd.p_phys]);
}
void *Logbase_2(void)
{ if(X_pd.p_log==AES_MON)
return(Logbase());
else
return(X_pd.p_baddr[X_pd.p_log]);
}
/*------------------------------------------------------------------*/
/* void v_opn_init_2( int *work_in_alt, int *handle,int *work_out )*/
/* ersetzt v_opnvwk */
/* */
/* Diese Routine wird einmal statt der normalen v_opnvwk */
/* ausgeführt, sie öfnet keine virtuelle WS, sondern eine */
/* Offscreenbitmap an der Stelle, an der sich der */
/* Bildschirmspeicher befindet. */
/* Au₧erdem wird sie noch einmal von Mxalloc_2 aufgerufen, um */
/* noch eine 2. Bitmap zu öffnen */
/* Beim 1. Aufruf wird auch noch einiges initialisiert, */
/* daher der Name */
/* */
/* Parameter: s. v_opnvwk */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void v_opn_init_2( int *work_in_alt, int *handle,int *work_out )
{ VDIPB vdipb;
int contrl[15], work_in[20],i,bm;
long farben,c_val;
int (*do_eddi)(int bn);
ICB *icb;
void *eddi;
/* 1. oder 2. Aufruf? */
if(X_pd.p_baddr[BITMAP_MON1]) /* Aufruf von Mxalloc für Bitmap[1] */
{ bm=BITMAP_MON2;
contrl[6]=work_in[0] =X_pd.p_bhdl[AES_MON];
}
else /* Aufruf von PD für Bitmap[0] */
{ bm=BITMAP_MON1;
if(get_cookie_0('_VDO', &c_val)) /* Grafikhardware ermitteln */
X_pd.p_masch=(int)(c_val>>16);
else
X_pd.p_masch=ST_MOD;
if (get_cookie_0('IMNE',(long *)&icb)) /* der NOVA-Cookie */
{ if (icb->id < '2.63') /* v_extnd ist fehlerhaft*/
X_pd.p_nova_alt=1;
if (icb->id >= '2.00') /* Zeichnen in Puffer erst ab Version 2.00:*/
X_pd.p_vopn=NOVA;
}
if(!X_pd.p_vopn)
{ if(get_cookie_0('EdDI',(long *)&eddi)) /* Off-Screen Bitmaps ? */
{ do_eddi=eddi;
if(do_eddi(0)>=0x0110)
X_pd.p_vopn=EdDI_1_1;
else
{ form_alert(1,"[3][Die VDI-Version unterstützt AFAIK|keine Offscreen-Bitmaps][Schade]");
*handle=0; /* Sollte PD zum Abbruch bewegen */
return;
}
}
}
X_pd.p_pdhdl=handle; /* hier speichert PD sein WS-Handel */
X_pd.p_baddr[BITMAP_MON1]=(void *)Supexec_0(init_sup_2);
X_pd.p_phys=X_pd.p_log=AES_MON; /* Aktuell AES-Monitor*/
X_pd.p_bhdl[AES_MON]=contrl[6]=work_in[0] = graf_handle(&i, &i, &i, &i);
}
/* Bitmap öffnen */
M_pd.fd_addr=X_pd.p_baddr[bm];
contrl[0]=100;
contrl[1]=0;
contrl[4]=0;
contrl[5]=1;
for(i=1;i<11;i++)
work_in[i]=work_in_alt[i];
work_in[11] = M_pd.fd_w-1;
work_in[12] = M_pd.fd_h-1;
vdipb.contrl=contrl;
vdipb.intin =work_in;
vdipb.intout=work_out;
vdipb.ptsout=work_out + 45;
/* nach NOVA oder EdDi Methode */
if(X_pd.p_vopn==NOVA)
{ work_in[13]=M_pd.fd_nplanes;
work_in[14]=1;
contrl[2]=6;
contrl[3]=15;
*((void **)(&contrl[7])) =M_pd.fd_addr;
}
else /* EdDi 1.1 */
{ work_in[13]=278; /* Breite eines Pixels in Mikrometern */
work_in[14]=278; /* Höhe eines Pixels in Mikrometern */
farben=1<<M_pd.fd_nplanes;
*(long *)&work_in[15]=farben;
work_in[17]=M_pd.fd_nplanes;
work_in[18]=0;
work_in[19]=1;
contrl[2]=0;
contrl[3]=20;
*((MFDB **)(&contrl[7])) =&M_pd;
}
vdi_2( &vdipb ); /* v_opnbm oder v_opnvwk2 */
X_pd.p_bhdl[bm]=*handle = contrl[6];
/* Bei meinen ersten Versuchen erschien die Schrift Wei₧ auf Wei₧,
deshalb sicherheitshalber auf Schwarz setzen */
contrl[0]=22;
contrl[1]=0;
contrl[2]=0;
contrl[3]=1;
contrl[4]=1;
contrl[5]=0;
contrl[6]=*handle;
work_in[0]=1;
vdipb.intout=work_in+3;
vdipb.ptsout=work_in+12;
vdi_2( &vdipb ); /* vst_color */
M_pd.fd_addr=X_pd.p_baddr[BITMAP_MON1];
}
/*------------------------------------------------------------------*/
/* long init_sup_2(void) */
/* */
/* Der Teil von v_opn_init_2, der im Supervisormode ausgeführt */
/* werden mu₧. Hier wird die Basepage ermittelt, die */
/* Bildschirmadresse (Bitmap-Monitor) bestimmt die Auflösung */
/* und die Farben gesetzt, letzteres wegen bildschirmschonern */
/* */
/* Parameter: keine */
/* Rückgabe : Bildschirmadresse als long wegen Supexec */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
long init_sup_2(void)
{ long addr;
Supexec_0(init_sup_0);
addr=(long)(*(unsigned char *)0xffff8201l);
addr=addr<<8;
addr|=(long)(*(unsigned char *)0xffff8203l);
addr=addr<<8;
if(X_pd.p_masch!=ST_MOD)
addr|=(long)(*(unsigned char *)0xffff820dl);
*( char *)0xffff8260l=X_pd.p_res;
if(X_pd.p_masch==TT_MOD)
{ *( char *)0xffff8262l&=0xF8;
*( char *)0xffff8262l|=X_pd.p_res;
*( int *)0xffff85fcl=0; /* Schwarz */
*( int *)0xffff85fel=0xfff; /* Wei₧ */
}
return(addr);
}
/*------------------------------------------------------------------*/
/* v_clsbm_2( int handle ) */
/* ersetzt v_clsvwk */
/* */
/* Die 2 Bitmap-WS abmelden und Bildschirm löschen, */
/* ist besser für den Monitor */
/* Parameter: s. v_clsvwk, wird aber ignoriert */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
#pragma warn -par
void v_clsbm_2( int handle )
{ VDIPB vdipb;
int contrl[15],dummy[20],pxy[8];
/* Bildschirm löschen */
pxy[0]=pxy[1]=pxy[4]=pxy[5]=0;
pxy[2]=pxy[6]=M_pd.fd_w-1;
pxy[3]=pxy[7]=M_pd.fd_h-1;
M_pd.fd_addr=X_pd.p_baddr[BITMAP_MON1];
vro_cpyfm(X_pd.p_bhdl[BITMAP_MON1],ALL_BLACK,pxy,&M_pd,&M_pd);
/* Beide Workstations schlie₧en */
if(X_pd.p_vopn==NOVA)
{ v_clsvwk(X_pd.p_bhdl[BITMAP_MON1]);
v_clsvwk(X_pd.p_bhdl[BITMAP_MON2]);
}
else
{ contrl[0]=101;
contrl[1]=contrl[2]=contrl[3]=contrl[4]=0;
contrl[5]=1;
vdipb.contrl=contrl;
vdipb.intin =dummy;
vdipb.intout=dummy;
vdipb.ptsout=dummy;
contrl[6] = X_pd.p_bhdl[BITMAP_MON1];
vdi_2( &vdipb );
contrl[6] = X_pd.p_bhdl[BITMAP_MON2];
vdi_2( &vdipb );
}
}
/*------------------------------------------------------------------*/
/* void vq_extnd_nova_2( int handle, int owflag, int *work_out ) */
/* */
/* ersetzt vq_extnd */
/* */
/* NOVA-VDI <2.63 gibt bei vq_extnd eine falsche Anzahl */
/* Planes zurück */
/* */
/* Parameter: s. vq_extnd */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
#pragma warn +par
void vq_extnd_nova_2( int handle, int owflag, int *work_out )
{ vq_extnd(handle,owflag,work_out );
if(owflag && X_pd.p_nova_alt)
work_out[4]=M_pd.fd_nplanes;
}
/*------------------------------------------------------------------*/
/* void vq_mouse_2( int handle, int *pstatus, int *x,int *y ) */
/* ersetzt vq_mouse */
/* */
/* Mauszeiger auf 2. Bildschirm zeichnen... */
/* es wird davon ausgegangen, da₧ die Auflösung des */
/* AES-Monitors grö₧er oder gleich der des kleinen ist. */
/* vq_mouse wird regelmä₧ig aufgerufen, deshalb pa₧t es hier */
/* */
/* Parameter: s. vq_mouse */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void vq_mouse_2( int handle, int *pstatus, int *x,int *y )
{ int pxy[8],w,h,xv,yv;
MFDB m_s;
m_s=*&M_pd;
m_s.fd_w=m_s.fd_h=16;
m_s.fd_wdwidth=1;
/* Die Mausposition und Status erfragen */
vq_mouse(handle,pstatus,x,y);
/* Falls au₧erhalb des kleinen Bildschirms Offset verändern*/
xv=*x-X_pd.p_x_offs;
if(xv<0)
{ X_pd.p_x_offs=*x;
*x=0;
}
else
{ if(xv>=M_pd.fd_w)
{ X_pd.p_x_offs=*x+1-M_pd.fd_w;
*x=M_pd.fd_w-1;
}
else
*x=xv;
}
yv=*y-X_pd.p_y_offs;
if(yv<0)
{ X_pd.p_y_offs=*y;
*y=0;
}
else
{ if(yv>=M_pd.fd_h)
{ X_pd.p_y_offs=*y+1-M_pd.fd_h;
*y=M_pd.fd_h-1;
}
else
*y=yv;
}
/* Falls die Maus sich bewegt hat mu₧ der Zeiger neu gezeichnet werden
natürlich nur wenn nicht der AES-Monitor aktiv ist*/
if((*x!=X_pd.p_x || *y!=X_pd.p_y)&& X_pd.p_phys!=AES_MON)
{ m_s.fd_addr=X_pd.p_msave;
/* Falls Mauszeiger an war Hintergrund restaurieren */
if(X_pd.p_x!=-1)
{ w=min(16,M_pd.fd_w-X_pd.p_x)-1;
h=min(16,M_pd.fd_h-X_pd.p_y)-1;
pxy[0]=pxy[1]=0;
pxy[2]=w;
pxy[3]=h;
pxy[6]=w+(pxy[4]=X_pd.p_x);
pxy[7]=h+(pxy[5]=X_pd.p_y);
vro_cpyfm(handle,S_ONLY,pxy,&m_s,&M_pd);
}
/* Falls jetzt an: Mauszeiger zeichnen */
if(!X_pd.p_ms)
{ w=min(16,M_pd.fd_w-*x)-1;
h=min(16,M_pd.fd_h-*y)-1;
pxy[2]=w+(pxy[0]=*x);
pxy[3]=h+(pxy[1]=*y);
pxy[4]=pxy[5]=0;
pxy[6]=w;
pxy[7]=h;
vro_cpyfm(handle,S_ONLY,pxy,&M_pd,&m_s);
m_s.fd_addr=X_pd.p_mmaske;
pxy[0]=pxy[1]=0;
pxy[2]=w;
pxy[3]=h;
pxy[6]=w+(pxy[4]=*x);
pxy[7]=h+(pxy[5]=*y);
vro_cpyfm(handle,NOTS_AND_D,pxy,&m_s,&M_pd);
m_s.fd_addr=X_pd.p_mzeiger;
vro_cpyfm(handle,S_OR_D,pxy,&m_s,&M_pd);
X_pd.p_x=*x;
X_pd.p_y=*y;
}
else
X_pd.p_x=-1; /* beim nächsten mal nicht restaurieren */
}
}
/*------------------------------------------------------------------*/
/* void hide_curs_2( void ) */
/* und void show_curs_2( void ) */
/* ersetzt hide_curs und show_curs */
/* */
/* Ein- und ausschalten des Mauscursors mu₧ auf die 2 Monitore */
/* verteilt werden. */
/* */
/* Parameter: keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void hide_curs_2( void )
{ int pxy[8],w,h;
MFDB m_s;
m_s=*&M_pd;
X_pd.p_ms++;
if(X_pd.p_phys==AES_MON) /* AES-Monitor */
v_hide_c(X_pd.p_bhdl[AES_MON]);
else /* Bitmap-Monitor */
{ if(X_pd.p_x>-1) /* Wenn er sichtbar war löschen */
{ m_s.fd_w=m_s.fd_h=16;
m_s.fd_wdwidth=1;
m_s.fd_addr=X_pd.p_msave;
w=min(16,M_pd.fd_w-X_pd.p_x)-1;
h=min(16,M_pd.fd_h-X_pd.p_y)-1;
pxy[0]=pxy[1]=0;
pxy[2]=w;
pxy[3]=h;
pxy[6]=w+(pxy[4]=X_pd.p_x);
pxy[7]=h+(pxy[5]=X_pd.p_y);
X_pd.p_x=-1;
vro_cpyfm(X_pd.p_bhdl[X_pd.p_phys],S_ONLY,pxy,&m_s,&M_pd);
}
}
}
void show_curs_2( void )
{ int x,y,ps,reset=1;
if(reset)
{ if(X_pd.p_ms)
X_pd.p_ms--;
}
else
X_pd.p_ms=0;
if(X_pd.p_phys==AES_MON)
{ if(!X_pd.p_ms)
reset=0;
v_show_c(X_pd.p_bhdl[AES_MON],reset);
}
else
vq_mouse_2(X_pd.p_bhdl[X_pd.p_phys],&ps,&x,&y);
}
#pragma warn -par
/*------------------------------------------------------------------*/
/* void Setscreen_2( void *laddr, void *paddr, int rez ) */
/* ersetzt Setscreen */
/* */
/* auch das Setscreen mu₧ auf die 2 Monitore verteilt werden */
/* */
/* Parameter: s. Setscreen rez wird in PD nie verwendet */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void Setscreen_2( void *laddr, void *paddr, int rez )
{ int monitor;
if((long)laddr!=-1l) /* Logbase ändern? */
{ if(X_pd.p_baddr[BITMAP_MON1]==laddr) /* auf welchen virtuellen Monitor soll gesetzt werden?*/
monitor=BITMAP_MON1;
else
{ if(X_pd.p_baddr[BITMAP_MON2]==laddr)
monitor=BITMAP_MON2;
else
monitor=AES_MON;
}
*X_pd.p_pdhdl=X_pd.p_bhdl[monitor]; /* dadurch simulierenm, da₧ PD ein anderes Handle untergejubelt wird */
X_pd.p_log=monitor; /* und merken */
}
if((long)paddr!=-1l) /* Physbase ändern */
{ if(X_pd.p_baddr[BITMAP_MON1]==paddr) /* auf welchen virtuellen Monitor soll gesetzt werden?*/
monitor=BITMAP_MON1;
else
{ if(X_pd.p_baddr[BITMAP_MON2]==paddr)
monitor=BITMAP_MON2;
else
monitor=AES_MON;
}
hide_curs_2();
if(monitor!=AES_MON) /* Bitmap-Monitor */
{ M_pd.fd_addr=paddr; /* Adresse für Videoshifter umsetzen */
Supexec_0(set_mon_2);
} /* AES-Monitor ist ja immer sichtbar */
X_pd.p_phys=monitor;
show_curs_2();
}
}
/*------------------------------------------------------------------*/
/* long set_mon_2(void) */
/* */
/* Bildschirmadresse für Videoshifter setzen, also eine Art */
/* Setscreen */
/* */
/* Parameter: über M_pd und X_pd */
/* Rückgabe : 0 als dummy wg. Supexec */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
/* Bildschirmadresse für Videoshifter setzen, also eine Art Setscreen */
long set_mon_2(void)
{
*(unsigned char *)0xffff8201l=(unsigned char)((long)M_pd.fd_addr>>16);
*(unsigned char *)0xffff8203l=(unsigned char)((long)M_pd.fd_addr>>8);
if(X_pd.p_masch!=ST_MOD)
*(unsigned char *)0xffff820dl=(unsigned char)M_pd.fd_addr;
return(0l);
}
/*------------------------------------------------------------------*/
/* void *Mxalloc_2( long amount, int mode ) */
/* ersetzt Mxalloc */
/* */
/* Mxalloc wird nur benutzt, um Speicher für den 2. und 3. */
/* Bildschirm zu reservieren, da PD davon ausgeht, da₧ sie */
/* ST-RAM benötigen. Da der Speicher für den 2. Bildschirm bereits */
/* vom AES reserviert ist, kann beim 1. Aufruf von Mxalloc der */
/* Speicher zurückgegeben werden, auf den die VideoBase Register */
/* zeigen. Da PD sicherheitshalber immer auf die nächste durch 256 */
/* teilbare Adresse aufrundet, und zwar so, da₧ wenn die von */
/* Mxalloc zurückgegebene Adresse bereits durch 256 teilbar ist, */
/* er 256 hinzuaddiert: */
/* addr+=256; */
/* addr&=0xffffff00; */
/* */
/* mu₧ diese Routine eine Adresse kleiner als Videobase */
/* zurückgeben. */
/* PD ruft zuerst Mxalloc auf, wenn dieses einen Wert <=0 */
/* ( Assembler: ble ) zurückgibt wird nochmal mit Malloc probiert. */
/* Es reicht also Mxalloc zu ersetzen, auch auf TOS Versionen */
/* ohne Mxalloc. */
/* Problem: */
/* Falls Videobase nicht durch 256 teilbar ist, wird es Probleme */
/* geben. Dies ist bei mir nie der Fall gewesen, das AES reserviert*/
/* wohl aus Kompatibilitätsgründen immer Speicher an einer */
/* Seitengrenze. Falls aber irgendwann andere Programme den */
/* 2. Bildschirm nutzen, und evtl. Feinscrolling machen ist dies */
/* nicht mehr gesichert. Dann mü₧te z.B. das Aufrunden weggepatcht */
/* werden: add.l #$100,D0 */
/* and.l #-$100,D0 */
/* dies kommt 2* vor */
/* Oder in v_opnbm neuer Speicher reserviert werden. */
/* */
/* Parameter: s. Mxalloc */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void *Mxalloc_2( long amount, int mode )
{ int work_in[11],work_out[65],i;
void *ret;
switch((int)X_pd.p_mxa)
{ case 0:
X_pd.p_mxa++;
*X_pd.p_pdhdl=X_pd.p_bhdl[X_pd.p_log];
ret=(void*)((long)X_pd.p_baddr[BITMAP_MON1]-2l);
break;
case 1:
X_pd.p_mxa++;
ret=Mxalloc(amount,mode );
for(i=0;i<10;i++)
work_in[i]=1;
work_in[10]=2;
X_pd.p_baddr[BITMAP_MON2]=(void *)(((long)ret+256l)&0xffffff00l);
v_opn_init_2(work_in,&X_pd.p_bhdl[BITMAP_MON2],work_out);
break;
default: /* sollte zwar nicht vorkommen, aber...*/
ret=Mxalloc(amount,mode );
}
return(ret);
}
/*------------------------------------------------------------------*/
/* Routinen zur Implementierung von XBRA */
/*------------------------------------------------------------------*/
/*------------------------------------------------------------------*/
/* void tst_sysv_x(BLOCK *mem) */
/* */
/* */
/* Diese Routine prüft ob einer der Systemvektoren (1-107,256-263, */
/* und derzeit 17 weitere) in einen freizugebenden Speicherblock */
/* zeigt. Dabei werden nicht nur die direkt im Systemvektor */
/* vorhandenen Adressen geprüft, sondern alle per XBRA verketteten.*/
/* Die Speicherblöcke müssen PD typisch verkettet sein. */
/* mem zeigt auf den 1. */
/* Parameter: mem s.o. */
/* Rückgabe : keine */
/* */
/* (c) Dimitri Junker */
/* Dank an Bernhard Held, der mir eine Liste der infragekommenden */
/* Vektoren zur Verfügung stellte. */
/*------------------------------------------------------------------*/
void tst_sysv_x(BLOCK *mem)
{ int vec_nr,anz_addr;
XBRA **vec_addr[]={ (XBRA **)0x42a,(XBRA **)0x46a,(XBRA **)0x46e,
(XBRA **)0x472,(XBRA **)0x476,(XBRA **)0x47a,(XBRA **)0x47e,
(XBRA **)0x4f6,(XBRA **)0x502,(XBRA **)0x506,(XBRA **)0x50a,
(XBRA **)0x50e,(XBRA **)0x512,(XBRA **)0x592,(XBRA **)0x5a0,
(XBRA **)0x5ac,(XBRA **)0x5b0};
if(!mem)
return;
for(vec_nr=1;vec_nr<108;vec_nr++) /* Vektoren 1-107 */
tst_1sysv_x(mem,vec_nr,NULL);
for(vec_nr=256;vec_nr<264;vec_nr++) /* Vektoren 256-263 */
tst_1sysv_x(mem,vec_nr,NULL);
anz_addr=(int)(sizeof(vec_addr)/sizeof(*vec_addr));
for(vec_nr=1;vec_nr<anz_addr;vec_nr++) /* Vektoren an krummen Adressen */
tst_1sysv_x(mem,0,vec_addr[vec_nr]);
}
/*------------------------------------------------------------------*/
/* void tst_1sysv_x(BLOCK *mem,int vec,XBRA **addr) */
/* */
/* */
/* Diese Routine prüft ob ein Systemvektor in einen freizugebenden */
/* Speicherblock zeigt. */
/* s.a. tst_sysv_x */
/* Da es auch nichtinitialisierte Vektoren gibt, die ins Nirwana */
/* zeigen könnte es bei normaler Vorgehensweise zu Abstürzen */
/* kommen. memcpyx ist eine PD interne Routine, die versucht */
/* Speicher zu kopieren und zurückgibt ob dies erfolgreich war */
/* oder ob die Adresse ungültig war */
/* Der zu prüfende Vektor kann auf 2 Arten übergeben werden, */
/* entweder als Vektornummer (s. Setexc) oder als Addresse */
/* Parameter: mem: s. tst_sysv_x. */
/* vec: zu prüfender Vektor, wie für Setexc oder 0 */
/* addr: zu prüfender Vektor, wird nur benutzt */
/* wenn vec=0 */
/* Rückgabe : keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void tst_1sysv_x(BLOCK *mem,int vec,XBRA **addr)
{ XBRA sv,*svp,*last;
BLOCK *bl;
int do_del;
if(vec)
svp=((XBRA *)Setexc(vec,(void(*)())-1))-1; /*Vektor holen */
else
memcpyx(&svp,addr,sizeof(*addr)); /*Addr ist zwar gültig aber geschützt*/
if(memcpyx(&sv, svp,sizeof(sv)))
sv.xb_magic=0l; /*ungültige Adresse */
last=NULL;
while(sv.xb_magic=='XBRA') /* Nur die, die eine gültige XBRA Struktur haben */
{ bl=mem;
do_del=0;
/* prüfen ob die Adresse in einem der Blöcke liegt */
{ if((long)svp>=(long)bl &&(long)svp<(long)bl+bl->bl_len)
do_del=1; /* löschen */
}while((bl=bl->bl_next)!=NULL && !do_del);
if(do_del)
{ if(!last) /* am Anfang der Kette */
if(vec)
Setexc(vec,(void(*)())svp->xb_oldvec);
else
memcpyx(addr,&svp->xb_oldvec,sizeof(*addr));
else
last->xb_oldvec=svp->xb_oldvec;
break;
}
else
last=svp;
svp=sv.xb_oldvec-1;
if(memcpyx(&sv, svp,sizeof(sv)))
sv.xb_magic=0l;
}
}
/*------------------------------------------------------------------*/
/* void tst_sysva_x(void) */
/* */
/* */
/* tut das gleiche wie: */
/* { tst_sysv_x(Mem_l1); */
/* tst_sysv_x(Prg_a_sp); */
/* } */
/* aber schneller, denn bei obiger Methode mü₧ten alle */
/* Systemvektoren 2* durchsucht werden, so nur 1*. */
/* Parameter: keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void tst_sysva_x(void)
{ BLOCK *bl,*all;
bl=Mem_l1;
if(bl)
{ while(bl->bl_next)
bl=bl->bl_next;
bl->bl_next=Prg_a_sp;
all=Mem_l1;
}
else
all=Prg_a_sp;
tst_sysv_x(all);
if(bl)
bl->bl_next=NULL; /*wahrscheinlich unnötig */
}
/*------------------------------------------------------------------*/
/* void res_gd_trm_x(void) */
/* */
/* restauriert Gemdos und etv_term nach XBRA */
/* Parameter: keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
/* Diese Routine ist die letzte die die Systemvektoren restauriert */
void res_gd_trm_x(void)
{
res_sysv_x(Ptr_Gemd,33,NULL);
res_sysv_x(Ptr_term,258,NULL);
}
/*------------------------------------------------------------------*/
/* void res_hcop_vb_x(void) */
/* */
/* restauriert Scrdmp und Vertical Blank nach XBRA */
/* Parameter: keine */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void res_hcop_vb_x(void)
{
res_sysv_x(Ptr_scrd,0,(XBRA **)0x502);
res_sysv_x(Ptr_vb,28,NULL);
}
/*------------------------------------------------------------------*/
/* void (*res_sysv_x(void (*exchdlr)() ,int vec,XBRA **addr)) () */
/* */
/* */
/* eigene Routine aus XBRA Kette ausklinken. Eigentlich reicht */
/* dafür die Nummer, aber falls die XBRA Kette unterbrochen ist*/
/* klappt das nicht. Deshalb kann für diesen Fall sozusagen */
/* klassisch der zu setzende Vektor angegeben werden, ist */
/* exchdlr=NULL, so wird nur XBRA berücksichtigt */
/* Parameter: exchdlr: Originalwert */
/* vec: zu prüfender Vektor, wie für Setexc oder 0 */
/* addr: zu prüfender Vektor, wird nur benutzt */
/* wenn vec=0 */
/* Rückgabe : voriger Wert */
/* */
/* (c) Dimitri Junker */
/* */
/*------------------------------------------------------------------*/
void res_sysv_x(void (*exchdlr)() ,int vec,XBRA **addr)
{ XBRA *svp,*last=NULL;
if(vec)
svp=((XBRA *)Setexc(vec,(void(*)())-1))-1; /*Vektor holen */
else
memcpyx(&svp,addr,sizeof(*addr)); /*Addr ist zwar gültig aber geschützt*/
while(svp->xb_magic=='XBRA') /* Nur die, die eine gültige XBRA Struktur haben */
{ if(svp->xb_id==My_id)
{ if(!last) /* am Anfang der Kette */
{ if(vec)
Setexc(vec,(void(*)())svp->xb_oldvec);
else
memcpyx(addr,&svp->xb_oldvec,sizeof(*addr));
}
else
last->xb_oldvec=svp->xb_oldvec;
exchdlr=NULL;
break;
}
else
last=svp;
svp=svp->xb_oldvec-1;
}
if(exchdlr) /* dann ist wohl die XBRA Kette unterbrochen */
{ if(vec)
Setexc(vec,exchdlr);
else
memcpyx(addr,&exchdlr,sizeof(*addr));
}
}