Compare commits

..

No commits in common. "main" and "jb/sprites" have entirely different histories.

45 changed files with 2305 additions and 1902 deletions

BIN
32x50

Binary file not shown.

View File

@ -1,90 +0,0 @@
/**
* What do we need
* * [ ] screen setup
*/
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <clib/graphics_protos.h>
#include "system/system.h"
#include "system/copper.h"
#include "system/blitter.h"
#include "screen.h"
extern struct Custom far custom;
extern struct CIA far ciaa;
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
extern unsigned char chip coolbun[];
int main(void) {
struct ScreenDefinition screenDefinition;
struct ActiveScreenBufferDetails activeScreenBufferDetails;
uint16_t *copperlist, *currentCopperlist;
void *copperlistBitplanePointers[8][2];
int i, plane;
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
320,
256,
2
);
copperlist = prepareNewCopperlist(300);
currentCopperlist = addDisplayToCopperlist(
copperlist,
&screenDefinition,
&activeScreenBufferDetails,
&copperlistBitplanePointers
);
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
endCopperlist(currentCopperlist);
takeOverSystem();
setCopperlist(copperlist);
setUpDisplay((uint32_t)screenDefinition.bitplanes);
// Render a bun at 32x50
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, 0);
custom.bltcon1 = BLTCON1(BLITTER_ASCENDING, 0);
custom.bltapt = coolbun + (plane * 4 * 32);
custom.bltdpt = activeScreenBufferDetails.planes[plane] + (50 * 320 / 8) + 32 / 8;
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltamod = 0;
custom.bltdmod = 40 - 4;
custom.bltsize = 2 + (32 << 6);
WaitBlit();
}
while (1) {
if ((ciaa.ciapra >> 6) != 3) break;
}
giveBackSystem();
freeCopperlist(copperlist);
teardownScreen(&screenDefinition);
}

BIN
33x50

Binary file not shown.

View File

@ -1,127 +0,0 @@
/**
* What do we need
* * [ ] screen setup
*/
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <clib/graphics_protos.h>
#include "system/system.h"
#include "system/copper.h"
#include "system/blitter.h"
#include "screen.h"
extern struct Custom far custom;
extern struct CIA far ciaa;
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
extern unsigned char chip coolbun[];
int main(void) {
struct ScreenDefinition screenDefinition;
struct ActiveScreenBufferDetails activeScreenBufferDetails;
uint16_t *copperlist, *currentCopperlist;
void *copperlistBitplanePointers[8][2];
int i, plane, x, y, dirX, dirY, shift, byteX;
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
320,
256,
2
);
copperlist = prepareNewCopperlist(300);
currentCopperlist = addDisplayToCopperlist(
copperlist,
&screenDefinition,
&activeScreenBufferDetails,
&copperlistBitplanePointers
);
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
endCopperlist(currentCopperlist);
takeOverSystem();
setCopperlist(copperlist);
setUpDisplay((uint32_t)screenDefinition.bitplanes);
// Render a bun at 32x50
x = 32;
y = 50;
dirX = 1;
dirY = 1;
while (1) {
WaitTOF();
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
shift = x & 15;
byteX = (x >> 4 * 2);
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, shift);
custom.bltcon1 = BLTCON1(BLITTER_ASCENDING, 0);
custom.bltapt = coolbun + (plane * 4 * 32);
custom.bltdpt = activeScreenBufferDetails.planes[plane] + (y * 320 / 8) + byteX;
custom.bltafwm = 0xffff;
if (shift == 0) {
custom.bltalwm = 0xffff;;
} else {
custom.bltalwm = 0x0000;
}
custom.bltamod = shift ? -2 : 0;
custom.bltdmod = 40 - (shift ? 6 : 4);
custom.bltsize = (shift ? 3 : 2) + (32 << 6);
WaitBlit();
}
x += dirX;
if (x == 320 - 32) {
x -= 1;
dirX = -dirX;
}
if (x < 0) {
x = 0;
dirX = -dirX;
}
y += dirY;
if (y == 256 - 32) {
y -= 1;
dirY = -dirY;
}
if (y > 0) {
y = 0;
dirY -= dirY;
}
if ((ciaa.ciapra >> 6) != 3) break;
}
giveBackSystem();
freeCopperlist(copperlist);
teardownScreen(&screenDefinition);
}

1
NOTES.md Normal file
View File

@ -0,0 +1 @@
* [ ] Move bun calculation to separate file for CuTest and vamos

View File

@ -1,50 +0,0 @@
## Cool Bun Demo
![demo](./demo.gif)
Built for [The Obligatory Amiga Blitter Video](https://makertube.net/w/eV545ku522sRq8CTcxDuFZ).
Uses a bunch of C and Assembler code to drive the blitter, sprites, and copper
to display high color Topaz art overtop of flying cool bun logos.
## Running
Click the mouse to escape any demo.
* `main`: Main demo
* `32x50`, `33x50`, `left_side`, `right_side`: Rendering Cool Bun in various
locations on screen.
* `any_position`: Cool Bun flies around like a DVD player pause screen.
* `keyboard_interrupt`: Tests using `input.device` to access the keyboard.
* `blitter_speed_test`: Get the speed of blitter vs. CPU memory operations
* `bun_test`: Run some unit tests (yes, really!)
This will get 50 fps on an 020, and 25 or lower on an 68EC020 and below.
## Building
### Vamos
You'll want [Vamos](https://github.com/cnvogelg/amitools/blob/master/docs/vamos.md),
and [SAS/C](https://www.amigaclub.be/blog/steffest/2/amiga-c%20compilers)
&amp; [GenAm from DevPac](https://archive.org/details/Devpac_v3.14_1994-12-16_HiSoft)
on Vamos's path:
```
# main
ruby ./image_converter.rb && touch images.s && vamos -- smake
# any others
vamos -- smake <other>
```
The image converter requires Ruby 3.2.4 and RMagick installed.
## Performance
The best way I can think of to make this way faster is for a script in
Ruby or Python to calculate every blitter register for every frame of data
for bun renders and clears, store that in a list of words, and rip through
those lists in Assembler, shotgunning the values directly into the registers
without the C code needing to track bun positions and bun clears. That's a
project for another day.

Binary file not shown.

View File

@ -1,144 +0,0 @@
/**
* What do we need
* * [ ] screen setup
*/
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <clib/graphics_protos.h>
#include "system/system.h"
#include "system/copper.h"
#include "system/blitter.h"
#include "screen.h"
extern struct Custom far custom;
extern struct CIA far ciaa;
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
extern unsigned char chip coolbun[];
int main(void) {
struct ScreenDefinition screenDefinition;
struct ActiveScreenBufferDetails activeScreenBufferDetails;
uint16_t *copperlist, *currentCopperlist;
void *copperlistBitplanePointers[8][2];
int i, plane, x, y, dirX, dirY, shift, byteX, clearY;
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
320,
256,
2
);
copperlist = prepareNewCopperlist(300);
currentCopperlist = addDisplayToCopperlist(
copperlist,
&screenDefinition,
&activeScreenBufferDetails,
&copperlistBitplanePointers
);
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
endCopperlist(currentCopperlist);
takeOverSystem();
setCopperlist(copperlist);
setUpDisplay((uint32_t)screenDefinition.bitplanes);
// Render a bun at 32x50
x = 32;
y = 50;
dirX = 1;
dirY = 1;
while (1) {
WaitTOF();
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
shift = x & 15;
byteX = ((x >> 4) * 2);
clearY = y - 4;
if (clearY < 0) clearY = 0;
if (clearY + 40 > 255) clearY = 255 - 40;
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xc0, 0, 0, 0, 1, 0);
custom.bltcon1 = 0;
custom.bltadat = 0x0000;
custom.bltdpt = activeScreenBufferDetails.planes[plane] + (clearY * 320 / 8);
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltsize = BLTSIZE(20, 40);
custom.bltdmod = 0;
WaitBlit();
}
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, shift);
custom.bltcon1 = BLTCON1(BLITTER_ASCENDING, 0);
custom.bltapt = coolbun + (plane * 4 * 32);
custom.bltdpt = activeScreenBufferDetails.planes[plane] + (y * 320 / 8) + byteX;
custom.bltafwm = 0xffff;
if (shift == 0) {
custom.bltalwm = 0xffff;;
} else {
custom.bltalwm = 0x0000;
}
custom.bltamod = shift ? -2 : 0;
custom.bltdmod = 40 - (shift ? 6 : 4);
custom.bltsize = (shift ? 3 : 2) + (32 << 6);
WaitBlit();
}
x += dirX;
if (x == 320 - 32) {
x -= 1;
dirX = -dirX;
}
if (x < 0) {
x = 0;
dirX = -dirX;
}
y += dirY;
if (y == 256 - 32) {
y -= 1;
dirY = -dirY;
}
if (y < 0) {
y = 0;
dirY = -dirY;
}
if ((ciaa.ciapra >> 6) != 3) break;
}
giveBackSystem();
freeCopperlist(copperlist);
teardownScreen(&screenDefinition);
}

BIN
basics Executable file

Binary file not shown.

172
basics.s Normal file
View File

@ -0,0 +1,172 @@
XREF _custom
; write this from scratch and get it working
; then plug it into C
FUNC_CNT SET -30
FUNCDEF MACRO
_LVO\1 EQU FUNC_CNT
FUNC_CNT SET FUNC_CNT-6
ENDM
INCDIR "include_i_39:"
INCDIR "extra_lvos_39:"
INCLUDE "exec/exec_lib.i"
INCLUDE "exec/types.i"
INCLUDE "exec/execbase.i"
INCLUDE "exec/libraries.i" # get the CALLLIB macro
INCLUDE "graphics/gfxbase.i"
INCLUDE "graphics_lvo.i"
INCLUDE "hardware/custom.i"
INCLUDE "hardware/dmabits.i"
START:
BSR _takeOverSystem
BSR _giveBackSystem
MOVE.L #0,D0
RTS
OpenGraphicsLibrary MACRO
LEA GraphicsLibrary,A1
MOVEQ #0,D0
CALLLIB _LVOOpenLibrary
MOVE.L D0,GraphicsBase
ENDM
TakeOverView MACRO
MOVE.L GraphicsBase,A6
MOVE.L gb_ActiView(A6),OldView
MOVEQ #0,D0
CALLLIB _LVOLoadView
CALLLIB _LVOWaitTOF
CALLLIB _LVOWaitTOF
ENDM
PreserveOldCopper MACRO
MOVE.L $26(A6),OldCopper1
MOVE.L $32(A6),OldCopper2
ENDM
GetVBRPointer MACRO
BSR getVBR
MOVE.L D0,VBRPtr
ENDM
PreserveOldRegisters MACRO
LEA _custom,A6
MOVE.W adkconr(A6),Oldadkcon
MOVE.W intenar(A6),Oldintena
MOVE.W dmaconr(A6),Olddmacon
ENDM
ClearRegisters MACRO
MOVE.W #$7FFF,D0
BSR waitRaster
MOVE.W D0,intena(A6)
MOVE.W D0,dmacon(A6)
MOVE.W D0,intreq(A6)
ENDM
SetRegisters MACRO
MOVE.W #$C000,intena(A6) ; enable master interrupt
MOVE.W #$3FFF,intena(A6) ; disable every other interrupt
MOVE.W #DMAF_SETCLR|DMAF_COPPER|DMAF_RASTER|DMAF_BLITTER,dmacon(A6)
MOVE.W #DMAF_AUDIO|DMAF_DISK|DMAF_SPRITE,dmacon(A6)
ENDM
_takeOverSystem:
MOVEM.L A6,-(SP)
CLR.W $100
MOVE.L $4,A6
CALLLIB _LVOForbid
OpenGraphicsLibrary
PreserveOldCopper
CALLLIB _LVOOwnBlitter
CALLLIB _LVOWaitBlit
PreserveOldRegisters
SetRegisters
TakeOverView
MOVEM.L (SP)+,A6
RTS
waitRaster:
MOVE.L D0,-(SP)
.loop:
MOVE.L $DFF004,D0
AND.L #$1FF00,D0
CMP.L #303<<8,D0
BNE .loop
MOVE.L (SP)+,D0
RTS
_giveBackSystem:
CLR.W $100
MOVEM.L A6,-(SP)
LEA _custom,A6
MOVE.W #$8000,d0
OR.W D0,Olddmacon
OR.W D0,Oldintena
OR.W D0,Oldadkcon
SUBQ #1,D0
;ClearRegisters
MOVE.L OldCopper1,cop1lc(A6)
MOVE.L OldCopper2,cop2lc(A6)
MOVE.W #1,copjmp1(A6)
MOVE.W Olddmacon,intena(A6)
MOVE.W Olddmacon,dmacon(A6)
MOVE.W Oldadkcon,adkcon(A6)
MOVE.L OldView,A1
MOVE.L GraphicsBase,A6
CALLLIB _LVOLoadView
CALLLIB _LVOWaitTOF
CALLLIB _LVOWaitTOF
MOVE.L $4,A6
MOVE.L GraphicsBase,D0
MOVE.L D0,A1
CALLLIB _LVOCloseLibrary
CALLLIB _LVOPermit
MOVEM.L (SP)+,A6
RTS
getVBR:
MOVE.L A5,-(SP)
MOVEQ #0,D0
MOVE.L $4,A6
BTST #0,AttnFlags+1(A6)
BEQ .is68K
LEA .get010VBR(pc),A5
CALLLIB _LVOSupervisor
.is68K:
MOVE.L (SP)+,A5
RTS
.get010VBR:
dc.l $4E7A0801 ; movec vcr,d0
RTE
CNOP 0,4
GraphicsLibrary dc.b 'graphics.library',0
CNOP 0,4
GraphicsBase dc.l 1
OldView dc.l 1
OldCopper1 dc.l 1
OldCopper2 dc.l 1
VBRPtr dc.l 1
Oldadkcon dc.w 0
Oldintena dc.w 0
Olddmacon dc.w 0

