-
Notifications
You must be signed in to change notification settings - Fork 3
/
controller.js
160 lines (151 loc) · 3.91 KB
/
controller.js
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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// TI calculator simulator
// Ken Shirriff, http://righto.com/ti
// Based on patent US3934233
//
// This file is the controller, which connects together all the pieces.
var Controller = function(calcImage, model, keygrid, display, display2, sourceWindow, cpu,
registers, instruction, playButton, stopButton, stepButton) {
this.calcImage = calcImage;
this.model = model;
this.keygrid = keygrid;
this.display = display;
this.display2 = display2;
this.sourceWindow = sourceWindow;
this.cpu = cpu;
this.registers = registers;
this.lineCount = [];
this.calcImage.callback = function(key) {
if (key == 'POWER') {
if (model.power == 1) {
model.display = 0;
model.address = 0;
stopButton.click();
model.power = 0;
} else {
model.power = 1;
model.display = 1;
model.address = 0;
playButton.click();
}
this.updatePower();
return;
}
if (model.keyPressed == key) {
// toggle off
model.keyPressed = '';
} else {
model.keyPressed = key;
}
keygrid.update();
};
model.running = 0;
var that = this;
playButton.click(function() {
if (model.power == 0) {
return;
}
playButton.hide();
stopButton.show();
model.running = 1;
that.update();
});
stopButton.click(function() {
if (model.power == 0) {
return;
}
stopButton.hide();
playButton.show();
model.running = 0;
that.lineCount = [];
});
stepButton.click(function() {
if (model.power == 0) {
return;
} else if (model.running) {
stopButton.hide();
playButton.show();
model.running = 0;
} else {
if (model.fastStep == 0) {
that.update();
} else {
// Don't make user manually step 10 times through one instruction
var address = model.address;
while (model.address == address) {
that.update();
if (model.dActive == 1) {
break;
}
}
}
}
}
);
stopButton.hide();
// Post-cpu updates
var updateInt = function(skipUpdate) {
if (!skipUpdate) {
keygrid.update(model.idle ? 0 : 0 /* fast */);
display.update();
if (display2) {
display2.update();
}
registers.update();
instruction.update();
sourceWindow.update();
} else {
keygrid.update(1 /* fast */);
}
}
updateInt();
this.update = function() {
var iterations;
if (model.speed == 'slow' || !model.running) {
// Slow or single-stepping.
iterations = 1;
} else if (model.speed == 'fast') {
// Do 100 operations between GUI updates
iterations = 100;
} else if (model.speed == 'auto') {
iterations = 1;
}
for (var i = 0; i < iterations; i++) {
// Hack to detect idle loop. Release any pressed key.
if (model.sinclair) {
if (model.address == 0x6) {
model.keyPressed = '';
}
} else {
if (model.address == 0x22) {
model.keyPressed = '';
}
}
// Turbo-mode over lines that we keep hitting.
that.lineCount[model.address] = (that.lineCount[model.address] || 0) + 1;
if (that.lineCount[model.address] > 5) {
iterations += .99; // Skip 99% of repeated lines
}
if (model.rom[model.address] >> 4 == 0x52 && model.keyPressed == '') { // WAITNO
model.idle = 1;
that.lineCount = []; /* reset turbo */
} else {
model.idle = 0;
}
cpu.step();
updateInt(1 /* skip */);
// Get breakpoint query parameter
var breakpoint = (RegExp('breakpoint=' + '(.+?)(&|$)').exec(location.search)||[,null])[1];
// Stop if address hits breakpoint
if (breakpoint && parseInt(breakpoint, 16) == model.address) {
stopButton.click();
}
}
updateInt();
if (model.running) {
// Slow down the loop if we're in the idle loop to save CPU
var timeout = model.idle ? 250 : (model.speed == 'slow' ? 50 : 1);
setTimeout(that.update, timeout);
}
};
playButton.click(); // Start it running
};