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

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

/*
 * reu.h - REU 1750 emulation.
 *
 * Written by
 *  Jouko Valta (jopi@stekt.oulu.fi)
 *  Richard Hable (K3027E7@edvz.uni-linz.ac.at)
 *
 * Fixes by
 *  Ettore Perazzoli (ettore@comm2000.it) [EP]
 *
 * 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 <string.h>
#ifndef NeXT
#include <malloc.h>
#endif

#include "reu.h"
#include "maincpu.h"
#include "mem.h"
#include "utils.h"

/* #define REU_DEBUG */

#define REUSIZE 512

/*
 * Status and Command Registers
 * bit	7	6	5	4	3	2	1	0
 * 00	Int	EOB	Fault	RamSize	________ Version ________
 * 01	Exec	0	Load	Delayed	0	0	   Mode
 */


/* global */

static int     ReuSize = REUSIZE << 10;
static BYTE    reu[16];        /* REC registers */
static BYTE   *reuram = 0;
static char   *reu_file_name;

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

int    reset_reu(int size)
{
    int i;

    if (size > 0)
	ReuSize = size;

    for (i=0; i < 16; i++)
	reu[i] = 0;

    if (ReuSize >= 256)
	reu[0] = 0x50;
    else
	reu[0] = 0x40;

    reu[1] = 0x4A;

    if (reuram == NULL) {
	reuram = xmalloc(ReuSize);
	printf("REU: %dKB unit installed.\n", REUSIZE);
	if (load_file(reu_file_name, reuram, ReuSize) == 0) {
	    printf ("REU: image `%s' loaded successfully.\n", reu_file_name);
	} else {
	    printf ("REU: (no image loaded).\n");
	}
    }

    return 0;
}

void activate_reu(void)
{
    if (reuram == NULL)
	reset_reu(0);
}

void close_reu(void)
{
    if (reuram == NULL || reu_file_name == NULL)
	return;

    if (save_file(reu_file_name, reuram, ReuSize) == 0)
	printf("REU: image `%s' saved successfully.\n", reu_file_name);
    else
	fprintf(stderr,"REU: cannot save image `%s'.\n", reu_file_name);
}


BYTE REGPARM1 read_reu(ADDRESS addr)
{
    BYTE retval;

    if (reuram == NULL)
	reset_reu(0);

    switch (addr) {
      case 0x0:
	/* fixed by [EP], 04-16-97. */
	retval = (reu[0] & 0x60) | (((ReuSize >> 10) >= 256) ? 0x10 : 0x00);
	reu[0] &= ~0xe0;	/* Bits 7-5 are cleared when register is
				   read. */
	break;

      case 0x6:
	/* wrong address of bank register corrected - RH */
	retval = reu[6] | 0xf8;
	break;

      case 0x9:
	retval = reu[6] | 0x3f;
	break;

      case 0xb:
      case 0xc:
      case 0xd:
      case 0xe:
      case 0xf:
	retval = 0xff;
	break;

      default:
	retval = reu[addr];
    }

#ifdef REU_DEBUG
    printf("REU: read [$%02X] => $%02X\n", addr, retval);
#endif
    return retval;
}


void REGPARM2 store_reu(ADDRESS addr, BYTE byte)
{
    if (reuram == NULL)
	reset_reu(0);

    reu[addr] = byte;

#ifdef REU_DEBUG
    printf("REU: store [$%02X] <= $%02X\n", addr, (int) byte);
#endif

    /* write REC command register
     * DMA only if execution bit (7) set  - RH */
    if ((addr == 0x1) && (byte & 0x80))
	reu_dma(byte & 0x10);
}

/* This function is called when write to REC command register or memory
 * location FF00 is detected.
 *
 * If host address exceeds ffff transfer contiues at 0000.
 * If reu address exceeds 7ffff transfer continues at 00000.
 * If address is fixed the same value is used during the whole transfer.
 */
/* Added correct handling of fixed addresses with transfer length 1  - RH */
/* Added fixed address support - [EP] */

