home *** CD-ROM | disk | FTP | other *** search
- *******************************************************************************
- **
- ** $Id: nice.S,v 1.8 92/11/03 17:14:16 tf Exp $
- **
- ** NiceOpenWindow(), NiceCloseWindow() with (DICE) C interface code
- ** written by Tobias Ferber 1992 with a little help and the idea from
- ** Harald Kunze.
- **
- *******************************************************************************
-
- include "exec/exec_lib.i"
- include "intuition/intuition_lib.i"
- include "intuition/screens.i"
- include "graphics/graphics_lib.i"
- include "graphics/rastport.i"
- include "graphics/layers.i"
- include "graphics/layers_lib.i"
-
- LIBRARY_VERSION: equ 33
-
- dc.b "$Id: nice.S,v 1.8 92/11/03 17:14:16 tf Exp $",0 ; rcs ID
- even
-
- section NiceInterface,code
-
- debug: set 1 ; produce debug information (see below)
- ; moderate: set 1
- wuslon: set 1 ; draw two frames instead of one
-
- ifd debug
- xdef NiceOpenWindow
- xdef NiceCloseWindow
- xdef OpenRectangle
- xdef CloseRectangle
- xdef Bresenham
- xdef cc_open
- xdef cc_close
- xdef drawframe
- endc ;debug
-
- xdef _NiceOpenWindow
- xdef _NiceCloseWindow
- xdef _NiceOpenSpeed
- xdef _NiceCloseSpeed
- xdef _OpenRectangle
- xdef _CloseRectangle
-
- _NiceOpenWindow:
-
- movem.l D1-D7/A0-A6,-(sp)
- link A5,#-4 ; A5 -> -(sp); sp -> A5; sp +(-4) -> sp
- clr.l -4(A5)
- lea IntuitionName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_IntuitionBase
- beq \exit
- lea GraphicsName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_GfxBase
- beq \nogfx
- lea LayersName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_LayersBase
- beq \nolayers
-
- move.w _NiceOpenSpeed,D0
- move.l 68(sp),A0 ; fish out the NewWindow struct ptr
- bsr NiceOpenWindow
- move.l D0,-4(A5) ; save our Window ptr
-
- move.l _LayersBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \nolayers:
- move.l _GfxBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \nogfx:
- move.l _IntuitionBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- move.l -4(A5),D0 ; return our Window ptr (in D0)
- \exit:
- unlk A5
- movem.l (sp)+,D1-D7/A0-A6
- rts
-
-
- _NiceCloseWindow:
-
- movem.l D0-D7/A0-A6,-(sp)
- lea IntuitionName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_IntuitionBase
- beq \exit
- lea GraphicsName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_GfxBase
- beq \nogfx
- lea LayersName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_LayersBase
- beq \nolayers
-
- move.w _NiceCloseSpeed,D0
- move.l 64(sp),A0 ; Window
- bsr NiceCloseWindow
-
- move.l _LayersBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \nolayers:
- move.l _GfxBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \nogfx:
- move.l _IntuitionBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \exit:
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
-
- _OpenRectangle:
-
- movem.l D0-D7/A0-A6,-(sp)
- lea GraphicsName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_GfxBase
- beq \nogfx
-
- move.l 64(sp),A1 ; (8+7)*4 +4
- move.l 68(sp),D0
- move.l 72(sp),D1
- move.l 76(sp),D2
- move.l 80(sp),D3
- move.l 84(sp),D4
-
- bsr OpenRectangle
- move.l _GfxBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
-
- \nogfx:
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
-
- _CloseRectangle:
-
- movem.l D0-D7/A0-A6,-(sp)
- lea GraphicsName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,_GfxBase
- beq \nogfx
-
- move.l 64(sp),A1 ; (8+7)*4 +4
- move.l 68(sp),D0
- move.l 72(sp),D1
- move.l 76(sp),D2
- move.l 80(sp),D3
- move.l 84(sp),D4
- bsr CloseRectangle
-
- move.l _GfxBase,A1
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
-
- \nogfx:
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
-
- section NiceInterface,data
-
- _IntuitionBase: ds.l 1
- _GfxBase: ds.l 1
- _LayersBase: ds.l 1
-
-
- IntuitionName: INTNAME
- GraphicsName: GRAFNAME
- LayersName: dc.b "layers.library",0
-
- even
-
- _NiceOpenSpeed: dc.w 8 ; default values
- _NiceCloseSpeed: dc.w 8
-
- NiceRastPort: ds.b rp_SIZEOF ; copy of pop-up screen's RP
-
-
- *******************************************************************************
- **
- ** Window= NiceOpenWindow ( NewWindow, OpenSpeed ) [NiceRastPort needed]
- ** D0 A0 D0
- **
- *******************************************************************************
-
- section Nice,code
-
- NiceOpenWindow:
-
- movem.l D1-D7/A0-A6,-(sp)
-
- tst.w D0
- beq \noframes ; ==> perform normal OpenWindow()
-
- move.w D0,D4 ; D4 is expected to be unchanged
- link A5,#-8
- move.l A0,-4(A5) ; save NewWindow
-
- move.l nw_Screen(A0),A0 ; have we got a Screen? (CUSTOMSCREEN ?)
- cmpa.l #0,A0
- bne \copyrp
-
- ; Find the Screen on which we're going to pop up
-
- moveq #0,D0 ; Lock for IntuitionBase
- move.l _IntuitionBase,A6
- jsr _LVOLockIBase(A6) ; ... now it's mine !
-
- move.l _IntuitionBase,A0
- move.l ib_FirstScreen(A0),-(sp) ; start with IntuitionBase->FirstScreen
-
- move.l D0,A0 ; Lock from LockIBase()
- move.l _IntuitionBase,A6
- jsr _LVOUnlockIBase(A6)
-
- move.l (sp)+,A0 ; IntuitionBase->FirstScreen
- move.l -4(A5),A1 ; NewWindow ptr
- move.w nw_Type(A1),D1 ; NewWindow->Type
- and.w #SCREENTYPE,D1 ; ... just to be sure
-
- \findscreen:
- cmpa.l #0,A0
- beq \noscreen
- move.w sc_Flags(A0),D0
- and.w #SCREENTYPE,D0 ; ... since we did it with D1
- and.w D1,D0 ; mask flags out from NewWindow->Type
- tst.w D0
- bne \copyrp ; yeah! this is a Screen we like ;)
- move.l sc_NextScreen(A0),A0
- bra \findscreen
-
- ; Get a copy. Don't mess with somebody else's RastPort !
-
- \copyrp:
- move.l A0,-8(A5) ; save Screen pointer
- lea sc_RastPort(A0),A0 ; source= &Screen->RastPort
- lea NiceRastPort,A1 ; dest= &NiceRastPort
- move.l #rp_SIZEOF,D0 ; numbytes= sizeof(struct RastPort)
- move.l (_SysBase).W,A6
- jsr _LVOCopyMem(A6)
-
- moveq #RP_COMPLEMENT,D0
- lea NiceRastPort,A1
- move.l _GfxBase,A6
- jsr _LVOSetDrMd(A6) ; SetDrawMode(COMPLEMENT)
-
- move.l -4(A5),A0 ; NewWindow
- move.w nw_DetailPen(A0),D0
- lea NiceRastPort,A1
- move.l _GfxBase,A6
- jsr _LVOSetAPen(A6) ; SetAPen(NewWindow->DetailPen)
-
- move.l -8(A5),A0 ; Screen
- lea sc_LayerInfo(A0),A0 ; &Screen->LayerInfo
- move.l _LayersBase,A6
- jsr _LVOLockLayerInfo(A6)
-
- move.l -4(A5),A0 ; NewWindow
- move.w nw_LeftEdge(A0),D0
- move.w nw_TopEdge(A0),D1
- move.w nw_Width(A0),D2
- move.w nw_Height(A0),D3
- lea NiceRastPort,A1
- bsr OpenRectangle
-
- move.l -8(A5),A0 ; Screen (with locked LayerInfo)
- lea sc_LayerInfo(A0),A0 ; &Screen->LayerInfo
- move.l _LayersBase,A6
- jsr _LVOUnlockLayerInfo(A6)
-
- \noscreen:
- move.l -4(A5),A0 ; NewWindow
- unlk A5
-
- \noframes:
- move.l _OldOpenWindow,A1
- cmpa.l #0,A1
- beq \notpatched
- move.l _IntuitionBase,A6
- jsr (A1)
- bra \exit
-
- \notpatched:
- move.l _IntuitionBase,A6
- jsr _LVOOpenWindow(A6) ; NewWindow in A0
-
- \exit:
- movem.l (sp)+,D1-D7/A0-A6
- rts
-
- *******************************************************************************
- **
- ** NiceCloseWindow ( Window, CloseSpeed ) [NiceRastPort needed]
- ** A0 D0
- **
- *******************************************************************************
-
- NiceCloseWindow:
-
- movem.l D0-D7/A0-A6,-(sp)
- link A5,#-14
- move.w wd_LeftEdge(A0),-2(A5)
- move.w wd_TopEdge(A0),-4(A5)
- move.w wd_Width(A0),-6(A5)
- move.w wd_Height(A0),-8(A5)
- move.w D0,-10(A5) ; closing speed
- move.l wd_WScreen(A0),A1
- move.l A1,-14(A5) ; save Window->WScreen
-
- move.l _OldCloseWindow,A1
- cmpa.l #0,A1
- beq \notpatched
- move.l _IntuitionBase,A6
- jsr (A1)
- bra \nice
-
- \notpatched:
- move.l _IntuitionBase,A6
- jsr _LVOCloseWindow(A6) ; close the window
-
- \nice:
- tst.w -10(A5) ; closing speed
- beq \noframes
-
- ; Get a copy. Don't mess with somebody else's RastPort !
-
- move.l -14(A5),A0 ; Window->WScreen
- lea sc_RastPort(A0),A0 ; source= &Window->WScreen->RastPort
- lea NiceRastPort,A1 ; dest= &NiceRastPort
- move.l #rp_SIZEOF,D0 ; numbytes= sizeof(struct RastPort)
- move.l (_SysBase).W,A6
- jsr _LVOCopyMem(A6)
-
- move.w #RP_COMPLEMENT,D0
- lea NiceRastPort,A1 ; copy of Window->WScreen->RastPort
- move.l _GfxBase,A6
- jsr _LVOSetDrMd(A6) ; SetDrawMode(COMPLEMENT)
-
- move.l -14(A5),A0 ; Window->WScreen
- lea sc_LayerInfo(A0),A0 ; &Window->WScreen->LayerInfo
- move.l _LayersBase,A6
- jsr _LVOLockLayerInfo(A6)
-
- move.w -2(A5),D0 ; LeftEdge
- move.w -4(A5),D1 ; TopEdge
- move.w -6(A5),D2 ; Width
- move.w -8(A5),D3 ; Height
- move.w -10(A5),D4 ; CloseSpeed
- lea NiceRastPort,A1 ; copy of Window->WScreen->RastPort
- bsr CloseRectangle
-
- move.l -14(A5),A0 ; Window->WScreen (with locked LayerInfo)
- lea sc_LayerInfo(A0),A0 ; &Window->WScreen->LayerInfo
- move.l _LayersBase,A6
- jsr _LVOUnlockLayerInfo(A6)
-
- \noframes:
- unlk A5
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
- ********************************************************************************
- **
- ** FUNCTIONs
- **
- ** OpenRectangle,CloseRectangle -- Open/Close a rectangle
- **
- ** SYNOPSIS
- **
- ** OpenRectangle( RastPort, LeftEdge, TopEdge, Width, Height, OpenSpeed )
- **
- ** CloseRectangle( RastPort, LeftEdge, TopEdge, Width, Height, CloseSpeed )
- ** A1 D0 D1 D2 D3 D4
- **
- **
- ** struct RastPort *RastPort;
- ** UWORD LeftEdge, TopEdge;
- ** UWORD Width, Height;
- ** UWORD OpenSpeed,CloseSpeed;
- **
- **
- ** DESCRIPTION
- **
- ** OpenRectangle draws the edges of a rectangle. This rectangle will grow
- ** out of its center in that way, that all 4 edges reach the borders at the
- ** same time. (i.e. proportionally)
- **
- ** CloseRectangle proportionally shrinks it back to it's center again.
- **
- ********************************************************************************
-
- OpenRectangle:
-
- movem.l D0-D7/A0-A6,-(sp)
- lea cc_open,A0
- bsr Bresenham
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
- CloseRectangle:
-
- movem.l D0-D7/A0-A6,-(sp)
- lea cc_close,A0
- bsr Bresenham
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
- ; Here we do the open/close stuff via Bresenham's algorithm for drawing
- ; a line. Note that opening and closing works nearly the same way since
- ; we compute the distance to move as a vector (dx|dy).
-
- Bresenham:
-
- tst.w d4
- beq \noframes ; no frames --> we're done
-
- ; compute the distances from the center to the border
-
- lsr.w #1,d2 ; D2= dx
- lsr.w #1,d3 ; D3= dy
-
- ; save the distances for cc_open
-
- move.w d2,d6
- move.w d3,d7
-
- ; comute the center of the rectangle in (D0|D1)
-
- add.w d2,d0 ; LeftEdge + Width/2
- add.w d3,d1 ; TopEdge + Height/2
-
- ; init our modulo
-
- move.w d2,d5
- lsr.w #1,d5 ; D5= modulo (initially dx/2)
-
- jsr (A0)
- bsr drawframe
-
- ifd wuslon
-
- ; make a copy of our initial coords
-
- movem.l D0/A4,-(sp)
- lea coords,A4
- move.l 0(A4),8(A4)
- move.l 4(A4),12(A4)
- movem.l (sp)+,D0/A4
- bsr drawframe
- endc ;wuslon
-
-
- \xloop:
-
- ifd moderate
- cmp.w D4,d2 ; if we are one x-step before the last then
- bge.s \goonx ; we set the speed to 1 in order to reach
- moveq #1,D4 ; exactly the borders of our rectangle.
- \goonx: ; (compiles to nothing if moderate is undefined)
- endc ;moderate
-
- cmp.w D4,d2 ; while dx>speed (better than dx > 0)
- ble \alldone
- add.w d3,d5 ; modulo += dy
-
- \yloop:
-
- ifd moderate
- cmp.w D4,d3 ; if we are one y-step before the last then
- bge.s \goony ; we set the speed to 1 in order to reach
- moveq #1,D4 ; exactly the borders of our rectangle.
- \goony: ; (compiles to nothing if moderate is undefined)
- endc ;moderate
-
- cmp.w d2,d5 ; while modulo>dx
- ble \ydone
- cmp.w D4,d3 ; ... and dy>step (better than dy > 0)
- ble \ydone
- sub.w d2,d5 ; modulo -= dx
- sub.w D4,d3 ; dy -= D4 (speed)
-
- ifd wuslon
- bsr swapframes
- endc ;wuslon
- bsr drawframe
- jsr (A0) ; compute coords
- bsr drawframe
- bra \yloop ; wend (y)
-
- \ydone:
- sub.w D4,d2 ; dx -= D4 (speed)
-
- ifd wuslon
- bsr swapframes
- endc ;wuslon
- bsr drawframe
- jsr (A0) ; compute coords
- bsr drawframe
- bra \xloop ; wend (x)
-
- \alldone:
- bsr drawframe ; delete the last box
- ifd wuslon
- bsr swapframes
- bsr drawframe
- endc ;wuslon
-
- \noframes:
- rts
-
- ; Here we [c]ompute the [c]oords of our rectangle for later use by drawframe.
- ; In case of cc_open we turn the vector (dx|dy) that way that it points from
- ; the corners of our rectangle to it's center. In the other case (cc_close)
- ; we make it point from the center to the corners.
-
- cc_open:
-
- ; D0.W x-pos of the box center ( unmodified )
- ; D1.W y-pos of the box center ( unmodified )
- ; D2.W dx ( unmodified )
- ; D3.W dy ( unmodified )
- ; D6.W rectangle width / 2 ( unmodified )
- ; D7.W rectangle height / 2 ( unmodified )
-
- movem.l D2-D3,-(sp)
- neg.w D2
- add.w D6,D2
- neg.w D3
- add.w D7,D3
- bsr cc_close
- movem.l (sp)+,D2-D3
- rts
-
- cc_close:
-
- ; D0.W x-pos of the box center ( unmodified )
- ; D1.W y-pos of the box center ( unmodified )
- ; D2.W dx ( unmodified )
- ; D3.W dy ( unmodified )
-
- movem.l D4/A0,-(sp)
-
- lea coords,A0 ; base pointer of our array
-
- move.w d0,d4
- sub.w d2,d4
- move.w d4,(A0)+ ; x-dx (left edge)
-
- move.w d0,d4
- add.w d2,d4
- move.w d4,(A0)+ ; x+dx (right edge)
-
- move.w d1,d4
- sub.w d3,d4
- move.w d4,(A0)+ ; y-dy (top edge)
-
- move.w d1,d4
- add.w d3,d4
- move.w d4,(A0) ; y+dy (bottom edge)
-
- movem.l (sp)+,D4/A0
- rts
-
- ; here we perform the wuslon stuff
-
- ifd wuslon
- swapframes:
- movem.l D0/A4,-(sp)
- lea coords,A4
- move.l 0(A4),D0
- move.l 8(A4),0(A4)
- move.l D0,8(A4)
- move.l 4(A4),D0
- move.l 12(A4),4(A4)
- move.l D0,12(A4)
- movem.l (sp)+,D0/A4
- rts
- endc ; wuslon
-
- ; here we draw the box with the coords in our array.
-
- drawframe: ; RastPort pointer needed in A1
-
- movem.l D0-D7/A0-A6,-(sp) ; ALL registers remain unchanged
-
- link A5,#-4 ; A5 is expected to be unchanged !
- move.l A1,-4(A5) ; save the RastPort
- lea coords,A4 ; A4 is expected to be unchanged !
-
- move.w 0(A4),D0 ; LeftEdge
- move.w 4(A4),D1 ; TopEdge
- move.l -4(A5),A1 ; RastPort
- move.l _GfxBase,A6
- jsr _LVOMove(A6)
-
- move.w 2(A4),D0 ; RightEdge
- move.w 4(A4),D1 ; TopEdge
- move.l -4(A5),A1 ; RastPort
- move.l _GfxBase,A6
- jsr _LVODraw(A6)
-
- move.w 2(A4),D0 ; RightEdge
- move.w 6(A4),D1 ; BottomEdge
- move.l -4(A5),A1 ; RastPort
- move.l _GfxBase,A6
- jsr _LVODraw(A6)
-
- move.w 0(A4),D0 ; LeftEdge
- move.w 6(A4),D1 ; BottomEdge
- move.l -4(A5),A1 ; RastPort
- move.l _GfxBase,A6
- jsr _LVODraw(A6)
-
- lea coords,A4
- move.w 0(A4),D0 ; LeftEdge
- move.w 4(A4),D1 ; TopEdge
- move.l -4(A5),A1 ; RastPort
- move.l _GfxBase,A6
- jsr _LVODraw(A6)
-
- \exit:
- unlk A5
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
- section nice,data
-
- coords: dc.w 0,0,0,0 ; x-dx, x+dx, y-dy, y+dy
- dc.w 0,0,0,0 ; (wuslon)
- even
-
- section patch,code
-
- xdef _PatchOpenWindow
- xdef _PatchCloseWindow
- xdef _OldOpenWindow
- xdef _OldCloseWindow
-
- NewOpenWindow:
- move.l A0,-(sp)
- bsr _NiceOpenWindow
- adda.l #4,sp
- rts
-
- NewCloseWindow:
- move.l A0,-(sp)
- bsr _NiceCloseWindow
- adda.l #4,sp
- rts
-
- _PatchOpenWindow:
-
- movem.l D0-D7/A0-A6,-(sp)
- link A5,#-4
- lea IntuitionName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,-4(A5)
- beq \exit
- move.l (_SysBase).W,A6
- jsr _LVOForbid(A6)
- move.l -4(A5),A1 ; library= IntuitionBase
- suba.l A0,A0
- move.w #_LVOOpenWindow,A0 ; funcOffset= #_LVOOpenWindow
- move.l #NewOpenWindow,D0 ; funcEntry= NewOpenWindow()
- move.l (_SysBase).W,A6
- jsr _LVOSetFunction(A6)
- move.l D0,_OldOpenWindow ; save oldFunc ptr
- move.l (_SysBase).W,A6
- jsr _LVOPermit(A6)
- move.l -4(A5),A1 ; IntuitionBase
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \exit:
- unlk A5
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
- _PatchCloseWindow:
-
- movem.l D0-D7/A0-A6,-(sp)
- link A5,#-4
- lea IntuitionName,A1
- moveq #LIBRARY_VERSION,D0
- move.l (_SysBase).W,A6
- jsr _LVOOpenLibrary(A6)
- move.l D0,-4(A5)
- beq \exit
- move.l (_SysBase).W,A6
- jsr _LVOForbid(A6)
- move.l -4(A5),A1 ; library= IntuitionBase
- suba.l A0,A0
- move.w #_LVOCloseWindow,A0 ; funcOffset= #_LVOCloseWindow
- move.l #NewCloseWindow,D0 ; funcEntry= NewCloseWindow()
- move.l (_SysBase).W,A6
- jsr _LVOSetFunction(A6)
- move.l D0,_OldCloseWindow ; save oldFunc ptr
- move.l (_SysBase).W,A6
- jsr _LVOPermit(A6)
- move.l -4(A5),A1 ; IntuitionBase
- move.l (_SysBase).W,A6
- jsr _LVOCloseLibrary(A6)
- \exit:
- unlk A5
- movem.l (sp)+,D0-D7/A0-A6
- rts
-
- section patch,data
-
- _OldOpenWindow: dc.l 0
- _OldCloseWindow: dc.l 0
-
- END
-