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"
+