A5200DS/arm9/source/a5200utils.c
2025-01-31 14:06:24 -05:00

1168 lines
43 KiB
C

// =====================================================================================
// Copyright (c) 2021-2025 Dave Bernazzani (wavemotion-dave)
//
// Copying and distribution of this emulator, its source code and associated
// readme files, with or without modification, are permitted in any medium without
// royalty provided this copyright notice is used and both alekmaul and wavemotion-dave
// are thanked profusely.
//
// The a5200ds emulator is offered as-is, without any warranty.
//
// Please see the README.md file as it contains much useful info.
// =====================================================================================
#include <nds.h>
#include <nds/fifomessages.h>
#include <stdio.h>
#include <fat.h>
#include <dirent.h>
#include <unistd.h>
#include "main.h"
#include "a5200utils.h"
#include "atari.h"
#include "cartridge.h"
#include "highscore.h"
#include "input.h"
#include "emu/pia.h"
#include "clickNoQuit_wav.h"
#include "bgBottom.h"
#include "bgStarRaiders.h"
#include "bgTop.h"
#include "bgFileSel.h"
#include "printf.h"
#include "altirra_5200_os.h"
FICA5200 a5200romlist[1024];
unsigned int counta5200=0, countfiles=0, ucFicAct=0;
int gTotalAtariFrames = 0;
int bg0, bg1, bg0b, bg1b, bg2, bg3;
unsigned short int etatEmu;
int atari_frames=0;
u8 bSoundMute __attribute__((section(".dtcm"))) = false;
u8 unMuteSoon = 0;
char padKey[] = {AKEY_5200_0,AKEY_5200_1,AKEY_5200_2,AKEY_5200_3,AKEY_5200_4,AKEY_5200_5,AKEY_5200_6,AKEY_5200_7,AKEY_5200_8,AKEY_5200_9,AKEY_5200_HASH,AKEY_5200_ASTERISK};
char padKeySR[] = {AKEY_5200_1,AKEY_5200_2,AKEY_5200_3,AKEY_5200_4,AKEY_5200_5,AKEY_5200_6,AKEY_5200_7,AKEY_5200_8,AKEY_5200_9,AKEY_5200_ASTERISK,AKEY_5200_0,AKEY_5200_HASH};
#define cxBG (myCart.offset_x<<8)
#define cyBG (myCart.offset_y<<8)
#define xdxBG (((320 / myCart.scale_x) << 8) | (320 % myCart.scale_x))
#define ydyBG (((256 / myCart.scale_y) << 8) | (256 % myCart.scale_y))
unsigned char sound_buffer[16] __attribute__ ((aligned (4))) = {0}; // Never fast memory as it's shared with ARM7
u16* aptr __attribute__((section(".dtcm"))) = (u16*) ((u32)&sound_buffer[0] + 0xA000000);
u16* bptr __attribute__((section(".dtcm"))) = (u16*) ((u32)&sound_buffer[2] + 0xA000000);
unsigned int atari_pal16[256] = {0};
static int last_key_code = 0x00;
static UWORD keys_dampen = 0;
char bStarRaiders=0;
char lcd_swap_counter = 0;
u16 myPokeyBufIdx __attribute__((section(".dtcm"))) = 0;
u8 lastSample __attribute__((section(".dtcm"))) = 0;
u16 sampleExtender[256] __attribute__((section(".dtcm"))) = {0};
#define MAX_DEBUG 16
u32 debug[MAX_DEBUG]={0};
char DEBUG_DUMP = 0;
static void DumpDebugData(void)
{
if (DEBUG_DUMP)
{
static char dbgbuf[32];
sprintf(dbgbuf, "Cart.offset_x: %03d", myCart.offset_x); dsPrintValue(1,2,0, dbgbuf);
sprintf(dbgbuf, "Cart.offset_y: %03d", myCart.offset_y); dsPrintValue(1,3,0, dbgbuf);
sprintf(dbgbuf, "Cart.scale_x: %03d", myCart.scale_x); dsPrintValue(1,4,0, dbgbuf);
sprintf(dbgbuf, "Cart.scale_y: %03d", myCart.scale_y); dsPrintValue(1,5,0, dbgbuf);
for (int i=0; i<MAX_DEBUG; i++)
{
sprintf(dbgbuf, "%02d: %-9d %08X", i, debug[i], debug[i]);
dsPrintValue(0,7+i,0, dbgbuf);
}
}
}
extern unsigned char pokey_buffer[];
extern u16 pokeyBufIdx;
void VsoundClear(void)
{
extern void PokeyClearBuffer(void);
PokeyClearBuffer();
myPokeyBufIdx = pokeyBufIdx = 0;
}
ITCM_CODE void VsoundHandler(void)
{
if (bSoundMute) {*aptr = *bptr;}
// If there is a fresh sample...
else if (myPokeyBufIdx != pokeyBufIdx)
{
*aptr = sampleExtender[pokey_buffer[myPokeyBufIdx]];
myPokeyBufIdx = (myPokeyBufIdx+1) & (SNDLENGTH-1);
if (myPokeyBufIdx != pokeyBufIdx)
{
*bptr = sampleExtender[pokey_buffer[myPokeyBufIdx]];
myPokeyBufIdx = (myPokeyBufIdx+1) & (SNDLENGTH-1);
} else *bptr = *aptr;
}
}
ITCM_CODE void VsoundHandlerDSi(void)
{
if (bSoundMute) {*aptr = *bptr;}
// If there is a fresh sample...
else if (myPokeyBufIdx != pokeyBufIdx)
{
*aptr = *bptr = sampleExtender[pokey_buffer[myPokeyBufIdx]];
myPokeyBufIdx = (myPokeyBufIdx+1) & (SNDLENGTH-1);
}
}
void restore_bottom_screen(void)
{
if (bStarRaiders)
{
decompress(bgStarRaidersTiles, bgGetGfxPtr(bg0b), LZ77Vram);
decompress(bgStarRaidersMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
dmaCopy((void *) bgStarRaidersPal,(u16*) BG_PALETTE_SUB,256*2);
unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32);
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
}
else
{
decompress(bgBottomTiles, bgGetGfxPtr(bg0b), LZ77Vram);
decompress(bgBottomMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
dmaCopy((void *) bgBottomPal,(u16*) BG_PALETTE_SUB,256*2);
unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32);
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
}
}
// Color fading effect
void FadeToColor(unsigned char ucSens, unsigned short ucBG, unsigned char ucScr, unsigned char valEnd, unsigned char uWait) {
unsigned short ucFade;
unsigned char ucBcl;
// Fade-out vers le noir
if (ucScr & 0x01) REG_BLDCNT=ucBG;
if (ucScr & 0x02) REG_BLDCNT_SUB=ucBG;
if (ucSens == 1) {
for(ucFade=0;ucFade<valEnd;ucFade++) {
if (ucScr & 0x01) REG_BLDY=ucFade;
if (ucScr & 0x02) REG_BLDY_SUB=ucFade;
for (ucBcl=0;ucBcl<uWait;ucBcl++) {
swiWaitForVBlank();
}
}
}
else {
for(ucFade=16;ucFade>valEnd;ucFade--) {
if (ucScr & 0x01) REG_BLDY=ucFade;
if (ucScr & 0x02) REG_BLDY_SUB=ucFade;
for (ucBcl=0;ucBcl<uWait;ucBcl++) {
swiWaitForVBlank();
}
}
}
}
UWORD sIndex __attribute__((section(".dtcm")))= 0;
UBYTE dampen_slide_y __attribute__((section(".dtcm")))= 0;
short int screen_slide_y __attribute__((section(".dtcm"))) = 0;
ITCM_CODE void vblankIntr()
{
REG_BG2PA = xdxBG;
REG_BG2PD = ydyBG;
REG_BG2X = cxBG;
if (++sIndex & 1)
{
// Slight jitter to help with X-screen scaling...
REG_BG2Y = cyBG+0x40 + (screen_slide_y<<8);
if (dampen_slide_y == 0)
{
if (screen_slide_y < 0) screen_slide_y++;
else if (screen_slide_y > 0) screen_slide_y--;
} else dampen_slide_y--;
}
else
{
REG_BG2Y = cyBG + (screen_slide_y<<8);
}
}
void dsInitScreenMain(void)
{
// Init vbl and hbl func
SetYtrigger(190); //trigger 2 lines before vsync
irqSet(IRQ_VBLANK, vblankIntr);
irqEnable(IRQ_VBLANK | IRQ_VCOUNT);
vramSetBankB(VRAM_B_MAIN_BG_0x06020000 ); // Not using this for video but could use it for faster access... 128K of faster VRAM!
vramSetBankD(VRAM_D_LCD ); // Not using this for video but faster RAM always useful! 128K Mapped at 0x06860000
vramSetBankE(VRAM_E_LCD ); // Not using this for video but faster RAM always useful! 64K Mapped at 0x06880000
vramSetBankF(VRAM_F_LCD ); // Not using this for video but faster RAM always useful! 16K Mapped at 0x06890000
vramSetBankG(VRAM_G_LCD ); // Not using this for video but faster RAM always useful! 16K Mapped at 0x06894000
vramSetBankH(VRAM_H_LCD ); // Not using this for video but faster RAM always useful! 32K Mapped at 0x06898000
vramSetBankI(VRAM_I_LCD ); // Not using this for video but faster RAM always useful! 16K Mapped at 0x068A0000
}
void dsInitTimer(void)
{
TIMER0_DATA=0;
TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024;
}
void dsShowScreenEmu(void)
{
// Change vram
videoSetMode(MODE_5_2D | DISPLAY_BG2_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG_0x06000000);
bg2 = bgInit(2, BgType_Bmp8, BgSize_B8_512x512, 0,0);
REG_BG2PB = 0;
REG_BG2PC = 0;
REG_BG2X = cxBG;
REG_BG2Y = cyBG;
REG_BG2PA = xdxBG;
REG_BG2PD = ydyBG;
REG_BLDCNT=0; REG_BLDCNT_SUB=0; REG_BLDY=0; REG_BLDY_SUB=0;
}
void dsShowScreenMain(void) {
// Init BG mode for 16 bits colors
videoSetMode(MODE_0_2D | DISPLAY_BG0_ACTIVE );
videoSetModeSub(MODE_0_2D | DISPLAY_BG0_ACTIVE | DISPLAY_BG1_ACTIVE);
vramSetBankA(VRAM_A_MAIN_BG); vramSetBankC(VRAM_C_SUB_BG);
bg0 = bgInit(0, BgType_Text8bpp, BgSize_T_256x256, 31,0);
bg0b = bgInitSub(0, BgType_Text8bpp, BgSize_T_256x256, 31,0);
bg1b = bgInitSub(1, BgType_Text8bpp, BgSize_T_256x256, 30,0);
bgSetPriority(bg0b,1);bgSetPriority(bg1b,0);
decompress(bgTopTiles, bgGetGfxPtr(bg0), LZ77Vram);
decompress(bgTopMap, (void*) bgGetMapPtr(bg0), LZ77Vram);
dmaCopy((void *) bgTopPal,(u16*) BG_PALETTE,256*2);
restore_bottom_screen();
REG_BLDCNT=0; REG_BLDCNT_SUB=0; REG_BLDY=0; REG_BLDY_SUB=0;
swiWaitForVBlank();
}
void dsFreeEmu(void) {
// Stop timer of sound
TIMER2_CR=0; irqDisable(IRQ_TIMER2);
}
#define PALETTE_SIZE 768
byte palette_data[PALETTE_SIZE] = { // NTSC_LUM1_HOT 5200 from Trebor
0x00, 0x00, 0x00, 0x1A, 0x1A, 0x1A, 0x2C, 0x2C, 0x2C, 0x3C, 0x3C, 0x3C, 0x4B, 0x4B, 0x4B, 0x59, 0x59, 0x59, 0x66, 0x66, 0x66, 0x73, 0x73, 0x73, 0x7F, 0x7F, 0x7F, 0x8B, 0x8B, 0x8B, 0x97, 0x97, 0x97, 0xA3, 0xA3, 0xA3, 0xAE, 0xAE, 0xAE, 0xB9,
0xB9, 0xB9, 0xC4, 0xC4, 0xC4, 0xCE, 0xCE, 0xCE, 0x27, 0x15, 0x00, 0x37, 0x28, 0x00, 0x46, 0x38, 0x00, 0x54, 0x47, 0x00, 0x62, 0x55, 0x00, 0x6F, 0x63, 0x00, 0x7C, 0x70, 0x00, 0x88, 0x7C, 0x00, 0x94, 0x88, 0x00, 0x9F, 0x94, 0x07, 0xAA, 0xA0,
0x1D, 0xB6, 0xAB, 0x2F, 0xC0, 0xB6, 0x3F, 0xCB, 0xC1, 0x4D, 0xD6, 0xCC, 0x5B, 0xE0, 0xD6, 0x68, 0x46, 0x00, 0x00, 0x54, 0x0A, 0x00, 0x62, 0x1F, 0x00, 0x6F, 0x31, 0x00, 0x7B, 0x40, 0x00, 0x87, 0x4F, 0x00, 0x93, 0x5D, 0x00, 0x9F, 0x6A, 0x00,
0xAA, 0x76, 0x07, 0xB5, 0x83, 0x1D, 0xC0, 0x8F, 0x2F, 0xCB, 0x9A, 0x3F, 0xD5, 0xA6, 0x4D, 0xE0, 0xB1, 0x5B, 0xEA, 0xBC, 0x69, 0xF4, 0xC7, 0x75, 0x56, 0x00, 0x00, 0x63, 0x00, 0x00, 0x70, 0x00, 0x00, 0x7D, 0x1A, 0x00, 0x89, 0x2C, 0x00, 0x95,
0x3C, 0x00, 0xA0, 0x4B, 0x1A, 0xAC, 0x59, 0x2C, 0xB7, 0x66, 0x3C, 0xC2, 0x73, 0x4B, 0xCC, 0x7F, 0x59, 0xD7, 0x8B, 0x66, 0xE1, 0x97, 0x73, 0xEB, 0xA3, 0x7F, 0xF6, 0xAE, 0x8B, 0xFF, 0xB9, 0x97, 0x56, 0x00, 0x00, 0x64, 0x00, 0x00, 0x71, 0x00,
0x19, 0x7D, 0x06, 0x2B, 0x89, 0x1D, 0x3B, 0x95, 0x2E, 0x4A, 0xA1, 0x3E, 0x58, 0xAC, 0x4D, 0x65, 0xB7, 0x5B, 0x72, 0xC2, 0x68, 0x7F, 0xCD, 0x75, 0x8B, 0xD7, 0x81, 0x97, 0xE1, 0x8D, 0xA2, 0xEC, 0x99, 0xAD, 0xF6, 0xA4, 0xB8, 0xFF, 0xB0, 0xC3,
0x47, 0x00, 0x3E, 0x55, 0x00, 0x4D, 0x63, 0x00, 0x5B, 0x70, 0x00, 0x68, 0x7C, 0x19, 0x75, 0x88, 0x2B, 0x81, 0x94, 0x3B, 0x8D, 0xA0, 0x4A, 0x99, 0xAB, 0x58, 0xA4, 0xB6, 0x66, 0xB0, 0xC1, 0x73, 0xBB, 0xCC, 0x7F, 0xC5, 0xD6, 0x8B, 0xD0, 0xE1,
0x97, 0xDB, 0xEB, 0xA2, 0xE5, 0xF5, 0xAE, 0xEF, 0x28, 0x00, 0x6E, 0x39, 0x00, 0x7B, 0x48, 0x00, 0x87, 0x56, 0x0F, 0x93, 0x63, 0x23, 0x9E, 0x70, 0x34, 0xAA, 0x7D, 0x43, 0xB5, 0x89, 0x52, 0xC0, 0x95, 0x5F, 0xCA, 0xA0, 0x6C, 0xD5, 0xAC, 0x79,
0xDF, 0xB7, 0x85, 0xEA, 0xC2, 0x91, 0xF4, 0xCC, 0x9D, 0xFE, 0xD7, 0xA8, 0xFF, 0xE1, 0xB3, 0xFF, 0x00, 0x00, 0x86, 0x0E, 0x00, 0x92, 0x22, 0x11, 0x9E, 0x33, 0x25, 0xA9, 0x43, 0x35, 0xB4, 0x51, 0x45, 0xBF, 0x5F, 0x53, 0xCA, 0x6C, 0x60, 0xD5,
0x79, 0x6E, 0xDF, 0x85, 0x7A, 0xE9, 0x91, 0x86, 0xF3, 0x9C, 0x92, 0xFD, 0xA8, 0x9E, 0xFF, 0xB3, 0xA9, 0xFF, 0xBE, 0xB4, 0xFF, 0xC9, 0xBF, 0xFF, 0x00, 0x00, 0x86, 0x00, 0x1A, 0x92, 0x00, 0x2C, 0x9E, 0x08, 0x3C, 0xA9, 0x1E, 0x4B, 0xB4, 0x30,
0x59, 0xBF, 0x3F, 0x66, 0xCA, 0x4E, 0x73, 0xD4, 0x5C, 0x7F, 0xDF, 0x69, 0x8B, 0xE9, 0x76, 0x97, 0xF3, 0x82, 0xA3, 0xFD, 0x8E, 0xAE, 0xFF, 0x9A, 0xB9, 0xFF, 0xA5, 0xC4, 0xFF, 0xB0, 0xCE, 0xFF, 0x00, 0x22, 0x6D, 0x00, 0x33, 0x7A, 0x00, 0x42,
0x86, 0x00, 0x51, 0x92, 0x00, 0x5E, 0x9E, 0x12, 0x6B, 0xA9, 0x26, 0x78, 0xB4, 0x36, 0x84, 0xBF, 0x45, 0x90, 0xCA, 0x54, 0x9C, 0xD4, 0x61, 0xA7, 0xDF, 0x6E, 0xB3, 0xE9, 0x7B, 0xBD, 0xF3, 0x87, 0xC8, 0xFD, 0x93, 0xD3, 0xFF, 0x9E, 0xDD, 0xFF,
0x00, 0x34, 0x3D, 0x00, 0x44, 0x4C, 0x00, 0x52, 0x5A, 0x00, 0x60, 0x67, 0x00, 0x6D, 0x74, 0x03, 0x79, 0x80, 0x1B, 0x85, 0x8C, 0x2D, 0x91, 0x98, 0x3D, 0x9D, 0xA4, 0x4B, 0xA8, 0xAF, 0x59, 0xB4, 0xBA, 0x67, 0xBE, 0xC5, 0x74, 0xC9, 0xCF, 0x80,
0xD4, 0xDA, 0x8C, 0xDE, 0xE4, 0x98, 0xE9, 0xEE, 0x00, 0x3C, 0x00, 0x00, 0x4B, 0x00, 0x00, 0x59, 0x17, 0x00, 0x66, 0x2A, 0x00, 0x73, 0x3A, 0x11, 0x80, 0x49, 0x25, 0x8C, 0x57, 0x36, 0x97, 0x64, 0x45, 0xA3, 0x71, 0x53, 0xAE, 0x7E, 0x61, 0xB9,
0x8A, 0x6E, 0xC4, 0x96, 0x7A, 0xCF, 0xA1, 0x87, 0xD9, 0xAD, 0x93, 0xE4, 0xB8, 0x9E, 0xEE, 0xC2, 0x00, 0x3A, 0x00, 0x00, 0x48, 0x00, 0x00, 0x57, 0x00, 0x06, 0x64, 0x00, 0x1D, 0x71, 0x00, 0x2F, 0x7D, 0x00, 0x3E, 0x8A, 0x18, 0x4D, 0x95, 0x2B,
0x5B, 0xA1, 0x3B, 0x68, 0xAC, 0x4A, 0x75, 0xB7, 0x58, 0x81, 0xC2, 0x65, 0x8D, 0xCD, 0x72, 0x99, 0xD7, 0x7E, 0xA5, 0xE2, 0x8B, 0xB0, 0xEC, 0x96, 0x00, 0x2C, 0x00, 0x0C, 0x3C, 0x00, 0x21, 0x4B, 0x00, 0x32, 0x59, 0x00, 0x42, 0x66, 0x00, 0x50,
0x73, 0x00, 0x5E, 0x7F, 0x00, 0x6B, 0x8C, 0x00, 0x78, 0x97, 0x06, 0x84, 0xA3, 0x1D, 0x90, 0xAE, 0x2E, 0x9C, 0xB9, 0x3E, 0xA7, 0xC4, 0x4D, 0xB2, 0xCF, 0x5B, 0xBD, 0xD9, 0x68, 0xC8, 0xE3, 0x75, 0x27, 0x14, 0x00, 0x38, 0x27, 0x00, 0x47, 0x38,
0x00, 0x55, 0x47, 0x00, 0x63, 0x55, 0x00, 0x70, 0x62, 0x00, 0x7C, 0x6F, 0x00, 0x88, 0x7C, 0x00, 0x94, 0x88, 0x00, 0xA0, 0x94, 0x07, 0xAB, 0x9F, 0x1D, 0xB6, 0xAB, 0x2F, 0xC1, 0xB6, 0x3F, 0xCC, 0xC1, 0x4D, 0xD6, 0xCB, 0x5B, 0xE1, 0xD6, 0x68,
0x46, 0x00, 0x00, 0x54, 0x09, 0x00, 0x62, 0x1F, 0x00, 0x6F, 0x30, 0x00, 0x7C, 0x40, 0x00, 0x88, 0x4E, 0x00, 0x94, 0x5C, 0x00, 0x9F, 0x69, 0x00, 0xAA, 0x76, 0x08, 0xB6, 0x82, 0x1E, 0xC0, 0x8E, 0x30, 0xCB, 0x9A, 0x3F, 0xD6, 0xA6, 0x4E, 0xE0,
0xB1, 0x5C, 0xEA, 0xBC, 0x69, 0xF5, 0xC7, 0x76
};
char filetmp[256];
char *bios_filename = "5200.rom";
char *bios_filename_alt = "a5200.rom";
int load_os(void)
{
FILE *romfile = fopen(bios_filename, "rb");
if (romfile == NULL)
{
sprintf(filetmp, "/roms/bios/%s", bios_filename);
romfile = fopen(filetmp, "rb");
}
if (romfile == NULL)
{
sprintf(filetmp, "/data/bios/%s", bios_filename);
romfile = fopen(filetmp, "rb");
}
if (romfile == NULL)
{
romfile = fopen(bios_filename_alt, "rb");
}
if (romfile == NULL)
{
sprintf(filetmp, "/roms/bios/%s", bios_filename_alt);
romfile = fopen(filetmp, "rb");
}
if (romfile == NULL)
{
sprintf(filetmp, "/data/bios/%s", bios_filename_alt);
romfile = fopen(filetmp, "rb");
}
if (romfile == NULL)
{
memcpy(atari_os, ROM_altirra_5200_os, 0x800); // No 5200.rom found... use open source Altirra OS instead
}
else
{
fread(atari_os, 0x800, 1, romfile);
fclose(romfile);
}
return 0;
} /* end load_os */
static u8 bFirstTimeLoad = 1;
void dsLoadGame(char *filename)
{
// load card game if ok
if (Atari800_OpenFile(filename, true, 1, true) != AFILE_ERROR)
{
// Initialize the virtual console emulation
dsShowScreenEmu();
INPUT_Initialise();
// Init palette
for(u16 index = 0; index < 256; index++) {
unsigned short r = palette_data[(index * 3) + 0];
unsigned short g = palette_data[(index * 3) + 1];
unsigned short b = palette_data[(index * 3) + 2];
BG_PALETTE[index] = RGB8(r, g, b);
atari_pal16[index] = index;
}
if (bFirstTimeLoad)
{
*aptr = *bptr = 0;
bFirstTimeLoad = 0;
bSoundMute = 1;
TIMER2_CR = 0;
if (isDSiMode())
{
TIMER2_DATA = TIMER_FREQ(SOUND_FREQ+20); // keep this a little faster than our Pokey sound generation
irqSet(IRQ_TIMER2, VsoundHandlerDSi);
}
else // Older DS uses lower sound quality
{
TIMER2_DATA = TIMER_FREQ((SOUND_FREQ/2)+10); // keep this a little faster than our Pokey sound generation
irqSet(IRQ_TIMER2, VsoundHandler);
}
TIMER2_CR = TIMER_DIV_1 | TIMER_IRQ_REQ | TIMER_ENABLE;
irqEnable(IRQ_TIMER2);
}
TIMER0_CR=0;
TIMER0_DATA=0;
TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024;
atari_frames=0;
}
else dsPrintValue(0,2,0, "UNABLE TO FIND GAME!!");
}
unsigned int dsReadPad(void) {
unsigned short int keys_pressed, ret_keys_pressed;
do {
keys_pressed = keysCurrent();
} while ((keys_pressed & (KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP | KEY_A | KEY_B | KEY_L | KEY_R))!=0);
do {
keys_pressed = keysCurrent();
} while ((keys_pressed & (KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP | KEY_A | KEY_B | KEY_L | KEY_R))==0);
ret_keys_pressed = keys_pressed;
do {
keys_pressed = keysCurrent();
} while ((keys_pressed & (KEY_LEFT | KEY_RIGHT | KEY_DOWN | KEY_UP | KEY_A | KEY_B | KEY_L | KEY_R))!=0);
return ret_keys_pressed;
}
bool dsWaitOnQuit(void) {
char bRet=false, bDone=false;
unsigned int keys_pressed;
char posdeb=0;
static char szName[32];
decompress(bgFileSelTiles, bgGetGfxPtr(bg0b), LZ77Vram);
decompress(bgFileSelMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
dmaCopy((void *) bgFileSelPal,(u16*) BG_PALETTE_SUB,256*2);
unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32);
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
strcpy(szName,"Quit A5200DS ?");
dsPrintValue(4,2,0,szName);
sprintf(szName,"%s","A TO CONFIRM, B TO GO BACK");
dsPrintValue(16-strlen(szName)/2,23,0,szName);
while(!bDone) {
strcpy(szName," YES ");
dsPrintValue(5,10+0,(posdeb == 0 ? 1 : 0),szName);
strcpy(szName," NO ");
dsPrintValue(5,14+1,(posdeb == 2 ? 1 : 0),szName);
swiWaitForVBlank();
// Check pad
keys_pressed=dsReadPad();
if (keys_pressed & KEY_UP) {
if (posdeb) posdeb-=2;
}
if (keys_pressed & KEY_DOWN) {
if (posdeb<1) posdeb+=2;
}
if (keys_pressed & KEY_A) {
bRet = (posdeb ? false : true);
bDone = true;
}
if (keys_pressed & KEY_B) {
bDone = true;
}
}
restore_bottom_screen();
return bRet;
}
void dsDisplayFiles(unsigned int NoDebGame,u32 ucSel) {
unsigned short int ucBcl,ucGame;
u8 maxLen;
static char szName[256];
// Display all games if possible
unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32);
dmaFillWords(dmaVal | (dmaVal<<16),(void*) (bgGetMapPtr(bg1b)),32*24*2);
countfiles ? sprintf(szName,"%04d/%04d GAMES",(int)(1+ucSel+NoDebGame),countfiles) : sprintf(szName,"%04d/%04d FOLDERS",(int)(1+ucSel+NoDebGame),counta5200);
dsPrintValue(2,1,0,szName);
dsPrintValue(31,5,0,(char *) (NoDebGame>0 ? "<" : " "));
dsPrintValue(31,22,0,(char *) (NoDebGame+14<counta5200 ? ">" : " "));
sprintf(szName,"%s","A TO SELECT A GAME, B TO GO BACK");
dsPrintValue(16-strlen(szName)/2,23,0,szName);
for (ucBcl=0;ucBcl<17; ucBcl++) {
ucGame= ucBcl+NoDebGame;
if (ucGame < counta5200) {
char szName2[256];
maxLen=strlen(a5200romlist[ucGame].filename);
strcpy(szName,a5200romlist[ucGame].filename);
if (maxLen>29) szName[29]='\0';
if (a5200romlist[ucGame].directory)
{
char szName3[36];
sprintf(szName3,"[%s]",szName);
sprintf(szName2,"%-29s",szName3);
dsPrintValue(0,5+ucBcl,(ucSel == ucBcl ? 1 : 0),szName2);
}
else
{
sprintf(szName2,"%-29s",strupr(szName));
dsPrintValue(1,5+ucBcl,(ucSel == ucBcl ? 1 : 0),szName2);
}
}
}
}
unsigned int dsWaitForRom(void)
{
char bDone=false, bRet=false;
u16 ucHaut=0x00, ucBas=0x00,ucSHaut=0x00, ucSBas=0x00,romSelected= 0, firstRomDisplay=0,nbRomPerPage, uNbRSPage, uLenFic=0,ucFlip=0, ucFlop=0;
static char szName[64];
decompress(bgFileSelTiles, bgGetGfxPtr(bg0b), LZ77Vram);
decompress(bgFileSelMap, (void*) bgGetMapPtr(bg0b), LZ77Vram);
dmaCopy((void *) bgFileSelPal,(u16*) BG_PALETTE_SUB,256*2);
unsigned short dmaVal = *(bgGetMapPtr(bg1b) +31*32);
dmaFillWords(dmaVal | (dmaVal<<16),(void*) bgGetMapPtr(bg1b),32*24*2);
nbRomPerPage = (counta5200>=17 ? 17 : counta5200);
uNbRSPage = (counta5200>=5 ? 5 : counta5200);
if (ucFicAct>counta5200-nbRomPerPage) {
firstRomDisplay=counta5200-nbRomPerPage;
romSelected=ucFicAct-counta5200+nbRomPerPage;
}
else {
firstRomDisplay=ucFicAct;
romSelected=0;
}
dsDisplayFiles(firstRomDisplay,romSelected);
while (!bDone) {
if (keysCurrent() & KEY_UP) {
if (!ucHaut) {
ucFicAct = (ucFicAct>0 ? ucFicAct-1 : counta5200-1);
if (romSelected>uNbRSPage) { romSelected -= 1; }
else {
if (firstRomDisplay>0) { firstRomDisplay -= 1; }
else {
if (romSelected>0) { romSelected -= 1; }
else {
firstRomDisplay=counta5200-nbRomPerPage;
romSelected=nbRomPerPage-1;
}
}
}
ucHaut=0x01;
dsDisplayFiles(firstRomDisplay,romSelected);
}
else {
ucHaut++;
if (ucHaut>10) ucHaut=0;
}
uLenFic=0; ucFlip=0;
}
else {
ucHaut = 0;
}
if (keysCurrent() & KEY_DOWN) {
if (!ucBas) {
ucFicAct = (ucFicAct< counta5200-1 ? ucFicAct+1 : 0);
if (romSelected<uNbRSPage-1) { romSelected += 1; }
else {
if (firstRomDisplay<counta5200-nbRomPerPage) { firstRomDisplay += 1; }
else {
if (romSelected<nbRomPerPage-1) { romSelected += 1; }
else {
firstRomDisplay=0;
romSelected=0;
}
}
}
ucBas=0x01;
dsDisplayFiles(firstRomDisplay,romSelected);
}
else {
ucBas++;
if (ucBas>10) ucBas=0;
}
uLenFic=0; ucFlip=0;
}
else {
ucBas = 0;
}
if ((keysCurrent() & KEY_R) || (keysCurrent() & KEY_RIGHT)) {
if (!ucSBas) {
ucFicAct = (ucFicAct< counta5200-nbRomPerPage ? ucFicAct+nbRomPerPage : counta5200-nbRomPerPage);
if (firstRomDisplay<counta5200-nbRomPerPage) { firstRomDisplay += nbRomPerPage; }
else { firstRomDisplay = counta5200-nbRomPerPage; }
if (ucFicAct == counta5200-nbRomPerPage) romSelected = 0;
ucSBas=0x01;
dsDisplayFiles(firstRomDisplay,romSelected);
}
else {
ucSBas++;
if (ucSBas>10) ucSBas=0;
}
}
else {
ucSBas = 0;
}
if ((keysCurrent() & KEY_L) || (keysCurrent() & KEY_LEFT)) {
if (!ucSHaut) {
ucFicAct = (ucFicAct> nbRomPerPage ? ucFicAct-nbRomPerPage : 0);
if (firstRomDisplay>nbRomPerPage) { firstRomDisplay -= nbRomPerPage; }
else { firstRomDisplay = 0; }
if (ucFicAct == 0) romSelected = 0;
if (romSelected > ucFicAct) romSelected = ucFicAct;
ucSHaut=0x01;
dsDisplayFiles(firstRomDisplay,romSelected);
}
else {
ucSHaut++;
if (ucSHaut>10) ucSHaut=0;
}
}
else {
ucSHaut = 0;
}
if ( keysCurrent() & KEY_B ) {
bDone=true;
while (keysCurrent() & KEY_B);
}
if (keysCurrent() & KEY_A)
{
if (!a5200romlist[ucFicAct].directory)
{
if (keysCurrent() & KEY_X) DEBUG_DUMP=1; else DEBUG_DUMP=0;
bRet=true;
bDone=true;
}
else
{
chdir(a5200romlist[ucFicAct].filename);
a52FindFiles();
ucFicAct = 0;
nbRomPerPage = (counta5200>=16 ? 16 : counta5200);
uNbRSPage = (counta5200>=5 ? 5 : counta5200);
if (ucFicAct>counta5200-nbRomPerPage) {
firstRomDisplay=counta5200-nbRomPerPage;
romSelected=ucFicAct-counta5200+nbRomPerPage;
}
else {
firstRomDisplay=ucFicAct;
romSelected=0;
}
dsDisplayFiles(firstRomDisplay,romSelected);
while (keysCurrent() & KEY_A);
}
}
// Scroll the current selection
if (strlen(a5200romlist[ucFicAct].filename) > 29) {
ucFlip++;
if (ucFlip >= 10) {
ucFlip = 0;
uLenFic++;
if ((uLenFic+29)>strlen(a5200romlist[ucFicAct].filename)) {
ucFlop++;
if (ucFlop >= 10) {
uLenFic=0;
ucFlop = 0;
}
else
uLenFic--;
}
strncpy(szName,a5200romlist[ucFicAct].filename+uLenFic,29);
szName[29] = '\0';
dsPrintValue(1,5+romSelected,1,szName);
}
}
swiWaitForVBlank();
}
restore_bottom_screen();
return bRet;
}
unsigned int dsWaitOnMenu(unsigned int actState) {
unsigned int uState=A5200_PLAYINIT;
unsigned int keys_pressed;
bool bDone=false, romSel;
int iTx,iTy;
while (!bDone) {
// wait for stylus
keys_pressed = keysCurrent();
if (keys_pressed & KEY_TOUCH) {
touchPosition touch;
touchRead(&touch);
iTx = touch.px;
iTy = touch.py;
if ((iTx>206) && (iTx<250) && (iTy>110) && (iTy<129)) { // 207,111 -> 249,128 quit
soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
bDone=dsWaitOnQuit();
if (bDone) uState=A5200_QUITSTDS;
}
if ((iTx>71) && (iTx<183) && (iTy>7) && (iTy<43)) { // 72,8 -> 182,42 cartridge slot
bDone=true;
// Find files in current directory and show it
a52FindFiles();
romSel=dsWaitForRom();
if (romSel) { uState=A5200_PLAYINIT;
dsLoadGame(a5200romlist[ucFicAct].filename); }
else { uState=actState; }
}
}
swiWaitForVBlank();
}
return uState;
}
void dsPrintValue(int x, int y, unsigned int isSelect, char *pchStr)
{
u16 *pusEcran,*pusMap;
u16 usCharac;
char *pTrTxt=pchStr;
char ch;
pusEcran=(u16*) (bgGetMapPtr(bg1b))+x+(y<<5);
pusMap=(u16*) (bgGetMapPtr(bg0b)+(2*isSelect+24)*32);
while((*pTrTxt)!='\0' )
{
ch = *pTrTxt;
if (ch >= 'a' && ch <= 'z') ch -= 32; // Faster than strcpy/strtoupper
usCharac=0x0000;
if ((ch) == '|')
usCharac=*(pusMap);
else if (((ch)<' ') || ((ch)>'_'))
usCharac=*(pusMap);
else if((ch)<'@')
usCharac=*(pusMap+(ch)-' ');
else
usCharac=*(pusMap+32+(ch)-'@');
*pusEcran++=usCharac;
pTrTxt++;
}
}
//----------------------------------------------------------------------------------
// Find files (a78 / bin) available
int a52Filescmp (const void *c1, const void *c2) {
FICA5200 *p1 = (FICA5200 *) c1;
FICA5200 *p2 = (FICA5200 *) c2;
if (p1->filename[0] == '.' && p2->filename[0] != '.')
return -1;
if (p2->filename[0] == '.' && p1->filename[0] != '.')
return 1;
if (p1->directory && !(p2->directory))
return -1;
if (p2->directory && !(p1->directory))
return 1;
return strcasecmp (p1->filename, p2->filename);
}
void a52FindFiles(void) {
DIR *pdir;
struct dirent *pent;
static char filenametmp[MAX_FILENAME_LEN];
counta5200 = countfiles= 0;
pdir = opendir(".");
if (pdir) {
while (((pent=readdir(pdir))!=NULL))
{
strcpy(filenametmp,pent->d_name);
if (pent->d_type == DT_DIR)
{
if (!( (filenametmp[0] == '.') && (strlen(filenametmp) == 1))) {
a5200romlist[counta5200].directory = true;
strcpy(a5200romlist[counta5200].filename,filenametmp);
counta5200++;
}
}
else {
if (strlen(filenametmp)>4) {
if ( (strcasecmp(strrchr(filenametmp, '.'), ".a52") == 0) ) {
a5200romlist[counta5200].directory = false;
strcpy(a5200romlist[counta5200].filename,filenametmp);
counta5200++;countfiles++;
}
if ( (strcasecmp(strrchr(filenametmp, '.'), ".bin") == 0) ) {
a5200romlist[counta5200].directory = false;
strcpy(a5200romlist[counta5200].filename,filenametmp);
counta5200++;countfiles++;
}
}
}
}
closedir(pdir);
}
if (counta5200)
{
qsort (a5200romlist, counta5200, sizeof (FICA5200), a52Filescmp);
}
else // Failsafe... always provide a back directory...
{
a5200romlist[counta5200].directory = true;
strcpy(a5200romlist[counta5200].filename,"..");
counta5200 = 1;
}
}
//---------------------------------------------------------------------------------
void dsInstallSoundEmuFIFO(void)
{
// We are going to use the 16-bit sound engine so we need to scale up our 8-bit values...
for (int i=0; i<256; i++)
{
sampleExtender[i] = (i << 8);
}
if (isDSiMode())
{
aptr = (u16*) ((u32)&sound_buffer[0] + 0xA000000);
bptr = (u16*) ((u32)&sound_buffer[2] + 0xA000000);
}
else
{
aptr = (u16*) ((u32)&sound_buffer[0] + 0x00400000);
bptr = (u16*) ((u32)&sound_buffer[2] + 0x00400000);
}
FifoMessage msg;
msg.SoundPlay.data = &sound_buffer;
msg.SoundPlay.freq = SOUND_FREQ*2;
msg.SoundPlay.volume = 127;
msg.SoundPlay.pan = 64;
msg.SoundPlay.loop = 1;
msg.SoundPlay.format = ((1)<<4) | SoundFormat_16Bit;
msg.SoundPlay.loopPoint = 0;
msg.SoundPlay.dataSize = 4 >> 2;
msg.type = EMUARM7_PLAY_SND;
fifoSendDatamsg(FIFO_USER_01, sizeof(msg), (u8*)&msg);
}
extern u16 trig0, trig1;
extern u16 stick0;
extern u16 stick1;
char full_speed = 0;
void dsMainLoop(void) {
static char fpsbuf[32];
unsigned short int keys_pressed,keys_touch=0, romSel;
short int iTx,iTy, shiftctrl;
char showFps=false;
// Timers are fed with 33.513982 MHz clock.
// With DIV_1024 the clock is 32,728.5 ticks per sec...
TIMER0_DATA=0;
TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024;
TIMER1_DATA=0;
TIMER1_CR=TIMER_ENABLE | TIMER_DIV_1024;
while(etatEmu != A5200_QUITSTDS)
{
switch (etatEmu)
{
case A5200_MENUINIT:
dsShowScreenMain();
etatEmu = A5200_MENUSHOW;
break;
case A5200_MENUSHOW:
etatEmu = dsWaitOnMenu(A5200_MENUSHOW);
Atari800_Initialise();
break;
case A5200_PLAYINIT:
dsShowScreenEmu();
VsoundClear();
unMuteSoon = 5;
etatEmu = A5200_PLAYGAME;
atari_frames=0;
TIMER0_CR=0;
TIMER0_DATA=0;
TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024;
TIMER1_DATA=0;
TIMER1_CR=TIMER_ENABLE | TIMER_DIV_1024;
break;
case A5200_PLAYGAME:
// 32,728.5 ticks = 1 second
// 1 frame = 1/50 or 1/60 (0.02 or 0.016)
// 655 -> 50 fps and 546 -> 60 fps
if (!full_speed)
{
while(TIMER0_DATA < (546*atari_frames))
;
}
if (unMuteSoon)
{
if (--unMuteSoon == 0) bSoundMute = false;
}
// Execute one frame
Atari800_Frame();
if (++atari_frames == 60)
{
TIMER0_CR=0;
TIMER0_DATA=0;
TIMER0_CR=TIMER_ENABLE|TIMER_DIV_1024;
atari_frames=0;
}
// -------------------------------------------------------------
// Stuff to do once/second such as FPS display and Debug Data
// -------------------------------------------------------------
if (TIMER1_DATA >= 32728) // 1000MS (1 sec)
{
TIMER1_CR = 0;
TIMER1_DATA = 0;
TIMER1_CR=TIMER_ENABLE | TIMER_DIV_1024;
if (!full_speed && (gTotalAtariFrames > 60)) gTotalAtariFrames--; // We tend to overshoot...
if (showFps) { sprintf(fpsbuf,"%03d",gTotalAtariFrames); dsPrintValue(0,0,0, fpsbuf); } // Show FPS
DumpDebugData();
gTotalAtariFrames = 0;
}
// Read keys
keys_pressed=keysCurrent();
key_consol = CONSOL_NONE; //|= (CONSOL_OPTION | CONSOL_SELECT | CONSOL_START); /* OPTION/START/SELECT key OFF */
shiftctrl = 0; key_shift = 0;
trig0 = ((keys_pressed & KEY_A) || (keys_pressed & KEY_Y)) ? 0 : 1;
stick0 = STICK_CENTRE;
stick1 = STICK_CENTRE;
if (keys_pressed & KEY_B) { shiftctrl ^= AKEY_SHFT; key_shift = 1; }
key_code = shiftctrl ? 0x40 : 0x00;
// if touch screen pressed
if (keys_pressed & KEY_TOUCH)
{
touchPosition touch;
touchRead(&touch);
iTx = touch.px;
iTy = touch.py;
if (iTy < 20)
{
if ((iTx>240) && (iTx<256) && (iTy>0) && (iTy<20)) { // Full Speed Toggle ... upper right corner...
if (keys_touch == 0)
{
full_speed = 1-full_speed;
if (full_speed) dsPrintValue(30,0,0,"FS"); else dsPrintValue(30,0,0," ");
keys_touch = 1;
}
}
else if ((iTx>0) && (iTx<20) && (iTy>0) && (iTy<20)) { // FPS Counter ... upper left corner...
if (keys_touch == 0)
{
showFps = 1-showFps;
dsPrintValue(0,0,0, " ");
keys_touch = 1;
}
}
}
else if (iTy < 50)
{
if ((iTx>70) && (iTx<185) && (iTy>7) && (iTy<50)) // 72,8 -> 182,42 cartridge slot
{
bSoundMute = true;
// Find files in current directory and show it
a52FindFiles();
romSel=dsWaitForRom();
if (romSel)
{
etatEmu=A5200_PLAYINIT;
dsLoadGame(a5200romlist[ucFicAct].filename);
if (full_speed) dsPrintValue(30,0,0,"FS"); else dsPrintValue(30,0,0," ");
}
}
}
else if (iTy < 130)
{
if ((iTx>211) && (iTx<250) && (iTy>112) && (iTy<130)) { //quit
bSoundMute = true;
soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
if (dsWaitOnQuit()) etatEmu=A5200_QUITSTDS;
else { unMuteSoon = 5;}
}
else if ((iTx>160) && (iTx<200) && (iTy>112) && (iTy<130)) { //highscore
bSoundMute = true;
highscore_display();
restore_bottom_screen();
unMuteSoon = 5;
}
else if ((iTx>115) && (iTx<150) && (iTy>112) && (iTy<130)) { //pause
if (!keys_touch) soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
key_code = AKEY_5200_PAUSE + key_code;
keys_touch = 1;
}
else if ((iTx>64) && (iTx<105) && (iTy>112) && (iTy<130)) { //reset
if (!keys_touch) soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
key_code = AKEY_5200_RESET + key_code;
keys_touch = 1;
}
else if ((iTx>8) && (iTx<54) && (iTy>112) && (iTy<130)) { //start
if (!keys_touch) soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
key_code = AKEY_5200_START + key_code;
keys_touch = 1;
}
}
else
{
if (bStarRaiders) // Special Overlay for Star Raiders
{
if ((iTy>144) && (iTy<191)) // This is our 5200 Keypad 0-9,#,*
{
if (!keys_dampen && (keys_touch==0)) // First time pressed?
{
keys_touch = 1;
soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
if (iTx > 0) iTx--;
if (iTy < 169) key_code = padKeySR[0 + (iTx / 42)];
else key_code = padKeySR[6 + (iTx / 42)];
last_key_code = key_code;
keys_dampen = 25; // Almost a half second for consistent debounce
}
else
{
key_code = last_key_code;
if (keys_dampen) keys_dampen--; else last_key_code=0x00;
}
}
}
else
{
if ((iTy>150) && (iTy<185)) // This is our 5200 Keypad 0-9,#,*
{
if (!keys_dampen) // First time pressed?
{
soundPlaySample(clickNoQuit_wav, SoundFormat_16Bit, clickNoQuit_wav_size, 22050, 127, 64, false, 0);
if (iTx > 0) iTx--;
key_code = padKey[iTx / 21] | key_code;
last_key_code = key_code;
keys_dampen = 15; // One-fourth of a second for consistent debounce
}
else
{
key_code = last_key_code;
keys_dampen--;
}
}
}
}
}
else
{
keys_touch = 0;
if (keys_dampen)
{
key_code = last_key_code;
keys_dampen--;
}
else
{
last_key_code = 0x00;
}
}
if ((myCart.control == CTRL_JOY) || (myCart.control == CTRL_SR))
{
if (keys_pressed & KEY_UP) stick0 = STICK_FORWARD;
if (keys_pressed & KEY_LEFT) stick0 = STICK_LEFT;
if (keys_pressed & KEY_RIGHT) stick0 = STICK_RIGHT;
if (keys_pressed & KEY_DOWN) stick0 = STICK_BACK;
if ((keys_pressed & KEY_UP) && (keys_pressed & KEY_LEFT)) stick0 = STICK_UL;
if ((keys_pressed & KEY_UP) && (keys_pressed & KEY_RIGHT)) stick0 = STICK_UR;
if ((keys_pressed & KEY_DOWN) && (keys_pressed & KEY_LEFT)) stick0 = STICK_LL;
if ((keys_pressed & KEY_DOWN) && (keys_pressed & KEY_RIGHT)) stick0 = STICK_LR;
}
else if (myCart.control == CTRL_SWAP)
{
trig1 = (keys_pressed & KEY_A) ? 0 : 1;
if (keys_pressed & KEY_UP) stick1 = STICK_FORWARD;
if (keys_pressed & KEY_LEFT) stick1 = STICK_LEFT;
if (keys_pressed & KEY_RIGHT) stick1 = STICK_RIGHT;
if (keys_pressed & KEY_DOWN) stick1 = STICK_BACK;
if ((keys_pressed & KEY_UP) && (keys_pressed & KEY_LEFT)) stick1 = STICK_UL;
if ((keys_pressed & KEY_UP) && (keys_pressed & KEY_RIGHT)) stick1 = STICK_UR;
if ((keys_pressed & KEY_DOWN) && (keys_pressed & KEY_LEFT)) stick1 = STICK_LL;
if ((keys_pressed & KEY_DOWN) && (keys_pressed & KEY_RIGHT)) stick1 = STICK_LR;
}
else if (myCart.control == CTRL_ROBO)
{
if (keys_pressed & KEY_UP) stick0 = STICK_FORWARD;
if (keys_pressed & KEY_LEFT) stick0 = STICK_LEFT;
if (keys_pressed & KEY_RIGHT) stick0 = STICK_RIGHT;
if (keys_pressed & KEY_DOWN) stick0 = STICK_BACK;
if ((keys_pressed & KEY_UP) && (keys_pressed & KEY_LEFT)) stick0 = STICK_UL;
if ((keys_pressed & KEY_UP) && (keys_pressed & KEY_RIGHT)) stick0 = STICK_UR;
if ((keys_pressed & KEY_DOWN) && (keys_pressed & KEY_LEFT)) stick0 = STICK_LL;
if ((keys_pressed & KEY_DOWN) && (keys_pressed & KEY_RIGHT)) stick0 = STICK_LR;
if (keys_pressed & KEY_X) stick1 = STICK_FORWARD;
if (keys_pressed & KEY_Y) stick1 = STICK_LEFT;
if (keys_pressed & KEY_A) stick1 = STICK_RIGHT;
if (keys_pressed & KEY_B) stick1 = STICK_BACK;
if ((keys_pressed & KEY_X) && (keys_pressed & KEY_Y)) stick1 = STICK_UL;
if ((keys_pressed & KEY_X) && (keys_pressed & KEY_A)) stick1 = STICK_UR;
if ((keys_pressed & KEY_B) && (keys_pressed & KEY_Y)) stick1 = STICK_LL;
if ((keys_pressed & KEY_B) && (keys_pressed & KEY_A)) stick1 = STICK_LR;
}
else if (myCart.control == CTRL_FROG)
{
trig0=0;
if (keys_pressed & KEY_UP) {stick0 = STICK_FORWARD; trig0=1;}
if (keys_pressed & KEY_LEFT) {stick0 = STICK_LEFT; trig0=1;}
if (keys_pressed & KEY_RIGHT) {stick0 = STICK_RIGHT;trig0=1;}
if (keys_pressed & KEY_DOWN) {stick0 = STICK_BACK; trig0=1;}
}
else if (myCart.control == CTRL_QBERT)
{
if (keys_pressed & KEY_UP) {stick0 = STICK_UR; }
if (keys_pressed & KEY_LEFT) {stick0 = STICK_UL;}
if (keys_pressed & KEY_RIGHT) {stick0 = STICK_LR;}
if (keys_pressed & KEY_DOWN) {stick0 = STICK_LL; }
trig0=0;
}
if (keys_pressed & KEY_START) key_code = AKEY_5200_START + key_code;
if (keys_pressed & KEY_SELECT) key_code = AKEY_5200_PAUSE + key_code;
if ((gTotalAtariFrames & 3) == 0) // Every fourth frame...
{
if ((keys_pressed & KEY_R) && (keys_pressed & KEY_UP)) myCart.offset_y++;
if ((keys_pressed & KEY_R) && (keys_pressed & KEY_DOWN)) myCart.offset_y--;
if ((keys_pressed & KEY_R) && (keys_pressed & KEY_LEFT)) myCart.offset_x++;
if ((keys_pressed & KEY_R) && (keys_pressed & KEY_RIGHT)) myCart.offset_x--;
if ((keys_pressed & KEY_L) && (keys_pressed & KEY_UP)) if (myCart.scale_y < 256) myCart.scale_y++;
if ((keys_pressed & KEY_L) && (keys_pressed & KEY_DOWN)) if (myCart.scale_y >= 192) myCart.scale_y--;
if ((keys_pressed & KEY_L) && (keys_pressed & KEY_RIGHT)) if (myCart.scale_x < 320) myCart.scale_x++;
if ((keys_pressed & KEY_L) && (keys_pressed & KEY_LEFT)) if (myCart.scale_x >= 192) myCart.scale_x--;
if ((keys_pressed & KEY_R) && (keys_pressed & KEY_L))
{
if (++lcd_swap_counter == 8)
{
if (keys_pressed & KEY_A) {lcdSwap();}
}
} else lcd_swap_counter = 0;
}
// Screen shift/slide
if (myCart.control != CTRL_ROBO)
{
if (keys_pressed & KEY_X)
{
if (myCart.x_function == X_PANUP)
{
screen_slide_y = 12; dampen_slide_y = 6;
}
else if (myCart.x_function == X_PANDN)
{
screen_slide_y = -12; dampen_slide_y = 6;
}
}
}
break;
}
}
}
void _putchar(char character) {}; // Not used but needed to link printf()