Ported DC, SMS and SG1000 to main folder, nw

This commit is contained in:
Angelo Salese 2011-05-06 10:52:23 +00:00
parent 249c2c6402
commit f280fd9f99
27 changed files with 14059 additions and 0 deletions

24
.gitattributes vendored
View File

@ -665,6 +665,8 @@ src/emu/fileio.c svneol=native#text/plain
src/emu/fileio.h svneol=native#text/plain
src/emu/hash.c svneol=native#text/plain
src/emu/hash.h svneol=native#text/plain
src/emu/hashfile.c svneol=native#text/plain
src/emu/hashfile.h svneol=native#text/plain
src/emu/image.c svneol=native#text/plain
src/emu/image.h svneol=native#text/plain
src/emu/imagedev/bitbngr.c svneol=native#text/plain
@ -857,6 +859,8 @@ src/emu/machine/msm58321.c svneol=native#text/plain
src/emu/machine/msm58321.h svneol=native#text/plain
src/emu/machine/msm6242.c svneol=native#text/plain
src/emu/machine/msm6242.h svneol=native#text/plain
src/emu/machine/msm8251.c svneol=native#text/plain
src/emu/machine/msm8251.h svneol=native#text/plain
src/emu/machine/nmc9306.c svneol=native#text/plain
src/emu/machine/nmc9306.h svneol=native#text/plain
src/emu/machine/nvram.c svneol=native#text/plain
@ -903,6 +907,8 @@ src/emu/machine/scsihd.c svneol=native#text/plain
src/emu/machine/scsihd.h svneol=native#text/plain
src/emu/machine/secflash.c svneol=native#text/plain
src/emu/machine/secflash.h svneol=native#text/plain
src/emu/machine/serial.c svneol=native#text/plain
src/emu/machine/serial.h svneol=native#text/plain
src/emu/machine/smc91c9x.c svneol=native#text/plain
src/emu/machine/smc91c9x.h svneol=native#text/plain
src/emu/machine/timekpr.c svneol=native#text/plain
@ -917,6 +923,8 @@ src/emu/machine/upd4701.c svneol=native#text/plain
src/emu/machine/upd4701.h svneol=native#text/plain
src/emu/machine/upd7201.c svneol=native#text/plain
src/emu/machine/upd7201.h svneol=native#text/plain
src/emu/machine/upd765.c svneol=native#text/plain
src/emu/machine/upd765.h svneol=native#text/plain
src/emu/machine/wd33c93.c svneol=native#text/plain
src/emu/machine/wd33c93.h svneol=native#text/plain
src/emu/machine/x2212.c svneol=native#text/plain
@ -1783,6 +1791,7 @@ src/mame/drivers/darkseal.c svneol=native#text/plain
src/mame/drivers/dassault.c svneol=native#text/plain
src/mame/drivers/dblewing.c svneol=native#text/plain
src/mame/drivers/dbz.c svneol=native#text/plain
src/mame/drivers/dc.c svneol=native#text/plain
src/mame/drivers/dcheese.c svneol=native#text/plain
src/mame/drivers/dcon.c svneol=native#text/plain
src/mame/drivers/dday.c svneol=native#text/plain
@ -2407,6 +2416,7 @@ src/mame/drivers/segas16b.c svneol=native#text/plain
src/mame/drivers/segas18.c svneol=native#text/plain
src/mame/drivers/segas24.c svneol=native#text/plain
src/mame/drivers/segas32.c svneol=native#text/plain
src/mame/drivers/segasms.c svneol=native#text/plain
src/mame/drivers/segaxbd.c svneol=native#text/plain
src/mame/drivers/segaybd.c svneol=native#text/plain
src/mame/drivers/seibuspi.c svneol=native#text/plain
@ -2419,6 +2429,7 @@ src/mame/drivers/sf.c svneol=native#text/plain
src/mame/drivers/sfbonus.c svneol=native#text/plain
src/mame/drivers/sfcbox.c svneol=native#text/plain
src/mame/drivers/sfkick.c svneol=native#text/plain
src/mame/drivers/sg1000.c svneol=native#text/plain
src/mame/drivers/sg1000a.c svneol=native#text/plain
src/mame/drivers/shadfrce.c svneol=native#text/plain
src/mame/drivers/shangha3.c svneol=native#text/plain
@ -2705,6 +2716,8 @@ src/mame/drivers/zodiack.c svneol=native#text/plain
src/mame/drivers/zr107.c svneol=native#text/plain
src/mame/etc/fd1094dp.c svneol=native#text/plain
src/mame/etc/jrcrypt.c svneol=native#text/plain
src/mame/formats/basicdsk.c svneol=native#text/plain
src/mame/formats/basicdsk.h svneol=native#text/plain
src/mame/includes/1942.h svneol=native#text/plain
src/mame/includes/1943.h svneol=native#text/plain
src/mame/includes/20pacgal.h svneol=native#text/plain
@ -3196,6 +3209,7 @@ src/mame/includes/segamsys.h svneol=native#text/plain
src/mame/includes/segas16.h svneol=native#text/plain
src/mame/includes/segas24.h svneol=native#text/plain
src/mame/includes/segas32.h svneol=native#text/plain
src/mame/includes/segasms.h svneol=native#text/plain
src/mame/includes/sei_crtc.h svneol=native#text/plain
src/mame/includes/seibuspi.h svneol=native#text/plain
src/mame/includes/seicross.h svneol=native#text/plain
@ -3203,6 +3217,7 @@ src/mame/includes/senjyo.h svneol=native#text/plain
src/mame/includes/seta.h svneol=native#text/plain
src/mame/includes/seta2.h svneol=native#text/plain
src/mame/includes/sf.h svneol=native#text/plain
src/mame/includes/sg1000.h svneol=native#text/plain
src/mame/includes/shadfrce.h svneol=native#text/plain
src/mame/includes/shangha3.h svneol=native#text/plain
src/mame/includes/shangkid.h svneol=native#text/plain
@ -3510,6 +3525,7 @@ src/mame/layout/slots.lay svneol=native#text/plain
src/mame/layout/sltblgpo.lay svneol=native#text/plain
src/mame/layout/sltblgtk.lay svneol=native#text/plain
src/mame/layout/smoto.lay svneol=native#text/plain
src/mame/layout/sms1.lay svneol=native#text/plain
src/mame/layout/snookr10.lay svneol=native#text/plain
src/mame/layout/solarq.lay svneol=native#text/plain
src/mame/layout/sos.lay svneol=native#text/plain
@ -3580,6 +3596,8 @@ src/mame/machine/cdislave.c svneol=native#text/plain
src/mame/machine/cdislave.h svneol=native#text/plain
src/mame/machine/chaknpop.c svneol=native#text/plain
src/mame/machine/cps2crpt.c svneol=native#text/plain
src/mame/machine/ctronics.c svneol=native#text/plain
src/mame/machine/ctronics.h svneol=native#text/plain
src/mame/machine/cx4data.c svneol=native#text/plain
src/mame/machine/cx4fn.c svneol=native#text/plain
src/mame/machine/cx4oam.c svneol=native#text/plain
@ -3587,6 +3605,7 @@ src/mame/machine/cx4ops.c svneol=native#text/plain
src/mame/machine/dc-ctrl.c svneol=native#text/plain
src/mame/machine/dc-ctrl.h svneol=native#text/plain
src/mame/machine/dc.c svneol=native#text/plain
src/mame/machine/dccons.c svneol=native#text/plain
src/mame/machine/dec0.c svneol=native#text/plain
src/mame/machine/deco102.c svneol=native#text/plain
src/mame/machine/deco156.c svneol=native#text/plain
@ -3609,6 +3628,8 @@ src/mame/machine/gaelcrpt.c svneol=native#text/plain
src/mame/machine/galaxold.c svneol=native#text/plain
src/mame/machine/gaplus.c svneol=native#text/plain
src/mame/machine/gdcrypt.c svneol=native#text/plain
src/mame/machine/gdrom.c svneol=native#text/plain
src/mame/machine/gdrom.h svneol=native#text/plain
src/mame/machine/harddriv.c svneol=native#text/plain
src/mame/machine/irem_cpu.c svneol=native#text/plain
src/mame/machine/irem_cpu.h svneol=native#text/plain
@ -3720,6 +3741,7 @@ src/mame/machine/segaic16.c svneol=native#text/plain
src/mame/machine/segaic16.h svneol=native#text/plain
src/mame/machine/segamsys.c svneol=native#text/plain
src/mame/machine/segas32.c svneol=native#text/plain
src/mame/machine/segasms.c svneol=native#text/plain
src/mame/machine/seibuspi.c svneol=native#text/plain
src/mame/machine/seibuspi.h svneol=native#text/plain
src/mame/machine/seicop.c svneol=native#text/plain
@ -4342,6 +4364,8 @@ src/mame/video/skykid.c svneol=native#text/plain
src/mame/video/skyraid.c svneol=native#text/plain
src/mame/video/slapfght.c svneol=native#text/plain
src/mame/video/slapshot.c svneol=native#text/plain
src/mame/video/smsvdp.c svneol=native#text/plain
src/mame/video/smsvdp.h svneol=native#text/plain
src/mame/video/snes.c svneol=native#text/plain
src/mame/video/snk.c svneol=native#text/plain
src/mame/video/snk6502.c svneol=native#text/plain

View File

@ -44,6 +44,7 @@ OBJDIRS += \
#-------------------------------------------------
EMUOBJS = \
$(EMUOBJ)/hashfile.o \
$(EMUOBJ)/addrmap.o \
$(EMUOBJ)/attotime.o \
$(EMUOBJ)/audit.o \
@ -204,6 +205,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/msm5832.o \
$(EMUMACHINE)/msm58321.o \
$(EMUMACHINE)/msm6242.o \
$(EMUMACHINE)/msm8251.o \
$(EMUMACHINE)/nmc9306.o \
$(EMUMACHINE)/nvram.o \
$(EMUMACHINE)/pc16552d.o \
@ -225,6 +227,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/scsidev.o \
$(EMUMACHINE)/scsihd.o \
$(EMUMACHINE)/secflash.o \
$(EMUMACHINE)/serial.o \
$(EMUMACHINE)/smc91c9x.o \
$(EMUMACHINE)/timekpr.o \
$(EMUMACHINE)/tmp68301.o \
@ -232,6 +235,7 @@ EMUMACHINEOBJS = \
$(EMUMACHINE)/upd1990a.o \
$(EMUMACHINE)/upd4701.o \
$(EMUMACHINE)/upd7201.o \
$(EMUMACHINE)/upd765.o \
$(EMUMACHINE)/wd33c93.o \
$(EMUMACHINE)/x2212.o \
$(EMUMACHINE)/x76f041.o \

617
src/emu/hashfile.c Normal file
View File

@ -0,0 +1,617 @@
/*********************************************************************
hashfile.c
Code for parsing hash info (*.hsi) files
*********************************************************************/
#include "hashfile.h"
#include "pool.h"
#include "expat.h"
#include "emuopts.h"
#include "hash.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _hash_info hash_info;
struct _hash_info
{
hash_collection *hashes;
const char *extrainfo;
};
typedef struct _hash_file hash_file;
typedef void (*hashfile_error_func)(const char *message);
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* opens a hash file; if is_preload is non-zero, the entire file is preloaded */
hash_file *hashfile_open(emu_options &options, const char *sysname, int is_preload, hashfile_error_func error_proc);
/* closes a hash file and associated resources */
void hashfile_close(hash_file *hashfile);
/* looks up information in a hash file */
const hash_info *hashfile_lookup(hash_file *hashfile, const hash_collection *hashes);
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
struct _hash_file
{
emu_file *file;
object_pool *pool;
astring functions[IO_COUNT];
hash_info **preloaded_hashes;
int preloaded_hash_count;
void (*error_proc)(const char *message);
};
enum hash_parse_position
{
HASH_POS_ROOT,
HASH_POS_MAIN,
HASH_POS_HASH
};
struct hash_parse_state
{
XML_Parser parser;
hash_file *hashfile;
int done;
int (*selector_proc)(hash_file *hashfile, void *param, const char *name, const hash_collection *hashes);
void (*use_proc)(hash_file *hashfile, void *param, hash_info *hi);
void (*error_proc)(const char *message);
void *param;
enum hash_parse_position pos;
char **text_dest;
hash_info *hi;
};
/***************************************************************************
PROTOTYPES
***************************************************************************/
static void *expat_malloc(size_t size);
static void *expat_realloc(void *ptr, size_t size);
static void expat_free(void *ptr);
/***************************************************************************
CORE IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
parse_error
-------------------------------------------------*/
static void ATTR_PRINTF(2,3) parse_error(struct hash_parse_state *state, const char *fmt, ...)
{
char buf[256];
va_list va;
if (state->error_proc)
{
va_start(va, fmt);
vsnprintf(buf, ARRAY_LENGTH(buf), fmt, va);
va_end(va);
(*state->error_proc)(buf);
}
}
/*-------------------------------------------------
unknown_tag
-------------------------------------------------*/
static void unknown_tag(struct hash_parse_state *state, const char *tagname)
{
parse_error(state, "[%lu:%lu]: Unknown tag: %s\n",
XML_GetCurrentLineNumber(state->parser),
XML_GetCurrentColumnNumber(state->parser),
tagname);
}
/*-------------------------------------------------
unknown_attribute
-------------------------------------------------*/
static void unknown_attribute(struct hash_parse_state *state, const char *attrname)
{
parse_error(state, "[%lu:%lu]: Unknown attribute: %s\n",
XML_GetCurrentLineNumber(state->parser),
XML_GetCurrentColumnNumber(state->parser),
attrname);
}
/*-------------------------------------------------
unknown_attribute_value
-------------------------------------------------*/
static void unknown_attribute_value(struct hash_parse_state *state,
const char *attrname, const char *attrvalue)
{
parse_error(state, "[%lu:%lu]: Unknown attribute value: %s\n",
XML_GetCurrentLineNumber(state->parser),
XML_GetCurrentColumnNumber(state->parser),
attrvalue);
}
/*-------------------------------------------------
start_handler
-------------------------------------------------*/
static void start_handler(void *data, const char *tagname, const char **attributes)
{
struct hash_parse_state *state = (struct hash_parse_state *) data;
const char *name;
hash_info *hi;
char **text_dest;
hash_collection hashes;
astring all_functions;
char functions;
iodevice_t device;
int i;
switch(state->pos)
{
case HASH_POS_ROOT:
if (!strcmp(tagname, "hashfile"))
{
}
else
{
unknown_tag(state, tagname);
}
break;
case HASH_POS_MAIN:
if (!strcmp(tagname, "hash"))
{
// we are now examining a hash tag
name = NULL;
device = IO_COUNT;
while(attributes[0])
{
functions = 0;
if (!strcmp(attributes[0], "name"))
{
/* name attribute */
name = attributes[1];
}
else if (!strcmp(attributes[0], "crc32"))
{
/* crc32 attribute */
functions = hash_collection::HASH_CRC;
}
else if (!strcmp(attributes[0], "md5"))
{
/* md5 attribute */
functions = hash_collection::HASH_MD5;
}
else if (!strcmp(attributes[0], "sha1"))
{
/* sha1 attribute */
functions = hash_collection::HASH_SHA1;
}
else if (!strcmp(attributes[0], "type"))
{
/* type attribute */
i = 0;//device_typeid(attributes[1]);
if (i < 0)
unknown_attribute_value(state, attributes[0], attributes[1]);
else
device = (iodevice_t) i;
}
else
{
/* unknown attribute */
unknown_attribute(state, attributes[0]);
}
if (functions)
{
hashes.add_from_string(functions, attributes[1], strlen(attributes[1]));
all_functions.cat(functions);
}
attributes += 2;
}
/* do we use this hash? */
if (!state->selector_proc || state->selector_proc(state->hashfile, state->param, name, &hashes))
{
hi = (hash_info*)pool_malloc_lib(state->hashfile->pool, sizeof(hash_info));
if (!hi)
return;
memset(hi, 0, sizeof(*hi));
hi->hashes = &hashes;
state->hi = hi;
}
}
else
{
unknown_tag(state, tagname);
}
break;
case HASH_POS_HASH:
text_dest = NULL;
if (!strcmp(tagname, "year")) {
}
else if (!strcmp(tagname, "manufacturer")){
}
else if (!strcmp(tagname, "status")){
}
else if (!strcmp(tagname, "pcb")){
}
else if (!strcmp(tagname, "extrainfo")) {
text_dest = (char **) &state->hi->extrainfo;
}
else
unknown_tag(state, tagname);
if (text_dest && state->hi)
state->text_dest = text_dest;
break;
}
state->pos = (hash_parse_position) (state->pos + 1);
}
/*-------------------------------------------------
end_handler
-------------------------------------------------*/
static void end_handler(void *data, const char *name)
{
struct hash_parse_state *state = (struct hash_parse_state *) data;
state->text_dest = NULL;
state->pos = (hash_parse_position) (state->pos - 1);
switch(state->pos)
{
case HASH_POS_ROOT:
case HASH_POS_HASH:
break;
case HASH_POS_MAIN:
if (state->hi)
{
if (state->use_proc)
(*state->use_proc)(state->hashfile, state->param, state->hi);
state->hi = NULL;
}
break;
}
}
/*-------------------------------------------------
data_handler
-------------------------------------------------*/
static void data_handler(void *data, const XML_Char *s, int len)
{
struct hash_parse_state *state = (struct hash_parse_state *) data;
int text_len;
char *text;
if (state->text_dest)
{
text = *state->text_dest;
text_len = text ? strlen(text) : 0;
text = (char*)pool_realloc_lib(state->hashfile->pool, text, text_len + len + 1);
if (!text)
return;
memcpy(&text[text_len], s, len);
text[text_len + len] = '\0';
*state->text_dest = text;
}
}
/*-------------------------------------------------
hashfile_parse
-------------------------------------------------*/
static void hashfile_parse(hash_file *hashfile,
int (*selector_proc)(hash_file *hashfile, void *param, const char *name, const hash_collection *hashes),
void (*use_proc)(hash_file *hashfile, void *param, hash_info *hi),
void (*error_proc)(const char *message),
void *param)
{
struct hash_parse_state state;
char buf[1024];
UINT32 len;
XML_Memory_Handling_Suite memcallbacks;
hashfile->file->seek(0, SEEK_SET);
memset(&state, 0, sizeof(state));
state.hashfile = hashfile;
state.selector_proc = selector_proc;
state.use_proc = use_proc;
state.error_proc = error_proc;
state.param = param;
/* create the XML parser */
memcallbacks.malloc_fcn = expat_malloc;
memcallbacks.realloc_fcn = expat_realloc;
memcallbacks.free_fcn = expat_free;
state.parser = XML_ParserCreate_MM(NULL, &memcallbacks, NULL);
if (!state.parser)
goto done;
XML_SetUserData(state.parser, &state);
XML_SetElementHandler(state.parser, start_handler, end_handler);
XML_SetCharacterDataHandler(state.parser, data_handler);
while(!state.done)
{
len = hashfile->file->read(buf, sizeof(buf));
state.done = hashfile->file->eof();
if (XML_Parse(state.parser, buf, len, state.done) == XML_STATUS_ERROR)
{
parse_error(&state, "[%lu:%lu]: %s\n",
XML_GetCurrentLineNumber(state.parser),
XML_GetCurrentColumnNumber(state.parser),
XML_ErrorString(XML_GetErrorCode(state.parser)));
goto done;
}
}
done:
if (state.parser)
XML_ParserFree(state.parser);
}
/*-------------------------------------------------
preload_use_proc
-------------------------------------------------*/
static void preload_use_proc(hash_file *hashfile, void *param, hash_info *hi)
{
hash_info **new_preloaded_hashes;
new_preloaded_hashes = (hash_info **)pool_realloc_lib(hashfile->pool, hashfile->preloaded_hashes,
(hashfile->preloaded_hash_count + 1) * sizeof(*new_preloaded_hashes));
if (!new_preloaded_hashes)
return;
hashfile->preloaded_hashes = new_preloaded_hashes;
hashfile->preloaded_hashes[hashfile->preloaded_hash_count++] = hi;
}
/*-------------------------------------------------
hashfile_open
-------------------------------------------------*/
hash_file *hashfile_open(emu_options &options, const char *sysname, int is_preload,
void (*error_proc)(const char *message))
{
hash_file *hashfile = NULL;
object_pool *pool = NULL;
file_error filerr;
/* create a pool for this hash file */
pool = pool_alloc_lib(error_proc);
if (!pool)
goto error;
/* allocate space for this hash file */
hashfile = (hash_file *) pool_malloc_lib(pool, sizeof(*hashfile));
if (!hashfile)
goto error;
/* set up the hashfile structure */
memset(hashfile, 0, sizeof(*hashfile));
hashfile->pool = pool;
hashfile->error_proc = error_proc;
/* open a file */
hashfile->file = global_alloc(emu_file(options.hash_path(), OPEN_FLAG_READ));
filerr = hashfile->file->open(sysname, ".hsi");
if (filerr != FILERR_NONE)
{
global_free(hashfile->file);
hashfile->file = NULL;
goto error;
}
if (is_preload)
hashfile_parse(hashfile, NULL, preload_use_proc, hashfile->error_proc, NULL);
return hashfile;
error:
if (hashfile != NULL)
hashfile_close(hashfile);
return NULL;
}
/*-------------------------------------------------
hashfile_close
-------------------------------------------------*/
void hashfile_close(hash_file *hashfile)
{
global_free(hashfile->file);
pool_free_lib(hashfile->pool);
}
/*-------------------------------------------------
singular_selector_proc
-------------------------------------------------*/
struct hashlookup_params
{
const hash_collection *hashes;
hash_info *hi;
};
static int singular_selector_proc(hash_file *hashfile, void *param, const char *name, const hash_collection *hashes)
{
astring tempstr;
struct hashlookup_params *hlparams = (struct hashlookup_params *) param;
return (*hashes == *hlparams->hashes);
}
/*-------------------------------------------------
singular_use_proc
-------------------------------------------------*/
static void singular_use_proc(hash_file *hashfile, void *param, hash_info *hi)
{
struct hashlookup_params *hlparams = (struct hashlookup_params *) param;
hlparams->hi = hi;
}
/*-------------------------------------------------
hashfile_lookup
-------------------------------------------------*/
const hash_info *hashfile_lookup(hash_file *hashfile, const hash_collection *hashes)
{
struct hashlookup_params param;
int i;
param.hashes = hashes;
param.hi = NULL;
for (i = 0; i < hashfile->preloaded_hash_count; i++)
{
if (singular_selector_proc(hashfile, &param, NULL, hashfile->preloaded_hashes[i]->hashes))
return hashfile->preloaded_hashes[i];
}
hashfile_parse(hashfile, singular_selector_proc, singular_use_proc,
hashfile->error_proc, (void *) &param);
return param.hi;
}
const char *extra_info = NULL;
const char *read_hash_config(device_image_interface &image, const char *sysname)
{
hash_file *hashfile = NULL;
const hash_info *info = NULL;
/* open the hash file */
hashfile = hashfile_open(image.device().machine().options(), sysname, FALSE, NULL);
if (!hashfile)
return NULL;
/* look up this entry in the hash file */
info = hashfile_lookup(hashfile, &image.hash());
if (!info || !info->extrainfo)
{
hashfile_close(hashfile);
return NULL;
}
extra_info = auto_strdup(image.device().machine(),info->extrainfo);
if (!extra_info)
{
hashfile_close(hashfile);
return NULL;
}
/* copy the relevant entries */
hashfile_close(hashfile);
return extra_info;
}
const char *hashfile_extrainfo(device_image_interface &image)
{
const char *rc;
/* now read the hash file */
image.crc();
extra_info = NULL;
int drv = driver_list::find(image.device().machine().system());
do
{
rc = read_hash_config(image,driver_list::driver(drv).name);
drv = driver_list::compatible_with(drv);
}
while(rc!=NULL && drv != -1);
return rc;
}
/***************************************************************************
EXPAT INTERFACES
***************************************************************************/
/*-------------------------------------------------
expat_malloc/expat_realloc/expat_free -
wrappers for memory allocation functions so
that they pass through out memory tracking
systems
-------------------------------------------------*/
static void *expat_malloc(size_t size)
{
return global_alloc_array_clear(UINT8,size);
}
static void *expat_realloc(void *ptr, size_t size)
{
if (ptr) global_free(ptr);
return global_alloc_array_clear(UINT8,size);
}
static void expat_free(void *ptr)
{
global_free(ptr);
}

17
src/emu/hashfile.h Normal file
View File

@ -0,0 +1,17 @@
/*********************************************************************
hashfile.h
Code for parsing hash info (*.hsi) files
*********************************************************************/
#ifndef __HASHFILE_H__
#define __HASHFILE_H__
#include "emu.h"
const char *hashfile_extrainfo(device_image_interface &image);
#endif /* __HASHFILE_H__ */

825
src/emu/machine/msm8251.c Normal file
View File