BIN
better_startup Executable file

Binary file not shown.

98
better_startup.c Normal file
View File

@ -0,0 +1,98 @@
#include <clib/exec_protos.h>
#include <clib/intuition_protos.h>
#include <clib/graphics_protos.h>
#include <exec/memory.h>
#include <graphics/gfxbase.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <exec/types.h>
extern struct GfxBase *GfxBase;
extern far struct Custom custom;
int main(void) {
UWORD OldDMACON,OldINTENA,OldINTREQ,OldADKCON;
struct View *OldView = ((struct GfxBase *)GfxBase)->ActiView;
ULONG OldCopper = custom.cop1lc;
ULONG OldCopper2 = custom.cop2lc;
UWORD *copperlist = AllocMem(10000, MEMF_CHIP | MEMF_CLEAR);
UWORD *currentCopperlist;
UBYTE *bitplanes = AllocMem(320 * 256, MEMF_CHIP | MEMF_CLEAR);
int i;
LoadView(0);
WaitTOF();
WaitTOF();
OwnBlitter();
WaitBlit();
Forbid();
OldDMACON = custom.dmaconr | 0x8000;
OldINTENA = custom.intenar | 0x8000;
//OldINTREQ = custom.intreqr | 0x8000;
OldADKCON = custom.adkconr | 0x8000;
custom.intreq = 0x7fff;
custom.cmacon = 0x7fff;
custom.cmacon = 0x7fff;
// enable
custom.dmacon = DMAF_SETCLR | DMAF_COPPER | DMAF_RASTER | DMAF_BLITTER;
// disable
custom.dmacon = DMAF_AUDIO | DMAF_DISK | DMAF_SPRITE;
custom.bplcon0 = (1 << 9) + (1 << 12);
custom.bplcon1 = 0;
custom.bplcon2 = 0;
custom.bpl1mod = 0;
custom.bpl2mod = 0;
custom.diwstrt = 0x2c21;
custom.diwstop = 0x2cc1;
custom.ddfstrt = 0x0038;
custom.ddfstop = 0x00d0;
currentCopperlist = copperlist;
*(currentCopperlist++) = 0x0050;
*(currentCopperlist++) = ((ULONG)bitplanes >> 16);
*(currentCopperlist++) = 0x0020;
*(currentCopperlist++) = ((ULONG)bitplanes && 16);
*(currentCopperlist++) = 0xffff;
*(currentCopperlist++) = 0xfffe;
custom.cop1lc = copperlist;
for (i = 0; i < 200; ++i) {
WaitTOF();
}
custom.dmacon = 0x7FFF;
custom.dmacon = OldDMACON;
custom.intena = 0x7FFF;
custom.intena = OldINTENA;
/*
custom.intreq = 0x7FFF;
custom.intreq = OldINTREQ;
*/
custom.adkcon = 0x7FFF;
custom.adkcon = OldADKCON;
custom.cop1lc = OldCopper;
custom.cop2lc = OldCopper1;
LoadView(OldView);
WaitTOF();
WaitTOF();
WaitBlit();
DisownBlitter();
Permit();
FreeMem(copperlist, 10000);
FreeMem(bitplanes, 320 * 256);
}

0
blitter_speed_test.q Normal file
View File

347
bun.c
View File

