[Core/VDP]

---------------
* added support for Master System compatibility mode (Z80 ports access mode), incl. Mode 5 rendering.
* added Mode 4 rendering for both Genesis & Master System modes.
* added alternate BG planes rendering functions (should be faster on PPC architectures).

[Core/IO]
---------------
* added support for Master System compatibility mode (Z80 ports access mode).
* added Master System peripherals emulation (Control Pad, Paddle, Sports Pad & Light Phaser).
* added XE-1AP (analog controller) emulation.
* added Activator emulation.

[Core/Extra]
---------------
* added support for all known Master System cartridge mappers.
* added copy-protection hardware emulation for a few MD unlicensed games: fixes 777 Casino (crash when talking to bunny girls).
(NB: most of those unlicensed games seem to have been already patched by ROM dumpers, main purpose is documenting them)
* added support for Top Shooter arcade board controller. (A=Shoot, B=Bet, C/RIGHT=Coins, START=Start, hold UP on startup to enter service mode)
* improved King of Fighters 98 mapper emulation (registers address decoding is now 100% accurate)
* fixed Game Genie when several codes affect same ROM address.
* fixed EEPROM types for Brian Lara Cricket & NBA Jam TE (verified on real cartridges)

[Core/General]
---------------
* added Master System compatibility mode emulation (automatically enabled when loading ROM file with .sms extension).
* improved savestate stability & compatibility (support for old 1.4.x savestates is preserved)
* various code cleanup & comments.

[Gamecube/Wii]
---------------
* fixed cheat codes handling when several codes affect same ROM address.
* improved input controller detection on menu exit.
* improved key remapping dialog box to match emulated device
* changed Menu key for Gamecube controller to allow MODE button mapping
* fixed DVD not being unmounted on swap (memory leak)

[Wii only]
---------------
* added USB mouse support for Sega Mouse emulation
* compiled with latest libogc: improves USB compatibility & fixes stability issues with Wiimotes.
This commit is contained in:
ekeeke31 2011-03-31 22:11:05 +00:00
parent f34b8d4557
commit ab4638144c
101 changed files with 16328 additions and 4588 deletions

View File

@ -1,3 +1,50 @@
---------------------------------------------------------------------------------------------------------
Genesis Plus GX 1.5.0 (31/03/2011) (Eke-Eke)
---------------------------------------------------------------------------------------------------------
[Core/VDP]
---------------
* added support for Master System compatibility mode (Z80 ports access mode), incl. Mode 5 rendering.
* added Mode 4 rendering for both Genesis & Master System modes.
* added alternate BG planes rendering functions (should be faster on PPC architectures).
[Core/IO]
---------------
* added support for Master System compatibility mode (Z80 ports access mode).
* added Master System peripherals emulation (Control Pad, Paddle, Sports Pad & Light Phaser).
* added XE-1AP (analog controller) emulation.
* added Activator emulation.
[Core/Extra]
---------------
* added support for all known Master System cartridge mappers.
* added copy-protection hardware emulation for a few MD unlicensed games: fixes 777 Casino (crash when talking to bunny girls).
(NB: most of those unlicensed games seem to have been already patched by ROM dumpers, main purpose is documenting them)
* added support for Top Shooter arcade board controller. (A=Shoot, B=Bet, C/RIGHT=Coins, START=Start, hold UP on startup to enter service mode)
* improved King of Fighters 98 mapper emulation (registers address decoding is now 100% accurate)
* fixed Game Genie when several codes affect same ROM address.
* fixed EEPROM types for Brian Lara Cricket & NBA Jam TE (verified on real cartridges)
[Core/General]
---------------
* added Master System compatibility mode emulation (automatically enabled when loading ROM file with .sms extension).
* improved savestate stability & compatibility (support for old 1.4.x savestates is preserved)
* various code cleanup & comments.
[Gamecube/Wii]
---------------
* fixed cheat codes handling when several codes affect same ROM address.
* improved input controller detection on menu exit.
* improved key remapping dialog box to match emulated device
* changed Menu key for Gamecube controller to allow MODE button mapping
* fixed DVD not being unmounted on swap (memory leak)
[Wii only]
---------------
* added USB mouse support for Sega Mouse emulation
* compiled with latest libogc: improves USB compatibility & fixes stability issues with Wiimotes.
---------------------------------------------------------------------------------------------------------
Genesis Plus GX 1.4.1 (04/12/2010) (Eke-Eke)
---------------------------------------------------------------------------------------------------------

View File

@ -17,9 +17,9 @@ include $(DEVKITPPC)/gamecube_rules
#---------------------------------------------------------------------------------
TARGET := genplus_cube
BUILD := build_cube
SOURCES := source source/m68k source/z80 source/sound source/ntsc source/cart_hw source/cart_hw/svp \
SOURCES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds
INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/cart_hw source/cart_hw/svp \
INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds \
$(BUILD)
@ -27,7 +27,7 @@ INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/cart_h
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -O3 -fomit-frame-pointer -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DWORDS_BIGENDIAN -DNGC -DHW_DOL
CFLAGS = -O3 -fomit-frame-pointer -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DALT_RENDERER -DNGC -DHW_DOL
CXXFLAGS = $(CFLAGS)
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map

View File

@ -17,9 +17,9 @@ include $(DEVKITPPC)/wii_rules
#---------------------------------------------------------------------------------
TARGET := genplus_wii
BUILD := build_wii
SOURCES := source source/m68k source/z80 source/sound source/ntsc source/cart_hw source/cart_hw/svp \
SOURCES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds
INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/cart_hw source/cart_hw/svp \
INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/input_hw source/cart_hw source/cart_hw/svp \
source/gx source/gx/utils source/gx/gui source/gx/fileio source/gx/images source/gx/sounds \
$(BUILD)
@ -27,7 +27,7 @@ INCLUDES := source source/m68k source/z80 source/sound source/ntsc source/cart_h
# options for code generation
#---------------------------------------------------------------------------------
CFLAGS = -O3 -fomit-frame-pointer -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DWORDS_BIGENDIAN -DNGC -DHW_RVL
CFLAGS = -O3 -fomit-frame-pointer -Wall -Wno-strict-aliasing $(MACHDEP) $(INCLUDE) -DALT_RENDERER -DNGC -DHW_RVL
CXXFLAGS = $(CFLAGS)
LDFLAGS = $(MACHDEP) -Wl,-Map,$(notdir $@).map

View File