@ -0,0 +1,825 @@
/*********************************************************************
msm8251.c
MSM/Intel 8251 Universal Synchronous/Asynchronous Receiver Transmitter code
*********************************************************************/
#include "emu.h"
#include "msm8251.h"
/***************************************************************************
MACROS
***************************************************************************/
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _msm8251_t msm8251_t;
struct _msm8251_t
{
devcb_resolved_read_line in_rxd_func;
devcb_resolved_write_line out_txd_func;
devcb_resolved_read_line in_dsr_func;
devcb_resolved_write_line out_dtr_func;
devcb_resolved_write_line out_rts_func;
devcb_resolved_write_line out_rxrdy_func;
devcb_resolved_write_line out_txrdy_func;
devcb_resolved_write_line out_txempty_func;
devcb_resolved_write_line out_syndet_func;
/* flags controlling how msm8251_control_w operates */
UINT8 flags;
/* offset into sync_bytes used during sync byte transfer */
UINT8 sync_byte_offset;
/* number of sync bytes written so far */
UINT8 sync_byte_count;
/* the sync bytes written */
UINT8 sync_bytes[2];
/* status of msm8251 */
UINT8 status;
UINT8 command;
/* mode byte - bit definitions depend on mode - e.g. synchronous, asynchronous */
UINT8 mode_byte;
/* data being received */
UINT8 data;
/* receive reg */
serial_receive_register receive_reg;
/* transmit reg */
serial_transmit_register transmit_reg;
data_form form;
/* the serial connection that data is transfered over */
/* this is usually connected to the serial device */
serial_connection connection;
};
/***************************************************************************
PROTOTYPES
***************************************************************************/
static void msm8251_in_callback(running_machine &machine, int id, unsigned long state);
static void msm8251_update_tx_empty(device_t *device);
static void msm8251_update_tx_ready(device_t *device);
/***************************************************************************
INLINE FUNCTIONS
***************************************************************************/
INLINE msm8251_t *get_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == MSM8251);
return (msm8251_t *) downcast<legacy_device_base *>(device)->token();
}
INLINE const msm8251_interface *get_interface(device_t *device)
{
assert(device != NULL);
assert(device->type() == MSM8251);
return (const msm8251_interface *) device->static_config();
}
/***************************************************************************
GLOBAL VARIABLES
***************************************************************************/
const msm8251_interface default_msm8251_interface = { DEVCB_NULL, };
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
msm8251_in_callback
-------------------------------------------------*/
static void msm8251_in_callback(running_machine &machine, int id, unsigned long state)
{
device_t *device;
msm8251_t *uart;
int changed;
/* NPW 29-Nov-2008 - These two lines are a hack and indicate why our "serial" infrastructure needs to be updated */
device = machine.device("uart");
uart = get_token(device);
changed = uart->connection.input_state^state;
uart->connection.input_state = state;
/* did cts change state? */
if (changed & SERIAL_STATE_CTS)
{
/* yes */
/* update tx ready */
/* msm8251_update_tx_ready(device); */
}
}
/*-------------------------------------------------
DEVICE_START( msm8251 )
-------------------------------------------------*/
static DEVICE_START( msm8251 )
{
msm8251_t *uart = get_token(device);
const msm8251_interface *intf = get_interface(device);
serial_helper_setup();
// resolve callbacks
uart->out_rxrdy_func.resolve(intf->out_rxrdy_func, *device);
uart->out_txrdy_func.resolve(intf->out_txrdy_func, *device);
uart->out_txempty_func.resolve(intf->out_txempty_func, *device);
/* setup this side of the serial connection */
serial_connection_init(device->machine(),&uart->connection);
serial_connection_set_in_callback(device->machine(),&uart->connection, msm8251_in_callback);
uart->connection.input_state = 0;
}
/*-------------------------------------------------
msm8251_update_rx_ready
-------------------------------------------------*/
static void msm8251_update_rx_ready(device_t *device)
{
msm8251_t *uart = get_token(device);
int state;
state = uart->status & MSM8251_STATUS_RX_READY;
/* masked? */
if ((uart->command & (1<<2))==0)
{
state = 0;
}
uart->out_rxrdy_func(state != 0);
}
/*-------------------------------------------------
msm8251_receive_clock
-------------------------------------------------*/
void msm8251_receive_clock(device_t *device)
{
msm8251_t *uart = get_token(device);
/* receive enable? */
if (uart->command & (1<<2))
{
//logerror("MSM8251\n");
/* get bit received from other side and update receive register */
receive_register_update_bit(&uart->receive_reg, get_in_data_bit(uart->connection.input_state));
if (uart->receive_reg.flags & RECEIVE_REGISTER_FULL)
{
receive_register_extract(&uart->receive_reg, &uart->form);
msm8251_receive_character(device, uart->receive_reg.byte_received);
}
}
}
/*-------------------------------------------------
msm8251_transmit_clock
-------------------------------------------------*/
void msm8251_transmit_clock(device_t *device)
{
msm8251_t *uart = get_token(device);
/* transmit enable? */
if (uart->command & (1<<0))
{
/* transmit register full? */
if ((uart->status & MSM8251_STATUS_TX_READY)==0)
{
/* if transmit reg is empty */
if ((uart->transmit_reg.flags & TRANSMIT_REGISTER_EMPTY)!=0)
{
/* set it up */
transmit_register_setup(&uart->transmit_reg, &uart->form, uart->data);
/* msm8251 transmit reg now empty */
uart->status |=MSM8251_STATUS_TX_EMPTY;
/* ready for next transmit */
uart->status |=MSM8251_STATUS_TX_READY;
msm8251_update_tx_empty(device);
msm8251_update_tx_ready(device);
}
}
/* if transmit is not empty... transmit data */
if ((uart->transmit_reg.flags & TRANSMIT_REGISTER_EMPTY)==0)
{
// logerror("MSM8251\n");
transmit_register_send_bit(device->machine(),&uart->transmit_reg, &uart->connection);
}
}
#if 0
/* hunt mode? */
/* after each bit has been shifted in, it is compared against the current sync byte */
if (uart->command & (1<<7))
{
/* data matches sync byte? */
if (uart->data == uart->sync_bytes[uart->sync_byte_offset])
{
/* sync byte matches */
/* update for next sync byte? */
uart->sync_byte_offset++;
/* do all sync bytes match? */
if (uart->sync_byte_offset == uart->sync_byte_count)
{
/* ent hunt mode */
uart->command &=~(1<<7);
}
}
else
{
/* if there is no match, reset */
uart->sync_byte_offset = 0;
}
}
#endif
}
/*-------------------------------------------------
msm8251_update_tx_ready
-------------------------------------------------*/
static void msm8251_update_tx_ready(device_t *device)
{
msm8251_t *uart = get_token(device);
/* clear tx ready state */
int tx_ready;
/* tx ready output is set if:
DB Buffer Empty &
CTS is set &
Transmit enable is 1
*/
tx_ready = 0;
/* transmit enable? */
if ((uart->command & (1<<0))!=0)
{
/* other side has rts set (comes in as CTS at this side) */
if (uart->connection.input_state & SERIAL_STATE_CTS)
{
if (uart->status & MSM8251_STATUS_TX_EMPTY)
{
/* enable transfer */
tx_ready = 1;
}
}
}
uart->out_txrdy_func(tx_ready);
}
/*-------------------------------------------------
msm8251_update_tx_empty
-------------------------------------------------*/
static void msm8251_update_tx_empty(device_t *device)
{
msm8251_t *uart = get_token(device);
if (uart->status & MSM8251_STATUS_TX_EMPTY)
{
/* tx is in marking state (high) when tx empty! */
set_out_data_bit(uart->connection.State, 1);
serial_connection_out(device->machine(),&uart->connection);
}
uart->out_txempty_func((uart->status & MSM8251_STATUS_TX_EMPTY) != 0);
}
/*-------------------------------------------------
DEVICE_RESET( msm8251 )
-------------------------------------------------*/
static DEVICE_RESET( msm8251 )
{
msm8251_t *uart = get_token(device);
LOG(("MSM8251: Reset\n"));
/* what is the default setup when the 8251 has been reset??? */
/* msm8251 datasheet explains the state of tx pin at reset */
/* tx is set to 1 */
set_out_data_bit(uart->connection.State,1);
/* assumption, rts is set to 1 */
uart->connection.State &= ~SERIAL_STATE_RTS;
serial_connection_out(device->machine(), &uart->connection);
transmit_register_reset(&uart->transmit_reg);
receive_register_reset(&uart->receive_reg);
/* expecting mode byte */
uart->flags |= MSM8251_EXPECTING_MODE;
/* not expecting a sync byte */
uart->flags &= ~MSM8251_EXPECTING_SYNC_BYTE;
/* no character to read by cpu */
/* transmitter is ready and is empty */
uart->status = MSM8251_STATUS_TX_EMPTY | MSM8251_STATUS_TX_READY;
uart->mode_byte = 0;
uart->command = 0;
/* update tx empty pin output */
msm8251_update_tx_empty(device);
/* update rx ready pin output */
msm8251_update_rx_ready(device);
/* update tx ready pin output */
msm8251_update_tx_ready(device);
}
/*-------------------------------------------------
WRITE8_DEVICE_HANDLER(msm8251_control_w)
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER(msm8251_control_w)
{
msm8251_t *uart = get_token(device);
if (uart->flags & MSM8251_EXPECTING_MODE)
{
if (uart->flags & MSM8251_EXPECTING_SYNC_BYTE)
{
LOG(("MSM8251: Sync byte\n"));
LOG(("Sync byte: %02x\n", data));
/* store sync byte written */
uart->sync_bytes[uart->sync_byte_offset] = data;
uart->sync_byte_offset++;
if (uart->sync_byte_offset == uart->sync_byte_count)
{
/* finished transfering sync bytes, now expecting command */
uart->flags &= ~(MSM8251_EXPECTING_MODE | MSM8251_EXPECTING_SYNC_BYTE);
uart->sync_byte_offset = 0;
// uart->status = MSM8251_STATUS_TX_EMPTY | MSM8251_STATUS_TX_READY;
}
}
else
{
LOG(("MSM8251: Mode byte\n"));
uart->mode_byte = data;
/* Synchronous or Asynchronous? */
if ((data & 0x03)!=0)
{
/* Asynchronous
bit 7,6: stop bit length
0 = inhibit
1 = 1 bit
2 = 1.5 bits
3 = 2 bits
bit 5: parity type
0 = parity odd
1 = parity even
bit 4: parity test enable
0 = disable
1 = enable
bit 3,2: character length
0 = 5 bits
1 = 6 bits
2 = 7 bits
3 = 8 bits
bit 1,0: baud rate factor
0 = defines command byte for synchronous or asynchronous
1 = x1
2 = x16
3 = x64
*/
LOG(("MSM8251: Asynchronous operation\n"));
LOG(("Character length: %d\n", (((data>>2) & 0x03)+5)));
if (data & (1<<4))
{
LOG(("enable parity checking\n"));
}
else
{
LOG(("parity check disabled\n"));
}
if (data & (1<<5))
{
LOG(("even parity\n"));
}
else
{
LOG(("odd parity\n"));
}
{
UINT8 stop_bit_length;
stop_bit_length = (data>>6) & 0x03;
switch (stop_bit_length)
{
case 0:
{
/* inhibit */
LOG(("stop bit: inhibit\n"));
}
break;
case 1:
{
/* 1 */
LOG(("stop bit: 1 bit\n"));
}
break;
case 2:
{
/* 1.5 */
LOG(("stop bit: 1.5 bits\n"));
}
break;
case 3:
{
/* 2 */
LOG(("stop bit: 2 bits\n"));
}
break;
}
}
uart->form.word_length = ((data>>2) & 0x03)+5;
uart->form.parity = SERIAL_PARITY_NONE;
switch ((data>>6) & 0x03)
{
case 0:
case 1:
uart->form.stop_bit_count = 1;
break;
case 2:
case 3:
uart->form.stop_bit_count = 2;
break;
}
receive_register_setup(&uart->receive_reg, &uart->form);
#if 0
/* data bits */
uart->receive_char_length = (((data>>2) & 0x03)+5);
if (data & (1<<4))
{
/* parity */
uart->receive_char_length++;
}
/* stop bits */
uart->receive_char_length++;
uart->receive_flags &=~MSM8251_TRANSFER_RECEIVE_SYNCHRONISED;
uart->receive_flags |= MSM8251_TRANSFER_RECEIVE_WAITING_FOR_START_BIT;
#endif
/* not expecting mode byte now */
uart->flags &= ~MSM8251_EXPECTING_MODE;
// uart->status = MSM8251_STATUS_TX_EMPTY | MSM8251_STATUS_TX_READY;
}
else
{
/* bit 7: Number of sync characters
0 = 1 character
1 = 2 character
bit 6: Synchronous mode
0 = Internal synchronisation
1 = External synchronisation
bit 5: parity type
0 = parity odd
1 = parity even
bit 4: parity test enable
0 = disable
1 = enable
bit 3,2: character length
0 = 5 bits
1 = 6 bits
2 = 7 bits
3 = 8 bits
bit 1,0 = 0
*/
LOG(("MSM8251: Synchronous operation\n"));
/* setup for sync byte(s) */
uart->flags |= MSM8251_EXPECTING_SYNC_BYTE;
uart->sync_byte_offset = 0;
if (data & 0x07)
{
uart->sync_byte_count = 1;
}
else
{
uart->sync_byte_count = 2;
}
}
}
}
else
{
/* command */
LOG(("MSM8251: Command byte\n"));
uart->command = data;
LOG(("Command byte: %02x\n", data));
if (data & (1<<7))
{
LOG(("hunt mode\n"));
}
if (data & (1<<5))
{
LOG(("/rts set to 0\n"));
}
else
{
LOG(("/rts set to 1\n"));
}
if (data & (1<<2))
{
LOG(("receive enable\n"));
}
else
{
LOG(("receive disable\n"));
}
if (data & (1<<1))
{
LOG(("/dtr set to 0\n"));
}
else
{
LOG(("/dtr set to 1\n"));
}
if (data & (1<<0))
{
LOG(("transmit enable\n"));
}
else
{
LOG(("transmit disable\n"));
}
/* bit 7:
0 = normal operation
1 = hunt mode
bit 6:
0 = normal operation
1 = internal reset
bit 5:
0 = /RTS set to 1
1 = /RTS set to 0
bit 4:
0 = normal operation
1 = reset error flag
bit 3:
0 = normal operation
1 = send break character
bit 2:
0 = receive disable
1 = receive enable
bit 1:
0 = /DTR set to 1
1 = /DTR set to 0
bit 0:
0 = transmit disable
1 = transmit enable
*/
uart->connection.State &=~SERIAL_STATE_RTS;
if (data & (1<<5))
{
/* rts set to 0 */
uart->connection.State |= SERIAL_STATE_RTS;
}
uart->connection.State &=~SERIAL_STATE_DTR;
if (data & (1<<1))
{
uart->connection.State |= SERIAL_STATE_DTR;
}
if ((data & (1<<0))==0)
{
/* held in high state when transmit disable */
set_out_data_bit(uart->connection.State,1);
}
/* refresh outputs */
serial_connection_out(device->machine(), &uart->connection);
if (data & (1<<4))
{
uart->status &= ~(MSM8251_STATUS_PARITY_ERROR | MSM8251_STATUS_OVERRUN_ERROR | MSM8251_STATUS_FRAMING_ERROR);
}
if (data & (1<<6))
{
device->reset();
}
msm8251_update_rx_ready(device);
msm8251_update_tx_ready(device);
}
}
/*-------------------------------------------------
READ8_DEVICE_HANDLER(msm8251_status_r)
-------------------------------------------------*/
READ8_DEVICE_HANDLER(msm8251_status_r)
{
msm8251_t *uart = get_token(device);
LOG(("status: %02x\n", uart->status));
return uart->status;
}
/*-------------------------------------------------
WRITE8_DEVICE_HANDLER(msm8251_data_w)
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER(msm8251_data_w)
{
msm8251_t *uart = get_token(device);
uart->data = data;
logerror("write data: %02x\n",data);
/* writing clears */
uart->status &=~MSM8251_STATUS_TX_READY;
/* if transmitter is active, then tx empty will be signalled */
msm8251_update_tx_ready(device);
}
/*-------------------------------------------------
msm8251_receive_character - called when last
bit of data has been received
-------------------------------------------------*/
void msm8251_receive_character(device_t *device, UINT8 ch)
{
msm8251_t *uart = get_token(device);
logerror("msm8251 receive char: %02x\n",ch);
uart->data = ch;
/* char has not been read and another has arrived! */
if (uart->status & MSM8251_STATUS_RX_READY)
{
uart->status |= MSM8251_STATUS_OVERRUN_ERROR;
}
uart->status |= MSM8251_STATUS_RX_READY;
msm8251_update_rx_ready(device);
}
/*-------------------------------------------------
READ8_DEVICE_HANDLER(msm8251_data_r) - read data
-------------------------------------------------*/
READ8_DEVICE_HANDLER(msm8251_data_r)
{
msm8251_t *uart = get_token(device);
logerror("read data: %02x, STATUS=%02x\n",uart->data,uart->status);
/* reading clears */
uart->status &= ~MSM8251_STATUS_RX_READY;
msm8251_update_rx_ready(device);
return uart->data;
}
/*-------------------------------------------------
msm8251_connect_to_serial_device - initialise
transfer using serial device - set the callback
which will be called when serial device has
updated it's state
-------------------------------------------------*/
void msm8251_connect_to_serial_device(device_t *device, device_t *image)
{
msm8251_t *uart = get_token(device);
serial_device_connect(image, &uart->connection);
}
/*-------------------------------------------------
msm8251_connect
-------------------------------------------------*/
void msm8251_connect(device_t *device, serial_connection *other_connection)
{
msm8251_t *uart = get_token(device);
serial_connection_link(device->machine(), &uart->connection, other_connection);
}
/*-------------------------------------------------
DEVICE_GET_INFO( msm8251 )
-------------------------------------------------*/
DEVICE_GET_INFO( msm8251 )
{
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(msm8251_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(msm8251); break;
case DEVINFO_FCT_STOP: /* Nothing */ break;
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(msm8251); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Intel 8251 UART"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Intel 8251 UART"); break;
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_CREDITS: /* Nothing */ break;
}
}
DEFINE_LEGACY_DEVICE(MSM8251, msm8251);

88
src/emu/machine/msm8251.h Normal file
View File

@ -0,0 +1,88 @@
/*********************************************************************
msm8251.h
MSM/Intel 8251 Universal Synchronous/Asynchronous Receiver Transmitter code
*********************************************************************/
#ifndef __MSM8251_H__
#define __MSM8251_H__
#include "machine/serial.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
DECLARE_LEGACY_DEVICE(MSM8251, msm8251);
#define MSM8251_EXPECTING_MODE 0x01
#define MSM8251_EXPECTING_SYNC_BYTE 0x02
#define MSM8251_STATUS_FRAMING_ERROR 0x020
#define MSM8251_STATUS_OVERRUN_ERROR 0x010
#define MSM8251_STATUS_PARITY_ERROR 0x08
#define MSM8251_STATUS_TX_EMPTY 0x04
#define MSM8251_STATUS_RX_READY 0x02
#define MSM8251_STATUS_TX_READY 0x01
#define MCFG_MSM8251_ADD(_tag, _intrf) \
MCFG_DEVICE_ADD(_tag, MSM8251, 0) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_MSM8251_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _msm8251_interface msm8251_interface;
struct _msm8251_interface
{
devcb_read_line in_rxd_func;
devcb_write_line out_txd_func;
devcb_read_line in_dsr_func;
devcb_write_line out_dtr_func;
devcb_write_line out_rts_func;
devcb_write_line out_rxrdy_func;
devcb_write_line out_txrdy_func;
devcb_write_line out_txempty_func;
devcb_write_line out_syndet_func;
};
/***************************************************************************
PROTOTYPES
***************************************************************************/
extern const msm8251_interface default_msm8251_interface;
/* read data register */
READ8_DEVICE_HANDLER(msm8251_data_r);
/* read status register */
READ8_DEVICE_HANDLER(msm8251_status_r);
/* write data register */
WRITE8_DEVICE_HANDLER(msm8251_data_w);
/* write control word */
WRITE8_DEVICE_HANDLER(msm8251_control_w);
/* The 8251 has seperate transmit and receive clocks */
/* use these two functions to update the msm8251 for each clock */
/* on NC100 system, the clocks are the same */
void msm8251_transmit_clock(device_t *device);
void msm8251_receive_clock(device_t *device);
/* connecting to serial output */
void msm8251_connect_to_serial_device(device_t *device, device_t *image);
void msm8251_connect(device_t *device, serial_connection *other_connection);
void msm8251_receive_character(device_t *device, UINT8 ch);
#endif /* __MSM8251_H__ */

733
src/emu/machine/serial.c Normal file
View File

