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

Subversion Repositories s80186

[/] [s80186/] [trunk/] [sim/] [display/] [Display.cpp] - 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/>.
 
#include "Display.h"
 
#include <cassert>
#include <cctype>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <stdexcept>
 
#include <SDL.h>
 
#include "Window.h"
 
Display::Display(unsigned num_rows, unsigned num_cols)
    : num_rows(num_rows), num_cols(num_cols), row(0), col(0)
{
    if (SDL_Init(SDL_INIT_VIDEO) != 0)
        throw std::runtime_error("Failed to initialize SDL " +
                                 std::string(SDL_GetError()));
 
    characters = std::make_unique<uint16_t[]>(num_rows * (num_cols + 1));
    window = std::make_unique<Window>("8086sim", 8 * num_cols, 8 * num_rows);
 
    load_font();
}
 
Display::~Display()
{
    SDL_Quit();
}
 
void Display::load_font()
{
    std::ifstream font_file;
    font_file.open(FONT_FILE, std::ios::binary | std::ios::in);
    font_file.read(font_bitmap, sizeof(font_bitmap));
    font_file.close();
}
 
void Display::set_cursor(unsigned row, unsigned col)
{
    this->row = row;
    this->col = col;
}
 
void Display::write_char(uint16_t c)
{
    uint16_t v = c;
 
    characters[this->row * (num_cols + 1) + this->col] = v;
    this->col++;
 
    if (this->col == num_cols) {
        this->col = 0;
        this->row++;
    }
    if (this->row == num_rows)
        this->row = num_rows - 1;
}
 
struct color {
    unsigned char r, g, b;
};
 
const struct color get_color(unsigned char idx)
{
    assert(idx < 16);
 
    struct color lut[] = {
        {0, 0, 0},          // black
        {0, 0, 0xaa},       // blue
        {0x00, 0xaa, 0x00}, // green
        {0x00, 0xaa, 0xaa}, // cyan
        {0xaa, 0x00, 0x00}, // red
        {0xaa, 0x00, 0xaa}, // magenta
        {0xaa, 0x55, 0x00}, // brown
        {0xaa, 0xaa, 0xaa}, // white
        {0x55, 0x55, 0x55}, // gray
        {0x55, 0x55, 0xff}, // bright blue
        {0x55, 0xff, 0x55}, // bright green
        {0x55, 0xff, 0xff}, // bright cyan
        {0xff, 0x55, 0x55}, // bright red
        {0xff, 0x55, 0xff}, // bright magenta
        {0xff, 0xff, 0x55}, // yellow
        {0xff, 0xff, 0xff}, // bright white
    };
 
    return lut[idx];
}
 
void Display::refresh(Cursor cursor)
{
    window->clear();
    for (unsigned y = 0; y < num_rows; ++y) {
        for (unsigned x = 0; x < num_cols; ++x) {
            uint16_t font_index = characters.get()[(y * (num_cols + 1)) + x];
            char *font_data = &font_bitmap[(font_index & 0xff) * 8];
 
            for (int i = 0; i < 8; ++i)
                for (int j = 0; j < 8; ++j) {
                    auto fg = get_color((font_index >> 8) & 0xf);
                    auto bg = get_color((font_index >> 12) & 0xf);
 
                    auto render_cursor =
                        cursor.is_active_at(y * 8 + i, x * 8 + j);
                    bool pixel_set = (font_data[i] & (1 << (8 - j)));
                    auto color = (pixel_set && !render_cursor) ||
                                         (!pixel_set && render_cursor)
                                     ? fg
                                     : bg;
                    window->set_pixel(x * 8 + j, y * 8 + i, color.r, color.g,
                                      color.b);
                }
        }
    }
 
    window->redraw();
 
    SDL_UpdateWindowSurface(window->get());
}
 

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.