ftp.nice.ch/pub/next/tools/emulators/vice.0.15.0.NeXT.sd.tgz#/vice-0.15.0/src/vic20/cartridge.c

This is cartridge.c in view mode; [Download] [Up]

/*
 * cartridge.c - Cartridge emulation.
 *
 * Written by
 *  André Fachat (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 <ctype.h>
#include <string.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <memory.h>
#include <assert.h>
#include <errno.h>

#include "cartridge.h"
#include "cmdline.h"
#include "file.h"
#include "interrupt.h"
#include "mem.h"
#include "resources.h"
#include "utils.h"
#include "vmachine.h"
#include "zfile.h"

/* Hm, if this gets more, I should introduce an array :-) */
static char *cartridge_file_2;
static char *cartridge_file_6;
static char *cartridge_file_A;
static char *cartridge_file_B;

static char *cartfile2;
static char *cartfile6;
static char *cartfileA;
static char *cartfileB;

static int set_cartridge_file_2(resource_value_t v)
{
    const char *name = (const char *) v;

    if (cartridge_file_2 != NULL && name != NULL
	&& strcmp(name, cartridge_file_2) == 0)
	return 0;

    string_set(&cartridge_file_2, name);
    string_set(&cartfile2, name);
    return cartridge_attach_image(CARTRIDGE_VIC20_8KB_2000, cartfile2);
}

static int set_cartridge_file_6(resource_value_t v)
{
    const char *name = (const char *) v;

    if (cartridge_file_6 != NULL && name != NULL
	&& strcmp(name, cartridge_file_6) == 0)
	return 0;

    string_set(&cartridge_file_6, name);
    string_set(&cartfile6, name);
    return cartridge_attach_image(CARTRIDGE_VIC20_8KB_6000, cartfile6);
}

static int set_cartridge_file_A(resource_value_t v)
{
    const char *name = (const char *) v;

    if (cartridge_file_A != NULL && name != NULL
	&& strcmp(name, cartridge_file_A) == 0)
	return 0;

    string_set(&cartridge_file_A, name);
    string_set(&cartfileA, name);
    return cartridge_attach_image(CARTRIDGE_VIC20_8KB_A000, cartfileA);
}

static int set_cartridge_file_B(resource_value_t v)
{
    const char *name = (const char *) v;

    if (cartridge_file_B != NULL && name != NULL
	&& strcmp(name, cartridge_file_B) == 0)
	return 0;

    string_set(&cartridge_file_B, name);
    string_set(&cartfileB, name);
    return cartridge_attach_image(CARTRIDGE_VIC20_4KB_B000, cartfileB);
}

static resource_t resources[] =
{
    {"CartridgeFile2000", RES_STRING, (resource_value_t) "",
     (resource_value_t *) & cartridge_file_2, set_cartridge_file_2},
    {"CartridgeFile6000", RES_STRING, (resource_value_t) "",
     (resource_value_t *) & cartridge_file_6, set_cartridge_file_6},
    {"CartridgeFileA000", RES_STRING, (resource_value_t) "",
     (resource_value_t *) & cartridge_file_A, set_cartridge_file_A},
    {"CartridgeFileB000", RES_STRING, (resource_value_t) "",
     (resource_value_t *) & cartridge_file_B, set_cartridge_file_B},
    {NULL}
};

int cartridge_init_resources(void)
{
    return resources_register(resources);
}

static int attach_cartB(const char *param, void *extra_param)
{
    return cartridge_attach_image(CARTRIDGE_VIC20_4KB_B000, param);
}

static int attach_cartA(const char *param, void *extra_param)
{
    return cartridge_attach_image(CARTRIDGE_VIC20_8KB_A000, param);
}

static int attach_cart6(const char *param, void *extra_param)
{
    return cartridge_attach_image(CARTRIDGE_VIC20_8KB_6000, param);
}

static int attach_cart2(const char *param, void *extra_param)
{
    return cartridge_attach_image(CARTRIDGE_VIC20_8KB_2000, param);
}

static cmdline_option_t cmdline_options[] =
{
    {"-cart2", CALL_FUNCTION, 1, attach_cart2, NULL, NULL, NULL,
     "<name>", "Specify 4/8K extension ROM name at $2000"},
    {"-cart6", CALL_FUNCTION, 1, attach_cart6, NULL, NULL, NULL,
     "<name>", "Specify 4/8K extension ROM name at $6000"},
    {"-cartA", CALL_FUNCTION, 1, attach_cartA, NULL, NULL, NULL,
     "<name>", "Specify 4/8K extension ROM name at $A000"},
    {"-cartB", CALL_FUNCTION, 1, attach_cartB, NULL, NULL, NULL,
     "<name>", "Specify 4K extension ROM name at $B000"},
    {NULL}
};