@ -13,7 +13,6 @@
#include "screen.h" #include "screen.h"
#include "bun.h" #include "bun.h"
#include "system/system.h" #include "system/system.h"
#include "system/blitter.h"
#define COOL_BUN_WIDTH (32) #define COOL_BUN_WIDTH (32)
#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8) #define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8)
@ -27,113 +26,82 @@
#define BUN_MAX_RANGE (31 + 320) #define BUN_MAX_RANGE (31 + 320)
#define BUN_COUNT (12)
#define BUN_SPEED (1) #define BUN_SPEED (1)
#define BUN_HORIZ_DISTANCE_BETWEEN_BUNS ((BUN_MAX_RANGE / 4) - COOL_BUN_WIDTH) #define BUN_HORIZ_DISTANCE_BETWEEN_BUNS ((BUN_MAX_RANGE / 4) - COOL_BUN_WIDTH)
#define BUN_TOTAL_HORIZ_DISTANCE (BUN_HORIZ_DISTANCE_BETWEEN_BUNS + COOL_BUN_WIDTH) #define BUN_TOTAL_HORIZ_DISTANCE (BUN_HORIZ_DISTANCE_BETWEEN_BUNS + COOL_BUN_WIDTH)
#define BUN_ROW_START (50) #define BUN_ROW_START (30)
#define BUN_VERT_DISTANCE_BETWEEN_BUNS (30) #define BUN_VERT_DISTANCE_BETWEEN_BUNS (20)
#define BUN_TOTAL_VERT_DISTANCE (COOL_BUN_HEIGHT + BUN_VERT_DISTANCE_BETWEEN_BUNS) #define BUN_TOTAL_VERT_DISTANCE (COOL_BUN_HEIGHT + BUN_VERT_DISTANCE_BETWEEN_BUNS)
#define FRAME_MAX (BUN_TOTAL_HORIZ_DISTANCE / BUN_SPEED) #define FRAME_MAX (BUN_TOTAL_HORIZ_DISTANCE / BUN_SPEED)
#define FRAMES_FOR_SCREEN (90)
#define BUN_WAVE_LENGTH (FRAMES_FOR_SCREEN / 2) #define BUN_WAVE_LENGTH (FRAMES_FOR_SCREEN / 2)
// linked as raw bytes in assembler // linked as raw bytes in assembler
extern unsigned char chip coolbun[]; extern unsigned char far coolbun[];
unsigned char *coolbunArea = 0;
#define BLTCON0( \
minterm, aChan, bChan, cChan, dChan, shift \
) (minterm + (aChan << 11) + (bChan << 10) + (cChan << 9) + (dChan << 8) + (shift << 12))
#define BLTCON1(descending, shift) ((descending << 1) + (shift << 12))
extern struct Custom far custom; extern struct Custom far custom;
struct BunClear { void setupBun(void) {
uint16_t memoryStartOffsetBytes; unsigned char *currentCoolBunArea, *currentCoolBun;
uint16_t widthWords;
uint16_t heightRows;
uint8_t direction;
};
#define BUN_OFF_RIGHT_SIDE (0) coolbunArea = AllocMem(COOL_BUN_MEMORY_SIZE, MEMF_CHIP | MEMF_CLEAR);
#define BUN_OFF_LEFT_SIDE (1) currentCoolBunArea = coolbunArea;
#define BUN_ANYWHERE (2) currentCoolBun = coolbun;
uint8_t *coolbunPlaneStarts[3][2]; CopyMem(coolbun, coolbunArea, COOL_BUN_MEMORY_SIZE);
}
uint16_t bunRightSide_bltalwmPrecalc[16]; void teardownBun(void) {
uint16_t bunLeftSide_bltalwmPrecalc[16]; if (coolbunArea) {
FreeMem(coolbunArea, COOL_BUN_MEMORY_SIZE);
void precalculateBunBLTALWM() {
int shift, j;
uint16_t bltalwm;
for (shift = 0; shift < 16; ++shift) {
// right
bltalwm = 0x0000;
for (j = 0; j < 15 - shift; ++j) {
bltalwm += (1 << (15 - j));
}
bunRightSide_bltalwmPrecalc[shift] = bltalwm;
//left
bltalwm = 0x0000;
for (j = 0; j <= 15 - shift; ++j) {
bltalwm += (1 << j);
}
bunLeftSide_bltalwmPrecalc[shift] = bltalwm;
} }
} }
void bun_offRightSide( void bun_offRightSide(
int plusXValue, int plusXValue,
int y, int y,
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *activeScreenBufferDetails, struct CurrentScreen *currentScreen
struct BunClear *bunClear
) { ) {
uint8_t i, plane = 0; uint8_t i, plane = 0;
uint8_t shift = plusXValue & 15; uint8_t shift = plusXValue & 15;
uint8_t wordShift = (plusXValue >> 4); uint8_t wordShift = (plusXValue >> 4);
uint16_t bltalwm, bltcon0, bltcon1, bltdmod, bltsize; uint16_t bltalwm;
bunClear->memoryStartOffsetBytes = (y * screenDefinition->byteWidth) + for (plane = 0; plane < 2; ++plane) {
screenDefinition->byteWidth - COOL_BUN_WIDTH_BYTES + custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
custom.bltcon1 = BLTCON1(0, shift);
custom.bltadat = 0xffff;
custom.bltbpt = coolbunArea +
plane * COOL_BUN_PLANE_SIZE;
custom.bltdpt = currentScreen->planes[plane] +
(y * screenSetup->byteWidth) +
screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES +
wordShift * 2; wordShift * 2;
bunClear->heightRows = COOL_BUN_HEIGHT;
bunClear->widthWords = 2 - wordShift;
bunClear->direction = BLITTER_ASCENDING;
bltalwm = bunRightSide_bltalwmPrecalc[shift]; custom.bltafwm = 0xffff;
/*
bltalwm = 0x0000; bltalwm = 0x0000;
for (i = 0; i <= 15 - shift; ++i) { for (i = 0; i <= 15 - shift; ++i) {
bltalwm += (1 << (15 - i)); bltalwm += (1 << (15 - i));
} }
*/
bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, shift);
bltcon1 = BLTCON1(bunClear->direction, shift);
bltdmod = screenDefinition->byteWidth - COOL_BUN_WIDTH_BYTES +
wordShift * 2;
bltsize = bunClear->widthWords + (bunClear->heightRows << 6);
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = bltcon0;
custom.bltcon1 = bltcon1;
custom.bltapt = coolbunPlaneStarts[BUN_OFF_RIGHT_SIDE][plane];
custom.bltdpt = activeScreenBufferDetails->planes[plane] +
bunClear->memoryStartOffsetBytes;
custom.bltafwm = 0xffff;
custom.bltalwm = bltalwm; custom.bltalwm = bltalwm;
custom.bltamod = wordShift * 2; custom.bltbmod = wordShift * 2;
custom.bltdmod = bltdmod; custom.bltdmod = screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES +
wordShift * 2;
custom.bltsize = bltsize; custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6);
WaitBlit(); WaitBlit();
} }
@ -142,58 +110,47 @@ void bun_offRightSide(
void bun_offLeftSide( void bun_offLeftSide(
int minusXValue, int minusXValue,
int y, int y,
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *activeScreenBufferDetails, struct CurrentScreen *currentScreen
struct BunClear *bunClear
) { ) {
unsigned char plane; unsigned char plane;
uint8_t shift = minusXValue & 15; uint8_t shift = minusXValue & 15;
uint8_t wordShift = (minusXValue >> 4); uint8_t wordShift = (minusXValue >> 4);
uint8_t i; uint8_t i;
uint16_t bltalwm, bltcon0, bltcon1, bltdmod, bltsize; uint16_t bltalwm;
// y can't be 0 otherwise we will corrupt memory for now // y can't be 0 otherwise we will corrupt memory for now
if (y == 0) return; if (y == 0) return;
bunClear->memoryStartOffsetBytes = (screenDefinition->byteWidth * (y + COOL_BUN_LAST_ROW)) + for (plane = 0; plane < 2; ++plane) {
2 - wordShift * 2; // shift left, so descending
bunClear->heightRows = COOL_BUN_HEIGHT; custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
bunClear->widthWords = 2 - wordShift; custom.bltcon1 = BLTCON1(1, shift);
bunClear->direction = BLITTER_DESCENDING;
bltalwm = bunLeftSide_bltalwmPrecalc[shift]; // a has a mask we're shifting
custom.bltadat = 0xffff;
// b has bun data
custom.bltbpt = coolbunArea + 2 +
COOL_BUN_LAST_ROW_BYTES +
plane * COOL_BUN_PLANE_SIZE;
/* // d is the part on screen
custom.bltdpt = currentScreen->planes[plane] +
(screenSetup->byteWidth * (y + COOL_BUN_LAST_ROW)) +
2 -
wordShift * 2;
custom.bltafwm = 0xffff;
bltalwm = 0x0000; bltalwm = 0x0000;
for (i = 0; i <= 15 - shift; ++i) { for (i = 0; i <= 15 - shift; ++i) {
bltalwm += (1 << i); bltalwm += (1 << i);
} }
*/
bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, shift);
bltcon1 = BLTCON1(bunClear->direction, shift);
bltdmod = screenDefinition->byteWidth - 4 + wordShift * 2;
bltsize = bunClear->widthWords + (bunClear->heightRows << 6);
for (plane = 0; plane < 2; ++plane) {
// shift left, so descending
custom.bltcon0 = bltcon0;
custom.bltcon1 = bltcon1;
// a has bun data
custom.bltapt = coolbunPlaneStarts[BUN_OFF_LEFT_SIDE][plane];
// d is the part on screen
custom.bltdpt = activeScreenBufferDetails->planes[plane] + bunClear->memoryStartOffsetBytes;
custom.bltafwm = 0xffff;
custom.bltalwm = bltalwm; custom.bltalwm = bltalwm;
custom.bltamod = wordShift * 2; custom.bltbmod = wordShift * 2;
custom.bltdmod = bltdmod; custom.bltdmod = screenSetup->byteWidth - 4 + wordShift * 2;
custom.bltsize = bltsize; custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6);
WaitBlit(); WaitBlit();
} }
@ -202,101 +159,65 @@ void bun_offLeftSide(
void bun_anywhere( void bun_anywhere(
int x, int x,
int y, int y,
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *activeScreenBufferDetails, struct CurrentScreen *currentScreen
struct BunClear *bunClear
) { ) {
uint8_t plane; uint8_t plane;
uint8_t shift = x & 15; uint8_t shift = x & 15;
uint8_t needsExtraWord = shift != 0; uint8_t needsExtraWord = shift != 0;
uint16_t bltcon0, bltcon1, bltalwm, bltamod, bltdmod, bltsize;
bunClear->memoryStartOffsetBytes = WORD_ALIGNED_BYTE_POSITION(screenDefinition->width, x, y);
bunClear->heightRows = COOL_BUN_HEIGHT;
bunClear->widthWords = 2 + needsExtraWord;
bunClear->direction = BLITTER_ASCENDING;
// buns will never interfere with a background so they don't need a mask
bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, shift);
bltcon1 = BLTCON1(bunClear->direction, shift);
if (needsExtraWord) {
bltalwm = 0x0000;
} else {
bltalwm = 0xffff;
}
bltamod = -(needsExtraWord * 2);
bltdmod = screenDefinition->byteWidth - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2);
bltsize = bunClear->widthWords + (bunClear->heightRows << 6);
for (plane = 0; plane < 2; ++plane) { for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = bltcon0; // if we extend the bun area by a word, we only need one write
custom.bltcon1 = bltcon1;
custom.bltapt = coolbunPlaneStarts[BUN_ANYWHERE][plane]; // buns will never interfere with a background so they don't need a mask
custom.bltdpt = activeScreenBufferDetails->planes[plane] + // they do need the scratch area though
bunClear->memoryStartOffsetBytes; custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
custom.bltcon1 = BLTCON1(0, shift);
custom.bltadat = 0xffff;
custom.bltbpt = coolbunArea + plane * COOL_BUN_PLANE_SIZE;
custom.bltdpt = currentScreen->planes[plane] +
WORD_ALIGNED_BYTE_POSITION(screenSetup->width, x, y);
// custom.bltdpt = screenSetup.memoryStart;
custom.bltafwm = 0xffff; custom.bltafwm = 0xffff;
custom.bltalwm = bltalwm; if (needsExtraWord) {
custom.bltalwm = 0x0000;
} else {
custom.bltalwm = 0xffff;
}
custom.bltamod = bltamod; custom.bltbmod = -(needsExtraWord * 2);
custom.bltdmod = bltdmod; custom.bltdmod = screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2);
custom.bltsize = bltsize; custom.bltsize = (2 + needsExtraWord) + (COOL_BUN_HEIGHT << 6);
WaitBlit(); WaitBlit();
} }
} }
#define ENABLE_RENDER_BUN_CHECKING (0)
void renderBun( void renderBun(
int x, int x,
int y, int y,
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *activeScreenBufferDetails, struct CurrentScreen *currentScreen
struct BunClear *bunClear
) { ) {
/** /**
* Conditions that will cause the program to crash if met. If your bun * Conditions that will cause the program to crash if met. If your bun
* isn't rendering, it's due to here. Turn off checking once you know * isn't rendering, it's due to here.
* everything is solid to save some CPU.
* *
* TODO: Handle top/bottom off-screen as well. * TODO: Handle top/bottom off-screen as well.
*/ */
if (ENABLE_RENDER_BUN_CHECKING) {
if (x < -31) return; if (x < -31) return;
if (x > screenDefinition->width + 31) return; if (x > screenSetup->width + 31) return;
if (y < 1) return; if (y < 1) return;
if (y > screenDefinition->height - COOL_BUN_HEIGHT - 1) return; if (y > screenSetup->height- COOL_BUN_HEIGHT - 1) return;
}
if (x < 0) { if (x < 0) {
bun_offLeftSide( bun_offLeftSide(-x, y, screenSetup, currentScreen);
-x, } else if (x > screenSetup->width - COOL_BUN_WIDTH) {
y, bun_offRightSide(x - (screenSetup->width - COOL_BUN_WIDTH), y, screenSetup, currentScreen);
screenDefinition,
activeScreenBufferDetails,
bunClear
);
} else if (x > screenDefinition->width - COOL_BUN_WIDTH) {
bun_offRightSide(
x - (screenDefinition->width - COOL_BUN_WIDTH),
y,
screenDefinition,
activeScreenBufferDetails,
bunClear
);
} else { } else {
bun_anywhere( bun_anywhere(x, y, screenSetup, currentScreen);
x,
y,
screenDefinition,
activeScreenBufferDetails,
bunClear
);
} }
} }
@ -307,7 +228,7 @@ int bunAngleAdjustments[BUN_COUNT];
void calculateBunPositions( void calculateBunPositions(
uint16_t frame, uint16_t frame,
short int bunPositions[BUN_COUNT][2], short int bunPositions[BUN_COUNT][2],
struct ScreenDefinition *screenDefinition struct ScreenSetup *screenSetup
) { ) {
int x, y, row, column, current; int x, y, row, column, current;
float angle, startAngle; float angle, startAngle;
@ -342,7 +263,7 @@ void calculateBunPositions(
short int allBunPositionsByFrame[FRAMES_FOR_SCREEN][BUN_COUNT][2]; short int allBunPositionsByFrame[FRAMES_FOR_SCREEN][BUN_COUNT][2];
void calculateAllBunPositions( void calculateAllBunPositions(
struct ScreenDefinition *screenDefinition struct ScreenSetup *screenSetup
) { ) {
int frame; int frame;
@ -350,12 +271,12 @@ void calculateAllBunPositions(
calculateBunPositions( calculateBunPositions(
frame, frame,
allBunPositionsByFrame[frame], allBunPositionsByFrame[frame],
screenDefinition screenSetup
); );
} }
} }
void buildBunAngleAdjustments(void) { void buildBunAngleAdjustments() {
int current, angleAdjustment; int current, angleAdjustment;
for (current = 0; current < BUN_COUNT; ++current) { for (current = 0; current < BUN_COUNT; ++current) {
angleAdjustment = 0; angleAdjustment = 0;
@ -366,70 +287,16 @@ void buildBunAngleAdjustments(void) {
} }
} }
void precalculateBunRenderInfo(void) {
int plane;
for (plane = 0; plane < 2; ++plane) {
coolbunPlaneStarts[BUN_OFF_RIGHT_SIDE][plane] = coolbun + plane * COOL_BUN_PLANE_SIZE;
coolbunPlaneStarts[BUN_ANYWHERE][plane] = coolbun + plane * COOL_BUN_PLANE_SIZE;
coolbunPlaneStarts[BUN_OFF_LEFT_SIDE][plane] = coolbun + 2 +
COOL_BUN_LAST_ROW_BYTES +
plane * COOL_BUN_PLANE_SIZE;
}
}
void setupBunRenderer( void setupBunRenderer(
struct BunRenderer *bunRenderer, struct BunRenderer *bunRenderer,
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *activeScreenBufferDetails) { struct CurrentScreen *currentScreen) {
bunRenderer->screenDefinition = screenDefinition; bunRenderer->screenSetup = screenSetup;
bunRenderer->activeScreenBufferDetails = activeScreenBufferDetails; bunRenderer->currentScreen = currentScreen;
setupBun();
buildBunAngleAdjustments(); buildBunAngleAdjustments();
calculateAllBunPositions(screenDefinition); calculateAllBunPositions(screenSetup);
precalculateBunRenderInfo();
precalculateBunBLTALWM();
}
/**
* Is there bun clear information for this frame? This is not true for the
* first frame in the demo.
*/
int hasBunClear[2] = {0,0};
struct BunClear bunClearForScreen[2][BUN_COUNT];
void clearCurrentBuns(
struct BunRenderer *bunRenderer
) {
int bun, plane;
struct BunClear *currentBunClear;
uint16_t bltcon0, bltcon1, bltdmod, bltsize;
if (!hasBunClear[bunRenderer->activeScreenBufferDetails->currentBuffer]) return;
bltcon0 = BLTCON0(0xc0, 0, 0, 0, 1, 0);
for (bun = 0; bun < BUN_COUNT; ++bun) {
currentBunClear = &bunClearForScreen[bunRenderer->activeScreenBufferDetails->currentBuffer][bun];
bltcon1 = BLTCON1(currentBunClear->direction, 0);
bltdmod = bunRenderer->screenDefinition->byteWidth - (currentBunClear->widthWords * 2);
bltsize = currentBunClear->widthWords + (currentBunClear->heightRows << 6);
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = bltcon0;
custom.bltcon1 = bltcon1;
custom.bltadat = 0x0000;
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltdpt = bunRenderer->activeScreenBufferDetails->planes[plane] +
currentBunClear->memoryStartOffsetBytes;
custom.bltdmod = bltdmod;
custom.bltsize = bltsize;
WaitBlit();
}
}
} }
void renderBunFrame( void renderBunFrame(
@ -444,14 +311,12 @@ void renderBunFrame(
renderBun( renderBun(
allBunPositionsByFrame[frame][bun][0], allBunPositionsByFrame[frame][bun][0],
allBunPositionsByFrame[frame][bun][1], allBunPositionsByFrame[frame][bun][1],
bunRenderer->screenDefinition, bunRenderer->screenSetup,
bunRenderer->activeScreenBufferDetails, bunRenderer->currentScreen
&bunClearForScreen[bunRenderer->activeScreenBufferDetails->currentBuffer][bun]
); );
} }
hasBunClear[bunRenderer->activeScreenBufferDetails->currentBuffer] = 1;
} }
void teardownBunRenderer() { void teardownBunRenderer() {
teardownBun();
} }

19
bun.h
View File

@ -3,31 +3,20 @@
#include "screen.h" #include "screen.h"
#define FRAMES_FOR_SCREEN (60)
#define BUN_COUNT (12)
struct BunRenderer { struct BunRenderer {
struct ScreenDefinition *screenDefinition; struct ScreenSetup *screenSetup;
struct ActiveScreenBufferDetails *activeScreenBufferDetails; struct CurrentScreen *currentScreen;
}; };
void setupBunRenderer( void setupBunRenderer(
struct BunRenderer *, struct BunRenderer *,
struct ScreenDefinition *, struct ScreenSetup *,
struct ActiveScreenBufferDetails * struct CurrentScreen *
); );
void renderBunFrame( void renderBunFrame(
int frame, int frame,
struct BunRenderer * struct BunRenderer *
); );
void clearCurrentBuns(
struct BunRenderer *
);
void teardownBunRenderer(void); void teardownBunRenderer(void);
void calculateNeededRedrawRanges(
int frame,
uint16_t redrawRanges[BUN_COUNT][4]
);
#endif #endif

Binary file not shown.

BIN
demo.gif

Binary file not shown.

Before

Width:  |  Height:  |  Size: 892 KiB

View File

@ -9,7 +9,7 @@ require 'rmagick'
# [ ] turn the big color counts into three bitplames worth of data # [ ] turn the big color counts into three bitplames worth of data
# [ ] turn the little color counts into up to 8 sprites worth of data strips & color changes # [ ] turn the little color counts into up to 8 sprites worth of data strips & color changes
image = Magick::Image.read('topaz-narrow.png').first image = Magick::Image.read('topaz.png').first
rows = [] rows = []
@ -17,10 +17,6 @@ class MaskPixel
def initialize; end def initialize; end
def color? = false def color? = false
def ==(other)
other.is_a?(MaskPixel)
end
end end
class Color class Color
@ -32,26 +28,10 @@ class Color
@blue = blue @blue = blue
end end
WHITE = new(red: 15, green: 15, blue: 15)
BLACK = new(red: 0, green: 0, blue: 0)
TRANSPARENT = new(red: -1, green: -1, blue: -1)
def ==(other) def ==(other)
red == other.red && green == other.green && blue == other.blue red == other.red && green == other.green && blue == other.blue
end end
def transparent?
red == -1 && green == -1 && blue == -1
end
def -(other)
red - other.red + green - other.green + blue - other.blue
end
def for_diff
2 * red * red + 4 * green * green + 3 * blue * blue
end
alias eql? == alias eql? ==
def hash def hash
@ -73,8 +53,6 @@ MAX_ALPHA = Magick::QuantumRange * 0.25
BIT_SHIFT = Math.log2(Magick::QuantumRange + 1) - 4 BIT_SHIFT = Math.log2(Magick::QuantumRange + 1) - 4
class PixelRow class PixelRow
include Enumerable
def initialize def initialize
@row = [] @row = []
end end
@ -83,284 +61,10 @@ class PixelRow
@row[x] = pixel @row[x] = pixel
end end
def each(&block)
@row.each(&block)
end
def prioritized_colors
colors_with_usage.sort_by(&:last).reverse.map(&:first)
end
private
def colors_with_usage def colors_with_usage
last = nil
count = 0
@row.find_all(&:color?).each_with_object({}) do |pixel, obj| @row.find_all(&:color?).each_with_object({}) do |pixel, obj|
if last != pixel.color
last = pixel.color
count = 1
end
count += count
obj[pixel.color] ||= 0 obj[pixel.color] ||= 0
obj[pixel.color] += count obj[pixel.color] += 1
end
end
end
class RowColors
def initialize; end
end
class RowColorCalculator
MAX_BITPLANE_COLORS = 8
MAX_SPRITE_COLORS = 8
def self.calculate(row:)
prioritized_colors = row.prioritized_colors
bitplane_pixels_by_color = {
Color::TRANSPARENT => 0,
Color::BLACK => 1,
Color::WHITE => 2
}
sprite_pixels_by_color = {}
colors_by_bitplane_pixel = {}
colors_by_sprite_pixel = {}
prioritized_colors.each do |color|
next if bitplane_pixels_by_color.keys.include?(color)
closest_matches = bitplane_pixels_by_color.keys.reject(&:transparent?).map do |bp_color|
[(bp_color.for_diff - color.for_diff).abs, bp_color]
end.compact
closest_match = closest_matches.min_by(&:first)
if bitplane_pixels_by_color.values.max == MAX_BITPLANE_COLORS - 1
bitplane_pixels_by_color[color] = bitplane_pixels_by_color[closest_match.last]
max_sprite_value = sprite_pixels_by_color.values.max
if !max_sprite_value || max_sprite_value < MAX_SPRITE_COLORS - 1
new_pixel_index = colors_by_sprite_pixel.count
sprite_pixels_by_color[color] = new_pixel_index
colors_by_sprite_pixel[new_pixel_index] = color
end
else
new_pixel_index = colors_by_bitplane_pixel.count + 3
bitplane_pixels_by_color[color] = new_pixel_index
colors_by_bitplane_pixel[new_pixel_index] = color
end
end
{
bitplane_pixels_by_color:,
sprite_pixels_by_color:,
colors_by_bitplane_pixel:,
colors_by_sprite_pixel:
}
end
end
class RowMaskBitplaneCalculator
def self.calculate(row:)
bits = row.map { |p| p.is_a?(MaskPixel) ? 0 : 1 }
bits.each_slice(8).map do |pixels|
byte = 0
pixels.each_with_index do |pixel, index|
bit = 7 - index
byte |= (pixel << bit)
end
byte
end
end
end
class RowBitplaneCalculator
def self.calculate(row:, bitplane_pixels_by_color:)
output_pixels = row.map do |pixel|
next 0 if pixel.is_a?(MaskPixel)
bitplane_pixels_by_color[pixel.color] || 0
end
bitplanes = [[], [], []]
output_pixels.each_slice(8) do |pixels|
bits = [0] * 3
pixels.each_with_index do |pixel, index|
bit = 7 - index
3.times do |i|
bits[i] |= (((pixel >> i) & 1) << bit)
end
end
3.times do |i|
bitplanes[i] << bits[i]
end
end
bitplanes
end
end
class Sprite
attr_reader :x, :y, :color, :pixels
# @!attribute color
# @return Color
def initialize(x:, y:, color:)
@x = x
@y = y
@color = color
@pixels = [0] * 16
end
def add_pixel(x:, index:)
return if x - @x >= 16
@pixels[x - @x] = index
end
end
class RowSpriteCalculator
def self.calculate(y:, row:, sprite_pixels_by_color:)
sprites_by_color = {}
row.each_with_index.map do |pixel, x|
next if pixel.is_a?(MaskPixel)
sprite_pixel = sprite_pixels_by_color[pixel.color]
next unless sprite_pixel
sprite = sprites_by_color[pixel.color]
unless sprite
sprite = Sprite.new(y:, x:, color: pixel.color)
sprites_by_color[pixel.color] = sprite
end
sprite.add_pixel(x:, index: 1)
end
sprites_by_color
end
end
module Amiga
class Util
TOTAL_HEIGHT = 256
TOP_OFFSET = 44
LEFT_OFFSET = 128 + 64
SPRITE_HEIGHT = TOTAL_HEIGHT + TOP_OFFSET
def self.color_to_amiga_word(color:)
(color.blue + (color.green << 4) + (color.red << 8))
end
def self.sprposctl(x:, y:)
y += TOP_OFFSET
x += LEFT_OFFSET
sprpos = ((y & 0xff) << 8) +
((x & 0x1fe) >> 1)
sprctl = (((y + TOTAL_HEIGHT) & 0xff) << 8) +
((y & 0x100) >> 6) +
(((y + TOTAL_HEIGHT) & 0x100) >> 7) +
(x & 1)
{ sprpos:, sprctl: }
end
end
class BitplaneCopperlistFactory
def self.build(colors_by_bitplane_pixel:)
5.times.map do |color_index|
color = colors_by_bitplane_pixel[color_index + 3] || Color::BLACK
Amiga::Util.color_to_amiga_word(color:)
end.pack('n*')
end
end
class BitplaneDataFactory
def self.build(bitplanes:)
bitplanes.map do |data|
data.pack('C*')
end
end
end
class BitplaneMaskDataFactory
def self.build(bitplane:)
bitplane.pack('C*')
end
end
class SpriteCopperlistFactory
# @param sprites [Array<Sprite>]
def self.build(sprites:, y_offset:)
obj = []
8.times do |sprite_index|
color = 0
sprpos = 0
sprctl = 0
sprite = sprites[sprite_index]
if sprite
result = Amiga::Util.sprposctl(x: sprite.x, y: sprite.y + y_offset)
color = Amiga::Util.color_to_amiga_word(color: sprite.color)
sprpos = result[:sprpos]
sprctl = result[:sprctl]
end
obj << color
obj << sprpos
obj << sprctl
end
obj.pack('n*')
end
end
class SpriteDataFactory
def self.build(sprites:)
sprite_out = [''] * 8
sprites_with_bitplane = sprites.zip([0, 1] * 4)
8.times do |sprite_index|
sprite, bitplane = sprites_with_bitplane[sprite_index]
2.times do |current_bitplane|
result = 0
if bitplane == current_bitplane
sprite.pixels.each_with_index do |pixel, bit|
result |= (pixel << (15 - bit))
end
end
sprite_out[sprite_index] += [result].pack('n*')
end
end
sprite_out
end end
end end
end end
@ -383,53 +87,4 @@ image.each_pixel do |px, x, y|
rows[y].add(pixel:, x:) rows[y].add(pixel:, x:)
end end
copper_colors = '' pp rows[50].colors_with_usage
topaz_bitplanes = [''] * 3
sprite_copperlist = ''
sprite_data = [''] * 8
mask_bitplane = ''
8.times do |i|
result = Amiga::Util.sprposctl(x: 319, y: 0)
sprite_data[i] = [result[:sprpos], result[:sprctl]].pack('n*')
end
rows.each_with_index do |row, y_offset|
result = RowColorCalculator.calculate(row:)
bitplane_pixels_by_color = result[:bitplane_pixels_by_color]
sprite_pixels_by_color = result[:sprite_pixels_by_color]
colors_by_bitplane_pixel = result[:colors_by_bitplane_pixel]
bitplanes = RowBitplaneCalculator.calculate(row:, bitplane_pixels_by_color:)
sprites = RowSpriteCalculator.calculate(y: y_offset, row:, sprite_pixels_by_color:).values
mask = RowMaskBitplaneCalculator.calculate(row:)
mask_bitplane += Amiga::BitplaneMaskDataFactory.build(bitplane: mask)
copper_colors += Amiga::BitplaneCopperlistFactory.build(colors_by_bitplane_pixel:)
raw_bitplanes = Amiga::BitplaneDataFactory.build(bitplanes:)
sprite_copperlist += Amiga::SpriteCopperlistFactory.build(sprites:, y_offset:)
raw_sprite_data = Amiga::SpriteDataFactory.build(sprites:)
raw_bitplanes.each_with_index do |raw, index|
topaz_bitplanes[index] += raw
end
raw_sprite_data.each_with_index do |raw, index|
sprite_data[index] += raw
end
end
8.times do |i|
sprite_data[i] += [0, 0].pack('n*')
end
File.open('copper-colors', 'wb') { |fh| fh.print copper_colors }
File.open('topaz-bitplane', 'wb') { |fh| fh.print topaz_bitplanes.join('') }
File.open('mask-bitplane', 'wb') { |fh| fh.print mask_bitplane }
File.open('sprite-copperlist', 'wb') { |fh| fh.print sprite_copperlist }
File.open('sprite-data', 'wb') { |fh| fh.print sprite_data.join('') }

View File

@ -1,30 +1,4 @@
XDEF _coolbun XDEF _coolbun
XDEF _TopazBitplanes
XDEF _CopperColors
XDEF _SpriteCopperlist
XDEF _SpriteData
XDEF _MaskBitplane
SECTION Topaz,Data_C
_coolbun: _coolbun:
INCBIN "images/bun small.raw" INCBIN "images/bun small.raw"
CNOP 0,4
_TopazBitplanes:
INCBIN "topaz-bitplane"
CNOP 0,4
_CopperColors:
INCBIN "copper-colors"
CNOP 0,4
_SpriteCopperlist:
INCBIN "sprite-copperlist"
CNOP 0,4
_SpriteData:
INCBIN "sprite-data"
CNOP 0,4
_MaskBitplane:
INCBIN "mask-bitplane"

Binary file not shown.

View File

@ -1,77 +0,0 @@
#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;
}

