/*
**    OBPP (ObtainBestPenPatch)
**
**        © 1996 by Timo C. Nentwig
**        All Rights Reserved !
**
**        Tcn@oxygen.in-berlin.de
**
*/

/// #include

#include "GST.h"
#include "Protos.h"

///
/// proto

static LONG        (*__asm Old_ObtainBestPen) (REG (a0) struct ColorMap *, REG (d1) ULONG, REG (d2) ULONG, REG (d3) ULONG, REG (a1) struct TagItem *, REG (a6) struct Library *);
proto  LONG __saveds __asm New_ObtainBestPen  (REG (a0) struct ColorMap *, REG (d1) ULONG, REG (d2) ULONG, REG (d3) ULONG, REG (a1) struct TagItem *, REG (a6) struct Library *);

proto  BOOL InstallWedge (VOID);
proto  VOID RemoveWedge  (VOID);

///

    // TRUE if patch is installed

static BOOL    PatchInstalled = FALSE;

    // Patch struct

struct Patch
{

    UWORD    Instruction;
    APTR     Function;

} *Patch;

/// InstallWedge ()

    /*
     *    FUNCTION    Install the patch.
     *
     *    EXAMPLE     InstallWedge ();
     *
     */

BOOL
InstallWedge (VOID)
{

    if (Patch = AllocStruct (Patch))
    {

        Forbid();

        Patch -> Instruction = 0x4ef9;
        Patch -> Function    = (APTR) New_ObtainBestPen;

            // Patch function: ObtainBestPen() (-0x348)

        Old_ObtainBestPen = SetFunction ((struct Library *) GfxBase, -0x348, (APTR) Patch);

            // Make sure data gets written to memory

        CacheClearU();

            // Patch installed

        PatchInstalled = TRUE;

        Permit();

        return (TRUE);

    }

    return (FALSE);

}

///
/// RemoveWedge ()

    /*
     *    FUNCTION    Remove the patch.
     *
     *    NOTE        Don't check if patch could
     *                really get removed.
     *
     *    EXAMPLE     RemoveWedge ();
     *
     */

VOID
RemoveWedge (VOID)
{

    if (PatchInstalled)
    {

        Forbid();

            // Redirect pointer to original function

        Patch -> Function = (APTR) Old_ObtainBestPen;

            // Make sure the data gets written to memory

        CacheClearU();

        Permit();

            // Patch removed

        PatchInstalled = FALSE;

    }

}

///
/// New_ObtainBestPen ()

    /*
     *    FUNCTION    Definable precision.
     *
     *    NOTE        AllocateTagItems() solution
     *                is not very satisfying ...
     *
     */

LONG __saveds __asm
New_ObtainBestPen (REG (a0) struct ColorMap *CMap, REG (d1) ULONG R, REG (d2) ULONG G, REG (d3) ULONG B, REG (a1) struct TagItem *TagList, REG (a6) struct Library *GfxBase)
{

    struct TagItem   *NewTagList;

    if (NewTagList = AllocateTagItems (3))
    {

        struct TagItem   *Tag = FindTagItem (OBP_FailIfBad, TagList);

        NewTagList [0] . ti_Tag  = OBP_Precision;
        NewTagList [0] . ti_Data = Set -> Precision;
        NewTagList [1] . ti_Tag  = OBP_FailIfBad,
        NewTagList [1] . ti_Data = Tag ? Tag -> ti_Data : FALSE;
        NewTagList [2] . ti_Tag  = TAG_END;

            // Use modified tag list

        return (Old_ObtainBestPen (CMap, R, G, B, NewTagList, GfxBase));

    }

        // Use original tag list

    return (Old_ObtainBestPen (CMap, R, G, B, TagList, GfxBase));

}

///

