mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-23 03:29:39 +00:00
c64: scrolling, sprites lib
This commit is contained in:
parent
411795f8fa
commit
c0eec49206
@ -1,5 +1,5 @@
|
||||
|
||||
#include "neslib.h"
|
||||
#include "common.h"
|
||||
|
||||
word bcd_add(word a, word b) {
|
||||
register word c, d; // intermediate values
|
||||
|
689
presets/c64/climber.c
Normal file
689
presets/c64/climber.c
Normal file
@ -0,0 +1,689 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <c64.h>
|
||||
#include <joystick.h>
|
||||
|
||||
#include "bcd.h"
|
||||
//#link "bcd.c"
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include "scrolling.h"
|
||||
//#link "scrolling.c"
|
||||
|
||||
#include "sprites.h"
|
||||
//#link "sprites.c"
|
||||
|
||||
// indices of sound effects (0..3)
|
||||
typedef enum { SND_START, SND_HIT, SND_COIN, SND_JUMP } SFXIndex;
|
||||
|
||||
///// DEFINES
|
||||
|
||||
#define MAX_FLOORS 20 // total # of floors in a stage
|
||||
#define GAPSIZE 4 // gap size in tiles
|
||||
#define BOTTOM_FLOOR_Y 2 // offset for bottommost floor
|
||||
|
||||
#define MAX_ACTORS 5 // max # of moving actors
|
||||
#define SCREEN_Y_BOTTOM 208 // bottom of screen in pixels
|
||||
#define ACTOR_MIN_X 16 // leftmost position of actor
|
||||
#define ACTOR_MAX_X 228 // rightmost position of actor
|
||||
#define ACTOR_SCROLL_UP_Y 110 // min Y position to scroll up
|
||||
#define ACTOR_SCROLL_DOWN_Y 140 // max Y position to scroll down
|
||||
#define JUMP_VELOCITY 18 // Y velocity when jumping
|
||||
|
||||
#define LADDER_XOFS -21
|
||||
#define XOFS 34
|
||||
#define BOTTOM_Y 242
|
||||
#define START_ORIGIN_Y (0xff - ROWS)
|
||||
#define GAP_OFS_X -16
|
||||
|
||||
// constants for various tiles
|
||||
#define CH_BLANK 0x20
|
||||
#define CH_WALL 0x7f
|
||||
#define CH_FLOOR 0x66
|
||||
#define CH_LADDER1 0x6b
|
||||
#define CH_LADDER2 0x73
|
||||
#define CH_ITEM 0x04
|
||||
|
||||
#define COLOR_LEVEL 0x01
|
||||
#define COLOR_LADDER 0x03
|
||||
|
||||
///// CHARS
|
||||
|
||||
const byte CHAR_TABLE[8][8] = {
|
||||
/*{w:8,h:8,brev:1,count:8}*/
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
{0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF},
|
||||
{0xFF,0xBF,0xBF,0x00,0xFF,0xFB,0xFB,0x00},
|
||||
{0x81,0xFF,0x81,0x81,0x81,0xFF,0x81,0x81},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00},
|
||||
};
|
||||
|
||||
const byte static_sprite_table[2][16*2] = {
|
||||
/*{w:16,h:16,brev:1,remap:[4,0,1,2,3,5,6,7,8,9],count:4}*/
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x3F,
|
||||
0x35, 0x2A, 0x20, 0x20, 0x20, 0x20, 0x20, 0x3F,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x40, 0xFC,
|
||||
0x54, 0xAC, 0x04, 0x04, 0x04, 0x04, 0x04, 0xFC,
|
||||
},{
|
||||
0x00, 0x19, 0x1F, 0x0A, 0x05, 0x07, 0x0E, 0x1C,
|
||||
0x3A, 0x2A, 0x3C, 0x2E, 0x1E, 0x18, 0x0E, 0x07,
|
||||
0x00, 0x80, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0x38,
|
||||
0xFC, 0xF4, 0x7C, 0xB4, 0xB8, 0x68, 0xF0, 0xE0,
|
||||
}
|
||||
};
|
||||
|
||||
const byte ITEM_CHARS[3][4] = {
|
||||
{ 0xe9,0xe9,0x5f,0x69 },
|
||||
{ 0x7f,0x7f,0x7f,0x7f },
|
||||
{ 0x7f,0x7f,0x7f,0x7f },
|
||||
};
|
||||
|
||||
/*{w:12,h:21,bpp:2,brev:1,count:5,aspect:2}*/
|
||||
const char SPRITE_DATA[5][3*21] = {
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0xA8,0x00,0x02,0xEA,0x00,
|
||||
0x02,0xEA,0x00,0x02,0xEA,0x00,0x02,0xEA,0x00,
|
||||
0x00,0xA8,0x50,0x00,0x15,0x50,0x00,0xAA,0x50,
|
||||
0x00,0xAA,0x50,0x00,0xAA,0x50,0x0A,0xAA,0x50,
|
||||
0x02,0xAA,0x50,0x00,0xFF,0x00,0x00,0xAA,0x00,
|
||||
0x00,0xAA,0x00,0x00,0xA2,0x80,0x00,0xA2,0x80,
|
||||
0x00,0x22,0x80,0x01,0x51,0x40,0x01,0x51,0x40
|
||||
},
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0xA8,0x00,0x02,0xAA,0x00,
|
||||
0x02,0xAA,0x00,0x22,0xAA,0x00,0x22,0xAA,0x00,
|
||||
0x20,0xA8,0x00,0x28,0x54,0x00,0x2A,0x56,0x80,
|
||||
0x0A,0x56,0xA0,0x02,0x56,0xA0,0x02,0x56,0x20,
|
||||
0x02,0x56,0x20,0x03,0xFF,0x20,0x02,0xAA,0x00,
|
||||
0x02,0x8A,0x00,0x02,0x8A,0x00,0x01,0x4A,0x00,
|
||||
0x05,0x4A,0x00,0x00,0x05,0x00,0x00,0x05,0x40
|
||||
},
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0xA8,0x00,0x02,0xEA,0x00,
|
||||
0x02,0xEA,0x00,0x02,0xEA,0x00,0x02,0xEA,0x00,
|
||||
0x00,0xA8,0x50,0x00,0x15,0x50,0x00,0xAA,0x50,
|
||||
0x20,0xAA,0x50,0x2A,0xAA,0x50,0x0A,0xAA,0x50,
|
||||
0x00,0xAA,0x50,0x00,0xFF,0x00,0x00,0xAA,0x00,
|
||||
0x00,0xAA,0x00,0x0A,0xA2,0x80,0x0A,0xA2,0x94,
|
||||
0x0A,0x02,0x94,0x15,0x00,0x94,0x15,0x00,0x04
|
||||
},
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0xA8,0x00,0x02,0xFE,0x00,
|
||||
0x02,0xBA,0x00,0x02,0xBA,0x00,0x02,0xBA,0x00,
|
||||
0x00,0xA8,0x00,0x00,0x54,0x08,0x82,0xAA,0xA8,
|
||||
0xAA,0xFE,0xA0,0x2A,0xAA,0x80,0x0A,0xFE,0x00,
|
||||
0x02,0xAA,0x00,0x03,0xFF,0x00,0x02,0xAA,0x00,
|
||||
0x02,0xAA,0x00,0x0A,0x8A,0x80,0x0A,0x02,0x80,
|
||||
0x0A,0x02,0x80,0x05,0x01,0x40,0x15,0x01,0x50
|
||||
},
|
||||
{
|
||||
0x00,0x00,0x00,0x00,0xA8,0x00,0x02,0xEA,0x00,
|
||||
0x02,0xEA,0x00,0x02,0xEA,0x00,0x02,0xEA,0x00,
|
||||
0x00,0xA8,0x50,0x00,0x15,0x50,0x00,0xAA,0x50,
|
||||
0x08,0xAA,0x90,0x0A,0xAA,0xA0,0x02,0xAA,0x60,
|
||||
0x00,0xAA,0x50,0x00,0xFF,0x00,0x00,0xAA,0x00,
|
||||
0x00,0xA2,0x00,0x00,0xA8,0x80,0x00,0x2A,0x80,
|
||||
0x02,0x8A,0x90,0x01,0x40,0x50,0x05,0x41,0x40
|
||||
},
|
||||
};
|
||||
|
||||
#define NUM_SPRITE_PATTERNS 5
|
||||
#define NUM_SPRITE_STATES 4
|
||||
|
||||
///// GLOBALS
|
||||
|
||||
// random byte between (a ... b-1)
|
||||
// use rand() because rand8() has a cycle of 255
|
||||
byte rndint(byte a, byte b) {
|
||||
return (rand() % (b-a)) + a;
|
||||
}
|
||||
|
||||
///// GAME LOGIC
|
||||
|
||||
// struct definition for a single floor
|
||||
typedef struct Floor {
|
||||
byte ypos; // # of tiles from ground
|
||||
int height:4; // # of tiles to next floor
|
||||
int gap:4; // X position of gap
|
||||
int ladder1:4; // X position of first ladder
|
||||
int ladder2:4; // X position of second ladder
|
||||
int objtype:4; // item type (FloorItem)
|
||||
int objpos:4; // X position of object
|
||||
} Floor;
|
||||
|
||||
// various items the player can pick up
|
||||
typedef enum FloorItem { ITEM_NONE, ITEM_MINE, ITEM_HEART, ITEM_POWER };
|
||||
|
||||
// array of floors
|
||||
Floor floors[MAX_FLOORS];
|
||||
|
||||
// is this x (pixel) position within the gap <gap>?
|
||||
bool is_in_gap(byte x, byte gap) {
|
||||
if (gap) {
|
||||
byte x1 = gap*16 + GAP_OFS_X;
|
||||
return (x > x1+2 && x < x1+GAPSIZE*8-14);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// is this ladder at (tile) position x within the gap?
|
||||
bool ladder_in_gap(byte x, byte gap) {
|
||||
return gap && x >= gap && x < gap+GAPSIZE*2;
|
||||
}
|
||||
|
||||
// create floors at start of game
|
||||
void make_floors() {
|
||||
byte i;
|
||||
byte y = BOTTOM_FLOOR_Y;
|
||||
Floor* prevlev = &floors[0];
|
||||
// create data for each floor
|
||||
for (i=0; i<MAX_FLOORS; i++) {
|
||||
Floor* lev = &floors[i];
|
||||
lev->height = rndint(4,8);
|
||||
do {
|
||||
// only have gaps in higher floors
|
||||
lev->gap = i>=3 ? rndint(0,COLS/2-5) : 0;
|
||||
} while (ladder_in_gap(prevlev->ladder1, lev->gap) ||
|
||||
ladder_in_gap(prevlev->ladder2, lev->gap));
|
||||
do {
|
||||
lev->ladder1 = rndint(2,COLS-6);
|
||||
lev->ladder2 = rndint(2,COLS-6);
|
||||
} while (ladder_in_gap(lev->ladder1, lev->gap) ||
|
||||
ladder_in_gap(lev->ladder2, lev->gap));
|
||||
if (i > 0) {
|
||||
lev->objtype = rndint(1,3);
|
||||
do {
|
||||
lev->objpos = rndint(2,COLS-7);
|
||||
} while (ladder_in_gap(lev->objpos, lev->gap));
|
||||
}
|
||||
lev->ypos = y;
|
||||
y += lev->height;
|
||||
prevlev = lev;
|
||||
}
|
||||
// top floor is special
|
||||
floors[MAX_FLOORS-1].height = 15;
|
||||
floors[MAX_FLOORS-1].gap = 0;
|
||||
floors[MAX_FLOORS-1].ladder1 = 0;
|
||||
floors[MAX_FLOORS-1].ladder2 = 0;
|
||||
floors[MAX_FLOORS-1].objtype = 0;
|
||||
}
|
||||
|
||||
// creete actors on floor_index, if slot is empty
|
||||
void create_actors_on_floor(byte floor_index);
|
||||
|
||||
// draw a nametable line into the frame buffer at <row_height>
|
||||
// 0 == bottom of stage
|
||||
void scroll_draw_row(byte row) {
|
||||
char *buf; // nametable buffer
|
||||
char *attrs; // attribute buffer
|
||||
byte floor; // floor counter
|
||||
byte dy; // height in rows above floor
|
||||
byte row_height; // rows above bottom of level
|
||||
// set screen/color buffer addresses
|
||||
buf = hidbuf + row*COLS;
|
||||
attrs = tempbuf + row*COLS;
|
||||
row_height = -(row + origin_y);
|
||||
// loop over all floors
|
||||
for (floor=0; floor<MAX_FLOORS; floor++) {
|
||||
Floor* lev = &floors[floor];
|
||||
// compute height in rows above floor
|
||||
dy = row_height - lev->ypos;
|
||||
// if below bottom floor (in basement)
|
||||
if (dy >= 255 - BOTTOM_FLOOR_Y) dy = 0;
|
||||
// does this floor intersect the desired row?
|
||||
if (dy < lev->height) {
|
||||
// set all colors to default
|
||||
memset(attrs, COLOR_LEVEL, COLS);
|
||||
// first two rows (floor)?
|
||||
if (dy == 0) {
|
||||
// draw floor
|
||||
memset(buf, CH_FLOOR, COLS);
|
||||
// is there a gap? if so, clear bytes
|
||||
if (lev->gap)
|
||||
memset(buf+lev->gap*2, CH_BLANK, GAPSIZE);
|
||||
} else {
|
||||
// clear buffer
|
||||
memset(buf, CH_BLANK, COLS);
|
||||
// draw walls
|
||||
if (floor < MAX_FLOORS-1) {
|
||||
buf[1] = CH_WALL; // left side
|
||||
buf[COLS-2] = CH_WALL; // right side
|
||||
}
|
||||
// draw ladders
|
||||
if (lev->ladder1) {
|
||||
byte i = lev->ladder1*2;
|
||||
buf[i] = CH_LADDER1; // left
|
||||
buf[i+1] = CH_LADDER2; // right
|
||||
attrs[i] = COLOR_LADDER;
|
||||
attrs[i+1] = COLOR_LADDER;
|
||||
}
|
||||
if (lev->ladder2) {
|
||||
byte i = lev->ladder2*2;
|
||||
buf[i] = CH_LADDER1; // left
|
||||
buf[i+1] = CH_LADDER2; // right
|
||||
attrs[i] = COLOR_LADDER;
|
||||
attrs[i+1] = COLOR_LADDER;
|
||||
}
|
||||
}
|
||||
// draw object, if it exists
|
||||
if (lev->objtype && (dy == 1 || dy == 2)) {
|
||||
const byte* ichars = ITEM_CHARS[lev->objtype - 1];
|
||||
byte i = lev->objpos*2;
|
||||
if (dy == 1) {
|
||||
buf[i+0] = ichars[2]; // bottom-left
|
||||
buf[i+1] = ichars[3]; // bottom-right
|
||||
} else {
|
||||
buf[i+0] = ichars[0]; // top-left
|
||||
buf[i+1] = ichars[1]; // top-right
|
||||
}
|
||||
attrs[i+0] = 0x7;
|
||||
attrs[i+1] = 0x7;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
// create actors on this floor, if needed
|
||||
// TODO: maybe this happens too early?
|
||||
if (dy == 0 && (floor >= 2)) {
|
||||
create_actors_on_floor(floor);
|
||||
}
|
||||
}
|
||||
|
||||
// not used, since we don't scroll left/right
|
||||
void scroll_draw_column(byte col) {
|
||||
col=col;
|
||||
}
|
||||
|
||||
// draw entire stage at current scroll position
|
||||
// filling up entire name table
|
||||
void draw_entire_stage() {
|
||||
byte y;
|
||||
for (y=0; y<ROWS; y++) {
|
||||
scroll_draw_row(y);
|
||||
}
|
||||
swap_needed = true;
|
||||
}
|
||||
|
||||
// ACTORS
|
||||
|
||||
word get_floor_yy(byte level) {
|
||||
return floors[level].ypos * 8 + 8;
|
||||
}
|
||||
|
||||
word get_ceiling_yy(byte level) {
|
||||
return (floors[level].ypos + floors[level].height) * 8 + 8;
|
||||
}
|
||||
|
||||
typedef enum ActorState {
|
||||
INACTIVE, WALKING, CLIMBING, JUMPING, FALLING
|
||||
};
|
||||
|
||||
typedef struct Actor {
|
||||
word yy;
|
||||
byte x;
|
||||
byte name;
|
||||
unsigned int color1:4;
|
||||
unsigned int color2:4;
|
||||
byte level;
|
||||
unsigned int state:4;
|
||||
unsigned int dir:1;
|
||||
unsigned int onscreen:1;
|
||||
sbyte yvel;
|
||||
sbyte xvel;
|
||||
} Actor;
|
||||
|
||||
Actor actors[MAX_ACTORS];
|
||||
|
||||
void create_actors_on_floor(byte level_index) {
|
||||
byte actor_index = (level_index % (MAX_ACTORS-1)) + 1;
|
||||
struct Actor* a = &actors[actor_index];
|
||||
if (!a->onscreen) {
|
||||
Floor *level = &floors[level_index];
|
||||
a->state = WALKING;
|
||||
a->color1 = level->ladder1 ^ level->ladder2;
|
||||
a->color2 = level->ladder2;
|
||||
a->name = 0;
|
||||
a->x = level->ladder1 ^ (level->ladder2<<3) ^ (level->gap<<6);
|
||||
a->yy = get_floor_yy(level_index);
|
||||
a->level = level_index;
|
||||
}
|
||||
}
|
||||
|
||||
static word yscroll;
|
||||
|
||||
void draw_actor(byte i) {
|
||||
byte name;
|
||||
struct Actor* a = &actors[i];
|
||||
word screen_y = yscroll - a->yy;
|
||||
if (screen_y > 240) {
|
||||
a->onscreen = 0;
|
||||
return; // offscreen vertically
|
||||
}
|
||||
name = 32 + (a->state - WALKING);
|
||||
switch (a->state) {
|
||||
case INACTIVE:
|
||||
a->onscreen = 0;
|
||||
return; // inactive, offscreen
|
||||
case WALKING:
|
||||
name += (a->x & 4);
|
||||
case JUMPING:
|
||||
case FALLING:
|
||||
//name = a->dir ? 16*4 : 0;
|
||||
break;
|
||||
case CLIMBING:
|
||||
//name += (a->yy & 4) ? 16*4 : 0;
|
||||
break;
|
||||
}
|
||||
sprite_draw(i, a->x + XOFS, screen_y, name);
|
||||
sprshad.spr_color[i] = a->color1;
|
||||
a->onscreen = 1;
|
||||
}
|
||||
|
||||
void refresh_actors() {
|
||||
byte i;
|
||||
yscroll = BOTTOM_Y + scroll_fine_y + (START_ORIGIN_Y - origin_y)*8;
|
||||
sprite_clear();
|
||||
for (i=0; i<MAX_ACTORS; i++)
|
||||
draw_actor(i);
|
||||
}
|
||||
|
||||
void refresh_screen() {
|
||||
draw_entire_stage();
|
||||
refresh_actors();
|
||||
}
|
||||
|
||||
byte is_ladder_close(byte actor_x, byte ladder_pos) {
|
||||
byte ladder_x;
|
||||
if (ladder_pos == 0)
|
||||
return 0;
|
||||
ladder_x = ladder_pos * 16 + LADDER_XOFS;
|
||||
return ((byte)(actor_x - ladder_x) < 16) ? ladder_x : 0;
|
||||
}
|
||||
|
||||
byte get_closest_ladder(byte player_x, byte level_index) {
|
||||
Floor* level = &floors[level_index];
|
||||
byte x;
|
||||
if (level_index >= MAX_FLOORS) return 0;
|
||||
x = is_ladder_close(player_x, level->ladder1);
|
||||
if (x) return x;
|
||||
x = is_ladder_close(player_x, level->ladder2);
|
||||
if (x) return x;
|
||||
return 0;
|
||||
}
|
||||
|
||||
byte mount_ladder(Actor* player, signed char level_adjust) {
|
||||
byte x = get_closest_ladder(player->x, player->level + level_adjust);
|
||||
if (x) {
|
||||
player->x = x + 8;
|
||||
player->state = CLIMBING;
|
||||
player->level += level_adjust;
|
||||
return 1;
|
||||
} else
|
||||
return 0;
|
||||
}
|
||||
|
||||
void check_scroll_up() {
|
||||
if (sprshad.spr_pos[0].y < BOTTOM_Y/2+16) {
|
||||
scroll_vert(1);
|
||||
}
|
||||
}
|
||||
|
||||
void check_scroll_down() {
|
||||
if (sprshad.spr_pos[0].y > BOTTOM_Y/2+32 && origin_y < START_ORIGIN_Y) {
|
||||
scroll_vert(-1);
|
||||
}
|
||||
}
|
||||
|
||||
void fall_down(struct Actor* actor) {
|
||||
actor->level--;
|
||||
actor->state = FALLING;
|
||||
actor->xvel = 0;
|
||||
actor->yvel = 0;
|
||||
}
|
||||
|
||||
void move_actor(struct Actor* actor, byte joystick, bool scroll) {
|
||||
switch (actor->state) {
|
||||
|
||||
case WALKING:
|
||||
// left/right has priority over climbing
|
||||
if (joystick & JOY_BTN_1_MASK) {
|
||||
actor->state = JUMPING;
|
||||
actor->xvel = 0;
|
||||
actor->yvel = 15;
|
||||
if (joystick & JOY_LEFT_MASK) actor->xvel = -1;
|
||||
if (joystick & JOY_RIGHT_MASK) actor->xvel = 1;
|
||||
} else if (joystick & JOY_LEFT_MASK) {
|
||||
actor->x--;
|
||||
actor->dir = 1;
|
||||
} else if (joystick & JOY_RIGHT_MASK) {
|
||||
actor->x++;
|
||||
actor->dir = 0;
|
||||
} else if (joystick & JOY_UP_MASK) {
|
||||
mount_ladder(actor, 0); // state -> CLIMBING
|
||||
} else if (joystick & JOY_DOWN_MASK) {
|
||||
mount_ladder(actor, -1); // state -> CLIMBING, level -= 1
|
||||
} else {
|
||||
//actor->state = STANDING;
|
||||
}
|
||||
if (scroll) {
|
||||
check_scroll_up();
|
||||
check_scroll_down();
|
||||
}
|
||||
break;
|
||||
|
||||
case CLIMBING:
|
||||
if (joystick & JOY_UP_MASK) {
|
||||
if (actor->yy >= get_ceiling_yy(actor->level)) {
|
||||
actor->level++;
|
||||
actor->state = WALKING;
|
||||
} else {
|
||||
actor->yy++;
|
||||
}
|
||||
if (scroll) check_scroll_up();
|
||||
} else if (joystick & JOY_DOWN_MASK) {
|
||||
if (actor->yy <= get_floor_yy(actor->level)) {
|
||||
actor->state = WALKING;
|
||||
} else {
|
||||
actor->yy--;
|
||||
}
|
||||
}
|
||||
if (scroll) {
|
||||
check_scroll_up();
|
||||
check_scroll_down();
|
||||
}
|
||||
break;
|
||||
|
||||
case FALLING:
|
||||
if (scroll) {
|
||||
check_scroll_up();
|
||||
check_scroll_down();
|
||||
}
|
||||
case JUMPING:
|
||||
actor->x += actor->xvel;
|
||||
actor->yy += actor->yvel/4;
|
||||
actor->yvel -= 1;
|
||||
if (actor->yy <= get_floor_yy(actor->level)) {
|
||||
actor->yy = get_floor_yy(actor->level);
|
||||
actor->state = WALKING;
|
||||
if (scroll) check_scroll_down();
|
||||
}
|
||||
break;
|
||||
}
|
||||
// don't allow player to travel past left/right edges of screen
|
||||
if (actor->x == 0) actor->x = 255; // we wrapped around right edge
|
||||
if (actor->x == 1) actor->x = 2; // left edge
|
||||
// if player lands in a gap, they fall (switch to JUMPING state)
|
||||
if (actor->state == WALKING &&
|
||||
is_in_gap(actor->x, floors[actor->level].gap)) {
|
||||
fall_down(actor);
|
||||
}
|
||||
}
|
||||
|
||||
void pickup_object(Actor* actor) {
|
||||
Floor* level = &floors[actor->level];
|
||||
byte objtype = level->objtype;
|
||||
if (objtype && actor->state == WALKING) {
|
||||
byte objx = level->objpos * 16 + 16 - XOFS;
|
||||
if (actor->x >= objx && actor->x < objx+16) {
|
||||
level->objtype = 0;
|
||||
refresh_screen();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void move_player() {
|
||||
char joy = joy_read(0);
|
||||
move_actor(&actors[0], joy, true);
|
||||
pickup_object(&actors[0]);
|
||||
}
|
||||
|
||||
byte iabs(int x) {
|
||||
return x >= 0 ? x : -x;
|
||||
}
|
||||
|
||||
bool check_collision(Actor* a) {
|
||||
byte i;
|
||||
for (i=1; i<MAX_ACTORS; i++) {
|
||||
Actor* b = &actors[i];
|
||||
// actors must be on same level
|
||||
// no need to apply XOFS because both sprites are offset
|
||||
if (a->level == b->level &&
|
||||
iabs(a->yy - b->yy) < 8 &&
|
||||
iabs(a->x - b->x) < 8) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
///
|
||||
|
||||
void preview_stage() {
|
||||
/*
|
||||
scroll_y = floors[MAX_LEVELS-1].ypos;
|
||||
while (scroll_y > 0) {
|
||||
wait_vblank();
|
||||
refresh_screen();
|
||||
refresh_actors();
|
||||
scroll_y--;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void draw_blimp(struct cvu_sprite* sprite) {
|
||||
/*
|
||||
sprite->name = 48;
|
||||
wait_vblank();
|
||||
cvu_set_sprite(SPRITES, 28, sprite);
|
||||
sprite->name += 4;
|
||||
sprite->x += 16;
|
||||
cvu_set_sprite(SPRITES, 29, sprite);
|
||||
sprite->name += 4;
|
||||
sprite->x += 16;
|
||||
cvu_set_sprite(SPRITES, 30, sprite);
|
||||
sprite->name += 4;
|
||||
sprite->x += 16;
|
||||
cvu_set_sprite(SPRITES, 31, sprite);
|
||||
refresh_actors();
|
||||
*/
|
||||
sprite=sprite;
|
||||
}
|
||||
|
||||
void blimp_pickup_scene() {
|
||||
/*
|
||||
struct cvu_sprite sprite;
|
||||
byte player_screen_y = cvu_vinb(SPRITES + 0); // sprite Y pos
|
||||
sprite.x = actors[0].x-14;
|
||||
sprite.y = 240;
|
||||
sprite.tag = 0x8f;
|
||||
while (sprite.y != player_screen_y-16) {
|
||||
draw_blimp(&sprite);
|
||||
sprite.x -= 48;
|
||||
sprite.y++;
|
||||
}
|
||||
while (sprite.y != 240) {
|
||||
draw_blimp(&sprite);
|
||||
sprite.x -= 48;
|
||||
sprite.y--;
|
||||
actors[0].yy++;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void play_scene() {
|
||||
byte i;
|
||||
|
||||
memset(actors, 0, sizeof(actors));
|
||||
actors[0].state = WALKING;
|
||||
actors[0].color1 = 0x1;
|
||||
actors[0].color2 = 0xb;
|
||||
actors[0].name = 0;
|
||||
actors[0].x = 64;
|
||||
actors[0].yy = get_floor_yy(0);
|
||||
actors[0].level = 0;
|
||||
|
||||
create_actors_on_floor(2);
|
||||
refresh_screen();
|
||||
|
||||
while (actors[0].level != MAX_FLOORS-1) {
|
||||
refresh_actors();
|
||||
move_player();
|
||||
// move all the actors
|
||||
for (i=1; i<MAX_ACTORS; i++) {
|
||||
move_actor(&actors[i], rand(), false);
|
||||
}
|
||||
// see if the player hit another actor
|
||||
if (VIC.spr_coll & 0x01) {
|
||||
if (actors[0].level > 0 && check_collision(&actors[0])) {
|
||||
fall_down(&actors[0]);
|
||||
}
|
||||
}
|
||||
wait_vblank();
|
||||
scroll_update();
|
||||
sprite_update(visbuf);
|
||||
}
|
||||
|
||||
blimp_pickup_scene();
|
||||
}
|
||||
|
||||
// MAIN
|
||||
|
||||
// main program
|
||||
void main() {
|
||||
byte i;
|
||||
|
||||
// set up scrolling
|
||||
scroll_setup();
|
||||
// set up sprites
|
||||
sprite_clear();
|
||||
for (i=0; i<5; i++) {
|
||||
sprite_shape(hidbuf, 32+i, SPRITE_DATA[i]);
|
||||
}
|
||||
sprshad.spr_mcolor = 0xff;
|
||||
sprshad.spr_mcolor0 = 0x0f;
|
||||
sprshad.spr_mcolor1 = 0x00;
|
||||
// set up character set
|
||||
VIC.addr = 0x15;
|
||||
// start scrolling @ bottom of level
|
||||
origin_y = START_ORIGIN_Y;
|
||||
joy_install (joy_static_stddrv);
|
||||
make_floors();
|
||||
draw_entire_stage();
|
||||
play_scene();
|
||||
/*
|
||||
while (1) {
|
||||
scroll_vert(2);
|
||||
scroll_update_regs();
|
||||
wait_vblank();
|
||||
}
|
||||
*/
|
||||
}
|
10
presets/c64/common.c
Normal file
10
presets/c64/common.c
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void raster_wait(unsigned char line) {
|
||||
while (VIC.rasterline < line) ;
|
||||
}
|
||||
|
||||
void wait_vblank(void) {
|
||||
raster_wait(255);
|
||||
}
|
18
presets/c64/common.h
Normal file
18
presets/c64/common.h
Normal file
@ -0,0 +1,18 @@
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include <c64.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint8_t byte;
|
||||
typedef uint16_t word;
|
||||
typedef int8_t sbyte;
|
||||
typedef enum { false, true } bool;
|
||||
|
||||
#define COLS 40
|
||||
#define ROWS 25
|
||||
|
||||
void raster_wait(unsigned char line);
|
||||
void wait_vblank(void);
|
||||
|
||||
#endif
|
@ -19,6 +19,17 @@ const char sprite[3*21] = {
|
||||
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
|
||||
};
|
||||
|
||||
/*{w:12,h:21,bpp:2,brev:1}*/
|
||||
const char spritemc[3*21] = {
|
||||
0x00,0xFF,0xC0,0x03,0xFF,0xF0,0x0F,0xFF,0xFC,
|
||||
0x0F,0xFB,0xFC,0x0F,0xEE,0xFC,0x0F,0xEF,0xFC,
|
||||
0x0F,0xEE,0xFC,0x0F,0xFB,0xFC,0x0F,0xFF,0xFC,
|
||||
0x09,0xFF,0xD8,0x08,0x7F,0x48,0x08,0x1D,0x08,
|
||||
0x02,0x0C,0x20,0x02,0x0C,0x20,0x02,0x0C,0x20,
|
||||
0x00,0x8C,0x80,0x00,0x8C,0x80,0x00,0x55,0x40,
|
||||
0x00,0x77,0x40,0x00,0x5D,0x40,0x00,0x15,0x00
|
||||
};
|
||||
|
||||
// Raster wait with line argument
|
||||
void rasterWait(unsigned char line) {
|
||||
while (VIC.rasterline < line) ;
|
||||
@ -28,6 +39,7 @@ int main (void)
|
||||
{
|
||||
int n;
|
||||
int x,y;
|
||||
char bgcoll;
|
||||
// install the joystick driver
|
||||
joy_install (joy_static_stddrv);
|
||||
// set background color
|
||||
@ -36,15 +48,21 @@ int main (void)
|
||||
__asm__("SEI");
|
||||
// set sprite bitmap data
|
||||
for (n = 0 ; n < sizeof(sprite) ; n++) {
|
||||
POKE(832 + n, sprite[n]);
|
||||
POKE(0x340 + n, sprite[n]);
|
||||
POKE(0x380 + n, spritemc[n]);
|
||||
}
|
||||
// enable 1st sprite
|
||||
VIC.spr_ena = 0x01;
|
||||
// enable 1st and 2nd sprite
|
||||
VIC.spr_ena = 0x03;
|
||||
VIC.spr_mcolor = 0x02;
|
||||
// set colors
|
||||
VIC.spr_mcolor0 = 4;
|
||||
VIC.spr_mcolor1 = 7;
|
||||
// 2x zoom 1st sprite
|
||||
VIC.spr_exp_x = 0x01;
|
||||
VIC.spr_exp_y = 0x01;
|
||||
// set address of sprite data
|
||||
POKE(2040, 13);
|
||||
POKE(0x7f8, 13);
|
||||
POKE(0x7f9, 14);
|
||||
// set initial x/y positions
|
||||
x = 160;
|
||||
y = 128;
|
||||
@ -59,13 +77,17 @@ int main (void)
|
||||
if (JOY_DOWN(joy)) ++y;
|
||||
// set VIC registers based on position
|
||||
VIC.spr0_x = x;
|
||||
VIC.spr0_y = y;
|
||||
VIC.spr0_y = y-32;
|
||||
VIC.spr1_x = x;
|
||||
VIC.spr1_y = y+32;
|
||||
VIC.spr_hi_x = (x & 256) ? 1 : 0;
|
||||
// change color when we collide with background
|
||||
VIC.spr0_color = (VIC.spr_bg_coll & 1) ? 10 : 0;
|
||||
bgcoll = VIC.spr_bg_coll;
|
||||
VIC.spr0_color = (bgcoll & 1) ? 10 : 0;
|
||||
VIC.spr1_color = (bgcoll & 2) ? 10 : 0;
|
||||
// wait for end of frame
|
||||
rasterWait(255);
|
||||
}
|
||||
}
|
||||
// uninstall joystick driver (not really necessary)
|
||||
joy_uninstall();
|
||||
return EXIT_SUCCESS;
|
||||
|
@ -23,11 +23,11 @@ void wait_vblank() {
|
||||
raster_wait(255); // TODO
|
||||
}
|
||||
|
||||
sbyte scroll_fine_x = 0;
|
||||
sbyte scroll_fine_y = 0;
|
||||
byte origin_x = 0x80;
|
||||
byte origin_y = 0x80;
|
||||
byte curbuf = 0;
|
||||
sbyte scroll_fine_x;
|
||||
sbyte scroll_fine_y;
|
||||
byte origin_x;
|
||||
byte origin_y;
|
||||
byte curbuf;
|
||||
byte* scrnbuf[2]; // screen buffer(s)
|
||||
byte tempbuf[COLS*ROWS];
|
||||
|
||||
@ -138,6 +138,11 @@ void scroll_vert(sbyte delta_y) {
|
||||
}
|
||||
|
||||
void scroll_setup() {
|
||||
scroll_fine_x = 0;
|
||||
scroll_fine_y = 0;
|
||||
origin_x = 0x80;
|
||||
origin_y = 0x80;
|
||||
curbuf = 0;
|
||||
// get screen buffer addresses
|
||||
scrnbuf[0] = (byte*) 0x8000;
|
||||
scrnbuf[1] = (byte*) 0x8400;
|
||||
|
93
presets/c64/scroll5.c
Normal file
93
presets/c64/scroll5.c
Normal file
@ -0,0 +1,93 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <conio.h>
|
||||
#include <c64.h>
|
||||
#include <cbm_petscii_charmap.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <joystick.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
|
||||
#include "scrolling.h"
|
||||
//#link "scrolling.c"
|
||||
|
||||
#include "sprites.h"
|
||||
//#link "sprites.c"
|
||||
|
||||
static void draw_cell(byte x, byte y) {
|
||||
byte xx = x + origin_x;
|
||||
byte yy = y + origin_y;
|
||||
byte ch = xx ^ yy;
|
||||
word ofs = x+y*COLS;
|
||||
hidbuf[ofs] = ch; // character
|
||||
tempbuf[ofs] = ch; // color
|
||||
}
|
||||
|
||||
void scroll_draw_column(byte col) {
|
||||
byte y;
|
||||
for (y=0; y<ROWS; y++) {
|
||||
draw_cell(col, y);
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_draw_row(byte row) {
|
||||
byte x;
|
||||
for (x=0; x<COLS; x++) {
|
||||
draw_cell(x, row);
|
||||
}
|
||||
}
|
||||
|
||||
/*{w:24,h:21,bpp:1,brev:1}*/
|
||||
const char SPRITE1[3*21] = {
|
||||
0x00,0x7F,0x00,0x01,0xFF,0xC0,0x03,0xFF,0xE0,
|
||||
0x03,0xE7,0xE0,0x07,0xD9,0xF0,0x07,0xDF,0xF0,
|
||||
0x07,0xD9,0xF0,0x03,0xE7,0xE0,0x03,0xFF,0xE0,
|
||||
0x03,0xFF,0xE0,0x02,0xFF,0xA0,0x01,0x7F,0x40,
|
||||
0x01,0x3E,0x40,0x00,0x9C,0x80,0x00,0x9C,0x80,
|
||||
0x00,0x49,0x00,0x00,0x49,0x00,0x00,0x3E,0x00,
|
||||
0x00,0x3E,0x00,0x00,0x3E,0x00,0x00,0x1C,0x00
|
||||
};
|
||||
|
||||
void main(void) {
|
||||
byte n = 0;
|
||||
|
||||
clrscr();
|
||||
printf("\r\n\r\n\r\n Hello World!");
|
||||
printf("\r\n\r\n\r\n This is how we scroll");
|
||||
printf("\r\n\r\n\r\n But color RAM can't move");
|
||||
printf("\r\n\r\n\r\n So we have to use a temp buffer");
|
||||
printf("\r\n\r\n\r\n And copy it just in time");
|
||||
|
||||
// setup scrolling library
|
||||
scroll_setup();
|
||||
|
||||
// setup sprite library and copy sprite to VIC bank
|
||||
sprite_clear();
|
||||
sprite_shape(hidbuf, 32, SPRITE1);
|
||||
|
||||
// install the joystick driver
|
||||
joy_install (joy_static_stddrv);
|
||||
|
||||
// infinite loop
|
||||
while (1) {
|
||||
// get joystick bits
|
||||
char joy = joy_read(0);
|
||||
// move sprite based on arrow keys
|
||||
if (JOY_LEFT(joy)) scroll_horiz(-1);
|
||||
if (JOY_UP(joy)) scroll_vert(-1);
|
||||
if (JOY_RIGHT(joy)) scroll_horiz(1);
|
||||
if (JOY_DOWN(joy)) scroll_vert(1);
|
||||
// animate sprite in shadow sprite ram
|
||||
sprite_draw(0, n++, 70, 32);
|
||||
// wait for vblank
|
||||
wait_vblank();
|
||||
// update scroll registers
|
||||
// and swap screens if we must
|
||||
scroll_update();
|
||||
// then update sprite registers
|
||||
sprite_update(visbuf);
|
||||
}
|
||||
}
|
122
presets/c64/scrolling.c
Normal file
122
presets/c64/scrolling.c
Normal file
@ -0,0 +1,122 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "scrolling.h"
|
||||
|
||||
sbyte scroll_fine_x;
|
||||
sbyte scroll_fine_y;
|
||||
byte origin_x;
|
||||
byte origin_y;
|
||||
byte* hidbuf;
|
||||
byte* visbuf;
|
||||
byte tempbuf[COLS*ROWS];
|
||||
byte swap_needed;
|
||||
|
||||
//
|
||||
|
||||
void scroll_swap(void) {
|
||||
byte* tmp;
|
||||
// set VIC bank address
|
||||
VIC.addr = (VIC.addr & 0xf) | (((word)hidbuf >> 8) << 2);
|
||||
// swap hidden and visible buffers
|
||||
tmp = hidbuf;
|
||||
hidbuf = visbuf;
|
||||
visbuf = tmp;
|
||||
}
|
||||
|
||||
void scroll_copy(void) {
|
||||
// copy temp buf to color ram
|
||||
memcpy(COLOR_RAM, tempbuf, COLS*ROWS);
|
||||
// copy visible buffer to hidden buffer
|
||||
memcpy(hidbuf, visbuf, COLS*ROWS);
|
||||
}
|
||||
|
||||
void scroll_update(void) {
|
||||
VIC.ctrl1 = (VIC.ctrl1 & 0xf8) | scroll_fine_y;
|
||||
VIC.ctrl2 = (VIC.ctrl2 & 0xf8) | scroll_fine_x;
|
||||
if (swap_needed) {
|
||||
scroll_swap();
|
||||
scroll_copy();
|
||||
swap_needed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: left and up can be faster, b/c we can copy color ram downward
|
||||
|
||||
void scroll_left(void) {
|
||||
memcpy(hidbuf, visbuf+1, COLS*ROWS-1);
|
||||
++origin_x;
|
||||
memcpy(tempbuf, COLOR_RAM+1, COLS*ROWS-1);
|
||||
scroll_draw_column(COLS-1);
|
||||
swap_needed = true;
|
||||
}
|
||||
|
||||
void scroll_up(void) {
|
||||
memcpy(hidbuf, visbuf+COLS, COLS*(ROWS-1));
|
||||
++origin_y;
|
||||
memcpy(tempbuf, COLOR_RAM+COLS, COLS*(ROWS-1));
|
||||
scroll_draw_row(ROWS-1);
|
||||
swap_needed = true;
|
||||
}
|
||||
|
||||
void scroll_right(void) {
|
||||
memcpy(hidbuf+1, visbuf, COLS*ROWS-1);
|
||||
--origin_x;
|
||||
memcpy(tempbuf+1, COLOR_RAM, COLS*ROWS-1);
|
||||
scroll_draw_column(0);
|
||||
swap_needed = true;
|
||||
}
|
||||
|
||||
void scroll_down(void) {
|
||||
memcpy(hidbuf+COLS, visbuf, COLS*(ROWS-1));
|
||||
--origin_y;
|
||||
memcpy(tempbuf+COLS, COLOR_RAM, COLS*(ROWS-1));
|
||||
scroll_draw_row(0);
|
||||
swap_needed = true;
|
||||
}
|
||||
|
||||
void scroll_horiz(sbyte delta_x) {
|
||||
scroll_fine_x += delta_x;
|
||||
while (scroll_fine_x < 0) {
|
||||
scroll_fine_x += 8;
|
||||
scroll_left();
|
||||
}
|
||||
while (scroll_fine_x >= 8) {
|
||||
scroll_fine_x -= 8;
|
||||
scroll_right();
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_vert(sbyte delta_y) {
|
||||
scroll_fine_y += delta_y;
|
||||
while (scroll_fine_y < 0) {
|
||||
scroll_fine_y += 8;
|
||||
scroll_up();
|
||||
}
|
||||
while (scroll_fine_y >= 8) {
|
||||
scroll_fine_y -= 8;
|
||||
scroll_down();
|
||||
}
|
||||
}
|
||||
|
||||
void scroll_setup(void) {
|
||||
scroll_fine_x = scroll_fine_y = 0;
|
||||
origin_x = origin_y = 0x80;
|
||||
swap_needed = true;
|
||||
|
||||
// get screen buffer addresses
|
||||
hidbuf = (byte*) 0x8000;
|
||||
visbuf = (byte*) 0x8400;
|
||||
// copy existing text to screen 0
|
||||
memcpy(hidbuf, (byte*)0x400, COLS*ROWS);
|
||||
// copy screen 1 to screen 0
|
||||
memcpy(visbuf, hidbuf, COLS*ROWS);
|
||||
|
||||
// set VIC bank ($4000-$7FFF)
|
||||
// https://www.c64-wiki.com/wiki/VIC_bank
|
||||
CIA2.pra = 0x01;
|
||||
|
||||
VIC.ctrl1 &= ~0x08; // 24 lines
|
||||
VIC.ctrl2 &= ~0x08; // 38 columns
|
||||
}
|
||||
|
33
presets/c64/scrolling.h
Normal file
33
presets/c64/scrolling.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef _SCROLLING_H
|
||||
#define _SCROLLING_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
// drawable screen area (only shows 38 x 24)
|
||||
#define COLS 40
|
||||
#define ROWS 25
|
||||
|
||||
extern sbyte scroll_fine_x; // X fine scroll (pixels)
|
||||
extern sbyte scroll_fine_y; // Y fine scroll (pixels)
|
||||
extern byte origin_x; // X scroll origin (columns)
|
||||
extern byte origin_y; // Y scroll origin (rows)
|
||||
extern byte* hidbuf; // hidden screen buffer(s)
|
||||
extern byte* visbuf; // visible screen buffer(s)
|
||||
extern byte tempbuf[COLS*ROWS]; // temporary buffer
|
||||
extern byte swap_needed; // TRUE if scroll_update() swaps
|
||||
|
||||
// call this at start of program
|
||||
void scroll_setup(void);
|
||||
|
||||
// scroll in X or Y directions
|
||||
void scroll_horiz(sbyte delta_x);
|
||||
void scroll_vert(sbyte delta_y);
|
||||
|
||||
// call this after vblank
|
||||
void scroll_update(void);
|
||||
|
||||
// caller must implement these two
|
||||
void scroll_draw_column(byte col);
|
||||
void scroll_draw_row(byte row);
|
||||
|
||||
#endif
|
40
presets/c64/sprites.c
Normal file
40
presets/c64/sprites.c
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
#include <string.h>
|
||||
#include "sprites.h"
|
||||
|
||||
SpriteShadow sprshad;
|
||||
|
||||
void sprite_update(char* screenram) {
|
||||
memcpy(screenram + 0x3f8, sprshad.spr_shapes, 8);
|
||||
VIC.spr_ena = sprshad.spr_ena;
|
||||
VIC.spr_hi_x = sprshad.spr_hi_x;
|
||||
memcpy(VIC.spr_pos, sprshad.spr_pos, 16);
|
||||
memcpy(VIC.spr_color, sprshad.spr_color, 8);
|
||||
VIC.spr_exp_x = sprshad.spr_exp_x;
|
||||
VIC.spr_exp_y = sprshad.spr_exp_y;
|
||||
VIC.spr_bg_prio = sprshad.spr_bg_prio;
|
||||
VIC.spr_mcolor = sprshad.spr_mcolor;
|
||||
VIC.spr_mcolor0 = sprshad.spr_mcolor0;
|
||||
VIC.spr_mcolor1 = sprshad.spr_mcolor1;
|
||||
}
|
||||
|
||||
void sprite_shape(char* vicbank, byte index, const char* sprite_data) {
|
||||
memcpy(vicbank + index*64, sprite_data, 64);
|
||||
}
|
||||
|
||||
void sprite_draw(byte i, word x, byte y, byte shape) {
|
||||
byte mask = 1 << i;
|
||||
sprshad.spr_ena |= mask;
|
||||
if (x >> 8)
|
||||
sprshad.spr_hi_x |= mask;
|
||||
else
|
||||
sprshad.spr_hi_x &= ~mask;
|
||||
sprshad.spr_pos[i].x = x;
|
||||
sprshad.spr_pos[i].y = y;
|
||||
sprshad.spr_shapes[i] = shape;
|
||||
}
|
||||
|
||||
void sprite_clear(void) {
|
||||
sprshad.spr_ena = 0;
|
||||
}
|
||||
|
30
presets/c64/sprites.h
Normal file
30
presets/c64/sprites.h
Normal file
@ -0,0 +1,30 @@
|
||||
#ifndef _SPRITES_H
|
||||
#define _SPRITES_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct {
|
||||
byte spr_ena; /* Enable sprites */
|
||||
byte spr_hi_x; /* High bits of X coordinate */
|
||||
byte spr_exp_x; /* Expand sprites in X dir */
|
||||
byte spr_exp_y; /* Expand sprites in Y dir */
|
||||
byte spr_bg_prio; /* Priority to background */
|
||||
byte spr_mcolor; /* Sprite multicolor bits */
|
||||
byte spr_mcolor0; /* Color 0 for multicolor sprites */
|
||||
byte spr_mcolor1; /* Color 1 for multicolor sprites */
|
||||
byte spr_color[8]; /* Colors for the sprites */
|
||||
struct {
|
||||
byte x; /* X coordinate */
|
||||
byte y; /* Y coordinate */
|
||||
} spr_pos[8];
|
||||
byte spr_shapes[8]; /* sprite shapes */
|
||||
} SpriteShadow;
|
||||
|
||||
extern SpriteShadow sprshad;
|
||||
|
||||
void sprite_update(char* screenram);
|
||||
void sprite_shape(char* vicbank, byte index, const char* sprite_data);
|
||||
void sprite_draw(byte i, word x, byte y, byte shape);
|
||||
void sprite_clear(void);
|
||||
|
||||
#endif
|
@ -309,6 +309,7 @@ var PREDEF_PALETTES = {
|
||||
0x002844,0x002844, 0x184864,0x184864, 0x306884,0x306884, 0x4484a0,0x4484a0, 0x589cb8,0x589cb8, 0x6cb4d0,0x6cb4d0, 0x7ccce8,0x7ccce8, 0x8ce0fc,0x8ce0fc
|
||||
],
|
||||
'astrocade':[0,2368548,4737096,7171437,9539985,11974326,14342874,16777215,12255269,14680137,16716142,16725394,16734903,16744155,16753663,16762879,11534409,13959277,16318866,16721334,16730842,16740095,16749311,16758783,10420330,12779662,15138995,16718039,16727291,16736767,16745983,16755199,8847495,11206827,13631696,15994612,16724735,16733951,16743423,16752639,6946975,9306307,11731175,14092287,16461055,16732415,16741631,16751103,4784304,7143637,9568505,11929087,14297599,16731647,16741119,16750335,2425019,4784352,7209215,9570047,12004095,14372863,16741375,16750847,191,2359523,4718847,7146495,9515263,11949311,14318079,16752127,187,224,2294015,4658431,7092735,9461247,11895551,14264063,176,213,249,2367999,4736511,7105279,9539327,11908095,159,195,3303,209151,2577919,4946431,7380735,9749247,135,171,7888,17140,681983,3050495,5484543,7853311,106,3470,12723,22231,31483,1548031,3916799,6285311,73,8557,17810,27318,36570,373759,2742271,5176575,4389,13641,23150,32402,41911,51163,2026495,4456447,9472,18724,27976,37485,46737,56246,1834970,4194303,14080,23296,32803,42055,51564,60816,2031541,4456409,18176,27648,36864,46116,55624,392556,2752401,5177269,21760,30976,40192,49667,58919,1572683,3932016,6291348,24320,33536,43008,52224,716810,3079982,5504851,7864183,25856,35328,44544,250368,2619136,4980503,7405371,9764703,26624,35840,45312,2413824,4782336,7143173,9568041,11927374,26112,35584,2338560,4707328,7141376,9502464,11927326,14286659,24832,2393344,4762112,7196160,9564928,11992832,14352155,16711487,2447360,4815872,7250176,9618688,12052992,14417664,16776990,16777027,4803328,7172096,9606144,11974912,14343424,16776965,16777001,16777038,6962176,9330688,11764992,14133504,16502272,16773655,16777019,16777055,8858112,11226880,13660928,16029440,16759818,16769070,16777043,16777079,10426112,12794624,15163392,16745475,16754727,16764235,16773488,16777108,11534848,13969152,16337664,16740388,16749640,16759148,16768401,16777141,12255232,14684928,16725795,16735047,16744556,16753808,16763317,16772569],
|
||||
'c64':[0x000000,0xffffff,0x2b3768,0xb2a470,0x863d6f,0x438d58,0x792835,0x6fc7b8,0x254f6f,0x003943,0x59679a,0x444444,0x6c6c6c,0x84d29a,0xb55e6c,0x959595],
|
||||
};
|
||||
|
||||
var PREDEF_LAYOUTS : {[id:string]:PixelEditorPaletteLayout} = {
|
||||
|
Loading…
Reference in New Issue
Block a user