Compare commits
No commits in common. "main" and "jb/sprites" have entirely different histories.
main
...
jb/sprites
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);
|
|
||||||
}
|
|
|
@ -0,0 +1 @@
|
||||||
|
* [ ] Move bun calculation to separate file for CuTest and vamos
|
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);
|
|
||||||
}
|
|
|
@ -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
|
Binary file not shown.
|
@ -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);
|
||||||
|
}
|
353
bun.c
353
bun.c
|
@ -13,7 +13,6 @@
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "bun.h"
|
#include "bun.h"
|
||||||
#include "system/system.h"
|
#include "system/system.h"
|
||||||
#include "system/blitter.h"
|
|
||||||
|
|
||||||
#define COOL_BUN_WIDTH (32)
|
#define COOL_BUN_WIDTH (32)
|
||||||
#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8)
|
#define COOL_BUN_WIDTH_BYTES (COOL_BUN_WIDTH / 8)
|
||||||
|
@ -27,113 +26,82 @@
|
||||||
|
|
||||||
#define BUN_MAX_RANGE (31 + 320)
|
#define BUN_MAX_RANGE (31 + 320)
|
||||||
|
|
||||||
|
#define BUN_COUNT (12)
|
||||||
#define BUN_SPEED (1)
|
#define BUN_SPEED (1)
|
||||||
|
|
||||||
#define BUN_HORIZ_DISTANCE_BETWEEN_BUNS ((BUN_MAX_RANGE / 4) - COOL_BUN_WIDTH)
|
#define BUN_HORIZ_DISTANCE_BETWEEN_BUNS ((BUN_MAX_RANGE / 4) - COOL_BUN_WIDTH)
|
||||||
#define BUN_TOTAL_HORIZ_DISTANCE (BUN_HORIZ_DISTANCE_BETWEEN_BUNS + COOL_BUN_WIDTH)
|
#define BUN_TOTAL_HORIZ_DISTANCE (BUN_HORIZ_DISTANCE_BETWEEN_BUNS + COOL_BUN_WIDTH)
|
||||||
#define BUN_ROW_START (50)
|
#define BUN_ROW_START (30)
|
||||||
#define BUN_VERT_DISTANCE_BETWEEN_BUNS (30)
|
#define BUN_VERT_DISTANCE_BETWEEN_BUNS (20)
|
||||||
#define BUN_TOTAL_VERT_DISTANCE (COOL_BUN_HEIGHT + BUN_VERT_DISTANCE_BETWEEN_BUNS)
|
#define BUN_TOTAL_VERT_DISTANCE (COOL_BUN_HEIGHT + BUN_VERT_DISTANCE_BETWEEN_BUNS)
|
||||||
#define FRAME_MAX (BUN_TOTAL_HORIZ_DISTANCE / BUN_SPEED)
|
#define FRAME_MAX (BUN_TOTAL_HORIZ_DISTANCE / BUN_SPEED)
|
||||||
|
|
||||||
|
#define FRAMES_FOR_SCREEN (90)
|
||||||
#define BUN_WAVE_LENGTH (FRAMES_FOR_SCREEN / 2)
|
#define BUN_WAVE_LENGTH (FRAMES_FOR_SCREEN / 2)
|
||||||
|
|
||||||
// linked as raw bytes in assembler
|
// linked as raw bytes in assembler
|
||||||
extern unsigned char chip coolbun[];
|
extern unsigned char far coolbun[];
|
||||||
|
|
||||||
|
unsigned char *coolbunArea = 0;
|
||||||
|
|
||||||
|
#define BLTCON0( \
|
||||||
|
minterm, aChan, bChan, cChan, dChan, shift \
|
||||||
|
) (minterm + (aChan << 11) + (bChan << 10) + (cChan << 9) + (dChan << 8) + (shift << 12))
|
||||||
|
#define BLTCON1(descending, shift) ((descending << 1) + (shift << 12))
|
||||||
|
|
||||||
extern struct Custom far custom;
|
extern struct Custom far custom;
|
||||||
|
|
||||||
struct BunClear {
|
void setupBun(void) {
|
||||||
uint16_t memoryStartOffsetBytes;
|
unsigned char *currentCoolBunArea, *currentCoolBun;
|
||||||
uint16_t widthWords;
|
|
||||||
uint16_t heightRows;
|
|
||||||
uint8_t direction;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define BUN_OFF_RIGHT_SIDE (0)
|
coolbunArea = AllocMem(COOL_BUN_MEMORY_SIZE, MEMF_CHIP | MEMF_CLEAR);
|
||||||
#define BUN_OFF_LEFT_SIDE (1)
|
currentCoolBunArea = coolbunArea;
|
||||||
#define BUN_ANYWHERE (2)
|
currentCoolBun = coolbun;
|
||||||
|
|
||||||
uint8_t *coolbunPlaneStarts[3][2];
|
CopyMem(coolbun, coolbunArea, COOL_BUN_MEMORY_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
uint16_t bunRightSide_bltalwmPrecalc[16];
|
void teardownBun(void) {
|
||||||
uint16_t bunLeftSide_bltalwmPrecalc[16];
|
if (coolbunArea) {
|
||||||
|
FreeMem(coolbunArea, COOL_BUN_MEMORY_SIZE);
|
||||||
void precalculateBunBLTALWM() {
|
|
||||||
int shift, j;
|
|
||||||
uint16_t bltalwm;
|
|
||||||
|
|
||||||
for (shift = 0; shift < 16; ++shift) {
|
|
||||||
// right
|
|
||||||
bltalwm = 0x0000;
|
|
||||||
|
|
||||||
for (j = 0; j < 15 - shift; ++j) {
|
|
||||||
bltalwm += (1 << (15 - j));
|
|
||||||
}
|
|
||||||
|
|
||||||
bunRightSide_bltalwmPrecalc[shift] = bltalwm;
|
|
||||||
|
|
||||||
//left
|
|
||||||
bltalwm = 0x0000;
|
|
||||||
for (j = 0; j <= 15 - shift; ++j) {
|
|
||||||
bltalwm += (1 << j);
|
|
||||||
}
|
|
||||||
|
|
||||||
bunLeftSide_bltalwmPrecalc[shift] = bltalwm;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void bun_offRightSide(
|
void bun_offRightSide(
|
||||||
int plusXValue,
|
int plusXValue,
|
||||||
int y,
|
int y,
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
struct CurrentScreen *currentScreen
|
||||||
struct BunClear *bunClear
|
|
||||||
) {
|
) {
|
||||||
uint8_t i, plane = 0;
|
uint8_t i, plane = 0;
|
||||||
uint8_t shift = plusXValue & 15;
|
uint8_t shift = plusXValue & 15;
|
||||||
uint8_t wordShift = (plusXValue >> 4);
|
uint8_t wordShift = (plusXValue >> 4);
|
||||||
uint16_t bltalwm, bltcon0, bltcon1, bltdmod, bltsize;
|
uint16_t bltalwm;
|
||||||
|
|
||||||
bunClear->memoryStartOffsetBytes = (y * screenDefinition->byteWidth) +
|
|
||||||
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);
|
|
||||||
|
|
||||||
for (plane = 0; plane < 2; ++plane) {
|
for (plane = 0; plane < 2; ++plane) {
|
||||||
custom.bltcon0 = bltcon0;
|
custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
|
||||||
custom.bltcon1 = bltcon1;
|
custom.bltcon1 = BLTCON1(0, shift);
|
||||||
|
|
||||||
custom.bltapt = coolbunPlaneStarts[BUN_OFF_RIGHT_SIDE][plane];
|
custom.bltadat = 0xffff;
|
||||||
custom.bltdpt = activeScreenBufferDetails->planes[plane] +
|
custom.bltbpt = coolbunArea +
|
||||||
bunClear->memoryStartOffsetBytes;
|
plane * COOL_BUN_PLANE_SIZE;
|
||||||
|
custom.bltdpt = currentScreen->planes[plane] +
|
||||||
|
(y * screenSetup->byteWidth) +
|
||||||
|
screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES +
|
||||||
|
wordShift * 2;
|
||||||
|
|
||||||
custom.bltafwm = 0xffff;
|
custom.bltafwm = 0xffff;
|
||||||
|
bltalwm = 0x0000;
|
||||||
|
for (i = 0; i <= 15 - shift; ++i) {
|
||||||
|
bltalwm += (1 << (15 - i));
|
||||||
|
}
|
||||||
custom.bltalwm = bltalwm;
|
custom.bltalwm = bltalwm;
|
||||||
|
|
||||||
custom.bltamod = wordShift * 2;
|
custom.bltbmod = wordShift * 2;
|
||||||
custom.bltdmod = bltdmod;
|
custom.bltdmod = screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES +
|
||||||
|
wordShift * 2;
|
||||||
|
|
||||||
custom.bltsize = bltsize;
|
custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6);
|
||||||
|
|
||||||
WaitBlit();
|
WaitBlit();
|
||||||
}
|
}
|
||||||
|
@ -142,58 +110,47 @@ void bun_offRightSide(
|
||||||
void bun_offLeftSide(
|
void bun_offLeftSide(
|
||||||
int minusXValue,
|
int minusXValue,
|
||||||
int y,
|
int y,
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
struct CurrentScreen *currentScreen
|
||||||
struct BunClear *bunClear
|
|
||||||
) {
|
) {
|
||||||
unsigned char plane;
|
unsigned char plane;
|
||||||
uint8_t shift = minusXValue & 15;
|
uint8_t shift = minusXValue & 15;
|
||||||
uint8_t wordShift = (minusXValue >> 4);
|
uint8_t wordShift = (minusXValue >> 4);
|
||||||
uint8_t i;
|
uint8_t i;
|
||||||
uint16_t bltalwm, bltcon0, bltcon1, bltdmod, bltsize;
|
uint16_t bltalwm;
|
||||||
|
|
||||||
// y can't be 0 otherwise we will corrupt memory for now
|
// y can't be 0 otherwise we will corrupt memory for now
|
||||||
if (y == 0) return;
|
if (y == 0) return;
|
||||||
|
|
||||||
bunClear->memoryStartOffsetBytes = (screenDefinition->byteWidth * (y + COOL_BUN_LAST_ROW)) +
|
|
||||||
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) {
|
for (plane = 0; plane < 2; ++plane) {
|
||||||
// shift left, so descending
|
// shift left, so descending
|
||||||
custom.bltcon0 = bltcon0;
|
custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
|
||||||
custom.bltcon1 = bltcon1;
|
custom.bltcon1 = BLTCON1(1, shift);
|
||||||
|
|
||||||
// a has bun data
|
// a has a mask we're shifting
|
||||||
custom.bltapt = coolbunPlaneStarts[BUN_OFF_LEFT_SIDE][plane];
|
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
|
// 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;
|
custom.bltafwm = 0xffff;
|
||||||
|
bltalwm = 0x0000;
|
||||||
|
for (i = 0; i <= 15 - shift; ++i) {
|
||||||
|
bltalwm += (1 << i);
|
||||||
|
}
|
||||||
custom.bltalwm = bltalwm;
|
custom.bltalwm = bltalwm;
|
||||||
|
|
||||||
custom.bltamod = wordShift * 2;
|
custom.bltbmod = wordShift * 2;
|
||||||
custom.bltdmod = bltdmod;
|
custom.bltdmod = screenSetup->byteWidth - 4 + wordShift * 2;
|
||||||
|
|
||||||
custom.bltsize = bltsize;
|
custom.bltsize = 2 - wordShift + (COOL_BUN_HEIGHT << 6);
|
||||||
|
|
||||||
WaitBlit();
|
WaitBlit();
|
||||||
}
|
}
|
||||||
|
@ -202,101 +159,65 @@ void bun_offLeftSide(
|
||||||
void bun_anywhere(
|
void bun_anywhere(
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
struct CurrentScreen *currentScreen
|
||||||
struct BunClear *bunClear
|
|
||||||
) {
|
) {
|
||||||
uint8_t plane;
|
uint8_t plane;
|
||||||
uint8_t shift = x & 15;
|
uint8_t shift = x & 15;
|
||||||
uint8_t needsExtraWord = shift != 0;
|
uint8_t needsExtraWord = shift != 0;
|
||||||
uint16_t bltcon0, bltcon1, bltalwm, bltamod, bltdmod, bltsize;
|
|
||||||
|
|
||||||
bunClear->memoryStartOffsetBytes = WORD_ALIGNED_BYTE_POSITION(screenDefinition->width, x, y);
|
|
||||||
|
|
||||||
bunClear->heightRows = COOL_BUN_HEIGHT;
|
|
||||||
bunClear->widthWords = 2 + needsExtraWord;
|
|
||||||
bunClear->direction = BLITTER_ASCENDING;
|
|
||||||
|
|
||||||
// buns will never interfere with a background so they don't need a mask
|
|
||||||
bltcon0 = BLTCON0(0xf0, 1, 0, 0, 1, shift);
|
|
||||||
bltcon1 = BLTCON1(bunClear->direction, shift);
|
|
||||||
|
|
||||||
if (needsExtraWord) {
|
|
||||||
bltalwm = 0x0000;
|
|
||||||
} else {
|
|
||||||
bltalwm = 0xffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
bltamod = -(needsExtraWord * 2);
|
|
||||||
bltdmod = screenDefinition->byteWidth - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2);
|
|
||||||
bltsize = bunClear->widthWords + (bunClear->heightRows << 6);
|
|
||||||
|
|
||||||
for (plane = 0; plane < 2; ++plane) {
|
for (plane = 0; plane < 2; ++plane) {
|
||||||
custom.bltcon0 = bltcon0;
|
// if we extend the bun area by a word, we only need one write
|
||||||
custom.bltcon1 = bltcon1;
|
|
||||||
|
|
||||||
custom.bltapt = coolbunPlaneStarts[BUN_ANYWHERE][plane];
|
// buns will never interfere with a background so they don't need a mask
|
||||||
custom.bltdpt = activeScreenBufferDetails->planes[plane] +
|
// they do need the scratch area though
|
||||||
bunClear->memoryStartOffsetBytes;
|
custom.bltcon0 = BLTCON0(0xc0, 0, 1, 0, 1, shift);
|
||||||
|
custom.bltcon1 = BLTCON1(0, shift);
|
||||||
|
|
||||||
|
custom.bltadat = 0xffff;
|
||||||
|
custom.bltbpt = coolbunArea + plane * COOL_BUN_PLANE_SIZE;
|
||||||
|
custom.bltdpt = currentScreen->planes[plane] +
|
||||||
|
WORD_ALIGNED_BYTE_POSITION(screenSetup->width, x, y);
|
||||||
|
|
||||||
|
// custom.bltdpt = screenSetup.memoryStart;
|
||||||
custom.bltafwm = 0xffff;
|
custom.bltafwm = 0xffff;
|
||||||
custom.bltalwm = bltalwm;
|
if (needsExtraWord) {
|
||||||
|
custom.bltalwm = 0x0000;
|
||||||
|
} else {
|
||||||
|
custom.bltalwm = 0xffff;
|
||||||
|
}
|
||||||
|
|
||||||
custom.bltamod = bltamod;
|
custom.bltbmod = -(needsExtraWord * 2);
|
||||||
custom.bltdmod = bltdmod;
|
custom.bltdmod = screenSetup->byteWidth - COOL_BUN_WIDTH_BYTES - (needsExtraWord * 2);
|
||||||
custom.bltsize = bltsize;
|
custom.bltsize = (2 + needsExtraWord) + (COOL_BUN_HEIGHT << 6);
|
||||||
|
|
||||||
WaitBlit();
|
WaitBlit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ENABLE_RENDER_BUN_CHECKING (0)
|
|
||||||
|
|
||||||
void renderBun(
|
void renderBun(
|
||||||
int x,
|
int x,
|
||||||
int y,
|
int y,
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
struct CurrentScreen *currentScreen
|
||||||
struct BunClear *bunClear
|
|
||||||
) {
|
) {
|
||||||
/**
|
/**
|
||||||
* Conditions that will cause the program to crash if met. If your bun
|
* Conditions that will cause the program to crash if met. If your bun
|
||||||
* isn't rendering, it's due to here. Turn off checking once you know
|
* isn't rendering, it's due to here.
|
||||||
* everything is solid to save some CPU.
|
|
||||||
*
|
*
|
||||||
* TODO: Handle top/bottom off-screen as well.
|
* TODO: Handle top/bottom off-screen as well.
|
||||||
*/
|
*/
|
||||||
if (ENABLE_RENDER_BUN_CHECKING) {
|
if (x < -31) return;
|
||||||
if (x < -31) return;
|
if (x > screenSetup->width + 31) return;
|
||||||
if (x > screenDefinition->width + 31) return;
|
if (y < 1) return;
|
||||||
if (y < 1) return;
|
if (y > screenSetup->height- COOL_BUN_HEIGHT - 1) return;
|
||||||
if (y > screenDefinition->height - COOL_BUN_HEIGHT - 1) return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (x < 0) {
|
if (x < 0) {
|
||||||
bun_offLeftSide(
|
bun_offLeftSide(-x, y, screenSetup, currentScreen);
|
||||||
-x,
|
} else if (x > screenSetup->width - COOL_BUN_WIDTH) {
|
||||||
y,
|
bun_offRightSide(x - (screenSetup->width - COOL_BUN_WIDTH), y, screenSetup, currentScreen);
|
||||||
screenDefinition,
|
|
||||||
activeScreenBufferDetails,
|
|
||||||
bunClear
|
|
||||||
);
|
|
||||||
} else if (x > screenDefinition->width - COOL_BUN_WIDTH) {
|
|
||||||
bun_offRightSide(
|
|
||||||
x - (screenDefinition->width - COOL_BUN_WIDTH),
|
|
||||||
y,
|
|
||||||
screenDefinition,
|
|
||||||
activeScreenBufferDetails,
|
|
||||||
bunClear
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
bun_anywhere(
|
bun_anywhere(x, y, screenSetup, currentScreen);
|
||||||
x,
|
|
||||||
y,
|
|
||||||
screenDefinition,
|
|
||||||
activeScreenBufferDetails,
|
|
||||||
bunClear
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +228,7 @@ int bunAngleAdjustments[BUN_COUNT];
|
||||||
void calculateBunPositions(
|
void calculateBunPositions(
|
||||||
uint16_t frame,
|
uint16_t frame,
|
||||||
short int bunPositions[BUN_COUNT][2],
|
short int bunPositions[BUN_COUNT][2],
|
||||||
struct ScreenDefinition *screenDefinition
|
struct ScreenSetup *screenSetup
|
||||||
) {
|
) {
|
||||||
int x, y, row, column, current;
|
int x, y, row, column, current;
|
||||||
float angle, startAngle;
|
float angle, startAngle;
|
||||||
|
@ -342,7 +263,7 @@ void calculateBunPositions(
|
||||||
short int allBunPositionsByFrame[FRAMES_FOR_SCREEN][BUN_COUNT][2];
|
short int allBunPositionsByFrame[FRAMES_FOR_SCREEN][BUN_COUNT][2];
|
||||||
|
|
||||||
void calculateAllBunPositions(
|
void calculateAllBunPositions(
|
||||||
struct ScreenDefinition *screenDefinition
|
struct ScreenSetup *screenSetup
|
||||||
) {
|
) {
|
||||||
int frame;
|
int frame;
|
||||||
|
|
||||||
|
@ -350,12 +271,12 @@ void calculateAllBunPositions(
|
||||||
calculateBunPositions(
|
calculateBunPositions(
|
||||||
frame,
|
frame,
|
||||||
allBunPositionsByFrame[frame],
|
allBunPositionsByFrame[frame],
|
||||||
screenDefinition
|
screenSetup
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void buildBunAngleAdjustments(void) {
|
void buildBunAngleAdjustments() {
|
||||||
int current, angleAdjustment;
|
int current, angleAdjustment;
|
||||||
for (current = 0; current < BUN_COUNT; ++current) {
|
for (current = 0; current < BUN_COUNT; ++current) {
|
||||||
angleAdjustment = 0;
|
angleAdjustment = 0;
|
||||||
|
@ -366,70 +287,16 @@ void buildBunAngleAdjustments(void) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void precalculateBunRenderInfo(void) {
|
|
||||||
int plane;
|
|
||||||
|
|
||||||
for (plane = 0; plane < 2; ++plane) {
|
|
||||||
coolbunPlaneStarts[BUN_OFF_RIGHT_SIDE][plane] = coolbun + plane * COOL_BUN_PLANE_SIZE;
|
|
||||||
coolbunPlaneStarts[BUN_ANYWHERE][plane] = coolbun + plane * COOL_BUN_PLANE_SIZE;
|
|
||||||
coolbunPlaneStarts[BUN_OFF_LEFT_SIDE][plane] = coolbun + 2 +
|
|
||||||
COOL_BUN_LAST_ROW_BYTES +
|
|
||||||
plane * COOL_BUN_PLANE_SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void setupBunRenderer(
|
void setupBunRenderer(
|
||||||
struct BunRenderer *bunRenderer,
|
struct BunRenderer *bunRenderer,
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails) {
|
struct CurrentScreen *currentScreen) {
|
||||||
bunRenderer->screenDefinition = screenDefinition;
|
bunRenderer->screenSetup = screenSetup;
|
||||||
bunRenderer->activeScreenBufferDetails = activeScreenBufferDetails;
|
bunRenderer->currentScreen = currentScreen;
|
||||||
|
|
||||||
|
setupBun();
|
||||||
buildBunAngleAdjustments();
|
buildBunAngleAdjustments();
|
||||||
calculateAllBunPositions(screenDefinition);
|
calculateAllBunPositions(screenSetup);
|
||||||
precalculateBunRenderInfo();
|
|
||||||
precalculateBunBLTALWM();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Is there bun clear information for this frame? This is not true for the
|
|
||||||
* first frame in the demo.
|
|
||||||
*/
|
|
||||||
int hasBunClear[2] = {0,0};
|
|
||||||
struct BunClear bunClearForScreen[2][BUN_COUNT];
|
|
||||||
|
|
||||||
void clearCurrentBuns(
|
|
||||||
struct BunRenderer *bunRenderer
|
|
||||||
) {
|
|
||||||
int bun, plane;
|
|
||||||
struct BunClear *currentBunClear;
|
|
||||||
uint16_t bltcon0, bltcon1, bltdmod, bltsize;
|
|
||||||
|
|
||||||
if (!hasBunClear[bunRenderer->activeScreenBufferDetails->currentBuffer]) return;
|
|
||||||
|
|
||||||
bltcon0 = BLTCON0(0xc0, 0, 0, 0, 1, 0);
|
|
||||||
|
|
||||||
for (bun = 0; bun < BUN_COUNT; ++bun) {
|
|
||||||
currentBunClear = &bunClearForScreen[bunRenderer->activeScreenBufferDetails->currentBuffer][bun];
|
|
||||||
|
|
||||||
bltcon1 = BLTCON1(currentBunClear->direction, 0);
|
|
||||||
bltdmod = bunRenderer->screenDefinition->byteWidth - (currentBunClear->widthWords * 2);
|
|
||||||
bltsize = currentBunClear->widthWords + (currentBunClear->heightRows << 6);
|
|
||||||
|
|
||||||
for (plane = 0; plane < 2; ++plane) {
|
|
||||||
custom.bltcon0 = bltcon0;
|
|
||||||
custom.bltcon1 = bltcon1;
|
|
||||||
custom.bltadat = 0x0000;
|
|
||||||
custom.bltafwm = 0xffff;
|
|
||||||
custom.bltalwm = 0xffff;
|
|
||||||
custom.bltdpt = bunRenderer->activeScreenBufferDetails->planes[plane] +
|
|
||||||
currentBunClear->memoryStartOffsetBytes;
|
|
||||||
custom.bltdmod = bltdmod;
|
|
||||||
custom.bltsize = bltsize;
|
|
||||||
|
|
||||||
WaitBlit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void renderBunFrame(
|
void renderBunFrame(
|
||||||
|
@ -444,14 +311,12 @@ void renderBunFrame(
|
||||||
renderBun(
|
renderBun(
|
||||||
allBunPositionsByFrame[frame][bun][0],
|
allBunPositionsByFrame[frame][bun][0],
|
||||||
allBunPositionsByFrame[frame][bun][1],
|
allBunPositionsByFrame[frame][bun][1],
|
||||||
bunRenderer->screenDefinition,
|
bunRenderer->screenSetup,
|
||||||
bunRenderer->activeScreenBufferDetails,
|
bunRenderer->currentScreen
|
||||||
&bunClearForScreen[bunRenderer->activeScreenBufferDetails->currentBuffer][bun]
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
hasBunClear[bunRenderer->activeScreenBufferDetails->currentBuffer] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void teardownBunRenderer() {
|
void teardownBunRenderer() {
|
||||||
|
teardownBun();
|
||||||
}
|
}
|
||||||
|
|
19
bun.h
19
bun.h
|
@ -3,31 +3,20 @@
|
||||||
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
|
||||||
#define FRAMES_FOR_SCREEN (60)
|
|
||||||
#define BUN_COUNT (12)
|
|
||||||
|
|
||||||
struct BunRenderer {
|
struct BunRenderer {
|
||||||
struct ScreenDefinition *screenDefinition;
|
struct ScreenSetup *screenSetup;
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails;
|
struct CurrentScreen *currentScreen;
|
||||||
};
|
};
|
||||||
|
|
||||||
void setupBunRenderer(
|
void setupBunRenderer(
|
||||||
struct BunRenderer *,
|
struct BunRenderer *,
|
||||||
struct ScreenDefinition *,
|
struct ScreenSetup *,
|
||||||
struct ActiveScreenBufferDetails *
|
struct CurrentScreen *
|
||||||
);
|
);
|
||||||
|
|
||||||
void renderBunFrame(
|
void renderBunFrame(
|
||||||
int frame,
|
int frame,
|
||||||
struct BunRenderer *
|
struct BunRenderer *
|
||||||
);
|
);
|
||||||
void clearCurrentBuns(
|
|
||||||
struct BunRenderer *
|
|
||||||
);
|
|
||||||
void teardownBunRenderer(void);
|
void teardownBunRenderer(void);
|
||||||
|
|
||||||
void calculateNeededRedrawRanges(
|
|
||||||
int frame,
|
|
||||||
uint16_t redrawRanges[BUN_COUNT][4]
|
|
||||||
);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
BIN
copper-colors
BIN
copper-colors
Binary file not shown.
|
@ -9,7 +9,7 @@ require 'rmagick'
|
||||||
# [ ] turn the big color counts into three bitplames worth of data
|
# [ ] turn the big color counts into three bitplames worth of data
|
||||||
# [ ] turn the little color counts into up to 8 sprites worth of data strips & color changes
|
# [ ] turn the little color counts into up to 8 sprites worth of data strips & color changes
|
||||||
|
|
||||||
image = Magick::Image.read('topaz-narrow.png').first
|
image = Magick::Image.read('topaz.png').first
|
||||||
|
|
||||||
rows = []
|
rows = []
|
||||||
|
|
||||||
|
@ -17,10 +17,6 @@ class MaskPixel
|
||||||
def initialize; end
|
def initialize; end
|
||||||
|
|
||||||
def color? = false
|
def color? = false
|
||||||
|
|
||||||
def ==(other)
|
|
||||||
other.is_a?(MaskPixel)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Color
|
class Color
|
||||||
|
@ -32,26 +28,10 @@ class Color
|
||||||
@blue = blue
|
@blue = blue
|
||||||
end
|
end
|
||||||
|
|
||||||
WHITE = new(red: 15, green: 15, blue: 15)
|
|
||||||
BLACK = new(red: 0, green: 0, blue: 0)
|
|
||||||
TRANSPARENT = new(red: -1, green: -1, blue: -1)
|
|
||||||
|
|
||||||
def ==(other)
|
def ==(other)
|
||||||
red == other.red && green == other.green && blue == other.blue
|
red == other.red && green == other.green && blue == other.blue
|
||||||
end
|
end
|
||||||
|
|
||||||
def transparent?
|
|
||||||
red == -1 && green == -1 && blue == -1
|
|
||||||
end
|
|
||||||
|
|
||||||
def -(other)
|
|
||||||
red - other.red + green - other.green + blue - other.blue
|
|
||||||
end
|
|
||||||
|
|
||||||
def for_diff
|
|
||||||
2 * red * red + 4 * green * green + 3 * blue * blue
|
|
||||||
end
|
|
||||||
|
|
||||||
alias eql? ==
|
alias eql? ==
|
||||||
|
|
||||||
def hash
|
def hash
|
||||||
|
@ -73,8 +53,6 @@ MAX_ALPHA = Magick::QuantumRange * 0.25
|
||||||
BIT_SHIFT = Math.log2(Magick::QuantumRange + 1) - 4
|
BIT_SHIFT = Math.log2(Magick::QuantumRange + 1) - 4
|
||||||
|
|
||||||
class PixelRow
|
class PixelRow
|
||||||
include Enumerable
|
|
||||||
|
|
||||||
def initialize
|
def initialize
|
||||||
@row = []
|
@row = []
|
||||||
end
|
end
|
||||||
|
@ -83,284 +61,10 @@ class PixelRow
|
||||||
@row[x] = pixel
|
@row[x] = pixel
|
||||||
end
|
end
|
||||||
|
|
||||||
def each(&block)
|
|
||||||
@row.each(&block)
|
|
||||||
end
|
|
||||||
|
|
||||||
def prioritized_colors
|
|
||||||
colors_with_usage.sort_by(&:last).reverse.map(&:first)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
|
||||||
|
|
||||||
def colors_with_usage
|
def colors_with_usage
|
||||||
last = nil
|
|
||||||
count = 0
|
|
||||||
|
|
||||||
@row.find_all(&:color?).each_with_object({}) do |pixel, obj|
|
@row.find_all(&:color?).each_with_object({}) do |pixel, obj|
|
||||||
if last != pixel.color
|
|
||||||
last = pixel.color
|
|
||||||
count = 1
|
|
||||||
end
|
|
||||||
|
|
||||||
count += count
|
|
||||||
|
|
||||||
obj[pixel.color] ||= 0
|
obj[pixel.color] ||= 0
|
||||||
obj[pixel.color] += count
|
obj[pixel.color] += 1
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class RowColors
|
|
||||||
def initialize; end
|
|
||||||
end
|
|
||||||
|
|
||||||
class RowColorCalculator
|
|
||||||
MAX_BITPLANE_COLORS = 8
|
|
||||||
MAX_SPRITE_COLORS = 8
|
|
||||||
|
|
||||||
def self.calculate(row:)
|
|
||||||
prioritized_colors = row.prioritized_colors
|
|
||||||
|
|
||||||
bitplane_pixels_by_color = {
|
|
||||||
Color::TRANSPARENT => 0,
|
|
||||||
Color::BLACK => 1,
|
|
||||||
Color::WHITE => 2
|
|
||||||
}
|
|
||||||
|
|
||||||
sprite_pixels_by_color = {}
|
|
||||||
|
|
||||||
colors_by_bitplane_pixel = {}
|
|
||||||
colors_by_sprite_pixel = {}
|
|
||||||
|
|
||||||
prioritized_colors.each do |color|
|
|
||||||
next if bitplane_pixels_by_color.keys.include?(color)
|
|
||||||
|
|
||||||
closest_matches = bitplane_pixels_by_color.keys.reject(&:transparent?).map do |bp_color|
|
|
||||||
[(bp_color.for_diff - color.for_diff).abs, bp_color]
|
|
||||||
end.compact
|
|
||||||
|
|
||||||
closest_match = closest_matches.min_by(&:first)
|
|
||||||
|
|
||||||
if bitplane_pixels_by_color.values.max == MAX_BITPLANE_COLORS - 1
|
|
||||||
bitplane_pixels_by_color[color] = bitplane_pixels_by_color[closest_match.last]
|
|
||||||
|
|
||||||
max_sprite_value = sprite_pixels_by_color.values.max
|
|
||||||
|
|
||||||
if !max_sprite_value || max_sprite_value < MAX_SPRITE_COLORS - 1
|
|
||||||
new_pixel_index = colors_by_sprite_pixel.count
|
|
||||||
sprite_pixels_by_color[color] = new_pixel_index
|
|
||||||
colors_by_sprite_pixel[new_pixel_index] = color
|
|
||||||
end
|
|
||||||
else
|
|
||||||
new_pixel_index = colors_by_bitplane_pixel.count + 3
|
|
||||||
bitplane_pixels_by_color[color] = new_pixel_index
|
|
||||||
colors_by_bitplane_pixel[new_pixel_index] = color
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
{
|
|
||||||
bitplane_pixels_by_color:,
|
|
||||||
sprite_pixels_by_color:,
|
|
||||||
colors_by_bitplane_pixel:,
|
|
||||||
colors_by_sprite_pixel:
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class RowMaskBitplaneCalculator
|
|
||||||
def self.calculate(row:)
|
|
||||||
bits = row.map { |p| p.is_a?(MaskPixel) ? 0 : 1 }
|
|
||||||
|
|
||||||
bits.each_slice(8).map do |pixels|
|
|
||||||
byte = 0
|
|
||||||
|
|
||||||
pixels.each_with_index do |pixel, index|
|
|
||||||
bit = 7 - index
|
|
||||||
|
|
||||||
byte |= (pixel << bit)
|
|
||||||
end
|
|
||||||
|
|
||||||
byte
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class RowBitplaneCalculator
|
|
||||||
def self.calculate(row:, bitplane_pixels_by_color:)
|
|
||||||
output_pixels = row.map do |pixel|
|
|
||||||
next 0 if pixel.is_a?(MaskPixel)
|
|
||||||
|
|
||||||
bitplane_pixels_by_color[pixel.color] || 0
|
|
||||||
end
|
|
||||||
|
|
||||||
bitplanes = [[], [], []]
|
|
||||||
|
|
||||||
output_pixels.each_slice(8) do |pixels|
|
|
||||||
bits = [0] * 3
|
|
||||||
|
|
||||||
pixels.each_with_index do |pixel, index|
|
|
||||||
bit = 7 - index
|
|
||||||
|
|
||||||
3.times do |i|
|
|
||||||
bits[i] |= (((pixel >> i) & 1) << bit)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
3.times do |i|
|
|
||||||
bitplanes[i] << bits[i]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
bitplanes
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class Sprite
|
|
||||||
attr_reader :x, :y, :color, :pixels
|
|
||||||
|
|
||||||
# @!attribute color
|
|
||||||
# @return Color
|
|
||||||
|
|
||||||
def initialize(x:, y:, color:)
|
|
||||||
@x = x
|
|
||||||
@y = y
|
|
||||||
@color = color
|
|
||||||
@pixels = [0] * 16
|
|
||||||
end
|
|
||||||
|
|
||||||
def add_pixel(x:, index:)
|
|
||||||
return if x - @x >= 16
|
|
||||||
|
|
||||||
@pixels[x - @x] = index
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class RowSpriteCalculator
|
|
||||||
def self.calculate(y:, row:, sprite_pixels_by_color:)
|
|
||||||
sprites_by_color = {}
|
|
||||||
|
|
||||||
row.each_with_index.map do |pixel, x|
|
|
||||||
next if pixel.is_a?(MaskPixel)
|
|
||||||
|
|
||||||
sprite_pixel = sprite_pixels_by_color[pixel.color]
|
|
||||||
next unless sprite_pixel
|
|
||||||
|
|
||||||
sprite = sprites_by_color[pixel.color]
|
|
||||||
unless sprite
|
|
||||||
sprite = Sprite.new(y:, x:, color: pixel.color)
|
|
||||||
sprites_by_color[pixel.color] = sprite
|
|
||||||
end
|
|
||||||
|
|
||||||
sprite.add_pixel(x:, index: 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
sprites_by_color
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
module Amiga
|
|
||||||
class Util
|
|
||||||
TOTAL_HEIGHT = 256
|
|
||||||
TOP_OFFSET = 44
|
|
||||||
LEFT_OFFSET = 128 + 64
|
|
||||||
|
|
||||||
SPRITE_HEIGHT = TOTAL_HEIGHT + TOP_OFFSET
|
|
||||||
|
|
||||||
def self.color_to_amiga_word(color:)
|
|
||||||
(color.blue + (color.green << 4) + (color.red << 8))
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.sprposctl(x:, y:)
|
|
||||||
y += TOP_OFFSET
|
|
||||||
x += LEFT_OFFSET
|
|
||||||
|
|
||||||
sprpos = ((y & 0xff) << 8) +
|
|
||||||
((x & 0x1fe) >> 1)
|
|
||||||
sprctl = (((y + TOTAL_HEIGHT) & 0xff) << 8) +
|
|
||||||
((y & 0x100) >> 6) +
|
|
||||||
(((y + TOTAL_HEIGHT) & 0x100) >> 7) +
|
|
||||||
(x & 1)
|
|
||||||
|
|
||||||
{ sprpos:, sprctl: }
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class BitplaneCopperlistFactory
|
|
||||||
def self.build(colors_by_bitplane_pixel:)
|
|
||||||
5.times.map do |color_index|
|
|
||||||
color = colors_by_bitplane_pixel[color_index + 3] || Color::BLACK
|
|
||||||
|
|
||||||
Amiga::Util.color_to_amiga_word(color:)
|
|
||||||
end.pack('n*')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class BitplaneDataFactory
|
|
||||||
def self.build(bitplanes:)
|
|
||||||
bitplanes.map do |data|
|
|
||||||
data.pack('C*')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class BitplaneMaskDataFactory
|
|
||||||
def self.build(bitplane:)
|
|
||||||
bitplane.pack('C*')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class SpriteCopperlistFactory
|
|
||||||
# @param sprites [Array<Sprite>]
|
|
||||||
def self.build(sprites:, y_offset:)
|
|
||||||
obj = []
|
|
||||||
|
|
||||||
8.times do |sprite_index|
|
|
||||||
color = 0
|
|
||||||
sprpos = 0
|
|
||||||
sprctl = 0
|
|
||||||
|
|
||||||
sprite = sprites[sprite_index]
|
|
||||||
if sprite
|
|
||||||
result = Amiga::Util.sprposctl(x: sprite.x, y: sprite.y + y_offset)
|
|
||||||
|
|
||||||
color = Amiga::Util.color_to_amiga_word(color: sprite.color)
|
|
||||||
sprpos = result[:sprpos]
|
|
||||||
sprctl = result[:sprctl]
|
|
||||||
end
|
|
||||||
|
|
||||||
obj << color
|
|
||||||
obj << sprpos
|
|
||||||
obj << sprctl
|
|
||||||
end
|
|
||||||
|
|
||||||
obj.pack('n*')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class SpriteDataFactory
|
|
||||||
def self.build(sprites:)
|
|
||||||
sprite_out = [''] * 8
|
|
||||||
|
|
||||||
sprites_with_bitplane = sprites.zip([0, 1] * 4)
|
|
||||||
|
|
||||||
8.times do |sprite_index|
|
|
||||||
sprite, bitplane = sprites_with_bitplane[sprite_index]
|
|
||||||
|
|
||||||
2.times do |current_bitplane|
|
|
||||||
result = 0
|
|
||||||
|
|
||||||
if bitplane == current_bitplane
|
|
||||||
sprite.pixels.each_with_index do |pixel, bit|
|
|
||||||
result |= (pixel << (15 - bit))
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
sprite_out[sprite_index] += [result].pack('n*')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
sprite_out
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -383,53 +87,4 @@ image.each_pixel do |px, x, y|
|
||||||
rows[y].add(pixel:, x:)
|
rows[y].add(pixel:, x:)
|
||||||
end
|
end
|
||||||
|
|
||||||
copper_colors = ''
|
pp rows[50].colors_with_usage
|
||||||
topaz_bitplanes = [''] * 3
|
|
||||||
sprite_copperlist = ''
|
|
||||||
sprite_data = [''] * 8
|
|
||||||
|
|
||||||
mask_bitplane = ''
|
|
||||||
|
|
||||||
8.times do |i|
|
|
||||||
result = Amiga::Util.sprposctl(x: 319, y: 0)
|
|
||||||
sprite_data[i] = [result[:sprpos], result[:sprctl]].pack('n*')
|
|
||||||
end
|
|
||||||
|
|
||||||
rows.each_with_index do |row, y_offset|
|
|
||||||
result = RowColorCalculator.calculate(row:)
|
|
||||||
|
|
||||||
bitplane_pixels_by_color = result[:bitplane_pixels_by_color]
|
|
||||||
sprite_pixels_by_color = result[:sprite_pixels_by_color]
|
|
||||||
colors_by_bitplane_pixel = result[:colors_by_bitplane_pixel]
|
|
||||||
|
|
||||||
bitplanes = RowBitplaneCalculator.calculate(row:, bitplane_pixels_by_color:)
|
|
||||||
sprites = RowSpriteCalculator.calculate(y: y_offset, row:, sprite_pixels_by_color:).values
|
|
||||||
|
|
||||||
mask = RowMaskBitplaneCalculator.calculate(row:)
|
|
||||||
|
|
||||||
mask_bitplane += Amiga::BitplaneMaskDataFactory.build(bitplane: mask)
|
|
||||||
|
|
||||||
copper_colors += Amiga::BitplaneCopperlistFactory.build(colors_by_bitplane_pixel:)
|
|
||||||
raw_bitplanes = Amiga::BitplaneDataFactory.build(bitplanes:)
|
|
||||||
|
|
||||||
sprite_copperlist += Amiga::SpriteCopperlistFactory.build(sprites:, y_offset:)
|
|
||||||
raw_sprite_data = Amiga::SpriteDataFactory.build(sprites:)
|
|
||||||
|
|
||||||
raw_bitplanes.each_with_index do |raw, index|
|
|
||||||
topaz_bitplanes[index] += raw
|
|
||||||
end
|
|
||||||
|
|
||||||
raw_sprite_data.each_with_index do |raw, index|
|
|
||||||
sprite_data[index] += raw
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
8.times do |i|
|
|
||||||
sprite_data[i] += [0, 0].pack('n*')
|
|
||||||
end
|
|
||||||
|
|
||||||
File.open('copper-colors', 'wb') { |fh| fh.print copper_colors }
|
|
||||||
File.open('topaz-bitplane', 'wb') { |fh| fh.print topaz_bitplanes.join('') }
|
|
||||||
File.open('mask-bitplane', 'wb') { |fh| fh.print mask_bitplane }
|
|
||||||
File.open('sprite-copperlist', 'wb') { |fh| fh.print sprite_copperlist }
|
|
||||||
File.open('sprite-data', 'wb') { |fh| fh.print sprite_data.join('') }
|
|
||||||
|
|
26
images.s
26
images.s
|
@ -1,30 +1,4 @@
|
||||||
XDEF _coolbun
|
XDEF _coolbun
|
||||||
XDEF _TopazBitplanes
|
|
||||||
XDEF _CopperColors
|
|
||||||
XDEF _SpriteCopperlist
|
|
||||||
XDEF _SpriteData
|
|
||||||
XDEF _MaskBitplane
|
|
||||||
|
|
||||||
SECTION Topaz,Data_C
|
|
||||||
_coolbun:
|
_coolbun:
|
||||||
INCBIN "images/bun small.raw"
|
INCBIN "images/bun small.raw"
|
||||||
|
|
||||||
CNOP 0,4
|
|
||||||
_TopazBitplanes:
|
|
||||||
INCBIN "topaz-bitplane"
|
|
||||||
|
|
||||||
CNOP 0,4
|
|
||||||
_CopperColors:
|
|
||||||
INCBIN "copper-colors"
|
|
||||||
|
|
||||||
CNOP 0,4
|
|
||||||
_SpriteCopperlist:
|
|
||||||
INCBIN "sprite-copperlist"
|
|
||||||
|
|
||||||
CNOP 0,4
|
|
||||||
_SpriteData:
|
|
||||||
INCBIN "sprite-data"
|
|
||||||
|
|
||||||
CNOP 0,4
|
|
||||||
_MaskBitplane:
|
|
||||||
INCBIN "mask-bitplane"
|
|
||||||
|
|
Binary file not shown.
|
@ -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);
|
|
||||||
}
|
|
539
main.c
539
main.c
|
@ -1,387 +1,260 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <clib/alib_protos.h>
|
|
||||||
#include <clib/dos_protos.h>
|
|
||||||
#include <clib/exec_protos.h>
|
#include <clib/exec_protos.h>
|
||||||
#include <clib/graphics_protos.h>
|
#include <clib/graphics_protos.h>
|
||||||
|
|
||||||
#include <exec/exec.h>
|
#include <exec/exec.h>
|
||||||
#include <exec/types.h>
|
|
||||||
#include <exec/memory.h>
|
|
||||||
#include <exec/interrupts.h>
|
|
||||||
|
|
||||||
#include <devices/input.h>
|
|
||||||
|
|
||||||
#include <hardware/custom.h>
|
#include <hardware/custom.h>
|
||||||
#include <hardware/dmabits.h>
|
#include <hardware/dmabits.h>
|
||||||
#include <hardware/cia.h>
|
|
||||||
|
|
||||||
#include <intuition/intuition.h>
|
|
||||||
|
|
||||||
#include <graphics/gfx.h>
|
#include <graphics/gfx.h>
|
||||||
|
|
||||||
#include "system/blitter.h"
|
#include "system/blitter.h"
|
||||||
#include "system/copper.h"
|
#include "system/copper.h"
|
||||||
#include "system/system.h"
|
#include "system/system.h"
|
||||||
#include "system/sprite.h"
|
|
||||||
|
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include "bun.h"
|
#include "bun.h"
|
||||||
|
|
||||||
/**
|
|
||||||
* This barely gets 50fps on an 020 but I'm leaving it for now.
|
|
||||||
* The demo is definitely CPU bound.
|
|
||||||
*
|
|
||||||
* Potential improvements:
|
|
||||||
*
|
|
||||||
* [ ] Precalculate even more of bun.c. This may get 50fps on an A500 if I do this.
|
|
||||||
* It would require more significant caching of as much stuff as possible.
|
|
||||||
* The A500 is spending entirely too much time on CPU tasks.
|
|
||||||
* [ ] Topaz re-rendering is limited to squares or rows that changed in the last frame.
|
|
||||||
* I tried this once but I need a more precise way of redrawing those areas.
|
|
||||||
* [ ] Cool bun clears and re-renders happen in the same pass.
|
|
||||||
* This would likely mean extending the cool bun art to have a blank word on the left,
|
|
||||||
* and enough blank rows above and below to cover clearing areas above and below.
|
|
||||||
*/
|
|
||||||
|
|
||||||
extern struct Custom far custom;
|
extern struct Custom far custom;
|
||||||
extern struct CIA far ciaa;
|
|
||||||
|
|
||||||
// change to 0 to not render sprites
|
// this should be large enough to hold one bitplane of the largest object
|
||||||
#define RENDER_SPRITES (1)
|
// you are blitting, plus one additional word on each side
|
||||||
|
#define SCRATCH_AREA_WIDTH_BYTES (8)
|
||||||
|
#define SCRATCH_AREA_HEIGHT_ROWS (34)
|
||||||
|
#define SCRATCH_AREA_MEMORY_SIZE (SCRATCH_AREA_WIDTH_BYTES * SCRATCH_AREA_HEIGHT_ROWS)
|
||||||
|
|
||||||
struct ScreenDefinition screenDefinition;
|
volatile short *dbg = (volatile short *)0x100;
|
||||||
struct ActiveScreenBufferDetails activeScreenBufferDetails;
|
|
||||||
|
|
||||||
/**
|
unsigned char *scratchArea;
|
||||||
* The locations within the copperlist data where the bitplanes are referenced.
|
struct ScreenSetup screenSetup;
|
||||||
* We change these areas of memory directly to implement double buffering.
|
struct CurrentScreen currentScreen;
|
||||||
* Addresses are to the high, then low, word of the plane memory address in the copperlist.
|
|
||||||
*
|
|
||||||
* @see addDisplayToCopperlist
|
|
||||||
*/
|
|
||||||
void *copperlistBitplanePointers[8][2];
|
void *copperlistBitplanePointers[8][2];
|
||||||
|
void *copperlistSpritePointers[8];
|
||||||
|
|
||||||
|
#define offsetof(s, m) &((struct s *)0)->m
|
||||||
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
|
uint16_t custom_color = (uint16_t)offsetof(Custom, color);
|
||||||
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
|
uint16_t custom_sprite = (uint16_t)offsetof(Custom, sprpt);
|
||||||
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
|
uint16_t custom_sprite_control = (uint16_t)offsetof(Custom, spr);
|
||||||
|
|
||||||
extern uint8_t chip TopazBitplanes[];
|
uint16_t chip spriteData[200];
|
||||||
extern uint16_t chip CopperColors[];
|
uint16_t chip spriteData2[20];
|
||||||
extern uint16_t chip SpriteCopperlist[];
|
|
||||||
extern uint16_t chip SpriteData[];
|
|
||||||
extern uint8_t chip MaskBitplane[];
|
|
||||||
|
|
||||||
#define TOPAZ_WIDTH_PIXELS (160)
|
uint16_t spritePositionsEachLine[256][2];
|
||||||
#define TOPAZ_WIDTH_BYTES (TOPAZ_WIDTH_PIXELS / 8)
|
|
||||||
#define TOPAZ_WIDTH_WORDS (TOPAZ_WIDTH_PIXELS / 16)
|
|
||||||
|
|
||||||
void renderTopaz(void) {
|
void calculageSpritePositionsEachLine() {
|
||||||
int plane;
|
|
||||||
|
|
||||||
uint16_t bltcmod;
|
|
||||||
uint8_t *bltbpt;
|
|
||||||
|
|
||||||
bltcmod = screenDefinition.byteWidth - TOPAZ_WIDTH_BYTES;
|
|
||||||
bltbpt = TopazBitplanes;
|
|
||||||
|
|
||||||
for (plane = 0; plane < 3; ++plane) {
|
|
||||||
custom.bltcon0 = BLTCON0(0xca, 1, 1, 1, 1, 0);
|
|
||||||
custom.bltcon1 = 0;
|
|
||||||
custom.bltafwm = 0xffff;
|
|
||||||
custom.bltalwm = 0xffff;
|
|
||||||
custom.bltapt = MaskBitplane;
|
|
||||||
custom.bltbpt = bltbpt;
|
|
||||||
custom.bltcpt = activeScreenBufferDetails.planes[plane] + 8;
|
|
||||||
custom.bltdpt = activeScreenBufferDetails.planes[plane] + 8;
|
|
||||||
custom.bltamod = 0;
|
|
||||||
custom.bltbmod = 0;
|
|
||||||
custom.bltcmod = bltcmod;
|
|
||||||
custom.bltdmod = bltcmod;
|
|
||||||
custom.bltsize = BLTSIZE(TOPAZ_WIDTH_WORDS, 256);
|
|
||||||
|
|
||||||
bltbpt += TOPAZ_WIDTH_BYTES * 256;
|
|
||||||
|
|
||||||
WaitBlit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define MOSTLY_TOPAZ_TOP_BOTTOM_CROP (30)
|
|
||||||
|
|
||||||
void renderMostlyTopaz(void) {
|
|
||||||
int plane;
|
|
||||||
|
|
||||||
uint16_t bltcmod;
|
|
||||||
uint8_t *bltbpt;
|
|
||||||
|
|
||||||
bltcmod = screenDefinition.byteWidth - TOPAZ_WIDTH_BYTES;
|
|
||||||
bltbpt = TopazBitplanes;
|
|
||||||
|
|
||||||
for (plane = 0; plane < 2; ++plane) {
|
|
||||||
custom.bltcon0 = BLTCON0(0xca, 1, 1, 1, 1, 0);
|
|
||||||
custom.bltcon1 = 0;
|
|
||||||
custom.bltafwm = 0xffff;
|
|
||||||
custom.bltalwm = 0xffff;
|
|
||||||
custom.bltapt = MaskBitplane + (MOSTLY_TOPAZ_TOP_BOTTOM_CROP * TOPAZ_WIDTH_BYTES);
|
|
||||||
custom.bltbpt = bltbpt + (MOSTLY_TOPAZ_TOP_BOTTOM_CROP * TOPAZ_WIDTH_BYTES);
|
|
||||||
custom.bltcpt = MOSTLY_TOPAZ_TOP_BOTTOM_CROP * screenDefinition.byteWidth + activeScreenBufferDetails.planes[plane] + 8;
|
|
||||||
custom.bltdpt = MOSTLY_TOPAZ_TOP_BOTTOM_CROP * screenDefinition.byteWidth + activeScreenBufferDetails.planes[plane] + 8;
|
|
||||||
custom.bltamod = 0;
|
|
||||||
custom.bltbmod = 0;
|
|
||||||
custom.bltcmod = bltcmod;
|
|
||||||
custom.bltdmod = bltcmod;
|
|
||||||
custom.bltsize = BLTSIZE(TOPAZ_WIDTH_WORDS, 256 - MOSTLY_TOPAZ_TOP_BOTTOM_CROP * 2);
|
|
||||||
|
|
||||||
bltbpt += TOPAZ_WIDTH_BYTES * 256;
|
|
||||||
|
|
||||||
WaitBlit();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define COPPERLIST_SIZE (10000)
|
|
||||||
|
|
||||||
uint16_t *copperlist;
|
|
||||||
|
|
||||||
void buildCopperlist(void) {
|
|
||||||
uint32_t spriteDataPointer;
|
|
||||||
uint16_t *currentCopperlist,
|
|
||||||
*currentCopperColors,
|
|
||||||
*currentSpriteCopperlist;
|
|
||||||
int i, j, y;
|
|
||||||
uint16_t spriteSetupRegisters[3];
|
|
||||||
|
|
||||||
copperlist = prepareNewCopperlist(COPPERLIST_SIZE);
|
|
||||||
|
|
||||||
currentCopperlist = addDisplayToCopperlist(
|
|
||||||
copperlist,
|
|
||||||
&screenDefinition,
|
|
||||||
&activeScreenBufferDetails,
|
|
||||||
&copperlistBitplanePointers
|
|
||||||
);
|
|
||||||
|
|
||||||
currentCopperColors = CopperColors;
|
|
||||||
currentSpriteCopperlist = SpriteCopperlist;
|
|
||||||
|
|
||||||
COPPERLIST_MOVE(currentCopperlist, custom_color, 0x3a6);
|
|
||||||
COPPERLIST_MOVE(currentCopperlist, custom_color + 2, 0x000);
|
|
||||||
COPPERLIST_MOVE(currentCopperlist, custom_color + 4, 0xfff);
|
|
||||||
|
|
||||||
if (RENDER_SPRITES) {
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
spriteDataPointer = (uint32_t)&SpriteData;
|
|
||||||
spriteDataPointer += ((256 + 2) * 4) * i;
|
|
||||||
|
|
||||||
COPPERLIST_MOVE_POINTER(
|
|
||||||
currentCopperlist,
|
|
||||||
custom_sprite + i * 4,
|
|
||||||
spriteDataPointer
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (y = 0; y < 256; ++y) {
|
|
||||||
if (RENDER_SPRITES) {
|
|
||||||
for (i = 0; i < 8; ++i) {
|
|
||||||
spriteSetupRegisters[0] = custom_color + 32 + (
|
|
||||||
// sprite color group
|
|
||||||
(i / 2) * 4 +
|
|
||||||
// 0 is transparent
|
|
||||||
1 +
|
|
||||||
i % 2
|
|
||||||
) * 2;
|
|
||||||
spriteSetupRegisters[1] = custom_sprite_control + i * 8;
|
|
||||||
spriteSetupRegisters[2] = custom_sprite_control + i * 8 + 2;
|
|
||||||
|
|
||||||
for (j = 0; j < 3; ++j) {
|
|
||||||
COPPERLIST_MOVE(
|
|
||||||
currentCopperlist,
|
|
||||||
spriteSetupRegisters[j],
|
|
||||||
*(currentSpriteCopperlist++)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//printf("Skipping render\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 3; i < 8; ++i) {
|
|
||||||
COPPERLIST_MOVE(
|
|
||||||
currentCopperlist,
|
|
||||||
custom_color + (i * 2),
|
|
||||||
*(currentCopperColors++)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
COPPERLIST_WAIT(
|
|
||||||
currentCopperlist,
|
|
||||||
(31 + (256 / 4)),
|
|
||||||
(44 + y),
|
|
||||||
0xFFFE
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
endCopperlist(currentCopperlist);
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct MsgPort *keyboardMessagePort = NULL;
|
|
||||||
static struct IOStdReq *keyboardIO = NULL;
|
|
||||||
static struct Interrupt keyboardInterrupt;
|
|
||||||
|
|
||||||
extern far ULONG keyboardPressed;
|
|
||||||
|
|
||||||
extern struct InputEvent * __asm KeyboardHandler(
|
|
||||||
register __a0 struct InputEvent *input,
|
|
||||||
register __a1 APTR id
|
|
||||||
);
|
|
||||||
|
|
||||||
void setupKeyboard(void) {
|
|
||||||
if (keyboardMessagePort = CreatePort(NULL, NULL)) {
|
|
||||||
if (keyboardIO = (struct IOStdReq *)CreateExtIO(
|
|
||||||
keyboardMessagePort,
|
|
||||||
sizeof(struct IOStdReq)
|
|
||||||
)) {
|
|
||||||
// OpenDevice returns 0 if successful
|
|
||||||
if (!OpenDevice(
|
|
||||||
"input.device",
|
|
||||||
0,
|
|
||||||
(struct IORequest *)keyboardIO,
|
|
||||||
0
|
|
||||||
)) {
|
|
||||||
keyboardInterrupt.is_Node.ln_Type = NT_INTERRUPT;
|
|
||||||
keyboardInterrupt.is_Node.ln_Pri = 100;
|
|
||||||
keyboardInterrupt.is_Node.ln_Name = (STRPTR)"cool bun";
|
|
||||||
keyboardInterrupt.is_Code = (void (*)())&KeyboardHandler;
|
|
||||||
|
|
||||||
keyboardIO->io_Data = (void *)&keyboardInterrupt;
|
|
||||||
keyboardIO->io_Command = IND_ADDHANDLER;
|
|
||||||
|
|
||||||
DoIO((struct IORequest *)keyboardIO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void teardownKeyboard(void) {
|
|
||||||
if (keyboardIO) {
|
|
||||||
keyboardIO->io_Data = (void *)&keyboardInterrupt;
|
|
||||||
keyboardIO->io_Command = IND_REMHANDLER;
|
|
||||||
DoIO((struct IORequest *)keyboardIO);
|
|
||||||
CloseDevice((struct IORequest *)keyboardIO);
|
|
||||||
DeleteIORequest((struct IORequest *)keyboardIO);
|
|
||||||
keyboardIO = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyboardMessagePort) {
|
|
||||||
DeleteMsgPort(keyboardMessagePort);
|
|
||||||
keyboardMessagePort = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(void) {
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
struct BunRenderer bunRenderer;
|
for (i = 0; i < 255; ++i) {
|
||||||
uint16_t redrawRanges[BUN_COUNT][4];
|
|
||||||
|
|
||||||
printf("\nCool bun blitter, copper, and sprite demo by John Bintz\n");
|
|
||||||
printf("\n");
|
|
||||||
printf("This is my first real go at writing graphics code for the Amiga.\n");
|
|
||||||
printf("It's a combination of C (SAS/C) and Assembler (DevPac), with a Ruby\n");
|
|
||||||
printf("script to do some image processing. The screen only uses three\n");
|
|
||||||
printf("bitplanes -- one color is the background, two colors are the flying\n");
|
|
||||||
printf("cool bun logo white and black, and the remaining 5 colors are used\n");
|
|
||||||
printf("by the Topaz smiling art. The Ruby script will process the PNG file\n");
|
|
||||||
printf("and figure out the best 5 colors (plus b&w) for that line of the\n");
|
|
||||||
printf("image, setting the colors via copperlist for that line.\n");
|
|
||||||
printf("It also builds the clipping mask for the blitter.\n\n");
|
|
||||||
|
|
||||||
printf("And, I'm also using sprites to add more colors to the Topaz art.\n");
|
|
||||||
printf("The Ruby script will figure out what small areas of each line weren't\n");
|
|
||||||
printf("covered by the bitplane colors and use the 8 available sprites,\n");
|
|
||||||
printf("changing the colors on each line via copper, to fill in the gaps.\n");
|
|
||||||
printf("Cool buns are animated via blitter rather than sprites, but I\n");
|
|
||||||
printf("managed to get it to run at a decent speed regardless.\n");
|
|
||||||
|
|
||||||
printf("\nEnjoy, and thanks for watching!\n");
|
|
||||||
printf("John (theindustriousrabbit.com)\n\n");
|
|
||||||
|
|
||||||
allocateDoubleBufferedScreenMemory(
|
|
||||||
&screenDefinition,
|
|
||||||
&activeScreenBufferDetails,
|
|
||||||
SCREEN_WIDTH,
|
|
||||||
SCREEN_HEIGHT,
|
|
||||||
3
|
|
||||||
);
|
|
||||||
|
|
||||||
setupBunRenderer(
|
|
||||||
&bunRenderer,
|
|
||||||
&screenDefinition,
|
|
||||||
&activeScreenBufferDetails
|
|
||||||
);
|
|
||||||
|
|
||||||
buildCopperlist();
|
|
||||||
|
|
||||||
/*
|
|
||||||
copperlist debugging
|
|
||||||
for (i = 0; i < 20; ++i) {
|
|
||||||
printf(
|
|
||||||
"%x %x %x %x\n",
|
|
||||||
*(copperlist + (i * 4)),
|
|
||||||
*(copperlist + (i * 4) + 1),
|
|
||||||
*(copperlist + (i * 4) + 2),
|
|
||||||
*(copperlist + (i * 4) + 3)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SPRPOS(x, y) (((y & 0xff) << 8) + ((x & 0x1fe) >> 1))
|
||||||
|
#define SPRCTL(x, y, height) ( \
|
||||||
|
((height & 0xff) << 8) + \
|
||||||
|
((y & 0x100) >> 6) + \
|
||||||
|
((height & 0x100) >> 7) + \
|
||||||
|
(x & 1) \
|
||||||
|
)
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
uint16_t *copperlist, *currentCopperlist, result;
|
||||||
|
int i, x, y, height, plane;
|
||||||
|
|
||||||
|
struct BunRenderer bunRenderer;
|
||||||
|
|
||||||
|
color_t colors[8];
|
||||||
|
|
||||||
|
colors[0] = 0x09b8;
|
||||||
|
colors[1] = 0x0000;
|
||||||
|
colors[2] = 0x0fff;
|
||||||
|
colors[3] = 0x000f;
|
||||||
|
|
||||||
|
printf("%p\n", &spriteData);
|
||||||
|
printf("setting up, i haven't crashed...yet.\n");
|
||||||
|
|
||||||
|
x = 150;
|
||||||
|
y = 47;
|
||||||
|
height = y + 98;
|
||||||
|
|
||||||
|
printf("%d, %d, %d\n", x, y, height);
|
||||||
|
|
||||||
|
spriteData[0] = SPRPOS(x, y);
|
||||||
|
spriteData[1] = SPRCTL(x, y, height);
|
||||||
|
|
||||||
|
printf("%0x %0x\n", spriteData[0], spriteData[1]);
|
||||||
|
|
||||||
|
for (i = 2; i < 198; i += 2) {
|
||||||
|
spriteData[i] = 0x0f + i % 16;
|
||||||
|
spriteData[i + 1] = 0xf0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
spriteData[198] = 0x0000;
|
||||||
|
spriteData[199] = 0x0000;
|
||||||
|
|
||||||
|
spriteData2[0] = SPRPOS(220, 70);
|
||||||
|
spriteData2[1] = SPRCTL(220, 70, 72);
|
||||||
|
/*
|
||||||
|
spriteData2[2] = 0x0345;
|
||||||
|
spriteData2[3] = 0x5678;
|
||||||
|
spriteData2[4] = 0x9abc;
|
||||||
|
spriteData2[5] = 0xdef0;
|
||||||
*/
|
*/
|
||||||
setupKeyboard();
|
spriteData2[2] = 0xffff;
|
||||||
|
spriteData2[3] = 0xffff;
|
||||||
|
spriteData2[4] = 0xffff;
|
||||||
|
spriteData2[5] = 0xffff;
|
||||||
|
spriteData2[6] = SPRPOS(230, 150);
|
||||||
|
spriteData2[7] = SPRCTL(230, 150, 151);
|
||||||
|
spriteData2[8] = 0xffff;
|
||||||
|
spriteData2[9] = 0xffff;
|
||||||
|
spriteData2[10] = 0;
|
||||||
|
spriteData2[11] = 0;
|
||||||
|
|
||||||
|
setupScreen(&screenSetup, SCREEN_WIDTH, SCREEN_HEIGHT, 3);
|
||||||
|
setupInitialCurrentScreen(&screenSetup, ¤tScreen);
|
||||||
|
|
||||||
|
//setupBunRenderer(&bunRenderer, &screenSetup, ¤tScreen);
|
||||||
|
|
||||||
|
// blitter copy the first bitplane row down to the second
|
||||||
|
|
||||||
|
copperlist = prepareNewCopperlist();
|
||||||
|
|
||||||
takeOverSystem();
|
takeOverSystem();
|
||||||
|
|
||||||
setCopperlist(copperlist);
|
setCopperlist(copperlist);
|
||||||
setUpDisplay((uint32_t)screenDefinition.bitplanes);
|
setUpDisplay((uint32_t)screenSetup.bitplanes);
|
||||||
|
|
||||||
renderTopaz();
|
currentCopperlist = addDisplayToCopperlist(
|
||||||
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
|
copperlist,
|
||||||
renderTopaz();
|
&screenSetup,
|
||||||
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
|
¤tScreen,
|
||||||
|
&copperlistBitplanePointers
|
||||||
updateDisplayInCopperList(
|
|
||||||
&screenDefinition,
|
|
||||||
&activeScreenBufferDetails,
|
|
||||||
copperlistBitplanePointers
|
|
||||||
);
|
);
|
||||||
|
|
||||||
i = 0;
|
currentCopperlist = setUpEmptySpritesInCopperlist(currentCopperlist);
|
||||||
|
|
||||||
while (1) {
|
*(currentCopperlist++) = custom_color;
|
||||||
WaitTOF();
|
*(currentCopperlist++) = 0x000;
|
||||||
|
|
||||||
swapCurrentScreenBuffer(&screenDefinition, &activeScreenBufferDetails);
|
*(currentCopperlist++) = custom_color + 2;
|
||||||
|
*(currentCopperlist++) = 0x000;
|
||||||
|
|
||||||
clearCurrentBuns(&bunRenderer);
|
*(currentCopperlist++) = custom_color + 4;
|
||||||
renderBunFrame(i, &bunRenderer);
|
*(currentCopperlist++) = 0xfff;
|
||||||
renderMostlyTopaz();
|
|
||||||
|
|
||||||
updateDisplayInCopperList(
|
*(currentCopperlist++) = custom_color + 6;
|
||||||
&screenDefinition,
|
*(currentCopperlist++) = 0x00F;
|
||||||
&activeScreenBufferDetails,
|
|
||||||
copperlistBitplanePointers
|
|
||||||
);
|
|
||||||
|
|
||||||
if (keyboardPressed) break;
|
// sprites
|
||||||
if ((ciaa.ciapra >> 6) != 3) break;
|
*(currentCopperlist++) = custom_color + 34;
|
||||||
|
*(currentCopperlist++) = 0xF0F;
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_color + 36;
|
||||||
|
*(currentCopperlist++) = 0xFF0;
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_color + 38;
|
||||||
|
*(currentCopperlist++) = 0x00F;
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite;
|
||||||
|
*(currentCopperlist++) = ((uint32_t)&spriteData2 >> 16);
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite + 2;
|
||||||
|
*(currentCopperlist++) = ((uint32_t)&spriteData2 & 0xffff);
|
||||||
|
|
||||||
|
for (y = 0; y < 256; ++y) {
|
||||||
|
/*
|
||||||
|
if (y > 100 && y < 135) {
|
||||||
|
*(currentCopperlist++) = custom_sprite_control;
|
||||||
|
*(currentCopperlist++) = SPRPOS(60 + y, y);
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite_control + 2;
|
||||||
|
*(currentCopperlist++) = SPRCTL(60 + y, y, 0);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
*(currentCopperlist++) = 1 + (1 << 1) + ((44 + y) << 8);
|
||||||
|
*(currentCopperlist++) = 0xFFFE;
|
||||||
|
|
||||||
|
if (y == 27) {
|
||||||
|
/*
|
||||||
|
*(currentCopperlist++) = custom_sprite_control;
|
||||||
|
*(currentCopperlist++) = 0;
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite_control + 2;
|
||||||
|
*(currentCopperlist++) = 0;
|
||||||
|
*/
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite;
|
||||||
|
*(currentCopperlist++) = ((uint32_t)&spriteData >> 16);
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite + 2;
|
||||||
|
*(currentCopperlist++) = ((uint32_t)&spriteData & 0xffff);
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite_control;
|
||||||
|
*(currentCopperlist++) = SPRPOS(60, 100);
|
||||||
|
|
||||||
|
*(currentCopperlist++) = custom_sprite_control + 2;
|
||||||
|
*(currentCopperlist++) = SPRCTL(60, 100, 198);
|
||||||
|
}
|
||||||
|
|
||||||
|
*(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;
|
||||||
|
|
||||||
i++;
|
|
||||||
if (i > FRAMES_FOR_SCREEN) i = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// somthing in here causes an A500 in KS 1.3 to crash
|
endCopperlist(currentCopperlist);
|
||||||
giveBackSystem();
|
|
||||||
teardownKeyboard();
|
|
||||||
|
|
||||||
teardownScreen(&screenDefinition);
|
for (i = 0; i < 200; ++i) {
|
||||||
|
/*
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
//renderBunFrame(i, &bunRenderer);
|
||||||
|
|
||||||
|
updateDisplayInCopperList(
|
||||||
|
&screenSetup,
|
||||||
|
¤tScreen,
|
||||||
|
copperlistBitplanePointers
|
||||||
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
|
WaitTOF();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
for (i = 0; i < 200; ++i) {
|
||||||
|
WaitTOF();
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
giveBackSystem();
|
||||||
|
|
||||||
|
for (i = 10; i < 50; ++i) {
|
||||||
|
printf("%x ", copperlist[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
teardownScreen(&screenSetup);
|
||||||
|
|
||||||
freeCopperlist(copperlist);
|
freeCopperlist(copperlist);
|
||||||
|
|
||||||
|
|
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)
|
#define TOTAL_SCREEN_SETUP_SIZE(s) ((s->width / 8) * s->height * s->bitplanes * 2)
|
||||||
|
|
||||||
/**
|
void setupScreen(
|
||||||
* Stores internal allocation details in screenSetup.
|
struct ScreenSetup *screenSetup,
|
||||||
* Sets current
|
|
||||||
*/
|
|
||||||
void allocateDoubleBufferedScreenMemory(
|
|
||||||
struct ScreenDefinition *screenDefinition,
|
|
||||||
struct ActiveScreenBufferDetails *activeScreenBufferDetails,
|
|
||||||
uint16_t width,
|
uint16_t width,
|
||||||
uint16_t height,
|
uint16_t height,
|
||||||
uint8_t bitplanes
|
uint8_t bitplanes
|
||||||
) {
|
) {
|
||||||
unsigned char *memory;
|
unsigned char *memory;
|
||||||
int buffer, plane;
|
|
||||||
|
|
||||||
screenDefinition->width = width;
|
screenSetup->width = width;
|
||||||
screenDefinition->height = height;
|
screenSetup->height = height;
|
||||||
screenDefinition->bitplanes = bitplanes;
|
screenSetup->bitplanes = bitplanes;
|
||||||
|
|
||||||
memory = (unsigned char *)AllocMem(
|
memory = (unsigned char *)AllocMem(
|
||||||
TOTAL_SCREEN_SETUP_SIZE(screenDefinition),
|
TOTAL_SCREEN_SETUP_SIZE(screenSetup),
|
||||||
MEMF_CLEAR | MEMF_CHIP
|
MEMF_CLEAR | MEMF_CHIP
|
||||||
);
|
);
|
||||||
|
|
||||||
screenDefinition->memoryStart = memory;
|
screenSetup->memoryStart = memory;
|
||||||
screenDefinition->byteWidth = width / 8;
|
screenSetup->byteWidth = width / 8;
|
||||||
|
|
||||||
// memory is not interleaved
|
// memory is not interleaved
|
||||||
screenDefinition->nextBitplaneAdvance = screenDefinition->byteWidth * height;
|
screenSetup->nextBitplaneAdvance = screenSetup->byteWidth * height;
|
||||||
screenDefinition->nextBufferAdvance = screenDefinition->nextBitplaneAdvance * bitplanes;
|
screenSetup->nextBufferAdvance = screenSetup->nextBitplaneAdvance * bitplanes;
|
||||||
|
|
||||||
for (buffer = 0; buffer < 2; ++buffer) {
|
|
||||||
for (plane = 0; plane < bitplanes; ++plane) {
|
|
||||||
screenDefinition->bufferPlanes[buffer][plane] = screenDefinition->memoryStart +
|
|
||||||
buffer * screenDefinition->nextBufferAdvance +
|
|
||||||
plane * screenDefinition->nextBitplaneAdvance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setActiveScreenBuffer(screenDefinition, activeScreenBufferDetails, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void teardownScreen(
|
void teardownScreen(
|
||||||
struct ScreenDefinition *screenDefinition
|
struct ScreenSetup *screenSetup
|
||||||
) {
|
) {
|
||||||
FreeMem(
|
FreeMem(
|
||||||
screenDefinition->memoryStart,
|
screenSetup->memoryStart,
|
||||||
TOTAL_SCREEN_SETUP_SIZE(screenDefinition)
|
TOTAL_SCREEN_SETUP_SIZE(screenSetup)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setActiveScreenBuffer(
|
void setCurrentScreen(
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *currentScreen,
|
struct CurrentScreen *currentScreen,
|
||||||
short int buffer
|
short int buffer
|
||||||
) {
|
) {
|
||||||
int plane;
|
int plane;
|
||||||
currentScreen->currentBuffer = buffer;
|
currentScreen->currentBuffer = buffer;
|
||||||
|
|
||||||
for (plane = 0; plane < screenDefinition->bitplanes; ++plane) {
|
for (plane = 0; plane < screenSetup->bitplanes; ++plane) {
|
||||||
currentScreen->planes[plane] = screenDefinition->bufferPlanes[buffer][plane];
|
currentScreen->planes[plane] = screenSetup->memoryStart +
|
||||||
|
buffer * screenSetup->nextBufferAdvance +
|
||||||
|
plane * screenSetup->nextBitplaneAdvance;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void swapCurrentScreenBuffer(
|
void swapCurrentScreenBuffer(
|
||||||
struct ScreenDefinition *screenDefinition,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *currentScreen
|
struct CurrentScreen *currentScreen
|
||||||
) {
|
) {
|
||||||
setActiveScreenBuffer(
|
setCurrentScreen(screenSetup, currentScreen, 1 - currentScreen->currentBuffer);
|
||||||
screenDefinition,
|
}
|
||||||
currentScreen,
|
|
||||||
1 - currentScreen->currentBuffer
|
void setupInitialCurrentScreen(
|
||||||
);
|
struct ScreenSetup *screenSetup,
|
||||||
|
struct CurrentScreen *currentScreen
|
||||||
|
) {
|
||||||
|
setCurrentScreen(screenSetup, currentScreen, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
screen.h
26
screen.h
|
@ -6,7 +6,7 @@
|
||||||
#define SCREEN_WIDTH (320)
|
#define SCREEN_WIDTH (320)
|
||||||
#define SCREEN_HEIGHT (256)
|
#define SCREEN_HEIGHT (256)
|
||||||
|
|
||||||
struct ScreenDefinition {
|
struct ScreenSetup {
|
||||||
// human entered
|
// human entered
|
||||||
uint16_t width;
|
uint16_t width;
|
||||||
uint16_t height;
|
uint16_t height;
|
||||||
|
@ -17,36 +17,34 @@ struct ScreenDefinition {
|
||||||
uint16_t byteWidth;
|
uint16_t byteWidth;
|
||||||
uint16_t nextBitplaneAdvance;
|
uint16_t nextBitplaneAdvance;
|
||||||
uint16_t nextBufferAdvance;
|
uint16_t nextBufferAdvance;
|
||||||
unsigned char *bufferPlanes[2][8];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ActiveScreenBufferDetails {
|
struct CurrentScreen {
|
||||||
uint16_t currentBuffer;
|
uint16_t currentBuffer;
|
||||||
unsigned char *planes[8];
|
unsigned char *planes[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
void allocateDoubleBufferedScreenMemory(
|
void setupScreen(
|
||||||
struct ScreenDefinition *screenSetup,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *currentScreen,
|
|
||||||
uint16_t width,
|
uint16_t width,
|
||||||
uint16_t height,
|
uint16_t height,
|
||||||
uint8_t bitplanes
|
uint8_t bitplanes
|
||||||
);
|
);
|
||||||
void teardownScreen(struct ScreenDefinition *screenSetup);
|
void teardownScreen(struct ScreenSetup *screenSetup);
|
||||||
|
|
||||||
void setActiveScreenBuffer(
|
void setCurrentScreen(
|
||||||
struct ScreenDefinition *screenSetup,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *currentScreen,
|
struct CurrentScreen *currentScreen,
|
||||||
short int buffer
|
short int buffer
|
||||||
);
|
);
|
||||||
|
|
||||||
void swapCurrentScreenBuffer(
|
void swapCurrentScreenBuffer(
|
||||||
struct ScreenDefinition *screenSetup,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *currentScreen
|
struct CurrentScreen *currentScreen
|
||||||
);
|
);
|
||||||
|
|
||||||
void setupInitialCurrentScreen(
|
void setupInitialCurrentScreen(
|
||||||
struct ScreenDefinition *screenSetup,
|
struct ScreenSetup *screenSetup,
|
||||||
struct ActiveScreenBufferDetails *currentScreen
|
struct CurrentScreen *currentScreen
|
||||||
);
|
);
|
||||||
#endif
|
#endif
|
||||||
|
|
24
smakefile
24
smakefile
|
@ -1,9 +1,4 @@
|
||||||
MAIN_OBJS = main.o images.o system.lib screen.o bun.o
|
MAIN_OBJS = main.o images.o system.lib screen.o bun.o
|
||||||
32_objs = 32x50_bun.o system.lib screen.o images.o
|
|
||||||
33_objs = 33x50_bun.o system.lib screen.o images.o
|
|
||||||
left_side_objs = left_side.o system.lib screen.o images.o
|
|
||||||
right_side_objs = right_side.o system.lib screen.o images.o
|
|
||||||
any_position = any_position.o system.lib screen.o images.o
|
|
||||||
|
|
||||||
all: main
|
all: main
|
||||||
|
|
||||||
|
@ -13,27 +8,12 @@ all: main
|
||||||
.s.o:
|
.s.o:
|
||||||
genam -l $*.s
|
genam -l $*.s
|
||||||
|
|
||||||
system.lib: system/system.o system/copper.o system/blitter.o system/debug.o
|
system.lib: system/system.o system/copper.o system/blitter.o
|
||||||
sc objectlibrary=system.lib system/system.o system/copper.o system/blitter.o system/debug.o
|
sc objectlibrary=system.lib system/system.o system/copper.o system/blitter.o
|
||||||
|
|
||||||
main: $(MAIN_OBJS)
|
main: $(MAIN_OBJS)
|
||||||
sc link to main math=standard $(MAIN_OBJS)
|
sc link to main math=standard $(MAIN_OBJS)
|
||||||
|
|
||||||
32x50: $(32_objs)
|
|
||||||
sc link to 32x50 $(32_objs)
|
|
||||||
|
|
||||||
33x50: $(33_objs)
|
|
||||||
sc link to 33x50 $(33_objs)
|
|
||||||
|
|
||||||
left_side: $(left_side_objs)
|
|
||||||
sc link to left_side $(left_side_objs)
|
|
||||||
|
|
||||||
right_side: $(right_side_objs)
|
|
||||||
sc link to right_side $(right_side_objs)
|
|
||||||
|
|
||||||
any_position: $(any_position)
|
|
||||||
sc link to any_position $(any_position)
|
|
||||||
|
|
||||||
test: bun_test.o bun.o
|
test: bun_test.o bun.o
|
||||||
sc link to bun_test identifierlength=32 math=standard bun_test.o bun.o cutest/CuTest.c
|
sc link to bun_test identifierlength=32 math=standard bun_test.o bun.o cutest/CuTest.c
|
||||||
|
|
||||||
|
|
Binary file not shown.
BIN
sprite-data
BIN
sprite-data
Binary file not shown.
|
@ -1,14 +1,8 @@
|
||||||
#ifndef __BLITTER_H__
|
#ifndef __BLITTER_H__
|
||||||
#define __BLITTER_H__
|
#define __BLITTER_H__
|
||||||
|
|
||||||
#define BLTSIZE(w, h) (w + (h << 6))
|
#include "types.h"
|
||||||
#define BLTCON0( \
|
#include "screen.h"
|
||||||
minterm, aChan, bChan, cChan, dChan, shift \
|
|
||||||
) (minterm + (aChan << 11) + (bChan << 10) + (cChan << 9) + (dChan << 8) + (shift << 12))
|
|
||||||
#define BLTCON1(descending, shift) ((descending << 1) + (shift << 12))
|
|
||||||
|
|
||||||
#define BLITTER_ASCENDING (0)
|
|
||||||
#define BLITTER_DESCENDING (1)
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -7,15 +7,9 @@
|
||||||
|
|
||||||
extern struct Custom far custom;
|
extern struct Custom far custom;
|
||||||
|
|
||||||
uint16_t copperlistSize;
|
uint16_t * prepareNewCopperlist(void) {
|
||||||
|
uint16_t *copperlist = AllocMem(
|
||||||
uint16_t * prepareNewCopperlist(uint16_t size_b) {
|
COPPERLIST_SIZE,
|
||||||
uint16_t *copperlist;
|
|
||||||
|
|
||||||
copperlistSize = size_b;
|
|
||||||
|
|
||||||
copperlist = AllocMem(
|
|
||||||
copperlistSize,
|
|
||||||
MEMF_CHIP | MEMF_CLEAR
|
MEMF_CHIP | MEMF_CLEAR
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -30,5 +24,5 @@ void setCopperlist(uint16_t *copperlist) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeCopperlist(uint16_t *copperlist) {
|
void freeCopperlist(uint16_t *copperlist) {
|
||||||
FreeMem(copperlist, copperlistSize);
|
FreeMem(copperlist, COPPERLIST_SIZE);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,31 +1,11 @@
|
||||||
#ifndef __COPPER_H__
|
#ifndef __COPPER_H__
|
||||||
#define __COPPER_H__
|
#define __COPPER_H__
|
||||||
|
|
||||||
|
#define COPPERLIST_SIZE (10000)
|
||||||
|
|
||||||
#include "../types.h"
|
#include "../types.h"
|
||||||
|
|
||||||
/**
|
uint16_t * prepareNewCopperlist(void);
|
||||||
* Sets register to value over two Copper words.
|
|
||||||
* Side-effect: Advances ptr by 4.
|
|
||||||
*/
|
|
||||||
#define COPPERLIST_MOVE(ptr,register,value) \
|
|
||||||
*(ptr++) = register; \
|
|
||||||
*(ptr++) = value;
|
|
||||||
|
|
||||||
#define COPPERLIST_WAIT(ptr,x,y,mask) \
|
|
||||||
*(ptr++) = 1 + (x << 1) + (y << 8); \
|
|
||||||
*(ptr++) = mask;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets high/low registers to pointer value over four Copper words.
|
|
||||||
* Side-effect: Advances ptr by 8.
|
|
||||||
*/
|
|
||||||
#define COPPERLIST_MOVE_POINTER(ptr,register,pointerValue) \
|
|
||||||
*(ptr++) = register; \
|
|
||||||
*(ptr++) = (pointerValue >> 16); \
|
|
||||||
*(ptr++) = register + 2; \
|
|
||||||
*(ptr++) = (pointerValue & 0xffff);
|
|
||||||
|
|
||||||
uint16_t * prepareNewCopperlist(uint16_t size_b);
|
|
||||||
void setCopperlist(uint16_t *copperlist);
|
void setCopperlist(uint16_t *copperlist);
|
||||||
void freeCopperlist(uint16_t *copperlist);
|
void freeCopperlist(uint16_t *copperlist);
|
||||||
|
|
||||||
|
|
|
@ -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
|
// copperlist
|
||||||
extern void initializeCopperlist(void *copperlist);
|
extern void initializeCopperlist(void *copperlist);
|
||||||
extern uint16_t* endCopperlist(uint16_t *copperlist);
|
extern uint16_t* endCopperlist(uint16_t *copperlist);
|
||||||
/**
|
|
||||||
* This only adds bitplane pointers to the copperlist
|
|
||||||
* and sets it up for double buffering.
|
|
||||||
* You still need to configure the playfield hardware.
|
|
||||||
*/
|
|
||||||
extern uint16_t* addDisplayToCopperlist(
|
extern uint16_t* addDisplayToCopperlist(
|
||||||
uint16_t *copperlist,
|
uint16_t *copperlist,
|
||||||
struct ScreenDefinition *,
|
struct ScreenSetup *,
|
||||||
struct ActiveScreenBufferDetails *,
|
struct CurrentScreen *,
|
||||||
void *copperlistBitplanePointers
|
void *copperlistBitplanePointers
|
||||||
);
|
);
|
||||||
extern void updateDisplayInCopperList(
|
extern void updateDisplayInCopperList(
|
||||||
struct ScreenDefinition *,
|
struct ScreenSetup *,
|
||||||
struct ActiveScreenBufferDetails *,
|
struct CurrentScreen *,
|
||||||
void *copperlistBitplanePointers
|
void *copperlistBitplanePointers
|
||||||
);
|
);
|
||||||
extern uint16_t* addColorsToCopperlist(uint16_t *copperlist, color_t[], int count);
|
extern uint16_t* addColorsToCopperlist(uint16_t *copperlist, color_t[], int count);
|
||||||
|
|
160
system/system.s
160
system/system.s
|
@ -9,9 +9,6 @@
|
||||||
XDEF _endCopperlist
|
XDEF _endCopperlist
|
||||||
XDEF _myWaitBlit
|
XDEF _myWaitBlit
|
||||||
XDEF _WaitBOF
|
XDEF _WaitBOF
|
||||||
XDEF _KeyboardHandler
|
|
||||||
|
|
||||||
XDEF _keyboardPressed
|
|
||||||
|
|
||||||
XREF _custom
|
XREF _custom
|
||||||
|
|
||||||
|
@ -32,8 +29,6 @@ FUNC_CNT SET FUNC_CNT-6
|
||||||
INCLUDE "hardware/custom.i"
|
INCLUDE "hardware/custom.i"
|
||||||
INCLUDE "hardware/dmabits.i"
|
INCLUDE "hardware/dmabits.i"
|
||||||
INCLUDE "hardware/intbits.i"
|
INCLUDE "hardware/intbits.i"
|
||||||
INCLUDE "exec/io.i"
|
|
||||||
INCLUDE "devices/inputevent.i"
|
|
||||||
|
|
||||||
; @param 1 Pointer to null terminated name of library
|
; @param 1 Pointer to null terminated name of library
|
||||||
; @param 2 Minimum version of library, 0 for any
|
; @param 2 Minimum version of library, 0 for any
|
||||||
|
@ -61,69 +56,24 @@ RestoreRegister MACRO
|
||||||
MOVE.W Old\1,\1(A0)
|
MOVE.W Old\1,\1(A0)
|
||||||
ENDM
|
ENDM
|
||||||
|
|
||||||
STRUCTURE ScreenDefinition,0
|
STRUCTURE ScreenSetup,0
|
||||||
UWORD ScreenDefinition_width
|
UWORD ScreenSetup_width
|
||||||
UWORD ScreenDefinition_height
|
UWORD ScreenSetup_height
|
||||||
UWORD ScreenDefinition_bitplanes
|
UWORD ScreenSetup_bitplanes
|
||||||
ULONG ScreenDefinition_memoryStart
|
ULONG ScreenSetup_memoryStart
|
||||||
UWORD ScreenDefinition_byteWidth
|
UWORD ScreenSetup_byteWidth
|
||||||
UWORD ScreenDefinition_nextBitplaneAdvance
|
UWORD ScreenSetup_nextBitplaneAdvance
|
||||||
UWORD ScreenDefinition_nextBufferAdvance
|
UWORD ScreenSetup_nextBufferAdvance
|
||||||
ULONG ScreenDefinition_copperlistBitplanePointers
|
ULONG ScreenSetup_copperlistBitplanePointers
|
||||||
LABEL ScreenDefinition_SIZEOF
|
LABEL ScreenSetup_SIZEOF
|
||||||
|
|
||||||
STRUCTURE ActiveScreenBufferDetails,0
|
STRUCTURE CurrentScreen,0
|
||||||
UWORD ActiveScreenBufferDetails_currentBuffer
|
UWORD CurrentScreen_currentBuffer
|
||||||
ActiveScreenBufferDetails_planes EQU SOFFSET
|
CurrentScreen_planes EQU SOFFSET
|
||||||
SOFFSET SET SOFFSET+(8*4)
|
SOFFSET SET SOFFSET+(8*4)
|
||||||
LABEL ActiveScreenBufferDetails_SIZEOF
|
LABEL CurrentScreen_SIZEOF
|
||||||
|
|
||||||
; @see https://amigadev.elowar.com/read/ADCD_2.1/Devices_Manual_guide/node019A.html
|
BPLCON0_COLOR EQU $200
|
||||||
; @register A0 struct InputEvent *
|
|
||||||
; @register A1 extra data about the event
|
|
||||||
; @output D0 The value of A0
|
|
||||||
_KeyboardHandler:
|
|
||||||
; @stack [RA,A0,current node]
|
|
||||||
MOVE.L A0,-(SP)
|
|
||||||
MOVE.L #0,-(SP)
|
|
||||||
|
|
||||||
_KeyboardHandler_CheckLoop:
|
|
||||||
CMP.B #IECLASS_RAWKEY,ie_Class(A0)
|
|
||||||
BNE.S _KeyboardHandler_NextEvent
|
|
||||||
|
|
||||||
MOVE.W ie_Code(A0),D0
|
|
||||||
AND.W #IECODE_UP_PREFIX,D0
|
|
||||||
SEQ _keyboardPressed
|
|
||||||
|
|
||||||
; if next_event:
|
|
||||||
; do the stack swap thing below
|
|
||||||
; else:
|
|
||||||
; change the A0 in the stack above it
|
|
||||||
TST.L (SP)
|
|
||||||
BNE.S _KeyboardHandler_hasLastEvent
|
|
||||||
|
|
||||||
MOVE.L (A0),4(SP)
|
|
||||||
BRA.S _KeyboardHandler_NextEvent
|
|
||||||
|
|
||||||
_KeyboardHandler_hasLastEvent:
|
|
||||||
; put the next event in the first pointer of the
|
|
||||||
; last event
|
|
||||||
MOVE.L A1,-(SP)
|
|
||||||
MOVE.L 4(SP),A1
|
|
||||||
MOVE.L (A0),(A1)
|
|
||||||
MOVE.L (SP)+,A1
|
|
||||||
|
|
||||||
_KeyboardHandler_NextEvent:
|
|
||||||
; next event is in first long of struct
|
|
||||||
MOVE.L (A0),D0
|
|
||||||
; store current node in stack
|
|
||||||
MOVE.L A0,(SP)
|
|
||||||
|
|
||||||
MOVE.L D0,A0
|
|
||||||
BNE.S _KeyboardHandler_CheckLoop
|
|
||||||
MOVE.L (SP)+,D0
|
|
||||||
MOVE.L (SP)+,D0
|
|
||||||
RTS
|
|
||||||
|
|
||||||
M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C
|
M68K_LEVEL3_INTERRUPT_AUTOVECTOR EQU $6C
|
||||||
_takeOverSystem:
|
_takeOverSystem:
|
||||||
|
@ -131,15 +81,13 @@ _takeOverSystem:
|
||||||
OpenLibrary #GraphicsLibrary,#0
|
OpenLibrary #GraphicsLibrary,#0
|
||||||
MOVE.L D0,GraphicsBase
|
MOVE.L D0,GraphicsBase
|
||||||
|
|
||||||
|
MOVE.L $4,A6
|
||||||
|
CALLLIB _LVOForbid
|
||||||
|
|
||||||
MOVE.L D0,A6
|
MOVE.L D0,A6
|
||||||
MOVE.L gb_ActiView(A6),OldView
|
MOVE.L gb_ActiView(A6),OldView
|
||||||
MOVE.L gb_copinit(A6),OldCopper
|
MOVE.L gb_copinit(A6),OldCopper
|
||||||
|
|
||||||
MOVE.L #0,A1
|
|
||||||
CALLLIB _LVOLoadView
|
|
||||||
CALLLIB _LVOWaitTOF
|
|
||||||
CALLLIB _LVOWaitTOF
|
|
||||||
|
|
||||||
CALLLIB _LVOOwnBlitter
|
CALLLIB _LVOOwnBlitter
|
||||||
CALLLIB _LVOWaitBlit
|
CALLLIB _LVOWaitBlit
|
||||||
|
|
||||||
|
@ -150,11 +98,17 @@ _takeOverSystem:
|
||||||
PreserveRegister intreq
|
PreserveRegister intreq
|
||||||
PreserveRegister adkcon
|
PreserveRegister adkcon
|
||||||
|
|
||||||
|
MOVE.L #0,A1
|
||||||
|
CALLLIB _LVOLoadView
|
||||||
|
CALLLIB _LVOWaitTOF
|
||||||
|
CALLLIB _LVOWaitTOF
|
||||||
|
|
||||||
|
LEA _custom,A0
|
||||||
|
|
||||||
; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0036.html
|
; http://amigadev.elowar.com/read/ADCD_2.1/Hardware_Manual_guide/node0036.html
|
||||||
MOVE.W #$7FFF,intena(A0) ; disable all interrupts
|
MOVE.W #$7FFF,intena(A0) ; disable all interrupts
|
||||||
; we need VERTB to use WaitTOF
|
; we need VERTB to use WaitTOF
|
||||||
; PORTS and EXTER give me access to the keyboard and mouse via OS interrupts
|
MOVE.W #INTF_SETCLR|INTF_INTEN|INTF_COPER|INTF_VERTB,intena(A0) ; enable master interrupt, copper, and VBR
|
||||||
MOVE.W #INTF_SETCLR|INTF_INTEN|INTF_COPER|INTF_PORTS|INTF_EXTER|INTF_VERTB,intena(A0) ; enable master interrupt, copper, and VBR
|
|
||||||
|
|
||||||
MOVE.W #$7FFF,dmacon(a0)
|
MOVE.W #$7FFF,dmacon(a0)
|
||||||
MOVE.W #DMAF_SETCLR|DMAF_MASTER|DMAF_COPPER|DMAF_RASTER|DMAF_BLITTER|DMAF_SPRITE,dmacon(A0)
|
MOVE.W #DMAF_SETCLR|DMAF_MASTER|DMAF_COPPER|DMAF_RASTER|DMAF_BLITTER|DMAF_SPRITE,dmacon(A0)
|
||||||
|
@ -210,6 +164,9 @@ _giveBackSystem:
|
||||||
CALLLIB _LVOWaitTOF
|
CALLLIB _LVOWaitTOF
|
||||||
CALLLIB _LVOWaitBlit
|
CALLLIB _LVOWaitBlit
|
||||||
CALLLIB _LVODisownBlitter
|
CALLLIB _LVODisownBlitter
|
||||||
|
|
||||||
|
MOVE.L $4,A6
|
||||||
|
CALLLIB _LVOPermit
|
||||||
MOVE.L (SP)+,A6
|
MOVE.L (SP)+,A6
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
|
@ -221,8 +178,8 @@ _initializeCopperlist:
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
; @stack *copperlist Pointer to copperlist
|
; @stack *copperlist Pointer to copperlist
|
||||||
; @stack ScreenDefinition Pointer to screenSetup struct
|
; @stack ScreenSetup Pointer to screenSetup struct
|
||||||
; @stack ActiveScreenBufferDetails Pointer to currentScreen struct
|
; @stack CurrentScreen Pointer to currentScreen struct
|
||||||
; @stack copperlistBitplanePointers Pointer to bitplane pointers within the copper list [[high, low], ...]
|
; @stack copperlistBitplanePointers Pointer to bitplane pointers within the copper list [[high, low], ...]
|
||||||
STRUCTURE updateDisplayInCopperList,4
|
STRUCTURE updateDisplayInCopperList,4
|
||||||
ULONG updateDisplayInCopperList_screenSetup
|
ULONG updateDisplayInCopperList_screenSetup
|
||||||
|
@ -237,9 +194,9 @@ _updateDisplayInCopperList:
|
||||||
MOVE.L D0,A2
|
MOVE.L D0,A2
|
||||||
; a2 has copperlistBitplanePointers
|
; a2 has copperlistBitplanePointers
|
||||||
|
|
||||||
MOVE.W ScreenDefinition_bitplanes(A0),D1
|
MOVE.W ScreenSetup_bitplanes(A0),D1
|
||||||
SUBQ #1,D1
|
SUBQ #1,D1
|
||||||
LEA ActiveScreenBufferDetails_planes(A1),A1
|
LEA CurrentScreen_planes(A1),A1
|
||||||
; a1 has planes
|
; a1 has planes
|
||||||
|
|
||||||
.continue:
|
.continue:
|
||||||
|
@ -290,13 +247,13 @@ _setUpEmptySpritesInCopperlist:
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
; @stack *copperlist Pointer to copperlist
|
; @stack *copperlist Pointer to copperlist
|
||||||
; @stack ScreenDefinition Pointer to screenDefinition struct
|
; @stack ScreenSetup Pointer to screenSetup struct
|
||||||
; @stack ActiveScreenBufferDetails Pointer to activeScreenBufferDetails struct
|
; @stack CurrentScreen Pointer to currentScreen struct
|
||||||
; @stack copperlistBitplanePointers Pointer to copperlistBitplanePointers struct
|
; @stack copperlistBitplanePointers Pointer to currentScreen struct
|
||||||
STRUCTURE AddDisplayToCopperListParams,4
|
STRUCTURE AddDisplayToCopperListParams,4
|
||||||
ULONG AddDisplayToCopperListParams_copperlistPtr
|
ULONG AddDisplayToCopperListParams_copperlistPtr
|
||||||
ULONG AddDisplayToCopperListParams_screenDefinitionPtr
|
ULONG AddDisplayToCopperListParams_screenSetupPtr
|
||||||
ULONG AddDisplayToCopperListParams_activeScreenBufferDetailsPtr
|
ULONG AddDisplayToCopperListParams_currentScreenPtr
|
||||||
ULONG AddDisplayToCopperListParams_copperlistBitplanePointersPtr
|
ULONG AddDisplayToCopperListParams_copperlistBitplanePointersPtr
|
||||||
_addDisplayToCopperlist:
|
_addDisplayToCopperlist:
|
||||||
MOVE.L A7,A0
|
MOVE.L A7,A0
|
||||||
|
@ -304,15 +261,16 @@ _addDisplayToCopperlist:
|
||||||
; A2,D2,D3
|
; A2,D2,D3
|
||||||
MOVEM.L A2-A4/D2-D4,-(SP)
|
MOVEM.L A2-A4/D2-D4,-(SP)
|
||||||
MOVE.L AddDisplayToCopperListParams_copperlistPtr(A0),A1 ; copperlist
|
MOVE.L AddDisplayToCopperListParams_copperlistPtr(A0),A1 ; copperlist
|
||||||
MOVE.L AddDisplayToCopperListParams_screenDefinitionPtr(A0),A2 ; screenDefinition
|
MOVE.L AddDisplayToCopperListParams_screenSetupPtr(A0),A2 ; screenSetup
|
||||||
MOVE.L AddDisplayToCopperListParams_activeScreenBufferDetailsPtr(A0),A3 ; currentScreen
|
MOVE.L AddDisplayToCopperListParams_currentScreenPtr(A0),A3 ; currentScreen
|
||||||
MOVE.L AddDisplayToCopperListParams_copperlistBitplanePointersPtr(A0),A4 ; copperlistBitplanePointers
|
MOVE.L AddDisplayToCopperListParams_copperlistBitplanePointersPtr(A0),A4 ; copperlistBitplanePointers
|
||||||
|
|
||||||
LEA ActiveScreenBufferDetails_planes(A3),A3
|
LEA CurrentScreen_planes(A3),A3
|
||||||
; a3 contains address to planes
|
; a3 contains address to planes
|
||||||
|
|
||||||
|
|
||||||
MOVEQ #0,D0
|
MOVEQ #0,D0
|
||||||
MOVE.W ScreenDefinition_bitplanes(A2),D0
|
MOVE.W ScreenSetup_bitplanes(A2),D0
|
||||||
; d0 is num of bitplanes
|
; d0 is num of bitplanes
|
||||||
|
|
||||||
; set up bplpt
|
; set up bplpt
|
||||||
|
@ -331,10 +289,9 @@ _addDisplayToCopperlist:
|
||||||
; get this position for later updating
|
; get this position for later updating
|
||||||
MOVE.L A1,(A4)+
|
MOVE.L A1,(A4)+
|
||||||
MOVE.W D3,(A1)+
|
MOVE.W D3,(A1)+
|
||||||
ADDQ #2,D1
|
|
||||||
|
|
||||||
; low byte
|
; low byte
|
||||||
SWAP D3
|
SWAP D3
|
||||||
|
ADDQ #2,D1
|
||||||
MOVE.W D1,(A1)+
|
MOVE.W D1,(A1)+
|
||||||
; get this position for later updating
|
; get this position for later updating
|
||||||
MOVE.L A1,(A4)+
|
MOVE.L A1,(A4)+
|
||||||
|
@ -383,45 +340,33 @@ _endCopperlist:
|
||||||
|
|
||||||
RTS
|
RTS
|
||||||
|
|
||||||
BPLCON0_ENABLE_COMPOSITE_COLOR EQU $200
|
|
||||||
|
|
||||||
; TODO: [ ] Create a stock display structure w/ all the default values in it
|
|
||||||
; that can be overridden, with guides/help on how to do so, then
|
|
||||||
; have this accept that structure
|
|
||||||
; @stack bitplaneCount
|
; @stack bitplaneCount
|
||||||
_setUpDisplay:
|
_setUpDisplay:
|
||||||
MOVE.L D2,-(SP)
|
MOVE.L D2,-(SP)
|
||||||
MOVE.L 8(A7),D2 ; bitplaneCount
|
MOVE.L 8(A7),D2
|
||||||
|
|
||||||
LEA _custom,A1
|
LEA _custom,A1
|
||||||
|
|
||||||
MOVEQ #0,D0
|
MOVEQ #0,D0
|
||||||
MOVE.W #BPLCON0_ENABLE_COMPOSITE_COLOR,D0
|
MOVE.W #BPLCON0_COLOR,D0
|
||||||
|
|
||||||
; move bitplane count to bits 12-14
|
|
||||||
MOVEQ #0,D1
|
MOVEQ #0,D1
|
||||||
MOVE.W D2,D1
|
MOVE.W D2,D1
|
||||||
|
|
||||||
AND.W #$7,D1
|
AND.W #$7,D1
|
||||||
ROL.W #8,D1
|
ROL.W #8,D1
|
||||||
ROL.W #4,D1
|
ROL.W #4,D1
|
||||||
ADD.W D1,D0
|
ADD.W D1,D0
|
||||||
|
|
||||||
MOVE.W D0,bplcon0(A1)
|
MOVE.W D0,bplcon0(A1)
|
||||||
|
|
||||||
; this controls horizontal scroll. I'm not good enough
|
|
||||||
; yet to provide opinions on this.
|
|
||||||
MOVE.W #0,bplcon1(A1)
|
MOVE.W #0,bplcon1(A1)
|
||||||
|
MOVE.W #0,bplcon2(A1)
|
||||||
; sprites always on top for this demo
|
|
||||||
MOVE.W #$0020,bplcon2(A1)
|
|
||||||
|
|
||||||
; no modulos needed
|
|
||||||
MOVE.W #0,bpl1mod(A1)
|
MOVE.W #0,bpl1mod(A1)
|
||||||
MOVE.W #0,bpl2mod(A1)
|
MOVE.W #0,bpl2mod(A1)
|
||||||
|
|
||||||
; pal default
|
|
||||||
MOVE.W #$2c81,diwstrt(A1)
|
MOVE.W #$2c81,diwstrt(A1)
|
||||||
MOVE.W #$2cc1,diwstop(A1)
|
; pal trick
|
||||||
|
MOVE.W #$f4c1,diwstop(A1)
|
||||||
|
MOVE.W #$38c1,diwstop(A1)
|
||||||
MOVE.W #$0038,ddfstrt(A1)
|
MOVE.W #$0038,ddfstrt(A1)
|
||||||
MOVE.W #$00d0,ddfstop(A1)
|
MOVE.W #$00d0,ddfstop(A1)
|
||||||
MOVE.L (SP)+,D2
|
MOVE.L (SP)+,D2
|
||||||
|
@ -482,8 +427,5 @@ VBIPtr dc.l 0
|
||||||
CNOP 0,4
|
CNOP 0,4
|
||||||
GraphicsLibrary GRAPHICSNAME
|
GraphicsLibrary GRAPHICSNAME
|
||||||
|
|
||||||
CNOP 0,4
|
|
||||||
_keyboardPressed dc.l 0
|
|
||||||
|
|
||||||
SECTION Sprite,Data_C
|
SECTION Sprite,Data_C
|
||||||
EmptySprite dc.w 0,0
|
EmptySprite dc.w 0,0
|
||||||
|
|
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>
|
#include <exec/types.h>
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the offset from the beginning of a struct. Useful for building
|
|
||||||
* references to custom chip registers dynamically for copperlists.
|
|
||||||
*
|
|
||||||
* @see Custom
|
|
||||||
*/
|
|
||||||
#define offsetof(s, m) &((struct s *)0)->m
|
|
||||||
|
|
||||||
typedef unsigned short color_t;
|
typedef unsigned short color_t;
|
||||||
typedef unsigned long uint32_t;
|
typedef unsigned long uint32_t;
|
||||||
typedef unsigned short uint16_t;
|
typedef unsigned short uint16_t;
|
||||||
|
|
Loading…
Reference in New Issue