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

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

/*
 * cartridge.c - Cartridge emulation.
 *
 * Written by
 *  Andreas Boose (boose@unixserv.rz.fh-hannover.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 "resources.h"
#include "file.h"
#include "mem.h"
#include "vmachine.h"
#include "interrupt.h"
#include "utils.h"
#include "cartridge.h"

static int cartridge_type;
static char *cartridge_file;

static int carttype = CARTRIDGE_NONE;
static int crttype = 0;
static char *cartfile;

static int set_cartridge_type(resource_value_t v)
{
    cartridge_type = (int) v;
    carttype = cartridge_type;

    return cartridge_attach_image(carttype, cartfile);
}

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

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

    string_set(&cartridge_file, name);
    string_set(&cartfile, name);
    return cartridge_attach_image(carttype, cartfile);
}

static resource_t resources[] = {
    { "CartridgeType", RES_INTEGER, (resource_value_t) CARTRIDGE_NONE,
      (resource_value_t *) &cartridge_type, set_cartridge_type },
    { "CartridgeFile", RES_STRING, (resource_value_t) "",
      (resource_value_t *) &cartridge_file, set_cartridge_file },
    { NULL }
};

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

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

int cartridge_attach_image(int type, const char *filename)
{
    BYTE rawcart[0x10000];
    FILE *fd;
    BYTE header[0x40], chipheader[0x10];
    int i;

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

    /* Do not detach cartridge when attaching the same cart type again.  */
    if (type != carttype)
	cartridge_detach_image();

    switch(type) {
      case CARTRIDGE_GENERIC_8KB:
	fd = fopen(filename, READ);
	if (!fd)
	    return -1;
	if (fread(rawcart, 0x2000, 1, fd) < 1) {
	    fclose(fd);
	    return -1;
	}
	fclose(fd);
	break;
      case CARTRIDGE_GENERIC_16KB:
	fd = fopen(filename, READ);
	if (!fd)
	    return -1;
	if (fread(rawcart, 0x4000, 1, fd) < 1) {
	    fclose(fd);
	    return -1;
	}
	fclose(fd);
	break;
      case CARTRIDGE_ACTION_REPLAY:
	fd = fopen(filename, READ);
	if (!fd)
	    return -1;
	if (fread(rawcart, 0x8000, 1, fd) < 1) {
	    fclose(fd);
	    return -1;
	}
	fclose(fd);
	break;
      case CARTRIDGE_CRT:
	fd = fopen(filename, READ);
	if (!fd)
	    return -1;
	if (fread(header, 0x40, 1, fd) < 1) {
	    fclose(fd);
	    return -1;
	}
	if (strncmp(header, "C64 CARTRIDGE   ", 16)) {
	    fclose(fd);
	    return -1;
	}
	crttype = header[0x17] + header[0x16] * 256;
	switch (crttype) {
	  case 0:
	    if (fread(chipheader, 0x10, 1, fd) < 1) {
		fclose(fd);
		return -1;
	    }
	    if (chipheader[0xc] == 0x80) {
		if (fread(rawcart, 0x2000, 1, fd) < 1) {
		    fclose(fd);
		    return -1;
		}
	    }
	    fclose(fd);
	    crttype = CARTRIDGE_GENERIC_8KB;
	    break;
	  case 1:
	    for (i = 0; i <= 3; i++) {
		if (fread(chipheader, 0x10, 1, fd) < 1) {
		    fclose(fd);
		    return -1;
		}
		if (chipheader[0xb] > 3) {
		    fclose(fd);
		    return -1;
		}
		if (fread(&rawcart[chipheader[0xb] << 13], 0x2000, 1, fd) < 1) {
		    fclose(fd);
		    return -1;
		}
	    }
	    fclose(fd);
	    break;
	  case 2:
	  case 4:
	    for (i = 0; i <= 1; i++) {
		if (fread(chipheader, 0x10, 1, fd) < 1) {
		    fclose(fd);
		    return -1;
		}
		if (chipheader[0xc] != 0x80 && chipheader[0xc] != 0xa0) {
		    fclose(fd);
		    return -1;
		}
		if (fread(&rawcart[(chipheader[0xc] << 8) - 0x8000], 0x2000,
		          1, fd) < 1) {
		    fclose(fd);
		    return -1;
		}
	    }
	    fclose(fd);
	    break;
	  default:
	    fclose(fd);
	    return -1;
	}
	break;
      default:
	return -1;
    }

    carttype = type;
    string_set(&cartfile, filename);
    mem_attach_cartridge((type == CARTRIDGE_CRT) ? crttype : type, rawcart);
    return 0;
}

void cartridge_detach_image(void)
{
    if (carttype != CARTRIDGE_NONE) {
	mem_detach_cartridge((carttype == CARTRIDGE_CRT) ? crttype : carttype);
	carttype = CARTRIDGE_NONE;
	crttype = CARTRIDGE_NONE;
        if (cartfile != NULL)
            free(cartfile), cartfile = NULL;
    }
}

void cartridge_set_default(void)
{
    set_cartridge_type((resource_value_t) carttype);
    set_cartridge_file((resource_value_t) (carttype == CARTRIDGE_NONE) ?
                       "" : cartfile);
}

void cartridge_trigger_freeze(void)
{
    if (crttype != CARTRIDGE_ACTION_REPLAY
        && carttype != CARTRIDGE_ACTION_REPLAY
        && crttype != CARTRIDGE_KCS_POWER)
	return;
    mem_freeze_cartridge((carttype == CARTRIDGE_CRT) ? crttype : carttype);
    maincpu_set_nmi(I_FREEZE, IK_NMI);
}

void cartridge_release_freeze(void)
{
    maincpu_set_nmi(I_FREEZE, 0);
}

const char *cartridge_get_file_name(ADDRESS addr_ignored)
{
    return cartfile;
}

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