integrated the vertical scrolling programs

This commit is contained in:
Wei-ju Wu 2016-06-17 10:54:26 -07:00
parent e506235e22
commit 2036f33ecb
17 changed files with 1290 additions and 28 deletions

View File

@ -3,3 +3,5 @@ xlimited
xylimited
xyunlimited
xyunlimited2
yunlimited
yunlimited2

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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__ */

115
scrolling_tricks/cop_y.asm Normal file
View File

@ -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

28
scrolling_tricks/cop_y.h Normal file
View File

@ -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[];

171
scrolling_tricks/cop_y2.asm Normal file
View File

@ -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

44
scrolling_tricks/cop_y2.h Normal file
View File

@ -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[];

View File

@ -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

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -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];

View File

@ -0,0 +1,412 @@
#include <exec/exec.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}

View File

@ -0,0 +1,461 @@
#include <exec/exec.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <graphics/gfx.h>
#include <hardware/custom.h>
#include <hardware/dmabits.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/graphics_protos.h>
#include <clib/intuition_protos.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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;
}