@ -0,0 +1,733 @@
/* internal serial transmission */
/* select a file on host filesystem to transfer using serial method,
setup serial interface software in driver and let the transfer begin */
/* this is used in the Amstrad NC Notepad emulation */
/*
the output starts at 1 level. It changes to 0 when the start bit has been transmitted.
This therefore signals that data is following.
When all data bits have been received, stop bits are transmitted with a value of 1.
msm8251 expects this in asynchronous mode:
packet format:
bit count function value
1 start bit 0
note 1 data bits x
note 2 parity bit x
note 3 stop bits 1
Note:
1. Data size can be defined (usual value is 8)
2. Parity bit (if parity is set to odd or even). Value of bit
is defined by data parity.
3. There should be at least 1 stop bit.
*/
#include "emu.h"
#include "serial.h"
#define VERBOSE 0
#define LOG(x) do { if (VERBOSE) logerror x; } while (0)
/* a read/write bit stream. used to transmit data and to receive data */
typedef struct _data_stream data_stream;
struct _data_stream
{
/* pointer to buffer */
unsigned char *pData;
/* length of buffer */
unsigned long DataLength;
/* bit offset within current byte */
unsigned long BitCount;
/* byte offset within data */
unsigned long ByteCount;
};
typedef struct _serial_t serial_t;
struct _serial_t
{
/* transmit data bit-stream */
data_stream transmit;
/* receive data bit-stream */
data_stream receive;
/* register to receive data */
serial_receive_register receive_reg;
/* register to transmit data */
serial_transmit_register transmit_reg;
/* connection to transmit/receive data over */
serial_connection connection;
/* data form to transmit/receive */
data_form form;
int transmit_state;
/* baud rate */
unsigned long BaudRate;
/* baud rate timer */
emu_timer *timer;
};
INLINE serial_t *get_safe_token(device_t *device)
{
assert(device != NULL);
//assert(device->type() == SERIAL);
return (serial_t *)downcast<legacy_device_base *>(device)->token();
}
/* the serial streams */
static TIMER_CALLBACK(serial_device_baud_rate_callback);
/*********************************************************/
static unsigned char serial_parity_table[256];
void serial_helper_setup(void)
{
int i;
/* if sum of all bits in the byte is even, then the data
has even parity, otherwise it has odd parity */
for (i=0; i<256; i++)
{
int data;
int sum;
int b;
sum = 0;
data = i;
for (b=0; b<8; b++)
{
sum+=data & 0x01;
data = data>>1;
}
serial_parity_table[i] = sum & 0x01;
}
}
static unsigned char serial_helper_get_parity(unsigned char data)
{
return serial_parity_table[data & 0x0ff];
}
static void serial_device_in_callback(running_machine &machine, int id, unsigned long status)
{
/* serial_t *ser = get_safe_token(device);
ser->connection.input_state = status;*/
}
/***** SERIAL DEVICE ******/
void serial_device_setup(device_t *device, int baud_rate, int num_data_bits, int stop_bit_count, int parity_code)
{
serial_t *ser = get_safe_token(device);
ser->BaudRate = baud_rate;
ser->form.word_length = num_data_bits;
ser->form.stop_bit_count = stop_bit_count;
ser->form.parity = parity_code;
ser->timer = device->machine().scheduler().timer_alloc(FUNC(serial_device_baud_rate_callback), (void *)device);
serial_connection_init(device->machine(),&ser->connection);
serial_connection_set_in_callback(device->machine(),&ser->connection, serial_device_in_callback);
/* signal to other end it is clear to send! */
/* data is initially high state */
/* set /rts */
ser->connection.State |= SERIAL_STATE_RTS;
/* signal to other end data is ready to be accepted */
/* set /dtr */
ser->connection.State |= SERIAL_STATE_DTR;
set_out_data_bit(ser->connection.State, 1);
serial_connection_out(device->machine(),&ser->connection);
transmit_register_reset(&ser->transmit_reg);
receive_register_reset(&ser->receive_reg);
receive_register_setup(&ser->receive_reg, &ser->form);
}
unsigned long serial_device_get_state(device_t *device)
{
serial_t *ser = get_safe_token(device);
return ser->connection.State;
}
void serial_device_set_transmit_state(device_t *device, int state)
{
int previous_state;
serial_t *ser = get_safe_token(device);
previous_state = ser->transmit_state;
ser->transmit_state = state;
if ((state^previous_state)!=0)
{
if (state)
{
/* start timer */
ser->timer->adjust(attotime::zero, 0, attotime::from_hz(ser->BaudRate));
}
else
{
/* remove timer */
ser->timer->reset();
}
}
}
/* get a bit from input stream */
static int data_stream_get_data_bit_from_data_byte(data_stream *stream)
{
int data_bit;
int data_byte;
if (stream->ByteCount<stream->DataLength)
{
/* get data from buffer */
data_byte= stream->pData[stream->ByteCount];
}
else
{
/* over end of buffer, so return 0 */
data_byte= 0;
}
/* get bit from data */
data_bit = (data_byte>>(7-stream->BitCount)) & 0x01;
/* update bit count */
stream->BitCount++;
/* ripple overflow onto byte count */
stream->ByteCount+=stream->BitCount>>3;
/* lock bit count into range */
stream->BitCount &=0x07;
/* do not let it read over end of data */
if (stream->ByteCount>=stream->DataLength)
{
stream->ByteCount = stream->DataLength-1;
}
return data_bit;
}
void receive_register_setup(serial_receive_register *receive, data_form *data_form)
{
receive->bit_count = data_form->word_length + data_form->stop_bit_count;
if (data_form->parity != SERIAL_PARITY_NONE)
{
receive->bit_count++;
}
}
/* this is generic code to be used in serial chip implementations */
/* the majority of serial chips work in the same way and this code will work */
/* for them */
/* receive a bit */
void receive_register_update_bit(serial_receive_register *receive, int bit)
{
int previous_bit;
LOG(("receive register receive bit: %1x\n",bit));
previous_bit = receive->register_data & 1;
/* shift previous bit 7 out */
receive->register_data = receive->register_data<<1;
/* shift new bit in */
receive->register_data = (receive->register_data & 0xfffe) | bit;
/* update bit count received */
receive->bit_count_received++;
/* asyncrhonouse mode */
if (receive->flags & RECEIVE_REGISTER_WAITING_FOR_START_BIT)
{
/* the previous bit is stored in uart.receive char bit 0 */
/* has the bit state changed? */
if (((previous_bit ^ bit) & 0x01)!=0)
{
/* yes */
if (bit==0)
{
//logerror("receive register saw start bit\n");
/* seen start bit! */
/* not waiting for start bit now! */
receive->flags &=~RECEIVE_REGISTER_WAITING_FOR_START_BIT;
receive->flags |=RECEIVE_REGISTER_SYNCHRONISED;
/* reset bit count received */
receive->bit_count_received = 0;
}
}
}
else
if (receive->flags & RECEIVE_REGISTER_SYNCHRONISED)
{
/* received all bits? */
if (receive->bit_count_received==receive->bit_count)
{
receive->bit_count_received = 0;
receive->flags &=~RECEIVE_REGISTER_SYNCHRONISED;
receive->flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT;
//logerror("receive register full\n");
receive->flags |= RECEIVE_REGISTER_FULL;
}
}
}
void receive_register_reset(serial_receive_register *receive_reg)
{
receive_reg->bit_count_received = 0;
receive_reg->flags &=~RECEIVE_REGISTER_FULL;
receive_reg->flags &=~RECEIVE_REGISTER_SYNCHRONISED;
receive_reg->flags |= RECEIVE_REGISTER_WAITING_FOR_START_BIT;
}
void receive_register_extract(serial_receive_register *receive_reg, data_form *data_form)
{
unsigned long data_shift;
UINT8 data;
receive_register_reset(receive_reg);
data_shift = 0;
/* if parity is even or odd, there should be a parity bit in the stream! */
if (data_form->parity!=SERIAL_PARITY_NONE)
{
data_shift++;
}
data_shift+=data_form->stop_bit_count;
/* strip off stop bits and parity */
data = receive_reg->register_data>>data_shift;
/* mask off other bits so data byte has 0's in unused bits */
data = data & (0x0ff
>>
(8-(data_form->word_length)));
receive_reg->byte_received = data;
/* parity enable? */
switch (data_form->parity)
{
case SERIAL_PARITY_NONE:
break;
/* check parity */
case SERIAL_PARITY_ODD:
case SERIAL_PARITY_EVEN:
{
//unsigned char computed_parity;
//unsigned char parity_received;
/* get state of parity bit received */
//parity_received = (receive_reg->register_data>>data_form->stop_bit_count) & 0x01;
/* compute parity for received bits */
//computed_parity = serial_helper_get_parity(data);
if (data_form->parity == SERIAL_PARITY_ODD)
{
/* odd parity */
}
else
{
/* even parity */
}
}
break;
}
}
/***** TRANSMIT REGISTER *****/
void transmit_register_reset(serial_transmit_register *transmit_reg)
{
transmit_reg->flags |=TRANSMIT_REGISTER_EMPTY;
}
/* used to construct data in stream format */
static void transmit_register_add_bit(serial_transmit_register *transmit_reg, int bit)
{
/* combine bit */
transmit_reg->register_data = transmit_reg->register_data<<1;
transmit_reg->register_data &=~1;
transmit_reg->register_data|=(bit & 0x01);
transmit_reg->bit_count++;
}
/* generate data in stream format ready for transfer */
void transmit_register_setup(serial_transmit_register *transmit_reg, data_form *data_form,unsigned char data_byte)
{
int i;
unsigned char transmit_data;
transmit_reg->bit_count_transmitted = 0;
transmit_reg->bit_count = 0;
transmit_reg->flags &=~TRANSMIT_REGISTER_EMPTY;
/* start bit */
transmit_register_add_bit(transmit_reg,0);
/* data bits */
transmit_data = data_byte;
for (i=0; i<data_form->word_length; i++)
{
int databit;
/* get bit from data */
databit = (transmit_data>>(data_form->word_length-1)) & 0x01;
/* add bit to formatted byte */
transmit_register_add_bit(transmit_reg, databit);
transmit_data = transmit_data<<1;
}
/* parity */
if (data_form->parity!=SERIAL_PARITY_NONE)
{
/* odd or even parity */
unsigned char parity;
/* get parity */
/* if parity = 0, data has even parity - i.e. there is an even number of one bits in the data */
/* if parity = 1, data has odd parity - i.e. there is an odd number of one bits in the data */
parity = serial_helper_get_parity(data_byte);
transmit_register_add_bit(transmit_reg, parity);
}
/* stop bit(s) */
for (i=0; i<data_form->stop_bit_count; i++)
{
transmit_register_add_bit(transmit_reg,1);
}
}
/* get a bit from the transmit register */
static int transmit_register_get_data_bit(serial_transmit_register *transmit_reg)
{
int bit;
bit = (transmit_reg->register_data>>
(transmit_reg->bit_count - 1 -
transmit_reg->bit_count_transmitted)) & 0x01;
transmit_reg->bit_count_transmitted++;
/* have all bits of this stream formatted byte been sent? */
if (transmit_reg->bit_count_transmitted==transmit_reg->bit_count)
{
/* yes - generate a new byte to send */
transmit_reg->flags |= TRANSMIT_REGISTER_EMPTY;
}
return bit;
}
void transmit_register_send_bit(running_machine &machine, serial_transmit_register *transmit_reg, serial_connection *connection)
{
int data;
data = transmit_register_get_data_bit(transmit_reg);
/* set tx data bit */
set_out_data_bit(connection->State, data);
/* state out through connection */
serial_connection_out(machine, connection);
}
static void serial_protocol_none_sent_char(device_t *device)
{
int i;
int bit;
unsigned char data_byte;
serial_t *ser = get_safe_token(device);
/* generate byte to transmit */
data_byte = 0;
for (i=0; i<ser->form.word_length; i++)
{
data_byte = data_byte<<1;
bit = data_stream_get_data_bit_from_data_byte(&ser->transmit);
data_byte = data_byte|bit;
}
/* setup register */
transmit_register_setup(&ser->transmit_reg,&ser->form, data_byte);
logerror("serial device transmitted char: %02x\n",data_byte);
}
static TIMER_CALLBACK(serial_device_baud_rate_callback)
{
serial_t *ser = get_safe_token((device_t*)ptr);
/* receive data into receive register */
receive_register_update_bit(&ser->receive_reg, get_in_data_bit(ser->connection.input_state));
if (ser->receive_reg.flags & RECEIVE_REGISTER_FULL)
{
//logerror("SERIAL DEVICE\n");
receive_register_extract(&ser->receive_reg, &ser->form);
logerror("serial device receive char: %02x\n",ser->receive_reg.byte_received);
}
/* is transmit empty? */
if (ser->transmit_reg.flags & TRANSMIT_REGISTER_EMPTY)
{
/* char has been sent, execute callback */
serial_protocol_none_sent_char((device_t*)ptr);
}
/* other side says it is clear to send? */
if (ser->connection.input_state & SERIAL_STATE_CTS)
{
/* send bit */
transmit_register_send_bit(machine, &ser->transmit_reg, &ser->connection);
}
}
/* connect the specified connection to this serial device */
void serial_device_connect(device_t *device, serial_connection *connection)
{
serial_t *ser = get_safe_token(device);
serial_connection_link(device->machine(), connection, &ser->connection);
}
/* load image */
static int serial_device_load_internal(device_image_interface &image, unsigned char **ptr, int *pDataSize)
{
int datasize;
unsigned char *data;
/* get file size */
datasize = image.length();
if (datasize!=0)
{
/* malloc memory for this data */
data = (unsigned char *)malloc(datasize);
if (data!=NULL)
{
/* read whole file */
image.fread(data, datasize);
*ptr = data;
*pDataSize = datasize;
logerror("File loaded!\r\n");
/* ok! */
return 1;
}
}
return 0;
}
/* reset position in stream */
static void data_stream_reset(data_stream *stream)
{
/* reset byte offset */
stream->ByteCount= 0;
/* reset bit count */
stream->BitCount = 0;
}
/* free stream */
static void data_stream_free(data_stream *stream)
{
if (stream->pData!=NULL)
{
free(stream->pData);
stream->pData = NULL;
}
stream->DataLength = 0;
}
/* initialise stream */
static void data_stream_init(data_stream *stream, unsigned char *pData, unsigned long DataLength)
{
stream->pData = pData;
stream->DataLength = DataLength;
data_stream_reset(stream);
}
DEVICE_START(serial)
{
//serial_t *ser = get_safe_token(device);
}
DEVICE_RESET(serial)
{
// serial_t *ser = get_safe_token(device);
}
DEVICE_IMAGE_LOAD(serial)
{
int data_length;
unsigned char *data;
device_t *device = &image.device();
serial_t *ser = get_safe_token(device);
/* load file and setup transmit data */
if (serial_device_load_internal(image, &data, &data_length))
{
data_stream_init(&ser->transmit, data, data_length);
return IMAGE_INIT_PASS;
}
return IMAGE_INIT_FAIL;
}
DEVICE_IMAGE_UNLOAD(serial)
{
device_t *device = &image.device();
serial_t *ser = get_safe_token(device);
/* stop transmit */
serial_device_set_transmit_state(device, 0);
/* free streams */
data_stream_free(&ser->transmit);
data_stream_free(&ser->receive);
}
DEVICE_GET_INFO( serial )
{
switch ( state )
{
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(serial_t); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
case DEVINFO_INT_IMAGE_TYPE: info->i = IO_SERIAL; break;
case DEVINFO_INT_IMAGE_READABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_WRITEABLE: info->i = 1; break;
case DEVINFO_INT_IMAGE_CREATABLE: info->i = 1; break;
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME( serial ); break;
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME( serial ); break;
case DEVINFO_FCT_IMAGE_LOAD: info->f = (genf *) DEVICE_IMAGE_LOAD_NAME( serial ); break;
case DEVINFO_FCT_IMAGE_UNLOAD: info->f = (genf *) DEVICE_IMAGE_UNLOAD_NAME(serial ); break;
case DEVINFO_STR_NAME: strcpy( info->s, "Serial port"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Serial port"); break;
case DEVINFO_STR_IMAGE_FILE_EXTENSIONS: strcpy(info->s, ""); break;
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright the MESS Team"); break;
}
}
/*******************************************************************************/
/*******************************************************************************/
/********* SERIAL CONNECTION ***********/
/* this converts state at this end to a state the other end can accept */
/* e.g. CTS at this end becomes RTS at other end.
RTS at this end becomes CTS at other end.
TX at this end becomes RX at other end.
RX at this end becomes TX at other end.
etc
The same thing is done inside the serial null-terminal lead */
static unsigned long serial_connection_spin_bits(unsigned long input_status)
{
return
/* cts -> rts */
(((input_status & 0x01)<<1) |
/* rts -> cts */
((input_status>>1) & 0x01) |
/* dsr -> dtr */
(((input_status>>2) & 0x01)<<3) |
/* dtr -> dsr */
(((input_status>>3) & 0x01)<<2) |
/* rx -> tx */
(((input_status>>4) & 0x01)<<5) |
/* tx -> rx */
(((input_status>>5) & 0x01)<<4));
}
/* setup callbacks for connection */
void serial_connection_init(running_machine &machine, serial_connection *connection)
{
connection->out_callback = NULL;
connection->in_callback = NULL;
}
/* set callback which will be executed when in status has changed */
void serial_connection_set_in_callback(running_machine &machine, serial_connection *connection, void (*in_cb)(running_machine &machine, int id, unsigned long status))
{
connection->in_callback = in_cb;
}
/* output new state through connection */
void serial_connection_out(running_machine &machine, serial_connection *connection)
{
if (connection->out_callback!=NULL)
{
unsigned long state_at_other_end;
state_at_other_end = serial_connection_spin_bits(connection->State);
connection->out_callback(machine, connection->id, state_at_other_end);
}
}
/* join two serial connections together */
void serial_connection_link(running_machine &machine, serial_connection *connection_a, serial_connection *connection_b)
{
/* both connections should have their in connection setup! */
/* the in connection is the callback they use to update their state based
on the output from the other side */
connection_a->out_callback = connection_b->in_callback;
connection_b->out_callback = connection_a->in_callback;
/* let b know the state of a */
serial_connection_out(machine,connection_a);
/* let a know the state of b */
serial_connection_out(machine,connection_b);
}
DEFINE_LEGACY_IMAGE_DEVICE(SERIAL, serial);

247
src/emu/machine/serial.h Normal file
View File

@ -0,0 +1,247 @@
/*****************************************************************************
*
* machine/serial.h
*
* internal serial transmission
*
* This code is used to transmit a file stored on the host filesystem
* (e.g. PC harddrive) to an emulated system.
*
* The file is converted into a serial bit-stream which can be received
* by the emulated serial chip in the emulated system.
*
* The file can be transmitted using different protocols.
*
* A and B are two computers linked with a serial connection
* A and B can transmit and receive data, through the same connection
*
* These flags apply to A and B, and give the state of the input & output
* signals at each side.
*
****************************************************************************/
#ifndef SERIAL_H_
#define SERIAL_H_
/*
CTS = Clear to Send. (INPUT)
Other end of connection is ready to accept data
NOTE:
This output is active low on serial chips (e.g. 0 is CTS is set),
but here it is active high!
*/
#define SERIAL_STATE_CTS 0x0001
/*
RTS = Request to Send. (OUTPUT)
This end is ready to send data, and requests if the other
end is ready to accept it
NOTE:
This output is active low on serial chips (e.g. 0 is RTS is set),
but here it is active high!
*/
#define SERIAL_STATE_RTS 0x0002
/*
DSR = Data Set ready. (INPUT)
Other end of connection has data
NOTE:
This output is active low on serial chips (e.g. 0 is DSR is set),
but here it is active high!
*/
#define SERIAL_STATE_DSR 0x0004
/*
DTR = Data terminal Ready. (OUTPUT)
TX contains new data.
NOTE:
This output is active low on serial chips (e.g. 0 is DTR is set),
but here it is active high!
*/
#define SERIAL_STATE_DTR 0x0008
/* RX = Recieve data. (INPUT) */
#define SERIAL_STATE_RX_DATA 0x00010
/* TX = Transmit data. (OUTPUT) */
#define SERIAL_STATE_TX_DATA 0x00020
/* parity selections */
/* if all the bits are added in a byte, if the result is:
even -> parity is even
odd -> parity is odd
*/
enum
{
SERIAL_PARITY_NONE, /* no parity. a parity bit will not be in the transmitted/received data */
SERIAL_PARITY_ODD, /* odd parity */
SERIAL_PARITY_EVEN /* even parity */
};
/* this macro is used to extract the received data from the status */
#define get_in_data_bit(x) ((x & SERIAL_STATE_RX_DATA)>>4)
/* this macro is used to set the transmitted data in the status */
#define set_out_data_bit(x, data) \
x&=~SERIAL_STATE_TX_DATA; \
x|=(data<<5)
/*******************************************************************************/
/**** SERIAL CONNECTION ***/
/* this structure represents a serial connection */
typedef struct _serial_connection serial_connection;
struct _serial_connection
{
int id;
/* state of this side */
unsigned long State;
/* state of other side - store here */
unsigned long input_state;
/* this callback is executed when this side has refreshed it's state,
to let the other end know */
void (*out_callback)(running_machine &machine, int id, unsigned long state);
/* this callback is executed when the other side has refreshed it's state,
to let the other end know */
void (*in_callback)(running_machine &machine, int id, unsigned long state);
};
/*----------- defined in machine/serial.c -----------*/
/* setup out and in callbacks */
void serial_connection_init(running_machine &machine, serial_connection *connection);
/* set callback which will be executed when in status has changed */
void serial_connection_set_in_callback(running_machine &machine, serial_connection *connection, void (*in_cb)(running_machine &machine, int id, unsigned long status));
/* output status, if callback is setup it will be executed with the new status */
void serial_connection_out(running_machine &machine, serial_connection *connection);
/* join two serial connections */
void serial_connection_link(running_machine &machine, serial_connection *connection_a, serial_connection *connection_b);
/*******************************************************************************/
/* form of data being transmitted and received */
typedef struct _data_form data_form;
struct _data_form
{
/* length of word in bits */
unsigned long word_length;
/* parity state */
unsigned long parity;
/* number of stop bits */
unsigned long stop_bit_count;
};
/*******************************************************************************/
/*******************************************************************************/
/**** RECEIVE AND TRANSMIT GENERIC CODE ****/
/* this can be used by most of the serial chip implementations,
because they all work in roughly the same way.
There is generic code to send and receive data in the specified form */
/* receive is waiting for start bit. The transition from high-low indicates
start of start bit. This is used to synchronise with the data being transfered */
#define RECEIVE_REGISTER_WAITING_FOR_START_BIT 0x01
/* receive is synchronised with data, data bits will be clocked in */
#define RECEIVE_REGISTER_SYNCHRONISED 0x02
/* set if receive register has been filled */
#define RECEIVE_REGISTER_FULL 0x04
/* the receive register holds data in receive form! */
/* this must be extracted to get the data byte received */
typedef struct _serial_receive_register serial_receive_register;
struct _serial_receive_register
{
/* data */
unsigned long register_data;
/* flags */
unsigned long flags;
/* bit count received */
unsigned long bit_count_received;
/* length of data to receive - includes data bits, parity bit and stop bit */
unsigned long bit_count;
/* the byte of data received */
unsigned char byte_received;
};
void receive_register_setup(serial_receive_register *receive, data_form *data_form);
void receive_register_update_bit(serial_receive_register *receive, int bit_state);
void receive_register_extract(serial_receive_register *receive_reg, data_form *data_form);
void receive_register_reset(serial_receive_register *receive_reg);
/* the transmit register is the final stage
in the serial transmit procedure */
/* normally, data is written to the transmit reg,
then it is assembled into transmit form and transmitted */
/* the transmit register holds data in transmit form */
/* register is empty and ready to be filled with data */
#define TRANSMIT_REGISTER_EMPTY 0x0001
typedef struct _serial_transmit_register serial_transmit_register;
struct _serial_transmit_register
{
/* data */
unsigned long register_data;
/* flags */
unsigned long flags;
/* number of bits transmitted */
unsigned long bit_count_transmitted;
/* length of data to send */
unsigned long bit_count;
};
/* setup transmit reg ready for transmit */
void transmit_register_setup(serial_transmit_register *transmit_reg, data_form *data_form,unsigned char data_byte);
void transmit_register_send_bit(running_machine &machine, serial_transmit_register *transmit_reg, serial_connection *connection);
void transmit_register_reset(serial_transmit_register *transmit_reg);
/*******************************************************************************/
/**** SERIAL HELPER ****/
void serial_helper_setup(void);
/*******************************************************************************/
/**** SERIAL DEVICE ****/
unsigned long serial_device_get_state(device_t *device);
/* connect this device to the emulated serial chip */
/* id is the serial device to connect to */
/* connection is the serial connection to connect to the serial device */
void serial_device_connect(device_t *image, serial_connection *connection);
DECLARE_LEGACY_IMAGE_DEVICE(SERIAL, serial);
#define MCFG_SERIAL_ADD(_tag) \
MCFG_DEVICE_ADD(_tag, SERIAL, 0)
DEVICE_START(serial);
DEVICE_IMAGE_LOAD(serial);
void serial_device_setup(device_t *image, int baud_rate, int num_data_bits, int stop_bit_count, int parity_code);
/* set the transmit state of the serial device */
void serial_device_set_transmit_state(device_t *image, int state);
#endif /* SERIAL_H_ */

2457
src/emu/machine/upd765.c Normal file

File diff suppressed because it is too large Load Diff

161
src/emu/machine/upd765.h Normal file
View File

@ -0,0 +1,161 @@
/***************************************************************************
machine/upd765.h
Functions to emulate a NEC upd765/Intel 8272 compatible
floppy disk controller
***************************************************************************/
#ifndef __UPD765_H__
#define __UPD765_H__
#include "devcb.h"
#include "imagedev/flopdrv.h"
/***************************************************************************
MACROS
***************************************************************************/
DECLARE_LEGACY_DEVICE(UPD765A, upd765a);
DECLARE_LEGACY_DEVICE(UPD765B, upd765b);
DECLARE_LEGACY_DEVICE(SMC37C78, smc37c78);
DECLARE_LEGACY_DEVICE(UPD72065, upd72065);
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
/* RDY pin connected state */
typedef enum
{
UPD765_RDY_PIN_NOT_CONNECTED = 0,
UPD765_RDY_PIN_CONNECTED = 1
} UPD765_RDY_PIN;
#define UPD765_DAM_DELETED_DATA 0x0f8
#define UPD765_DAM_DATA 0x0fb
typedef device_t *(*upd765_get_image_func)(device_t *device, int floppy_index);
#define UPD765_GET_IMAGE(name) device_t *name(device_t *device, int floppy_index )
typedef struct upd765_interface
{
/* interrupt issued */
devcb_write_line out_int_func;
/* dma data request */
devcb_write_line out_drq_func;
/* image lookup */
upd765_get_image_func get_image;
UPD765_RDY_PIN rdy_pin;
const char *floppy_drive_tags[4];
} upd765_interface;
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
/* read of data register */
READ8_DEVICE_HANDLER(upd765_data_r);
/* write to data register */
WRITE8_DEVICE_HANDLER(upd765_data_w);
/* read of main status register */
READ8_DEVICE_HANDLER(upd765_status_r);
/* dma acknowledge with write */
WRITE8_DEVICE_HANDLER(upd765_dack_w);
/* dma acknowledge with read */
READ8_DEVICE_HANDLER(upd765_dack_r);
/* reset upd765 */
void upd765_reset(device_t *device, int);
/* reset pin of upd765 */
WRITE_LINE_DEVICE_HANDLER(upd765_reset_w);
/* set upd765 terminal count input state */
WRITE_LINE_DEVICE_HANDLER(upd765_tc_w);
/* set upd765 ready input*/
WRITE_LINE_DEVICE_HANDLER(upd765_ready_w);
void upd765_idle(device_t *device);
/*********************/
/* STATUS REGISTER 1 */
/* this is set if a TC signal was not received after the sector data was read */
#define UPD765_ST1_END_OF_CYLINDER (1<<7)
/* this is set if the sector ID being searched for is not found */
#define UPD765_ST1_NO_DATA (1<<2)
/* set if disc is write protected and a write/format operation was performed */
#define UPD765_ST1_NOT_WRITEABLE (1<<1)
/*********************/
/* STATUS REGISTER 2 */
/* C parameter specified did not match C value read from disc */
#define UPD765_ST2_WRONG_CYLINDER (1<<4)
/* C parameter specified did not match C value read from disc, and C read from disc was 0x0ff */
#define UPD765_ST2_BAD_CYLINDER (1<<1)
/* this is set if the FDC encounters a Deleted Data Mark when executing a read data
command, or FDC encounters a Data Mark when executing a read deleted data command */
#define UPD765_ST2_CONTROL_MARK (1<<6)
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
#define MCFG_UPD765A_ADD(_tag, _intrf) \
MCFG_DEVICE_ADD(_tag, UPD765A, 0) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_UPD765A_MODIFY(_tag, _intrf) \
MCFG_DEVICE_MODIFY(_tag) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_UPD765A_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
#define MCFG_UPD765B_ADD(_tag, _intrf) \
MCFG_DEVICE_ADD(_tag, UPD765B, 0) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_UPD765B_MODIFY(_tag, _intrf) \
MCFG_DEVICE_MODIFY(_tag) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_UPD765B_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
#define MCFG_SMC37C78_ADD(_tag, _intrf) \
MCFG_DEVICE_ADD(_tag, SMC37C78, 0) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_SMC37C78_MODIFY(_tag, _intrf) \
MCFG_DEVICE_MODIFY(_tag) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_SMC37C78_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
#define MCFG_UPD72065_ADD(_tag, _intrf) \
MCFG_DEVICE_ADD(_tag, UPD72065, 0) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_UPD72065_MODIFY(_tag, _intrf) \
MCFG_DEVICE_MODIFY(_tag) \
MCFG_DEVICE_CONFIG(_intrf)
#define MCFG_UPD72065_REMOVE(_tag) \
MCFG_DEVICE_REMOVE(_tag)
#endif /* __UPD765_H__ */

379
src/mame/drivers/dc.c Normal file
View File

@ -0,0 +1,379 @@
/*
dc.c - Sega Dreamcast driver
by R. Belmont
SH-4 @ 200 MHz
ARM7DI @ 2.8223 MHz (no T or M extensions)
PowerVR 3D video
AICA audio
GD-ROM drive (modified ATAPI interface)
NTSC/N NTSC/I PAL/N PAL/I VGA
(x/240) (x/480) (x/240) (x/480) (640x480)
VTOTAL 262 524 312 624 524
HTOTAL 857 857 863 863 857
PCLKs = 26917135 (NTSC 480 @ 59.94), 26944080 (VGA 480 @ 60.0), 13458568 (NTSC 240 @ 59.94),
25925600 (PAL 480 @ 50.00), 13462800 (PAL 240 @ 50.00)
*/
#include "emu.h"
#include "cpu/arm7/arm7.h"
#include "cpu/sh4/sh4.h"
#include "cpu/arm7/arm7core.h"
#include "sound/aica.h"
#include "includes/dc.h"
#include "imagedev/chd_cd.h"
#include "machine/maple-dc.h"
#define CPU_CLOCK (200000000)
#ifdef MESS
UINT16 actel_id;
int jvsboard_type;
#else
extern UINT16 actel_id;
extern int jvsboard_type;
#endif
// things from mess/machine/dc.c
void dreamcast_atapi_init(running_machine &machine);
void dreamcast_atapi_reset(running_machine &machine);
extern READ64_HANDLER( dc_mess_gdrom_r );
extern WRITE64_HANDLER( dc_mess_gdrom_w );
extern READ64_HANDLER( dc_mess_g1_ctrl_r );
extern WRITE64_HANDLER( dc_mess_g1_ctrl_w );
static UINT32 *dc_sound_ram;
static UINT64 *dc_ram;
static READ64_HANDLER( dcus_idle_skip_r )
{
if (cpu_get_pc(&space->device())==0xc0ba52a)
device_spin_until_time(&space->device(), attotime::from_usec(2500));
// device_spinuntil_int(&space->device());
return dc_ram[0x2303b0/8];
}
static READ64_HANDLER( dcjp_idle_skip_r )
{
if (cpu_get_pc(&space->device())==0xc0bac62)
device_spin_until_time(&space->device(), attotime::from_usec(2500));
// device_spinuntil_int(&space->device());
return dc_ram[0x2302f8/8];
}
static DRIVER_INIT(dc)
{
dreamcast_atapi_init(machine);
}
static DRIVER_INIT(dcus)
{
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xc2303b0, 0xc2303b7, FUNC(dcus_idle_skip_r));
DRIVER_INIT_CALL(dc);
}
static DRIVER_INIT(dcjp)
{
machine.device("maincpu")->memory().space(AS_PROGRAM)->install_legacy_read_handler(0xc2302f8, 0xc2302ff, FUNC(dcjp_idle_skip_r));
DRIVER_INIT_CALL(dc);
}
static UINT64 PDTRA, PCTRA;
static READ64_HANDLER( dc_pdtra_r )
{
UINT64 out = PCTRA<<32;
out |= PDTRA & ~3;
// if both bits are inputs
if (!(PCTRA & 0x5))
{
out |= 3;
}
// one's input one's output, always pull up both bits
if (((PCTRA & 5) == 1) || ((PCTRA & 5) == 4))
{
if (PDTRA & 3)
{
out |= 3;
}
}
return out;
}
static WRITE64_HANDLER( dc_pdtra_w )
{
PCTRA = (data>>16) & 0xffff;
PDTRA = (data & 0xffff);
}
static READ64_HANDLER( dc_arm_r )
{
return *((UINT64 *)dc_sound_ram+offset);
}
static WRITE64_HANDLER( dc_arm_w )
{
COMBINE_DATA((UINT64 *)dc_sound_ram + offset);
}
// SB_LMMODE0
static WRITE64_HANDLER( ta_texture_directpath0_w )
{
int mode = pvrctrl_regs[SB_LMMODE0]&1;
if (mode&1)
{
printf("ta_texture_directpath0_w 32-bit access!\n");
COMBINE_DATA(&dc_framebuffer_ram[offset]);
}
else
{
COMBINE_DATA(&dc_texture_ram[offset]);
}
}
// SB_LMMODE1
static WRITE64_HANDLER( ta_texture_directpath1_w )
{
int mode = pvrctrl_regs[SB_LMMODE1]&1;
if (mode&1)
{
printf("ta_texture_directpath0_w 32-bit access!\n");
COMBINE_DATA(&dc_framebuffer_ram[offset]);
}
else
{
COMBINE_DATA(&dc_texture_ram[offset]);
}
}
static ADDRESS_MAP_START( dc_map, AS_PROGRAM, 64 )
AM_RANGE(0x00000000, 0x001fffff) AM_ROM AM_WRITENOP // BIOS
AM_RANGE(0x00200000, 0x0021ffff) AM_ROM AM_REGION("maincpu", 0x200000) // flash
AM_RANGE(0x005f6800, 0x005f69ff) AM_READWRITE( dc_sysctrl_r, dc_sysctrl_w )
AM_RANGE(0x005f6c00, 0x005f6cff) AM_DEVREADWRITE32_MODERN( "maple_dc", maple_dc_device, sb_mdstar_r, sb_mdstar_w, U64(0xffffffff00000000) )
AM_RANGE(0x005f7000, 0x005f70ff) AM_READWRITE( dc_mess_gdrom_r, dc_mess_gdrom_w )
AM_RANGE(0x005f7400, 0x005f74ff) AM_READWRITE( dc_mess_g1_ctrl_r, dc_mess_g1_ctrl_w )
AM_RANGE(0x005f7800, 0x005f78ff) AM_READWRITE( dc_g2_ctrl_r, dc_g2_ctrl_w )
AM_RANGE(0x005f7c00, 0x005f7cff) AM_READWRITE( pvr_ctrl_r, pvr_ctrl_w )
AM_RANGE(0x005f8000, 0x005f9fff) AM_READWRITE( pvr_ta_r, pvr_ta_w )
AM_RANGE(0x00600000, 0x006007ff) AM_READWRITE( dc_modem_r, dc_modem_w )
AM_RANGE(0x00700000, 0x00707fff) AM_DEVREADWRITE("aica", dc_aica_reg_r, dc_aica_reg_w )
AM_RANGE(0x00710000, 0x0071000f) AM_READWRITE( dc_rtc_r, dc_rtc_w )
AM_RANGE(0x00800000, 0x009fffff) AM_READWRITE( dc_arm_r, dc_arm_w )
/* Area 1 */
AM_RANGE(0x04000000, 0x04ffffff) AM_RAM AM_BASE( &dc_texture_ram ) // texture memory 64 bit access
AM_RANGE(0x05000000, 0x05ffffff) AM_RAM AM_BASE( &dc_framebuffer_ram ) // apparently this actually accesses the same memory as the 64-bit texture memory access, but in a different format, keep it apart for now
/* Area 3 */
AM_RANGE(0x0c000000, 0x0cffffff) AM_RAM AM_SHARE("share4") AM_BASE(&dc_ram)
AM_RANGE(0x0d000000, 0x0dffffff) AM_RAM AM_SHARE("share4")// extra ram on Naomi (mirror on DC)
AM_RANGE(0x0e000000, 0x0effffff) AM_RAM AM_SHARE("share4")// mirror
AM_RANGE(0x0f000000, 0x0fffffff) AM_RAM AM_SHARE("share4")// mirror
/* Area 4 */
AM_RANGE(0x10000000, 0x107fffff) AM_WRITE( ta_fifo_poly_w )
AM_RANGE(0x10800000, 0x10ffffff) AM_WRITE( ta_fifo_yuv_w )
AM_RANGE(0x11000000, 0x117fffff) AM_WRITE( ta_texture_directpath0_w ) AM_MIRROR(0x00800000) // access to texture / fraembfufer memory (either 32-bit or 64-bit area depending on SB_LMMODE0 register - cannot be written directly, only through dma / store queue
AM_RANGE(0x12000000, 0x127fffff) AM_WRITE( ta_fifo_poly_w )
AM_RANGE(0x12800000, 0x12ffffff) AM_WRITE( ta_fifo_yuv_w )
AM_RANGE(0x13000000, 0x137fffff) AM_WRITE( ta_texture_directpath1_w ) AM_MIRROR(0x00800000) // access to texture / fraembfufer memory (either 32-bit or 64-bit area depending on SB_LMMODE1 register - cannot be written directly, only through dma / store queue
AM_RANGE(0x8c000000, 0x8cffffff) AM_RAM AM_SHARE("share4") // another RAM mirror
AM_RANGE(0xa0000000, 0xa01fffff) AM_ROM AM_REGION("maincpu", 0)
ADDRESS_MAP_END
static ADDRESS_MAP_START( dc_port, AS_IO, 64 )
AM_RANGE(0x00000000, 0x00000007) AM_READWRITE( dc_pdtra_r, dc_pdtra_w )
ADDRESS_MAP_END
static ADDRESS_MAP_START( dc_audio_map, AS_PROGRAM, 32 )
AM_RANGE(0x00000000, 0x001fffff) AM_RAM AM_BASE(&dc_sound_ram) /* shared with SH-4 */
AM_RANGE(0x00800000, 0x00807fff) AM_DEVREADWRITE("aica", dc_arm_aica_r, dc_arm_aica_w)
ADDRESS_MAP_END
static MACHINE_RESET( dc_console )
{
device_t *aica = machine.device("aica");
MACHINE_RESET_CALL(dc);
aica_set_ram_base(aica, dc_sound_ram, 2*1024*1024);
dreamcast_atapi_reset(machine);
}
static void aica_irq(device_t *device, int irq)
{
cputag_set_input_line(device->machine(), "soundcpu", ARM7_FIRQ_LINE, irq ? ASSERT_LINE : CLEAR_LINE);
}
static const aica_interface dc_aica_interface =
{
0,
0,
aica_irq
};
static const struct sh4_config sh4cpu_config = { 1, 0, 1, 0, 0, 0, 1, 1, 0, CPU_CLOCK };
static MACHINE_CONFIG_START( dc, driver_device )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", SH4, CPU_CLOCK)
MCFG_CPU_CONFIG(sh4cpu_config)
MCFG_CPU_PROGRAM_MAP(dc_map)
MCFG_CPU_IO_MAP(dc_port)
MCFG_CPU_ADD("soundcpu", ARM7, ((XTAL_33_8688MHz*2)/3)/8) // AICA bus clock is 2/3rds * 33.8688. ARM7 gets 1 bus cycle out of each 8.
MCFG_CPU_PROGRAM_MAP(dc_audio_map)
MCFG_MACHINE_START( dc )
MCFG_MACHINE_RESET( dc_console )
MCFG_MAPLE_DC_ADD( "maple_dc", "maincpu" )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_REFRESH_RATE(60)
MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(2500) /* not accurate */)
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_SIZE(640, 480)
MCFG_SCREEN_VISIBLE_AREA(0, 640-1, 0, 480-1)
MCFG_SCREEN_UPDATE(dc)
MCFG_PALETTE_LENGTH(0x1000)
MCFG_VIDEO_START(dc)
MCFG_SPEAKER_STANDARD_STEREO("lspeaker", "rspeaker")
MCFG_SOUND_ADD("aica", AICA, 0)
MCFG_SOUND_CONFIG(dc_aica_interface)
MCFG_SOUND_ROUTE(0, "lspeaker", 2.0)
MCFG_SOUND_ROUTE(0, "rspeaker", 2.0)
MCFG_CDROM_ADD( "cdrom" )
MACHINE_CONFIG_END
ROM_START(dc)
ROM_REGION(0x220000, "maincpu", 0)
ROM_LOAD( "dc101d_us.bin", 0x000000, 0x200000, CRC(89f2b1a1) SHA1(8951d1bb219ab2ff8583033d2119c899cc81f18c) ) // BIOS
ROM_LOAD( "dcus_ntsc.bin", 0x200000, 0x020000, CRC(c611b498) SHA1(94d44d7f9529ec1642ba3771ed3c5f756d5bc872) ) // Flash
ROM_END
ROM_START( dceu )
ROM_REGION(0x220000, "maincpu", 0)
ROM_LOAD( "dc101d_eu.bin", 0x000000, 0x200000, CRC(a2564fad) SHA1(edc5d3d70a93c935703d26119b37731fd317d2bf) ) // BIOS
ROM_LOAD( "dceu_pal.bin", 0x200000, 0x020000, CRC(b7e5aeeb) SHA1(11e02433e13b793ec7ffe0ae2356750bb8a575b4) ) // Flash
ROM_END
ROM_START( dcjp )
ROM_REGION(0x220000, "maincpu", 0)
ROM_LOAD( "dc1004jp.bin", 0x000000, 0x200000, CRC(5454841f) SHA1(1ea132c0fbbf07ef76789eadc07908045c089bd6) ) // BIOS
/* ROM_LOAD( "dcjp_ntsc.bad", 0x200000, 0x020000, BAD_DUMP CRC(307a7035) SHA1(1411423a9d071340ea52c56e19c1aafc4e1309ee) ) // Hacked Flash */
ROM_LOAD( "dcjp_ntsc.bin", 0x200000, 0x020000, CRC(5F92BF76) SHA1(BE78B834F512AB2CF3D67B96E377C9F3093FF82A) ) // Flash
ROM_END
ROM_START( dcdev )
ROM_REGION(0x220000, "maincpu", 0)
ROM_LOAD( "hkt-0120.bin", 0x000000, 0x200000, CRC(2186E0E5) SHA1(6BD18FB83F8FDB56F1941E079580E5DD672A6DAD) ) // BIOS
ROM_LOAD( "hkt-0120-flash.bin", 0x200000, 0x020000, CRC(7784C304) SHA1(31EF57F550D8CD13E40263CBC657253089E53034) ) // Flash
ROM_END
static INPUT_PORTS_START( dc )
PORT_START("P1L")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(1)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START1 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(1)
PORT_START("P1H")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN1 )
PORT_SERVICE_NO_TOGGLE( 0x40, IP_ACTIVE_LOW )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE1 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(1)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(1)
PORT_START("P2L")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START2 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(2)
PORT_START("P2H")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN2 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE2 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(2)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(2)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(2)
PORT_START("P3L")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(3)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START3 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(3)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(3)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(3)
PORT_START("P3H")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN3 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE3 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(3)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(3)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(3)
PORT_START("P4L")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(4)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_START4 )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(4)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(4)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_PLAYER(4)
PORT_START("P4H")
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_COIN4 )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_SERVICE4 )
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON4 ) PORT_PLAYER(4)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON5 ) PORT_PLAYER(4)
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON6 ) PORT_PLAYER(4)
PORT_START("MAMEDEBUG") \
PORT_DIPNAME( 0x01, 0x00, "Bilinear Filtering" )
PORT_DIPSETTING( 0x00, DEF_STR( Off ) )
PORT_DIPSETTING( 0x01, DEF_STR( On ) )
INPUT_PORTS_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME */
CONS( 1999, dc, dcjp, 0, dc, dc, dcus, "Sega", "Dreamcast (USA, NTSC)", GAME_NOT_WORKING )
CONS( 1998, dcjp, 0, 0, dc, dc, dcjp, "Sega", "Dreamcast (Japan, NTSC)", GAME_NOT_WORKING )
CONS( 1999, dceu, dcjp, 0, dc, dc, dcus, "Sega", "Dreamcast (Europe, PAL)", GAME_NOT_WORKING )
CONS( 1998, dcdev, dcjp, 0, dc, dc, dc, "Sega", "HKT-0120 Sega Dreamcast Development Box", GAME_NOT_WORKING )

