diff --git a/scrolling_tricks/.gitignore b/scrolling_tricks/.gitignore index 00dc32a..635e0e1 100644 --- a/scrolling_tricks/.gitignore +++ b/scrolling_tricks/.gitignore @@ -3,3 +3,5 @@ xlimited xylimited xyunlimited xyunlimited2 +yunlimited +yunlimited2 diff --git a/scrolling_tricks/Makefile b/scrolling_tricks/Makefile index 709f4c2..4d275a1 100644 --- a/scrolling_tricks/Makefile +++ b/scrolling_tricks/Makefile @@ -1,7 +1,7 @@ ASM=vasmm68k_mot ASM_FLAGS = -Fhunk -devpac .SUFFIXES = .o .asm .c -PROGRAMS=xunlimited xlimited xylimited xyunlimited xyunlimited2 +PROGRAMS=xunlimited xlimited xylimited xyunlimited xyunlimited2 yunlimited yunlimited2 CC=vc +aos68k CFLAGS=-c99 -I$(NDK_INC) -DDEBUG @@ -20,7 +20,6 @@ clean: xunlimited: hardware.o cop_x.o common.o xunlimited.o $(CC) -o $@ $^ -lamiga -lauto - xlimited: hardware.o cop_x.o common.o xlimited.o $(CC) -o $@ $^ -lamiga -lauto @@ -32,3 +31,9 @@ xyunlimited: hardware.o cop_xy.o common.o xyunlimited.o xyunlimited2: hardware.o cop_xy.o common.o xyunlimited2.o $(CC) -o $@ $^ -lamiga -lauto + +yunlimited: hardware.o cop_y.o common.o yunlimited.o + $(CC) -o $@ $^ -lamiga -lauto + +yunlimited2: hardware.o cop_y2.o common.o yunlimited2.o + $(CC) -o $@ $^ -lamiga -lauto diff --git a/scrolling_tricks/README.md b/scrolling_tricks/README.md index c86a1e7..f2afde0 100644 --- a/scrolling_tricks/README.md +++ b/scrolling_tricks/README.md @@ -1,13 +1,38 @@ # Scrolling Tricks -This is a project to rework the Aminet Scrolling Tricks by Georg Steger into a -version that has higher internal reuse, is smaller and compiles with -VBCC. The purpose is mainly to better understand the algorithms +## Description -# System Requirements +This is a project to rework the Aminet Scrolling Tricks project by Georg Steger into a +version that has higher internal reuse, is smaller and compiles with VBCC. The purpose +is mainly to better understand the algorithms. By separating the common functionality such +as data loading and argument parsing the main source file can mainly focus on screen setup +and scrolling. + +## System Requirements This software requires V39 libraries and therefore only runs on the -3.x releases or greater of AmigaOS +3.x releases or greater of AmigaOS. The reason is that the original source +relies on the support for interleaved bitmaps in graphics.library, which was +not available in earlier versions. + +I originally wanted to backport this to 1.x, but that would defeat the purpose +as a pure study project. + +## Building + +This project was built and tested on a cross-compiling system using VBCC on Linux. +Make sure your NDK_INC path is set to the directory that includes the NDK include +files for C. + +The programs should all be built with + +make + +## Running + +I used FS-UAE, but it should run on any classic 68k AmigaOS system starting from +version 3.0. + ## Original source diff --git a/scrolling_tricks/common.c b/scrolling_tricks/common.c index f09c288..642e3fb 100644 --- a/scrolling_tricks/common.c +++ b/scrolling_tricks/common.c @@ -105,7 +105,7 @@ BOOL read_level_map(const char *path, struct LevelMap *level_map, char *s) return TRUE; } -struct BitMap *read_blocks(UWORD *colors, char *s, int blocks_width, int blocks_height) +struct BitMap *read_blocks(const char *path, UWORD *colors, char *s, int blocks_width, int blocks_height) { LONG l; struct BitMap *bitmap; @@ -120,7 +120,7 @@ struct BitMap *read_blocks(UWORD *colors, char *s, int blocks_width, int blocks_ return NULL; } - if (!(fhandle = Open(BLOCKSNAME, MODE_OLDFILE))) { + if (!(fhandle = Open(path, MODE_OLDFILE))) { Fault(IoErr(), 0, s, 255); FreeBitMap(bitmap); return NULL; diff --git a/scrolling_tricks/common.h b/scrolling_tricks/common.h index db3e161..2c8520e 100644 --- a/scrolling_tricks/common.h +++ b/scrolling_tricks/common.h @@ -39,6 +39,6 @@ struct LevelMap { extern ULONG get_mode_id(BOOL option_how, BOOL option_ntsc); extern BOOL get_arguments(struct PrgOptions *options, char *s); extern BOOL read_level_map(const char * path, struct LevelMap *level_map, char *s); -extern struct BitMap *read_blocks(UWORD *colors, char *s, int blocks_width, int blocks_height); +extern struct BitMap *read_blocks(const char *path, UWORD *colors, char *s, int blocks_width, int blocks_height); #endif /* __COMMON_H__ */ diff --git a/scrolling_tricks/cop_y.asm b/scrolling_tricks/cop_y.asm new file mode 100644 index 0000000..3e3696e --- /dev/null +++ b/scrolling_tricks/cop_y.asm @@ -0,0 +1,115 @@ + SECTION copperlist,DATA,CHIP + + XDEF _CopperList + XDEF _CopFETCHMODE + XDEF _CopBPLCON0 + XDEF _CopBPLCON1 + XDEF _CopBPLCON3 + XDEF _CopBPLMODA + XDEF _CopBPLMODB + XDEF _CopDIWSTART + XDEF _CopDIWSTOP + XDEF _CopDDFSTART + XDEF _CopDDFSTOP + XDEF _CopPLANE1H + XDEF _CopPLANE1L + XDEF _CopPLANE2H + XDEF _CopPLANE2L + XDEF _CopPLANE3H + XDEF _CopPLANE3L + XDEF _CopPLANE4H + XDEF _CopPLANE4L + XDEF _CopPLANE5H + XDEF _CopPLANE5L + XDEF _CopPLANE6H + XDEF _CopPLANE6L + XDEF _CopPLANE7H + XDEF _CopPLANE7L + XDEF _CopPLANE8H + XDEF _CopPLANE8L + +_CopperList: + dc.w $180,0 + +_CopFETCHMODE: + dc.w $1FC,0 + +_CopBPLCON0: + dc.w $100,0 + +_CopBPLCON1: + dc.w $102,0 + +_CopBPLCON3: + dc.w $106,0 + +_CopBPLMODA: + dc.w $108,0 + +_CopBPLMODB: + dc.w $10A,0 + +_CopDIWSTART: + dc.w $8e,0 + +_CopDIWSTOP: + dc.w $90,0 + +_CopDDFSTART: + dc.w $92,0 + +_CopDDFSTOP: + dc.w $94,0 + +_CopPLANE1H: + dc.w $e0,0 + +_CopPLANE1L: + dc.w $e2,0 + +_CopPLANE2H: + dc.w $e4,0 + +_CopPLANE2L: + dc.w $e6,0 + +_CopPLANE3H: + dc.w $e8,0 + +_CopPLANE3L: + dc.w $ea,0 + +_CopPLANE4H: + dc.w $ec,0 + +_CopPLANE4L: + dc.w $ee,0 + +_CopPLANE5H: + dc.w $f0,0 + +_CopPLANE5L: + dc.w $f2,0 + +_CopPLANE6H: + dc.w $f4,0 + +_CopPLANE6L: + dc.w $f6,0 + +_CopPLANE7H: + dc.w $f8,0 + +_CopPLANE7L: + dc.w $fa,0 + +_CopPLANE8H: + dc.w $fc,0 + +_CopPLANE8L: + dc.w $fe,0 + + dc.w -1,-2 + + END + diff --git a/scrolling_tricks/cop_y.h b/scrolling_tricks/cop_y.h new file mode 100644 index 0000000..385fa5d --- /dev/null +++ b/scrolling_tricks/cop_y.h @@ -0,0 +1,28 @@ +extern WORD CopperList[]; +extern WORD CopFETCHMODE[]; +extern WORD CopBPLCON0[]; +extern WORD CopBPLCON1[]; +extern WORD CopBPLCON3[]; +extern WORD CopBPLMODA[]; +extern WORD CopBPLMODB[]; +extern WORD CopDIWSTART[]; +extern WORD CopDIWSTOP[]; +extern WORD CopDDFSTART[]; +extern WORD CopDDFSTOP[]; +extern WORD CopPLANE1H[]; +extern WORD CopPLANE1L[]; +extern WORD CopPLANE2H[]; +extern WORD CopPLANE2L[]; +extern WORD CopPLANE3H[]; +extern WORD CopPLANE3L[]; +extern WORD CopPLANE4H[]; +extern WORD CopPLANE4L[]; +extern WORD CopPLANE5H[]; +extern WORD CopPLANE5L[]; +extern WORD CopPLANE6H[]; +extern WORD CopPLANE6L[]; +extern WORD CopPLANE7H[]; +extern WORD CopPLANE7L[]; +extern WORD CopPLANE8H[]; +extern WORD CopPLANE8L[]; + diff --git a/scrolling_tricks/cop_y2.asm b/scrolling_tricks/cop_y2.asm new file mode 100644 index 0000000..4f419f7 --- /dev/null +++ b/scrolling_tricks/cop_y2.asm @@ -0,0 +1,171 @@ + SECTION copperlist,DATA,CHIP + + XDEF _CopperList + XDEF _CopFETCHMODE + XDEF _CopBPLCON0 + XDEF _CopBPLCON1 + XDEF _CopBPLCON3 + XDEF _CopBPLMODA + XDEF _CopBPLMODB + XDEF _CopDIWSTART + XDEF _CopDIWSTOP + XDEF _CopDDFSTART + XDEF _CopDDFSTOP + XDEF _CopPLANE1H + XDEF _CopPLANE1L + XDEF _CopPLANE2H + XDEF _CopPLANE2L + XDEF _CopPLANE3H + XDEF _CopPLANE3L + XDEF _CopPLANE4H + XDEF _CopPLANE4L + XDEF _CopPLANE5H + XDEF _CopPLANE5L + XDEF _CopPLANE6H + XDEF _CopPLANE6L + XDEF _CopPLANE7H + XDEF _CopPLANE7L + XDEF _CopPLANE8H + XDEF _CopPLANE8L + + XDEF _CopVIDEOSPLIT + XDEF _CopVIDEOSPLITMODULO + XDEF _CopVIDEOSPLIT2 + XDEF _CopVIDEOSPLITRESETMODULO + + XDEF _CopPLANE2_1H + XDEF _CopPLANE2_2H + XDEF _CopPLANE2_3H + XDEF _CopPLANE2_4H + XDEF _CopPLANE2_5H + XDEF _CopPLANE2_6H + XDEF _CopPLANE2_7H + XDEF _CopPLANE2_8H + +_CopperList: + dc.w $180,0 + +_CopFETCHMODE: + dc.w $1FC,0 + +_CopBPLCON0: + dc.w $100,0 + +_CopBPLCON1: + dc.w $102,0 + +_CopBPLCON3: + dc.w $106,0 + +_CopBPLMODA: + dc.w $108,0 + +_CopBPLMODB: + dc.w $10A,0 + +_CopDIWSTART: + dc.w $8e,0 + +_CopDIWSTOP: + dc.w $90,0 + +_CopDDFSTART: + dc.w $92,0 + +_CopDDFSTOP: + dc.w $94,0 + + dc.w $2001,-2 + +_CopPLANE1H: + dc.w $e0,0 + +_CopPLANE1L: + dc.w $e2,0 + +_CopPLANE2H: + dc.w $e4,0 + +_CopPLANE2L: + dc.w $e6,0 + +_CopPLANE3H: + dc.w $e8,0 + +_CopPLANE3L: + dc.w $ea,0 + +_CopPLANE4H: + dc.w $ec,0 + +_CopPLANE4L: + dc.w $ee,0 + +_CopPLANE5H: + dc.w $f0,0 + +_CopPLANE5L: + dc.w $f2,0 + +_CopPLANE6H: + dc.w $f4,0 + +_CopPLANE6L: + dc.w $f6,0 + +_CopPLANE7H: + dc.w $f8,0 + +_CopPLANE7L: + dc.w $fa,0 + +_CopPLANE8H: + dc.w $fc,0 + +_CopPLANE8L: + dc.w $fe,0 + +_CopVIDEOSPLIT: + dc.w -1,-2 + dc.w -1,-2 + +_CopVIDEOSPLITMODULO: + dc.w $108,0 + dc.w $10A,0 + +_CopVIDEOSPLIT2: + dc.w -1,-2 + dc.w -1,-2 + +_CopPLANE2_1H: + dc.w $e0,0 + +_CopPLANE2_2H: + dc.w $e4,0 + +_CopPLANE2_3H: + dc.w $e8,0 + +_CopPLANE2_4H: + dc.w $ec,0 + +_CopPLANE2_5H: + dc.w $f0,0 + +_CopPLANE2_6H: + dc.w $f4,0 + +_CopPLANE2_7H: + dc.w $f8,0 + +_CopPLANE2_8H: + dc.w $fc,0 + +_CopVIDEOSPLITRESETMODULO: + dc.w $108,0 + dc.w $10A,0 + + dc.w -1,-2 + + END + diff --git a/scrolling_tricks/cop_y2.h b/scrolling_tricks/cop_y2.h new file mode 100644 index 0000000..168df34 --- /dev/null +++ b/scrolling_tricks/cop_y2.h @@ -0,0 +1,44 @@ +extern WORD CopperList[]; +extern WORD CopFETCHMODE[]; +extern WORD CopBPLCON0[]; +extern WORD CopBPLCON1[]; +extern WORD CopBPLCON3[]; +extern WORD CopBPLMODA[]; +extern WORD CopBPLMODB[]; +extern WORD CopDIWSTART[]; +extern WORD CopDIWSTOP[]; +extern WORD CopDDFSTART[]; +extern WORD CopDDFSTOP[]; +extern WORD CopPLANE1H[]; +extern WORD CopPLANE1L[]; +extern WORD CopPLANE2H[]; +extern WORD CopPLANE2L[]; +extern WORD CopPLANE3H[]; +extern WORD CopPLANE3L[]; +extern WORD CopPLANE4H[]; +extern WORD CopPLANE4L[]; +extern WORD CopPLANE5H[]; +extern WORD CopPLANE5L[]; +extern WORD CopPLANE6H[]; +extern WORD CopPLANE6L[]; +extern WORD CopPLANE7H[]; +extern WORD CopPLANE7L[]; +extern WORD CopPLANE8H[]; +extern WORD CopPLANE8L[]; + +extern WORD CopVIDEOSPLIT[]; +extern WORD CopVIDEOSPLITMODULO[]; +extern WORD CopVIDEOSPLIT2[]; + +extern WORD CopPLANE2_1H[]; +extern WORD CopPLANE2_2H[]; +extern WORD CopPLANE2_3H[]; +extern WORD CopPLANE2_4H[]; +extern WORD CopPLANE2_5H[]; +extern WORD CopPLANE2_6H[]; +extern WORD CopPLANE2_7H[]; +extern WORD CopPLANE2_8H[]; + +extern WORD CopVIDEOSPLITRESETMODULO[]; + + diff --git a/scrolling_tricks/global_defs.h b/scrolling_tricks/global_defs.h index fccfe80..2276baa 100644 --- a/scrolling_tricks/global_defs.h +++ b/scrolling_tricks/global_defs.h @@ -10,7 +10,11 @@ #define ARG_FMODE 4 #define NUM_ARGS 5 -#define BLOCKSNAME "blocks/demoblocks.raw" +#define DEMO_BLOCKS_PATH "blocks/demoblocks.raw" +#define LARGE_MAP_PATH "maps/large.raw" +#define SCROLLER_MAP_PATH "maps/scroller.raw" +#define RACE_BLOCKS_PATH "blocks/raceblocks.raw" +#define RACE_MAP_PATH "maps/race.raw" #define SCREENWIDTH 320 #define SCREENHEIGHT 256 diff --git a/scrolling_tricks/xlimited.c b/scrolling_tricks/xlimited.c index 5591296..9e56904 100644 --- a/scrolling_tricks/xlimited.c +++ b/scrolling_tricks/xlimited.c @@ -19,7 +19,6 @@ #include "global_defs.h" #include "common.h" -#define MAPNAME "maps/large.raw" #define EXTRAWIDTH 32 #define BITMAPWIDTH (SCREENWIDTH + EXTRAWIDTH) @@ -417,10 +416,10 @@ int main(int argc, char **argv) { BOOL res = get_arguments(&options, s); if (!res) Cleanup(s); - res = read_level_map(MAPNAME, &level_map, s); + res = read_level_map(LARGE_MAP_PATH, &level_map, s); if (!res) Cleanup(s); - BlocksBitmap = read_blocks(colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + BlocksBitmap = read_blocks(DEMO_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); if (!BlocksBitmap) Cleanup(s); blocksbuffer = BlocksBitmap->Planes[0]; diff --git a/scrolling_tricks/xunlimited.c b/scrolling_tricks/xunlimited.c index a4c5c25..d9e4169 100644 --- a/scrolling_tricks/xunlimited.c +++ b/scrolling_tricks/xunlimited.c @@ -19,7 +19,6 @@ #include "global_defs.h" #include "common.h" -#define MAPNAME "maps/large.raw" #define EXTRAWIDTH 32 #define BITMAPWIDTH ((SCREENWIDTH + EXTRAWIDTH) * 2) @@ -357,10 +356,10 @@ int main(int argc, char **argv) { BOOL res = get_arguments(&options, s); if (!res) Cleanup(s); - res = read_level_map(MAPNAME, &level_map, s); + res = read_level_map(LARGE_MAP_PATH, &level_map, s); if (!res) Cleanup(s); - BlocksBitmap = read_blocks(colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + BlocksBitmap = read_blocks(DEMO_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); if (!BlocksBitmap) Cleanup(s); blocksbuffer = BlocksBitmap->Planes[0]; diff --git a/scrolling_tricks/xylimited.c b/scrolling_tricks/xylimited.c index 8a1297a..12affd4 100644 --- a/scrolling_tricks/xylimited.c +++ b/scrolling_tricks/xylimited.c @@ -19,7 +19,6 @@ #include "global_defs.h" #include "common.h" -#define MAPNAME "maps/Scroller.raw" #define EXTRAWIDTH 64 #define EXTRAHEIGHT 32 @@ -780,10 +779,10 @@ int main(int argc, char **argv) { BOOL res = get_arguments(&options, s); if (!res) Cleanup(s); - res = read_level_map(MAPNAME, &level_map, s); + res = read_level_map(SCROLLER_MAP_PATH, &level_map, s); if (!res) Cleanup(s); - BlocksBitmap = read_blocks(colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + BlocksBitmap = read_blocks(DEMO_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); if (!BlocksBitmap) Cleanup(s); blocksbuffer = BlocksBitmap->Planes[0]; diff --git a/scrolling_tricks/xyunlimited.c b/scrolling_tricks/xyunlimited.c index 54b1b16..6a5a0b1 100644 --- a/scrolling_tricks/xyunlimited.c +++ b/scrolling_tricks/xyunlimited.c @@ -19,7 +19,6 @@ #include "global_defs.h" #include "common.h" -#define MAPNAME "maps/scroller.raw" #define EXTRAWIDTH 64 #define EXTRAHEIGHT 32 @@ -63,8 +62,8 @@ struct Screen *scr; struct RastPort *ScreenRastPort; -struct BitMap *BlocksBitmap,*ScreenBitmap; -UBYTE *frontbuffer,*blocksbuffer; +struct BitMap *BlocksBitmap, *ScreenBitmap; +UBYTE *frontbuffer, *blocksbuffer; WORD mapposx,mapposy,videoposx,videoposy,block_videoposy; WORD mapblockx,mapblocky,stepx,stepy; @@ -866,10 +865,10 @@ int main(int argc, char **argv) { BOOL res = get_arguments(&options, s); if (!res) Cleanup(s); - res = read_level_map(MAPNAME, &level_map, s); + res = read_level_map(SCROLLER_MAP_PATH, &level_map, s); if (!res) Cleanup(s); - BlocksBitmap = read_blocks(colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + BlocksBitmap = read_blocks(DEMO_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); if (!BlocksBitmap) Cleanup(s); blocksbuffer = BlocksBitmap->Planes[0]; diff --git a/scrolling_tricks/xyunlimited2.c b/scrolling_tricks/xyunlimited2.c index ed60eea..c6ef22e 100644 --- a/scrolling_tricks/xyunlimited2.c +++ b/scrolling_tricks/xyunlimited2.c @@ -19,7 +19,6 @@ #include "global_defs.h" #include "common.h" -#define MAPNAME "maps/scroller.raw" #define EXTRAWIDTH 64 #define EXTRAHEIGHT 32 @@ -884,10 +883,10 @@ int main(int argc, char *argv) { BOOL res = get_arguments(&options, s); if (!res) Cleanup(s); - res = read_level_map(MAPNAME, &level_map, s); + res = read_level_map(SCROLLER_MAP_PATH, &level_map, s); if (!res) Cleanup(s); - BlocksBitmap = read_blocks(colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + BlocksBitmap = read_blocks(DEMO_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); if (!BlocksBitmap) Cleanup(s); blocksbuffer = BlocksBitmap->Planes[0]; diff --git a/scrolling_tricks/yunlimited.c b/scrolling_tricks/yunlimited.c new file mode 100644 index 0000000..3b7926d --- /dev/null +++ b/scrolling_tricks/yunlimited.c @@ -0,0 +1,412 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "hardware.h" +#include "cop_y.h" +#include "global_defs.h" +#include "common.h" + +#define EXTRAHEIGHT 32 + +#define BITMAPWIDTH SCREENWIDTH +#define BITMAPBYTESPERROW (BITMAPWIDTH / 8) +#define BITMAPHEIGHT ((SCREENHEIGHT + EXTRAHEIGHT) * 2) +#define HALFBITMAPHEIGHT (BITMAPHEIGHT / 2) + +#define BLOCKSWIDTH 320 +#define BLOCKSHEIGHT 200 + +#define BLOCKSBYTESPERROW (BLOCKSWIDTH / 8) +#define BLOCKSPERROW (BLOCKSWIDTH / BLOCKWIDTH) + +#define BITMAPBLOCKSPERROW (BITMAPWIDTH / BLOCKWIDTH) +#define BITMAPBLOCKSPERCOL (BITMAPHEIGHT / BLOCKHEIGHT) +#define HALFBITMAPBLOCKSPERCOL (BITMAPBLOCKSPERCOL / 2) + +#define VISIBLEBLOCKSX (SCREENWIDTH / BLOCKWIDTH) +#define VISIBLEBLOCKSY (SCREENHEIGHT / BLOCKHEIGHT) + +#define BITMAPPLANELINES (BITMAPHEIGHT * BLOCKSDEPTH) +#define BLOCKPLANELINES (BLOCKHEIGHT * BLOCKSDEPTH) + +#define BLOCKSFILESIZE (BLOCKSWIDTH * BLOCKSHEIGHT * BLOCKSPLANES / 8 + PALSIZE) + +// calculate how many times (steps) y-scrolling needs to +// blit two blocks instead of one block to make sure a +// complete row is blitted after 16 pixels of y-scrolling +// +// x * 2 + (16 - x) = BITMAPBLOCKSPERROW +// 2x + 16 - x = BITMAPBLOCKSPERROW +// x = BITMAPBLOCKSPERROW - 16 + +#define TWOBLOCKS (BITMAPBLOCKSPERROW - NUMSTEPS) +#define TWOBLOCKSTEP (NUMSTEPS - TWOBLOCKS) + +struct Screen *scr; +struct RastPort *ScreenRastPort; +struct BitMap *BlocksBitmap,*ScreenBitmap; +UBYTE *frontbuffer, *blocksbuffer; + +WORD mapposy,videoposy; +WORD bitmapheight; + +struct PrgOptions options; +struct LevelMap level_map; + +UWORD colors[BLOCKSCOLORS]; +char s[256]; + +struct FetchInfo fetchinfo [] = +{ + {0x38,0xD0,0}, /* normal */ + {0x38,0xC8,0}, /* BPL32 */ + {0x38,0xC8,0}, /* BPAGEM */ + {0x38,0xB8,0} /* BPL32 + BPAGEM */ +}; + +/************* SETUP/CLEANUP ROUTINES ***************/ + +static void Cleanup (char *msg) +{ + WORD rc; + if (msg) { + printf("Error: %s\n",msg); + rc = RETURN_WARN; + } else { + rc = RETURN_OK; + } + + if (scr) CloseScreen(scr); + + if (ScreenBitmap) { + WaitBlit(); + FreeBitMap(ScreenBitmap); + } + + if (BlocksBitmap) { + WaitBlit(); + FreeBitMap(BlocksBitmap); + } + if (level_map.raw_map) FreeVec(level_map.raw_map); + exit(rc); +} + +static void OpenDisplay(void) +{ + DisplayInfoHandle dih; + struct DimensionInfo diminfo; + ULONG modeid; + LONG l; + + bitmapheight = BITMAPHEIGHT + 3; + + if (!(ScreenBitmap = AllocBitMap(BITMAPWIDTH, bitmapheight, BLOCKSDEPTH, + BMF_STANDARD | BMF_INTERLEAVED | BMF_CLEAR,0))) { + Cleanup("Can't alloc screen bitmap!"); + } + frontbuffer = ScreenBitmap->Planes[0]; + + if (!(TypeOfMem(ScreenBitmap->Planes[0]) & MEMF_CHIP)) { + Cleanup("Screen bitmap is not in CHIP RAM!?? If you have a gfx card try disabling \"planes to fast\" or similiar options in your RTG system!"); + } + + l = GetBitMapAttr(ScreenBitmap,BMA_FLAGS); + if (!(GetBitMapAttr(ScreenBitmap,BMA_FLAGS) & BMF_INTERLEAVED)) { + Cleanup("Screen bitmap is not in interleaved format!??"); + } + + modeid = get_mode_id(options.how, options.ntsc); + if (!(scr = OpenScreenTags(0,SA_Width,BITMAPWIDTH, + SA_Height,bitmapheight, + SA_Depth,BLOCKSDEPTH, + SA_DisplayID,modeid, + SA_BitMap,ScreenBitmap, + options.how ? SA_Overscan : TAG_IGNORE,OSCAN_TEXT, + options.how ? SA_AutoScroll : TAG_IGNORE,TRUE, + SA_Quiet,TRUE, + TAG_DONE))) + { + Cleanup("Can't open screen!"); + } + + if (scr->RastPort.BitMap->Planes[0] != ScreenBitmap->Planes[0]) + { + Cleanup("Screen was not created with the custom bitmap I supplied!??"); + } + ScreenRastPort = &scr->RastPort; + LoadRGB4(&scr->ViewPort,colors,BLOCKSCOLORS); +} + +static void InitCopperlist(void) +{ + WORD *wp; + LONG l; + + WaitVBL(); + + custom->dmacon = 0x7FFF; + custom->beamcon0 = options.ntsc ? 0 : DISPLAYPAL; + + CopFETCHMODE[1] = options.fetchmode; + + // bitplane control registers + + CopBPLCON0[1] = ((BLOCKSDEPTH * BPL0_BPU0_F) & BPL0_BPUMASK) + + ((BLOCKSDEPTH / 8) * BPL0_BPU3_F) + + BPL0_COLOR_F + + (options.speed ? 0 : BPL0_USEBPLCON3_F); + + CopBPLCON1[1] = 0; + + CopBPLCON3[1] = BPLCON3_BRDNBLNK; + + // bitplane modulos + + l = BITMAPBYTESPERROW * BLOCKSDEPTH - + SCREENBYTESPERROW - fetchinfo[options.fetchmode].modulooffset; + + CopBPLMODA[1] = l; + CopBPLMODB[1] = l; + + // display window start/stop + CopDIWSTART[1] = DIWSTART; + CopDIWSTOP[1] = DIWSTOP; + + // display data fetch start/stop + CopDDFSTART[1] = fetchinfo[options.fetchmode].ddfstart; + CopDDFSTOP[1] = fetchinfo[options.fetchmode].ddfstop; + + // plane pointers + + wp = CopPLANE1H; + + for (l = 0; l < BLOCKSDEPTH; l++) { + wp[1] = (WORD)(((ULONG)ScreenBitmap->Planes[l]) >> 16); + wp[3] = (WORD)(((ULONG)ScreenBitmap->Planes[l]) & 0xFFFF); + wp += 4; + } + custom->intena = 0x7FFF; + custom->dmacon = DMAF_SETCLR | DMAF_BLITTER | DMAF_COPPER | DMAF_RASTER | DMAF_MASTER; + custom->cop2lc = (ULONG)CopperList; +} + +/******************* SCROLLING **********************/ + +static void DrawBlock(LONG x,LONG y,LONG mapx,LONG mapy) +{ + UBYTE block; + + // x = in pixels + // y = in "planelines" (1 realline = BLOCKSDEPTH planelines) + x = (x / 8) & 0xFFFE; + y = y * BITMAPBYTESPERROW; + + block = level_map.data[mapy * level_map.width + mapx]; + + mapx = (block % BLOCKSPERROW) * (BLOCKWIDTH / 8); + mapy = (block / BLOCKSPERROW) * (BLOCKPLANELINES * BLOCKSBYTESPERROW); + + if (options.how) OwnBlitter(); + + HardWaitBlit(); + + custom->bltcon0 = 0x9F0; // use A and D. Op: D = A + custom->bltcon1 = 0; + custom->bltafwm = 0xFFFF; + custom->bltalwm = 0xFFFF; + custom->bltamod = BLOCKSBYTESPERROW - (BLOCKWIDTH / 8); + custom->bltdmod = BITMAPBYTESPERROW - (BLOCKWIDTH / 8); + custom->bltapt = blocksbuffer + mapy + mapx; + custom->bltdpt = frontbuffer + y + x; + + custom->bltsize = BLOCKPLANELINES * 64 + (BLOCKWIDTH / 16); + + if (options.how) DisownBlitter(); +} + +static void FillScreen(void) +{ + WORD a,b,x,y; + + for (b = 0; b < HALFBITMAPBLOCKSPERCOL; b++) { + for (a = 0; a < BITMAPBLOCKSPERROW; a++) { + x = a * BLOCKWIDTH; + y = b * BLOCKPLANELINES; + DrawBlock(x,y,a,b); + DrawBlock(x,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,a,b); + } + } +} + +static void ScrollUp(void) +{ + WORD mapx,mapy,x,y; + + if (mapposy < 1) return; + + mapposy--; + videoposy = mapposy % HALFBITMAPHEIGHT; + + mapx = mapposy & (NUMSTEPS - 1); + mapy = mapposy / BLOCKHEIGHT; + y = ROUND2BLOCKHEIGHT(videoposy) * BLOCKSDEPTH; + + if (mapx < TWOBLOCKSTEP) { + // blit only one block per half bitmap + x = mapx * BLOCKWIDTH; + DrawBlock(x,y,mapx,mapy); + DrawBlock(x,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,mapx,mapy); + } else { + // blit two blocks per half bitmap + mapx = TWOBLOCKSTEP + (mapx - TWOBLOCKSTEP) * 2; + x = mapx * BLOCKWIDTH; + + DrawBlock(x,y,mapx,mapy); + DrawBlock(x,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,mapx,mapy); + + DrawBlock(x + BLOCKWIDTH,y,mapx + 1,mapy); + DrawBlock(x + BLOCKWIDTH,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,mapx + 1,mapy); + } +} + +static void ScrollDown(void) +{ + WORD mapx,mapy,x,y; + + if (mapposy >= (level_map.height * BLOCKHEIGHT - SCREENHEIGHT - BLOCKHEIGHT)) return; + + mapx = mapposy & (NUMSTEPS - 1); + mapy = HALFBITMAPBLOCKSPERCOL + mapposy / BLOCKHEIGHT; + + y = ROUND2BLOCKHEIGHT(videoposy) * BLOCKSDEPTH; + + if (mapx < TWOBLOCKSTEP) { + // blit only one block per half bitmap + x = mapx * BLOCKWIDTH; + DrawBlock(x,y,mapx,mapy); + DrawBlock(x,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,mapx,mapy); + } else { + // blit two blocks per half bitmap + mapx = TWOBLOCKSTEP + (mapx - TWOBLOCKSTEP) * 2; + x = mapx * BLOCKWIDTH; + + DrawBlock(x,y,mapx,mapy); + DrawBlock(x,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,mapx,mapy); + + DrawBlock(x + BLOCKWIDTH,y,mapx + 1,mapy); + DrawBlock(x + BLOCKWIDTH,y + HALFBITMAPHEIGHT * BLOCKSDEPTH,mapx + 1,mapy); + } + + mapposy++; + videoposy = mapposy % HALFBITMAPHEIGHT; +} + +static void CheckJoyScroll(void) +{ + WORD i,count; + + if (JoyFire()) count = 8; else count = 1; + + if (JoyUp()) { + for (i = 0; i < count; i++) { + ScrollUp(); + } + } + + if (JoyDown()) { + for (i = 0; i < count; i++) { + ScrollDown(); + } + } +} + +static void UpdateCopperlist(void) +{ + ULONG pl; + LONG planeadd; + WORD i; + WORD *wp; + + planeadd = ((LONG)(videoposy + BLOCKHEIGHT)) * BITMAPBYTESPERROW * BLOCKSDEPTH; + + // set plane pointers + wp = CopPLANE1H; + + for (i = 0; i < BLOCKSDEPTH; i++) { + pl = ((ULONG)ScreenBitmap->Planes[i]) + planeadd; + wp[1] = (WORD)(pl >> 16); + wp[3] = (WORD)(pl & 0xFFFF); + wp += 4; + } +} + +static void MainLoop(void) +{ + if (!options.how) { + // activate copperlist + HardWaitBlit(); + WaitVBL(); + custom->copjmp2 = 0; + } + + while (!LMBDown()) { + if (!options.how) { + WaitVBeam(199); + WaitVBeam(200); + } else { + Delay(1); + } + if (options.speed) *(WORD *)0xdff180 = 0xFF0; + + CheckJoyScroll(); + + if (options.speed) *(WORD *)0xdff180 = 0xF00; + + if (!options.how) { + UpdateCopperlist(); + } + } +} + +/********************* MAIN *************************/ + +int main(int argc, char **argv) +{ + BOOL res = get_arguments(&options, s); + if (!res) Cleanup(s); + res = read_level_map(RACE_MAP_PATH, &level_map, s); + if (!res) Cleanup(s); + + BlocksBitmap = read_blocks(RACE_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + if (!BlocksBitmap) Cleanup(s); + blocksbuffer = BlocksBitmap->Planes[0]; + + OpenDisplay(); + + if (!options.how) { + Delay(2*50); + KillSystem(); + InitCopperlist(); + } + FillScreen(); + MainLoop(); + + if (!options.how) { + ActivateSystem(); + } + Cleanup(0); + return 0; +} diff --git a/scrolling_tricks/yunlimited2.c b/scrolling_tricks/yunlimited2.c new file mode 100644 index 0000000..d19d2cf --- /dev/null +++ b/scrolling_tricks/yunlimited2.c @@ -0,0 +1,461 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "hardware.h" +#include "cop_y2.h" +#include "global_defs.h" +#include "common.h" + +#define EXTRAHEIGHT 32 + +#define BITMAPWIDTH SCREENWIDTH +#define BITMAPBYTESPERROW (BITMAPWIDTH / 8) +#define BITMAPHEIGHT (SCREENHEIGHT + EXTRAHEIGHT) + +#define BLOCKSWIDTH 320 +#define BLOCKSHEIGHT 200 + +#define BLOCKSBYTESPERROW (BLOCKSWIDTH / 8) +#define BLOCKSPERROW (BLOCKSWIDTH / BLOCKWIDTH) + +#define BITMAPBLOCKSPERROW (BITMAPWIDTH / BLOCKWIDTH) +#define BITMAPBLOCKSPERCOL (BITMAPHEIGHT / BLOCKHEIGHT) + +#define VISIBLEBLOCKSX (SCREENWIDTH / BLOCKWIDTH) +#define VISIBLEBLOCKSY (SCREENHEIGHT / BLOCKHEIGHT) + +#define BITMAPPLANELINES (BITMAPHEIGHT * BLOCKSDEPTH) +#define BLOCKPLANELINES (BLOCKHEIGHT * BLOCKSDEPTH) + +#define BLOCKSFILESIZE (BLOCKSWIDTH * BLOCKSHEIGHT * BLOCKSPLANES / 8 + PALSIZE) + +// calculate how many times (steps) y-scrolling needs to +// blit two blocks instead of one block to make sure a +// complete row is blitted after 16 pixels of y-scrolling +// +// x * 2 + (16 - x) = BITMAPBLOCKSPERROW +// 2x + 16 - x = BITMAPBLOCKSPERROW +// x = BITMAPBLOCKSPERROW - 16 + +#define TWOBLOCKS (BITMAPBLOCKSPERROW - NUMSTEPS) +#define TWOBLOCKSTEP (NUMSTEPS - TWOBLOCKS) + +struct Screen *scr; +struct RastPort *ScreenRastPort; +struct BitMap *BlocksBitmap,*ScreenBitmap; +UBYTE *frontbuffer,*blocksbuffer; + +WORD mapposy,videoposy; +WORD bitmapheight; + +struct PrgOptions options; +struct LevelMap level_map; + +UWORD colors[BLOCKSCOLORS]; +WORD bplmodulo; +char s[256]; + +struct FetchInfo fetchinfo [] = +{ + {0x38,0xD0,0}, /* normal */ + {0x38,0xC8,0}, /* BPL32 */ + {0x38,0xC8,0}, /* BPAGEM */ + {0x38,0xB8,0} /* BPL32 + BPAGEM */ +}; + +/************* SETUP/CLEANUP ROUTINES ***************/ + +static void Cleanup (char *msg) +{ + WORD rc; + + if (msg) + { + printf("Error: %s\n",msg); + rc = RETURN_WARN; + } else { + rc = RETURN_OK; + } + + if (scr) CloseScreen(scr); + + if (ScreenBitmap) + { + WaitBlit(); + FreeBitMap(ScreenBitmap); + } + + if (BlocksBitmap) + { + WaitBlit(); + FreeBitMap(BlocksBitmap); + } + if (level_map.raw_map) FreeVec(level_map.raw_map); + exit(rc); +} + +static void OpenDisplay(void) +{ + struct DimensionInfo diminfo; + DisplayInfoHandle dih; + ULONG modeid; + LONG l; + + bitmapheight = BITMAPHEIGHT + 3; + + if (!(ScreenBitmap = AllocBitMap(BITMAPWIDTH,bitmapheight,BLOCKSDEPTH,BMF_STANDARD | BMF_INTERLEAVED | BMF_CLEAR,0))) + { + Cleanup("Can't alloc screen bitmap!"); + } + frontbuffer = ScreenBitmap->Planes[0]; + + if (!(TypeOfMem(ScreenBitmap->Planes[0]) & MEMF_CHIP)) + { + Cleanup("Screen bitmap is not in CHIP RAM!?? If you have a gfx card try disabling \"planes to fast\" or similiar options in your RTG system!"); + } + + l = GetBitMapAttr(ScreenBitmap,BMA_FLAGS); + + if (!(GetBitMapAttr(ScreenBitmap,BMA_FLAGS) & BMF_INTERLEAVED)) + { + Cleanup("Screen bitmap is not in interleaved format!??"); + } + + modeid = get_mode_id(options.how, options.ntsc); + if (!(scr = OpenScreenTags(0,SA_Width,BITMAPWIDTH, + SA_Height,bitmapheight, + SA_Depth,BLOCKSDEPTH, + SA_DisplayID,modeid, + SA_BitMap,ScreenBitmap, + options.how ? SA_Overscan : TAG_IGNORE,OSCAN_TEXT, + options.how ? SA_AutoScroll : TAG_IGNORE,TRUE, + SA_Quiet,TRUE, + TAG_DONE))) + { + Cleanup("Can't open screen!"); + } + + if (scr->RastPort.BitMap->Planes[0] != ScreenBitmap->Planes[0]) + { + Cleanup("Screen was not created with the custom bitmap I supplied!??"); + } + ScreenRastPort = &scr->RastPort; + LoadRGB4(&scr->ViewPort,colors,BLOCKSCOLORS); +} + +static void InitCopperlist(void) +{ + WORD *wp,*wp2; + ULONG plane,plane2; + LONG l; + + WaitVBL(); + + custom->dmacon = 0x7FFF; + custom->beamcon0 = options.ntsc ? 0 : DISPLAYPAL; + + CopFETCHMODE[1] = options.fetchmode; + + // bitplane control registers + + CopBPLCON0[1] = ((BLOCKSDEPTH * BPL0_BPU0_F) & BPL0_BPUMASK) + + ((BLOCKSDEPTH / 8) * BPL0_BPU3_F) + + BPL0_COLOR_F + + (options.speed ? 0 : BPL0_USEBPLCON3_F); + + CopBPLCON1[1] = 0; + + CopBPLCON3[1] = BPLCON3_BRDNBLNK; + + // bitplane modulos + + l = BITMAPBYTESPERROW * BLOCKSDEPTH - + SCREENBYTESPERROW - fetchinfo[options.fetchmode].modulooffset; + + CopBPLMODA[1] = l; + CopBPLMODB[1] = l; + + CopVIDEOSPLITRESETMODULO[1] = l; + CopVIDEOSPLITRESETMODULO[3] = l; + + bplmodulo = l; + + // display window start/stop + CopDIWSTART[1] = DIWSTART; + CopDIWSTOP[1] = DIWSTOP; + + // display data fetch start/stop + CopDDFSTART[1] = fetchinfo[options.fetchmode].ddfstart; + CopDDFSTOP[1] = fetchinfo[options.fetchmode].ddfstop; + + // plane pointers + wp = CopPLANE1H; + wp2 = CopPLANE2_1H; //only hiwords here + + for (l = 0; l < BLOCKSDEPTH; l++) { + plane = (ULONG)ScreenBitmap->Planes[l]; + + wp[1] = plane >> 16; + wp[3] = plane & 0xFFFF; + + wp2[1] = plane >> 16; + + wp += 4;wp2 += 2; + } + + // Setup modulo trick + plane = (ULONG)ScreenBitmap->Planes[0]; + + plane2 = plane + + (BITMAPHEIGHT - 1) * BITMAPBYTESPERROW * BLOCKSDEPTH + + SCREENBYTESPERROW; + + l = (plane - plane2) & 0xFFFF; + + CopVIDEOSPLITMODULO[1] = l; + CopVIDEOSPLITMODULO[3] = l; + + custom->intena = 0x7FFF; + custom->dmacon = DMAF_SETCLR | DMAF_BLITTER | DMAF_COPPER | DMAF_RASTER | DMAF_MASTER; + custom->cop2lc = (ULONG)CopperList; +} + +/******************* SCROLLING **********************/ + +static void DrawBlock(LONG x,LONG y,LONG mapx,LONG mapy) +{ + UBYTE block; + + // x = in pixels + // y = in "planelines" (1 realline = BLOCKSDEPTH planelines) + x = (x / 8) & 0xFFFE; + y = y * BITMAPBYTESPERROW; + block = level_map.data[mapy * level_map.width + mapx]; + + mapx = (block % BLOCKSPERROW) * (BLOCKWIDTH / 8); + mapy = (block / BLOCKSPERROW) * (BLOCKPLANELINES * BLOCKSBYTESPERROW); + + if (options.how) OwnBlitter(); + + HardWaitBlit(); + + custom->bltcon0 = 0x9F0; // use A and D. Op: D = A + custom->bltcon1 = 0; + custom->bltafwm = 0xFFFF; + custom->bltalwm = 0xFFFF; + custom->bltamod = BLOCKSBYTESPERROW - (BLOCKWIDTH / 8); + custom->bltdmod = BITMAPBYTESPERROW - (BLOCKWIDTH / 8); + custom->bltapt = blocksbuffer + mapy + mapx; + custom->bltdpt = frontbuffer + y + x; + + custom->bltsize = BLOCKPLANELINES * 64 + (BLOCKWIDTH / 16); + + if (options.how) DisownBlitter(); +} + +static void FillScreen(void) +{ + WORD a,b,x,y; + + for (b = 0;b < BITMAPBLOCKSPERCOL;b++) { + for (a = 0;a < BITMAPBLOCKSPERROW;a++) { + x = a * BLOCKWIDTH; + y = b * BLOCKPLANELINES; + + DrawBlock(x,y,a,b); + } + } +} + +static void ScrollUp(void) +{ + WORD mapx,mapy,x,y; + + if (mapposy < 1) return; + + mapposy--; + videoposy = mapposy % BITMAPHEIGHT; + + mapx = mapposy & (NUMSTEPS - 1); + mapy = mapposy / BLOCKHEIGHT; + + y = ROUND2BLOCKHEIGHT(videoposy) * BLOCKSDEPTH; + + if (mapx < TWOBLOCKSTEP) { + // blit only one block + x = mapx * BLOCKWIDTH; + DrawBlock(x,y,mapx,mapy); + } else { + // blit two blocks + mapx = TWOBLOCKSTEP + (mapx - TWOBLOCKSTEP) * 2; + x = mapx * BLOCKWIDTH; + + DrawBlock(x,y,mapx,mapy); + DrawBlock(x + BLOCKWIDTH,y,mapx + 1,mapy); + } +} + +static void ScrollDown(void) +{ + WORD mapx,mapy,x,y; + + if (mapposy >= (level_map.height * BLOCKHEIGHT - SCREENHEIGHT - BLOCKHEIGHT)) return; + + mapx = mapposy & (NUMSTEPS - 1); + mapy = BITMAPBLOCKSPERCOL + mapposy / BLOCKHEIGHT; + + y = ROUND2BLOCKHEIGHT(videoposy) * BLOCKSDEPTH; + + if (mapx < TWOBLOCKSTEP) { + // blit only one block + + x = mapx * BLOCKWIDTH; + DrawBlock(x,y,mapx,mapy); + } else { + // blit two blocks + mapx = TWOBLOCKSTEP + (mapx - TWOBLOCKSTEP) * 2; + x = mapx * BLOCKWIDTH; + + DrawBlock(x,y,mapx,mapy); + DrawBlock(x + BLOCKWIDTH,y,mapx + 1,mapy); + } + mapposy++; + videoposy = mapposy % BITMAPHEIGHT; +} + +static void CheckJoyScroll(void) +{ + WORD i,count; + + if (JoyFire()) count = 8; else count = 1; + + if (JoyUp()) { + for (i = 0; i < count; i++) { + ScrollUp(); + } + } + + if (JoyDown()) { + for (i = 0; i < count; i++) { + ScrollDown(); + } + } +} + +static void UpdateCopperlist(void) +{ + ULONG pl; + LONG planeadd; + WORD i,yoffset; + WORD *wp; + + yoffset = (videoposy + BLOCKHEIGHT) % BITMAPHEIGHT; + planeadd = ((LONG)yoffset) * BITMAPBYTESPERROW * BLOCKSDEPTH; + + // set top plane pointers + wp = CopPLANE1H; + + for (i = 0; i < BLOCKSDEPTH; i++) { + pl = ((ULONG)ScreenBitmap->Planes[i]) + planeadd; + wp[1] = (WORD)(pl >> 16); + wp[3] = (WORD)(pl & 0xFFFF); + wp += 4; + } + + yoffset = BITMAPHEIGHT - yoffset; + yoffset += (DIWSTART >> 8); + + /* CopVIDEOSPLIT must wait for line (yoffset -1 ) + CopVIDEOSPLIT2 must wait for line (yoffset) */ + + if (yoffset <= 255) + { + CopVIDEOSPLIT[0] = 0x0001; + CopVIDEOSPLIT[2] = (yoffset - 1) * 256 + 0x1; + + CopVIDEOSPLIT2[0] = 0x0001; + CopVIDEOSPLIT2[2] = yoffset * 256 + 0x1; + } else if (yoffset == 256) + { + CopVIDEOSPLIT[0] = 0x0001; + CopVIDEOSPLIT[2] = 255 * 256 + 0x1; + + CopVIDEOSPLIT2[0] = 0xFFDF; + CopVIDEOSPLIT2[2] = (256 - 256) * 256 + 0x1; + } else { + CopVIDEOSPLIT[0] = 0xFFDF; + CopVIDEOSPLIT[2] = (yoffset - 256 - 1) * 256 + 0x1; + + CopVIDEOSPLIT2[0] = 0x001; + CopVIDEOSPLIT2[2] = (yoffset - 256) * 256 + 0x1; + } +} + +static void MainLoop(void) +{ + if (!options.how) { + // activate copperlist + HardWaitBlit(); + WaitVBL(); + custom->copjmp2 = 0; + } + + while (!LMBDown()) + { + if (!options.how) { + WaitVBeam(1); + UpdateCopperlist(); + WaitVBeam(200); + } else { + Delay(1); + } + if (options.speed) *(WORD *)0xdff180 = 0xFF0; + + CheckJoyScroll(); + + if (options.speed) *(WORD *)0xdff180 = 0xF00; + } +} + +/********************* MAIN *************************/ + +int main(int argc, char **argv) +{ + BOOL res = get_arguments(&options, s); + if (!res) Cleanup(s); + res = read_level_map(RACE_MAP_PATH, &level_map, s); + if (!res) Cleanup(s); + + BlocksBitmap = read_blocks(RACE_BLOCKS_PATH, colors, s, BLOCKSWIDTH, BLOCKSHEIGHT); + if (!BlocksBitmap) Cleanup(s); + blocksbuffer = BlocksBitmap->Planes[0]; + + OpenDisplay(); + + if (!options.how) { + Delay(2*50); + KillSystem(); + InitCopperlist(); + } + FillScreen(); + MainLoop(); + + if (!options.how) { + ActivateSystem(); + } + Cleanup(0); + return 0; +}