/* Update LCD screen part */ int hid_update_lcd(void) { int i, j, k, l; uint8_t *lcd_bitmap = &tihw.ram[tihw.lcd_adr]; uint8_t *lcd_buf = (uint8_t *)lcd_bytmap; GdkRect src; guchar *p; tihw.lcd_ptr = (char *) &tihw.ram[tihw.lcd_adr]; if(!pixmap || !lcd_mem || !tihw.lcd_ptr) return 0; // Check for LCD state change (from TI HW) if(lcd_state != tihw.on_off) { lcd_state = tihw.on_off; lcd_changed = 1; if(!lcd_state) redraw_lcd(); // to clear LCD } // Check for contrast change (from TI HW) if(contrast != tihw.contrast) { gint c = contrast = tihw.contrast; new_contrast = (c + old_contrast) / 2; old_contrast = c; compute_grayscale(); lcd_changed = 1; } // Check for gray plane change (menu/hw) if(max_plane != ngc) { max_plane = ngc; compute_grayscale(); } // LCD off or unchanged: don't refresh ! if(!lcd_state || !lcd_changed) return 0; // Reset LCD changed flag. lcd_changed = 0; // Convert the bitmap screen to a bytemap screen and grayscalize memset(lcd_bytmap, 0, LCDMEM_H*LCDMEM_W); for(l = 0; l < 8; l++) { int pp = gp_seq[ngc][l]; if(pp == -1) break; lcd_bitmap = lcd_planebufs[pp]; for(j = 0, k = 0; k < LCDMEM_H; k++) { for(i = 0; i < LCDMEM_W/8; i++, lcd_bitmap++) { lcd_bytmap[j++] += convtab[(*lcd_bitmap << 1) ]; lcd_bytmap[j++] += convtab[(*lcd_bitmap << 1)+1]; } } } if(1) { // Copy LCD from buffer to pixbuf for(j = 0; j < LCDMEM_H; j++) { for (i = 0; i < LCDMEM_W; i++) { p = li.pixels + j * li.rowstride + i * li.n_channels; p[0] = grayscales[*lcd_buf].r; p[1] = grayscales[*lcd_buf].g; p[2] = grayscales[*lcd_buf].b; lcd_buf++; } } // Set region to update src.x = src.y = 0; src.w = (tihw.log_w > tihw.lcd_w) ? tihw.lcd_w : tihw.log_w; src.h = (tihw.log_h > tihw.lcd_h) ? tihw.lcd_h : tihw.log_h; // Copy surface into window if(sf) { src.w = (int)(sf * src.w); src.h = (int)(sf * src.h); // scale image g_object_unref(skin_infos.image); skin_infos.image = gdk_pixbuf_scale_simple(lcd, lr.w, lr.h, GDK_INTERP_NEAREST); // and draw image into pixmap (next, into window on expose event) gdk_draw_pixbuf(pixmap, main_wnd->style->fg_gc[GTK_WIDGET_STATE(main_wnd)], skin_infos.image, src.x, src.y, lr.x, lr.y, src.w, src.h, GDK_RGB_DITHER_NONE, 0, 0); gtk_widget_queue_draw_area(area, lr.x, lr.y, src.w, src.h); } else { // and draw image into pixmap (next, into window on expose event) gdk_draw_pixbuf(pixmap, main_wnd->style->fg_gc[GTK_WIDGET_STATE(main_wnd)], lcd_mem, src.x, src.y, lr.x, lr.y, src.w, src.h, GDK_RGB_DITHER_NONE, 0, 0); gtk_widget_queue_draw_area(area, lr.x, lr.y, src.w, src.h); } } // Screen shot if(!--skip_cnt && shot_cnt > 0) { skip_cnt = options2.skips; hid_screenshot_single(); shot_cnt--; } return -1; }
int hid_init(void) { // Found a PC keyboard keymap match_keymap(tihw.calc_type); // Load kbd keymap if(keymap_load(options.keys_file) == -1) { gchar *s = g_strdup_printf("unable to load this keymap: <%s>\n", options.keys_file); tiemu_error(0, s); g_free(s); return -1; } // Found a skin match_skin(tihw.calc_type); // Load skin (2 parts) if(skin_load(&skin_infos, options.skin_file) == -1) { gchar *s = g_strdup_printf("unable to load this skin: <%s>\n", options.skin_file); tiemu_error(0, s); g_free(s); return -1; } // Allocate the skn pixbuf (if needed) skn = skin_infos.image; // Set skin keymap depending on calculator type switch(tihw.calc_type) { case TI92: case TI92p: case V200: skn_keymap = sknKey92; break; case TI89: case TI89t: skn_keymap = sknKey89; break; default: { gchar *s = g_strdup_printf("no skin found for this calc\n"); tiemu_error(0, s); g_free(s); return -1; } } // Set window/LCD sizes set_scale(options.view); set_infos(); // Allocate the TI screen buffer lcd_bytmap = (uint32_t *)malloc(LCDMEM_W * LCDMEM_H); // Allocate the lcd pixbuf lcd = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, si.t * LCDMEM_W, si.t * LCDMEM_H); if(lcd == NULL) { gchar *s = g_strdup_printf("unable to create LCD pixbuf.\n"); tiemu_error(0, s); g_free(s); return -1; } // Used by TI89 (the LCD view is clipped from memory view) si.l = gdk_pixbuf_new_subpixbuf(lcd, 0, 0, tihw.lcd_w, tihw.lcd_h); // Constants for LCD update (speed-up) li.n_channels = gdk_pixbuf_get_n_channels (lcd); li.width = gdk_pixbuf_get_width (lcd); li.height = gdk_pixbuf_get_height (lcd); li.rowstride = gdk_pixbuf_get_rowstride (lcd); li.pixels = gdk_pixbuf_get_pixels (lcd); // Create main window display_main_wnd(); // Allocate the backing pixmap (used for drawing and refresh) pixmap = gdk_pixmap_new(main_wnd->window, wr.w, wr.h, -1); if(pixmap == NULL) { gchar *s = g_strdup_printf("unable to create backing pixbuf.\n"); tiemu_error(0, s); g_free(s); return -1; } // Draw the skin and compute grayscale palette redraw_skin(); compute_grayscale(); // Init the planar/chunky conversion table for LCD compute_convtable(); // Install LCD refresh: 100 FPS (10 ms) tid = g_timeout_add((params.lcd_rate == -1) ? 50 : params.lcd_rate, (GtkFunction)hid_refresh, NULL); gtk_widget_show(main_wnd); // show wnd here if(options.view == VIEW_FULL) gdk_window_fullscreen(main_wnd->window); return 0; }