BIN
left_side

Binary file not shown.

View File

@ -1,90 +0,0 @@
/**
* What do we need
* * [ ] screen setup
*/
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <clib/graphics_protos.h>
#include "system/system.h"
#include "system/copper.h"
#include "system/blitter.h"
#include "screen.h"
extern struct Custom far custom;
extern struct CIA far ciaa;
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
extern unsigned char chip coolbun[];
int main(void) {
struct ScreenDefinition screenDefinition;
struct ActiveScreenBufferDetails activeScreenBufferDetails;
uint16_t *copperlist, *currentCopperlist;
void *copperlistBitplanePointers[8][2];
int i, plane;
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
320,
256,
2
);
copperlist = prepareNewCopperlist(300);
currentCopperlist = addDisplayToCopperlist(
copperlist,
&screenDefinition,
&activeScreenBufferDetails,
&copperlistBitplanePointers
);
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
endCopperlist(currentCopperlist);
takeOverSystem();
setCopperlist(copperlist);
setUpDisplay((uint32_t)screenDefinition.bitplanes);
// Render a cut off bun at -8x50
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, 8);
custom.bltcon1 = BLTCON1(BLITTER_DESCENDING, 8);
custom.bltapt = coolbun + (plane * 4 * 32) + (31 * 4) + 2;
custom.bltdpt = activeScreenBufferDetails.planes[plane] + ((50 + 31) * 320 / 8) + 2;
custom.bltafwm = 0xffff;
custom.bltalwm = 0x00ff;
custom.bltamod = 0;
custom.bltdmod = 40 - 4;
custom.bltsize = 2 + (32 << 6);
WaitBlit();
}
while (1) {
if ((ciaa.ciapra >> 6) != 3) break;
}
giveBackSystem();
freeCopperlist(copperlist);
teardownScreen(&screenDefinition);
}

