76
87
static unsigned int playback_active = 0, record_active = 0;
89
static unsigned int current_timestamp, milestone_timestamp, playback_time;
90
static CLOCK next_timestamp_clk;
91
static CLOCK milestone_timestamp_alarm;
93
/* the VICE version an event history was made with */
94
static char event_version[16];
78
96
static char *event_snapshot_dir = NULL;
79
97
static char *event_start_snapshot = NULL;
80
98
static char *event_end_snapshot = NULL;
81
99
static char *event_snapshot_path_str = NULL;
82
100
static unsigned int event_start_mode;
84
103
static char *event_snapshot_path(const char *snapshot_file)
86
105
if (event_snapshot_path_str != NULL)
92
111
return event_snapshot_path_str;
115
/* searches for a filename in the image list */
116
/* returns 0 if found */
117
/* returns 1 and appends it if not found */
118
static int event_image_append(const char *filename, char **mapped_name)
120
event_image_list_t *event_image_list_ptr = event_image_list_base;
122
while (event_image_list_ptr->next != NULL) {
123
if (strcmp(filename, event_image_list_ptr->next->orig_filename) == 0) {
124
if (mapped_name != NULL)
125
*mapped_name = lib_stralloc(event_image_list_ptr->next->mapped_filename);
130
event_image_list_ptr = event_image_list_ptr->next;
133
event_image_list_ptr->next = (
134
event_image_list_t *) lib_calloc(1, sizeof(event_image_list_t));
136
event_image_list_ptr = event_image_list_ptr->next;
137
event_image_list_ptr->next = NULL;
138
event_image_list_ptr->orig_filename = lib_stralloc(filename);
139
event_image_list_ptr->mapped_filename = NULL;
140
if (mapped_name != NULL)
141
event_image_list_ptr->mapped_filename = lib_stralloc(*mapped_name);
147
void event_record_attach_image(unsigned int unit, const char *filename,
148
unsigned int read_only)
153
if (record_active == 0)
156
event_list_current->type = EVENT_ATTACHIMAGE;
157
event_list_current->clk = maincpu_clk;
158
event_list_current->next
159
= (event_list_t *)lib_calloc(1, sizeof(event_list_t));
161
size = strlen(filename) + 3;
163
event_data = lib_malloc(size);
164
event_data[0] = unit;
165
event_data[1] = read_only;
166
strcpy(&event_data[2], filename);
168
if (event_image_append(filename, NULL) == 1) {
172
fd = fopen(filename, MODE_READ);
175
file_len = util_file_length(fd);
176
event_data = lib_realloc(event_data, size + file_len);
178
if (fread(&event_data[size], file_len, 1, fd) != 1)
179
log_error(event_log, "Cannot load image file %s", filename);
183
log_error(event_log, "Cannot open image file %s", filename);
188
event_list_current->size = size;
189
event_list_current->data = event_data;
190
event_list_current = event_list_current->next;
194
static void event_playback_attach_image(void *data, unsigned int size)
196
unsigned int unit, read_only;
197
char *orig_filename, *filename;
201
unit = (unsigned int)((char*)data)[0];
202
read_only = (unsigned int)((char*)data)[1];
203
orig_filename = &((char*)data)[2];
204
file_len = size - strlen(orig_filename) - 3;
209
sprintf(str, "img%04d", image_number++);
210
filename = util_concat(event_snapshot_dir, str, FSDEV_EXT_SEP_STR,
211
util_get_extension(orig_filename), NULL);
213
fd = fopen(filename, MODE_WRITE);
215
ui_error("Cannot create image file %s", filename);
219
if (fwrite((char*)data + strlen(orig_filename) + 3, file_len, 1, fd) != 1) {
220
ui_error("Cannot write image file %s", filename);
225
event_image_append(orig_filename, &filename);
227
if (event_image_append(orig_filename, &filename) != 0) {
228
ui_error("Cannot find mapped name for %s", orig_filename);
233
/* now filename holds the name to attach */
234
/* FIXME: read_only isn't handled for tape */
236
tape_image_event_playback(unit, filename);
238
resources_set_sprintf("AttachDevice%dReadonly",
239
(resource_value_t) read_only, unit);
240
file_system_event_playback(unit, filename);
95
248
void event_record(unsigned int type, void *data, unsigned int size)
97
250
void *event_data = NULL;
167
331
case EVENT_DATASETTE:
168
332
datasette_event_playback(offset, event_list_current->data);
334
case EVENT_ATTACHIMAGE:
335
event_playback_attach_image(event_list_current->data,
336
event_list_current->size);
170
338
case EVENT_ATTACHDISK:
171
file_system_event_playback(offset, event_list_current->data);
173
339
case EVENT_ATTACHTAPE:
174
tape_image_event_playback(offset, event_list_current->data);
341
/* old style attach via absolute filename and detach*/
343
const char *filename;
345
unit = (unsigned int)((char*)event_list_current->data)[0];
346
filename = &((char*)event_list_current->data)[1];
349
tape_image_event_playback(unit, filename);
351
file_system_event_playback(unit, filename);
177
355
machine_reset_event_playback(offset, event_list_current->data);
357
case EVENT_TIMESTAMP:
358
ui_display_event_time(current_timestamp++, playback_time);
179
360
case EVENT_LIST_END:
180
361
event_playback_stop();
183
366
log_error(event_log, "Unknow event type %i.", event_list_current->type);
186
369
if (event_list_current->type != EVENT_LIST_END
187
&& event_list_current->type != EVENT_RESET) {
370
&& event_list_current->type != EVENT_RESETCPU) {
188
371
next_current_list();
189
372
next_alarm_set();
222
434
curr = event_list_base;
224
while (curr->type != EVENT_LIST_END)
436
while (curr->type != EVENT_LIST_END) {
438
if (curr->type == EVENT_ATTACHIMAGE)
439
event_image_append(&((char*)curr->data)[2], NULL);
225
441
curr = curr->next;
227
444
memset(curr, 0, sizeof(event_list_t));
228
445
event_list_current = curr;
231
447
/*-----------------------------------------------------------------------*/
448
/* writes or replaces version string in the initial event */
449
static void event_write_version(void)
453
unsigned int ver_idx;
455
if (event_list_base->type != EVENT_INITIAL) {
456
/* EVENT_INITIAL is missing (bug in 1.14.xx); fix it */
457
event_list_t *new_event;
459
new_event = (event_list_t *)lib_calloc(1, sizeof(event_list_t));
460
new_event->clk = event_list_base->clk;
461
new_event->size = strlen(event_start_snapshot) + 2;
462
new_event->type = EVENT_INITIAL;
463
data = lib_malloc(new_event->size);
464
data[0] = EVENT_START_MODE_FILE_SAVE;
465
strcpy((char *)&data[1], event_start_snapshot);
466
new_event->data = data;
467
new_event->next = event_list_base;
468
event_list_base = new_event;
471
data = event_list_base->data;
474
if (data[0] == EVENT_START_MODE_FILE_SAVE)
475
ver_idx += strlen((char *)&data[1]) + 1;
477
event_list_base->size = ver_idx + strlen(VERSION) + 1;
478
new_data = lib_malloc(event_list_base->size);
480
memcpy(new_data, data, ver_idx);
482
strcpy((char *)&new_data[ver_idx], VERSION);
484
event_list_base->data = new_data;
233
488
static void event_initial_write(void)
262
519
case EVENT_START_MODE_FILE_SAVE:
263
520
if (machine_write_snapshot(event_snapshot_path(event_start_snapshot),
265
ui_error(_("Could not create start snapshot file."));
522
ui_error(_("Could not create start snapshot file %s."),
523
event_snapshot_path(event_start_snapshot));
524
ui_display_recording(0);
270
529
record_active = 1;
271
530
event_initial_write();
531
next_timestamp_clk = maincpu_clk;
532
current_timestamp = 0;
273
534
case EVENT_START_MODE_FILE_LOAD:
274
535
if (machine_read_snapshot(
275
536
event_snapshot_path(event_end_snapshot), 1) < 0) {
276
ui_error(_("Error reading start snapshot file."));
537
ui_error(_("Error reading end snapshot file %s."),
538
event_snapshot_path(event_end_snapshot));
280
542
record_active = 1;
543
next_timestamp_clk = maincpu_clk;
544
current_timestamp = playback_time;
282
546
case EVENT_START_MODE_RESET:
283
547
machine_trigger_reset(MACHINE_RESET_MODE_HARD);
286
550
record_active = 1;
287
551
event_initial_write();
552
next_timestamp_clk = 0;
553
current_timestamp = 0;
555
case EVENT_START_MODE_PLAYBACK:
556
cut_list(event_list_current->next);
557
destroy_image_list();
558
event_write_version();
560
next_timestamp_clk = maincpu_clk;
290
563
log_error(event_log, "Unknown event start mode %i", event_start_mode);
568
debug_start_recording();
571
/* use alarm for timestamps */
572
milestone_timestamp_alarm = 0;
573
alarm_set(event_alarm, next_timestamp_clk);
295
576
int event_record_start(void)
297
if (playback_active != 0)
578
if (event_start_mode == EVENT_START_MODE_PLAYBACK) {
579
if (playback_active != 0)
580
event_playback_stop();
300
585
if (record_active != 0)
303
589
interrupt_maincpu_trigger_trap(event_record_start_trap, (void *)0);
305
591
ui_display_recording(1);
382
684
case EVENT_START_MODE_FILE_SAVE:
383
685
/*log_debug("READING %s", (char *)(&data[1]));*/
384
686
if (machine_read_snapshot(
385
event_snapshot_path((char *)(&data[1])), 0) < 0) {
386
ui_error(_("Error reading start snapshot file."));
687
event_snapshot_path((char *)(&data[1])), 0) < 0
688
&& machine_read_snapshot(
689
event_snapshot_path(event_start_snapshot), 0) < 0)
691
char *st = lib_stralloc(event_snapshot_path((char *)(&data[1])));
692
ui_error(_("Error reading start snapshot file. Tried %s and %s"),
693
st, event_snapshot_path(event_start_snapshot));
695
ui_display_playback(0, NULL);
699
if (event_list_current->size > strlen(&data[1]) + 2)
700
strncpy(event_version, (char *)(&data[strlen(&data[1]) + 2]), 15);
389
702
next_current_list();
390
703
next_alarm_set();
392
705
case EVENT_START_MODE_RESET:
393
706
/*log_debug("RESET MODE!");*/
394
707
machine_trigger_reset(MACHINE_RESET_MODE_HARD);
708
if (event_list_current->size > 1)
709
strncpy(event_version, (char *)(&data[1]), 15);
395
710
next_current_list();
396
711
/* Alarm will be set if reset is ack'ed. */
397
712
playback_reset_ack = 1;
442
767
static void event_record_set_milestone_trap(WORD addr, void *data)
444
769
if (machine_write_snapshot(
445
event_snapshot_path(event_end_snapshot), 1, 1, 1) < 0)
446
ui_error(_("Could not create end snapshot file."));
770
event_snapshot_path(event_end_snapshot), 1, 1, 1) < 0) {
771
ui_error(_("Could not create end snapshot file %s."),
772
event_snapshot_path(event_end_snapshot));
774
milestone_timestamp_alarm = next_timestamp_clk;
775
milestone_timestamp = current_timestamp;
777
debug_set_milestone();
449
782
int event_record_set_milestone(void)
519
862
curr = event_list_base;
863
num_of_timestamps = 0;
865
next_timestamp_clk = CLOCK_MAX;
522
if (SMR_DW_INT(m, (int*)&(curr->type)) < 0) {
523
snapshot_module_close(m);
527
if (SMR_DW(m, &(curr->clk)) < 0) {
528
snapshot_module_close(m);
532
if (SMR_DW_INT(m, (int*)&(curr->size)) < 0) {
533
snapshot_module_close(m);
537
if (curr->size > 0) {
538
curr->data = lib_malloc(curr->size);
539
if (SMR_BA(m, curr->data, curr->size) < 0) {
540
snapshot_module_close(m);
545
if (curr->type == EVENT_LIST_END)
868
unsigned int type, size;
873
throw away recorded timestamp (recording them was introduced in
874
1.14.x so there might exist history files with TIMESTAMP events)
877
if (SMR_DW_INT(m, (int*)&(type)) < 0) {
878
snapshot_module_close(m);
882
if (SMR_DW(m, &(clk)) < 0) {
883
snapshot_module_close(m);
887
if (SMR_DW_INT(m, (int*)&(size)) < 0) {
888
snapshot_module_close(m);
892
} while (type == EVENT_TIMESTAMP);
895
data = lib_malloc(size);
896
if (SMR_BA(m, data, size) < 0) {
897
snapshot_module_close(m);
902
if (next_timestamp_clk == CLOCK_MAX) /* if EVENT_INITIAL is missing */
903
next_timestamp_clk = clk;
905
if (type == EVENT_INITIAL) {
906
if (data[0] == EVENT_START_MODE_RESET)
907
next_timestamp_clk = 0;
909
next_timestamp_clk = clk;
911
/* insert timestamps each second */
912
while (next_timestamp_clk < clk || (type == EVENT_OVERFLOW
913
&& next_timestamp_clk < maincpu_clk_guard->clk_max_value))
915
curr->type = EVENT_TIMESTAMP;
916
curr->clk = next_timestamp_clk;
918
curr->next = (event_list_t *)lib_calloc(1, sizeof(event_list_t));
920
next_timestamp_clk += machine_get_cycles_per_second();
924
if (type == EVENT_OVERFLOW)
925
next_timestamp_clk -= clk_guard_clock_sub(maincpu_clk_guard);
931
curr->data = (size > 0 ? data : NULL);
933
if (type == EVENT_LIST_END)
936
if (type == EVENT_RESETCPU)
937
next_timestamp_clk -= clk;
548
939
curr->next = (event_list_t *)lib_calloc(1, sizeof(event_list_t));
549
940
curr = curr->next;
943
if (num_of_timestamps > 0)
944
playback_time = num_of_timestamps - 1;
552
946
snapshot_module_close(m);
687
1083
/*-----------------------------------------------------------------------*/
1085
static void clk_overflow_callback(CLOCK sub, void *data)
1087
if (event_record_active())
1088
event_record(EVENT_OVERFLOW, NULL, 0);
1090
if (next_timestamp_clk)
1091
next_timestamp_clk -= sub;
689
1095
void event_init(void)
691
1097
event_log = log_open("Event");
693
1099
event_alarm = alarm_new(maincpu_alarm_context, "Event",
694
1100
event_alarm_handler, NULL);
1102
clk_guard_add_callback(maincpu_clk_guard, clk_overflow_callback, NULL);