This is autostart.c in view mode; [Download] [Up]
/* * autostart.c - automatic image loading and starting * * Written by * Teemu Rantanen (tvr@cs.hut.fi) * Ettore Perazzoli (ettore@comm2000.it) * * Patches by * André Fachat (a.fachat@physik.tu-chemnitz.de) * * This file is part of VICE, the Versatile Commodore Emulator. * See README for copyright notice. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA * 02111-1307 USA. * */ #include "vice.h" #include <stdio.h> #include <stdlib.h> #include "autostart.h" #include "attach.h" #include "drive.h" #include "interrupt.h" #include "kbdbuf.h" #include "mem.h" #include "resources.h" #include "serial.h" #include "tape.h" #include "ui.h" #include "utils.h" #include "vmachine.h" #include "warn.h" /* Kernal addresses. Set by `autostart_init()'. */ static int blnsw; /* Cursor Blink enable: 0 = Flash Cursor */ static int pnt; /* Pointer: Current Screen Line Address */ static int pntr; /* Cursor Column on Current Line */ static int lnmx; /* Physical Screen Line Length */ /* Current state of the autostart routine. */ static enum { AUTOSTART_NONE, AUTOSTART_ERROR, AUTOSTART_HASTAPE, AUTOSTART_LOADINGTAPE, AUTOSTART_HASDISK, AUTOSTART_LOADINGDISK, AUTOSTART_DONE } autostartmode = AUTOSTART_NONE; /* Warnings. */ static warn_t *pwarn = NULL; /* Flag: was true 1541 emulation turned on when we started booting the disk image? */ static int orig_true1541_state = 0; /* Program name to load. NULL if default */ static char *autostart_program_name = NULL; /* Minimum number of cycles before we feed BASIC with commands. */ static CLOCK min_cycles; /* Flag: Do we want to switch true 1541 emulation on/off during autostart? */ static int handle_true1541; /* Flag: autostart is initialized. */ static int autostart_enabled = 0; /* ------------------------------------------------------------------------- */ /* Deallocate program name if we have one */ static void deallocate_program_name(void) { if (autostart_program_name) { free(autostart_program_name); autostart_program_name = NULL; } } static enum { YES, NO, NOT_YET } check(const char *s) { int screen_addr = mem_read(pnt) | (mem_read(pnt + 1) << 8); int line_length = lnmx < 0 ? -lnmx : mem_read(lnmx) + 1; int cursor_column = mem_read(pntr); int addr, i; if (!kbd_buf_is_empty() || cursor_column != 0 || mem_read(blnsw) != 0) return NOT_YET; addr = screen_addr - line_length; for (i = 0; s[i] != '\0'; i++) { if (mem_read((ADDRESS) (addr + i)) != s[i] % 64) { if (mem_read((ADDRESS) (addr + i)) != (BYTE) 32) return NO; return NOT_YET; } } return YES; } static void set_true1541_mode(int on) { resources_set_value("True1541", (resource_value_t) on); ui_update_menus(); } static int get_true1541_state(void) { int value; if (resources_get_value("True1541", (resource_value_t *) & value) < 0) return 0; return value; } /* ------------------------------------------------------------------------- */ /* Initialize autostart. */ int autostart_init(CLOCK _min_cycles, int _handle_true1541, int _blnsw, int _pnt, int _pntr, int _lnmx) { blnsw = _blnsw; pnt = _pnt; pntr = _pntr; lnmx = _lnmx; if (!pwarn) { pwarn = warn_init("AUTOSTART", 32); if (!pwarn) return -1; } min_cycles = _min_cycles; handle_true1541 = _handle_true1541; if (_min_cycles) autostart_enabled = 1; else autostart_enabled = 0; return 0; } void autostart_disable(void) { if (!autostart_enabled) return; autostartmode = AUTOSTART_ERROR; deallocate_program_name(); warn(pwarn, -1, "disabling autostart"); } /* ------------------------------------------------------------------------- */ /* This function is called by the `serialreceivebyte()' trap as soon as EOF is reached. */ static void disk_eof_callback(void) { if (handle_true1541) { if (orig_true1541_state) warn(pwarn, -1, "switching true 1541 on"); set_true1541_mode(orig_true1541_state); } warn(pwarn, -1, "starting program"); autostartmode = AUTOSTART_DONE; serial_set_eof_callback(NULL); } /* This function is called by the `serialattention()' trap before returning. */ static void disk_attention_callback(void) { kbd_buf_feed("run\r"); serial_set_attention_callback(NULL); /* Next step is waiting for end of loading, to turn true 1541 emulation on. */ serial_set_eof_callback(disk_eof_callback); } /* Execute the actions for the current `autostartmode', advancing to the next mode if necessary. */ void autostart_advance(void) { char *tmp; if (clk < min_cycles || !autostart_enabled) return; switch (autostartmode) { case AUTOSTART_HASTAPE: switch (check("READY.")) { case YES: warn(pwarn, -1, "loading tape"); if (autostart_program_name) { tmp = concat("load\"", autostart_program_name, "\"\r", NULL); kbd_buf_feed(tmp); free(tmp); } else kbd_buf_feed("load\r"); autostartmode = AUTOSTART_LOADINGTAPE; deallocate_program_name(); break; case NO: autostart_disable(); break; case NOT_YET: break; } break; case AUTOSTART_LOADINGTAPE: switch (check("READY.")) { case YES: warn(pwarn, -1, "starting program"); kbd_buf_feed("run\r"); autostartmode = AUTOSTART_DONE; break; case NO: autostart_disable(); break; case NOT_YET: break; } break; case AUTOSTART_HASDISK: switch (check("READY.")) { case YES: { int no_traps; warn(pwarn, -1, "loading disk"); orig_true1541_state = get_true1541_state(); if (handle_true1541) { resources_get_value("NoTraps", (resource_value_t *) & no_traps); if (!no_traps) { if (orig_true1541_state) warn(pwarn, -1, "switching true 1541 emulation off"); set_true1541_mode(0); } else { if (!orig_true1541_state) warn(pwarn, -1, "switching true 1541 emulation on"); set_true1541_mode(1); } } else no_traps = 0; if (autostart_program_name) { tmp = alloca(strlen(autostart_program_name) + 20); sprintf(tmp, "load\"%s\",8,1\r", autostart_program_name); kbd_buf_feed(tmp); } else kbd_buf_feed("load\"*\",8,1\r"); if (no_traps) { kbd_buf_feed("run\r"); autostartmode = AUTOSTART_DONE; } else { autostartmode = AUTOSTART_LOADINGDISK; deallocate_program_name(); serial_set_attention_callback(disk_attention_callback); } break; } case NO: autostart_disable(); break; case NOT_YET: break; } break; default: return; } if (autostartmode == AUTOSTART_ERROR && handle_true1541) { warn(pwarn, -1, "now turning true 1541 emulation %s", orig_true1541_state ? "on" : "off"); set_true1541_mode(orig_true1541_state); } } static int autostart_ignore_reset = 0; /* Clean memory and reboot for autostart. */ static void reboot_for_autostart(const char *program_name) { if (!autostart_enabled) return; warn(pwarn, -1, "rebooting..."); mem_powerup(); autostart_ignore_reset = 1; maincpu_trigger_reset(); deallocate_program_name(); if (program_name) autostart_program_name = stralloc(program_name); } /* ------------------------------------------------------------------------- */ /* Autostart tape image `file_name'. */ int autostart_tape(const char *file_name, const char *program_name) { if (file_name == NULL || !autostart_enabled) return -1; if (serial_select_file(DT_TAPE, 1, file_name) < 0) { warn(pwarn, -1, "cannot attach file '%s' (as a tape)", file_name); autostartmode = AUTOSTART_ERROR; deallocate_program_name(); return -1; } warn(pwarn, -1, "attached file `%s' as a tape image", file_name); autostartmode = AUTOSTART_HASTAPE; reboot_for_autostart(program_name); return 0; } /* Autostart disk image `file_name'. */ int autostart_disk(const char *file_name, const char *program_name) { if (file_name == NULL || !autostart_enabled) return -1; if (file_system_attach_disk(8, file_name) < 0) { warn(pwarn, -1, "cannot attach file `%s' as a disk image", file_name); file_system_detach_disk(8); autostartmode = AUTOSTART_ERROR; deallocate_program_name(); return -1; } warn(pwarn, -1, "attached file `%s' as a disk image to device #8", file_name); autostartmode = AUTOSTART_HASDISK; reboot_for_autostart(program_name); return 0; } /* Autostart `file_name', trying to auto-detect its type. */ int autostart_autodetect(const char *file_name, const char *program_name) { if (file_name == NULL) return -1; if (!autostart_enabled) { fprintf(stderr, "Couldn't autostart - unknown kernal!"); return -1; } if (autostart_disk(file_name, program_name) == 0) warn(pwarn, -1, "`%s' detected as a disk image", file_name); else if (autostart_tape(file_name, program_name) == 0) warn(pwarn, -1, "`%s' detected as a tape image", file_name); else { warn(pwarn, -1, "type of file `%s' unrecognized", file_name); return -1; } return 0; } /* Autostart the image attached to device `num'. */ int autostart_device(int num) { if (!autostart_enabled) return -1; switch (num) { case 8: autostartmode = AUTOSTART_HASDISK; break; case 1: autostartmode = AUTOSTART_HASTAPE; break; default: return -1; } reboot_for_autostart(NULL); return 0; } /* Disable autostart on reset. */ void autostart_reset(void) { if (!autostart_enabled) return; if (!autostart_ignore_reset && autostartmode != AUTOSTART_NONE && autostartmode != AUTOSTART_ERROR) { warn(pwarn, -1, "disabling autostart"); autostartmode = AUTOSTART_NONE; deallocate_program_name(); } autostart_ignore_reset = 0; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.