BIN
main

Binary file not shown.

539
main.c
View File

@ -1,387 +1,260 @@
#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 <intuition/intuition.h>
#include <graphics/gfx.h> #include <graphics/gfx.h>
#include "system/blitter.h" #include "system/blitter.h"
#include "system/copper.h" #include "system/copper.h"
#include "system/system.h" #include "system/system.h"
#include "system/sprite.h"
#include "screen.h" #include "screen.h"
#include "types.h" #include "types.h"
#include "bun.h" #include "bun.h"
/**
* This barely gets 50fps on an 020 but I'm leaving it for now.
* The demo is definitely CPU bound.
*
* Potential improvements:
*
* [ ] Precalculate even more of bun.c. This may get 50fps on an A500 if I do this.
* It would require more significant caching of as much stuff as possible.
* The A500 is spending entirely too much time on CPU tasks.
* [ ] Topaz re-rendering is limited to squares or rows that changed in the last frame.
* I tried this once but I need a more precise way of redrawing those areas.
* [ ] Cool bun clears and re-renders happen in the same pass.
* This would likely mean extending the cool bun art to have a blank word on the left,
* and enough blank rows above and below to cover clearing areas above and below.
*/
extern struct Custom far custom; extern struct Custom far custom;
extern struct CIA far ciaa;
// change to 0 to not render sprites // this should be large enough to hold one bitplane of the largest object
#define RENDER_SPRITES (1) // you are blitting, plus one additional word on each side
#define SCRATCH_AREA_WIDTH_BYTES (8)
#define SCRATCH_AREA_HEIGHT_ROWS (34)
#define SCRATCH_AREA_MEMORY_SIZE (SCRATCH_AREA_WIDTH_BYTES * SCRATCH_AREA_HEIGHT_ROWS)
struct ScreenDefinition screenDefinition; volatile short *dbg = (volatile short *)0x100;
struct ActiveScreenBufferDetails activeScreenBufferDetails;
/** unsigned char *scratchArea;
* The locations within the copperlist data where the bitplanes are referenced. struct ScreenSetup screenSetup;
* We change these areas of memory directly to implement double buffering. struct CurrentScreen currentScreen;
* Addresses are to the high, then low, word of the plane memory address in the copperlist.
*
* @see addDisplayToCopperlist
*/
void *copperlistBitplanePointers[8][2]; void *copperlistBitplanePointers[8][2];
void *copperlistSpritePointers[8];
#define offsetof(s, m) &((struct s *)0)->m
uint16_t custom_color = (uint16_t)offsetof(Custom, color); uint16_t custom_color = (uint16_t)offsetof(Custom, color);
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt); uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr); uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
extern uint8_t chip TopazBitplanes[]; uint16_t chip spriteData[200];
extern uint16_t chip CopperColors[]; uint16_t chip spriteData2[20];
extern uint16_t chip SpriteCopperlist[];
extern uint16_t chip SpriteData[];
extern uint8_t chip MaskBitplane[];
#define TOPAZ_WIDTH_PIXELS (160) uint16_t spritePositionsEachLine[256][2];
#define TOPAZ_WIDTH_BYTES (TOPAZ_WIDTH_PIXELS / 8)
#define TOPAZ_WIDTH_WORDS (TOPAZ_WIDTH_PIXELS / 16)
void renderTopaz(void) { void calculageSpritePositionsEachLine() {
int plane;
uint16_t bltcmod;
uint8_t *bltbpt;
bltcmod = screenDefinition.byteWidth - TOPAZ_WIDTH_BYTES;
bltbpt = TopazBitplanes;
for (plane = 0; plane < 3; ++plane) {
custom.bltcon0 = BLTCON0(0xca, 1, 1, 1, 1, 0);
custom.bltcon1 = 0;
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltapt = MaskBitplane;
custom.bltbpt = bltbpt;
custom.bltcpt = activeScreenBufferDetails.planes[plane] + 8;
custom.bltdpt = activeScreenBufferDetails.planes[plane] + 8;
custom.bltamod = 0;
custom.bltbmod = 0;
custom.bltcmod = bltcmod;
custom.bltdmod = bltcmod;
custom.bltsize = BLTSIZE(TOPAZ_WIDTH_WORDS, 256);
bltbpt += TOPAZ_WIDTH_BYTES * 256;
WaitBlit();
}
}
#define MOSTLY_TOPAZ_TOP_BOTTOM_CROP (30)
void renderMostlyTopaz(void) {
int plane;
uint16_t bltcmod;
uint8_t *bltbpt;
bltcmod = screenDefinition.byteWidth - TOPAZ_WIDTH_BYTES;
bltbpt = TopazBitplanes;
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xca, 1, 1, 1, 1, 0);
custom.bltcon1 = 0;
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltapt = MaskBitplane + (MOSTLY_TOPAZ_TOP_BOTTOM_CROP * TOPAZ_WIDTH_BYTES);
custom.bltbpt = bltbpt + (MOSTLY_TOPAZ_TOP_BOTTOM_CROP * TOPAZ_WIDTH_BYTES);
custom.bltcpt = MOSTLY_TOPAZ_TOP_BOTTOM_CROP * screenDefinition.byteWidth + activeScreenBufferDetails.planes[plane] + 8;
custom.bltdpt = MOSTLY_TOPAZ_TOP_BOTTOM_CROP * screenDefinition.byteWidth + activeScreenBufferDetails.planes[plane] + 8;
custom.bltamod = 0;
custom.bltbmod = 0;
custom.bltcmod = bltcmod;
custom.bltdmod = bltcmod;
custom.bltsize = BLTSIZE(TOPAZ_WIDTH_WORDS, 256 - MOSTLY_TOPAZ_TOP_BOTTOM_CROP * 2);
bltbpt += TOPAZ_WIDTH_BYTES * 256;
WaitBlit();
}
}
#define COPPERLIST_SIZE (10000)
uint16_t *copperlist;
void buildCopperlist(void) {
uint32_t spriteDataPointer;
uint16_t *currentCopperlist,
*currentCopperColors,
*currentSpriteCopperlist;
int i, j, y;
uint16_t spriteSetupRegisters[3];
copperlist = prepareNewCopperlist(COPPERLIST_SIZE);
currentCopperlist = addDisplayToCopperlist(
copperlist,
&screenDefinition,
&activeScreenBufferDetails,
&copperlistBitplanePointers
);
currentCopperColors = CopperColors;
currentSpriteCopperlist = SpriteCopperlist;
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
if (RENDER_SPRITES) {
for (i = 0; i < 8; ++i) {
spriteDataPointer = (uint32_t)&SpriteData;
spriteDataPointer += ((256 + 2) * 4) * i;
COPPERLIST_MOVE_POINTER(
currentCopperlist,
custom_sprite + i * 4,
spriteDataPointer
);
}
} else {
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
}
for (y = 0; y < 256; ++y) {
if (RENDER_SPRITES) {
for (i = 0; i < 8; ++i) {
spriteSetupRegisters[0] = custom_color + 32 + (
// sprite color group
(i / 2) * 4 +
// 0 is transparent
1 +
i % 2
) * 2;
spriteSetupRegisters[1] = custom_sprite_control + i * 8;
spriteSetupRegisters[2] = custom_sprite_control + i * 8 + 2;
for (j = 0; j < 3; ++j) {
COPPERLIST_MOVE(
currentCopperlist,
spriteSetupRegisters[j],
*(currentSpriteCopperlist++)
);
}
}
} else {
//printf("Skipping render\n");
}
for (i = 3; i < 8; ++i) {
COPPERLIST_MOVE(
currentCopperlist,
custom_color + (i * 2),
*(currentCopperColors++)
);
}
COPPERLIST_WAIT(
currentCopperlist,
(31 + (256 / 4)),
(44 + y),
0xFFFE
);
}
endCopperlist(currentCopperlist);
}
static struct MsgPort *keyboardMessagePort = NULL;
static struct IOStdReq *keyboardIO = NULL;
static struct Interrupt keyboardInterrupt;
extern far ULONG keyboardPressed;
extern struct InputEvent * __asm KeyboardHandler(
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 (*)())&KeyboardHandler;
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 i; int i;
struct BunRenderer bunRenderer; for (i = 0; i < 255; ++i) {
uint16_t redrawRanges[BUN_COUNT][4];
printf("\nCool bun blitter, copper, and sprite demo by John Bintz\n");
printf("\n");
printf("This is my first real go at writing graphics code for the Amiga.\n");
printf("It's a combination of C (SAS/C) and Assembler (DevPac), with a Ruby\n");
printf("script to do some image processing. The screen only uses three\n");
printf("bitplanes -- one color is the background, two colors are the flying\n");
printf("cool bun logo white and black, and the remaining 5 colors are used\n");
printf("by the Topaz smiling art. The Ruby script will process the PNG file\n");
printf("and figure out the best 5 colors (plus b&w) for that line of the\n");
printf("image, setting the colors via copperlist for that line.\n");
printf("It also builds the clipping mask for the blitter.\n\n");
printf("And, I'm also using sprites to add more colors to the Topaz art.\n");
printf("The Ruby script will figure out what small areas of each line weren't\n");
printf("covered by the bitplane colors and use the 8 available sprites,\n");
printf("changing the colors on each line via copper, to fill in the gaps.\n");
printf("Cool buns are animated via blitter rather than sprites, but I\n");
printf("managed to get it to run at a decent speed regardless.\n");
printf("\nEnjoy, and thanks for watching!\n");
printf("John (theindustriousrabbit.com)\n\n");
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
SCREEN_WIDTH,
SCREEN_HEIGHT,
3
);
setupBunRenderer(
&bunRenderer,
&screenDefinition,
&activeScreenBufferDetails
);
buildCopperlist();
/*
copperlist debugging
for (i = 0; i < 20; ++i) {
printf(
"%x %x %x %x\n",
*(copperlist + (i * 4)),
*(copperlist + (i * 4) + 1),
*(copperlist + (i * 4) + 2),
*(copperlist + (i * 4) + 3)
);
} }
}
#define SPRPOS(x, y) (((y & 0xff) << 8) + ((x & 0x1fe) >> 1))
#define SPRCTL(x, y, height) ( \
((height & 0xff) << 8) + \
((y & 0x100) >> 6) + \
((height & 0x100) >> 7) + \
(x & 1) \
)
int main(void) {
uint16_t *copperlist, *currentCopperlist, result;
int i, x, y, height, plane;
struct BunRenderer bunRenderer;
color_t colors[8];
colors[0] = 0x09b8;
colors[1] = 0x0000;
colors[2] = 0x0fff;
colors[3] = 0x000f;
printf("%p\n", &spriteData);
printf("setting up, i haven't crashed...yet.\n");
x = 150;
y = 47;
height = y + 98;
printf("%d, %d, %d\n", x, y, height);
spriteData[0] = SPRPOS(x, y);
spriteData[1] = SPRCTL(x, y, height);
printf("%0x %0x\n", spriteData[0], spriteData[1]);
for (i = 2; i < 198; i += 2) {
spriteData[i] = 0x0f + i % 16;
spriteData[i + 1] = 0xf0f0;
}
spriteData[198] = 0x0000;
spriteData[199] = 0x0000;
spriteData2[0] = SPRPOS(220, 70);
spriteData2[1] = SPRCTL(220, 70, 72);
/*
spriteData2[2] = 0x0345;
spriteData2[3] = 0x5678;
spriteData2[4] = 0x9abc;
spriteData2[5] = 0xdef0;
*/ */
setupKeyboard(); spriteData2[2] = 0xffff;
spriteData2[3] = 0xffff;
spriteData2[4] = 0xffff;
spriteData2[5] = 0xffff;
spriteData2[6] = SPRPOS(230, 150);
spriteData2[7] = SPRCTL(230, 150, 151);
spriteData2[8] = 0xffff;
spriteData2[9] = 0xffff;
spriteData2[10] = 0;
spriteData2[11] = 0;
setupScreen(&screenSetup, SCREEN_WIDTH, SCREEN_HEIGHT, 3);
setupInitialCurrentScreen(&screenSetup, &currentScreen);
//setupBunRenderer(&bunRenderer, &screenSetup, &currentScreen);
// blitter copy the first bitplane row down to the second
copperlist = prepareNewCopperlist();
takeOverSystem(); takeOverSystem();
setCopperlist(copperlist); setCopperlist(copperlist);
setUpDisplay((uint32_t)screenDefinition.bitplanes); setUpDisplay((uint32_t)screenSetup.bitplanes);
renderTopaz(); currentCopperlist = addDisplayToCopperlist(
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails); copperlist,
renderTopaz(); &screenSetup,
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails); &currentScreen,
&copperlistBitplanePointers
updateDisplayInCopperList(
&screenDefinition,
&activeScreenBufferDetails,
copperlistBitplanePointers
); );
i = 0; currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
while (1) { *(currentCopperlist++) = custom_color;
WaitTOF(); *(currentCopperlist++) = 0x000;
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails); *(currentCopperlist++) = custom_color + 2;
*(currentCopperlist++) = 0x000;
clearCurrentBuns(&bunRenderer); *(currentCopperlist++) = custom_color + 4;
renderBunFrame(i, &bunRenderer); *(currentCopperlist++) = 0xfff;
renderMostlyTopaz();
updateDisplayInCopperList( *(currentCopperlist++) = custom_color + 6;
&screenDefinition, *(currentCopperlist++) = 0x00F;
&activeScreenBufferDetails,
copperlistBitplanePointers
);
if (keyboardPressed) break; // sprites
if ((ciaa.ciapra >> 6) != 3) break; *(currentCopperlist++) = custom_color + 34;
*(currentCopperlist++) = 0xF0F;
i++; *(currentCopperlist++) = custom_color + 36;
if (i > FRAMES_FOR_SCREEN) i = 0; *(currentCopperlist++) = 0xFF0;
*(currentCopperlist++) = custom_color + 38;
*(currentCopperlist++) = 0x00F;
*(currentCopperlist++) = custom_sprite;
*(currentCopperlist++) = ((uint32_t)&spriteData2 >> 16);
*(currentCopperlist++) = custom_sprite + 2;
*(currentCopperlist++) = ((uint32_t)&spriteData2 & 0xffff);
for (y = 0; y < 256; ++y) {
/*
if (y > 100 && y < 135) {
*(currentCopperlist++) = custom_sprite_control;
*(currentCopperlist++) = SPRPOS(60 + y, y);
*(currentCopperlist++) = custom_sprite_control + 2;
*(currentCopperlist++) = SPRCTL(60 + y, y, 0);
}
*/
*(currentCopperlist++) = 1 + (1 << 1) + ((44 + y) << 8);
*(currentCopperlist++) = 0xFFFE;
if (y == 27) {
/*
*(currentCopperlist++) = custom_sprite_control;
*(currentCopperlist++) = 0;
*(currentCopperlist++) = custom_sprite_control + 2;
*(currentCopperlist++) = 0;
*/
*(currentCopperlist++) = custom_sprite;
*(currentCopperlist++) = ((uint32_t)&spriteData >> 16);
*(currentCopperlist++) = custom_sprite + 2;
*(currentCopperlist++) = ((uint32_t)&spriteData & 0xffff);
*(currentCopperlist++) = custom_sprite_control;
*(currentCopperlist++) = SPRPOS(60, 100);
*(currentCopperlist++) = custom_sprite_control + 2;
*(currentCopperlist++) = SPRCTL(60, 100, 198);
} }
// somthing in here causes an A500 in KS 1.3 to crash *(currentCopperlist++) = 1 + (31 << 1) + ((44 + y) << 8);
giveBackSystem(); *(currentCopperlist++) = 0xFFFE;
teardownKeyboard(); *(currentCopperlist++) = custom_color;
*(currentCopperlist++) = 0x9b8;
teardownScreen(&screenDefinition); *(currentCopperlist++) = 1 + ((31 + (320 / 4)) << 1) + ((44 + y) << 8);
*(currentCopperlist++) = 0xFFFE;
*(currentCopperlist++) = custom_color;
*(currentCopperlist++) = 0x000;
}
endCopperlist(currentCopperlist);
for (i = 0; i < 200; ++i) {
/*
swapCurrentScreenBuffer(&screenSetup, &currentScreen);
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = 0xc0 + (1 << 8);
custom.bltcon1 = 0;
custom.bltadat = 0x0000;
custom.bltafwm = 0xffff;
custom.bltalwm = 0xffff;
custom.bltdpt = currentScreen.planes[plane];
custom.bltdmod = 0;
custom.bltsize = screenSetup.byteWidth / 2 + (screenSetup.height << 6);
WaitBlit();
}
//renderBunFrame(i, &bunRenderer);
updateDisplayInCopperList(
&screenSetup,
&currentScreen,
copperlistBitplanePointers
);
*/
WaitTOF();
}
/*
for (i = 0; i < 200; ++i) {
WaitTOF();
}
*/
giveBackSystem();
for (i = 10; i < 50; ++i) {
printf("%x ", copperlist[i]);
}
teardownScreen(&screenSetup);
freeCopperlist(copperlist); freeCopperlist(copperlist);

