mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-25 00:02:16 +00:00
ported some SMS and GG presets from coleco
This commit is contained in:
1 parent
801dc79c3a
commit
ced4721c13
13 files changed
+1224
-29
No files matched your search
+44
-17
@@ -5,13 +5,41 @@
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Unified common code for libcv platforms (coleco, msx-libcv, sms-sg1000-libcv,
|
||||
sms-sms-libcv, sms-gg-libcv). Differences are selected by the CV_CV / CV_MSX /
|
||||
CV_SMS defines (set by the platform) plus CV_MODE4 for SMS/GG mode-4 builds.
|
||||
/* Unified common code for libcv platforms.
|
||||
Differences are selected by the CV_CV / CV_MSX / CV_SMS defines
|
||||
(set by the platform) plus CV_MODE4 for SMS/GG mode-4 builds.
|
||||
Keep this file identical across those preset directories. */
|
||||
|
||||
volatile uint_fast8_t vint_counter;
|
||||
|
||||
#if defined(CV_MODE4)
|
||||
// current name-table attribute (palette/flip/priority) used for text output
|
||||
byte text_attr = 0;
|
||||
|
||||
// default mode-4 palette: entries 0-15 are the background (tile) palette,
|
||||
// entries 16-31 are the sprite palette. CHR_GENERIC glyphs use colors 0-3.
|
||||
#if defined(__PLATFORM_SMS_GG_LIBCV__)
|
||||
#define PALCOL(r,g,b) ((unsigned short)(((b)*5)<<8 | ((g)*5)<<4 | ((r)*5)))
|
||||
const unsigned short DEFAULT_PALETTE[32] = {
|
||||
#else
|
||||
#define PALCOL(r,g,b) ((unsigned char)(((b)<<4) | ((g)<<2) | (r)))
|
||||
const unsigned char DEFAULT_PALETTE[32] = {
|
||||
#endif
|
||||
PALCOL(0,0,0), PALCOL(3,3,3), PALCOL(3,3,0), PALCOL(1,3,1),
|
||||
PALCOL(0,0,3), PALCOL(3,0,0), PALCOL(3,0,3), PALCOL(0,3,3),
|
||||
PALCOL(2,2,2), PALCOL(1,1,1), PALCOL(3,1,1), PALCOL(3,3,1),
|
||||
PALCOL(1,1,3), PALCOL(2,0,0), PALCOL(0,2,0), PALCOL(0,0,2),
|
||||
PALCOL(0,0,0), PALCOL(3,3,3), PALCOL(3,3,0), PALCOL(3,0,0),
|
||||
PALCOL(0,3,0), PALCOL(0,0,3), PALCOL(3,0,3), PALCOL(0,3,3),
|
||||
PALCOL(2,2,2), PALCOL(3,1,1), PALCOL(1,3,1), PALCOL(1,1,3),
|
||||
PALCOL(2,0,0), PALCOL(0,2,0), PALCOL(0,0,2), PALCOL(1,1,1),
|
||||
};
|
||||
|
||||
void set_default_palette() {
|
||||
cvu_memtocmemcpy(0xc000, DEFAULT_PALETTE, sizeof(DEFAULT_PALETTE));
|
||||
}
|
||||
#endif
|
||||
|
||||
void vint_handler(void) {
|
||||
vint_counter++;
|
||||
}
|
||||
@@ -39,7 +67,12 @@ void clrscr() {
|
||||
}
|
||||
|
||||
word getimageaddr(byte x, byte y) {
|
||||
#if defined(CV_MODE4)
|
||||
// mode 4: two bytes per cell (tile + attribute)
|
||||
return IMAGE + y*ROWSTRIDE + x*2;
|
||||
#else
|
||||
return IMAGE + y*ROWSTRIDE + x;
|
||||
#endif
|
||||
}
|
||||
|
||||
byte getcharxy(byte x, byte y) {
|
||||
@@ -47,7 +80,13 @@ byte getcharxy(byte x, byte y) {
|
||||
}
|
||||
|
||||
void putcharxy(byte x, byte y, byte attr) {
|
||||
#if defined(CV_MODE4)
|
||||
cv_vmemp addr = getimageaddr(x,y);
|
||||
cvu_voutb(attr, addr);
|
||||
cvu_voutb(text_attr, addr+1);
|
||||
#else
|
||||
cvu_voutb(attr, getimageaddr(x,y));
|
||||
#endif
|
||||
}
|
||||
|
||||
void putstringxy(byte x, byte y, const char* string) {
|
||||
@@ -57,18 +96,7 @@ void putstringxy(byte x, byte y, const char* string) {
|
||||
}
|
||||
|
||||
#if defined(CV_MODE4)
|
||||
// mode 4 aliases (same functions, shorter names)
|
||||
byte getchar(byte x, byte y) {
|
||||
return getcharxy(x, y);
|
||||
}
|
||||
|
||||
void putchar(byte x, byte y, byte attr) {
|
||||
putcharxy(x, y, attr);
|
||||
}
|
||||
|
||||
void putstring(byte x, byte y, const char* string) {
|
||||
putstringxy(x, y, string);
|
||||
}
|
||||
// mode 4 uses the same putcharxy()/putstringxy()/getcharxy() API as other modes.
|
||||
#endif
|
||||
|
||||
void delay(byte i) {
|
||||
@@ -130,8 +158,6 @@ void vdp_setup() {
|
||||
cv_set_screen_mode(CV_SCREENMODE_4_224);
|
||||
cv_set_character_pattern_t(PATTERN | 0x3000);
|
||||
cv_set_image_table(IMAGE | 0x400);
|
||||
// cv_set_color_table(COLOR | 0xfff);
|
||||
// cv_set_sprite_pattern_table(SPRITE_PATTERNS | 0x1800);
|
||||
#else
|
||||
cv_set_screen_mode(CV_SCREENMODE_STANDARD);
|
||||
cv_set_image_table(IMAGE);
|
||||
@@ -145,6 +171,7 @@ void vdp_setup() {
|
||||
copy_default_character_set();
|
||||
cvu_vmemset(COLOR, 0xf1, 32);
|
||||
#endif
|
||||
cvu_vmemset(SPRITES, 0xff, 0x400);
|
||||
cv_set_sprite_attribute_table(SPRITES);
|
||||
cv_set_sprite_big(true);
|
||||
}
|
||||
|
||||
@@ -67,12 +67,8 @@ extern char font_bitmap_0[];
|
||||
#define COLOR_FG(fg) (((fg)<<4))
|
||||
|
||||
#ifndef LOCHAR
|
||||
#if defined(CV_MODE4)
|
||||
#define LOCHAR 0x20
|
||||
#else
|
||||
#define LOCHAR 0x0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define CHAR(ch) (ch-LOCHAR)
|
||||
|
||||
@@ -94,10 +90,10 @@ extern byte getcharxy(byte x, byte y);
|
||||
extern void putcharxy(byte x, byte y, byte attr);
|
||||
extern void putstringxy(byte x, byte y, const char* string);
|
||||
#if defined(CV_MODE4)
|
||||
// mode 4 aliases (same functions, shorter names)
|
||||
extern byte getchar(byte x, byte y);
|
||||
extern void putchar(byte x, byte y, byte attr);
|
||||
extern void putstring(byte x, byte y, const char* string);
|
||||
// name-table attribute (palette/flip/priority) used by putcharxy()/putstringxy()
|
||||
extern byte text_attr;
|
||||
// load the default 32-entry mode-4 palette into CRAM
|
||||
extern void set_default_palette();
|
||||
#endif
|
||||
extern void delay(byte i);
|
||||
extern byte rndint(byte a, byte b);
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
../coleco/common.c
|
||||
@@ -0,0 +1,202 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
/* Unified common code for libcv platforms.
|
||||
Differences are selected by the CV_CV / CV_MSX / CV_SMS defines
|
||||
(set by the platform) plus CV_MODE4 for SMS/GG mode-4 builds.
|
||||
Keep this file identical across those preset directories. */
|
||||
|
||||
volatile uint_fast8_t vint_counter;
|
||||
|
||||
#if defined(CV_MODE4)
|
||||
// current name-table attribute (palette/flip/priority) used for text output
|
||||
byte text_attr = 0;
|
||||
|
||||
// default mode-4 palette: entries 0-15 are the background (tile) palette,
|
||||
// entries 16-31 are the sprite palette. CHR_GENERIC glyphs use colors 0-3.
|
||||
#if defined(__PLATFORM_SMS_GG_LIBCV__)
|
||||
/*{pal:444,n:32}*/
|
||||
const unsigned short DEFAULT_PALETTE[32] = {
|
||||
0x000, 0x00F, 0x0F0, 0x0FF, 0xF00, 0xF0F, 0xFF0, 0xFFF,
|
||||
0x555, 0x55F, 0xFA5, 0x5AF, 0xAA0, 0xAFA, 0xFAF, 0xAFF,
|
||||
0x000, 0x00F, 0x0F0, 0x0FF, 0xF00, 0xF0F, 0xFF0, 0xFFF,
|
||||
0x555, 0x55F, 0xFA5, 0x5AF, 0xAA0, 0xAFA, 0xFAF, 0xAFF
|
||||
};
|
||||
#else
|
||||
/*{pal:222,n:32}*/
|
||||
const unsigned char DEFAULT_PALETTE[32] = {
|
||||
0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
|
||||
0x15, 0x17, 0x39, 0x1B, 0x28, 0x2E, 0x3B, 0x2F,
|
||||
0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F,
|
||||
0x15, 0x17, 0x39, 0x1B, 0x28, 0x2E, 0x3B, 0x2F,
|
||||
};
|
||||
#endif
|
||||
|
||||
void set_default_palette() {
|
||||
cvu_memtocmemcpy(0xc000, DEFAULT_PALETTE, sizeof(DEFAULT_PALETTE));
|
||||
}
|
||||
#endif
|
||||
|
||||
void vint_handler(void) {
|
||||
vint_counter++;
|
||||
}
|
||||
|
||||
const unsigned char reverse_lookup[16] = {
|
||||
0x0, 0x8, 0x4, 0xc, 0x2, 0xa, 0x6, 0xe, 0x1, 0x9, 0x5, 0xd, 0x3, 0xb, 0x7, 0xf, };
|
||||
|
||||
byte reverse_bits(byte n) {
|
||||
return (reverse_lookup[n&0b1111] << 4) | reverse_lookup[n>>4];
|
||||
}
|
||||
|
||||
void flip_sprite_patterns(word dest, const byte* patterns, word len) {
|
||||
word i;
|
||||
for (i=0; i<len; i++) {
|
||||
#if defined(CV_MODE4)
|
||||
cvu_voutb(reverse_bits(*patterns++), dest++);
|
||||
#else
|
||||
cvu_voutb(reverse_bits(*patterns++), dest++ ^ 16); // swap left/right chars
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void clrscr() {
|
||||
cvu_vmemset(IMAGE, 0, ROWSTRIDE*ROWS);
|
||||
}
|
||||
|
||||
word getimageaddr(byte x, byte y) {
|
||||
#if defined(CV_MODE4)
|
||||
// mode 4: two bytes per cell (tile + attribute)
|
||||
return IMAGE + y*ROWSTRIDE + x*2;
|
||||
#else
|
||||
return IMAGE + y*ROWSTRIDE + x;
|
||||
#endif
|
||||
}
|
||||
|
||||
byte getcharxy(byte x, byte y) {
|
||||
return cvu_vinb(getimageaddr(x,y));
|
||||
}
|
||||
|
||||
void putcharxy(byte x, byte y, byte attr) {
|
||||
#if defined(CV_MODE4)
|
||||
cv_vmemp addr = getimageaddr(x,y);
|
||||
cvu_voutb(attr, addr);
|
||||
cvu_voutb(text_attr, addr+1);
|
||||
#else
|
||||
cvu_voutb(attr, getimageaddr(x,y));
|
||||
#endif
|
||||
}
|
||||
|
||||
void putstringxy(byte x, byte y, const char* string) {
|
||||
while (*string) {
|
||||
putcharxy(x++, y, CHAR(*string++));
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(CV_MODE4)
|
||||
// mode 4 uses the same putcharxy()/putstringxy()/getcharxy() API as other modes.
|
||||
#endif
|
||||
|
||||
void delay(byte i) {
|
||||
while (i--) {
|
||||
wait_vsync();
|
||||
}
|
||||
}
|
||||
|
||||
byte rndint(byte a, byte b) {
|
||||
return ((byte)rand() % (b-a+1)) + a;
|
||||
}
|
||||
|
||||
void memset_safe(void* _dest, char ch, word size) {
|
||||
byte* dest = _dest;
|
||||
while (size--) {
|
||||
*dest++ = ch;
|
||||
}
|
||||
}
|
||||
|
||||
char in_rect(byte x, byte y, byte x0, byte y0, byte w, byte h) {
|
||||
return ((byte)(x-x0) < w && (byte)(y-y0) < h); // unsigned
|
||||
}
|
||||
|
||||
void draw_bcd_word(byte x, byte y, word bcd) {
|
||||
byte j;
|
||||
x += 3;
|
||||
for (j=0; j<4; j++) {
|
||||
putcharxy(x, y, CHAR('0'+(bcd&0xf)));
|
||||
x--;
|
||||
bcd >>= 4;
|
||||
}
|
||||
}
|
||||
|
||||
// add two 16-bit BCD values
|
||||
word bcd_add(word a, word b) __naked {
|
||||
a; b; // to avoid warning
|
||||
__asm
|
||||
push ix
|
||||
ld ix,#0
|
||||
add ix,sp
|
||||
ld a,4 (ix)
|
||||
add a, 6 (ix)
|
||||
daa
|
||||
ld c,a
|
||||
ld a,5 (ix)
|
||||
adc a, 7 (ix)
|
||||
daa
|
||||
ld b,a
|
||||
ld l, c
|
||||
ld h, b
|
||||
pop ix
|
||||
ret
|
||||
__endasm;
|
||||
}
|
||||
|
||||
void vdp_setup() {
|
||||
cv_set_screen_active(false);
|
||||
#if defined(CV_MODE4)
|
||||
cv_set_screen_mode(CV_SCREENMODE_4_224);
|
||||
cv_set_character_pattern_t(PATTERN | 0x3000);
|
||||
cv_set_image_table(IMAGE | 0x400);
|
||||
#else
|
||||
cv_set_screen_mode(CV_SCREENMODE_STANDARD);
|
||||
cv_set_image_table(IMAGE);
|
||||
cv_set_character_pattern_t(PATTERN);
|
||||
cv_set_color_table(COLOR);
|
||||
cv_set_sprite_pattern_table(SPRITE_PATTERNS);
|
||||
// load the default font and set a visible default color (white on black).
|
||||
// the MSX startup code does this for us, but the ColecoVision and
|
||||
// SG-1000 leave VRAM zeroed -- without this, putstringxy() output is
|
||||
// invisible (blank pattern table) and the color table is transparent.
|
||||
copy_default_character_set();
|
||||
cvu_vmemset(COLOR, 0xf1, 32);
|
||||
#endif
|
||||
cvu_vmemset(SPRITES, 0xff, 0x400);
|
||||
cv_set_sprite_attribute_table(SPRITES);
|
||||
cv_set_sprite_big(true);
|
||||
}
|
||||
|
||||
void set_shifted_pattern(const byte* src, word dest, byte shift) {
|
||||
byte y;
|
||||
for (y=0; y<8; y++) {
|
||||
byte a = src[y+8];
|
||||
byte b = src[y];
|
||||
cvu_voutb(a>>shift, dest);
|
||||
cvu_voutb(b>>shift | a<<(8-shift), dest+8);
|
||||
cvu_voutb(b<<(8-shift), dest+16);
|
||||
dest++;
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(CV_MODE4)
|
||||
void copy_default_character_set() {
|
||||
#ifdef CV_MSX
|
||||
static byte __at(0xf91f) CGPNT;
|
||||
static byte* __at(0xf920) CGADDR;
|
||||
cvu_memtovmemcpy(PATTERN, CGADDR, 256*8);
|
||||
#else
|
||||
cvu_memtovmemcpy(PATTERN, (void *)(font_bitmap_0 - '0'*8), 256*8);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -1 +0,0 @@
|
||||
../coleco/common.h
|
||||
@@ -0,0 +1,115 @@
|
||||
|
||||
#ifndef _CV_COMMON_H
|
||||
#define _CV_COMMON_H
|
||||
|
||||
/* Unified common header for libcv platforms.
|
||||
The build defines one of: CV_CV (ColecoVision), CV_MSX, CV_SMS (SG-1000/SMS/Game Gear).
|
||||
CV_MODE4 is defined for SMS/GG mode-4 builds (2 bytes per tile, 32x28).
|
||||
Keep this file identical across the coleco, msx-libcv, sms-sg1000-libcv,
|
||||
sms-sms-libcv and sms-gg-libcv preset directories. */
|
||||
|
||||
#if defined(CV_MODE4)
|
||||
/* VRAM map (mode 4)
|
||||
0x0000 - 0x3fff character pattern table
|
||||
0x3000 - 0x36ff image table
|
||||
0x3c00 - 0x3fff sprite attribute table */
|
||||
#define PATTERN ((const cv_vmemp)0x0000)
|
||||
#define IMAGE ((const cv_vmemp)0x3000)
|
||||
#define SPRITES ((const cv_vmemp)0x3c00)
|
||||
#else
|
||||
/* VRAM map
|
||||
0x0000 - 0x17ff character pattern table
|
||||
0x1800 - 0x1aff image table
|
||||
0x2000 - 0x37ff color table
|
||||
0x3800 - 0x3bff sprite pattern table
|
||||
0x3c00 - 0x3fff sprite attribute table */
|
||||
#define PATTERN ((const cv_vmemp)0x0000)
|
||||
#define IMAGE ((const cv_vmemp)0x1800)
|
||||
#define COLOR ((const cv_vmemp)0x2000)
|
||||
#define SPRITE_PATTERNS ((const cv_vmemp)0x3800)
|
||||
#define SPRITES ((const cv_vmemp)0x3c00)
|
||||
#endif
|
||||
|
||||
#ifndef COLS
|
||||
#define COLS 32
|
||||
#endif
|
||||
|
||||
#ifndef ROWS
|
||||
#if defined(CV_MODE4)
|
||||
#define ROWS 28
|
||||
#else
|
||||
#define ROWS 24
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* bytes per row in the name table (mode 4 has a color byte per tile) */
|
||||
#if defined(CV_MODE4)
|
||||
#define ROWSTRIDE (COLS*2)
|
||||
#else
|
||||
#define ROWSTRIDE COLS
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef signed char sbyte;
|
||||
typedef unsigned short word;
|
||||
|
||||
#ifdef CV_CV
|
||||
uintptr_t __at(0x6a) font_bitmap_a;
|
||||
uintptr_t __at(0x6c) font_bitmap_0;
|
||||
#endif
|
||||
|
||||
#ifdef CV_SMS
|
||||
extern char font_bitmap_a[];
|
||||
extern char font_bitmap_0[];
|
||||
#endif
|
||||
|
||||
#define COLOR_FGBG(fg,bg) (((fg)<<4)|(bg))
|
||||
#define COLOR_FG(fg) (((fg)<<4))
|
||||
|
||||
#ifndef LOCHAR
|
||||
#define LOCHAR 0x0
|
||||
#endif
|
||||
|
||||
#define CHAR(ch) (ch-LOCHAR)
|
||||
|
||||
#define wait_vsync() __asm__("halt")
|
||||
|
||||
extern volatile uint_fast8_t vint_counter;
|
||||
|
||||
extern void vint_handler(void);
|
||||
extern byte reverse_bits(byte n);
|
||||
extern void flip_sprite_patterns(word dest, const byte* patterns, word len);
|
||||
|
||||
extern char cursor_x;
|
||||
extern char cursor_y;
|
||||
|
||||
extern void clrscr();
|
||||
|
||||
extern word getimageaddr(byte x, byte y);
|
||||
extern byte getcharxy(byte x, byte y);
|
||||
extern void putcharxy(byte x, byte y, byte attr);
|
||||
extern void putstringxy(byte x, byte y, const char* string);
|
||||
#if defined(CV_MODE4)
|
||||
// name-table attribute (palette/flip/priority) used by putcharxy()/putstringxy()
|
||||
extern byte text_attr;
|
||||
// load the default 32-entry mode-4 palette into CRAM
|
||||
extern void set_default_palette();
|
||||
#endif
|
||||
extern void delay(byte i);
|
||||
extern byte rndint(byte a, byte b);
|
||||
|
||||
extern void memset_safe(void* _dest, char ch, word size);
|
||||
extern char in_rect(byte x, byte y, byte x0, byte y0, byte w, byte h);
|
||||
// print 4-digit BCD value
|
||||
extern void draw_bcd_word(byte x, byte y, word bcd);
|
||||
// add two 16-bit BCD values
|
||||
extern word bcd_add(word a, word b);
|
||||
|
||||
extern void vdp_setup();
|
||||
extern void set_shifted_pattern(const byte* src, word dest, byte shift);
|
||||
|
||||
#if !defined(CV_MODE4)
|
||||
extern void copy_default_character_set();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
This demo animates two 16 x 16 sprites.
|
||||
It also uses the collision detection bit.
|
||||
|
||||
Ported to the Sega VDP's mode 4: each 8x16 sprite is
|
||||
built from two 8x8 pattern tiles, and a 16x16 cursor is
|
||||
two sprites side by side (a "metasprite").
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
// tile number of the cursor's top-left 8x8 tile
|
||||
#define SPR_CURSOR 0x80
|
||||
// inverted cursor used to show collision (SPR_CURSOR+4)
|
||||
#define SPR_CURSOR_HIT (SPR_CURSOR+4)
|
||||
|
||||
// 16x16 monochrome cursor (a crosshair), 2 bytes per row
|
||||
static const uint8_t cursor_mono[16*2] = {
|
||||
0x00, 0x00,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0xff, 0xff,
|
||||
0xff, 0xff,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x01, 0x80,
|
||||
0x00, 0x00,
|
||||
};
|
||||
|
||||
// Expand a 16x16 mono bitmap into four mode-4 8x8 tiles
|
||||
// (top-left, bottom-left, top-right, bottom-right).
|
||||
// Each tile is 8 rows of 4 plane bytes; we use plane 0
|
||||
// so the sprites are drawn in color 1 of the sprite palette.
|
||||
void expand_cursor(word dest, byte invert) {
|
||||
byte r;
|
||||
for (r=0; r<16; r++) {
|
||||
byte left = cursor_mono[r*2];
|
||||
byte right = cursor_mono[r*2+1];
|
||||
byte half = r >> 3; // 0 = top half, 1 = bottom half
|
||||
word a = dest + half*32 + (r & 7)*4;
|
||||
if (invert) { left = ~left; right = ~right; }
|
||||
cvu_voutb(left, a);
|
||||
cvu_voutb(0, a+1);
|
||||
cvu_voutb(0, a+2);
|
||||
cvu_voutb(0, a+3);
|
||||
cvu_voutb(right, a+2*32);
|
||||
cvu_voutb(0, a+2*32+1);
|
||||
cvu_voutb(0, a+2*32+2);
|
||||
cvu_voutb(0, a+2*32+3);
|
||||
}
|
||||
}
|
||||
|
||||
void setup_graphics() {
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
set_default_palette();
|
||||
// build the normal and inverted cursor sprites
|
||||
expand_cursor(PATTERN + SPR_CURSOR*32, 0);
|
||||
expand_cursor(PATTERN + SPR_CURSOR_HIT*32, 1);
|
||||
}
|
||||
|
||||
// Set all sprites offscreen.
|
||||
void set_sprites_offscreen() {
|
||||
struct cvu_sprite4 s;
|
||||
byte i;
|
||||
s.x = 0;
|
||||
s.y = 240; // set offscreen
|
||||
s.name = 0;
|
||||
for (i=0; i<64; i++) {
|
||||
cvu_set_sprite4(SPRITES, i, &s);
|
||||
}
|
||||
}
|
||||
|
||||
// Move a cursor with the specified controller.
|
||||
// The struct stores the top-left corner of the 16x16 cursor.
|
||||
void move_cursor(struct cvu_sprite4 *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 > 231) x = 231;
|
||||
if (y < 0) y = 0;
|
||||
if (y > 151) y = 151;
|
||||
|
||||
// Update the cursor struct in CPU RAM.
|
||||
s->x = x;
|
||||
s->y = y;
|
||||
}
|
||||
|
||||
// Write a 16x16 cursor as two 8x16 sprites.
|
||||
void draw_cursor(byte index, struct cvu_sprite4 *s) {
|
||||
struct cvu_sprite4 right;
|
||||
right.y = s->y;
|
||||
right.x = s->x + 8;
|
||||
right.name = s->name + 2;
|
||||
cvu_set_sprite4(SPRITES, index, s);
|
||||
cvu_set_sprite4(SPRITES, index+1, &right);
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
struct cvu_sprite4 s; // The sprite used for the player cursor.
|
||||
struct cvu_sprite4 s2; // The sprite used for the target cursor.
|
||||
byte name;
|
||||
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
|
||||
cv_set_sprite_magnification(false); // no sprite magnification
|
||||
cv_set_sprite_big(true); // 8x16 pixel sprites.
|
||||
|
||||
// Set all sprites offscreen initially.
|
||||
// This ensures they won't set the collision bit.
|
||||
set_sprites_offscreen();
|
||||
|
||||
// Set attributes for cursor 0.
|
||||
s.x = 60;
|
||||
s.y = 60;
|
||||
s.name = SPR_CURSOR;
|
||||
// Set attributes for cursor 1.
|
||||
s2.x = 120;
|
||||
s2.y = 60;
|
||||
s2.name = SPR_CURSOR;
|
||||
|
||||
// Turn on video display.
|
||||
cv_set_screen_active(true);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
// Wait for VBLANK (next frame).
|
||||
wait_vsync();
|
||||
// Use the inverted cursor if there was a collision last frame.
|
||||
name = cv_get_sprite_collission() ? SPR_CURSOR_HIT : SPR_CURSOR;
|
||||
// Move both cursors by their corresponding joystick.
|
||||
move_cursor(&s, 0);
|
||||
move_cursor(&s2, 1);
|
||||
s.name = name;
|
||||
s2.name = name;
|
||||
// Update VRAM with new sprite records.
|
||||
draw_cursor(0, &s);
|
||||
draw_cursor(2, &s2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
This is a demonstration of integrating the C
|
||||
standard I/O (stdio) functions with the display,
|
||||
so that standard functions like printf() can be used.
|
||||
|
||||
It has been ported to the Sega VDP's mode 4 text mode.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
char cursor_x; // current cursor column
|
||||
char cursor_y; // current cursor row
|
||||
|
||||
void setup_graphics() {
|
||||
// copy the font/tileset into the character pattern table
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
// load the default mode-4 palette
|
||||
set_default_palette();
|
||||
cv_set_colors(CV_COLOR_BLACK, CV_COLOR_BLACK);
|
||||
}
|
||||
|
||||
void setup_stdio() {
|
||||
cursor_x = 0;
|
||||
cursor_y = 0;
|
||||
clrscr();
|
||||
}
|
||||
|
||||
// scroll the screen upward, by copying each row
|
||||
// of VRAM to its previous row.
|
||||
void scrollup() {
|
||||
char buf[ROWSTRIDE];
|
||||
char y;
|
||||
for (y=0; y<ROWS-1; y++) {
|
||||
cvu_vmemtomemcpy(buf, IMAGE + ROWSTRIDE*(y+1), ROWSTRIDE);
|
||||
cvu_memtovmemcpy(IMAGE + ROWSTRIDE*y, buf, ROWSTRIDE);
|
||||
}
|
||||
cvu_vmemset(IMAGE + ROWSTRIDE*(ROWS-1), 0, ROWSTRIDE);
|
||||
}
|
||||
|
||||
// move cursor to next line, scrolling when it hits the bottom.
|
||||
void newline() {
|
||||
if (cursor_y >= ROWS-1) {
|
||||
scrollup();
|
||||
} else {
|
||||
cursor_y++;
|
||||
}
|
||||
}
|
||||
|
||||
// write a character to the screen.
|
||||
int putchar(int ch) {
|
||||
switch (ch) {
|
||||
case '\n':
|
||||
newline(); // move cursor to next line
|
||||
case '\r':
|
||||
cursor_x = 0; // move cursor to start of line
|
||||
return 0;
|
||||
}
|
||||
// output character (tile) + attribute to the name table
|
||||
putcharxy(cursor_x, cursor_y, ch);
|
||||
// move cursor to right, going to next line if necessary
|
||||
cursor_x++;
|
||||
if (cursor_x >= COLS) {
|
||||
newline();
|
||||
cursor_x = 0;
|
||||
}
|
||||
return ch;
|
||||
}
|
||||
|
||||
void main() {
|
||||
unsigned char byteval = 123;
|
||||
signed char charval = 123;
|
||||
short shortval = 12345;
|
||||
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
setup_stdio();
|
||||
cv_set_screen_active(true);
|
||||
printf("HELLO WORLD!\n");
|
||||
while (1) {
|
||||
printf("char %d byte %u sh %d\n",
|
||||
charval++, byteval++, shortval++);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,114 @@
|
||||
|
||||
/*
|
||||
Demonstrates playing multi-voice music on the SN76489A PSG
|
||||
using the CVLib functions.
|
||||
|
||||
Similar to the music example in "Making Arcade Games in C".
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
#include "common.h"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
//
|
||||
// MUSIC ROUTINES
|
||||
//
|
||||
|
||||
void music_start(const byte* music);
|
||||
void music_update();
|
||||
|
||||
// Namespace(bias=0, freq=1789772.5, length=64, maxbits=15.0, upper=49)
|
||||
// 437.0 459.515928524 49
|
||||
const int note_table[64] = {
|
||||
17356, 32764, 30926, 29190, 27551, 26005, 24546, 23168, 21868, 20640, 19482, 18388, 17356, 32765, 30926, 29190, 27552, 26005, 24546, 23168, 21868, 20640, 19482, 18389, 17357, 16382, 15463, 14595, 13776, 13003, 12273, 11584, 10934, 10320, 9741, 9194, 8678, 8191, 7731, 7298, 6888, 6501, 6136, 5792, 5467, 5160, 4871, 4597, 4339, 4096, 3866, 3649, 3444, 3251, 3068, 2896, 2733, 2580, 2435, 2299, 2170, 2048, 1933, 1824, };
|
||||
|
||||
struct {
|
||||
byte volume;
|
||||
} voice[3];
|
||||
|
||||
byte music_index = 0;
|
||||
byte cur_duration = 0;
|
||||
byte num_voices = 3;
|
||||
|
||||
static const byte* music_ptr = NULL;
|
||||
|
||||
inline byte next_music_byte() {
|
||||
return *music_ptr++;
|
||||
}
|
||||
|
||||
void music_update() {
|
||||
byte ch;
|
||||
byte freech = 0;
|
||||
for (ch=0; ch<num_voices; ch++) {
|
||||
if (voice[ch].volume) {
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_0+ch*2, 32-voice[ch].volume--);
|
||||
} else {
|
||||
freech = ch;
|
||||
}
|
||||
}
|
||||
if (music_ptr) {
|
||||
ch = freech;
|
||||
while (cur_duration == 0) {
|
||||
byte note = next_music_byte();
|
||||
if ((note & 0x80) == 0) {
|
||||
int period = note_table[note & 63];
|
||||
cv_set_attenuation(CV_SOUNDCHANNEL_0+ch*2, 32);
|
||||
cv_set_frequency(CV_SOUNDCHANNEL_0+ch*2, period);
|
||||
voice[ch].volume = 31;
|
||||
ch = ch ? ch-1 : num_voices-1;
|
||||
} else {
|
||||
if (note == 0xff)
|
||||
music_ptr = NULL;
|
||||
cur_duration = note & 63;
|
||||
}
|
||||
}
|
||||
cur_duration--;
|
||||
}
|
||||
}
|
||||
|
||||
void music_start(const byte* music) __critical {
|
||||
music_ptr = music;
|
||||
cur_duration = 0;
|
||||
}
|
||||
|
||||
///
|
||||
/// MUSIC TEST
|
||||
///
|
||||
|
||||
#ifdef __MAIN__
|
||||
|
||||
const byte music1[] = {
|
||||
0x35,0x41,0x8a,0x37,0x43,0x8a,0x33,0x3f,0x8a,0x30,0x3c,0x94,0x3e,0x32,0x8a,0x3a,0x2e,0x94,0x35,0x29,0x8a,0x37,0x2b,0x8a,0x33,0x27,0x8a,0x30,0x24,0x94,0x32,0x26,0x8a,0x2e,0x22,0x94,0x29,0x1d,0x8a,0x2b,0x1f,0x8a,0x27,0x1b,0x8a,0x24,0x18,0x94,0x1a,0x26,0x8a,0x18,0x24,0x8a,0x17,0x23,0x8a,0x16,0x22,0xa8,0x3a,0x35,0x32,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x22,0x1f,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x41,0x8a,0x42,0x39,0x36,0x8a,0x43,0x3a,0x37,0x8a,0x3f,0x37,0x33,0x8a,0x35,0x41,0x38,0x8a,0x3a,0x37,0x43,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x41,0x38,0x35,0x94,0x3f,0x33,0x37,0x94,0x1f,0x22,0x27,0x94,0x27,0x22,0x1f,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x1f,0x22,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x24,0x27,0x94,0x1f,0x13,0x94,0x3c,0x33,0x30,0x8a,0x3a,0x33,0x2e,0x8a,0x39,0x33,0x2d,0x8a,0x3c,0x30,0x8a,0x3f,0x33,0x1d,0x8a,0x43,0x37,0x8a,0x1d,0x8a,0x41,0x35,0x8a,0x3f,0x33,0x27,0x8a,0x3c,0x30,0x8a,0x41,0x35,0x38,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x27,0x22,0x1f,0x8a,0x2b,0x8a,0x33,0x16,0x22,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x13,0x1f,0x8a,0x3f,0x33,0x37,0x8a,0x41,0x38,0x35,0x8a,0x42,0x39,0x36,0x8a,0x37,0x3a,0x43,0x8a,0x3f,0x37,0x33,0x8a,0x41,0x38,0x35,0x8a,0x43,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x41,0x38,0x35,0x94,0x3f,0x37,0x33,0x94,0x27,0x22,0x1f,0x94,0x2b,0x27,0x22,0x94,0x3f,0x33,0x8a,0x41,0x35,0x8a,0x43,0x37,0x27,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2b,0x8a,0x43,0x37,0x8a,0x25,0x19,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2b,0x8a,0x3f,0x33,0x8a,0x43,0x37,0x24,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2c,0x8a,0x43,0x37,0x8a,0x23,0x17,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2c,0x8a,0x3f,0x33,0x8a,0x3a,0x37,0x43,0x8a,0x3f,0x37,0x33,0x8a,0x41,0x38,0x35,0x8a,0x43,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x32,0x35,0x8a,0x41,0x35,0x38,0x94,0x3f,0x33,0x37,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x27,0x22,0x1f,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x25,0x22,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x35,0x41,0x38,0x8a,0x42,0x39,0x36,0x8a,0x43,0x3a,0x37,0x8a,0x3f,0x37,0x33,0x8a,0x38,0x35,0x41,0x8a,0x43,0x3a,0x37,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x35,0x41,0x38,0x94,0x37,0x33,0x3f,0x94,0x27,0x22,0x1f,0x94,0x27,0x22,0x1f,0x94,0x29,0x26,0x22,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x22,0x1f,0x27,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x27,0x24,0x94,0x1f,0x13,0x94,0x3c,0x33,0x30,0x8a,0x3a,0x33,0x2e,0x8a,0x2d,0x33,0x39,0x8a,0x3c,0x30,0x8a,0x3f,0x33,0x27,0x8a,0x43,0x37,0x8a,0x1d,0x8a,0x41,0x35,0x8a,0x33,0x3f,0x27,0x8a,0x3c,0x30,0x8a,0x41,0x38,0x35,0x94,0x22,0x16,0x94,0x24,0x18,0x94,0x29,0x26,0x1a,0x8a,0x2a,0x8a,0x2b,0x1b,0x8a,0x33,0x8a,0x22,0x27,0x1f,0x8a,0x2b,0x8a,0x33,0x22,0x16,0x94,0x2b,0x27,0x25,0x8a,0x33,0x8a,0x20,0x14,0x94,0x24,0x27,0x94,0x1f,0x13,0x8a,0x3f,0x37,0x33,0x8a,0x41,0x38,0x35,0x8a,0x36,0x39,0x42,0x8a,0x43,0x3a,0x37,0x8a,0x3f,0x37,0x33,0x8a,0x41,0x38,0x35,0x8a,0x37,0x43,0x3a,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x41,0x38,0x35,0x94,0x33,0x37,0x3f,0x94,0x27,0x22,0x1f,0x94,0x22,0x27,0x2b,0x94,0x3f,0x33,0x8a,0x41,0x35,0x8a,0x43,0x37,0x27,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2b,0x8a,0x43,0x37,0x8a,0x25,0x19,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2b,0x8a,0x3f,0x33,0x8a,0x43,0x37,0x24,0x8a,0x33,0x3f,0x8a,0x41,0x35,0x2c,0x8a,0x43,0x37,0x8a,0x23,0x17,0x8a,0x3f,0x33,0x8a,0x41,0x35,0x2c,0x8a,0x3f,0x33,0x8a,0x43,0x3a,0x37,0x8a,0x3f,0x37,0x33,0x8a,0x41,0x38,0x35,0x8a,0x37,0x3a,0x43,0x8a,0x16,0x8a,0x3e,0x35,0x32,0x8a,0x41,0x38,0x35,0x94,0x33,0x37,0x3f,0x94,0x22,0x16,0x94,0x1b,0x0f,0x8a,0x37,0x2b,0x33,0x8a,0x38,0x2c,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x3a,0x2e,0x37,0x8a,0x16,0x8a,0x37,0x33,0x2b,0x8a,0x2c,0x38,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x2e,0x37,0x3a,0x8a,0x16,0x8a,0x37,0x8a,0x33,0x27,0x2b,0x8a,0x2e,0x8a,0x30,0x14,0x8a,0x32,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x37,0x20,0x8a,0x35,0x8a,0x33,0x2c,0x27,0x8a,0x35,0x8a,0x2e,0x1f,0x8a,0x37,0x8a,0x38,0x2b,0x27,0x8a,0x3a,0x8a,0x3c,0x16,0x8a,0x3a,0x8a,0x37,0x22,0x2b,0x8a,0x38,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x30,0x37,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x37,0x33,0x2b,0x8a,0x38,0x2c,0x35,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x3c,0x37,0x30,0x8a,0x2e,0x37,0x3a,0x8a,0x1f,0x8a,0x3a,0x8a,0x3c,0x1e,0x8a,0x3d,0x8a,0x3e,0x3a,0x35,0x8a,0x3e,0x35,0x3a,0x8a,0x22,0x29,0x26,0x8a,0x3e,0x33,0x39,0x8a,0x1d,0x8a,0x3c,0x8a,0x39,0x33,0x29,0x8a,0x35,0x8a,0x3a,0x32,0x29,0x94,0x20,0x14,0x94,0x1f,0x13,0x8a,0x37,0x2b,0x33,0x8a,0x38,0x35,0x2c,0x8a,0x39,0x36,0x2d,0x8a,0x2e,0x3a,0x37,0x94,0x3c,0x37,0x30,0x8a,0x3a,0x37,0x2e,0x8a,0x16,0x8a,0x33,0x2b,0x37,0x8a,0x38,0x35,0x2c,0x8a,0x39,0x36,0x2d,0x8a,0x3a,0x37,0x2e,0x94,0x30,0x37,0x3c,0x8a,0x3a,0x2e,0x37,0x8a,0x16,0x8a,0x37Line truncated
|
||||
};
|
||||
|
||||
void music_vint(void) {
|
||||
cv_set_colors(CV_COLOR_TRANSPARENT, CV_COLOR_BLUE);
|
||||
music_update();
|
||||
cv_set_colors(CV_COLOR_TRANSPARENT, CV_COLOR_TRANSPARENT);
|
||||
}
|
||||
|
||||
void setup_graphics() {
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
set_default_palette();
|
||||
}
|
||||
|
||||
void main(void) {
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
clrscr();
|
||||
putstringxy(1, 0, "Multivoice Music");
|
||||
cv_set_screen_active(true);
|
||||
cv_set_vint_handler(music_vint);
|
||||
while (1) {
|
||||
if (!music_ptr) music_start(music1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
Text-based version of a Blockade-style game.
|
||||
For more information, see "Making Arcade Games in C".
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
////////// GAME DATA
|
||||
|
||||
typedef struct {
|
||||
byte x;
|
||||
byte y;
|
||||
byte dir;
|
||||
word score;
|
||||
char head_attr;
|
||||
char tail_attr;
|
||||
char collided:1;
|
||||
char human:1;
|
||||
} Player;
|
||||
|
||||
Player players[2];
|
||||
|
||||
byte credits = 0;
|
||||
byte frames_per_move;
|
||||
|
||||
#define START_SPEED 12
|
||||
#define MAX_SPEED 5
|
||||
#define MAX_SCORE 7
|
||||
|
||||
///////////
|
||||
|
||||
const char BOX_CHARS[8] = {
|
||||
CHAR('+'), CHAR('+'), CHAR('+'), CHAR('+'),
|
||||
CHAR('-'), CHAR('-'), CHAR('!'), CHAR('!') };
|
||||
|
||||
void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) {
|
||||
byte x1 = x;
|
||||
putcharxy(x, y, chars[2]);
|
||||
putcharxy(x2, y, chars[3]);
|
||||
putcharxy(x, y2, chars[0]);
|
||||
putcharxy(x2, y2, chars[1]);
|
||||
while (++x < x2) {
|
||||
putcharxy(x, y, chars[5]);
|
||||
putcharxy(x, y2, chars[4]);
|
||||
}
|
||||
while (++y < y2) {
|
||||
putcharxy(x1, y, chars[6]);
|
||||
putcharxy(x2, y, chars[7]);
|
||||
}
|
||||
}
|
||||
|
||||
void draw_playfield() {
|
||||
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
|
||||
putstringxy(0,0,"Plyr1:");
|
||||
putstringxy(20,0,"Plyr2:");
|
||||
putcharxy(7,0,CHAR(players[0].score+'0'));
|
||||
putcharxy(27,0,CHAR(players[1].score+'0'));
|
||||
}
|
||||
|
||||
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
|
||||
const char DIR_X[4] = { 1, 0, -1, 0 };
|
||||
const char DIR_Y[4] = { 0, 1, 0, -1 };
|
||||
|
||||
void init_game() {
|
||||
memset(players, 0, sizeof(players));
|
||||
players[0].head_attr = CHAR('1');
|
||||
players[1].head_attr = CHAR('2');
|
||||
players[0].tail_attr = CHAR('@');
|
||||
players[1].tail_attr = CHAR('%');
|
||||
frames_per_move = START_SPEED;
|
||||
}
|
||||
|
||||
void reset_players() {
|
||||
players[0].x = players[0].y = 5;
|
||||
players[0].dir = D_RIGHT;
|
||||
players[1].x = 25;
|
||||
players[1].y = 19;
|
||||
players[1].dir = D_LEFT;
|
||||
players[0].collided = players[1].collided = 0;
|
||||
}
|
||||
|
||||
void draw_player(Player* p) {
|
||||
putcharxy(p->x, p->y, p->head_attr);
|
||||
}
|
||||
|
||||
void move_player(Player* p) {
|
||||
putcharxy(p->x, p->y, p->tail_attr);
|
||||
p->x += DIR_X[p->dir];
|
||||
p->y += DIR_Y[p->dir];
|
||||
if (getcharxy(p->x, p->y) != 0)
|
||||
p->collided = 1;
|
||||
draw_player(p);
|
||||
}
|
||||
|
||||
void human_control(Player* p) {
|
||||
byte dir = 0xff;
|
||||
struct cv_controller_state cs;
|
||||
cv_get_controller_state(&cs, 0); // Read the controller.
|
||||
if (!p->human) return;
|
||||
if (cs.joystick & CV_LEFT) dir = D_LEFT;
|
||||
if (cs.joystick & CV_RIGHT) dir = D_RIGHT;
|
||||
if (cs.joystick & CV_UP) dir = D_UP;
|
||||
if (cs.joystick & CV_DOWN) dir = D_DOWN;
|
||||
// don't let the player reverse
|
||||
if (dir < 0x80 && dir != (p->dir ^ 2)) {
|
||||
p->dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
byte ai_try_dir(Player* p, dir_t dir, byte shift) {
|
||||
byte x,y;
|
||||
dir &= 3;
|
||||
x = p->x + (DIR_X[dir] << shift);
|
||||
y = p->y + (DIR_Y[dir] << shift);
|
||||
if (x < 29 && y < 27 && getcharxy(x, y) == 0) {
|
||||
p->dir = dir;
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ai_control(Player* p) {
|
||||
dir_t dir;
|
||||
if (p->human) return;
|
||||
dir = p->dir;
|
||||
if (!ai_try_dir(p, dir, 0)) {
|
||||
ai_try_dir(p, dir+1, 0);
|
||||
ai_try_dir(p, dir-1, 0);
|
||||
} else {
|
||||
ai_try_dir(p, dir-1, 0) && ai_try_dir(p, dir-1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir+1, 0) && ai_try_dir(p, dir+1, 1+(rand() & 3));
|
||||
ai_try_dir(p, dir, rand() & 3);
|
||||
}
|
||||
}
|
||||
|
||||
byte gameover;
|
||||
|
||||
void flash_colliders() {
|
||||
byte i;
|
||||
// flash players that collided
|
||||
for (i=0; i<56; i++) {
|
||||
//cv_set_frequency(CV_SOUNDCHANNEL_0, 1000+i*8);
|
||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, i/2);
|
||||
if (players[0].collided) players[0].head_attr ^= 0x80;
|
||||
if (players[1].collided) players[1].head_attr ^= 0x80;
|
||||
delay(2);
|
||||
draw_player(&players[0]);
|
||||
draw_player(&players[1]);
|
||||
}
|
||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, 28);
|
||||
}
|
||||
|
||||
void make_move() {
|
||||
byte i;
|
||||
for (i=0; i<frames_per_move; i++) {
|
||||
human_control(&players[0]);
|
||||
delay(1);
|
||||
}
|
||||
ai_control(&players[0]);
|
||||
ai_control(&players[1]);
|
||||
// if players collide, 2nd player gets the point
|
||||
move_player(&players[1]);
|
||||
move_player(&players[0]);
|
||||
}
|
||||
|
||||
void play_game();
|
||||
|
||||
void declare_winner(byte winner) {
|
||||
byte i;
|
||||
clrscr();
|
||||
for (i=0; i<ROWS/2-3; i++) {
|
||||
draw_box(i,i,COLS-1-i,ROWS-1-i,BOX_CHARS);
|
||||
delay(1);
|
||||
}
|
||||
putstringxy(12,10,"WINNER:");
|
||||
putstringxy(12,13,"PLAYER ");
|
||||
putcharxy(12+7, 13, CHAR('1')+winner);
|
||||
delay(75);
|
||||
gameover = 1;
|
||||
}
|
||||
|
||||
void play_round() {
|
||||
reset_players();
|
||||
clrscr();
|
||||
draw_playfield();
|
||||
while (1) {
|
||||
make_move();
|
||||
if (players[0].collided || players[1].collided) break;
|
||||
}
|
||||
flash_colliders();
|
||||
// add scores to players that didn't collide
|
||||
if (players[0].collided) players[1].score++;
|
||||
if (players[1].collided) players[0].score++;
|
||||
// increase speed
|
||||
if (frames_per_move > MAX_SPEED) frames_per_move--;
|
||||
// game over?
|
||||
if (players[0].score != players[1].score) {
|
||||
if (players[0].score >= MAX_SCORE)
|
||||
declare_winner(0);
|
||||
else if (players[1].score >= MAX_SCORE)
|
||||
declare_winner(1);
|
||||
}
|
||||
}
|
||||
|
||||
void play_game() {
|
||||
gameover = 0;
|
||||
init_game();
|
||||
players[0].human = 1;
|
||||
while (!gameover) {
|
||||
play_round();
|
||||
}
|
||||
}
|
||||
|
||||
void setup_graphics() {
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
set_default_palette();
|
||||
cv_set_colors(CV_COLOR_TRANSPARENT, CV_COLOR_BLUE);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
cv_set_screen_active(true);
|
||||
cv_set_vint_handler(&vint_handler);
|
||||
draw_playfield();
|
||||
play_game();
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
|
||||
/*
|
||||
This demonstrates the cvu_play_music() function.
|
||||
Command-line tools generate the music file from ABC source files.
|
||||
|
||||
For more information, see:
|
||||
http://www.colecovision.eu/ColecoVision/development/tutorial2.shtml
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
#include "common.h"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
const uint16_t notes[] = { 12846, 12334, 11086, 10062, 10062, 9806, 10062, 10574, 11086, 10062, 11086, 12430, 11042, 12334, 12878, 14158, 14158, 12878, 13390, 13646, 10574, 9806, 10574, 12430, 12846, 12334, 11086, 10062, 10062, 9806, 10062, 10574, 11086, 10062, 11086, 12430, 11054, 12334, 12878, 14158, 14158, 12878, 13390, 13646, 10574, 10062, 10062, 10126, 11054, 12334, 12878, 14158, 13902, 14158, 14670, 14158, 13646, 12878, 13390, 13646, 3918, 12878, 14158, 13902, 12878, 12366, 12878, 12366, 12878, 11086, 10062, 9870, 12334, 11054, 11086, 10062, 10062, 9806, 10062, 10574, 11086, 10062, 11086, 12430, 11054, 12334, 12878, 14158, 14158, 12878, 13390, 13646, 10574, 10062, 10062, 10126, 0xffff };
|
||||
|
||||
#include <cv.h>
|
||||
struct cvu_music music;
|
||||
|
||||
void setup_graphics() {
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
set_default_palette();
|
||||
}
|
||||
|
||||
// change screen colors to show how long the music
|
||||
// routine takes to run after screen interrupt
|
||||
void play(void)
|
||||
{
|
||||
cv_set_colors(CV_COLOR_TRANSPARENT, CV_COLOR_BLUE);
|
||||
cvu_play_music(&music);
|
||||
cv_set_colors(CV_COLOR_TRANSPARENT, CV_COLOR_TRANSPARENT);
|
||||
}
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
clrscr();
|
||||
putstringxy(1, 0, "Simple Music");
|
||||
cv_set_screen_active(true);
|
||||
cvu_init_music(&music);
|
||||
music.notes = notes;
|
||||
cv_set_vint_handler(&play);
|
||||
for(;;);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
This is a demo of an animated starfield, ported to
|
||||
the Sega VDP's mode 4.
|
||||
|
||||
Mode 4 has no hardware scrolling registers, so
|
||||
scrolling requires rewriting the name/pattern tables.
|
||||
|
||||
There is actually only one star in the pattern table,
|
||||
just a single pixel. We move it vertically between 16
|
||||
different character tiles (8 * 16 = 128 pixels high).
|
||||
We then draw vertical stripes of 8 repeating consecutive
|
||||
characters into the image table.
|
||||
|
||||
By randomly offsetting where we begin each stripe, we
|
||||
create what appears to be a random starfield.
|
||||
|
||||
This demo uses an interrupt handler to increment a
|
||||
counter 60 times per second. We use this counter to
|
||||
determine the new position of the star pixel when we animate.
|
||||
*/
|
||||
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
#include "common.h"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
// the starting character index in the pattern table
|
||||
#define STAR_BASE_CHAR 0xf0
|
||||
// 16 tiles * 8 rows = 128 star positions
|
||||
#define STAR_COUNT (16*8)
|
||||
|
||||
// a random offset for every vertical column
|
||||
const char star_yoffsets[32] = {
|
||||
31, 11, 25, 10, 21, 1, 9, 6,
|
||||
22, 3, 7, 14, 15, 18, 0, 29,
|
||||
30, 5, 16, 28, 20, 12, 24, 17,
|
||||
13, 8, 26, 19, 23, 27, 2, 4
|
||||
};
|
||||
|
||||
// returns the tile index for every (x,y) position
|
||||
byte starfield_get_tile_xy(byte x, byte y) {
|
||||
return ((star_yoffsets[x] + y) & 15) + STAR_BASE_CHAR;
|
||||
}
|
||||
|
||||
// each mode-4 tile is 32 bytes: 8 rows of 4 plane bytes.
|
||||
// the star pixel lives in plane 0 of a given row.
|
||||
word starfield_addr(byte index) {
|
||||
return PATTERN + STAR_BASE_CHAR*32 + index*4;
|
||||
}
|
||||
|
||||
// set up starfield image and pattern table
|
||||
void starfield_setup() {
|
||||
byte x, y;
|
||||
// clear star patterns
|
||||
cvu_vmemset(PATTERN + STAR_BASE_CHAR*32, 0, 16*32);
|
||||
// write starfield image table
|
||||
for (x=0; x<32; x++) {
|
||||
for (y=0; y<ROWS; y++) {
|
||||
putcharxy(x, y, starfield_get_tile_xy(x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// call each frame to animate starfield
|
||||
void starfield_update() {
|
||||
static byte oldcounter;
|
||||
byte counter = vint_counter;
|
||||
byte mask = STAR_COUNT-1; // 128 star positions
|
||||
// erase old star, create new star in pattern table
|
||||
cvu_voutb(0, starfield_addr(oldcounter & mask));
|
||||
cvu_voutb(8, starfield_addr(counter & mask));
|
||||
// remember counter value in case we skip a frame
|
||||
oldcounter = counter;
|
||||
}
|
||||
|
||||
void setup_graphics() {
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
set_default_palette();
|
||||
cv_set_colors(CV_COLOR_BLACK, CV_COLOR_BLACK);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
// set up default interrupt handler
|
||||
cv_set_vint_handler(&vint_handler);
|
||||
starfield_setup();
|
||||
cv_set_screen_active(true);
|
||||
while(1) {
|
||||
wait_vsync();
|
||||
starfield_update();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
This is a demonstration of the Sega VDP's mode 4
|
||||
(tile-based) text mode. The name table stores two
|
||||
bytes per cell: a tile number and an attribute byte
|
||||
(palette, flip, priority).
|
||||
*/
|
||||
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
void setup_graphics() {
|
||||
// copy the font/tileset into the character pattern table
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
// load the default mode-4 palette
|
||||
set_default_palette();
|
||||
// black backdrop
|
||||
cv_set_colors(CV_COLOR_BLACK, CV_COLOR_BLACK);
|
||||
}
|
||||
|
||||
void show_text() {
|
||||
// clear the name table (tile + attribute bytes)
|
||||
clrscr();
|
||||
// draw message at row 0, column 1
|
||||
putstringxy(1, 0, "Greetings Professor Falken");
|
||||
// turn on display
|
||||
cv_set_screen_active(true);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
show_text();
|
||||
while (1); // infinite loop
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
Demonstration of mode 4 text with per-character colors.
|
||||
|
||||
In mode 4 the name table stores a tile number and an
|
||||
attribute byte for every cell. The low bit of the
|
||||
attribute selects one of the two 16-color palettes.
|
||||
*/
|
||||
|
||||
#include <cv.h>
|
||||
#include <cvu.h>
|
||||
|
||||
#include "common.h"
|
||||
//#link "common.c"
|
||||
//#link "chr_generic.c"
|
||||
|
||||
extern const unsigned char CHR_GENERIC[8192];
|
||||
|
||||
void setup_graphics() {
|
||||
// copy the font/tileset into the character pattern table
|
||||
cvu_memtovmemcpy(PATTERN, CHR_GENERIC, sizeof(CHR_GENERIC));
|
||||
// load the default mode-4 palette
|
||||
set_default_palette();
|
||||
cv_set_colors(CV_COLOR_BLACK, CV_COLOR_BLACK);
|
||||
}
|
||||
|
||||
void show_text() {
|
||||
byte x, y;
|
||||
// fill the name table with characters
|
||||
for (y=0; y<ROWS; y++) {
|
||||
// set a different text attribute per line
|
||||
text_attr = y+5;
|
||||
for (x=0; x<COLS; x++) {
|
||||
putcharxy(x, y, 'L');
|
||||
}
|
||||
}
|
||||
// draw the message at row 0, column 1
|
||||
putstringxy(1, 0, "Greetings Professor Falken");
|
||||
// turn on display
|
||||
cv_set_screen_active(true);
|
||||
}
|
||||
|
||||
void main() {
|
||||
vdp_setup();
|
||||
setup_graphics();
|
||||
show_text();
|
||||
while (1);
|
||||
}
|
||||
+10
-2
@@ -22,8 +22,16 @@ export var SG1000_PRESETS = [
|
||||
];
|
||||
|
||||
export var SMS_PRESETS = [
|
||||
{id:'mode4test.c', name:'Mode 4 Test'},
|
||||
{id:'climber.c', name:'Climber Game'},
|
||||
{ id: 'mode4test.c', name: 'Mode 4 Test' },
|
||||
{ id: 'text.c', name: 'Text Mode' },
|
||||
{ id: 'hello.c', name: 'Scrolling Text' },
|
||||
{ id: 'text32.c', name: '32-Column Color Text' },
|
||||
{ id: 'stars.c', name: 'Scrolling Starfield' },
|
||||
{ id: 'cursorsmooth.c', name: 'Moving Cursor' },
|
||||
{ id: 'simplemusic.c', name: 'Simple Music' },
|
||||
{ id: 'musicplayer.c', name: 'Multivoice Music' },
|
||||
{ id: 'siegegame.c', name: 'Siege Game' },
|
||||
{ id: 'climber.c', name: 'Climber Game' },
|
||||
];
|
||||
|
||||
///
|
||||
|
||||
Reference in new issue
Block a user