Keyboard handling, just get this up to 50fps

The partial render approach was going to require more coordination than
I needed to just get this to 50fps.
This commit is contained in:
John Bintz 2024-09-22 06:31:08 -04:00
parent 3048754012
commit 1dfbec0252
5 changed files with 419 additions and 33 deletions

BIN
keyboard_interrupt Executable file

Binary file not shown.

77
keyboard_interrupt.c Normal file
View File

@ -0,0 +1,77 @@
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h>
#include <clib/graphics_protos.h>
#include <exec/exec.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <intuition/intuition.h>
static struct MsgPort *keyboardMessagePort = NULL;
static struct IOStdReq *keyboardIO = NULL;
static struct Interrupt keyboardInterrupt;
extern far ULONG keyboardPressed;
extern struct InputEvent * __asm stupidKeyboardHandler(
register __a0 struct InputEvent *input,
register __a1 APTR id
);
void setupKeyboard(void) {
if (keyboardMessagePort = CreatePort(NULL, NULL)) {
if (keyboardIO = (struct IOStdReq *)CreateExtIO(
keyboardMessagePort,
sizeof(struct IOStdReq)
)) {
// OpenDevice returns 0 if successful
if (!OpenDevice(
"input.device",
0,
(struct IORequest *)keyboardIO,
0
)) {
keyboardInterrupt.is_Node.ln_Type = NT_INTERRUPT;
keyboardInterrupt.is_Node.ln_Pri = 100;
keyboardInterrupt.is_Node.ln_Name = (STRPTR)"cool bun";
keyboardInterrupt.is_Code = (void (*)())&stupidKeyboardHandler;
keyboardIO->io_Data = (void *)&keyboardInterrupt;
keyboardIO->io_Command = IND_ADDHANDLER;
DoIO((struct IORequest *)keyboardIO);
}
}
}
}
void teardownKeyboard(void) {
if (keyboardIO) {
keyboardIO->io_Data = (void *)&keyboardInterrupt;
keyboardIO->io_Command = IND_REMHANDLER;
DoIO((struct IORequest *)keyboardIO);
CloseDevice((struct IORequest *)keyboardIO);
DeleteIORequest((struct IORequest *)keyboardIO);
keyboardIO = NULL;
}
if (keyboardMessagePort) {
DeleteMsgPort(keyboardMessagePort);
keyboardMessagePort = NULL;
}
}
int main(void) {
setupKeyboard();
while (!keyboardPressed) {}
teardownKeyboard();
return 0;
}

315
main.c
View File

