diff --git a/presets/atari7800/atari7800.h b/presets/atari7800/atari7800.h index 98f35369..15c1f3b4 100644 --- a/presets/atari7800/atari7800.h +++ b/presets/atari7800/atari7800.h @@ -1,3 +1,5 @@ +#ifndef _ATARI7800 +#define _ATARI7800 // define basic types for convenience typedef unsigned char byte; // 8-bit unsigned @@ -140,3 +142,5 @@ typedef struct DL5Entry { #define STROBE(addr) __asm__ ("sta %w", addr) #define WSYNC() STROBE(0x24) + +#endif diff --git a/presets/atari7800/dlist.c b/presets/atari7800/dlist.c deleted file mode 100644 index 42640551..00000000 --- a/presets/atari7800/dlist.c +++ /dev/null @@ -1,133 +0,0 @@ - -#include "atari7800.h" - -#include - -//#link "chr_font.s" - -//#link "generic8x16.s" - -#define SLOTHEIGHT 16 -#define DOUBLEBUFFER - -#ifdef DOUBLEBUFFER -#define NUMSLOTS 32 -#define SLOTSIZE 32 -byte slot0 = 0; -#else -#define NUMSLOTS 16 -#define SLOTSIZE 64 -const byte slot0 = 0; -#endif - - -byte DL[NUMSLOTS][SLOTSIZE]; -byte DL_len[NUMSLOTS]; -DLLEntry DLL[NUMSLOTS]; - -void dll_clear() { - byte i; - for (i=slot0; i>8; - MARIA.DPPL = (byte)(DLL+16); - } else { - MARIA.DPPH = (word)DLL>>8; - MARIA.DPPL = (byte)DLL; - } -} -#endif - -void* dll_alloc(byte slot, byte len) { - byte dlofs; - slot &= NUMSLOTS-1; - dlofs = DL_len[slot]; - DL_len[slot] += len; - DL[slot][dlofs+len+1] = 0; - return &DL[slot][dlofs]; -} - -void dll_add_sprite(word addr, byte x, byte y, byte wpal) { - byte slot = (y >> 4) | slot0; - register DL4Entry* dl = (DL4Entry*) dll_alloc(slot, 4); - dl->data_lo = (byte)addr; - dl->data_hi = (byte)(addr>>8) + (y & 15); - dl->xpos = x; - dl->width_pal = wpal; - if (y & 15) { - DL4Entry* dl2 = (DL4Entry*) dll_alloc(slot+1, 4); - *dl2 = *dl; - dl2->data_hi -= SLOTHEIGHT; - } -} - -void dll_add_string(const char* str, byte x, byte y, byte wpal) { - byte slot = (y >> 4) | slot0; - register DL5Entry* dl = (DL5Entry*) dll_alloc(slot, 5); - dl->data_lo = (byte)str; - dl->data_hi = (word)str>>8; - dl->flags = DL5_INDIRECT; - dl->width_pal = wpal; - dl->xpos = x; -} - -void dll_setup() { - byte i; - byte* dlptr = &DL[0][0]; - register DLLEntry *dll = &DLL[0]; - for (i=0; ioffset_flags = DLL_H16 | (SLOTHEIGHT-1); - dll->dl_hi = (word)dlptr>>8; - dll->dl_lo = (byte)dlptr; - dlptr += sizeof(DL[0]); - dll++; - } - dll_clear(); -#ifdef DOUBLEBUFFER - dll_swap(); - dll_clear(); -#endif -} - -char* hello = "\2\4\6\0\220\222\102"; - -void main() { - byte i; - byte y = 0; - - dll_setup(); - - // activate DMA - MARIA.CHARBASE = 0x80; - MARIA.DPPH = (word)DLL>>8; - MARIA.DPPL = (byte)DLL; - MARIA.CTRL = CTRL_DMA_ON | CTRL_DBLBYTE | CTRL_160AB; - MARIA.P0C1 = 0x8f; - MARIA.P0C2 = 0x4f; - MARIA.P0C3 = 0x1f; - MARIA.P1C1 = 0x34; - MARIA.P1C2 = 0x28; - MARIA.P1C3 = 0x1f; - MARIA.BACKGRND = 0; - - while (1) { - while ((MARIA.MSTAT & MSTAT_VBLANK) == 0) ; - dll_swap(); - dll_clear(); - dll_add_string(hello, y+32, 32, DL_WP(8,0)); - for (i=0; i<8; i++) { - dll_add_sprite(0xa068, i*4, i*16+y, DL_WP(4,1)); - dll_add_sprite(0xa06c, i*8+y, i*16, DL_WP(4,1)); - } - while ((MARIA.MSTAT & MSTAT_VBLANK) != 0) ; - y++; - } -} diff --git a/presets/atari7800/dll.c b/presets/atari7800/dll.c new file mode 100644 index 00000000..058ecbbd --- /dev/null +++ b/presets/atari7800/dll.c @@ -0,0 +1,150 @@ + +#include "dll.h" +#include + +DLLEntry DLL[NUMSLOTS]; // display list list +byte DL[NUMSLOTS][SLOTSIZE]; // display list slots +byte DL_len[NUMSLOTS]; // current bytes in each slot +#ifdef DLSAVE +byte DL_save[NUMSLOTS]; // save lengths of each slot +#endif + +byte slot0 = 0; // current page offset + +// set display list list address registers +void dll_set_addr(const void* dpp) { + MARIA.DPPH = (word)dpp>>8; + MARIA.DPPL = (byte)dpp; +} + +// clear the current page +void dll_clear() { + byte i; + for (i=slot0; idata_lo = (byte)addr; + dl->data_hi = (byte)(addr>>8) + (y & 15); + dl->xpos = x; + dl->width_pal = wpal; + if (y & 15) { + DL4Entry* dl2 = (DL4Entry*) dll_alloc(slot+1, 4); + *dl2 = *dl; + dl2->data_hi -= SLOTHEIGHT; + } +} + +// add a string to currently selected page +// strings are aligned to top of slot +void dll_add_string(const char* str, byte x, byte y, byte wpal) { + byte slot = (y / SLOTHEIGHT) | slot0; + register DL5Entry* dl = (DL5Entry*) dll_alloc(slot, 5); + dl->data_lo = (byte)str; + dl->data_hi = (word)str>>8; + dl->flags = DL5_INDIRECT; + dl->width_pal = wpal; + dl->xpos = x; +} + +// set up display lists +void dll_setup() { + byte i; + byte* dlptr = &DL[0][0]; + register DLLEntry *dll = &DLL[0]; + for (i=0; ioffset_flags = DLL_FLAGS | (SLOTHEIGHT-1); + dll->dl_hi = (word)dlptr>>8; + dll->dl_lo = (byte)dlptr; + dlptr += sizeof(DL[0]); + dll++; + } + dll_clear(); +#ifdef DOUBLEBUFFER + dll_swap(); + dll_clear(); + dll_swap(); +#else + dll_set_addr(DLL); +#endif +#ifdef DLSAVE + memset(DL_save, 0, sizeof(DL_save)); +#endif +} diff --git a/presets/atari7800/dll.h b/presets/atari7800/dll.h new file mode 100644 index 00000000..5e7b4976 --- /dev/null +++ b/presets/atari7800/dll.h @@ -0,0 +1,46 @@ +#ifndef _DLL_H +#define _DLL_H + +#include "atari7800.h" + +#define DLL_FLAGS DLL_H16 // 4k DMA holes +#define SLOTHEIGHT 16 // lines per display list +#define SLOTSIZE 32 // bytes per display list +#define SLOTSPERPAGE 16 // display lists per page +#define DOUBLEBUFFER // double buffer (2 pages) +#define DLSAVE // enable save buffer + +#ifdef DOUBLEBUFFER +#define NUMPAGES 2 +#else +#define NUMPAGES 1 +#endif +#define NUMSLOTS (SLOTSPERPAGE*NUMPAGES) + +extern DLLEntry DLL[NUMSLOTS]; // display list list +extern byte DL[NUMSLOTS][SLOTSIZE]; // display list slots +extern byte DL_len[NUMSLOTS]; // current bytes in each slot +#ifdef DLSAVE +extern byte DL_save[NUMSLOTS]; // save lengths of each slot +#endif + +// set current page (0 or 1) +#define dll_page(page) (slot0 = (page)*SLOTSPERPAGE) + +extern byte slot0; + +void dll_setup(void); +void dll_add_string(const char* str, byte x, byte y, byte wpal); +void dll_add_sprite(word addr, byte x, byte y, byte wpal); +sbyte dll_bytesleft(byte slot); +void* dll_alloc(byte slot, byte len); +void dll_set_scroll(byte y); +void dll_save(void); +void dll_restore(void); +void dll_restore_all(void); +void dll_clear(void); + +void dll_swap(void); +void dll_copy(void); + +#endif diff --git a/presets/atari7800/scroll.c b/presets/atari7800/scroll.c index 14d76f0f..8fd74df7 100644 --- a/presets/atari7800/scroll.c +++ b/presets/atari7800/scroll.c @@ -12,141 +12,14 @@ be written while the other is displayed. */ #include "atari7800.h" - #include +#include "dll.h" +//#link "dll.c" + //#link "chr_font.s" //#link "generic8x16.s" -#define DLL_FLAGS DLL_H16 -#define SLOTHEIGHT 16 -#define SLOTSIZE 32 -#define DOUBLEBUFFER -#define DLSAVE - -#ifdef DOUBLEBUFFER -#define NUMSLOTS 32 -byte slot0 = 0; -#else -#define NUMSLOTS 16 -const byte slot0 = 0; -#endif - - -DLLEntry DLL[NUMSLOTS]; - -byte DL[NUMSLOTS][SLOTSIZE]; -byte DL_len[NUMSLOTS]; - -#ifdef DLSAVE -byte DL_save[NUMSLOTS]; -#endif - -void dll_set_addr(const void* dpp) { - MARIA.DPPH = (word)dpp>>8; - MARIA.DPPL = (byte)dpp; -} - -void dll_clear() { - byte i; - for (i=slot0; idata_lo = (byte)addr; - dl->data_hi = (byte)(addr>>8) + (y & 15); - dl->xpos = x; - dl->width_pal = wpal; - if (y & 15) { - DL4Entry* dl2 = (DL4Entry*) dll_alloc(slot+1, 4); - *dl2 = *dl; - dl2->data_hi -= SLOTHEIGHT; - } -} - -void dll_add_string(const char* str, byte x, byte y, byte wpal) { - byte slot = (y / SLOTHEIGHT) | slot0; - register DL5Entry* dl = (DL5Entry*) dll_alloc(slot, 5); - dl->data_lo = (byte)str; - dl->data_hi = (word)str>>8; - dl->flags = DL5_INDIRECT; - dl->width_pal = wpal; - dl->xpos = x; -} - -void dll_setup() { - byte i; - byte* dlptr = &DL[0][0]; - register DLLEntry *dll = &DLL[0]; - for (i=0; ioffset_flags = DLL_FLAGS | (SLOTHEIGHT-1); - dll->dl_hi = (word)dlptr>>8; - dll->dl_lo = (byte)dlptr; - dlptr += sizeof(DL[0]); - dll++; - } - dll_clear(); -#ifdef DOUBLEBUFFER - dll_swap(); - dll_clear(); - dll_swap(); -#endif -#ifdef DLSAVE - memset(DL_save, 0, sizeof(DL_save)); -#endif -} - -// __MAIN__ - char* hello = "\2\4\6\0\220\222\102"; void main() { @@ -164,26 +37,31 @@ void main() { MARIA.P1C2 = 0x28; MARIA.P1C3 = 0x1f; MARIA.BACKGRND = 0; - dll_set_addr(DLL); MARIA.CTRL = CTRL_DMA_ON | CTRL_DBLBYTE | CTRL_160AB; dll_clear(); dll_add_string(hello, y+32, 32, DL_WP(8,0)); for (i=0; i<8; i++) { - slot0 = 0; + dll_page(0); dll_add_sprite(0xa068, i*4, i*33, DL_WP(4,1)); dll_add_sprite(0xa06c, i*8, i*25, DL_WP(4,1)); - slot0 = 16; + dll_page(1); dll_add_sprite(0xa068, i*4, i*32, DL_WP(4,1)); dll_add_sprite(0xa06c, 128-i*8, i*24, DL_WP(4,1)); } dll_save(); while (1) { + // wait for vsync to end while ((MARIA.MSTAT & MSTAT_VBLANK) == 0) ; dll_set_scroll(y); - dll_restore(); - dll_add_sprite(0xa06c, y, y, DL_WP(4,1)); + dll_restore_all(); + // first sprite doesn't have time to draw when y < 40 + dll_page(0); + dll_add_sprite(0xa06c, y, 128, DL_WP(4,1)); + dll_page(1); + dll_add_sprite(0xa06c, y, 0, DL_WP(4,1)); + // wait for vsync to start while ((MARIA.MSTAT & MSTAT_VBLANK) != 0) ; y++; } diff --git a/presets/atari7800/sprites.c b/presets/atari7800/sprites.c new file mode 100644 index 00000000..2a6341f1 --- /dev/null +++ b/presets/atari7800/sprites.c @@ -0,0 +1,88 @@ + +/* +This demo sets up two DLLs (Display List Lists) of +16 slots each. + +By swapping between the two DLLs each frame, one DLL can +be written while the other is displayed. +*/ + +#include "atari7800.h" +#include +#include + +#include "dll.h" +//#link "dll.c" + +//#link "chr_font.s" +//#link "generic8x16.s" + +#define NUMSPRITES 16 +byte xpos[NUMSPRITES]; +byte ypos[NUMSPRITES]; + +char* hello = "\2\4\6\0\220\222\102"; + +// draw a text string randomly into the background +void draw_background() { + byte x = rand(); + byte y = rand(); + if (dll_bytesleft(y/SLOTHEIGHT) > 20) { + dll_add_string(hello, x, y, DL_WP(7,0)); + dll_swap(); + dll_copy(); + dll_save(); + } +} + +void main() { + byte i; + byte y = 0; + + dll_setup(); + + // activate DMA + MARIA.CHARBASE = 0x80; + MARIA.P0C1 = 0x8f; + MARIA.P0C2 = 0x4f; + MARIA.P0C3 = 0x1f; + MARIA.P1C1 = 0x34; + MARIA.P1C2 = 0x28; + MARIA.P1C3 = 0x1f; + MARIA.BACKGRND = 0; + MARIA.CTRL = CTRL_DMA_ON | CTRL_DBLBYTE | CTRL_160AB; + + // set background sprites and save to buffer + dll_clear(); + draw_background(); + + // set up sprite positions randomly + for (i=0; i