ported some SMS and GG presets from coleco

This commit is contained in:
Steven Hugg committed 2026-09-12 21:59:24 +02:00
1 parent 801dc79c3a
commit ced4721c13
13 files changed
+1224 -29

No files matched your search

+44 -17
View File
@@ -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);
}
+4 -8
View File
@@ -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
View File
@@ -1 +0,0 @@
../coleco/common.c
+202
View File
@@ -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
View File
@@ -1 +0,0 @@
../coleco/common.h
+115
View File
@@ -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
+171
View File
@@ -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);
}
}
+93
View File
@@ -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++);
}
}
+114
View File
@@ -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
+237
View File
@@ -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();
}
+50
View File
@@ -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(;;);
}
+97
View File
@@ -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();
}
}
+40
View File
@@ -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
}
+47
View File
@@ -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
View File
@@ -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' },
];
///