void    reu_dma(int immed)
{
    static int delay = 0;
    unsigned int len;
    int reu_step, host_step;
    ADDRESS host_addr;
    int reu_addr;
    BYTE c;

    if (!immed) {
	delay++;
	return;
    }
    else {
	if (!delay && (immed < 0))
	    return;
	delay = 0;
    }

    /* wrong address of bank register & calculations corrected  - RH */
    host_addr = (ADDRESS)(reu[2]) | ( (ADDRESS)( reu[3] ) << 8 );
    reu_addr  = (int)(reu[4]) | ((int)(reu[5]) << 8) | ((int)(reu[6] & 7) << 16);
    if (( len = (int)(reu[7]) | ( (int)(reu[8]) << 8)) == 0)
	len = 0x10000;

    /* Fixed addresses implemented -- [EP] 04-16-97. */
    host_step = reu[0xA] & 0x80 ? 0 : 1;
    reu_step = reu[0xA] & 0x40 ? 0 : 1;

    /* clk += len; */

    switch (reu[1] & 0x03) {
      case 0: /* C64 -> REU */
#ifdef REU_DEBUG
	printf("REU: copy ext $%05X %s<= main $%04X%s, $%04X (%d) bytes.\n",
	       reu_addr, reu_step ? "" : "(fixed) ", host_addr,
	       host_step ? "" : " (fixed)", len, len);
#endif
	for (; len--; host_addr = (host_addr + host_step) & 0xffff, reu_addr += reu_step) {
	    BYTE value = mem_read(host_addr);
	    reuram[reu_addr % ReuSize] = value;
	}
	break;

      case 1: /* REU -> C64 */
#ifdef REU_DEBUG
	printf("REU: copy ext $%05X %s=> main $%04X%s, $%04X (%d) bytes.\n",
	       reu_addr, reu_step ? "" : "(fixed) ", host_addr,
	       host_step ? "" : " (fixed)", len, len);
#endif
	for (; len--; host_addr += host_step, reu_addr += reu_step )
	    mem_store((host_addr & 0xffff), reuram[reu_addr % ReuSize]);
	break;

      case 2: /* swap */
        /* for-loop corrected - RH */
	/* clk += len; */	/* [EP] 04-16-97. */
#ifdef REU_DEBUG
	printf("REU: swap ext $%05X %s<=> main $%04X%s, $%04X (%d) bytes.\n",
	       reu_addr, reu_step ? "" : "(fixed) ", host_addr,
	       host_step ? "" : " (fixed)", len, len);
#endif
	for (; len--; host_addr += host_step, reu_addr += reu_step ) {
	    c = reuram[reu_addr % ReuSize];
	    reuram[reu_addr % ReuSize] = mem_read(host_addr & 0xffff);
	    mem_store((host_addr & 0xffff), c);
	}
	break;

      case 3: /* compare */
#ifdef REU_DEBUG
	printf("REU: compare ext $%05X %s<=> main $%04X%s, $%04X (%d) bytes.\n",
	       reu_addr, reu_step ? "" : "(fixed) ", host_addr,
	       host_step ? "" : " (fixed)", len, len);
#endif
	while (len--) {
	    if (reuram[reu_addr % ReuSize] != mem_read(host_addr & 0xffff)) {
		reu[0] |= 0x20; /* FAULT */
		break;
	    }
	    host_addr += host_step; reu_addr += reu_step;
	}
	break;
    }

    if (!(reu[1] & 0x20)) {
	/* not autoload
         * incr. of addr. disabled, as already pointing to correct addr.
	 * address changes only if not fixed, correct reu base registers  -RH
	 */
#ifdef REU_DEBUG
	printf("No autoload\n");
#endif
        if ( !(reu[0xA] & 0x80)) {
	    reu[2] = host_addr & 0xff;
	    reu[3] = (host_addr >> 8) & 0xff;
	}
        if ( !(reu[0xA] & 0x40)) {
	    reu[4] = reu_addr & 0xff;
	    reu[5] = (reu_addr >> 8) & 0xff;
	    reu[6] = (reu_addr>>16);
	}

	reu[7] = 1;
	reu[8] = 0;
    }

    /* [EP] 04-16-97. */
    reu[0] |= 0x40;
    reu[1] &= 0x7f;
}

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