-
Notifications
You must be signed in to change notification settings - Fork 0
/
MainWindow.cs
127 lines (101 loc) · 2.86 KB
/
MainWindow.cs
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
using System;
using System.Drawing;
using Gtk;
using MicroLibrary;
public partial class MainWindow: Gtk.Window
{
// The Emulator Core
CHIP8_Emulator.Chip8 emulator;
// The Timer for the emulator
MicroTimer hiResTimer = new MicroTimer((long)(1000000.0f / 60.0f)); //60 Hz
// Display settings
private const int SCREEN_WIDTH = 64;
private const int SCREEN_HEIGHT = 32;
private const int SCREEN_ZOOM = 8;
// Display
DrawingArea da;
Bitmap screen = new Bitmap(SCREEN_WIDTH, SCREEN_HEIGHT);
/*
* 1 2 3 4 1 2 3 C
* Q W E R __\ 4 5 6 D
* A S D F / 7 8 9 E
* Z X C V A 0 B F
*/
private uint[] keymap = {
120, 49, 50, 51,
113, 119, 101, 97,
115, 100, 122, 99,
52, 114, 102, 118,
};
public MainWindow (): base (Gtk.WindowType.Toplevel)
{
Build ();
// Setup Emulator
emulator = new CHIP8_Emulator.Chip8();
emulator.Load("../../ROMS/PONG2");
// Register our timer function
hiResTimer.MicroTimerElapsed += new MicroTimer.MicroTimerElapsedEventHandler(hiResTick);
hiResTimer.Enabled = true;
// Install drawing area
da = new DrawingArea();
Add (da);
da.Show();
// Setup drawing function
da.ExposeEvent += ScreenExposeEvent;
}
void ScreenExposeEvent (object o, ExposeEventArgs args)
{
Gdk.EventExpose ev = args.Event;
Gdk.Window window = ev.Window;
using (Graphics g = Gtk.DotNet.Graphics.FromDrawable(window)) {
g.DrawImage((System.Drawing.Image)screen, new Rectangle(0, 0, SCREEN_WIDTH * SCREEN_ZOOM, SCREEN_HEIGHT * SCREEN_ZOOM));
}
}
private void hiResTick(object sender, MicroTimerEventArgs timerEventArgs)
{
// Emulate a cycle
emulator.Cycle();
// If the screen was updated, draw it
if (emulator.DrawRequired()) {
byte[] screen_data = emulator.GetDisplay();
for (int y = 0; y < SCREEN_HEIGHT; ++y)
{
for (int x = 0; x < SCREEN_WIDTH; ++x)
{
if (screen_data[(y * SCREEN_WIDTH) + x] == 0)
screen.SetPixel(x, y, Color.Black);
else
screen.SetPixel(x, y, Color.White);
}
}
QueueDraw();
}
}
protected void OnDeleteEvent (object sender, DeleteEventArgs a)
{
hiResTimer.Enabled = false;
Application.Quit ();
a.RetVal = true;
}
private byte GetKeyFromMap(uint KeyValue)
{
for (byte i = 0; i < keymap.Length; i++) {
if (KeyValue == keymap[i]) {
return i;
}
}
return 255;
}
protected override bool OnKeyPressEvent (Gdk.EventKey evnt)
{
byte KeyValue = GetKeyFromMap(evnt.KeyValue);
if (KeyValue != 255) emulator.KeyDown(KeyValue);
return base.OnKeyPressEvent (evnt);
}
protected override bool OnKeyReleaseEvent (Gdk.EventKey evnt)
{
byte KeyValue = GetKeyFromMap(evnt.KeyValue);
if (KeyValue != 255) emulator.KeyUp(KeyValue);
return base.OnKeyReleaseEvent (evnt);
}
}