mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2026-10-25 00:02:16 +00:00
atari8: updated presets, added 5th player
This commit is contained in:
1 parent
e89e339dcd
commit
087759549d
6 files changed
+358
-16
No files matched your search
@@ -378,6 +378,60 @@ void a8_pmg_clear_collisions(void) {
|
||||
GTIA_WRITE.hitclr = 0;
|
||||
}
|
||||
|
||||
static byte pmg_sizem;
|
||||
|
||||
void a8_pmg_5th_enable(byte on) {
|
||||
if (on) {
|
||||
GTIA_WRITE.prior |= PRIOR_5TH_PLAYER;
|
||||
GTIA_WRITE.gractl |= GRACTL_MISSLES;
|
||||
GTIA_WRITE.sizem = 0; /* every missile 2 px wide, so they tile */
|
||||
} else {
|
||||
GTIA_WRITE.prior &= (byte)~PRIOR_5TH_PLAYER;
|
||||
}
|
||||
pmg_sizem = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
0: 8 color clocks (1 per pixel)
|
||||
1: 16 color clocks (2 per pixel)
|
||||
3: 32 color clocks (4 per pixel)
|
||||
*/
|
||||
void a8_pmg_5th_size(byte size) {
|
||||
size &= 3;
|
||||
pmg_sizem = size;
|
||||
size |= size << 2;
|
||||
size |= size << 4;
|
||||
GTIA_WRITE.sizem = size;
|
||||
}
|
||||
|
||||
static const byte pmg_size_tab[4] = { 2, 4, 2, 8 };
|
||||
|
||||
void a8_pmg_5th_x(byte x) {
|
||||
byte* m = (byte*)>IA_WRITE.hposm0;
|
||||
byte inc = pmg_size_tab[pmg_sizem];
|
||||
m[0] = x;
|
||||
x += inc;
|
||||
m[1] = x;
|
||||
x += inc;
|
||||
m[2] = x;
|
||||
x += inc;
|
||||
m[3] = x;
|
||||
}
|
||||
|
||||
void a8_pmg_5th_shape(const byte* shape, byte len, byte y) {
|
||||
byte* p = a8_pmg_missile(0) + y;
|
||||
while (len--) {
|
||||
/* GRAFM packs two bits per missile, M0 in bits 1:0, and each missile
|
||||
shifts its pair out MSB first, so the leftmost pixel is bit 1. Swap
|
||||
the bit pairs to accept the usual player order (bit 7 = leftmost). */
|
||||
byte s = *shape++;
|
||||
*p++ = (byte)(((s >> 6) & 0x03)
|
||||
| ((s >> 2) & 0x0c)
|
||||
| ((s << 2) & 0x30)
|
||||
| ((s << 6) & 0xc0));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*==========================================================================*/
|
||||
/* POKEY */
|
||||
@@ -466,16 +520,16 @@ void a8_set_colpm(byte i, byte c) {
|
||||
/* Input and utility */
|
||||
/*==========================================================================*/
|
||||
|
||||
byte a8_console(void) {
|
||||
byte a8_get_console(void) {
|
||||
return GTIA_READ.consol;
|
||||
}
|
||||
|
||||
byte a8_trigger(byte n) {
|
||||
byte a8_get_trigger(byte n) {
|
||||
return (byte)(((byte*)>IA_READ.trig0)[n] & 1 ? 0 : 1);
|
||||
}
|
||||
|
||||
#if !defined(__ATARI5200__)
|
||||
byte a8_stick(byte n) {
|
||||
byte a8_get_stick(byte n) {
|
||||
byte v = n ? PIA.portb : PIA.porta;
|
||||
return (byte)((~v) & 0x1f);
|
||||
}
|
||||
|
||||
@@ -232,6 +232,23 @@ byte a8_pmg_hit_pf(byte i); /* player i hit playfield? */
|
||||
byte a8_pmg_hit_pl(void); /* any player-player hit mask */
|
||||
void a8_pmg_clear_collisions(void);
|
||||
|
||||
/* The four missiles can be combined into one extra, 8-pixel-wide "5th
|
||||
player", colored with COLPF3 (PRIOR bit 4). It shares the missile
|
||||
hardware, so the per-missile helpers above don't work while it is on.
|
||||
The four missiles sit two pixels apart, M0 leftmost. Like players,
|
||||
the shape lives in the P/M area (ANTIC reloads GRAFM from memory every
|
||||
scanline), so write it with a8_pmg_5th_shape() rather than GRAFM. */
|
||||
#ifndef PRIOR_5TH_PLAYER
|
||||
#define PRIOR_5TH_PLAYER 0x10
|
||||
#endif
|
||||
void a8_pmg_5th_enable(byte on);
|
||||
/* x is the left edge of the 8-pixel player. */
|
||||
void a8_pmg_5th_x(byte x);
|
||||
/* Copy a shape into the missile area at vertical byte offset y. len and
|
||||
orientation are just like a8_pmg_set_shape(): bit 7 is the left pixel. */
|
||||
void a8_pmg_5th_shape(const byte* shape, byte len, byte y);
|
||||
void a8_pmg_5th_size(byte size);
|
||||
|
||||
|
||||
/*==========================================================================*/
|
||||
/* POKEY sound */
|
||||
@@ -272,13 +289,13 @@ void a8_set_colpm(byte i, byte c);
|
||||
/*==========================================================================*/
|
||||
|
||||
/* Console keys: bit0 start, bit1 select, bit2 option (0 = pressed). */
|
||||
byte a8_console(void);
|
||||
byte a8_get_console(void);
|
||||
/* Trigger n (0..3): nonzero when pressed. */
|
||||
byte a8_trigger(byte n);
|
||||
byte a8_get_trigger(byte n);
|
||||
|
||||
#if !defined(__ATARI5200__)
|
||||
/* Joystick 0/1 direction+fire bits (JOY_xxx_MASK order). 0 if none. */
|
||||
byte a8_stick(byte n);
|
||||
byte a8_get_stick(byte n);
|
||||
#endif
|
||||
|
||||
/* Wait for the start of the next frame. (cc65 provides waitvsync(),
|
||||
|
||||
@@ -58,6 +58,7 @@ static void build_display(void) {
|
||||
void main(void) {
|
||||
byte x = 128;
|
||||
byte dx = 2;
|
||||
byte i;
|
||||
|
||||
fill_screen();
|
||||
build_display();
|
||||
@@ -73,10 +74,18 @@ void main(void) {
|
||||
a8_dli_install();
|
||||
|
||||
a8_pmg_init(A8_PMG_DOUBLE);
|
||||
a8_pmg_set_x(0, x);
|
||||
a8_pmg_set_color(0, A8_COLOR(HUE_GREY, 0x0f));
|
||||
a8_pmg_set_size(0, A8_PMG_NORMAL);
|
||||
a8_pmg_set_shape(0, ball, sizeof(ball), 0x38);
|
||||
// set up all 4 sprites
|
||||
for (i=0; i<4; i++) {
|
||||
a8_pmg_set_x(i, x);
|
||||
a8_pmg_set_color(i, A8_COLOR(HUE_GREY, 0x0f-i));
|
||||
a8_pmg_set_size(i, A8_PMG_NORMAL);
|
||||
a8_pmg_set_shape(i, ball, sizeof(ball), i*16 + 8);
|
||||
}
|
||||
// combine missiles into 5th sprite
|
||||
// colors are taken from the 4 sprites
|
||||
a8_pmg_5th_enable(1);
|
||||
a8_pmg_5th_x(100);
|
||||
a8_pmg_5th_shape(ball, sizeof(ball), 0x48);
|
||||
|
||||
// set interrupt and start music
|
||||
a8_pokey_init();
|
||||
@@ -89,12 +98,25 @@ void main(void) {
|
||||
x += dx;
|
||||
if (x < 48) { x = 48; dx = 2; }
|
||||
if (x > 208) { x = 208; dx = (byte)-2; }
|
||||
a8_pmg_set_x(0, x);
|
||||
|
||||
if (a8_trigger(0)) {
|
||||
a8_pmg_set_size(0, A8_PMG_QUADW);
|
||||
// set sprite sizes if joystick moved or trigger pushed
|
||||
if (a8_get_trigger(0)) {
|
||||
a8_pmg_5th_size(A8_PMG_QUADW);
|
||||
} else {
|
||||
a8_pmg_5th_size(A8_PMG_NORMAL);
|
||||
}
|
||||
if (a8_get_stick(0)) {
|
||||
a8_pmg_set_size(a8_get_stick(0) & 3, A8_PMG_QUADW);
|
||||
} else {
|
||||
a8_pmg_set_size(0, A8_PMG_NORMAL);
|
||||
a8_pmg_set_size(1, A8_PMG_NORMAL);
|
||||
a8_pmg_set_size(2, A8_PMG_NORMAL);
|
||||
a8_pmg_set_size(3, A8_PMG_NORMAL);
|
||||
}
|
||||
// set X positions
|
||||
a8_pmg_set_x(0, x);
|
||||
a8_pmg_set_x(1, x);
|
||||
a8_pmg_set_x(2, x);
|
||||
a8_pmg_set_x(3, x);
|
||||
a8_pmg_5th_x(255-x);
|
||||
}
|
||||
}
|
||||
@@ -18,8 +18,8 @@ typedef signed char sbyte;
|
||||
typedef unsigned short word;
|
||||
|
||||
// pointer to screen memory
|
||||
// TODO: use OS.savmsc
|
||||
static byte** SAVMSC = (byte**) 0x58;
|
||||
// pointer to screen memory
|
||||
static byte** SAVMSC = &OS.savmsc;
|
||||
|
||||
byte getchar(byte x, byte y) {
|
||||
return (*SAVMSC)[x+y*COLS]; // lookup value @ cursor address
|
||||
|
||||
@@ -0,0 +1,248 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <cc65.h>
|
||||
#include <conio.h>
|
||||
#include <ctype.h>
|
||||
#include <modload.h>
|
||||
#include <tgi.h>
|
||||
#include <atari.h>
|
||||
|
||||
//#tooldef ld cfgfile=atari.cfg
|
||||
//#symbol ld __RESERVED_MEMORY__=8192
|
||||
|
||||
/* Color values passed to TGI functions are indices into the default palette. */
|
||||
#define COLOR_BACK 0
|
||||
#define COLOR_FORE 1
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Data */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
/* Driver stuff */
|
||||
static unsigned MaxX;
|
||||
static unsigned MaxY;
|
||||
static unsigned AspectRatio;
|
||||
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Code */
|
||||
/*****************************************************************************/
|
||||
|
||||
|
||||
|
||||
static void CheckError (const char* S)
|
||||
{
|
||||
unsigned char Error = tgi_geterror ();
|
||||
|
||||
if (Error != TGI_ERR_OK) {
|
||||
cputs("Error ");
|
||||
cputs(S);
|
||||
if (doesclrscrafterexit ()) {
|
||||
cgetc ();
|
||||
}
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Note that everywhere else in the TGI API, colors are referred to via an index
|
||||
* to the current palette.
|
||||
*
|
||||
* TGI_COLOR_ values can be used (ONLY!) for setting the palette, using them
|
||||
* with other TGI functions only works by chance, on some targets.
|
||||
*/
|
||||
static void DoPalette (int n)
|
||||
{
|
||||
static const unsigned char Palette[4][2] = {
|
||||
{ TGI_COLOR_BLACK, TGI_COLOR_BLUE },
|
||||
{ TGI_COLOR_WHITE, TGI_COLOR_BLACK },
|
||||
{ TGI_COLOR_RED, TGI_COLOR_BLACK },
|
||||
};
|
||||
tgi_setpalette (Palette[n]);
|
||||
}
|
||||
|
||||
|
||||
static void DoCircles (void)
|
||||
{
|
||||
unsigned char I;
|
||||
unsigned char Color = COLOR_BACK;
|
||||
const unsigned X = MaxX / 2;
|
||||
const unsigned Y = MaxY / 2;
|
||||
const unsigned Limit = (X < Y) ? Y : X;
|
||||
|
||||
tgi_setcolor (COLOR_FORE);
|
||||
tgi_clear ();
|
||||
tgi_line (0, 0, MaxX, MaxY);
|
||||
tgi_line (0, MaxY, MaxX, 0);
|
||||
while (!kbhit ()) {
|
||||
Color = (Color == COLOR_FORE) ? COLOR_BACK : COLOR_FORE;
|
||||
tgi_setcolor (Color);
|
||||
for (I = 10; I <= Limit; I += 10) {
|
||||
tgi_ellipse (X, Y, I, tgi_imulround (I, AspectRatio));
|
||||
}
|
||||
}
|
||||
while (kbhit ()) {
|
||||
cgetc ();
|
||||
}
|
||||
cgetc ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoCheckerboard (void)
|
||||
{
|
||||
unsigned X, Y;
|
||||
unsigned char Color = COLOR_BACK;
|
||||
|
||||
tgi_clear ();
|
||||
|
||||
while (1) {
|
||||
for (Y = 0; Y <= MaxY; Y += 10) {
|
||||
for (X = 0; X <= MaxX; X += 10) {
|
||||
Color = (Color == COLOR_FORE) ? COLOR_BACK : COLOR_FORE;
|
||||
tgi_setcolor (Color);
|
||||
tgi_bar (X, Y, X+9, Y+9);
|
||||
if (kbhit ()) {
|
||||
cgetc ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
|
||||
}
|
||||
Color = Color == COLOR_FORE ? COLOR_BACK : COLOR_FORE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoDiagram (void)
|
||||
{
|
||||
int XOrigin, YOrigin;
|
||||
int Amp;
|
||||
int X, Y;
|
||||
unsigned I;
|
||||
|
||||
tgi_setcolor (COLOR_FORE);
|
||||
tgi_clear ();
|
||||
|
||||
/* Determine zero and amplitude */
|
||||
YOrigin = MaxY / 2;
|
||||
XOrigin = 10;
|
||||
Amp = (MaxY - 19) / 2;
|
||||
|
||||
/* Y axis */
|
||||
tgi_line (XOrigin, 10, XOrigin, MaxY-10);
|
||||
tgi_line (XOrigin-2, 12, XOrigin, 10);
|
||||
tgi_lineto (XOrigin+2, 12);
|
||||
|
||||
/* X axis */
|
||||
tgi_line (XOrigin, YOrigin, MaxX-10, YOrigin);
|
||||
tgi_line (MaxX-12, YOrigin-2, MaxX-10, YOrigin);
|
||||
tgi_lineto (MaxX-12, YOrigin+2);
|
||||
|
||||
/* Sine */
|
||||
tgi_gotoxy (XOrigin, YOrigin);
|
||||
for (I = 0; I <= 360; I += 5) {
|
||||
|
||||
/* Calculate the next points */
|
||||
X = (int) (((long) (MaxX - 19) * I) / 360);
|
||||
Y = (int) (((long) Amp * -_sin (I)) / 256);
|
||||
|
||||
/* Draw the line */
|
||||
tgi_lineto (XOrigin + X, YOrigin + Y);
|
||||
}
|
||||
|
||||
while (kbhit ()) {
|
||||
cgetc ();
|
||||
}
|
||||
cgetc ();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void DoLines (void)
|
||||
{
|
||||
unsigned X;
|
||||
const unsigned Min = (MaxX < MaxY) ? MaxX : MaxY;
|
||||
|
||||
tgi_setcolor (COLOR_FORE);
|
||||
tgi_clear ();
|
||||
|
||||
for (X = 0; X <= Min; X += 10) {
|
||||
tgi_line (0, 0, Min, X);
|
||||
tgi_line (0, 0, X, Min);
|
||||
tgi_line (Min, Min, 0, Min-X);
|
||||
tgi_line (Min, Min, Min-X, 0);
|
||||
}
|
||||
|
||||
while (kbhit ()) {
|
||||
cgetc ();
|
||||
}
|
||||
cgetc ();
|
||||
}
|
||||
|
||||
#define DRIVER_COUNT 11
|
||||
|
||||
const void* drivers[DRIVER_COUNT] = {
|
||||
atr3_tgi,
|
||||
atr4_tgi,
|
||||
atr5_tgi,
|
||||
atr6_tgi,
|
||||
atr7_tgi,
|
||||
atr8_tgi,
|
||||
atr9_tgi,
|
||||
atr10_tgi,
|
||||
atr11_tgi,
|
||||
atr14_tgi,
|
||||
atr15_tgi,
|
||||
};
|
||||
|
||||
int main (void)
|
||||
{
|
||||
unsigned char Border;
|
||||
unsigned int driverIndex;
|
||||
|
||||
/* Set the palette, set the border color */
|
||||
Border = bordercolor (COLOR_BLACK);
|
||||
|
||||
for (driverIndex = 0; driverIndex < DRIVER_COUNT; driverIndex++) {
|
||||
/* Install the driver */
|
||||
tgi_install (drivers[driverIndex]);
|
||||
CheckError ("tgi_install");
|
||||
|
||||
// __RESERVED_MEMORY__ can't override on atari-cart.cfg
|
||||
//OS.appmhi = (unsigned char*)0x2000;
|
||||
tgi_init ();
|
||||
CheckError ("tgi_init");
|
||||
|
||||
/* Get stuff from the driver */
|
||||
MaxX = tgi_getmaxx ();
|
||||
MaxY = tgi_getmaxy ();
|
||||
AspectRatio = tgi_getaspectratio ();
|
||||
|
||||
/* Do graphics stuff */
|
||||
|
||||
/* use default palette */
|
||||
DoCircles ();
|
||||
DoPalette (0);
|
||||
DoCheckerboard ();
|
||||
DoPalette (1);
|
||||
DoDiagram ();
|
||||
DoPalette (2);
|
||||
DoLines ();
|
||||
|
||||
/* Uninstall the driver */
|
||||
tgi_uninstall ();
|
||||
}
|
||||
|
||||
/* Reset the border */
|
||||
(void) bordercolor (Border);
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
@@ -9,6 +9,7 @@ var Atari8_PRESETS : Preset[] = [
|
||||
{id:'hellopm.dasm', name:'Hello Sprites'},
|
||||
{id:'helloconio.c', name:'Text Mode', category:'C'},
|
||||
{id:'siegegame.c', name:'Siege Game'},
|
||||
{id:'tgidemo.c', name:'TGI Demo'},
|
||||
{id:'hellodlist.c', name:'Display List'},
|
||||
{id:'libdemo.c', name:'Library Demo'},
|
||||
];
|
||||
|
||||
Reference in new issue
Block a user