Z80Emulator : サンプル1ソース

◎Z80Sample1.cpp

////////////////////////////////////////////////////////////
// Z80 Emulator Class Library Sample 1
//
// Written by Manuke

////////////////////////////////////////////////////////////
// include

#include "StdHeader.h"

#include "Z80.h"

////////////////////////////////////////////////////////////
// OS dependence console input/output library

#ifdef _MSC_VER // Win32 platform & Visual C++

#include <conio.h>

void InitConsole() {
}

void CloseConsole() {
}

#elif defined(__BORLANDC__) // Win32 platform & Borland C++

#include <conio.h>

#define _kbhit  kbhit
#define _getch  getch
#define _putch  putch

void InitConsole() {
}

void CloseConsole() {
}

#else // GNU/Linux platform & g++

#include <termios.h>

static struct termios g_tiosOrg, g_tiosNew;
static int g_chPeek = -1;

void InitConsole() {
    tcgetattr(0, &g_tiosOrg);
    g_tiosNew = g_tiosOrg;
    g_tiosNew.c_lflag &= ~(ICANON | ECHO | ISIG);
    g_tiosNew.c_cc[VMIN] = 1;
    g_tiosNew.c_cc[VTIME] = 0;
    tcsetattr(0, TCSANOW, &g_tiosNew);
}

void CloseConsole() {
    tcsetattr(0, TCSANOW, &g_tiosOrg);
}

int _kbhit() {
    char ch;
    int nRead;
    if (g_chPeek != -1) {
        return 1;
    }
    g_tiosNew.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &g_tiosNew);
    nRead = read(0, &ch, 1);
    g_tiosNew.c_cc[VMIN] = 1;
    tcsetattr(0, TCSANOW, &g_tiosNew);
    if (nRead == 1) {
        g_chPeek = ch;
        return 1;
    }
    return 0;
}

int _getch() {
    char ch;
    if (g_chPeek != -1) {
        ch = (char)g_chPeek;
        g_chPeek = -1;
    } else {
        if (read(0, &ch, 1) != 1)  {
            // ignore
        }
    }
    if (ch == "\n") {
        ch = "\r";
    }
    return ch;
}

int _putch(int a) {
    int nResult = putchar(a);
    fflush(stdout);
    return nResult;
}

#endif // Platform

////////////////////////////////////////////////////////////
// CZ80Sample1

#ifdef Z80CFG_NOUSE_TEMPLATE

////////////////////////////////////////////////////////////
// exsample of imprement in non-template mode

class CZ80Sample1 : public CZ80 {
// attribute
protected:
    bool m_bExit;
    uint8_t m_abtRom[1024];

public:
    bool IsExit() {
        return m_bExit;
    }

// construct/destruct
public:
    CZ80Sample1() {
    }
    virtual ~CZ80Sample1() {
    }

// initialize
public:
    virtual void Initialize() {
        CZ80::Initialize();
        m_bExit = false;
        memset(m_abtRom, 0x00, sizeof(m_abtRom));
        static const uint8_t abtProgram[] = {
            0xDB, 0x00, //  00000H  IN      A, (000H)
            0xA7,       //  00002H  AND     A
            0x28, 0xFB, //  00003H  JR      Z, 00000H
            0xFE, 0x1B, //  00005H  CP      01BH
            0x28, 0x0C, //  00007H  JR      Z, 00015H
            0xD3, 0x01, //  00009H  OUT     (001H), A
            0xFE, 0x0D, //  0000BH  CP      00DH
            0x20, 0xF1, //  0000DH  JR      NZ, 00000H
            0x3E, 0x0A, //  0000FH  LD      A, 00AH
            0xD3, 0x01, //  00011H  OUT     (001H), A
            0x18, 0xEB, //  00013H  JR      00000H
            0xD3, 0x02, //  00015H  OUT     (002H), A
            0x76        //  00017H  HALT
        };
        memcpy(m_abtRom, abtProgram, sizeof(abtProgram));
    }
    virtual void Reset() {
        CZ80::Reset();
    }

// memory operation
protected:
    virtual uint8_t ReadMemory(int nAddress) {
        uint8_t btResult = 0xFF;
        if (nAddress < 1024) {
            btResult = m_abtRom[nAddress];
        }
        return btResult;
    }
    virtual void WriteMemory(int /*nAddress*/, uint8_t /*btData*/) {
    }
    virtual uint8_t ReadMemoryM1(int nAddress) {
        return ReadMemory(nAddress);
    }
    virtual uint8_t ReadIO(int nAddress) {
        uint8_t btResult = 0xFF;
        if (nAddress == 0x00) {
            btResult = 0x00;
            if (_kbhit()) {
                btResult = (uint8_t)_getch();
            }
        }
        return btResult;
    }
    virtual void WriteIO(int nAddress, uint8_t btData) {
        if (nAddress == 0x01) {
            _putch((char)btData);
        } else if (nAddress == 0x02) {
            m_bExit = true;
        }
    }
};

