static int perform_mode_change(raster_t *raster) { if (!video_disabled_mode && raster->canvas && raster->canvas->palette != NULL) { if (video_canvas_set_palette(raster->canvas, raster->canvas->palette) < 0) { return -1; } } raster_force_repaint(raster); video_viewport_resize(raster->canvas, 1); return 0; }
static int perform_mode_change(raster_t *raster) { if (!video_disabled_mode && raster->canvas && raster->canvas->palette != NULL) { if (video_canvas_set_palette(raster->canvas, raster->canvas->palette) < 0) return -1; } raster_force_repaint(raster); /* FIXME: `video_viewport_resize()' already calls `video_canvas_resize()'. */ video_canvas_resize(raster->canvas, raster->canvas->draw_buffer->canvas_width, raster->canvas->draw_buffer->canvas_height); video_viewport_resize(raster->canvas); return 0; }
int vic_snapshot_read_module(snapshot_t *s) { WORD i; snapshot_module_t *m; BYTE major_version, minor_version; WORD w; BYTE b; sound_close(); m = snapshot_module_open(s, snap_module_name, &major_version, &minor_version); if (m == NULL) { return -1; } if (major_version > SNAP_MAJOR || minor_version > SNAP_MINOR) { log_error(vic.log, "Snapshot module version (%d.%d) newer than %d.%d.", major_version, minor_version, SNAP_MAJOR, SNAP_MINOR); goto fail; } if (SMR_B(m, &b) < 0) { goto fail; } if (b != VIC_RASTER_CYCLE(maincpu_clk)) { log_error(vic.log, "Cycle value (%d) incorrect; should be %d.", (int)b, VIC_RASTER_CYCLE(maincpu_clk)); goto fail; } vic.raster_cycle = (unsigned int)b; if (SMR_W(m, &w) < 0) { goto fail; } if (w != VIC_RASTER_Y(maincpu_clk)) { log_error(vic.log, "Raster line value (%d) incorrect; should be %d.", (int)w, VIC_RASTER_Y(maincpu_clk)); goto fail; } if (SMR_W(m, &w) < 0) { goto fail; } vic.area = (vic_area_state_t)w; if (SMR_W(m, &w) < 0) { goto fail; } vic.fetch_state = (vic_fetch_state_t)w; if (0 || (SMR_DW_UINT(m, &vic.raster_line) < 0) || (SMR_DW_UINT(m, &vic.text_cols) < 0) || (SMR_DW_UINT(m, &vic.text_lines) < 0) || (SMR_DW_UINT(m, &vic.pending_text_cols) < 0) || (SMR_DW_UINT(m, &vic.line_was_blank) < 0) || (SMR_DW_UINT(m, &vic.memptr) < 0) || (SMR_DW_UINT(m, &vic.memptr_inc) < 0) || (SMR_DW_UINT(m, &vic.row_counter) < 0) || (SMR_DW_UINT(m, &vic.buf_offset) < 0) || SMR_B_INT(m, &vic.light_pen.state) < 0 || SMR_B_INT(m, &vic.light_pen.triggered) < 0 || SMR_DW_INT(m, &vic.light_pen.x) < 0 || SMR_DW_INT(m, &vic.light_pen.y) < 0 || SMR_DW_INT(m, &vic.light_pen.x_extra_bits) < 0 || SMR_DW(m, &vic.light_pen.trigger_cycle) < 0 || (SMR_B(m, &vic.vbuf) < 0)) { goto fail; } /* Color RAM. */ if (SMR_BA(m, mem_ram + 0x9400, 0x400) < 0) { goto fail; } for (i = 0; i < 0x10; i++) { if (SMR_B(m, &b) < 0) { goto fail; } /* XXX: This assumes that there are no side effects. */ vic_store(i, b); } raster_force_repaint(&vic.raster); return snapshot_module_close(m); fail: if (m != NULL) snapshot_module_close(m); return -1; }
int ted_snapshot_read_module(snapshot_t *s) { BYTE major_version, minor_version; int i; snapshot_module_t *m; m = snapshot_module_open(s, snap_module_name, &major_version, &minor_version); if (m == NULL) { return -1; } if (major_version > SNAP_MAJOR || minor_version > SNAP_MINOR) { log_error(ted.log, "Snapshot module version (%d.%d) newer than %d.%d.", major_version, minor_version, SNAP_MAJOR, SNAP_MINOR); goto fail; } /* FIXME: initialize changes? */ if (0 || SMR_DW(m, &ted.last_emulate_line_clk) < 0 /* AllowBadLines */ || SMR_B_INT(m, &ted.allow_bad_lines) < 0 /* BadLine */ || SMR_B_INT(m, &ted.bad_line) < 0 /* Blank */ || SMR_B_INT(m, &ted.raster.blank_enabled) < 0 /* ColorBuf */ || SMR_BA(m, ted.cbuf, 40) < 0 /* IdleState */ || SMR_B_INT(m, &ted.idle_state) < 0 /* MatrixBuf */ || SMR_BA(m, ted.vbuf, 40) < 0 ) { goto fail; } /* Read the current raster line and the current raster cycle. As they are a function of `clk', this is just a sanity check. */ { WORD RasterLine; BYTE RasterCycle; if (SMR_B(m, &RasterCycle) < 0 || SMR_W(m, &RasterLine) < 0) { goto fail; } DBG(("TED read snapshot at clock: %d cycle: %d (%d) tedline: %d (%d) rasterline: %d\n", maincpu_clk, TED_RASTER_CYCLE(maincpu_clk), RasterCycle, TED_RASTER_Y(maincpu_clk), RasterLine, ted.raster.current_line)); if (RasterCycle != (BYTE)TED_RASTER_CYCLE(maincpu_clk)) { log_error(ted.log, "Not matching raster cycle (%d) in snapshot; should be %d.", RasterCycle, TED_RASTER_CYCLE(maincpu_clk)); goto fail; } if (RasterLine != (WORD)TED_RASTER_Y(maincpu_clk)) { log_error(ted.log, "Not matching raster line (%d) in snapshot; should be %d.", RasterLine, TED_RASTER_Y(maincpu_clk)); goto fail; } } for (i = 0; i < 0x40; i++) { if (SMR_B(m, &ted.regs[i]) < 0 /* Registers */) { goto fail; } } if (0 || SMR_DW_INT(m, (int*)&ted.ted_raster_counter) < 0 /* Vc */ || SMR_W_INT(m, &ted.mem_counter) < 0 /* VcInc */ || SMR_B_INT(m, &ted.mem_counter_inc) < 0 /* VcBase */ || SMR_W_INT(m, &ted.memptr) < 0 /* VideoInt */ || SMR_B_INT(m, &ted.irq_status) < 0) { goto fail; } /* FIXME: Recalculate alarms and derived values. */ ted_irq_set_raster_line(ted.regs[0x0b] | ((ted.regs[0x0a] & 1) << 8)); ted_update_memory_ptrs(TED_RASTER_CYCLE(maincpu_clk)); ted.raster.xsmooth = ted.regs[0x07] & 0x7; ted.raster.ysmooth = ted.regs[0x06] & 0x7; ted.raster.current_line = TED_RASTER_Y(maincpu_clk); /* FIXME? */ /* Update colors. */ ted.raster.border_color = ted.regs[0x19]; ted.raster.background_color = ted.regs[0x15]; ted.ext_background_color[0] = ted.regs[0x16]; ted.ext_background_color[1] = ted.regs[0x17]; ted.ext_background_color[2] = ted.regs[0x18]; ted.raster.blank = !(ted.regs[0x06] & 0x10); if (TED_IS_ILLEGAL_MODE (ted.raster.video_mode)) { ted.raster.idle_background_color = 0; ted.force_black_overscan_background_color = 1; } else { ted.raster.idle_background_color = ted.raster.background_color; ted.force_black_overscan_background_color = 0; } if (ted.regs[0x06] & 0x8) { ted.raster.display_ystart = ted.row_25_start_line; ted.raster.display_ystop = ted.row_25_stop_line; } else { ted.raster.display_ystart = ted.row_24_start_line; ted.raster.display_ystop = ted.row_24_stop_line; } if (ted.regs[0x07] & 0x8) { ted.raster.display_xstart = TED_40COL_START_PIXEL; ted.raster.display_xstop = TED_40COL_STOP_PIXEL; } else { ted.raster.display_xstart = TED_38COL_START_PIXEL; ted.raster.display_xstop = TED_38COL_STOP_PIXEL; } /* `ted.raster.draw_idle_state', `ted.raster.open_right_border' and `ted.raster.open_left_border' should be needed, but they would only affect the current ted.raster line, and would not cause any difference in timing. So who cares. */ /* FIXME: `ted.ycounter_reset_checked'? */ /* FIXME: `ted.force_display_state'? */ ted.memory_fetch_done = 0; /* FIXME? */ ted_update_video_mode(TED_RASTER_CYCLE(maincpu_clk)); ted.draw_clk = maincpu_clk + (ted.draw_cycle - TED_RASTER_CYCLE(maincpu_clk)); ted.last_emulate_line_clk = ted.draw_clk - ted.cycles_per_line; alarm_set(ted.raster_draw_alarm, ted.draw_clk); { DWORD dw; if (SMR_DW(m, &dw) < 0) { /* FetchEventTick */ goto fail; } ted.fetch_clk = maincpu_clk + dw; alarm_set(ted.raster_fetch_alarm, ted.fetch_clk); } if (ted.irq_status & 0x80) { interrupt_restore_irq(maincpu_int_status, ted.int_num, 1); } raster_force_repaint(&ted.raster); DBG(("TED: snapshot loaded.\n")); return 0; fail: if (m != NULL) { snapshot_module_close(m); } log_error(ted.log, "could not load TED snapshot."); return -1; }
int vicii_snapshot_read_module(snapshot_t *s) { BYTE major_version, minor_version; int i; snapshot_module_t *m; BYTE color_ram[0x400]; m = snapshot_module_open(s, snap_module_name, &major_version, &minor_version); if (m == NULL) { return -1; } if (major_version > SNAP_MAJOR || minor_version > SNAP_MINOR) { log_error(vicii.log, "Snapshot module version (%d.%d) newer than %d.%d.", major_version, minor_version, SNAP_MAJOR, SNAP_MINOR); goto fail; } /* FIXME: initialize changes? */ if (0 /* AllowBadLines */ || SMR_B_INT(m, &vicii.allow_bad_lines) < 0 /* BadLine */ || SMR_B_INT(m, &vicii.bad_line) < 0 /* Blank */ || SMR_B_INT(m, &vicii.raster.blank_enabled) < 0 /* ColorBuf */ || SMR_BA(m, vicii.cbuf, 40) < 0 /* ColorRam */ || SMR_BA(m, color_ram, 1024) < 0 /* IdleState */ || SMR_B_INT(m, &vicii.idle_state) < 0 /* LPTrigger */ || SMR_B_INT(m, &vicii.light_pen.triggered) < 0 /* LPX */ || SMR_B_INT(m, &vicii.light_pen.x) < 0 /* LPY */ || SMR_B_INT(m, &vicii.light_pen.y) < 0 /* MatrixBuf */ || SMR_BA(m, vicii.vbuf, 40) < 0 /* NewSpriteDmaMask */ || SMR_B(m, &vicii.raster.sprite_status->new_dma_msk) < 0) { goto fail; } mem_color_ram_from_snapshot(color_ram); { DWORD RamBase; if (SMR_DW(m, &RamBase) < 0) { goto fail; } vicii.ram_base_phi1 = mem_ram + RamBase; } /* Read the current raster line and the current raster cycle. As they are a function of `clk', this is just a sanity check. */ { WORD RasterLine; BYTE RasterCycle; if (SMR_B(m, &RasterCycle) < 0 || SMR_W(m, &RasterLine) < 0) { goto fail; } if (RasterCycle != (BYTE)VICII_RASTER_CYCLE(maincpu_clk)) { log_error(vicii.log, "Not matching raster cycle (%d) in snapshot; should be %d.", RasterCycle, VICII_RASTER_CYCLE(maincpu_clk)); goto fail; } if (RasterLine != (WORD)VICII_RASTER_Y(maincpu_clk)) { log_error(vicii.log, "VIC-II: Not matching raster line (%d) in snapshot; should be %d.", RasterLine, VICII_RASTER_Y(maincpu_clk)); goto fail; } } for (i = 0; i < 0x40; i++) { if (SMR_B(m, &vicii.regs[i]) < 0 /* Registers */) { goto fail; } } if (0 /* SbCollMask */ || SMR_B(m, &vicii.sprite_background_collisions) < 0 /* SpriteDmaMask */ || SMR_B(m, &vicii.raster.sprite_status->dma_msk) < 0 /* SsCollMask */ || SMR_B(m, &vicii.sprite_sprite_collisions) < 0 /* VBank */ || SMR_W_INT(m, &vicii.vbank_phi1) < 0 /* Vc */ || SMR_W_INT(m, &vicii.mem_counter) < 0 /* VcInc */ || SMR_B_INT(m, &vicii.mem_counter_inc) < 0 /* VcBase */ || SMR_W_INT(m, &vicii.memptr) < 0 /* VideoInt */ || SMR_B_INT(m, &vicii.irq_status) < 0) { goto fail; } for (i = 0; i < 8; i++) { if (0 /* SpriteXMemPtr */ || SMR_B_INT(m, &vicii.raster.sprite_status->sprites[i].memptr) < 0 /* SpriteXMemPtrInc */ || SMR_B_INT(m, &vicii.raster.sprite_status->sprites[i].memptr_inc) < 0 /* SpriteXExpFlipFlop */ || SMR_B_INT(m, &vicii.raster.sprite_status->sprites[i].exp_flag) < 0 ) { goto fail; } } /* FIXME: Recalculate alarms and derived values. */ #if 1 { /* We cannot use vicii_irq_set_raster_line as this would delay an alarm on line 0 for one frame */ unsigned int line = vicii.regs[0x12] | ((vicii.regs[0x11] & 0x80) << 1); if (line < (unsigned int)vicii.screen_height) { vicii.raster_irq_clk = (VICII_LINE_START_CLK(maincpu_clk) + VICII_RASTER_IRQ_DELAY - INTERRUPT_DELAY + (vicii.cycles_per_line * line)); /* Raster interrupts on line 0 are delayed by 1 cycle. */ if (line == 0) { vicii.raster_irq_clk++; } alarm_set(vicii.raster_irq_alarm, vicii.raster_irq_clk); } else { vicii.raster_irq_clk = CLOCK_MAX; alarm_unset(vicii.raster_irq_alarm); } vicii.raster_irq_line = line; } #else vicii_irq_set_raster_line(vicii.regs[0x12] | ((vicii.regs[0x11] & 0x80) << 1)); #endif /* compatibility with older versions */ vicii.ram_base_phi2 = vicii.ram_base_phi1; vicii.vbank_phi2 = vicii.vbank_phi1; vicii_update_memory_ptrs(VICII_RASTER_CYCLE(maincpu_clk)); /* Update sprite parameters. We had better do this manually, or the VIC-II emulation could be quite upset. */ { BYTE msk; for (i = 0, msk = 0x1; i < 8; i++, msk <<= 1) { raster_sprite_t *sprite; int tmp; sprite = vicii.raster.sprite_status->sprites + i; /* X/Y coordinates. */ tmp = vicii.regs[i * 2] + ((vicii.regs[0x10] & msk) ? 0x100 : 0); /* (-0xffff makes sure it's updated NOW.) */ vicii_sprites_set_x_position(i, tmp, -0xffff); sprite->y = (int)vicii.regs[i * 2 + 1]; sprite->x_expanded = (int)(vicii.regs[0x1d] & msk); sprite->y_expanded = (int)(vicii.regs[0x17] & msk); sprite->multicolor = (int)(vicii.regs[0x1c] & msk); sprite->in_background = (int)(vicii.regs[0x1b] & msk); sprite->color = (int) vicii.regs[0x27 + i] & 0xf; sprite->dma_flag = (int)(vicii.raster.sprite_status->new_dma_msk & msk); } } vicii.sprite_fetch_msk = vicii.raster.sprite_status->new_dma_msk; vicii.sprite_fetch_clk = VICII_LINE_START_CLK(maincpu_clk) + vicii.sprite_fetch_cycle - vicii.cycles_per_line; /* calculate the sprite_fetch_idx */ { const vicii_sprites_fetch_t *sf; sf = vicii_sprites_fetch_table[vicii.sprite_fetch_msk]; i = 0; while (sf[i].cycle >= 0 && sf[i].cycle + vicii.sprite_fetch_cycle <= vicii.cycles_per_line) { i++; } vicii.sprite_fetch_idx = i; } vicii.raster.xsmooth = vicii.regs[0x16] & 0x7; vicii.raster.sprite_xsmooth = vicii.regs[0x16] & 0x7; vicii.raster.ysmooth = vicii.regs[0x11] & 0x7; vicii.raster.current_line = VICII_RASTER_Y(maincpu_clk); /* FIXME? */ vicii.raster.sprite_status->visible_msk = vicii.regs[0x15]; /* Update colors. */ vicii.raster.border_color = vicii.regs[0x20] & 0xf; vicii.raster.background_color = vicii.regs[0x21] & 0xf; vicii.ext_background_color[0] = vicii.regs[0x22] & 0xf; vicii.ext_background_color[1] = vicii.regs[0x23] & 0xf; vicii.ext_background_color[2] = vicii.regs[0x24] & 0xf; vicii.raster.sprite_status->mc_sprite_color_1 = vicii.regs[0x25] & 0xf; vicii.raster.sprite_status->mc_sprite_color_2 = vicii.regs[0x26] & 0xf; vicii.raster.blank = !(vicii.regs[0x11] & 0x10); if (VICII_IS_ILLEGAL_MODE(vicii.raster.video_mode)) { vicii.raster.idle_background_color = 0; vicii.force_black_overscan_background_color = 1; } else { vicii.raster.idle_background_color = vicii.raster.background_color; vicii.force_black_overscan_background_color = 0; } if (vicii.regs[0x11] & 0x8) { vicii.raster.display_ystart = vicii.row_25_start_line; vicii.raster.display_ystop = vicii.row_25_stop_line; } else { vicii.raster.display_ystart = vicii.row_24_start_line; vicii.raster.display_ystop = vicii.row_24_stop_line; } if (vicii.regs[0x16] & 0x8) { vicii.raster.display_xstart = VICII_40COL_START_PIXEL; vicii.raster.display_xstop = VICII_40COL_STOP_PIXEL; } else { vicii.raster.display_xstart = VICII_38COL_START_PIXEL; vicii.raster.display_xstop = VICII_38COL_STOP_PIXEL; } /* `vicii.raster.draw_idle_state', `vicii.raster.open_right_border' and `vicii.raster.open_left_border' should be needed, but they would only affect the current vicii.raster line, and would not cause any difference in timing. So who cares. */ /* FIXME: `vicii.ycounter_reset_checked'? */ /* FIXME: `vicii.force_display_state'? */ vicii.memory_fetch_done = 0; /* FIXME? */ vicii_update_video_mode(VICII_RASTER_CYCLE(maincpu_clk)); vicii.draw_clk = maincpu_clk + (vicii.draw_cycle - VICII_RASTER_CYCLE(maincpu_clk)); vicii.last_emulate_line_clk = vicii.draw_clk - vicii.cycles_per_line; alarm_set(vicii.raster_draw_alarm, vicii.draw_clk); { DWORD dw; BYTE b; if (0 || SMR_DW(m, &dw) < 0 /* FetchEventTick */ || SMR_B(m, &b) < 0 /* FetchEventType */ ) { goto fail; } vicii.fetch_clk = maincpu_clk + dw; vicii.fetch_idx = b; alarm_set(vicii.raster_fetch_alarm, vicii.fetch_clk); } if (vicii.irq_status & 0x80) { interrupt_restore_irq(maincpu_int_status, vicii.int_num, 1); } /* added in version 1.1 of snapshot format */ if (minor_version > 0) { DWORD RamBase; if (0 || SMR_DW(m, &RamBase) < 0 || SMR_W_INT(m, &vicii.vbank_phi2) < 0 /* VBank */ ) { goto fail; } vicii.ram_base_phi2 = mem_ram + RamBase; vicii_update_memory_ptrs(VICII_RASTER_CYCLE(maincpu_clk)); } raster_force_repaint(&vicii.raster); snapshot_module_close(m); return 0; fail: if (m != NULL) { snapshot_module_close(m); } return -1; }
/* Redraw the current raster line. */ static void vdc_raster_draw_alarm_handler(CLOCK offset, void *data) { int in_visible_area, in_idle_state; in_visible_area = (vdc.raster.current_line >= vdc.first_displayed_line && vdc.raster.current_line <= vdc.last_displayed_line); in_idle_state = (vdc.raster.current_line < vdc.border_height) || (vdc.raster.current_line > (vdc.border_height + vdc.screen_ypix)); if (vdc.raster.current_line == vdc.first_displayed_line * 2 + 1) { vdc.screen_adr = ((vdc.regs[12] << 8) | vdc.regs[13]) & vdc.vdc_address_mask; vdc.attribute_adr = ((vdc.regs[20] << 8) | vdc.regs[21]) & vdc.vdc_address_mask; } if (vdc.raster.current_line == 0) { vdc.mem_counter = 0; vdc.bitmap_counter = 0; vdc.raster.ycounter = 0; vdc.frame_counter++; if (vdc.regs[24] & 0x20) vdc.attribute_blink = vdc.frame_counter & 16; else vdc.attribute_blink = vdc.frame_counter & 8; if (vdc.update_geometry) { vdc_update_geometry(); vdc.force_resize = 1; vdc.force_repaint = 1; /* Screen height has changed, so do not invalidate cache with the new value. It will be recreated by resize anyway. */ vdc.force_cache_flush = 0; } else { if (vdc.force_cache_flush) { vdc_invalidate_cache(&vdc.raster, vdc.screen_height); vdc.force_cache_flush = 0; } } if (vdc.force_resize) { if (vdc.initialized) { vdc_set_geometry(); raster_mode_change(); } vdc.force_resize = 0; } if (vdc.force_repaint) { vdc.force_repaint = 0; raster_force_repaint(&vdc.raster); } } raster_line_emulate(&vdc.raster); #ifdef __MSDOS__ if (vdc.raster.canvas->viewport->update_canvas) canvas_set_border_color(vdc.raster.canvas, vdc.raster.border_color); #endif if (in_visible_area && !in_idle_state) { vdc_increment_memory_pointer(); vdc_set_video_mode(); } vdc_set_next_alarm(offset); }