raldus/roland

View on GitHub
src/cpc/memman.cpp

Summary

Maintainability
Test Coverage
/***************************************************************************
 *   Copyright (C) by Fred Klaus                                           *
 *       development@fkweb.de                                              *
 *                                                                         *
 *   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.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/
#include "memman.h"

#include <memory>
#include <fstream>
#include <iostream>

using std::ifstream;
using std::string;

namespace cpcx
{

    MemMan::MemMan(Z80 *z80, GateArray *gatearray, const string &cpcrom,
                   const string &amsdos)
    {
        mGateArray = gatearray;
        mZ80 = z80;

        mRam = 0;
        mRamSize = 0;
        mLowerRom = mCpcRom;
        mUpperRom = mCpcRom + 0x4000;

        for (int i = 0; i < 256; i++)
            mRom[i] = 0;

        init();
    }

    int MemMan::init(Z80 *z80, GateArray *gatearray)
    {
        mGateArray = gatearray;
        mZ80 = z80;
        return init();
    }

    int MemMan::init(tUWORD ramsize, const string & cpcrom, const string & amsdos)
    {
        int ret = 0;
        mRamSize = ramsize;
        if ((ramsize < 64) && (ramsize > 572))
            return ErrRamSize; // @todo (type6128 < 128kb) ram error.
        if (ramsize % 64)
            return ErrRamSize;

        if (mRam)
            delete[] mRam;
        mRam = new tUBYTE[mRamSize * 1024];
        if (!mRam)
            return ErrMemory;
        memset(mRam, 0, mRamSize * 1024);

        for (int i = 0; i < 256; i++)
        {
            if (mRom[i])
                delete[] mRom[i];
            mRom[i] = 0;
        }

        if (!openCpcRom(cpcrom))
            ret |= ErrCpcRom;
        if (!openRom(7, amsdos))
            ret |= ErrAmsdos;
        if (ret)
            return ret;

        initBanking();

        // toggleRam();
        return ret;
    }

    bool MemMan::openRom(int idx, const string &filename)
    {
        if (filename.empty())
            return false;
#ifdef _WIN32
        ifstream in(filename.c_str(), std::ios::binary); // @todo size checking !
#else
        ifstream in(filename.c_str());
#endif
        if (!in)
        {
            std::cout << "*** Rom not found ***\n";
            return false;
        }
        if (mRom[idx])
        {
            delete[] mRom[idx];
            mRom[idx] = 0;
        }
        mRom[idx] = new tUBYTE[16384]; // @todo all new statements should be checked
                                      // for enough mem!!
        in.read((char *)mRom[idx], 16384);
        in.close();
        return true;
    }

    bool MemMan::openCpcRom(const string &filename)
    {
        if (filename.empty())
            return false;
#ifdef _WIN32
        ifstream in(filename.c_str(), std::ios::binary); // @todo size checking !
#else
        ifstream in(filename.c_str());
#endif
        if (!in)
        {
            std::cout << "*** CPC-Rom not found ***\n";
            return false;
        }
        memset(mCpcRom, 0, 2 * 16384);
        in.read((char *)mCpcRom, 2 * 16384);
        in.close();
        return true;
    }

    inline void MemMan::initBanking()
    {
        tUBYTE *rom0, *rom1, *rom2, *rom3, *rom4, *rom5, *rom6, *rom7;
        tUBYTE *rambank;

        rom0 = mRam;
        rom1 = mRam + 1 * 16384;
        rom2 = mRam + 2 * 16384;
        rom3 = mRam + 3 * 16384;

        std::cout << "initBanking-ramBank: " << (int)mGateArray->ramBank() << "\n";

        rambank = mRam + ((mGateArray->ramBank() + 1) * (4 * 16384)); // 64 KB
        rom4 = rambank;
        rom5 = rambank + 1 * 16384;
        rom6 = rambank + 2 * 16384;
        rom7 = rambank + 3 * 16384;

        mMemBankConfig[0][0] = rom0;
        mMemBankConfig[0][1] = rom1;
        mMemBankConfig[0][2] = rom2;
        mMemBankConfig[0][3] = rom3;

        mMemBankConfig[1][0] = rom0;
        mMemBankConfig[1][1] = rom1;
        mMemBankConfig[1][2] = rom2;
        mMemBankConfig[1][3] = rom7;

        mMemBankConfig[2][0] = rom4;
        mMemBankConfig[2][1] = rom5;
        mMemBankConfig[2][2] = rom6;
        mMemBankConfig[2][3] = rom7;

        mMemBankConfig[3][0] = rom0;
        mMemBankConfig[3][1] = rom3;
        mMemBankConfig[3][2] = rom2;
        mMemBankConfig[3][3] = rom7;

        mMemBankConfig[4][0] = rom0;
        mMemBankConfig[4][1] = rom4;
        mMemBankConfig[4][2] = rom2;
        mMemBankConfig[4][3] = rom3;

        mMemBankConfig[5][0] = rom0;
        mMemBankConfig[5][1] = rom5;
        mMemBankConfig[5][2] = rom2;
        mMemBankConfig[5][3] = rom3;

        mMemBankConfig[6][0] = rom0;
        mMemBankConfig[6][1] = rom6;
        mMemBankConfig[6][2] = rom2;
        mMemBankConfig[6][3] = rom3;

        mMemBankConfig[7][0] = rom0;
        mMemBankConfig[7][1] = rom7;
        mMemBankConfig[7][2] = rom2;
        mMemBankConfig[7][3] = rom3;
    }

    void MemMan::memoryManager()
    {
        tUBYTE membank;
        if (mRamSize == 64) // 64KB of RAM?
        {
            membank = 0;                 // no expansion memory
            mGateArray->setRamConfig(0); // the only valid configuration is 0
        }
        else
        {
            membank =
                (mGateArray->ramConfig() >> 3) & 7; // extract expansion memory bank
            if (((membank + 1) * 64) >
                mRamSize) // @todo selection is beyond available memory? ### +2 ###
            {
                membank = 0; // force default mapping
            }
        }
        if (membank !=
            mGateArray
                ->ramBank()) // requested bank is different from the active one?
        {
            mGateArray->setRamBank(membank);
            initBanking();
        }

        mZ80->setMembank_read(0, mMemBankConfig[mGateArray->ramConfig() & 7][0]);
        mZ80->setMembank_read(1, mMemBankConfig[mGateArray->ramConfig() & 7][1]);
        mZ80->setMembank_read(2, mMemBankConfig[mGateArray->ramConfig() & 7][2]);
        mZ80->setMembank_read(3, mMemBankConfig[mGateArray->ramConfig() & 7][3]);

        mZ80->setMembank_write(0, mMemBankConfig[mGateArray->ramConfig() & 7][0]);
        mZ80->setMembank_write(1, mMemBankConfig[mGateArray->ramConfig() & 7][1]);
        mZ80->setMembank_write(2, mMemBankConfig[mGateArray->ramConfig() & 7][2]);
        mZ80->setMembank_write(3, mMemBankConfig[mGateArray->ramConfig() & 7][3]);

        toggleUpperRom();
        toggleLowerRom();
    }

} // cpc


    /*
    inline void MemMan::toggleUpperRom()
    {

        if (!(mGateArray->romConfig() & 0x08))
        {
            if (mGateArray->upperRom() == 0)
            {
                mZ80->setMembank_read(3, mUpperRom);
                return;
            }
            if (mRom[mGateArray->upperRom()] != 0)
            {
                mZ80->setMembank_read(3, mRom[mGateArray->upperRom()]);
            }
            else
            {
                mZ80->setMembank_read(3, mUpperRom); // revert to Basic
            }
        }
    //  else
    //  {
    //      mZ80->setMembank_read(3, mMemBankConfig[mGateArray->ramConfig() & 7]
    [3]);
    //  }
    }

    inline void MemMan::toggleLowerRom()
    {
        if (!(mGateArray->romConfig() & 0x04))
        {
            mZ80->setMembank_read(0, mLowerRom);
        }
    //  else
    //  {
    //      mZ80->setMembank_read(0, mMemBankConfig[mGateArray->ramConfig() & 7]
    [0]);
    //  }
    }
    */