Add NFrame.
Signed-off-by: Andrea Odetti <mariofutire@gmail.com>
This commit is contained in:
parent
54a3bbf773
commit
6ca8aedcf2
7 changed files with 370 additions and 359 deletions
|
@ -18,6 +18,7 @@
|
|||
#include "linux/benchmark.h"
|
||||
#include "linux/paddle.h"
|
||||
#include "linux/interface.h"
|
||||
#include "linux/context.h"
|
||||
#include "frontends/common2/fileregistry.h"
|
||||
#include "frontends/common2/programoptions.h"
|
||||
#include "frontends/common2/utils.h"
|
||||
|
@ -26,8 +27,7 @@
|
|||
|
||||
namespace
|
||||
{
|
||||
|
||||
bool ContinueExecution(const EmulatorOptions & options)
|
||||
bool ContinueExecution(const EmulatorOptions & options, const std::shared_ptr<NFrame> & frame)
|
||||
{
|
||||
const auto start = std::chrono::steady_clock::now();
|
||||
|
||||
|
@ -53,7 +53,7 @@ namespace
|
|||
|
||||
cardManager.GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted);
|
||||
|
||||
const int key = ProcessKeyboard();
|
||||
const int key = ProcessKeyboard(frame);
|
||||
|
||||
switch (key)
|
||||
{
|
||||
|
@ -92,7 +92,7 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
ProcessInput();
|
||||
frame->ProcessEvDev();
|
||||
|
||||
const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
|
||||
if (g_dwCyclesThisFrame >= dwClksPerFrame)
|
||||
|
@ -100,7 +100,7 @@ namespace
|
|||
g_dwCyclesThisFrame = g_dwCyclesThisFrame % dwClksPerFrame;
|
||||
if (!options.headless)
|
||||
{
|
||||
NVideoRedrawScreen();
|
||||
frame->VideoPresentScreen();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -130,10 +130,10 @@ namespace
|
|||
}
|
||||
}
|
||||
|
||||
void EnterMessageLoop(const EmulatorOptions & options)
|
||||
void EnterMessageLoop(const EmulatorOptions & options, const std::shared_ptr<NFrame> & frame)
|
||||
{
|
||||
LogFileTimeUntilFirstKeyReadReset();
|
||||
while (ContinueExecution(options))
|
||||
while (ContinueExecution(options, frame))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -147,6 +147,11 @@ namespace
|
|||
if (!run)
|
||||
return 1;
|
||||
|
||||
std::shared_ptr<NFrame> frame(new NFrame(options.paddleDeviceName));
|
||||
SetFrame(frame);
|
||||
// does not seem to be a problem calling endwin() multiple times
|
||||
std::atexit(NFrame::Cleanup);
|
||||
|
||||
if (options.log)
|
||||
{
|
||||
LogInit();
|
||||
|
@ -157,22 +162,19 @@ namespace
|
|||
g_nMemoryClearType = options.memclear;
|
||||
|
||||
initialiseEmulator();
|
||||
NVideoInitialise(options.headless);
|
||||
SetCtrlCHandler(options.headless);
|
||||
applyOptions(options);
|
||||
PaddleInitialise(options.paddleDeviceName);
|
||||
|
||||
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES | DRAW_DISK_STATUS);
|
||||
|
||||
if (options.benchmark)
|
||||
{
|
||||
VideoBenchmark(&NVideoRedrawScreen, &NVideoRedrawScreen);
|
||||
const auto redraw = [&frame]() { frame->VideoRedrawScreen(); };
|
||||
VideoBenchmark(redraw, redraw);
|
||||
}
|
||||
else
|
||||
{
|
||||
EnterMessageLoop(options);
|
||||
EnterMessageLoop(options, frame);
|
||||
}
|
||||
|
||||
Frame::unInitialise();
|
||||
uninitialiseEmulator();
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -1,24 +1,94 @@
|
|||
#include "StdAfx.h"
|
||||
#include "frontends/ncurses/nframe.h"
|
||||
#include "frontends/ncurses/colors.h"
|
||||
#include "frontends/ncurses/asciiart.h"
|
||||
#include "frontends/ncurses/evdevpaddle.h"
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Memory.h"
|
||||
|
||||
#include <signal.h>
|
||||
#include <locale.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
bool Frame::ourInitialised = false;
|
||||
std::shared_ptr<GraphicsColors> Frame::ourColors;
|
||||
struct NCurses
|
||||
{
|
||||
NCurses()
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
initscr();
|
||||
|
||||
Frame::Frame() : myColumns(-1), myRows(-1)
|
||||
curs_set(0);
|
||||
|
||||
noecho();
|
||||
cbreak();
|
||||
set_escdelay(0);
|
||||
|
||||
// make sure this happens when ncurses is indeed initialised
|
||||
colors.reset(new GraphicsColors(20, 20, 32));
|
||||
}
|
||||
~NCurses()
|
||||
{
|
||||
endwin();
|
||||
colors.reset();
|
||||
}
|
||||
std::shared_ptr<GraphicsColors> colors;
|
||||
};
|
||||
|
||||
NFrame::NFrame(const std::string & paddleDevice)
|
||||
: myPaddleDevice(paddleDevice)
|
||||
, myRows(-1)
|
||||
, myColumns(-1)
|
||||
{
|
||||
// only initialise if actually used
|
||||
// so we can run headless
|
||||
}
|
||||
|
||||
void Frame::init(int rows, int columns)
|
||||
void NFrame::Initialize()
|
||||
{
|
||||
LinuxFrame::Initialize();
|
||||
myTextFlashCounter = 0;
|
||||
myTextFlashState = 0;
|
||||
myAsciiArt.reset(new ASCIIArt());
|
||||
myPaddle.reset(new EvDevPaddle(myPaddleDevice));
|
||||
Paddle::instance = myPaddle;
|
||||
}
|
||||
|
||||
void NFrame::Destroy()
|
||||
{
|
||||
LinuxFrame::Destroy();
|
||||
myTextFlashCounter = 0;
|
||||
myTextFlashState = 0;
|
||||
myFrame.reset();
|
||||
myStatus.reset();
|
||||
myAsciiArt.reset();
|
||||
|
||||
myPaddle.reset();
|
||||
Paddle::instance.reset();
|
||||
|
||||
myNCurses.reset();
|
||||
}
|
||||
|
||||
void NFrame::ProcessEvDev()
|
||||
{
|
||||
myPaddle->poll();
|
||||
}
|
||||
|
||||
void NFrame::ChangeColumns(const int x)
|
||||
{
|
||||
myAsciiArt->changeColumns(x);
|
||||
}
|
||||
|
||||
void NFrame::ChangeRows(const int x)
|
||||
{
|
||||
myAsciiArt->changeRows(x);
|
||||
}
|
||||
|
||||
void NFrame::Init(int rows, int columns)
|
||||
{
|
||||
if (myRows != rows || myColumns != columns)
|
||||
{
|
||||
initialise();
|
||||
InitialiseNCurses();
|
||||
if (columns < myColumns || rows < myRows)
|
||||
{
|
||||
werase(myStatus.get());
|
||||
|
@ -46,55 +116,244 @@ void Frame::init(int rows, int columns)
|
|||
|
||||
}
|
||||
|
||||
WINDOW * Frame::getWindow()
|
||||
WINDOW * NFrame::GetWindow()
|
||||
{
|
||||
return myFrame.get();
|
||||
}
|
||||
|
||||
WINDOW * Frame::getStatus()
|
||||
WINDOW * NFrame::GetStatus()
|
||||
{
|
||||
return myStatus.get();
|
||||
}
|
||||
|
||||
int Frame::getColumns() const
|
||||
void NFrame::InitialiseNCurses()
|
||||
{
|
||||
return myColumns;
|
||||
}
|
||||
|
||||
void Frame::initialise()
|
||||
{
|
||||
if (!ourInitialised)
|
||||
if (!myNCurses)
|
||||
{
|
||||
setlocale(LC_ALL, "");
|
||||
initscr();
|
||||
|
||||
// does not seem to be a problem calling endwin() multiple times
|
||||
std::atexit(Frame::unInitialise);
|
||||
|
||||
curs_set(0);
|
||||
|
||||
noecho();
|
||||
cbreak();
|
||||
set_escdelay(0);
|
||||
|
||||
// make sure this happens when ncurses is indeed initialised
|
||||
ourColors.reset(new GraphicsColors(20, 20, 32));
|
||||
|
||||
ourInitialised = true;
|
||||
myNCurses.reset(new NCurses());
|
||||
}
|
||||
}
|
||||
|
||||
void Frame::unInitialise()
|
||||
void NFrame::VideoPresentScreen()
|
||||
{
|
||||
if (ourInitialised)
|
||||
VideoUpdateFlash();
|
||||
|
||||
Video & video = GetVideo();
|
||||
|
||||
const int displaypage2 = video.VideoGetSWPAGE2() == 0 ? 0 : 1;
|
||||
|
||||
myHiresBank1 = MemGetAuxPtr (0x2000 << displaypage2);
|
||||
myHiresBank0 = MemGetMainPtr(0x2000 << displaypage2);
|
||||
myTextBank1 = MemGetAuxPtr (0x400 << displaypage2);
|
||||
myTextBank0 = MemGetMainPtr(0x400 << displaypage2);
|
||||
|
||||
typedef bool (NFrame::* VideoUpdateFuncPtr_t)(Video &, int, int, int, int, int);
|
||||
|
||||
VideoUpdateFuncPtr_t update = video.VideoGetSWTEXT()
|
||||
? video.VideoGetSW80COL()
|
||||
? &NFrame::Update80ColCell
|
||||
: &NFrame::Update40ColCell
|
||||
: video.VideoGetSWHIRES()
|
||||
? (video.VideoGetSWDHIRES() && video.VideoGetSW80COL())
|
||||
? &NFrame::UpdateDHiResCell
|
||||
: &NFrame::UpdateHiResCell
|
||||
: (video.VideoGetSWDHIRES() && video.VideoGetSW80COL())
|
||||
? &NFrame::UpdateDLoResCell
|
||||
: &NFrame::UpdateLoResCell;
|
||||
|
||||
int y = 0;
|
||||
int ypixel = 0;
|
||||
while (y < 20) {
|
||||
int offset = ((y & 7) << 7) + ((y >> 3) * 40);
|
||||
int x = 0;
|
||||
int xpixel = 0;
|
||||
while (x < 40) {
|
||||
(this->*update)(video, x, y, xpixel, ypixel, offset + x);
|
||||
++x;
|
||||
xpixel += 14;
|
||||
}
|
||||
++y;
|
||||
ypixel += 16;
|
||||
}
|
||||
|
||||
if (video.VideoGetSWMIXED())
|
||||
update = video.VideoGetSW80COL() ? &NFrame::Update80ColCell
|
||||
: &NFrame::Update40ColCell;
|
||||
|
||||
while (y < 24) {
|
||||
int offset = ((y & 7) << 7) + ((y >> 3) * 40);
|
||||
int x = 0;
|
||||
int xpixel = 0;
|
||||
while (x < 40) {
|
||||
(this->*update)(video, x, y, xpixel, ypixel, offset + x);
|
||||
++x;
|
||||
xpixel += 14;
|
||||
}
|
||||
++y;
|
||||
ypixel += 16;
|
||||
}
|
||||
|
||||
wrefresh(myFrame.get());
|
||||
}
|
||||
|
||||
void NFrame::VideoUpdateFlash()
|
||||
{
|
||||
++myTextFlashCounter;
|
||||
|
||||
if (myTextFlashCounter == 16) // Flash rate = 0.5 * 60 / 16 Hz (as we need 2 changes for a period)
|
||||
{
|
||||
ourColors.reset();
|
||||
endwin();
|
||||
ourInitialised = false;
|
||||
myTextFlashCounter = 0;
|
||||
myTextFlashState = myTextFlashState;
|
||||
}
|
||||
}
|
||||
|
||||
GraphicsColors & Frame::getColors()
|
||||
chtype NFrame::MapCharacter(Video & video, BYTE ch)
|
||||
{
|
||||
return *ourColors;
|
||||
const char low = ch & 0x7f;
|
||||
const char high = ch & 0x80;
|
||||
|
||||
chtype result = low;
|
||||
|
||||
const int code = low >> 5;
|
||||
switch (code)
|
||||
{
|
||||
case 0: // 00 - 1F
|
||||
result += 0x40; // UPPERCASE
|
||||
break;
|
||||
case 1: // 20 - 3F
|
||||
// SPECIAL CHARACTER
|
||||
break;
|
||||
case 2: // 40 - 5F
|
||||
// UPPERCASE
|
||||
break;
|
||||
case 3: // 60 - 7F
|
||||
// LOWERCASE
|
||||
if (high == 0 && !video.VideoGetSWAltCharSet())
|
||||
{
|
||||
result -= 0x40;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == 0x7f)
|
||||
{
|
||||
result = ACS_CKBOARD;
|
||||
}
|
||||
|
||||
if (!high)
|
||||
{
|
||||
if (!video.VideoGetSWAltCharSet() && (low >= 0x40))
|
||||
{
|
||||
// result |= A_BLINK; // does not work on my terminal
|
||||
if (myTextFlashState)
|
||||
{
|
||||
result |= A_REVERSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result |= A_REVERSE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool NFrame::Update40ColCell(Video & video, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
Init(24, 40);
|
||||
myAsciiArt->init(1, 1);
|
||||
|
||||
BYTE ch = *(myTextBank0+offset);
|
||||
|
||||
const chtype ch2 = MapCharacter(video, ch);
|
||||
mvwaddch(myFrame.get(), 1 + y, 1 + x, ch2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NFrame::Update80ColCell(Video & video, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
Init(24, 80);
|
||||
myAsciiArt->init(1, 2);
|
||||
|
||||
BYTE ch1 = *(myTextBank1+offset);
|
||||
BYTE ch2 = *(myTextBank0+offset);
|
||||
|
||||
WINDOW * win = myFrame.get();
|
||||
|
||||
const chtype ch12 = MapCharacter(video, ch1);
|
||||
mvwaddch(win, 1 + y, 1 + 2 * x, ch12);
|
||||
|
||||
const chtype ch22 = MapCharacter(video, ch2);
|
||||
mvwaddch(win, 1 + y, 1 + 2 * x + 1, ch22);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NFrame::UpdateLoResCell(Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
BYTE val = *(myTextBank0+offset);
|
||||
|
||||
const int pair = myNCurses->colors->getPair(val);
|
||||
|
||||
WINDOW * win = myFrame.get();
|
||||
|
||||
wcolor_set(win, pair, NULL);
|
||||
if (myColumns == 40)
|
||||
{
|
||||
mvwaddstr(win, 1 + y, 1 + x, "\u2580");
|
||||
}
|
||||
else
|
||||
{
|
||||
mvwaddstr(win, 1 + y, 1 + 2 * x, "\u2580\u2580");
|
||||
}
|
||||
wcolor_set(win, 0, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NFrame::UpdateDLoResCell(Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NFrame::UpdateHiResCell(Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
const BYTE * base = myHiresBank0 + offset;
|
||||
|
||||
const ASCIIArt::array_char_t & chs = myAsciiArt->getCharacters(base);
|
||||
|
||||
const auto shape = chs.shape();
|
||||
const size_t rows = shape[0];
|
||||
const size_t cols = shape[1];
|
||||
|
||||
Init(24 * rows, 40 * cols);
|
||||
WINDOW * win = myFrame.get();
|
||||
|
||||
const GraphicsColors & colors = *myNCurses->colors;
|
||||
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < cols; ++j)
|
||||
{
|
||||
const int pair = colors.getGrey(chs[i][j].foreground, chs[i][j].background);
|
||||
|
||||
wcolor_set(win, pair, NULL);
|
||||
mvwaddstr(win, 1 + rows * y + i, 1 + cols * x + j, chs[i][j].c);
|
||||
}
|
||||
}
|
||||
wcolor_set(win, 0, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NFrame::UpdateDHiResCell(Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void NFrame::Cleanup()
|
||||
{
|
||||
GetFrame().Destroy();
|
||||
}
|
||||
|
|
|
@ -1,35 +1,65 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include "linux/linuxframe.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <ncurses.h>
|
||||
|
||||
class GraphicsColors;
|
||||
class ASCIIArt;
|
||||
class EvDevPaddle;
|
||||
struct NCurses;
|
||||
|
||||
class Frame
|
||||
class NFrame : public LinuxFrame
|
||||
{
|
||||
public:
|
||||
Frame();
|
||||
public:
|
||||
NFrame(const std::string & paddleDevice);
|
||||
|
||||
WINDOW * getWindow();
|
||||
WINDOW * getStatus();
|
||||
WINDOW * GetWindow();
|
||||
WINDOW * GetStatus();
|
||||
|
||||
void init(int rows, int columns);
|
||||
int getColumns() const;
|
||||
virtual void Initialize();
|
||||
virtual void Destroy();
|
||||
virtual void VideoPresentScreen();
|
||||
|
||||
static GraphicsColors & getColors();
|
||||
void ProcessEvDev();
|
||||
|
||||
static void unInitialise();
|
||||
void ChangeColumns(const int x);
|
||||
void ChangeRows(const int x);
|
||||
|
||||
private:
|
||||
void Init(int rows, int columns);
|
||||
|
||||
static void Cleanup();
|
||||
|
||||
private:
|
||||
|
||||
const std::string myPaddleDevice;
|
||||
int myRows;
|
||||
int myColumns;
|
||||
int myTextFlashCounter;
|
||||
bool myTextFlashState;
|
||||
|
||||
std::shared_ptr<WINDOW> myFrame;
|
||||
std::shared_ptr<WINDOW> myStatus;
|
||||
std::shared_ptr<ASCIIArt> myAsciiArt;
|
||||
std::shared_ptr<EvDevPaddle> myPaddle;
|
||||
std::shared_ptr<NCurses> myNCurses;
|
||||
|
||||
static std::shared_ptr<GraphicsColors> ourColors;
|
||||
static bool ourInitialised;
|
||||
static void initialise();
|
||||
LPBYTE myTextBank1; // Aux
|
||||
LPBYTE myTextBank0; // Main
|
||||
LPBYTE myHiresBank1;
|
||||
LPBYTE myHiresBank0;
|
||||
|
||||
void VideoUpdateFlash();
|
||||
|
||||
chtype MapCharacter(Video & video, BYTE ch);
|
||||
|
||||
bool Update40ColCell(Video & video, int x, int y, int xpixel, int ypixel, int offset);
|
||||
bool Update80ColCell(Video & video, int x, int y, int xpixel, int ypixel, int offset);
|
||||
bool UpdateLoResCell(Video &, int x, int y, int xpixel, int ypixel, int offset);
|
||||
bool UpdateDLoResCell(Video &, int x, int y, int xpixel, int ypixel, int offset);
|
||||
bool UpdateHiResCell(Video &, int x, int y, int xpixel, int ypixel, int offset);
|
||||
bool UpdateDHiResCell(Video &, int x, int y, int xpixel, int ypixel, int offset);
|
||||
|
||||
void InitialiseNCurses();
|
||||
};
|
||||
|
|
|
@ -3,55 +3,18 @@
|
|||
|
||||
#include <ncurses.h>
|
||||
#include <signal.h>
|
||||
#include <iostream>
|
||||
|
||||
#include "Common.h"
|
||||
#include "CardManager.h"
|
||||
#include "Disk.h"
|
||||
#include "Video.h"
|
||||
#include "CPU.h"
|
||||
#include "Log.h"
|
||||
#include "DiskImageHelper.h"
|
||||
#include "Memory.h"
|
||||
#include "Core.h"
|
||||
#include "RGBMonitor.h"
|
||||
#include "Interface.h"
|
||||
|
||||
#include "linux/interface.h"
|
||||
#include "linux/paddle.h"
|
||||
#include "linux/data.h"
|
||||
#include "linux/keyboard.h"
|
||||
|
||||
#include "frontends/ncurses/nframe.h"
|
||||
#include "frontends/ncurses/colors.h"
|
||||
#include "frontends/ncurses/asciiart.h"
|
||||
#include "frontends/ncurses/evdevpaddle.h"
|
||||
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
std::shared_ptr<Frame> frame;
|
||||
std::shared_ptr<ASCIIArt> asciiArt;
|
||||
std::shared_ptr<EvDevPaddle> paddle;
|
||||
|
||||
int g_nTrackDrive1 = -1;
|
||||
int g_nTrackDrive2 = -1;
|
||||
int g_nSectorDrive1 = -1;
|
||||
int g_nSectorDrive2 = -1;
|
||||
TCHAR g_sTrackDrive1 [8] = TEXT("??");
|
||||
TCHAR g_sTrackDrive2 [8] = TEXT("??");
|
||||
TCHAR g_sSectorDrive1[8] = TEXT("??");
|
||||
TCHAR g_sSectorDrive2[8] = TEXT("??");
|
||||
Disk_Status_e g_eStatusDrive1 = DISK_STATUS_OFF;
|
||||
Disk_Status_e g_eStatusDrive2 = DISK_STATUS_OFF;
|
||||
|
||||
LPBYTE g_pTextBank1; // Aux
|
||||
LPBYTE g_pTextBank0; // Main
|
||||
LPBYTE g_pHiresBank1;
|
||||
LPBYTE g_pHiresBank0;
|
||||
|
||||
bool g_bTextFlashState = false;
|
||||
|
||||
void sig_handler_pass(int signo)
|
||||
{
|
||||
// Ctrl-C
|
||||
|
@ -65,169 +28,6 @@ namespace
|
|||
g_stop = true;
|
||||
}
|
||||
|
||||
chtype mapCharacter(Video & video, BYTE ch)
|
||||
{
|
||||
const char low = ch & 0x7f;
|
||||
const char high = ch & 0x80;
|
||||
|
||||
chtype result = low;
|
||||
|
||||
const int code = low >> 5;
|
||||
switch (code)
|
||||
{
|
||||
case 0: // 00 - 1F
|
||||
result += 0x40; // UPPERCASE
|
||||
break;
|
||||
case 1: // 20 - 3F
|
||||
// SPECIAL CHARACTER
|
||||
break;
|
||||
case 2: // 40 - 5F
|
||||
// UPPERCASE
|
||||
break;
|
||||
case 3: // 60 - 7F
|
||||
// LOWERCASE
|
||||
if (high == 0 && !video.VideoGetSWAltCharSet())
|
||||
{
|
||||
result -= 0x40;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (result == 0x7f)
|
||||
{
|
||||
result = ACS_CKBOARD;
|
||||
}
|
||||
|
||||
if (!high)
|
||||
{
|
||||
if (!video.VideoGetSWAltCharSet() && (low >= 0x40))
|
||||
{
|
||||
// result |= A_BLINK; // does not work on my terminal
|
||||
if (g_bTextFlashState)
|
||||
{
|
||||
result |= A_REVERSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result |= A_REVERSE;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void VideoUpdateFlash()
|
||||
{
|
||||
static UINT nTextFlashCnt = 0;
|
||||
|
||||
++nTextFlashCnt;
|
||||
|
||||
if (nTextFlashCnt == 16) // Flash rate = 0.5 * 60 / 16 Hz (as we need 2 changes for a period)
|
||||
{
|
||||
nTextFlashCnt = 0;
|
||||
g_bTextFlashState = !g_bTextFlashState;
|
||||
}
|
||||
}
|
||||
|
||||
typedef bool (*VideoUpdateFuncPtr_t)(Video &, int, int, int, int, int);
|
||||
|
||||
bool NUpdate40ColCell (Video & video, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
frame->init(24, 40);
|
||||
asciiArt->init(1, 1);
|
||||
|
||||
BYTE ch = *(g_pTextBank0+offset);
|
||||
|
||||
WINDOW * win = frame->getWindow();
|
||||
|
||||
const chtype ch2 = mapCharacter(video, ch);
|
||||
mvwaddch(win, 1 + y, 1 + x, ch2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUpdate80ColCell (Video & video, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
frame->init(24, 80);
|
||||
asciiArt->init(1, 2);
|
||||
|
||||
BYTE ch1 = *(g_pTextBank1+offset);
|
||||
BYTE ch2 = *(g_pTextBank0+offset);
|
||||
|
||||
WINDOW * win = frame->getWindow();
|
||||
|
||||
const chtype ch12 = mapCharacter(video, ch1);
|
||||
mvwaddch(win, 1 + y, 1 + 2 * x, ch12);
|
||||
|
||||
const chtype ch22 = mapCharacter(video, ch2);
|
||||
mvwaddch(win, 1 + y, 1 + 2 * x + 1, ch22);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUpdateLoResCell (Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
BYTE val = *(g_pTextBank0+offset);
|
||||
|
||||
const int pair = frame->getColors().getPair(val);
|
||||
|
||||
WINDOW * win = frame->getWindow();
|
||||
|
||||
wcolor_set(win, pair, NULL);
|
||||
if (frame->getColumns() == 40)
|
||||
{
|
||||
mvwaddstr(win, 1 + y, 1 + x, "\u2580");
|
||||
}
|
||||
else
|
||||
{
|
||||
mvwaddstr(win, 1 + y, 1 + 2 * x, "\u2580\u2580");
|
||||
}
|
||||
wcolor_set(win, 0, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUpdateDLoResCell (Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUpdateHiResCell (Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
const BYTE * base = g_pHiresBank0 + offset;
|
||||
|
||||
const ASCIIArt::array_char_t & chs = asciiArt->getCharacters(base);
|
||||
|
||||
const auto shape = chs.shape();
|
||||
const size_t rows = shape[0];
|
||||
const size_t cols = shape[1];
|
||||
|
||||
frame->init(24 * rows, 40 * cols);
|
||||
WINDOW * win = frame->getWindow();
|
||||
|
||||
const GraphicsColors & colors = frame->getColors();
|
||||
|
||||
for (size_t i = 0; i < rows; ++i)
|
||||
{
|
||||
for (size_t j = 0; j < cols; ++j)
|
||||
{
|
||||
const int pair = colors.getGrey(chs[i][j].foreground, chs[i][j].background);
|
||||
|
||||
wcolor_set(win, pair, NULL);
|
||||
mvwaddstr(win, 1 + rows * y + i, 1 + cols * x + j, chs[i][j].c);
|
||||
}
|
||||
}
|
||||
wcolor_set(win, 0, NULL);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NUpdateDHiResCell (Video &, int x, int y, int xpixel, int ypixel, int offset)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double g_relativeSpeed = 1.0;
|
||||
|
@ -239,17 +39,8 @@ int MessageBox(HWND, const char * text, const char * caption, UINT)
|
|||
return IDOK;
|
||||
}
|
||||
|
||||
void PaddleInitialise(const std::string & device)
|
||||
void SetCtrlCHandler(const bool headless)
|
||||
{
|
||||
paddle.reset(new EvDevPaddle(device));
|
||||
Paddle::instance = paddle;
|
||||
}
|
||||
|
||||
void NVideoInitialise(const bool headless)
|
||||
{
|
||||
frame.reset(new Frame());
|
||||
asciiArt.reset(new ASCIIArt());
|
||||
|
||||
if (headless)
|
||||
{
|
||||
signal(SIGINT, sig_handler_exit);
|
||||
|
@ -261,69 +52,9 @@ void NVideoInitialise(const bool headless)
|
|||
}
|
||||
}
|
||||
|
||||
void NVideoRedrawScreen()
|
||||
int ProcessKeyboard(const std::shared_ptr<NFrame> & frame)
|
||||
{
|
||||
VideoUpdateFlash();
|
||||
|
||||
Video & video = GetVideo();
|
||||
|
||||
const int displaypage2 = video.VideoGetSWPAGE2() == 0 ? 0 : 1;
|
||||
|
||||
g_pHiresBank1 = MemGetAuxPtr (0x2000 << displaypage2);
|
||||
g_pHiresBank0 = MemGetMainPtr(0x2000 << displaypage2);
|
||||
g_pTextBank1 = MemGetAuxPtr (0x400 << displaypage2);
|
||||
g_pTextBank0 = MemGetMainPtr(0x400 << displaypage2);
|
||||
|
||||
VideoUpdateFuncPtr_t update = video.VideoGetSWTEXT()
|
||||
? video.VideoGetSW80COL()
|
||||
? NUpdate80ColCell
|
||||
: NUpdate40ColCell
|
||||
: video.VideoGetSWHIRES()
|
||||
? (video.VideoGetSWDHIRES() && video.VideoGetSW80COL())
|
||||
? NUpdateDHiResCell
|
||||
: NUpdateHiResCell
|
||||
: (video.VideoGetSWDHIRES() && video.VideoGetSW80COL())
|
||||
? NUpdateDLoResCell
|
||||
: NUpdateLoResCell;
|
||||
|
||||
int y = 0;
|
||||
int ypixel = 0;
|
||||
while (y < 20) {
|
||||
int offset = ((y & 7) << 7) + ((y >> 3) * 40);
|
||||
int x = 0;
|
||||
int xpixel = 0;
|
||||
while (x < 40) {
|
||||
update(video, x, y, xpixel, ypixel, offset + x);
|
||||
++x;
|
||||
xpixel += 14;
|
||||
}
|
||||
++y;
|
||||
ypixel += 16;
|
||||
}
|
||||
|
||||
if (video.VideoGetSWMIXED())
|
||||
update = video.VideoGetSW80COL() ? NUpdate80ColCell
|
||||
: NUpdate40ColCell;
|
||||
|
||||
while (y < 24) {
|
||||
int offset = ((y & 7) << 7) + ((y >> 3) * 40);
|
||||
int x = 0;
|
||||
int xpixel = 0;
|
||||
while (x < 40) {
|
||||
update(video, x, y, xpixel, ypixel, offset + x);
|
||||
++x;
|
||||
xpixel += 14;
|
||||
}
|
||||
++y;
|
||||
ypixel += 16;
|
||||
}
|
||||
|
||||
wrefresh(frame->getWindow());
|
||||
}
|
||||
|
||||
int ProcessKeyboard()
|
||||
{
|
||||
WINDOW * window = frame->getWindow();
|
||||
WINDOW * window = frame->GetWindow();
|
||||
if (!window)
|
||||
{
|
||||
return ERR;
|
||||
|
@ -357,16 +88,16 @@ int ProcessKeyboard()
|
|||
ch = 0x7f;
|
||||
break;
|
||||
case 543 ... 546: // Various values for Ctrl/Alt - Left on Ubuntu and Pi OS
|
||||
asciiArt->changeColumns(-1);
|
||||
frame->ChangeColumns(-1);
|
||||
break;
|
||||
case 558 ... 561: // Ctrl/Alt - Right
|
||||
asciiArt->changeColumns(+1);
|
||||
frame->ChangeColumns(+1);
|
||||
break;
|
||||
case 564 ... 567: // Ctrl/Alt - Up
|
||||
asciiArt->changeRows(-1);
|
||||
frame->ChangeRows(-1);
|
||||
break;
|
||||
case 523 ... 526: // Ctrl/Alt - Down
|
||||
asciiArt->changeRows(+1);
|
||||
frame->ChangeRows(+1);
|
||||
break;
|
||||
default:
|
||||
if (inch < 0x80)
|
||||
|
@ -396,11 +127,6 @@ int ProcessKeyboard()
|
|||
}
|
||||
}
|
||||
|
||||
void ProcessInput()
|
||||
{
|
||||
paddle->poll();
|
||||
}
|
||||
|
||||
// Mockingboard
|
||||
void registerSoundBuffer(IDirectSoundBuffer * buffer)
|
||||
{
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
int ProcessKeyboard();
|
||||
void ProcessInput();
|
||||
void NVideoInitialise(const bool headless);
|
||||
void NVideoRedrawScreen();
|
||||
void PaddleInitialise(const std::string & device);
|
||||
class NFrame;
|
||||
|
||||
int ProcessKeyboard(const std::shared_ptr<NFrame> & frame);
|
||||
void SetCtrlCHandler(const bool headless);
|
||||
|
||||
extern double g_relativeSpeed;
|
||||
|
||||
|
|
|
@ -61,10 +61,6 @@ void LinuxFrame::Destroy()
|
|||
GetVideo().Destroy(); // this resets the Video's FrameBuffer pointer
|
||||
}
|
||||
|
||||
void LinuxFrame::VideoPresentScreen()
|
||||
{
|
||||
}
|
||||
|
||||
void LinuxFrame::ChooseMonochromeColor()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ public:
|
|||
|
||||
virtual void SetLoadedSaveStateFlag(const bool bFlag);
|
||||
|
||||
virtual void VideoPresentScreen();
|
||||
virtual void ChooseMonochromeColor();
|
||||
virtual void Benchmark();
|
||||
virtual void DisplayLogo();
|
||||
|
|
Loading…
Add table
Reference in a new issue