cog/Frameworks/libsidplay/sidplay-residfp-code/.svn/pristine/8f/8f47fa38ff47541d8695bd88fad...

322 lines
6.3 KiB
Plaintext

/*
* This file is part of libsidplayfp, a SID player engine.
*
* Copyright 2011-2014 Leandro Nini <drfiemost@users.sourceforge.net>
* Copyright 2007-2010 Antti Lankila
* Copyright 2000 Simon White
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#ifndef C64_H
#define C64_H
#include <stdint.h>
#include <cstdio>
#include <map>
#include "Banks/IOBank.h"
#include "Banks/ColorRAMBank.h"
#include "Banks/DisconnectedBusBank.h"
#include "Banks/SidBank.h"
#include "Banks/ExtraSidBank.h"
#include "EventScheduler.h"
#include "c64/c64env.h"
#include "c64/c64cpu.h"
#include "c64/c64cia.h"
#include "c64/c64vic.h"
#include "c64/mmu.h"
#include "sidcxx11.h"
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
class sidmemory;
namespace libsidplayfp
{
class c64sid;
#ifdef PC64_TESTSUITE
class testEnv
{
public:
virtual ~testEnv() {}
virtual void load(const char *) =0;
};
#endif
/**
* Commodore 64 emulation core.
*
* It consists of the following chips:
* - CPU 6510
* - VIC-II 6567/6569/6572
* - CIA 6526
* - SID 6581/8580
* - PLA 7700/82S100
* - Color RAM 2114
* - System RAM 4164-20/50464-150
* - Character ROM 2332
* - Basic ROM 2364
* - Kernal ROM 2364
*/
class c64: private c64env
{
public:
typedef enum
{
PAL_B = 0 ///< PAL C64
,NTSC_M ///< NTSC C64
,OLD_NTSC_M ///< Old NTSC C64
,PAL_N ///< C64 Drean
} model_t;
private:
typedef std::map<int, ExtraSidBank*> sidBankMap_t;
private:
/// System clock frequency
double m_cpuFreq;
/// Number of sources asserting IRQ
int irqCount;
/// BA state
bool oldBAState;
/// System event context
EventScheduler m_scheduler;
/// CPU
c64cpu cpu;
/// CIA1
c64cia1 cia1;
/// CIA2
c64cia2 cia2;
/// VIC
c64vic vic;
/// Color RAM
ColorRAMBank colorRAMBank;
/// SID
SidBank sidBank;
/// Extra SIDs
sidBankMap_t extraSidBanks;
/// I/O Area #1 and #2
DisconnectedBusBank disconnectedBusBank;
/// I/O Area
IOBank ioBank;
/// MMU chip
MMU mmu;
private:
static double getCpuFreq(model_t model);
private:
/**
* Access memory as seen by CPU.
*
* @param addr the address where to read from
* @return value at address
*/
uint8_t cpuRead(uint_least16_t addr) override { return mmu.cpuRead(addr); }
/**
* Access memory as seen by CPU.
*
* @param addr the address where to write to
* @param data the value to write
*/
void cpuWrite(uint_least16_t addr, uint8_t data) override { mmu.cpuWrite(addr, data); }
/**
* IRQ trigger signal.
*
* Calls permitted any time, but normally originated by chips at PHI1.
*
* @param state
*/
inline void interruptIRQ(bool state) override;
/**
* NMI trigger signal.
*
* Calls permitted any time, but normally originated by chips at PHI1.
*/
inline void interruptNMI() override { cpu.triggerNMI(); }
/**
* Reset signal.
*/
inline void interruptRST() override { cpu.triggerRST(); }
/**
* BA signal.
*
* Calls permitted during PHI1.
*
* @param state
*/
inline void setBA(bool state) override;
inline void lightpen(bool state) override;
#ifdef PC64_TESTSUITE
testEnv *m_env;
void loadFile(const char *file) override
{
m_env->load(file);
}
#endif
void resetIoBank();
public:
c64();
~c64() {}
#ifdef PC64_TESTSUITE
void setTestEnv(testEnv *env)
{
m_env = env;
}
#endif
/**
* Get C64's event scheduler
*
* @return the scheduler
*/
//@{
EventScheduler *getEventScheduler() { return &m_scheduler; }
const EventScheduler &getEventScheduler() const { return m_scheduler; }
//@}
void debug(bool enable, FILE *out) { cpu.debug(enable, out); }
void reset();
void resetCpu() { cpu.reset(); }
/**
* Set the c64 model.
*/
void setModel(model_t model);
void setRoms(const uint8_t* kernal, const uint8_t* basic, const uint8_t* character)
{
mmu.setRoms(kernal, basic, character);
}
/**
* Get the CPU clock speed.
*
* @return the speed in Hertz
*/
double getMainCpuSpeed() const { return m_cpuFreq; }
/**
* Set the base SID.
*
* @param s the sid emu to set
*/
void setBaseSid(c64sid *s);
/**
* Add an extra SID.
*
* @param s the sid emu to set
* @param sidAddress
* base address (e.g. 0xd420)
*
* @return false if address is unsupported
*/
bool addExtraSid(c64sid *s, int address);
/**
* Remove all the SIDs.
*/
void clearSids();
/**
* Get the components credits
*/
//@{
const char* cpuCredits() const { return cpu.credits(); }
const char* ciaCredits() const { return cia1.credits(); }
const char* vicCredits() const { return vic.credits(); }
//@}
sidmemory *getMemInterface() { return &mmu; }
uint_least16_t getCia1TimerA() const { return cia1.getTimerA(); }
};
void c64::interruptIRQ(bool state)
{
if (state)
{
if (irqCount == 0)
cpu.triggerIRQ();
irqCount ++;
}
else
{
irqCount --;
if (irqCount == 0)
cpu.clearIRQ();
}
}
void c64::setBA(bool state)
{
// only react to changes in state
if (state == oldBAState)
return;
oldBAState = state;
// Signal changes in BA to interested parties
cpu.setRDY(state);
}
void c64::lightpen(bool state)
{
if (state)
vic.triggerLightpen();
else
vic.clearLightpen();
}
}
#endif // C64_H