#else // Z80CFG_USE_TEMPLATE

////////////////////////////////////////////////////////////
// exsample of imprement in template mode

class CZ80Sample1 : public CZ80_1 {
// attribute
protected:
    static bool m_bExit;
    static uint8_t m_abtRom[1024];

public:
    static bool IsExit() {
        return m_bExit;
    }

// construct/destruct
public:
    CZ80Sample1() {
    }
    virtual ~CZ80Sample1() {
    }

// initialize
public:
    virtual void Initialize() {
        CZ80_1::Initialize();
        m_bExit = false;
        memset(m_abtRom, 0x00, sizeof(m_abtRom));
        static const uint8_t abtProgram[] = {
            0xDB, 0x00, //  00000H  IN      A, (000H)
            0xA7,       //  00002H  AND     A
            0x28, 0xFB, //  00003H  JR      Z, 00000H
            0xFE, 0x1B, //  00005H  CP      01BH
            0x28, 0x0C, //  00007H  JR      Z, 00015H
            0xD3, 0x01, //  00009H  OUT     (001H), A
            0xFE, 0x0D, //  0000BH  CP      00DH
            0x20, 0xF1, //  0000DH  JR      NZ, 00000H
            0x3E, 0x0A, //  0000FH  LD      A, 00AH
            0xD3, 0x01, //  00011H  OUT     (001H), A
            0x18, 0xEB, //  00013H  JR      00000H
            0xD3, 0x02, //  00015H  OUT     (002H), A
            0x76        //  00017H  HALT
        };
        memcpy(m_abtRom, abtProgram, sizeof(abtProgram));
    }
    virtual void Reset() {
        CZ80_1::Reset();
        // initialize of memory access procedure
        int i;
        for (i = 0; i < 64; i++) {
            SetReadMemoryProc(i, ReadNONE);
            SetReadMemoryM1Proc(i, ReadNONE);
            SetWriteMemoryProc(i, WriteNONE);
        }
        SetReadMemoryProc(0, ReadMemoryRom);
        SetReadMemoryM1Proc(0, ReadMemoryRom);
        // initialize of I/O access procedure
        for (i = 0; i < 256; i++) {
            SetReadIOProc(i, ReadNONE);
            SetWriteIOProc(i, WriteNONE);
        }
        SetReadIOProc(0x00, ReadIO_00);
        SetWriteIOProc(0x01, WriteIO_01);
        SetWriteIOProc(0x02, WriteIO_02);
    }

// memory operation
protected:
    static uint8_t ReadNONE(int /*nAddress*/) {
        return 0xFF;
    }
    static void WriteNONE(int /*nAddress*/, uint8_t /*btData*/) {
    }
    static uint8_t ReadMemoryRom(int nAddress) {
        return m_abtRom[nAddress];
    }
    static uint8_t ReadIO_00(int /*nAddress*/) {
        uint8_t btResult = 0x00;
        if (_kbhit()) {
            btResult = (uint8_t)_getch();
        }
        return btResult;
    }
    static void WriteIO_01(int /*nAddress*/, uint8_t btData) {
        _putch((char)btData);
    }
    static void WriteIO_02(int /*nAddress*/, uint8_t /*btData*/) {
        m_bExit = true;
    }
};

bool CZ80Sample1::m_bExit;
uint8_t CZ80Sample1::m_abtRom[1024];

#endif // Z80CFG_USE/NOUSE_TEMPLATE

////////////////////////////////////////////////////////////
// main

int main(void) {
    InitConsole();
    CZ80Sample1 z80;
    z80.Initialize();
    z80.Reset();
    do {
        z80.ExecuteOneOpCode();
    } while (!z80.IsExit());
    CloseConsole();
    return 0;
}