mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-25 03:34:05 +00:00
137 lines
3.8 KiB
C
137 lines
3.8 KiB
C
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <cv.h>
|
|
#include <cvu.h>
|
|
|
|
// number of sprite patterns
|
|
#define NUM_SPRITE_PATTERNS 1
|
|
|
|
// Sprite bitmap -- can edit with Edit Bitmap button
|
|
const uint8_t sprite_data[NUM_SPRITE_PATTERNS][32] = {/*{w:16,h:16,remap:[4,0,1,2,3],brev:1}*/
|
|
{0xE0, 0xC0, 0xA0, 0x11, 0x0B, 0x05, 0x0B, 0x1F, 0x1F, 0x0F, 0x05, 0x0B, 0x11, 0xA0, 0xC0, 0xE0, 0x07, 0x03, 0x05, 0x88, 0xD0, 0xA0, 0xD0, 0xF8, 0xF8, 0xD0, 0xA0, 0xD0, 0x88, 0x05, 0x03, 0x07}
|
|
};
|
|
|
|
const cv_vmemp IMAGE = 0x1800;
|
|
const cv_vmemp SPRITES = 0x3c00;
|
|
const cv_vmemp SPRITE_PATTERNS = 0x3800;
|
|
|
|
// Make this variable volatile since it's modified in the NMI handler.
|
|
volatile bool vblank;
|
|
|
|
// NMI handler routine.
|
|
void nmi(void) {
|
|
vblank = true;
|
|
}
|
|
|
|
// Wait for next VBLANK (next frame)
|
|
void waitvblank() {
|
|
vblank = false; // reset vblank flag
|
|
while(!vblank); // wait for the NMI handler to set this flag.
|
|
}
|
|
|
|
// Move sprite s with specified controller.
|
|
void move_cursor(struct cvu_sprite *s, int controller) {
|
|
int x, y;
|
|
struct cv_controller_state cs;
|
|
|
|
// Read the game controller state.
|
|
cv_get_controller_state(&cs, controller);
|
|
|
|
// Copy the sprite X and Y coordinates to local variables.
|
|
x = s->x;
|
|
y = s->y;
|
|
|
|
// Move one pixel in the direction the joystick is pointed.
|
|
if (cs.joystick & CV_RIGHT) x++;
|
|
if (cs.joystick & CV_LEFT) x--;
|
|
if (cs.joystick & CV_DOWN) y++;
|
|
if (cs.joystick & CV_UP) y--;
|
|
|
|
// Make sure cursor doesn't leave the screen.
|
|
if(x < 0) x = 0;
|
|
if(x > 239) x = 239;
|
|
if(y < 0) y = 0;
|
|
if(y > 152) y = 152;
|
|
|
|
// Update the cursor struct in CPU RAM.
|
|
s->x = x;
|
|
s->y = y;
|
|
}
|
|
|
|
// Set all sprites offscreen.
|
|
void set_sprites_offscreen() {
|
|
struct cvu_sprite s;
|
|
s.x = 0;
|
|
s.y = 208; // set offscreen
|
|
s.name = 0;
|
|
s.tag = 0;
|
|
for (int i=0; i<32; i++) {
|
|
cvu_set_sprite(SPRITES, i, &s); // set sprite in Video RAM
|
|
}
|
|
}
|
|
|
|
void setup_vdp() {
|
|
cv_set_color_table(0x3fff);
|
|
cv_set_character_pattern_t(0x1fff);
|
|
cv_set_image_table(IMAGE);
|
|
cv_set_sprite_pattern_table(SPRITE_PATTERNS);
|
|
cv_set_sprite_attribute_table(SPRITES);
|
|
cv_set_screen_mode(CV_SCREENMODE_BITMAP); // Doesn't really matter much here. We only need a screen mode that supports sprites.
|
|
cvu_vmemset(0, 0, 0x4000); // clear Video RAM
|
|
}
|
|
|
|
void main(void)
|
|
{
|
|
struct cvu_sprite s; // The sprite used for the player cursor.
|
|
struct cvu_sprite s2; // The sprite used for the target cursor.
|
|
|
|
cv_set_screen_active(false); // Switch screen off.
|
|
setup_vdp(); // Setup VDP tables, erase video RAM
|
|
|
|
cv_set_sprite_magnification(false); // no sprite magnification
|
|
cv_set_sprite_big(true); // 16x16 pixel sprites.
|
|
|
|
// Set all sprites offscreen initially.
|
|
// This ensures they won't set the collision bit.
|
|
set_sprites_offscreen();
|
|
|
|
// Set attributes for sprite 0.
|
|
s.x = 60;
|
|
s.y = 60;
|
|
s.name = 0; // Use sprite pattern number 0.
|
|
cvu_set_sprite_color(&s, CV_COLOR_WHITE);
|
|
// Set attributes for sprite 1.
|
|
s2.x = 120;
|
|
s2.y = 60;
|
|
s2.name = 0;
|
|
cvu_set_sprite_color(&s2, CV_COLOR_YELLOW);
|
|
// Copy sprite pattern number 0 to graphics memory.
|
|
// Each sprite takes up 16*2 = 32 bytes.
|
|
cvu_memtovmemcpy(SPRITE_PATTERNS,
|
|
sprite_data,
|
|
NUM_SPRITE_PATTERNS*32);
|
|
|
|
// Turn on video display.
|
|
cv_set_screen_active(true);
|
|
|
|
// Set NMI handler so we can detect VBLANK.
|
|
cv_set_vint_handler(nmi);
|
|
// Set background color
|
|
cv_set_colors(0, CV_COLOR_BLUE);
|
|
for(;;)
|
|
{
|
|
// Wait for VBLANK (next frame).
|
|
waitvblank();
|
|
// Turn sprite 0 red if there was a collision last frame.
|
|
cvu_set_sprite_color(&s, cv_get_sprite_collission() ?
|
|
CV_COLOR_RED : CV_COLOR_WHITE);
|
|
// Move both cursors by their corresponding joystick.
|
|
move_cursor(&s, 0);
|
|
move_cursor(&s2, 1);
|
|
// Update VRAM with new sprite records.
|
|
cvu_set_sprite(SPRITES, 0, &s);
|
|
cvu_set_sprite(SPRITES, 1, &s2);
|
|
}
|
|
}
|