1604
marquee.svg Normal file

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Binary file not shown.

View File

@ -1,90 +0,0 @@
/**
* What do we need
* * [ ] screen setup
*/
#include <hardware/custom.h>
#include <hardware/cia.h>
#include <clib/graphics_protos.h>
#include "system/system.h"
#include "system/copper.h"
#include "system/blitter.h"
#include "screen.h"
extern struct Custom far custom;
extern struct CIA far ciaa;
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
extern unsigned char chip coolbun[];
int main(void) {
struct ScreenDefinition screenDefinition;
struct ActiveScreenBufferDetails activeScreenBufferDetails;
uint16_t *copperlist, *currentCopperlist;
void *copperlistBitplanePointers[8][2];
int i, plane;
allocateDoubleBufferedScreenMemory(
&screenDefinition,
&activeScreenBufferDetails,
320,
256,
2
);
copperlist = prepareNewCopperlist(300);
currentCopperlist = addDisplayToCopperlist(
copperlist,
&screenDefinition,
&activeScreenBufferDetails,
&copperlistBitplanePointers
);
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
endCopperlist(currentCopperlist);
takeOverSystem();
setCopperlist(copperlist);
setUpDisplay((uint32_t)screenDefinition.bitplanes);
// Render a cut off bun at -8x50
for (plane = 0; plane < 2; ++plane) {
custom.bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, 8);
custom.bltcon1 = BLTCON1(BLITTER_ASCENDING, 8);
custom.bltapt = coolbun + (plane * 4 * 32);
custom.bltdpt = activeScreenBufferDetails.planes[plane] + (50 * 320 / 8) + (40 - 4);
custom.bltafwm = 0xffff;
custom.bltalwm = 0xff00;
custom.bltamod = 0;
custom.bltdmod = 40 - 4;
custom.bltsize = 2 + (32 << 6);
WaitBlit();
}
while (1) {
if ((ciaa.ciapra >> 6) != 3) break;
}
giveBackSystem();
freeCopperlist(copperlist);
teardownScreen(&screenDefinition);
}

View File

@ -9,77 +9,66 @@
*/ */
#define TOTAL_SCREEN_SETUP_SIZE(s) ((s->width / 8) * s->height * s->bitplanes * 2) #define TOTAL_SCREEN_SETUP_SIZE(s) ((s->width / 8) * s->height * s->bitplanes * 2)
/** void setupScreen(
* Stores internal allocation details in screenSetup. struct ScreenSetup *screenSetup,
* Sets current
*/
void allocateDoubleBufferedScreenMemory(
struct ScreenDefinition *screenDefinition,
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
uint16_t width, uint16_t width,
uint16_t height, uint16_t height,
uint8_t bitplanes uint8_t bitplanes
) { ) {
unsigned char *memory; unsigned char *memory;
int buffer, plane;
screenDefinition->width = width; screenSetup->width = width;
screenDefinition->height = height; screenSetup->height = height;
screenDefinition->bitplanes = bitplanes; screenSetup->bitplanes = bitplanes;
memory = (unsigned char *)AllocMem( memory = (unsigned char *)AllocMem(
TOTAL_SCREEN_SETUP_SIZE(screenDefinition), TOTAL_SCREEN_SETUP_SIZE(screenSetup),
MEMF_CLEAR | MEMF_CHIP MEMF_CLEAR | MEMF_CHIP
); );
screenDefinition->memoryStart = memory; screenSetup->memoryStart = memory;
screenDefinition->byteWidth = width / 8; screenSetup->byteWidth = width / 8;
// memory is not interleaved // memory is not interleaved
screenDefinition->nextBitplaneAdvance = screenDefinition->byteWidth * height; screenSetup->nextBitplaneAdvance = screenSetup->byteWidth * height;
screenDefinition->nextBufferAdvance = screenDefinition->nextBitplaneAdvance * bitplanes; screenSetup->nextBufferAdvance = screenSetup->nextBitplaneAdvance * bitplanes;
for (buffer = 0; buffer < 2; ++buffer) {
for (plane = 0; plane < bitplanes; ++plane) {
screenDefinition->bufferPlanes[buffer][plane] = screenDefinition->memoryStart +
buffer * screenDefinition->nextBufferAdvance +
plane * screenDefinition->nextBitplaneAdvance;
}
}
setActiveScreenBuffer(screenDefinition, activeScreenBufferDetails, 0);
} }
void teardownScreen( void teardownScreen(
struct ScreenDefinition *screenDefinition struct ScreenSetup *screenSetup
) { ) {
FreeMem( FreeMem(
screenDefinition->memoryStart, screenSetup->memoryStart,
TOTAL_SCREEN_SETUP_SIZE(screenDefinition) TOTAL_SCREEN_SETUP_SIZE(screenSetup)
); );
} }
void setActiveScreenBuffer( void setCurrentScreen(
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *currentScreen, struct CurrentScreen *currentScreen,
short int buffer short int buffer
) { ) {
int plane; int plane;
currentScreen->currentBuffer = buffer; currentScreen->currentBuffer = buffer;
for (plane = 0; plane < screenDefinition->bitplanes; ++plane) { for (plane = 0; plane < screenSetup->bitplanes; ++plane) {
currentScreen->planes[plane] = screenDefinition->bufferPlanes[buffer][plane]; currentScreen->planes[plane] = screenSetup->memoryStart +
buffer * screenSetup->nextBufferAdvance +
plane * screenSetup->nextBitplaneAdvance;
} }
} }
void swapCurrentScreenBuffer( void swapCurrentScreenBuffer(
struct ScreenDefinition *screenDefinition, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *currentScreen struct CurrentScreen *currentScreen
) { ) {
setActiveScreenBuffer( setCurrentScreen(screenSetup, currentScreen, 1 - currentScreen->currentBuffer);
screenDefinition, }
currentScreen,
1 - currentScreen->currentBuffer void setupInitialCurrentScreen(
); struct ScreenSetup *screenSetup,
struct CurrentScreen *currentScreen
) {
setCurrentScreen(screenSetup, currentScreen, 0);
} }

