Compare commits
No commits in common. "main" and "jb/reworking-screen-memory-and-bun-drawing" have entirely different histories.
main
...
jb/reworki
@ -1,2 +0,0 @@
|
||||
AllCops:
|
||||
TargetRubyVersion: 3.2
|
90
32x50_bun.c
90
32x50_bun.c
@ -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);
|
||||
}
|
127
33x50_bun.c
127
33x50_bun.c
@ -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);
|
||||
}
|
3
NOTES.md
Normal file
3
NOTES.md
Normal file
@ -0,0 +1,3 @@
|
||||
Left off at implementing asm routine for injecting point in
|
||||
copperlist ram where bitplane pointers are going for
|
||||
easy replacement for double buffering.
|
50
README.md
50
README.md
@ -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)
|
||||
& [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.
|
BIN
any_position
BIN
any_position
Binary file not shown.
144
any_position.c
144
any_position.c
@ -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);
|
||||
}
|
172
basics.s
Normal file
172
basics.s
Normal 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
BIN
better_startup
Executable file
Binary file not shown.
98
better_startup.c
Normal file
98
better_startup.c
Normal 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
0
blitter_speed_test.q
Normal file
446
bun.c
446
bun.c
@ -1,5 +1,3 @@
|
||||
#include <math.h>
|
||||
|
||||
// Custom
|
||||
#include <hardware/custom.h>
|
||||
|
||||
@ -13,127 +11,69 @@
|
||||
#include "screen.h"
|
||||
#include "bun.h"
|
||||
#include "system/system.h"
|
||||
#include "system/blitter.h"
|
||||
|
||||
#define COOL_BUN_WIDTH (32)
|
||||
#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8)
|
||||
#define COOL_BUN_HEIGHT (32)
|
||||
#define COOL_BUN_PLANES (2)
|
||||
#define COOL_BUN_LAST_ROW (COOL_BUN_HEIGHT - 1)
|
||||
#define COOL_BUN_LAST_ROW_BYTES (COOL_BUN_LAST_ROW * COOL_BUN_WIDTH_BYTES)
|
||||
|
||||
#define COOL_BUN_PLANE_SIZE (COOL_BUN_WIDTH_BYTES * COOL_BUN_HEIGHT)
|
||||
#define COOL_BUN_MEMORY_SIZE (COOL_BUN_PLANE_SIZE * COOL_BUN_PLANES)
|
||||
|
||||
#define BUN_MAX_RANGE (31 + 320)
|
||||
|
||||
#define BUN_SPEED (1)
|
||||
|
||||
#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_ROW_START (50)
|
||||
#define BUN_VERT_DISTANCE_BETWEEN_BUNS (30)
|
||||
#define BUN_TOTAL_VERT_DISTANCE (COOL_BUN_HEIGHT + BUN_VERT_DISTANCE_BETWEEN_BUNS)
|
||||
#define FRAME_MAX (BUN_TOTAL_HORIZ_DISTANCE / BUN_SPEED)
|
||||
|
||||
#define BUN_WAVE_LENGTH (FRAMES_FOR_SCREEN / 2)
|
||||
|
||||
// linked as raw bytes in assembler
|
||||
extern unsigned char chip coolbun[];
|
||||
extern unsigned char far coolbun[];
|
||||
|
||||
unsigned char *coolbunArea;
|
||||
|
||||
#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;
|
||||
|
||||
struct BunClear {
|
||||
uint16_t memoryStartOffsetBytes;
|
||||
uint16_t widthWords;
|
||||
uint16_t heightRows;
|
||||
uint8_t direction;
|
||||
};
|
||||
void setupBun() {
|
||||
unsigned char *currentCoolBunArea, *currentCoolBun;
|
||||
unsigned int x, y, plane;
|
||||
|
||||
#define BUN_OFF_RIGHT_SIDE (0)
|
||||
#define BUN_OFF_LEFT_SIDE (1)
|
||||
#define BUN_ANYWHERE (2)
|
||||
coolbunArea = AllocMem(COOL_BUN_MEMORY_SIZE, MEMF_CHIP | MEMF_CLEAR);
|
||||
currentCoolBunArea = coolbunArea;
|
||||
currentCoolBun = coolbun;
|
||||
|
||||
uint8_t *coolbunPlaneStarts[3][2];
|
||||
CopyMem(coolbun, coolbunArea, COOL_BUN_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
uint16_t bunRightSide_bltalwmPrecalc[16];
|
||||
uint16_t bunLeftSide_bltalwmPrecalc[16];
|
||||
|
||||
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 teardownBun() {
|
||||
FreeMem(coolbunArea, COOL_BUN_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
void bun_offRightSide(
|
||||
int plusXValue,
|
||||
int y,
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
||||
struct BunClear *bunClear
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
) {
|
||||
uint8_t i, plane = 0;
|
||||
uint8_t shift = plusXValue & 15;
|
||||
uint8_t wordShift = (plusXValue >> 4);
|
||||
uint16_t bltalwm, bltcon0, bltcon1, bltdmod, bltsize;
|
||||
|
||||
bunClear->memoryStartOffsetBytes = (y * screenDefinition->byteWidth) +
|
||||
screenDefinition->byteWidth - COOL_BUN_WIDTH_BYTES +
|
||||
wordShift * 2;
|
||||
bunClear->heightRows = COOL_BUN_HEIGHT;
|
||||
bunClear->widthWords = 2 - wordShift;
|
||||
bunClear->direction = BLITTER_ASCENDING;
|
||||
|
||||
bltalwm = bunRightSide_bltalwmPrecalc[shift];
|
||||
|
||||
/*
|
||||
bltalwm = 0x0000;
|
||||
for (i = 0; i <= 15 - shift; ++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);
|
||||
uint16_t bltalwm;
|
||||
|
||||
for (plane = 0; plane < 2; ++plane) {
|
||||
custom.bltcon0 = bltcon0;
|
||||
custom.bltcon1 = bltcon1;
|
||||
custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
|
||||
custom.bltcon1 = BLTCON1(0, shift);
|
||||
|
||||
custom.bltapt = coolbunPlaneStarts[BUN_OFF_RIGHT_SIDE][plane];
|
||||
custom.bltdpt = activeScreenBufferDetails->planes[plane] +
|
||||
bunClear->memoryStartOffsetBytes;
|
||||
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;
|
||||
|
||||
custom.bltafwm = 0xffff;
|
||||
bltalwm = 0x0000;
|
||||
for (i = 0; i <= 15 - shift; ++i) {
|
||||
bltalwm += (1 << (15 - i));
|
||||
}
|
||||
custom.bltalwm = bltalwm;
|
||||
|
||||
custom.bltamod = wordShift * 2;
|
||||
custom.bltdmod = bltdmod;
|
||||
custom.bltbmod = wordShift * 2;
|
||||
custom.bltdmod = screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES +
|
||||
wordShift * 2;
|
||||
|
||||
custom.bltsize = bltsize;
|
||||
custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6);
|
||||
|
||||
WaitBlit();
|
||||
}
|
||||
@ -142,58 +82,47 @@ void bun_offRightSide(
|
||||
void bun_offLeftSide(
|
||||
int minusXValue,
|
||||
int y,
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
||||
struct BunClear *bunClear
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
) {
|
||||
unsigned char plane;
|
||||
uint8_t shift = minusXValue & 15;
|
||||
uint8_t wordShift = (minusXValue >> 4);
|
||||
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
|
||||
if (y == 0) return;
|
||||
|
||||
bunClear->memoryStartOffsetBytes = (screenDefinition->byteWidth * (y + COOL_BUN_LAST_ROW)) +
|
||||
2 - wordShift * 2;
|
||||
bunClear->heightRows = COOL_BUN_HEIGHT;
|
||||
bunClear->widthWords = 2 - wordShift;
|
||||
bunClear->direction = BLITTER_DESCENDING;
|
||||
|
||||
bltalwm = bunLeftSide_bltalwmPrecalc[shift];
|
||||
|
||||
/*
|
||||
bltalwm = 0x0000;
|
||||
for (i = 0; i <= 15 - shift; ++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;
|
||||
custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
|
||||
custom.bltcon1 = BLTCON1(1, shift);
|
||||
|
||||
// a has bun data
|
||||
custom.bltapt = coolbunPlaneStarts[BUN_OFF_LEFT_SIDE][plane];
|
||||
// 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 = activeScreenBufferDetails->planes[plane] + bunClear->memoryStartOffsetBytes;
|
||||
custom.bltdpt = currentScreen->planes[plane] +
|
||||
(screenSetup->byteWidth * (y + COOL_BUN_LAST_ROW)) +
|
||||
2 -
|
||||
wordShift * 2;
|
||||
|
||||
custom.bltafwm = 0xffff;
|
||||
bltalwm = 0x0000;
|
||||
for (i = 0; i <= 15 - shift; ++i) {
|
||||
bltalwm += (1 << i);
|
||||
}
|
||||
custom.bltalwm = bltalwm;
|
||||
|
||||
custom.bltamod = wordShift * 2;
|
||||
custom.bltdmod = bltdmod;
|
||||
custom.bltbmod = wordShift * 2;
|
||||
custom.bltdmod = screenSetup->byteWidth - 4 + wordShift * 2;
|
||||
|
||||
custom.bltsize = bltsize;
|
||||
custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6);
|
||||
|
||||
WaitBlit();
|
||||
}
|
||||
@ -202,256 +131,65 @@ void bun_offLeftSide(
|
||||
void bun_anywhere(
|
||||
int x,
|
||||
int y,
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
||||
struct BunClear *bunClear
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
) {
|
||||
uint8_t plane;
|
||||
uint8_t shift = x & 15;
|
||||
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) {
|
||||
custom.bltcon0 = bltcon0;
|
||||
custom.bltcon1 = bltcon1;
|
||||
// if we extend the bun area by a word, we only need one write
|
||||
|
||||
custom.bltapt = coolbunPlaneStarts[BUN_ANYWHERE][plane];
|
||||
custom.bltdpt = activeScreenBufferDetails->planes[plane] +
|
||||
bunClear->memoryStartOffsetBytes;
|
||||
// buns will never interfere with a background so they don't need a mask
|
||||
// they do need the scratch area though
|
||||
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.bltalwm = bltalwm;
|
||||
if (needsExtraWord) {
|
||||
custom.bltalwm = 0x0000;
|
||||
} else {
|
||||
custom.bltalwm = 0xffff;
|
||||
}
|
||||
|
||||
custom.bltamod = bltamod;
|
||||
custom.bltdmod = bltdmod;
|
||||
custom.bltsize = bltsize;
|
||||
custom.bltbmod = -(needsExtraWord * 2);
|
||||
custom.bltdmod = screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2);
|
||||
custom.bltsize = (2 + needsExtraWord) + (COOL_BUN_HEIGHT << 6);
|
||||
|
||||
WaitBlit();
|
||||
}
|
||||
}
|
||||
|
||||
#define ENABLE_RENDER_BUN_CHECKING (0)
|
||||
|
||||
void renderBun(
|
||||
int x,
|
||||
int y,
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
||||
struct BunClear *bunClear
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
) {
|
||||
/**
|
||||
* 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
|
||||
* everything is solid to save some CPU.
|
||||
* isn't rendering, it's due to here.
|
||||
*
|
||||
* TODO: Handle top/bottom off-screen as well.
|
||||
*/
|
||||
if (ENABLE_RENDER_BUN_CHECKING) {
|
||||
if (x < -31) return;
|
||||
if (x > screenDefinition->width + 31) return;
|
||||
if (y < 1) return;
|
||||
if (y > screenDefinition->height - COOL_BUN_HEIGHT - 1) return;
|
||||
}
|
||||
if (x < -31) return;
|
||||
if (x > screenSetup->width + 31) return;
|
||||
if (y < 1) return;
|
||||
if (y > screenSetup->height- COOL_BUN_HEIGHT - 1) return;
|
||||
|
||||
if (x < 0) {
|
||||
bun_offLeftSide(
|
||||
-x,
|
||||
y,
|
||||
screenDefinition,
|
||||
activeScreenBufferDetails,
|
||||
bunClear
|
||||
);
|
||||
} else if (x > screenDefinition->width - COOL_BUN_WIDTH) {
|
||||
bun_offRightSide(
|
||||
x - (screenDefinition->width - COOL_BUN_WIDTH),
|
||||
y,
|
||||
screenDefinition,
|
||||
activeScreenBufferDetails,
|
||||
bunClear
|
||||
);
|
||||
bun_offLeftSide(-x, y, screenSetup, currentScreen);
|
||||
} else if (x > screenSetup->width - COOL_BUN_WIDTH) {
|
||||
bun_offRightSide(x - (screenSetup->width - COOL_BUN_WIDTH), y, screenSetup, currentScreen);
|
||||
} else {
|
||||
bun_anywhere(
|
||||
x,
|
||||
y,
|
||||
screenDefinition,
|
||||
activeScreenBufferDetails,
|
||||
bunClear
|
||||
);
|
||||
bun_anywhere(x, y, screenSetup, currentScreen);
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_SINE_WAVE_CHANGE (20)
|
||||
|
||||
int bunAngleAdjustments[BUN_COUNT];
|
||||
|
||||
void calculateBunPositions(
|
||||
uint16_t frame,
|
||||
short int bunPositions[BUN_COUNT][2],
|
||||
struct ScreenDefinition *screenDefinition
|
||||
) {
|
||||
int x, y, row, column, current;
|
||||
float angle, startAngle;
|
||||
|
||||
frame %= FRAMES_FOR_SCREEN;
|
||||
|
||||
startAngle = (float)(frame % BUN_WAVE_LENGTH) * 360 / BUN_WAVE_LENGTH;
|
||||
|
||||
for (current = 0; current < BUN_COUNT; ++current) {
|
||||
row = current / 4;
|
||||
column = current % 4;
|
||||
angle = startAngle + bunAngleAdjustments[current];
|
||||
|
||||
x = column * BUN_TOTAL_HORIZ_DISTANCE + ((float)frame * BUN_MAX_RANGE / FRAMES_FOR_SCREEN);
|
||||
if (row == 1) {
|
||||
x += BUN_TOTAL_HORIZ_DISTANCE / 2;
|
||||
}
|
||||
x %= BUN_MAX_RANGE;
|
||||
x -= 31;
|
||||
|
||||
angle = angle * PI / 180;
|
||||
|
||||
y = BUN_ROW_START +
|
||||
row * BUN_TOTAL_VERT_DISTANCE +
|
||||
sin(angle) * MAX_SINE_WAVE_CHANGE;
|
||||
|
||||
bunPositions[current][0] = x;
|
||||
bunPositions[current][1] = y;
|
||||
}
|
||||
}
|
||||
|
||||
short int allBunPositionsByFrame[FRAMES_FOR_SCREEN][BUN_COUNT][2];
|
||||
|
||||
void calculateAllBunPositions(
|
||||
struct ScreenDefinition *screenDefinition
|
||||
) {
|
||||
int frame;
|
||||
|
||||
for (frame = 0; frame < FRAMES_FOR_SCREEN; ++frame) {
|
||||
calculateBunPositions(
|
||||
frame,
|
||||
allBunPositionsByFrame[frame],
|
||||
screenDefinition
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void buildBunAngleAdjustments(void) {
|
||||
int current, angleAdjustment;
|
||||
for (current = 0; current < BUN_COUNT; ++current) {
|
||||
angleAdjustment = 0;
|
||||
if (current % 2 == 1) angleAdjustment += 180;
|
||||
if (current / 4 == 1) angleAdjustment += 90;
|
||||
|
||||
bunAngleAdjustments[current] = angleAdjustment;
|
||||
}
|
||||
}
|
||||
|
||||
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(
|
||||
struct BunRenderer *bunRenderer,
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails) {
|
||||
bunRenderer->screenDefinition = screenDefinition;
|
||||
bunRenderer->activeScreenBufferDetails = activeScreenBufferDetails;
|
||||
|
||||
buildBunAngleAdjustments();
|
||||
calculateAllBunPositions(screenDefinition);
|
||||
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(
|
||||
int frame,
|
||||
struct BunRenderer *bunRenderer
|
||||
) {
|
||||
int bun;
|
||||
|
||||
frame %= FRAMES_FOR_SCREEN;
|
||||
|
||||
for (bun = 0; bun < BUN_COUNT; ++bun) {
|
||||
renderBun(
|
||||
allBunPositionsByFrame[frame][bun][0],
|
||||
allBunPositionsByFrame[frame][bun][1],
|
||||
bunRenderer->screenDefinition,
|
||||
bunRenderer->activeScreenBufferDetails,
|
||||
&bunClearForScreen[bunRenderer->activeScreenBufferDetails->currentBuffer][bun]
|
||||
);
|
||||
}
|
||||
|
||||
hasBunClear[bunRenderer->activeScreenBufferDetails->currentBuffer] = 1;
|
||||
}
|
||||
|
||||
void teardownBunRenderer() {
|
||||
}
|
||||
|
38
bun.h
38
bun.h
@ -3,31 +3,23 @@
|
||||
|
||||
#include "screen.h"
|
||||
|
||||
#define FRAMES_FOR_SCREEN (60)
|
||||
#define BUN_COUNT (12)
|
||||
#define COOL_BUN_WIDTH (32)
|
||||
#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8)
|
||||
#define COOL_BUN_HEIGHT (32)
|
||||
#define COOL_BUN_PLANES (2)
|
||||
#define COOL_BUN_LAST_ROW (COOL_BUN_HEIGHT - 1)
|
||||
#define COOL_BUN_LAST_ROW_BYTES (COOL_BUN_LAST_ROW * COOL_BUN_WIDTH_BYTES)
|
||||
|
||||
struct BunRenderer {
|
||||
struct ScreenDefinition *screenDefinition;
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails;
|
||||
};
|
||||
#define COOL_BUN_PLANE_SIZE (COOL_BUN_WIDTH_BYTES * COOL_BUN_HEIGHT)
|
||||
#define COOL_BUN_MEMORY_SIZE (COOL_BUN_PLANE_SIZE * COOL_BUN_PLANES)
|
||||
|
||||
void setupBunRenderer(
|
||||
struct BunRenderer *,
|
||||
struct ScreenDefinition *,
|
||||
struct ActiveScreenBufferDetails *
|
||||
void setupBun(void);
|
||||
void renderBun(
|
||||
int x,
|
||||
int y,
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
);
|
||||
void teardownBun(void);
|
||||
|
||||
void renderBunFrame(
|
||||
int frame,
|
||||
struct BunRenderer *
|
||||
);
|
||||
void clearCurrentBuns(
|
||||
struct BunRenderer *
|
||||
);
|
||||
void teardownBunRenderer(void);
|
||||
|
||||
void calculateNeededRedrawRanges(
|
||||
int frame,
|
||||
uint16_t redrawRanges[BUN_COUNT][4]
|
||||
);
|
||||
#endif
|
||||
|
30
bun_test.c
30
bun_test.c
@ -1,30 +0,0 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "bun.h"
|
||||
#include "cutest/CuTest.h"
|
||||
|
||||
void *coolbun;
|
||||
|
||||
void TBun_calculateBunPositions(CuTest *tc) {
|
||||
printf("wow\n");
|
||||
}
|
||||
|
||||
CuSuite *BunSuite() {
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
||||
SUITE_ADD_TEST(suite, TBun_calculateBunPositions);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CuString *output = CuStringNew();
|
||||
CuSuite *suite = CuSuiteNew();
|
||||
|
||||
CuSuiteAddSuite(suite, BunSuite());
|
||||
|
||||
CuSuiteRun(suite);
|
||||
CuSuiteSummary(suite, output);
|
||||
CuSuiteDetails(suite, output);
|
||||
printf("%s\n", output->buffer);
|
||||
|
||||
return 0;
|
||||
}
|
BIN
copper-colors
BIN
copper-colors
Binary file not shown.
@ -1,435 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
|
||||
require 'rmagick'
|
||||
|
||||
# [ ] load the image
|
||||
# [ ] map each pixel to a 12 bit color, with pixels less than 25% transparent as mask
|
||||
# [ ] sort the color counts
|
||||
# [ ] transparent pixels become the mask
|
||||
# [ ] 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
|
||||
|
||||
image = Magick::Image.read('topaz-narrow.png').first
|
||||
|
||||
rows = []
|
||||
|
||||
class MaskPixel
|
||||
def initialize; end
|
||||
|
||||
def color? = false
|
||||
|
||||
def ==(other)
|
||||
other.is_a?(MaskPixel)
|
||||
end
|
||||
end
|
||||
|
||||
class Color
|
||||
attr_reader :red, :green, :blue
|
||||
|
||||
def initialize(red:, green:, blue:)
|
||||
@red = red
|
||||
@green = green
|
||||
@blue = blue
|
||||
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)
|
||||
red == other.red && green == other.green && blue == other.blue
|
||||
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? ==
|
||||
|
||||
def hash
|
||||
red * 256 + green * 16 + blue
|
||||
end
|
||||
end
|
||||
|
||||
class BitplanePixel
|
||||
attr_reader :color
|
||||
|
||||
def initialize(color:)
|
||||
@color = color
|
||||
end
|
||||
|
||||
def color? = true
|
||||
end
|
||||
|
||||
MAX_ALPHA = Magick::QuantumRange * 0.25
|
||||
BIT_SHIFT = Math.log2(Magick::QuantumRange + 1) - 4
|
||||
|
||||
class PixelRow
|
||||
include Enumerable
|
||||
|
||||
def initialize
|
||||
@row = []
|
||||
end
|
||||
|
||||
def add(pixel:, x:)
|
||||
@row[x] = pixel
|
||||
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
|
||||
last = nil
|
||||
count = 0
|
||||
|
||||
@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] += count
|
||||
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
|
||||
|
||||
image.each_pixel do |px, x, y|
|
||||
rows[y] ||= PixelRow.new
|
||||
|
||||
pixel = if px.alpha < MAX_ALPHA
|
||||
MaskPixel.new
|
||||
else
|
||||
BitplanePixel.new(
|
||||
color: Color.new(
|
||||
red: px.red >> BIT_SHIFT,
|
||||
green: px.green >> BIT_SHIFT,
|
||||
blue: px.blue >> BIT_SHIFT
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
rows[y].add(pixel:, x:)
|
||||
end
|
||||
|
||||
copper_colors = ''
|
||||
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('') }
|
26
images.s
26
images.s
@ -1,30 +1,4 @@
|
||||
XDEF _coolbun
|
||||
XDEF _TopazBitplanes
|
||||
XDEF _CopperColors
|
||||
XDEF _SpriteCopperlist
|
||||
XDEF _SpriteData
|
||||
XDEF _MaskBitplane
|
||||
|
||||
SECTION Topaz,Data_C
|
||||
_coolbun:
|
||||
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.
@ -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;
|
||||
}
|
90
left_side.c
90
left_side.c
@ -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);
|
||||
}
|
446
main.c
446
main.c
@ -1,391 +1,195 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#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 <hardware/custom.h>
|
||||
#include <hardware/dmabits.h>
|
||||
#include <hardware/cia.h>
|
||||
|
||||
#include <intuition/intuition.h>
|
||||
|
||||
#include <graphics/gfx.h>
|
||||
|
||||
#include "system/blitter.h"
|
||||
#include "system/copper.h"
|
||||
#include "system/system.h"
|
||||
#include "system/sprite.h"
|
||||
|
||||
#include "screen.h"
|
||||
#include "types.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 CIA far ciaa;
|
||||
|
||||
// change to 0 to not render sprites
|
||||
#define RENDER_SPRITES (1)
|
||||
// this should be large enough to hold one bitplane of the largest object
|
||||
// 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;
|
||||
struct ActiveScreenBufferDetails activeScreenBufferDetails;
|
||||
volatile short *dbg = (volatile short *)0x100;
|
||||
|
||||
/**
|
||||
* The locations within the copperlist data where the bitplanes are referenced.
|
||||
* We change these areas of memory directly to implement double buffering.
|
||||
* Addresses are to the high, then low, word of the plane memory address in the copperlist.
|
||||
*
|
||||
* @see addDisplayToCopperlist
|
||||
*/
|
||||
unsigned char *scratchArea;
|
||||
struct ScreenSetup screenSetup;
|
||||
struct CurrentScreen currentScreen;
|
||||
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_sprite = (uint16_t)offsetof(Custom, sprpt);
|
||||
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
|
||||
|
||||
extern uint8_t chip TopazBitplanes[];
|
||||
extern uint16_t chip CopperColors[];
|
||||
extern uint16_t chip SpriteCopperlist[];
|
||||
extern uint16_t chip SpriteData[];
|
||||
extern uint8_t chip MaskBitplane[];
|
||||
#define BUN_COUNT (12)
|
||||
#define BUN_SPEED (2)
|
||||
|
||||
#define TOPAZ_WIDTH_PIXELS (160)
|
||||
#define TOPAZ_WIDTH_BYTES (TOPAZ_WIDTH_PIXELS / 8)
|
||||
#define TOPAZ_WIDTH_WORDS (TOPAZ_WIDTH_PIXELS / 16)
|
||||
short int bunPositions[BUN_COUNT][2];
|
||||
|
||||
void renderTopaz(void) {
|
||||
int plane;
|
||||
#define BUN_MAX_RANGE (31 + 320 - 1)
|
||||
|
||||
uint16_t bltcmod;
|
||||
uint8_t *bltbpt;
|
||||
#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_ROW_START (10)
|
||||
#define BUN_VERT_DISTANCE_BETWEEN_BUNS (20)
|
||||
#define BUN_TOTAL_VERT_DISTANCE (COOL_BUN_HEIGHT + BUN_VERT_DISTANCE_BETWEEN_BUNS)
|
||||
#define FRAME_MAX (BUN_TOTAL_HORIZ_DISTANCE / BUN_SPEED)
|
||||
|
||||
bltcmod = screenDefinition.byteWidth - TOPAZ_WIDTH_BYTES;
|
||||
bltbpt = TopazBitplanes;
|
||||
void calculateBunPositions(
|
||||
uint16_t frame,
|
||||
short int bunPositions[BUN_COUNT][2],
|
||||
struct ScreenSetup *screenSetup
|
||||
) {
|
||||
int x, y, row, column, current;
|
||||
|
||||
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);
|
||||
frame %= FRAME_MAX;
|
||||
|
||||
bltbpt += TOPAZ_WIDTH_BYTES * 256;
|
||||
for (current = 0; current < BUN_COUNT; ++current) {
|
||||
row = current / 4;
|
||||
column = current % 4;
|
||||
|
||||
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
|
||||
);
|
||||
x = column * BUN_TOTAL_HORIZ_DISTANCE + frame * BUN_SPEED;
|
||||
if (row == 1) {
|
||||
//x += BUN_TOTAL_HORIZ_DISTANCE / 2;
|
||||
}
|
||||
} else {
|
||||
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
|
||||
}
|
||||
x %= BUN_MAX_RANGE;
|
||||
x -= 31;
|
||||
y = BUN_ROW_START + row * BUN_TOTAL_VERT_DISTANCE;
|
||||
|
||||
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;
|
||||
bunPositions[current][0] = x;
|
||||
bunPositions[current][1] = y;
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
int i;
|
||||
uint16_t *copperlist, *currentCopperlist, result;
|
||||
int i, j, x, y, plane;
|
||||
int blitShiftRight, memoryXOffset, blitWidth;
|
||||
uint32_t wow, wow2;
|
||||
|
||||
struct BunRenderer bunRenderer;
|
||||
uint16_t redrawRanges[BUN_COUNT][4];
|
||||
color_t colors[8];
|
||||
|
||||
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");
|
||||
colors[0] = 0x09b8;
|
||||
colors[1] = 0x0000;
|
||||
colors[2] = 0x0fff;
|
||||
colors[3] = 0x000f;
|
||||
|
||||
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");
|
||||
setupBun();
|
||||
setupScreen(&screenSetup, SCREEN_WIDTH, SCREEN_HEIGHT, 3);
|
||||
setupInitialCurrentScreen(&screenSetup, ¤tScreen);
|
||||
|
||||
printf("\nEnjoy, and thanks for watching!\n");
|
||||
printf("John (theindustriousrabbit.com)\n\n");
|
||||
// blitter copy the first bitplane row down to the second
|
||||
|
||||
allocateDoubleBufferedScreenMemory(
|
||||
&screenDefinition,
|
||||
&activeScreenBufferDetails,
|
||||
SCREEN_WIDTH,
|
||||
SCREEN_HEIGHT,
|
||||
3
|
||||
);
|
||||
copperlist = prepareNewCopperlist();
|
||||
|
||||
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)
|
||||
);
|
||||
}
|
||||
*/
|
||||
setupKeyboard();
|
||||
takeOverSystem();
|
||||
|
||||
setCopperlist(copperlist);
|
||||
setUpDisplay((uint32_t)screenDefinition.bitplanes);
|
||||
setUpDisplay((uint32_t)screenSetup.bitplanes);
|
||||
|
||||
renderTopaz();
|
||||
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
|
||||
renderTopaz();
|
||||
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
|
||||
|
||||
updateDisplayInCopperList(
|
||||
&screenDefinition,
|
||||
&activeScreenBufferDetails,
|
||||
copperlistBitplanePointers
|
||||
currentCopperlist = addDisplayToCopperlist(
|
||||
copperlist,
|
||||
&screenSetup,
|
||||
¤tScreen,
|
||||
&copperlistBitplanePointers
|
||||
);
|
||||
|
||||
i = 0;
|
||||
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
|
||||
|
||||
while (1) {
|
||||
WaitTOF();
|
||||
*(currentCopperlist++) = custom_color;
|
||||
*(currentCopperlist++) = 0x000;
|
||||
|
||||
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
|
||||
*(currentCopperlist++) = custom_color + 2;
|
||||
*(currentCopperlist++) = 0x000;
|
||||
|
||||
clearCurrentBuns(&bunRenderer);
|
||||
renderBunFrame(i, &bunRenderer);
|
||||
renderMostlyTopaz();
|
||||
*(currentCopperlist++) = custom_color + 4;
|
||||
*(currentCopperlist++) = 0xfff;
|
||||
|
||||
*(currentCopperlist++) = custom_color + 6;
|
||||
*(currentCopperlist++) = 0x00F;
|
||||
|
||||
for (y = 0; y < 256; ++y) {
|
||||
*(currentCopperlist++) = 1 + (31 << 1) + ((44 + y) << 8);
|
||||
*(currentCopperlist++) = 0xFFFE;
|
||||
*(currentCopperlist++) = custom_color;
|
||||
*(currentCopperlist++) = 0x9b8;
|
||||
|
||||
*(currentCopperlist++) = 1 + ((31 + (320 / 4)) << 1) + ((44 + y) << 8);
|
||||
*(currentCopperlist++) = 0xFFFE;
|
||||
*(currentCopperlist++) = custom_color;
|
||||
*(currentCopperlist++) = 0x000;
|
||||
}
|
||||
|
||||
endCopperlist(currentCopperlist);
|
||||
|
||||
for (i = 0; i < FRAME_MAX * 6; ++i) {
|
||||
calculateBunPositions(i, bunPositions, &screenSetup);
|
||||
|
||||
swapCurrentScreenBuffer(&screenSetup, ¤tScreen);
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
for (j = 0; j < BUN_COUNT; ++j) {
|
||||
renderBun(
|
||||
bunPositions[j][0],
|
||||
bunPositions[j][1],
|
||||
&screenSetup,
|
||||
¤tScreen
|
||||
);
|
||||
}
|
||||
|
||||
updateDisplayInCopperList(
|
||||
&screenDefinition,
|
||||
&activeScreenBufferDetails,
|
||||
&screenSetup,
|
||||
¤tScreen,
|
||||
copperlistBitplanePointers
|
||||
);
|
||||
|
||||
if (keyboardPressed) break;
|
||||
if ((ciaa.ciapra >> 6) != 3) break;
|
||||
|
||||
i++;
|
||||
if (i > FRAMES_FOR_SCREEN) i = 0;
|
||||
WaitTOF();
|
||||
}
|
||||
|
||||
// somthing in here causes an A500 in KS 1.3 to crash
|
||||
giveBackSystem();
|
||||
teardownKeyboard();
|
||||
/*
|
||||
for (i = 0; i < 200; ++i) {
|
||||
WaitTOF();
|
||||
}
|
||||
*/
|
||||
|
||||
teardownScreen(&screenDefinition);
|
||||
giveBackSystem();
|
||||
|
||||
teardownScreen(&screenSetup);
|
||||
|
||||
freeCopperlist(copperlist);
|
||||
|
||||
teardownBunRenderer();
|
||||
teardownBun();
|
||||
|
||||
for (i = 0; i < BUN_COUNT; ++i) {
|
||||
printf("%d %d\n", bunPositions[i][0], bunPositions[i][1]);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
1604
marquee.svg
Normal file
1604
marquee.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 62 KiB |
BIN
mask-bitplane
BIN
mask-bitplane
Binary file not shown.
BIN
right_side
BIN
right_side
Binary file not shown.
90
right_side.c
90
right_side.c
@ -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);
|
||||
}
|
71
screen.c
71
screen.c
@ -9,77 +9,66 @@
|
||||
*/
|
||||
#define TOTAL_SCREEN_SETUP_SIZE(s) ((s->width / 8) * s->height * s->bitplanes * 2)
|
||||
|
||||
/**
|
||||
* Stores internal allocation details in screenSetup.
|
||||
* Sets current
|
||||
*/
|
||||
void allocateDoubleBufferedScreenMemory(
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
||||
void setupScreen(
|
||||
struct ScreenSetup *screenSetup,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint8_t bitplanes
|
||||
) {
|
||||
unsigned char *memory;
|
||||
int buffer, plane;
|
||||
|
||||
screenDefinition->width = width;
|
||||
screenDefinition->height = height;
|
||||
screenDefinition->bitplanes = bitplanes;
|
||||
screenSetup->width = width;
|
||||
screenSetup->height = height;
|
||||
screenSetup->bitplanes = bitplanes;
|
||||
|
||||
memory = (unsigned char *)AllocMem(
|
||||
TOTAL_SCREEN_SETUP_SIZE(screenDefinition),
|
||||
TOTAL_SCREEN_SETUP_SIZE(screenSetup),
|
||||
MEMF_CLEAR | MEMF_CHIP
|
||||
);
|
||||
|
||||
screenDefinition->memoryStart = memory;
|
||||
screenDefinition->byteWidth = width / 8;
|
||||
screenSetup->memoryStart = memory;
|
||||
screenSetup->byteWidth = width / 8;
|
||||
|
||||
// memory is not interleaved
|
||||
screenDefinition->nextBitplaneAdvance = screenDefinition->byteWidth * height;
|
||||
screenDefinition->nextBufferAdvance = screenDefinition->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);
|
||||
screenSetup->nextBitplaneAdvance = screenSetup->byteWidth * height;
|
||||
screenSetup->nextBufferAdvance = screenSetup->nextBitplaneAdvance * bitplanes;
|
||||
}
|
||||
|
||||
void teardownScreen(
|
||||
struct ScreenDefinition *screenDefinition
|
||||
struct ScreenSetup *screenSetup
|
||||
) {
|
||||
FreeMem(
|
||||
screenDefinition->memoryStart,
|
||||
TOTAL_SCREEN_SETUP_SIZE(screenDefinition)
|
||||
screenSetup->memoryStart,
|
||||
TOTAL_SCREEN_SETUP_SIZE(screenSetup)
|
||||
);
|
||||
}
|
||||
|
||||
void setActiveScreenBuffer(
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *currentScreen,
|
||||
void setCurrentScreen(
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen,
|
||||
short int buffer
|
||||
) {
|
||||
int plane;
|
||||
currentScreen->currentBuffer = buffer;
|
||||
|
||||
for (plane = 0; plane < screenDefinition->bitplanes; ++plane) {
|
||||
currentScreen->planes[plane] = screenDefinition->bufferPlanes[buffer][plane];
|
||||
for (plane = 0; plane < screenSetup->bitplanes; ++plane) {
|
||||
currentScreen->planes[plane] = screenSetup->memoryStart +
|
||||
buffer * screenSetup->nextBufferAdvance +
|
||||
plane * screenSetup->nextBitplaneAdvance;
|
||||
}
|
||||
}
|
||||
|
||||
void swapCurrentScreenBuffer(
|
||||
struct ScreenDefinition *screenDefinition,
|
||||
struct ActiveScreenBufferDetails *currentScreen
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
) {
|
||||
setActiveScreenBuffer(
|
||||
screenDefinition,
|
||||
currentScreen,
|
||||
1 - currentScreen->currentBuffer
|
||||
);
|
||||
setCurrentScreen(screenSetup, currentScreen, 1 - currentScreen->currentBuffer);
|
||||
}
|
||||
|
||||
void setupInitialCurrentScreen(
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
) {
|
||||
setCurrentScreen(screenSetup, currentScreen, 0);
|
||||
}
|
||||
|
||||
|
26
screen.h
26
screen.h
@ -6,7 +6,7 @@
|
||||
#define SCREEN_WIDTH (320)
|
||||
#define SCREEN_HEIGHT (256)
|
||||
|
||||
struct ScreenDefinition {
|
||||
struct ScreenSetup {
|
||||
// human entered
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
@ -17,36 +17,34 @@ struct ScreenDefinition {
|
||||
uint16_t byteWidth;
|
||||
uint16_t nextBitplaneAdvance;
|
||||
uint16_t nextBufferAdvance;
|
||||
unsigned char *bufferPlanes[2][8];
|
||||
};
|
||||
|
||||
struct ActiveScreenBufferDetails {
|
||||
struct CurrentScreen {
|
||||
uint16_t currentBuffer;
|
||||
unsigned char *planes[8];
|
||||
};
|
||||
|
||||
void allocateDoubleBufferedScreenMemory(
|
||||
struct ScreenDefinition *screenSetup,
|
||||
struct ActiveScreenBufferDetails *currentScreen,
|
||||
void setupScreen(
|
||||
struct ScreenSetup *screenSetup,
|
||||
uint16_t width,
|
||||
uint16_t height,
|
||||
uint8_t bitplanes
|
||||
);
|
||||
void teardownScreen(struct ScreenDefinition *screenSetup);
|
||||
void teardownScreen(struct ScreenSetup *screenSetup);
|
||||
|
||||
void setActiveScreenBuffer(
|
||||
struct ScreenDefinition *screenSetup,
|
||||
struct ActiveScreenBufferDetails *currentScreen,
|
||||
void setCurrentScreen(
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen,
|
||||
short int buffer
|
||||
);
|
||||
|
||||
void swapCurrentScreenBuffer(
|
||||
struct ScreenDefinition *screenSetup,
|
||||
struct ActiveScreenBufferDetails *currentScreen
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
);
|
||||
|
||||
void setupInitialCurrentScreen(
|
||||
struct ScreenDefinition *screenSetup,
|
||||
struct ActiveScreenBufferDetails *currentScreen
|
||||
struct ScreenSetup *screenSetup,
|
||||
struct CurrentScreen *currentScreen
|
||||
);
|
||||
#endif
|
||||
|
30
smakefile
30
smakefile
@ -1,9 +1,4 @@
|
||||
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
|
||||
|
||||
@ -13,27 +8,12 @@ all: main
|
||||
.s.o:
|
||||
genam -l $*.s
|
||||
|
||||
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 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
|
||||
|
||||
main: $(MAIN_OBJS)
|
||||
sc link to main math=standard $(MAIN_OBJS)
|
||||
sc link to main $(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
|
||||
sc link to bun_test identifierlength=32 math=standard bun_test.o bun.o cutest/CuTest.c
|
||||
test: blitter_test.o blitter.o system.o
|
||||
sc link to blitter_test identifierlength=32 math=standard blitter_test.o blitter.o cutest/CuTest.c system.o
|
||||
|
||||
|
Binary file not shown.
BIN
sprite-data
BIN
sprite-data
Binary file not shown.
@ -1,14 +1,8 @@
|
||||
#ifndef __BLITTER_H__
|
||||
#define __BLITTER_H__
|
||||
|
||||
#define BLTSIZE(w, h) (w + (h << 6))
|
||||
#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))
|
||||
|
||||
#define BLITTER_ASCENDING (0)
|
||||
#define BLITTER_DESCENDING (1)
|
||||
#include "types.h"
|
||||
#include "screen.h"
|
||||
|
||||
|
||||
/*
|
||||
|
@ -7,15 +7,9 @@
|
||||
|
||||
extern struct Custom far custom;
|
||||
|
||||
uint16_t copperlistSize;
|
||||
|
||||
uint16_t * prepareNewCopperlist(uint16_t size_b) {
|
||||
uint16_t *copperlist;
|
||||
|
||||
copperlistSize = size_b;
|
||||
|
||||
copperlist = AllocMem(
|
||||
copperlistSize,
|
||||
uint16_t * prepareNewCopperlist(void) {
|
||||
uint16_t *copperlist = AllocMem(
|
||||
COPPERLIST_SIZE,
|
||||
MEMF_CHIP | MEMF_CLEAR
|
||||
);
|
||||
|
||||
@ -26,9 +20,9 @@ uint16_t * prepareNewCopperlist(uint16_t size_b) {
|
||||
|
||||
void setCopperlist(uint16_t *copperlist) {
|
||||
custom.cop1lc = copperlist;
|
||||
custom.copjmp1 = 1;
|
||||
//custom.copjmp1 = 1;
|
||||
}
|
||||
|
||||
void freeCopperlist(uint16_t *copperlist) {
|
||||
FreeMem(copperlist, copperlistSize);
|
||||
FreeMem(copperlist, COPPERLIST_SIZE);
|
||||
}
|
||||
|
@ -1,31 +1,11 @@
|
||||
#ifndef __COPPER_H__
|
||||
#define __COPPER_H__
|
||||
|
||||
#define COPPERLIST_SIZE (10000)
|
||||
|
||||
#include "../types.h"
|
||||
|
||||
/**
|
||||
* 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);
|
||||
uint16_t * prepareNewCopperlist(void);
|
||||
void setCopperlist(uint16_t *copperlist);
|
||||
void freeCopperlist(uint16_t *copperlist);
|
||||
|
||||
|
@ -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;
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
#ifndef __SYSTEM_DEBUG__
|
||||
#define __SYSTEM_DEBUG__
|
||||
|
||||
void triggerUAEDebugger(void);
|
||||
|
||||
#endif
|
@ -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) \
|
||||
)
|
@ -12,20 +12,15 @@
|
||||
// copperlist
|
||||
extern void initializeCopperlist(void *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(
|
||||
uint16_t *copperlist,
|
||||
struct ScreenDefinition *,
|
||||
struct ActiveScreenBufferDetails *,
|
||||
struct ScreenSetup *,
|
||||
struct CurrentScreen *,
|
||||
void *copperlistBitplanePointers
|
||||
);
|
||||
extern void updateDisplayInCopperList(
|
||||
struct ScreenDefinition *,
|
||||
struct ActiveScreenBufferDetails *,
|
||||
struct ScreenSetup *,
|
||||
struct CurrentScreen *,
|
||||
void *copperlistBitplanePointers
|
||||
);
|
||||
extern uint16_t* addColorsToCopperlist(uint16_t *copperlist, color_t[], int count);
|
||||
|
164
system/system.s
164
system/system.s
@ -9,9 +9,6 @@
|
||||
XDEF _endCopperlist
|
||||
XDEF _myWaitBlit
|
||||
XDEF _WaitBOF
|
||||
XDEF _KeyboardHandler
|
||||
|
||||
XDEF _keyboardPressed
|
||||
|
||||
XREF _custom
|
||||
|
||||
@ -32,8 +29,6 @@ FUNC_CNT SET FUNC_CNT-6
|
||||
INCLUDE "hardware/custom.i"
|
||||
INCLUDE "hardware/dmabits.i"
|
||||
INCLUDE "hardware/intbits.i"
|
||||
INCLUDE "exec/io.i"
|
||||
INCLUDE "devices/inputevent.i"
|
||||
|
||||
; @param 1 Pointer to null terminated name of library
|
||||
; @param 2 Minimum version of library, 0 for any
|
||||
@ -61,69 +56,24 @@ RestoreRegister MACRO
|
||||
MOVE.W Old\1,\1(A0)
|
||||
ENDM
|
||||
|
||||
STRUCTURE ScreenDefinition,0
|
||||
UWORD ScreenDefinition_width
|
||||
UWORD ScreenDefinition_height
|
||||
UWORD ScreenDefinition_bitplanes
|
||||
ULONG ScreenDefinition_memoryStart
|
||||
UWORD ScreenDefinition_byteWidth
|
||||
UWORD ScreenDefinition_nextBitplaneAdvance
|
||||
UWORD ScreenDefinition_nextBufferAdvance
|
||||
ULONG ScreenDefinition_copperlistBitplanePointers
|
||||
LABEL ScreenDefinition_SIZEOF
|
||||
STRUCTURE ScreenSetup,0
|
||||
UWORD ScreenSetup_width
|
||||
UWORD ScreenSetup_height
|
||||
UWORD ScreenSetup_bitplanes
|
||||
ULONG ScreenSetup_memoryStart
|
||||
UWORD ScreenSetup_byteWidth
|
||||
UWORD ScreenSetup_nextBitplaneAdvance
|
||||
UWORD ScreenSetup_nextBufferAdvance
|
||||
ULONG ScreenSetup_copperlistBitplanePointers
|
||||
LABEL ScreenSetup_SIZEOF
|
||||
|
||||
STRUCTURE ActiveScreenBufferDetails,0
|
||||
UWORD ActiveScreenBufferDetails_currentBuffer
|
||||
ActiveScreenBufferDetails_planes EQU SOFFSET
|
||||
STRUCTURE CurrentScreen,0
|
||||
UWORD CurrentScreen_currentBuffer
|
||||
CurrentScreen_planes EQU SOFFSET
|
||||
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
|
||||
; @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
|
||||
BPLCON0_COLOR EQU $200
|
||||
|
||||
M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C
|
||||
_takeOverSystem:
|
||||
@ -131,15 +81,13 @@ _takeOverSystem:
|
||||
OpenLibrary #GraphicsLibrary,#0
|
||||
MOVE.L D0,GraphicsBase
|
||||
|
||||
MOVE.L $4,A6
|
||||
CALLLIB _LVOForbid
|
||||
|
||||
MOVE.L D0,A6
|
||||
MOVE.L gb_ActiView(A6),OldView
|
||||
MOVE.L gb_copinit(A6),OldCopper
|
||||
|
||||
MOVE.L #0,A1
|
||||
CALLLIB _LVOLoadView
|
||||
CALLLIB _LVOWaitTOF
|
||||
CALLLIB _LVOWaitTOF
|
||||
|
||||
CALLLIB _LVOOwnBlitter
|
||||
CALLLIB _LVOWaitBlit
|
||||
|
||||
@ -150,14 +98,20 @@ _takeOverSystem:
|
||||
PreserveRegister intreq
|
||||
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
|
||||
MOVE.W #$7FFF,intena(A0) ; disable all interrupts
|
||||
; 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_PORTS|INTF_EXTER|INTF_VERTB,intena(A0) ; enable master interrupt, copper, and VBR
|
||||
MOVE.W #INTF_SETCLR|INTF_INTEN|INTF_COPER|INTF_VERTB,intena(A0) ; enable master interrupt, copper, and VBR
|
||||
|
||||
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,dmacon(A0)
|
||||
MOVEM.L (SP)+,A2/A6
|
||||
RTS
|
||||
|
||||
@ -193,6 +147,7 @@ NewLevel3VBI:
|
||||
MOVEM.L (SP)+,D0-A6
|
||||
RTE
|
||||
|
||||
|
||||
_giveBackSystem:
|
||||
MOVE.L A6,-(SP)
|
||||
LEA _custom,A0
|
||||
@ -210,6 +165,9 @@ _giveBackSystem:
|
||||
CALLLIB _LVOWaitTOF
|
||||
CALLLIB _LVOWaitBlit
|
||||
CALLLIB _LVODisownBlitter
|
||||
|
||||
MOVE.L $4,A6
|
||||
CALLLIB _LVOPermit
|
||||
MOVE.L (SP)+,A6
|
||||
RTS
|
||||
|
||||
@ -221,8 +179,8 @@ _initializeCopperlist:
|
||||
RTS
|
||||
|
||||
; @stack *copperlist Pointer to copperlist
|
||||
; @stack ScreenDefinition Pointer to screenSetup struct
|
||||
; @stack ActiveScreenBufferDetails Pointer to currentScreen struct
|
||||
; @stack ScreenSetup Pointer to screenSetup struct
|
||||
; @stack CurrentScreen Pointer to currentScreen struct
|
||||
; @stack copperlistBitplanePointers Pointer to bitplane pointers within the copper list [[high, low], ...]
|
||||
STRUCTURE updateDisplayInCopperList,4
|
||||
ULONG updateDisplayInCopperList_screenSetup
|
||||
@ -237,9 +195,9 @@ _updateDisplayInCopperList:
|
||||
MOVE.L D0,A2
|
||||
; a2 has copperlistBitplanePointers
|
||||
|
||||
MOVE.W ScreenDefinition_bitplanes(A0),D1
|
||||
MOVE.W ScreenSetup_bitplanes(A0),D1
|
||||
SUBQ #1,D1
|
||||
LEA ActiveScreenBufferDetails_planes(A1),A1
|
||||
LEA CurrentScreen_planes(A1),A1
|
||||
; a1 has planes
|
||||
|
||||
.continue:
|
||||
@ -290,13 +248,13 @@ _setUpEmptySpritesInCopperlist:
|
||||
RTS
|
||||
|
||||
; @stack *copperlist Pointer to copperlist
|
||||
; @stack ScreenDefinition Pointer to screenDefinition struct
|
||||
; @stack ActiveScreenBufferDetails Pointer to activeScreenBufferDetails struct
|
||||
; @stack copperlistBitplanePointers Pointer to copperlistBitplanePointers struct
|
||||
; @stack ScreenSetup Pointer to screenSetup struct
|
||||
; @stack CurrentScreen Pointer to currentScreen struct
|
||||
; @stack copperlistBitplanePointers Pointer to currentScreen struct
|
||||
STRUCTURE AddDisplayToCopperListParams,4
|
||||
ULONG AddDisplayToCopperListParams_copperlistPtr
|
||||
ULONG AddDisplayToCopperListParams_screenDefinitionPtr
|
||||
ULONG AddDisplayToCopperListParams_activeScreenBufferDetailsPtr
|
||||
ULONG AddDisplayToCopperListParams_screenSetupPtr
|
||||
ULONG AddDisplayToCopperListParams_currentScreenPtr
|
||||
ULONG AddDisplayToCopperListParams_copperlistBitplanePointersPtr
|
||||
_addDisplayToCopperlist:
|
||||
MOVE.L A7,A0
|
||||
@ -304,15 +262,16 @@ _addDisplayToCopperlist:
|
||||
; A2,D2,D3
|
||||
MOVEM.L A2-A4/D2-D4,-(SP)
|
||||
MOVE.L AddDisplayToCopperListParams_copperlistPtr(A0),A1 ; copperlist
|
||||
MOVE.L AddDisplayToCopperListParams_screenDefinitionPtr(A0),A2 ; screenDefinition
|
||||
MOVE.L AddDisplayToCopperListParams_activeScreenBufferDetailsPtr(A0),A3 ; currentScreen
|
||||
MOVE.L AddDisplayToCopperListParams_screenSetupPtr(A0),A2 ; screenSetup
|
||||
MOVE.L AddDisplayToCopperListParams_currentScreenPtr(A0),A3 ; currentScreen
|
||||
MOVE.L AddDisplayToCopperListParams_copperlistBitplanePointersPtr(A0),A4 ; copperlistBitplanePointers
|
||||
|
||||
LEA ActiveScreenBufferDetails_planes(A3),A3
|
||||
LEA CurrentScreen_planes(A3),A3
|
||||
; a3 contains address to planes
|
||||
|
||||
|
||||
MOVEQ #0,D0
|
||||
MOVE.W ScreenDefinition_bitplanes(A2),D0
|
||||
MOVE.W ScreenSetup_bitplanes(A2),D0
|
||||
; d0 is num of bitplanes
|
||||
|
||||
; set up bplpt
|
||||
@ -331,10 +290,9 @@ _addDisplayToCopperlist:
|
||||
; get this position for later updating
|
||||
MOVE.L A1,(A4)+
|
||||
MOVE.W D3,(A1)+
|
||||
ADDQ #2,D1
|
||||
|
||||
; low byte
|
||||
SWAP D3
|
||||
ADDQ #2,D1
|
||||
MOVE.W D1,(A1)+
|
||||
; get this position for later updating
|
||||
MOVE.L A1,(A4)+
|
||||
@ -349,6 +307,7 @@ _addDisplayToCopperlist:
|
||||
MOVE.L A1,D0
|
||||
MOVEM.L (SP)+,A2-A4/D2-D4
|
||||
|
||||
|
||||
RTS
|
||||
|
||||
; @stack *copperlist
|
||||
@ -383,45 +342,33 @@ _endCopperlist:
|
||||
|
||||
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
|
||||
_setUpDisplay:
|
||||
MOVE.L D2,-(SP)
|
||||
MOVE.L 8(A7),D2 ; bitplaneCount
|
||||
MOVE.L 8(A7),D2
|
||||
|
||||
LEA _custom,A1
|
||||
|
||||
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
|
||||
MOVE.W D2,D1
|
||||
|
||||
AND.W #$7,D1
|
||||
ROL.W #8,D1
|
||||
ROL.W #4,D1
|
||||
ADD.W D1,D0
|
||||
|
||||
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)
|
||||
|
||||
; sprites always on top for this demo
|
||||
MOVE.W #$0020,bplcon2(A1)
|
||||
|
||||
; no modulos needed
|
||||
MOVE.W #0,bplcon2(A1)
|
||||
MOVE.W #0,bpl1mod(A1)
|
||||
MOVE.W #0,bpl2mod(A1)
|
||||
|
||||
; pal default
|
||||
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 #$00d0,ddfstop(A1)
|
||||
MOVE.L (SP)+,D2
|
||||
@ -482,8 +429,5 @@ VBIPtr dc.l 0
|
||||
CNOP 0,4
|
||||
GraphicsLibrary GRAPHICSNAME
|
||||
|
||||
CNOP 0,4
|
||||
_keyboardPressed dc.l 0
|
||||
|
||||
SECTION Sprite,Data_C
|
||||
EmptySprite dc.w 0,0
|
||||
|
BIN
topaz-bitplane
BIN
topaz-bitplane
Binary file not shown.
BIN
topaz-narrow.png
BIN
topaz-narrow.png
Binary file not shown.
Before Width: | Height: | Size: 46 KiB |
8
types.h
8
types.h
@ -3,14 +3,6 @@
|
||||
|
||||
#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 long uint32_t;
|
||||
typedef unsigned short uint16_t;
|
||||
|
Loading…
Reference in New Issue
Block a user