OpenCores
URL https://opencores.org/ocsvn/s80186/s80186/trunk

Subversion Repositories s80186

[/] [s80186/] [trunk/] [sim/] [CGA.h] - Rev 2

Compare with Previous | Blame | View Log

// Copyright Jamie Iles, 2017
//
// This file is part of s80x86.
//
// s80x86 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 3 of the License, or
// (at your option) any later version.
//
// s80x86 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 s80x86.  If not, see <http://www.gnu.org/licenses/>.
 
#pragma once
 
#include <boost/serialization/list.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/version.hpp>
 
#include "CPU.h"
#include "Cursor.h"
#include "Display.h"
 
class CGA : public IOPorts
{
private:
    enum CRTCRegs {
        CURSOR_SCAN_START = 0xa,
        CURSOR_SCAN_END = 0xb,
        CURSOR_HIGH = 0xe,
        CURSOR_LOW = 0xf,
    };
 
public:
    const phys_addr buffer_phys = 0xb8000;
 
    explicit CGA(Memory *mem)
        : IOPorts(0x03d4, 8), mem(mem), reg_idx(0), status(0)
    {
        memset(idx_regs, 0, sizeof(idx_regs));
    }
 
    void write8(uint16_t __unused port_num,
                unsigned __unused offs,
                uint8_t __unused v)
    {
        if (port_num == 0 && offs == 0) {
            reg_idx = v;
        } else if (port_num == 0 && offs == 1) {
            idx_regs[reg_idx] = v;
        }
    }
 
    uint8_t read8(uint16_t __unused port_num, unsigned __unused offs)
    {
        if (port_num == 0) {
            return offs == 0 ? reg_idx : idx_regs[reg_idx];
        } else if (port_num == 6 && offs == 0) {
            status ^= 0x1;
            return status;
        }
 
        return 0;
    }
 
    void update();
 
private:
    Cursor get_cursor() const
    {
        auto cursor_loc = (static_cast<uint16_t>(idx_regs[CURSOR_HIGH]) << 8) |
                          idx_regs[CURSOR_LOW];
        auto cursor_row = cursor_loc / 80;
        auto cursor_col = cursor_loc % 80;
        auto cursor_scan_start = idx_regs[CURSOR_SCAN_START] & 0xf;
        auto cursor_scan_end = idx_regs[CURSOR_SCAN_END] & 0xf;
        auto cursor_enabled = (idx_regs[CURSOR_SCAN_START] & 0x30) != 0x10;
 
        return Cursor(cursor_row * 8 + (cursor_scan_start),
                      cursor_row * 8 + (cursor_scan_end), cursor_col * 8,
                      cursor_col * 8 + 8, cursor_enabled);
    }
 
    Memory *mem;
    Display display;
    uint8_t reg_idx;
    uint8_t idx_regs[256];
    uint8_t status;
 
    friend class boost::serialization::access;
    template <class Archive>
    void serialize(Archive &ar, const unsigned int __unused version)
    {
        // clang-format off
        ar & mem;
        ar & reg_idx;
        ar & idx_regs;
        ar & status;
        // clang-format on
    }
};
 
void CGA::update()
{
    int cols = 80;
    int rows = 25;
 
    for (auto row = 0; row < rows; ++row) {
        for (auto col = 0; col < cols; ++col) {
            auto addr = buffer_phys + ((row * cols) + col) * sizeof(uint16_t);
            auto char_attr = mem->read<uint16_t>(addr);
 
            display.set_cursor(row, col);
            display.write_char(char_attr);
        }
    }
 
    display.refresh(get_cursor());
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.