droid48-gwh/jni/memory.c
2010-09-18 01:13:52 +02:00

1535 lines
47 KiB
C

/*
* This file is part of x48, an emulator of the HP-48sx Calculator.
* Copyright (C) 1994 Eddie C. Dost (ecd@dressler.de)
*
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
/* $Log: memory.c,v $
* Revision 1.15 1995/01/11 18:20:01 ecd
* major update to support HP48 G/GX
*
* Revision 1.14 1994/12/08 22:14:50 ecd
* corrected setting of display.lines
*
* Revision 1.13 1994/12/07 20:20:50 ecd
* minor fixes
*
* Revision 1.12 1994/11/28 02:00:51 ecd
* corrected setting of display.contrast
*
* Revision 1.11 1994/11/02 15:07:54 ecd
* deleted trailing NULL characters
*
* Revision 1.10 1994/11/02 14:44:28 ecd
* minor changes
*
* Revision 1.9 1994/10/09 20:32:02 ecd
* added support for bit offset, changed handling of display_t
* variables.
*
* Revision 1.8 1994/10/06 16:30:05 ecd
* changed char to unsigned
*
* Revision 1.7 1994/10/05 08:36:44 ecd
* removed display addr queue
*
* Revision 1.6 1994/10/01 10:12:53 ecd
* added schedule_event = 0 for any display touch
*
* Revision 1.5 1994/09/30 12:37:09 ecd
* support for faster display and scheduler
*
* Revision 1.4 1994/09/18 15:29:22 ecd
* turned off unused rcsid message
*
* Revision 1.3 1994/09/13 16:57:00 ecd
* changed to plain X11
*
* Revision 1.2 1994/08/31 18:23:21 ecd
* changed memory access routines.
*
* Revision 1.1 1994/08/26 11:09:02 ecd
* Initial revision
*
* $Id: memory.c,v 1.15 1995/01/11 18:20:01 ecd Exp ecd $
*/
#include "global.h"
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <unistd.h>
#include <string.h>
#ifdef SUNOS
#include <memory.h>
#endif
#include "hp48.h"
#include "device.h"
#include "hp48_emu.h"
#include "romio.h"
#include "resources.h"
#include "mmu.h"
extern int device_check;
extern short port1_is_ram;
extern long port1_mask;
extern short port2_is_ram;
extern long port2_mask;
#define DEBUG_UNKNOWN 1
/* #define DEBUG_SERIAL 1 */
/* #define DEBUG_SERIALb 1 */
/* #define DEBUG_DISPLAY 1 */
/* #define DEBUG_IR 1 */
/* #define DEBUG_CONTRAST 1 */
/* #define DEBUG_CARDS 1 */
/* #define DEBUG_BAD_MEM 1 */
/* #define DEBUG_BASE_NIBBLE 1 */
/* #define DEBUG_BANK_SWITCH 1 */
long nibble_masks[16] = {
0x0000000f,
0x000000f0,
0x00000f00,
0x0000f000,
0x000f0000,
0x00f00000,
0x0f000000,
0xf0000000,
0x0000000f,
0x000000f0,
0x00000f00,
0x0000f000,
0x000f0000,
0x00f00000,
0x0f000000,
0xf0000000
};
void (*write_nibble) __ProtoType__((long addr, int val));
int (*read_nibble) __ProtoType__((long addr));
int (*read_nibble_crc) __ProtoType__((long addr));
static int line_counter = -1;
static inline int
#ifdef __FunctionProto__
calc_crc(int nib)
#else
calc_crc(nib)
int nib;
#endif
{
saturn.crc = (saturn.crc >> 4) ^ (((saturn.crc ^ nib) & 0xf) * 0x1081);
return nib;
}
void
#ifdef __FunctionProto__
write_dev_mem(long addr, int val)
#else
write_dev_mem(addr, val)
long addr;
int val;
#endif
{
static int old_line_offset = -1;
device_check = 1;
schedule_event = 0;
switch ((int)addr) {
case 0x100: /* DISPIO */
if (val != saturn.disp_io) {
saturn.disp_io = val;
display.on = (val & 0x8) >> 3;
display.offset = val & 0x7;
disp.offset = 2 * display.offset;
if (display.offset > 3)
display.nibs_per_line =
(NIBBLES_PER_ROW+saturn.line_offset+2) & 0xfff;
else
display.nibs_per_line =
(NIBBLES_PER_ROW+saturn.line_offset) & 0xfff;
display.disp_end = display.disp_start +
(display.nibs_per_line * (display.lines + 1));
device.display_touched = DISP_INSTR_OFF;
}
#ifdef DEBUG_DISPLAY
LOGE( "%.5lx: DISP ON: %x\n", saturn.PC, display.on);
#endif
return;
case 0x101: /* CONTRAST CONTROL */
saturn.contrast_ctrl = val;
display.contrast &= ~0x0f;
display.contrast |= val;
#ifdef DEBUG_CONTRAST
LOGE( "%.5lx: Contrast: 0x%x\n", saturn.PC, display.contrast);
#endif
device.contrast_touched = 1;
return;
case 0x102: /* DISPLAY TEST */
display.contrast &= ~0xf0;
display.contrast |= ((val & 0x1) << 4);
#ifdef DEBUG_CONTRAST
LOGE( "%.5lx: Contrast: 0x%x\n", saturn.PC, display.contrast);
#endif
device.contrast_touched = 1;
/* Fall through */
case 0x103: /* DISPLAY TEST */
saturn.disp_test &= ~nibble_masks[addr - 0x102];
saturn.disp_test |= val << ((addr - 0x102) * 4);
#ifdef DEBUG_DISPLAY
LOGE( "%.5lx: DISP TEST: %x\n", saturn.PC, saturn.disp_test);
#endif
device.disp_test_touched = 1;
return;
case 0x104: case 0x105: case 0x106: case 0x107: /* CRC */
saturn.crc &= ~nibble_masks[addr - 0x104];
saturn.crc |= val << ((addr - 0x104) * 4);
return;
case 0x108: /* POWER STATUS */
saturn.power_status = val;
device.power_status_touched = 1;
return;
case 0x109: /* POWER CONTROL */
saturn.power_ctrl = val;
device.power_ctrl_touched = 1;
return;
case 0x10a: /* MODE */
saturn.mode = val;
device.mode_touched = 1;
return;
case 0x10b: case 0x10c: /* ANNUNC */
saturn.annunc &= ~nibble_masks[addr - 0x10b];
saturn.annunc |= val << ((addr - 0x10b) * 4);
display.annunc = saturn.annunc;
device.ann_touched = 1;
return;
case 0x10d: /* BAUD */
saturn.baud = val;
device.baud_touched = 1;
#ifdef DEBUG_SERIALb
LOGE( "%.5lx: BAUD write: %x\n", saturn.PC, saturn.baud);
#endif
return;
case 0x10e: /* CARD CONTROL */
saturn.card_ctrl = val;
if (saturn.card_ctrl & 0x02)
saturn.MP = 1;
if (saturn.card_ctrl & 0x01)
do_interupt();
device.card_ctrl_touched = 1;
#ifdef DEBUG_CARDS
LOGE( "%.5lx: CardControl write: %x\n",
saturn.PC, saturn.card_ctrl);
#endif
return;
case 0x10f: /* CARD STATUS */
#ifdef DEBUG_CARDS
LOGE( "%.5lx: CardStatus write: %x\n",
saturn.PC, saturn.card_status);
#endif
return;
case 0x110: /* IO CONTROL */
saturn.io_ctrl = val;
device.ioc_touched = 1;
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: IOC write: %x\n", saturn.PC, saturn.io_ctrl);
#endif
return;
case 0x111: /* RCS */
saturn.rcs = val;
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: RCS: %x\n", saturn.PC, saturn.rcs);
#endif
return;
case 0x112: /* TCS */
saturn.tcs = val;
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: TCS: %x\n", saturn.PC, saturn.tcs);
#endif
return;
case 0x113: /* CRER */
saturn.rcs &= 0x0b;
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: CRER, RCS: %x\n", saturn.PC, saturn.rcs);
#endif
return;
case 0x114: case 0x115: /* RBR */
return;
case 0x116: case 0x117: /* TBR */
saturn.tbr &= ~nibble_masks[addr - 0x116];
saturn.tbr |= val << ((addr - 0x116) * 4);
saturn.tcs |= 0x01;
device.tbr_touched = 1;
return;
case 0x118: case 0x119: /* SERVICE REQ */
saturn.sreq &= ~nibble_masks[addr - 0x118];
saturn.sreq |= val << ((addr - 0x118) * 4);
device.sreq_touched = 1;
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: SREQ? write: %x\n", saturn.PC, saturn.sreq);
#endif
return;
case 0x11a: /* IR CONTROL */
saturn.ir_ctrl = val;
device.ir_ctrl_touched = 1;
#ifdef DEBUG_IR
LOGE( "%.5lx: IRC write: %x\n", saturn.PC, saturn.ir_ctrl);
#endif
return;
case 0x11b: /* BASE NIB OFFSET */
saturn.base_off = val;
device.base_off_touched = 1;
return;
case 0x11c: /* LED CONTROL */
saturn.lcr = val;
device.lcr_touched = 1;
#ifdef DEBUG_IR
LOGE( "%.5lx: LCR write: %x\n", saturn.PC, saturn.lcr);
#endif
return;
case 0x11d: /* LED BUFFER */
saturn.lbr = val;
device.lbr_touched = 1;
#ifdef DEBUG_IR
LOGE( "%.5lx: LBR write: %x\n", saturn.PC, saturn.lbr);
#endif
return;
case 0x11e: /* SCRATCH PAD */
saturn.scratch = val;
device.scratch_touched = 1;
return;
case 0x11f: /* BASENIBBLE */
saturn.base_nibble = val;
device.base_nibble_touched = 1;
#ifdef DEBUG_BASE_NIBBLE
if (opt_gx)
LOGE( "%.5lx: BASENIB: %x\n", saturn.PC, saturn.base_nibble);
#endif
return;
case 0x120: case 0x121: case 0x122: case 0x123: /* DISP_ADDR */
case 0x124:
saturn.disp_addr &= ~nibble_masks[addr - 0x120];
saturn.disp_addr |= val << ((addr - 0x120) * 4);
if (display.disp_start != (saturn.disp_addr & 0xffffe)) {
display.disp_start = saturn.disp_addr & 0xffffe;
display.disp_end = display.disp_start +
(display.nibs_per_line * (display.lines + 1));
device.display_touched = DISP_INSTR_OFF;
}
#ifdef DEBUG_DISPLAY
LOGE( "%.5lx: DISPLAY: %lx\n", saturn.PC, display.disp_start);
LOGE( "%.5lx: DISP END: %lx\n", saturn.PC, display.disp_end);
#endif
return;
case 0x125: case 0x126: case 0x127: /* LINE_OFFSET */
saturn.line_offset &= ~nibble_masks[addr - 0x125];
saturn.line_offset |= val << ((addr - 0x125) * 4);
if (saturn.line_offset != old_line_offset) {
old_line_offset = saturn.line_offset;
if (display.offset > 3)
display.nibs_per_line =
(NIBBLES_PER_ROW+saturn.line_offset+2) & 0xfff;
else
display.nibs_per_line =
(NIBBLES_PER_ROW+saturn.line_offset) & 0xfff;
display.disp_end = display.disp_start +
(display.nibs_per_line * (display.lines + 1));
device.display_touched = DISP_INSTR_OFF;
}
#ifdef DEBUG_DISPLAY
LOGE( "%.5lx: DISP LINE SIZE: %x\n",
saturn.PC, display.nibs_per_line);
LOGE( "%.5lx: DISP END: %lx\n", saturn.PC, display.disp_end);
#endif
return;
case 0x128: case 0x129: /* LINE_COUNT */
saturn.line_count &= ~nibble_masks[addr - 0x128];
saturn.line_count |= val << ((addr - 0x128) * 4);
line_counter = -1;
if (display.lines != (saturn.line_count & 0x3f)) {
display.lines = saturn.line_count & 0x3f;
if (display.lines == 0)
display.lines = 63;
disp.lines = 2 * display.lines;
display.disp_end = display.disp_start +
(display.nibs_per_line * (display.lines + 1));
device.display_touched = DISP_INSTR_OFF;
}
#ifdef DEBUG_DISPLAY
LOGE( "%.5lx: DISP LINES: %x\n", saturn.PC, display.lines);
LOGE( "%.5lx: DISP END: %lx\n", saturn.PC, display.disp_end);
#endif
return;
case 0x12a: case 0x12b: case 0x12c: case 0x12d: /* Dont know yet */
saturn.unknown &= ~nibble_masks[addr - 0x12a];
saturn.unknown |= val << ((addr - 0x12a) * 4);
#ifdef DEBUG_UNKNOWN
LOGE( "Unknown device @0x%ld: %.4x\n", addr, saturn.unknown);
#endif
device.unknown_touched = 1;
return;
case 0x12e: /* TIMER 1 CONTROL */
saturn.t1_ctrl = val;
device.t1_ctrl_touched = 1;
return;
case 0x12f: /* TIMER 2 CONTROL */
saturn.t2_ctrl = val;
device.t2_ctrl_touched = 1;
return;
case 0x130: case 0x131: case 0x132: case 0x133: /* MENU_ADDR */
case 0x134:
saturn.menu_addr &= ~nibble_masks[addr - 0x130];
saturn.menu_addr |= val << ((addr - 0x130) * 4);
if (display.menu_start != saturn.menu_addr) {
display.menu_start = saturn.menu_addr;
display.menu_end = display.menu_start + 0x110;
device.display_touched = DISP_INSTR_OFF;
}
return;
case 0x135: case 0x136: /* Dont know yet 2 */
saturn.unknown2 &= ~nibble_masks[addr - 0x135];
saturn.unknown2 |= val << ((addr - 0x135) * 4);
#ifdef DEBUG_UNKNOWN
LOGE( "Unknown device @0x%ld: %.2x\n", addr, saturn.unknown2);
#endif
device.unknown2_touched = 1;
return;
case 0x137: /* TIMER1 */
saturn.timer1 = val;
device.t1_touched = 1;
return;
case 0x138: case 0x139: case 0x13a: case 0x13b:
case 0x13c: case 0x13d: case 0x13e: case 0x13f: /* TIMER2 */
saturn.timer2 &= ~nibble_masks[addr - 0x138];
saturn.timer2 |= val << ((addr - 0x138) * 4);
device.t2_touched = 1;
return;
default:
if (!quiet)
LOGE( "%.5lx: UNKNOWN DEVICE WRITE AT 0x%lx !!!\n",
saturn.PC, addr);
return;
}
}
int
#ifdef __FunctionProto__
read_dev_mem(long addr)
#else
read_dev_mem(addr)
long addr;
#endif
{
switch ((int)addr) {
case 0x100: /* DISPLAY IO */
return saturn.disp_io & 0x0f;
case 0x101: /* CONTRAST CONTROL */
return saturn.contrast_ctrl & 0x0f;
case 0x102: case 0x103: /* DISPLAY TEST */
return (saturn.disp_test >> ((addr - 0x102) * 4)) & 0x0f;
case 0x104: case 0x105: case 0x106: case 0x107: /* CRC */
return (saturn.crc >> ((addr - 0x104) * 4)) & 0x0f;
case 0x108: /* POWER STATUS */
return saturn.power_status & 0x0f;
case 0x109: /* POWER CONTROL */
return saturn.power_ctrl & 0x0f;
case 0x10a: /* MODE */
return saturn.mode & 0x0f;
case 0x10b: case 0x10c: /* ANNUNC */
return (saturn.annunc >> ((addr - 0x10b) * 4)) & 0x0f;
case 0x10d: /* BAUD */
#ifdef DEBUG_SERIALb
LOGE( "%.5lx: BAUD read: %x\n", saturn.PC, saturn.baud);
#endif
return saturn.baud & 0x0f;
case 0x10e: /* CARD CONTROL */
return saturn.card_ctrl & 0x0f;
case 0x10f: /* CARD STATUS */
return saturn.card_status & 0x0f;
case 0x110: /* IO CONTROL */
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: IOC read: %x\n", saturn.PC, saturn.io_ctrl);
#endif
return saturn.io_ctrl & 0x0f;
case 0x111: /* RCS */
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: RCS read: %x\n", saturn.PC, saturn.rcs);
#endif
return saturn.rcs & 0x0f;
case 0x112: /* TCS */
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: TCS read: %x\n", saturn.PC, saturn.tcs);
#endif
return saturn.tcs & 0x0f;
case 0x113: /* CRER */
return 0x00;
case 0x114: case 0x115: /* RBR */
saturn.rcs &= 0x0e;
device.rbr_touched = 1;
device_check = 1;
schedule_event = 0;
return (saturn.rbr >> ((addr - 0x114) * 4)) & 0x0f;
case 0x116: case 0x117: /* TBR */
return 0x00;
case 0x118: case 0x119: /* SERVICE REQ */
#ifdef DEBUG_SERIAL
LOGE( "%.5lx: SREQ? read: %x\n", saturn.PC, saturn.sreq);
#endif
return (saturn.sreq >> ((addr - 0x118) * 4)) & 0x0f;
case 0x11a: /* IR CONTROL */
#ifdef DEBUG_IR
LOGE( "%.5lx: IRC read: %x\n", saturn.PC, saturn.ir_ctrl);
#endif
return saturn.ir_ctrl & 0x0f;
case 0x11b: /* BASE NIB OFFSET */
return saturn.base_off & 0x0f;
case 0x11c: /* LED CONTROL */
#if 0
#ifdef DEBUG_IR
LOGE( "%.5lx: LCR read: %x\n", saturn.PC, saturn.lcr);
#endif
#endif
return saturn.lcr & 0x0f;
case 0x11d: /* LED BUFFER */
#if 0
#ifdef DEBUG_IR
LOGE( "%.5lx: LBR read: %x\n", saturn.PC, saturn.lbr);
#endif
#endif
return saturn.lbr & 0x0f;
case 0x11e: /* SCRATCH PAD */
return saturn.scratch & 0x0f;
case 0x11f: /* BASENIBBLE */
return saturn.base_nibble & 0x0f;
case 0x120: case 0x121: case 0x122: case 0x123: /* DISP_ADDR */
case 0x124:
return (saturn.disp_addr >> ((addr - 0x120) * 4)) & 0x0f;
case 0x125: case 0x126: case 0x127: /* LINE_OFFSET */
return (saturn.line_offset >> ((addr - 0x125) * 4)) & 0x0f;
case 0x128: case 0x129: /* LINE_COUNT */
line_counter++;
if (line_counter > 0x3f)
line_counter = -1;
return (((saturn.line_count & 0xc0) | (line_counter & 0x3f)) >>
((addr - 0x128) * 4)) & 0x0f;
case 0x12a: case 0x12b: case 0x12c: case 0x12d: /* Dont know yet */
return (saturn.unknown >> ((addr - 0x12a) * 4)) & 0x0f;
case 0x12e: /* TIMER 1 CONTROL */
return saturn.t1_ctrl & 0x0f;
case 0x12f: /* TIMER 2 CONTROL */
return saturn.t2_ctrl & 0x0f;
case 0x130: case 0x131: case 0x132: case 0x133: /* MENU_ADDR */
case 0x134:
return (saturn.menu_addr >> ((addr - 0x130) * 4)) & 0x0f;
case 0x135: case 0x136: /* Dont know yet 2 */
return (saturn.unknown2 >> ((addr - 0x135) * 4)) & 0x0f;
case 0x137:
return saturn.timer1 & 0xf;
case 0x138: case 0x139: case 0x13a: case 0x13b:
case 0x13c: case 0x13d: case 0x13e: case 0x13f:
return (saturn.timer2 >> ((addr - 0x138) * 4)) & 0xf;
default:
if (!quiet)
LOGE( "%.5lx: UNKNOWN DEVICE READ AT 0x%lx !!!\n",
saturn.PC, addr);
return 0x00;
}
}
void
#ifdef __FunctionProto__
write_nibble_sx(long addr, int val)
#else
write_nibble_sx(addr, val)
long addr;
int val;
#endif
{
addr &= 0xfffff;
val &= 0x0f;
switch ((int)(addr >> 16) & 0x0f) {
case 0:
if (addr < 0x140 && addr >= 0x100 &&
saturn.mem_cntl[MCTL_MMIO_SX].config[0] == 0x100)
{
write_dev_mem(addr, val);
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 1: case 2: case 3: case 4: case 5: case 6:
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 7:
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0x70000)
{
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfc000
&& addr < 0x74000)
{
saturn.ram[addr - 0x70000] = val;
break;
}
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfe000
&& addr < 0x72000)
{
saturn.ram[addr - 0x70000] = val;
break;
}
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xf0000)
{
saturn.ram[addr - 0x70000] = val;
break;
}
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 8: case 9: case 0xa: case 0xb:
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0x80000)
{
if (port1_is_ram)
saturn.port1[(addr - 0x80000) & port1_mask] = val;
return;
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0x80000)
{
if (port2_is_ram)
saturn.port2[(addr - 0x80000) & port2_mask] = val;
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to NULL at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 0xc: case 0xd: case 0xe:
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000)
{
if (port1_is_ram)
saturn.port1[(addr - 0xc0000) & port1_mask] = val;
return;
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000)
{
if (port2_is_ram)
saturn.port2[(addr - 0xc0000) & port2_mask] = val;
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to NULL at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 0xf:
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0xf0000)
{
saturn.ram[addr - 0xf0000] = val;
break;
}
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000)
{
if (port1_is_ram)
saturn.port1[(addr - 0xc0000) & port1_mask] = val;
return;
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000)
{
if (port2_is_ram)
saturn.port2[(addr - 0xc0000) & port2_mask] = val;
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to NULL at %.5lx\n",
saturn.PC, addr);
#endif
return;
}
if (device.display_touched || !disp.mapped)
return;
if (addr >= display.disp_start && addr < display.disp_end)
{
disp_draw_nibble(addr, val);
}
if (display.lines == 63)
return;
if (addr >= display.menu_start && addr < display.menu_end)
{
menu_draw_nibble(addr, val);
}
}
void
#ifdef __FunctionProto__
write_nibble_gx(long addr, int val)
#else
write_nibble_gx(addr, val)
long addr;
int val;
#endif
{
addr &= 0xfffff;
val &= 0x0f;
switch ((int)(addr >> 16) & 0x0f)
{
case 0:
if (addr < 0x140 && addr >= 0x100 &&
saturn.mem_cntl[MCTL_MMIO_GX].config[0] == 0x100)
{
write_dev_mem(addr, val);
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 1: case 2: case 3: case 5: case 6:
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: BAD WRITE TO ROM AT ADDRESS %.5lx\n",
saturn.PC, addr);
#endif
return;
case 4:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x40000)
{
saturn.ram[addr - 0x40000] = val;
break;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: BAD WRITE TO ROM AT ADDRESS %.5lx\n",
saturn.PC, addr);
#endif
return;
case 7:
if (addr >= 0x7f000 &&
saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x7f000)
{
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: write to bank switch at %.5lx\n",
saturn.PC, addr);
#endif
return;
}
if (addr >= 0x7e000 && addr < 0x7f000 &&
saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0x7e000)
{
#ifdef DEBUG_PORTS
LOGE( "%.5lx: write to port 1 at %.5lx\n",
saturn.PC, addr);
#endif
return;
}
if (addr >= 0x7e000 && addr < 0x7f000 &&
saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0x7e000)
{
#ifdef DEBUG_PORTS
LOGE( "%.5lx: write to port 2 at %.5lx\n",
saturn.PC, addr);
#endif
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 8:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
{
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000
&& addr < 0x84000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000
&& addr < 0x82000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xf0000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 9:
if (saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x90000)
{
if (addr < 0x91000)
{
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: write to bank switch at %.5lx\n",
saturn.PC, addr);
#endif
return;
}
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 0xa:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xa0000)
{
if (port1_is_ram)
saturn.port1[(addr - 0xa0000) & port1_mask] = val;
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 0xb:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
{
saturn.ram[addr - 0x80000] = val;
break;
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xb0000)
{
if (port2_is_ram)
saturn.port2[((saturn.bank_switch << 18) + (addr - 0xb0000))
& port2_mask] = val;
/*
if (port2_size > (saturn.bank_switch << 18))
{
if (port2_is_ram)
saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xb0000)] = val;
}
*/
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 0xc:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000)
{
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000
&& addr < 0xc4000)
{
saturn.ram[addr - 0xc0000] = val;
break;
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000
&& addr < 0xc2000)
{
saturn.ram[addr - 0xc0000] = val;
break;
}
saturn.ram[addr - 0xc0000] = val;
break;
}
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000)
{
if (port1_is_ram)
saturn.port1[(addr - 0xc0000) & port1_mask] = val;
return;
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000)
{
if (port2_is_ram)
saturn.port2[((saturn.bank_switch << 18) + (addr - 0xc0000))
& port2_mask] = val;
/*
if (port2_size > (saturn.bank_switch << 18))
{
if (port2_is_ram)
saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xc0000)] = val;
}
*/
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
case 0xd: case 0xe: case 0xf:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
{
saturn.ram[addr - 0xc0000] = val;
break;
}
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_PORT1_GX].config[1] == 0xc0000)
{
if (port1_is_ram)
saturn.port1[(addr - 0xc0000) & port1_mask] = val;
return;
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_PORT2_GX].config[1] == 0xc0000)
{
if (port2_is_ram)
saturn.port2[((saturn.bank_switch << 18) + (addr - 0xc0000))
& port2_mask] = val;
/*
if (port2_size > (saturn.bank_switch << 18))
{
if (port2_is_ram)
saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xc0000)] = val;
}
*/
return;
}
#ifdef DEBUG_BAD_MEM
LOGE( "%.5lx: write to ROM at %.5lx\n",
saturn.PC, addr);
#endif
return;
}
if (device.display_touched || !disp.mapped)
return;
if (addr >= display.disp_start && addr < display.disp_end)
{
disp_draw_nibble(addr, val);
}
if (display.lines == 63) {
return;
}
if (addr >= display.menu_start && addr < display.menu_end)
{
menu_draw_nibble(addr, val);
}
return;
}
int
#ifdef __FunctionProto__
read_nibble_sx(long addr)
#else
read_nibble_sx(addr)
long addr;
#endif
{
addr &= 0xfffff;
switch ((int)(addr >> 16) & 0x0f) {
case 0:
if (addr < 0x140 && addr >= 0x100)
{
if (saturn.mem_cntl[MCTL_MMIO_SX].config[0] == 0x100)
return read_dev_mem(addr);
else
return 0x00;
}
return saturn.rom[addr];
case 1: case 2: case 3: case 4: case 5: case 6:
return saturn.rom[addr];
case 7:
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0x70000)
{
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfc000
&& addr < 0x74000)
return saturn.ram[addr - 0x70000];
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfe000
&& addr < 0x72000)
return saturn.ram[addr - 0x70000];
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xf0000)
return saturn.ram[addr - 0x70000];
}
return saturn.rom[addr];
case 8: case 9: case 0xa: case 0xb:
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0x80000)
{
return saturn.port1[(addr - 0x80000) & port1_mask];
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0x80000)
{
return saturn.port2[(addr - 0x80000) & port2_mask];
}
return 0x00;
case 0xc: case 0xd: case 0xe:
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000)
{
return saturn.port1[(addr - 0xc0000) & port1_mask];
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000)
{
return saturn.port2[(addr - 0xc0000) & port2_mask];
}
return 0x00;
case 0xf:
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0xf0000)
return saturn.ram[addr - 0xf0000];
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000)
{
return saturn.port1[(addr - 0xc0000) & port1_mask];
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000)
{
return saturn.port2[(addr - 0xc0000) & port2_mask];
}
return 0x00;
}
return 0x00;
}
int
#ifdef __FunctionProto__
read_nibble_gx(long addr)
#else
read_nibble_gx(addr)
long addr;
#endif
{
addr &= 0xfffff;
switch ((int)(addr >> 16) & 0x0f)
{
case 0:
if (addr < 0x140 && addr >= 0x100)
{
if (saturn.mem_cntl[0].config[0] == 0x100)
return read_dev_mem(addr);
else
return 0x00;
}
return saturn.rom[addr];
case 1: case 2: case 3: case 5: case 6:
return saturn.rom[addr];
case 4:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x40000)
return saturn.ram[addr - 0x40000];
return saturn.rom[addr];
case 7:
if (addr >= 0x7f000 &&
saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x7f000)
{
if (addr == 0x7f000)
{
saturn.bank_switch = 0;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: disable bank switch\n", saturn.PC);
#endif
}
if (addr >= 0x7f040 && addr < 0x7f080)
{
saturn.bank_switch = (addr - 0x7f040) / 2;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: switch to bank %d\n",
saturn.PC, saturn.bank_switch);
#endif
}
return 0x7;
}
if (addr >= 0x7e000 && addr < 0x7f000 &&
saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0x7e000)
{
#ifdef DEBUG_PORTS
LOGE( "%.5lx: read from port 1 at %.5lx\n",
saturn.PC, addr);
#endif
return 0x7;
}
if (addr >= 0x7e000 && addr < 0x7f000 &&
saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0x7e000)
{
#ifdef DEBUG_PORTS
LOGE( "%.5lx: read from port 2 at %.5lx\n",
saturn.PC, addr);
#endif
return 0x7;
}
return saturn.rom[addr];
case 8:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
{
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000
&& addr < 0x84000)
return saturn.ram[addr - 0x80000];
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000
&& addr < 0x82000)
return saturn.ram[addr - 0x80000];
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xf0000)
return saturn.ram[addr - 0x80000];
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return saturn.ram[addr - 0x80000];
}
return saturn.rom[addr];
case 9:
if (saturn.mem_cntl[0].config[0] == 0x90000)
{
if (addr < 0x91000)
{
if (addr == 0x90000)
{
saturn.bank_switch = 0;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: disable bank switch\n", saturn.PC);
#endif
}
if (addr >= 0x90040 && addr < 0x90080)
{
saturn.bank_switch = (addr - 0x90040) / 2;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: switch to bank %d\n",
saturn.PC, saturn.bank_switch);
#endif
}
return 0x7;
}
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return saturn.ram[addr - 0x80000];
return saturn.rom[addr];
case 0xa:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return saturn.ram[addr - 0x80000];
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xa0000)
{
return saturn.port1[(addr - 0xa0000) & port1_mask];
}
return saturn.rom[addr];
case 0xb:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return saturn.ram[addr - 0x80000];
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xb0000)
{
return saturn.port2[((saturn.bank_switch << 18) + (addr - 0xb0000))
& port2_mask];
/*
if (port2_size > (saturn.bank_switch << 18))
{
return saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xb0000)];
}
return 0x00;
*/
}
return saturn.rom[addr];
case 0xc:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000)
{
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000
&& addr < 0xc4000)
return saturn.ram[addr - 0xc0000];
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000
&& addr < 0xc2000)
return saturn.ram[addr - 0xc0000];
return saturn.ram[addr - 0xc0000];
}
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000)
{
return saturn.port1[(addr - 0xc0000) & port1_mask];
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000)
{
return saturn.port2[((saturn.bank_switch << 18) + (addr - 0xc0000))
& port2_mask];
/*
if (port2_size > (saturn.bank_switch << 18))
{
return saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xc0000)];
}
return 0x00;
*/
}
return saturn.rom[addr];
case 0xd: case 0xe: case 0xf:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return saturn.ram[addr - 0xc0000];
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_PORT1_GX].config[1] == 0xc0000)
{
return saturn.port1[(addr - 0xc0000) & port1_mask];
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_PORT2_GX].config[1] == 0xc0000)
{
return saturn.port2[((saturn.bank_switch << 18) +
(addr - 0xc0000)) & port2_mask];
/*
if (port2_size > (saturn.bank_switch << 18))
{
return saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xc0000)];
}
return 0x00;
*/
}
return saturn.rom[addr];
}
return 0x00;
}
int
#ifdef __FunctionProto__
read_nibble_crc_sx(long addr)
#else
read_nibble_crc_sx(addr)
long addr;
#endif
{
addr &= 0xfffff;
switch ((int)(addr >> 16) & 0x0f) {
case 0:
if (addr < 0x140 && addr >= 0x100)
{
if (saturn.mem_cntl[MCTL_MMIO_SX].config[0] == 0x100)
return read_dev_mem(addr);
else
return calc_crc(0x00);
}
return calc_crc(saturn.rom[addr]);
case 1: case 2: case 3: case 4: case 5: case 6:
return calc_crc(saturn.rom[addr]);
case 7:
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0x70000)
{
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfc000
&& addr < 0x74000)
return calc_crc(saturn.ram[addr - 0x70000]);
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xfe000
&& addr < 0x72000)
return calc_crc(saturn.ram[addr - 0x70000]);
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[1] == 0xf0000)
return calc_crc(saturn.ram[addr - 0x70000]);
}
return calc_crc(saturn.rom[addr]);
case 8: case 9: case 0xa: case 0xb:
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0x80000)
{
return calc_crc(saturn.port1[(addr - 0x80000) & port1_mask]);
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0x80000)
{
return calc_crc(saturn.port2[(addr - 0x80000) & port2_mask]);
}
return 0x00;
case 0xc: case 0xd: case 0xe:
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000)
{
return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]);
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000)
{
return calc_crc(saturn.port2[(addr - 0xc0000) & port2_mask]);
}
return 0x00;
case 0xf:
if (saturn.mem_cntl[MCTL_SysRAM_SX].config[0] == 0xf0000)
return calc_crc(saturn.ram[addr - 0xf0000]);
if (saturn.mem_cntl[MCTL_PORT1_SX].config[0] == 0xc0000)
{
return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]);
}
if (saturn.mem_cntl[MCTL_PORT2_SX].config[0] == 0xc0000)
{
return calc_crc(saturn.port2[(addr - 0xc0000) & port2_mask]);
}
return 0x00;
}
return 0x00;
}
int
#ifdef __FunctionProto__
read_nibble_crc_gx(long addr)
#else
read_nibble_crc_gx(addr)
long addr;
#endif
{
addr &= 0xfffff;
switch ((int)(addr >> 16) & 0x0f)
{
case 0:
if (addr < 0x140 && addr >= 0x100)
{
if (saturn.mem_cntl[MCTL_MMIO_GX].config[0] == 0x100)
return read_dev_mem(addr);
else
return calc_crc(0x00);
}
return calc_crc(saturn.rom[addr]);
case 1: case 2: case 3: case 5: case 6:
return calc_crc(saturn.rom[addr]);
case 4:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x40000)
return calc_crc(saturn.ram[addr - 0x40000]);
return calc_crc(saturn.rom[addr]);
case 7:
if (addr >= 0x7f000 &&
saturn.mem_cntl[MCTL_BANK_GX].config[0] == 0x7f000)
{
if (addr == 0x7f000)
{
saturn.bank_switch = 0;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: disable bank switch\n", saturn.PC);
#endif
}
if (addr >= 0x7f040 && addr < 0x7f080)
{
saturn.bank_switch = (addr - 0x7f040) / 2;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: switch to bank %d\n",
saturn.PC, saturn.bank_switch);
#endif
}
return 0x7;
}
if (addr >= 0x7e000 && addr < 0x7f000 &&
saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0x7e000)
{
#ifdef DEBUG_PORTS
LOGE( "%.5lx: read from port 1 at %.5lx\n",
saturn.PC, addr);
#endif
return 0x7;
}
if (addr >= 0x7e000 && addr < 0x7f000 &&
saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0x7e000)
{
#ifdef DEBUG_PORTS
LOGE( "%.5lx: read from port 2 at %.5lx\n",
saturn.PC, addr);
#endif
return 0x7;
}
return calc_crc(saturn.rom[addr]);
case 8:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
{
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000
&& addr < 0x84000)
return calc_crc(saturn.ram[addr - 0x80000]);
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000
&& addr < 0x82000)
return calc_crc(saturn.ram[addr - 0x80000]);
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xf0000)
return calc_crc(saturn.ram[addr - 0x80000]);
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return calc_crc(saturn.ram[addr - 0x80000]);
}
return calc_crc(saturn.rom[addr]);
case 9:
if (saturn.mem_cntl[0].config[0] == 0x90000)
{
if (addr < 0x91000)
{
if (addr == 0x90000)
{
saturn.bank_switch = 0;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: disable bank switch\n", saturn.PC);
#endif
}
if (addr >= 0x90040 && addr < 0x90080)
{
saturn.bank_switch = (addr - 0x90040) / 2;
#ifdef DEBUG_BANK_SWITCH
LOGE( "%.5lx: switch to bank %d\n",
saturn.PC, saturn.bank_switch);
#endif
}
return 0x7;
}
}
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return calc_crc(saturn.ram[addr - 0x80000]);
return calc_crc(saturn.rom[addr]);
case 0xa:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return calc_crc(saturn.ram[addr - 0x80000]);
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xa0000)
{
return calc_crc(saturn.port1[(addr - 0xa0000) & port1_mask]);
}
return calc_crc(saturn.rom[addr]);
case 0xb:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0x80000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return calc_crc(saturn.ram[addr - 0x80000]);
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xb0000)
{
return calc_crc(saturn.port2[((saturn.bank_switch << 18) +
(addr - 0xb0000)) & port2_mask]);
/*
if (port2_size > (saturn.bank_switch << 18))
{
return calc_crc(saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xb0000)]);
}
return 0x00;
*/
}
return calc_crc(saturn.rom[addr]);
case 0xc:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000)
{
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfc000
&& addr < 0xc4000)
return calc_crc(saturn.ram[addr - 0xc0000]);
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xfe000
&& addr < 0xc2000)
return calc_crc(saturn.ram[addr - 0xc0000]);
return calc_crc(saturn.ram[addr - 0xc0000]);
}
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000)
{
return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]);
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000)
{
return calc_crc(saturn.port2[((saturn.bank_switch << 18) +
(addr - 0xc0000)) & port2_mask]);
/*
if (port2_size > (saturn.bank_switch << 18))
{
return calc_crc(saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xc0000)]);
}
return 0x00;
*/
}
return calc_crc(saturn.rom[addr]);
case 0xd: case 0xe: case 0xf:
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_SysRAM_GX].config[1] == 0xc0000)
return calc_crc(saturn.ram[addr - 0xc0000]);
if (saturn.mem_cntl[MCTL_PORT1_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_PORT1_GX].config[1] == 0xc0000)
{
return calc_crc(saturn.port1[(addr - 0xc0000) & port1_mask]);
}
if (saturn.mem_cntl[MCTL_PORT2_GX].config[0] == 0xc0000)
if (saturn.mem_cntl[MCTL_PORT2_GX].config[1] == 0xc0000)
{
return calc_crc(saturn.port2[((saturn.bank_switch << 18) +
(addr - 0xc0000)) & port2_mask]);
/*
if (port2_size > (saturn.bank_switch << 18))
{
return calc_crc(saturn.port2[(saturn.bank_switch << 18)
+ (addr - 0xc0000)]);
}
return 0x00;
*/
}
return calc_crc(saturn.rom[addr]);
}
return 0x00;
}
long
#ifdef __FunctionProto__
read_nibbles(long addr, int len)
#else
read_nibbles(addr, len)
long addr;
int len;
#endif
{
long val = 0;
addr += len;
while (len-- > 0) {
val = (val << 4) | read_nibble(--addr);
}
return val;
}
void
#ifdef __FunctionProto__
write_nibbles(long addr, long val, int len)
#else
write_nibbles(addr, val, len)
long addr;
long val;
int len;
#endif
{
while (len-- > 0) {
write_nibble(addr++, val);
val >>= 4;
}
}
void
#ifdef __FunctionProto__
dev_memory_init(void)
#else
dev_memory_init()
#endif
{
if (opt_gx)
{
read_nibble = read_nibble_gx;
read_nibble_crc = read_nibble_crc_gx;
write_nibble = write_nibble_gx;
}
else
{
read_nibble = read_nibble_sx;
read_nibble_crc = read_nibble_crc_sx;
write_nibble = write_nibble_sx;
}
memset(&device, 0, sizeof(device));
}