Top secrets sources NedoPC pentevo

Rev

Blame | Last modification | View Log | Download | RSS feed | ?url?

// From https://github.com/tslabs/zx-evo/blob/master/pentevo/unreal/Unreal/sound/dev_moonsound.cpp

#include "../std.h"
#include "../emul.h"
#include "../vars.h"
#include "../util.h"
#include "dev_moonsound.h"

#include "ymf262.h"
#include "ymf278.h"

#define MASTER_CLOCK 33868800

struct ZXMMoonSound_priv
{
friend class ZXMMoonSound;

public:
        ZXMMoonSound_priv();
        ~ZXMMoonSound_priv();

private:
        YMF262 *ymf262;
        int opl3latch;

        YMF278 *ymf278;
        int opl4latch;
};

inline EmuTime SystemTime()
{
        return cpu.t + comp.frame_counter * conf.frame;
}

ZXMMoonSound_priv::ZXMMoonSound_priv()
{
        EmuTime systemTime = 0;

        ymf262 = new YMF262(0, systemTime);
        ymf262->setSampleRate(44100, 1);
        ymf262->setVolume(32767 * 2 / 10);

        ymf278 = new YMF278(0, 4096, 2048*1024, systemTime);
        ymf278->setSampleRate(44100, 1);
        ymf278->setVolume(32767 * 2 / 10);
}

ZXMMoonSound_priv::~ZXMMoonSound_priv()
{
        delete ymf262;
        delete ymf278;
}

/*  */
ZXMMoonSound::ZXMMoonSound() :
        system_clock_rate( 0 )
{
        d = new ZXMMoonSound_priv();
        reset();
}

int ZXMMoonSound::load_rom(char *path)
{
        FILE *fp = fopen( path, "rb" );
        if ( !fp )
        {
                return -1;
        }

        fread( d->ymf278->getRom(), 1, d->ymf278->getRomSize(), fp );

        fclose( fp );

        return 0;
}

void ZXMMoonSound::reset()
{
        unsigned tStatesPerSecond = conf.frame * conf.intfq;
        EmuTime systemTime = SystemTime();

        d->ymf262->reset( systemTime, tStatesPerSecond );
        d->ymf278->reset( systemTime );
}

bool ZXMMoonSound::write( u8 port, u8 val )
{
        //printf("ZXM-MoonSound write(%.2x, %.2x)\n", port, val);

        EmuTime systemTime = SystemTime();

        if ( (port & 0xFE) == 0xC2 )
        {
                switch (port & 0x01) {
                case 0: // select register
                        d->opl4latch = val;
                        break;
                case 1:
                        d->ymf278->writeRegOPL4(d->opl4latch, val, systemTime);
                        break;
                }

                return true;
        }
        else if ( (port & 0xFC) == 0xC4 )
        {
                switch (port & 0x03) {
                case 0:
                        d->opl3latch = val;
                        break;
                case 2: // select register bank 1
                        d->opl3latch = val | 0x100;
                        break;
                case 1:
                case 3: // write fm register
                        d->ymf262->writeReg(d->opl3latch, val, systemTime);
                        break;
                }

                return true;
        }

        return false;
}

bool ZXMMoonSound::read( u8 port, u8 &val )
{
        //printf("ZXM-MoonSound read(%.2x)\n", port);

        EmuTime systemTime = SystemTime();

        if ( (port & 0xFE) == 0xC2 )
        {
                switch (port & 0x01) {
                case 1: // read wave register
                        val = d->ymf278->readRegOPL4(d->opl4latch, systemTime);
                        break;
                }

                return true;
        }
        else if( (port & 0xFC) == 0xC4 )
        {
                switch (port & 0x03) {
                case 0: // read status
                case 2:
                        val = d->ymf262->readStatus(systemTime) | d->ymf278->readStatus(systemTime);
                        break;
                case 1:
                case 3: // read fm register
                        val = d->ymf262->readReg(d->opl3latch);
                        break;
                }

                return true;
        }

        return false;
}


void ZXMMoonSound::set_timings(unsigned system_clock_rate, unsigned chip_clock_rate, unsigned sample_rate)
{
        d->ymf262->setSampleRate( sample_rate, 1 );
        d->ymf262->setVolume((u16)(1 * (conf.sound.moonsound_vol / 8192.0))); // doesn't work
        d->ymf278->setSampleRate( sample_rate, 1 );
        d->ymf278->setVolume((u16)(2000 * (conf.sound.moonsound_vol / 8192.0)));
       
        chip_clock_rate = sample_rate;

        ZXMMoonSound::system_clock_rate = system_clock_rate;
        ZXMMoonSound::chip_clock_rate = chip_clock_rate;

        SNDRENDER::set_timings(chip_clock_rate, sample_rate);
        passed_chip_ticks = passed_clk_ticks = 0;
        t = 0;
}

void ZXMMoonSound::start_frame(bufptr_t dst)
{
    SNDRENDER::start_frame(dst);
}

unsigned ZXMMoonSound::end_frame(unsigned clk_ticks)
{
        u64 end_chip_tick = ((passed_clk_ticks + clk_ticks) * chip_clock_rate) / system_clock_rate;

        flush((unsigned)(end_chip_tick - passed_chip_ticks));

    unsigned Val = SNDRENDER::end_frame(t);
        passed_clk_ticks += clk_ticks;
    passed_chip_ticks += t;
    t = 0;

    return Val;
}

void ZXMMoonSound::flush(unsigned chiptick)
{
        while (t < chiptick)
    {
                int buffer[2] = { 0, 0 };
                int *buf;

                t++;

                buf = d->ymf262->updateBuffer(1);
                if ( buf )
                {
                        buffer[0] += buf[0] / 10;
                        buffer[1] += buf[1] / 10;
                }

                buf = d->ymf278->updateBuffer(1);
                if ( buf )
                {
                        buffer[0] += buf[0];
                        buffer[1] += buf[1];
                }
               
                SNDRENDER::update( t, buffer[0], buffer[1] );
        }
}

ZXMMoonSound zxmmoonsound;