comparison sms.c @ 2534:35dbe1873c8f

Speed up pasting and do some prep for pasting characters that need keys pressed in sequence
author Michael Pavone <pavone@retrodev.com>
date Wed, 27 Nov 2024 16:43:56 -0800
parents f4a471730ba4
children 0c6519125a28
comparison
equal deleted inserted replaced
2533:bebc3589dedf 2534:35dbe1873c8f
24 TAPE_STOPPED, 24 TAPE_STOPPED,
25 TAPE_PLAYING, 25 TAPE_PLAYING,
26 TAPE_RECORDING 26 TAPE_RECORDING
27 }; 27 };
28 28
29 #define PASTE_DELAY 3420 * 16 29 #define PASTE_DELAY (3420 * 16)
30 30
31 static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value) 31 static void *memory_io_write(uint32_t location, void *vcontext, uint8_t value)
32 { 32 {
33 z80_context *z80 = vcontext; 33 z80_context *z80 = vcontext;
34 sms_context *sms = z80->system; 34 sms_context *sms = z80->system;
231 } 231 }
232 } 232 }
233 233
234 typedef struct { 234 typedef struct {
235 uint8_t main; 235 uint8_t main;
236 uint8_t mod1; 236 uint8_t mod;
237 uint8_t mod2; 237 uint8_t before;
238 uint8_t after;
238 } cp_keys; 239 } cp_keys;
239 240
240 static cp_keys cp_to_keys(int cp) 241 static cp_keys cp_to_keys(int cp)
241 { 242 {
242 uint8_t shift = 0; 243 uint8_t shift = 0;
250 //accented latin letters only have a single case 251 //accented latin letters only have a single case
251 cp -= 0xE0 - 0xC0; 252 cp -= 0xE0 - 0xC0;
252 } 253 }
253 switch (cp) 254 switch (cp)
254 { 255 {
255 case '0': return (cp_keys){0x45, 0, 0}; 256 case '0': return (cp_keys){0x45};
256 case '1': return (cp_keys){0x16, shift, 0}; 257 case '1': return (cp_keys){0x16, shift};
257 case '2': return (cp_keys){0x1E, shift, 0}; 258 case '2': return (cp_keys){0x1E, shift};
258 case '3': return (cp_keys){0x26, shift, 0}; 259 case '3': return (cp_keys){0x26, shift};
259 case '4': return (cp_keys){0x25, shift, 0}; 260 case '4': return (cp_keys){0x25, shift};
260 case '5': return (cp_keys){0x2E, shift, 0}; 261 case '5': return (cp_keys){0x2E, shift};
261 case '6': return (cp_keys){0x36, shift, 0}; 262 case '6': return (cp_keys){0x36, shift};
262 case '7': return (cp_keys){0x3D, shift, 0}; 263 case '7': return (cp_keys){0x3D, shift};
263 case '8': return (cp_keys){0x3E, shift, 0}; 264 case '8': return (cp_keys){0x3E, shift};
264 case '9': return (cp_keys){0x46, shift, 0}; 265 case '9': return (cp_keys){0x46, shift};
265 case 'A': return (cp_keys){0x1C, shift, 0}; 266 case 'A': return (cp_keys){0x1C, shift};
266 case 'B': return (cp_keys){0x32, shift, 0}; 267 case 'B': return (cp_keys){0x32, shift};
267 case 'C': return (cp_keys){0x21, shift, 0}; 268 case 'C': return (cp_keys){0x21, shift};
268 case 'D': return (cp_keys){0x23, shift, 0}; 269 case 'D': return (cp_keys){0x23, shift};
269 case 'E': return (cp_keys){0x24, shift, 0}; 270 case 'E': return (cp_keys){0x24, shift};
270 case 'F': return (cp_keys){0x2B, shift, 0}; 271 case 'F': return (cp_keys){0x2B, shift};
271 case 'G': return (cp_keys){0x34, shift, 0}; 272 case 'G': return (cp_keys){0x34, shift};
272 case 'H': return (cp_keys){0x33, shift, 0}; 273 case 'H': return (cp_keys){0x33, shift};
273 case 'I': return (cp_keys){0x43, shift, 0}; 274 case 'I': return (cp_keys){0x43, shift};
274 case 'J': return (cp_keys){0x3B, shift, 0}; 275 case 'J': return (cp_keys){0x3B, shift};
275 case 'K': return (cp_keys){0x42, shift, 0}; 276 case 'K': return (cp_keys){0x42, shift};
276 case 'L': return (cp_keys){0x4B, shift, 0}; 277 case 'L': return (cp_keys){0x4B, shift};
277 case 'M': return (cp_keys){0x3A, shift, 0}; 278 case 'M': return (cp_keys){0x3A, shift};
278 case 'N': return (cp_keys){0x31, shift, 0}; 279 case 'N': return (cp_keys){0x31, shift};
279 case 'O': return (cp_keys){0x44, shift, 0}; 280 case 'O': return (cp_keys){0x44, shift};
280 case 'P': return (cp_keys){0x4D, shift, 0}; 281 case 'P': return (cp_keys){0x4D, shift};
281 case 'Q': return (cp_keys){0x15, shift, 0}; 282 case 'Q': return (cp_keys){0x15, shift};
282 case 'R': return (cp_keys){0x2D, shift, 0}; 283 case 'R': return (cp_keys){0x2D, shift};
283 case 'S': return (cp_keys){0x1B, shift, 0}; 284 case 'S': return (cp_keys){0x1B, shift};
284 case 'T': return (cp_keys){0x2C, shift, 0}; 285 case 'T': return (cp_keys){0x2C, shift};
285 case 'U': return (cp_keys){0x3C, shift, 0}; 286 case 'U': return (cp_keys){0x3C, shift};
286 case 'V': return (cp_keys){0x2A, shift, 0}; 287 case 'V': return (cp_keys){0x2A, shift};
287 case 'W': return (cp_keys){0x1D, shift, 0}; 288 case 'W': return (cp_keys){0x1D, shift};
288 case 'X': return (cp_keys){0x22, shift, 0}; 289 case 'X': return (cp_keys){0x22, shift};
289 case 'Y': return (cp_keys){0x35, shift, 0}; 290 case 'Y': return (cp_keys){0x35, shift};
290 case 'Z': return (cp_keys){0x1A, shift, 0}; 291 case 'Z': return (cp_keys){0x1A, shift};
291 case '-': return (cp_keys){0x4E, 0, 0}; 292 case '-': return (cp_keys){0x4E};
292 case '=': return (cp_keys){0x4E, 0x12, 0}; 293 case '=': return (cp_keys){0x4E, 0x12};
293 case ';': return (cp_keys){0x4C, 0, 0}; 294 case ';': return (cp_keys){0x4C};
294 case '+': return (cp_keys){0x4C, 0x12, 0}; 295 case '+': return (cp_keys){0x4C, 0x12};
295 case ':': return (cp_keys){0x52, 0, 0}; 296 case ':': return (cp_keys){0x52};
296 case '*': return (cp_keys){0x52, 0x12, 0}; 297 case '*': return (cp_keys){0x52, 0x12};
297 case ',': return (cp_keys){0x41, 0, 0}; 298 case ',': return (cp_keys){0x41};
298 case '<': return (cp_keys){0x41, 0x12, 0}; 299 case '<': return (cp_keys){0x41, 0x12};
299 case '.': return (cp_keys){0x49, 0, 0}; 300 case '.': return (cp_keys){0x49};
300 case '>': return (cp_keys){0x49, 0x12, 0}; 301 case '>': return (cp_keys){0x49, 0x12};
301 case '/': return (cp_keys){0x4A, 0, 0}; 302 case '/': return (cp_keys){0x4A};
302 case '?': return (cp_keys){0x4A, 0x12, 0}; 303 case '?': return (cp_keys){0x4A, 0x12};
303 case '^': return (cp_keys){0x55, 0, 0}; 304 case '^': return (cp_keys){0x55};
304 case '~': return (cp_keys){0x55, 0x12, 0}; 305 case '~': return (cp_keys){0x55, 0x12};
305 case '[': return (cp_keys){0x54, 0, 0}; 306 case '[': return (cp_keys){0x54};
306 case '{': return (cp_keys){0x54, 0x12, 0}; 307 case '{': return (cp_keys){0x54, 0x12};
307 case ']': return (cp_keys){0x5B, 0, 0}; 308 case ']': return (cp_keys){0x5B};
308 case '}': return (cp_keys){0x5B, 0x12, 0}; 309 case '}': return (cp_keys){0x5B, 0x12};
309 case '@': return (cp_keys){0x85, 0, 0}; 310 case '@': return (cp_keys){0x85};
310 case '`': return (cp_keys){0x85, 0x12, 0}; 311 case '`': return (cp_keys){0x85, 0x12};
311 case '\n': return (cp_keys){0x5A, 0, 0}; 312 case '\n': return (cp_keys){0x5A};
312 case ' ': return (cp_keys){0x29, 0, 0}; 313 case ' ': return (cp_keys){0x29};
313 case 0xA5: return (cp_keys){0x5D, 0, 0};//¥ 314 case 0xA5: return (cp_keys){0x5D};//¥
314 //Accented latin letters will only work right with export BASIC 315 //Accented latin letters will only work right with export BASIC
315 case 0xA1: return (cp_keys){0x32, 0x81, 0};//¡ 316 case 0xA1: return (cp_keys){0x32, 0x81};//¡
316 case 0xA3: return (cp_keys){0x5D, 0x81, 0};//£ 317 case 0xA3: return (cp_keys){0x5D, 0x81};//£
317 case 0xBF: return (cp_keys){0x2A, 0x81, 0};//¿ 318 case 0xBF: return (cp_keys){0x2A, 0x81};//¿
318 case 0xC0: return (cp_keys){0x1D, 0x81, 0};//À 319 case 0xC0: return (cp_keys){0x1D, 0x81};//À
319 case 0xC1: return (cp_keys){0x15, 0x81, 0};//Á 320 case 0xC1: return (cp_keys){0x15, 0x81};//Á
320 case 0xC2: return (cp_keys){0x16, 0x81, 0};//Â 321 case 0xC2: return (cp_keys){0x16, 0x81};//Â
321 case 0xC3: return (cp_keys){0x23, 0x81, 0};//Ã 322 case 0xC3: return (cp_keys){0x23, 0x81};//Ã
322 case 0xC4: return (cp_keys){0x1C, 0x81, 0};//Ä 323 case 0xC4: return (cp_keys){0x1C, 0x81};//Ä
323 case 0xC5: return (cp_keys){0x1B, 0x81, 0};//Å 324 case 0xC5: return (cp_keys){0x1B, 0x81};//Å
324 case 0xC7: return (cp_keys){0x21, 0x81, 0};//Ç 325 case 0xC7: return (cp_keys){0x21, 0x81};//Ç
325 case 0xC8: return (cp_keys){0x2D, 0x81, 0};//È 326 case 0xC8: return (cp_keys){0x2D, 0x81};//È
326 case 0xC9: return (cp_keys){0x24, 0x81, 0};//É 327 case 0xC9: return (cp_keys){0x24, 0x81};//É
327 case 0xCA: return (cp_keys){0x26, 0x81, 0};//Ê 328 case 0xCA: return (cp_keys){0x26, 0x81};//Ê
328 case 0xCB: return (cp_keys){0x2E, 0x81, 0};//Ë 329 case 0xCB: return (cp_keys){0x2E, 0x81};//Ë
329 case 0xCC: return (cp_keys){0x44, 0x81, 0};//Ì 330 case 0xCC: return (cp_keys){0x44, 0x81};//Ì
330 case 0xCD: return (cp_keys){0x4B, 0x81, 0};//Í 331 case 0xCD: return (cp_keys){0x4B, 0x81};//Í
331 case 0xCE: return (cp_keys){0x49, 0x81, 0};//Î 332 case 0xCE: return (cp_keys){0x49, 0x81};//Î
332 case 0xCF: return (cp_keys){0x4C, 0x81, 0};//Ï 333 case 0xCF: return (cp_keys){0x4C, 0x81};//Ï
333 case 0xD1: return (cp_keys){0x2C, 0x81, 0};//Ñ 334 case 0xD1: return (cp_keys){0x2C, 0x81};//Ñ
334 case 0xD2: return (cp_keys){0x85, 0x81, 0};//Ò 335 case 0xD2: return (cp_keys){0x85, 0x81};//Ò
335 case 0xD3: return (cp_keys){0x4D, 0x81, 0};//Ó 336 case 0xD3: return (cp_keys){0x4D, 0x81};//Ó
336 case 0xD4: return (cp_keys){0x45, 0x81, 0};//Ô 337 case 0xD4: return (cp_keys){0x45, 0x81};//Ô
337 case 0xD5: return (cp_keys){0x0E, 0x81, 0};//Õ 338 case 0xD5: return (cp_keys){0x0E, 0x81};//Õ
338 case 0xD6: return (cp_keys){0x52, 0x81, 0};//Ö 339 case 0xD6: return (cp_keys){0x52, 0x81};//Ö
339 //character in font doesn't really look like a phi to me 340 //character in font doesn't really look like a phi to me
340 //but Wikipedia lists it as such 341 //but Wikipedia lists it as such
341 case 0x3A6: //Φ 342 case 0x3A6: //Φ
342 case 0xD8: return (cp_keys){0x54, 0x81, 0};//Ø 343 case 0xD8: return (cp_keys){0x54, 0x81};//Ø
343 case 0xD9: return (cp_keys){0x43, 0x81, 0};//Ù 344 case 0xD9: return (cp_keys){0x43, 0x81};//Ù
344 case 0xDA: return (cp_keys){0x3C, 0x81, 0};//Ú 345 case 0xDA: return (cp_keys){0x3C, 0x81};//Ú
345 case 0xDB: return (cp_keys){0x3D, 0x81, 0};//Û 346 case 0xDB: return (cp_keys){0x3D, 0x81};//Û
346 case 0xDC: return (cp_keys){0x42, 0x81, 0};//Ü 347 case 0xDC: return (cp_keys){0x42, 0x81};//Ü
347 case 0x3A3: return (cp_keys){0x5B, 0x81, 0};//Σ 348 case 0x3A3: return (cp_keys){0x5B, 0x81};//Σ
348 case 0x3A9: return (cp_keys){0x3A, 0x81, 0};//Ω 349 case 0x3A9: return (cp_keys){0x3A, 0x81};//Ω
349 case 0x3B1: return (cp_keys){0x34, 0x81, 0};//α 350 case 0x3B1: return (cp_keys){0x34, 0x81};//α
350 case 0x3B2: return (cp_keys){0x33, 0x81, 0};//β 351 case 0x3B2: return (cp_keys){0x33, 0x81};//β
351 case 0x3B8: return (cp_keys){0x3B, 0x81, 0};//θ 352 case 0x3B8: return (cp_keys){0x3B, 0x81};//θ
352 case 0x3BB: return (cp_keys){0x22, 0x81, 0};//λ 353 case 0x3BB: return (cp_keys){0x22, 0x81};//λ
353 case 0xB5://µ 354 case 0xB5://µ
354 case 0x3BC: return (cp_keys){0x1A, 0x81, 0};//μ 355 case 0x3BC: return (cp_keys){0x1A, 0x81};//μ
355 case 0x3C0: return (cp_keys){0x0E, 0x12, 0};//π 356 case 0x3C0: return (cp_keys){0x0E, 0x12};//π
356 default: return (cp_keys){0,0,0}; 357 default: return (cp_keys){0};
357 } 358 }
358 } 359 }
359 360
360 static void advance_paste_buffer(sms_context *sms, const char *paste) 361 static void advance_paste_buffer(sms_context *sms, const char *paste)
361 { 362 {
365 } else { 366 } else {
366 sms->header.paste_cur_char = paste - sms->header.paste_buffer; 367 sms->header.paste_cur_char = paste - sms->header.paste_buffer;
367 } 368 }
368 } 369 }
369 370
371
372 static uint8_t paste_internal(sms_context *sms, uint8_t prev_key)
373 {
374 const char *paste = sms->header.paste_buffer + sms->header.paste_cur_char;
375 int cp = utf8_codepoint(&paste);
376 cp_keys keys = cp_to_keys(cp);
377 if (!keys.main) {
378 advance_paste_buffer(sms, paste);
379 return 0;
380 }
381 if (sms->paste_toggle) {
382 //key up
383 sms->header.keyboard_up(&sms->header, keys.main);
384 if (keys.mod) {
385 sms->header.keyboard_up(&sms->header, keys.mod);
386 }
387 advance_paste_buffer(sms, paste);
388 } else {
389 //key down
390 if (prev_key == keys.main) {
391 // we're pressing the key that was just released, we need to wait to the next scan
392 return 0;
393 }
394 sms->header.keyboard_down(&sms->header, keys.main);
395 if (keys.mod) {
396 sms->header.keyboard_down(&sms->header, keys.mod);
397 }
398 }
399 sms->paste_toggle = !sms->paste_toggle;
400 return keys.main;
401 }
402
370 static void process_paste(sms_context *sms, uint32_t cycle) 403 static void process_paste(sms_context *sms, uint32_t cycle)
371 { 404 {
372 if (sms->header.paste_buffer && cycle > sms->last_paste_cycle && cycle - sms->last_paste_cycle >= PASTE_DELAY) { 405 if (sms->header.paste_buffer && cycle > sms->last_paste_cycle && cycle - sms->last_paste_cycle >= PASTE_DELAY) {
373 const char *paste = sms->header.paste_buffer + sms->header.paste_cur_char; 406
374 int cp = utf8_codepoint(&paste); 407 uint8_t main_key;
375 cp_keys keys = cp_to_keys(cp); 408 if ((main_key = paste_internal(sms, 0))) {
376 if (!keys.main) { 409 sms->last_paste_cycle = cycle;
377 advance_paste_buffer(sms, paste); 410 if (sms->header.paste_buffer && !sms->paste_toggle) {
378 return; 411 paste_internal(sms, main_key);
379 }
380 if (sms->paste_toggle) {
381 //key up
382 sms->header.keyboard_up(&sms->header, keys.main);
383 if (keys.mod1) {
384 sms->header.keyboard_up(&sms->header, keys.mod1);
385 if (keys.mod2) {
386 sms->header.keyboard_up(&sms->header, keys.mod2);
387 }
388 } 412 }
389 advance_paste_buffer(sms, paste); 413 }
390 } else {
391 //key down
392 sms->header.keyboard_down(&sms->header, keys.main);
393 if (keys.mod1) {
394 sms->header.keyboard_down(&sms->header, keys.mod1);
395 if (keys.mod2) {
396 sms->header.keyboard_down(&sms->header, keys.mod2);
397 }
398 }
399 }
400 sms->paste_toggle = !sms->paste_toggle;
401 sms->last_paste_cycle = cycle;
402 } 414 }
403 } 415 }
404 416
405 static uint8_t i8255_input_poll(i8255 *ppi, uint32_t cycle, uint32_t port) 417 static uint8_t i8255_input_poll(i8255 *ppi, uint32_t cycle, uint32_t port)
406 { 418 {