2015-11-27 10:02:41 +00:00
|
|
|
// MSX computer KSS music file emulator
|
|
|
|
|
|
|
|
// Game_Music_Emu $vers
|
|
|
|
#ifndef KSS_CORE_H
|
|
|
|
#define KSS_CORE_H
|
|
|
|
|
|
|
|
#include "Gme_Loader.h"
|
|
|
|
#include "Rom_Data.h"
|
|
|
|
#include "Z80_Cpu.h"
|
|
|
|
|
|
|
|
class Kss_Core : public Gme_Loader {
|
|
|
|
public:
|
|
|
|
// KSS file header
|
|
|
|
struct header_t
|
|
|
|
{
|
|
|
|
enum { size = 0x20 };
|
|
|
|
enum { base_size = 0x10 };
|
|
|
|
enum { ext_size = size - base_size };
|
|
|
|
|
|
|
|
byte tag [4];
|
|
|
|
byte load_addr [2];
|
|
|
|
byte load_size [2];
|
|
|
|
byte init_addr [2];
|
|
|
|
byte play_addr [2];
|
|
|
|
byte first_bank;
|
|
|
|
byte bank_mode;
|
|
|
|
byte extra_header;
|
|
|
|
byte device_flags;
|
|
|
|
|
|
|
|
// KSSX extended data, if extra_header==0x10
|
|
|
|
byte data_size [4];
|
|
|
|
byte unused [4];
|
|
|
|
byte first_track [2];
|
|
|
|
byte last_track [2]; // if no extended data, we set this to 0xFF
|
|
|
|
byte psg_vol;
|
|
|
|
byte scc_vol;
|
|
|
|
byte msx_music_vol;
|
|
|
|
byte msx_audio_vol;
|
|
|
|
};
|
|
|
|
|
|
|
|
// Header for currently loaded file
|
|
|
|
header_t const& header() const { return header_; }
|
|
|
|
|
|
|
|
// ROM data
|
|
|
|
Rom_Data const& rom_() const { return rom; }
|
|
|
|
|
|
|
|
typedef int time_t;
|
|
|
|
void set_play_period( time_t p ) { play_period = p; }
|
|
|
|
|
|
|
|
blargg_err_t start_track( int );
|
|
|
|
|
|
|
|
blargg_err_t end_frame( time_t );
|
|
|
|
|
|
|
|
protected:
|
|
|
|
typedef Z80_Cpu Kss_Cpu;
|
|
|
|
Kss_Cpu cpu;
|
|
|
|
|
|
|
|
void set_bank( int logical, int physical );
|
|
|
|
|
|
|
|
typedef int addr_t;
|
|
|
|
virtual void cpu_write( addr_t, int ) = 0;
|
|
|
|
virtual int cpu_in( time_t, addr_t );
|
|
|
|
virtual void cpu_out( time_t, addr_t, int );
|
|
|
|
|
|
|
|
// Called after one frame of emulation
|
|
|
|
virtual void update_gain() = 0;
|
|
|
|
|
|
|
|
// Implementation
|
|
|
|
public:
|
|
|
|
Kss_Core();
|
|
|
|
virtual ~Kss_Core();
|
|
|
|
|
|
|
|
protected:
|
|
|
|
virtual blargg_err_t load_( Data_Reader& );
|
|
|
|
virtual void unload();
|
|
|
|
|
|
|
|
private:
|
|
|
|
enum { idle_addr = 0xFFFF };
|
|
|
|
|
|
|
|
Rom_Data rom;
|
|
|
|
header_t header_;
|
|
|
|
bool gain_updated;
|
|
|
|
int bank_count;
|
|
|
|
time_t play_period;
|
|
|
|
time_t next_play;
|
|
|
|
|
|
|
|
// large items
|
|
|
|
enum { mem_size = 0x10000 };
|
|
|
|
byte ram [mem_size + Kss_Cpu::cpu_padding];
|
|
|
|
byte unmapped_read [0x100]; // TODO: why isn't this page_size?
|
|
|
|
// because CPU can't read beyond this in last page? or because it will spill into unmapped_write?
|
|
|
|
|
|
|
|
byte unmapped_write [Kss_Cpu::page_size];
|
|
|
|
|
|
|
|
int bank_size() const { return (16 * 1024) >> (header_.bank_mode >> 7 & 1); }
|
|
|
|
bool run_cpu( time_t end );
|
|
|
|
void jsr( byte const (&addr) [2] );
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|