diff --git a/blitplay/.gitignore b/blitplay/.gitignore new file mode 100644 index 0000000..f4a9313 --- /dev/null +++ b/blitplay/.gitignore @@ -0,0 +1,3 @@ +*.o +blitplay +refcode diff --git a/blitplay/LICENSE b/blitplay/LICENSE new file mode 100644 index 0000000..65c5ca8 --- /dev/null +++ b/blitplay/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/blitplay/Makefile b/blitplay/Makefile new file mode 100644 index 0000000..d61f07a --- /dev/null +++ b/blitplay/Makefile @@ -0,0 +1,15 @@ +CC=vc +aos68k +CFLAGS=-c99 -I$(MUI_INC) -I$(NDK_INC) -DCLIB_MUIMASTER_PROTOS_H +OBJECTS=main.o canvas.o +EXE=blitplay + +all: $(EXE) + +clean: + rm -f *.o $(EXE) + +c.o : + $(CC) $(CFLAGS) -c $< + +$(EXE):$(OBJECTS) mui_util.h canvas.h + $(CC) $(OBJECTS) -lamiga -o $(EXE) diff --git a/blitplay/README.md b/blitplay/README.md new file mode 100644 index 0000000..7f4d176 --- /dev/null +++ b/blitplay/README.md @@ -0,0 +1,25 @@ +# Blitter Playground + +This is an application to tinker with the Blitter under Amiga OS 2.x/3.x. +It was inspired by Blitlab, an application originally written for +Amiga OS 1.x. + +The application was written and tested with the VBCC cross compiler +on GNU/Linux, and requires two environment variables to be set: + + * NDK_INC should point to your NDK C include directory + * MUI_INC should point to your MUI 3.8 include directory + +If VBCC, NDK and MUI were setup correctly, you should be +able to build the application on a GNU/Linux system with a simple + +make + +The resulting blitplay application can be executed on a classic +680x0 Amiga system or the corresponding UAE configuration. + +This application was tested on an Amiga 4000 configuration on +FS-UAE, but it should work on any other 2.x/3.x 68k system as well. + +-- Wei-ju Wu April 23rd, 2013 + diff --git a/blitplay/canvas.c b/blitplay/canvas.c new file mode 100644 index 0000000..5ed4c95 --- /dev/null +++ b/blitplay/canvas.c @@ -0,0 +1,227 @@ +/* canvas.c - implementation of the Canvas MUI class */ + +#include +#include + +#include +#include +#include +#include + +#include "canvas.h" + +/* + * For now, we use the real dimensions and use those as a base for the + * blit view area. This makes things easy, we also just use one bitplane + * at the moment + */ +#define CANVAS_WIDTH 320 +#define CANVAS_HEIGHT 32 +#define CANVAS_DEPTH 1 +#define CANVAS_FLAGS BMF_DISPLAYABLE | BMF_CLEAR + +extern struct Library *MUIMasterBase; + +struct CanvasData { + /* dimensions of the canvas */ + LONG left, top, width, height; + + /* bitmap pointer */ + struct BitMap *bitmap; + + /* pointers to the x display and y display gadgets */ + Object *xdisplay, *ydisplay; + + /* drawing state */ + int mousex, mousey, is_drawing; +}; + +/* This is the new method dispatcher for our custom bitmap class */ +ULONG mSetup(struct IClass *cl, Object *obj, struct MUIP_Setup *msg) +{ + if (!DoSuperMethodA(cl, obj, (APTR) msg)) return FALSE; + MUI_RequestIDCMP(obj, IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE); + return TRUE; +} + +ULONG mCleanup(struct IClass *cl, Object *obj, struct MUIP_Cleanup *msg) +{ + MUI_RejectIDCMP(obj, IDCMP_MOUSEBUTTONS|IDCMP_MOUSEMOVE); + return DoSuperMethodA(cl, obj, (APTR) msg); +} +ULONG mAskMinMax(struct IClass *cl, Object *obj, struct MUIP_AskMinMax *msg) +{ + DoSuperMethodA(cl, obj, (APTR) msg); + msg->MinMaxInfo->MinWidth += CANVAS_WIDTH; + msg->MinMaxInfo->DefWidth += CANVAS_WIDTH; + msg->MinMaxInfo->MaxWidth += CANVAS_WIDTH; + msg->MinMaxInfo->MinHeight += CANVAS_HEIGHT; + msg->MinMaxInfo->DefHeight += CANVAS_HEIGHT; + msg->MinMaxInfo->MaxHeight += CANVAS_HEIGHT; + return 0; +} +ULONG mDraw(struct IClass *cl, Object *obj, struct MUIP_Draw *msg) +{ + struct CanvasData *data = INST_DATA(cl, obj); + ULONG result = 0; + int pixelnum = (data->mousey - data->top) * CANVAS_WIDTH + (data->mousex - data->left), + byteOff = 0, bitnum = 0; + DoSuperMethodA(cl, obj, (APTR) msg); + + if (msg->flags & MADF_DRAWUPDATE) { + /* + we draw directly into the window's RastPort, note that there is no + clipping !!! + */ + byteOff = pixelnum / 8; + bitnum = pixelnum & 0x07; + data->bitmap->Planes[0][byteOff] |= 1 << ((7 - bitnum)); + + BltBitMapRastPort(data->bitmap, 0, 0, _rp(obj), + data->left, data->top, + CANVAS_WIDTH, CANVAS_HEIGHT, + 0xc0); + + } else if (msg->flags & MADF_DRAWOBJECT) { + LONG leftEdge, topEdge, innerLeft, innerTop; + + GetAttr(MUIA_LeftEdge, obj, &leftEdge); + GetAttr(MUIA_TopEdge, obj, &topEdge); + GetAttr(MUIA_InnerLeft, obj, &innerLeft); + GetAttr(MUIA_InnerTop, obj, &innerTop); + + data->left = leftEdge + innerLeft + 2; /* I think the "off" sizes */ + data->top = topEdge + innerTop + 1; /* are actually the borders TODO */ + data->width = CANVAS_WIDTH; + data->height = CANVAS_HEIGHT; + /* + printf("updating component l = %d, t = %d, il = %d it = %d\n", + (int) leftEdge, (int) topEdge, (int) innerLeft, (int) innerTop); + */ + BltBitMapRastPort(data->bitmap, 0, 0, _rp(obj), + data->left, data->top, + CANVAS_WIDTH, CANVAS_HEIGHT, + 0xc0); + } + return 0; +} + +ULONG mHandleInput(struct IClass *cl, Object *obj, struct MUIP_HandleInput *msg) +{ + struct CanvasData *data = INST_DATA(cl, obj); + LONG mx, my; + + if (msg->imsg) { + switch (msg->imsg->Class) { + case IDCMP_MOUSEBUTTONS: + mx = msg->imsg->MouseX; + my = msg->imsg->MouseY; + if (mx >= data->left && mx < data->left + data->width + && my >= data->top && my < data->top + data->height) { + data->is_drawing = msg->imsg->Code == SELECTDOWN; + if (data->is_drawing) { + data->mousex = msg->imsg->MouseX; + data->mousey = msg->imsg->MouseY; + MUI_Redraw(obj, MADF_DRAWUPDATE); + } + } + break; + case IDCMP_MOUSEMOVE: + /* only handle movements inside the boundaries */ + mx = msg->imsg->MouseX; + my = msg->imsg->MouseY; + + if (mx >= data->left && mx < data->left + data->width + && my >= data->top && my < data->top + data->height) { + int index = (my - data->top) * CANVAS_WIDTH + (mx - data->left); + if (data->xdisplay) + set(data->xdisplay, MUIA_String_Integer, index / 16); + if (data->ydisplay) + set(data->ydisplay, MUIA_String_Integer, index % 16); + + if (data->is_drawing) { + data->mousex = msg->imsg->MouseX; + data->mousey = msg->imsg->MouseY; + + MUI_Redraw(obj, MADF_DRAWUPDATE); + } + } + break; + default: + break; + } + } + return DoSuperMethodA(cl, obj, (APTR) msg); +} + +ULONG mNewInstance(struct IClass *cl, Object *obj, struct opSet *msg) +{ + struct TagItem *tagListState = msg->ops_AttrList, *tag; + Object *instance = (Object *) DoSuperMethodA(cl, obj, (APTR) msg); + struct CanvasData *data = INST_DATA(cl, instance); + + /* This is the way to allocate the bitmap in an application for > V39 */ + data->bitmap = AllocBitMap(CANVAS_WIDTH, CANVAS_HEIGHT, CANVAS_DEPTH, + CANVAS_FLAGS, NULL); + + while (tag = NextTagItem(&tagListState)) { + switch (tag->ti_Tag) { + case CANVASA_XDISPLAY: + data->xdisplay = (Object *) tag->ti_Data; + break; + case CANVASA_YDISPLAY: + data->ydisplay = (Object *) tag->ti_Data; + break; + } + } + return (ULONG) instance; +} + +ULONG mDisposeInstance(struct IClass *cl, Object *obj, struct opSet *msg) +{ + struct CanvasData *data = INST_DATA(cl, obj); + /* Wait for blitter always, when freeing bitmap */ + WaitBlit(); + FreeBitMap(data->bitmap); + return DoSuperMethodA(cl, obj, (APTR) msg); +} + +ULONG mGet(struct IClass *cl, Object *obj, struct opGet *msg) +{ + struct CanvasData *data = INST_DATA(cl, obj); + switch (msg->opg_AttrID) { + case CANVASA_BITMAP: + *(msg->opg_Storage) = (ULONG) data->bitmap; + return TRUE; + default: + break; + } + return DoSuperMethodA(cl, obj, (APTR) msg); +} + +ULONG CanvasDispatcher(__reg("a0") struct IClass *cl, + __reg("a2") Object *obj, + __reg("a1") Msg msg) +{ + switch (msg->MethodID) { + case OM_NEW: return mNewInstance(cl, obj, (APTR) msg); + case OM_DISPOSE: return mDisposeInstance(cl, obj, (APTR) msg); + case OM_GET: return mGet(cl, obj, (APTR) msg); + + case MUIM_AskMinMax: return mAskMinMax(cl, obj, (APTR) msg); + case MUIM_Draw: return mDraw(cl, obj, (APTR) msg); + case MUIM_HandleInput: return mHandleInput(cl, obj, (APTR) msg); + case MUIM_Setup: return mSetup(cl, obj, (APTR) msg); + case MUIM_Cleanup: return mCleanup(cl, obj, (APTR) msg); + default: + break; + } + return DoSuperMethodA(cl, obj, msg); +} + +struct MUI_CustomClass *CreateCanvasClass() +{ + return MUI_CreateCustomClass(NULL, MUIC_Area, NULL, + sizeof(struct CanvasData), + (APTR) CanvasDispatcher); +} diff --git a/blitplay/canvas.h b/blitplay/canvas.h new file mode 100644 index 0000000..2c5015c --- /dev/null +++ b/blitplay/canvas.h @@ -0,0 +1,17 @@ +#ifndef __CANVAS_H__ +#define __CANVAS_H__ + +/* + * A custom MUI class for a canvas where the user can freely draw + * with the mouse. + * The CANVASA_XDISPLAY/CANVASA_YDISPLAY attributes are pointers + * to MUI string gadgets and will be used to display the relative + * mouse x and y coordinates if they are defined. + */ +#define CANVASA_XDISPLAY (TAG_USER + 1) +#define CANVASA_YDISPLAY (TAG_USER + 2) +#define CANVASA_BITMAP (TAG_USER + 3) + +extern struct MUI_CustomClass *CreateCanvasClass(); + +#endif /* __CANVAS_H__ */ diff --git a/blitplay/main.c b/blitplay/main.c new file mode 100644 index 0000000..46bd54c --- /dev/null +++ b/blitplay/main.c @@ -0,0 +1,600 @@ +/* + main.c - MUI application to play with the blitter + This code was written to be compiled with either VBCC +*/ +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include "mui_util.h" +#include "canvas.h" + +/* + This is one of the magic variables of an Amiga program: + the address of this structure is set to the base + address of the custom registers and the structure corresponds + to the memory layout of the custom registers, so we reads + and writes are direct accesses to the memory-mapped custom + chip registers. +*/ +extern struct Custom custom; + +/* + Make sure that these pointers to the library bases are set to a valid values. + The BOOPSI/MUI/Intuition/Graphics calls expect it and will crash the + application in spectacular ways. + */ +struct Library *IntuitionBase = NULL, *MUIMasterBase = NULL, + *GfxBase = NULL, *UtilityBase = NULL; + +BOOL Init() +{ + if (!(IntuitionBase = OpenLibrary("intuition.library", 39))) return 0; + if (!(GfxBase = OpenLibrary("graphics.library", 39))) { + CloseLibrary(IntuitionBase); + return 0; + } + if (!(UtilityBase = OpenLibrary("utility.library", 39))) { + CloseLibrary(GfxBase); + CloseLibrary(IntuitionBase); + return 0; + } + if (!(MUIMasterBase = OpenLibrary(MUIMASTER_NAME, 19))) { + CloseLibrary(UtilityBase); + CloseLibrary(GfxBase); + CloseLibrary(IntuitionBase); + return 0; + } + return 1; +} + +void Cleanup() +{ + if (MUIMasterBase) CloseLibrary(MUIMasterBase); + if (UtilityBase) CloseLibrary(UtilityBase); + if (GfxBase) CloseLibrary(GfxBase); + if (IntuitionBase) CloseLibrary(IntuitionBase); +} + +/* For simplicity, I just have all the controls as a module-global + variable, so the handlers can access them */ +Object *strAddrA, *strModA, *strShiftA, *strDataA, *strAFWM, *strALWM; +Object *strAddrB, *strModB, *strShiftB, *strDataB; +Object *strAddrC, *strModC, *strDataC; +Object *strAddrD, *strModD; +Object *window, *canvas, *strWidth, *strHeight, *strFunction; + +LONG selectDMAA = 0, selectDMAB = 0, selectDMAC = 0, selectDMAD = 0; + +/* We have a select func per DMA group - it's cleaner */ +ULONG SelectDMAChannelAFunc(__reg("a0") struct Hook *h, + __reg("a2") Object *app, + __reg("a1") Object **pObj) +{ + get(*pObj, MUIA_Selected, &selectDMAA); + set(strAddrA, MUIA_Disabled, !selectDMAA); + set(strModA, MUIA_Disabled, !selectDMAA); + set(strDataA, MUIA_Disabled, !selectDMAA); + set(strShiftA, MUIA_Disabled, !selectDMAA); + set(strAFWM, MUIA_Disabled, !selectDMAA); + set(strALWM, MUIA_Disabled, !selectDMAA); + return 0; +} +ULONG SelectDMAChannelBFunc(__reg("a0") struct Hook *h, + __reg("a2") Object *app, + __reg("a1") Object **pObj) +{ + get(*pObj, MUIA_Selected, &selectDMAB); + set(strAddrB, MUIA_Disabled, !selectDMAB); + set(strModB, MUIA_Disabled, !selectDMAB); + set(strDataB, MUIA_Disabled, !selectDMAB); + set(strShiftB, MUIA_Disabled, !selectDMAB); + return 0; +} +ULONG SelectDMAChannelCFunc(__reg("a0") struct Hook *h, + __reg("a2") Object *app, + __reg("a1") Object **pObj) +{ + get(*pObj, MUIA_Selected, &selectDMAC); + set(strAddrC, MUIA_Disabled, !selectDMAC); + set(strModC, MUIA_Disabled, !selectDMAC); + set(strDataC, MUIA_Disabled, !selectDMAC); + return 0; +} +ULONG SelectDMAChannelDFunc(__reg("a0") struct Hook *h, + __reg("a2") Object *app, + __reg("a1") Object **pObj) +{ + get(*pObj, MUIA_Selected, &selectDMAD); + set(strAddrD, MUIA_Disabled, !selectDMAD); + set(strModD, MUIA_Disabled, !selectDMAD); + return 0; +} + +BOOL IsBlitSafe(Object *app, Object *win) +{ + int flags = 0; + if (!selectDMAD) return TRUE; /* If destination is off, why bother ? */ + /* Now we need to check the sizes for validity */ + //MUI_Request(app, win, flags, "Unsafe Blit", "OK", + // "Can not perform blit"); + return TRUE; +} + +void DoBlit(Object *app) +{ + char *str; + LONG functionNum, blitWidth, blitHeight, activeChannels = 0; + LONG addrA, modA, dataA, shiftA, addrB, modB, dataB, shiftB, + addrC, modC, dataC, addrD, modD; + PLANEPTR bitplane; + struct BitMap *bitmap; + + + get(strAddrA, MUIA_String_Contents, (LONG *) &str); + get(canvas, CANVASA_BITMAP, (ULONG *) &bitmap); + get(strFunction, MUIA_String_Integer, (LONG *) &functionNum); + get(strWidth, MUIA_String_Integer, (LONG *) &blitWidth); + get(strHeight, MUIA_String_Integer, (LONG *) &blitHeight); + bitplane = bitmap->Planes[0]; + + get(strAddrA, MUIA_String_Integer, (LONG *) &addrA); + get(strModA, MUIA_String_Integer, (LONG *) &modA); + get(strDataA, MUIA_String_Integer, (LONG *) &dataA); + get(strShiftA, MUIA_String_Integer, (LONG *) &shiftA); + + get(strAddrB, MUIA_String_Integer, (LONG *) &addrB); + get(strModB, MUIA_String_Integer, (LONG *) &modB); + get(strDataB, MUIA_String_Integer, (LONG *) &dataB); + get(strShiftB, MUIA_String_Integer, (LONG *) &shiftB); + + get(strAddrC, MUIA_String_Integer, (LONG *) &addrC); + get(strModC, MUIA_String_Integer, (LONG *) &modC); + get(strDataC, MUIA_String_Integer, (LONG *) &dataC); + + get(strAddrD, MUIA_String_Integer, (LONG *) &addrD); + get(strModD, MUIA_String_Integer, (LONG *) &modD); + + printf("you pushed me ! '%s', function: %d\n", str, (int) functionNum); + + /* do the blit action */ + if (selectDMAA) activeChannels |= BC0F_SRCA; + if (selectDMAB) activeChannels |= BC0F_SRCB; + if (selectDMAC) activeChannels |= BC0F_SRCC; + if (selectDMAD) activeChannels |= BC0F_DEST; + + if (IsBlitSafe(app, window)) { + OwnBlitter(); + WaitBlit(); + + custom.bltcon0 = activeChannels | (functionNum & 0xff); + custom.bltcon1 = 0x0000; + + custom.bltadat = dataA; + custom.bltbdat = dataB; + custom.bltcdat = dataC; + + custom.bltamod = modA; + custom.bltbmod = modB; + custom.bltcmod = modC; + custom.bltdmod = modD; + + custom.bltafwm = 0xffff; + custom.bltalwm = 0xffff; + + custom.bltapt = bitplane + addrA; + custom.bltbpt = bitplane + addrB; + custom.bltcpt = bitplane + addrC; + custom.bltdpt = bitplane + addrD; + + custom.bltsize = (blitHeight << 6) | blitWidth; /* max 20 x 32 (320x32 pixel ) */ + DisownBlitter(); + MUI_Redraw(canvas, MADF_DRAWUPDATE); + } +} + +#define ACCEPT_POSITIVE_NUMS "0123456789" +#define ACCEPT_BINARY "01%" +#define ACCEPT_HEX "0123456789ABCDEFXabcdefx" + +/* Menu definition */ +/* Menu ids */ +enum { + MENU_NONE, MENU_PROJECT, MENU_ABOUT, MENU_QUIT, + MENU_EXECUTE, MENU_GO, + /* AREXX commands */ + ID_PING +}; + +/* Menu structure */ +static struct NewMenu menudata[] = { + {NM_TITLE, "Project", 0, 0, 0, (APTR) MENU_PROJECT}, + {NM_ITEM, "About", "?", 0, 0, (APTR) MENU_ABOUT}, + {NM_ITEM, NM_BARLABEL, 0, 0, 0, (APTR) MENU_NONE}, + {NM_ITEM, "Quit", "Q", 0, 0, (APTR) MENU_QUIT}, + + {NM_TITLE, "Execute", 0, 0, 0, (APTR) MENU_EXECUTE}, + {NM_ITEM, "Go !", "G", 0, 0, (APTR) MENU_GO}, + + {NM_END, NULL, 0, 0, 0, NULL } +}; + +/* send simple commands with + address blitplay.1 +*/ +static struct MUI_Command arexx_commands[] = { + {"ping", MC_TEMPLATE_ID, ID_PING, NULL}, + {NULL, NULL, 0, NULL} +}; + +static char *pageTitles[] = {"Copy/Block Mode", "Line Mode", NULL }; + +int main(int argc, char **argv) +{ + int plane_size; + struct MUI_CustomClass *canvasClass; + + Object *app = NULL, *xdisplay = NULL, *ydisplay; + Object *cmEnableDMA[4]; + struct Hook SelectDMAChannelAHook = { {0, 0}, SelectDMAChannelAFunc, NULL, NULL }; + struct Hook SelectDMAChannelBHook = { {0, 0}, SelectDMAChannelBFunc, NULL, NULL }; + struct Hook SelectDMAChannelCHook = { {0, 0}, SelectDMAChannelCFunc, NULL, NULL }; + struct Hook SelectDMAChannelDHook = { {0, 0}, SelectDMAChannelDFunc, NULL, NULL }; + + if (!Init()) + { + printf("Cannot open libs\n"); + return 0; + } + + printf("custom base: %04x\n", (int) &custom); + + /* override the BitMap class to support drawing with the mouse */ + if (!(canvasClass = CreateCanvasClass())) { + Cleanup(); + return 0; + } + xdisplay = StringObject, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + End; + ydisplay = StringObject, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + End; + + app = ApplicationObject, + MUIA_Application_Title, "BlitterPlayground", + MUIA_Application_Version, "1.0", + MUIA_Application_Copyright, "©2013, Wei-ju Wu", + MUIA_Application_Author, "Wei-ju Wu", + MUIA_Application_Description, "A Blitter Toy", + MUIA_Application_Base, "blitplay", + MUIA_Application_Commands, arexx_commands, + SubWindow, window = WindowObject, + MUIA_Window_Title, "Blitter Playground 1.0", + MUIA_Window_ID, MAKE_ID('A', 'P', 'P', 'W'), + MUIA_Window_AppWindow, TRUE, + MUIA_Background, MUII_WindowBack, + MUIA_Window_Menustrip, MUI_MakeObject(MUIO_MenustripNM, menudata, 0), + MUIA_Window_SizeGadget, FALSE, + WindowContents, VGroup, + Child, HGroup, + Child, canvas = NewObject(canvasClass->mcc_Class, NULL, + CANVASA_XDISPLAY, xdisplay, + CANVASA_YDISPLAY, ydisplay, + MUIA_Frame, MUIV_Frame_Text, + TAG_DONE), + + Child, ColGroup(2), + Child, Label("Address (M+): "), + Child, xdisplay, + Child, Label("Shift: "), + Child, ydisplay, + End, + + /* define a frame around the bitmap */ + MUIA_Frame, MUIV_Frame_Group, + End, + Child, HGroup, + Child, Label("Width"), + Child, strWidth = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_MaxLen, 3, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_ShortHelp, "Width of blit in 16-bit words", + MUIA_MaxWidth, 60, + End, + Child, Label("Height"), + Child, strHeight = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_MaxLen, 3, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_ShortHelp, "Height of blit in pixels", + MUIA_MaxWidth, 60, + End, + Child, Label("Function"), + Child, strFunction = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_MaxLen, 4, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_ShortHelp, "Function number", + MUIA_MaxWidth, 60, + End, + End, + Child, RegisterGroup(pageTitles), + MUIA_Register_Frame, TRUE, + /* DMA channel setup */ + Child, VGroup, + MUIA_Frame, MUIV_Frame_Group, + MUIA_FrameTitle, "DMA Channels", + + Child, ColGroup(6), + + /* Headers */ + Child, Label("Ch"), + Child, Label("Use"), + Child, Label("Address"), + Child, Label("Modulo"), + Child, Label("Data"), + Child, Label("Shift"), + + /* Channel A inputs */ + Child, Label("A"), + Child, cmEnableDMA[0] = CheckMark(FALSE), + Child, strAddrA = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Source address DMA channel A", + End, + Child, strModA = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Modulo DMA channel A", + End, + Child, strDataA = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Data register DMA channel A", + End, + Child, strShiftA = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_MaxLen, 3, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Shift register DMA channel A", + End, + + /* Channel B inputs */ + Child, Label("B"), + Child, cmEnableDMA[1] = CheckMark(FALSE), + Child, strAddrB = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Source address DMA channel B", + End, + Child, strModB = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + End, + Child, strDataB = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Modulo DMA channel B", + End, + Child, strShiftB = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_MaxLen, 3, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Data register DMA channel B", + End, + + /* Channel C inputs */ + Child, Label("C"), + Child, cmEnableDMA[2] = CheckMark(FALSE), + Child, strAddrC = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Source address DMA channel C", + End, + Child, strModC = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Modulo DMA channel C", + End, + Child, strDataC = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Data register DMA channel C", + End, + Child, RectangleObject, + MUIA_MaxWidth, 40, + End, + + /* Channel D inputs */ + Child, Label("D"), + Child, cmEnableDMA[3] = CheckMark(FALSE), + Child, strAddrD = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Source address DMA channel D", + End, + Child, strModD = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Integer, 0, + MUIA_String_Accept, ACCEPT_POSITIVE_NUMS, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Modulo DMA channel D", + MUIA_MaxWidth, 50, + End, + Child, RectangleObject, + MUIA_MaxWidth, 50, + End, + Child, RectangleObject, + MUIA_MaxWidth, 50, + End, + + End, /* ColGroup */ + + Child, HGroup, + Child, Label("Ch. A FWM"), + Child, strAFWM = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Contents, "%1111111111111111", + MUIA_String_MaxLen, 18, + MUIA_String_Accept, ACCEPT_BINARY, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "First word mask channel A", + End, + + Child, Label("Ch. A LWM"), + Child, strALWM = StringObject, + StringFrame, + MUIA_CycleChain, 1, + MUIA_String_Contents, "%1111111111111111", + MUIA_String_MaxLen, 18, + MUIA_String_Accept, ACCEPT_BINARY, + MUIA_String_Format, MUIV_String_Format_Right, + MUIA_Disabled, TRUE, + MUIA_ShortHelp, "Last word mask channel A", + End, + End, + + End, /* DMA channel setup */ + End, /* Register */ + End, + End, + End; + if (!app) { + printf("Cannot create application.\n"); + return 0; + } + + DoMethod(window, MUIM_Notify, MUIA_Window_CloseRequest, TRUE, + app, 2, MUIM_Application_ReturnID, MUIV_Application_ReturnID_Quit); + DoMethod(cmEnableDMA[0], MUIM_Notify, MUIA_Selected, MUIV_EveryTime, + app, 3, MUIM_CallHook, &SelectDMAChannelAHook, cmEnableDMA[0]); + DoMethod(cmEnableDMA[1], MUIM_Notify, MUIA_Selected, MUIV_EveryTime, + app, 3, MUIM_CallHook, &SelectDMAChannelBHook, cmEnableDMA[1]); + DoMethod(cmEnableDMA[2], MUIM_Notify, MUIA_Selected, MUIV_EveryTime, + app, 3, MUIM_CallHook, &SelectDMAChannelCHook, cmEnableDMA[2]); + DoMethod(cmEnableDMA[3], MUIM_Notify, MUIA_Selected, MUIV_EveryTime, + app, 3, MUIM_CallHook, &SelectDMAChannelDHook, cmEnableDMA[3]); + + SetAttrs(window, MUIA_Window_Open, TRUE, TAG_DONE); + { + BOOL running = TRUE; + ULONG sigs = 0, id; + + while (running) { + id = DoMethod(app, MUIM_Application_NewInput, &sigs); + switch(id) + { + case MENU_QUIT: + case MUIV_Application_ReturnID_Quit: + running = FALSE; + break; + case MENU_ABOUT: + MUI_Request(app, window, 0, NULL, "Close", "Blitter Playground 1.0"); + break; + case MENU_GO: + DoBlit(app); + break; + case ID_PING: + printf("Ping !\n"); + break; + default: + break; + } + if (running && sigs) { + sigs = Wait(sigs | SIGBREAKF_CTRL_C); + if (sigs & SIGBREAKF_CTRL_C) break; + } + } + } + set((APTR) window, MUIA_Window_Open, FALSE); + MUI_DisposeObject(app); + MUI_DeleteCustomClass(canvasClass); + + Cleanup(); + return 0; +} diff --git a/blitplay/mui_util.h b/blitplay/mui_util.h new file mode 100644 index 0000000..a654f05 --- /dev/null +++ b/blitplay/mui_util.h @@ -0,0 +1,9 @@ +#pragma once +#ifndef __MUI_UTIL_H__ +#define __MUI_UTIL_H__ + +#ifndef MAKE_ID +#define MAKE_ID(a,b,c,d) ((ULONG) (a)<<24 | (ULONG) (b)<<16 | (ULONG) (c)<<8 | (ULONG) (d)) +#endif + +#endif /* __MUI_UTIL_H__ */ diff --git a/blitplay/rexx/ping.rexx b/blitplay/rexx/ping.rexx new file mode 100644 index 0000000..1ddc5e8 --- /dev/null +++ b/blitplay/rexx/ping.rexx @@ -0,0 +1,3 @@ +/* ping.rexx - sends a ping to the application, run with rx ping */ +address "BLITPLAY.1" "ping" +