mirror of
https://github.com/wavemotion-dave/A7800DS.git
synced 2025-06-18 21:35:32 -04:00
191 lines
7.4 KiB
C
191 lines
7.4 KiB
C
// ----------------------------------------------------------------------------
|
|
// ___ ___ ___ ___ ___ ____ ___ _ _
|
|
// /__/ /__/ / / /__ /__/ /__ / /_ / |/ /
|
|
// / / \ /__/ ___/ ___/ ___/ / /__ / / emulator
|
|
//
|
|
// ----------------------------------------------------------------------------
|
|
// Copyright 2003, 2004 Greg Stanton
|
|
//
|
|
// This program is free software; you can redistribute it and/or modify
|
|
// it under the terms of the GNU General Public License as published by
|
|
// the Free Software Foundation; either version 2 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
// ----------------------------------------------------------------------------
|
|
// ProSystem.cpp
|
|
// ----------------------------------------------------------------------------
|
|
|
|
#include "ProSystem.h"
|
|
#include "Database.h"
|
|
|
|
extern u8 isDS_LITE;
|
|
extern u8 frameSkipMask;
|
|
|
|
uint prosystem_cycles __attribute__((section(".dtcm"))) = 0;
|
|
uint32 bg32 __attribute__((section(".dtcm"))) = 0;
|
|
uint bRenderFrame __attribute__((section(".dtcm"))) = 0;
|
|
|
|
|
|
#define CYCLES_BEFORE_DMA 28 // Number of cycles before DMA kicks in (really 7 CPU cycles)
|
|
#define CYCLES_PER_SCANLINE 454 // 454 Cycles per Scanline in an NTSC system (really 113.5 CPU cycles)
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Reset
|
|
// ----------------------------------------------------------------------------
|
|
void prosystem_Reset()
|
|
{
|
|
if(cartridge_IsLoaded())
|
|
{
|
|
sally_Reset();
|
|
region_Reset();
|
|
tia_Clear();
|
|
tia_Reset();
|
|
pokey_Clear();
|
|
pokey_Reset();
|
|
memory_Reset();
|
|
maria_Clear();
|
|
maria_Reset();
|
|
riot_Reset();
|
|
cartridge_LoadHighScoreCart();
|
|
|
|
cartridge_Store(); // Always call this - it may setup some RAM or other stuff below the BIOS region...
|
|
|
|
// Load 7800 BIOS if available... otherwise direct load the CART
|
|
if(bios_available && !bSkipBIOS)
|
|
{
|
|
bios_Store();
|
|
bios_show_counter = myCartInfo.biosTimeout;
|
|
}
|
|
|
|
prosystem_cycles = sally_ExecuteRES();
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// ExecuteFrame - this is hand-tuned for NTSC output with hard-coded
|
|
// NTSC frame values ... this will not work properly if a PAL ROM is used.
|
|
// ----------------------------------------------------------------------------
|
|
ITCM_CODE void prosystem_ExecuteFrame(const byte * input)
|
|
{
|
|
extern u16 gTotalAtariFrames;
|
|
extern word * framePtr;
|
|
extern uint maria_cycles;
|
|
|
|
gTotalAtariFrames++;
|
|
bRenderFrame = 0;
|
|
|
|
riot_SetInput(input);
|
|
|
|
// ---------------------------------------------------------------------
|
|
// Handle the VERTICAL BLANK area first... speeds up processing below...
|
|
// ---------------------------------------------------------------------
|
|
memory_ram[MSTAT] = 128; // Into the Vertical Blank...
|
|
|
|
// -------------------------------------------------------------------------------------------
|
|
// Note: this is not accurate. It should be 263 scanlines total but it doesn't work for all
|
|
// games at 263 so we've gone with 262 for maximum compatibility. This is likely due to some
|
|
// emulation cycle counting inaccuracies. At 263, some games run too fast (Asteroids, Deluxe)
|
|
// and some crash (Robotron) and some issues with Pole Position II and the joystick selection
|
|
// of a course to play. I've also seen graphical glitches in Crossbow when loaded via the
|
|
// BIOS and all kinds of graphical oddities in Xenophobe. Be very careful if you change this...
|
|
// be sure you understand the consequences (and this developer doesn't... so be warned!).
|
|
// -------------------------------------------------------------------------------------------
|
|
for(maria_scanline = 1; maria_scanline <= 21; maria_scanline++)
|
|
{
|
|
prosystem_cycles = 0;
|
|
|
|
if(maria_scanline == 21) // Maria can start to do her thing... We've had 20 VBLANK scanlines
|
|
{
|
|
memory_ram[MSTAT] = 0; // Out of the vertical blank
|
|
framePtr = (word * )(maria_surface);
|
|
sally_Execute(CYCLES_BEFORE_DMA);
|
|
|
|
maria_RenderScanlineTOP();
|
|
|
|
// Cycle Stealing happens here...
|
|
prosystem_cycles += ((maria_cycles + 3) >> 2) << 2; // Always a multiple of 4
|
|
if(riot_and_wsync & 2) riot_UpdateTimer(maria_cycles >> 2);
|
|
}
|
|
else
|
|
{
|
|
sally_Execute(CYCLES_BEFORE_DMA);
|
|
}
|
|
|
|
sally_Execute(CYCLES_PER_SCANLINE);
|
|
|
|
if(myCartInfo.pokeyType) // If pokey enabled, we process 1 pokey sample and 1 TIA sample. Good enough.
|
|
{
|
|
pokey_Process();
|
|
pokey_Scanline();
|
|
}
|
|
else tia_Process(); // If all we have to deal with is the TIA, we can do so at 31KHz
|
|
}
|
|
|
|
// ------------------------------------------------------------
|
|
// Now handle the Main display area...
|
|
// ------------------------------------------------------------
|
|
for(; maria_scanline < 263; maria_scanline++)
|
|
{
|
|
prosystem_cycles = 0;
|
|
|
|
if(maria_scanline >= 30)
|
|
{
|
|
// --------------------------------------------------------------------------
|
|
// We can start to render the scanlines if we are not skipping this frame.
|
|
// The DS/DSi only has 192 vertical pixels and we can perform some hardware
|
|
// scaling but there is a point at which we really can't show any more lines.
|
|
// To that end, we'll render ~223 lines which is good enough for most games.
|
|
// If a game uses more overscan area - those scanlines won't show on screen.
|
|
// ---------------------------------------------------------------------------
|
|
if(maria_scanline >= 253)
|
|
{
|
|
bRenderFrame = 0; // We can stop rendering frames... DS can't show it anyway with limited vertical resolution.
|
|
}
|
|
else
|
|
{
|
|
bRenderFrame = gTotalAtariFrames & frameSkipMask;
|
|
}
|
|
}
|
|
|
|
sally_Execute(CYCLES_BEFORE_DMA);
|
|
|
|
maria_RenderScanline();
|
|
|
|
// Cycle Stealing happens here...
|
|
prosystem_cycles += ((maria_cycles + 3) >> 2) << 2; // Always a multiple of 4
|
|
if(riot_and_wsync & 2) riot_UpdateTimer(maria_cycles >> 2);
|
|
|
|
sally_Execute(CYCLES_PER_SCANLINE);
|
|
|
|
if(myCartInfo.pokeyType) // If pokey enabled, we process 1 pokey sample and 1 TIA sample. Good enough.
|
|
{
|
|
pokey_Process();
|
|
pokey_Scanline();
|
|
}
|
|
else tia_Process(); // If all we have to deal with is the TIA, we can do so at 31KHz
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------------------
|
|
// Close
|
|
// ----------------------------------------------------------------------------
|
|
void prosystem_Close()
|
|
{
|
|
cartridge_Release();
|
|
maria_Reset();
|
|
maria_Clear();
|
|
memory_Reset();
|
|
tia_Reset();
|
|
tia_Clear();
|
|
}
|