diff --git a/016.copper_fun/Makefile b/016.copper_fun/Makefile new file mode 100644 index 0000000..90f554e --- /dev/null +++ b/016.copper_fun/Makefile @@ -0,0 +1,14 @@ +FLOPPY=bin/copper_fun.adf +EXTRA=out/copper-new.s +LIBS=`GraphicsMagick-config --ldflags --libs` +MODULE=copper_fun.s +BASE_ADDRESS=10000 +include ../shared/base.mk + +out/copper-new.s: assets/test.gif out/copper_fun_generate + /opt/ImageMagick/bin/convert assets/test.gif out/%05d.png + ./convert.sh > out/copper-new.s + +out/copper_fun_generate: copper_fun_generate.c Makefile + gcc $(HOST_CFLAGS) `GraphicsMagick-config --cppflags` copper_fun_generate.c -o out/copper_fun_generate $(LIBS) + diff --git a/016.copper_fun/README.md b/016.copper_fun/README.md new file mode 100644 index 0000000..b95bb06 --- /dev/null +++ b/016.copper_fun/README.md @@ -0,0 +1,11 @@ +copper fun +========== + +screenshot +---------- +![Screenshot](screenshot.png?raw=true) + +try it +------ + * [Download disk image](bin/copper_vert.adf?raw=true) + * Run in SAE diff --git a/016.copper_fun/assets/test.gif b/016.copper_fun/assets/test.gif new file mode 100644 index 0000000..82085dd Binary files /dev/null and b/016.copper_fun/assets/test.gif differ diff --git a/016.copper_fun/bin/copper_fun.adf b/016.copper_fun/bin/copper_fun.adf new file mode 100644 index 0000000..93294c7 Binary files /dev/null and b/016.copper_fun/bin/copper_fun.adf differ diff --git a/016.copper_fun/convert.sh b/016.copper_fun/convert.sh new file mode 100755 index 0000000..041502b --- /dev/null +++ b/016.copper_fun/convert.sh @@ -0,0 +1,13 @@ +ODD=1 +for I in out/*.png; do + if [ $ODD = 0 ] ; then + echo `echo $I | sed -e 's/\///' -e 's/\.png//'`":" + ./out/copper_fun_generate $I + echo " dc.l \$fffffffe" + ODD=1 + + else + ODD=0 + fi + +done \ No newline at end of file diff --git a/016.copper_fun/copper_fun.s b/016.copper_fun/copper_fun.s new file mode 100644 index 0000000..fc71642 --- /dev/null +++ b/016.copper_fun/copper_fun.s @@ -0,0 +1,77 @@ + include "../include/registers.i" + include "hardware/dmabits.i" + include "hardware/intbits.i" + +LVL3_INT_VECTOR equ $6c +SCREEN_WIDTH equ 320 +SCREEN_HEIGHT equ 256 +SCREEN_WIDTH_BYTES equ (SCREEN_WIDTH/8) +SCREEN_BIT_DEPTH equ 1 +SCREEN_RES equ 8 ; 8=lo resolution, 4=hi resolution +RASTER_X_START equ $81 ; hard coded coordinates from hardware manual +RASTER_Y_START equ $2c +RASTER_X_STOP equ RASTER_X_START+SCREEN_WIDTH +RASTER_Y_STOP equ RASTER_Y_START+SCREEN_HEIGHT + +entry: + ;; custom chip base globally in a6 + lea CUSTOM,a6 + + move #$7ff,DMACON(a6) ; disable all dma + move #$7fff,INTENA(a6) ; disable all interrupts + + ;; set up playfield + move.w #(RASTER_Y_START<<8)|RASTER_X_START,DIWSTRT(a6) + move.w #((RASTER_Y_STOP-256)<<8)|(RASTER_X_STOP-256),DIWSTOP(a6) + + move.w #(RASTER_X_START/2-SCREEN_RES),DDFSTRT(a6) + move.w #(RASTER_X_START/2-SCREEN_RES)+(8*((SCREEN_WIDTH/16)-1)),DDFSTOP(a6) + + move.w #(SCREEN_BIT_DEPTH<<12)|$200,BPLCON0(a6) + move.w #SCREEN_WIDTH_BYTES*SCREEN_BIT_DEPTH-SCREEN_WIDTH_BYTES,BPL1MOD(a6) + + ;; install copper list, then enable dma and selected interrupts + if 0 + lea copper(pc),a0 + move.l a0,COP1LC(a6) + endif + move.w COPJMP1(a6),d0 + move.w #(DMAF_SETCLR!DMAF_COPPER!DMAF_RASTER!DMAF_MASTER),DMACON(a6) + move.w #(INTF_SETCLR|INTF_INTEN|INTF_EXTER),INTENA(a6) + +.mainLoop: + bsr waitVerticalBlank + + lea bitplane(pc),a1 + lea.l BPL1PT(a6),a0 + move.l a1,(a0) + + move.l counter,d0 + cmpi.l #5,counter + bne .ok + move.l #0,counter + move.l copperptr,a0 + move.l a0,COP1LC(a6) + add.l #size,copperptr + move.l copperptr,d0 + cmpi.l #end,d0 + bne .ok + move.l #copper,copperptr +.ok + addi.l #1,counter + bra.b .mainLoop + + include "utils.s" + +size equ out00003-out00001 + +counter: + dc.l 0 + +copperptr: + dc.l out00001 +bitplane: + dcb.b (SCREEN_WIDTH*SCREEN_HEIGHT)/8,$00 +copper: + include "out/copper-new.s" +end: \ No newline at end of file diff --git a/016.copper_fun/copper_fun_generate.c b/016.copper_fun/copper_fun_generate.c new file mode 100644 index 0000000..9e0bc29 --- /dev/null +++ b/016.copper_fun/copper_fun_generate.c @@ -0,0 +1,129 @@ +#include +#include +#include +#include +#include +#include +#include + +#define HEIGHT 256+16 +#define COPPER_WIDTH 52 + +typedef struct { + char** argv; + float blur; + int debug; +} config_t; + +typedef struct { + Image *image; + Image *resizeImage; + ImageInfo *imageInfo; +} image_t; + +image_t image = {0}; +config_t config = {.blur = 0.75}; + +static void +cleanup() +{ + if (image.image != (Image *) NULL) { + DestroyImage(image.image); + } + + if (image.resizeImage != (Image *)NULL) { + DestroyImage(image.resizeImage); + } + + + if (image.imageInfo != (ImageInfo *) NULL) { + DestroyImageInfo(image.imageInfo); + } + DestroyMagick(); +} + + +static void +abort_(const char * s, ...) +{ + fprintf(stderr, "%s: ", config.argv[0]); + va_list args; + va_start(args, s); + vfprintf(stderr, s, args); + fprintf(stderr, "\n"); + va_end(args); + cleanup(); + exit(1); +} + + +static void +getframedata(char* inputFile) +{ + ExceptionInfo exception; + InitializeMagick(NULL); + image.imageInfo=CloneImageInfo(0); + GetExceptionInfo(&exception); + char* outputFile = "resized.png"; + + (void) strcpy(image.imageInfo->filename, inputFile); + image.image = ReadImage(image.imageInfo, &exception); + if (image.image == (Image *) NULL) { + CatchException(&exception); + abort_("Failed to read image %s\n", inputFile); + } + + int width = COPPER_WIDTH; + int height = HEIGHT; + + image.resizeImage=ResizeImage(image.image, width, height, BesselFilter, config.blur, &exception); + + strcpy(image.resizeImage->filename, outputFile); + + if (config.debug) { + if (!WriteImage(image.imageInfo, image.resizeImage)) { + CatchException(&image.resizeImage->exception); + abort_("Failed to write image %d\n", outputFile); + } + } +} + + +int +main(int argc, char** argv) +{ + config.argv = argv; + getframedata(argv[1]); + + int startLine = 0x2c-16; + int screenHeight = HEIGHT; + int endLine = startLine+screenHeight; + int startHpos = 6+8; + int i, line; + + for (line = startLine; line < endLine; ++line) { + if (line <= 255) { + printf("\tdc.w $%x,$fffe\n",line<<8|startHpos|1); + } else { + printf("\tdc.w $%x,$fffe\n", (line-256)<<8|startHpos|1); + } + + int endw = COPPER_WIDTH; + if (line == 255) { + endw = 50; + } + + for (i = 0; i < endw; i++) { + PixelPacket pixel = GetOnePixel(image.resizeImage, i, line-startLine); + printf("\tdc.w COLOR00,$%x%x%x\n", pixel.red>>4, pixel.green>>4, pixel.blue>>4); + } + + if (line <= 255) { + printf("\tdc.w $%x,$fffe\n",line<<8|0xe1|1); + } + } + + cleanup(); + + return 0; +} diff --git a/016.copper_fun/screenshot.png b/016.copper_fun/screenshot.png new file mode 100644 index 0000000..510ea92 Binary files /dev/null and b/016.copper_fun/screenshot.png differ diff --git a/016.copper_fun/utils.s b/016.copper_fun/utils.s new file mode 100644 index 0000000..bdde568 --- /dev/null +++ b/016.copper_fun/utils.s @@ -0,0 +1,23 @@ +waitVerticalBlank: + movem.l d0-a6,-(sp) +.loop move.l $dff004,d0 + and.l #$1ff00,d0 + cmp.l #303<<8,d0 + bne.b .loop + movem.l (sp)+,d0-a6 + rts + + + +waitRaster: ;wait for rasterline d0.w. Modifies d0-d2/a0. + movem.l d0-a6,-(sp) + move.l #$1ff00,d2 + lsl.l #8,d0 + and.l d2,d0 + lea $dff004,a0 +.wr: move.l (a0),d1 + and.l d2,d1 + cmp.l d1,d0 + bne.s .wr + movem.l (sp)+,d0-a6 + rts \ No newline at end of file