-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathDisplay.cs
More file actions
146 lines (118 loc) · 3.49 KB
/
Display.cs
File metadata and controls
146 lines (118 loc) · 3.49 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
using System.Text;
abstract class Display : Device
{
private DateTime _prev_ts = DateTime.UtcNow;
private long _last_hsync = 0;
private List<EmulatorConsole> _consoles = null;
protected GraphicalFrame _gf = new();
protected int _gf_version = 1;
private Mutex _vsync_lock = new();
protected bool _palette_per_scanline = false;
public Display(List<EmulatorConsole> consoles)
{
_consoles = consoles;
foreach(var c in _consoles)
c.RegisterDisplay(this); // for Redraw()
TerminalClear();
}
public virtual int GetWidth()
{
return 640;
}
public virtual int GetHeight()
{
return 400;
}
public override int GetIRQNumber()
{
return -1;
}
public int GetFrameVersion()
{
return _gf_version;
}
public void RegisterPalettePerScanline(bool state)
{
_palette_per_scanline = state;
}
public virtual GraphicalFrame GetFrame(bool force)
{
if (force == false)
WaitVSync();
// TODO locking
GraphicalFrame gf = new();
gf.width = _gf.width;
gf.height = _gf.height;
int n_bytes = _gf.width * _gf.height * 3;
if (_gf.rgb_pixels != null)
gf.rgb_pixels = (byte [])_gf.rgb_pixels.Clone();
else
gf.rgb_pixels = new byte[n_bytes];
return gf;
}
private void WriteTextConsole(char what)
{
foreach(var c in _consoles)
{
if (c is TextConsole)
c.Write($"{what}");
}
}
private void WriteTextConsole(string what)
{
foreach(var c in _consoles)
{
if (c is TextConsole)
c.Write($"{what}");
}
}
protected void TerminalClear()
{
WriteTextConsole((char)27); // clear screen
WriteTextConsole("[2J");
}
public abstract override String GetName();
public abstract override void RegisterDevice(Dictionary <ushort, Device> mappings);
public abstract override bool IO_Write(ushort port, byte value);
public abstract int GetCurrentScanLine();
public abstract bool IsInHSync();
public abstract bool IsInVSync();
public void WaitVSync()
{
lock(_vsync_lock)
{
Monitor.Wait(_vsync_lock);
}
}
protected void PublishVSync()
{
lock(_vsync_lock)
{
Monitor.Pulse(_vsync_lock);
}
}
public abstract override byte IO_Read(ushort port);
protected void EmulateTextDisplay(uint x, uint y, byte character, byte attributes)
{
// attribute, character
#if DEBUG
if (character >= 32 && character < 127)
Log.DoLog($"Display::WriteByte {x},{y} = {(char)character}", LogLevel.TRACE);
#endif
WriteTextConsole((char)27); // position cursor
WriteTextConsole($"[{y + 1};{x + 1}H");
int [] colormap = { 0, 4, 2, 6, 1, 5, 3, 7 };
int fg = colormap[(attributes >> 4) & 7];
int bg = colormap[attributes & 7];
WriteTextConsole((char)27); // set attributes
WriteTextConsole($"[0;{40 + fg};{30 + bg}m"); // BG & FG color
if ((attributes & 8) == 8)
{
WriteTextConsole((char)27); // set attributes
WriteTextConsole($"[1m"); // bright
}
WriteTextConsole((char)character);
}
public abstract override void WriteByte(uint offset, byte value);
public abstract override byte ReadByte(uint offset);
}