783
src/mame/drivers/segasms.c Normal file
View File

@ -0,0 +1,783 @@
/******************************************************************************
Contributors:
Marat Fayzullin (MG source)
Charles Mac Donald
Mathis Rosenhauer
Brad Oliver
Michael Luong
To do:
- PSG control for Game Gear (needs custom SN76489 with stereo output for each channel)
- SIO interface for Game Gear (needs netplay, I guess)
- SMS lightgun support
- LCD persistence emulation for GG
- SMS 3D glass support
The Game Gear SIO and PSG hardware are not emulated but have some
placeholders in 'machine/sms.c'
Changes:
Apr 02 - Added raster palette effects for SMS & GG (ML)
- Added sprite collision (ML)
- Added zoomed sprites (ML)
May 02 - Fixed paging bug (ML)
- Fixed sprite and tile priority bug (ML)
- Fixed bug #66 (ML)
- Fixed bug #78 (ML)
- try to implement LCD persistence emulation for GG (ML)
Jun 10, 02 - Added bios emulation (ML)
Jun 12, 02 - Added PAL & NTSC systems (ML)
Jun 25, 02 - Added border emulation (ML)
Jun 27, 02 - Version bits for Game Gear (bits 6 of port 00) (ML)
Nov-Dec, 05 - Numerous cleanups, fixes, updates (WP)
Mar, 07 - More cleanups, fixes, mapper additions, etc (WP)
SMS Store Unit memory map for the second CPU:
0000-3FFF - BIOS
4000-47FF - RAM
8000 - System Control Register (R/W)
Reading:
bit7 - ready (0 = ready, 1 = not ready)
bit6-bit5 - unknown
bit4-bit3 - timer selection bit switches
bit2-bit0 - unknown
Writing:
bit7-bit4 - unknown, maybe led of selected game to set?
bit3 - unknown, 1 seems to be written all the time
bit2 - unknown, 1 seems to be written all the time
bit1 - reset signal for sms cpu, 0 = reset low, 1 = reset high
bit0 - which cpu receives interrupt signals, 0 = sms cpu, 1 = controlling cpu
C000 - Card/Cartridge selction register (W)
bit7-bit4 - slot to select
bit3 - slot type (0 = cartridge, 1 = card ?)
bit2-bit0 - unknown
C400 - ???? (used once)
D800 - Selection buttons #1, 1-8 (R)
DC00 - Selection buttons #2, 9-16 (R)
******************************************************************************/
#include "emu.h"
#include "cpu/z80/z80.h"
#include "sound/sn76496.h"
#include "sound/2413intf.h"
#include "includes/segasms.h"
#include "video/smsvdp.h"
#include "imagedev/cartslot.h"
#include "sms1.lh"
#define MASTER_CLOCK_PAL 53203400 /* This might be a tiny bit too low */
static ADDRESS_MAP_START( sms1_mem, AS_PROGRAM, 8 )
AM_RANGE(0x0000, 0x03ff) AM_ROMBANK("bank1") /* First 0x0400 part always points to first page */
AM_RANGE(0x0400, 0x3fff) AM_ROMBANK("bank2") /* switchable rom bank */
AM_RANGE(0x4000, 0x5fff) AM_ROMBANK("bank3") /* switchable rom bank */
AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank4") /* switchable rom bank */
AM_RANGE(0x8000, 0x9fff) AM_READ_BANK("bank5") AM_WRITE(sms_cartram_w) /* ROM bank / on-cart RAM */
AM_RANGE(0xa000, 0xbfff) AM_READ_BANK("bank6") AM_WRITE(sms_cartram2_w) /* ROM bank / on-cart RAM */
AM_RANGE(0xc000, 0xdff7) AM_MIRROR(0x2000) AM_RAM /* RAM (mirror at 0xE000) */
AM_RANGE(0xdff8, 0xdfff) AM_RAM /* RAM "underneath" frame registers */
AM_RANGE(0xfff8, 0xfffb) AM_READWRITE(sms_sscope_r, sms_sscope_w) /* 3-D glasses */
AM_RANGE(0xfffc, 0xffff) AM_READWRITE(sms_mapper_r, sms_mapper_w) /* Bankswitch control */
ADDRESS_MAP_END
static ADDRESS_MAP_START( sms_mem, AS_PROGRAM, 8 )
AM_RANGE(0x0000, 0x03ff) AM_ROMBANK("bank1") /* First 0x0400 part always points to first page */
AM_RANGE(0x0400, 0x3fff) AM_ROMBANK("bank2") /* switchable rom bank */
AM_RANGE(0x4000, 0x5fff) AM_ROMBANK("bank3") /* switchable rom bank */
AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank4") /* switchable rom bank */
AM_RANGE(0x8000, 0x9fff) AM_READ_BANK("bank5") AM_WRITE(sms_cartram_w) /* ROM bank / on-cart RAM */
AM_RANGE(0xa000, 0xbfff) AM_READ_BANK("bank6") AM_WRITE(sms_cartram2_w) /* ROM bank / on-cart RAM */
AM_RANGE(0xc000, 0xdffb) AM_MIRROR(0x2000) AM_RAM /* RAM (mirror at 0xE000) */
AM_RANGE(0xdffc, 0xdfff) AM_RAM /* RAM "underneath" frame registers */
AM_RANGE(0xfffc, 0xffff) AM_READWRITE(sms_mapper_r, sms_mapper_w) /* Bankswitch control */
ADDRESS_MAP_END
static ADDRESS_MAP_START( sms_store_mem, AS_PROGRAM, 8 )
AM_RANGE(0x0000, 0x3fff) AM_ROM /* BIOS */
AM_RANGE(0x4000, 0x47ff) AM_RAM /* RAM */
AM_RANGE(0x6000, 0x7fff) AM_ROMBANK("bank10") /* Cartridge/card peek area */
AM_RANGE(0x8000, 0x8000) AM_READWRITE(sms_store_control_r, sms_store_control_w) /* Control */
AM_RANGE(0xc000, 0xc000) AM_READWRITE(sms_store_cart_select_r, sms_store_cart_select_w) /* cartridge/card slot selector */
AM_RANGE(0xd800, 0xd800) AM_READ(sms_store_select1) /* Game selector port #1 */
AM_RANGE(0xdc00, 0xdc00) AM_READ(sms_store_select2) /* Game selector port #2 */
ADDRESS_MAP_END
static ADDRESS_MAP_START( sms_io, AS_IO, 8 )
ADDRESS_MAP_GLOBAL_MASK(0xff)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x00, 0x00) AM_MIRROR(0x3e) AM_WRITE(sms_bios_w)
AM_RANGE(0x01, 0x01) AM_MIRROR(0x3e) AM_WRITE(sms_io_control_w)
AM_RANGE(0x40, 0x7f) AM_READ(sms_count_r)
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("smsiii", sn76496_w)
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sms_vdp_data_r, sms_vdp_data_w)
AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sms_vdp_ctrl_r, sms_vdp_ctrl_w)
AM_RANGE(0xc0, 0xc0) AM_MIRROR(0x1e) AM_READ(sms_input_port_0_r)
AM_RANGE(0xc1, 0xc1) AM_MIRROR(0x1e) AM_READ(sms_input_port_1_r)
AM_RANGE(0xe0, 0xe0) AM_MIRROR(0x0e) AM_READ(sms_input_port_0_r)
AM_RANGE(0xe1, 0xe1) AM_MIRROR(0x0e) AM_READ(sms_input_port_1_r)
AM_RANGE(0xf0, 0xf0) AM_READWRITE(sms_input_port_0_r, sms_ym2413_register_port_0_w)
AM_RANGE(0xf1, 0xf1) AM_READWRITE(sms_input_port_1_r, sms_ym2413_data_port_0_w)
AM_RANGE(0xf2, 0xf2) AM_READWRITE(sms_fm_detect_r, sms_fm_detect_w)
AM_RANGE(0xf3, 0xf3) AM_READ(sms_input_port_1_r)
AM_RANGE(0xf4, 0xf4) AM_MIRROR(0x02) AM_READ(sms_input_port_0_r)
AM_RANGE(0xf5, 0xf5) AM_MIRROR(0x02) AM_READ(sms_input_port_1_r)
AM_RANGE(0xf8, 0xf8) AM_MIRROR(0x06) AM_READ(sms_input_port_0_r)
AM_RANGE(0xf9, 0xf9) AM_MIRROR(0x06) AM_READ(sms_input_port_1_r)
ADDRESS_MAP_END
static ADDRESS_MAP_START( gg_io, AS_IO, 8 )
ADDRESS_MAP_GLOBAL_MASK(0xff)
ADDRESS_MAP_UNMAP_HIGH
AM_RANGE(0x00, 0x00) AM_READ(gg_input_port_2_r)
AM_RANGE(0x01, 0x05) AM_READWRITE(gg_sio_r, gg_sio_w)
AM_RANGE(0x06, 0x06) AM_DEVWRITE("gamegear", sn76496_stereo_w)
AM_RANGE(0x07, 0x07) AM_WRITE(sms_io_control_w)
AM_RANGE(0x08, 0x08) AM_MIRROR(0x06) AM_WRITE(sms_bios_w)
AM_RANGE(0x09, 0x09) AM_MIRROR(0x06) AM_WRITE(sms_io_control_w)
AM_RANGE(0x10, 0x10) AM_MIRROR(0x0e) AM_WRITE(sms_bios_w)
AM_RANGE(0x11, 0x11) AM_MIRROR(0x0e) AM_WRITE(sms_io_control_w)
AM_RANGE(0x20, 0x20) AM_MIRROR(0x1e) AM_WRITE(sms_bios_w)
AM_RANGE(0x21, 0x21) AM_MIRROR(0x1e) AM_WRITE(sms_io_control_w)
AM_RANGE(0x40, 0x7f) AM_READ(sms_count_r)
AM_RANGE(0x40, 0x7f) AM_DEVWRITE("gamegear", sn76496_w)
AM_RANGE(0x80, 0x80) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sms_vdp_data_r, sms_vdp_data_w)
AM_RANGE(0x81, 0x81) AM_MIRROR(0x3e) AM_DEVREADWRITE("sms_vdp", sms_vdp_ctrl_r, sms_vdp_ctrl_w)
AM_RANGE(0xc0, 0xc0) AM_READ_PORT("PORT_DC")
AM_RANGE(0xc1, 0xc1) AM_READ_PORT("PORT_DD")
AM_RANGE(0xdc, 0xdc) AM_READ_PORT("PORT_DC")
AM_RANGE(0xdd, 0xdd) AM_READ_PORT("PORT_DD")
ADDRESS_MAP_END
static INPUT_PORTS_START( sms )
PORT_START("PORT_DC")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CATEGORY(10) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(10) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(10) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(10) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(10) PORT_PLAYER(1)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CATEGORY(10) PORT_PLAYER(1)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_CATEGORY(20) PORT_PLAYER(2) PORT_8WAY
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_CATEGORY(20) PORT_PLAYER(2) PORT_8WAY
PORT_START("PORT_DD")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_CATEGORY(20) PORT_PLAYER(2) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_CATEGORY(20) PORT_PLAYER(2) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(20) PORT_PLAYER(2)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CATEGORY(20) PORT_PLAYER(2)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_UNUSED ) /* Software Reset bit */
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNUSED ) /* Port A TH */
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNUSED ) /* Port B TH */
PORT_START("PAUSE")
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START ) PORT_NAME(DEF_STR(Pause))
PORT_START("LPHASER0") /* Light phaser X - player 1 */
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR( X, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CATEGORY(11) PORT_PLAYER(1) PORT_CHANGED(lgun1_changed, NULL)
PORT_START("LPHASER1") /* Light phaser Y - player 1 */
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR( Y, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CATEGORY(11) PORT_PLAYER(1) PORT_CHANGED(lgun1_changed, NULL)
PORT_START("LPHASER2") /* Light phaser X - player 2 */
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_CROSSHAIR( X, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(15) PORT_CATEGORY(21) PORT_PLAYER(2) PORT_CHANGED(lgun2_changed, NULL)
PORT_START("LPHASER3") /* Light phaser Y - player 2 */
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_Y ) PORT_CROSSHAIR( Y, 1.0, 0.0, 0 ) PORT_SENSITIVITY(50) PORT_KEYDELTA(25) PORT_CATEGORY(21) PORT_PLAYER(2) PORT_CHANGED(lgun2_changed, NULL)
PORT_START("RFU") /* Rapid Fire Unit */
PORT_CONFNAME( 0x03, 0x00, "Rapid Fire Unit - Player 1" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
PORT_CONFSETTING( 0x01, "Button A" )
PORT_CONFSETTING( 0x02, "Button B" )
PORT_CONFSETTING( 0x03, "Button A + B" )
PORT_CONFNAME( 0x0c, 0x00, "Rapid Fire Unit - Player 2" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
PORT_CONFSETTING( 0x04, "Button A" )
PORT_CONFSETTING( 0x08, "Button B" )
PORT_CONFSETTING( 0x0c, "Button A + B" )
PORT_START("PADDLE0") /* Paddle player 1 */
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) PORT_CATEGORY(12) PORT_PLAYER(1)
PORT_START("PADDLE1") /* Paddle player 2 */
PORT_BIT( 0xff, 0x80, IPT_PADDLE) PORT_SENSITIVITY(40) PORT_KEYDELTA(20) PORT_CENTERDELTA(0) PORT_MINMAX(0,255) PORT_CATEGORY(22) PORT_PLAYER(2)
PORT_START("CTRLIPT") /* Light Phaser and Paddle Control buttons */
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(11) PORT_PLAYER(1)
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(12) PORT_PLAYER(1)
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(13) PORT_PLAYER(1)
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CATEGORY(13) PORT_PLAYER(1)
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(21) PORT_PLAYER(2)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(22) PORT_PLAYER(2)
PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_CATEGORY(23) PORT_PLAYER(2)
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_CATEGORY(23) PORT_PLAYER(2)
PORT_START("CTRLSEL") /* Controller selection */
PORT_CATEGORY_CLASS( 0x0f, 0x00, "Player 1 Controller" )
PORT_CATEGORY_ITEM( 0x00, DEF_STR( Joystick ), 10 )
PORT_CATEGORY_ITEM( 0x01, "Light Phaser", 11 )
PORT_CATEGORY_ITEM( 0x02, "Sega Paddle Control", 12 )
PORT_CATEGORY_ITEM( 0x03, "Sega Sports Pad", 13 )
PORT_CATEGORY_CLASS( 0xf0, 0x00, "Player 2 Controller" )
PORT_CATEGORY_ITEM( 0x00, DEF_STR( Joystick ), 20 )
PORT_CATEGORY_ITEM( 0x10, "Light Phaser", 21 )
PORT_CATEGORY_ITEM( 0x20, "Sega Paddle Control", 22 )
PORT_CATEGORY_ITEM( 0x30, "Sega Sports Pad", 23 )
PORT_START("SPORT0") /* Player 1 Sports Pad X axis */
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_CATEGORY(13) PORT_PLAYER(1)
PORT_START("SPORT1") /* Player 1 Sports Pad Y axis */
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_CATEGORY(13) PORT_PLAYER(1)
PORT_START("SPORT2") /* Player 2 Sports Pad X axis */
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_X ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_CATEGORY(23) PORT_PLAYER(2)
PORT_START("SPORT3") /* Player 2 Sports Pad Y axis */
PORT_BIT( 0xff, 0x00, IPT_TRACKBALL_Y ) PORT_SENSITIVITY(50) PORT_KEYDELTA(40) PORT_RESET PORT_REVERSE PORT_CATEGORY(23) PORT_PLAYER(2)
INPUT_PORTS_END
static INPUT_PORTS_START( sms1 )
PORT_INCLUDE( sms )
PORT_START("RESET")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_NAME("Reset Button")
PORT_START("SEGASCOPE")
PORT_CONFNAME( 0x01, 0x00, "SegaScope (3-D Glasses)" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
PORT_CONFSETTING( 0x01, DEF_STR( On ) )
PORT_START("SSCOPE_BINOCULAR")
PORT_CONFNAME( 0x03, 0x00, "SegaScope - Binocular Hack" ) PORT_CONDITION("SEGASCOPE", 0x01, PORTCOND_EQUALS, 0x01)
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
PORT_CONFSETTING( 0x01, "Left Lens" )
PORT_CONFSETTING( 0x02, "Right Lens" )
PORT_CONFSETTING( 0x03, "Both Lens" )
PORT_BIT( 0x03, 0x00, IPT_UNUSED ) PORT_CONDITION("SEGASCOPE", 0x01, PORTCOND_EQUALS, 0x00)
INPUT_PORTS_END
static INPUT_PORTS_START( smsj )
PORT_INCLUDE( sms1 )
PORT_START("TVDRAW")
PORT_CONFNAME( 0x01, 0x00, "Terebi Oekaki Graphics Tablet" )
PORT_CONFSETTING( 0x00, DEF_STR( Off ) )
PORT_CONFSETTING( 0x01, DEF_STR( On ) )
PORT_START("TVDRAW_X")
PORT_BIT( 0xff, 0x80, IPT_LIGHTGUN_X ) PORT_NAME("Tablet - X Axis") PORT_CROSSHAIR(X, 1.0, 0.0, 0) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1)
PORT_CONDITION("TVDRAW", 0x01, PORTCOND_EQUALS, 0x01)
PORT_START("TVDRAW_Y")
PORT_BIT( 0xff, 0x60, IPT_LIGHTGUN_Y ) PORT_NAME("Tablet - Y Axis") PORT_CROSSHAIR(Y, 1.0, 0.0, 0) PORT_MINMAX(0, 191) PORT_SENSITIVITY(50) PORT_KEYDELTA(10) PORT_PLAYER(1)
PORT_CONDITION("TVDRAW", 0x01, PORTCOND_EQUALS, 0x01)
PORT_START("TVDRAW_PEN")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_BUTTON3 ) PORT_NAME("Tablet - Pen") PORT_CONDITION("TVDRAW", 0x01, PORTCOND_EQUALS, 0x01)
INPUT_PORTS_END
static INPUT_PORTS_START( gg )
PORT_START("PORT_DC")
PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_8WAY
PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(1)
PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(1)
PORT_BIT( 0xc0, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("PORT_DD")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_START("START")
PORT_BIT( 0x7f, IP_ACTIVE_LOW, IPT_UNUSED )
PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_START ) PORT_NAME("Start") /* Game Gear START */
INPUT_PORTS_END
static PALETTE_INIT( sms )
{
int i;
for (i = 0; i < 64; i++)
{
int r = i & 0x03;
int g = (i & 0x0c) >> 2;
int b = (i & 0x30) >> 4;
palette_set_color_rgb(machine, i, r << 6, g << 6, b << 6);
}
/* TMS9918 palette */
palette_set_color_rgb(machine, 64+ 0, 0, 0, 0);
palette_set_color_rgb(machine, 64+ 1, 0, 0, 0);
palette_set_color_rgb(machine, 64+ 2, 33, 200, 66);
palette_set_color_rgb(machine, 64+ 3, 94, 220, 120);
palette_set_color_rgb(machine, 64+ 4, 84, 85, 237);
palette_set_color_rgb(machine, 64+ 5, 125, 118, 252);
palette_set_color_rgb(machine, 64+ 6, 212, 82, 77);
palette_set_color_rgb(machine, 64+ 7, 66, 235, 245);
palette_set_color_rgb(machine, 64+ 8, 252, 85, 84);
palette_set_color_rgb(machine, 64+ 9, 255, 121, 120);
palette_set_color_rgb(machine, 64+10, 212, 193, 84);
palette_set_color_rgb(machine, 64+11, 230, 206, 128);
palette_set_color_rgb(machine, 64+12, 33, 176, 59);
palette_set_color_rgb(machine, 64+13, 201, 91, 186);
palette_set_color_rgb(machine, 64+14, 204, 204, 204);
palette_set_color_rgb(machine, 64+15, 255, 255, 255);
}
static PALETTE_INIT( gamegear )
{
int i;
for (i = 0; i < 4096; i++)
{
int r = i & 0x000f;
int g = (i & 0x00f0) >> 4;
int b = (i & 0x0f00) >> 8;
palette_set_color_rgb(machine, i, r << 4, g << 4, b << 4);
}
}
static void sms_int_callback( running_machine &machine, int state )
{
cputag_set_input_line(machine, "maincpu", 0, state);
}
static const smsvdp_interface _315_5124_intf =
{
MODEL_315_5124,
sms_int_callback,
sms_pause_callback
};
static const smsvdp_interface _315_5246_intf =
{
MODEL_315_5246,
sms_int_callback,
sms_pause_callback
};
static const smsvdp_interface _315_5378_intf =
{
MODEL_315_5378,
sms_int_callback,
sms_pause_callback
};
static const smsvdp_interface sms_store_intf =
{
MODEL_315_5124,
sms_store_int_callback,
sms_pause_callback
};
static MACHINE_CONFIG_FRAGMENT( sms_cartslot )
MCFG_CARTSLOT_ADD("cart1")
MCFG_CARTSLOT_EXTENSION_LIST("sms,bin")
MCFG_CARTSLOT_NOT_MANDATORY
MCFG_CARTSLOT_INTERFACE("sms_cart")
MCFG_CARTSLOT_START(sms_cart)
MCFG_CARTSLOT_LOAD(sms_cart)
MCFG_SOFTWARE_LIST_ADD("cart_list","sms")
MACHINE_CONFIG_END
static MACHINE_CONFIG_FRAGMENT( gg_cartslot )
MCFG_CARTSLOT_ADD("cart1")
MCFG_CARTSLOT_EXTENSION_LIST("gg,bin")
MCFG_CARTSLOT_MANDATORY
MCFG_CARTSLOT_INTERFACE("gamegear_cart")
MCFG_CARTSLOT_START(sms_cart)
MCFG_CARTSLOT_LOAD(sms_cart)
MCFG_SOFTWARE_LIST_ADD("cart_list","gamegear")
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( sms_ntsc_base, sms_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", Z80, XTAL_53_693175MHz/15)
MCFG_CPU_PROGRAM_MAP(sms_mem)
MCFG_CPU_IO_MAP(sms_io)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_MACHINE_START(sms)
MCFG_MACHINE_RESET(sms)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("smsiii", SMSIII, XTAL_53_693175MHz/15)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MCFG_FRAGMENT_ADD( sms_cartslot )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms2_ntsc, sms_ntsc_base )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(XTAL_53_693175MHz/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, NTSC_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS + 224)
MCFG_SCREEN_UPDATE(sms)
MCFG_PALETTE_LENGTH(64+16)
MCFG_PALETTE_INIT(sms)
MCFG_SMSVDP_ADD("sms_vdp", _315_5246_intf)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms1_ntsc, sms_ntsc_base )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(sms1_mem) // This adds the SegaScope handlers for 3-D glasses
MCFG_CPU_IO_MAP(sms_io)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(XTAL_53_693175MHz/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, NTSC_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS + 224)
MCFG_SCREEN_UPDATE(sms1)
MCFG_SCREEN_ADD("left_lcd", LCD) // This is needed for SegaScope Left LCD
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(XTAL_53_693175MHz/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, NTSC_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS + 224)
MCFG_SCREEN_UPDATE(sms1)
MCFG_SCREEN_ADD("right_lcd", LCD) // This is needed for SegaScope Right LCD
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(XTAL_53_693175MHz/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, NTSC_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS, TBORDER_START + NTSC_224_TBORDER_Y_PIXELS + 224)
MCFG_SCREEN_UPDATE(sms1)
MCFG_DEFAULT_LAYOUT(layout_sms1)
MCFG_PALETTE_LENGTH(64+16)
MCFG_PALETTE_INIT(sms)
MCFG_VIDEO_START(sms1)
MCFG_SMSVDP_ADD("sms_vdp", _315_5124_intf)
MACHINE_CONFIG_END
#define MCFG_SMSSDISP_CARTSLOT_ADD(_tag) \
MCFG_CARTSLOT_ADD(_tag) \
MCFG_CARTSLOT_EXTENSION_LIST("sms,bin") \
MCFG_CARTSLOT_NOT_MANDATORY \
MCFG_CARTSLOT_INTERFACE("sms_cart") \
MCFG_CARTSLOT_START(sms_cart) \
MCFG_CARTSLOT_LOAD(sms_cart)
static MACHINE_CONFIG_DERIVED( sms_sdisp, sms2_ntsc )
MCFG_DEVICE_REMOVE("sms_vdp")
MCFG_SMSVDP_ADD("sms_vdp", sms_store_intf)
MCFG_CPU_ADD("control", Z80, XTAL_53_693175MHz/15)
MCFG_CPU_PROGRAM_MAP(sms_store_mem)
/* Both CPUs seem to communicate with the VDP etc? */
MCFG_CPU_IO_MAP(sms_io)
MCFG_CARTSLOT_MODIFY("cart1")
MCFG_CARTSLOT_EXTENSION_LIST("sms,bin")
MCFG_CARTSLOT_MANDATORY
MCFG_CARTSLOT_INTERFACE("sms_cart")
MCFG_CARTSLOT_START(sms_cart)
MCFG_CARTSLOT_LOAD(sms_cart)
MCFG_SMSSDISP_CARTSLOT_ADD("cart2")
MCFG_SMSSDISP_CARTSLOT_ADD("cart3")
MCFG_SMSSDISP_CARTSLOT_ADD("cart4")
MCFG_SMSSDISP_CARTSLOT_ADD("cart5")
MCFG_SMSSDISP_CARTSLOT_ADD("cart6")
MCFG_SMSSDISP_CARTSLOT_ADD("cart7")
MCFG_SMSSDISP_CARTSLOT_ADD("cart8")
MCFG_SMSSDISP_CARTSLOT_ADD("cart9")
MCFG_SMSSDISP_CARTSLOT_ADD("cart10")
MCFG_SMSSDISP_CARTSLOT_ADD("cart11")
MCFG_SMSSDISP_CARTSLOT_ADD("cart12")
MCFG_SMSSDISP_CARTSLOT_ADD("cart13")
MCFG_SMSSDISP_CARTSLOT_ADD("cart14")
MCFG_SMSSDISP_CARTSLOT_ADD("cart15")
MCFG_SMSSDISP_CARTSLOT_ADD("cart16")
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( sms_pal_base, sms_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", Z80, MASTER_CLOCK_PAL/15)
MCFG_CPU_PROGRAM_MAP(sms_mem)
MCFG_CPU_IO_MAP(sms_io)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_MACHINE_START(sms)
MCFG_MACHINE_RESET(sms)
/* sound hardware */
MCFG_SPEAKER_STANDARD_MONO("mono")
MCFG_SOUND_ADD("smsiii", SMSIII, MASTER_CLOCK_PAL/15)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MCFG_FRAGMENT_ADD( sms_cartslot )
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms2_pal, sms_pal_base )
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_PAL/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, PAL_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS + 240)
MCFG_SCREEN_UPDATE(sms)
MCFG_PALETTE_LENGTH(64+16)
MCFG_PALETTE_INIT(sms)
MCFG_SMSVDP_ADD("sms_vdp", _315_5246_intf)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms1_pal, sms_pal_base )
MCFG_CPU_MODIFY("maincpu")
MCFG_CPU_PROGRAM_MAP(sms1_mem) // This adds the SegaScope handlers for 3-D glasses
MCFG_CPU_IO_MAP(sms_io)
/* video hardware */
MCFG_SCREEN_ADD("screen", RASTER)
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_PAL/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, PAL_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS + 240)
MCFG_SCREEN_UPDATE(sms1)
MCFG_SCREEN_ADD("left_lcd", LCD) // This is needed for SegaScope Left LCD
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_PAL/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, PAL_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS + 240)
MCFG_SCREEN_UPDATE(sms1)
MCFG_SCREEN_ADD("right_lcd", LCD) // This is needed for SegaScope Right LCD
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(MASTER_CLOCK_PAL/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS - 2, LBORDER_START + LBORDER_X_PIXELS + 256 + 10, PAL_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS, TBORDER_START + PAL_240_TBORDER_Y_PIXELS + 240)
MCFG_SCREEN_UPDATE(sms1)
MCFG_PALETTE_LENGTH(64+16)
MCFG_PALETTE_INIT(sms)
MCFG_DEFAULT_LAYOUT(layout_sms1)
MCFG_SMSVDP_ADD("sms_vdp", _315_5124_intf)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms_fm, sms1_ntsc )
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_53_693175MHz/15)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sg1000m3, sms_fm )
MCFG_CARTSLOT_MODIFY("cart1")
MCFG_CARTSLOT_EXTENSION_LIST("sms,bin,sg")
MCFG_CARTSLOT_MANDATORY
MCFG_CARTSLOT_START(sms_cart)
MCFG_CARTSLOT_LOAD(sms_cart)
MACHINE_CONFIG_END
static MACHINE_CONFIG_DERIVED( sms2_fm, sms2_ntsc )
MCFG_SOUND_ADD("ym2413", YM2413, XTAL_53_693175MHz/15)
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
MACHINE_CONFIG_END
static MACHINE_CONFIG_START( gamegear, sms_state )
/* basic machine hardware */
MCFG_CPU_ADD("maincpu", Z80, XTAL_53_693175MHz/15)
MCFG_CPU_PROGRAM_MAP(sms_mem)
MCFG_CPU_IO_MAP(gg_io)
MCFG_QUANTUM_TIME(attotime::from_hz(60))
MCFG_MACHINE_START(sms)
MCFG_MACHINE_RESET(sms)
/* video hardware */
MCFG_SCREEN_ADD("screen", LCD)
MCFG_SCREEN_FORMAT(BITMAP_FORMAT_RGB32)
MCFG_SCREEN_RAW_PARAMS(XTAL_53_693175MHz/10, SMS_X_PIXELS, LBORDER_START + LBORDER_X_PIXELS + 6*8, LBORDER_START + LBORDER_X_PIXELS + 26*8, NTSC_Y_PIXELS, TBORDER_START + NTSC_192_TBORDER_Y_PIXELS + 3*8, TBORDER_START + NTSC_192_TBORDER_Y_PIXELS + 21*8 )
MCFG_SCREEN_UPDATE(gamegear)
MCFG_PALETTE_LENGTH(4096)
MCFG_PALETTE_INIT(gamegear)
MCFG_VIDEO_START(gamegear)
MCFG_SMSVDP_ADD("sms_vdp", _315_5378_intf)
/* sound hardware */
MCFG_SPEAKER_STANDARD_STEREO("lspeaker","rspeaker")
MCFG_SOUND_ADD("gamegear", GAMEGEAR, XTAL_53_693175MHz/15)
MCFG_SOUND_ROUTE(0, "lspeaker", 1.00)
MCFG_SOUND_ROUTE(1, "rspeaker", 1.00)
/* cartridge */
MCFG_FRAGMENT_ADD( gg_cartslot )
MACHINE_CONFIG_END
ROM_START(sms1)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x20000, "user1", 0)
ROM_SYSTEM_BIOS( 0, "bios13", "US/European BIOS v1.3 (1986)" )
ROMX_LOAD("bios13fx.rom", 0x0000, 0x2000, CRC(0072ED54) SHA1(c315672807d8ddb8d91443729405c766dd95cae7), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 1, "hangonsh", "US/European BIOS v2.4 with Hang On and Safari Hunt (1988)" )
ROMX_LOAD("hshbios.rom", 0x0000, 0x20000, CRC(91E93385) SHA1(9e179392cd416af14024d8f31c981d9ee9a64517), ROM_BIOS(2))
ROM_SYSTEM_BIOS( 2, "hangon", "US/European BIOS v3.4 with Hang On (1988)" )
ROMX_LOAD("hangbios.rom", 0x0000, 0x20000, CRC(8EDF7AC6) SHA1(51fd6d7990f62cd9d18c9ecfc62ed7936169107e), ROM_BIOS(3))
ROM_SYSTEM_BIOS( 3, "missiled", "US/European BIOS v4.4 with Missile Defense 3D (1988)" )
ROMX_LOAD("missiled.rom", 0x0000, 0x20000, CRC(E79BB689) SHA1(aa92ae576ca670b00855e278378d89e9f85e0351), ROM_BIOS(4))
ROM_SYSTEM_BIOS( 4, "proto", "US Master System Prototype BIOS" )
ROMX_LOAD("m404prot.rom", 0x0000, 0x2000, CRC(1a15dfcc) SHA1(4a06c8e66261611dce0305217c42138b71331701), ROM_BIOS(5))
ROM_END
ROM_START(sms)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x20000, "user1", 0)
ROM_SYSTEM_BIOS( 0, "alexkidd", "US/European BIOS with Alex Kidd in Miracle World (1990)" )
ROMX_LOAD("akbios.rom", 0x0000, 0x20000, CRC(CF4A09EA) SHA1(3af7b66248d34eb26da40c92bf2fa4c73a46a051), ROM_BIOS(1))
ROM_END
ROM_START(smssdisp)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0x00)
ROM_REGION(0x4000, "user1", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x4000, "control", 0)
ROM_LOAD("smssdisp.rom", 0x0000, 0x4000, CRC(ee2c29ba) SHA1(fc465122134d95363112eb51b9ab71db3576cefd))
ROM_END
ROM_START(sms1pal)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x20000, "user1", 0)
ROM_SYSTEM_BIOS( 0, "bios13", "US/European BIOS v1.3 (1986)" )
ROMX_LOAD("bios13fx.rom", 0x0000, 0x2000, CRC(0072ED54) SHA1(c315672807d8ddb8d91443729405c766dd95cae7), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 1, "hangonsh", "US/European BIOS v2.4 with Hang On and Safari Hunt (1988)" )
ROMX_LOAD("hshbios.rom", 0x0000, 0x20000, CRC(91E93385) SHA1(9e179392cd416af14024d8f31c981d9ee9a64517), ROM_BIOS(2))
ROM_SYSTEM_BIOS( 2, "hangon", "Sega Master System - US/European BIOS v3.4 with Hang On (1988)" )
ROMX_LOAD("hangbios.rom", 0x0000, 0x20000, CRC(8EDF7AC6) SHA1(51fd6d7990f62cd9d18c9ecfc62ed7936169107e), ROM_BIOS(3))
ROM_SYSTEM_BIOS( 3, "missiled", "US/European BIOS v4.4 with Missile Defense 3D (1988)" )
ROMX_LOAD("missiled.rom", 0x0000, 0x20000, CRC(E79BB689) SHA1(aa92ae576ca670b00855e278378d89e9f85e0351), ROM_BIOS(4))
ROM_END
ROM_START(smspal)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x40000, "user1", 0)
ROM_SYSTEM_BIOS( 0, "alexkidd", "US/European BIOS with Alex Kidd in Miracle World (1990)" )
ROMX_LOAD("akbios.rom", 0x0000, 0x20000, CRC(CF4A09EA) SHA1(3af7b66248d34eb26da40c92bf2fa4c73a46a051), ROM_BIOS(1))
ROM_SYSTEM_BIOS( 1, "sonic", "European/Brazilian BIOS with Sonic the Hedgehog (1991)" )
ROMX_LOAD("sonbios.rom", 0x0000, 0x40000, CRC(81C3476B) SHA1(6aca0e3dffe461ba1cb11a86cd4caf5b97e1b8df), ROM_BIOS(2))
ROM_END
ROM_START(sg1000m3)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0x00)
ROM_END
ROM_START(smsj)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x4000, "user1", 0)
ROM_SYSTEM_BIOS( 0, "jbios21", "Japanese BIOS v2.1 (1987)" )
ROMX_LOAD("jbios21.rom", 0x0000, 0x2000, CRC(48D44A13) SHA1(a8c1b39a2e41137835eda6a5de6d46dd9fadbaf2), ROM_BIOS(1))
ROM_END
ROM_START(sms2kr)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0xff)
ROM_REGION(0x20000, "user1", 0)
ROM_SYSTEM_BIOS( 0, "akbioskr", "Samsung Gam*Boy II with Alex Kidd in Miracle World (1990)" )
ROMX_LOAD("akbioskr.rom", 0x000, 0x20000, CRC(9c5bad91) SHA1(2feafd8f1c40fdf1bd5668f8c5c02e5560945b17), ROM_BIOS(1))
ROM_END
ROM_START(gamegear)
ROM_REGION(0x4000, "maincpu", 0)
ROM_FILL(0x0000, 0x4000, 0x00)
ROM_REGION(0x0400, "user1", 0)
ROM_SYSTEM_BIOS( 0, "none", "No BIOS" ) /* gamegear */
ROM_SYSTEM_BIOS( 1, "majesco", "Majesco BIOS" ) /* gamg */
ROMX_LOAD("majbios.rom", 0x0000, 0x0400, CRC(0EBEA9D4) SHA1(914aa165e3d879f060be77870d345b60cfeb4ede), ROM_BIOS(2))
ROM_END
#define rom_gamegeaj rom_gamegear
/***************************************************************************
Game driver(s)
US
- Sega Master System I (sms1)
- prototype bios - 1986
- without built-in game v1.3 - 1986
- built-in Hang On/Safari Hunt v2.4 - 1988
- built-in Hang On v3.4 - 1988
- built-in Missile Defense 3-D v4.4 - 1988
- built-in Hang On/Astro Warrior ????
- Sega Master System II (sms/sms2)
- built-in Alex Kidd in Miracle World - 1990
JP
- Sega SG-1000 Mark III (smsm3)
- no bios
- Sega Master System (I) (smsj)
- without built-in game v2.1 - 1987
KR
- Sega Master System II (sms2kr)
- built-in Alex Kidd in Miracle World (Korean)
EU
- Sega Master System I (sms1pal)
- without built-in game v1.3 - 1986
- built-in Hang On/Safari Hunt v2.4 - 1988
- built-in Hang On v3.4 - 1988
- built-in Missile Defense 3-D v4.4 - 1988
- built-in Hang On/Astro Warrior ????
- Sega Master System II (sms2pal)
- built-in Alex Kidd in Miracle World - 1990
- built-in Sonic the Hedgehog - 1991
BR
- Sega Master System I - 1987
- Sega Master System II???
- Sega Master System III - Tec Toy, 1987
- Sega Master System Compact - Tec Toy, 1992
- Sega Master System Girl - Tec Toy, 1992
***************************************************************************/
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
CONS( 1984, sg1000m3, sms, 0, sg1000m3, smsj, sg1000m3, "Sega", "SG-1000 Mark III", 0 )
CONS( 1986, sms1, sms, 0, sms1_ntsc, sms1, sms1, "Sega", "Master System I", 0 )
CONS( 1986, sms1pal, sms, 0, sms1_pal, sms1, sms1, "Sega", "Master System I (PAL)" , 0 )
CONS( 1986, smssdisp, sms, 0, sms_sdisp, sms, smssdisp, "Sega", "Master System Store Display Unit", GAME_NOT_WORKING )
CONS( 1987, smsj, sms, 0, sms_fm, smsj, smsj, "Sega", "Master System (Japan)", 0 )
CONS( 1990, sms, 0, 0, sms2_ntsc, sms, sms1, "Sega", "Master System II", 0 )
CONS( 1990, smspal, sms, 0, sms2_pal, sms, sms1, "Sega", "Master System II (PAL)", 0 )
CONS( 1990, sms2kr, sms, 0, sms2_fm, sms, sms2kr, "Samsung", "Gam*Boy II (Korea)", 0 )
CONS( 1990, gamegear, 0, sms, gamegear, gg, gamegear, "Sega", "Game Gear (Europe/America)", 0 )
CONS( 1990, gamegeaj, gamegear, 0, gamegear, gg, gamegeaj, "Sega", "Game Gear (Japan)", 0 )

