Example program for the Cidco MailStation Z80 computer
1#!/usr/bin/env ruby
2#
3# generate scancode lookup tables
4# Copyright (c) 2019 joshua stein <jcs@jcs.org>
5#
6# Permission to use, copy, modify, and distribute this software for any
7# purpose with or without fee is hereby granted, provided that the above
8# copyright notice and this permission notice appear in all copies.
9#
10# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17#
18
19META_KEY_BEGIN = 200
20
21KEYS = [
22 :MAIN_MENU,
23 :BACK,
24 :PRINT,
25 :F1,
26 :F2,
27 :F3,
28 :F4,
29 :F5,
30 :POWER,
31 :SIZE,
32 :SPELLING,
33 :EMAIL,
34 :PAGE_UP,
35 :PAGE_DOWN,
36 :CAPS_LOCK,
37 :LEFT_SHIFT,
38 :RIGHT_SHIFT,
39 :FN,
40 :UP,
41 :DOWN,
42 :LEFT,
43 :RIGHT,
44]
45
46META_KEY_NONE = 255
47
48UPPERCASES = {
49 "`" => "~",
50 "1" => "!",
51 "2" => "@",
52 "3" => "#",
53 "4" => "$",
54 "5" => "%",
55 "6" => "^",
56 "7" => "&",
57 "8" => "*",
58 "9" => "(",
59 "0" => ")",
60 "-" => "_",
61 "=" => "+",
62 "\\" => "|",
63 "[" => "{",
64 "]" => "}",
65 ";" => ":",
66 "'" => "\"",
67 "," => "<",
68 "." => ">",
69 "/" => "?",
70}
71
72CONTROLS = {
73 "a" => 1,
74 "b" => 2,
75 "c" => 3,
76 "d" => 4,
77 "e" => 5,
78 "f" => 6,
79 "g" => 7,
80 "h" => 8,
81 "i" => 9,
82 "j" => 10,
83 "k" => 11,
84 "l" => 12,
85 "m" => 13,
86 "n" => 14,
87 "o" => 15,
88 "p" => 16,
89 "q" => 17,
90 "r" => 18,
91 "s" => 19,
92 "t" => 20,
93 "u" => 21,
94 "v" => 22,
95 "w" => 23,
96 "x" => 24,
97 "y" => 25,
98 "z" => 26,
99 "3" => 27,
100 "[" => 27,
101 "4" => 28,
102 "\\" => 28,
103 "5" => 29,
104 "]" => 29,
105 "6" => 30,
106 "7" => 31,
107 "-" => 31,
108 "/" => 31,
109 "8" => 127,
110}
111
112SCANCODES = {
113 0 => :MAIN_MENU,
114 1 => :BACK,
115 2 => :PRINT,
116 3 => :F1,
117 4 => :F2,
118 5 => :F3,
119 6 => :F4,
120 7 => :F5,
121 15 => :POWER,
122 19 => "@",
123 20 => :SIZE,
124 21 => :SPELLING,
125 22 => :EMAIL,
126 23 => :PAGE_UP,
127 32 => "`",
128 33 => "1",
129 34 => "2",
130 35 => "3",
131 36 => "4",
132 37 => "5",
133 38 => "6",
134 39 => "7",
135 48 => "8",
136 49 => "9",
137 50 => "0",
138 51 => "-",
139 52 => "=",
140 53 => "\b", # backspace
141 54 => "\\",
142 55 => :PAGE_DOWN,
143 64 => "\t",
144 65 => "q",
145 66 => "w",
146 67 => "e",
147 68 => "r",
148 69 => "t",
149 70 => "y",
150 71 => "u",
151 80 => "i",
152 81 => "o",
153 82 => "p",
154 83 => "[",
155 84 => "]",
156 85 => ";",
157 86 => "'",
158 87 => "\n",
159 96 => :CAPS_LOCK,
160 97 => "a",
161 98 => "s",
162 99 => "d",
163 100 => "f",
164 101 => "g",
165 102 => "h",
166 103 => "j",
167 112 => "k",
168 113 => "l",
169 114 => ",",
170 115 => ".",
171 116 => "/",
172 117 => :UP,
173 118 => :DOWN,
174 119 => :RIGHT,
175 128 => :LEFT_SHIFT,
176 129 => "z",
177 130 => "x",
178 131 => "c",
179 132 => "v",
180 133 => "b",
181 134 => "n",
182 135 => "m",
183 144 => :FN,
184 147 => " ",
185 150 => :RIGHT_SHIFT,
186 151 => :LEFT,
187}
188
189File.open("#{__dir__}/../scancodes.inc", "w+") do |scf|
190 scf.puts "; AUTOMATICALLY GENERATED FILE - see tools/generate_scancodes.rb"
191 scf.puts "\t.equ\tMETA_KEY_BEGIN,\t#0d#{sprintf("%03d", META_KEY_BEGIN)}"
192 scf.puts "\t.equ\tMETA_KEY_NONE,\t#0d#{sprintf("%03d", META_KEY_NONE)}"
193 scf.puts
194
195 3.times do |x|
196 if x == 0
197 scf.puts "scancode_table:"
198 elsif x == 1
199 scf.puts
200 scf.puts "scancode_table_uppercase:"
201 elsif x == 2
202 scf.puts
203 scf.puts "scancode_table_control:"
204 end
205
206 (0 .. SCANCODES.keys.last).each do |sc|
207 if k = SCANCODES[sc]
208 origk = k
209 if k.is_a?(Symbol)
210 k = META_KEY_BEGIN + KEYS.index(k)
211 elsif k.is_a?(String)
212 k = k.ord
213 end
214 raise if !k
215
216 if x == 1
217 if u = UPPERCASES[origk]
218 k = u.ord
219 origk = u
220 elsif ("a" .. "z").include?(origk)
221 k = origk.upcase.ord
222 origk = origk.upcase
223 end
224 elsif x == 2
225 if u = CONTROLS[origk]
226 k = u
227 origk = u
228 end
229 end
230
231 scf.puts "\t.db #0d#{sprintf("%03d", k)}\t\t; #{origk.inspect}"
232 else
233 scf.puts "\t.db #0d#{sprintf("%03d", META_KEY_NONE)}"
234 end
235 end
236 end
237end
238
239File.open("#{__dir__}/../meta_keys.h", "w+") do |mkh|
240 mkh.puts "/* AUTOMATICALLY GENERATED FILE - see tools/generate_scancodes.rb */"
241 mkh.puts "#define\tMETA_KEY_BEGIN\t#{META_KEY_BEGIN}"
242
243 KEYS.each_with_index do |k,x|
244 mkh.puts "#define\tKEY_#{k}\t#{k.length < 3 ? "\t" : ""}#{META_KEY_BEGIN + x}"
245 end
246
247 mkh.puts
248 mkh.puts "#define\tMETA_KEY_NONE\t#{META_KEY_NONE}"
249end