Mercurial > repos > blastem
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 { |