1221
src/mame/drivers/sg1000.c Normal file

File diff suppressed because it is too large Load Diff

352
src/mame/formats/basicdsk.c Normal file
View File

@ -0,0 +1,352 @@
/*********************************************************************
formats/basicdsk.c
Floppy format code for basic disks
*********************************************************************/
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include "basicdsk.h"
static floperr_t basicdsk_read_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen);
static floperr_t basicdsk_write_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
static floperr_t basicdsk_read_indexed_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen);
static floperr_t basicdsk_write_indexed_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam);
static floperr_t basicdsk_get_sector_length(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length);
static floperr_t basicdsk_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags);
static int basicdsk_get_heads_per_disk(floppy_image *floppy);
static int basicdsk_get_tracks_per_disk(floppy_image *floppy);
static floperr_t basicdsk_format_track(floppy_image *floppy, int head, int track, option_resolution *params);
#define BASICDSK_TAG "basicdsktag"
struct basicdsk_tag
{
struct basicdsk_geometry geometry;
};
/********************************************************************/
static const struct basicdsk_geometry *get_geometry(floppy_image *floppy)
{
const struct basicdsk_tag *tag;
tag = (const basicdsk_tag *)floppy_tag(floppy);
return &tag->geometry;
}
floperr_t basicdsk_construct(floppy_image *floppy, const struct basicdsk_geometry *geometry)
{
struct basicdsk_tag *tag;
struct FloppyCallbacks *format;
assert(geometry->heads);
assert(geometry->tracks);
assert(geometry->sectors);
tag = (struct basicdsk_tag *) floppy_create_tag(floppy, sizeof(struct basicdsk_tag));
if (!tag)
return FLOPPY_ERROR_OUTOFMEMORY;
tag->geometry = *geometry;
/* set up format callbacks */
format = floppy_callbacks(floppy);
format->read_sector = basicdsk_read_sector;
format->write_sector = basicdsk_write_sector;
format->read_indexed_sector = basicdsk_read_indexed_sector;
format->write_indexed_sector = basicdsk_write_indexed_sector;
format->get_sector_length = basicdsk_get_sector_length;
format->get_heads_per_disk = basicdsk_get_heads_per_disk;
format->get_tracks_per_disk = basicdsk_get_tracks_per_disk;
format->get_indexed_sector_info = basicdsk_get_indexed_sector_info;
format->format_track = basicdsk_format_track;
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t get_offset(floppy_image *floppy, int head, int track, int sector, int sector_is_index, UINT64 *offset)
{
const struct basicdsk_geometry *geom;
UINT64 offs;
geom = get_geometry(floppy);
/* translate the sector to a raw sector */
if (!sector_is_index)
{
sector -= geom->first_sector_id;
}
if (geom->translate_sector)
sector = geom->translate_sector(floppy, sector);
/* check to see if we are out of range */
if ((head < 0) || (head >= geom->heads) || (track < 0) || (track >= geom->tracks)
|| (sector < 0) || (sector >= geom->sectors))
return FLOPPY_ERROR_SEEKERROR;
if (geom->translate_offset)
offs = geom->translate_offset(floppy, geom, track, head, sector);
else
{
offs = 0;
offs += track;
offs *= geom->heads;
offs += head;
offs *= geom->sectors;
offs += sector;
}
offs *= geom->sector_length;
offs += geom->offset;
if (offset)
*offset = offs;
return FLOPPY_ERROR_SUCCESS;
}
static int internal_basicdsk_translate_sector_interleave(floppy_image *floppy, int sector)
{
const struct basicdsk_geometry *geom = get_geometry(floppy);
if (sector >= geom->sectors)
return sector;
return geom->sector_map[sector];
}
static floperr_t internal_basicdsk_read_sector(floppy_image *floppy, int head, int track, int sector, int sector_is_index, void *buffer, size_t buflen)
{
UINT64 offset;
floperr_t err;
err = get_offset(floppy, head, track, sector, sector_is_index, &offset);
if (err)
return err;
floppy_image_read(floppy, buffer, offset, buflen);
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t internal_basicdsk_write_sector(floppy_image *floppy, int head, int track, int sector, int sector_is_index, const void *buffer, size_t buflen, int ddam)
{
UINT64 offset;
floperr_t err;
err = get_offset(floppy, head, track, sector, sector_is_index, &offset);
if (err)
return err;
floppy_image_write(floppy, buffer, offset, buflen);
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t basicdsk_read_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen)
{
return internal_basicdsk_read_sector(floppy, head, track, sector, FALSE, buffer, buflen);
}
static floperr_t basicdsk_write_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
{
return internal_basicdsk_write_sector(floppy, head, track, sector, FALSE, buffer, buflen, ddam);
}
static floperr_t basicdsk_read_indexed_sector(floppy_image *floppy, int head, int track, int sector, void *buffer, size_t buflen)
{
return internal_basicdsk_read_sector(floppy, head, track, sector, TRUE, buffer, buflen);
}
static floperr_t basicdsk_write_indexed_sector(floppy_image *floppy, int head, int track, int sector, const void *buffer, size_t buflen, int ddam)
{
return internal_basicdsk_write_sector(floppy, head, track, sector, TRUE, buffer, buflen, ddam);
}
static floperr_t basicdsk_format_track(floppy_image *floppy, int head, int track, option_resolution *params)
{
floperr_t err = FLOPPY_ERROR_SUCCESS;
UINT8 local_buffer[512];
void *alloc_buffer = NULL;
void *buffer;
UINT32 sector_length;
int sector;
const struct basicdsk_geometry *geometry;
geometry = get_geometry(floppy);
sector_length = geometry->sector_length;
if (sector_length > sizeof(local_buffer))
{
alloc_buffer = malloc(sector_length);
if (!alloc_buffer)
{
err = FLOPPY_ERROR_OUTOFMEMORY;
goto done;
}
buffer = alloc_buffer;
}
else
{
alloc_buffer = NULL;
buffer = local_buffer;
}
memset(buffer, floppy_get_filler(floppy), sector_length);
for (sector = 0; sector < geometry->sectors; sector++)
{
err = basicdsk_write_sector(floppy, head, track, sector + geometry->first_sector_id, buffer, sector_length, 0);
if (err)
goto done;
}
done:
if (alloc_buffer)
free(alloc_buffer);
return err;
}
static int basicdsk_get_heads_per_disk(floppy_image *floppy)
{
return get_geometry(floppy)->heads;
}
static int basicdsk_get_tracks_per_disk(floppy_image *floppy)
{
return get_geometry(floppy)->tracks;
}
static floperr_t basicdsk_get_sector_length(floppy_image *floppy, int head, int track, int sector, UINT32 *sector_length)
{
floperr_t err;
err = get_offset(floppy, head, track, sector, FALSE, NULL);
if (err)
return err;
if (sector_length)
*sector_length = get_geometry(floppy)->sector_length;
return FLOPPY_ERROR_SUCCESS;
}
static floperr_t basicdsk_get_indexed_sector_info(floppy_image *floppy, int head, int track, int sector_index, int *cylinder, int *side, int *sector, UINT32 *sector_length, unsigned long *flags)
{
const struct basicdsk_geometry *geom = get_geometry(floppy);
if (geom->translate_sector)
sector_index = geom->translate_sector(floppy, sector_index);
sector_index += geom->first_sector_id;
if (cylinder)
*cylinder = track;
if (side)
*side = head;
if (sector)
*sector = sector_index;
if (flags) {
/* TODO: read DAM or DDAM and determine flags */
*flags = 0;
if (geom->get_ddam)
*flags = geom->get_ddam(floppy, geom, track, head, sector_index);
}
return basicdsk_get_sector_length(floppy, head, track, sector_index, sector_length);
}
/********************************************************************
* Generic Basicdsk Constructors
********************************************************************/
static void basicdsk_default_geometry(const struct FloppyFormat *format, struct basicdsk_geometry *geometry)
{
optreserr_t err;
int sector_length;
memset(geometry, 0, sizeof(*geometry));
err = option_resolution_getdefault(format->param_guidelines, PARAM_HEADS, &geometry->heads);
assert(!err);
err = option_resolution_getdefault(format->param_guidelines, PARAM_TRACKS, &geometry->tracks);
assert(!err);
err = option_resolution_getdefault(format->param_guidelines, PARAM_SECTORS, &geometry->sectors);
assert(!err);
err = option_resolution_getdefault(format->param_guidelines, PARAM_FIRST_SECTOR_ID, &geometry->first_sector_id);
assert(!err);
err = option_resolution_getdefault(format->param_guidelines, PARAM_INTERLEAVE, &geometry->interleave);
if (err!=0) {
geometry->interleave = 1;
}
err = option_resolution_getdefault(format->param_guidelines, PARAM_SECTOR_LENGTH, &sector_length);
assert(!err);
geometry->sector_length = sector_length;
if (geometry->interleave > 1)
{
int sector = 0;
for (int i = 0; i < geometry->sectors; i++)
{
geometry->sector_map[i] = sector;
sector += geometry->interleave;
if (sector >= geometry->sectors)
sector -= geometry->sectors;
}
geometry->translate_sector = internal_basicdsk_translate_sector_interleave;
}
}
FLOPPY_CONSTRUCT(basicdsk_construct_default)
{
struct basicdsk_geometry geometry;
basicdsk_default_geometry(format, &geometry);
return basicdsk_construct(floppy, &geometry);
}
FLOPPY_IDENTIFY(basicdsk_identify_default)
{
UINT64 expected_size;
struct basicdsk_geometry geometry;
basicdsk_default_geometry(format, &geometry);
expected_size = geometry.sector_length;
expected_size *= geometry.heads;
expected_size *= geometry.tracks;
expected_size *= geometry.sectors;
*vote = (floppy_image_size(floppy) == expected_size) ? 100 : 0;
return FLOPPY_ERROR_SUCCESS;
}

View File

@ -0,0 +1,35 @@
/*********************************************************************
formats/basicdsk.h
Floppy format code for basic disks
*********************************************************************/
#ifndef BASICDSK_H
#define BASICDSK_H
#include "imagedev/flopimg.h"
struct basicdsk_geometry
{
int heads;
int tracks;
int sectors;
int first_sector_id;
int interleave;
int sector_map[256];
UINT32 sector_length;
UINT64 offset;
int (*translate_sector)(floppy_image *floppy, int sector);
UINT64 (*translate_offset)(floppy_image *floppy, const struct basicdsk_geometry *geom, int track, int head, int sector);
UINT64 (*get_ddam)(floppy_image *floppy, const struct basicdsk_geometry *geom, int track, int head, int sector);
};
floperr_t basicdsk_construct(floppy_image *floppy, const struct basicdsk_geometry *geometry);
FLOPPY_IDENTIFY(basicdsk_identify_default);
FLOPPY_CONSTRUCT(basicdsk_construct_default);
#endif /* BASICDSK_H */

183
src/mame/includes/segasms.h Normal file
View File

@ -0,0 +1,183 @@
/*****************************************************************************
*
* includes/sms.h
*
****************************************************************************/
#ifndef SMS_H_
#define SMS_H_
#define LOG_REG
#define LOG_PAGING
#define LOG_COLOR
#define NVRAM_SIZE (0x08000)
#define CPU_ADDRESSABLE_SIZE (0x10000)
#define MAX_CARTRIDGES 16
class sms_state : public driver_device
{
public:
sms_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag) { }
// device_ts
device_t *m_main_cpu;
device_t *m_control_cpu;
device_t *m_vdp;
device_t *m_ym;
device_t *m_main_scr;
device_t *m_left_lcd;
device_t *m_right_lcd;
UINT8 m_bios_page_count;
UINT8 m_fm_detect;
UINT8 m_ctrl_reg;
int m_paused;
UINT8 m_bios_port;
UINT8 *m_BIOS;
UINT8 *m_mapper_ram;
UINT8 m_mapper[4];
// we are going to use 1-6, same as bank numbers. Notice, though, that most mappers
// only work on 16K banks and, hence, banks 4-6 are not always directly set
// (they often use bank3 + 0x2000 and bank5 + 0x2000)
UINT8 *m_banking_bios[7];
UINT8 *m_banking_cart[7];
UINT8 *m_banking_none[7];
UINT8 m_gg_sio[5];
UINT8 m_store_control;
UINT8 m_input_port0;
UINT8 m_input_port1;
// for gamegear LCD persistence hack
bitmap_t *m_tmp_bitmap;
bitmap_t *m_prev_bitmap;
// for 3D glass binocular hack
bitmap_t *m_prevleft_bitmap;
bitmap_t *m_prevright_bitmap;
/* Model identifiers */
UINT8 m_is_gamegear;
UINT8 m_is_region_japan;
UINT8 m_has_bios_0400;
UINT8 m_has_bios_2000;
UINT8 m_has_bios_full;
UINT8 m_has_bios;
UINT8 m_has_fm;
/* Data needed for Rapid Fire Unit support */
emu_timer *m_rapid_fire_timer;
UINT8 m_rapid_fire_state_1;
UINT8 m_rapid_fire_state_2;
/* Data needed for Paddle Control controller */
UINT32 m_last_paddle_read_time;
UINT8 m_paddle_read_state;
/* Data needed for Sports Pad controller */
UINT32 m_last_sports_pad_time_1;
UINT32 m_last_sports_pad_time_2;
UINT8 m_sports_pad_state_1;
UINT8 m_sports_pad_state_2;
UINT8 m_sports_pad_last_data_1;
UINT8 m_sports_pad_last_data_2;
UINT8 m_sports_pad_1_x;
UINT8 m_sports_pad_1_y;
UINT8 m_sports_pad_2_x;
UINT8 m_sports_pad_2_y;
/* Data needed for Light Phaser */
emu_timer *m_lphaser_1_timer;
emu_timer *m_lphaser_2_timer;
UINT8 m_lphaser_1_latch;
UINT8 m_lphaser_2_latch;
int m_lphaser_x_offs; /* Needed to 'calibrate' lphaser; set at cart loading */
/* Data needed for SegaScope (3D glasses) */
UINT8 m_sscope_state;
/* Data needed for Terebi Oekaki (TV Draw) */
UINT8 m_tvdraw_data;
/* Cartridge slot info */
UINT8 m_current_cartridge;
struct
{
UINT8 *ROM; /* Pointer to ROM image data */
UINT32 size; /* Size of the ROM image */
UINT8 features; /* on-cartridge special hardware */
UINT8 *cartSRAM; /* on-cartridge SRAM */
UINT8 sram_save; /* should be the contents of the on-cartridge SRAM be saved */
UINT8 *cartRAM; /* additional on-cartridge RAM (64KB for Ernie Els Golf) */
UINT32 ram_size; /* size of the on-cartridge RAM */
UINT8 ram_page; /* currently swapped in cartridge RAM */
} m_cartridge[MAX_CARTRIDGES];
};
/*----------- defined in machine/sms.c -----------*/
/* Function prototypes */
WRITE8_HANDLER( sms_cartram_w );
WRITE8_HANDLER( sms_cartram2_w );
WRITE8_HANDLER( sms_fm_detect_w );
READ8_HANDLER( sms_fm_detect_r );
READ8_HANDLER( sms_input_port_0_r );
READ8_HANDLER( sms_input_port_1_r );
WRITE8_HANDLER( sms_ym2413_register_port_0_w );
WRITE8_HANDLER( sms_ym2413_data_port_0_w );
WRITE8_HANDLER( sms_io_control_w );
READ8_HANDLER( sms_count_r );
WRITE8_HANDLER( sms_sscope_w );
READ8_HANDLER( sms_sscope_r );
WRITE8_HANDLER( sms_mapper_w );
READ8_HANDLER( sms_mapper_r );
WRITE8_HANDLER( sms_bios_w );
WRITE8_HANDLER( gg_sio_w );
READ8_HANDLER( gg_sio_r );
READ8_HANDLER( gg_input_port_2_r );
INPUT_CHANGED( lgun1_changed );
INPUT_CHANGED( lgun2_changed );
void sms_pause_callback( running_machine &machine );
void sms_store_int_callback( running_machine &machine, int state );
DEVICE_START( sms_cart );
DEVICE_IMAGE_LOAD( sms_cart );
MACHINE_START( sms );
MACHINE_RESET( sms );
READ8_HANDLER( sms_store_cart_select_r );
WRITE8_HANDLER( sms_store_cart_select_w );
READ8_HANDLER( sms_store_select1 );
READ8_HANDLER( sms_store_select2 );
READ8_HANDLER( sms_store_control_r );
WRITE8_HANDLER( sms_store_control_w );
#define IO_EXPANSION (0x80) /* Expansion slot enable (1= disabled, 0= enabled) */
#define IO_CARTRIDGE (0x40) /* Cartridge slot enable (1= disabled, 0= enabled) */
#define IO_CARD (0x20) /* Card slot disabled (1= disabled, 0= enabled) */
#define IO_WORK_RAM (0x10) /* Work RAM disabled (1= disabled, 0= enabled) */
#define IO_BIOS_ROM (0x08) /* BIOS ROM disabled (1= disabled, 0= enabled) */
#define IO_CHIP (0x04) /* I/O chip disabled (1= disabled, 0= enabled) */
DRIVER_INIT( sg1000m3 );
DRIVER_INIT( sms1 );
DRIVER_INIT( smsj );
DRIVER_INIT( sms2kr );
DRIVER_INIT( smssdisp );
DRIVER_INIT( gamegear );
DRIVER_INIT( gamegeaj );
VIDEO_START( sms1 );
VIDEO_START( gamegear );
SCREEN_UPDATE( sms1 );
SCREEN_UPDATE( sms );
SCREEN_UPDATE( gamegear );
#endif /* SMS_H_ */

102
src/mame/includes/sg1000.h Normal file
View File

@ -0,0 +1,102 @@
#ifndef __SG1000__
#define __SG1000__
#include "machine/ram.h"
#define SCREEN_TAG "screen"
#define Z80_TAG "z80"
#define SN76489A_TAG "sn76489a"
#define UPD765_TAG "upd765"
#define CASSETTE_TAG "cassette"
#define UPD8251_TAG "upd8251"
#define UPD9255_TAG "upd9255"
#define UPD9255_0_TAG "upd9255_0"
#define UPD9255_1_TAG "upd9255_1"
#define CENTRONICS_TAG "centronics"
#define IS_CARTRIDGE_TV_DRAW(ptr) \
(!strncmp("annakmn", (const char *)&ptr[0x13b3], 7))
#define IS_CARTRIDGE_THE_CASTLE(ptr) \
(!strncmp("ASCII 1986", (const char *)&ptr[0x1cc3], 10))
#define IS_CARTRIDGE_BASIC_LEVEL_III(ptr) \
(!strncmp("SC-3000 BASIC Level 3 ver 1.0", (const char *)&ptr[0x6a20], 29))
#define IS_CARTRIDGE_MUSIC_EDITOR(ptr) \
(!strncmp("PIANO", (const char *)&ptr[0x0841], 5))
class sg1000_state : public driver_device
{
public:
sg1000_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag),
m_maincpu(*this, Z80_TAG),
m_ram(*this, RAM_TAG)
{ }
required_device<cpu_device> m_maincpu;
required_device<device_t> m_ram;
virtual void machine_start();
void install_cartridge(UINT8 *ptr, int size);
DECLARE_WRITE8_MEMBER( tvdraw_axis_w );
DECLARE_READ8_MEMBER( tvdraw_status_r );
DECLARE_READ8_MEMBER( tvdraw_data_r );
DECLARE_READ8_MEMBER( joysel_r );
/* keyboard state */
UINT8 m_keylatch;
/* TV Draw state */
UINT8 m_tvdraw_data;
};
class sc3000_state : public sg1000_state
{
public:
sc3000_state(const machine_config &mconfig, device_type type, const char *tag)
: sg1000_state(mconfig, type, tag),
m_cassette(*this, CASSETTE_TAG)
{ }
required_device<device_t> m_cassette;
virtual void machine_start();
void install_cartridge(UINT8 *ptr, int size);
DECLARE_READ8_MEMBER( ppi_pa_r );
DECLARE_READ8_MEMBER( ppi_pb_r );
DECLARE_WRITE8_MEMBER( ppi_pc_w );
};
class sf7000_state : public sc3000_state
{
public:
sf7000_state(const machine_config &mconfig, device_type type, const char *tag)
: sc3000_state(mconfig, type, tag),
m_fdc(*this, UPD765_TAG),
m_centronics(*this, CENTRONICS_TAG),
m_floppy0(*this, FLOPPY_0)
{ }
required_device<device_t> m_fdc;
required_device<device_t> m_centronics;
required_device<device_t> m_floppy0;
virtual void machine_start();
virtual void machine_reset();
DECLARE_READ8_MEMBER( ppi_pa_r );
DECLARE_WRITE8_MEMBER( ppi_pc_w );
DECLARE_WRITE_LINE_MEMBER( fdc_intrq_w );
/* floppy state */
int m_fdc_irq;
int m_fdc_index;
};
#endif

