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.