View File

@ -6,7 +6,7 @@
#define SCREEN_WIDTH (320) #define SCREEN_WIDTH (320)
#define SCREEN_HEIGHT (256) #define SCREEN_HEIGHT (256)
struct ScreenDefinition { struct ScreenSetup {
// human entered // human entered
uint16_t width; uint16_t width;
uint16_t height; uint16_t height;
@ -17,36 +17,34 @@ struct ScreenDefinition {
uint16_t byteWidth; uint16_t byteWidth;
uint16_t nextBitplaneAdvance; uint16_t nextBitplaneAdvance;
uint16_t nextBufferAdvance; uint16_t nextBufferAdvance;
unsigned char *bufferPlanes[2][8];
}; };
struct ActiveScreenBufferDetails { struct CurrentScreen {
uint16_t currentBuffer; uint16_t currentBuffer;
unsigned char *planes[8]; unsigned char *planes[8];
}; };
void allocateDoubleBufferedScreenMemory( void setupScreen(
struct ScreenDefinition *screenSetup, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *currentScreen,
uint16_t width, uint16_t width,
uint16_t height, uint16_t height,
uint8_t bitplanes uint8_t bitplanes
); );
void teardownScreen(struct ScreenDefinition *screenSetup); void teardownScreen(struct ScreenSetup *screenSetup);
void setActiveScreenBuffer( void setCurrentScreen(
struct ScreenDefinition *screenSetup, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *currentScreen, struct CurrentScreen *currentScreen,
short int buffer short int buffer
); );
void swapCurrentScreenBuffer( void swapCurrentScreenBuffer(
struct ScreenDefinition *screenSetup, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *currentScreen struct CurrentScreen *currentScreen
); );
void setupInitialCurrentScreen( void setupInitialCurrentScreen(
struct ScreenDefinition *screenSetup, struct ScreenSetup *screenSetup,
struct ActiveScreenBufferDetails *currentScreen struct CurrentScreen *currentScreen
); );
#endif #endif

View File

@ -1,9 +1,4 @@
MAIN_OBJS = main.o images.o system.lib screen.o bun.o MAIN_OBJS = main.o images.o system.lib screen.o bun.o
32_objs = 32x50_bun.o system.lib screen.o images.o
33_objs = 33x50_bun.o system.lib screen.o images.o
left_side_objs = left_side.o system.lib screen.o images.o
right_side_objs = right_side.o system.lib screen.o images.o
any_position = any_position.o system.lib screen.o images.o
all: main all: main
@ -13,27 +8,12 @@ all: main
.s.o: .s.o:
genam -l $*.s genam -l $*.s
system.lib: system/system.o system/copper.o system/blitter.o system/debug.o system.lib: system/system.o system/copper.o system/blitter.o
sc objectlibrary=system.lib system/system.o system/copper.o system/blitter.o system/debug.o sc objectlibrary=system.lib system/system.o system/copper.o system/blitter.o
main: $(MAIN_OBJS) main: $(MAIN_OBJS)
sc link to main math=standard $(MAIN_OBJS) sc link to main math=standard $(MAIN_OBJS)
32x50: $(32_objs)
sc link to 32x50 $(32_objs)
33x50: $(33_objs)
sc link to 33x50 $(33_objs)
left_side: $(left_side_objs)
sc link to left_side $(left_side_objs)
right_side: $(right_side_objs)
sc link to right_side $(right_side_objs)
any_position: $(any_position)
sc link to any_position $(any_position)
test: bun_test.o bun.o test: bun_test.o bun.o
sc link to bun_test identifierlength=32 math=standard bun_test.o bun.o cutest/CuTest.c sc link to bun_test identifierlength=32 math=standard bun_test.o bun.o cutest/CuTest.c

Binary file not shown.

Binary file not shown.

View File

@ -1,14 +1,8 @@
#ifndef __BLITTER_H__ #ifndef __BLITTER_H__
#define __BLITTER_H__ #define __BLITTER_H__
#define BLTSIZE(w, h) (w + (h << 6)) #include "types.h"
#define BLTCON0( \ #include "screen.h"
minterm, aChan, bChan, cChan, dChan, shift \
) (minterm + (aChan << 11) + (bChan << 10) + (cChan << 9) + (dChan << 8) + (shift << 12))
#define BLTCON1(descending, shift) ((descending << 1) + (shift << 12))
#define BLITTER_ASCENDING (0)
#define BLITTER_DESCENDING (1)
/* /*

View File

@ -7,15 +7,9 @@
extern struct Custom far custom; extern struct Custom far custom;
uint16_t copperlistSize; uint16_t * prepareNewCopperlist(void) {
uint16_t *copperlist = AllocMem(
uint16_t * prepareNewCopperlist(uint16_t size_b) { COPPERLIST_SIZE,
uint16_t *copperlist;
copperlistSize = size_b;
copperlist = AllocMem(
copperlistSize,
MEMF_CHIP | MEMF_CLEAR MEMF_CHIP | MEMF_CLEAR
); );
@ -30,5 +24,5 @@ void setCopperlist(uint16_t *copperlist) {
} }
void freeCopperlist(uint16_t *copperlist) { void freeCopperlist(uint16_t *copperlist) {
FreeMem(copperlist, copperlistSize); FreeMem(copperlist, COPPERLIST_SIZE);
} }

View File

@ -1,31 +1,11 @@
#ifndef __COPPER_H__ #ifndef __COPPER_H__
#define __COPPER_H__ #define __COPPER_H__
#define COPPERLIST_SIZE (10000)
#include "../types.h" #include "../types.h"
/** uint16_t * prepareNewCopperlist(void);
* Sets register to value over two Copper words.
* Side-effect: Advances ptr by 4.
*/
#define COPPERLIST_MOVE(ptr,register,value) \
*(ptr++) = register; \
*(ptr++) = value;
#define COPPERLIST_WAIT(ptr,x,y,mask) \
*(ptr++) = 1 + (x << 1) + (y << 8); \
*(ptr++) = mask;
/**
* Sets high/low registers to pointer value over four Copper words.
* Side-effect: Advances ptr by 8.
*/
#define COPPERLIST_MOVE_POINTER(ptr,register,pointerValue) \
*(ptr++) = register; \
*(ptr++) = (pointerValue >> 16); \
*(ptr++) = register + 2; \
*(ptr++) = (pointerValue & 0xffff);
uint16_t * prepareNewCopperlist(uint16_t size_b);
void setCopperlist(uint16_t *copperlist); void setCopperlist(uint16_t *copperlist);
void freeCopperlist(uint16_t *copperlist); void freeCopperlist(uint16_t *copperlist);

View File

@ -1,11 +0,0 @@
#include "debug.h"
volatile short *dbg = (volatile short *)0x100;
/**
* Create a two-word write watch in the UAE debugger at memory location 0x100
* and call this function.
*/
void triggerUAEDebugger() {
*(dbg) = 0;
}

View File

@ -1,6 +0,0 @@
#ifndef __SYSTEM_DEBUG__
#define __SYSTEM_DEBUG__
void triggerUAEDebugger(void);
#endif

View File

@ -1,7 +0,0 @@
#define SPRPOS(x, y) (((y & 0xff) << 8) + ((x & 0x1fe) >> 1))
#define SPRCTL(x, y, height) ( \
((height & 0xff) << 8) + \
((y & 0x100) >> 6) + \
((height & 0x100) >> 7) + \
(x & 1) \
)

View File

@ -12,20 +12,15 @@
// copperlist // copperlist
extern void initializeCopperlist(void *copperlist); extern void initializeCopperlist(void *copperlist);
extern uint16_t* endCopperlist(uint16_t *copperlist); extern uint16_t* endCopperlist(uint16_t *copperlist);
/**
* This only adds bitplane pointers to the copperlist
* and sets it up for double buffering.
* You still need to configure the playfield hardware.
*/
extern uint16_t* addDisplayToCopperlist( extern uint16_t* addDisplayToCopperlist(
uint16_t *copperlist, uint16_t *copperlist,
struct ScreenDefinition *, struct ScreenSetup *,
struct ActiveScreenBufferDetails *, struct CurrentScreen *,
void *copperlistBitplanePointers void *copperlistBitplanePointers
); );
extern void updateDisplayInCopperList( extern void updateDisplayInCopperList(
struct ScreenDefinition *, struct ScreenSetup *,
struct ActiveScreenBufferDetails *, struct CurrentScreen *,
void *copperlistBitplanePointers void *copperlistBitplanePointers
); );
extern uint16_t* addColorsToCopperlist(uint16_t *copperlist, color_t[], int count); extern uint16_t* addColorsToCopperlist(uint16_t *copperlist, color_t[], int count);

View File