@ -38,10 +38,10 @@ static const T_GAME_ENTRY database[GAME_CNT] =
/* 24C02 (old mapper) */
{{"T-081326" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (UE) */
{{"T-81033" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200001, 0, 1, 1}}, /* NBA Jam (J) */
/* 24C02 */
{{"T-81406" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
{{"T-081276" }, 0, {8, 0xFF, 0xFF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club */
/* 24C04 */
{{"T-81406" }, 0, {8, 0x1FF, 0x1FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NBA Jam TE */
/* 24C16 */
{{"T-081586" }, 0, {8, 0x7FF, 0x7FF, 0x200001, 0x200001, 0x200000, 0, 0, 0}}, /* NFL Quarterback Club '96 */
/* 24C65 */
@ -68,9 +68,8 @@ static const T_GAME_ENTRY database[GAME_CNT] =
{{"G-4524" }, 0, {7, 0x7F, 0x7F, 0x200001, 0x200001, 0x200001, 0, 0, 1}}, /* Ninja Burai Densetsu */
/* CODEMASTERS mapper */
/* 24C01 */
{{"T-120106"}, 0, {7, 0x7F, 0x7F, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
/* 24C08 */
{{"T-120106" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Brian Lara Cricket */
{{"T-120096" }, 0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines 2 - Turbo Tournament (E) */
{{"00000000-00"}, 0x168B, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military */
{{"00000000-00"}, 0xCEE0, {8, 0x3FF, 0x3FF, 0x300000, 0x380001, 0x300000, 0, 7, 1}}, /* Micro Machines Military (Bad)*/

View File

@ -118,7 +118,7 @@ void ggenie_reset(int hard)
void ggenie_switch(int enable)
{
int i,j;
int i;
if (enable)
{
/* enable cheats */

1200
source/cart_hw/md_cart.c Normal file

File diff suppressed because it is too large Load Diff

75
source/cart_hw/md_cart.h Normal file
View File

@ -0,0 +1,75 @@
/****************************************************************************
* Genesis Plus
* Mega Drive cartridge hardware support
*
* Copyright (C) 2007-2011 Eke-Eke (GCN/Wii port)
*
* Lots of protection mechanism have been discovered by Haze
* (http://haze.mameworld.info/)
*
* Realtec mapper has been figured out by TascoDeluxe
*
* 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
***************************************************************************/
#ifndef _MD_CART_H_
#define _MD_CART_H_
/* Lock-On cartridge type */
#define TYPE_GG 0x01 /* Game Genie */
#define TYPE_AR 0x02 /* (Pro) Action Replay */
#define TYPE_SK 0x03 /* Sonic & Knuckles */
/* Special hardware (0x01 reserved for SMS 3-D glasses) */
#define HW_J_CART 0x02
#define HW_LOCK_ON 0x04
/* Cartridge extra hardware */
typedef struct
{
uint8 regs[4]; /* internal registers (R/W) */
uint32 mask[4]; /* registers address mask */
uint32 addr[4]; /* registers address */
uint16 realtec; /* realtec mapper */
uint16 bankshift; /* cartridge with bankshift mecanism reseted on software reset */
unsigned int (*time_r)(unsigned int address); /* !TIME signal ($a130xx) read handler */
void (*time_w)(unsigned int address, unsigned int data); /* !TIME signal ($a130xx) write handler */
unsigned int (*regs_r)(unsigned int address); /* cart hardware registers read handler */
void (*regs_w)(unsigned int address, unsigned int data); /* cart hardware registers write handler */
} T_CART_HW;
/* Cartridge type */
typedef struct
{
uint8 *rom; /* ROM area */
uint8 *base; /* ROM base (saved for OS/Cartridge ROM swap) */
uint32 romsize; /* ROM size */
uint32 mask; /* ROM mask */
uint8 special; /* Lock-On, J-Cart or SMS 3-D glasses hardware */
T_CART_HW hw; /* Extra mapping hardware */
} T_CART;
/* global variables */
extern T_CART cart;
/* Function prototypes */
extern void md_cart_init(void);
extern void md_cart_reset(int hard_reset);
extern int md_cart_context_save(uint8 *state);
extern int md_cart_context_load(uint8 *state, char *version);
#endif

631
source/cart_hw/sms_cart.c Normal file
View File

@ -0,0 +1,631 @@
/****************************************************************************
* Genesis Plus
* Master System cartridge hardware support
*
*
* Copyright (C) 1998-2007 Charles MacDonald (SMS Plus original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* Most cartridge protections documented by Haze
* (http://haze.mameworld.info/)
*
* Realtec mapper documented by TascoDeluxe
*
* 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 "shared.h"
#define MAPPER_NONE (0)
#define MAPPER_SEGA (1)
#define MAPPER_CODIES (2)
#define MAPPER_KOREA (3)
#define MAPPER_MSX (4)
#define GAME_DATABASE_CNT (75)
typedef struct
{
uint32 crc;
uint8 glasses_3d;
uint8 peripheral;
uint8 mapper;
uint8 region;
} rominfo_t;
static struct
{
uint8 fcr[4];
uint8 mapper;
} slot;
/* SMS game database */
static const rominfo_t game_list[GAME_DATABASE_CNT] =
{
/* games requiring CODEMASTER mapper (NOTE: extended video modes don't work on Genesis VDP !) */
{0x29822980, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Cosmic Spacehead */
{0xA577CE46, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Micro Machines */
{0xF7C524F6, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Micro Machines [BAD DUMP] */
{0xDBE8895C, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Micro Machines 2 - Turbo Tournament */
{0xC1756BEE, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Pete Sampras Tennis */
{0x8813514B, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_EUROPE}, /* Excellent Dizzy Collection, The [Proto] */
{0xEA5C3A6F, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Dinobasher - Starring Bignose the Caveman [Proto] */
{0x152F0DCC, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Drop Zone" */
{0xAA140C9C, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Excellent Dizzy Collection, The [SMS-GG] */
{0xB9664AE1, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Fantastic Dizzy */
{0xC888222B, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Fantastic Dizzy [SMS-GG] */
{0x76C5BDFB, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Jang Pung 2 [SMS-GG] */
{0xD9A7F170, 0, SYSTEM_MS_GAMEPAD, MAPPER_CODIES, REGION_USA}, /* Man Overboard! */
/* games requiring KOREA mappers (NOTE: TMS9918 video modes don't work on Genesis VDP !) */
{0x17AB6883, 0, SYSTEM_MS_GAMEPAD, MAPPER_NONE, REGION_JAPAN_NTSC}, /* FA Tetris (KR) */
{0x61E8806F, 0, SYSTEM_MS_GAMEPAD, MAPPER_NONE, REGION_JAPAN_NTSC}, /* Flash Point (KR) */
{0x445525E2, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* Penguin Adventure (KR) */
{0x83F0EEDE, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* Street Master (KR) */
{0xA05258F5, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* Won-Si-In (KR) */
{0x06965ED9, 0, SYSTEM_MS_GAMEPAD, MAPPER_MSX, REGION_JAPAN_NTSC}, /* F-1 Spirit - The way to Formula-1 (KR) */
{0x89B79E77, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Dodgeball King (KR) */
{0x18FB98A3, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Jang Pung 3 (KR) */
{0x97D03541, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Sangokushi 3 (KR)"} */
{0x67C2F0FF, 0, SYSTEM_MS_GAMEPAD, MAPPER_KOREA, REGION_JAPAN_NTSC}, /* Super Boy 2 (KR) */
/* games requiring PAL timings */
{0x72420F38, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Addams Familly */
{0x2D48C1D3, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Back to the Future Part III */
{0x1CBB7BF1, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Battlemaniacs (BR) */
{0x1B10A951, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Bram Stoker's Dracula */
{0xC0E25D62, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* California Games II */
{0x45C50294, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Jogos de Verao II (BR) */
{0xC9DBF936, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Home Alone */
{0x0047B615, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Predator2 */
{0xF42E145C, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Quest for the Shaven Yak Starring Ren Hoek & Stimpy (BR) */
{0x9F951756, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* RoboCop 3 */
{0xF8176918, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sensible Soccer */
{0x1575581D, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Shadow of the Beast */
{0x96B3F29E, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sonic Blast (BR) */
{0x5B3B922C, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sonic the Hedgehog 2 [V0] */
{0xD6F2BFCA, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Sonic the Hedgehog 2 [V1] */
{0xCA1D3752, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Space Harrier [50 Hz] */
{0x85CFC9C9, 0, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_EUROPE}, /* Taito Chase H.Q. */
/* games requiring 3-D Glasses */
{0x871562b0, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Maze Walker */
{0x156948f9, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Space Harrier 3-D (J) */
{0x6BD5C2BF, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Space Harrier 3-D */
{0x8ECD201C, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Blade Eagle 3-D */
{0xFBF96C81, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Blade Eagle 3-D (BR) */
{0x58D5FC48, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Blade Eagle 3-D [Proto] */
{0x31B8040B, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Maze Hunter 3-D */
{0xABD48AD2, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Poseidon Wars 3-D */
{0xA3EF13CB, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Zaxxon 3-D */
{0xBBA74147, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Zaxxon 3-D [Proto] */
{0xD6F43DDA, 1, SYSTEM_MS_GAMEPAD, MAPPER_SEGA, REGION_USA}, /* Out Run 3-D */
/* games requiring 3-D Glasses & Sega Light Phaser */
{0xFBE5CFBB, 1, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Missile Defense 3D */
{0xE79BB689, 1, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Missile Defense 3D [BIOS] */
/* games requiring Sega Light Phaser */
{0x861B6E79, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Assault City [Light Phaser] */
{0x5FC74D2A, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Gangster Town */
{0xE167A561, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Hang-On / Safari Hunt */
{0xC5083000, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Hang-On / Safari Hunt [BAD DUMP] */
{0x91E93385, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Hang-On / Safari Hunt [BIOS] */
{0xE8EA842C, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Marksman Shooting / Trap Shooting */
{0xE8215C2E, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Marksman Shooting / Trap Shooting / Safari Hunt */
{0x205CAAE8, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Operation Wolf (can be played with gamepad in port B)*/
{0x23283F37, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Operation Wolf [A] (can be played with gamepad in port B) */
{0xDA5A7013, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Rambo 3 */
{0x79AC8E7F, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Rescue Mission */
{0x4B051022, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Shooting Gallery */
{0xA908CFF5, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Spacegun */
{0x5359762D, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Wanted */
{0x0CA95637, 0, SYSTEM_LIGHTPHASER, MAPPER_SEGA, REGION_USA}, /* Laser Ghost */
/* games requiring Sega Paddle */
{0xF9DBB533, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Alex Kidd BMX Trial */
{0xA6FA42D0, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Galactic Protector */
{0x29BC7FAD, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Megumi Rescue */
{0x315917D4, 0, SYSTEM_PADDLE, MAPPER_SEGA, REGION_JAPAN_NTSC}, /* Woody Pop */
/* games requiring Sega Sport Pad */
{0x0CB7E21F, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, REGION_USA}, /* Great Ice Hockey */
{0xE42E4998, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, REGION_USA}, /* Sports Pad Football */
{0x41C948BF, 0, SYSTEM_SPORTSPAD, MAPPER_SEGA, REGION_USA} /* Sports Pad Soccer */
};
/* 1K trash buffer */
static uint8 dummy[0x400];
/* Function prorotypes */
static void mapper_8k_w(int offset, unsigned int data);
static void mapper_16k_w(int offset, unsigned int data);
static void write_mapper_none(unsigned int address, unsigned char data);
static void write_mapper_sega(unsigned int address, unsigned char data);
static void write_mapper_codies(unsigned int address, unsigned char data);
static void write_mapper_korea(unsigned int address, unsigned char data);
static void write_mapper_msx(unsigned int address, unsigned char data);
void sms_cart_init(void)
{
/* default mapper */
slot.mapper = MAPPER_SEGA;
/* default supported peripheral */
uint8 device = SYSTEM_MS_GAMEPAD;
cart.special = 0;
/* compute CRC */
uint32 crc = crc32(0, cart.rom, cart.romsize);
/* detect cartridge mapper */
int i;
for (i=0; i<GAME_DATABASE_CNT; i++)
{
if (crc == game_list[i].crc)
{
cart.special = game_list[i].glasses_3d;
slot.mapper = game_list[i].mapper;
device = game_list[i].peripheral;
i = GAME_DATABASE_CNT;
}
}
/* initialize Z80 write handler */
switch(slot.mapper)
{
case MAPPER_NONE:
z80_writemem = write_mapper_none;
break;
case MAPPER_CODIES:
z80_writemem = write_mapper_codies;
break;
case MAPPER_KOREA:
z80_writemem = write_mapper_korea;
break;
case MAPPER_MSX:
z80_writemem = write_mapper_msx;
break;
default:
z80_writemem = write_mapper_sega;
break;
}
/* initialize default SRAM (32K max.) */
sram_init();
/* restore previous input settings */
if (old_system[0] != -1)
{
input.system[0] = old_system[0];
}
if (old_system[1] != -1)
{
input.system[1] = old_system[1];
}
/* default gun offset */
input.x_offset = 20;
input.y_offset = 0;
/* detect if game requires specific peripheral */
if (device != SYSTEM_MS_GAMEPAD)
{
/* save port A setting */
if (old_system[0] == -1)
{
old_system[0] = input.system[0];
}
/* force port A configuration */
input.system[0] = device;
/* SpaceGun & Gangster Town use different gun offset */
if ((crc == 0x5359762D) || (crc == 0x5FC74D2A))
{
input.x_offset = 16;
}
}
}
void sms_cart_reset(void)
{
int i;
/* Unmapped memory return $FF */
memset(dummy, 0xFF, 0x400);
/* Reset Z80 memory mapping at $0000-$BFFF (first 32k of ROM mirrored) */
for(i = 0x00; i < 0x30; i++)
{
z80_readmap[i] = &cart.rom[(i & 0x1F) << 10];
z80_writemap[i] = dummy;
}
/* Reset Z80 memory mapping at $C000-$FFFF (first 8K of 68k RAM mirrored) */
for(i = 0x30; i < 0x40; i++)
{
z80_readmap[i] = z80_writemap[i] = &work_ram[(i & 0x07) << 10];
}
/* Reset cartridge paging registers */
switch(slot.mapper)
{
case MAPPER_NONE:
case MAPPER_SEGA:
{
slot.fcr[0] = 0;
slot.fcr[1] = 0;
slot.fcr[2] = 1;
slot.fcr[3] = 2;
break;
}
default:
{
slot.fcr[0] = 0;
slot.fcr[1] = 0;
slot.fcr[2] = 1;
slot.fcr[3] = 0;
break;
}
}
/* Set default memory map */
if (slot.mapper != MAPPER_MSX)
{
mapper_16k_w(0,slot.fcr[0]);
mapper_16k_w(1,slot.fcr[1]);
mapper_16k_w(2,slot.fcr[2]);
mapper_16k_w(3,slot.fcr[3]);
}
else
{
mapper_8k_w(0,slot.fcr[0]);
mapper_8k_w(1,slot.fcr[1]);
mapper_8k_w(2,slot.fcr[2]);
mapper_8k_w(3,slot.fcr[3]);
}
}
void sms_cart_switch(int enabled)
{
int i;
if (enabled)
{
/* Enable cartdige ROM at $0000-$BFFF */
for(i = 0x00; i < 0x30; i++)
{
z80_readmap[i] = &cart.rom[(i & 0x1F) << 10];
z80_writemap[i] = dummy;
}
}
else
{
/* Disable cartridge ROM at $0000-$BFFF */
for(i = 0x00; i < 0x30; i++)
{
z80_readmap[i] = z80_writemap[i] = dummy;
}
}
}
int sms_cart_region_detect(void)
{
/* compute CRC */
uint32 crc = crc32(0, cart.rom, cart.romsize);
/* detect game region */
int i;
for (i=0; i<GAME_DATABASE_CNT; i++)
{
if (crc == game_list[i].crc)
{
return game_list[i].region;
}
}
/* default region */
return REGION_USA;
}
int sms_cart_context_save(uint8 *state)
{
int bufferptr = 0;
save_param(slot.fcr, sizeof(slot.fcr));
return bufferptr;
}
int sms_cart_context_load(uint8 *state, char *version)
{
int bufferptr = 0;
load_param(slot.fcr, sizeof(slot.fcr));
/* Set default memory map */
if (slot.mapper != MAPPER_MSX)
{
mapper_16k_w(0,slot.fcr[0]);
mapper_16k_w(1,slot.fcr[1]);
mapper_16k_w(2,slot.fcr[2]);
mapper_16k_w(3,slot.fcr[3]);
}
else
{
mapper_8k_w(0,slot.fcr[0]);
mapper_8k_w(1,slot.fcr[1]);
mapper_8k_w(2,slot.fcr[2]);
mapper_8k_w(3,slot.fcr[3]);
}
return bufferptr;
}
void mapper_8k_w(int offset, unsigned int data)
{
int i;
/* cartridge ROM page (8k) */
uint8 page = data % (cart.romsize >> 13);
/* Save frame control register data */
slot.fcr[offset] = data;
/* 4 x 8k banks */
switch (offset & 3)
{
case 0: /* cartridge ROM bank (8k) at $8000-$9FFF */
{
for(i = 0x20; i < 0x28; i++)
{
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
}
break;
}
case 1: /* cartridge ROM bank (8k) at $A000-$BFFF */
{
for(i = 0x28; i < 0x30; i++)
{
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
}
break;
}
case 2: /* cartridge ROM bank (8k) at $4000-$5FFF */
{
for(i = 0x10; i < 0x18; i++)
{
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
}
break;
}
case 3: /* cartridge ROM bank (8k) at $6000-$7FFF */
{
for(i = 0x18; i < 0x20; i++)
{
z80_readmap[i] = &cart.rom[(page << 13) | ((i & 0x07) << 10)];
}
break;
}
}
}
void mapper_16k_w(int offset, unsigned int data)
{
int i;
/* cartridge ROM page (16k) */
uint8 page = data % (cart.romsize >> 14);
/* page index increment (SEGA mapper) */
if (slot.fcr[0] & 0x03)
{
page = (page + ((4 - (slot.fcr[0] & 0x03)) << 3)) % (cart.romsize >> 14);
}
/* save frame control register data */
slot.fcr[offset] = data;
switch (offset)
{
case 0: /* control register (SEGA mapper) */
{
if(data & 0x08)
{
/* external RAM (upper or lower 16K) mapped at $8000-$BFFF */
for(i = 0x20; i <= 0x2F; i++)
{
z80_readmap[i] = z80_writemap[i] = &sram.sram[((data & 0x04) << 12) + ((i & 0x0F) << 10)];
}
}
else
{
/* cartridge ROM page (16k) */
page = slot.fcr[3] % (cart.romsize >> 14);
/* page index increment (SEGA mapper) */
if (data & 0x03)
{
page = (page + ((4 - (data & 0x03)) << 3)) % (cart.romsize >> 14);
}
/* cartridge ROM mapped at $8000-$BFFF */
for(i = 0x20; i < 0x30; i++)
{
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
z80_writemap[i] = dummy;
}
}
if(data & 0x10)
{
/* external RAM (lower 16K) mapped at $C000-$FFFF */
for(i = 0x30; i < 0x40; i++)
{
z80_readmap[i] = z80_writemap[i] = &sram.sram[(i & 0x0F) << 10];
}
}
else
{
/* internal RAM (8K mirrorred) mapped at $C000-$FFFF */
for(i = 0x30; i < 0x40; i++)
{
z80_readmap[i] = z80_writemap[i] = &work_ram[(i & 0x07) << 10];
}
}
break;
}
case 1: /* cartridge ROM bank (16k) at $0000-$3FFF */
{
/* first 1k is not fixed (CODEMASTER mapper) */
if (slot.mapper == MAPPER_CODIES)
{
z80_readmap[0] = &cart.rom[(page << 14)];
}
for(i = 0x01; i < 0x10; i++)
{
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
}
break;
}
case 2: /* cartridge ROM bank (16k) at $4000-$7FFF */
{
for(i = 0x10; i < 0x20; i++)
{
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
}
/* Ernie Elf's Golf external RAM switch */
if (slot.mapper == MAPPER_CODIES)
{
if (data & 0x80)
{
/* external RAM (8k) mapped at $A000-$BFFF */
for(i = 0x28; i < 0x30; i++)
{
z80_readmap[i] = z80_writemap[i] = &sram.sram[(i & 0x0F) << 10];
}
}
else
{
/* cartridge ROM page (16k) */
page = slot.fcr[3] % (cart.romsize >> 14);
/* cartridge ROM mapped at $A000-$BFFF */
for(i = 0x28; i < 0x30; i++)
{
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
z80_writemap[i] = dummy;
}
}
}
break;
}
case 3: /* cartridge ROM bank (16k) at $8000-$BFFF */
{
/* check that external RAM (16k) is not mapped at $8000-$BFFF (SEGA mapper) */
if ((slot.fcr[0] & 0x08)) break;
/* first 8k */
for(i = 0x20; i < 0x28; i++)
{
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
}
/* check that external RAM (8k) is not mapped at $A000-$BFFF (CODEMASTER mapper) */
if ((slot.mapper == MAPPER_CODIES) && (slot.fcr[2] & 0x80)) break;
/* last 8k */
for(i = 0x28; i < 0x30; i++)
{
z80_readmap[i] = &cart.rom[(page << 14) | ((i & 0x0F) << 10)];
}
break;
}
}
}
static void write_mapper_none(unsigned int address, unsigned char data)
{
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_sega(unsigned int address, unsigned char data)
{
if(address >= 0xFFFC)
{
mapper_16k_w(address & 3, data);
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_codies(unsigned int address, unsigned char data)
{
if (address == 0x0000)
{
mapper_16k_w(1,data);
return;
}
if (address == 0x4000)
{
mapper_16k_w(2,data);
return;
}
if (address == 0x8000)
{
mapper_16k_w(3,data);
return;
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_korea(unsigned int address, unsigned char data)
{
if (address == 0xA000)
{
mapper_16k_w(3,data);
return;
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}
static void write_mapper_msx(unsigned int address, unsigned char data)
{
if (address <= 0x0003)
{
mapper_8k_w(address,data);
return;
}
z80_writemap[address >> 10][address & 0x03FF] = data;
}

38
source/cart_hw/sms_cart.h Normal file
View File

@ -0,0 +1,38 @@
/****************************************************************************
* Genesis Plus
* Master System cartridge hardware support
*
* Copyright (C) 1998-2007 Charles MacDonald (SMS Plus original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* Realtec mapper has been figured out by TascoDeluxe
*
* 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
***************************************************************************/
#ifndef _SMS_CART_H_
#define _SMS_CART_H_
/* Function prototypes */
extern void sms_cart_init(void);
extern void sms_cart_reset(void);
extern void sms_cart_switch(int enabled);
extern int sms_cart_region_detect(void);
extern int sms_cart_context_save(uint8 *state);
extern int sms_cart_context_load(uint8 *state, char *version);
#endif

View File

@ -59,7 +59,9 @@ void sram_init()
/* fixe some bad header informations */
if ((sram.start > sram.end) || ((sram.end - sram.start) >= 0x10000))
{
sram.end = sram.start + 0xffff;
}
sram.start &= 0xfffffffe;
sram.end |= 1;

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* Genesis internals & Bus controller
* Internal Hardware & Bus controllers
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
@ -42,16 +42,18 @@ void gen_init(void)
{
int i;
/* initialize CPUs */
/* initialize 68k */
m68k_set_cpu_type(M68K_CPU_TYPE_68000);
m68k_init();
/* initialize Z80 */
z80_init(0,z80_irq_callback);
/* initialize 68k mapped memory */
/* $000000-$7fffff is affected to cartridge area (see cart_hw.c) */
/* $800000-$ffffff is affected to WRAM (see VDP DMA) */
/* initialize 68k memory map */
/* $000000-$7FFFFF is affected to cartridge area (see md_cart.c) */
for (i=0x80; i<0x100; i++)
{
/* $800000-$FFFFFF is affected to WRAM (see VDP DMA) */
m68k_memory_map[i].base = work_ram;
m68k_memory_map[i].read8 = NULL;
m68k_memory_map[i].read16 = NULL;
@ -64,7 +66,7 @@ void gen_init(void)
/* initialize 68k memory handlers */
for (i=0x80; i<0xe0; i++)
{
/* illegal area */
/* $800000-$DFFFFF : illegal area by default */
m68k_memory_map[i].read8 = m68k_lockup_r_8;
m68k_memory_map[i].read16 = m68k_lockup_r_16;
m68k_memory_map[i].write8 = m68k_lockup_w_8;
@ -73,11 +75,7 @@ void gen_init(void)
zbank_memory_map[i].write = zbank_lockup_w;
}
/* Z80 bus (bank access) */
zbank_memory_map[0xa0].read = zbank_lockup_r;
zbank_memory_map[0xa0].write = zbank_lockup_w;
/* I/O & Control registers */
/* $A10000-$A1FFFF : I/O & Control registers */
m68k_memory_map[0xa1].read8 = ctrl_io_read_byte;
m68k_memory_map[0xa1].read16 = ctrl_io_read_word;
m68k_memory_map[0xa1].write8 = ctrl_io_write_byte;
@ -85,110 +83,155 @@ void gen_init(void)
zbank_memory_map[0xa1].read = zbank_read_ctrl_io;
zbank_memory_map[0xa1].write = zbank_write_ctrl_io;
/* VDP (initially locked on models with TMSS) */
if (!(config.tmss & 1))
/* $C0xxxx, $C8xxxx, $D0xxxx, $D8xxxx : VDP ports */
for (i=0xc0; i<0xe0; i+=8)
{
for (i=0xc0; i<0xe0; i+=8)
{
m68k_memory_map[i].read8 = vdp_read_byte;
m68k_memory_map[i].read16 = vdp_read_word;
m68k_memory_map[i].write8 = vdp_write_byte;
m68k_memory_map[i].write16 = vdp_write_word;
zbank_memory_map[i].read = zbank_read_vdp;
zbank_memory_map[i].write = zbank_write_vdp;
}
m68k_memory_map[i].read8 = vdp_read_byte;
m68k_memory_map[i].read16 = vdp_read_word;
m68k_memory_map[i].write8 = vdp_write_byte;
m68k_memory_map[i].write16 = vdp_write_word;
zbank_memory_map[i].read = zbank_read_vdp;
zbank_memory_map[i].write = zbank_write_vdp;
}
/* SEGA PICO */
if (system_hw == SYSTEM_PICO)
/* MS COMPATIBILITY mode */
if (system_hw == SYSTEM_PBC)
{
m68k_memory_map[0x80].read8 = pico_read_byte;
m68k_memory_map[0x80].read16 = pico_read_word;
m68k_memory_map[0x80].write8 = m68k_unused_8_w;
m68k_memory_map[0x80].write16 = m68k_unused_16_w;
/* initialize Z80 read handler */
/* NB: memory map & write handler are defined by cartridge hardware */
z80_readmem = z80_sms_memory_r;
/* there is no I/O area (Notaz) */
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
/* initialize Z80 ports handlers */
z80_writeport = z80_sms_port_w;
z80_readport = z80_sms_port_r;
/* page registers */
pico_current = 0x00;
pico_page[0] = 0x00;
pico_page[1] = 0x01;
pico_page[2] = 0x03;
pico_page[3] = 0x07;
pico_page[4] = 0x0F;
pico_page[5] = 0x1F;
pico_page[6] = 0x3F;
/* initialize MS cartridge hardware */
sms_cart_init();
}
else
{
/* PICO hardware */
if (system_hw == SYSTEM_PICO)
{
/* additional registers mapped to $800000-$80FFFF */
m68k_memory_map[0x80].read8 = pico_read_byte;
m68k_memory_map[0x80].read16 = pico_read_word;
m68k_memory_map[0x80].write8 = m68k_unused_8_w;
m68k_memory_map[0x80].write16 = m68k_unused_16_w;
/* there is no I/O area (Notaz) */
m68k_memory_map[0xa1].read8 = m68k_read_bus_8;
m68k_memory_map[0xa1].read16 = m68k_read_bus_16;
m68k_memory_map[0xa1].write8 = m68k_unused_8_w;
m68k_memory_map[0xa1].write16 = m68k_unused_16_w;
/* page registers */
pico_current = 0x00;
pico_page[0] = 0x00;
pico_page[1] = 0x01;
pico_page[2] = 0x03;
pico_page[3] = 0x07;
pico_page[4] = 0x0F;
pico_page[5] = 0x1F;
pico_page[6] = 0x3F;
}
/* initialize Z80 memory map */
/* $0000-$3FFF is mapped to Z80 RAM (8K mirrored) */
/* $4000-$FFFF is mapped to hardware but Z80.PC should never point there */
for (i=0; i<64; i++)
{
z80_readmap[i] = &zram[(i & 7) << 10];
}
/* initialize Z80 memory handlers */
z80_writemem = z80_md_memory_w;
z80_readmem = z80_md_memory_r;
/* initialize Z80 port handlers */
z80_writeport = z80_unused_port_w;
z80_readport = z80_unused_port_r;
/* initialize MD cartridge hardware */
md_cart_init();
}
}
void gen_hardreset(void)
void gen_reset(int hard_reset)
{
/* Clear RAM */
memset (work_ram, 0x00, sizeof (work_ram));
memset (zram, 0x00, sizeof (zram));
/* TMSS + OS ROM support */
memset(tmss, 0x00, sizeof(tmss));
if (config.tmss == 3)
/* System Reset */
if (hard_reset)
{
m68k_memory_map[0].base = bios_rom;
/* clear RAM */
memset (work_ram, 0x00, sizeof (work_ram));
memset (zram, 0x00, sizeof (zram));
/* TMSS & OS ROM support */
if (config.tmss & 1)
{
/* clear TMSS register */
memset(tmss, 0x00, sizeof(tmss));
/* VDP access is locked by default */
int i;
for (i=0xc0; i<0xe0; i+=8)
{
m68k_memory_map[i].read8 = m68k_lockup_r_8;
m68k_memory_map[i].read16 = m68k_lockup_r_16;
m68k_memory_map[i].write8 = m68k_lockup_w_8;
m68k_memory_map[i].write16 = m68k_lockup_w_16;
zbank_memory_map[i].read = zbank_lockup_r;
zbank_memory_map[i].write = zbank_lockup_w;
}
/* OS ROM is mapped at $000000-$0007FF */
if (config.tmss & 2)
{
m68k_memory_map[0].base = bios_rom;
}
}
}
else
{
/* reset YM2612 (on hard reset, this is done by sound_reset) */
fm_reset(0);
}
/* 68k & Z80 could restart anywhere in VDP frame (Bonkers, Eternal Champions, X-Men 2) */
mcycles_68k = mcycles_z80 = (uint32)((MCYCLES_PER_LINE * lines_per_frame) * ((double)rand() / (double)RAND_MAX));
/* Z80 bus is released & Z80 is stopped */
zstate = 0;
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
/* Assume default bank is $000000-$007FFF */
zbank = 0;
/* Reset 68k & Z80 */
m68k_pulse_reset();
z80_reset();
}
void gen_softreset(int state)
{
if (state)
if (system_hw == SYSTEM_PBC)
{
/* Halt 68k */
/* reset MS cartridge hardware */
sms_cart_reset();
/* Z80 is running */
zstate = 1;
/* 68k is halted */
m68k_pulse_halt();
}
else
{
/* reset MD cartridge hardware */
md_cart_reset(hard_reset);
/* Z80 bus is released & Z80 is reseted */
zstate = 0;
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
zstate = 0;
/* Assume default bank is $000000-$007FFF */
/* assume default bank is $000000-$007FFF */
zbank = 0;
/* Reset YM2612 */
fm_reset(0);
}
else
{
/* Reset Cartridge Hardware */
cart_hw_reset(0);
/* 68k & Z80 could restart anywhere in VDP frame (Bonkers, Eternal Champions, X-Men 2) */
mcycles_68k = mcycles_z80 = (uint32)((MCYCLES_PER_LINE * lines_per_frame) * ((double)rand() / (double)RAND_MAX));
/* Reset 68k, Z80 & YM2612 */
/* reset 68k */
m68k_pulse_reset();
z80_reset();
fm_reset(0);
}
/* reset Z80 */
z80_reset();
}
void gen_shutdown(void)
@ -197,16 +240,16 @@ void gen_shutdown(void)
}
/*-----------------------------------------------------------------------
OS ROM / TMSS register control functions
-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* OS ROM / TMSS register control functions (Genesis mode) */
/*-----------------------------------------------------------------------*/
void gen_tmss_w(unsigned int offset, unsigned int data)
{
/* write TMSS regisiter */
WRITE_WORD(tmss, offset, data);
/* VDP requires "SEGA" value to be written in TMSSS register */
/* VDP requires "SEGA" value to be written in TMSS register */
int i;
if (strncmp((char *)tmss, "SEGA", 4) == 0)
{
@ -236,7 +279,7 @@ void gen_tmss_w(unsigned int offset, unsigned int data)
void gen_bankswitch_w(unsigned int data)
{
/* BIOS has not been loaded yet */
/* OS ROM has not been loaded yet */
if (!(config.tmss & 2))
{
config.tmss |= 2;
@ -262,9 +305,10 @@ unsigned int gen_bankswitch_r(void)
}
/*-----------------------------------------------------------------------
Z80 Bus controller chip functions
-----------------------------------------------------------------------*/
/*-----------------------------------------------------------------------*/
/* Z80 Bus controller chip functions (Genesis mode) */
/* ----------------------------------------------------------------------*/
void gen_zbusreq_w(unsigned int data, unsigned int cycles)
{
if (data) /* !ZBUSREQ asserted */
@ -276,11 +320,10 @@ void gen_zbusreq_w(unsigned int data, unsigned int cycles)
z80_run(cycles);
/* enable 68k access to Z80 bus */
_m68k_memory_map *base = &m68k_memory_map[0xa0];
base->read8 = z80_read_byte;
base->read16 = z80_read_word;
base->write8 = z80_write_byte;
base->write16 = z80_write_word;
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
}
/* update Z80 bus status */
@ -295,11 +338,10 @@ void gen_zbusreq_w(unsigned int data, unsigned int cycles)
mcycles_z80 = cycles;
/* disable 68k access to Z80 bus */
_m68k_memory_map *base = &m68k_memory_map[0xa0];
base->read8 = m68k_read_bus_8;
base->read16 = m68k_read_bus_16;
base->write8 = m68k_unused_8_w;
base->write16 = m68k_unused_16_w;
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
}
/* update Z80 bus status */
@ -326,11 +368,10 @@ void gen_zreset_w(unsigned int data, unsigned int cycles)
else if (zstate == 2)
{
/* enable 68k access to Z80 bus */
_m68k_memory_map *base = &m68k_memory_map[0xa0];
base->read8 = z80_read_byte;
base->read16 = z80_read_word;
base->write8 = z80_write_byte;
base->write16 = z80_write_word;
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
/* reset Z80 & YM2612 */
z80_reset();
@ -353,11 +394,10 @@ void gen_zreset_w(unsigned int data, unsigned int cycles)
else if (zstate == 3)
{
/* disable 68k access to Z80 bus */
_m68k_memory_map *base = &m68k_memory_map[0xa0];
base->read8 = m68k_read_bus_8;
base->read16 = m68k_read_bus_16;
base->write8 = m68k_unused_8_w;
base->write16 = m68k_unused_16_w;
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
}
/* stop YM2612 */
@ -373,6 +413,11 @@ void gen_zbank_w (unsigned int data)
zbank = ((zbank >> 1) | ((data & 1) << 23)) & 0xFF8000;
}
/*-----------------------------------------------------------------------*/
/* Z80 interrupt callback */
/* ----------------------------------------------------------------------*/
int z80_irq_callback (int param)
{
return 0xFF;

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* Genesis internals & Bus controller
* Internal hardware & Bus controllers
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
@ -36,8 +36,7 @@ extern uint8 pico_page[7];
/* Function prototypes */
extern void gen_init(void);
extern void gen_hardreset(void);
extern void gen_softreset(int state);
extern void gen_reset(int hard_reset);
extern void gen_shutdown(void);
extern void gen_tmss_w(unsigned int offset, unsigned int data);
extern void gen_bankswitch_w(unsigned int data);

View File

@ -55,6 +55,9 @@ static char *fileDir;
/* current device */
static int deviceType = -1;
/* DVD status flag */
static u8 dvd_mounted = 0;
/***************************************************************************
* MountDVD
*
@ -64,18 +67,31 @@ static int MountDVD(void)
{
GUI_MsgBoxOpen("Information", "Mounting DVD ...",1);
/* check if DVD is already mounted */
if (dvd_mounted)
{
/* unmount DVD */
ISO9660_Unmount("dvd:");
dvd_mounted = 0;
}
/* check if disc is found */
if(!dvd->isInserted())
{
GUI_WaitPrompt("Error","No Disc inserted !");
return 0;
}
if(!ISO9660_Mount())
/* mount DVD */
if(!ISO9660_Mount("dvd",dvd))
{
GUI_WaitPrompt("Error","Disc can not be read !");
return 0;
}
/* DVD is mounted */
dvd_mounted = 1;
GUI_MsgBoxClose();
return 1;
}
@ -198,7 +214,7 @@ int ParseDirectory(void)
* This functions return the actual size of data copied into the buffer
*
****************************************************************************/
int LoadFile(u8 *buffer, u32 selection)
int LoadFile(u8 *buffer, u32 selection, char *filename)
{
char fname[MAXPATHLEN];
char *filepath;
@ -264,11 +280,14 @@ int LoadFile(u8 *buffer, u32 selection)
fread(buffer + done, length, 1, fd);
done += length;
GUI_MsgBoxClose();
/* update ROM filename (with extension) */
sprintf(filename, "%s", filelist[selection].filename);
}
else
{
/* unzip file */
done = UnZipBuffer(buffer, fd);
done = UnZipBuffer(buffer, fd, filename);
}
/* close file */

View File

@ -39,6 +39,6 @@
extern int OpenDirectory(int device);
extern int UpdateDirectory(bool go_up, char *filename);
extern int ParseDirectory(void);
extern int LoadFile(u8* buffer,u32 selection);
extern int LoadFile(u8* buffer,u32 selection, char *filename);
#endif

View File

@ -92,9 +92,8 @@ int IsZipFile (char *buffer)
/*****************************************************************************
* UnZipBuffer
*
* It should be noted that there is a limit of 5MB total size for any ROM
******************************************************************************/
int UnZipBuffer (unsigned char *outbuffer, FILE *fd)
int UnZipBuffer (unsigned char *outbuffer, FILE *fd, char *filename)
{
PKZIPHEADER pkzip;
int zipoffset = 0;
@ -137,21 +136,27 @@ int UnZipBuffer (unsigned char *outbuffer, FILE *fd)
return 0;
}
/*** Get file name (first file) ***/
int size = FLIP16 (pkzip.filenameLength);
if (size > 255) size = 255;
strncpy(filename, &readbuffer[sizeof(PKZIPHEADER)], size);
filename[size] = 0;
/*** Set ZipChunk for first pass ***/
zipoffset = (sizeof (PKZIPHEADER) + FLIP16 (pkzip.filenameLength) + FLIP16 (pkzip.extraDataLength));
zipoffset = (sizeof (PKZIPHEADER) + size + FLIP16 (pkzip.extraDataLength));
zipchunk = ZIPCHUNK - zipoffset;
/*** Now do it! ***/
do
{
zs.avail_in = zipchunk;
zs.next_in = (Bytef *) & readbuffer[zipoffset];
zs.next_in = (Bytef *) &readbuffer[zipoffset];
/*** Now inflate until input buffer is exhausted ***/
do
{
zs.avail_out = ZIPCHUNK;
zs.next_out = (Bytef *) & out;
zs.next_out = (Bytef *) &out;
res = inflate (&zs, Z_NO_FLUSH);
if (res == Z_MEM_ERROR)

View File

@ -30,6 +30,6 @@
#define _UNZIP_H_
extern int IsZipFile (char *buffer);
int UnZipBuffer (unsigned char *outbuffer, FILE *fd);
int UnZipBuffer (unsigned char *outbuffer, FILE *fd, char *filename);
#endif

View File

@ -542,7 +542,7 @@ int FileSelector(void)
areplay_shutdown();
/* load ROM file from device */
size = LoadFile(cart.rom, selection);
size = LoadFile(cart.rom, selection, fname);
/* exit menu */
GUI_DeleteMenu(m);
@ -557,7 +557,7 @@ int FileSelector(void)
}
/* reinitialize emulation */
reloadrom(size,filelist[selection].filename);
reloadrom(size,fname);
}
return size;

View File

@ -32,6 +32,10 @@
#include <ogc/lwp_threads.h>
#ifdef HW_RVL
#include <ogc/usbmouse.h>
#endif
/* Credits */
extern const u8 Bg_credits_png[];
@ -77,10 +81,16 @@ extern const u8 Button_delete_over_png[];
/* Controller Settings */
extern const u8 Ctrl_4wayplay_png[];
extern const u8 Ctrl_gamepad_png[];
extern const u8 Ctrl_gamepad_md_png[];
extern const u8 Ctrl_gamepad_ms_png[];
extern const u8 Ctrl_justifiers_png[];
extern const u8 Ctrl_menacer_png[];
extern const u8 Ctrl_mouse_png[];
extern const u8 Ctrl_xe_a1p_png[];
extern const u8 Ctrl_activator_png[];
extern const u8 Ctrl_lightphaser_png[];
extern const u8 Ctrl_paddle_png[];
extern const u8 Ctrl_sportspad_png[];
extern const u8 Ctrl_none_png[];
extern const u8 Ctrl_teamplayer_png[];
extern const u8 Ctrl_pad3b_png[];
@ -1011,6 +1021,15 @@ static void soundmenu ()
* System Settings menu
*
****************************************************************************/
static const uint16 vc_table[4][2] =
{
/* NTSC, PAL */
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
{0xEA , 0x102}, /* Mode 5 (224 lines) */
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
{0x106, 0x10A} /* Mode 5 (240 lines) */
};
static void systemmenu ()
{
int ret, quit = 0;
@ -1104,11 +1123,7 @@ static void systemmenu ()
}
/* reinitialize VC max value */
vc_max = 0xEA + 24*vdp_pal;
if (reg[1] & 8)
{
vc_max += (28 - 20*vdp_pal);
}
vc_max = vc_table[(reg[1] >> 2) & 3][vdp_pal];
}
break;
@ -1119,7 +1134,10 @@ static void systemmenu ()
case 2: /*** 68k Address Error ***/
config.addr_error ^= 1;
cart_hw_init ();
if (system_hw != SYSTEM_PBC)
{
md_cart_init ();
}
sprintf (items[2].text, "68k Address Error: %s", config.addr_error ? "ON" : "OFF");
break;
@ -1449,6 +1467,9 @@ static void videomenu ()
sprintf (items[VI_OFFSET+1].text, "Borders: V ONLY");
else
sprintf (items[VI_OFFSET+1].text, "Borders: NONE");
/* update viewport */
bitmap.viewport.x = (config.overscan & 2) * 7;
break;
case VI_OFFSET+2: /*** aspect ratio ***/
@ -1614,7 +1635,7 @@ static void ctrlmenu_raz(void)
{
m->buttons[i+2].data = &button_player_data;
m->buttons[i+2].state |= BUTTON_ACTIVE;
if (cart.jcart && (i > 4))
if ((cart.special & HW_J_CART) && (i > 4))
sprintf(m->items[i+2].comment,"Configure Player %d (J-CART) settings", max + 1);
else
sprintf(m->items[i+2].comment,"Configure Player %d settings", max + 1);
@ -1696,47 +1717,65 @@ static void ctrlmenu(void)
gui_item *items = NULL;
u8 *special = NULL;
u32 exp;
u8 type = 0;
/* System devices */
gui_item items_sys[2][7] =
gui_item items_sys[2][13] =
{
{
{NULL,Ctrl_none_png ,"","Select Port 1 device",110,130,48,72},
{NULL,Ctrl_gamepad_png ,"","Select Port 1 device", 87,117,96,84},
{NULL,Ctrl_gamepad_md_png ,"","Select Port 1 device", 85,117,96,84},
{NULL,Ctrl_mouse_png ,"","Select Port 1 device", 97,113,64,88},
{NULL,Ctrl_menacer_png ,"","Select Port 1 device", 94,113,80,88},
{NULL,Ctrl_justifiers_png ,"","Select Port 1 device", 88,117,80,84},
{NULL,Ctrl_xe_a1p_png ,"","Select Port 1 device", 98,118,72,84},
{NULL,Ctrl_activator_png ,"","Select Port 1 device", 94,121,72,80},
{NULL,Ctrl_gamepad_ms_png ,"","Select Port 1 device", 91,125,84,76},
{NULL,Ctrl_lightphaser_png,"","Select Port 1 device", 89,109,88,92},
{NULL,Ctrl_paddle_png ,"","Select Port 1 device", 86,117,96,84},
{NULL,Ctrl_sportspad_png ,"","Select Port 1 device", 95,117,76,84},
{NULL,Ctrl_teamplayer_png ,"","Select Port 1 device", 94,109,80,92},
{NULL,Ctrl_4wayplay_png ,"","Select Port 1 device", 98,110,72,92}
},
{
{NULL,Ctrl_none_png ,"","Select Port 2 device",110,300,48,72},
{NULL,Ctrl_gamepad_png ,"","Select Port 2 device", 87,287,96,84},
{NULL,Ctrl_gamepad_md_png ,"","Select Port 2 device", 85,287,96,84},
{NULL,Ctrl_mouse_png ,"","Select Port 2 device", 97,283,64,88},
{NULL,Ctrl_menacer_png ,"","Select Port 2 device", 94,283,80,88},
{NULL,Ctrl_justifiers_png ,"","Select Port 2 device", 88,287,80,84},
{NULL,Ctrl_xe_a1p_png ,"","Select Port 2 device", 98,288,72,84},
{NULL,Ctrl_activator_png ,"","Select Port 2 device", 94,291,72,80},
{NULL,Ctrl_gamepad_ms_png ,"","Select Port 2 device", 91,295,84,76},
{NULL,Ctrl_lightphaser_png,"","Select Port 2 device", 89,279,88,92},
{NULL,Ctrl_paddle_png ,"","Select Port 2 device", 86,287,96,84},
{NULL,Ctrl_sportspad_png ,"","Select Port 2 device", 95,287,76,84},
{NULL,Ctrl_teamplayer_png ,"","Select Port 2 device", 94,279,80,92},
{NULL,Ctrl_4wayplay_png ,"","Select Port 2 device", 98,280,72,92}
}
};
/* Player Configuration special items */
gui_item items_special[3][2] =
/* Specific controller options */
gui_item items_special[4][2] =
{
{
/* Gamepad options */
/* Gamepad option */
{NULL,Ctrl_pad3b_png,"Pad\nType","Use 3-buttons Pad",528,180,44,28},
{NULL,Ctrl_pad6b_png,"Pad\nType","Use 6-buttons Pad",528,180,44,28}
},
{
/* Mouse options */
{NULL,ctrl_option_off_png,"Invert\nMouse","Enable/Disable Mouse Y-Axis inversion",534,180,24,24},
{NULL,ctrl_option_on_png ,"Invert\nMouse","Enable/Disable Mouse Y-Axis inversion",534,180,24,24},
/* Mouse option */
{NULL,ctrl_option_off_png,"Invert\nMouse","Enable/Disable Y-Axis inversion",534,180,24,24},
{NULL,ctrl_option_on_png ,"Invert\nMouse","Enable/Disable Y-Axis inversion",534,180,24,24},
},
{
/* Gun options */
/* Gun option */
{NULL,ctrl_option_off_png,"Show\nCursor","Enable/Disable Lightgun cursor",534,180,24,24},
{NULL,ctrl_option_on_png ,"Show\nCursor","Enable/Disable Lightgun cursor",534,180,24,24},
},
{
/* no option */
{NULL,NULL,"No Option","",436,180,160,52},
{NULL,NULL,"","",0,0,0,0},
}
};
@ -1768,13 +1807,10 @@ static void ctrlmenu(void)
button_player_none_data.texture[0] = gxTextureOpenPNG(button_player_none_data.image[0],0);
/* initialize custom images */
items_sys[1][0].texture = items_sys[0][0].texture = gxTextureOpenPNG(items_sys[0][0].data,0);
items_sys[1][1].texture = items_sys[0][1].texture = gxTextureOpenPNG(items_sys[0][1].data,0);
items_sys[1][2].texture = items_sys[0][2].texture = gxTextureOpenPNG(items_sys[0][2].data,0);
items_sys[1][3].texture = items_sys[0][3].texture = gxTextureOpenPNG(items_sys[0][3].data,0);
items_sys[1][4].texture = items_sys[0][4].texture = gxTextureOpenPNG(items_sys[0][4].data,0);
items_sys[1][5].texture = items_sys[0][5].texture = gxTextureOpenPNG(items_sys[0][5].data,0);
items_sys[1][6].texture = items_sys[0][6].texture = gxTextureOpenPNG(items_sys[0][6].data,0);
for (i=0; i<13; i++)
{
items_sys[1][i].texture = items_sys[0][i].texture = gxTextureOpenPNG(items_sys[0][i].data,0);
}
items_special[0][0].texture = gxTextureOpenPNG(items_special[0][0].data,0);
items_special[0][1].texture = gxTextureOpenPNG(items_special[0][1].data,0);
items_special[2][0].texture = items_special[1][0].texture = gxTextureOpenPNG(items_special[1][0].data,0);
@ -1811,16 +1847,8 @@ static void ctrlmenu(void)
{
case 0: /* update port 1 system */
{
if (input.system[0] == SYSTEM_MOUSE)
{
/* lightguns are never used on Port 1 */
input.system[0] += 3;
}
else
{
/* next connected device */
input.system[0]++;
}
/* next connected device */
input.system[0]++;
/* allow only one connected mouse */
if ((input.system[0] == SYSTEM_MOUSE) && (input.system[1] == SYSTEM_MOUSE))
@ -1828,6 +1856,18 @@ static void ctrlmenu(void)
input.system[0] += 3;
}
/* Menacer & Justifiers on Port B only */
if (input.system[0] == SYSTEM_MENACER)
{
input.system[0] += 2;
}
/* allow only one gun type */
if ((input.system[0] == SYSTEM_LIGHTPHASER) && ((input.system[1] == SYSTEM_MENACER) || (input.system[1] == SYSTEM_JUSTIFIER)))
{
input.system[0] ++;
}
/* 4-wayplay uses both ports */
if (input.system[0] == SYSTEM_WAYPLAY)
{
@ -1838,7 +1878,7 @@ static void ctrlmenu(void)
if (input.system[0] > SYSTEM_WAYPLAY)
{
input.system[0] = NO_SYSTEM;
input.system[1] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_MD_GAMEPAD;
}
/* reset I/O ports */
@ -1886,7 +1926,7 @@ static void ctrlmenu(void)
case 1: /* update port 2 system */
{
/* J-CART uses fixed configuration */
if (cart.jcart) break;
if (cart.special & HW_J_CART) break;
/* next connected device */
input.system[1] ++;
@ -1897,6 +1937,24 @@ static void ctrlmenu(void)
input.system[1] ++;
}
/* allow only one gun type */
if ((input.system[0] == SYSTEM_LIGHTPHASER) && (input.system[1] == SYSTEM_MENACER))
{
input.system[1] += 3;
}
/* allow only one gun type */
if ((input.system[0] == SYSTEM_LIGHTPHASER) && (input.system[1] == SYSTEM_JUSTIFIER))
{
input.system[1] += 2;
}
/* XE-1AP on port A only */
if (input.system[1] == SYSTEM_XE_A1P)
{
input.system[1] ++;
}
/* 4-wayplay uses both ports */
if (input.system[1] == SYSTEM_WAYPLAY)
{
@ -1907,7 +1965,7 @@ static void ctrlmenu(void)
if (input.system[1] > SYSTEM_WAYPLAY)
{
input.system[1] = NO_SYSTEM;
input.system[0] = SYSTEM_GAMEPAD;
input.system[0] = SYSTEM_MD_GAMEPAD;
}
/* reset I/O ports */
@ -2010,24 +2068,61 @@ static void ctrlmenu(void)
m->buttons[9].shift[3] = 1;
}
/* emulated device type */
type = input.dev[m->selected - 2];
/* retrieve current player informations */
if (input.dev[m->selected-2] == DEVICE_LIGHTGUN)
switch (type)
{
items = items_special[2];
special = &config.gun_cursor[m->selected & 1];
case DEVICE_PAD3B:
case DEVICE_PAD6B:
{
items = items_special[0];
special = &config.input[player].padtype;
break;
}
case DEVICE_MOUSE:
{
items = items_special[1];
special = &config.invert_mouse;
break;
}
case DEVICE_LIGHTGUN:
{
items = items_special[2];
if ((input.system[1] == SYSTEM_MENACER) || (input.system[1] == SYSTEM_JUSTIFIER))
{
/* Menacer & Justifiers affected to devices 4 & 5 */
special = &config.gun_cursor[m->selected & 1];
}
else
{
/* Lightphasers affected to devices 0 & 4 */
special = &config.gun_cursor[m->selected >> 2];
}
break;
}
default:
{
items = items_special[3];
special = NULL;
break;
}
}
else if (input.dev[m->selected-2] == DEVICE_MOUSE)
if (special)
{
items = items_special[1];
special = &config.invert_mouse;
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
}
else
{
items = items_special[0];
special = &config.input[player].padtype;
memcpy(&m->items[10],&items[0],sizeof(gui_item));
}
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
memcpy(&m->items[11],&items_device[config.input[player].device + 1],sizeof(gui_item));
/* slide in configuration window */
@ -2037,8 +2132,18 @@ static void ctrlmenu(void)
m->selected = 10;
GUI_DrawMenuFX(m, 20, 0);
/* some devices require analog sticks */
if ((type == DEVICE_XE_A1P) && ((config.input[player].device == -1) || (config.input[player].device == 1)))
{
GUI_WaitPrompt("Warning","One Analog Stick required !");
}
else if ((type == DEVICE_ACTIVATOR) && ((config.input[player].device != 0) && (config.input[player].device != 3)))
{
GUI_WaitPrompt("Warning","Two Analog Sticks required !");
}
/* update title */
if (cart.jcart && (player > 1))
if ((cart.special & HW_J_CART) && (player > 1))
{
sprintf(m->title,"Controller Settings (Player %d) (J-CART)",player+1);
}
@ -2051,20 +2156,25 @@ static void ctrlmenu(void)
case 10: /* specific option */
{
if (special == &config.input[player].padtype)
{
if (config.input[player].device == 1) break;
config.input[player].padtype ^= 1;
input_init();
input_reset();
}
else
if (special)
{
/* switch option */
*special ^= 1;
}
/* update menu items */
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
/* specific case: controller type */
if (type < 2)
{
/* re-initialize emulated device */
input_init();
input_reset();
/* update emulated device type */
type = *special;
}
/* update menu items */
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
}
break;
}
@ -2205,8 +2315,11 @@ static void ctrlmenu(void)
/* force 3-buttons gamepad when using Wiimote */
if (config.input[player].device == 1)
{
config.input[player].padtype = DEVICE_3BUTTON;
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
config.input[player].padtype = DEVICE_PAD3B;
if (special)
{
memcpy(&m->items[10],&items[*special],sizeof(gui_item));
}
}
#endif
@ -2218,30 +2331,12 @@ static void ctrlmenu(void)
case 12: /* Controller Keys Configuration */
{
if (config.input[player].device < 0) break;
GUI_MsgBoxOpen("Keys Configuration", "",0);
if (config.input[player].padtype == DEVICE_6BUTTON)
if (config.input[player].device >= 0)
{
/* 6-buttons gamepad */
if (config.input[player].device == 0)
{
/* Gamecube PAD: 6-buttons w/o MODE */
gx_input_Config(config.input[player].port, config.input[player].device, 7);
}
else
{
gx_input_Config(config.input[player].port, config.input[player].device, 8);
}
GUI_MsgBoxOpen("Keys Configuration", "",0);
gx_input_Config(config.input[player].port, config.input[player].device, type);
GUI_MsgBoxClose();
}
else
{
/* 3-Buttons gamepad, mouse, lightgun */
gx_input_Config(config.input[player].port, config.input[player].device, 4);
}
GUI_MsgBoxClose();
break;
}
}
@ -2364,13 +2459,10 @@ static void ctrlmenu(void)
gxTextureClose(&button_player_none_data.texture[0]);
/* delete custom images */
gxTextureClose(&items_sys[0][0].texture);
gxTextureClose(&items_sys[0][1].texture);
gxTextureClose(&items_sys[0][2].texture);
gxTextureClose(&items_sys[0][3].texture);
gxTextureClose(&items_sys[0][4].texture);
gxTextureClose(&items_sys[0][5].texture);
gxTextureClose(&items_sys[0][6].texture);
for (i=0; i<13; i++)
{
gxTextureClose(&items_sys[0][i].texture);
}
gxTextureClose(&items_special[0][0].texture);
gxTextureClose(&items_special[0][1].texture);
gxTextureClose(&items_special[1][0].texture);
@ -3284,6 +3376,16 @@ void menu_execute(void)
#ifdef HW_RVL
while (WPAD_ButtonsHeld(0)) WPAD_ScanPads();
gxTextureClose(&w_pointer);
/* USB Mouse support */
if ((input.system[0] == SYSTEM_MOUSE) || (input.system[1] == SYSTEM_MOUSE))
{
MOUSE_Init();
}
else
{
MOUSE_Deinit();
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@ -31,7 +31,7 @@
#define MAX_INPUTS 8
#endif
/* Genesis controller keys */
/* Configurable keys */
#define MAX_KEYS 8
/* Key configuration structure */
@ -46,7 +46,7 @@ typedef struct
extern void gx_input_Init(void);
extern int gx_input_FindDevices(void);
extern void gx_input_SetDefault(void);
extern void gx_input_Config(u8 num, u8 type, u8 max_keys);
extern void gx_input_Config(u8 chan, u8 device, u8 type);
extern void gx_input_UpdateEmu(void);
extern void gx_input_UpdateMenu(u32 cnt);

View File

@ -477,7 +477,7 @@ static void gxSetAspectRatio(int *xscale, int *yscale)
if (config.overscan & 2)
{
/* max visible range is ~712 pixels, not 720 */
*xscale = 356;
*xscale = (reg[12] & 1) ? 356 : 360;
}
else
{
@ -1400,11 +1400,11 @@ void gx_video_Start(void)
}
/* lightgun textures */
if (config.gun_cursor[0] && (input.dev[4] == DEVICE_LIGHTGUN))
if (config.gun_cursor[0] && ((input.system[1] == SYSTEM_MENACER) || (input.system[1] == SYSTEM_JUSTIFIER) || (input.system[0] == SYSTEM_LIGHTPHASER)))
{
crosshair[0] = gxTextureOpenPNG(Crosshair_p1_png,0);
}
if (config.gun_cursor[1] && (input.dev[5] == DEVICE_LIGHTGUN))
if (config.gun_cursor[1] && ((input.system[1] == SYSTEM_JUSTIFIER) || (input.system[1] == SYSTEM_LIGHTPHASER)))
{
crosshair[1] = gxTextureOpenPNG(Crosshair_p2_png,0);
}
@ -1486,14 +1486,30 @@ void gx_video_Update(void)
/* render textured quad */
draw_square();
/* Lightgun marks */
/* Lightgun # 1 screen mark */
if (crosshair[0])
{
gxDrawCrosshair(crosshair[0], input.analog[0][0],input.analog[0][1]);
if (input.system[0] == SYSTEM_LIGHTPHASER)
{
gxDrawCrosshair(crosshair[0], input.analog[0][0],input.analog[0][1]);
}
else
{
gxDrawCrosshair(crosshair[0], input.analog[4][0],input.analog[4][1]);
}
}
/* Lightgun # 2 screen mark */
if (crosshair[1])
{
gxDrawCrosshair(crosshair[1], input.analog[1][0],input.analog[1][1]);
if (input.system[1] == SYSTEM_LIGHTPHASER)
{
gxDrawCrosshair(crosshair[1], input.analog[1][0],input.analog[1][1]);
}
else
{
gxDrawCrosshair(crosshair[1], input.analog[5][0],input.analog[5][1]);
}
}
/* swap XFB */

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

@ -4,7 +4,7 @@
* Genesis Plus GX
*
* Softdev (2006)
* Eke-Eke (2007,2008,2009)
* Eke-Eke (2007-2010)
*
* 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
@ -53,13 +53,21 @@ u32 ConfigRequested = 1;
/****************************************************************************
* Power Button callback
***************************************************************************/
static void Power_Off(void)
static void PowerOff_cb(void)
{
Shutdown = 1;
ConfigRequested = 1;
}
#endif
/****************************************************************************
* Reset Button callback
***************************************************************************/
static void Reset_cb(void)
{
gen_reset(0);
}
/***************************************************************************
* Genesis Plus Virtual Machine
*
@ -202,24 +210,43 @@ void reloadrom (int size, char *name)
/* hot-swap previous & current cartridge */
bool hotswap = config.hot_swap && cart.romsize;
/* load ROM file */
/* ROM size */
cart.romsize = size;
/* load ROM file */
load_rom(name);
/* ROM filename without extension*/
sprintf(rom_filename,"%s",name);
rom_filename[strlen(rom_filename) - 4] = 0;
if (hotswap)
{
cart_hw_init();
cart_hw_reset(1);
if (system_hw == SYSTEM_PBC)
{
sms_cart_init();
sms_cart_reset();
}
else
{
md_cart_init();
md_cart_reset(1);
}
}
else
{
/* initialize audio back-end */
/* 60hz video mode requires synchronization with Video Interrupt. */
/* Framerate is 59.94 fps in interlaced/progressive modes, ~59.825 fps in non-interlaced mode */
/* initialize audio emulation */
/* To prevent any sound skipping, sound chips must run at the exact same speed as the rest of emulation (see sound.c) */
/* In 60hz video modes with NTSC emulation, we need perfect synchronization with video hardware interrupt (VSYNC) */
/* Wii & GC framerate has been measured to be exactly 59.94 fps in 240i/480i/480p video modes, ~59.825 fps in 240p */
/* In other modes, emulation is synchronized with audio hardware instead and we use default framerates (50Hz for PAL, 60Hz for NTSC). */
float framerate = vdp_pal ? 50.0 : ((config.tv_mode == 1) ? 60.0 : (config.render ? 59.94 : (1000000.0/16715.0)));
/* output samplerate has been measured to be ~48044 samples/sec on GC, 48000 samples/sec on Wii */
audio_init(SAMPLERATE_48KHZ, framerate);
/* System Power ON */
/* system power ON */
system_init ();
system_reset ();
}
@ -273,6 +300,8 @@ u32 frameticker = 0;
int main (int argc, char *argv[])
{
char pathname[MAXPATHLEN];
#ifdef HW_RVL
/* initialize DI interface */
DI_UseCache(0);
@ -305,7 +334,6 @@ int main (int argc, char *argv[])
if (fatMounted)
{
/* base directory */
char pathname[MAXPATHLEN];
sprintf (pathname, DEFAULT_PATH);
DIR_ITER *dir = diropen(pathname);
if (dir) dirclose(dir);
@ -356,10 +384,10 @@ int main (int argc, char *argv[])
SILENT = 1;
if (OpenDirectory(TYPE_RECENT))
{
int size = LoadFile(cart.rom,0);
int size = LoadFile(cart.rom,0,pathname);
if (size)
{
reloadrom(size,filelist[0].filename);
reloadrom(size,pathname);
gx_video_Start();
gx_audio_Start();
frameticker = 1;
@ -371,9 +399,12 @@ int main (int argc, char *argv[])
#ifdef HW_RVL
/* power button callback */
SYS_SetPowerCallback(Power_Off);
SYS_SetPowerCallback(PowerOff_cb);
#endif
/* reset button callback */
SYS_SetResetCallback(Reset_cb);
/* main emulation loop */
run_emulation();

View File

@ -2,8 +2,6 @@
#ifndef _OSD_H_
#define _OSD_H_
#define NGC 1
#include <gccore.h>
#include <ogcsys.h>
#include <stdio.h>
@ -33,9 +31,9 @@
#define SK_UPMEM "/genplus/sk2chip.bin"
#ifdef HW_RVL
#define VERSION "Genesis Plus GX 1.4.1 (WII)"
#define VERSION "Genesis Plus GX 1.5.0 (WII)"
#else
#define VERSION "Genesis Plus GX 1.4.1 (GCN)"
#define VERSION "Genesis Plus GX 1.5.0 (GCN)"
#endif
#define osd_input_Update() gx_input_UpdateEmu()

View File

@ -125,7 +125,7 @@
/***************************************************************/
/* */
/* H-counter timings in H40 & H32 modes (starts from HINT) */
/* H-counter timings in H32 & H40 modes (starts from HINT) */
/* */
/* There are exactly 3420 Master Clock counts per raster line. */
/* */
@ -138,6 +138,245 @@
/* */
/***************************************************************/
static const uint8 cycle2hc32[3420] =
{
/* end of active display (16 pixels -> 160 Mcycles) , H interrupt triggered, Vcounter increment */
0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c,
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
/* right border (14 pixels -> 140 Mcycles) */
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
/* right blanking (9 pixels -> 90 Mcycles) , VDP status HBLANK flag set */
0xe9, 0xe9, 0xe9, 0xe9,
0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
0xea, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec,
0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed,
0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
/* horizontal sync (26 pixels -> 260 Mcycles) */
0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
/* left blanking (24 pixels -> 240 Mcycles) */
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
/* V interrupt triggered (MD mode) */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
/* left border (13 pixels -> 130 Mcycles) , VDP status HBLANK flag cleared */
0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
/* remaining active display (240 pixels -> 2400 Mcycles) */
0x0d, 0x0d, 0x0d, 0x0d,
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d,
0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35,
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e,
0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43,
0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46,
0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49,
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b,
0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d,
0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d,
0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x51,
0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
0x56, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59,
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d,
0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d,
0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
0x62, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x69,
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b,
0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d,
0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e,
0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71,
0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75,
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c,
0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d,
0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
};
static const uint8 cycle2hc40[3420] =
{
/* end of active display (16 pixels -> 128 Mcycles) , HINT triggered , Vcounter increment */
@ -372,249 +611,7 @@ static const uint8 cycle2hc40[3420] =
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa2, 0xa2, 0xa2, 0xa2,
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa3, 0xa3, 0xa3, 0xa3,
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa4, 0xa4, 0xa4, 0xa4,
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
};
static const uint8 cycle2hc32[3420] =
{
/* end of active display (16 pixels -> 160 Mcycles) , HINT triggered ? , Vcounter increment */
0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
0x85, 0x85, 0x85, 0x85, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x88, 0x88, 0x88, 0x88,
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
0x89, 0x89, 0x89, 0x89, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8c, 0x8c, 0x8c, 0x8c,
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
/* right border (14 pixels -> 140 Mcycles) */
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
0x8d, 0x8d, 0x8d, 0x8d, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x90, 0x90, 0x90, 0x90,
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90,
0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
0x91, 0x91, 0x91, 0x91, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93, 0x93,
/* right blanking (9 pixels -> 90 Mcycles) , VDP status HBLANK flag set */
0xe9, 0xe9, 0xe9, 0xe9,
0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9, 0xe9,
0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea, 0xea,
0xea, 0xea, 0xea, 0xea, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb,
0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xeb, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec,
0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xec, 0xed, 0xed, 0xed, 0xed,
0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
/* horizontal sync (26 pixels -> 260 Mcycles) */
0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed, 0xed,
0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee, 0xee,
0xee, 0xee, 0xee, 0xee, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, 0xf1, 0xf1, 0xf1,
0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1, 0xf1,
0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
0xf2, 0xf2, 0xf2, 0xf2, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3,
0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf3, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4,
0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf4, 0xf5, 0xf5, 0xf5, 0xf5,
0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5, 0xf5,
0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6, 0xf6,
0xf6, 0xf6, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7,
0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8,
0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, 0xf9, 0xf9, 0xf9,
0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
/* left blanking (24 pixels -> 240 Mcycles) */
0xfa, 0xfa, 0xfa, 0xfa, 0xfa, 0xfa,
0xfa, 0xfa, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb,
0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc,
0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd,
0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd,
0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe,
0xfe, 0xfe, 0xfe, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
0x01, 0x01, 0x01, 0x01,
/* Vertical Interrupt triggered ? */
0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
/* left border (13 pixels -> 130 Mcycles) , VDP status HBLANK flag cleared */
0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09,
0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
0x0a, 0x0a, 0x0a, 0x0a, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c,
/* remaining active display (240 pixels -> 2400 Mcycles) */
0x0d, 0x0d, 0x0d, 0x0d,
0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d,
0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e, 0x0e,
0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f,
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11,
0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12, 0x12,
0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13,
0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14,
0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15,
0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16,
0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17,
0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x17, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19,
0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x1a,
0x1a, 0x1a, 0x1a, 0x1a, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b,
0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c,
0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1d, 0x1d, 0x1d, 0x1d,
0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d, 0x1d,
0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f,
0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x21, 0x21, 0x21, 0x21,
0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21, 0x21,
0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22,
0x22, 0x22, 0x22, 0x22, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x23, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24,
0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x24, 0x25, 0x25, 0x25, 0x25,
0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26,
0x26, 0x26, 0x26, 0x26, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27,
0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x27, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x29, 0x29, 0x29, 0x29,
0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29, 0x29,
0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a, 0x2a,
0x2a, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c,
0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2c, 0x2d, 0x2d, 0x2d, 0x2d,
0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d, 0x2d,
0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e, 0x2e,
0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x31, 0x31, 0x31, 0x31,
0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32, 0x32,
0x32, 0x32, 0x32, 0x32, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34,
0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x34, 0x35, 0x35, 0x35, 0x35,
0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35, 0x35,
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
0x36, 0x36, 0x36, 0x36, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37,
0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x37, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38,
0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x39, 0x39, 0x39, 0x39,
0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39, 0x39,
0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a, 0x3a,
0x3a, 0x3a, 0x3a, 0x3a, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b,
0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3b, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c,
0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3d, 0x3d, 0x3d, 0x3d,
0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d, 0x3d,
0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e,
0x3e, 0x3e, 0x3e, 0x3e, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f,
0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x41, 0x41, 0x41,
0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41,
0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42,
0x42, 0x42, 0x42, 0x42, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43,
0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x43, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44,
0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x45, 0x45, 0x45, 0x45,
0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46, 0x46,
0x46, 0x46, 0x46, 0x46, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48,
0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x48, 0x49, 0x49, 0x49, 0x49,
0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49, 0x49,
0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a, 0x4a,
0x4a, 0x4a, 0x4a, 0x4a, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b,
0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4b, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c,
0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4d, 0x4d, 0x4d, 0x4d,
0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d, 0x4d,
0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e, 0x4e,
0x4e, 0x4e, 0x4e, 0x4e, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50,
0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x50, 0x51, 0x51, 0x51, 0x51,
0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51, 0x51,
0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52, 0x52,
0x52, 0x52, 0x52, 0x52, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53,
0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x53, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54,
0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x54, 0x55, 0x55, 0x55, 0x55,
0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56, 0x56,
0x56, 0x56, 0x56, 0x56, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57,
0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x57, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58,
0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x59, 0x59, 0x59, 0x59,
0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59, 0x59,
0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a, 0x5a,
0x5a, 0x5a, 0x5a, 0x5a, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b,
0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5b, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c,
0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5c, 0x5d, 0x5d, 0x5d, 0x5d,
0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d, 0x5d,
0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e, 0x5e,
0x5e, 0x5e, 0x5e, 0x5e, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f,
0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60,
0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x61, 0x61, 0x61, 0x61,
0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61,
0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62, 0x62,
0x62, 0x62, 0x62, 0x62, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63,
0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64,
0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x64, 0x65, 0x65, 0x65, 0x65,
0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66,
0x66, 0x66, 0x66, 0x66, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67,
0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x67, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68,
0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x68, 0x69, 0x69, 0x69, 0x69,
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a, 0x6a,
0x6a, 0x6a, 0x6a, 0x6a, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b,
0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c,
0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6d, 0x6d, 0x6d, 0x6d,
0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d, 0x6d,
0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e,
0x6e, 0x6e, 0x6e, 0x6e, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70,
0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x71, 0x71, 0x71, 0x71,
0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71, 0x71,
0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72, 0x72,
0x72, 0x72, 0x72, 0x72, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73,
0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x73, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74,
0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x74, 0x75, 0x75, 0x75, 0x75,
0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75, 0x75,
0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76, 0x76,
0x76, 0x76, 0x76, 0x76, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77,
0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78,
0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x79, 0x79, 0x79, 0x79,
0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79,
0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a, 0x7a,
0x7a, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b,
0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c,
0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7d, 0x7d, 0x7d, 0x7d,
0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d, 0x7d,
0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e, 0x7e,
0x7e, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f,
0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, 0x81, 0x81, 0x81,
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
0x82, 0x82, 0x82, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x85, 0x85, 0x85, 0x85,
0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
};
static const uint8 *hctab;
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4};
#endif /* _HVC_H_ */

121
source/input_hw/activator.c Normal file
View File

@ -0,0 +1,121 @@
/***************************************************************************************
* Genesis Plus
* Sega Activator support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
static struct
{
uint8 State;
uint8 Counter;
} activator[2];
void activator_reset(int index)
{
activator[index].State = 0x40;
activator[index].Counter = 0;
}
static inline unsigned char activator_read(int port)
{
/* IR sensors 1-16 data (active low) */
uint16 data = ~input.pad[port];
/* Device index */
port = port >> 2;
/* D1 = D0 (data is ready) */
uint8 temp = (activator[port].State & 0x01) << 1;
switch (activator[port].Counter)
{
case 0: /* x x x x 0 1 0 0 */
temp |= 0x04;
break;
case 1: /* x x l1 l2 l3 l4 1 1 */
temp |= ((data << 2) & 0x3C);
break;
case 2: /* x x l5 l6 l7 l8 0 0 */
temp |= ((data >> 2) & 0x3C);
break;
case 3: /* x x h1 h2 h3 h4 1 1 */
temp |= ((data >> 6) & 0x3C);
break;
case 4: /* x x h5 h6 h7 h8 0 0 */
temp |= ((data >> 10) & 0x3C);
break;
}
return temp;
}
static inline void activator_write(int index, unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (activator[index].State & ~mask) | (data & mask);
/* TH transitions */
if ((activator[index].State ^ data) & 0x40)
{
/* reset sequence cycle */
activator[index].Counter = 0;
}
else
{
/* D0 transitions */
if ((activator[index].State ^ data) & 0x01)
{
/* increment sequence cycle */
if (activator[index].Counter < 4)
{
activator[index].Counter++;
}
}
}
/* update internal state */
activator[index].State = data;
}
unsigned char activator_1_read(void)
{
return activator_read(0);
}
unsigned char activator_2_read(void)
{
return activator_read(4);
}
void activator_1_write(unsigned char data, unsigned char mask)
{
activator_write(0, data, mask);
}
void activator_2_write(unsigned char data, unsigned char mask)
{
activator_write(1, data, mask);
}

View File

@ -0,0 +1,33 @@
/***************************************************************************************
* Genesis Plus
* Sega Activator support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _ACTIVATOR_H_
#define _ACTIVATOR_H_
/* Function prototypes */
extern void activator_reset(int index);
extern unsigned char activator_1_read(void);
extern unsigned char activator_2_read(void);
extern void activator_1_write(unsigned char data, unsigned char mask);
extern void activator_2_write(unsigned char data, unsigned char mask);
#endif

225
source/input_hw/gamepad.c Normal file
View File

@ -0,0 +1,225 @@
/***************************************************************************************
* Genesis Plus
* 3-Buttons & 6-Buttons pad support (incl. 4-WayPlay & J-Cart handlers)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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 "shared.h"
#include "gamepad.h"
static struct
{
uint8 State;
uint8 Counter;
uint8 Timeout;
} gamepad[MAX_DEVICES];
static uint8 pad_index;
void gamepad_reset(int port)
{
/* default state (Gouketsuji Ichizoku / Power Instinct, Samurai Spirits / Samurai Shodown) */
gamepad[port].State = 0x40;
gamepad[port].Counter = 0;
gamepad[port].Timeout = 0;
/* reset pad index (4-WayPlay) */
pad_index = 0;
}
void gamepad_refresh(int port)
{
/* 6-buttons pad */
if (gamepad[port].Timeout++ > 25)
{
gamepad[port].Counter = 0;
gamepad[port].Timeout = 0;
}
}
static inline unsigned char gamepad_read(int port)
{
/* bit 7 is latched, returns current TH state */
unsigned int data = (gamepad[port].State & 0x40) | 0x3F;
/* pad value */
unsigned int val = input.pad[port];
/* get current step (TH state) */
unsigned int step = (gamepad[port].Counter & 6) | ((data >> 6) & 1);
switch (step)
{
case 1: /*** First High ***/
case 3: /*** Second High ***/
case 5: /*** Third High ***/
{
/* TH = 1 : ?1CBRLDU */
data &= ~(val & 0x3F);
break;
}
case 0: /*** First low ***/
case 2: /*** Second low ***/
{
/* TH = 0 : ?0SA00DU */
data &= ~(val & 0x03);
data &= ~((val >> 2) & 0x30);
data &= ~0x0C;
break;
}
/* 6buttons specific (taken from gen-hw.txt) */
/* A 6-button gamepad allows the extra buttons to be read based on how */
/* many times TH is switched from 1 to 0 (and not 0 to 1). Observe the */
/* following sequence */
/*
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA00DU 3-button pad return value
TH = 1 : ?1CBRLDU 3-button pad return value
TH = 0 : ?0SA0000 D3-0 are forced to '0'
TH = 1 : ?1CBMXYZ Extra buttons returned in D3-0
TH = 0 : ?0SA1111 D3-0 are forced to '1'
*/
case 4: /*** Third Low ***/
{
/* TH = 0 : ?0SA0000 D3-0 are forced to '0'*/
data &= ~((val >> 2) & 0x30);
data &= ~0x0F;
break;
}
case 6: /*** Fourth Low ***/
{
/* TH = 0 : ?0SA1111 D3-0 are forced to '1'*/
data &= ~((val >> 2) & 0x30);
break;
}
case 7: /*** Fourth High ***/
{
/* TH = 1 : ?1CBMXYZ Extra buttons returned in D3-0*/
data &= ~(val & 0x30);
data &= ~((val >> 8) & 0x0F);
break;
}
}
return data;
}
static inline void gamepad_write(int port, unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (gamepad[port].State & ~mask) | (data & mask);
if (input.dev[port] == DEVICE_PAD6B)
{
/* check TH transitions */
if ((gamepad[port].State ^ data) & 0x40)
{
gamepad[port].Counter++;
gamepad[port].Timeout = 0;
}
}
/* update internal state */
gamepad[port].State = data;
}
/*--------------------------------------------------------------------------*/
/* Default ports handlers */
/*--------------------------------------------------------------------------*/
unsigned char gamepad_1_read(void)
{
return gamepad_read(0);
}
unsigned char gamepad_2_read(void)
{
return gamepad_read(4);
}
void gamepad_1_write(unsigned char data, unsigned char mask)
{
gamepad_write(0, data, mask);
}
void gamepad_2_write(unsigned char data, unsigned char mask)
{
gamepad_write(4, data, mask);
}
/*--------------------------------------------------------------------------*/
/* 4-WayPlay ports handler */
/*--------------------------------------------------------------------------*/
unsigned char wayplay_1_read(void)
{
if (pad_index < 4)
{
return gamepad_read(pad_index);
}
/* multitap detection */
return 0x70;
}
unsigned char wayplay_2_read(void)
{
return 0x7F;
}
void wayplay_1_write(unsigned char data, unsigned char mask)
{
if (pad_index < 4)
{
gamepad_write(pad_index, data, mask);
}
}
void wayplay_2_write(unsigned char data, unsigned char mask)
{
if ((mask & 0x70) == 0x70)
{
pad_index = (data & 0x70) >> 4;
}
}
/*--------------------------------------------------------------------------*/
/* J-Cart memory handlers */
/*--------------------------------------------------------------------------*/
unsigned int jcart_read(unsigned int address)
{
/* TH2 output read is fixed to zero (fixes Micro Machines 2) */
return ((gamepad_read(5) & 0x7F) | ((gamepad_read(6) & 0x3F) << 8));
}
void jcart_write(unsigned int address, unsigned int data)
{
gamepad_write(5, (data & 1) << 6, 0x40);
gamepad_write(6, (data & 1) << 6, 0x40);
return;
}

41
source/input_hw/gamepad.h Normal file
View File

@ -0,0 +1,41 @@
/***************************************************************************************
* Genesis Plus
* 3-Buttons & 6-Buttons pad support (incl. 4-WayPlay & J-Cart handlers)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
*
****************************************************************************************/
#ifndef _GAMEPAD_H_
#define _GAMEPAD_H_
/* Function prototypes */
extern void gamepad_reset(int port);
extern void gamepad_refresh(int port);
extern unsigned char gamepad_1_read(void);
extern unsigned char gamepad_2_read(void);
extern void gamepad_1_write(unsigned char data, unsigned char mask);
extern void gamepad_2_write(unsigned char data, unsigned char mask);
extern unsigned char wayplay_1_read(void);
extern unsigned char wayplay_2_read(void);
extern void wayplay_1_write(unsigned char data, unsigned char mask);
extern void wayplay_2_write(unsigned char data, unsigned char mask);
extern unsigned int jcart_read(unsigned int address);
extern void jcart_write(unsigned int address, unsigned int data);
#endif

338
source/input_hw/input.c Normal file
View File

@ -0,0 +1,338 @@
/***************************************************************************************
* Genesis Plus
* Input peripherals support
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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 "shared.h"
#include "gamepad.h"
#include "lightgun.h"
#include "mouse.h"
#include "activator.h"
#include "xe_a1p.h"
#include "teamplayer.h"
#include "paddle.h"
#include "sportspad.h"
t_input input;
int old_system[2] = {-1,-1};
void input_init(void)
{
int i;
int player = 0;
for (i=0; i<MAX_DEVICES; i++)
{
input.dev[i] = NO_DEVICE;
input.pad[i] = 0;
}
/* PICO tablet & pen */
if (system_hw == SYSTEM_PICO)
{
input.dev[0] = DEVICE_TABLET;
return;
}
switch (input.system[0])
{
case SYSTEM_MS_GAMEPAD:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_PAD2B;
player++;
break;
}
case SYSTEM_MD_GAMEPAD:
{
if (player == MAX_INPUTS) return;
input.dev[0] = config.input[player].padtype;
player++;
break;
}
case SYSTEM_MOUSE:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_MOUSE;
player++;
break;
}
case SYSTEM_ACTIVATOR:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_ACTIVATOR;
player++;
break;
}
case SYSTEM_XE_A1P:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_XE_A1P;
player++;
break;
}
case SYSTEM_WAYPLAY:
{
for (i=0; i< 4; i++)
{
if (player == MAX_INPUTS) return;
input.dev[i] = config.input[player].padtype;
player++;
}
break;
}
case SYSTEM_TEAMPLAYER:
{
for (i=0; i<4; i++)
{
if (player == MAX_INPUTS) return;
input.dev[i] = config.input[player].padtype;
player++;
}
teamplayer_init(0);
break;
}
case SYSTEM_LIGHTPHASER:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_LIGHTGUN;
player++;
break;
}
case SYSTEM_PADDLE:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_PADDLE;
player++;
break;
}
case SYSTEM_SPORTSPAD:
{
if (player == MAX_INPUTS) return;
input.dev[0] = DEVICE_SPORTSPAD;
player++;
break;
}
}
switch (input.system[1])
{
case SYSTEM_MS_GAMEPAD:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_PAD2B;
player++;
break;
}
case SYSTEM_MD_GAMEPAD:
{
if (player == MAX_INPUTS) return;
input.dev[4] = config.input[player].padtype;
player++;
break;
}
case SYSTEM_MOUSE:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_MOUSE;
player++;
break;
}
case SYSTEM_ACTIVATOR:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_ACTIVATOR;
player++;
break;
}
case SYSTEM_MENACER:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_LIGHTGUN;
player++;
break;
}
case SYSTEM_JUSTIFIER:
{
for (i=4; i<6; i++)
{
if (player == MAX_INPUTS) return;
input.dev[i] = DEVICE_LIGHTGUN;
player++;
}
break;
}
case SYSTEM_TEAMPLAYER:
{
for (i=4; i<8; i++)
{
if (player == MAX_INPUTS) return;
input.dev[i] = config.input[player].padtype;
player++;
}
teamplayer_init(1);
break;
}
case SYSTEM_LIGHTPHASER:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_LIGHTGUN;
player++;
break;
}
case SYSTEM_PADDLE:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_PADDLE;
player++;
break;
}
case SYSTEM_SPORTSPAD:
{
if (player == MAX_INPUTS) return;
input.dev[4] = DEVICE_SPORTSPAD;
player++;
break;
}
}
/* J-CART */
if (cart.special & HW_J_CART)
{
/* two additional gamepads */
for (i=5; i<7; i++)
{
if (player == MAX_INPUTS) return;
input.dev[i] = config.input[player].padtype;
player ++;
}
}
}
void input_reset(void)
{
/* Reset input devices */
int i;
for (i=0; i<MAX_DEVICES; i++)
{
switch (input.dev[i])
{
case DEVICE_PAD2B:
case DEVICE_PAD3B:
case DEVICE_PAD6B:
{
gamepad_reset(i);
break;
}
case DEVICE_LIGHTGUN:
{
lightgun_reset(i);
break;
}
case DEVICE_MOUSE:
{
mouse_reset(i);
break;
}
case DEVICE_ACTIVATOR:
{
activator_reset(i >> 2);
break;
}
case DEVICE_XE_A1P:
{
xe_a1p_reset();
break;
}
case DEVICE_PADDLE:
{
paddle_reset(i >> 2);
break;
}
case DEVICE_SPORTSPAD:
{
sportspad_reset(i >> 2);
break;
}
default:
{
break;
}
}
}
/* Team Player */
for (i=0; i<2; i++)
{
if (input.system[i] == SYSTEM_TEAMPLAYER)
{
teamplayer_reset(i);
}
}
}
void input_refresh(void)
{
int i;
for (i=0; i<MAX_DEVICES; i++)
{
switch (input.dev[i])
{
case DEVICE_PAD6B:
{
gamepad_refresh(i);
break;
}
case DEVICE_LIGHTGUN:
{
lightgun_refresh(i);
break;
}
}
}
}

128
source/input_hw/input.h Normal file
View File

@ -0,0 +1,128 @@
/***************************************************************************************
* Genesis Plus
* Input peripherals support
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
*
****************************************************************************************/
#ifndef _INPUT_H_
#define _INPUT_H_
/* Max. number of devices */
#define MAX_DEVICES (8)
/* Ports configuration */
#define NO_SYSTEM (0) /* unconnected port*/
#define SYSTEM_MD_GAMEPAD (1) /* single 3-buttons or 6-buttons Control Pad */
#define SYSTEM_MOUSE (2) /* Sega Mouse */
#define SYSTEM_MENACER (3) /* Sega Menacer (port B only) */
#define SYSTEM_JUSTIFIER (4) /* Konami Justifiers (port B only) */
#define SYSTEM_XE_A1P (5) /* XE-A1P analog controller (port A only) */
#define SYSTEM_ACTIVATOR (6) /* Sega Activator */
#define SYSTEM_MS_GAMEPAD (7) /* single 2-buttons Control Pad (Master System) */
#define SYSTEM_LIGHTPHASER (8) /* Sega Light Phaser (Master System) */
#define SYSTEM_PADDLE (9) /* Sega Paddle Control (Master System) */
#define SYSTEM_SPORTSPAD (10) /* Sega Sports Pad (Master System) */
#define SYSTEM_TEAMPLAYER (11) /* Sega TeamPlayer */
#define SYSTEM_WAYPLAY (12) /* EA 4-Way Play (use both ports) */
/* Device type */
#define DEVICE_PAD3B (0x00) /* 3-buttons Control Pad */
#define DEVICE_PAD6B (0x01) /* 6-buttons Control Pad */
#define DEVICE_MOUSE (0x02) /* Sega Mouse */
#define DEVICE_XE_A1P (0x03) /* XE-A1P analog controller */
#define DEVICE_ACTIVATOR (0x04) /* Activator */
#define DEVICE_LIGHTGUN (0x05) /* Sega Light Phaser, Menacer or Konami Justifiers */
#define DEVICE_PAD2B (0x06) /* 2-buttons Control Pad */
#define DEVICE_PADDLE (0x07) /* Sega Paddle Control */
#define DEVICE_SPORTSPAD (0x08) /* Sega Sports Pad */
#define DEVICE_TABLET (0x09) /* PICO tablet & pen */
#define NO_DEVICE (0xff) /* unconnected device */
/* Default Input bitmasks */
#define INPUT_MODE (0x0800)
#define INPUT_X (0x0400)
#define INPUT_Y (0x0200)
#define INPUT_Z (0x0100)
#define INPUT_START (0x0080)
#define INPUT_A (0x0040)
#define INPUT_C (0x0020)
#define INPUT_B (0x0010)
#define INPUT_RIGHT (0x0008)
#define INPUT_LEFT (0x0004)
#define INPUT_DOWN (0x0002)
#define INPUT_UP (0x0001)
/* Master System specific bitmasks */
#define INPUT_BUTTON2 (0x0020)
#define INPUT_BUTTON1 (0x0010)
/* Mouse specific bitmask */
#define INPUT_MOUSE_CENTER (0x0040)
#define INPUT_MOUSE_RIGHT (0x0020)
#define INPUT_MOUSE_LEFT (0x0010)
/* XE-1AP specific bitmask */
#define INPUT_XE_E1 (0x0800)
#define INPUT_XE_E2 (0x0400)
#define INPUT_XE_START (0x0200)
#define INPUT_XE_SELECT (0x0100)
#define INPUT_XE_A (0x0080)
#define INPUT_XE_B (0x0040)
#define INPUT_XE_C (0x0020)
#define INPUT_XE_D (0x0010)
/* Activator specific bitmasks */
#define INPUT_ACTIVATOR_8U (0x8000)
#define INPUT_ACTIVATOR_8L (0x4000)
#define INPUT_ACTIVATOR_7U (0x2000)
#define INPUT_ACTIVATOR_7L (0x1000)
#define INPUT_ACTIVATOR_6U (0x0800)
#define INPUT_ACTIVATOR_6L (0x0400)
#define INPUT_ACTIVATOR_5U (0x0200)
#define INPUT_ACTIVATOR_5L (0x0100)
#define INPUT_ACTIVATOR_4U (0x0080)
#define INPUT_ACTIVATOR_4L (0x0040)
#define INPUT_ACTIVATOR_3U (0x0020)
#define INPUT_ACTIVATOR_3L (0x0010)
#define INPUT_ACTIVATOR_2U (0x0008)
#define INPUT_ACTIVATOR_2L (0x0004)
#define INPUT_ACTIVATOR_1U (0x0002)
#define INPUT_ACTIVATOR_1L (0x0001)
typedef struct
{
uint8 system[2]; /* can be one of the SYSTEM_* values */
uint8 dev[MAX_DEVICES]; /* can be one of the DEVICE_* values */
uint16 pad[MAX_DEVICES]; /* digital inputs (any of INPUT_* values) */
int16 analog[MAX_DEVICES][2]; /* analog inputs (x/y) */
uint8 x_offset; /* gun horizontal offset */
uint8 y_offset; /* gun vertical offset */
} t_input;
/* Global variables */
extern t_input input;
extern int old_system[2];
/* Function prototypes */
extern void input_init(void);
extern void input_reset(void);
extern void input_refresh(void);
#endif

216
source/input_hw/lightgun.c Normal file
View File

@ -0,0 +1,216 @@
/***************************************************************************************
* Genesis Plus
* Sega Light Phaser, Menacer & Konami Justifiers support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
/************************************************************************************/
/* */
/* H-counter values returned in H40 & H32 modes */
/* */
/* Inside VDP, dot counter register is 9-bit, with only upper 8 bits being returned */
/* */
/* The number of dots per raster line is 342 in H32 mode and 420 in H40 mode */
/* */
/************************************************************************************/
static const uint8 hc_256[171] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93,
0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
static const uint8 hc_320[210] =
{
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F,
0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F,
0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F,
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B, 0x9C, 0x9D, 0x9E, 0x9F,
0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7, 0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF,
0xB0, 0xB1, 0xB2, 0xB3, 0xB4, 0xB5, 0xB6,
0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED,
0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD,
0xFE, 0xFF
};
static struct
{
uint8 State;
uint8 Port;
} lightgun;
void lightgun_reset(int port)
{
input.analog[port][0] = bitmap.viewport.w >> 1;
input.analog[port][1] = bitmap.viewport.h >> 1;
lightgun.State = 0x40;
lightgun.Port = 4;
}
void lightgun_refresh(int port)
{
/* Check that lightgun is enabled */
if (port == lightgun.Port)
{
/* check if line falls within current gun Y position */
if ((input.analog[port][1] == v_counter + input.y_offset))
{
/* HL enabled ? */
if (io_reg[5] & 0x80)
{
/* External Interrupt ? */
if (reg[11] & 0x08)
{
m68k_irq_state |= 0x12;
}
/* HV Counter Latch:
1) some games does not enable HVC latch but instead use bigger X offset
--> we force the HV counter value read by the gun routine
2) for games using H40 mode, the gun routine scales up the Hcounter value
--> H-Counter range is approx. 290 dot clocks
*/
hvc_latch = 0x10000 | (v_counter << 8);
if (reg[12] & 1)
{
hvc_latch |= hc_320[((input.analog[port][0] * 290) / (2 * 320) + input.x_offset) % 210];
}
else
{
hvc_latch |= hc_256[(input.analog[port][0] / 2 + input.x_offset) % 171];
}
}
}
}
}
/*--------------------------------------------------------------------------*/
/* Sega Phaser */
/*--------------------------------------------------------------------------*/
static inline unsigned char phaser_read(int port)
{
/* FIRE button status (active low) */
unsigned char temp = ~(input.pad[port] & 0x10);
/* Check that TH is set as an input */
if (io_reg[0] & (0x02 << (port >> 1)))
{
/* Get current X position (phaser is only used in MS compatiblity mode) */
int hcounter = hctab[(mcycles_z80 + Z80_CYCLE_OFFSET) % MCYCLES_PER_LINE];
/* Compare with gun position */
int dx = input.analog[port][0] - (hcounter << 1);
int dy = input.analog[port][1] - (v_counter);
/* Check if current pixel is within lightgun spot ? */
if ((abs(dy) <= 5) && (abs(dx) <= 60))
{
/* set TH low */
temp &= ~0x40;
/* prevents multiple latch at each port read */
if (lightgun.State)
{
/* latch estimated HC value */
hvc_latch = 0x10000 | (input.x_offset + (input.analog[port][0] >> 1));
lightgun.State = 0;
}
else
{
lightgun.State = 1;
}
}
}
return temp & 0x7F;
}
unsigned char phaser_1_read(void)
{
return phaser_read(0);
}
unsigned char phaser_2_read(void)
{
return phaser_read(4);
}
/*--------------------------------------------------------------------------*/
/* Sega Menacer */
/*--------------------------------------------------------------------------*/
unsigned char menacer_read(void)
{
/* Return START,A,B,C buttons status in D0-D3 (active high) */
/* TL & TR pins always return 0 (normally set as output) */
return ((input.pad[4] >> 4) & 0x0F);
}
/*--------------------------------------------------------------------------*/
/* Konami Justifiers */
/*--------------------------------------------------------------------------*/
unsigned char justifier_read(void)
{
/* Gun detection */
if (lightgun.State & 0x40)
{
return 0x30;
}
/* Return A & START button status in D0-D1 (active low) */
/* TL & TR pins should always return 1 (normally set as output) */
/* LEFT & RIGHT pins should always return 0 */
return (((~input.pad[lightgun.Port] >> 6) & 0x03) | 0x70);
}
void justifier_write(unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (lightgun.State & ~mask) | (data & mask);
/* gun index */
lightgun.Port = 4 + ((data >> 5) & 1);
/* update internal state */
lightgun.State = data;
}

View File

@ -0,0 +1,35 @@
/***************************************************************************************
* Genesis Plus
* Sega Light Phaser, Menacer & Konami Justifiers support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _LIGHTGUN_H_
#define _LIGHTGUN_H_
/* Input devices port handlers */
extern void lightgun_reset(int index);
extern void lightgun_refresh(int port);
extern unsigned char phaser_1_read(void);
extern unsigned char phaser_2_read(void);
extern unsigned char menacer_read(void);
extern unsigned char justifier_read(void);
extern void justifier_write(unsigned char data, unsigned char mask);
#endif

153
source/input_hw/mouse.c Normal file
View File

@ -0,0 +1,153 @@
/***************************************************************************************
* Genesis Plus
* Sega Mouse support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
static struct
{
uint8 State;
uint8 Counter;
uint8 Wait;
uint8 Port;
} mouse;
void mouse_reset(int port)
{
input.analog[port][0] = 0;
input.analog[port][1] = 0;
mouse.State = 0x60;
mouse.Counter = 0;
mouse.Wait = 0;
mouse.Port = port;
}
unsigned char mouse_read()
{
unsigned int temp = 0x00;
int x = input.analog[mouse.Port][0];
int y = input.analog[mouse.Port][1];
switch (mouse.Counter)
{
case 0: /* initial */
temp = 0x00;
break;
case 1: /* xxxx1011 */
temp = 0x0B;
break;
case 2: /* xxxx1111 */
temp = 0x0F;
break;
case 3: /* xxxx1111 */
temp = 0x0F;
break;
case 4: /* Axis sign & overflow (not emulated) bits */
temp |= (x < 0);
temp |= (y < 0) << 1;
/*
temp |= (abs(x) > 255) << 2;
temp |= (abs(y) > 255) << 3;
*/
break;
case 5: /* START, A, B, C buttons state (active high) */
temp = (input.pad[mouse.Port] >> 4) & 0x0F;
break;
case 6: /* X Axis MSB */
temp = (x >> 4) & 0x0F;
break;
case 7: /* X Axis LSB */
temp = (x & 0x0F);
break;
case 8: /* Y Axis MSB */
temp = (y >> 4) & 0x0F;
break;
case 9: /* Y Axis LSB */
temp = (y & 0x0F);
break;
}
/* TL = busy status */
if (mouse.Wait)
{
/* wait before ACK, fix some buggy mouse routine (Shangai 2, Wack World,...) */
mouse.Wait = 0;
/* TL = !TR */
temp |= (~mouse.State & 0x20) >> 1;
}
else
{
/* TL = TR (data is ready) */
temp |= (mouse.State & 0x20) >> 1;
}
return temp;
}
void mouse_write(unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (mouse.State & ~mask) | (data & mask);
if (mouse.Counter == 0)
{
/* wait for TH 1->0 transition */
if ((mouse.State & 0x40) && !(data & 0x40))
{
/* start acquisition */
mouse.Counter = 1;
}
}
else
{
/* TR handshake */
if ((mouse.State ^ data) & 0x20)
{
/* increment phase */
if (mouse.Counter < 10)
{
mouse.Counter++;
}
/* input latency */
mouse.Wait = 1;
}
}
/* end of acquisition (TH=1) */
if (data & 0x40)
{
mouse.Counter = 0;
}
/* update internal state */
mouse.State = data;
}

31
source/input_hw/mouse.h Normal file
View File

@ -0,0 +1,31 @@
/***************************************************************************************
* Genesis Plus
* Sega Mouse support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _MOUSE_H_
#define _MOUSE_H_
/* Function prototypes */
extern void mouse_reset(int port);
extern unsigned char mouse_read(void);
extern void mouse_write(unsigned char data, unsigned char mask);
#endif

95
source/input_hw/paddle.c Normal file
View File

@ -0,0 +1,95 @@
/***************************************************************************************
* Genesis Plus
* Sega Paddle Control support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
static struct
{
uint8 State;
} paddle[2];
void paddle_reset(int index)
{
input.analog[index << 2][0] = 128;
paddle[index].State = 0x40;
}
static inline unsigned char paddle_read(int port)
{
/* FIRE button status (active low) */
unsigned char temp = ~(input.pad[port] & 0x10);
/* Pad index */
int index = port >> 2;
/* Clear low bits */
temp &= 0x70;
/* Japanese model: automatic flip-flop */
if (region_code < REGION_USA)
{
paddle[index].State ^= 0x40;
}
if (paddle[index].State & 0x40)
{
/* return higher bits */
temp |= (input.analog[port][0] >> 4) & 0x0F;
}
else
{
/* return lower bits */
temp |= input.analog[port][0] & 0x0F;
/* set TR low */
temp &= ~0x20;
}
return temp;
}
static inline void paddle_write(int index, unsigned char data, unsigned char mask)
{
/* update bits set as output only */
paddle[index].State = (paddle[index].State & ~mask) | (data & mask);
}
unsigned char paddle_1_read(void)
{
return paddle_read(0);
}
unsigned char paddle_2_read(void)
{
return paddle_read(4);
}
void paddle_1_write(unsigned char data, unsigned char mask)
{
paddle_write(0, data, mask);
}
void paddle_2_write(unsigned char data, unsigned char mask)
{
paddle_write(1, data, mask);
}

33
source/input_hw/paddle.h Normal file
View File

@ -0,0 +1,33 @@
/***************************************************************************************
* Genesis Plus
* Sega Paddle Control support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _PADDLE_H_
#define _PADDLE_H_
/* Function prototypes */
extern void paddle_reset(int index);
extern unsigned char paddle_1_read(void);
extern unsigned char paddle_2_read(void);
extern void paddle_1_write(unsigned char data, unsigned char mask);
extern void paddle_2_write(unsigned char data, unsigned char mask);
#endif

118
source/input_hw/sportspad.c Normal file
View File

@ -0,0 +1,118 @@
/***************************************************************************************
* Genesis Plus
* Sega Sports Pad support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
static struct
{
uint8 State;
uint8 Counter;
} sportspad[2];
void sportspad_reset(int index)
{
input.analog[index << 2][0] = 128;
input.analog[index << 2][1] = 128;
sportspad[index].State = 0x40;
sportspad[index].Counter = 0;
}
static inline unsigned char sportspad_read(int port)
{
/* Buttons 1(B) & 2(C) status (active low) */
unsigned char temp = ~(input.pad[port] & 0x30);
/* Pad index */
int index = port >> 2;
/* Clear low bits */
temp &= 0x70;
/* Detect current state */
switch (sportspad[index].Counter & 3)
{
case 1:
{
/* X position high bits */
temp |= (input.analog[port][0] >> 4) & 0x0F;
break;
}
case 2:
{
/* X position low bits */
temp |= input.analog[port][0] & 0x0F;
break;
}
case 3:
{
/* Y position high bits */
temp |= (input.analog[port][1] >> 4) & 0x0F;
break;
}
default:
{
/* Y position low bits */
temp |= input.analog[port][1] & 0x0F;
break;
}
}
return temp;
}
static inline void sportspad_write(int index, unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (sportspad[index].State & ~mask) | (data & mask);
/* check TH transitions */
if ((data ^ sportspad[index].State) & 0x40)
{
sportspad[index].Counter++;
}
/* update internal state */
sportspad[index].State = data;
}
unsigned char sportspad_1_read(void)
{
return sportspad_read(0);
}
unsigned char sportspad_2_read(void)
{
return sportspad_read(4);
}
void sportspad_1_write(unsigned char data, unsigned char mask)
{
sportspad_write(0, data, mask);
}
void sportspad_2_write(unsigned char data, unsigned char mask)
{
sportspad_write(1, data, mask);
}

View File

@ -0,0 +1,33 @@
/***************************************************************************************
* Genesis Plus
* Sega Sports Pad support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _SPORTSPAD_H_
#define _SPORTSPAD_H_
/* Function prototypes */
extern void sportspad_reset(int index);
extern unsigned char sportspad_1_read(void);
extern unsigned char sportspad_2_read(void);
extern void sportspad_1_write(unsigned char data, unsigned char mask);
extern void sportspad_2_write(unsigned char data, unsigned char mask);
#endif

View File

@ -0,0 +1,160 @@
/***************************************************************************************
* Genesis Plus
* Team Player support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
static struct
{
uint8 State;
uint8 Counter;
uint8 Table[12];
} teamplayer[2];
void teamplayer_init(int port)
{
int i,padnum;
int index = 0;
/* this table determines which gamepad input should be returned during acquisition sequence
index = teamplayer read table index: 0=1st read, 1=2nd read, ...
table = high bits are pad index, low bits are pad input shift: 0=RLDU, 4=SABC, 8=MXYZ
*/
for (i=0; i<4; i++)
{
padnum = (4 * port) + i;
if (input.dev[padnum] == DEVICE_PAD3B)
{
padnum = padnum << 4;
teamplayer[port].Table[index++] = padnum;
teamplayer[port].Table[index++] = padnum | 4;
}
else
{
padnum = padnum << 4;
teamplayer[port].Table[index++] = padnum;
teamplayer[port].Table[index++] = padnum | 4;
teamplayer[port].Table[index++] = padnum | 8;
}
}
}
void teamplayer_reset(int port)
{
teamplayer[port].State = 0x60; /* TH = 1, TR = 1 */
teamplayer[port].Counter = 0;
}
static inline unsigned int teamplayer_read(int port)
{
unsigned int counter = teamplayer[port].Counter;
/* acquisition sequence */
switch (counter)
{
case 0: /* initial state: TH = 1, TR = 1 -> RLDU = 0011 */
{
return 0x73;
}
case 1: /* start request: TH = 0, TR = 1 -> RLDU = 1111 */
{
return 0x3F;
}
case 2:
case 3: /* ack request: TH=0, TR=0/1 -> RLDU = 0000 */
{
/* TL should match TR */
return ((teamplayer[port].State & 0x20) >> 1);
}
case 4:
case 5:
case 6:
case 7: /* PAD type */
{
unsigned int retval = input.dev[(port << 2) + (counter - 4)];
/* TL should match TR */
return (((teamplayer[port].State & 0x20) >> 1) | retval);
}
default: /* PAD status */
{
unsigned int retval = 0x0F;
/* SEGA teamplayer returns successively PAD1 -> PAD2 -> PAD3 -> PAD4 inputs */
unsigned int padnum = teamplayer[port].Table[counter - 8] >> 4;
/* Each PAD inputs is obtained through 2 or 3 sequential reads: RLDU -> SACB -> MXYZ */
retval &= ~(input.pad[padnum] >> (teamplayer[port].Table[counter - 8] & 0x0F));
/* TL should match TR */
return (((teamplayer[port].State & 0x20) >> 1) | retval);
}
}
}
static inline void teamplayer_write(int port, unsigned char data, unsigned char mask)
{
/* update bits set as output only */
unsigned int state = (teamplayer[port].State & ~mask) | (data & mask);
/* TH & TR handshaking */
if ((teamplayer[port].State ^ state) & 0x60)
{
if (state & 0x40)
{
/* TH high -> reset counter */
teamplayer[port].Counter = 0;
}
else
{
/* increment counter */
teamplayer[port].Counter++;
}
/* update internal state */
teamplayer[port].State = state;
}
}
unsigned char teamplayer_1_read(void)
{
return teamplayer_read(0);
}
unsigned char teamplayer_2_read(void)
{
return teamplayer_read(1);
}
void teamplayer_1_write(unsigned char data, unsigned char mask)
{
teamplayer_write(0, data, mask);
}
void teamplayer_2_write(unsigned char data, unsigned char mask)
{
teamplayer_write(1, data, mask);
}

View File

@ -0,0 +1,34 @@
/***************************************************************************************
* Genesis Plus
* Team Player support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _TEAMPLAYER_H_
#define _TEAMPLAYER_H_
/* Function prototypes */
extern void teamplayer_init(int port);
extern void teamplayer_reset(int port);
extern unsigned char teamplayer_1_read(void);
extern unsigned char teamplayer_2_read(void);
extern void teamplayer_1_write(unsigned char data, unsigned char mask);
extern void teamplayer_2_write(unsigned char data, unsigned char mask);
#endif

144
source/input_hw/xe_a1p.c Normal file
View File

@ -0,0 +1,144 @@
/***************************************************************************************
* Genesis Plus
* XE-A1P analog controller support
*
* Copyright Eke-Eke (2007-2011)
*
* 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 "shared.h"
static struct
{
uint8 State;
uint8 Counter;
uint8 Latency;
} xe_a1p;
void xe_a1p_reset(void)
{
input.analog[0][0] = 128;
input.analog[0][1] = 128;
input.analog[1][0] = 128;
xe_a1p.State = 0x40;
xe_a1p.Counter = 0;
xe_a1p.Latency = 0;
}
unsigned char xe_a1p_read()
{
unsigned int temp = 0x40;
/* Left Stick X & Y analog values (bidirectional) */
int x = input.analog[0][0];
int y = input.analog[0][1];
/* Right Stick X or Y value (unidirectional) */
int z = input.analog[1][0];
/* Buttons status (active low) */
uint16 pad = ~input.pad[0];
/* Current 4-bit data cycle */
/* There are eight internal data cycle for each 5 acquisition sequence */
/* First 4 return the same 4-bit data, next 4 return next 4-bit data */
switch (xe_a1p.Counter >> 2)
{
case 0:
temp |= ((pad >> 8) & 0x0F); /* E1 E2 Start Select */
break;
case 1:
temp |= ((pad >> 4) & 0x0F); /* A B C D */
break;
case 2:
temp |= ((x >> 4) & 0x0F);
break;
case 3:
temp |= ((y >> 4) & 0x0F);
break;
case 4:
break;
case 5:
temp |= ((z >> 4) & 0x0F);
break;
case 6:
temp |= (x & 0x0F);
break;
case 7:
temp |= (y & 0x0F);
break;
case 8:
break;
case 9:
temp |= (z & 0x0F);
break;
}
/* Get current internal cycle (0-7) */
unsigned int cycle = xe_a1p.Counter & 7;
/* TL indicates which part of data is returned (0=1st part, 1=2nd part) */
temp |= ((cycle & 4) << 2);
/* TR indicates if data is ready (0=ready, 1=not ready) */
/* Fastest One input routine actually expects this bit to switch between 0 & 1 */
/* so we make the first read of a data cycle return 1 then 0 for remaining reads */
temp |= (!(cycle & 3) << 5);
/* Automatically increment data cycle on each read (within current acquisition sequence) */
cycle = (cycle + 1) & 7;
/* Update internal cycle counter */
xe_a1p.Counter = (xe_a1p.Counter & ~7) | cycle;
/* Update internal latency on each read */
xe_a1p.Latency++;
return temp;
}
void xe_a1p_write(unsigned char data, unsigned char mask)
{
/* update bits set as output only */
data = (xe_a1p.State & ~mask) | (data & mask);
/* look for TH 1->0 transitions */
if (!(data & 0x40) && (xe_a1p.State & 0x40))
{
/* reset acquisition cycle */
xe_a1p.Latency = xe_a1p.Counter = 0;
}
else
{
/* some games immediately write new data to TH */
/* so we make sure first sequence has actually been handled */
if (xe_a1p.Latency > 2)
{
/* next acquisition sequence */
xe_a1p.Counter = (xe_a1p.Counter & ~7) + 8;
/* 5 sequence max with 8 cycles each */
if (xe_a1p.Counter > 32)
{
xe_a1p.Counter = 32;
}
}
}
/* update internal state */
xe_a1p.State = data;
}

31
source/input_hw/xe_a1p.h Normal file
View File

@ -0,0 +1,31 @@
/***************************************************************************************
* Genesis Plus
* XE-A1P analog controller support
*
* Copyright Eke-Eke (2007-2011)
*
* 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
*
****************************************************************************************/
#ifndef _XE_A1PH_
#define _XE_A1PH_
/* Function prototypes */
extern void xe_a1p_reset(void);
extern unsigned char xe_a1p_read(void);
extern void xe_a1p_write(unsigned char data, unsigned char mask);
#endif

450
source/io_ctrl.c Normal file
View File

@ -0,0 +1,450 @@
/***************************************************************************************
* Genesis Plus
* I/O controller (MD & MS compatibility modes)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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 "shared.h"
#include "gamepad.h"
#include "lightgun.h"
#include "mouse.h"
#include "activator.h"
#include "xe_a1p.h"
#include "teamplayer.h"
#include "paddle.h"
#include "sportspad.h"
uint8 io_reg[0x10];
uint8 region_code = REGION_USA;
static struct port_t
{
void (*data_w)(unsigned char data, unsigned char mask);
unsigned char (*data_r)(void);
} port[3];
static void dummy_write(unsigned char data, unsigned char mask)
{
}
static unsigned char dummy_read(void)
{
return 0x7F;
}
/*****************************************************************************
* I/O chip functions *
* *
*****************************************************************************/
void io_init(void)
{
/* Initialize connected peripherals */
input_init();
/* Initialize IO Ports handlers & connected peripherals */
switch (input.system[0])
{
case SYSTEM_MS_GAMEPAD:
{
port[0].data_w = dummy_write;
port[0].data_r = gamepad_1_read;
break;
}
case SYSTEM_MD_GAMEPAD:
{
port[0].data_w = gamepad_1_write;
port[0].data_r = gamepad_1_read;
break;
}
case SYSTEM_MOUSE:
{
port[0].data_w = mouse_write;
port[0].data_r = mouse_read;
break;
}
case SYSTEM_ACTIVATOR:
{
port[0].data_w = activator_1_write;
port[0].data_r = activator_1_read;
break;
}
case SYSTEM_XE_A1P:
{
port[0].data_w = xe_a1p_write;
port[0].data_r = xe_a1p_read;
break;
}
case SYSTEM_WAYPLAY:
{
port[0].data_w = wayplay_1_write;
port[0].data_r = wayplay_1_read;
break;
}
case SYSTEM_TEAMPLAYER:
{
port[0].data_w = teamplayer_1_write;
port[0].data_r = teamplayer_1_read;
break;
}
case SYSTEM_LIGHTPHASER:
{
port[0].data_w = dummy_write;
port[0].data_r = phaser_1_read;
break;
}
case SYSTEM_PADDLE:
{
port[0].data_w = paddle_1_write;
port[0].data_r = paddle_1_read;
break;
}
case SYSTEM_SPORTSPAD:
{
port[0].data_w = sportspad_1_write;
port[0].data_r = sportspad_1_read;
break;
}
default:
{
port[0].data_w = dummy_write;
port[0].data_r = dummy_read;
break;
}
}
switch (input.system[1])
{
case SYSTEM_MS_GAMEPAD:
{
port[1].data_w = dummy_write;
port[1].data_r = gamepad_2_read;
break;
}
case SYSTEM_MD_GAMEPAD:
{
port[1].data_w = gamepad_2_write;
port[1].data_r = gamepad_2_read;
break;
}
case SYSTEM_MOUSE:
{
port[1].data_w = mouse_write;
port[1].data_r = mouse_read;
break;
}
case SYSTEM_ACTIVATOR:
{
port[1].data_w = activator_2_write;
port[1].data_r = activator_2_read;
break;
}
case SYSTEM_MENACER:
{
port[1].data_w = dummy_write;
port[1].data_r = menacer_read;
break;
}
case SYSTEM_JUSTIFIER:
{
port[1].data_w = justifier_write;
port[1].data_r = justifier_read;
break;
}
case SYSTEM_WAYPLAY:
{
port[1].data_w = wayplay_2_write;
port[1].data_r = wayplay_2_read;
break;
}
case SYSTEM_TEAMPLAYER:
{
port[1].data_w = teamplayer_2_write;
port[1].data_r = teamplayer_2_read;
break;
}
case SYSTEM_LIGHTPHASER:
{
port[1].data_w = dummy_write;
port[1].data_r = phaser_2_read;
break;
}
case SYSTEM_PADDLE:
{
port[1].data_w = paddle_2_write;
port[1].data_r = paddle_2_read;
break;
}
case SYSTEM_SPORTSPAD:
{
port[1].data_w = sportspad_2_write;
port[1].data_r = sportspad_2_read;
break;
}
default:
{
port[1].data_w = dummy_write;
port[1].data_r = dummy_read;
break;
}
}
/* External Port (unconnected) */
port[2].data_w = dummy_write;
port[2].data_r = dummy_read;
}
void io_reset(void)
{
/* Reset I/O registers */
if (system_hw == SYSTEM_PBC)
{
/* SMS compatibility mode control register */
io_reg[0x00] = 0xFF;
}
else
{
/* Genesis mode registers */
io_reg[0x00] = region_code | 0x20 | (config.tmss & 1);
io_reg[0x01] = 0x00;
io_reg[0x02] = 0x00;
io_reg[0x03] = 0x00;
io_reg[0x04] = 0x00;
io_reg[0x05] = 0x00;
io_reg[0x06] = 0x00;
io_reg[0x07] = 0xFF;
io_reg[0x08] = 0x00;
io_reg[0x09] = 0x00;
io_reg[0x0A] = 0xFF;
io_reg[0x0B] = 0x00;
io_reg[0x0C] = 0x00;
io_reg[0x0D] = 0xFB;
io_reg[0x0E] = 0x00;
io_reg[0x0F] = 0x00;
}
/* Reset connected peripherals */
input_reset();
}
void io_68k_write(unsigned int offset, unsigned int data)
{
switch (offset)
{
case 0x01: /* Port A Data */
case 0x02: /* Port B Data */
case 0x03: /* Port C Data */
{
io_reg[offset] = data;
port[offset-1].data_w(data, io_reg[offset + 3]);
return;
}
case 0x04: /* Port A Ctrl */
case 0x05: /* Port B Ctrl */
case 0x06: /* Port C Ctrl */
{
if (data != io_reg[offset])
{
io_reg[offset] = data;
port[offset-4].data_w(io_reg[offset-3], data);
}
return;
}
case 0x07: /* Port A TxData */
case 0x0A: /* Port B TxData */
case 0x0D: /* Port C TxData */
{
io_reg[offset] = data;
return;
}
case 0x09: /* Port A S-Ctrl */
case 0x0C: /* Port B S-Ctrl */
case 0x0F: /* Port C S-Ctrl */
{
io_reg[offset] = data & 0xF8;
return;
}
default: /* Read-only ports */
{
return;
}
}
}
unsigned int io_68k_read(unsigned int offset)
{
switch(offset)
{
case 0x01: /* Port A Data */
case 0x02: /* Port B Data */
case 0x03: /* Port C Data */
{
unsigned int mask = 0x80 | io_reg[offset + 3];
unsigned int data = port[offset-1].data_r();
return (io_reg[offset] & mask) | (data & ~mask);
}
default: /* return register value */
{
return io_reg[offset];
}
}
}
void io_z80_write(unsigned int data)
{
/* pins can't be configured as output on japanese models */
if (region_code & REGION_USA)
{
/*
Bit Function
--------------
D7 : Port B TH pin output level (1=high, 0=low)
D6 : Port B TR pin output level (1=high, 0=low)
D5 : Port A TH pin output level (1=high, 0=low)
D4 : Port A TR pin output level (1=high, 0=low)
D3 : Port B TH pin direction (1=input, 0=output)
D2 : Port B TR pin direction (1=input, 0=output)
D1 : Port A TH pin direction (1=input, 0=output)
D0 : Port A TR pin direction (1=input, 0=output)
*/
/* Send TR/TH state to connected peripherals */
port[0].data_w((data << 1) & 0x60, (~io_reg[0] << 5) & 0x60);
port[1].data_w((data >> 1) & 0x60, (~io_reg[0] << 3) & 0x60);
/* Check for TH low-to-high transitions on both ports */
if ((!(io_reg[0] & 0x80) && (data & 0x80)) ||
(!(io_reg[0] & 0x20) && (data & 0x20)))
{
/* Latch new HVC */
hvc_latch = hctab[(mcycles_z80 + Z80_CYCLE_OFFSET) % MCYCLES_PER_LINE] | 0x10000;
}
}
else
{
/* outputs return fixed value */
data &= 0x0F;
}
/* Update control register */
io_reg[0] = data;
}
unsigned int io_z80_read(unsigned int offset)
{
/* Read port A & port B input data */
unsigned int data = (port[0].data_r()) | (port[1].data_r() << 8);
/* Read control register value */
unsigned int ctrl = io_reg[0];
/* I/O ports */
if (offset)
{
/*
Bit Function
--------------
D7 : Port B TH pin input
D6 : Port A TH pin input
D5 : Unused (0 on Mega Drive, 1 otherwise)
D4 : RESET button (always 1 on Mega Drive)
D3 : Port B TR pin input
D2 : Port B TL pin input
D1 : Port B Right pin input
D0 : Port B Left pin input
*/
data = ((data >> 10) & 0x0F) | (data & 0x40) | ((data >> 7) & 0x80) | 0x10;
/* Adjust port B TH state if configured as output */
if (!(ctrl & 0x08))
{
data &= ~0x80;
data |= (ctrl & 0x80);
}
/* Adjust port A TH state if configured as output */
if (!(ctrl & 0x02))
{
data &= ~0x40;
data |= ((ctrl & 0x20) << 1);
}
/* Adjust port B TR state if configured as output */
if (!(ctrl & 0x04))
{
data &= ~0x08;
data |= ((ctrl & 0x40) >> 3);
}
}
else
{
/*
Bit Function
--------------
D7 : Port B Down pin input
D6 : Port B Up pin input
D5 : Port A TR pin input
D4 : Port A TL pin input
D3 : Port A Right pin input
D2 : Port A Left pin input
D1 : Port A Down pin input
D0 : Port A Up pin input
*/
data = (data & 0x3F) | ((data >> 2) & 0xC0);
/* Adjust port A TR state if configured as output */
if (!(ctrl & 0x01))
{
data &= ~0x20;
data |= ((ctrl & 0x10) << 1);
}
}
return data;
}

45
source/io_ctrl.h Normal file
View File

@ -0,0 +1,45 @@
/***************************************************************************************
* Genesis Plus
* I/O controller (MD & MS compatibility modes)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
*
****************************************************************************************/
#ifndef _GEN_IO_H_
#define _GEN_IO_H_
#define REGION_JAPAN_NTSC 0x00
#define REGION_JAPAN_PAL 0x40
#define REGION_USA 0x80
#define REGION_EUROPE 0xC0
/* Global variables */
extern uint8 io_reg[0x10];
extern uint8 region_code;
/* Function prototypes */
extern void io_init(void);
extern void io_reset(void);
extern void io_68k_write(unsigned int offset, unsigned int data);
extern unsigned int io_68k_read(unsigned int offset);
extern void io_z80_write(unsigned int data);
extern unsigned int io_z80_read(unsigned int offset);
#endif /* _IO_H_ */

View File

@ -60,7 +60,6 @@
#define MAXCOMPANY 64
#define MAXPERIPHERALS 14
typedef struct
{
char companyid[6];
@ -84,7 +83,8 @@ char rom_filename[256];
* Based on the document provided at
* http://www.zophar.net/tech/files/Genesis_ROM_Format.txt
**************************************************************************/
static COMPANYINFO companyinfo[MAXCOMPANY] = {
static const COMPANYINFO companyinfo[MAXCOMPANY] =
{
{"ACLD", "Ballistic"},
{"RSI", "Razorsoft"},
{"SEGA", "SEGA"},
@ -157,7 +157,8 @@ static COMPANYINFO companyinfo[MAXCOMPANY] = {
* Based on the document provided at
* http://www.zophar.net/tech/files/Genesis_ROM_Format.txt
***************************************************************************/
static PERIPHERALINFO peripheralinfo[MAXPERIPHERALS] = {
static const PERIPHERALINFO peripheralinfo[MAXPERIPHERALS] =
{
{"J", "3B Joypad"},
{"6", "6B Joypad"},
{"K", "Keyboard"},
@ -175,11 +176,10 @@ static PERIPHERALINFO peripheralinfo[MAXPERIPHERALS] = {
};
/***************************************************************************
* GetRealChecksum
*
* Compute ROM checksum.
* Compute ROM real checksum.
***************************************************************************/
static uint16 GetRealChecksum (uint8 *rom, int length)
static uint16 getchecksum(uint8 *rom, int length)
{
int i;
uint16 checksum = 0;
@ -193,60 +193,157 @@ static uint16 GetRealChecksum (uint8 *rom, int length)
}
/***************************************************************************
* getrominfo
*
* Pass a pointer to the ROM base address.
***************************************************************************/
static void getrominfo (char *romheader)
static void getrominfo(char *romheader)
{
int i,j;
uint16 offset = 0;
/* Clear ROM info structure */
memset (&rominfo, 0, sizeof (ROMINFO));
memcpy (&rominfo.consoletype, romheader + ROMCONSOLE, 16);
memcpy (&rominfo.copyright, romheader + ROMCOPYRIGHT, 16);
rominfo.domestic[0] = romheader[ROMDOMESTIC];
j=1;
for (i=1; i<48; i++)
/* Look for Master System ROM header */
if (!memcmp (&cart.rom[0x1ff0], "TMR SEGA", 8))
{
if ((rominfo.domestic[j-1] != 32) || (romheader[ROMDOMESTIC + i] != 32))
offset = 0x1ff0;
}
else if (!memcmp (&cart.rom[0x3ff0], "TMR SEGA", 8))
{
offset = 0x3ff0;
}
else if (!memcmp (&cart.rom[0x7ff0], "TMR SEGA", 8))
{
offset = 0x7ff0;
}
/* If found, assume this is a SMS game */
if (offset)
{
/* force SMS compatibilty mode */
system_hw = SYSTEM_PBC;
/* checksum */
rominfo.checksum = cart.rom[offset + 0x0a] | (cart.rom[offset + 0x0b] << 8);
/* product code & version */
sprintf(&rominfo.product[0], "%02d", cart.rom[offset + 0x0e] >> 4);
sprintf(&rominfo.product[2], "%02x", cart.rom[offset + 0x0d]);
sprintf(&rominfo.product[4], "%02x", cart.rom[offset + 0x0c]);
sprintf(&rominfo.product[6], "-%d", cart.rom[offset + 0x0e] & 0x0F);
/* region code */
switch (cart.rom[offset + 0x0f] >> 4)
{
rominfo.domestic[j] = romheader[ROMDOMESTIC + i];
j++;
case 3:
strcpy(rominfo.country,"SMS Japan");
break;
case 4:
strcpy(rominfo.country,"SMS Export");
break;
case 5:
strcpy(rominfo.country,"GG Japan");
break;
case 6:
strcpy(rominfo.country,"GG Export");
break;
case 7:
strcpy(rominfo.country,"GG International");
break;
default:
sprintf(rominfo.country,"Unknown (%d)", cart.rom[offset + 0x0f] >> 4);
break;
}
/* ROM size */
rominfo.romstart = 0;
switch (cart.rom[offset + 0x0f] & 0x0F)
{
case 0x00:
rominfo.romend = 0x3FFFF;
break;
case 0x01:
rominfo.romend = 0x7FFFF;
break;
case 0x02:
rominfo.romend = 0xFFFFF;
break;
case 0x0a:
rominfo.romend = 0x1FFF;
break;
case 0x0b:
rominfo.romend = 0x3FFF;
break;
case 0x0c:
rominfo.romend = 0x7FFF;
break;
case 0x0d:
rominfo.romend = 0xBFFF;
break;
case 0x0e:
rominfo.romend = 0xFFFF;
break;
case 0x0f:
rominfo.romend = 0x1FFFF;
break;
}
}
rominfo.domestic[j] = 0;
rominfo.international[0] = romheader[ROMWORLD];
j=1;
for (i=1; i<48; i++)
else
{
if ((rominfo.international[j-1] != 32) || (romheader[ROMWORLD + i] != 32))
/* Some SMS games don't have any header */
if (system_hw == SYSTEM_PBC) return;
/* Genesis ROM header support */
memcpy (&rominfo.consoletype, romheader + ROMCONSOLE, 16);
memcpy (&rominfo.copyright, romheader + ROMCOPYRIGHT, 16);
/* Domestic (japanese) name */
rominfo.domestic[0] = romheader[ROMDOMESTIC];
int i, j = 1;
for (i=1; i<48; i++)
{
rominfo.international[j] = romheader[ROMWORLD + i];
j++;
if ((rominfo.domestic[j-1] != 32) || (romheader[ROMDOMESTIC + i] != 32))
{
rominfo.domestic[j] = romheader[ROMDOMESTIC + i];
j++;
}
}
}
rominfo.international[j] = 0;
rominfo.domestic[j] = 0;
memcpy (&rominfo.ROMType, romheader + ROMTYPE, 2);
memcpy (&rominfo.product, romheader + ROMPRODUCT, 12);
memcpy (&rominfo.checksum, romheader + ROMCHECKSUM, 2);
memcpy (&rominfo.romstart, romheader + ROMROMSTART, 4);
memcpy (&rominfo.romend, romheader + ROMROMEND, 4);
memcpy (&rominfo.country, romheader + ROMCOUNTRY, 16);
/* International name */
rominfo.international[0] = romheader[ROMWORLD];
j=1;
for (i=1; i<48; i++)
{
if ((rominfo.international[j-1] != 32) || (romheader[ROMWORLD + i] != 32))
{
rominfo.international[j] = romheader[ROMWORLD + i];
j++;
}
}
rominfo.international[j] = 0;
/* ROM informations */
memcpy (&rominfo.ROMType, romheader + ROMTYPE, 2);
memcpy (&rominfo.product, romheader + ROMPRODUCT, 12);
memcpy (&rominfo.checksum, romheader + ROMCHECKSUM, 2);
memcpy (&rominfo.romstart, romheader + ROMROMSTART, 4);
memcpy (&rominfo.romend, romheader + ROMROMEND, 4);
memcpy (&rominfo.country, romheader + ROMCOUNTRY, 16);
/* Checksums */
#ifdef LSB_FIRST
rominfo.checksum = (rominfo.checksum >> 8) | ((rominfo.checksum & 0xff) << 8);
rominfo.checksum = (rominfo.checksum >> 8) | ((rominfo.checksum & 0xff) << 8);
#endif
rominfo.realchecksum = GetRealChecksum (((uint8 *) cart.rom) + 0x200, cart.romsize - 0x200);
rominfo.realchecksum = getchecksum(((uint8 *) cart.rom) + 0x200, cart.romsize - 0x200);
rominfo.peripherals = 0;
for (i = 0; i < 14; i++)
for (j=0; j < 14; j++)
if (romheader[ROMIOSUPPORT+i] == peripheralinfo[j].pID[0])
rominfo.peripherals |= (1 << j);
/* Supported peripherals */
rominfo.peripherals = 0;
for (i = 0; i < 14; i++)
for (j=0; j < 14; j++)
if (romheader[ROMIOSUPPORT+i] == peripheralinfo[j].pID[0])
rominfo.peripherals |= (1 << j);
}
}
/***************************************************************************
@ -273,28 +370,51 @@ static void deinterleave_block(uint8 * src)
***************************************************************************/
int load_rom(char *filename)
{
int i, size, offset = 0;
int i, size;
#ifdef NGC
size = cart.romsize;
sprintf(rom_filename,"%s",filename);
rom_filename[strlen(rom_filename) - 4] = 0;
#else
uint8 *ptr;
ptr = load_archive(filename, &size);
if(!ptr) return (0);
memcpy(cart.rom, ptr + offset, size);
memcpy(cart.rom, ptr, size);
free(ptr);
#endif
/* detect interleaved format (.SMD) */
/* Minimal ROM size */
if (size < 0x4000)
{
memset(cart.rom + size, 0xFF, 0x4000 - size);
size = 0x4000;
}
/* Get file extension */
if (!strnicmp(".sms", &filename[strlen(filename) - 4], 4))
{
/* Force SMS compatibility mode */
system_hw = SYSTEM_PBC;
}
else
{
/* Assume Genesis mode */
system_hw = SYSTEM_GENESIS;
}
/* Take care of 512 byte header, if present */
if (strncmp((char *)(cart.rom + 0x100),"SEGA", 4) && ((size / 512) & 1))
{
size -= 512;
offset += 512;
for (i = 0; i < (size / 0x4000); i += 1)
deinterleave_block (cart.rom + offset + (i * 0x4000));
memcpy(cart.rom, cart.rom + offset, size);
memcpy (cart.rom, cart.rom + 512, size);
/* interleaved ROM format (.smd) */
if (system_hw != SYSTEM_PBC)
{
for (i = 0; i < (size / 0x4000); i++)
{
deinterleave_block (cart.rom + (i * 0x4000));
}
}
}
/* max. 10 MBytes supported */
@ -307,27 +427,14 @@ int load_rom(char *filename)
/* get infos from ROM header */
getrominfo((char *)cart.rom);
/* get specific input devices */
input_autodetect();
/* get default region */
/* detect console region */
region_autodetect();
/* Genesis ROM specific */
if (system_hw != SYSTEM_PBC)
{
#ifdef LSB_FIRST
/* Byteswap ROM */
uint8 temp;
for(i = 0; i < size; i += 2)
{
temp = cart.rom[i];
cart.rom[i] = cart.rom[i+1];
cart.rom[i+1] = temp;
}
#endif
/* byteswapped RADICA dumps (from Haze) */
if (((strstr(rominfo.product,"-K0101") != NULL) && (rominfo.checksum == 0xf424)) ||
((strstr(rominfo.product,"-K0109") != NULL) && (rominfo.checksum == 0x4f10)))
{
/* Byteswap ROM */
uint8 temp;
for(i = 0; i < size; i += 2)
{
@ -335,15 +442,27 @@ int load_rom(char *filename)
cart.rom[i] = cart.rom[i+1];
cart.rom[i+1] = temp;
}
}
#endif
/* console hardware */
if (strstr(rominfo.consoletype, "SEGA PICO") != NULL)
system_hw = SYSTEM_PICO;
else if (strstr(rominfo.consoletype, "SEGA MEGADRIVE") != NULL)
system_hw = SYSTEM_MEGADRIVE;
else
system_hw = SYSTEM_GENESIS;
/* byteswapped RADICA dumps (from Haze) */
if (((strstr(rominfo.product,"-K0101") != NULL) && (rominfo.checksum == 0xf424)) ||
((strstr(rominfo.product,"-K0109") != NULL) && (rominfo.checksum == 0x4f10)))
{
uint8 temp;
for(i = 0; i < size; i += 2)
{
temp = cart.rom[i];
cart.rom[i] = cart.rom[i+1];
cart.rom[i+1] = temp;
}
}
/* PICO hardware */
if (strstr(rominfo.consoletype, "SEGA PICO") != NULL)
{
system_hw = SYSTEM_PICO;
}
}
return(1);
}
@ -356,83 +475,79 @@ int load_rom(char *filename)
****************************************************************************/
void region_autodetect(void)
{
/* country codes used to differentiate region */
/* 0001 = japan ntsc (1) */
/* 0010 = japan pal (2) */
/* 0100 = usa (4) */
/* 1000 = europe (8) */
int country = 0;
int i = 0;
char c;
/* reading header to find the country */
if (!strnicmp(rominfo.country, "eur", 3)) country |= 8;
else if (!strnicmp(rominfo.country, "usa", 3)) country |= 4;
else if (!strnicmp(rominfo.country, "jap", 3)) country |= 1;
else for(i = 0; i < 4; i++)
if (system_hw == SYSTEM_PBC)
{
c = toupper((int)rominfo.country[i]);
if (c == 'U') country |= 4;
else if (c == 'J') country |= 1;
else if (c == 'E') country |= 8;
else if (c == 'K') country |= 1;
else if (c < 16) country |= c;
else if ((c >= '0') && (c <= '9')) country |= c - '0';
else if ((c >= 'A') && (c <= 'F')) country |= c - 'A' + 10;
region_code = sms_cart_region_detect();
}
else
{
/* country codes used to differentiate region */
/* 0001 = japan ntsc (1) */
/* 0010 = japan pal (2) */
/* 0100 = usa (4) */
/* 1000 = europe (8) */
int country = 0;
int i = 0;
char c;
/* from Gens */
if (!strnicmp(rominfo.country, "eur", 3)) country |= 8;
else if (!strnicmp(rominfo.country, "usa", 3)) country |= 4;
else if (!strnicmp(rominfo.country, "jap", 3)) country |= 1;
else
{
/* look for each characters */
for(i = 0; i < 4; i++)
{
c = toupper((int)rominfo.country[i]);
if (c == 'U') country |= 4;
else if (c == 'J') country |= 1;
else if (c == 'E') country |= 8;
else if (c == 'K') country |= 1;
else if (c < 16) country |= c;
else if ((c >= '0') && (c <= '9')) country |= c - '0';
else if ((c >= 'A') && (c <= 'F')) country |= c - 'A' + 10;
}
}
/* set default console region (USA > JAPAN > EUROPE) */
if (country & 4) region_code = REGION_USA;
else if (country & 1) region_code = REGION_JAPAN_NTSC;
else if (country & 8) region_code = REGION_EUROPE;
else if (country & 2) region_code = REGION_JAPAN_PAL;
else region_code = REGION_USA;
/* some games need specific REGION setting */
if (((strstr(rominfo.product,"T-45033") != NULL) && (rominfo.checksum == 0x0F81)) || /* Alisia Dragon (Europe) */
(strstr(rominfo.product,"T-69046-50") != NULL) || /* Back to the Future III (Europe) */
(strstr(rominfo.product,"T-120106-00") != NULL) || /* Brian Lara Cricket (Europe) */
(strstr(rominfo.product,"T-70096 -00") != NULL)) /* Muhammad Ali Heavyweight Boxing (Europe) */
{
/* need PAL settings */
region_code = REGION_EUROPE;
}
if ((rominfo.realchecksum == 0x532e) && (strstr(rominfo.product,"1011-00") != NULL))
{
/* On Dal Jang Goon (Korea) needs JAPAN region code */
region_code = REGION_JAPAN_NTSC;
}
}
/* automatic detection */
/* setting region */
/* this is used by IO register */
if (country & 4) region_code = REGION_USA;
else if (country & 1) region_code = REGION_JAPAN_NTSC;
else if (country & 8) region_code = REGION_EUROPE;
else if (country & 2) region_code = REGION_JAPAN_PAL;
else region_code = REGION_USA;
/* forced console region */
if (config.region_detect == 1) region_code = REGION_USA;
else if (config.region_detect == 2) region_code = REGION_EUROPE;
else if (config.region_detect == 3) region_code = REGION_JAPAN_NTSC;
else if (config.region_detect == 4) region_code = REGION_JAPAN_PAL;
/* some games need specific REGION setting */
if (((strstr(rominfo.product,"T-45033") != NULL) && (rominfo.checksum == 0x0F81)) || /* Alisia Dragon (PAL) */
(strstr(rominfo.product,"T-69046-50") != NULL) || /* Back to the Future III (PAL) */
(strstr(rominfo.product,"T-120106-00") != NULL) || /* Brian Lara Cricket (PAL) */
(strstr(rominfo.product,"T-70096 -00") != NULL)) /* Muhammad Ali Heavyweight Boxing (PAL) */
{
/* need PAL settings */
region_code = REGION_EUROPE;
}
else if ((rominfo.realchecksum == 0x532e) && (strstr(rominfo.product,"1011-00") != NULL))
{
/* On Dal Jang Goon (Korea) needs JAP region code */
region_code = REGION_JAPAN_NTSC;
}
/* Force region setting */
if (config.region_detect == 1)
region_code = REGION_USA;
else if (config.region_detect == 2)
region_code = REGION_EUROPE;
else if (config.region_detect == 3)
region_code = REGION_JAPAN_NTSC;
else if (config.region_detect == 4)
region_code = REGION_JAPAN_PAL;
/* Set VDP default mode */
switch (region_code)
{
case REGION_EUROPE:
case REGION_JAPAN_PAL:
vdp_pal = 1;
break;
default:
vdp_pal = 0;
break;
}
/* PAL/NTSC timings */
vdp_pal = (region_code & REGION_JAPAN_PAL) >> 6;
}
/****************************************************************************
* get_company
* get_company (Softdev - 2006)
*
* Try to determine which company made this rom
*
@ -447,7 +562,9 @@ char *get_company(void)
char company[10];
for (i = 3; i < 8; i++)
{
company[i - 3] = rominfo.copyright[i];
}
company[5] = 0;
/** OK, first look for a hyphen
@ -466,19 +583,19 @@ char *get_company(void)
company[i] = 0;
if (strlen (company) == 0)
return companyinfo[MAXCOMPANY - 1].company;
return (char *)companyinfo[MAXCOMPANY - 1].company;
for (i = 0; i < MAXCOMPANY - 1; i++)
{
if (!(strncmp (company, companyinfo[i].companyid, strlen (company))))
return companyinfo[i].company;
return (char *)companyinfo[i].company;
}
return companyinfo[MAXCOMPANY - 1].company;
return (char *)companyinfo[MAXCOMPANY - 1].company;
}
/****************************************************************************
* get_peripheral
* get_peripheral (Softdev - 2006)
*
* Return peripheral name based on header code
*
@ -486,7 +603,7 @@ char *get_company(void)
char *get_peripheral(int index)
{
if (index < MAXPERIPHERALS)
return peripheralinfo[index].pName;
return companyinfo[MAXCOMPANY - 1].company;
return (char *)peripheralinfo[index].pName;
return (char *)companyinfo[MAXCOMPANY - 1].company;
}

View File

@ -381,7 +381,7 @@ unsigned int m68k_disassemble(char* str_buff, unsigned int pc, unsigned int cpu_
unsigned int m68k_disassemble_raw(char* str_buff, unsigned int pc, const unsigned char* opdata, const unsigned char* argdata, unsigned int cpu_type);
/*** Not really required, but makes for clean compile under DevkitPPC ***/
extern int vdp_int_ack_callback(int int_level);
extern int vdp_68k_irq_ack(int int_level);
/* ======================================================================== */
/* ============================== MAME STUFF ============================== */

View File

@ -82,7 +82,7 @@
* auto-clear when the interrupt is serviced.
*/
#define M68K_EMULATE_INT_ACK OPT_SPECIFY_HANDLER
#define M68K_INT_ACK_CALLBACK(A) vdp_int_ack_callback(A)
#define M68K_INT_ACK_CALLBACK(A) vdp_68k_irq_ack(A)
/* If ON, CPU will call the breakpoint acknowledge callback when it encounters

View File

@ -846,7 +846,7 @@ void m68k_set_irq(unsigned int int_level)
extern uint16 v_counter;
extern void error(char *format, ...);
#endif
extern uint8 irq_status;
extern uint8 m68k_irq_state;
void m68k_run (unsigned int cycles)
{
@ -856,13 +856,13 @@ void m68k_run (unsigned int cycles)
while (mcycles_68k < cycles)
{
/* check IRQ triggering */
if (irq_status & 0x10)
if (m68k_irq_state & 0x10)
{
irq_status &= ~0x10;
CPU_INT_LEVEL = (irq_status & 6) << 8;
m68k_irq_state &= ~0x10;
CPU_INT_LEVEL = (m68k_irq_state & 6) << 8;
/* IRQ was triggered during previous instruction */
if (irq_status & 0x20)
if (m68k_irq_state & 0x20)
{
/* one instruction latency */
REG_IR = m68ki_read_imm_16();

View File

@ -1451,9 +1451,13 @@ INLINE void m68ki_jump(uint new_pc)
INLINE void m68ki_jump_vector(uint vector)
{
#if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
REG_PC = (vector<<2) + REG_VBR;
REG_PC = m68ki_read_data_32(REG_PC);
#else
REG_PC = m68ki_read_data_32(vector<<2);
m68ki_pc_changed(REG_PC);
#endif
}
@ -1993,10 +1997,6 @@ INLINE void m68ki_exception_address_error(void)
/* Service an interrupt request and start exception processing */
INLINE void m68ki_exception_interrupt(uint int_level)
{
uint vector;
uint sr;
uint new_pc;
#if M68K_EMULATE_ADDRESS_ERROR == OPT_ON
if(CPU_TYPE_IS_000(CPU_TYPE))
{
@ -2012,30 +2012,23 @@ INLINE void m68ki_exception_interrupt(uint int_level)
return;
/* Acknowledge the interrupt */
vector = m68ki_int_ack(int_level);
m68ki_int_ack(int_level);
/* Get the interrupt vector */
if(vector == M68K_INT_ACK_AUTOVECTOR)
/* Use the autovectors. This is the most commonly used implementation */
vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
else if(vector == M68K_INT_ACK_SPURIOUS)
/* Called if no devices respond to the interrupt acknowledge */
vector = EXCEPTION_SPURIOUS_INTERRUPT;
else if(vector > 255)
{
M68K_DO_LOG_EMU((M68K_LOG_FILEHANDLE "%s at %08x: Interrupt acknowledge returned invalid vector $%x\n",
m68ki_cpu_names[CPU_TYPE], ADDRESS_68K(REG_PC), vector));
return;
}
/* Always use the autovectors. */
uint vector = EXCEPTION_INTERRUPT_AUTOVECTOR+int_level;
/* Start exception processing */
sr = m68ki_init_exception();
uint sr = m68ki_init_exception();
/* Set the interrupt mask to the level of the one being serviced */
FLAG_INT_MASK = int_level<<8;
/* Get the new PC */
new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
#if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
uint new_pc = m68ki_read_data_32((vector<<2) + REG_VBR);
#else
uint new_pc = m68ki_read_data_32(vector<<2);
#endif
/* If vector is uninitialized, call the uninitialized interrupt vector */
if(new_pc == 0)
@ -2043,6 +2036,7 @@ INLINE void m68ki_exception_interrupt(uint int_level)
/* Generate a stack frame */
m68ki_stack_frame_0000(REG_PC, sr, vector);
#if M68K_EMULATE_040 || M68K_EMULATE_020 || M68K_EMULATE_EC020 || M68K_EMULATE_010
if(FLAG_M && CPU_TYPE_IS_EC020_PLUS(CPU_TYPE))
{
/* Create throwaway frame */
@ -2050,6 +2044,7 @@ INLINE void m68ki_exception_interrupt(uint int_level)
sr |= 0x2000; /* Same as SR in master stack frame except S is forced high */
m68ki_stack_frame_0001(REG_PC, sr, vector);
}
#endif
m68ki_jump(new_pc);

View File

@ -1,6 +1,6 @@
/***************************************************************************************
* Genesis Plus
* 68k bus address decoding
* 68k bus controller
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
@ -124,7 +124,7 @@ unsigned int eeprom_read_byte(unsigned int address)
unsigned int eeprom_read_word(unsigned int address)
{
if (address == (eeprom.type.sda_out_adr & 0xfffffe))
if (address == (eeprom.type.sda_out_adr & 0xFFFFFE))
{
return eeprom_read(1);
}
@ -143,7 +143,7 @@ void eeprom_write_byte(unsigned int address, unsigned int data)
void eeprom_write_word(unsigned int address, unsigned int data)
{
if ((address == (eeprom.type.sda_in_adr & 0xfffffe)) || (address == (eeprom.type.scl_adr & 0xfffffe)))
if ((address == (eeprom.type.sda_in_adr & 0xFFFFFE)) || (address == (eeprom.type.scl_adr & 0xFFFFFE)))
{
eeprom_write(address, data, 1);
return;
@ -166,17 +166,17 @@ unsigned int z80_read_byte(unsigned int address)
case 3: /* Misc */
{
if ((address & 0xff00) == 0x7f00)
if ((address & 0xFF00) == 0x7F00)
{
/* VDP (through 68k bus) */
return m68k_lockup_r_8(address);
}
return (m68k_read_bus_8(address) | 0xff);
return (m68k_read_bus_8(address) | 0xFF);
}
default: /* ZRAM */
{
return zram[address & 0x1fff];
return zram[address & 0x1FFF];
}
}
}
@ -199,7 +199,7 @@ void z80_write_byte(unsigned int address, unsigned int data)
case 3:
{
switch ((address >> 8) & 0x7f)
switch ((address >> 8) & 0x7F)
{
case 0x60: /* Bank register */
{
@ -207,7 +207,7 @@ void z80_write_byte(unsigned int address, unsigned int data)
return;
}
case 0x7f: /* VDP */
case 0x7F: /* VDP */
{
m68k_lockup_w_8(address, data);
return;
@ -223,7 +223,7 @@ void z80_write_byte(unsigned int address, unsigned int data)
default: /* ZRAM */
{
zram[address & 0x1fff] = data;
zram[address & 0x1FFF] = data;
mcycles_68k += 8; /* ZRAM access latency (fixes Pacman 2: New Adventures) */
return;
}
@ -241,13 +241,13 @@ void z80_write_word(unsigned int address, unsigned int data)
/*--------------------------------------------------------------------------*/
unsigned int ctrl_io_read_byte(unsigned int address)
{
switch ((address >> 8) & 0xff)
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
{
if (!(address & 0xe0))
if (!(address & 0xE0))
{
return io_read((address >> 1) & 0x0f);
return io_68k_read((address >> 1) & 0x0F);
}
return m68k_read_bus_8(address);
}
@ -256,7 +256,7 @@ unsigned int ctrl_io_read_byte(unsigned int address)
{
if (!(address & 1))
{
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xfe;
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xFE;
if (zstate == 3)
{
return data;
@ -273,7 +273,7 @@ unsigned int ctrl_io_read_byte(unsigned int address)
unsigned int data = cart.hw.time_r(address);
if (address & 1)
{
return (data & 0xff);
return (data & 0xFF);
}
return (data >> 8);
}
@ -284,7 +284,7 @@ unsigned int ctrl_io_read_byte(unsigned int address)
{
if (address & 1)
{
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xfe;
unsigned int data = m68k_read_pcrelative_8(REG_PC) & 0xFE;
return (gen_bankswitch_r() | data);
}
return m68k_read_bus_8(address);
@ -309,13 +309,13 @@ unsigned int ctrl_io_read_byte(unsigned int address)
unsigned int ctrl_io_read_word(unsigned int address)
{
switch ((address >> 8) & 0xff)
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
{
if (!(address & 0xe0))
if (!(address & 0xE0))
{
unsigned int data = io_read((address >> 1) & 0x0f);
unsigned int data = io_68k_read((address >> 1) & 0x0F);
return (data << 8 | data);
}
return m68k_read_bus_16(address);
@ -323,7 +323,7 @@ unsigned int ctrl_io_read_word(unsigned int address)
case 0x11: /* BUSACK */
{
unsigned int data = m68k_read_pcrelative_16(REG_PC) & 0xfeff;
unsigned int data = m68k_read_pcrelative_16(REG_PC) & 0xFEFF;
if (zstate == 3)
{
return data;
@ -342,12 +342,12 @@ unsigned int ctrl_io_read_word(unsigned int address)
case 0x50: /* SVP */
{
if ((address & 0xfd) == 0)
if ((address & 0xFD) == 0)
{
return svp->ssp1601.gr[SSP_XST].h;
}
if ((address & 0xff) == 4)
if ((address & 0xFF) == 4)
{
unsigned int data = svp->ssp1601.gr[SSP_PM0].h;
svp->ssp1601.gr[SSP_PM0].h &= ~1;
@ -376,14 +376,14 @@ unsigned int ctrl_io_read_word(unsigned int address)
void ctrl_io_write_byte(unsigned int address, unsigned int data)
{
switch ((address >> 8) & 0xff)
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
{
if ((address & 0xe1) == 0x01)
if ((address & 0xE1) == 0x01)
{
/* get /LWR only */
io_write((address >> 1) & 0x0f, data);
io_68k_write((address >> 1) & 0x0F, data);
return;
}
m68k_unused_8_w(address, data);
@ -449,13 +449,13 @@ void ctrl_io_write_byte(unsigned int address, unsigned int data)
void ctrl_io_write_word(unsigned int address, unsigned int data)
{
switch ((address >> 8) & 0xff)
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
{
if (!(address & 0xe0))
if (!(address & 0xE0))
{
io_write((address >> 1) & 0x0f, data & 0xff);
io_68k_write((address >> 1) & 0x0F, data & 0xFF);
return;
}
m68k_unused_16_w(address, data);
@ -493,7 +493,7 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
case 0x50: /* SVP REGISTERS */
{
if (!(address & 0xfd))
if (!(address & 0xFD))
{
svp->ssp1601.gr[SSP_XST].h = data;
svp->ssp1601.gr[SSP_PM0].h |= 2;
@ -527,44 +527,44 @@ void ctrl_io_write_word(unsigned int address, unsigned int data)
/*--------------------------------------------------------------------------*/
unsigned int vdp_read_byte(unsigned int address)
{
switch (address & 0xfd)
switch (address & 0xFD)
{
case 0x00: /* DATA */
{
return (vdp_data_r() >> 8);
return (vdp_68k_data_r() >> 8);
}
case 0x01: /* DATA */
{
return (vdp_data_r() & 0xff);
return (vdp_68k_data_r() & 0xFF);
}
case 0x04: /* CTRL */
{
return (((vdp_ctrl_r(mcycles_68k) >> 8) & 3) | (m68k_read_pcrelative_8(REG_PC) & 0xfc));
return (((vdp_ctrl_r(mcycles_68k) >> 8) & 3) | (m68k_read_pcrelative_8(REG_PC) & 0xFC));
}
case 0x05: /* CTRL */
{
return (vdp_ctrl_r(mcycles_68k) & 0xff);
return (vdp_ctrl_r(mcycles_68k) & 0xFF);
}
case 0x08: /* HVC */
case 0x0c:
case 0x0C:
{
return (vdp_hvc_r(mcycles_68k) >> 8);
}
case 0x09: /* HVC */
case 0x0d:
case 0x0D:
{
return (vdp_hvc_r(mcycles_68k) & 0xff);
return (vdp_hvc_r(mcycles_68k) & 0xFF);
}
case 0x18: /* Unused */
case 0x19:
case 0x1c:
case 0x1d:
case 0x1C:
case 0x1D:
{
return m68k_read_bus_8(address);
}
@ -578,11 +578,11 @@ unsigned int vdp_read_byte(unsigned int address)
unsigned int vdp_read_word(unsigned int address)
{
switch (address & 0xfc)
switch (address & 0xFC)
{
case 0x00: /* DATA */
{
return vdp_data_r();
return vdp_68k_data_r();
}
case 0x04: /* CTRL */
@ -591,13 +591,13 @@ unsigned int vdp_read_word(unsigned int address)
}
case 0x08: /* HVC */
case 0x0c:
case 0x0C:
{
return vdp_hvc_r(mcycles_68k);
}
case 0x18: /* Unused */
case 0x1c:
case 0x1C:
{
return m68k_read_bus_16(address);
}
@ -611,17 +611,17 @@ unsigned int vdp_read_word(unsigned int address)
void vdp_write_byte(unsigned int address, unsigned int data)
{
switch (address & 0xfc)
switch (address & 0xFC)
{
case 0x00: /* Data port */
{
vdp_data_w(data << 8 | data);
vdp_68k_data_w(data << 8 | data);
return;
}
case 0x04: /* Control port */
{
vdp_ctrl_w(data << 8 | data);
vdp_68k_ctrl_w(data << 8 | data);
return;
}
@ -643,7 +643,7 @@ void vdp_write_byte(unsigned int address, unsigned int data)
return;
}
case 0x1c: /* TEST register */
case 0x1C: /* TEST register */
{
vdp_test_w(data << 8 | data);
return;
@ -659,24 +659,24 @@ void vdp_write_byte(unsigned int address, unsigned int data)
void vdp_write_word(unsigned int address, unsigned int data)
{
switch (address & 0xfc)
switch (address & 0xFC)
{
case 0x00: /* DATA */
{
vdp_data_w(data);
vdp_68k_data_w(data);
return;
}
case 0x04: /* CTRL */
{
vdp_ctrl_w(data);
vdp_68k_ctrl_w(data);
return;
}
case 0x10: /* PSG */
case 0x14:
{
psg_write(mcycles_68k, data & 0xff);
psg_write(mcycles_68k, data & 0xFF);
return;
}
@ -686,7 +686,7 @@ void vdp_write_word(unsigned int address, unsigned int data)
return;
}
case 0x1c: /* Test register */
case 0x1C: /* Test register */
{
vdp_test_w(data);
return;
@ -706,7 +706,7 @@ void vdp_write_word(unsigned int address, unsigned int data)
unsigned int pico_read_byte(unsigned int address)
{
/* PICO */
switch (address & 0xff)
switch (address & 0xFF)
{
case 0x01: /* VERSION register */
{
@ -715,7 +715,7 @@ unsigned int pico_read_byte(unsigned int address)
case 0x03: /* IO register */
{
unsigned int retval = 0xff;
unsigned int retval = 0xFF;
if (input.pad[0] & INPUT_B) retval &= ~0x10;
if (input.pad[0] & INPUT_A) retval &= ~0x80;
if (input.pad[0] & INPUT_UP) retval &= ~0x01;
@ -734,7 +734,7 @@ unsigned int pico_read_byte(unsigned int address)
case 0x07: /* LSB PEN X coordinate */
{
return (input.analog[0][0] & 0xff);
return (input.analog[0][0] & 0xFF);
}
case 0x09: /* MSB PEN Y coordinate */
@ -742,12 +742,12 @@ unsigned int pico_read_byte(unsigned int address)
return (input.analog[0][1] >> 8);
}
case 0x0b: /* LSB PEN Y coordinate */
case 0x0B: /* LSB PEN Y coordinate */
{
return (input.analog[0][1] & 0xff);
return (input.analog[0][1] & 0xFF);
}
case 0x0d: /* PAGE register (TODO) */
case 0x0D: /* PAGE register (TODO) */
{
return pico_page[pico_current];
}

View File

@ -1,6 +1,6 @@
/***************************************************************************************
* Genesis Plus
* 68k bus arbitration
* 68k bus controller
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port

View File

@ -30,9 +30,9 @@
unsigned int zbank_unused_r(unsigned int address)
{
#ifdef LOGERROR
error("Z80 bank unused read %06X\n", address);
error("Z80 bank unused read %06X (%x)\n", address, Z80.pc.d);
#endif
return (address & 1) ? 0x00 : 0xff;
return (address & 1) ? 0x00 : 0xFF;
}
void zbank_unused_w(unsigned int address, unsigned int data)
@ -45,24 +45,24 @@ void zbank_unused_w(unsigned int address, unsigned int data)
unsigned int zbank_lockup_r(unsigned int address)
{
#ifdef LOGERROR
error("Z80 bank lockup read %06X\n", address);
error("Z80 bank lockup read %06X (%x)\n", address, Z80.pc.d);
#endif
if (!config.force_dtack)
{
mcycles_z80 = 0xffffffff;
mcycles_z80 = 0xFFFFFFFF;
zstate = 0;
}
return 0xff;
return 0xFF;
}
void zbank_lockup_w(unsigned int address, unsigned int data)
{
#ifdef LOGERROR
error("Z80 bank lockup write %06X = %02X\n", address, data);
error("Z80 bank lockup write %06X = %02X (%x)\n", address, data, Z80.pc.d);
#endif
if (!config.force_dtack)
{
mcycles_z80 = 0xffffffff;
mcycles_z80 = 0xFFFFFFFF;
zstate = 0;
}
}
@ -70,13 +70,13 @@ void zbank_lockup_w(unsigned int address, unsigned int data)
/* I/O & Control registers */
unsigned int zbank_read_ctrl_io(unsigned int address)
{
switch ((address >> 8) & 0xff)
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
{
if (!(address & 0xe0))
if (!(address & 0xE0))
{
return (io_read((address >> 1) & 0x0f));
return (io_68k_read((address >> 1) & 0x0F));
}
return zbank_unused_r(address);
}
@ -87,7 +87,7 @@ unsigned int zbank_read_ctrl_io(unsigned int address)
{
return zbank_unused_r(address);
}
return 0xff;
return 0xFF;
}
case 0x30: /* TIME */
@ -97,7 +97,7 @@ unsigned int zbank_read_ctrl_io(unsigned int address)
unsigned int data = cart.hw.time_r(address);
if (address & 1)
{
return (data & 0xff);
return (data & 0xFF);
}
return (data >> 8);
}
@ -108,7 +108,7 @@ unsigned int zbank_read_ctrl_io(unsigned int address)
{
if (address & 1)
{
return (gen_bankswitch_r() | 0xfe);
return (gen_bankswitch_r() | 0xFE);
}
return zbank_unused_r(address);
}
@ -132,14 +132,14 @@ unsigned int zbank_read_ctrl_io(unsigned int address)
void zbank_write_ctrl_io(unsigned int address, unsigned int data)
{
switch ((address >> 8) & 0xff)
switch ((address >> 8) & 0xFF)
{
case 0x00: /* I/O chip */
{
/* get /LWR only */
if ((address & 0xe1) == 0x01)
if ((address & 0xE1) == 0x01)
{
io_write((address >> 1) & 0x0f, data);
io_68k_write((address >> 1) & 0x0F, data);
return;
}
zbank_unused_w(address, data);
@ -207,44 +207,44 @@ void zbank_write_ctrl_io(unsigned int address, unsigned int data)
/* VDP */
unsigned int zbank_read_vdp(unsigned int address)
{
switch (address & 0xfd)
switch (address & 0xFD)
{
case 0x00: /* DATA */
{
return (vdp_data_r() >> 8);
return (vdp_68k_data_r() >> 8);
}
case 0x01: /* DATA */
{
return (vdp_data_r() & 0xff);
return (vdp_68k_data_r() & 0xFF);
}
case 0x04: /* CTRL */
{
return (((vdp_ctrl_r(mcycles_z80) >> 8) & 3) | 0xfc);
return (((vdp_ctrl_r(mcycles_z80) >> 8) & 3) | 0xFC);
}
case 0x05: /* CTRL */
{
return (vdp_ctrl_r(mcycles_z80) & 0xff);
return (vdp_ctrl_r(mcycles_z80) & 0xFF);
}
case 0x08: /* HVC */
case 0x0c:
case 0x0C:
{
return (vdp_hvc_r(mcycles_z80) >> 8);
}
case 0x09: /* HVC */
case 0x0d:
case 0x0D:
{
return (vdp_hvc_r(mcycles_z80) & 0xff);
return (vdp_hvc_r(mcycles_z80) & 0xFF);
}
case 0x18: /* Unused */
case 0x19:
case 0x1c:
case 0x1d:
case 0x1C:
case 0x1D:
{
return zbank_unused_r(address);
}
@ -258,17 +258,17 @@ unsigned int zbank_read_vdp(unsigned int address)
void zbank_write_vdp(unsigned int address, unsigned int data)
{
switch (address & 0xfc)
switch (address & 0xFC)
{
case 0x00: /* Data port */
{
vdp_data_w(data << 8 | data);
vdp_68k_data_w(data << 8 | data);
return;
}
case 0x04: /* Control port */
{
vdp_ctrl_w(data << 8 | data);
vdp_68k_ctrl_w(data << 8 | data);
return;
}
@ -290,7 +290,7 @@ void zbank_write_vdp(unsigned int address, unsigned int data)
return;
}
case 0x1c: /* TEST register */
case 0x1C: /* TEST register */
{
vdp_test_w(data << 8 | data);
return;

View File

@ -1,6 +1,6 @@
/***************************************************************************************
* Genesis Plus
* 68k bus banked access from Z80
* Z80 bank access to 68k bus
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* Z80 bus address decoding (Genesis mode)
* Z80 bus controller (MD & MS compatibility modes)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
@ -22,104 +22,106 @@
****************************************************************************************/
#include "shared.h"
/*
Handlers for access to unused addresses and those which make the
machine lock up.
*/
static inline void z80_unused_w(unsigned int address, unsigned int data)
/*--------------------------------------------------------------------------*/
/* Handlers for access to unused addresses and those which make the */
/* machine lock up. */
/*--------------------------------------------------------------------------*/
static inline void z80_unused_w(unsigned int address, unsigned char data)
{
#ifdef LOGERROR
error("Z80 unused write %04X = %02X\n", address, data);
error("Z80 unused write %04X = %02X (%x)\n", address, data, Z80.pc.w.l);
#endif
}
static inline unsigned int z80_unused_r(unsigned int address)
static inline unsigned char z80_unused_r(unsigned int address)
{
#ifdef LOGERROR
error("Z80 unused read %04X\n", address);
error("Z80 unused read %04X (%x)\n", address, Z80.pc.w.l);
#endif
return 0xff;
return 0xFF;
}
static inline void z80_lockup_w(unsigned int address, unsigned int data)
static inline void z80_lockup_w(unsigned int address, unsigned char data)
{
#ifdef LOGERROR
error("Z80 lockup write %04X = %02X\n", address, data);
error("Z80 lockup write %04X = %02X (%x)\n", address, data, Z80.pc.w.l);
#endif
if (!config.force_dtack)
{
mcycles_z80 = 0xffffffff;
mcycles_z80 = 0xFFFFFFFF;
zstate = 0;
}
}
static inline unsigned int z80_lockup_r(unsigned int address)
static inline unsigned char z80_lockup_r(unsigned int address)
{
#ifdef LOGERROR
error("Z80 lockup read %04X\n", address);
error("Z80 lockup read %04X (%x)\n", address, Z80.pc);
#endif
if (!config.force_dtack)
{
mcycles_z80 = 0xffffffff;
mcycles_z80 = 0xFFFFFFFF;
zstate = 0;
}
return 0xff;
return 0xFF;
}
/*
Z80 memory handlers
*/
unsigned int cpu_readmem16(unsigned int address)
/*--------------------------------------------------------------------------*/
/* Z80 Memory handlers (Genesis mode) */
/*--------------------------------------------------------------------------*/
unsigned char z80_md_memory_r(unsigned int address)
{
switch((address >> 13) & 7)
{
case 0: /* Work RAM */
case 0: /* $0000-$3FFF: Z80 RAM (8K mirrored) */
case 1:
{
return zram[address & 0x1fff];
return zram[address & 0x1FFF];
}
case 2: /* YM2612 */
case 2: /* $4000-$5FFF: YM2612 */
{
return fm_read(mcycles_68k, address & 3);
return fm_read(mcycles_z80, address & 3);
}
case 3: /* VDP */
case 3: /* $7F00-$7FFF: VDP */
{
if ((address >> 8) == 0x7f)
if ((address >> 8) == 0x7F)
{
return (*zbank_memory_map[0xc0].read)(address);
}
return z80_unused_r(address);
}
default: /* V-bus bank */
default: /* $8000-$FFFF: 68k bank (32K) */
{
address = zbank | (address & 0x7fff);
address = zbank | (address & 0x7FFF);
unsigned int slot = address >> 16;
if (zbank_memory_map[slot].read)
{
return (*zbank_memory_map[slot].read)(address);
}
return READ_BYTE(m68k_memory_map[slot].base, address & 0xffff);
return READ_BYTE(m68k_memory_map[slot].base, address & 0xFFFF);
}
}
}
void cpu_writemem16(unsigned int address, unsigned int data)
void z80_md_memory_w(unsigned int address, unsigned char data)
{
switch((address >> 13) & 7)
{
case 0: /* Work RAM */
case 0: /* $0000-$3FFF: Z80 RAM (8K mirrored) */
case 1:
{
zram[address & 0x1fff] = data;
zram[address & 0x1FFF] = data;
return;
}
case 2: /* YM2612 */
case 2: /* $4000-$5FFF: YM2612 */
{
fm_write(mcycles_z80, address & 3, data);
return;
@ -129,13 +131,13 @@ void cpu_writemem16(unsigned int address, unsigned int data)
{
switch(address >> 8)
{
case 0x60:
case 0x60: /* $6000-$60FF: Bank register */
{
gen_zbank_w(data & 1);
return;
}
case 0x7f:
case 0x7F: /* $7F00-$7FFF: VDP */
{
(*zbank_memory_map[0xc0].write)(address, data);
return;
@ -149,39 +151,146 @@ void cpu_writemem16(unsigned int address, unsigned int data)
}
}
default: /* V-bus bank */
default: /* $8000-$FFFF: 68k bank (32K) */
{
address = zbank | (address & 0x7fff);
address = zbank | (address & 0x7FFF);
unsigned int slot = address >> 16;
if (zbank_memory_map[slot].write)
{
(*zbank_memory_map[slot].write)(address, data);
return;
}
WRITE_BYTE(m68k_memory_map[slot].base, address & 0xffff, data);
WRITE_BYTE(m68k_memory_map[slot].base, address & 0xFFFF, data);
return;
}
}
}
/*
Port handlers. Ports are unused when not in Mark III compatability mode.
Games that access ports anyway:
/*--------------------------------------------------------------------------*/
/* Z80 Memory handlers (Master System mode) */
/*--------------------------------------------------------------------------*/
unsigned char z80_sms_memory_r(unsigned int address)
{
return z80_readmap[(address) >> 10][(address) & 0x03FF];
}
/*--------------------------------------------------------------------------*/
/* Z80 Port handlers */
/*--------------------------------------------------------------------------*/
/*
Ports are unused when not in Mark III compatibility mode.
Genesis games that access ports anyway:
Thunder Force IV reads port $BF in it's interrupt handler.
*/
unsigned int cpu_readport16(unsigned int port)
unsigned char z80_unused_port_r(unsigned int port)
{
#if LOGERROR
error("Z80 read port %04X\n", port);
error("Z80 unused read from port %04X (%x)\n", port, Z80.pc.w.l);
#endif
return 0xff;
return 0xFF;
}
void cpu_writeport16(unsigned int port, unsigned int data)
void z80_unused_port_w(unsigned int port, unsigned char data)
{
#if LOGERROR
error("Z80 write %02X to port %04X\n", data, port);
error("Z80 unused write to port %04X = %02X (%x)\n", port, data, Z80.pc.w.l);
#endif
}
void z80_sms_port_w(unsigned int port, unsigned char data)
{
switch (port & 0xC1)
{
case 0x01:
{
io_z80_write(data);
return;
}
case 0x40:
case 0x41:
{
psg_write(mcycles_z80, data);
return;
}
case 0x80:
{
vdp_z80_data_w(data);
return;
}
case 0x81:
{
vdp_z80_ctrl_w(data);
return;
}
default:
{
if ((port & 0xFF) == 0x3E)
{
/* Memory Control Register */
/* NB: this register does not exist on MD hardware but is partially emulated to support BIOS ROM image files */
if (data & 0x40)
{
/* Assume only BIOS would disable Cartridge ROM */
if (data & 0x08)
{
/* BIOS ROM disabled */
sms_cart_switch(0);
}
else
{
/* BIOS ROM enabled */
sms_cart_switch(1);
}
}
return;
}
z80_unused_port_w(port, data);
return;
}
}
}
unsigned char z80_sms_port_r(unsigned int port)
{
switch (port & 0xC1)
{
case 0x40:
{
return ((vdp_hvc_r(mcycles_z80) >> 8) & 0xFF);
}
case 0x41:
{
return (vdp_hvc_r(mcycles_z80) & 0xFF);
}
case 0x80:
{
return vdp_z80_data_r();
}
case 0x81:
{
return (vdp_ctrl_r(mcycles_z80) & 0xFF);
}
default:
{
port &= 0xFF;
if ((port == 0xC0) || (port == 0xC1) || (port == 0xDC) || (port == 0xDD) || (port == 0xDE) || (port == 0xDF))
{
return io_z80_read(port & 1);
}
return z80_unused_port_r(port);
}
}
}

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* Z80 bus arbitration (Genesis mode)
* Z80 bus controller (MD & MS compatibility mode)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
@ -23,9 +23,13 @@
#ifndef _MEMZ80_H_
#define _MEMZ80_H_
extern unsigned int cpu_readmem16(unsigned int address);
extern void cpu_writemem16(unsigned int address, unsigned int data);
extern unsigned int cpu_readport16(unsigned int port);
extern void cpu_writeport16(unsigned int port, unsigned int data);
extern unsigned char z80_md_memory_r(unsigned int address);
extern void z80_md_memory_w(unsigned int address, unsigned char data);
extern unsigned char z80_sms_memory_r(unsigned int address);
extern unsigned char z80_unused_port_r(unsigned int port);
extern void z80_unused_port_w(unsigned int port, unsigned char data);
extern unsigned char z80_sms_port_r(unsigned int port);
extern void z80_sms_port_w(unsigned int port, unsigned char data);
#endif /* _MEMZ80_H_ */

View File

@ -1,6 +1,7 @@
/* md_ntsc 0.1.2. http://www.slack.net/~ant/ */
/* Added a custom blitter to double the height md_ntsc_blit_y2 -- AamirM */
/* Added a custom blitter to work with Genesis Plus GX -- EkeEke*/
#include "shared.h"
#include "md_ntsc.h"

View File

@ -14,6 +14,8 @@ details. You should have received a copy of the GNU Lesser General Public
License along with this module; if not, write to the Free Software Foundation,
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
/* Added a custom blitter to work with Genesis Plus GX -- EkeEke*/
sms_ntsc_setup_t const sms_ntsc_monochrome = { 0,-1, 0, 0,.2, 0, .2,-.2,-.2,-1, 0, 0 };
sms_ntsc_setup_t const sms_ntsc_composite = { 0, 0, 0, 0, 0, 0,.25, 0, 0, 0, 0, 0 };
sms_ntsc_setup_t const sms_ntsc_svideo = { 0, 0, 0, 0, 0, 0,.25, -1, -1, 0, 0, 0 };

View File

@ -11,19 +11,20 @@
#include "z80.h"
#include "system.h"
#include "genesis.h"
#include "vdp.h"
#include "render.h"
#include "vdp_ctrl.h"
#include "vdp_render.h"
#include "mem68k.h"
#include "memz80.h"
#include "membnk.h"
#include "gen_io.h"
#include "gen_input.h"
#include "io_ctrl.h"
#include "input.h"
#include "state.h"
#include "sound.h"
#include "sn76489.h"
#include "ym2612.h"
#include "loadrom.h"
#include "cart_hw.h"
#include "sms_cart.h"
#include "md_cart.h"
#include "eeprom.h"
#include "sram.h"
#include "ggenie.h"

View File

@ -87,7 +87,7 @@ int Fir_Resampler_avail()
end_pos -= WIDTH * STEREO;
do
{
count++;
count++;
remain--;
in += (skip * STEREO) & STEREO;
skip >>= 1;
@ -257,10 +257,10 @@ int Fir_Resampler_read( sample_t* out, long count )
end_pos -= WIDTH * STEREO;
do
{
count--;
count--;
if ( count < 0 )
break;
if ( count < 0 )
break;
/* accumulate in extended precision */
l = 0;

View File

@ -2,7 +2,6 @@
#include "blip.h"
//#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stddef.h>
@ -29,135 +28,128 @@ typedef int buf_t; /* type of element in delta buffer */
struct blip_buffer_t
{
int factor; /* clocks to samples conversion factor */
int offset; /* fractional position of clock 0 in delta buffer */
int amp; /* current output amplitude (sum of all deltas up to now) */
int size; /* size of delta buffer */
buf_t buf [65536]; /* delta buffer, only size elements actually allocated */
int factor; /* clocks to samples conversion factor */
int offset; /* fractional position of clock 0 in delta buffer */
int amp; /* current output amplitude (sum of all deltas up to now) */
int size; /* size of delta buffer */
buf_t buf [65536]; /* delta buffer, only size elements actually allocated */
};
blip_buffer_t* blip_alloc( double clock_rate, double sample_rate, int size )
{
/* Allocate space for structure and delta buffer */
blip_buffer_t* s = (blip_buffer_t*) malloc(
offsetof (blip_buffer_t, buf) + (size + buf_extra) * sizeof (buf_t) );
if ( s != NULL )
{
/* Calculate output:input ratio and convert to fixed-point */
double ratio = sample_rate / clock_rate;
s->factor = (int) (ratio * time_unit + 0.5);
/* Allocate space for structure and delta buffer */
blip_buffer_t* s = (blip_buffer_t*) malloc(
offsetof (blip_buffer_t, buf) + (size + buf_extra) * sizeof (buf_t) );
if ( s != NULL )
{
/* Calculate output:input ratio and convert to fixed-point */
double ratio = sample_rate / clock_rate;
s->factor = (int) (ratio * time_unit + 0.5);
s->size = size;
blip_clear( s );
}
return s;
s->size = size;
blip_clear( s );
}
return s;
}
void blip_free( blip_buffer_t* s )
{
free( s );
free( s );
}
void blip_clear( blip_buffer_t* s )
{
s->offset = 0;
s->amp = 0;
memset( s->buf, 0, (s->size + buf_extra) * sizeof (buf_t) );
s->offset = 0;
s->amp = 0;
memset( s->buf, 0, (s->size + buf_extra) * sizeof (buf_t) );
}
void blip_add( blip_buffer_t* s, int clocks, int delta )
{
/* Convert to fixed-point time in terms of output samples */
int fixed_time = clocks * s->factor + s->offset;
/* Convert to fixed-point time in terms of output samples */
int fixed_time = clocks * s->factor + s->offset;
/* Extract whole and fractional parts */
int index = fixed_time >> time_bits; /* whole */
int phase = fixed_time >> phase_shift & (phase_count - 1); /* fraction */
/* Extract whole and fractional parts */
int index = fixed_time >> time_bits; /* whole */
int phase = fixed_time >> phase_shift & (phase_count - 1); /* fraction */
/* Split delta between first and second samples */
int second = delta * phase;
int first = delta * phase_count - second;
/* Split delta between first and second samples */
int second = delta * phase;
int first = delta * phase_count - second;
/* Be sure index is within buffer */
//assert( index >= 0 && index+1 < s->size + buf_extra );
/* Add deltas to buffer */
s->buf [index ] += first;
s->buf [index+1] += second;
/* Add deltas to buffer */
s->buf [index ] += first;
s->buf [index+1] += second;
}
int blip_clocks_needed( const blip_buffer_t* s, int samples )
{
int fixed_needed;
if ( samples > s->size )
samples = s->size;
int fixed_needed;
if ( samples > s->size )
samples = s->size;
/* Fixed-point number of samples needed in addition to those in buffer */
fixed_needed = samples * time_unit - s->offset;
/* Fixed-point number of samples needed in addition to those in buffer */
fixed_needed = samples * time_unit - s->offset;
/* If more are needed, convert to clocks and round up */
return (fixed_needed <= 0) ? 0 : (fixed_needed - 1) / s->factor + 1;
/* If more are needed, convert to clocks and round up */
return (fixed_needed <= 0) ? 0 : (fixed_needed - 1) / s->factor + 1;
}
void blip_end_frame( blip_buffer_t* s, int clocks )
{
s->offset += clocks * s->factor;
/* Ensure time wasn't past end of buffer */
//assert( blip_samples_avail( s ) <= s->size );
s->offset += clocks * s->factor;
}
int blip_samples_avail( const blip_buffer_t* s )
{
return s->offset >> time_bits;
return s->offset >> time_bits;
}
/* Removes n samples from buffer */
static void remove_samples( blip_buffer_t* s, int n )
{
int remain = blip_samples_avail( s ) + buf_extra - n;
int remain = blip_samples_avail( s ) + buf_extra - n;
s->offset -= n * time_unit;
//assert( s->offset >= 0 );
s->offset -= n * time_unit;
/* Copy remaining samples to beginning of buffer and clear the rest */
memmove( s->buf, &s->buf [n], remain * sizeof (buf_t) );
memset( &s->buf [remain], 0, n * sizeof (buf_t) );
/* Copy remaining samples to beginning of buffer and clear the rest */
memmove( s->buf, &s->buf [n], remain * sizeof (buf_t) );
memset( &s->buf [remain], 0, n * sizeof (buf_t) );
}
int blip_read_samples( blip_buffer_t* s, short out [], int count, int stereo )
{
/* can't read more than available */
int avail = blip_samples_avail( s );
if ( count > avail )
count = avail;
/* can't read more than available */
int avail = blip_samples_avail( s );
if ( count > avail )
count = avail;
if ( count )
{
/* Sum deltas and write out */
int i;
for ( i = 0; i < count; ++i )
{
int sample;
if ( count )
{
/* Sum deltas and write out */
int i;
for ( i = 0; i < count; ++i )
{
int sample;
/* Apply slight high-pass filter */
s->amp -= s->amp >> 9;
/* Apply slight high-pass filter */
s->amp -= s->amp >> 9;
/* Add next delta */
s->amp += s->buf [i];
/* Add next delta */
s->amp += s->buf [i];
/* Calculate output sample */
sample = s->amp >> phase_bits;
/* Calculate output sample */
sample = s->amp >> phase_bits;
/* Keep within 16-bit sample range */
if ( sample < -32768 ) sample = -32768;
if ( sample > +32767 ) sample = +32767;
/* Keep within 16-bit sample range */
if ( sample < -32768 ) sample = -32768;
if ( sample > +32767 ) sample = +32767;
out [i << stereo] = sample;
}
out [i << stereo] = sample;
}
remove_samples( s, count );
}
remove_samples( s, count );
}
return count;
return count;
}

View File

@ -7,7 +7,7 @@ band-limited synthesis. */
#define BLIP_H
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
/* Creates a new blip_buffer with specified input clock rate, output
@ -45,7 +45,7 @@ easy interleving of two channels into a stereo output buffer. */
int blip_read_samples( blip_buffer_t*, short out [], int n, int stereo );
#ifdef __cplusplus
}
}
#endif
#endif

View File

@ -40,7 +40,7 @@
//| Constants |
// -----------
static double vsa = (1.0 / 4294967295.0); // Very small amount (Denormal Fix)
static double vsa = (1.0 / 4294967295.0); // Very small amount (Denormal Fix)
// ---------------
@ -87,7 +87,7 @@ double do_3band(EQSTATE * es, int sample)
{
// Locals
double l, m, h; // Low / Mid / High - Sample Values
double l, m, h; // Low / Mid / High - Sample Values
// Filter #1 (lowpass)

View File

@ -26,31 +26,31 @@
typedef struct {
// Filter #1 (Low band)
double lf; // Frequency
double f1p0; // Poles ...
double lf; // Frequency
double f1p0; // Poles ...
double f1p1;
double f1p2;
double f1p3;
// Filter #2 (High band)
double hf; // Frequency
double f2p0; // Poles ...
double hf; // Frequency
double f2p0; // Poles ...
double f2p1;
double f2p2;
double f2p3;
// Sample history buffer
double sdm1; // Sample data minus 1
double sdm2; // 2
double sdm3; // 3
double sdm1; // Sample data minus 1
double sdm2; // 2
double sdm3; // 3
// Gain Controls
double lg; // low gain
double mg; // mid gain
double hg; // high gain
double lg; // low gain
double mg; // mid gain
double hg; // high gain
} EQSTATE;
@ -60,8 +60,8 @@ typedef struct {
// ---------
extern void init_3band_state(EQSTATE * es, int lowfreq, int highfreq,
int mixfreq);
int mixfreq);
extern double do_3band(EQSTATE * es, int sample);
#endif // #ifndef __EQ3BAND__
#endif // #ifndef __EQ3BAND__

View File

@ -1,21 +1,13 @@
/*
SN76489 emulation
by Maxim in 2001 and 2002
converted from my original Delphi implementation
I'm a C newbie so I'm sure there are loads of stupid things
in here which I'll come back to some day and redo
Includes:
- Super-high quality tone channel "oversampling" by calculating fractional positions on transitions
- Noise output pattern reverse engineered from actual SMS output
- Volume levels taken from actual SMS output
*/
#ifndef _SN76489_H_
#define _SN76489_H_
/* Function prototypes */
extern void SN76489_Init(double PSGClockValue, int SamplingRate);
extern void SN76489_Reset(void);
extern void SN76489_Shutdown(void);

View File

@ -172,7 +172,8 @@ int sound_context_load(uint8 *state, char *version)
int bufferptr = YM2612LoadContext(state, version);
load_param(SN76489_GetContextPtr(),SN76489_GetContextSize());
if (version[15] > 0x30)
/* extended state (from 1.4.1 and above) */
if ((version[11] > 0x31) || (version[13] > 0x34) || (version[15] > 0x30))
{
load_param(&fm_cycles_count,sizeof(fm_cycles_count));
load_param(&psg_cycles_count,sizeof(psg_cycles_count));

View File

@ -1,28 +1,28 @@
/*
**
** software implementation of Yamaha YM2612 FM sound generator (taken from M.A.M.E fm.c)
** software implementation of Yamaha FM sound generator (YM2612/YM3438)
**
** Original code (MAME fm.c)
**
** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
**
** Version 1.4 (final beta)
**
*/
/*
** History:
** Additional code & fixes by Eke-Eke for Genesis Plus GX
**
** 2006~2009 Eke-Eke (Genesis Plus GX):
** Huge thanks to Nemesis, lot of those fixes came from his tests on Sega Genesis hardware
** Huge thanks to Nemesis, most of those fixes came from his tests on Sega Genesis hardware
** More informations at http://gendev.spritesmind.net/forum/viewtopic.php?t=386
**
** TODO:
**
** - core documentation
** - BUSY flag support
**
** - better documentation
** - BUSY flag emulation
*/
/*
** CHANGELOG:
**
** 2006~2011 Eke-Eke (Genesis Plus GX):
** - removed unused multichip support
** - added YM2612 Context external access functions
** - fixed LFO implementation:
@ -40,6 +40,7 @@
** - implemented accurate CSM mode emulation
** - implemented accurate SSG-EG emulation (Asterix, Beavis&Butthead, Bubba'n Stix & many other games)
** - implemented accurate address/data ports behavior
** - added preliminar support for DAC precision
**
**
** 03-08-2003 Jarek Burczynski:
@ -2213,8 +2214,8 @@ int YM2612LoadContext(unsigned char *state, char *version)
/* restore YM2612 context */
YM2612Restore(state);
/* extended state */
if (version[15] > 0x31)
/* extended state (from 1.5.0 and above) */
if ((version[11] > 0x31) || (version[13] > 0x34))
{
int c,s;
uint8 index;

View File

@ -1,13 +1,16 @@
/*
**
** File: ym2612.h -- header for ym2612.c
** software implementation of Yamaha FM sound generator
** software implementation of Yamaha FM sound generator (YM2612/YM3438)
**
** Original code (MAME fm.c)
**
** Copyright (C) 2001, 2002, 2003 Jarek Burczynski (bujar at mame dot net)
** Copyright (C) 1998 Tatsuyuki Satoh , MultiArcadeMachineEmulator development
**
** Version 1.4 (final beta)
**
** Additional code & fixes by Eke-Eke for Genesis Plus GX
**
*/
#ifndef _H_YM2612_
@ -18,7 +21,6 @@
#define INLINE static __inline__
#endif
extern int YM2612Init(double clock, int rate);
extern int YM2612ResetChip(void);
extern void YM2612Update(long int *buffer, int length);
@ -30,5 +32,4 @@ extern void YM2612Restore(unsigned char *buffer);
extern int YM2612LoadContext(unsigned char *state, char *version);
extern int YM2612SaveContext(unsigned char *state);
#endif /* _YM2612_ */

View File

@ -2,7 +2,7 @@
* Genesis Plus
* Savestate support
*
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
* Copyright (C) 2007-2011 Eke-Eke (GCN/Wii port)
*
* 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
@ -37,11 +37,18 @@ int state_load(unsigned char *buffer)
outbytes = STATE_SIZE;
uncompress ((Bytef *)state, &outbytes, (Bytef *)(buffer + 4), inbytes);
/* version check */
/* signature check (GENPLUS-GX x.x.x) */
char version[17];
load_param(version,16);
version[16] = 0;
if (strncmp(version,STATE_VERSION,15))
if (strncmp(version,STATE_VERSION,11))
{
free(state);
return -1;
}
/* version check (1.4.0 and above) */
if ((version[11] < 0x31) || ((version[11] == 0x31) && (version[13] < 0x34)))
{
free(state);
return -1;
@ -51,26 +58,34 @@ int state_load(unsigned char *buffer)
system_reset();
// GENESIS
load_param(work_ram, sizeof(work_ram));
load_param(zram, sizeof(zram));
load_param(&zstate, sizeof(zstate));
load_param(&zbank, sizeof(zbank));
if (zstate == 3)
if (system_hw == SYSTEM_PBC)
{
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
load_param(work_ram, 0x2000);
}
else
{
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
load_param(work_ram, sizeof(work_ram));
load_param(zram, sizeof(zram));
load_param(&zstate, sizeof(zstate));
load_param(&zbank, sizeof(zbank));
if (zstate == 3)
{
m68k_memory_map[0xa0].read8 = z80_read_byte;
m68k_memory_map[0xa0].read16 = z80_read_word;
m68k_memory_map[0xa0].write8 = z80_write_byte;
m68k_memory_map[0xa0].write16 = z80_write_word;
}
else
{
m68k_memory_map[0xa0].read8 = m68k_read_bus_8;
m68k_memory_map[0xa0].read16 = m68k_read_bus_16;
m68k_memory_map[0xa0].write8 = m68k_unused_8_w;
m68k_memory_map[0xa0].write16 = m68k_unused_16_w;
}
}
if (version[15] > 0x30)
/* 1.4.1 and above */
if ((version[11] > 0x31) || (version[13] > 0x34) || (version[15] > 0x30))
{
/* extended state */
load_param(&mcycles_68k, sizeof(mcycles_68k));
@ -78,8 +93,15 @@ int state_load(unsigned char *buffer)
}
// IO
load_param(io_reg, sizeof(io_reg));
io_reg[0] = region_code | 0x20 | (config.tmss & 1);
if (system_hw == SYSTEM_PBC)
{
load_param(&io_reg[0], 1);
}
else
{
load_param(io_reg, sizeof(io_reg));
io_reg[0] = region_code | 0x20 | (config.tmss & 1);
}
// VDP
bufferptr += vdp_context_load(&state[bufferptr], version);
@ -88,34 +110,44 @@ int state_load(unsigned char *buffer)
bufferptr += sound_context_load(&state[bufferptr], version);
// 68000
uint16 tmp16;
uint32 tmp32;
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D0, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D1, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D2, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D3, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D4, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D5, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D6, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D7, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A0, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A1, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A2, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A3, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A4, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A5, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A6, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A7, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_PC, tmp32);
load_param(&tmp16, 2); m68k_set_reg(M68K_REG_SR, tmp16);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_USP,tmp32);
if (system_hw != SYSTEM_PBC)
{
uint16 tmp16;
uint32 tmp32;
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D0, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D1, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D2, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D3, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D4, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D5, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D6, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_D7, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A0, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A1, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A2, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A3, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A4, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A5, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A6, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_A7, tmp32);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_PC, tmp32);
load_param(&tmp16, 2); m68k_set_reg(M68K_REG_SR, tmp16);
load_param(&tmp32, 4); m68k_set_reg(M68K_REG_USP,tmp32);
}
// Z80
load_param(&Z80, sizeof(Z80_Regs));
Z80.irq_callback = z80_irq_callback;
// Cartridge HW
bufferptr += cart_hw_context_load(&state[bufferptr], version);
if (system_hw == SYSTEM_PBC)
{
bufferptr += sms_cart_context_load(&state[bufferptr], version);
}
else
{
bufferptr += md_cart_context_load(&state[bufferptr], version);
}
free(state);
return 1;
@ -136,15 +168,29 @@ int state_save(unsigned char *buffer)
save_param(version, 16);
// GENESIS
save_param(work_ram, sizeof(work_ram));
save_param(zram, sizeof(zram));
save_param(&zstate, sizeof(zstate));
save_param(&zbank, sizeof(zbank));
if (system_hw == SYSTEM_PBC)
{
save_param(work_ram, 0x2000);
}
else
{
save_param(work_ram, sizeof(work_ram));
save_param(zram, sizeof(zram));
save_param(&zstate, sizeof(zstate));
save_param(&zbank, sizeof(zbank));
}
save_param(&mcycles_68k, sizeof(mcycles_68k));
save_param(&mcycles_z80, sizeof(mcycles_z80));
// IO
save_param(io_reg, sizeof(io_reg));
if (system_hw == SYSTEM_PBC)
{
save_param(&io_reg[0], 1);
}
else
{
save_param(io_reg, sizeof(io_reg));
}
// VDP
bufferptr += vdp_context_save(&state[bufferptr]);
@ -153,33 +199,43 @@ int state_save(unsigned char *buffer)
bufferptr += sound_context_save(&state[bufferptr]);
// 68000
uint16 tmp16;
uint32 tmp32;
tmp32 = m68k_get_reg(NULL, M68K_REG_D0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_PC); save_param(&tmp32, 4);
tmp16 = m68k_get_reg(NULL, M68K_REG_SR); save_param(&tmp16, 2);
tmp32 = m68k_get_reg(NULL, M68K_REG_USP); save_param(&tmp32, 4);
if (system_hw != SYSTEM_PBC)
{
uint16 tmp16;
uint32 tmp32;
tmp32 = m68k_get_reg(NULL, M68K_REG_D0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_D7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A0); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A1); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A2); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A3); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A4); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A5); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A6); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_A7); save_param(&tmp32, 4);
tmp32 = m68k_get_reg(NULL, M68K_REG_PC); save_param(&tmp32, 4);
tmp16 = m68k_get_reg(NULL, M68K_REG_SR); save_param(&tmp16, 2);
tmp32 = m68k_get_reg(NULL, M68K_REG_USP); save_param(&tmp32, 4);
}
// Z80
save_param(&Z80, sizeof(Z80_Regs));
// Cartridge HW
bufferptr += cart_hw_context_save(&state[bufferptr]);
if (system_hw == SYSTEM_PBC)
{
bufferptr += sms_cart_context_save(&state[bufferptr]);
}
else
{
bufferptr += md_cart_context_save(&state[bufferptr]);
}
/* compress state file */
unsigned long inbytes = bufferptr;

View File

@ -2,7 +2,7 @@
* Genesis Plus
* Savestate support
*
* Copyright (C) 2007, 2008, 2009 Eke-Eke (GCN/Wii port)
* Copyright (C) 2007-2011 Eke-Eke (GCN/Wii port)
*
* 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
@ -24,7 +24,7 @@
#define _STATE_H_
#define STATE_SIZE 0x48100
#define STATE_VERSION "GENPLUS-GX 1.4.2"
#define STATE_VERSION "GENPLUS-GX 1.5.0"
#define load_param(param, size) \
memcpy(param, &state[bufferptr], size); \

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* Main Emulation
* Virtual System emulation
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
@ -32,11 +32,82 @@ uint32 mcycles_vdp;
uint32 mcycles_z80;
uint32 mcycles_68k;
uint8 system_hw;
void (*system_frame)(int do_skip);
static void system_frame_md(int do_skip);
static void system_frame_sms(int do_skip);
static int pause_b;
static EQSTATE eq;
static int32 llp,rrp;
/****************************************************************
* AUDIO equalizer
* Audio subsystem
****************************************************************/
static EQSTATE eq;
int audio_init (int samplerate, float framerate)
{
/* Shutdown first */
audio_shutdown();
/* Clear the sound data context */
memset(&snd, 0, sizeof (snd));
/* Default settings */
snd.sample_rate = samplerate;
snd.frame_rate = framerate;
/* Calculate the sound buffer size (for one frame) */
snd.buffer_size = (int)(samplerate / framerate) + 32;
/* SN76489 stream buffers */
snd.psg.buffer = (int16 *) malloc(snd.buffer_size * sizeof(int16));
if (!snd.psg.buffer) return (-1);
/* YM2612 stream buffers */
snd.fm.buffer = (int32 *) malloc(snd.buffer_size * sizeof(int32) * 2);
if (!snd.fm.buffer) return (-1);
#ifndef NGC
/* Output buffers */
snd.buffer[0] = (int16 *) malloc(snd.buffer_size * sizeof(int16));
snd.buffer[1] = (int16 *) malloc(snd.buffer_size * sizeof(int16));
if (!snd.buffer[0] || !snd.buffer[1]) return (-1);
#endif
/* Resampling buffer */
if (config.hq_fm && !Fir_Resampler_initialize(4096)) return (-1);
/* Set audio enable flag */
snd.enabled = 1;
/* Reset audio */
audio_reset();
return (0);
}
void audio_reset(void)
{
/* Low-Pass filter */
llp = 0;
rrp = 0;
/* 3 band EQ */
audio_set_equalizer();
/* Resampling buffer */
Fir_Resampler_clear();
/* Audio buffers */
snd.psg.pos = snd.psg.buffer;
snd.fm.pos = snd.fm.buffer;
if (snd.psg.buffer) memset (snd.psg.buffer, 0, snd.buffer_size * sizeof(int16));
if (snd.fm.buffer) memset (snd.fm.buffer, 0, snd.buffer_size * sizeof(int32) * 2);
#ifndef NGC
if (snd.buffer[0]) memset (snd.buffer[0], 0, snd.buffer_size * sizeof(int16));
if (snd.buffer[1]) memset (snd.buffer[1], 0, snd.buffer_size * sizeof(int16));
#endif
}
void audio_set_equalizer(void)
{
@ -46,10 +117,19 @@ void audio_set_equalizer(void)
eq.hg = (double)(config.hg) / 100.0;
}
/****************************************************************
* AUDIO stream update & mixing
****************************************************************/
static int32 llp,rrp;
void audio_shutdown(void)
{
/* Sound buffers */
if (snd.fm.buffer) free(snd.fm.buffer);
if (snd.psg.buffer) free(snd.psg.buffer);
#ifndef NGC
if (snd.buffer[0]) free(snd.buffer[0]);
if (snd.buffer[1]) free(snd.buffer[1]);
#endif
/* Resampling buffer */
Fir_Resampler_shutdown();
}
int audio_update (void)
{
@ -129,14 +209,10 @@ int audio_update (void)
}
/* clipping (16-bit samples) */
if (l > 32767)
l = 32767;
else if (l < -32768)
l = -32768;
if (r > 32767)
r = 32767;
else if (r < -32768)
r = -32768;
if (l > 32767) l = 32767;
else if (l < -32768) l = -32768;
if (r > 32767) r = 32767;
else if (r < -32768) r = -32768;
/* update sound buffer */
#ifndef NGC
@ -163,181 +239,58 @@ int audio_update (void)
return size;
}
/****************************************************************
* AUDIO System initialization
****************************************************************/
int audio_init (int samplerate, float framerate)
{
/* Shutdown first */
audio_shutdown();
/* Clear the sound data context */
memset(&snd, 0, sizeof (snd));
/* Default settings */
snd.sample_rate = samplerate;
snd.frame_rate = framerate;
/* Calculate the sound buffer size (for one frame) */
snd.buffer_size = (int)(samplerate / framerate) + 32;
#ifndef NGC
/* Output buffers */
snd.buffer[0] = (int16 *) malloc(snd.buffer_size * sizeof(int16));
snd.buffer[1] = (int16 *) malloc(snd.buffer_size * sizeof(int16));
if (!snd.buffer[0] || !snd.buffer[1])
return (-1);
#endif
/* SN76489 stream buffers */
snd.psg.buffer = (int16 *) malloc(snd.buffer_size * sizeof(int16));
if (!snd.psg.buffer)
return (-1);
/* YM2612 stream buffers */
snd.fm.buffer = (int32 *) malloc(snd.buffer_size * sizeof(int32) * 2);
if (!snd.fm.buffer)
return (-1);
/* Resampling buffer */
if (config.hq_fm)
{
if (!Fir_Resampler_initialize(4096))
return (-1);
}
/* Set audio enable flag */
snd.enabled = 1;
/* Reset audio */
audio_reset();
return (0);
}
/****************************************************************
* AUDIO System reset
****************************************************************/
void audio_reset(void)
{
/* Low-Pass filter */
llp = 0;
rrp = 0;
/* 3 band EQ */
audio_set_equalizer();
/* audio buffers */
Fir_Resampler_clear();
snd.psg.pos = snd.psg.buffer;
snd.fm.pos = snd.fm.buffer;
#ifndef NGC
if (snd.buffer[0])
memset (snd.buffer[0], 0, snd.buffer_size * sizeof(int16));
if (snd.buffer[1])
memset (snd.buffer[1], 0, snd.buffer_size * sizeof(int16));
#endif
if (snd.psg.buffer)
memset (snd.psg.buffer, 0, snd.buffer_size * sizeof(int16));
if (snd.fm.buffer)
memset (snd.fm.buffer, 0, snd.buffer_size * sizeof(int32) * 2);
}
/****************************************************************
* AUDIO System shutdown
****************************************************************/
void audio_shutdown(void)
{
/* Sound buffers */
#ifndef NGC
if (snd.buffer[0])
free(snd.buffer[0]);
if (snd.buffer[1])
free(snd.buffer[1]);
#endif
if (snd.fm.buffer)
free(snd.fm.buffer);
if (snd.psg.buffer)
free(snd.psg.buffer);
/* Resampling buffer */
Fir_Resampler_shutdown();
}
/****************************************************************
* Virtual Genesis initialization
****************************************************************/
void system_init (void)
void system_init(void)
{
/* Genesis hardware */
gen_init();
io_init();
vdp_init();
render_init();
/* Cartridge hardware */
cart_hw_init();
/* Sound hardware */
sound_init();
system_frame = (system_hw == SYSTEM_PBC) ? system_frame_sms : system_frame_md;
}
/****************************************************************
* Virtual Genesis Hard Reset
* Virtual System emulation
****************************************************************/
void system_reset (void)
void system_reset(void)
{
/* Cartridge Hardware */
cart_hw_reset(1);
/* Genesis hardware */
gen_hardreset();
gen_reset(1);
io_reset();
vdp_reset();
render_reset();
/* Sound hardware */
sound_reset();
/* Audio system */
audio_reset();
}
/****************************************************************
* Virtual Genesis shutdown
****************************************************************/
void system_shutdown (void)
{
gen_shutdown ();
vdp_shutdown ();
render_shutdown ();
SN76489_Shutdown ();
gen_shutdown();
SN76489_Shutdown();
}
/****************************************************************
* Virtual Genesis Frame emulation
****************************************************************/
void system_frame (int do_skip)
static void system_frame_md(int do_skip)
{
/* line counter */
int line = 0;
/* Z80 interrupt flag */
int zirq = 0;
int zirq = 1;
/* reload H Counter */
int h_counter = reg[10];
/* reset line master cycle count */
mcycles_vdp = 0;
/* reload V Counter */
v_counter = lines_per_frame - 1;
/* reset VDP FIFO */
fifo_write_cnt = 0;
fifo_lastwrite = 0;
/* reset line cycle count */
mcycles_vdp = 0;
fifo_write_cnt = 0;
fifo_lastwrite = 0;
/* update 6-Buttons & Lightguns */
input_refresh();
@ -349,34 +302,43 @@ void system_frame (int do_skip)
/* interlaced mode */
int old_interlaced = interlaced;
interlaced = (reg[12] & 2) >> 1;
interlaced = (reg[12] & 0x02) >> 1;
if (old_interlaced != interlaced)
{
im2_flag = ((reg[12] & 6) == 6);
im2_flag = ((reg[12] & 0x06) == 0x06);
odd_frame = 1;
bitmap.viewport.changed = 5;
/* update rendering mode */
if (reg[1] & 0x04)
{
if (im2_flag)
{
render_bg = (reg[11] & 0x04) ? render_bg_m5_im2_vs : render_bg_m5_im2;
render_obj = (reg[12] & 0x08) ? render_obj_m5_im2_ste : render_obj_m5_im2;
}
else
{
render_bg = (reg[11] & 0x04) ? render_bg_m5_vs : render_bg_m5;
render_obj = (reg[12] & 0x08) ? render_obj_m5_ste : render_obj_m5;
}
}
}
/* active screen height */
bitmap.viewport.h = 224 + ((reg[1] & 8) << 1);
bitmap.viewport.y = (config.overscan & 1) * (8 - (reg[1] & 8) + vdp_pal*24);
if (reg[1] & 0x04)
{
bitmap.viewport.h = 224 + ((reg[1] & 0x08) << 1);
bitmap.viewport.y = (config.overscan & 1) * ((240 + 48*vdp_pal - bitmap.viewport.h) >> 1);
}
else
{
bitmap.viewport.h = 192;
bitmap.viewport.y = (config.overscan & 1) * 24 * (vdp_pal + 1);
}
/* active screen width */
bitmap.viewport.w = 256 + ((reg[12] & 1) << 6);
bitmap.viewport.x = (config.overscan & 2) * 7;
}
/* render last line of overscan */
if (!do_skip && bitmap.viewport.y)
{
render_line(v_counter);
}
/* parse first line of sprites */
object_which = 1;
if (reg[1] & 0x40)
{
parse_satb(0x80);
bitmap.viewport.w = 256 + ((reg[12] & 0x01) << 6);
}
/* clear VBLANK, DMA, FIFO FULL & field flags */
@ -395,7 +357,19 @@ void system_frame (int do_skip)
/* update VDP DMA */
if (dma_length)
{
vdp_update_dma(0);
vdp_dma_update(0);
}
/* render last line of overscan */
if (bitmap.viewport.y)
{
blank_line(v_counter, -bitmap.viewport.x, bitmap.viewport.w + 2*bitmap.viewport.x);
}
/* parse first line of sprites */
if (reg[1] & 0x40)
{
parse_satb(-1);
}
/* run 68k & Z80 */
@ -437,31 +411,22 @@ void system_frame (int do_skip)
hint_pending = 0x10;
if (reg[0] & 0x10)
{
irq_status = (irq_status & 2) | 0x14;
m68k_irq_state |= 0x14;
}
}
/* update VDP DMA */
if (dma_length)
{
vdp_update_dma(mcycles_vdp);
vdp_dma_update(mcycles_vdp);
}
/* swap sprite line buffers */
object_which ^= 1;
/* render scanline */
if (!do_skip)
{
render_line(line);
}
/* parse next line of sprites */
if ((reg[1] & 0x40) && (line < (bitmap.viewport.h - 1)))
{
parse_satb(0x81 + line);
}
/* run 68k & Z80 */
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
if (zstate == 1)
@ -487,22 +452,8 @@ void system_frame (int do_skip)
/* end of active display */
v_counter = line;
/* update 6-Buttons & Lightguns */
input_refresh();
/* H Interrupt */
if(--h_counter < 0)
{
/* reload H Counter */
h_counter = reg[10];
/* interrupt level 4 */
hint_pending = 0x10;
if (reg[0] & 0x10)
{
irq_status = (irq_status & 2) | 0x14;
}
}
/* set VBLANK flag */
status |= 0x08;
/* overscan area */
int start = lines_per_frame - bitmap.viewport.y;
@ -516,19 +467,33 @@ void system_frame (int do_skip)
bitmap.viewport.changed |= 1;
}
/* set VBLANK flag */
status |= 0x08;
/* update 6-Buttons & Lightguns */
input_refresh();
/* H Interrupt */
if(--h_counter < 0)
{
/* reload H Counter */
h_counter = reg[10];
/* interrupt level 4 */
hint_pending = 0x10;
if (reg[0] & 0x10)
{
m68k_irq_state |= 0x14;
}
}
/* update VDP DMA */
if (dma_length)
{
vdp_update_dma(mcycles_vdp);
vdp_dma_update(mcycles_vdp);
}
/* render overscan */
if (!do_skip && (line < end))
if (line < end)
{
render_line(line);
blank_line(line, -bitmap.viewport.x, bitmap.viewport.w + 2*bitmap.viewport.x);
}
/* update inputs before VINT (Warriors of Eternal Sun) */
@ -553,14 +518,13 @@ void system_frame (int do_skip)
vint_pending = 0x20;
if (reg[1] & 0x20)
{
irq_status = 0x16;
m68k_irq_state = 0x16;
}
/* Z80 interrupt */
z80_set_irq_line(0, ASSERT_LINE);
zirq = 1;
/* assert Z80 interrupt */
Z80.irq_state = ASSERT_LINE;
/* run 68k & Z80 */
/* run 68k & Z80 until end of line */
m68k_run(mcycles_vdp + MCYCLES_PER_LINE);
if (zstate == 1)
{
@ -593,14 +557,14 @@ void system_frame (int do_skip)
input_refresh();
/* render overscan */
if (!do_skip && ((line < end) || (line >= start)))
if ((line < end) || (line >= start))
{
render_line(line);
blank_line(line, -bitmap.viewport.x, bitmap.viewport.w + 2*bitmap.viewport.x);
}
/* Z80 interrupt is asserted for one line */
if (zirq)
{
/* Z80 interrupt is asserted exactly for one line */
m68k_run(mcycles_vdp + 788);
if (zstate == 1)
{
@ -612,7 +576,7 @@ void system_frame (int do_skip)
}
/* clear Z80 interrupt */
z80_set_irq_line(0, CLEAR_LINE);
Z80.irq_state = CLEAR_LINE;
zirq = 0;
}
@ -638,7 +602,277 @@ void system_frame (int do_skip)
}
while (++line < (lines_per_frame - 1));
/* adjust cpu cycle count for next frame */
/* adjust 68k & Z80 cycle count for next frame */
mcycles_68k -= mcycles_vdp;
mcycles_z80 -= mcycles_vdp;
}
static void system_frame_sms(int do_skip)
{
/* line counter */
int line = 0;
/* reload H Counter */
int h_counter = reg[10];
/* reset line master cycle count */
mcycles_vdp = 0;
/* reload V Counter */
v_counter = lines_per_frame - 1;
/* reset VDP FIFO */
fifo_write_cnt = 0;
fifo_lastwrite = 0;
/* update 6-Buttons & Lightguns */
input_refresh();
/* display changed during VBLANK */
if (bitmap.viewport.changed & 2)
{
bitmap.viewport.changed &= ~2;
/* interlaced mode */
int old_interlaced = interlaced;
interlaced = (reg[12] & 0x02) >> 1;
if (old_interlaced != interlaced)
{
im2_flag = ((reg[12] & 0x06) == 0x06);
odd_frame = 1;
bitmap.viewport.changed = 5;
/* update rendering mode */
if (reg[1] & 0x04)
{
if (im2_flag)
{
render_bg = (reg[11] & 0x04) ? render_bg_m5_im2_vs : render_bg_m5_im2;
render_obj = render_obj_m5_im2;
}
else
{
render_bg = (reg[11] & 0x04) ? render_bg_m5_vs : render_bg_m5;
render_obj = render_obj_m5;
}
}
}
/* active screen height */
if (reg[1] & 0x04)
{
bitmap.viewport.h = 224 + ((reg[1] & 0x08) << 1);
bitmap.viewport.y = (config.overscan & 1) * ((240 + 48*vdp_pal - bitmap.viewport.h) >> 1);
}
else
{
bitmap.viewport.h = 192;
bitmap.viewport.y = (config.overscan & 1) * 24 * (vdp_pal + 1);
}
/* active screen width */
bitmap.viewport.w = 256 + ((reg[12] & 0x01) << 6);
}
/* Detect pause button input */
if (input.pad[0] & INPUT_START)
{
/* NMI is edge-triggered */
if (!pause_b)
{
pause_b = 1;
z80_set_nmi_line(ASSERT_LINE);
z80_set_nmi_line(CLEAR_LINE);
}
}
else
{
pause_b = 0;
}
/* 3-D glasses faking: skip rendering of left lens frame */
do_skip |= (work_ram[0x1ffb] & cart.special);
/* clear VBLANK, DMA, FIFO FULL & field flags */
status &= 0xFEE5;
/* set FIFO EMPTY flag */
status |= 0x0200;
/* even/odd field flag (interlaced modes only) */
odd_frame ^= 1;
if (interlaced)
{
status |= (odd_frame << 4);
}
/* update VDP DMA */
if (dma_length)
{
vdp_dma_update(0);
}
/* render last line of overscan */
if (bitmap.viewport.y)
{
blank_line(v_counter, -bitmap.viewport.x, bitmap.viewport.w + 2*bitmap.viewport.x);
}
/* parse first line of sprites */
if (reg[1] & 0x40)
{
parse_satb(-1);
}
/* latch Horizontal Scroll register (if modified during VBLANK) */
hscroll = reg[0x08];
/* run Z80 */
z80_run(MCYCLES_PER_LINE);
/* update line cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
/* latch Vertical Scroll register */
vscroll = reg[0x09];
/* Active Display */
do
{
/* update V Counter */
v_counter = line;
/* update 6-Buttons & Lightguns */
input_refresh();
/* H Interrupt */
if(--h_counter < 0)
{
/* reload H Counter */
h_counter = reg[10];
/* interrupt level 4 */
hint_pending = 0x10;
if (reg[0] & 0x10)
{
Z80.irq_state = ASSERT_LINE;
}
}
/* update VDP DMA */
if (dma_length)
{
vdp_dma_update(mcycles_vdp);
}
/* render scanline */
if (!do_skip)
{
render_line(line);
}
/* run Z80 */
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
/* update line cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
}
while (++line < bitmap.viewport.h);
/* end of active display */
v_counter = line;
/* set VBLANK flag */
status |= 0x08;
/* overscan area */
int start = lines_per_frame - bitmap.viewport.y;
int end = bitmap.viewport.h + bitmap.viewport.y;
/* check viewport changes */
if ((bitmap.viewport.w != bitmap.viewport.ow) || (bitmap.viewport.h != bitmap.viewport.oh))
{
bitmap.viewport.ow = bitmap.viewport.w;
bitmap.viewport.oh = bitmap.viewport.h;
bitmap.viewport.changed |= 1;
}
/* update 6-Buttons & Lightguns */
input_refresh();
/* H Interrupt */
if(--h_counter < 0)
{
/* reload H Counter */
h_counter = reg[10];
/* interrupt level 4 */
hint_pending = 0x10;
if (reg[0] & 0x10)
{
Z80.irq_state = ASSERT_LINE;
}
}
/* update VDP DMA */
if (dma_length)
{
vdp_dma_update(mcycles_vdp);
}
/* render overscan */
if (line < end)
{
blank_line(line, -bitmap.viewport.x, bitmap.viewport.w + 2*bitmap.viewport.x);
}
/* update inputs before VINT (Warriors of Eternal Sun) */
osd_input_Update();
/* run Z80 until end of line */
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
/* VINT flag */
status |= 0x80;
/* V Interrupt */
vint_pending = 0x20;
if (reg[1] & 0x20)
{
Z80.irq_state = ASSERT_LINE;
}
/* update line cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
/* increment line count */
line++;
/* Vertical Blanking */
do
{
/* update V Counter */
v_counter = line;
/* update 6-Buttons & Lightguns */
input_refresh();
/* render overscan */
if ((line < end) || (line >= start))
{
blank_line(line, -bitmap.viewport.x, bitmap.viewport.w + 2*bitmap.viewport.x);
}
/* run Z80 */
z80_run(mcycles_vdp + MCYCLES_PER_LINE);
/* update line cycle count */
mcycles_vdp += MCYCLES_PER_LINE;
}
while (++line < (lines_per_frame - 1));
/* adjust Z80 cycle count for next frame */
mcycles_z80 -= mcycles_vdp;
}

View File

@ -1,9 +1,9 @@
/***************************************************************************************
* Genesis Plus
* Main Emulation
* Virtual System Emulation
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007,2008,2009), additional code & fixes for the GCN/Wii port
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
@ -24,18 +24,21 @@
#ifndef _SYSTEM_H_
#define _SYSTEM_H_
#define SYSTEM_GENESIS 0
#define SYSTEM_MEGADRIVE 1
#define SYSTEM_PICO 2
#define SYSTEM_PBC 0x00
#define SYSTEM_GENESIS 0x01
#define SYSTEM_MEGADRIVE 0x02
#define SYSTEM_PICO 0x03
#define MCYCLES_PER_LINE 3420
#define Z80_CYCLE_OFFSET 550 /* horizontal timings offset when running in SMS mode */
typedef struct
{
uint8 *data; /* Bitmap data */
int width; /* Bitmap width (32+512+32) */
int height; /* Bitmap height (256) */
int depth; /* Color depth (8 bits) */
int width; /* Bitmap width */
int height; /* Bitmap height */
int depth; /* Color depth (8-32 bits) */
int pitch; /* Width of bitmap in bytes */
int granularity; /* Size of each pixel in bytes */
int remap; /* 1= Translate pixel data */
@ -51,7 +54,6 @@ typedef struct
} viewport;
} t_bitmap;
typedef struct
{
int sample_rate; /* Output Sample rate (8000-48000) */
@ -71,12 +73,13 @@ typedef struct
} psg;
} t_snd;
/* Global variables */
extern t_bitmap bitmap;
extern t_snd snd;
extern uint32 mcycles_vdp;
extern uint32 mcycles_z80;
extern uint32 mcycles_68k;
extern uint32 mcycles_vdp;
extern uint8 system_hw;
/* Function prototypes */
@ -88,7 +91,7 @@ extern void audio_set_equalizer(void);
extern void system_init(void);
extern void system_reset(void);
extern void system_shutdown(void);
extern void system_frame(int do_skip);
extern void (*system_frame)(int do_skip);
#endif /* _SYSTEM_H_ */

View File

@ -19,52 +19,63 @@ FLAGS = -I. -I.. -I../z80 -I../m68k -I../dos -I../sound -I../sound/SRC -I../cart
LIBS = -lalleg -laudio -lz -lm
OBJ = obj/z80.o
OBJECTS = obj/z80.o
OBJ += obj/m68kcpu.o \
OBJECTS += obj/m68kcpu.o \
obj/m68kops.o
OBJ += obj/genesis.o \
obj/vdp.o \
obj/render.o \
obj/system.o \
obj/gen_io.o \
obj/gen_input.o \
obj/mem68k.o \
obj/memz80.o \
obj/membnk.o \
OBJECTS += obj/genesis.o \
obj/vdp_ctrl.o \
obj/vdp_render.o \
obj/system.o \
obj/io_ctrl.o \
obj/mem68k.o \
obj/memz80.o \
obj/membnk.o \
obj/state.o
OBJ += obj/sound.o \
obj/sn76489.o \
OBJECTS += obj/input.o \
obj/gamepad.o \
obj/lightgun.o \
obj/mouse.o \
obj/activator.o \
obj/xe_a1p.o \
obj/teamplayer.o \
obj/paddle.o \
obj/sportspad.o
OBJECTS += obj/sound.o \
obj/sn76489.o \
obj/ym2612.o
OBJ += obj/samplerate.o \
obj/src_linear.o \
obj/src_sinc.o \
obj/src_zoh.o \
OBJECTS += obj/Fir_Resampler.o
OBJECTS += obj/blip.o
OBJ += obj/blip.o \
OBJECTS += obj/eq.o \
OBJ += obj/eq.o \
OBJ += obj/sram.o \
OBJECTS += obj/sram.o \
obj/eeprom.o \
obj/svp.o \
obj/ssp16.o \
obj/cart_hw.o
obj/ggenie.o \
obj/areplay.o \
obj/md_cart.o \
obj/sms_cart.o
OBJ += obj/dos.o \
obj/sealintf.o \
OBJECTS += obj/dos.o \
obj/sealintf.o \
obj/config.o \
obj/error.o \
obj/unzip.o \
obj/fileio.o \
obj/loadrom.o
OBJ += obj/sms_ntsc.o \
OBJECTS += obj/sms_ntsc.o \
obj/md_ntsc.o
EXE = ../gen.exe
all : $(EXE)
@ -88,6 +99,9 @@ obj/%.o : ../sound/SRC/%.c ../sound/SRC/%.h
obj/%.o : ../sound/SRC/%.c
$(CC) -c $< -o $@ $(FLAGS)
obj/%.o : ../input_hw/%.c ../input_hw/%.h
$(CC) -c $< -o $@ $(FLAGS)
obj/%.o : ../cart_hw/%.c ../cart_hw/%.h
$(CC) -c $< -o $@ $(FLAGS)

View File

@ -122,13 +122,13 @@ void set_config_defaults(void)
config.render = 0;
/* controllers options */
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_GAMEPAD;
input.system[0] = SYSTEM_MD_GAMEPAD;
input.system[1] = SYSTEM_MD_GAMEPAD;
config.gun_cursor[0] = 1;
config.gun_cursor[1] = 1;
config.invert_mouse = 0;
for (i=0;i<MAX_INPUTS;i++)
config.input[i].padtype = DEVICE_3BUTTON;
config.input[i].padtype = DEVICE_PAD3B;
}

View File

@ -286,8 +286,8 @@ void dos_update_input(void)
poll_mouse();
/* Calculate X Y axis values */
input.analog[joynum - 4][0] = (mouse_x * bitmap.viewport.w) / SCREEN_W;
input.analog[joynum - 4][1] = (mouse_y * bitmap.viewport.h) / SCREEN_H;
input.analog[joynum][0] = (mouse_x * bitmap.viewport.w) / SCREEN_W;
input.analog[joynum][1] = (mouse_y * bitmap.viewport.h) / SCREEN_H;
/* Map mouse buttons to player #1 inputs */
if(mouse_b & 4) input.pad[joynum] |= INPUT_C;
@ -301,14 +301,14 @@ void dos_update_input(void)
poll_mouse();
/* Get X & Y quantity of movement */
get_mouse_mickeys(&input.analog[2][0], &input.analog[2][1]);
get_mouse_mickeys(&input.analog[joynum][0], &input.analog[joynum][1]);
/* Sega Mouse range is -256;+256 */
input.analog[2][0] = (input.analog[2][0] * 256) / SCREEN_W;
input.analog[2][1] = (input.analog[2][1] * 256) / SCREEN_H;
input.analog[joynum][0] = (input.analog[joynum][0] * 256) / SCREEN_W;
input.analog[joynum][1] = (input.analog[joynum][1] * 256) / SCREEN_H;
/* Vertical movement is upsidedown */
if (!config.invert_mouse) input.analog[2][1] = 0 - input.analog[2][1];
if (!config.invert_mouse) input.analog[joynum][1] = 0 - input.analog[joynum][1];
/* Map mouse buttons to player #1 inputs */
if(mouse_b & 4) input.pad[joynum] |= INPUT_C;
@ -383,11 +383,15 @@ void dos_update_input(void)
}
/* reinitialize VC max value */
vc_max = 0xEA + 24*vdp_pal;
if (reg[1] & 8)
static const uint16 vc_table[4][2] =
{
vc_max += (28 - 20*vdp_pal);
}
/* NTSC, PAL */
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
{0xEA , 0x102}, /* Mode 5 (224 lines) */
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
{0x106, 0x10A} /* Mode 5 (240 lines) */
};
vc_max = vc_table[(reg[1] >> 2) & 3][vdp_pal];
/* reinitialize overscan area */
bitmap.viewport.y = (config.overscan & 1) ? (((reg[1] & 8) ? 0 : 8) + (vdp_pal ? 24 : 0)) : 0;

View File

@ -27,7 +27,7 @@ uint8 *load_archive(char *filename, int *file_size)
return (NULL);
}
ret = unzGetCurrentFileInfo(fd, &info, NULL, 0, NULL, 0, NULL, 0);
ret = unzGetCurrentFileInfo(fd, &info, filename, 128, NULL, 0, NULL, 0);
if(ret != UNZ_OK)
{
unzClose(fd);

View File

@ -19,7 +19,7 @@ CFLAGS = `sdl-config --cflags` -march=i686 -O6 -fomit-frame-pointer -Wall -Wn
#LDFLAGS = -pg
DEFINES = -DLSB_FIRST
INCLUDES = -I. -I.. -I../z80 -I../m68k -I../sound -I../cart_hw -I../cart_hw/svp -I../ntsc
INCLUDES = -I. -I.. -I../z80 -I../m68k -I../sound -I../input_hw -I../cart_hw -I../cart_hw/svp -I../ntsc
LIBS = `sdl-config --libs` -lz -lm
OBJECTS = obj/z80.o
@ -28,19 +28,29 @@ OBJECTS += obj/m68kcpu.o \
obj/m68kops.o
OBJECTS += obj/genesis.o \
obj/vdp.o \
obj/render.o \
obj/system.o \
obj/gen_io.o \
obj/gen_input.o \
obj/mem68k.o \
obj/memz80.o \
obj/membnk.o \
OBJECTS += obj/genesis.o \
obj/vdp_ctrl.o \
obj/vdp_render.o \
obj/system.o \
obj/io_ctrl.o \
obj/mem68k.o \
obj/memz80.o \
obj/membnk.o \
obj/state.o
OBJECTS += obj/sound.o \
obj/sn76489.o \
OBJECTS += obj/input.o \
obj/gamepad.o \
obj/lightgun.o \
obj/mouse.o \
obj/activator.o \
obj/xe_a1p.o \
obj/teamplayer.o \
obj/paddle.o \
obj/sportspad.o
OBJECTS += obj/sound.o \
obj/sn76489.o \
obj/ym2612.o
OBJECTS += obj/Fir_Resampler.o
@ -54,7 +64,8 @@ OBJECTS += obj/sram.o \
obj/ssp16.o \
obj/ggenie.o \
obj/areplay.o \
obj/cart_hw.o
obj/md_cart.o \
obj/sms_cart.o
OBJECTS += obj/main.o \
obj/config.o \
@ -84,6 +95,9 @@ obj/%.o : ../sound/%.c ../sound/%.h
obj/%.o : ../sound/%.c
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
obj/%.o : ../input_hw/%.c ../input_hw/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@
obj/%.o : ../cart_hw/%.c ../cart_hw/%.h
$(CC) -c $(CFLAGS) $(INCLUDES) $(DEFINES) $< -o $@

View File

@ -28,7 +28,7 @@ void set_config_defaults(void)
config.force_dtack = 0;
config.addr_error = 1;
config.tmss = 0;
config.lock_on = 0;
config.lock_on = 0;//TYPE_SK;
config.romtype = 0;
/* display options */
@ -36,13 +36,13 @@ void set_config_defaults(void)
config.render = 0;
/* controllers options */
input.system[0] = SYSTEM_GAMEPAD;
input.system[1] = SYSTEM_GAMEPAD;
input.system[0] = SYSTEM_MD_GAMEPAD;
input.system[1] = SYSTEM_MD_GAMEPAD;
config.gun_cursor[0] = 1;
config.gun_cursor[1] = 1;
config.invert_mouse = 0;
for (i=0;i<MAX_INPUTS;i++)
{
config.input[i].padtype = DEVICE_3BUTTON;
config.input[i].padtype = DEVICE_PAD6B;
}
}

View File

@ -27,7 +27,7 @@ uint8 *load_archive(char *filename, int *file_size)
return (NULL);
}
ret = unzGetCurrentFileInfo(fd, &info, NULL, 0, NULL, 0, NULL, 0);
ret = unzGetCurrentFileInfo(fd, &info, filename, 128, NULL, 0, NULL, 0);
if(ret != UNZ_OK)
{
unzClose(fd);

View File

@ -10,7 +10,7 @@
#define SOUND_FREQUENCY 48000
#define SOUND_SAMPLES_SIZE 2048
#define VIDEO_WIDTH 320
#define VIDEO_WIDTH 320
#define VIDEO_HEIGHT 240
int joynum = 0;
@ -362,11 +362,15 @@ static int sdl_control_update(SDLKey keystate)
}
/* reinitialize VC max value */
vc_max = 0xEA + 24*vdp_pal;
if (reg[1] & 8)
static const uint16 vc_table[4][2] =
{
vc_max += (28 - 20*vdp_pal);
}
/* NTSC, PAL */
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
{0xEA , 0x102}, /* Mode 5 (224 lines) */
{0xDA , 0xF2}, /* Mode 4 (192 lines) */
{0x106, 0x10A} /* Mode 5 (240 lines) */
};
vc_max = vc_table[(reg[1] >> 2) & 3][vdp_pal];
/* reinitialize display area */
bitmap.viewport.changed = 3;
@ -389,11 +393,11 @@ static int sdl_control_update(SDLKey keystate)
case SDLK_F12:
{
while (input.dev[++joynum] == NO_DEVICE)
joynum = (joynum + 1) % MAX_DEVICES;
while (input.dev[joynum] == NO_DEVICE)
{
joynum = joynum % MAX_DEVICES;
joynum = (joynum + 1) % MAX_DEVICES;
}
joynum = joynum % MAX_DEVICES;
break;
}
@ -412,25 +416,10 @@ static int sdl_control_update(SDLKey keystate)
int sdl_input_update(void)
{
uint8 *keystate = SDL_GetKeyState(NULL);
while (input.dev[joynum] == NO_DEVICE)
{
joynum ++;
if (joynum > MAX_DEVICES - 1) joynum = 0;
}
/* reset input */
input.pad[joynum] = 0;
/* keyboard */
if(keystate[SDLK_a]) input.pad[joynum] |= INPUT_A;
if(keystate[SDLK_s]) input.pad[joynum] |= INPUT_B;
if(keystate[SDLK_d]) input.pad[joynum] |= INPUT_C;
if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START;
if(keystate[SDLK_z]) input.pad[joynum] |= INPUT_X;
if(keystate[SDLK_x]) input.pad[joynum] |= INPUT_Y;
if(keystate[SDLK_c]) input.pad[joynum] |= INPUT_Z;
if(keystate[SDLK_v]) input.pad[joynum] |= INPUT_MODE;
switch (input.dev[joynum])
{
case DEVICE_LIGHTGUN:
@ -440,13 +429,46 @@ int sdl_input_update(void)
int state = SDL_GetMouseState(&x,&y);
/* Calculate X Y axis values */
input.analog[joynum - 4][0] = (x * bitmap.viewport.w) / 640;
input.analog[joynum - 4][1] = (y * bitmap.viewport.h) / 480;
input.analog[joynum][0] = (x * bitmap.viewport.w) / VIDEO_WIDTH;
input.analog[joynum][1] = (y * bitmap.viewport.h) / VIDEO_HEIGHT;
/* Map mouse buttons to player #1 inputs */
if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_C;
if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_B;
if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_A;
/* Start,Left,Right,Middle buttons -> 0 0 0 0 START MIDDLE RIGHT LEFT */
if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B;
if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_C;
if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_A;
if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START;
break;
}
case DEVICE_PADDLE:
{
/* get mouse (absolute values) */
int x;
int state = SDL_GetMouseState(&x, NULL);
/* Range is [0;256], 128 being middle position */
input.analog[joynum][0] = x * 256 /VIDEO_WIDTH;
/* Button I -> 0 0 0 0 0 0 0 I*/
if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B;
break;
}
case DEVICE_SPORTSPAD:
{
/* get mouse (relative values) */
int x,y;
int state = SDL_GetRelativeMouseState(&x,&y);
/* Range is [0;256] */
input.analog[joynum][0] = (unsigned char)(-x & 0xFF);
input.analog[joynum][1] = (unsigned char)(-y & 0xFF);
/* Buttons I & II -> 0 0 0 0 0 0 II I*/
if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B;
if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_C;
break;
}
@ -457,24 +479,82 @@ int sdl_input_update(void)
int x,y;
int state = SDL_GetRelativeMouseState(&x,&y);
/* Sega Mouse range is -256;+256 */
input.analog[2][0] = x * 2;
input.analog[2][1] = y * 2;
/* Sega Mouse range is [-256;+256] */
input.analog[joynum][0] = x * 2;
input.analog[joynum][1] = y * 2;
/* Vertical movement is upsidedown */
if (!config.invert_mouse)
input.analog[2][1] = 0 - input.analog[2][1];
input.analog[joynum][1] = 0 - input.analog[joynum][1];
/* Map mouse buttons to player #1 inputs */
if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_C;
if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_B;
if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_A;
/* Start,Left,Right,Middle buttons -> 0 0 0 0 START MIDDLE RIGHT LEFT */
if(state & SDL_BUTTON_LMASK) input.pad[joynum] |= INPUT_B;
if(state & SDL_BUTTON_RMASK) input.pad[joynum] |= INPUT_C;
if(state & SDL_BUTTON_MMASK) input.pad[joynum] |= INPUT_A;
if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START;
break;
}
case DEVICE_XE_A1P:
{
/* A,B,C,D,Select,START,E1,E2 buttons -> E1(?) E2(?) START SELECT(?) A B C D */
if(keystate[SDLK_a]) input.pad[joynum] |= INPUT_START;
if(keystate[SDLK_s]) input.pad[joynum] |= INPUT_A;
if(keystate[SDLK_d]) input.pad[joynum] |= INPUT_C;
if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_Y;
if(keystate[SDLK_z]) input.pad[joynum] |= INPUT_B;
if(keystate[SDLK_x]) input.pad[joynum] |= INPUT_X;
if(keystate[SDLK_c]) input.pad[joynum] |= INPUT_MODE;
if(keystate[SDLK_v]) input.pad[joynum] |= INPUT_Z;
/* Left Analog Stick (bidirectional) */
if(keystate[SDLK_UP]) input.analog[joynum][1]-=2;
else if(keystate[SDLK_DOWN]) input.analog[joynum][1]+=2;
else input.analog[joynum][1] = 128;
if(keystate[SDLK_LEFT]) input.analog[joynum][0]-=2;
else if(keystate[SDLK_RIGHT]) input.analog[joynum][0]+=2;
else input.analog[joynum][0] = 128;
/* Right Analog Stick (unidirectional) */
if(keystate[SDLK_KP8]) input.analog[joynum+1][0]-=2;
else if(keystate[SDLK_KP2]) input.analog[joynum+1][0]+=2;
else if(keystate[SDLK_KP4]) input.analog[joynum+1][0]-=2;
else if(keystate[SDLK_KP6]) input.analog[joynum+1][0]+=2;
else input.analog[joynum+1][0] = 128;
/* Limiters */
if (input.analog[joynum][0] > 0xFF) input.analog[joynum][0] = 0xFF;
else if (input.analog[joynum][0] < 0) input.analog[joynum][0] = 0;
if (input.analog[joynum][1] > 0xFF) input.analog[joynum][1] = 0xFF;
else if (input.analog[joynum][1] < 0) input.analog[joynum][1] = 0;
if (input.analog[joynum+1][0] > 0xFF) input.analog[joynum+1][0] = 0xFF;
else if (input.analog[joynum+1][0] < 0) input.analog[joynum+1][0] = 0;
if (input.analog[joynum+1][1] > 0xFF) input.analog[joynum+1][1] = 0xFF;
else if (input.analog[joynum+1][1] < 0) input.analog[joynum+1][1] = 0;
break;
}
case DEVICE_ACTIVATOR:
{
if(keystate[SDLK_g]) input.pad[joynum] |= INPUT_ACTIVATOR_7L;
if(keystate[SDLK_h]) input.pad[joynum] |= INPUT_ACTIVATOR_7U;
if(keystate[SDLK_j]) input.pad[joynum] |= INPUT_ACTIVATOR_8L;
if(keystate[SDLK_k]) input.pad[joynum] |= INPUT_ACTIVATOR_8U;
}
default:
{
if(keystate[SDLK_a]) input.pad[joynum] |= INPUT_A;
if(keystate[SDLK_s]) input.pad[joynum] |= INPUT_B;
if(keystate[SDLK_d]) input.pad[joynum] |= INPUT_C;
if(keystate[SDLK_f]) input.pad[joynum] |= INPUT_START;
if(keystate[SDLK_z]) input.pad[joynum] |= INPUT_X;
if(keystate[SDLK_x]) input.pad[joynum] |= INPUT_Y;
if(keystate[SDLK_c]) input.pad[joynum] |= INPUT_Z;
if(keystate[SDLK_v]) input.pad[joynum] |= INPUT_MODE;
if(keystate[SDLK_UP]) input.pad[joynum] |= INPUT_UP;
else
if(keystate[SDLK_DOWN]) input.pad[joynum] |= INPUT_DOWN;

2205
source/vdp_ctrl.c Normal file

File diff suppressed because it is too large Load Diff

86
source/vdp_ctrl.h Normal file
View File

@ -0,0 +1,86 @@
/***************************************************************************************
* Genesis Plus
* Video Display Processor (68k & Z80 CPU interface)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
*
****************************************************************************************/
#ifndef _VDP_H_
#define _VDP_H_
/* VDP context */
extern uint8 reg[0x20];
extern uint8 sat[0x400];
extern uint8 vram[0x10000];
extern uint8 cram[0x80];
extern uint8 vsram[0x80];
extern uint8 hint_pending;
extern uint8 vint_pending;
extern uint8 m68k_irq_state;
extern uint16 status;
extern uint32 dma_length;
/* Global variables */
extern uint16 ntab;
extern uint16 ntbb;
extern uint16 ntwb;
extern uint16 satb;
extern uint16 hscb;
extern uint8 bg_name_dirty[0x800];
extern uint16 bg_name_list[0x800];
extern uint16 bg_list_index;
extern uint8 bg_pattern_cache[0x80000];
extern uint8 hscroll_mask;
extern uint8 playfield_shift;
extern uint8 playfield_col_mask;
extern uint16 playfield_row_mask;
extern uint8 odd_frame;
extern uint8 im2_flag;
extern uint8 interlaced;
extern uint8 vdp_pal;
extern uint16 v_counter;
extern uint16 vc_max;
extern uint16 hscroll;
extern uint16 vscroll;
extern uint16 lines_per_frame;
extern int32 fifo_write_cnt;
extern uint32 fifo_lastwrite;
extern uint32 hvc_latch;
extern const uint8 *hctab;
/* Function pointers */
extern void (*vdp_68k_data_w)(unsigned int data);
extern void (*vdp_z80_data_w)(unsigned int data);
extern unsigned int (*vdp_68k_data_r)(void);
extern unsigned int (*vdp_z80_data_r)(void);
/* Function prototypes */
extern void vdp_init(void);
extern void vdp_reset(void);
extern int vdp_context_save(uint8 *state);
extern int vdp_context_load(uint8 *state, char *version);
extern void vdp_dma_update(unsigned int cycles);
extern void vdp_68k_ctrl_w(unsigned int data);
extern void vdp_z80_ctrl_w(unsigned int data);
extern unsigned int vdp_ctrl_r(unsigned int cycles);
extern unsigned int vdp_hvc_r(unsigned int cycles);
extern void vdp_test_w(unsigned int data);
extern int vdp_68k_irq_ack(int int_level);
#endif /* _VDP_H_ */

3705
source/vdp_render.c Normal file

File diff suppressed because it is too large Load Diff

65
source/vdp_render.h Normal file
View File

@ -0,0 +1,65 @@
/***************************************************************************************
* Genesis Plus
* Video Display Processor (Mode 4 & Mode 5 rendering)
*
* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Charles Mac Donald (original code)
* Eke-Eke (2007-2011), additional code & fixes for the GCN/Wii port
*
* 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
*
****************************************************************************************/
#ifndef _RENDER_H_
#define _RENDER_H_
/* Global variables */
extern uint8 object_count;
/* Function prototypes */
extern void render_init(void);
extern void render_reset(void);
extern void render_line(int line);
extern void blank_line(int line, int offset, int width);
extern void remap_line(int line);
extern void window_clip(unsigned int data, unsigned int sw);
extern void render_bg_m4(int line, int width);
extern void render_bg_m5(int line, int width);
extern void render_bg_m5_vs(int line, int width);
extern void render_bg_m5_im2(int line, int width);
extern void render_bg_m5_im2_vs(int line, int width);
extern void render_obj_m4(int max_width);
extern void render_obj_m5(int max_width);
extern void render_obj_m5_ste(int max_width);
extern void render_obj_m5_im2(int max_width);
extern void render_obj_m5_im2_ste(int max_width);
extern void parse_satb_m4(int line);
extern void parse_satb_m5(int line);
extern void update_bg_pattern_cache_m4(int index);
extern void update_bg_pattern_cache_m5(int index);
#ifdef NGC
extern void color_update(int index, unsigned int data);
#endif
/* Function pointers */
extern void (*render_bg)(int line, int width);
extern void (*render_obj)(int max_width);
extern void (*parse_satb)(int line);
extern void (*update_bg_pattern_cache)(int index);
#ifndef NGC
extern void (*color_update)(int index, unsigned int data);
#endif
#endif /* _RENDER_H_ */

View File

@ -1,27 +1,26 @@
/*******************************************************************************
* *
* Define size independent data types and operations. *
* *
* The following types must be supported by all platforms: *
* *
* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer *
* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer *
* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer *
* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer *
* *
* *
* *
* Define size independent data types and operations. *
* *
* The following types must be supported by all platforms: *
* *
* UINT8 - Unsigned 8-bit Integer INT8 - Signed 8-bit integer *
* UINT16 - Unsigned 16-bit Integer INT16 - Signed 16-bit integer *
* UINT32 - Unsigned 32-bit Integer INT32 - Signed 32-bit integer *
* UINT64 - Unsigned 64-bit Integer INT64 - Signed 64-bit integer *
* *
* *
* The macro names for the artithmatic operations are composed as follows: *
* *
* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) *
* R - The type of the result *
* A - The type of operand 1 *
* B - The type of operand 2 (if binary operation) *
* *
* Each type is one of: U8,8,U16,16,U32,32,U64,64 *
* *
* *
* XXX_R_A_B, where XXX - 3 letter operation code (ADD, SUB, etc.) *
* R - The type of the result *
* A - The type of operand 1 *
* B - The type of operand 2 (if binary operation) *
* *
* Each type is one of: U8,8,U16,16,U32,32,U64,64 *
* *
*******************************************************************************/
#ifndef OSD_CPU_H
#define OSD_CPU_H
@ -52,6 +51,7 @@ __extension__ typedef signed long long INT64;
* thus PAIR.d can be used to pass arguments to the memory system
* which expects 'int' really.
******************************************************************************/
typedef union {
#ifdef LSB_FIRST
struct { UINT8 l,h,h2,h3; } b;

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,18 @@
#ifndef Z80_H_
#define Z80_H_
#include "cpuintrf.h"
#include "memz80.h"
#include "osd_cpu.h"
enum
{
/* line states */
CLEAR_LINE = 0, /* clear (a fired, held or pulsed) line */
ASSERT_LINE, /* assert an interrupt immediately */
HOLD_LINE, /* hold interrupt line until acknowledged */
PULSE_LINE /* pulse interrupt line for one instruction */
};
enum {
Z80_PC, Z80_SP,
Z80_A, Z80_B, Z80_C, Z80_D, Z80_E, Z80_H, Z80_L,
Z80_AF, Z80_BC, Z80_DE, Z80_HL,
@ -43,14 +50,22 @@ typedef struct
extern Z80_Regs Z80;
void z80_init(const void *config, int (*irqcallback)(int));
void z80_reset (void);
void z80_exit (void);
void z80_run(unsigned int cycles);
void z80_burn(unsigned int cycles);
void z80_get_context (void *dst);
void z80_set_context (void *src);
void z80_set_irq_line(int irqline, int state);
extern unsigned char *z80_readmap[64];
extern unsigned char *z80_writemap[64];
extern void (*z80_writemem)(unsigned int address, unsigned char data);
extern unsigned char (*z80_readmem)(unsigned int port);
extern void (*z80_writeport)(unsigned int port, unsigned char data);
extern unsigned char (*z80_readport)(unsigned int port);
extern void z80_init(const void *config, int (*irqcallback)(int));
extern void z80_reset (void);
extern void z80_exit (void);
extern void z80_run(unsigned int cycles);
extern void z80_burn(unsigned int cycles);
extern void z80_get_context (void *dst);
extern void z80_set_context (void *src);
extern void z80_set_nmi_line(int state);
#endif