Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!lll-winken!lll-lcc!ames!oliveb!amiga!bart From: bart@amiga.UUCP (Barry A. Whitebook) Newsgroups: comp.sys.amiga Subject: System Wedges and Overscan for V1.2/V1.2.1 (example code) Message-ID: <1966@amiga.amiga.UUCP> Date: Tue, 17-Nov-87 23:07:59 EST Article-I.D.: amiga.1966 Posted: Tue Nov 17 23:07:59 1987 Date-Received: Fri, 20-Nov-87 20:47:24 EST Reply-To: bart@amiga.UUCP (Barry A. Whitebook) Organization: Commodore-Amiga Inc, Los Gatos, CA Lines: 849 Keywords: Overscan Wedges [ eat this source -- please!] this is amiga!bart: this demo code was written as ONE (of many possible examples) way of supporting overscan mouse limits under V1.2 or V1.2.1... it features a new idea of multi- tasking friendly "wedges" whose primary purpose is to avoid the complications involved in SetFunction() contention among various processes. ------------------------------- cut here ------------------------------------- #define INTUITIONPRIVATE #include #include #include #include #include #include #include #include #include #include #include #ifdef DEBUG #define KPRINTF #endif #ifdef KPRINTF #define printf kprintf #endif #define DEPTH 2 #define IS_PAL (((struct GfxBase *)GfxBase)->DisplayFlags & PAL) #define IS_NTSC (((struct GfxBase *)GfxBase)->DisplayFlags & NTSC) #define NORMAL_HEIGHT (((struct GfxBase *)GfxBase)->NormalDisplayRows) #define NORMAL_WIDTH (((struct GfxBase *)GfxBase)->NormalDisplayColumns) #define OVERSCAN_WIDTH 704 #define OVERSCAN_HEIGHT 236 #define WINDOW_FLAGS (ACTIVATE|SIMPLE_REFRESH|BORDERLESS|BACKDROP|RMBTRAP) #define IDCMP_FLAGS (ACTIVEWINDOW|INACTIVEWINDOW|MOUSEBUTTONS|MOUSEMOVE) #define MIN_WIDTH 30 #define MIN_HEIGHT 20 #define ALL_PLANES 0xFF #define FIRST_PLANE 0x01 #define V1_POINT_2 33 #define V1_POINT_2_POINT_1 34 #define MAXBYTES 256 #define JSR_ABS 0x4EB9 #define JSR_dPC 0x4EBA #define JMP_ABS 0x4EF9 #define JMP_dPC 0x4EFA #define RTS 0x4E75 struct Wedge { UWORD wedge_Vectors[6]; struct Library wedge_Library; WORD wedge_Offset; } ; UBYTE stringbuffer[MAXBYTES] = {NULL}; UBYTE PAL_STRING[] = "this is a PAL machine..."; UBYTE NTSC_STRING[] = "this is an NTSC machine..."; UBYTE ACTIVE_STRING[] = "this window is active..."; UBYTE INACTIVE_STRING[] = "this window is inactive..."; UBYTE SELECTUP_STRING[] = "the select button is up..."; UBYTE SELECTDOWN_STRING[] = "the select button is down..."; UBYTE MOUSEPOSITION_STRING[] = "the mouse position is: x = %u y = %u ..."; UBYTE TRAPDEBUG_STRING[] = "trapping lib = %lx offset = %ld ..."; UBYTE MENUDOWN_STRING[] = "the menu button is down, about to close the screen..."; UBYTE MOUSEBOUNDS_STRING[] = "mousebounds for this screen are : xmax = %u ymax = %u ..."; extern ULONG ibase_lock; extern struct ExecBase *SysBase; extern ULONG trap_function(); extern ULONG wedge; extern LONG LVOObtainSemaphore; extern WORD old_mousebounds[]; extern WORD new_mousebounds[]; struct GfxBase *GfxBase; struct IntuitionBase *IntuitionBase; struct Screen *test_screen=NULL; struct Window *test_window=NULL; struct NewScreen newscreen; struct NewWindow newwindow; struct Window *OpenWindow(); struct Screen *OpenScreen(); struct TextAttr Font = { "topaz.font", 8, FS_NORMAL, FPF_ROMFONT, }; UWORD x_pos= MIN_WIDTH, y_pos= MIN_HEIGHT; /***************************************************************************** * * overscan -- open an overscan screen under V1.2 or V1.2.1 and * install a trap to intercept calls to LockIBase() * set the mouse limits so that when the overscan screen * is first, the mouse can move to the overscan limits: * when another screen is first, restore the system limits... * *****************************************************************************/ overscan() { int error = FALSE; USHORT view_modes = NULL; struct IntuiMessage *message; if ((GfxBase = (struct GfxBase *) OpenLibrary("graphics.library",V1_POINT_2)) == NULL) { return(-1); } if( ((IntuitionBase = (struct IntuitionBase *) OpenLibrary("intuition.library",V1_POINT_2)) == NULL) ) { CloseLibrary(GfxBase); return(-2); } if(IntuitionBase->LibNode.lib_Version > V1_POINT_2_POINT_1) { CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); return(-3); } /* values for newscreen */ newscreen.LeftEdge = 0; newscreen.TopEdge = 0; newscreen.Width = OVERSCAN_WIDTH; newscreen.Height = OVERSCAN_HEIGHT; newscreen.Depth = DEPTH; newscreen.DetailPen = 0xff; newscreen.BlockPen = 0xff; /* specify view_modes */ if(OVERSCAN_WIDTH > 320) view_modes |= HIRES; newscreen.ViewModes = view_modes; newscreen.Type = CUSTOMSCREEN; newscreen.Font = &Font; newscreen.DefaultTitle = NULL; newscreen.Gadgets = NULL; test_screen = OpenScreen(&newscreen); if (test_screen == 0) { CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); return(-4); } else { ShowTitle(test_screen,FALSE); } newwindow.LeftEdge = 0; newwindow.TopEdge = 0; newwindow.Width = test_screen->Width; newwindow.Height = test_screen->Height; newwindow.DetailPen = 11; newwindow.BlockPen = 11; newwindow.Flags = WINDOW_FLAGS; newwindow.IDCMPFlags = IDCMP_FLAGS; newwindow.FirstGadget = NULL; newwindow.CheckMark = NULL; newwindow.Title = NULL; newwindow.Screen = test_screen; newwindow.BitMap = NULL; newwindow.MinWidth = MIN_WIDTH; newwindow.MinHeight = MIN_HEIGHT; newwindow.MaxWidth = test_screen->Width; newwindow.MaxHeight = ~0; /* V1_POINT_2 : tell Intuition to limit the */ /* maximum height of this window to screen's */ /* height */ newwindow.Type = CUSTOMSCREEN; test_window = OpenWindow(&newwindow); if(!test_window) { CloseScreen(test_screen); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); return(-5); } else { fill_window(test_window,ALL_PLANES); } /* trap to act before screens change */ print_message (test_window->RPort,trapdebug_string(SysBase,&LVOObtainSemaphore)); /* initialize lock comparison */ ibase_lock = (ULONG) &IntuitionBase->ISemaphore[IBASELOCK]; /* protect ourselves */ LockIBase(0); /* save current limits */ save_mousebounds(); /* proceed to mess with intuition's fields via the installed trap */ UnlockIBase(0); { /* store new limits */ new_mousebounds[0] = 0; new_mousebounds[1] = (view_modes & HIRES)? (test_screen->Width)-1: (test_screen->Width<<1)-1; new_mousebounds[2] = 0; new_mousebounds[3] = (view_modes & LACE)? (test_screen->Height)-1: (test_screen->Height<<1)-1; print_message(test_window->RPort,mousebounds_string(new_mousebounds)); } /* special function will only be executed while ibase_lock is free */ trap(SysBase,&LVOObtainSemaphore); /* tell the user whether we are pal or ntsc */ error = print_pal_or_ntsc_message(test_window->RPort); /* now wait for close message */ WAIT_LOOP: /* be nice, let other tasks run */ WaitPort(test_window->UserPort); /* ok, now look at all the messages that have arrived */ while((message=(struct IntuiMessage *)GetMsg(test_window->UserPort))!=NULL) { switch(message ->Class) { case ACTIVEWINDOW: { print_message(test_window->RPort,ACTIVE_STRING); }break; case INACTIVEWINDOW: { print_message(test_window->RPort,INACTIVE_STRING); }break; case MOUSEBUTTONS: { switch(message->Code) { case SELECTDOWN: { print_message (test_window->RPort,SELECTDOWN_STRING); print_message (test_window->RPort, mousebounds_string(new_mousebounds)); print_message (test_window->RPort,mouseposition_string(message)); }break; case SELECTUP: { print_message(test_window->RPort,SELECTUP_STRING); }break; case MENUDOWN: { print_message(test_window->RPort,MENUDOWN_STRING); }break; case MENUUP: { ReplyMsg(message); CloseWindow(test_window); CloseScreen(test_screen); CloseLibrary(IntuitionBase); CloseLibrary(GfxBase); untrap(SysBase,&LVOObtainSemaphore); return(error); }break; } }break; case MOUSEMOVE: { }break; default: { }break; } ReplyMsg(message); } goto WAIT_LOOP; } /***************************************************************************** * * support utilities -- handle the details... * *****************************************************************************/ trap(lib,offset) struct Library *lib; WORD offset; { if((lib)&&(offset<0)) { wedge = install_wedge(lib,offset,trap_function); } } untrap(lib,offset) struct Library *lib; WORD offset; { remove_wedge(wedge); } strlen(strptr) UBYTE *strptr; { unsigned int count = 0; while(*strptr != NULL) { count++; strptr++; } return(count); } Position(rp,xp,yp) struct RastPort *rp; UWORD *xp, *yp; { UWORD old_yp = *yp; if((*yp=MAX(MIN_HEIGHT,(old_yp+Font.ta_YSize)%test_screen->Height))RPort) && (bm=rp->BitMap) ) { SetDrMd(rp,JAM1); SetAPen(rp,planes); RectFill(rp,0,0,((bm->BytesPerRow<<3)-1),(bm->Rows-1)); } } print_pal_or_ntsc_message(rp) struct RastPort *rp; { int error = FALSE; if(IS_PAL) print_message(rp, PAL_STRING); if(IS_NTSC) print_message(rp, NTSC_STRING); if((IS_PAL) && (IS_NTSC)) error = TRUE; return(error); } print_message(rp,string) struct RastPort *rp; STRPTR string; { int error = FALSE; SetDrMd(rp,JAM1); SetAPen(rp,FIRST_PLANE); Position(rp,&x_pos,&y_pos); Text(rp, string, strlen(string) ); return(error); } mousebounds_string(mb) WORD mb[]; { sprintf(stringbuffer,MOUSEBOUNDS_STRING,mb[1],mb[3]); return((int)stringbuffer); } mouseposition_string(msg) struct IntuiMessage *msg; { sprintf(stringbuffer,MOUSEPOSITION_STRING,msg->MouseX,msg->MouseY); return((int)stringbuffer); } trapdebug_string(lib,offset) struct Library *lib; WORD offset; { sprintf(stringbuffer,TRAPDEBUG_STRING,lib,offset); return((int)stringbuffer); } save_mousebounds() { int i = 4; WORD *op = old_mousebounds; WORD *ml = (WORD *)&IntuitionBase->MinXMouse; /* save current limits */ while(i--) { *op++ = *ml++; } } store_mousebounds() { int i = 4; WORD *np = new_mousebounds; WORD *nl = (WORD *)&IntuitionBase->MinXMouse; /* stuff new limits */ while(i--) { *nl++ = *np++; } } restore_mousebounds() { int i = 4; WORD *op = old_mousebounds; WORD *ml = (WORD *)&IntuitionBase->MinXMouse; /* restore current limits */ while(i--) { *ml++ = *op++; } IntuitionBase->MouseX = MAX(IntuitionBase->MouseX,IntuitionBase->MinXMouse); IntuitionBase->MouseX = MIN(IntuitionBase->MouseX,IntuitionBase->MaxXMouse); IntuitionBase->MouseY = MAX(IntuitionBase->MouseY,IntuitionBase->MinYMouse); IntuitionBase->MouseY = MIN(IntuitionBase->MouseY,IntuitionBase->MaxYMouse); } /***************************************************************************** * * wedge utilities -- create, install, remove and delete system friendly * wedges that can exist in a multitasking environment. * *****************************************************************************/ new_wedge() { struct Wedge *wp = NULL; /* allocate a wedge */ if(wp=(struct Wedge *)AllocMem(sizeof(struct Wedge),MEMF_PUBLIC|MEMF_CLEAR)) { /* initialize the wedge library to default values */ wp->wedge_Library.lib_Node.ln_Type = NT_LIBRARY; wp->wedge_Library.lib_NegSize = 12; wp->wedge_Library.lib_PosSize = sizeof(struct Library)+sizeof(WORD); wp->wedge_Library.lib_Version = 35; wp->wedge_Library.lib_Revision = 1; /* initialize the wedge vectors to default values */ wp->wedge_Vectors[0] = JSR_dPC; wp->wedge_Vectors[1] = 0x0004; wp->wedge_Vectors[2] = RTS; wp->wedge_Vectors[3] = JMP_dPC; wp->wedge_Vectors[4] = 0x0002; wp->wedge_Vectors[5] = RTS; } return((ULONG)wp); } dispose_wedge(wp) struct Wedge *wp; { if (wp) FreeMem(wp,sizeof(struct Wedge)); } test_wedge(wp) struct Wedge *wp; { ULONG is_wedge = NULL; UBYTE *pred; /* make certain that wp is not odd -- it will be if wp == default vector */ if(((ULONG)wp)^1) { if(wp->wedge_Library.lib_Node.ln_Type == NT_LIBRARY) { if(pred = wp->wedge_Library.lib_Node.ln_Pred) { if(((ULONG)pred)^1) { if(wp==(struct Wedge *)*(ULONG *)(pred+wp->wedge_Offset+2)) { is_wedge = (ULONG)wp; } } } } } return(is_wedge); } link_wedge(lib,offset,wedge) UBYTE *lib; WORD offset; struct Wedge *wedge; { ULONG is_wedge = NULL; struct Wedge *owp; UBYTE *pred; if(owp = (struct Wedge *)test_wedge(*(ULONG *)(lib+offset+2))) { is_wedge = (ULONG)owp; owp->wedge_Library.lib_Node.ln_Pred = wedge; owp->wedge_Offset = -6; } return(is_wedge); } delink_wedge(lib,offset,wp) UBYTE *lib; WORD offset; struct Wedge *wp; { struct Wedge *owp = NULL; struct Wedge *nwp; if(wp) { /* prevent unpleasant suprises */ Disable(); /* is this still a valid wedge? */ if(owp = (struct Wedge *)test_wedge(wp)) { struct Library *pred = owp->wedge_Library.lib_Node.ln_Pred; /* yes, valid. does this wedge point to another wedge? */ if( nwp = (struct Wedge *) test_wedge(*(ULONG *)(&owp->wedge_Vectors[4])) ) { nwp->wedge_Library.lib_Node.ln_Pred = pred; } /* does the previous library point to this wedge's library */ if(pred->lib_Node.ln_Succ == &owp->wedge_Library) { /* yes, make previous library point to next wedge's library */ pred->lib_Node.ln_Succ == &nwp->wedge_Library; } /* make previous vector point to next vector */ SetFunction( wp->wedge_Library.lib_Node.ln_Pred, wp->wedge_Offset, *(ULONG *)(&wp->wedge_Vectors[4])); } else { /* not validated... */ /* assume both that has been setfunction'ed away, */ /* and may be setfunction'ed back in the near future: */ /* so replace current vector with default... */ wp->wedge_Vectors[0] = JSR_dPC; wp->wedge_Vectors[1] = 0x0004; wp->wedge_Vectors[2] = RTS; } /* suprises ok now, i guess... */ Enable(); } return((ULONG)owp); } install_wedge(lib,offset,entry) struct Library *lib; WORD offset; ULONG entry; { struct Wedge *wp = NULL; if( (entry) && (wp = (struct Wedge *)new_wedge()) ) { /* prevent unpleasant suprises */ Disable(); /* point this wedge at our new entry */ wp->wedge_Vectors[0] = JSR_ABS; *(ULONG *)(&wp->wedge_Vectors[1]) = entry; /* point this wedge at the previous entry */ wp->wedge_Library.lib_Node.ln_Pred = lib; wp->wedge_Offset = offset; /* link this wedge to existing wedge? */ wp->wedge_Library.lib_Node.ln_Succ = (struct Node *) link_wedge(lib,offset,wp); /* install this wedge in place of the old entry */ wp->wedge_Vectors[3] = JMP_ABS; *(ULONG *)(&wp->wedge_Vectors[4]) = SetFunction(lib,offset,wp); /* suprises ok now, i guess... */ Enable(); } return((ULONG)wp); } remove_wedge(wedge) struct Wedge *wedge; { dispose_wedge(delink_wedge(wedge)); } /***************************************************************************** * * main -- open a screen as large as possible and print a message in it * *****************************************************************************/ main() { int error = FALSE; error = overscan(); /* success, or a negative code to indicate a failure. */ /* exit and return an appropriate success/failure code to system */ exit(error); } /***************************************************************************** * * trap function -- assembly language routine to install as a wedge * intercept calls to LockIBase... avoid recursion * ****************************************************************************** INCLUDE "exec/types.i" INCLUDE "exec/nodes.i" INCLUDE "exec/lists.i" INCLUDE "exec/semaphores.i" INCLUDE "intuition/intuitionbase.i" XREF _save_mousebounds XREF _store_mousebounds XREF _restore_mousebounds XREF _IntuitionBase XREF _test_screen XDEF _wedge XDEF _trap_function XDEF _ibase_lock XDEF _old_mousebounds XDEF _new_mousebounds XDEF store_flag XDEF restore_flag CNOP 0,4 ; make sure vector is long word aligned _wedge: DC.L -1 _ibase_lock: DC.L -1 _old_mousebounds: DC.W 0 DC.W 0 DC.W 0 DC.W 0 _new_mousebounds: DC.W 0 DC.W 0 DC.W 0 DC.W 0 local_flag: DC.L -1 store_flag: DC.L -1 restore_flag: DC.L -1 _trap_function: MOVEM.L D0-D1/A0-A1,-(SP) ; your mileage may vary... LEA.L _ibase_lock,A1 CMPA.L (A1),A0 ; are we about to obtain ibase_lock ? BNE.S not_free MOVE.L (A1),A1 TST.W SS_QUEUECOUNT(A1) ; is it currently unlocked ? BGE.S not_free MOVE.L _IntuitionBase,A1 ; get ibase MOVE.L ib_FirstScreen(A1),A0 ; pointer to the first_screen CMPA.L _test_screen,A0 ; is it us ? BNE.S not_first LEA.L local_flag,A1 ; are we recursing ? ADDQ.L #1,(A1) BNE.S not_again LEA.L store_flag,A1 ; must keep poking until not first TST.L (A1) BEQ.S not_increment ADDQ.L #1,(A1) LEA.L _save_mousebounds,A0 ; save current bounds then swap in new ones JSR (A0) not_increment: LEA.L restore_flag,A1 ; toggle flags MOVE.L #-1,(A1) ; reset LEA.L _store_mousebounds,A0 ; swap in new mousebounds (again) JSR (A0) not_again: LEA.L local_flag,A1 SUBQ.L #1,(A1) BRA.S not_free not_first: LEA.L local_flag,A1 ; are we recursing ? ADDQ.L #1,(A1) BNE.S not_again LEA.L restore_flag,A1 ; only need to restore once when not first TST.L (A1) BEQ.S not_again ADDQ.L #1,(A1) LEA.L store_flag,A1 ; toggle flags MOVE.L #-1,(A1) ; reset LEA.L _restore_mousebounds,A0 JSR (A0) BRA.S not_again not_free: MOVEM.L (SP)+,D0-D1/A0-A1 RTS END ***************************** end-of-file ***********************************/ -- //----------------------------------------------------- ----------\\ //| Bart Whitebook | {|V|))) |\\ | | ()^()-)))| | 16795 Lark Avenue, Suite #106, Los Gatos, CA 95030 | /_ ?))| | UUCP: pyramid!oliveb!amiga!bart | { _ } )\ | | BIX: amiga_bart | \ // | \\|_____________________________________________________|__\//____ |// \\ //