-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathC64Key.swift
More file actions
311 lines (266 loc) · 10.7 KB
/
C64Key.swift
File metadata and controls
311 lines (266 loc) · 10.7 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
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
//
// This file is part of VirtualC64 - A cycle accurate Commodore 64 emulator
//
// Copyright (C) Dirk W. Hoffmann. www.dirkwhoffmann.de
// Licensed under the GNU General Public License v3
//
// See https://www.gnu.org for license information
//
// swiftlint:disable comma
import Foundation
/// The C64Key structure represents a physical keys on the C64 keyboard.
/// Each of the 66 keys is specified uniquely by it's number ranging from
/// 0 to 64. When a key is pressed, a row bit and a column bit is set in the
/// keyboard matrix that can be read by the CIA chip. Note that the CapsLock
/// and the Restore key behave differently. Caps lock is a switch that holds
/// down the left shift key until it is released and restore has no key matrix
/// representation at all. Instead, it is directly connected to the NMI line.
struct C64Key: Codable {
// A number that identifies this key uniquely
var nr = -1
// Row index
var row = -1
// Column index
var col = -1
// Flags for key modifiers
let DEFAULT = 0
let SHIFT = 1
let COMMODORE = 2
let LOWER = 4
init(_ nr: Int) {
precondition(nr >= 0 && nr <= 65)
let rowcol = [
// First physical key row
(7, 1), (7, 0), (7, 3), (1, 0), (1, 3), (2, 0), (2, 3), (3, 0),
(3, 3), (4, 0), (4, 3), (5, 0), (5, 3), (6, 0), (6, 3), (0, 0),
(0, 4) /* f1 */,
// Second physical key row
(7, 2), (7, 6), (1, 1), (1, 6), (2, 1), (2, 6), (3, 1), (3, 6),
(4, 1), (4, 6), (5, 1), (5, 6), (6, 1), (6, 6), (9, 9), (0, 5) /* f3 */,
// Third physical key row
(7, 7), (9, 9), (1, 2), (1, 5), (2, 2), (2, 5), (3, 2), (3, 5),
(4, 2), (4, 5), (5, 2), (5, 5), (6, 2), (6, 5), (0, 1), (0, 6) /* f5 */,
// Fourth physical key row
(7, 5), (1, 7), (1, 4), (2, 7), (2, 4), (3, 7), (3, 4), (4, 7),
(4, 4), (5, 7), (5, 4), (6, 7), (6, 4), (0, 7), (0, 2), (0, 3) /* f7 */,
// Fifth physical key row
(7, 4) /* space */
]
precondition(rowcol.count == 66)
self.nr = nr
if nr != 31 /* RESTORE */ && nr != 34 /* SHIFT LOCK */ {
self.row = rowcol[nr].0
self.col = rowcol[nr].1
} else {
precondition(rowcol[nr].0 == 9 && rowcol[nr].1 == 9)
}
}
init(_ rowcol: (Int, Int) ) {
precondition(rowcol.0 >= 0 && rowcol.0 < 8)
precondition(rowcol.1 >= 0 && rowcol.1 < 8)
let nr = [ 15, 47, 63, 64, 16, 32, 48, 62,
3, 19, 35, 4, 51, 36, 20, 50,
5, 21, 37, 6, 53, 38, 22, 52,
7, 23, 39, 8, 55, 40, 24, 54,
9, 25, 41, 10, 57, 42, 26, 56,
11, 27, 43, 12, 59, 44, 28, 58,
13, 29, 45, 14, 61, 46, 30, 60,
1, 0, 17, 2, 65, 49, 18, 33
]
precondition(nr.count == 64)
self.row = rowcol.0
self.col = rowcol.1
self.nr = nr[8 * row + col]
}
}
extension C64Key: Equatable {
static func == (lhs: C64Key, rhs: C64Key) -> Bool {
return lhs.nr == rhs.nr
}
}
extension C64Key: Hashable {
func hash(into hasher: inout Hasher) {
return hasher.combine(nr)
}
}
extension C64Key {
// First row
static let delete = C64Key(15)
static let ret = C64Key(47)
static let curLeftRight = C64Key(63)
static let F7F8 = C64Key(64)
static let F1F2 = C64Key(16)
static let F3F4 = C64Key(32)
static let F5F6 = C64Key(48)
static let curUpDown = C64Key(62)
// Second row
static let digit3 = C64Key(3)
static let W = C64Key(19)
static let A = C64Key(35)
static let digit4 = C64Key(4)
static let Z = C64Key(51)
static let S = C64Key(36)
static let E = C64Key(20)
static let shift = C64Key(50)
// Third row
static let digit5 = C64Key(5)
static let R = C64Key(21)
static let D = C64Key(37)
static let digit6 = C64Key(6)
static let C = C64Key(53)
static let F = C64Key(38)
static let T = C64Key(22)
static let X = C64Key(52)
// Fourth row
static let digit7 = C64Key(7)
static let Y = C64Key(23)
static let G = C64Key(39)
static let digit8 = C64Key(8)
static let B = C64Key(55)
static let H = C64Key(40)
static let U = C64Key(24)
static let V = C64Key(54)
// Fifth row
static let digit9 = C64Key(9)
static let I = C64Key(25)
static let J = C64Key(41)
static let digit0 = C64Key(10)
static let M = C64Key(57)
static let K = C64Key(42)
static let O = C64Key(26)
static let N = C64Key(56)
// Sixth row
static let plus = C64Key(11)
static let P = C64Key(27)
static let L = C64Key(43)
static let minus = C64Key(12)
static let period = C64Key(59)
static let colon = C64Key(44)
static let at = C64Key(28)
static let comma = C64Key(58)
// Seventh row
static let pound = C64Key(13)
static let asterisk = C64Key(29)
static let semicolon = C64Key(45)
static let home = C64Key(14)
static let rightShift = C64Key(61)
static let equal = C64Key(46)
static let upArrow = C64Key(30)
static let slash = C64Key(60)
// Eights row
static let digit1 = C64Key(1)
static let leftArrow = C64Key(0)
static let control = C64Key(17)
static let digit2 = C64Key(2)
static let space = C64Key(65)
static let commodore = C64Key(49)
static let Q = C64Key(18)
static let runStop = C64Key(33)
// Restore key
static let restore = C64Key(31)
// Translates a character to a list of corresponding C64 keys
// This function is used for symbolically mapping Mac keys to C64 keys
static func translate(char: String?) -> [C64Key] {
if char == nil { return [] }
switch char! {
// First row of C64 keyboard
case "ü": return [C64Key.leftArrow]
case "1": return [C64Key.digit1]
case "!": return [C64Key.digit1, C64Key.shift]
case "2": return [C64Key.digit2]
case "\"": return [C64Key.digit2, C64Key.shift]
case "3": return [C64Key.digit3]
case "#": return [C64Key.digit3, C64Key.shift]
case "4": return [C64Key.digit4]
case "$": return [C64Key.digit4, C64Key.shift]
case "5": return [C64Key.digit5]
case "%": return [C64Key.digit5, C64Key.shift]
case "6": return [C64Key.digit6]
case "&": return [C64Key.digit6, C64Key.shift]
case "7": return [C64Key.digit7]
case "'": return [C64Key.digit7, C64Key.shift]
case "8": return [C64Key.digit8]
case "(": return [C64Key.digit8, C64Key.shift]
case "9": return [C64Key.digit9]
case ")": return [C64Key.digit9, C64Key.shift]
case "0": return [C64Key.digit0]
case "+": return [C64Key.plus]
case "-": return [C64Key.minus]
case "§": return [C64Key.pound]
// Second row of C64 keyboard
case "q": return [C64Key.Q]
case "Q": return [C64Key.Q, C64Key.shift]
case "w": return [C64Key.W]
case "W": return [C64Key.W, C64Key.shift]
case "e": return [C64Key.E]
case "E": return [C64Key.E, C64Key.shift]
case "r": return [C64Key.R]
case "R": return [C64Key.R, C64Key.shift]
case "t": return [C64Key.T]
case "T": return [C64Key.T, C64Key.shift]
case "y": return [C64Key.Y]
case "Y": return [C64Key.Y, C64Key.shift]
case "u": return [C64Key.U]
case "U": return [C64Key.U, C64Key.shift]
case "i": return [C64Key.I]
case "I": return [C64Key.I, C64Key.shift]
case "o": return [C64Key.O]
case "O": return [C64Key.O, C64Key.shift]
case "p": return [C64Key.P]
case "P": return [C64Key.P, C64Key.shift]
case "@": return [C64Key.at]
case "ö": return [C64Key.at]
case "*": return [C64Key.asterisk]
case "ä": return [C64Key.upArrow]
// Third row of C64 keyboard
case "a": return [C64Key.A]
case "A": return [C64Key.A, C64Key.shift]
case "s": return [C64Key.S]
case "S": return [C64Key.S, C64Key.shift]
case "d": return [C64Key.D]
case "D": return [C64Key.D, C64Key.shift]
case "f": return [C64Key.F]
case "F": return [C64Key.F, C64Key.shift]
case "g": return [C64Key.G]
case "G": return [C64Key.G, C64Key.shift]
case "h": return [C64Key.H]
case "H": return [C64Key.H, C64Key.shift]
case "j": return [C64Key.J]
case "J": return [C64Key.J, C64Key.shift]
case "k": return [C64Key.K]
case "K": return [C64Key.K, C64Key.shift]
case "l": return [C64Key.L]
case "L": return [C64Key.L, C64Key.shift]
case ":": return [C64Key.colon]
case "[": return [C64Key.colon, C64Key.shift]
case ";": return [C64Key.semicolon]
case "]": return [C64Key.semicolon, C64Key.shift]
case "=": return [C64Key.equal]
case "\n": return [C64Key.ret]
// Fourth row of C64 keyboard
case "z": return [C64Key.Z]
case "Z": return [C64Key.Z, C64Key.shift]
case "x": return [C64Key.X]
case "X": return [C64Key.X, C64Key.shift]
case "c": return [C64Key.C]
case "C": return [C64Key.C, C64Key.shift]
case "v": return [C64Key.V]
case "V": return [C64Key.V, C64Key.shift]
case "b": return [C64Key.B]
case "B": return [C64Key.B, C64Key.shift]
case "n": return [C64Key.N]
case "N": return [C64Key.N, C64Key.shift]
case "m": return [C64Key.M]
case "M": return [C64Key.M, C64Key.shift]
case ",": return [C64Key.comma]
case "<": return [C64Key.comma, C64Key.shift]
case ".": return [C64Key.period]
case ">": return [C64Key.period, C64Key.shift]
case "/": return [C64Key.slash]
case "?": return [C64Key.slash, C64Key.shift]
// Fifth row of C64 keyboard
case " ": return [C64Key.space]
default: return []
}
}
}