/* Set the video mode according to the values in registers 6 and 7 of TED */ void ted_update_video_mode(unsigned int cycle) { static int old_video_mode = -1; int new_video_mode; new_video_mode = ((ted.regs[0x06] & 0x60) | (ted.regs[0x07] & 0x10)) >> 4; if (new_video_mode != old_video_mode) { if (TED_IS_ILLEGAL_MODE(new_video_mode)) { /* Force the overscan color to black. */ raster_changes_background_add_int (&ted.raster, TED_RASTER_X(cycle), &ted.raster.idle_background_color, 0); raster_changes_background_add_int (&ted.raster, TED_RASTER_X(cycle), &ted.raster.xsmooth_color, 0); ted.force_black_overscan_background_color = 1; } else { /* The overscan background color is given by the background color register. */ if (ted.raster.idle_background_color != ted.regs[0x15]) { raster_changes_background_add_int (&ted.raster, TED_RASTER_X(cycle), &ted.raster.idle_background_color, ted.regs[0x15]); raster_changes_background_add_int (&ted.raster, TED_RASTER_X(cycle), &ted.raster.xsmooth_color, ted.regs[0x15]); } ted.force_black_overscan_background_color = 0; } { int pos; pos = TED_RASTER_CHAR(cycle); raster_changes_foreground_add_int(&ted.raster, pos, &ted.raster.video_mode, new_video_mode); if (ted.idle_data_location != IDLE_NONE) { if (ted.regs[0x06] & 0x40) { raster_changes_foreground_add_int (&ted.raster, pos, (void *)&ted.idle_data, mem_ram[0xffff]); } else { raster_changes_foreground_add_int (&ted.raster, pos, (void *)&ted.idle_data, mem_ram[0xffff]); } } } old_video_mode = new_video_mode; } #ifdef TED_VMODE_DEBUG switch (new_video_mode) { case TED_NORMAL_TEXT_MODE: TED_DEBUG_VMODE(("Standard Text")); break; case TED_MULTICOLOR_TEXT_MODE: TED_DEBUG_VMODE(("Multicolor Text")); break; case TED_HIRES_BITMAP_MODE: TED_DEBUG_VMODE(("Hires Bitmap")); break; case TED_MULTICOLOR_BITMAP_MODE: TED_DEBUG_VMODE(("Multicolor Bitmap")); break; case TED_EXTENDED_TEXT_MODE: TED_DEBUG_VMODE(("Extended Text")); break; case TED_ILLEGAL_TEXT_MODE: TED_DEBUG_VMODE(("Illegal Text")); break; case TED_ILLEGAL_BITMAP_MODE_1: TED_DEBUG_VMODE(("Invalid Bitmap")); break; case TED_ILLEGAL_BITMAP_MODE_2: TED_DEBUG_VMODE(("Invalid Bitmap")); break; default: /* cannot happen */ TED_DEBUG_VMODE(("???")); } TED_DEBUG_VMODE((" Mode enabled at line $%04X, cycle %d.", TED_RASTER_Y(clk), cycle)); #endif }
int ted_snapshot_write_module(snapshot_t *s) { int i; snapshot_module_t *m; /* FIXME: Dispatch all events? */ m = snapshot_module_create (s, snap_module_name, SNAP_MAJOR, SNAP_MINOR); if (m == NULL) { return -1; } DBG(("TED write snapshot at clock: %d cycle: %d tedline: %d rasterline: %d\n", maincpu_clk, TED_RASTER_CYCLE(maincpu_clk), TED_RASTER_Y(maincpu_clk), ted.raster.current_line)); if (0 || SMW_DW(m, ted.last_emulate_line_clk) < 0 /* AllowBadLines */ || SMW_B(m, (BYTE)ted.allow_bad_lines) < 0 /* BadLine */ || SMW_B(m, (BYTE)ted.bad_line) < 0 /* Blank */ || SMW_B(m, (BYTE)ted.raster.blank_enabled) < 0 /* ColorBuf */ || SMW_BA(m, ted.cbuf, 40) < 0 /* IdleState */ || SMW_B(m, (BYTE)ted.idle_state) < 0 /* MatrixBuf */ || SMW_BA(m, ted.vbuf, 40) < 0 /* RasterCycle */ || SMW_B(m, (BYTE)TED_RASTER_CYCLE(maincpu_clk)) < 0 /* RasterLine */ || SMW_W(m, (WORD)(TED_RASTER_Y(maincpu_clk))) < 0 ) { goto fail; } for (i = 0; i < 0x40; i++) { /* Registers */ if (SMW_B(m, ted.regs[i]) < 0) { goto fail; } } if (0 || SMW_DW(m, (DWORD)ted.ted_raster_counter) < 0 /* Vc */ || SMW_W(m, (WORD)ted.mem_counter) < 0 /* VcInc */ || SMW_B(m, (BYTE)ted.mem_counter_inc) < 0 /* VcBase */ || SMW_W(m, (WORD)ted.memptr) < 0 /* VideoInt */ || SMW_B(m, (BYTE)ted.irq_status) < 0 ) { goto fail; } if (0 /* FetchEventTick */ || SMW_DW(m, ted.fetch_clk - maincpu_clk) < 0 ) { goto fail; } DBG(("TED snapshot written.\n")); return snapshot_module_close(m); fail: if (m != NULL) { snapshot_module_close(m); } DBG(("error writing TED snapshot.\n")); 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 ted_snapshot_write_module(snapshot_t *s) { int i; snapshot_module_t *m; /* FIXME: Dispatch all events? */ m = snapshot_module_create (s, snap_module_name, SNAP_MAJOR, SNAP_MINOR); if (m == NULL) return -1; if (0 /* AllowBadLines */ || SMW_B(m, (BYTE)ted.allow_bad_lines) < 0 /* BadLine */ || SMW_B(m, (BYTE)ted.bad_line) < 0 /* Blank */ || SMW_B(m, (BYTE)ted.raster.blank_enabled) < 0 /* ColorBuf */ || SMW_BA(m, ted.cbuf, 40) < 0 /* IdleState */ || SMW_B(m, (BYTE)ted.idle_state) < 0 /* MatrixBuf */ || SMW_BA(m, ted.vbuf, 40) < 0 /* NewSpriteDmaMask */ || SMW_B(m, ted.raster.sprite_status->new_dma_msk) < 0 /* RasterCycle */ || SMW_B(m, (BYTE)TED_RASTER_CYCLE(maincpu_clk)) < 0 /* RasterLine */ || SMW_W(m, (WORD)(TED_RASTER_Y(maincpu_clk))) < 0 ) goto fail; for (i = 0; i < 0x40; i++) /* Registers */ if (SMW_B(m, (BYTE)ted.regs[i]) < 0) goto fail; if (0 /* SpriteDmaMask */ || SMW_B(m, (BYTE)ted.raster.sprite_status->dma_msk) < 0 /* Vc */ || SMW_W(m, (WORD)ted.mem_counter) < 0 /* VcInc */ || SMW_B(m, (BYTE)ted.mem_counter_inc) < 0 /* VcBase */ || SMW_W(m, (WORD)ted.memptr) < 0 /* VideoInt */ || SMW_B(m, (BYTE)ted.irq_status) < 0 ) goto fail; for (i = 0; i < 8; i++) { if (0 /* SpriteXMemPtr */ || SMW_B(m, (BYTE)ted.raster.sprite_status->sprites[i].memptr) < 0 /* SpriteXMemPtrInc */ || SMW_B(m, (BYTE)ted.raster.sprite_status->sprites[i].memptr_inc) < 0 /* SpriteXExpFlipFlop */ || SMW_B(m, (BYTE)ted.raster.sprite_status->sprites[i].exp_flag) < 0 ) goto fail; } if (0 /* FetchEventTick */ || SMW_DW(m, ted.fetch_clk - maincpu_clk) < 0 ) goto fail; return snapshot_module_close(m); fail: if (m != NULL) snapshot_module_close(m); return -1; }