@ -9,9 +9,6 @@
XDEF _endCopperlist XDEF _endCopperlist
XDEF _myWaitBlit XDEF _myWaitBlit
XDEF _WaitBOF XDEF _WaitBOF
XDEF _KeyboardHandler
XDEF _keyboardPressed
XREF _custom XREF _custom
@ -32,8 +29,6 @@ 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
@ -61,69 +56,24 @@ RestoreRegister MACRO
MOVE.W Old\1,\1(A0) MOVE.W Old\1,\1(A0)
ENDM ENDM
STRUCTURE ScreenDefinition,0 STRUCTURE ScreenSetup,0
UWORD ScreenDefinition_width UWORD ScreenSetup_width
UWORD ScreenDefinition_height UWORD ScreenSetup_height
UWORD ScreenDefinition_bitplanes UWORD ScreenSetup_bitplanes
ULONG ScreenDefinition_memoryStart ULONG ScreenSetup_memoryStart
UWORD ScreenDefinition_byteWidth UWORD ScreenSetup_byteWidth
UWORD ScreenDefinition_nextBitplaneAdvance UWORD ScreenSetup_nextBitplaneAdvance
UWORD ScreenDefinition_nextBufferAdvance UWORD ScreenSetup_nextBufferAdvance
ULONG ScreenDefinition_copperlistBitplanePointers ULONG ScreenSetup_copperlistBitplanePointers
LABEL ScreenDefinition_SIZEOF LABEL ScreenSetup_SIZEOF
STRUCTURE ActiveScreenBufferDetails,0 STRUCTURE CurrentScreen,0
UWORD ActiveScreenBufferDetails_currentBuffer UWORD CurrentScreen_currentBuffer
ActiveScreenBufferDetails_planes EQU SOFFSET CurrentScreen_planes EQU SOFFSET
SOFFSET SET SOFFSET+(8*4) SOFFSET SET SOFFSET+(8*4)
LABEL ActiveScreenBufferDetails_SIZEOF LABEL CurrentScreen_SIZEOF
; @see https://amigadev.elowar.com/read/ADCD_2.1/Devices_Manual_guide/node019A.html BPLCON0_COLOR EQU $200
; @register A0 struct InputEvent *
; @register A1 extra data about the event
; @output D0 The value of A0
_KeyboardHandler:
; @stack [RA,A0,current node]
MOVE.L A0,-(SP)
MOVE.L #0,-(SP)
_KeyboardHandler_CheckLoop:
CMP.B #IECLASS_RAWKEY,ie_Class(A0)
BNE.S _KeyboardHandler_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 _KeyboardHandler_hasLastEvent
MOVE.L (A0),4(SP)
BRA.S _KeyboardHandler_NextEvent
_KeyboardHandler_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
_KeyboardHandler_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 _KeyboardHandler_CheckLoop
MOVE.L (SP)+,D0
MOVE.L (SP)+,D0
RTS
M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C
_takeOverSystem: _takeOverSystem:
@ -131,15 +81,13 @@ _takeOverSystem:
OpenLibrary #GraphicsLibrary,#0 OpenLibrary #GraphicsLibrary,#0
MOVE.L D0,GraphicsBase MOVE.L D0,GraphicsBase
MOVE.L $4,A6
CALLLIB _LVOForbid
MOVE.L D0,A6 MOVE.L D0,A6
MOVE.L gb_ActiView(A6),OldView MOVE.L gb_ActiView(A6),OldView
MOVE.L gb_copinit(A6),OldCopper MOVE.L gb_copinit(A6),OldCopper
MOVE.L #0,A1
CALLLIB _LVOLoadView
CALLLIB _LVOWaitTOF
CALLLIB _LVOWaitTOF
CALLLIB _LVOOwnBlitter CALLLIB _LVOOwnBlitter
CALLLIB _LVOWaitBlit CALLLIB _LVOWaitBlit
@ -150,11 +98,17 @@ _takeOverSystem:
PreserveRegister intreq PreserveRegister intreq
PreserveRegister adkcon PreserveRegister adkcon
MOVE.L #0,A1
CALLLIB _LVOLoadView
CALLLIB _LVOWaitTOF
CALLLIB _LVOWaitTOF
LEA _custom,A0
; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0036.html ; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0036.html
MOVE.W #$7FFF,intena(A0) ; disable all interrupts MOVE.W #$7FFF,intena(A0) ; disable all interrupts
; we need VERTB to use WaitTOF ; we need VERTB to use WaitTOF
; PORTS and EXTER give me access to the keyboard and mouse via OS interrupts MOVE.W #INTF_SETCLR|INTF_INTEN|INTF_COPER|INTF_VERTB,intena(A0) ; enable master interrupt, copper, and VBR
MOVE.W #INTF_SETCLR|INTF_INTEN|INTF_COPER|INTF_PORTS|INTF_EXTER|INTF_VERTB,intena(A0) ; enable master interrupt, copper, and VBR
MOVE.W #$7FFF,dmacon(a0) MOVE.W #$7FFF,dmacon(a0)
MOVE.W #DMAF_SETCLR|DMAF_MASTER|DMAF_COPPER|DMAF_RASTER|DMAF_BLITTER|DMAF_SPRITE,dmacon(A0) MOVE.W #DMAF_SETCLR|DMAF_MASTER|DMAF_COPPER|DMAF_RASTER|DMAF_BLITTER|DMAF_SPRITE,dmacon(A0)
@ -210,6 +164,9 @@ _giveBackSystem:
CALLLIB _LVOWaitTOF CALLLIB _LVOWaitTOF
CALLLIB _LVOWaitBlit CALLLIB _LVOWaitBlit
CALLLIB _LVODisownBlitter CALLLIB _LVODisownBlitter
MOVE.L $4,A6
CALLLIB _LVOPermit
MOVE.L (SP)+,A6 MOVE.L (SP)+,A6
RTS RTS
@ -221,8 +178,8 @@ _initializeCopperlist:
RTS RTS
; @stack *copperlist Pointer to copperlist ; @stack *copperlist Pointer to copperlist
; @stack ScreenDefinition Pointer to screenSetup struct ; @stack ScreenSetup Pointer to screenSetup struct
; @stack ActiveScreenBufferDetails Pointer to currentScreen struct ; @stack CurrentScreen Pointer to currentScreen struct
; @stack copperlistBitplanePointers Pointer to bitplane pointers within the copper list [[high, low], ...] ; @stack copperlistBitplanePointers Pointer to bitplane pointers within the copper list [[high, low], ...]
STRUCTURE updateDisplayInCopperList,4 STRUCTURE updateDisplayInCopperList,4
ULONG updateDisplayInCopperList_screenSetup ULONG updateDisplayInCopperList_screenSetup
@ -237,9 +194,9 @@ _updateDisplayInCopperList:
MOVE.L D0,A2 MOVE.L D0,A2
; a2 has copperlistBitplanePointers ; a2 has copperlistBitplanePointers
MOVE.W ScreenDefinition_bitplanes(A0),D1 MOVE.W ScreenSetup_bitplanes(A0),D1
SUBQ #1,D1 SUBQ #1,D1
LEA ActiveScreenBufferDetails_planes(A1),A1 LEA CurrentScreen_planes(A1),A1
; a1 has planes ; a1 has planes
.continue: .continue:
@ -290,13 +247,13 @@ _setUpEmptySpritesInCopperlist:
RTS RTS
; @stack *copperlist Pointer to copperlist ; @stack *copperlist Pointer to copperlist
; @stack ScreenDefinition Pointer to screenDefinition struct ; @stack ScreenSetup Pointer to screenSetup struct
; @stack ActiveScreenBufferDetails Pointer to activeScreenBufferDetails struct ; @stack CurrentScreen Pointer to currentScreen struct
; @stack copperlistBitplanePointers Pointer to copperlistBitplanePointers struct ; @stack copperlistBitplanePointers Pointer to currentScreen struct
STRUCTURE AddDisplayToCopperListParams,4 STRUCTURE AddDisplayToCopperListParams,4
ULONG AddDisplayToCopperListParams_copperlistPtr ULONG AddDisplayToCopperListParams_copperlistPtr
ULONG AddDisplayToCopperListParams_screenDefinitionPtr ULONG AddDisplayToCopperListParams_screenSetupPtr
ULONG AddDisplayToCopperListParams_activeScreenBufferDetailsPtr ULONG AddDisplayToCopperListParams_currentScreenPtr
ULONG AddDisplayToCopperListParams_copperlistBitplanePointersPtr ULONG AddDisplayToCopperListParams_copperlistBitplanePointersPtr
_addDisplayToCopperlist: _addDisplayToCopperlist:
MOVE.L A7,A0 MOVE.L A7,A0
@ -304,15 +261,16 @@ _addDisplayToCopperlist:
; A2,D2,D3 ; A2,D2,D3
MOVEM.L A2-A4/D2-D4,-(SP) MOVEM.L A2-A4/D2-D4,-(SP)
MOVE.L AddDisplayToCopperListParams_copperlistPtr(A0),A1 ; copperlist MOVE.L AddDisplayToCopperListParams_copperlistPtr(A0),A1 ; copperlist
MOVE.L AddDisplayToCopperListParams_screenDefinitionPtr(A0),A2 ; screenDefinition MOVE.L AddDisplayToCopperListParams_screenSetupPtr(A0),A2 ; screenSetup
MOVE.L AddDisplayToCopperListParams_activeScreenBufferDetailsPtr(A0),A3 ; currentScreen MOVE.L AddDisplayToCopperListParams_currentScreenPtr(A0),A3 ; currentScreen
MOVE.L AddDisplayToCopperListParams_copperlistBitplanePointersPtr(A0),A4 ; copperlistBitplanePointers MOVE.L AddDisplayToCopperListParams_copperlistBitplanePointersPtr(A0),A4 ; copperlistBitplanePointers
LEA ActiveScreenBufferDetails_planes(A3),A3 LEA CurrentScreen_planes(A3),A3
; a3 contains address to planes ; a3 contains address to planes
MOVEQ #0,D0 MOVEQ #0,D0
MOVE.W ScreenDefinition_bitplanes(A2),D0 MOVE.W ScreenSetup_bitplanes(A2),D0
; d0 is num of bitplanes ; d0 is num of bitplanes
; set up bplpt ; set up bplpt
@ -331,10 +289,9 @@ _addDisplayToCopperlist:
; get this position for later updating ; get this position for later updating
MOVE.L A1,(A4)+ MOVE.L A1,(A4)+
MOVE.W D3,(A1)+ MOVE.W D3,(A1)+
ADDQ #2,D1
; low byte ; low byte
SWAP D3 SWAP D3
ADDQ #2,D1
MOVE.W D1,(A1)+ MOVE.W D1,(A1)+
; get this position for later updating ; get this position for later updating
MOVE.L A1,(A4)+ MOVE.L A1,(A4)+
@ -383,45 +340,33 @@ _endCopperlist:
RTS RTS
BPLCON0_ENABLE_COMPOSITE_COLOR EQU $200
; TODO: [ ] Create a stock display structure w/ all the default values in it
; that can be overridden, with guides/help on how to do so, then
; have this accept that structure
; @stack bitplaneCount ; @stack bitplaneCount
_setUpDisplay: _setUpDisplay:
MOVE.L D2,-(SP) MOVE.L D2,-(SP)
MOVE.L 8(A7),D2 ; bitplaneCount MOVE.L 8(A7),D2
LEA _custom,A1 LEA _custom,A1
MOVEQ #0,D0 MOVEQ #0,D0
MOVE.W #BPLCON0_ENABLE_COMPOSITE_COLOR,D0 MOVE.W #BPLCON0_COLOR,D0
; move bitplane count to bits 12-14
MOVEQ #0,D1 MOVEQ #0,D1
MOVE.W D2,D1 MOVE.W D2,D1
AND.W #$7,D1 AND.W #$7,D1
ROL.W #8,D1 ROL.W #8,D1
ROL.W #4,D1 ROL.W #4,D1
ADD.W D1,D0 ADD.W D1,D0
MOVE.W D0,bplcon0(A1) MOVE.W D0,bplcon0(A1)
; this controls horizontal scroll. I'm not good enough
; yet to provide opinions on this.
MOVE.W #0,bplcon1(A1) MOVE.W #0,bplcon1(A1)
MOVE.W #0,bplcon2(A1)
; sprites always on top for this demo
MOVE.W #$0020,bplcon2(A1)
; no modulos needed
MOVE.W #0,bpl1mod(A1) MOVE.W #0,bpl1mod(A1)
MOVE.W #0,bpl2mod(A1) MOVE.W #0,bpl2mod(A1)
; pal default
MOVE.W #$2c81,diwstrt(A1) MOVE.W #$2c81,diwstrt(A1)
MOVE.W #$2cc1,diwstop(A1) ; pal trick
MOVE.W #$f4c1,diwstop(A1)
MOVE.W #$38c1,diwstop(A1)
MOVE.W #$0038,ddfstrt(A1) MOVE.W #$0038,ddfstrt(A1)
MOVE.W #$00d0,ddfstop(A1) MOVE.W #$00d0,ddfstop(A1)
MOVE.L (SP)+,D2 MOVE.L (SP)+,D2
@ -482,8 +427,5 @@ 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

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

View File

@ -3,14 +3,6 @@
#include <exec/types.h> #include <exec/types.h>
/**
* Get the offset from the beginning of a struct. Useful for building
* references to custom chip registers dynamically for copperlists.
*
* @see Custom
*/
#define offsetof(s, m) &((struct s *)0)->m
typedef unsigned short color_t; typedef unsigned short color_t;
typedef unsigned long uint32_t; typedef unsigned long uint32_t;
typedef unsigned short uint16_t; typedef unsigned short uint16_t;