bart@amiga.UUCP (Barry A. Whitebook) (11/18/87)
[ 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 <exec/types.h> #include <exec/memory.h> #include <exec/nodes.h> #include <exec/lists.h> #include <graphics/gfx.h> #include <clib/macros.h> #include <graphics/view.h> #include <graphics/gfxbase.h> #include <graphics/text.h> #include <intuition/intuition.h> #include <intuition/intuitionbase.h> #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))<old_yp) { fill_window(test_window,ALL_PLANES); } Move(rp,*xp,*yp); } fill_window(w,planes) struct Window *w; UBYTE planes; { struct RastPort *rp; struct BitMap *bm; if( (w) && (rp=w->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 | \ // | \\|_____________________________________________________|__\//____ |// \\ //
keithd@cadovax.UUCP (Keith Doyle) (11/19/87)
Jeez, Bart, an incredible effort. Thanks a million. Now none of the rest of you guys better say anything about Commodore Amiga not being responsive to developers needs, or you're likely to get flamed from me (if you're not already in my kill file). Keith Doyle # {ucbvax,decvax}!trwrb!cadovax!keithd Contel Business Systems 213-323-8170
840445m@aucs.UUCP (ALAN) (11/21/87)
Hi again folks. Just a quicky question about the Amiga 1000 expasion bus. I am interested in developing a number of periph's for my Amiga. I need some tech stuff on the bus, Zorro, Auto-Config, Pass - through , etc.,etc. Do I have to get this form C=. If so do I have to pay to be a registered developer. I am not really interested in marketing my projects (yet) I just want to "play" with everything my machine has to offer. Could some one please tell me where a can get the above info. Any one from C= A wish to divulge? Thanks in advance ...... ============================================================================== "The average mathematician should never forget that INTUITION is the final authority " - J. Barkley Posser __@_ \ / || \ |\ "Hang 10" /\ / \ ______' | / \ - Alan W. McKay --+# \ #1 Amigan in N.S / \ CANADA ~~~~~~~~~~~~~~~~~~~~~~~~~~~/ ~~~~~~~~~~~~~~~~~~~~~~~~~~ Amy Tech B.B.S (902) 542 SWAK Nighttime and when not using AMY.