62
src/mame/layout/sms1.lay Normal file
View File

@ -0,0 +1,62 @@
<?xml version="1.0"?>
<mamelayout version="2">
<view name="Main Screen Standard (4:3)">
<screen index="0">
<bounds left="0" top="0" right="4" bottom="3" />
</screen>
</view>
<view name="SegaScope Left LCD Standard (4:3)">
<screen index="1">
<bounds left="0" top="0" right="4" bottom="3" />
</screen>
</view>
<view name="SegaScope Right LCD Standard (4:3)">
<screen index="2">
<bounds left="0" top="0" right="4" bottom="3" />
</screen>
</view>
<view name="Main Screen Pixel Aspect (~scr0nativexaspect~:~scr0nativeyaspect~)">
<screen index="0">
<bounds left="0" top="0" right="~scr0width~" bottom="~scr0height~" />
</screen>
</view>
<view name="SegaScope Left LCD Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
<screen index="1">
<bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
</screen>
</view>
<view name="SegaScope Right LCD Pixel Aspect (~scr1nativexaspect~:~scr1nativeyaspect~)">
<screen index="2">
<bounds left="0" top="0" right="~scr1width~" bottom="~scr1height~" />
</screen>
</view>
<view name="Main Screen">
<screen index="0">
<bounds x="0" y="0" width="4" height="3" />
</screen>
</view>
<view name="SegaScope 3-D Glasses">
<screen index="1">
<bounds x="0" y="0" width="4" height="3" />
</screen>
<screen index="2">
<bounds x="4.03" y="0" width="4" height="3" />
</screen>
</view>
<view name="SegaScope 3-D Glasses (Gapless)">
<screen index="1">
<bounds x="0" y="0" width="4" height="3" />
</screen>
<screen index="2">
<bounds x="4" y="0" width="4" height="3" />
</screen>
</view>
</mamelayout>

391
src/mame/machine/ctronics.c Normal file
View File

