2
* autostart.c - Automatic image loading and starting.
5
* Teemu Rantanen <tvr@cs.hut.fi>
6
* Ettore Perazzoli <ettore@comm2000.it>
7
* Andr� Fachat <a.fachat@physik.tu-chemnitz.de>
8
* Andreas Boose <viceteam@t-online.de>
9
* Thomas Bretz <tbretz@ph.tum.de>
11
* This file is part of VICE, the Versatile Commodore Emulator.
12
* See README for copyright notice.
14
* This program is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License as published by
16
* the Free Software Foundation; either version 2 of the License, or
17
* (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31
/* #define DEBUG_AUTOSTART */
41
#include "autostart.h"
42
#include "autostart-prg.h"
46
#include "datasette.h"
50
#include "imagecontents.h"
51
#include "tapecontents.h"
52
#include "diskcontents.h"
53
#include "interrupt.h"
57
#include "machine-bus.h"
63
#include "resources.h"
66
#include "translate.h"
71
#include "vdrive-bam.h"
72
#include "vice-event.h"
74
#ifdef DEBUG_AUTOSTART
75
#define DBG(_x_) log_debug _x_
80
static void autostart_done(void);
81
static void autostart_finish(void);
83
/* Kernal addresses. Set by `autostart_init()'. */
85
static WORD blnsw; /* Cursor Blink enable: 0 = Flash Cursor */
86
static int pnt; /* Pointer: Current Screen Line Address */
87
static int pntr; /* Cursor Column on Current Line */
88
static int lnmx; /* Physical Screen Line Length */
90
/* Current state of the autostart routine. */
95
AUTOSTART_PRESSPLAYONTAPE,
96
AUTOSTART_LOADINGTAPE,
98
AUTOSTART_LOADINGDISK,
99
AUTOSTART_HASSNAPSHOT,
100
AUTOSTART_WAITLOADREADY,
101
AUTOSTART_WAITLOADING,
102
AUTOSTART_WAITSEARCHINGFOR,
105
} autostartmode = AUTOSTART_NONE;
107
#define AUTOSTART_WAIT_BLINK 0
108
#define AUTOSTART_NOWAIT_BLINK 1
110
/* Log descriptor. */
111
static log_t autostart_log = LOG_ERR;
113
/* Flag: was true drive emulation turned on when we started booting the disk
115
static int orig_drive_true_emulation_state = -1;
117
/* Flag: warp mode state before booting */
118
static int orig_warp_mode = -1;
120
/* PETSCII name of the program to load. NULL if default */
121
static char *autostart_program_name = NULL;
123
/* Minimum number of cycles before we feed BASIC with commands. */
124
static CLOCK min_cycles;
125
static CLOCK autostart_initial_delay_cycles;
127
/* Flag: Do we want to switch true drive emulation on/off during autostart?
128
* Normally, this is the same as handle_drive_true_emulation_by_machine;
129
* however, the user can override this decision by specifying
130
* -autostart-no-true-drive-emulation
132
static int handle_drive_true_emulation_overridden;
134
/* Flag: Does the machine want us to switch true drive emulation on/off during autostart? */
135
static int handle_drive_true_emulation_by_machine;
137
/* Flag: autostart is initialized. */
138
static int autostart_enabled = 0;
140
/* Flag: Autostart the file or just load it? */
141
static unsigned int autostart_run_mode;
143
/* Flag: maincpu_clk isn't resetted yet */
144
static int autostart_wait_for_reset;
146
/* Flag: load stage after LOADING enters ROM area */
147
static int entered_rom = 0;
149
/* Flag: trap monitor after done */
150
static int trigger_monitor = 0;
152
int autostart_ignore_reset = 0; /* FIXME: only used by datasette.c, does it really have to be global? */
154
/* additional random delay of up to 10 frames */
155
#define AUTOSTART_RAND() (1 + (int)(((float)machine_get_cycles_per_frame()) * 10.0f * rand() / (RAND_MAX + 1.0)))
157
/* flag for special case handling of C128 80 columns mode */
158
static int c128_column4080_key;
160
/* ------------------------------------------------------------------------- */
162
static int autostart_basic_load = 0;
164
static int AutostartRunWithColon = 0;
166
static int AutostartHandleTrueDriveEmulation = 0;
168
static int AutostartWarp = 0;
170
static int AutostartDelay = 0;
171
static int AutostartDelayRandom = 0;
173
static int AutostartPrgMode = AUTOSTART_PRG_MODE_VFS;
175
static char *AutostartPrgDiskImage = NULL;
177
static const char * const AutostartRunCommandsAvailable[] = {
181
static const char * AutostartRunCommand = NULL;
183
static void set_handle_true_drive_emulation_state(void)
185
handle_drive_true_emulation_overridden =
186
AutostartHandleTrueDriveEmulation ?
187
handle_drive_true_emulation_by_machine : 0;
190
/*! \internal \brief set if autostart should use LOAD ... ,1 */
191
static int set_autostart_basic_load(int val, void *param)
193
autostart_basic_load = val ? 1 : 0;
198
/*! \internal \brief set if autostart should execute with a colon or not
201
if 0, the "RUN" command at the end of autostart is executed without
202
a colon; else, it will be executed with a colon.
208
0 on success. else -1.
210
static int set_autostart_run_with_colon(int val, void *param)
212
AutostartRunWithColon = val ? 1 : 0;
214
AutostartRunCommand = AutostartRunCommandsAvailable[AutostartRunWithColon];
219
/*! \internal \brief set if autostart should handle TDE or not
222
if 0, autostart does not handle TDE even if the machine says it can
229
0 on success. else -1.
231
static int set_autostart_handle_tde(int val, void *param)
233
AutostartHandleTrueDriveEmulation = val ? 1 : 0;
235
set_handle_true_drive_emulation_state();
240
/*! \internal \brief set if autostart should enable warp mode */
241
static int set_autostart_warp(int val, void *param)
243
AutostartWarp = val ? 1 : 0;
248
/*! \internal \brief set initial autostart delay. 0 means default. */
249
static int set_autostart_delay(int val, void *param)
251
if ((val < 0) || (val > 1000)) {
254
AutostartDelay = val;
258
/*! \internal \brief set initial autostart random delay. 0 means off, 1 means on. */
259
static int set_autostart_delayrandom(int val, void *param)
261
AutostartDelayRandom = val ? 1 : 0;
265
/*! \internal \brief set autostart prg mode */
266
static int set_autostart_prg_mode(int val, void *param)
268
AutostartPrgMode = val;
269
if ((val < 0) || (val > AUTOSTART_PRG_MODE_LAST)) {
276
/*! \internal \brief set disk image name of autostart prg mode */
278
static int set_autostart_prg_disk_image(const char *val, void *param)
280
if (util_string_set(&AutostartPrgDiskImage, val)) {
287
/*! \brief string resources used by autostart */
288
static resource_string_t resources_string[] = {
289
{ "AutostartPrgDiskImage", NULL, RES_EVENT_NO, NULL,
290
&AutostartPrgDiskImage, set_autostart_prg_disk_image, NULL },
294
/*! \brief integer resources used by autostart */
295
static const resource_int_t resources_int[] = {
296
{ "AutostartBasicLoad", 0, RES_EVENT_NO, (resource_value_t)0,
297
&autostart_basic_load, set_autostart_basic_load, NULL },
298
{ "AutostartRunWithColon", 0, RES_EVENT_NO, (resource_value_t)0,
299
&AutostartRunWithColon, set_autostart_run_with_colon, NULL },
300
{ "AutostartHandleTrueDriveEmulation", 0, RES_EVENT_NO, (resource_value_t)0,
301
&AutostartHandleTrueDriveEmulation, set_autostart_handle_tde, NULL },
302
{ "AutostartWarp", 1, RES_EVENT_NO, (resource_value_t)0,
303
&AutostartWarp, set_autostart_warp, NULL },
304
{ "AutostartPrgMode", 0, RES_EVENT_NO, (resource_value_t)0,
305
&AutostartPrgMode, set_autostart_prg_mode, NULL },
306
{ "AutostartDelay", 0, RES_EVENT_NO, (resource_value_t)0,
307
&AutostartDelay, set_autostart_delay, NULL },
308
{ "AutostartDelayRandom", 1, RES_EVENT_NO, (resource_value_t)0,
309
&AutostartDelayRandom, set_autostart_delayrandom, NULL },
313
/*! \brief initialize the resources
315
0 on success, else -1.
318
Registers the integer resources
320
int autostart_resources_init(void)
322
resources_string[0].factory_value = archdep_default_autostart_disk_image_file_name();
324
if (resources_register_string(resources_string) < 0) {
328
return resources_register_int(resources_int);
331
void autostart_resources_shutdown(void)
333
lib_free(AutostartPrgDiskImage);
334
lib_free(resources_string[0].factory_value);
337
/* ------------------------------------------------------------------------- */
339
static const cmdline_option_t cmdline_options[] =
341
{ "-basicload", SET_RESOURCE, 0,
342
NULL, NULL, "AutostartBasicLoad", (resource_value_t)1,
343
USE_PARAM_STRING, USE_DESCRIPTION_ID,
344
IDCLS_UNUSED, IDCLS_AUTOSTART_LOAD_TO_BASIC_START,
346
{ "+basicload", SET_RESOURCE, 0,
347
NULL, NULL, "AutostartBasicLoad", (resource_value_t)0,
348
USE_PARAM_STRING, USE_DESCRIPTION_ID,
349
IDCLS_UNUSED, IDCLS_AUTOSTART_LOAD_WITH_1,
351
{ "-autostartwithcolon", SET_RESOURCE, 0,
352
NULL, NULL, "AutostartRunWithColon", (resource_value_t)1,
353
USE_PARAM_STRING, USE_DESCRIPTION_ID,
354
IDCLS_UNUSED, IDCLS_ENABLE_AUTOSTARTWITHCOLON,
356
{ "+autostartwithcolon", SET_RESOURCE, 0,
357
NULL, NULL, "AutostartRunWithColon", (resource_value_t)0,
358
USE_PARAM_STRING, USE_DESCRIPTION_ID,
359
IDCLS_UNUSED, IDCLS_DISABLE_AUTOSTARTWITHCOLON,
361
{ "-autostart-handle-tde", SET_RESOURCE, 0,
362
NULL, NULL, "AutostartHandleTrueDriveEmulation", (resource_value_t)1,
363
USE_PARAM_STRING, USE_DESCRIPTION_ID,
364
IDCLS_UNUSED, IDCLS_ENABLE_AUTOSTART_HANDLE_TDE,
366
{ "+autostart-handle-tde", SET_RESOURCE, 0,
367
NULL, NULL, "AutostartHandleTrueDriveEmulation", (resource_value_t)0,
368
USE_PARAM_STRING, USE_DESCRIPTION_ID,
369
IDCLS_UNUSED, IDCLS_DISABLE_AUTOSTART_HANDLE_TDE,
371
{ "-autostart-warp", SET_RESOURCE, 0,
372
NULL, NULL, "AutostartWarp", (resource_value_t)1,
373
USE_PARAM_STRING, USE_DESCRIPTION_ID,
374
IDCLS_UNUSED, IDCLS_ENABLE_WARP_MODE_AUTOSTART,
376
{ "+autostart-warp", SET_RESOURCE, 0,
377
NULL, NULL, "AutostartWarp", (resource_value_t)0,
378
USE_PARAM_STRING, USE_DESCRIPTION_ID,
379
IDCLS_UNUSED, IDCLS_DISABLE_WARP_MODE_AUTOSTART,
381
{ "-autostartprgmode", SET_RESOURCE, 1,
382
NULL, NULL, "AutostartPrgMode", NULL,
383
USE_PARAM_ID, USE_DESCRIPTION_ID,
384
IDCLS_UNUSED, IDCLS_SET_AUTOSTART_MODE_FOR_PRG,
386
{ "-autostartprgdiskimage", SET_RESOURCE, 1,
387
NULL, NULL, "AutostartPrgDiskImage", NULL,
388
USE_PARAM_ID, USE_DESCRIPTION_ID,
389
IDCLS_UNUSED, IDCLS_SET_DISK_IMAGE_FOR_AUTOSTART_PRG,
391
{ "-autostart-delay", SET_RESOURCE, 1,
392
NULL, NULL, "AutostartDelay", NULL,
393
USE_PARAM_ID, USE_DESCRIPTION_ID,
394
IDCLS_UNUSED, IDCLS_SET_AUTOSTART_DELAY,
396
{ "-autostart-delay-random", SET_RESOURCE, 0,
397
NULL, NULL, "AutostartDelayRandom", (resource_value_t)1,
398
USE_PARAM_STRING, USE_DESCRIPTION_ID,
399
IDCLS_UNUSED, IDCLS_ENABLE_AUTOSTART_RANDOM_DELAY,
401
{ "+autostart-delay-random", SET_RESOURCE, 0,
402
NULL, NULL, "AutostartDelayRandom", (resource_value_t)0,
403
USE_PARAM_STRING, USE_DESCRIPTION_ID,
404
IDCLS_UNUSED, IDCLS_DISABLE_AUTOSTART_RANDOM_DELAY,
409
/*! \brief initialize the command-line options
412
0 on success, else -1.
415
Registers the command-line options
417
int autostart_cmdline_options_init(void)
419
return cmdline_register_options(cmdline_options);
422
/* ------------------------------------------------------------------------- */
424
/* Deallocate program name if we have one */
425
static void deallocate_program_name(void)
427
lib_free(autostart_program_name);
428
autostart_program_name = NULL;
431
static enum { YES, NO, NOT_YET } check(const char *s, unsigned int blink_mode)
433
int screen_addr, line_length, cursor_column, addr, i;
435
screen_addr = (int)(mem_read((WORD)(pnt)) | (mem_read((WORD)(pnt + 1)) << 8));
436
cursor_column = (int)mem_read((WORD)(pntr));
438
line_length = (int)(lnmx < 0 ? -lnmx : mem_read((WORD)(lnmx)) + 1);
440
DBG(("check(%s) addr:%04x column:%d, linelen:%d blnsw:%04x(%d)", s, screen_addr, cursor_column, line_length, blnsw, mem_read(blnsw)));
442
if (!kbdbuf_is_empty()) {
446
if (blink_mode == AUTOSTART_WAIT_BLINK && cursor_column != 0) {
450
if (blink_mode == AUTOSTART_WAIT_BLINK && blnsw != 0 && mem_read(blnsw) != 0) {
454
if (blink_mode == AUTOSTART_WAIT_BLINK) {
455
addr = screen_addr - line_length;
460
for (i = 0; s[i] != '\0'; i++) {
461
if (mem_read((WORD)(addr + i)) != s[i] % 64) {
462
if (mem_read((WORD)(addr + i)) != (BYTE)32) {
471
static void set_true_drive_emulation_mode(int on)
473
resources_set_int("DriveTrueEmulation", on);
477
static int get_true_drive_emulation_state(void)
481
if (resources_get_int("DriveTrueEmulation", &value) < 0) {
488
static void set_warp_mode(int on)
490
resources_set_int("WarpMode", on);
494
static int get_warp_mode(void)
498
if (resources_get_int("WarpMode", &value) < 0) {
505
static void enable_warp_if_requested(void)
507
/* enable warp mode? */
509
orig_warp_mode = get_warp_mode();
510
if (!orig_warp_mode) {
511
log_message(autostart_log, "Turning Warp mode on");
517
static void disable_warp_if_was_requested(void)
519
/* disable warp mode */
521
if (!orig_warp_mode) {
522
log_message(autostart_log, "Turning Warp mode off");
528
static void check_rom_area(void)
532
if (reg_pc >= 0xe000) {
533
log_message(autostart_log, "Entered ROM at $%04x", reg_pc);
537
/* special case for auto-starters: ROM left. We also consider
538
* BASIC area to be ROM, because it's responsible for writing "READY."
540
if (machine_addr_in_ram(reg_pc)) {
541
log_message(autostart_log, "Left ROM for $%04x", reg_pc);
542
disable_warp_if_was_requested();
548
/* ------------------------------------------------------------------------- */
550
static void load_snapshot_trap(WORD unused_addr, void *unused_data)
552
if (autostart_program_name
553
&& machine_read_snapshot((char *)autostart_program_name, 0) < 0) {
554
ui_error(translate_text(IDGS_CANNOT_LOAD_SNAPSHOT_FILE));
560
/* ------------------------------------------------------------------------- */
562
/* Reset autostart. */
563
void autostart_reinit(CLOCK _min_cycles, int _handle_drive_true_emulation,
564
int _blnsw, int _pnt, int _pntr, int _lnmx)
566
blnsw = (WORD)(_blnsw);
571
min_cycles = _min_cycles;
573
handle_drive_true_emulation_by_machine = _handle_drive_true_emulation;
575
set_handle_true_drive_emulation_state();
578
autostart_enabled = 1;
580
autostart_enabled = 0;
584
/* Initialize autostart. */
585
int autostart_init(CLOCK _min_cycles, int handle_drive_true_emulation,
586
int blnsw, int pnt, int pntr, int lnmx)
588
autostart_prg_init();
590
autostart_reinit(_min_cycles, handle_drive_true_emulation, blnsw, pnt,
593
if (autostart_log == LOG_ERR) {
594
autostart_log = log_open("AUTOSTART");
595
if (autostart_log == LOG_ERR) {
603
void autostart_disable(void)
605
if (!autostart_enabled) {
609
autostartmode = AUTOSTART_ERROR;
611
deallocate_program_name();
612
log_error(autostart_log, "Turned off.");
615
/* Control if the monitor will be triggered after an autostart */
616
void autostart_trigger_monitor(int enable)
618
trigger_monitor = enable;
621
/* this is called after successful loading */
622
static void autostart_finish(void)
624
if (autostart_run_mode == AUTOSTART_MODE_RUN) {
625
log_message(autostart_log, "Starting program.");
626
if ((machine_class == VICE_MACHINE_C128) && (c128_column4080_key == 0)) {
627
kbdbuf_feed("GRAPHIC5:");
629
kbdbuf_feed(AutostartRunCommand);
631
log_message(autostart_log, "Program loaded.");
632
if ((machine_class == VICE_MACHINE_C128) && (c128_column4080_key == 0)) {
633
kbdbuf_feed("GRAPHIC5\x0d");
638
/* This is called if all steps of an autostart operation were passed successfully */
639
static void autostart_done(void)
641
autostartmode = AUTOSTART_DONE;
643
if (machine_class == VICE_MACHINE_C128) {
644
/* restore original state of key */
645
resources_set_int("40/80ColumnKey", c128_column4080_key);
648
/* Enter monitor after done */
649
if (trigger_monitor) {
651
monitor_startup_trap();
652
log_message(autostart_log, "Done. Returning to Monitor.");
654
log_message(autostart_log, "Done.");
658
/* ------------------------------------------------------------------------- */
660
/* This function is called by the `serialreceivebyte()' trap as soon as EOF
662
static void disk_eof_callback(void)
664
if (handle_drive_true_emulation_overridden) {
665
BYTE id[2], *buffer = NULL;
666
unsigned int track, sector;
667
/* FIXME: shouldnt this loop over all drives? */
668
if (orig_drive_true_emulation_state) {
669
log_message(autostart_log, "Turning true drive emulation on.");
670
if (vdrive_bam_get_disk_id(8, id) == 0) {
671
vdrive_get_last_read(&track, §or, &buffer);
674
set_true_drive_emulation_mode(orig_drive_true_emulation_state);
675
if (orig_drive_true_emulation_state) {
677
log_message(autostart_log, "Restoring true drive state of drive 8.");
678
drive_set_disk_memory(id, track, sector, drive_context[0]);
679
drive_set_last_read(track, sector, buffer, drive_context[0]);
681
log_message(autostart_log, "No Disk Image in drive 8.");
686
if (autostartmode != AUTOSTART_NONE) {
692
machine_bus_eof_callback_set(NULL);
694
disable_warp_if_was_requested();
697
/* This function is called by the `serialattention()' trap before
699
static void disk_attention_callback(void)
701
machine_bus_attention_callback_set(NULL);
703
/* Next step is waiting for end of loading, to turn true drive emulation
705
machine_bus_eof_callback_set(disk_eof_callback);
708
/* ------------------------------------------------------------------------- */
710
static void advance_hastape(void)
714
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
716
log_message(autostart_log, "Loading file.");
717
if (autostart_program_name) {
718
tmp = util_concat("LOAD\"", autostart_program_name, "\":\r", NULL);
722
kbdbuf_feed("LOAD:\r");
724
autostartmode = AUTOSTART_PRESSPLAYONTAPE;
726
deallocate_program_name();
729
disable_warp_if_was_requested();
737
static void advance_pressplayontape(void)
739
switch (check("PRESS PLAY ON TAPE", AUTOSTART_NOWAIT_BLINK)) {
741
autostartmode = AUTOSTART_LOADINGTAPE;
742
datasette_control(DATASETTE_CONTROL_START);
745
disable_warp_if_was_requested();
753
static void advance_loadingtape(void)
755
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
757
disable_warp_if_was_requested();
762
disable_warp_if_was_requested();
766
/* leave autostart and disable warp if ROM area was left */
772
static void advance_hasdisk(void)
777
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
779
if (autostart_program_name) {
780
log_message(autostart_log, "Loading program '%s'",
781
autostart_program_name);
783
log_message(autostart_log, "Loading program '*'");
785
orig_drive_true_emulation_state = get_true_drive_emulation_state();
786
if (handle_drive_true_emulation_overridden) {
787
resources_get_int("VirtualDevices", &traps);
789
if (orig_drive_true_emulation_state) {
790
log_message(autostart_log,
791
"Turning true drive emulation off.");
793
set_true_drive_emulation_mode(0);
795
if (!orig_drive_true_emulation_state) {
796
log_message(autostart_log,
797
"Turning true drive emulation on.");
799
set_true_drive_emulation_mode(1);
802
if (!orig_drive_true_emulation_state) {
809
tmp = lib_msprintf("LOAD\"%s\",8%s:\r",
810
autostart_program_name ?
811
autostart_program_name : "*",
812
autostart_basic_load ? "" : ",1");
813
DBG(("advance_hasdisk '%s'", tmp));
819
autostartmode = AUTOSTART_WAITSEARCHINGFOR;
821
/* be most compatible if warp is disabled */
826
autostartmode = AUTOSTART_LOADINGDISK;
827
machine_bus_attention_callback_set(disk_attention_callback);
830
deallocate_program_name();
833
orig_drive_true_emulation_state = get_true_drive_emulation_state();
834
disable_warp_if_was_requested();
842
static void advance_hassnapshot(void)
844
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
847
log_message(autostart_log, "Restoring snapshot.");
848
interrupt_maincpu_trigger_trap(load_snapshot_trap, 0);
858
/* ----- stages for tde disk loading with warp --------------------------- */
860
static void advance_waitsearchingfor(void)
862
switch (check("SEARCHING FOR", AUTOSTART_NOWAIT_BLINK)) {
864
log_message(autostart_log, "Searching for ...");
865
autostartmode = AUTOSTART_WAITLOADING;
868
log_message(autostart_log, "NO Searching for ...");
869
disable_warp_if_was_requested();
877
static void advance_waitloading(void)
879
switch (check("LOADING", AUTOSTART_NOWAIT_BLINK)) {
881
log_message(autostart_log, "Loading");
883
autostartmode = AUTOSTART_WAITLOADREADY;
886
/* still showing SEARCHING FOR ? */
887
if (check("SEARCHING FOR", AUTOSTART_NOWAIT_BLINK) == YES) {
890
/* no something else is shown -> error! */
891
log_message(autostart_log, "NO Loading");
892
disable_warp_if_was_requested();
900
static void advance_waitloadready(void)
902
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
904
log_message(autostart_log, "Ready");
905
disable_warp_if_was_requested();
910
log_message(autostart_log, "NO Ready");
911
disable_warp_if_was_requested();
915
/* leave autostart and disable warp if ROM area was left */
921
/* After a reset a PRG file has to be injected into RAM */
922
static void advance_inject(void)
924
if (autostart_prg_perform_injection(autostart_log) < 0) {
925
disable_warp_if_was_requested();
928
/* wait for ready cursor and type RUN */
929
autostartmode = AUTOSTART_WAITLOADREADY;
933
/* Execute the actions for the current `autostartmode', advancing to the next
934
mode if necessary. */
935
void autostart_advance(void)
937
if (!autostart_enabled) {
941
if (orig_drive_true_emulation_state == -1) {
942
orig_drive_true_emulation_state = get_true_drive_emulation_state();
945
if (maincpu_clk < autostart_initial_delay_cycles) {
946
autostart_wait_for_reset = 0;
950
if (autostart_wait_for_reset) {
954
switch (autostartmode) {
955
case AUTOSTART_HASTAPE:
958
case AUTOSTART_PRESSPLAYONTAPE:
959
advance_pressplayontape();
961
case AUTOSTART_LOADINGTAPE:
962
advance_loadingtape();
964
case AUTOSTART_HASDISK:
967
case AUTOSTART_HASSNAPSHOT:
968
advance_hassnapshot();
970
case AUTOSTART_WAITLOADREADY:
971
advance_waitloadready();
973
case AUTOSTART_WAITLOADING:
974
advance_waitloading();
976
case AUTOSTART_WAITSEARCHINGFOR:
977
advance_waitsearchingfor();
979
case AUTOSTART_INJECT:
986
if (autostartmode == AUTOSTART_ERROR && handle_drive_true_emulation_overridden) {
987
log_message(autostart_log, "Now turning true drive emulation %s.",
988
orig_drive_true_emulation_state ? "on" : "off");
989
set_true_drive_emulation_mode(orig_drive_true_emulation_state);
993
/* Clean memory and reboot for autostart. */
994
static void reboot_for_autostart(const char *program_name, unsigned int mode,
995
unsigned int runmode)
999
if (!autostart_enabled) {
1003
log_message(autostart_log, "Resetting the machine to autostart '%s'",
1004
program_name ? program_name : "*");
1006
/* on x128 autostart will only work in 40 columns mode (and can not be fixed
1007
easily for VDC mode). We work around that by switching to 40 columns and
1009
if (machine_class == VICE_MACHINE_C128) {
1010
resources_get_int("40/80ColumnKey", &c128_column4080_key);
1011
resources_set_int("40/80ColumnKey", 1);
1016
autostart_ignore_reset = 1;
1017
deallocate_program_name();
1018
if (program_name && program_name[0]) {
1019
autostart_program_name = lib_stralloc(program_name);
1022
autostart_initial_delay_cycles = min_cycles;
1023
resources_get_int("AutostartDelayRandom", &rnd);
1025
autostart_initial_delay_cycles += AUTOSTART_RAND();
1027
DBG(("autostart_initial_delay_cycles: %d", autostart_initial_delay_cycles));
1029
machine_trigger_reset(MACHINE_RESET_MODE_SOFT);
1031
/* The autostartmode must be set AFTER the shutdown to make the autostart
1032
threadsafe for OS/2 */
1033
autostartmode = mode;
1034
autostart_run_mode = runmode;
1035
autostart_wait_for_reset = 1;
1037
/* enable warp before reset */
1038
if (mode != AUTOSTART_HASSNAPSHOT) {
1039
enable_warp_if_requested();
1043
/* ------------------------------------------------------------------------- */
1045
/* Autostart snapshot file `file_name'. */
1046
int autostart_snapshot(const char *file_name, const char *program_name)
1048
BYTE vmajor, vminor;
1051
if (network_connected() || event_record_active() || event_playback_active()
1052
|| file_name == NULL || !autostart_enabled) {
1056
deallocate_program_name(); /* not needed at all */
1058
if (!(snap = snapshot_open(file_name, &vmajor, &vminor, machine_get_name()))) {
1059
autostartmode = AUTOSTART_ERROR;
1063
log_message(autostart_log, "Loading snapshot file `%s'.", file_name);
1064
snapshot_close(snap);
1066
/*autostart_program_name = lib_stralloc(file_name);
1067
interrupt_maincpu_trigger_trap(load_snapshot_trap, 0);*/
1068
/* use for snapshot */
1069
reboot_for_autostart(file_name, AUTOSTART_HASSNAPSHOT, AUTOSTART_MODE_RUN);
1074
/* Autostart tape image `file_name'. */
1075
int autostart_tape(const char *file_name, const char *program_name,
1076
unsigned int program_number, unsigned int runmode)
1080
if (network_connected() || event_record_active() || event_playback_active()
1081
|| !file_name || !autostart_enabled) {
1085
if (!(tape_image_attach(1, file_name) < 0)) {
1086
log_message(autostart_log,
1087
"Attached file `%s' as a tape image.", file_name);
1088
if (!tape_tap_attached()) {
1089
if (program_number == 0 || program_number == 1) {
1092
program_number -= 1;
1095
if (program_number > 0) {
1096
/* program numbers in tape_seek_to_file() start at 0 */
1097
tape_seek_to_file(tape_image_dev1, program_number - 1);
1099
tape_seek_start(tape_image_dev1);
1102
resources_set_int("VirtualDevices", 1); /* Kludge: iAN CooG - for t64 images we need devtraps ON */
1103
reboot_for_autostart(program_name, AUTOSTART_HASTAPE, runmode);
1108
autostartmode = AUTOSTART_ERROR;
1109
deallocate_program_name();
1114
/* Cope with 0xa0 padded file names. */
1115
static void autostart_disk_cook_name(char **name)
1121
while ((*name)[pos] != '\0') {
1122
if (((unsigned char)((*name)[pos])) == 0xa0) {
1125
ptr = lib_malloc(pos + 1);
1126
memcpy(ptr, *name, pos);
1136
/* Autostart disk image `file_name'. */
1137
int autostart_disk(const char *file_name, const char *program_name,
1138
unsigned int program_number, unsigned int runmode)
1142
if (network_connected() || event_record_active() || event_playback_active()
1143
|| !file_name || !autostart_enabled) {
1147
/* Get program name first to avoid more than one file handle open on
1149
if (!program_name && program_number > 0) {
1150
name = image_contents_filename_by_number(diskcontents_filesystem_read(file_name), program_number);
1152
name = lib_stralloc(program_name ? program_name : "*");
1156
autostart_disk_cook_name(&name);
1157
if (!(file_system_attach_disk(8, file_name) < 0)) {
1158
log_message(autostart_log,
1159
"Attached file `%s' as a disk image.", file_name);
1160
reboot_for_autostart(name, AUTOSTART_HASDISK, runmode);
1167
autostartmode = AUTOSTART_ERROR;
1168
deallocate_program_name();
1174
/* Autostart PRG file `file_name'. The PRG file can either be a raw CBM file
1176
int autostart_prg(const char *file_name, unsigned int runmode)
1178
fileio_info_t *finfo;
1180
const char *boot_file_name;
1183
if (network_connected() || event_record_active() || event_playback_active()) {
1188
finfo = fileio_open(file_name, NULL, FILEIO_FORMAT_RAW | FILEIO_FORMAT_P00,
1189
FILEIO_COMMAND_READ | FILEIO_COMMAND_FSNAME,
1192
/* can't open file */
1193
if (finfo == NULL) {
1194
log_error(autostart_log, "Cannot open `%s'.", file_name);
1198
/* determine how to load file */
1199
switch (AutostartPrgMode) {
1200
case AUTOSTART_PRG_MODE_VFS:
1201
log_message(autostart_log, "Loading PRG file `%s' with virtual FS on unit #8.", file_name);
1202
result = autostart_prg_with_virtual_fs(file_name, finfo, autostart_log);
1203
mode = AUTOSTART_HASDISK;
1204
boot_file_name = (const char *)finfo->name;
1206
case AUTOSTART_PRG_MODE_INJECT:
1207
log_message(autostart_log, "Loading PRG file `%s' with direct RAM injection.", file_name);
1208
result = autostart_prg_with_ram_injection(file_name, finfo, autostart_log);
1209
mode = AUTOSTART_INJECT;
1210
boot_file_name = NULL;
1212
case AUTOSTART_PRG_MODE_DISK:
1213
log_message(autostart_log, "Loading PRG file `%s' with autostart disk image.", file_name);
1214
result = autostart_prg_with_disk_image(file_name, finfo, autostart_log, AutostartPrgDiskImage);
1215
mode = AUTOSTART_HASDISK;
1216
boot_file_name = "*";
1219
log_error(autostart_log, "Invalid PRG autostart mode: %d", AutostartPrgMode);
1224
/* Now either proceed with disk image booting or prg injection after reset */
1227
reboot_for_autostart(boot_file_name, mode, runmode);
1230
/* close prg file */
1231
fileio_close(finfo);
1236
/* ------------------------------------------------------------------------- */
1238
int autostart_autodetect_opt_prgname(const char *file_prog_name,
1239
unsigned int alt_prg_number,
1240
unsigned int runmode)
1245
/* Check for image:prg -format. */
1246
tmp = strrchr(file_prog_name, ':');
1248
char *autostart_prg_name;
1249
char *autostart_file;
1251
autostart_file = lib_stralloc(file_prog_name);
1252
autostart_prg_name = strrchr(autostart_file, ':');
1253
*autostart_prg_name++ = '\0';
1254
/* Does the image exist? */
1255
if (util_file_exists(autostart_file)) {
1258
charset_petconvstring((BYTE *)autostart_prg_name, 0);
1259
name = charset_replace_hexcodes(autostart_prg_name);
1260
result = autostart_autodetect(autostart_file, name, 0,
1264
result = autostart_autodetect(file_prog_name, NULL, alt_prg_number,
1267
lib_free(autostart_file);
1269
result = autostart_autodetect(file_prog_name, NULL, alt_prg_number,
1275
/* Autostart `file_name', trying to auto-detect its type. */
1276
int autostart_autodetect(const char *file_name, const char *program_name,
1277
unsigned int program_number, unsigned int runmode)
1279
if (network_connected() || event_record_active() || event_playback_active()
1280
|| file_name == NULL) {
1284
if (!autostart_enabled) {
1285
log_error(autostart_log,
1286
"Autostart is not available on this setup.");
1290
log_message(autostart_log, "Autodetecting image type of `%s'.", file_name);
1292
if (autostart_disk(file_name, program_name, program_number, runmode) == 0) {
1293
log_message(autostart_log, "`%s' recognized as disk image.", file_name);
1297
if (machine_class != VICE_MACHINE_C64DTV && machine_class != VICE_MACHINE_SCPU64) {
1298
if (autostart_tape(file_name, program_name, program_number, runmode) == 0) {
1299
log_message(autostart_log, "`%s' recognized as tape image.", file_name);
1304
if (autostart_snapshot(file_name, program_name) == 0) {
1305
log_message(autostart_log, "`%s' recognized as snapshot image.",
1309
if (autostart_prg(file_name, runmode) == 0) {
1310
log_message(autostart_log, "`%s' recognized as program/p00 file.",
1315
log_error(autostart_log, "`%s' is not a valid file.", file_name);
1319
/* Autostart the image attached to device `num'. */
1320
int autostart_device(int num)
1322
if (network_connected() || event_playback_active() || event_record_active()
1323
|| !autostart_enabled) {
1329
reboot_for_autostart(NULL, AUTOSTART_HASDISK, AUTOSTART_MODE_RUN);
1332
reboot_for_autostart(NULL, AUTOSTART_HASTAPE, AUTOSTART_MODE_RUN);
1338
int autostart_in_progress(void)
1340
return (autostartmode != AUTOSTART_NONE && autostartmode != AUTOSTART_DONE);
1343
/* Disable autostart on reset. */
1344
void autostart_reset(void)
1348
if (!autostart_enabled) {
1352
if (!autostart_ignore_reset
1353
&& autostartmode != AUTOSTART_NONE
1354
&& autostartmode != AUTOSTART_ERROR) {
1355
oldmode = autostartmode;
1356
autostartmode = AUTOSTART_NONE;
1357
if (oldmode != AUTOSTART_DONE) {
1358
disk_eof_callback();
1360
autostartmode = AUTOSTART_NONE;
1361
trigger_monitor = 0;
1362
deallocate_program_name();
1363
log_message(autostart_log, "Turned off.");
1365
autostart_ignore_reset = 0;
1368
void autostart_shutdown(void)
1370
deallocate_program_name();
1372
autostart_prg_shutdown();
1375
#ifdef ANDROID_COMPILE
1376
void loader_set_warpmode(int on)
2
* autostart.c - Automatic image loading and starting.
5
* Teemu Rantanen <tvr@cs.hut.fi>
6
* Ettore Perazzoli <ettore@comm2000.it>
7
* Andr� Fachat <a.fachat@physik.tu-chemnitz.de>
8
* Andreas Boose <viceteam@t-online.de>
9
* Thomas Bretz <tbretz@ph.tum.de>
11
* This file is part of VICE, the Versatile Commodore Emulator.
12
* See README for copyright notice.
14
* This program is free software; you can redistribute it and/or modify
15
* it under the terms of the GNU General Public License as published by
16
* the Free Software Foundation; either version 2 of the License, or
17
* (at your option) any later version.
19
* This program is distributed in the hope that it will be useful,
20
* but WITHOUT ANY WARRANTY; without even the implied warranty of
21
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22
* GNU General Public License for more details.
24
* You should have received a copy of the GNU General Public License
25
* along with this program; if not, write to the Free Software
26
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
31
/* #define DEBUG_AUTOSTART */
41
#include "autostart.h"
42
#include "autostart-prg.h"
46
#include "datasette.h"
50
#include "imagecontents.h"
51
#include "tapecontents.h"
52
#include "diskcontents.h"
53
#include "interrupt.h"
57
#include "machine-bus.h"
63
#include "resources.h"
66
#include "translate.h"
71
#include "vdrive-bam.h"
72
#include "vice-event.h"
74
#ifdef DEBUG_AUTOSTART
75
#define DBG(_x_) log_debug _x_
80
static void autostart_done(void);
81
static void autostart_finish(void);
83
/* Kernal addresses. Set by `autostart_init()'. */
85
static WORD blnsw; /* Cursor Blink enable: 0 = Flash Cursor */
86
static int pnt; /* Pointer: Current Screen Line Address */
87
static int pntr; /* Cursor Column on Current Line */
88
static int lnmx; /* Physical Screen Line Length */
90
/* Current state of the autostart routine. */
95
AUTOSTART_PRESSPLAYONTAPE,
96
AUTOSTART_LOADINGTAPE,
98
AUTOSTART_LOADINGDISK,
99
AUTOSTART_HASSNAPSHOT,
100
AUTOSTART_WAITLOADREADY,
101
AUTOSTART_WAITLOADING,
102
AUTOSTART_WAITSEARCHINGFOR,
105
} autostartmode = AUTOSTART_NONE;
107
#define AUTOSTART_WAIT_BLINK 0
108
#define AUTOSTART_NOWAIT_BLINK 1
110
/* Log descriptor. */
111
static log_t autostart_log = LOG_ERR;
113
/* Flag: was true drive emulation turned on when we started booting the disk
115
static int orig_drive_true_emulation_state = -1;
117
/* Flag: warp mode state before booting */
118
static int orig_warp_mode = -1;
120
/* PETSCII name of the program to load. NULL if default */
121
static char *autostart_program_name = NULL;
123
/* Minimum number of cycles before we feed BASIC with commands. */
124
static CLOCK min_cycles;
125
static CLOCK autostart_initial_delay_cycles;
127
/* Flag: Do we want to switch true drive emulation on/off during autostart?
128
* Normally, this is the same as handle_drive_true_emulation_by_machine;
129
* however, the user can override this decision by specifying
130
* -autostart-no-true-drive-emulation
132
static int handle_drive_true_emulation_overridden;
134
/* Flag: Does the machine want us to switch true drive emulation on/off during autostart? */
135
static int handle_drive_true_emulation_by_machine;
137
/* Flag: autostart is initialized. */
138
static int autostart_enabled = 0;
140
/* Flag: Autostart the file or just load it? */
141
static unsigned int autostart_run_mode;
143
/* Flag: maincpu_clk isn't resetted yet */
144
static int autostart_wait_for_reset;
146
/* Flag: load stage after LOADING enters ROM area */
147
static int entered_rom = 0;
149
/* Flag: trap monitor after done */
150
static int trigger_monitor = 0;
152
int autostart_ignore_reset = 0; /* FIXME: only used by datasette.c, does it really have to be global? */
154
/* additional random delay of up to 10 frames */
155
#define AUTOSTART_RAND() (1 + (int)(((float)machine_get_cycles_per_frame()) * 10.0f * rand() / (RAND_MAX + 1.0)))
157
/* flag for special case handling of C128 80 columns mode */
158
static int c128_column4080_key;
160
/* ------------------------------------------------------------------------- */
162
static int autostart_basic_load = 0;
164
static int AutostartRunWithColon = 0;
166
static int AutostartHandleTrueDriveEmulation = 0;
168
static int AutostartWarp = 0;
170
static int AutostartDelay = 0;
171
static int AutostartDelayRandom = 0;
173
static int AutostartPrgMode = AUTOSTART_PRG_MODE_VFS;
175
static char *AutostartPrgDiskImage = NULL;
177
static const char * const AutostartRunCommandsAvailable[] = {
181
static const char * AutostartRunCommand = NULL;
183
static void set_handle_true_drive_emulation_state(void)
185
handle_drive_true_emulation_overridden =
186
AutostartHandleTrueDriveEmulation ?
187
handle_drive_true_emulation_by_machine : 0;
190
/*! \internal \brief set if autostart should use LOAD ... ,1 */
191
static int set_autostart_basic_load(int val, void *param)
193
autostart_basic_load = val ? 1 : 0;
198
/*! \internal \brief set if autostart should execute with a colon or not
201
if 0, the "RUN" command at the end of autostart is executed without
202
a colon; else, it will be executed with a colon.
208
0 on success. else -1.
210
static int set_autostart_run_with_colon(int val, void *param)
212
AutostartRunWithColon = val ? 1 : 0;
214
AutostartRunCommand = AutostartRunCommandsAvailable[AutostartRunWithColon];
219
/*! \internal \brief set if autostart should handle TDE or not
222
if 0, autostart does not handle TDE even if the machine says it can
229
0 on success. else -1.
231
static int set_autostart_handle_tde(int val, void *param)
233
AutostartHandleTrueDriveEmulation = val ? 1 : 0;
235
set_handle_true_drive_emulation_state();
240
/*! \internal \brief set if autostart should enable warp mode */
241
static int set_autostart_warp(int val, void *param)
243
AutostartWarp = val ? 1 : 0;
248
/*! \internal \brief set initial autostart delay. 0 means default. */
249
static int set_autostart_delay(int val, void *param)
251
if ((val < 0) || (val > 1000)) {
254
AutostartDelay = val;
258
/*! \internal \brief set initial autostart random delay. 0 means off, 1 means on. */
259
static int set_autostart_delayrandom(int val, void *param)
261
AutostartDelayRandom = val ? 1 : 0;
265
/*! \internal \brief set autostart prg mode */
266
static int set_autostart_prg_mode(int val, void *param)
268
if ((val < 0) || (val > AUTOSTART_PRG_MODE_LAST)) {
269
val = AUTOSTART_PRG_MODE_DEFAULT;
271
AutostartPrgMode = val;
276
/*! \internal \brief set disk image name of autostart prg mode */
278
static int set_autostart_prg_disk_image(const char *val, void *param)
280
if (util_string_set(&AutostartPrgDiskImage, val)) {
287
/*! \brief string resources used by autostart */
288
static resource_string_t resources_string[] = {
289
{ "AutostartPrgDiskImage", NULL, RES_EVENT_NO, NULL,
290
&AutostartPrgDiskImage, set_autostart_prg_disk_image, NULL },
294
/*! \brief integer resources used by autostart */
295
static const resource_int_t resources_int[] = {
296
{ "AutostartBasicLoad", 0, RES_EVENT_NO, (resource_value_t)0,
297
&autostart_basic_load, set_autostart_basic_load, NULL },
298
{ "AutostartRunWithColon", 0, RES_EVENT_NO, (resource_value_t)0,
299
&AutostartRunWithColon, set_autostart_run_with_colon, NULL },
300
{ "AutostartHandleTrueDriveEmulation", 0, RES_EVENT_NO, (resource_value_t)0,
301
&AutostartHandleTrueDriveEmulation, set_autostart_handle_tde, NULL },
302
{ "AutostartWarp", 1, RES_EVENT_NO, (resource_value_t)0,
303
&AutostartWarp, set_autostart_warp, NULL },
304
{ "AutostartPrgMode", AUTOSTART_PRG_MODE_DEFAULT, RES_EVENT_NO, (resource_value_t)0,
305
&AutostartPrgMode, set_autostart_prg_mode, NULL },
306
{ "AutostartDelay", 0, RES_EVENT_NO, (resource_value_t)0,
307
&AutostartDelay, set_autostart_delay, NULL },
308
{ "AutostartDelayRandom", 1, RES_EVENT_NO, (resource_value_t)0,
309
&AutostartDelayRandom, set_autostart_delayrandom, NULL },
313
/*! \brief initialize the resources
315
0 on success, else -1.
318
Registers the integer resources
320
int autostart_resources_init(void)
322
resources_string[0].factory_value = archdep_default_autostart_disk_image_file_name();
324
if (resources_register_string(resources_string) < 0) {
328
return resources_register_int(resources_int);
331
void autostart_resources_shutdown(void)
333
lib_free(AutostartPrgDiskImage);
334
lib_free(resources_string[0].factory_value);
337
/* ------------------------------------------------------------------------- */
339
static const cmdline_option_t cmdline_options[] =
341
{ "-basicload", SET_RESOURCE, 0,
342
NULL, NULL, "AutostartBasicLoad", (resource_value_t)1,
343
USE_PARAM_STRING, USE_DESCRIPTION_ID,
344
IDCLS_UNUSED, IDCLS_AUTOSTART_LOAD_TO_BASIC_START,
346
{ "+basicload", SET_RESOURCE, 0,
347
NULL, NULL, "AutostartBasicLoad", (resource_value_t)0,
348
USE_PARAM_STRING, USE_DESCRIPTION_ID,
349
IDCLS_UNUSED, IDCLS_AUTOSTART_LOAD_WITH_1,
351
{ "-autostartwithcolon", SET_RESOURCE, 0,
352
NULL, NULL, "AutostartRunWithColon", (resource_value_t)1,
353
USE_PARAM_STRING, USE_DESCRIPTION_ID,
354
IDCLS_UNUSED, IDCLS_ENABLE_AUTOSTARTWITHCOLON,
356
{ "+autostartwithcolon", SET_RESOURCE, 0,
357
NULL, NULL, "AutostartRunWithColon", (resource_value_t)0,
358
USE_PARAM_STRING, USE_DESCRIPTION_ID,
359
IDCLS_UNUSED, IDCLS_DISABLE_AUTOSTARTWITHCOLON,
361
{ "-autostart-handle-tde", SET_RESOURCE, 0,
362
NULL, NULL, "AutostartHandleTrueDriveEmulation", (resource_value_t)1,
363
USE_PARAM_STRING, USE_DESCRIPTION_ID,
364
IDCLS_UNUSED, IDCLS_ENABLE_AUTOSTART_HANDLE_TDE,
366
{ "+autostart-handle-tde", SET_RESOURCE, 0,
367
NULL, NULL, "AutostartHandleTrueDriveEmulation", (resource_value_t)0,
368
USE_PARAM_STRING, USE_DESCRIPTION_ID,
369
IDCLS_UNUSED, IDCLS_DISABLE_AUTOSTART_HANDLE_TDE,
371
{ "-autostart-warp", SET_RESOURCE, 0,
372
NULL, NULL, "AutostartWarp", (resource_value_t)1,
373
USE_PARAM_STRING, USE_DESCRIPTION_ID,
374
IDCLS_UNUSED, IDCLS_ENABLE_WARP_MODE_AUTOSTART,
376
{ "+autostart-warp", SET_RESOURCE, 0,
377
NULL, NULL, "AutostartWarp", (resource_value_t)0,
378
USE_PARAM_STRING, USE_DESCRIPTION_ID,
379
IDCLS_UNUSED, IDCLS_DISABLE_WARP_MODE_AUTOSTART,
381
{ "-autostartprgmode", SET_RESOURCE, 1,
382
NULL, NULL, "AutostartPrgMode", NULL,
383
USE_PARAM_ID, USE_DESCRIPTION_ID,
384
IDCLS_P_MODE, IDCLS_SET_AUTOSTART_MODE_FOR_PRG,
386
{ "-autostartprgdiskimage", SET_RESOURCE, 1,
387
NULL, NULL, "AutostartPrgDiskImage", NULL,
388
USE_PARAM_ID, USE_DESCRIPTION_ID,
389
IDCLS_P_NAME, IDCLS_SET_DISK_IMAGE_FOR_AUTOSTART_PRG,
391
{ "-autostart-delay", SET_RESOURCE, 1,
392
NULL, NULL, "AutostartDelay", NULL,
393
USE_PARAM_ID, USE_DESCRIPTION_ID,
394
IDCLS_P_SECONDS, IDCLS_SET_AUTOSTART_DELAY,
396
{ "-autostart-delay-random", SET_RESOURCE, 0,
397
NULL, NULL, "AutostartDelayRandom", (resource_value_t)1,
398
USE_PARAM_STRING, USE_DESCRIPTION_ID,
399
IDCLS_UNUSED, IDCLS_ENABLE_AUTOSTART_RANDOM_DELAY,
401
{ "+autostart-delay-random", SET_RESOURCE, 0,
402
NULL, NULL, "AutostartDelayRandom", (resource_value_t)0,
403
USE_PARAM_STRING, USE_DESCRIPTION_ID,
404
IDCLS_UNUSED, IDCLS_DISABLE_AUTOSTART_RANDOM_DELAY,
409
/*! \brief initialize the command-line options
412
0 on success, else -1.
415
Registers the command-line options
417
int autostart_cmdline_options_init(void)
419
return cmdline_register_options(cmdline_options);
422
/* ------------------------------------------------------------------------- */
424
/* Deallocate program name if we have one */
425
static void deallocate_program_name(void)
427
lib_free(autostart_program_name);
428
autostart_program_name = NULL;
431
static enum { YES, NO, NOT_YET } check(const char *s, unsigned int blink_mode)
433
int screen_addr, line_length, cursor_column, addr, i;
435
screen_addr = (int)(mem_read((WORD)(pnt)) | (mem_read((WORD)(pnt + 1)) << 8));
436
cursor_column = (int)mem_read((WORD)(pntr));
438
line_length = (int)(lnmx < 0 ? -lnmx : mem_read((WORD)(lnmx)) + 1);
440
DBG(("check(%s) addr:%04x column:%d, linelen:%d blnsw:%04x(%d)", s, screen_addr, cursor_column, line_length, blnsw, mem_read(blnsw)));
442
if (!kbdbuf_is_empty()) {
446
if (blink_mode == AUTOSTART_WAIT_BLINK && cursor_column != 0) {
450
if (blink_mode == AUTOSTART_WAIT_BLINK && blnsw != 0 && mem_read(blnsw) != 0) {
454
if (blink_mode == AUTOSTART_WAIT_BLINK) {
455
addr = screen_addr - line_length;
460
for (i = 0; s[i] != '\0'; i++) {
461
if (mem_read((WORD)(addr + i)) != s[i] % 64) {
462
if (mem_read((WORD)(addr + i)) != (BYTE)32) {
471
static void set_true_drive_emulation_mode(int on)
473
resources_set_int("DriveTrueEmulation", on);
477
static int get_true_drive_emulation_state(void)
481
if (resources_get_int("DriveTrueEmulation", &value) < 0) {
488
static void set_warp_mode(int on)
490
resources_set_int("WarpMode", on);
494
static int get_warp_mode(void)
498
if (resources_get_int("WarpMode", &value) < 0) {
505
static void enable_warp_if_requested(void)
507
/* enable warp mode? */
509
orig_warp_mode = get_warp_mode();
510
if (!orig_warp_mode) {
511
log_message(autostart_log, "Turning Warp mode on");
517
static void disable_warp_if_was_requested(void)
519
/* disable warp mode */
521
if (!orig_warp_mode) {
522
log_message(autostart_log, "Turning Warp mode off");
528
static void check_rom_area(void)
532
if (reg_pc >= 0xe000) {
533
log_message(autostart_log, "Entered ROM at $%04x", reg_pc);
537
/* special case for auto-starters: ROM left. We also consider
538
* BASIC area to be ROM, because it's responsible for writing "READY."
540
if (machine_addr_in_ram(reg_pc)) {
541
log_message(autostart_log, "Left ROM for $%04x", reg_pc);
542
disable_warp_if_was_requested();
548
/* ------------------------------------------------------------------------- */
550
static void load_snapshot_trap(WORD unused_addr, void *unused_data)
552
if (autostart_program_name
553
&& machine_read_snapshot((char *)autostart_program_name, 0) < 0) {
554
ui_error(translate_text(IDGS_CANNOT_LOAD_SNAPSHOT_FILE));
560
/* ------------------------------------------------------------------------- */
562
/* Reset autostart. */
563
void autostart_reinit(CLOCK _min_cycles, int _handle_drive_true_emulation,
564
int _blnsw, int _pnt, int _pntr, int _lnmx)
566
blnsw = (WORD)(_blnsw);
571
min_cycles = _min_cycles;
573
handle_drive_true_emulation_by_machine = _handle_drive_true_emulation;
575
set_handle_true_drive_emulation_state();
578
autostart_enabled = 1;
580
autostart_enabled = 0;
584
/* Initialize autostart. */
585
int autostart_init(CLOCK _min_cycles, int handle_drive_true_emulation,
586
int blnsw, int pnt, int pntr, int lnmx)
588
autostart_prg_init();
590
autostart_reinit(_min_cycles, handle_drive_true_emulation, blnsw, pnt,
593
if (autostart_log == LOG_ERR) {
594
autostart_log = log_open("AUTOSTART");
595
if (autostart_log == LOG_ERR) {
603
void autostart_disable(void)
605
if (!autostart_enabled) {
609
autostartmode = AUTOSTART_ERROR;
611
deallocate_program_name();
612
log_error(autostart_log, "Turned off.");
615
/* Control if the monitor will be triggered after an autostart */
616
void autostart_trigger_monitor(int enable)
618
trigger_monitor = enable;
621
/* this is called after successful loading */
622
static void autostart_finish(void)
624
if (autostart_run_mode == AUTOSTART_MODE_RUN) {
625
log_message(autostart_log, "Starting program.");
626
if ((machine_class == VICE_MACHINE_C128) && (c128_column4080_key == 0)) {
627
kbdbuf_feed("GRAPHIC5:");
629
kbdbuf_feed(AutostartRunCommand);
631
log_message(autostart_log, "Program loaded.");
632
if ((machine_class == VICE_MACHINE_C128) && (c128_column4080_key == 0)) {
633
kbdbuf_feed("GRAPHIC5\x0d");
638
/* This is called if all steps of an autostart operation were passed successfully */
639
static void autostart_done(void)
641
autostartmode = AUTOSTART_DONE;
643
if (machine_class == VICE_MACHINE_C128) {
644
/* restore original state of key */
645
resources_set_int("40/80ColumnKey", c128_column4080_key);
648
/* Enter monitor after done */
649
if (trigger_monitor) {
651
monitor_startup_trap();
652
log_message(autostart_log, "Done. Returning to Monitor.");
654
log_message(autostart_log, "Done.");
658
/* ------------------------------------------------------------------------- */
660
/* This function is called by the `serialreceivebyte()' trap as soon as EOF
662
static void disk_eof_callback(void)
664
if (handle_drive_true_emulation_overridden) {
665
BYTE id[2], *buffer = NULL;
666
unsigned int track, sector;
667
/* FIXME: shouldnt this loop over all drives? */
668
if (orig_drive_true_emulation_state) {
669
log_message(autostart_log, "Turning true drive emulation on.");
670
if (vdrive_bam_get_disk_id(8, id) == 0) {
671
vdrive_get_last_read(&track, §or, &buffer);
674
set_true_drive_emulation_mode(orig_drive_true_emulation_state);
675
if (orig_drive_true_emulation_state) {
677
log_message(autostart_log, "Restoring true drive state of drive 8.");
678
drive_set_disk_memory(id, track, sector, drive_context[0]);
679
drive_set_last_read(track, sector, buffer, drive_context[0]);
681
log_message(autostart_log, "No Disk Image in drive 8.");
686
if (autostartmode != AUTOSTART_NONE) {
692
machine_bus_eof_callback_set(NULL);
694
disable_warp_if_was_requested();
697
/* This function is called by the `serialattention()' trap before
699
static void disk_attention_callback(void)
701
machine_bus_attention_callback_set(NULL);
703
/* Next step is waiting for end of loading, to turn true drive emulation
705
machine_bus_eof_callback_set(disk_eof_callback);
708
/* ------------------------------------------------------------------------- */
710
static void advance_hastape(void)
714
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
716
log_message(autostart_log, "Loading file.");
717
if (autostart_program_name) {
718
tmp = util_concat("LOAD\"", autostart_program_name, "\":\r", NULL);
722
kbdbuf_feed("LOAD:\r");
724
autostartmode = AUTOSTART_PRESSPLAYONTAPE;
726
deallocate_program_name();
729
disable_warp_if_was_requested();
737
static void advance_pressplayontape(void)
739
switch (check("PRESS PLAY ON TAPE", AUTOSTART_NOWAIT_BLINK)) {
741
autostartmode = AUTOSTART_LOADINGTAPE;
742
datasette_control(DATASETTE_CONTROL_START);
745
disable_warp_if_was_requested();
753
static void advance_loadingtape(void)
755
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
757
disable_warp_if_was_requested();
762
disable_warp_if_was_requested();
766
/* leave autostart and disable warp if ROM area was left */
772
static void advance_hasdisk(void)
777
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
779
if (autostart_program_name) {
780
log_message(autostart_log, "Loading program '%s'",
781
autostart_program_name);
783
log_message(autostart_log, "Loading program '*'");
785
orig_drive_true_emulation_state = get_true_drive_emulation_state();
786
if (handle_drive_true_emulation_overridden) {
787
resources_get_int("VirtualDevices", &traps);
789
if (orig_drive_true_emulation_state) {
790
log_message(autostart_log,
791
"Turning true drive emulation off.");
793
set_true_drive_emulation_mode(0);
795
if (!orig_drive_true_emulation_state) {
796
log_message(autostart_log,
797
"Turning true drive emulation on.");
799
set_true_drive_emulation_mode(1);
802
if (!orig_drive_true_emulation_state) {
809
tmp = lib_msprintf("LOAD\"%s\",8%s:\r",
810
autostart_program_name ?
811
autostart_program_name : "*",
812
autostart_basic_load ? "" : ",1");
813
DBG(("advance_hasdisk '%s'", tmp));
819
autostartmode = AUTOSTART_WAITSEARCHINGFOR;
821
/* be most compatible if warp is disabled */
826
autostartmode = AUTOSTART_LOADINGDISK;
827
machine_bus_attention_callback_set(disk_attention_callback);
830
deallocate_program_name();
833
orig_drive_true_emulation_state = get_true_drive_emulation_state();
834
disable_warp_if_was_requested();
842
static void advance_hassnapshot(void)
844
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
847
log_message(autostart_log, "Restoring snapshot.");
848
interrupt_maincpu_trigger_trap(load_snapshot_trap, 0);
858
/* ----- stages for tde disk loading with warp --------------------------- */
860
static void advance_waitsearchingfor(void)
862
switch (check("SEARCHING FOR", AUTOSTART_NOWAIT_BLINK)) {
864
log_message(autostart_log, "Searching for ...");
865
autostartmode = AUTOSTART_WAITLOADING;
868
log_message(autostart_log, "NO Searching for ...");
869
disable_warp_if_was_requested();
877
static void advance_waitloading(void)
879
switch (check("LOADING", AUTOSTART_NOWAIT_BLINK)) {
881
log_message(autostart_log, "Loading");
883
autostartmode = AUTOSTART_WAITLOADREADY;
886
/* still showing SEARCHING FOR ? */
887
if (check("SEARCHING FOR", AUTOSTART_NOWAIT_BLINK) == YES) {
890
/* no something else is shown -> error! */
891
log_message(autostart_log, "NO Loading");
892
disable_warp_if_was_requested();
900
static void advance_waitloadready(void)
902
switch (check("READY.", AUTOSTART_WAIT_BLINK)) {
904
log_message(autostart_log, "Ready");
905
disable_warp_if_was_requested();
910
log_message(autostart_log, "NO Ready");
911
disable_warp_if_was_requested();
915
/* leave autostart and disable warp if ROM area was left */
921
/* After a reset a PRG file has to be injected into RAM */
922
static void advance_inject(void)
924
if (autostart_prg_perform_injection(autostart_log) < 0) {
925
disable_warp_if_was_requested();
928
/* wait for ready cursor and type RUN */
929
autostartmode = AUTOSTART_WAITLOADREADY;
933
/* Execute the actions for the current `autostartmode', advancing to the next
934
mode if necessary. */
935
void autostart_advance(void)
937
if (!autostart_enabled) {
941
if (orig_drive_true_emulation_state == -1) {
942
orig_drive_true_emulation_state = get_true_drive_emulation_state();
945
if (maincpu_clk < autostart_initial_delay_cycles) {
946
autostart_wait_for_reset = 0;
950
if (autostart_wait_for_reset) {
954
switch (autostartmode) {
955
case AUTOSTART_HASTAPE:
958
case AUTOSTART_PRESSPLAYONTAPE:
959
advance_pressplayontape();
961
case AUTOSTART_LOADINGTAPE:
962
advance_loadingtape();
964
case AUTOSTART_HASDISK:
967
case AUTOSTART_HASSNAPSHOT:
968
advance_hassnapshot();
970
case AUTOSTART_WAITLOADREADY:
971
advance_waitloadready();
973
case AUTOSTART_WAITLOADING:
974
advance_waitloading();
976
case AUTOSTART_WAITSEARCHINGFOR:
977
advance_waitsearchingfor();
979
case AUTOSTART_INJECT:
986
if (autostartmode == AUTOSTART_ERROR && handle_drive_true_emulation_overridden) {
987
log_message(autostart_log, "Now turning true drive emulation %s.",
988
orig_drive_true_emulation_state ? "on" : "off");
989
set_true_drive_emulation_mode(orig_drive_true_emulation_state);
993
/* Clean memory and reboot for autostart. */
994
static void reboot_for_autostart(const char *program_name, unsigned int mode,
995
unsigned int runmode)
999
if (!autostart_enabled) {
1003
log_message(autostart_log, "Resetting the machine to autostart '%s'",
1004
program_name ? program_name : "*");
1006
/* on x128 autostart will only work in 40 columns mode (and can not be fixed
1007
easily for VDC mode). We work around that by switching to 40 columns and
1009
if (machine_class == VICE_MACHINE_C128) {
1010
resources_get_int("40/80ColumnKey", &c128_column4080_key);
1011
resources_set_int("40/80ColumnKey", 1);
1016
autostart_ignore_reset = 1;
1017
deallocate_program_name();
1018
if (program_name && program_name[0]) {
1019
autostart_program_name = lib_stralloc(program_name);
1022
autostart_initial_delay_cycles = min_cycles;
1023
resources_get_int("AutostartDelayRandom", &rnd);
1025
autostart_initial_delay_cycles += AUTOSTART_RAND();
1027
DBG(("autostart_initial_delay_cycles: %d", autostart_initial_delay_cycles));
1029
machine_trigger_reset(MACHINE_RESET_MODE_SOFT);
1031
/* The autostartmode must be set AFTER the shutdown to make the autostart
1032
threadsafe for OS/2 */
1033
autostartmode = mode;
1034
autostart_run_mode = runmode;
1035
autostart_wait_for_reset = 1;
1037
/* enable warp before reset */
1038
if (mode != AUTOSTART_HASSNAPSHOT) {
1039
enable_warp_if_requested();
1043
/* ------------------------------------------------------------------------- */
1045
/* Autostart snapshot file `file_name'. */
1046
int autostart_snapshot(const char *file_name, const char *program_name)
1048
BYTE vmajor, vminor;
1051
if (network_connected() || event_record_active() || event_playback_active()
1052
|| file_name == NULL || !autostart_enabled) {
1056
deallocate_program_name(); /* not needed at all */
1058
if (!(snap = snapshot_open(file_name, &vmajor, &vminor, machine_get_name()))) {
1059
autostartmode = AUTOSTART_ERROR;
1063
log_message(autostart_log, "Loading snapshot file `%s'.", file_name);
1064
snapshot_close(snap);
1066
/*autostart_program_name = lib_stralloc(file_name);
1067
interrupt_maincpu_trigger_trap(load_snapshot_trap, 0);*/
1068
/* use for snapshot */
1069
reboot_for_autostart(file_name, AUTOSTART_HASSNAPSHOT, AUTOSTART_MODE_RUN);
1074
/* Autostart tape image `file_name'. */
1075
int autostart_tape(const char *file_name, const char *program_name,
1076
unsigned int program_number, unsigned int runmode)
1080
if (network_connected() || event_record_active() || event_playback_active()
1081
|| !file_name || !autostart_enabled) {
1085
if (!(tape_image_attach(1, file_name) < 0)) {
1086
log_message(autostart_log,
1087
"Attached file `%s' as a tape image.", file_name);
1088
if (!tape_tap_attached()) {
1089
if (program_number == 0 || program_number == 1) {
1092
program_number -= 1;
1095
if (program_number > 0) {
1096
/* program numbers in tape_seek_to_file() start at 0 */
1097
tape_seek_to_file(tape_image_dev1, program_number - 1);
1099
tape_seek_start(tape_image_dev1);
1102
resources_set_int("VirtualDevices", 1); /* Kludge: iAN CooG - for t64 images we need devtraps ON */
1103
reboot_for_autostart(program_name, AUTOSTART_HASTAPE, runmode);
1108
autostartmode = AUTOSTART_ERROR;
1109
deallocate_program_name();
1114
/* Cope with 0xa0 padded file names. */
1115
static void autostart_disk_cook_name(char **name)
1121
while ((*name)[pos] != '\0') {
1122
if (((unsigned char)((*name)[pos])) == 0xa0) {
1125
ptr = lib_malloc(pos + 1);
1126
memcpy(ptr, *name, pos);
1136
/* Autostart disk image `file_name'. */
1137
int autostart_disk(const char *file_name, const char *program_name,
1138
unsigned int program_number, unsigned int runmode)
1142
if (network_connected() || event_record_active() || event_playback_active()
1143
|| !file_name || !autostart_enabled) {
1147
/* Get program name first to avoid more than one file handle open on
1149
if (!program_name && program_number > 0) {
1150
name = image_contents_filename_by_number(diskcontents_filesystem_read(file_name), program_number);
1152
name = lib_stralloc(program_name ? program_name : "*");
1156
autostart_disk_cook_name(&name);
1157
if (!(file_system_attach_disk(8, file_name) < 0)) {
1158
log_message(autostart_log,
1159
"Attached file `%s' as a disk image.", file_name);
1160
reboot_for_autostart(name, AUTOSTART_HASDISK, runmode);
1167
autostartmode = AUTOSTART_ERROR;
1168
deallocate_program_name();
1174
/* Autostart PRG file `file_name'. The PRG file can either be a raw CBM file
1176
int autostart_prg(const char *file_name, unsigned int runmode)
1178
fileio_info_t *finfo;
1180
const char *boot_file_name;
1183
if (network_connected() || event_record_active() || event_playback_active()) {
1188
finfo = fileio_open(file_name, NULL, FILEIO_FORMAT_RAW | FILEIO_FORMAT_P00,
1189
FILEIO_COMMAND_READ | FILEIO_COMMAND_FSNAME,
1192
/* can't open file */
1193
if (finfo == NULL) {
1194
log_error(autostart_log, "Cannot open `%s'.", file_name);
1198
/* determine how to load file */
1199
switch (AutostartPrgMode) {
1200
case AUTOSTART_PRG_MODE_VFS:
1201
log_message(autostart_log, "Loading PRG file `%s' with virtual FS on unit #8.", file_name);
1202
result = autostart_prg_with_virtual_fs(file_name, finfo, autostart_log);
1203
mode = AUTOSTART_HASDISK;
1204
boot_file_name = (const char *)finfo->name;
1206
case AUTOSTART_PRG_MODE_INJECT:
1207
log_message(autostart_log, "Loading PRG file `%s' with direct RAM injection.", file_name);
1208
result = autostart_prg_with_ram_injection(file_name, finfo, autostart_log);
1209
mode = AUTOSTART_INJECT;
1210
boot_file_name = NULL;
1212
case AUTOSTART_PRG_MODE_DISK:
1213
log_message(autostart_log, "Loading PRG file `%s' with autostart disk image.", file_name);
1214
result = autostart_prg_with_disk_image(file_name, finfo, autostart_log, AutostartPrgDiskImage);
1215
mode = AUTOSTART_HASDISK;
1216
boot_file_name = "*";
1219
log_error(autostart_log, "Invalid PRG autostart mode: %d", AutostartPrgMode);
1224
/* Now either proceed with disk image booting or prg injection after reset */
1227
reboot_for_autostart(boot_file_name, mode, runmode);
1230
/* close prg file */
1231
fileio_close(finfo);
1236
/* ------------------------------------------------------------------------- */
1238
int autostart_autodetect_opt_prgname(const char *file_prog_name,
1239
unsigned int alt_prg_number,
1240
unsigned int runmode)
1245
/* Check for image:prg -format. */
1246
tmp = strrchr(file_prog_name, ':');
1248
char *autostart_prg_name;
1249
char *autostart_file;
1251
autostart_file = lib_stralloc(file_prog_name);
1252
autostart_prg_name = strrchr(autostart_file, ':');
1253
*autostart_prg_name++ = '\0';
1254
/* Does the image exist? */
1255
if (util_file_exists(autostart_file)) {
1258
charset_petconvstring((BYTE *)autostart_prg_name, 0);
1259
name = charset_replace_hexcodes(autostart_prg_name);
1260
result = autostart_autodetect(autostart_file, name, 0,
1264
result = autostart_autodetect(file_prog_name, NULL, alt_prg_number,
1267
lib_free(autostart_file);
1269
result = autostart_autodetect(file_prog_name, NULL, alt_prg_number,
1275
/* Autostart `file_name', trying to auto-detect its type. */
1276
int autostart_autodetect(const char *file_name, const char *program_name,
1277
unsigned int program_number, unsigned int runmode)
1279
if (network_connected() || event_record_active() || event_playback_active()
1280
|| file_name == NULL) {
1284
if (!autostart_enabled) {
1285
log_error(autostart_log,
1286
"Autostart is not available on this setup.");
1290
log_message(autostart_log, "Autodetecting image type of `%s'.", file_name);
1292
if (autostart_disk(file_name, program_name, program_number, runmode) == 0) {
1293
log_message(autostart_log, "`%s' recognized as disk image.", file_name);
1297
if (machine_class != VICE_MACHINE_C64DTV && machine_class != VICE_MACHINE_SCPU64) {
1298
if (autostart_tape(file_name, program_name, program_number, runmode) == 0) {
1299
log_message(autostart_log, "`%s' recognized as tape image.", file_name);
1304
if (autostart_snapshot(file_name, program_name) == 0) {
1305
log_message(autostart_log, "`%s' recognized as snapshot image.",
1309
if (autostart_prg(file_name, runmode) == 0) {
1310
log_message(autostart_log, "`%s' recognized as program/p00 file.",
1315
log_error(autostart_log, "`%s' is not a valid file.", file_name);
1319
/* Autostart the image attached to device `num'. */
1320
int autostart_device(int num)
1322
if (network_connected() || event_playback_active() || event_record_active()
1323
|| !autostart_enabled) {
1329
reboot_for_autostart(NULL, AUTOSTART_HASDISK, AUTOSTART_MODE_RUN);
1332
reboot_for_autostart(NULL, AUTOSTART_HASTAPE, AUTOSTART_MODE_RUN);
1338
int autostart_in_progress(void)
1340
return (autostartmode != AUTOSTART_NONE && autostartmode != AUTOSTART_DONE);
1343
/* Disable autostart on reset. */
1344
void autostart_reset(void)
1348
if (!autostart_enabled) {
1352
if (!autostart_ignore_reset
1353
&& autostartmode != AUTOSTART_NONE
1354
&& autostartmode != AUTOSTART_ERROR) {
1355
oldmode = autostartmode;
1356
autostartmode = AUTOSTART_NONE;
1357
if (oldmode != AUTOSTART_DONE) {
1358
disk_eof_callback();
1360
autostartmode = AUTOSTART_NONE;
1361
trigger_monitor = 0;
1362
deallocate_program_name();
1363
log_message(autostart_log, "Turned off.");
1365
autostart_ignore_reset = 0;
1368
void autostart_shutdown(void)
1370
deallocate_program_name();
1372
autostart_prg_shutdown();
1375
#ifdef ANDROID_COMPILE
1376
void loader_set_warpmode(int on)