@ -1,13 +1,23 @@
#include <stdio.h> #include <stdio.h>
#include <clib/alib_protos.h>
#include <clib/dos_protos.h>
#include <clib/exec_protos.h> #include <clib/exec_protos.h>
#include <clib/graphics_protos.h> #include <clib/graphics_protos.h>
#include <exec/exec.h> #include <exec/exec.h>
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/interrupts.h>
#include <devices/input.h>
#include <hardware/custom.h> #include <hardware/custom.h>
#include <hardware/dmabits.h> #include <hardware/dmabits.h>
#include <hardware/cia.h> #include <hardware/cia.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h> #include <graphics/gfx.h>
#include "system/blitter.h" #include "system/blitter.h"
@ -84,6 +94,38 @@ void renderTopaz(void) {
} }
} }
void renderMostlyTopaz(void) {
int plane;
uint16_t bltcon0, bltcmod;
uint8_t *bltbpt;
bltcon0 = 0xca + (1 << 8) + (1 << 9) + (1 << 10) + (1 << 11);
bltcmod = screenDefinition.byteWidth - TOPAZ_WIDTH_BYTES;
bltbpt = TopazBitplanes;
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = bltcon0;
custom.bltcon1 = 0;
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltapt = MaskBitplane + (30 * TOPAZ_WIDTH_BYTES);
custom.bltbpt = bltbpt + (30 * TOPAZ_WIDTH_BYTES);
custom.bltcpt = 30 * screenDefinition.byteWidth + activeScreenBufferDetails.planes[plane] + 8;
custom.bltdpt = 30 * screenDefinition.byteWidth + activeScreenBufferDetails.planes[plane] + 8;
custom.bltamod = 0;
custom.bltbmod = 0;
custom.bltcmod = bltcmod;
custom.bltdmod = bltcmod;
custom.bltsize = BLTSIZE(TOPAZ_WIDTH_WORDS, 196);
bltbpt += TOPAZ_WIDTH_BYTES * 256;
WaitBlit();
}
}
#define COPPERLIST_SIZE (10000) #define COPPERLIST_SIZE (10000)
uint16_t *copperlist; uint16_t *copperlist;
@ -124,7 +166,6 @@ void buildCopperlist(void) {
); );
} }
} else { } else {
printf("Skipping render\n");
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist); currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
} }
@ -150,7 +191,7 @@ void buildCopperlist(void) {
} }
} }
} else { } else {
printf("Skipping render\n"); //printf("Skipping render\n");
} }
for (i = 3; i < 8; ++i) { for (i = 3; i < 8; ++i) {
@ -172,20 +213,86 @@ void buildCopperlist(void) {
endCopperlist(currentCopperlist); endCopperlist(currentCopperlist);
} }
uint16_t renderPartialAreas[BUN_COUNT][5];
void calculateTopazRenderPartialAreas(
uint16_t redrawRanges[BUN_COUNT][4]
) {
int topazX;
uint16_t i, width, height, screenX;
for (i = 0; i < BUN_COUNT; ++i) {
renderPartialAreas[i][0] = 0;
if (redrawRanges[i][2] - redrawRanges[i][0] < TOPAZ_WIDTH_PIXELS) {
if (
(redrawRanges[i][2] > 64 && redrawRanges[i][0] < (64 + TOPAZ_WIDTH_PIXELS)) ||
(redrawRanges[i][0] < (64 + TOPAZ_WIDTH_PIXELS) && redrawRanges[i][2] > 64)
) {
width = redrawRanges[i][2] - redrawRanges[i][0] + 16;
height = redrawRanges[i][3] - redrawRanges[i][1];
topazX = redrawRanges[i][0] - 64;
screenX = redrawRanges[i][0];
if (topazX < 0) {
//printf("Too far left, adjusting...\n");
topazX += 16;
screenX += 16;
width -= 16;
}
if (topazX + width > 64 + TOPAZ_WIDTH_PIXELS) {
//printf("Too far right, adjusting...\n");
width -= 16;
}
renderPartialAreas[i][0] = width;
renderPartialAreas[i][1] = height;
renderPartialAreas[i][2] = topazX;
renderPartialAreas[i][3] = screenX;
renderPartialAreas[i][4] = redrawRanges[i][1];
}
}
}
}
void calculateTopazRenderPartialBlitterSettings() {
uint16_t bltapt, bltcpt, bltamod, bltcmod, bltsize;
int i;
for (i = 0; i < BUN_COUNT; ++i) {
if (renderPartialAreas[i][0] == 0) continue;
bltapt = renderPartialAreas[i][4] * TOPAZ_WIDTH_BYTES + (renderPartialAreas[i][2] >> 4) * 2;
bltcpt = renderPartialAreas[i][4] * screenDefinition.byteWidth + (renderPartialAreas[i][3] >> 4) * 2;
printf("%d, %d\n", screenDefinition.byteWidth, renderPartialAreas[i][0]);
bltamod = TOPAZ_WIDTH_BYTES - (renderPartialAreas[i][0] >> 4) * 2;
bltcmod = screenDefinition.byteWidth - (renderPartialAreas[i][0] >> 4) * 2;
bltsize = BLTSIZE((renderPartialAreas[i][0] >> 4), renderPartialAreas[i][1]);
renderPartialAreas[i][0] = bltapt;
renderPartialAreas[i][1] = bltcpt;
renderPartialAreas[i][2] = bltamod;
renderPartialAreas[i][3] = bltcmod;
renderPartialAreas[i][4] = bltsize;
}
}
void renderTopazPartials( void renderTopazPartials(
uint16_t redrawRanges[BUN_COUNT][4] uint16_t redrawRanges[BUN_COUNT][4]
) { ) {
int plane, i, topazX; int plane, i, topazX, screenX;
uint16_t bltcon0; uint16_t bltcon0;
uint16_t bltamod, bltbmod, bltcmod, bltdmod; uint16_t bltamod, bltbmod, bltcmod, bltdmod;
uint16_t width, height, bltsize; uint16_t width, height, bltsize;
uint8_t *bltapt, *bltbpt, *bltcpt, *bltdpt; uint32_t bltapt, bltbpt, bltcpt, bltdpt;
bltcon0 = 0xca + (1 << 8) + (1 << 9) + (1 << 10) + (1 << 11); bltcon0 = 0xca + (1 << 8) + (1 << 9) + (1 << 10) + (1 << 11);
bltcmod = screenDefinition.byteWidth;
bltbpt = TopazBitplanes;
WaitTOF();
for (i = 0; i < BUN_COUNT; ++i) { for (i = 0; i < BUN_COUNT; ++i) {
if (redrawRanges[i][2] - redrawRanges[i][0] < TOPAZ_WIDTH_PIXELS) { if (redrawRanges[i][2] - redrawRanges[i][0] < TOPAZ_WIDTH_PIXELS) {
@ -193,20 +300,26 @@ void renderTopazPartials(
(redrawRanges[i][2] > 64 && redrawRanges[i][0] < (64 + TOPAZ_WIDTH_PIXELS)) || (redrawRanges[i][2] > 64 && redrawRanges[i][0] < (64 + TOPAZ_WIDTH_PIXELS)) ||
(redrawRanges[i][0] < (64 + TOPAZ_WIDTH_PIXELS) && redrawRanges[i][2] > 64) (redrawRanges[i][0] < (64 + TOPAZ_WIDTH_PIXELS) && redrawRanges[i][2] > 64)
) { ) {
width = redrawRanges[i][2] - redrawRanges[i][0]; width = redrawRanges[i][2] - redrawRanges[i][0] + 16;
height = redrawRanges[i][3] - redrawRanges[i][1]; height = redrawRanges[i][3] - redrawRanges[i][1];
topazX = redrawRanges[i][0] - 64; topazX = redrawRanges[i][0] - 64;
screenX = redrawRanges[i][0];
if (topazX < 0) { if (topazX < 0) {
//printf("Too far left, adjusting...\n");
topazX += 16; topazX += 16;
screenX += 16;
width -= 16;
}
if (topazX + width > 64 + TOPAZ_WIDTH_PIXELS) {
//printf("Too far right, adjusting...\n");
width -= 16; width -= 16;
} }
// always round up to the next word
width += 16;
bltapt = redrawRanges[i][1] * TOPAZ_WIDTH_BYTES + (topazX >> 4) * 2; bltapt = redrawRanges[i][1] * TOPAZ_WIDTH_BYTES + (topazX >> 4) * 2;
bltbpt = bltapt; bltbpt = bltapt;
bltcpt = redrawRanges[i][1] * screenDefinition.byteWidth + (redrawRanges[i][0] >> 4) * 2; bltcpt = redrawRanges[i][1] * screenDefinition.byteWidth + (screenX >> 4) * 2;
bltdpt = bltcpt; bltdpt = bltcpt;
bltamod = TOPAZ_WIDTH_BYTES - (width >> 4) * 2; bltamod = TOPAZ_WIDTH_BYTES - (width >> 4) * 2;
@ -215,6 +328,7 @@ void renderTopazPartials(
bltdmod = bltcmod; bltdmod = bltcmod;
bltsize = BLTSIZE((width >> 4), height); bltsize = BLTSIZE((width >> 4), height);
/*
printf( printf(
"Coords: %d, %d -> %d, %d\n", "Coords: %d, %d -> %d, %d\n",
@ -227,10 +341,18 @@ void renderTopazPartials(
printf("topazX: %d\n", topazX); printf("topazX: %d\n", topazX);
printf("width: %d\n", width); printf("width: %d\n", width);
printf("MaskBitplane: %d\n", MaskBitplane);
printf("TopazBitplanes: %d\n", TopazBitplanes);
printf("ActiveScreenBuffer Plane 0: %d\n", activeScreenBufferDetails.planes[0]);
printf("BLTAPT: %d\n", bltapt); printf("BLTAPT: %d\n", bltapt);
printf("BLTAPT src: %d\n", bltapt + (uint32_t)MaskBitplane);
printf("BLTBPT: %d\n", bltbpt); printf("BLTBPT: %d\n", bltbpt);
printf("BLTBPT src: %d\n", bltbpt + (uint32_t)TopazBitplanes);
printf("BLTCPT: %d\n", bltcpt); printf("BLTCPT: %d\n", bltcpt);
printf("BLTCPT src: %d\n", bltcpt + (uint32_t)activeScreenBufferDetails.planes[0] + 8);
printf("BLTDPT: %d\n", bltdpt); printf("BLTDPT: %d\n", bltdpt);
printf("BLTDPT src: %d\n", bltdpt + (uint32_t)activeScreenBufferDetails.planes[0] + 8);
printf("BLTAMOD: %d\n", bltamod); printf("BLTAMOD: %d\n", bltamod);
printf("BLTBMOD: %d\n", bltbmod); printf("BLTBMOD: %d\n", bltbmod);
@ -238,39 +360,151 @@ void renderTopazPartials(
printf("BLTDMOD: %d\n", bltdmod); printf("BLTDMOD: %d\n", bltdmod);
printf("BLTSIZE: %d, %d\n", (width >> 4), height); printf("BLTSIZE: %d, %d\n", (width >> 4), height);
*/
/* bltapt += (uint32_t)MaskBitplane;
for (plane = 0; plane < 3; ++plane) { bltbpt += (uint32_t)TopazBitplanes;
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = bltcon0; custom.bltcon0 = bltcon0;
custom.bltcon1 = 0; custom.bltcon1 = 0;
custom.bltafwm = 0xffff; custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff; custom.bltalwm = 0xffff;
custom.bltapt = MaskBitplane; custom.bltapt = bltapt;
custom.bltbpt = bltbpt; custom.bltbpt = bltbpt + (plane * TOPAZ_WIDTH_BYTES * 256);
custom.bltcpt = activeScreenBufferDetails.planes[plane] + 8; custom.bltcpt = bltcpt + activeScreenBufferDetails.planes[plane];
custom.bltdpt = activeScreenBufferDetails.planes[plane] + 8; custom.bltdpt = bltdpt + activeScreenBufferDetails.planes[plane];
custom.bltamod = 0; custom.bltamod = bltamod;
custom.bltbmod = 0; custom.bltbmod = bltbmod;
custom.bltcmod = bltcmod; custom.bltcmod = bltcmod;
custom.bltdmod = bltcmod; custom.bltdmod = bltdmod;
custom.bltsize = BLTSIZE(TOPAZ_WIDTH_WORDS, 256); custom.bltsize = bltsize;
bltbpt += TOPAZ_WIDTH_BYTES * 256;
WaitBlit(); WaitBlit();
} }
*/
break;
} }
} }
} }
} }
static struct MsgPort *keyboardMessagePort = NULL;
static struct IOStdReq *keyboardIO = NULL;
static struct Interrupt keyboardInterrupt;
extern far ULONG keyboardPressed;
extern struct InputEvent * __asm stupidKeyboardHandler(
register __a0 struct InputEvent *input,
register __a1 APTR id
);
void setupKeyboard(void) {
if (keyboardMessagePort = CreatePort(NULL, NULL)) {
if (keyboardIO = (struct IOStdReq *)CreateExtIO(
keyboardMessagePort,
sizeof(struct IOStdReq)
)) {
// OpenDevice returns 0 if successful
if (!OpenDevice(
"input.device",
0,
(struct IORequest *)keyboardIO,
0
)) {
keyboardInterrupt.is_Node.ln_Type = NT_INTERRUPT;
keyboardInterrupt.is_Node.ln_Pri = 100;
keyboardInterrupt.is_Node.ln_Name = (STRPTR)"cool bun";
keyboardInterrupt.is_Code = (void (*)())&stupidKeyboardHandler;
keyboardIO->io_Data = (void *)&keyboardInterrupt;
keyboardIO->io_Command = IND_ADDHANDLER;
DoIO((struct IORequest *)keyboardIO);
}
}
}
}
void teardownKeyboard(void) {
if (keyboardIO) {
keyboardIO->io_Data = (void *)&keyboardInterrupt;
keyboardIO->io_Command = IND_REMHANDLER;
DoIO((struct IORequest *)keyboardIO);
CloseDevice((struct IORequest *)keyboardIO);
DeleteIORequest((struct IORequest *)keyboardIO);
keyboardIO = NULL;
}
if (keyboardMessagePort) {
DeleteMsgPort(keyboardMessagePort);
keyboardMessagePort = NULL;
}
}
int main(void) { int main(void) {
int i; int i;
struct BunRenderer bunRenderer; struct BunRenderer bunRenderer;
uint16_t redrawRanges[BUN_COUNT][4]; uint16_t redrawRanges[BUN_COUNT][4];
/*
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
SCREEN_WIDTH,
SCREEN_HEIGHT,
3
);
setupBunRenderer(
&bunRenderer,
&screenDefinition,
&activeScreenBufferDetails
);
calculateNeededRedrawRanges(i, redrawRanges);
calculateTopazRenderPartialAreas(redrawRanges);
printf("********\n");
for (i = 0; i < BUN_COUNT; ++i) {
if (renderPartialAreas[i][0] == 0) continue;
printf(
"%d, %d, %d, %d, %d\n",
renderPartialAreas[i][0],
renderPartialAreas[i][1],
renderPartialAreas[i][2],
renderPartialAreas[i][3],
renderPartialAreas[i][4]
);
}
calculateTopazRenderPartialBlitterSettings();
printf("********\n");
for (i = 0; i < BUN_COUNT; ++i) {
if (renderPartialAreas[i][0] == 0) continue;
printf(
"%d, %d, %d, %d, %x\n",
renderPartialAreas[i][0],
renderPartialAreas[i][1],
renderPartialAreas[i][2],
renderPartialAreas[i][3],
renderPartialAreas[i][4]
);
}
teardownScreen(&screenDefinition);
return 0;
*/
printf("\nCool bun blitter, copper, and sprite demo by John Bintz\n"); printf("\nCool bun blitter, copper, and sprite demo by John Bintz\n");
printf("\n"); printf("\n");
printf("This is my first real go at writing graphics code for the Amiga.\n"); printf("This is my first real go at writing graphics code for the Amiga.\n");
@ -310,6 +544,7 @@ int main(void) {
buildCopperlist(); buildCopperlist();
/* /*
copperlist debugging copperlist debugging
for (i = 0; i < 20; ++i) { for (i = 0; i < 20; ++i) {
@ -322,11 +557,7 @@ int main(void) {
); );
} }
*/ */
setupKeyboard();
calculateNeededRedrawRanges(0, redrawRanges);
renderTopazPartials(redrawRanges);
/*
takeOverSystem(); takeOverSystem();
setCopperlist(copperlist); setCopperlist(copperlist);
@ -337,16 +568,31 @@ int main(void) {
renderTopaz(); renderTopaz();
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails); swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
updateDisplayInCopperList(
&screenDefinition,
&activeScreenBufferDetails,
copperlistBitplanePointers
);
i = 0; i = 0;
while (1) {
WaitTOF();
while (0) {
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails); swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
clearCurrentBuns(&bunRenderer); clearCurrentBuns(&bunRenderer);
renderBunFrame(i, &bunRenderer); renderBunFrame(i, &bunRenderer);
/*
calculateNeededRedrawRanges(i, redrawRanges);
renderTopazPartials(redrawRanges);
*/
renderMostlyTopaz();
//WaitTOF();
updateDisplayInCopperList( updateDisplayInCopperList(
&screenDefinition, &screenDefinition,
@ -354,16 +600,21 @@ int main(void) {
copperlistBitplanePointers copperlistBitplanePointers
); );
WaitBOF(250); //WaitBOF(100);
//WaitTOF();
if (keyboardPressed) {
i++;
}
if ((ciaa.ciapra >> 6) != 3) break; if ((ciaa.ciapra >> 6) != 3) break;
i++; i++;
//i %= FRAMES_FOR_SCREEN; i %= FRAMES_FOR_SCREEN;
} }
giveBackSystem(); giveBackSystem();
*/ teardownKeyboard();
teardownScreen(&screenDefinition); teardownScreen(&screenDefinition);

View File

@ -69,6 +69,10 @@ void swapCurrentScreenBuffer(
struct ScreenDefinition *screenDefinition, struct ScreenDefinition *screenDefinition,
struct ActiveScreenBufferDetails *currentScreen struct ActiveScreenBufferDetails *currentScreen
) { ) {
setActiveScreenBuffer(screenDefinition, currentScreen, 1 - currentScreen->currentBuffer); setActiveScreenBuffer(
screenDefinition,
currentScreen,
1 - currentScreen->currentBuffer
);
} }

View File

@ -9,6 +9,9 @@
XDEF _endCopperlist XDEF _endCopperlist
XDEF _myWaitBlit XDEF _myWaitBlit
XDEF _WaitBOF XDEF _WaitBOF
XDEF _stupidKeyboardHandler
XDEF _keyboardPressed
XREF _custom XREF _custom
@ -29,6 +32,8 @@ FUNC_CNT SET FUNC_CNT-6
INCLUDE "hardware/custom.i" INCLUDE "hardware/custom.i"
INCLUDE "hardware/dmabits.i" INCLUDE "hardware/dmabits.i"
INCLUDE "hardware/intbits.i" INCLUDE "hardware/intbits.i"
INCLUDE "exec/io.i"
INCLUDE "devices/inputevent.i"
; @param 1 Pointer to null terminated name of library ; @param 1 Pointer to null terminated name of library
; @param 2 Minimum version of library, 0 for any ; @param 2 Minimum version of library, 0 for any
@ -73,6 +78,52 @@ ActiveScreenBufferDetails_planes EQU SOFFSET
SOFFSET SET SOFFSET+(8*4) SOFFSET SET SOFFSET+(8*4)
LABEL ActiveScreenBufferDetails_SIZEOF LABEL ActiveScreenBufferDetails_SIZEOF
; @see https://amigadev.elowar.com/read/ADCD_2.1/Devices_Manual_guide/node019A.html
; @register A0 struct InputEvent *
; @register A1 extra data about the event
; @output D0 The value of A0
_stupidKeyboardHandler:
; @stack [RA,A0,current node]
MOVE.L A0,-(SP)
MOVE.L #0,-(SP)
_stupidKeyboardHandler_CheckLoop:
CMP.B #IECLASS_RAWKEY,ie_Class(A0)
BNE.S _stupidKeyboardHandler_NextEvent
MOVE.W ie_Code(A0),D0
AND.W #IECODE_UP_PREFIX,D0
SEQ _keyboardPressed
; if next_event:
; do the stack swap thing below
; else:
; change the A0 in the stack above it
TST.L (SP)
BNE.S _stupidKeyboardHandler_hasLastEvent
MOVE.L (A0),4(SP)
BRA.S _stupidKeyboardHandler_NextEvent
_stupidKeyboardHandler_hasLastEvent:
; put the next event in the first pointer of the
; last event
MOVE.L A1,-(SP)
MOVE.L 4(SP),A1
MOVE.L (A0),(A1)
MOVE.L (SP)+,A1
_stupidKeyboardHandler_NextEvent:
; next event is in first long of struct
MOVE.L (A0),D0
; store current node in stack
MOVE.L A0,(SP)
MOVE.L D0,A0
BNE.S _stupidKeyboardHandler_CheckLoop
MOVE.L (SP)+,D0
MOVE.L (SP)+,D0
RTS
M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C
_takeOverSystem: _takeOverSystem:
@ -438,5 +489,8 @@ VBIPtr dc.l 0
CNOP 0,4 CNOP 0,4
GraphicsLibrary GRAPHICSNAME GraphicsLibrary GRAPHICSNAME
CNOP 0,4
_keyboardPressed dc.l 0
SECTION Sprite,Data_C SECTION Sprite,Data_C
EmptySprite dc.w 0,0 EmptySprite dc.w 0,0