This is the sourcecode for a simple 8-way scrolling demo. It includes everything except the low-level pixel copying functions, which were written in assembly and gathered in the modexc.lib file. I expect that these are pretty standard functions, although your library no doubt uses different names and perhaps slightly different arguments. It also depends on having a .wld file in a format of my own devising, but you would have your own format for tiles and world maps, and functions for reading them in. That has nothing to do with the scrolling method anyway. This code is released to the public domain by the author. Learn from it, use it, rewrite it... whatever you will. -]Frank[- /* ------------------- file SCROLL.H ----------------------------------- */ #define PG_WID 88 #define WLD_WID 32 #define WLD_HGT 17 #define LOW_LIMIT 14848 #define BALL_WID 16 #define BALL_HGT 10 typedef struct b { int x, y, oldx, oldy, xdir, ydir; } BALL; enum { SCROLL_N, SCROLL_NE, SCROLL_E, SCROLL_SE, SCROLL_S, SCROLL_SW, SCROLL_W, SCROLL_NW }; extern char ballmap[]; extern BALL *ball; extern char pal[3*256]; extern char *tiles; extern char (*world)[WLD_WID]; extern int world_rows, world_cols; extern int win_moved_x, win_moved_y; extern int deferred_copy; #define COPY_TOP 0x11 #define COPY_BOT 0x21 #define COPY_LFT 0x31 #define COPY_RGT 0x41 #define NOT_YET 0x01 extern unsigned visible_off, active_off, back_off; extern int window_x, window_y; extern int world_x, world_y; /* functions */ int read_world( char *fname, char **tiles, char **world, int *w_rows, int *w_cols, char *pal ); void scroll_north( void ), scroll_south( void ); void scroll_east( void ), scroll_west( void ); void put_tile_row( unsigned pg_off, int row, char *tiles); void put_tile_col( unsigned pg_off, int col, char *tiles); /* -------------------- file SCROLL.C ------------------------------- */ #include #include #include "scroll.h" char ballmap[] = { 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 29, 29, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 0, 24, 24, 29, 29, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 24, 24, 29, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 24, 24, 23, 24, 24, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 24, 23, 23, 24, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 23, 23, 24, 24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 24, 24, 24, 24, 0, 0, 0, 0, 0, 0 }; char pal[3*256]; char *tiles; BALL *ball; int num_balls; char (*world)[WLD_WID]; int world_rows, world_cols; int win_moved_x, win_moved_y; int deferred_copy = FALSE; unsigned visible_off = 360, active_off = 22208, back_off = 44052; int window_x = 16, window_y = 16; int world_x = 0, world_y = 0; /*+----------------------------------------------------------------------+ | main() | +----------------------------------------------------------------------+*/ void main( int argc, char *argv[] ) { int i, dir=SCROLL_NE; unsigned utemp, frames=0; int old_win_x=0, old_win_y=0; if( argc != 2 ) num_balls = 8; else num_balls = atoi( argv[1] ); if( num_balls > 0 ) if( (ball=calloc(sizeof(BALL),num_balls)) == NULL ) { puts("Not enough memory"); exit(1); } srand( *((int far *)0x0040006cL) ); for( i=0; i 44416 ) { utemp = active_off; active_off = back_off; back_off = utemp; } /* save frame of reference */ old_win_x = window_x; old_win_y = window_y; for( i=0; ioldx = this->x; this->oldy = this->y; /* update ball positions */ this->x += this->xdir; this->y += this->ydir; /* check collisions */ if( this->x < 2 || this->x > 301 ) this->xdir = -(this->xdir); if( this->y < 2 || this->y > 188 ) this->ydir = -(this->ydir); /* draw balls in new positions */ spr_to_vram( ballmap, active_off, this->x + window_x, this->y + window_y, BALL_WID, BALL_HGT ); } } /**** end main loop ****/ free( tiles ); free( world ); setvmode( 3 ); } /* ---------------------- file DOSCROLL.C ----------------------------- */ #include #include #include "scroll.h" /*+----------------------------------------------------------------------+ | scroll_north() scroll_south() scroll_east() scroll_west() | +----------------------------------------------------------------------+*/ void scroll_east( void ) { if( ++window_x == 33 ) { /* move all pages right one tile */ visible_off += 4; active_off += 4; back_off += 4; /* move right in world */ if( ++world_x == WLD_WID ) world_x = 0; /* grab new row of tiles */ put_tile_col( active_off, 21, tiles ); /* copy to other pages */ rect_vram_to_vram( active_off, back_off, 336, 0, 16, 240 ); deferred_copy = COPY_RGT; /* reposition window */ window_x = 17; } win_moved_x = 1; } /*-------------------------------*/ void scroll_west( void ) { if( --window_x < 0 ) { /* move all pages left one tile */ visible_off -= 4; active_off -= 4; back_off -= 4; /* move left in world */ if( --world_x < 0 ) world_x += WLD_WID; /* grab new row of tiles */ put_tile_col( active_off, 0, tiles ); /* copy to other pages */ rect_vram_to_vram( active_off, back_off, 0, 0, 16, 240 ); deferred_copy = COPY_LFT; /* reposition window */ window_x = 15; } win_moved_x = -1; } /*-------------------------------*/ void scroll_north( void ) { if( --window_y < 0 ) { /* check if we have deferred write pending */ if( deferred_copy ) { ++window_y; /* cancel move */ return; /* wait until next time */ } /* move all pages up one tile */ visible_off -= 16*PG_WID; active_off -= 16*PG_WID; back_off -= 16*PG_WID; /* move up in world */ if( --world_y < 0 ) world_y += WLD_HGT; /* grab new row of tiles */ put_tile_row( active_off, 0, tiles ); /* copy to other pages */ rect_vram_to_vram( active_off, back_off, 0, 0, 352, 16 ); deferred_copy = COPY_TOP; /* reposition window */ window_y = 15; } win_moved_y = -1; } /*-------------------------------*/ void scroll_south( void ) { if( ++window_y == 20 ) { /* check if we have deferred write pending */ if( deferred_copy ) { --window_y; /* cancel move */ return; /* wait until next time */ } /* grab new row of tiles */ put_tile_row( active_off, 14, tiles ); /* copy to other pages */ rect_vram_to_vram( active_off, back_off, 0, 224, 352, 16 ); deferred_copy = COPY_BOT; } else if( window_y == 33 ) { /* move all pages down one tile */ visible_off += 16*PG_WID; active_off += 16*PG_WID; back_off += 16*PG_WID; /* move down in world */ if( ++world_y == WLD_HGT ) world_y = 0; /* reposition window */ window_y = 17; } win_moved_y = 1; } /* ---------------------- file DOTILES.C ------------------------------- */ #include #include #include "scroll.h" /*+----------------------------------------------------------------------+ | read_world() put_tile_row() put_tile_col() | +----------------------------------------------------------------------+*/ int read_world( char *fname, char **tiles, char **world, int *w_rows, int *w_cols, char *pal ) { signed char code, pix; int numtiles, r, c; char *p; FILE *fp; if( (fp=fopen(fname,"rb")) == NULL ) return FALSE; numtiles = fgetc( fp ); if( (*tiles=malloc(numtiles*256)) == NULL ) { fclose(fp); return FALSE; } /* unpack tiles */ p = *tiles; while( (code=fgetc(fp)) != 0 ) { if( code > 0 ) { pix = fgetc(fp); while( code-- ) *p++ = pix; } else while( code++ ) *p++ = fgetc(fp); } /* now do world */ fread( w_rows, 2, 1, fp ); /* stored as ints */ fread( w_cols, 2, 1, fp ); if( *w_rows!=WLD_HGT || *w_cols!=WLD_WID ) { puts("Wrong world size"); fclose(fp); return FALSE; } if( (*world=malloc((*w_rows)*(*w_cols))) == NULL ) { fclose(fp); return FALSE; } fread( *world, *w_rows, *w_cols, fp ); /* finally, the pallette */ fread( pal, 3, 256, fp ); fclose(fp); return TRUE; } /*-------------------------------*/ void put_tile_row( unsigned pg_off, int row, char *tiles ) { int c, wld_x, wld_y, tilenum; unsigned start_off; if( (wld_y = world_y + row) >= WLD_HGT ) wld_y -= WLD_HGT; wld_x = world_x; /* alias offset so multipication done just once */ start_off = pg_off + ( (unsigned)PG_WID << 4 ) * row; for( c=0; c<22; c++ ) { tilenum = world[wld_y][wld_x]; ltile_to_vram( tiles, tilenum, start_off, c<<4, 0 ); if( ++wld_x == WLD_WID ) wld_x = 0; } } /*-------------------------------*/ void put_tile_col( unsigned pg_off, int col, char *tiles ) { int r, wld_x, wld_y, tilenum; if( (wld_x = world_x + col) >= WLD_WID ) wld_x -= WLD_WID; wld_y = world_y; for( r=0; r<15; r++ ) { tilenum = world[wld_y][wld_x]; ltile_to_vram( tiles, tilenum, pg_off, col<<4, r<<4 ); if( ++wld_y == WLD_HGT ) wld_y = 0; } } /*-------------------------------*/