home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of A1200
/
World_Of_A1200.iso
/
programs
/
disk
/
misc
/
dcmp
/
source
/
source.lha
/
nice.S
< prev
next >
Wrap
Text File
|
1993-01-29
|
19KB
|
746 lines
*******************************************************************************
**
** $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