Skip to content

Commit

Permalink
80-columns mode support
Browse files Browse the repository at this point in the history
  • Loading branch information
fvdhoef committed Oct 21, 2023
1 parent baf63cb commit c73d051
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 77 deletions.
2 changes: 1 addition & 1 deletion System/emulator/Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@

#define CPU_FREQ (3579545)

#define VIDEO_WIDTH (352)
#define VIDEO_WIDTH (704)
#define VIDEO_HEIGHT (240)

static inline void stripTrailingSlashes(std::string &path) {
Expand Down
2 changes: 1 addition & 1 deletion System/emulator/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class Config {
int wndPosX = SDL_WINDOWPOS_CENTERED;
int wndPosY = SDL_WINDOWPOS_CENTERED;
int wndWidth = VIDEO_WIDTH * 2;
int wndHeight = VIDEO_HEIGHT * 2;
int wndHeight = (VIDEO_HEIGHT * 2) * 2;
int scrScale = 1;
bool enableSound = true;
bool enableMouse = true;
Expand Down
23 changes: 18 additions & 5 deletions System/emulator/EmuState.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -340,12 +340,25 @@ void EmuState::memWrite(size_t param, uint16_t addr, uint8_t data) {
addr &= 0x3FFF;

if (overlayRam && addr >= 0x3000) {
if (addr < 0x3400) {
emuState.screenRam[addr & 0x3FF] = data;
} else if (addr < 0x3800) {
emuState.colorRam[addr & 0x3FF] = data;
} else {
if (addr >= 0x3800) {
emuState.mainRam[addr] = data;
return;
}

if (emuState.videoCtrl & VCTRL_80_COLUMNS) {
if (emuState.videoCtrl & VCTRL_TRAM_PAGE) {
emuState.colorRam[addr & 0x7FF] = data;
} else {
emuState.screenRam[addr & 0x7FF] = data;
}

} else {
unsigned offset = (emuState.videoCtrl & VCTRL_TRAM_PAGE) ? 0x400 : 0;
if (addr < 0x3400) {
emuState.screenRam[offset | (addr & 0x3FF)] = data;
} else {
emuState.colorRam[offset | (addr & 0x3FF)] = data;
}
}
return;
}
Expand Down
4 changes: 2 additions & 2 deletions System/emulator/EmuState.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ struct EmuState {
bool cpmRemap = false; // $FD<1>: Remap memory for CP/M

// Memory space
uint8_t screenRam[1024]; // $3000-33FF: Screen RAM for text mode
uint8_t colorRam[1024]; // $3400-37FF: Color RAM for text mode
uint8_t screenRam[2048]; // $3000-33FF: Screen RAM for text mode
uint8_t colorRam[2048]; // $3400-37FF: Color RAM for text mode
uint8_t systemRom[256 * 1024]; // Flash memory
uint8_t mainRam[512 * 1024]; // Main RAM
uint8_t cartRom[16 * 1024]; // Cartridge ROM
Expand Down
19 changes: 9 additions & 10 deletions System/emulator/UI/UI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ void UI::start(
}

// Create screen texture
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, VIDEO_WIDTH, VIDEO_HEIGHT);
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, VIDEO_WIDTH, VIDEO_HEIGHT * 2);
if (texture == NULL) {
fprintf(stderr, "SDL_CreateTexture Error: %s\n", SDL_GetError());
SDL_Quit();
Expand Down Expand Up @@ -337,7 +337,7 @@ void UI::mainLoop() {
// Update mouse
const ImVec2 p0((float)dst.x, (float)dst.y);
const ImVec2 p1((float)(dst.x + dst.w), (float)(dst.y + dst.h));
auto pos = (io.MousePos - p0) / (p1 - p0) * ImVec2(VIDEO_WIDTH, VIDEO_HEIGHT) - ImVec2(16, 16);
auto pos = (io.MousePos - p0) / (p1 - p0) * ImVec2(VIDEO_WIDTH / 2, VIDEO_HEIGHT) - ImVec2(16, 16);

bool hideMouse =
(emuState.mouseHideTimeout > 0) &&
Expand Down Expand Up @@ -377,11 +377,10 @@ void UI::renderScreen() {

const uint16_t *fb = emuState.video.getFb();

for (int j = 0; j < VIDEO_HEIGHT; j++) {
for (int j = 0; j < VIDEO_HEIGHT * 2; j++) {
for (int i = 0; i < VIDEO_WIDTH; i++) {

// Convert from RGB444 to RGB888
uint16_t col444 = fb[j * VIDEO_WIDTH + i];
uint16_t col444 = fb[j / 2 * VIDEO_WIDTH + i];

unsigned r4 = (col444 >> 8) & 0xF;
unsigned g4 = (col444 >> 4) & 0xF;
Expand Down Expand Up @@ -417,9 +416,9 @@ SDL_Rect UI::renderTexture() {

// Retain aspect ratio
int w1 = (w / VIDEO_WIDTH) * VIDEO_WIDTH;
int h1 = (w1 * VIDEO_HEIGHT) / VIDEO_WIDTH;
int h2 = (h / VIDEO_HEIGHT) * VIDEO_HEIGHT;
int w2 = (h2 * VIDEO_WIDTH) / VIDEO_HEIGHT;
int h1 = (w1 * (VIDEO_HEIGHT * 2)) / VIDEO_WIDTH;
int h2 = (h / (VIDEO_HEIGHT * 2)) * (VIDEO_HEIGHT * 2);
int w2 = (h2 * VIDEO_WIDTH) / (VIDEO_HEIGHT * 2);

int sw, sh;
if (w1 == 0 || h1 == 0) {
Expand Down Expand Up @@ -750,11 +749,11 @@ void UI::wndScreen(bool *p_open) {
if (texture) {
ImGuiIO &io = ImGui::GetIO();

auto sz = ImVec2((float)(VIDEO_WIDTH * e), (float)(VIDEO_HEIGHT * e));
auto sz = ImVec2((float)(VIDEO_WIDTH * e), (float)(VIDEO_HEIGHT * 2 * e));
ImGui::InvisibleButton("##imgbtn", sz, ImGuiButtonFlags_MouseButtonLeft | ImGuiButtonFlags_MouseButtonRight | ImGuiButtonFlags_MouseButtonMiddle);
const ImVec2 p0 = ImGui::GetItemRectMin();
const ImVec2 p1 = ImGui::GetItemRectMax();
auto pos = (io.MousePos - p0) / (p1 - p0) * ImVec2(VIDEO_WIDTH, VIDEO_HEIGHT) - ImVec2(16, 16);
auto pos = (io.MousePos - p0) / (p1 - p0) * ImVec2(VIDEO_WIDTH / 2, VIDEO_HEIGHT) - ImVec2(16, 16);

int mx = std::max(0, std::min((int)pos.x, 319));
int my = std::max(0, std::min((int)pos.y, 199));
Expand Down
117 changes: 59 additions & 58 deletions System/emulator/Video.cpp
Original file line number Diff line number Diff line change
@@ -1,18 +1,6 @@
#include "Video.h"
#include "EmuState.h"

enum {
VCTRL_TEXT_ENABLE = (1 << 0),
VCTRL_MODE_OFF = (0 << 1),
VCTRL_MODE_TILEMAP = (1 << 1),
VCTRL_MODE_BITMAP = (2 << 1),
VCTRL_MODE_BITMAP_4BPP = (3 << 1),
VCTRL_MODE_MASK = (3 << 1),
VCTRL_SPRITES_ENABLE = (1 << 3),
VCTRL_TEXT_PRIORITY = (1 << 4),
VCTRL_REMAP_BORDER_CHAR = (1 << 5),
};

Video::Video() {
}

Expand All @@ -21,32 +9,40 @@ void Video::drawLine() {
if (line < 0 || line >= VIDEO_HEIGHT)
return;

bool vActive = line >= 16 && line < 216;

// Render text
uint8_t lineText[512];
unsigned idx = 512 - 16;
uint8_t lineText[1024];
{
unsigned idx = 1024 - 32;
for (int i = 0; i < VIDEO_WIDTH; i++) {
// Draw text character
unsigned addr = 0;
int pixidx = i;

if (vActive && idx < 640) {
int row = (line - 16) / 8;
if (emuState.videoCtrl & VCTRL_80_COLUMNS) {
int column = (i - 32) / 8;
addr = row * 80 + column;
} else {
int column = ((i / 2) - 16) / 8;
addr = row * 40 + column;
pixidx /= 2;
}

bool vActive = line >= 16 && line < 216;
} else if (emuState.videoCtrl & VCTRL_REMAP_BORDER_CHAR) {
addr = (emuState.videoCtrl & VCTRL_80_COLUMNS) ? 0x7FF : 0x3FF;
}

for (int i = 0; i < VIDEO_WIDTH; i++) {
// Draw text character
uint8_t ch;
uint8_t color;
if (vActive && idx < 320) {
int row = (line - 16) / 8;
int column = (i - 16) / 8;
ch = emuState.screenRam[row * 40 + column];
color = emuState.colorRam[row * 40 + column];

} else {
unsigned borderAddr = (emuState.videoCtrl & VCTRL_REMAP_BORDER_CHAR) ? 0x3FF : 0;

ch = emuState.screenRam[borderAddr];
color = emuState.colorRam[borderAddr];
}
uint8_t ch = emuState.screenRam[addr];
uint8_t color = emuState.colorRam[addr];

uint8_t charBm = emuState.charRam[ch * 8 + (line & 7)];

uint8_t charBm = emuState.charRam[ch * 8 + (line & 7)];
lineText[idx] = (charBm & (1 << (7 - (i & 7)))) ? (color >> 4) : (color & 0xF);
idx = (idx + 1) & 511;
lineText[idx] = (charBm & (1 << (7 - (pixidx & 7)))) ? (color >> 4) : (color & 0xF);
idx = (idx + 1) & 1023;
}
}

// Render bitmap/tile layer
Expand Down Expand Up @@ -83,7 +79,7 @@ void Video::drawLine() {

case VCTRL_MODE_TILEMAP: {
// Tile mode
idx = (-(emuState.videoScrX & 7)) & 511;
unsigned idx = (-(emuState.videoScrX & 7)) & 511;
unsigned tileLine = (bmline + emuState.videoScrY) & 255;
unsigned row = (tileLine >> 3) & 31;
unsigned col = emuState.videoScrX >> 3;
Expand Down Expand Up @@ -168,7 +164,7 @@ void Video::drawLine() {
uint8_t palette = sprAttr & 0x30;
bool priority = (sprAttr & (1 << 6)) != 0;

idx = sprX;
unsigned idx = sprX;

if (vFlip)
sprLine ^= (h16 ? 15 : 7);
Expand Down Expand Up @@ -219,28 +215,33 @@ void Video::drawLine() {
}

// Compose layers
uint16_t *pd = &screen[line * VIDEO_WIDTH];
idx = 512 - 16;

for (int i = 0; i < VIDEO_WIDTH; i++) {
bool active = idx < 320 && vActive;
bool textPriority = (emuState.videoCtrl & VCTRL_TEXT_PRIORITY) != 0;
bool textEnable = (emuState.videoCtrl & VCTRL_TEXT_ENABLE) != 0;

uint8_t colIdx = 0;
if (!active) {
if (textEnable)
colIdx = lineText[idx];
} else {
if (textEnable && !textPriority)
colIdx = lineText[idx];
if (!textEnable || textPriority || (lineGfx[idx] & 0xF) != 0)
colIdx = lineGfx[idx];
if (textEnable && textPriority && (lineText[idx] & 0xF) != 0)
colIdx = lineText[idx];
}
{
uint16_t *pd = &screen[line * VIDEO_WIDTH];
unsigned idx = 1024 - 32;

for (int i = 0; i < VIDEO_WIDTH; i++) {
bool active = idx < 640 && vActive;
bool textPriority = (emuState.videoCtrl & VCTRL_TEXT_PRIORITY) != 0;
bool textEnable = (emuState.videoCtrl & VCTRL_TEXT_ENABLE) != 0;

uint8_t colIdx = 0;
if (!active) {
if (textEnable)
colIdx = lineText[idx];
} else {
if (textEnable)
colIdx = lineText[idx];

if (textEnable && !textPriority)
colIdx = lineText[idx];
if (!textEnable || textPriority || (lineGfx[idx / 2] & 0xF) != 0)
colIdx = lineGfx[idx / 2];
if (textEnable && textPriority && (lineText[idx] & 0xF) != 0)
colIdx = lineText[idx];
}

pd[i] = emuState.videoPalette[colIdx & 0x3F];
idx = (idx + 1) & 511;
pd[i] = emuState.videoPalette[colIdx & 0x3F];
idx = (idx + 1) & 1023;
}
}
}
14 changes: 14 additions & 0 deletions System/emulator/Video.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@
#include "Common.h"
#include "SDL.h"

enum {
VCTRL_TEXT_ENABLE = (1 << 0),
VCTRL_MODE_OFF = (0 << 1),
VCTRL_MODE_TILEMAP = (1 << 1),
VCTRL_MODE_BITMAP = (2 << 1),
VCTRL_MODE_BITMAP_4BPP = (3 << 1),
VCTRL_MODE_MASK = (3 << 1),
VCTRL_SPRITES_ENABLE = (1 << 3),
VCTRL_TEXT_PRIORITY = (1 << 4),
VCTRL_REMAP_BORDER_CHAR = (1 << 5),
VCTRL_80_COLUMNS = (1 << 6),
VCTRL_TRAM_PAGE = (1 << 7),
};

class Video {
public:
Video();
Expand Down

0 comments on commit c73d051

Please sign in to comment.