int cartridge_init_cmdline_options(void)
{
    return cmdline_register_options(cmdline_options);
}

/* ------------------------------------------------------------------------- */

int cartridge_attach_image(int type, const char *filename)
{
    BYTE rawcart[0x4000];
    FILE *fd;
    int addr;
    size_t n;

    /* Attaching no cartridge always works.  */
    if (type == CARTRIDGE_NONE || *filename == '\0')
	return 0;

    printf("Cartridge: Attach type %d, file=%s\n", type, filename);

    fd = zfopen(filename, READ);
    if (!fd)
	return -1;

    addr = fgetc(fd);
    addr = (addr & 0xff) | ((fgetc(fd) << 8) & 0xff00);

    if (type == CARTRIDGE_VIC20_DETECT) {
	if (addr == 0x6000) {
	    type = CARTRIDGE_VIC20_8KB_6000;
	} else if (addr == 0xA000) {
	    type = CARTRIDGE_VIC20_8KB_A000;
	} else if (addr == 0x2000) {
	    type = CARTRIDGE_VIC20_8KB_2000;
	} else if (addr == 0xB000) {
	    type = CARTRIDGE_VIC20_4KB_B000;
	}
    }
    memset(rawcart, 0xff, 0x4000);

    switch (type) {
      case CARTRIDGE_VIC20_8KB_2000:
	  if ((n = fread(rawcart, 0x1000, 2, fd)) < 1) {
	      zfclose(fd);
	      return -1;
	  }
	  if (n < 2) {
	      /* type = CARTRIDGE_VIC20_4KB_2000; */
	      memcpy(rawcart + 0x1000, rawcart, 0x1000);
	  }
	  string_set(&cartfile2, filename);
	  break;
      case CARTRIDGE_VIC20_8KB_6000:
	  if ((n = fread(rawcart, 0x1000, 2, fd)) < 1) {
	      zfclose(fd);
	      return -1;
	  }
	  if (n < 2) {
	      /* type = CARTRIDGE_VIC20_4KB_6000; */
	      memcpy(rawcart + 0x1000, rawcart, 0x1000);
	  }
	  string_set(&cartfile6, filename);
	  break;
      case CARTRIDGE_VIC20_8KB_A000:
	  if ((n = fread(rawcart, 0x1000, 2, fd)) < 1) {
	      zfclose(fd);
	      return -1;
	  }
	  if (n < 2) {
	      if (cartfileB) {
		  type = CARTRIDGE_VIC20_4KB_A000;
	      } else {
		  memcpy(rawcart + 0x1000, rawcart, 0x1000);
	      }
	  }
	  string_set(&cartfileA, filename);
	  break;
      case CARTRIDGE_VIC20_4KB_B000:
	  if ((n = fread(rawcart, 0x1000, 1, fd)) < 1) {
	      zfclose(fd);
	      return -1;
	  }
	  string_set(&cartfileB, filename);
	  break;
      default:
	  zfclose(fd);
	  return -1;
    }

    zfclose(fd);

    mem_attach_cartridge(type, rawcart);

    return 0;
}

void cartridge_detach_image(void)
{
    mem_detach_cartridge(CARTRIDGE_VIC20_8KB_2000);
    mem_detach_cartridge(CARTRIDGE_VIC20_8KB_6000);
    mem_detach_cartridge(CARTRIDGE_VIC20_8KB_A000);
    string_set(&cartfile2, NULL);
    string_set(&cartfile6, NULL);
    string_set(&cartfileA, NULL);
    string_set(&cartfileB, NULL);
}

void cartridge_set_default(void)
{
    set_cartridge_file_2((resource_value_t) cartfile2);
    set_cartridge_file_6((resource_value_t) cartfile6);
    set_cartridge_file_A((resource_value_t) cartfileA);
    set_cartridge_file_B((resource_value_t) cartfileB);
}

const char *cartridge_get_file_name(ADDRESS addr)
{
    switch (addr) {
      case 0x2000:
	  return cartfile2;
      case 0x6000:
	  return cartfile6;
      case 0xa000:
	  return cartfileA;
      case 0xb000:
	  return cartfileB;
      default:
	  return NULL;
    }
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.