@ -0,0 +1,391 @@
/***************************************************************************
Centronics printer interface
***************************************************************************/
#include "emu.h"
#include "ctronics.h"
#include "imagedev/printer.h"
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
static WRITE_LINE_DEVICE_HANDLER( centronics_printer_online );
static TIMER_CALLBACK( ack_callback );
static TIMER_CALLBACK( busy_callback );
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _centronics_state centronics_state;
struct _centronics_state
{
device_t *printer;
devcb_resolved_write_line out_ack_func;
devcb_resolved_write_line out_busy_func;
devcb_resolved_write_line out_not_busy_func;
int strobe;
int busy;
int ack;
int auto_fd;
int pe;
int fault;
UINT8 data;
};
/*****************************************************************************
INLINE FUNCTIONS
*****************************************************************************/
INLINE centronics_state *get_safe_token(device_t *device)
{
assert(device != NULL);
assert(device->type() == CENTRONICS);
return (centronics_state *)downcast<legacy_device_base *>(device)->token();
}
/*****************************************************************************
GLOBAL VARIABLES
*****************************************************************************/
const centronics_interface standard_centronics =
{
FALSE,
DEVCB_NULL,
DEVCB_NULL,
DEVCB_NULL
};
/*****************************************************************************
PRINTER INTERFACE
*****************************************************************************/
static MACHINE_CONFIG_FRAGMENT( centronics )
MCFG_PRINTER_ADD("printer")
MCFG_PRINTER_ONLINE(centronics_printer_online)
MACHINE_CONFIG_END
/*****************************************************************************
DEVICE INTERFACE
*****************************************************************************/
static DEVICE_START( centronics )
{
centronics_state *centronics = get_safe_token(device);
const centronics_interface *intf = (const centronics_interface *)device->static_config();
/* validate some basic stuff */
assert(device->static_config() != NULL);
/* set some initial values */
centronics->pe = FALSE;
centronics->fault = FALSE;
centronics->busy = TRUE;
centronics->strobe = TRUE;
/* get printer device */
centronics->printer = device->subdevice("printer");
/* resolve callbacks */
centronics->out_ack_func.resolve(intf->out_ack_func, *device);
centronics->out_busy_func.resolve(intf->out_busy_func, *device);
centronics->out_not_busy_func.resolve(intf->out_not_busy_func, *device);
/* register for state saving */
device->save_item(NAME(centronics->auto_fd));
device->save_item(NAME(centronics->strobe));
device->save_item(NAME(centronics->busy));
device->save_item(NAME(centronics->ack));
device->save_item(NAME(centronics->data));
}
static DEVICE_RESET( centronics )
{
}
DEVICE_GET_INFO( centronics )
{
switch (state)
{
/* --- the following bits of info are returned as 64-bit signed integers --- */
case DEVINFO_INT_TOKEN_BYTES: info->i = sizeof(centronics_state); break;
case DEVINFO_INT_INLINE_CONFIG_BYTES: info->i = 0; break;
/* --- the following bits of info are returned as pointers --- */
case DEVINFO_PTR_MACHINE_CONFIG: info->machine_config = MACHINE_CONFIG_NAME(centronics); break;
/* --- the following bits of info are returned as pointers to data or functions --- */
case DEVINFO_FCT_START: info->start = DEVICE_START_NAME(centronics); break;
case DEVINFO_FCT_STOP: /* Nothing */ break;
case DEVINFO_FCT_RESET: info->reset = DEVICE_RESET_NAME(centronics); break;
/* --- the following bits of info are returned as NULL-terminated strings --- */
case DEVINFO_STR_NAME: strcpy(info->s, "Centronics"); break;
case DEVINFO_STR_FAMILY: strcpy(info->s, "Centronics"); break;
case DEVINFO_STR_VERSION: strcpy(info->s, "1.0"); break;
case DEVINFO_STR_SOURCE_FILE: strcpy(info->s, __FILE__); break;
case DEVINFO_STR_CREDITS: strcpy(info->s, "Copyright MESS Team"); break;
}
}
/***************************************************************************
IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
centronics_printer_online - callback that
sets us busy when the printer goes offline
-------------------------------------------------*/
void centronics_printer_online(device_t *device, int state)
{
centronics_state *centronics = get_safe_token(device->owner());
/* when going online, set PE and FAULT high and BUSY low */
centronics->pe = state;
centronics->fault = state;
centronics->busy = !state;
}
static TIMER_CALLBACK( ack_callback )
{
centronics_state *centronics = (centronics_state *)ptr;
/* signal change */
centronics->out_ack_func(param);
centronics->ack = param;
if (param == FALSE)
{
/* data is now ready, output it */
printer_output(centronics->printer, centronics->data);
/* ready to receive more data, return BUSY to low */
machine.scheduler().timer_set(attotime::from_usec(7), FUNC(busy_callback), FALSE, ptr);
}
}
static TIMER_CALLBACK( busy_callback )
{
centronics_state *centronics = (centronics_state *)ptr;
/* signal change */
centronics->out_busy_func(param);
centronics->out_not_busy_func(!param);
centronics->busy = param;
if (param == TRUE)
{
/* timer to turn ACK low to receive data */
machine.scheduler().timer_set(attotime::from_usec(10), FUNC(ack_callback), FALSE, ptr);
}
else
{
/* timer to return ACK to high state */
machine.scheduler().timer_set(attotime::from_usec(5), FUNC(ack_callback), TRUE, ptr);
}
}
/*-------------------------------------------------
centronics_data_w - write print data
-------------------------------------------------*/
WRITE8_DEVICE_HANDLER( centronics_data_w )
{
centronics_state *centronics = get_safe_token(device);
centronics->data = data;
}
/*-------------------------------------------------
centronics_data_r - return current data
-------------------------------------------------*/
READ8_DEVICE_HANDLER( centronics_data_r )
{
centronics_state *centronics = get_safe_token(device);
return centronics->data;
}
/*-------------------------------------------------
set_line - helper to set individual bits
-------------------------------------------------*/
static void set_line(device_t *device, int line, int state)
{
centronics_state *centronics = get_safe_token(device);
if (state)
centronics->data |= 1 << line;
else
centronics->data &= ~(1 << line);
}
/*-------------------------------------------------
centronics_dx_w - write line dx print data
-------------------------------------------------*/
WRITE_LINE_DEVICE_HANDLER( centronics_d0_w ) { set_line(device, 0, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d1_w ) { set_line(device, 1, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d2_w ) { set_line(device, 2, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d3_w ) { set_line(device, 3, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d4_w ) { set_line(device, 4, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d5_w ) { set_line(device, 5, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d6_w ) { set_line(device, 6, state); }
WRITE_LINE_DEVICE_HANDLER( centronics_d7_w ) { set_line(device, 7, state); }
/*-------------------------------------------------
centronics_strobe_w - signal that data is
ready
-------------------------------------------------*/
WRITE_LINE_DEVICE_HANDLER( centronics_strobe_w )
{
centronics_state *centronics = get_safe_token(device);
/* look for a high -> low transition */
if (centronics->strobe == TRUE && state == FALSE && centronics->busy == FALSE)
{
/* STROBE has gone low, data is ready */
device->machine().scheduler().timer_set(attotime::zero, FUNC(busy_callback), TRUE, centronics);
}
centronics->strobe = state;
}
/*-------------------------------------------------
centronics_prime_w - initialize and reset
printer (centronics mode)
-------------------------------------------------*/
WRITE_LINE_DEVICE_HANDLER( centronics_prime_w )
{
assert(((const centronics_interface *)device->static_config())->is_ibmpc == FALSE);
/* reset printer if line is low */
if (state == FALSE)
DEVICE_RESET_CALL( centronics );
}
/*-------------------------------------------------
centronics_init_w - initialize and reset
printer (ibm mode)
-------------------------------------------------*/
WRITE_LINE_DEVICE_HANDLER( centronics_init_w )
{
assert(((const centronics_interface *)device->static_config())->is_ibmpc == TRUE);
/* reset printer if line is low */
if (state == FALSE)
DEVICE_RESET_CALL( centronics );
}
/*-------------------------------------------------
centronics_autofeed_w - auto line feed
-------------------------------------------------*/
WRITE_LINE_DEVICE_HANDLER( centronics_autofeed_w )
{
centronics_state *centronics = get_safe_token(device);
assert(((const centronics_interface *)device->static_config())->is_ibmpc == TRUE);
centronics->auto_fd = state;
}
/*-------------------------------------------------
centronics_ack_r - return the state of the
ack line
-------------------------------------------------*/
READ_LINE_DEVICE_HANDLER( centronics_ack_r )
{
centronics_state *centronics = get_safe_token(device);
return centronics->ack;
}
/*-------------------------------------------------
centronics_busy_r - return the state of the
busy line
-------------------------------------------------*/
READ_LINE_DEVICE_HANDLER( centronics_busy_r )
{
centronics_state *centronics = get_safe_token(device);
return centronics->busy;
}
/*-------------------------------------------------
centronics_pe_r - return the state of the
pe line
-------------------------------------------------*/
READ_LINE_DEVICE_HANDLER( centronics_pe_r )
{
centronics_state *centronics = get_safe_token(device);
return centronics->pe;
}
/*-------------------------------------------------
centronics_not_busy_r - return the state of the
not busy line
-------------------------------------------------*/
READ_LINE_DEVICE_HANDLER( centronics_not_busy_r )
{
centronics_state *centronics = get_safe_token(device);
return !centronics->busy;
}
/*-------------------------------------------------
centronics_vcc_r - return the state of the
vcc line
-------------------------------------------------*/
READ_LINE_DEVICE_HANDLER( centronics_vcc_r )
{
/* always return high */
return TRUE;
}
/*-------------------------------------------------
centronics_fault_r - return the state of the
fault line
-------------------------------------------------*/
READ_LINE_DEVICE_HANDLER( centronics_fault_r )
{
centronics_state *centronics = get_safe_token(device);
return centronics->fault;
}
DEFINE_LEGACY_DEVICE(CENTRONICS, centronics);

View File

@ -0,0 +1,75 @@
/***************************************************************************
Centronics printer interface
***************************************************************************/
#ifndef __CTRONICS_H__
#define __CTRONICS_H__
#include "devcb.h"
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef struct _centronics_interface centronics_interface;
struct _centronics_interface
{
int is_ibmpc;
devcb_write_line out_ack_func;
devcb_write_line out_busy_func;
devcb_write_line out_not_busy_func;
};
/***************************************************************************
FUNCTION PROTOTYPES
***************************************************************************/
WRITE8_DEVICE_HANDLER( centronics_data_w );
READ8_DEVICE_HANDLER( centronics_data_r );
/* access to the individual bits */
WRITE_LINE_DEVICE_HANDLER( centronics_d0_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d1_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d2_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d3_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d4_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d5_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d6_w );
WRITE_LINE_DEVICE_HANDLER( centronics_d7_w );
WRITE_LINE_DEVICE_HANDLER( centronics_strobe_w );
WRITE_LINE_DEVICE_HANDLER( centronics_prime_w );
WRITE_LINE_DEVICE_HANDLER( centronics_init_w );
WRITE_LINE_DEVICE_HANDLER( centronics_autofeed_w );
READ_LINE_DEVICE_HANDLER( centronics_ack_r );
READ_LINE_DEVICE_HANDLER( centronics_busy_r );
READ_LINE_DEVICE_HANDLER( centronics_pe_r );
READ_LINE_DEVICE_HANDLER( centronics_not_busy_r );
READ_LINE_DEVICE_HANDLER( centronics_vcc_r );
READ_LINE_DEVICE_HANDLER( centronics_fault_r );
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
DECLARE_LEGACY_DEVICE(CENTRONICS, centronics);
#define MCFG_CENTRONICS_ADD(_tag, _intf) \
MCFG_DEVICE_ADD(_tag, CENTRONICS, 0) \
MCFG_DEVICE_CONFIG(_intf)
/***************************************************************************
DEFAULT INTERFACES
***************************************************************************/
extern const centronics_interface standard_centronics;
#endif /* __CTRONICS_H__ */

725
src/mame/machine/dccons.c Normal file
View File

@ -0,0 +1,725 @@
/*
dc.c - Sega Dreamcast hardware
MESS (DC home console) hardware overrides (GD-ROM drive etc)
c230048 - 5 is written, want 6
c0d9d9e - where bad happens, from routine @ c0da260
c0d9d8e - R0 on return is the value to put in
cfffee0 - stack location when bad happens
*/
#include "emu.h"
#include "cdrom.h"
#include "debugger.h"
#include "includes/dc.h"
#include "cpu/sh4/sh4.h"
#include "sound/aica.h"
#include "includes/naomi.h"
#include "machine/gdrom.h"
#include "imagedev/chd_cd.h"
#define ATAPI_CYCLES_PER_SECTOR (5000) // TBD for Dreamcast
#define ATAPI_STAT_BSY 0x80
#define ATAPI_STAT_DRDY 0x40
#define ATAPI_STAT_DMARDDF 0x20
#define ATAPI_STAT_SERVDSC 0x10
#define ATAPI_STAT_DRQ 0x08
#define ATAPI_STAT_CORR 0x04
#define ATAPI_STAT_CHECK 0x01
#define ATAPI_INTREASON_COMMAND 0x01
#define ATAPI_INTREASON_IO 0x02
#define ATAPI_INTREASON_RELEASE 0x04
#define ATAPI_REG_DATA 0
#define ATAPI_REG_FEATURES 1
#define ATAPI_REG_INTREASON 2
#define ATAPI_REG_SAMTAG 3
#define ATAPI_REG_COUNTLOW 4
#define ATAPI_REG_COUNTHIGH 5
#define ATAPI_REG_DRIVESEL 6
#define ATAPI_REG_CMDSTATUS 7
#define ATAPI_REG_ERROR 16 // read-only ERROR (write is FEATURES)
#define ATAPI_REG_MAX 24
#define ATAPI_XFER_PIO 0x00
#define ATAPI_XFER_PIO_FLOW 0x08
#define ATAPI_XFER_MULTI_DMA 0x20
#define ATAPI_XFER_ULTRA_DMA 0x40
#define ATAPI_DATA_SIZE ( 64 * 1024 )
static UINT8 *atapi_regs;
static emu_timer *atapi_timer;
static SCSIInstance *gdrom_device;
static UINT8 *atapi_data;
static int atapi_data_ptr, atapi_data_len, atapi_xferlen, atapi_xferbase, atapi_cdata_wait, atapi_xfermod;
static UINT32 gdrom_alt_status;
static UINT8 xfer_mode = ATAPI_XFER_PIO;
#define MAX_TRANSFER_SIZE ( 63488 )
extern UINT32 dc_sysctrl_regs[0x200/4];
extern UINT32 g1bus_regs[0x100/4];
static void gdrom_raise_irq(running_machine &machine)
{
dc_sysctrl_regs[SB_ISTEXT] |= IST_EXT_GDROM;
dc_update_interrupt_status(machine);
}
static TIMER_CALLBACK( atapi_xfer_end )
{
UINT8 sector_buffer[ 4096 ];
atapi_timer->adjust(attotime::never);
printf("atapi_xfer_end atapi_xferlen = %d, atapi_xfermod=%d\n", atapi_xfermod, atapi_xferlen );
mame_printf_debug("ATAPI: xfer_end. xferlen = %d, atapi_xfermod = %d\n", atapi_xferlen, atapi_xfermod);
while (atapi_xferlen > 0 )
{
struct sh4_ddt_dma ddtdata;
// get a sector from the SCSI device
SCSIReadData( gdrom_device, sector_buffer, 2048 );
atapi_xferlen -= 2048;
// perform the DMA
ddtdata.destination = atapi_xferbase; // destination address
ddtdata.length = 2048/4;
ddtdata.size = 4;
ddtdata.buffer = sector_buffer;
ddtdata.direction=1; // 0 source to buffer, 1 buffer to destination
ddtdata.channel= -1; // not used
ddtdata.mode= -1; // copy from/to buffer
printf("ATAPI: DMA one sector to %x, %x remaining\n", atapi_xferbase, atapi_xferlen);
sh4_dma_ddt(machine.device("maincpu"), &ddtdata);
atapi_xferbase += 2048;
}
if (atapi_xfermod > MAX_TRANSFER_SIZE)
{
atapi_xferlen = MAX_TRANSFER_SIZE;
atapi_xfermod = atapi_xfermod - MAX_TRANSFER_SIZE;
}
else
{
atapi_xferlen = atapi_xfermod;
atapi_xfermod = 0;
}
if (atapi_xferlen > 0)
{
printf("ATAPI: starting next piece of multi-part transfer\n");
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
atapi_timer->adjust(machine.device<cpu_device>("maincpu")->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048))));
}
else
{
printf("ATAPI: Transfer completed, dropping DRQ\n");
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRDY;
gdrom_alt_status = ATAPI_STAT_DRDY;
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO | ATAPI_INTREASON_COMMAND;
g1bus_regs[SB_GDST]=0;
dc_sysctrl_regs[SB_ISTNRM] |= IST_DMA_GDROM;
dc_update_interrupt_status(machine);
}
gdrom_raise_irq(machine);
printf( "atapi_xfer_end: %d %d\n", atapi_xferlen, atapi_xfermod );
}
static READ32_HANDLER( atapi_r )
{
running_machine &machine = space->machine();
int reg, data;
if (mem_mask == 0x0000ffff) // word-wide command read
{
// mame_printf_debug("ATAPI: packet read = %04x\n", atapi_data[atapi_data_ptr]);
// assert IRQ and drop DRQ
if (atapi_data_ptr == 0 && atapi_data_len == 0)
{
// get the data from the device
if( atapi_xferlen > 0 )
{
SCSIReadData( gdrom_device, atapi_data, atapi_xferlen );
atapi_data_len = atapi_xferlen;
}
if (atapi_xfermod > MAX_TRANSFER_SIZE)
{
atapi_xferlen = MAX_TRANSFER_SIZE;
atapi_xfermod = atapi_xfermod - MAX_TRANSFER_SIZE;
}
else
{
atapi_xferlen = atapi_xfermod;
atapi_xfermod = 0;
}
// printf( "atapi_r: atapi_xferlen=%d\n", atapi_xferlen );
if( atapi_xferlen != 0 )
{
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_SERVDSC;
gdrom_alt_status = ATAPI_STAT_DRQ | ATAPI_STAT_SERVDSC;
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
}
else
{
//mame_printf_debug("ATAPI: dropping DRQ\n");
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
gdrom_alt_status = 0;
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
}
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
gdrom_raise_irq(machine);
}
if( atapi_data_ptr < atapi_data_len )
{
data = atapi_data[atapi_data_ptr++];
data |= ( atapi_data[atapi_data_ptr++] << 8 );
if( atapi_data_ptr >= atapi_data_len )
{
// printf( "atapi_r: read all bytes\n" );
atapi_data_ptr = 0;
atapi_data_len = 0;
if( atapi_xferlen == 0 )
{
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
gdrom_alt_status = 0;
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
gdrom_raise_irq(machine);
}
}
}
else
{
data = 0;
}
}
else
{
reg = offset;
// get read-only side of read-only/write-only registers from elsewhere
if (reg == ATAPI_REG_FEATURES)
{
reg = ATAPI_REG_ERROR;
}
data = atapi_regs[reg];
#if 0
switch( reg )
{
case ATAPI_REG_DATA:
printf( "atapi_r: data=%02x\n", data );
break;
case ATAPI_REG_ERROR:
printf( "atapi_r: error=%02x\n", data );
break;
case ATAPI_REG_INTREASON:
printf( "atapi_r: intreason=%02x\n", data );
break;
case ATAPI_REG_SAMTAG:
printf( "atapi_r: samtag=%02x\n", data );
break;
case ATAPI_REG_COUNTLOW:
printf( "atapi_r: countlow=%02x\n", data );
break;
case ATAPI_REG_COUNTHIGH:
printf( "atapi_r: counthigh=%02x\n", data );
break;
case ATAPI_REG_DRIVESEL:
printf( "atapi_r: drivesel=%02x\n", data );
break;
case ATAPI_REG_CMDSTATUS:
printf( "atapi_r: cmdstatus=%02x\n", data );
break;
}
#endif
mame_printf_debug("ATAPI: read reg %d = %x (PC=%x)\n", reg, data, cpu_get_pc(&space->device()));
}
// printf( "atapi_r( %08x, %08x ) %08x\n", offset, mem_mask, data );
return data;
}
static WRITE32_HANDLER( atapi_w )
{
running_machine &machine = space->machine();
int reg;
// printf( "atapi_w( %08x, %08x, %08x )\n", offset, mem_mask, data );
if (mem_mask == 0x0000ffff) // word-wide command write
{
// printf("atapi_w: data=%04x\n", data );
// printf("ATAPI: packet write %04x\n", data);
atapi_data[atapi_data_ptr++] = data & 0xff;
atapi_data[atapi_data_ptr++] = data >> 8;
if (atapi_cdata_wait)
{
// printf("ATAPI: waiting, ptr %d wait %d\n", atapi_data_ptr, atapi_cdata_wait);
if (atapi_data_ptr == atapi_cdata_wait)
{
// send it to the device
SCSIWriteData( gdrom_device, atapi_data, atapi_cdata_wait );
// assert IRQ
gdrom_raise_irq(machine);
// not sure here, but clear DRQ at least?
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
}
}
else if ( atapi_data_ptr == 12 )
{
int phase;
// printf("atapi_w: command %02x\n", atapi_data[0]&0xff );
// reset data pointer for reading SCSI results
atapi_data_ptr = 0;
atapi_data_len = 0;
// send it to the SCSI device
SCSISetCommand( gdrom_device, atapi_data, 12 );
SCSIExecCommand( gdrom_device, &atapi_xferlen );
SCSIGetPhase( gdrom_device, &phase );
if (atapi_xferlen != -1)
{
printf("ATAPI: SCSI command %02x returned %d bytes from the device\n", atapi_data[0]&0xff, atapi_xferlen);
// store the returned command length in the ATAPI regs, splitting into
// multiple transfers if necessary
atapi_xfermod = 0;
if (atapi_xferlen > MAX_TRANSFER_SIZE)
{
atapi_xfermod = atapi_xferlen - MAX_TRANSFER_SIZE;
atapi_xferlen = MAX_TRANSFER_SIZE;
}
atapi_regs[ATAPI_REG_COUNTLOW] = atapi_xferlen & 0xff;
atapi_regs[ATAPI_REG_COUNTHIGH] = (atapi_xferlen>>8)&0xff;
gdrom_alt_status = 0; // (I guess?)
if (atapi_xferlen == 0)
{
// if no data to return, set the registers properly
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRDY;
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO|ATAPI_INTREASON_COMMAND;
}
else
{
// indicate data ready: set DRQ and DMA ready, and IO in INTREASON
if (atapi_regs[ATAPI_REG_FEATURES] & 0x01) // DMA feature
{
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_BSY | ATAPI_STAT_DRDY | ATAPI_STAT_SERVDSC;
}
else
{
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_SERVDSC | ATAPI_STAT_DRQ;
}
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_IO;
}
switch( phase )
{
case SCSI_PHASE_DATAOUT:
atapi_cdata_wait = atapi_xferlen;
break;
}
// perform special ATAPI processing of certain commands
switch (atapi_data[0]&0xff)
{
case 0x00: // BUS RESET / TEST UNIT READY
case 0xbb: // SET CDROM SPEED
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
break;
case 0x45: // PLAY
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_BSY;
atapi_timer->adjust( downcast<cpu_device *>(&space->device())->cycles_to_attotime(ATAPI_CYCLES_PER_SECTOR ) );
break;
}
// assert IRQ
gdrom_raise_irq(machine);
}
else
{
printf("ATAPI: SCSI device returned error!\n");
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ | ATAPI_STAT_CHECK;
atapi_regs[ATAPI_REG_ERROR] = 0x50; // sense key = ILLEGAL REQUEST
atapi_regs[ATAPI_REG_COUNTLOW] = 0;
atapi_regs[ATAPI_REG_COUNTHIGH] = 0;
}
}
}
else
{
reg = offset;
#if 0
switch( reg )
{
case ATAPI_REG_DATA:
printf( "atapi_w: data=%02x\n", data );
break;
case ATAPI_REG_FEATURES:
printf( "atapi_w: features=%02x\n", data );
break;
case ATAPI_REG_INTREASON:
printf( "atapi_w: intreason=%02x\n", data );
break;
case ATAPI_REG_SAMTAG:
printf( "atapi_w: samtag=%02x\n", data );
break;
case ATAPI_REG_COUNTLOW:
printf( "atapi_w: countlow=%02x\n", data );
break;
case ATAPI_REG_COUNTHIGH:
printf( "atapi_w: counthigh=%02x\n", data );
break;
case ATAPI_REG_DRIVESEL:
printf( "atapi_w: drivesel=%02x\n", data );
break;
case ATAPI_REG_CMDSTATUS:
printf( "atapi_w: cmdstatus=%02x\n", data );
break;
}
#endif
atapi_regs[reg] = data;
// mame_printf_debug("ATAPI: reg %d = %x (offset %x mask %x PC=%x)\n", reg, data, offset, mem_mask, cpu_get_pc(&space->device()));
if (reg == ATAPI_REG_CMDSTATUS)
{
printf("ATAPI command %x issued! (PC=%x)\n", data, cpu_get_pc(&space->device()));
switch (data)
{
case 0xa0: // PACKET
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ;
gdrom_alt_status = ATAPI_STAT_DRQ;
atapi_regs[ATAPI_REG_INTREASON] = ATAPI_INTREASON_COMMAND;
atapi_data_ptr = 0;
atapi_data_len = 0;
/* we have no data */
atapi_xferlen = 0;
atapi_xfermod = 0;
atapi_cdata_wait = 0;
break;
case 0xa1: // IDENTIFY PACKET DEVICE
atapi_regs[ATAPI_REG_CMDSTATUS] = ATAPI_STAT_DRQ;
gdrom_alt_status = ATAPI_STAT_DRQ;
atapi_data_ptr = 0;
atapi_data_len = 512;
/* we have no data */
atapi_xferlen = 0;
atapi_xfermod = 0;
memset( atapi_data, 0, atapi_data_len );
atapi_data[ 0 ^ 1 ] = 0x86; // ATAPI device, cmd set 6 compliant, DRQ within 3 ms of PACKET command
atapi_data[ 1 ^ 1 ] = 0x00;
memset( &atapi_data[ 46 ], ' ', 8 );
atapi_data[ 46 ^ 1 ] = 'S';
atapi_data[ 47 ^ 1 ] = 'E';
memset( &atapi_data[ 54 ], ' ', 40 );
atapi_data[ 54 ^ 1 ] = 'C';
atapi_data[ 55 ^ 1 ] = 'D';
atapi_data[ 56 ^ 1 ] = '-';
atapi_data[ 57 ^ 1 ] = 'R';
atapi_data[ 58 ^ 1 ] = 'O';
atapi_data[ 59 ^ 1 ] = 'M';
atapi_data[ 60 ^ 1 ] = ' ';
atapi_data[ 61 ^ 1 ] = 'D';
atapi_data[ 62 ^ 1 ] = 'R';
atapi_data[ 63 ^ 1 ] = 'I';
atapi_data[ 64 ^ 1 ] = 'V';
atapi_data[ 65 ^ 1 ] = 'E';
atapi_data[ 66 ^ 1 ] = ' ';
atapi_data[ 67 ^ 1 ] = ' ';
atapi_data[ 68 ^ 1 ] = ' ';
atapi_data[ 69 ^ 1 ] = ' ';
atapi_data[ 70 ^ 1 ] = '6';
atapi_data[ 71 ^ 1 ] = '.';
atapi_data[ 72 ^ 1 ] = '4';
atapi_data[ 73 ^ 1 ] = '2';
atapi_data[ 98 ^ 1 ] = 0x04; // IORDY may be disabled
atapi_data[ 99 ^ 1 ] = 0x00;
atapi_regs[ATAPI_REG_COUNTLOW] = 0;
atapi_regs[ATAPI_REG_COUNTHIGH] = 2;
gdrom_raise_irq(space->machine());
break;
case 0xef: // SET FEATURES
// set xfer mode?
if (atapi_regs[ATAPI_REG_FEATURES] == 0x03)
{
printf("Set transfer mode to %x\n", atapi_regs[ATAPI_REG_COUNTLOW] & 0xf8);
xfer_mode = atapi_regs[ATAPI_REG_COUNTLOW] & 0xf8;
}
else
{
printf("ATAPI: Unknown set features %x\n", atapi_regs[ATAPI_REG_FEATURES]);
}
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
gdrom_alt_status = 0; // is this correct?
atapi_data_ptr = 0;
atapi_data_len = 0;
gdrom_raise_irq(space->machine());
break;
default:
mame_printf_debug("ATAPI: Unknown IDE command %x\n", data);
break;
}
}
}
}
static void dreamcast_atapi_exit(running_machine& machine)
{
if (gdrom_device != NULL)
{
SCSIDeleteInstance( gdrom_device );
}
}
void dreamcast_atapi_init(running_machine &machine)
{
atapi_regs = auto_alloc_array(machine, UINT8, ATAPI_REG_MAX );
memset(atapi_regs, 0, sizeof(atapi_regs));
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
atapi_regs[ATAPI_REG_ERROR] = 1;
atapi_regs[ATAPI_REG_COUNTLOW] = 0x14;
atapi_regs[ATAPI_REG_COUNTHIGH] = 0xeb;
atapi_data_ptr = 0;
atapi_data_len = 0;
atapi_cdata_wait = 0;
atapi_timer = machine.scheduler().timer_alloc(FUNC(atapi_xfer_end));
atapi_timer->adjust(attotime::never);
gdrom_device = NULL;
machine.add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(FUNC(dreamcast_atapi_exit),&machine));
atapi_data = auto_alloc_array(machine, UINT8, ATAPI_DATA_SIZE );
state_save_register_global_pointer(machine, atapi_regs, ATAPI_REG_MAX );
state_save_register_global_pointer(machine, atapi_data, ATAPI_DATA_SIZE / 2 );
state_save_register_global(machine, atapi_data_ptr );
state_save_register_global(machine, atapi_data_len );
state_save_register_global(machine, atapi_xferlen );
state_save_register_global(machine, atapi_xferbase );
state_save_register_global(machine, atapi_cdata_wait );
state_save_register_global(machine, atapi_xfermod );
}
void dreamcast_atapi_reset(running_machine &machine)
{
atapi_regs[ATAPI_REG_CMDSTATUS] = 0;
atapi_regs[ATAPI_REG_ERROR] = 1;
atapi_regs[ATAPI_REG_COUNTLOW] = 0x14;
atapi_regs[ATAPI_REG_COUNTHIGH] = 0xeb;
atapi_data_ptr = 0;
atapi_data_len = 0;
atapi_cdata_wait = 0;
atapi_xferlen = 0;
atapi_xfermod = 0;
if ( cd_get_cdrom_file(machine.device( "cdrom" )) != NULL )
{
SCSIAllocInstance( machine, &SCSIClassGDROM, &gdrom_device, "cdrom" );
}
else
{
gdrom_device = NULL;
}
}
/*
GDROM regsters:
5f7018: alternate status/device control
5f7080: data
5f7084: error/features
5f7088: interrupt reason/sector count
5f708c: sector number
5f7090: byte control low
5f7094: byte control high
5f7098: drive select
5f709c: status/command
c002910 - ATAPI packet writes
c002796 - aux status read after that
c000776 - DMA triggered to c008000
*/
READ64_HANDLER( dc_mess_gdrom_r )
{
UINT32 off;
if ((int)~mem_mask & 1)
{
off=(offset << 1) | 1;
}
else
{
off=offset << 1;
}
// printf("gdrom_r: @ %x (off %x), mask %llx (PC %x)\n", offset, off, mem_mask, cpu_get_pc(&space->device()));
if (offset == 3)
{
return gdrom_alt_status;
}
else if (off >= 0x20)
{
return atapi_r(space, off-0x20, 0xff);
}
return 0;
}
WRITE64_HANDLER( dc_mess_gdrom_w )
{
UINT32 dat,off;
if ((int)~mem_mask & 1)
{
dat=(UINT32)(data >> 32);
off=(offset << 1) | 1;
}
else
{
dat=(UINT32)data;
off=offset << 1;
}
// printf("GDROM: [%08x=%x]write %llx to %x, mask %llx (PC %x)\n", 0x5f7000+off*4, dat, data, offset, mem_mask, cpu_get_pc(&space->device()));
if (off >= 0x20)
{
atapi_w(space, off-0x20, dat, (UINT32)mem_mask);
}
}
// register decode helpers
// this accepts only 32-bit accesses
INLINE int decode_reg32_64(running_machine &machine, UINT32 offset, UINT64 mem_mask, UINT64 *shift)
{
int reg = offset * 2;
*shift = 0;
// non 32-bit accesses have not yet been seen here, we need to know when they are
if ((mem_mask != U64(0xffffffff00000000)) && (mem_mask != U64(0x00000000ffffffff)))
{
mame_printf_verbose("%s:Wrong mask!\n", machine.describe_context());
// debugger_break(machine);
}
if (mem_mask == U64(0xffffffff00000000))
{
reg++;
*shift = 32;
}
return reg;
}
READ64_HANDLER( dc_mess_g1_ctrl_r )
{
int reg;
UINT64 shift;
reg = decode_reg32_64(space->machine(), offset, mem_mask, &shift);
mame_printf_verbose("G1CTRL: Unmapped read %08x\n", 0x5f7400+reg*4);
return (UINT64)g1bus_regs[reg] << shift;
}
WRITE64_HANDLER( dc_mess_g1_ctrl_w )
{
int reg;
UINT64 shift;
UINT32 old,dat;
reg = decode_reg32_64(space->machine(), offset, mem_mask, &shift);
dat = (UINT32)(data >> shift);
old = g1bus_regs[reg];
g1bus_regs[reg] = dat; // 5f7400+reg*4=dat
mame_printf_verbose("G1CTRL: [%08x=%x] write %" I64FMT "x to %x, mask %" I64FMT "x\n", 0x5f7400+reg*4, dat, data, offset, mem_mask);
switch (reg)
{
case SB_GDST:
if (dat & 1 && g1bus_regs[SB_GDEN] == 1) // 0 -> 1
{
if (g1bus_regs[SB_GDDIR] == 0)
{
printf("G1CTRL: unsupported transfer\n");
return;
}
atapi_xferbase = g1bus_regs[SB_GDSTAR];
atapi_timer->adjust(space->machine().device<cpu_device>("maincpu")->cycles_to_attotime((ATAPI_CYCLES_PER_SECTOR * (atapi_xferlen/2048))));
}
break;
}
}

874
src/mame/machine/gdrom.c Normal file
View File

@ -0,0 +1,874 @@
/***************************************************************************
gdrom.c - Implementation of the Sega GD-ROM device
***************************************************************************/
#include "emu.h"
#include "machine/scsidev.h"
#include "cdrom.h"
#include "sound/cdda.h"
#include "imagedev/chd_cd.h"
#include "gdrom.h"
typedef struct
{
UINT32 lba;
UINT32 blocks;
UINT32 last_lba;
UINT32 bytes_per_sector;
UINT32 num_subblocks;
UINT32 cur_subblock;
UINT32 play_err_flag;
UINT32 read_type; // for command 0x30 only
UINT32 data_select; // for command 0x30 only
cdrom_file *cdrom;
bool is_file;
} SCSIGd;
static const UINT8 GDROM_Cmd11_Reply[32] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0xB4, 0x19, 0x00, 0x00, 0x08, 0x53, 0x45, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x52, 0x65, 0x76, 0x20, 0x36, 0x2E, 0x34, 0x32, 0x39, 0x39, 0x30, 0x33, 0x31, 0x36
};
static void phys_frame_to_msf(int phys_frame, int *m, int *s, int *f)
{
*m = phys_frame / (60*75);
phys_frame -= (*m * 60 * 75);
*s = phys_frame / 75;
*f = phys_frame % 75;
}
// scsicd_exec_command
//
// Execute a SCSI command.
static int scsicd_exec_command( SCSIInstance *scsiInstance, UINT8 *statusCode )
{
UINT8 *command;
int commandLength;
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
cdrom_file *cdrom = our_this->cdrom;
device_t *cdda;
int trk;
SCSIGetCommand( scsiInstance, &command, &commandLength );
switch ( command[0] )
{
case 0x03: // REQUEST SENSE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
case 0x11: // REQ_MODE
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
printf("REQ_MODE %02x %02x %02x %02x %02x %02x\n",
command[0], command[1],
command[2], command[3],
command[4], command[5]);
// if (SCSILengthFromUINT8( &command[ 4 ] ) < 32) return -1;
return 32; //SCSILengthFromUINT8( &command[ 4 ] );
case 0x12: // INQUIRY
logerror("GDROM: REQUEST SENSE\n");
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
case 0x15: // MODE SELECT(6)
logerror("GDROM: MODE SELECT(6) length %x control %x\n", command[4], command[5]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT8( &command[ 4 ] );
case 0x1a: // MODE SENSE(6)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT8( &command[ 4 ] );
case 0x1b: // START STOP UNIT
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
case 0x1e: // PREVENT ALLOW MEDIUM REMOVAL
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
case 0x25: // READ CAPACITY
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return 8;
case 0x28: // READ(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
logerror("GDROM: READ(10) at LBA %x for %d blocks (%d bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
if (our_this->num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
}
else
{
our_this->cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
case 0x30: // CD_READ
if (command[1] & 1)
{
fatalerror("GDROM: MSF mode used for CD_READ, unsupported");
return 0;
}
else
{
our_this->lba = (command[2]<<16 | command[3]<<8 | command[4]) - 150;
our_this->blocks = command[8]<<16 | command[9]<<8 | command[10];
our_this->read_type = (command[1] >> 1) & 7;
our_this->data_select = (command[1]>>4) & 0xf;
if (our_this->read_type != 2) // mode 1
{
fatalerror("GDROM: Unhandled read_type %d", our_this->read_type);
}
if (our_this->data_select != 2) // just sector data
{
fatalerror("GDROM: Unhandled data_select %d", our_this->data_select);
}
printf("GDROM: CD_READ at LBA %x for %d blocks (%d bytes, read type %d, data select %d)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector, our_this->read_type, our_this->data_select);
if (our_this->num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
}
else
{
our_this->cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
}
case 0x42: // READ SUB-CHANNEL
// logerror("GDROM: READ SUB-CHANNEL type %d\n", command[3]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT16( &command[ 7 ] );
case 0x43: // READ TOC
{
int start_trk = command[6];
int end_trk = cdrom_get_last_track(cdrom);
int length;
int allocation_length = SCSILengthFromUINT16( &command[ 7 ] );
if( start_trk == 0 )
{
start_trk = 1;
}
if( start_trk == 0xaa )
{
end_trk = start_trk;
}
length = 4 + ( 8 * ( ( end_trk - start_trk ) + 1 ) );
if( length > allocation_length )
{
length = allocation_length;
}
else if( length < 4 )
{
length = 4;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return length;
}
case 0x45: // PLAY AUDIO(10)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = SCSILengthFromUINT16( &command[7] );
// special cases: lba of 0 means MSF of 00:02:00
if (our_this->lba == 0)
{
our_this->lba = 150;
}
else if (our_this->lba == 0xffffffff)
{
logerror("GDROM: play audio from current not implemented!\n");
}
logerror("GDROM: PLAY AUDIO(10) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
trk = cdrom_get_track(cdrom, our_this->lba);
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
{
our_this->play_err_flag = 0;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
}
else
{
logerror("GDROM: track is NOT audio!\n");
our_this->play_err_flag = 1;
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
case 0x48: // PLAY AUDIO TRACK/INDEX
// be careful: tracks here are zero-based, but the SCSI command
// uses the real CD track number which is 1-based!
our_this->lba = cdrom_get_track_start(cdrom, command[4]-1);
our_this->blocks = cdrom_get_track_start(cdrom, command[7]-1) - our_this->lba;
if (command[4] > command[7])
{
our_this->blocks = 0;
}
if (command[4] == command[7])
{
our_this->blocks = cdrom_get_track_start(cdrom, command[4]) - our_this->lba;
}
if (our_this->blocks && cdrom)
{
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
}
logerror("GDROM: PLAY AUDIO T/I: strk %d idx %d etrk %d idx %d frames %d\n", command[4], command[5], command[7], command[8], our_this->blocks);
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
case 0x4b: // PAUSE/RESUME
if (cdrom)
{
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
cdda_pause_audio(cdda, (command[8] & 0x01) ^ 0x01);
}
logerror("GDROM: PAUSE/RESUME: %s\n", command[8]&1 ? "RESUME" : "PAUSE");
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
case 0x55: // MODE SELECT(10)
logerror("GDROM: MODE SELECT length %x control %x\n", command[7]<<8 | command[8], command[1]);
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAOUT );
return SCSILengthFromUINT16( &command[ 7 ] );
case 0x5a: // MODE SENSE(10)
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return SCSILengthFromUINT16( &command[ 7 ] );
case 0xa5: // PLAY AUDIO(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[6]<<24 | command[7]<<16 | command[8]<<8 | command[9];
// special cases: lba of 0 means MSF of 00:02:00
if (our_this->lba == 0)
{
our_this->lba = 150;
}
else if (our_this->lba == 0xffffffff)
{
logerror("GDROM: play audio from current not implemented!\n");
}
logerror("GDROM: PLAY AUDIO(12) at LBA %x for %x blocks\n", our_this->lba, our_this->blocks);
trk = cdrom_get_track(cdrom, our_this->lba);
if (cdrom_get_track_type(cdrom, trk) == CD_TRACK_AUDIO)
{
our_this->play_err_flag = 0;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
cdda_start_audio(cdda, our_this->lba, our_this->blocks);
}
else
{
logerror("GDROM: track is NOT audio!\n");
our_this->play_err_flag = 1;
}
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
case 0xa8: // READ(12)
our_this->lba = command[2]<<24 | command[3]<<16 | command[4]<<8 | command[5];
our_this->blocks = command[7]<<16 | command[8]<<8 | command[9];
logerror("GDROM: READ(12) at LBA %x for %x blocks (%x bytes)\n", our_this->lba, our_this->blocks, our_this->blocks * our_this->bytes_per_sector);
if (our_this->num_subblocks > 1)
{
our_this->cur_subblock = our_this->lba % our_this->num_subblocks;
our_this->lba /= our_this->num_subblocks;
}
else
{
our_this->cur_subblock = 0;
}
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL)
{
cdda_stop_audio(cdda);
}
SCSISetPhase( scsiInstance, SCSI_PHASE_DATAIN );
return our_this->blocks * our_this->bytes_per_sector;
case 0xbb: // SET CD SPEED
logerror("GDROM: SET CD SPEED to %d kbytes/sec.\n", command[2]<<8 | command[3]);
SCSISetPhase( scsiInstance, SCSI_PHASE_STATUS );
return 0;
default:
return SCSIBase( &SCSIClassGDROM, SCSIOP_EXEC_COMMAND, scsiInstance, 0, NULL );
}
}
// scsicd_read_data
//
// Read data from the device resulting from the execution of a command
static void scsicd_read_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
int i;
UINT32 last_phys_frame;
cdrom_file *cdrom = our_this->cdrom;
UINT32 temp;
UINT8 tmp_buffer[2048];
device_t *cdda;
SCSIGetCommand( scsiInstance, &command, &commandLength );
switch ( command[0] )
{
case 0x03: // REQUEST SENSE
logerror("GDROM: Reading REQUEST SENSE data\n");
memset( data, 0, dataLength );
data[0] = 0x71; // deferred error
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
if (cdda != NULL && cdda_audio_active(cdda))
{
data[12] = 0x00;
data[13] = 0x11; // AUDIO PLAY OPERATION IN PROGRESS
}
else if (our_this->play_err_flag)
{
our_this->play_err_flag = 0;
data[12] = 0x64; // ILLEGAL MODE FOR THIS TRACK
data[13] = 0x00;
}
// (else 00/00 means no error to report)
break;
case 0x11: // REQ_MODE
printf("REQ_MODE: dataLength %d\n", dataLength);
memcpy(data, &GDROM_Cmd11_Reply[0], (dataLength >= 32) ? 32 : dataLength);
break;
case 0x12: // INQUIRY
memset( data, 0, dataLength );
data[0] = 0x05; // device is present, device is CD/DVD (MMC-3)
data[1] = 0x80; // media is removable
data[2] = 0x05; // device complies with SPC-3 standard
data[3] = 0x02; // response data format = SPC-3 standard
// some Konami games freak out if this isn't "Sony", so we'll lie
// this is the actual drive on my Nagano '98 board
strcpy((char *)&data[8], "Sony");
strcpy((char *)&data[16], "CDU-76S");
strcpy((char *)&data[32], "1.0");
break;
case 0x25: // READ CAPACITY
logerror("GDROM: READ CAPACITY\n");
temp = cdrom_get_track_start(cdrom, 0xaa);
temp--; // return the last used block on the disc
data[0] = (temp>>24) & 0xff;
data[1] = (temp>>16) & 0xff;
data[2] = (temp>>8) & 0xff;
data[3] = (temp & 0xff);
data[4] = 0;
data[5] = 0;
data[6] = (our_this->bytes_per_sector>>8)&0xff;
data[7] = (our_this->bytes_per_sector & 0xff);
break;
case 0x28: // READ(10)
case 0xa8: // READ(12)
logerror("GDROM: read %x dataLength, \n", dataLength);
if ((our_this->cdrom) && (our_this->blocks))
{
while (dataLength > 0)
{
if (!cdrom_read_data(our_this->cdrom, our_this->lba, tmp_buffer, CD_TRACK_MODE1))
{
logerror("GDROM: CD read error!\n");
}
logerror("True LBA: %d, buffer half: %d\n", our_this->lba, our_this->cur_subblock * our_this->bytes_per_sector);
memcpy(data, &tmp_buffer[our_this->cur_subblock * our_this->bytes_per_sector], our_this->bytes_per_sector);
our_this->cur_subblock++;
if (our_this->cur_subblock >= our_this->num_subblocks)
{
our_this->cur_subblock = 0;
our_this->lba++;
our_this->blocks--;
}
our_this->last_lba = our_this->lba;
dataLength -= our_this->bytes_per_sector;
data += our_this->bytes_per_sector;
}
}
break;
case 0x30: // CD_READ
logerror("GDROM: read %x dataLength, \n", dataLength);
if ((our_this->cdrom) && (our_this->blocks))
{
while (dataLength > 0)
{
if (!cdrom_read_data(our_this->cdrom, our_this->lba, tmp_buffer, CD_TRACK_MODE1))
{
logerror("GDROM: CD read error!\n");
}
logerror("True LBA: %d, buffer half: %d\n", our_this->lba, our_this->cur_subblock * our_this->bytes_per_sector);
memcpy(data, &tmp_buffer[our_this->cur_subblock * our_this->bytes_per_sector], our_this->bytes_per_sector);
our_this->cur_subblock++;
if (our_this->cur_subblock >= our_this->num_subblocks)
{
our_this->cur_subblock = 0;
our_this->lba++;
our_this->blocks--;
}
our_this->last_lba = our_this->lba;
dataLength -= our_this->bytes_per_sector;
data += our_this->bytes_per_sector;
}
}
case 0x42: // READ SUB-CHANNEL
switch (command[3])
{
case 1: // return current position
{
int audio_active;
int msf;
if (!cdrom)
{
return;
}
logerror("GDROM: READ SUB-CHANNEL Time = %x, SUBQ = %x\n", command[1], command[2]);
msf = command[1] & 0x2;
cdda = cdda_from_cdrom(scsiInstance->machine(), cdrom);
audio_active = cdda != NULL && cdda_audio_active(cdda);
if (audio_active)
{
if (cdda_audio_paused(cdda))
{
data[1] = 0x12; // audio is paused
}
else
{
data[1] = 0x11; // audio in progress
}
}
else
{
if (cdda != NULL && cdda_audio_ended(cdda))
{
data[1] = 0x13; // ended successfully
}
else
{
// data[1] = 0x14; // stopped due to error
data[1] = 0x15; // No current audio status to return
}
}
// if audio is playing, get the latest LBA from the CDROM layer
if (audio_active)
{
our_this->last_lba = cdda_get_audio_lba(cdda);
}
else
{
our_this->last_lba = 0;
}
data[2] = 0;
data[3] = 12; // data length
data[4] = 0x01; // sub-channel format code
data[5] = 0x10 | (audio_active ? 0 : 4);
data[6] = cdrom_get_track(cdrom, our_this->last_lba) + 1; // track
data[7] = 0; // index
last_phys_frame = our_this->last_lba;
if (msf)
{
int m,s,f;
phys_frame_to_msf(last_phys_frame, &m, &s, &f);
data[8] = 0;
data[9] = m;
data[10] = s;
data[11] = f;
}
else
{
data[8] = last_phys_frame>>24;
data[9] = (last_phys_frame>>16)&0xff;
data[10] = (last_phys_frame>>8)&0xff;
data[11] = last_phys_frame&0xff;
}
last_phys_frame -= cdrom_get_track_start(cdrom, data[6] - 1);
if (msf)
{
int m,s,f;
phys_frame_to_msf(last_phys_frame, &m, &s, &f);
data[12] = 0;
data[13] = m;
data[14] = s;
data[15] = f;
}
else
{
data[12] = last_phys_frame>>24;
data[13] = (last_phys_frame>>16)&0xff;
data[14] = (last_phys_frame>>8)&0xff;
data[15] = last_phys_frame&0xff;
}
break;
}
default:
logerror("GDROM: Unknown subchannel type %d requested\n", command[3]);
}
break;
case 0x43: // READ TOC
/*
Track numbers are problematic here: 0 = lead-in, 0xaa = lead-out.
That makes sense in terms of how real-world CDs are referred to, but
our internal routines for tracks use "0" as track 1. That probably
should be fixed...
*/
logerror("GDROM: READ TOC, format = %d time=%d\n", command[2]&0xf,(command[1]>>1)&1);
switch (command[2] & 0x0f)
{
case 0: // normal
{
int start_trk;
int end_trk;
int len;
int in_len;
int dptr;
UINT32 tstart;
start_trk = command[6];
if( start_trk == 0 )
{
start_trk = 1;
}
end_trk = cdrom_get_last_track(cdrom);
len = (end_trk * 8) + 2;
// the returned TOC DATA LENGTH must be the full amount,
// regardless of how much we're able to pass back due to in_len
dptr = 0;
data[dptr++] = (len>>8) & 0xff;
data[dptr++] = (len & 0xff);
data[dptr++] = 1;
data[dptr++] = end_trk;
if( start_trk == 0xaa )
{
end_trk = 0xaa;
}
in_len = command[7]<<8 | command[8];
for (i = start_trk; i <= end_trk; i++)
{
int cdrom_track = i;
if( cdrom_track != 0xaa )
{
cdrom_track--;
}
if( dptr >= in_len )
{
break;
}
data[dptr++] = 0;
data[dptr++] = cdrom_get_adr_control(cdrom, cdrom_track);
data[dptr++] = i;
data[dptr++] = 0;
tstart = cdrom_get_track_start(cdrom, cdrom_track);
if ((command[1]&2)>>1)
tstart = lba_to_msf(tstart);
data[dptr++] = (tstart>>24) & 0xff;
data[dptr++] = (tstart>>16) & 0xff;
data[dptr++] = (tstart>>8) & 0xff;
data[dptr++] = (tstart & 0xff);
}
}
break;
default:
logerror("GDROM: Unhandled READ TOC format %d\n", command[2]&0xf);
break;
}
break;
case 0x1a: // MODE SENSE(6)
case 0x5a: // MODE SENSE(10)
logerror("GDROM: MODE SENSE page code = %x, PC = %x\n", command[2] & 0x3f, (command[2]&0xc0)>>6);
switch (command[2] & 0x3f)
{
case 0xe: // CD Audio control page
data[0] = 0x8e; // page E, parameter is savable
data[1] = 0x0e; // page length
data[2] = 0x04; // IMMED = 1, SOTC = 0
data[3] = data[4] = data[5] = data[6] = data[7] = 0; // reserved
// connect each audio channel to 1 output port
data[8] = 1;
data[10] = 2;
data[12] = 4;
data[14] = 8;
// indicate max volume
data[9] = data[11] = data[13] = data[15] = 0xff;
break;
default:
logerror("GDROM: MODE SENSE unknown page %x\n", command[2] & 0x3f);
break;
}
break;
default:
SCSIBase( &SCSIClassGDROM, SCSIOP_READ_DATA, scsiInstance, dataLength, data );
break;
}
}
// scsicd_write_data
//
// Write data to the CD-ROM device as part of the execution of a command
static void scsicd_write_data( SCSIInstance *scsiInstance, UINT8 *data, int dataLength )
{
UINT8 *command;
int commandLength;
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
SCSIGetCommand( scsiInstance, &command, &commandLength );
switch (command[ 0 ])
{
case 0x15: // MODE SELECT(6)
case 0x55: // MODE SELECT(10)
logerror("GDROM: MODE SELECT page %x\n", data[0] & 0x3f);
switch (data[0] & 0x3f)
{
case 0x0: // vendor-specific
// check for SGI extension to force 512-byte blocks
if ((data[3] == 8) && (data[10] == 2))
{
logerror("GDROM: Experimental SGI 512-byte block extension enabled\n");
our_this->bytes_per_sector = 512;
our_this->num_subblocks = 4;
}
else
{
logerror("GDROM: Unknown vendor-specific page!\n");
}
break;
case 0xe: // audio page
logerror("Ch 0 route: %x vol: %x\n", data[8], data[9]);
logerror("Ch 1 route: %x vol: %x\n", data[10], data[11]);
logerror("Ch 2 route: %x vol: %x\n", data[12], data[13]);
logerror("Ch 3 route: %x vol: %x\n", data[14], data[15]);
break;
}
break;
default:
SCSIBase( &SCSIClassGDROM, SCSIOP_WRITE_DATA, scsiInstance, dataLength, data );
break;
}
}
static void scsicd_alloc_instance( SCSIInstance *scsiInstance, const char *diskregion )
{
running_machine &machine = scsiInstance->machine();
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
our_this->lba = 0;
our_this->blocks = 0;
our_this->last_lba = 0;
our_this->bytes_per_sector = 2048;
our_this->num_subblocks = 1;
our_this->cur_subblock = 0;
our_this->play_err_flag = 0;
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->lba );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->blocks );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->last_lba );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->bytes_per_sector );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->num_subblocks );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->cur_subblock );
state_save_register_item( machine, "scsicd", diskregion, 0, our_this->play_err_flag );
if (machine.device( diskregion )) {
our_this->is_file = TRUE;
our_this->cdrom = cd_get_cdrom_file( machine.device( diskregion ) );
} else {
our_this->is_file = FALSE;
our_this->cdrom = cdrom_open(get_disk_handle( machine, diskregion ));
}
if (!our_this->cdrom)
{
logerror("GDROM: no CD found!\n");
}
}
static void scsicd_delete_instance( SCSIInstance *scsiInstance )
{
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
if (!our_this->is_file) {
if( our_this->cdrom )
{
cdrom_close( our_this->cdrom );
}
}
}
static void scsicd_get_device( SCSIInstance *scsiInstance, cdrom_file **cdrom )
{
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
*cdrom = our_this->cdrom;
}
static void scsicd_set_device( SCSIInstance *scsiInstance, cdrom_file *cdrom )
{
SCSIGd *our_this = (SCSIGd *)SCSIThis( &SCSIClassGDROM, scsiInstance );
our_this->cdrom = cdrom;
}
static int scsigd_dispatch(int operation, void *file, INT64 intparm, void *ptrparm)
{
SCSIAllocInstanceParams *params;
switch (operation)
{
case SCSIOP_EXEC_COMMAND:
return scsicd_exec_command( (SCSIInstance *)file, (UINT8 *)ptrparm );
case SCSIOP_READ_DATA:
scsicd_read_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_WRITE_DATA:
scsicd_write_data( (SCSIInstance *)file, (UINT8 *)ptrparm, intparm );
return 0;
case SCSIOP_ALLOC_INSTANCE:
params = (SCSIAllocInstanceParams *)ptrparm;
SCSIBase( &SCSIClassGDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
scsicd_alloc_instance( params->instance, params->diskregion );
return 0;
case SCSIOP_DELETE_INSTANCE:
scsicd_delete_instance( (SCSIInstance *)file );
break;
case SCSIOP_GET_DEVICE:
scsicd_get_device( (SCSIInstance *)file, (cdrom_file **)ptrparm );
return 0;
case SCSIOP_SET_DEVICE:
scsicd_set_device( (SCSIInstance *)file, (cdrom_file *)ptrparm );
return 0;
}
return SCSIBase( &SCSIClassGDROM, operation, (SCSIInstance *)file, intparm, (UINT8 *)ptrparm );
}
const SCSIClass SCSIClassGDROM =
{
&SCSIClassDevice,
scsigd_dispatch,
sizeof( SCSIGd )
};

17
src/mame/machine/gdrom.h Normal file
View File

@ -0,0 +1,17 @@
/***************************************************************************
gdrom.h
***************************************************************************/
#ifndef _GDROM_H_
#define _GDROM_H_
#include "machine/scsi.h"
// Sega GD-ROM handler
extern const SCSIClass SCSIClassGDROM;
#define SCSI_DEVICE_GDROM &SCSIClassGDROM
#endif

2053
src/mame/machine/segasms.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@ DRIVERS = $(MAMEOBJ)/drivers
LAYOUT = $(MAMEOBJ)/layout
MACHINE = $(MAMEOBJ)/machine
VIDEO = $(MAMEOBJ)/video
FORMATS = $(MAMEOBJ)/formats
OBJDIRS += \
$(AUDIO) \
@ -25,6 +26,7 @@ OBJDIRS += \
$(LAYOUT) \
$(MACHINE) \
$(VIDEO) \
$(FORMATS) \
@ -335,6 +337,7 @@ DRVLIBS += \
$(MAMEOBJ)/misc.a \
$(MAMEOBJ)/pinball.a \
$(MAMEOBJ)/shared.a \
$(MAMEOBJ)/formats.a \
@ -345,6 +348,7 @@ DRVLIBS += \
$(MAMEOBJ)/shared.a: \
$(MACHINE)/nmk112.o \
$(MACHINE)/ctronics.o \
$(MACHINE)/pckeybrd.o \
$(MACHINE)/pcshare.o \
$(MACHINE)/segacrpt.o \
@ -352,7 +356,12 @@ $(MAMEOBJ)/shared.a: \
$(MACHINE)/ticket.o \
$(VIDEO)/avgdvg.o \
#-------------------------------------------------
# file formats, mostly used for MESS software
#-------------------------------------------------
$(MAMEOBJ)/formats.a: \
$(FORMATS)/basicdsk.o \
#-------------------------------------------------
# manufacturer-specific groupings for drivers
@ -1219,6 +1228,13 @@ $(MAMEOBJ)/sega.a: \
$(VIDEO)/segaic16.o \
$(VIDEO)/sega16sp.o \
$(VIDEO)/segaic24.o \
$(VIDEO)/smsvdp.o \
$(MACHINE)/segasms.o \
$(DRIVERS)/segasms.o \
$(DRIVERS)/sg1000.o \
$(DRIVERS)/dc.o \
$(MACHINE)/dccons.o \
$(MACHINE)/gdrom.o \
$(MAMEOBJ)/seibu.a: \
$(DRIVERS)/bloodbro.o $(VIDEO)/bloodbro.o \
@ -1976,6 +1992,8 @@ $(DRIVERS)/segaorun.o: $(LAYOUT)/outrun.lh
$(DRIVERS)/segas32.o: $(LAYOUT)/radr.lh
$(DRIVERS)/segasms.o: $(LAYOUT)/sms1.lh
$(DRIVERS)/segaybd.o: $(LAYOUT)/pdrift.lh
$(DRIVERS)/snookr10.o: $(LAYOUT)/snookr10.lh

1530
src/mame/video/smsvdp.c Normal file

File diff suppressed because it is too large Load Diff

86
src/mame/video/smsvdp.h Normal file
View File

@ -0,0 +1,86 @@
/*************************************************************************
smsvdp.h
Implementation of Sega VDP chip used in Master System and Game Gear
**************************************************************************/
#ifndef __SMSVDP_H__
#define __SMSVDP_H__
#include "devcb.h"
/***************************************************************************
CONSTANTS
***************************************************************************/
#define MODEL_315_5124 0x0001
#define MODEL_315_5246 0x0002
#define MODEL_315_5378 0x0004
#define SMS_X_PIXELS 342 /* 342 pixels */
#define NTSC_Y_PIXELS 262 /* 262 lines */
#define PAL_Y_PIXELS 313 /* 313 lines */
#define LBORDER_START (1 + 2 + 14 + 8)
#define LBORDER_X_PIXELS (0x0d) /* 13 pixels */
#define RBORDER_X_PIXELS (0x0f) /* 15 pixels */
#define TBORDER_START (3 + 13)
#define NTSC_192_TBORDER_Y_PIXELS (0x1b) /* 27 lines */
#define NTSC_192_BBORDER_Y_PIXELS (0x18) /* 24 lines */
#define NTSC_224_TBORDER_Y_PIXELS (0x0b) /* 11 lines */
#define NTSC_224_BBORDER_Y_PIXELS (0x08) /* 8 lines */
#define PAL_192_TBORDER_Y_PIXELS (0x36) /* 54 lines */
#define PAL_192_BBORDER_Y_PIXELS (0x30) /* 48 lines */
#define PAL_224_TBORDER_Y_PIXELS (0x26) /* 38 lines */
#define PAL_224_BBORDER_Y_PIXELS (0x20) /* 32 lines */
#define PAL_240_TBORDER_Y_PIXELS (0x1e) /* 30 lines */
#define PAL_240_BBORDER_Y_PIXELS (0x18) /* 24 lines */
/***************************************************************************
TYPE DEFINITIONS
***************************************************************************/
typedef void (*smsvdp_int_cb)( running_machine &machine, int state );
typedef void (*smsvdp_pause_cb)( running_machine &machine );
typedef struct _smsvdp_interface smsvdp_interface;
struct _smsvdp_interface
{
UINT32 model; /* Select model/features for the emulation */
smsvdp_int_cb int_callback; /* Interrupt callback function */
smsvdp_pause_cb pause_callback; /* Pause callback function */
};
/***************************************************************************
DEVICE CONFIGURATION MACROS
***************************************************************************/
DECLARE_LEGACY_DEVICE(SMSVDP, smsvdp);
#define MCFG_SMSVDP_ADD(_tag, _interface) \
MCFG_DEVICE_ADD(_tag, SMSVDP, 0) \
MCFG_DEVICE_CONFIG(_interface)
/***************************************************************************
DEVICE I/O FUNCTIONS
***************************************************************************/
/* prototypes */
UINT32 sms_vdp_update( device_t *device, bitmap_t *bitmap, const rectangle *cliprect );
READ8_DEVICE_HANDLER( sms_vdp_vcount_r );
READ8_DEVICE_HANDLER( sms_vdp_hcount_latch_r );
WRITE8_DEVICE_HANDLER( sms_vdp_hcount_latch_w );
READ8_DEVICE_HANDLER( sms_vdp_data_r );
WRITE8_DEVICE_HANDLER( sms_vdp_data_w );
READ8_DEVICE_HANDLER( sms_vdp_ctrl_r );
WRITE8_DEVICE_HANDLER( sms_vdp_ctrl_w );
void sms_vdp_set_ggsmsmode( device_t *device, int mode );
int sms_vdp_check_brightness( device_t *device, int x, int y );
#endif /* __SMSVDP_H__ */