8bitworkshop/presets/vcs/vcslib/vcslib.h

266 lines
7.5 KiB
C

#ifndef _VCSLIB_H
#define _VCSLIB_H
#include <atari2600.h>
#include <stdint.h>
// Define data types for different data sizes and signedness
typedef unsigned char byte; // 8-bit unsigned data type
typedef signed char sbyte; // 8-bit signed data type
typedef unsigned short word; // 16-bit unsigned data type
typedef signed short sword; // 16-bit signed data type
// Bank switching functions that will be called directly when needed
// These are for changing which section of ROM or RAM the Atari 2600 accesses
// Select a ROM bank by index
extern void fastcall bankselect(byte bankindex);
// Select a RAM bank by index
extern void fastcall ramselect(byte ramindex);
// Set address in extended RAM
extern void fastcall xramset(void* address);
// Write a byte to extended RAM at set address
extern void fastcall xramwrite(byte value);
// Read a byte from extended RAM at set address
extern byte fastcall xramread(void);
// Copies initialized data from ROM to RAM at startup, if used
extern void copyxdata(void);
// Atari 2600 kernel helpers, called in a sequence every frame
extern void kernel_1(void); // before preframe
extern void kernel_2(void); // before kernel
extern void kernel_3(void); // after kernel
extern void kernel_4(void); // after postframe
// Function to set horizontal position of a game object.
// The position and object index are packed into a single int.
// Hi byte = object index
// Lo byte = X coordinate
extern void fastcall set_horiz_pos(int hi_obj__lo_xpos);
// Waits for next scanline start
#define do_wsync() asm("sta $42 ; WSYNC");
// Applies horizontal motion to sprite(s) after set_horiz_pos()
#define apply_hmove() \
asm("sta $42 ; WSYNC"); \
asm("sta $6a ; HMOVE");
/**** SCOREBOARD ROUTINES ****/
// Add 4-digit BCD to 6-digit BCD score
extern void fastcall score6_add(int delta_bcd);
#pragma wrapped-call (push, bankselect, bank)
// Setup TIA for Playfield score display
extern void scorepf_build(void);
// Kernel for Playfield score display
extern void scorepf_kernel(void);
#pragma wrapped-call (pop)
/**** SOUND AND MUSIC ROUTINES ****/
#pragma wrapped-call (push, bankselect, bank)
// Update sound playback (once per frame)
extern void sound_update();
// Play a specific sound
extern void sound_play(byte sndindex);
// Update music playback
extern void music_update();
#pragma wrapped-call (pop)
extern const byte* music_ptr; // Pointer to current music data
#pragma zpsym("music_ptr");
// Macro to set music data pointer and begin playback
#define music_play(ptr) music_ptr = (ptr);
extern byte sndchan_timer[2]; // sound channel timers, 0 = free channel
#pragma zpsym("sndchan_timer");
extern byte sndchan_sfx[2]; // sound channel sound index
#pragma zpsym("sndchan_sfx");
/**** 48-PIXEL BITMAP ROUTINES ****/
// Setup TIA for 48-pixel wide bitmap mode
extern void fastcall bitmap48_setup();
#pragma wrapped-call (push, ramselect, 0)
// Draws a 48-pixel wide bitmap
extern void fastcall bitmap48_kernel(unsigned char nlines);
// Sets height for bitmap48_setaddress() function
extern void fastcall bitmap48_setheight(byte height);
// Sets address of 48-pixel bitmap data
// Bitmap should be 6 bytes wide
extern void fastcall bitmap48_setaddress(byte* bitmap);
// Builds a 6-digit score display in XRAM
extern void fastcall score6_build();
#pragma wrapped-call (pop)
#pragma wrapped-call (push, bankselect, bank)
// Create 48-pixel font from string (requires tinyfont48.c)
extern void tinyfont48_build(byte* dest, const char str[12]);
#pragma wrapped-call (pop)
/////
#define P0 0
#define P1 1
#define M0 2
#define M1 3
#define BALL 4
#define OBJ_PLAYER_0 0x000
#define OBJ_PLAYER_1 0x100
#define OBJ_MISSILE_0 0x200
#define OBJ_MISSILE_1 0x300
#define OBJ_BALL 0x400
#define SW_RESET() ((RIOT.swchb & RESET_MASK) == 0)
#define SW_SELECT() ((RIOT.swchb & SELECT_MASK) == 0)
#define SW_COLOR() ((RIOT.swchb & BW_MASK) != 0)
#define SW_P0_PRO() ((RIOT.swchb & P0_DIFF_MASK) != 0)
#define SW_P1_PRO() ((RIOT.swchb & P1_DIFF_MASK) != 0)
#define COLOR_CONV(color) (SW_COLOR() ? color : color & 0x0f)
#define _CYCLES(lines) (((lines) * 76) - 13)
#define _TIM64(cycles) (((cycles) >> 6) - (((cycles) & 63) < 12))
#define _T1024(cycles) ((cycles) >> 10)
#ifdef PAL
#define VBLANK_TIM64 _TIM64(_CYCLES(45))
#define KERNAL_T1024 _T1024(_CYCLES(250))
#define OVERSCAN_TIM64 _TIM64(_CYCLES(36))
#else
#define VBLANK_TIM64 _TIM64(_CYCLES(37))
#define KERNAL_TIM64 _TIM64(_CYCLES(198))
#define OVERSCAN_TIM64 _TIM64(_CYCLES(28))
#endif
#define JOY_UP(plyr) (!(RIOT.swcha & ((plyr) ? 0x1 : ~MOVE_UP)))
#define JOY_DOWN(plyr) (!(RIOT.swcha & ((plyr) ? 0x2 : ~MOVE_DOWN)))
#define JOY_LEFT(plyr) (!(RIOT.swcha & ((plyr) ? 0x4 : ~MOVE_LEFT)))
#define JOY_RIGHT(plyr) (!(RIOT.swcha & ((plyr) ? 0x8 : ~MOVE_RIGHT)))
#define JOY_FIRE(plyr) !(((plyr) ? TIA.inpt5 : TIA.inpt4) & 0x80)
// TIA - CONSTANTS
#define HMOVE_L7 (0x70)
#define HMOVE_L6 (0x60)
#define HMOVE_L5 (0x50)
#define HMOVE_L4 (0x40)
#define HMOVE_L3 (0x30)
#define HMOVE_L2 (0x20)
#define HMOVE_L1 (0x10)
#define HMOVE_0 (0x00)
#define HMOVE_R1 (0xF0)
#define HMOVE_R2 (0xE0)
#define HMOVE_R3 (0xD0)
#define HMOVE_R4 (0xC0)
#define HMOVE_R5 (0xB0)
#define HMOVE_R6 (0xA0)
#define HMOVE_R7 (0x90)
#define HMOVE_R8 (0x80)
// Values for ENAMx and ENABL
#define DISABLE_BM (0b00)
#define ENABLE_BM (0b10)
// Values for RESMPx
#define LOCK_MISSILE (0b10)
#define UNLOCK_MISSILE (0b00)
// Values for REFPx
#define NO_REFLECT (0b0000)
#define REFLECT (0b1000)
// Values for NUSIZx
#define ONE_COPY (0b000)
#define TWO_COPIES (0b001)
#define TWO_MED_COPIES (0b010)
#define THREE_COPIES (0b011)
#define TWO_WIDE_COPIES (0b100)
#define DOUBLE_SIZE (0b101)
#define THREE_MED_COPIES (0b110)
#define QUAD_SIZE (0b111)
#define MSBL_SIZE1 (0b000000)
#define MSBL_SIZE2 (0b010000)
#define MSBL_SIZE4 (0b100000)
#define MSBL_SIZE8 (0b110000)
// Values for CTRLPF
#define PF_PRIORITY (0b100)
#define PF_SCORE (0b10)
#define PF_REFLECT (0b01)
#define PF_NO_REFLECT (0b00)
// Values for SWCHB
#define P1_DIFF_MASK (0b10000000)
#define P0_DIFF_MASK (0b01000000)
#define BW_MASK (0b00001000)
#define SELECT_MASK (0b00000010)
#define RESET_MASK (0b00000001)
#define VERTICAL_DELAY (1)
// SWCHA joystick bits
#define MOVE_RIGHT (0b01111111)
#define MOVE_LEFT (0b10111111)
#define MOVE_DOWN (0b11011111)
#define MOVE_UP (0b11101111)
#define P0_JOYSTICK_MASK (0b11110000)
#define P1_JOYSTICK_MASK (0b00001111)
#define P0_NO_MOVE (P0_JOYSTICK_MASK)
#define P1_NO_MOVE (P1_JOYSTICK_MASK)
#define NO_MOVE (P0_NO_MOVE | P1_NO_MOVE)
#define P0_HORIZ_MOVE (MOVE_RIGHT & MOVE_LEFT & P0_NO_MOVE)
#define P0_VERT_MOVE (MOVE_UP & MOVE_DOWN & P0_NO_MOVE)
#define P1_HORIZ_MOVE (((MOVE_RIGHT & MOVE_LEFT) >> 4) & P1_NO_MOVE)
#define P1_VERT_MOVE (((MOVE_UP & MOVE_DOWN) >> 4) & P1_NO_MOVE)
// SWCHA paddle bits
#define P0_TRIGGER_PRESSED (0b01111111)
#define P1_TRIGGER_PRESSED (0b10111111)
#define P2_TRIGGER_PRESSED (0b11110111)
#define P3_TRIGGER_PRESSED (0b11111011)
// Values for VBLANK
#define DUMP_PORTS (0b10000000)
#define ENABLE_LATCHES (0b01000000)
#define DISABLE_TIA (0b00000010)
#define ENABLE_TIA (0b00000000)
// Values for VSYNC
#define START_VERT_SYNC (0b10)
#define STOP_VERT_SYNC (0b00)
#endif