mirror of
https://github.com/holub/mame
synced 2025-07-05 01:48:29 +03:00
sorcerer: quickload changes
- merged snapshot and quickload; - fixed snapshot which had been broken by the memory system upgrade; - added interface to future software list.
This commit is contained in:
parent
6fb35fced8
commit
c54f6940d5
@ -173,19 +173,11 @@ Exidy Sorcerer Video/Disk Unit:
|
|||||||
void sorcerer_state::sorcerer_mem(address_map &map)
|
void sorcerer_state::sorcerer_mem(address_map &map)
|
||||||
{
|
{
|
||||||
map.unmap_value_high();
|
map.unmap_value_high();
|
||||||
map(0x0000, 0xbfff).ram();
|
map(0x0000, 0xffff).ram();
|
||||||
//map(0xc000, 0xdfff).rom(); // mapped by the cartslot
|
//map(0xc000, 0xdfff).rom(); // mapped by the cartslot
|
||||||
map(0xe000, 0xefff).rom().region("maincpu", 0).nopw(); // bios
|
map(0xe000, 0xefff).rom().region("maincpu", 0).nopw(); // bios
|
||||||
map(0xf000, 0xf7ff).ram(); // screen ram
|
|
||||||
map(0xf800, 0xfbff).rom().region("chargen", 0).nopw(); // inbuilt characters
|
map(0xf800, 0xfbff).rom().region("chargen", 0).nopw(); // inbuilt characters
|
||||||
map(0xfc00, 0xffff).ram().share("pcg"); // PCG
|
map(0xfc00, 0xffff).share("pcg"); // PCG
|
||||||
}
|
|
||||||
|
|
||||||
void sorcerer_state::sorcererb_mem(address_map &map)
|
|
||||||
{
|
|
||||||
map.unmap_value_high();
|
|
||||||
sorcerer_mem(map);
|
|
||||||
map(0xc000, 0xdfff).ram();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sorcererd_state::sorcererd_mem(address_map &map)
|
void sorcererd_state::sorcererd_mem(address_map &map)
|
||||||
@ -477,8 +469,9 @@ void sorcerer_state::sorcerer(machine_config &config)
|
|||||||
INPUT_BUFFER(config, "cent_status_in");
|
INPUT_BUFFER(config, "cent_status_in");
|
||||||
|
|
||||||
/* quickload */
|
/* quickload */
|
||||||
SNAPSHOT(config, "snapshot", "snp", attotime::from_seconds(4)).set_load_callback(FUNC(sorcerer_state::snapshot_cb));
|
quickload_image_device &quickload(QUICKLOAD(config, "quickload", "bin,snp", attotime::from_seconds(4)));
|
||||||
QUICKLOAD(config, "quickload", "bin", attotime::from_seconds(4)).set_load_callback(FUNC(sorcerer_state::quickload_cb));
|
quickload.set_load_callback(FUNC(sorcerer_state::quickload_cb));
|
||||||
|
quickload.set_interface("sorcerer_quik");
|
||||||
|
|
||||||
CASSETTE(config, m_cassette1);
|
CASSETTE(config, m_cassette1);
|
||||||
m_cassette1->set_formats(sorcerer_cassette_formats);
|
m_cassette1->set_formats(sorcerer_cassette_formats);
|
||||||
@ -498,6 +491,7 @@ void sorcerer_state::sorcerer(machine_config &config)
|
|||||||
/* software lists */
|
/* software lists */
|
||||||
SOFTWARE_LIST(config, "cart_list").set_original("sorcerer_cart");
|
SOFTWARE_LIST(config, "cart_list").set_original("sorcerer_cart");
|
||||||
SOFTWARE_LIST(config, "cass_list").set_original("sorcerer_cass");
|
SOFTWARE_LIST(config, "cass_list").set_original("sorcerer_cass");
|
||||||
|
SOFTWARE_LIST(config, "quik_list").set_original("sorcerer_quik");
|
||||||
|
|
||||||
// internal ram
|
// internal ram
|
||||||
RAM(config, RAM_TAG).set_default_size("48K").set_extra_options("8K,16K,32K");
|
RAM(config, RAM_TAG).set_default_size("48K").set_extra_options("8K,16K,32K");
|
||||||
@ -559,7 +553,6 @@ void sorcerer_state::sorcerera(machine_config &config)
|
|||||||
void sorcerer_state::sorcererb(machine_config &config)
|
void sorcerer_state::sorcererb(machine_config &config)
|
||||||
{
|
{
|
||||||
sorcerer(config);
|
sorcerer(config);
|
||||||
m_maincpu->set_addrmap(AS_PROGRAM, &sorcerer_state::sorcererb_mem);
|
|
||||||
m_maincpu->set_addrmap(AS_IO, &sorcerer_state::sorcererb_io);
|
m_maincpu->set_addrmap(AS_IO, &sorcerer_state::sorcererb_io);
|
||||||
|
|
||||||
Z80DMA(config, m_dma, ES_CPU_CLOCK);
|
Z80DMA(config, m_dma, ES_CPU_CLOCK);
|
||||||
|
@ -97,7 +97,6 @@ protected:
|
|||||||
void portff_w(u8 data);
|
void portff_w(u8 data);
|
||||||
TIMER_CALLBACK_MEMBER(cassette_tc);
|
TIMER_CALLBACK_MEMBER(cassette_tc);
|
||||||
TIMER_CALLBACK_MEMBER(serial_tc);
|
TIMER_CALLBACK_MEMBER(serial_tc);
|
||||||
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
|
|
||||||
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
|
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
|
||||||
void machine_start_common(offs_t endmem);
|
void machine_start_common(offs_t endmem);
|
||||||
void machine_reset_common();
|
void machine_reset_common();
|
||||||
|
@ -529,121 +529,137 @@ void sorcererd_state::machine_reset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
Snapshot Handling
|
|
||||||
******************************************************************************/
|
|
||||||
|
|
||||||
SNAPSHOT_LOAD_MEMBER(sorcerer_state::snapshot_cb)
|
|
||||||
{
|
|
||||||
u8 *RAM = memregion(m_maincpu->tag())->base();
|
|
||||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
|
||||||
u8 header[28];
|
|
||||||
unsigned char s_byte;
|
|
||||||
|
|
||||||
/* check size */
|
|
||||||
if (image.length() != 0x1001c)
|
|
||||||
{
|
|
||||||
image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Snapshot must be 65564 bytes");
|
|
||||||
image.message("Snapshot must be 65564 bytes");
|
|
||||||
return image_init_result::FAIL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the header */
|
|
||||||
image.fread( &header, sizeof(header));
|
|
||||||
|
|
||||||
/* write it to ram */
|
|
||||||
for (int i = 0; i < 0xc000; i++)
|
|
||||||
{
|
|
||||||
image.fread( &s_byte, 1);
|
|
||||||
space.write_byte(i, s_byte);
|
|
||||||
}
|
|
||||||
image.fread( RAM+0xc000, 0x4000);
|
|
||||||
|
|
||||||
/* patch CPU registers */
|
|
||||||
m_maincpu->set_state_int(Z80_I, header[0]);
|
|
||||||
m_maincpu->set_state_int(Z80_HL2, header[1] | (header[2] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_DE2, header[3] | (header[4] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_BC2, header[5] | (header[6] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_AF2, header[7] | (header[8] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_HL, header[9] | (header[10] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_DE, header[11] | (header[12] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_BC, header[13] | (header[14] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_IY, header[15] | (header[16] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_IX, header[17] | (header[18] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_IFF1, header[19]&2 ? 1 : 0);
|
|
||||||
m_maincpu->set_state_int(Z80_IFF2, header[19]&4 ? 1 : 0);
|
|
||||||
m_maincpu->set_state_int(Z80_R, header[20]);
|
|
||||||
m_maincpu->set_state_int(Z80_AF, header[21] | (header[22] << 8));
|
|
||||||
m_maincpu->set_state_int(STATE_GENSP, header[23] | (header[24] << 8));
|
|
||||||
m_maincpu->set_state_int(Z80_IM, header[25]);
|
|
||||||
m_maincpu->set_pc(header[26] | (header[27] << 8));
|
|
||||||
|
|
||||||
return image_init_result::PASS;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*-------------------------------------------------
|
/*-------------------------------------------------
|
||||||
QUICKLOAD_LOAD_MEMBER( sorcerer_state, sorcerer )
|
QUICKLOAD_LOAD_MEMBER( sorcerer_state, sorcerer )
|
||||||
|
Handles BIN and SNP extensions.
|
||||||
-------------------------------------------------*/
|
-------------------------------------------------*/
|
||||||
|
|
||||||
QUICKLOAD_LOAD_MEMBER(sorcerer_state::quickload_cb)
|
QUICKLOAD_LOAD_MEMBER(sorcerer_state::quickload_cb)
|
||||||
{
|
{
|
||||||
uint16_t execute_address, start_address, end_address;
|
// get autorun setting
|
||||||
int autorun;
|
bool autorun = BIT(m_iop_config->read(), 0);
|
||||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||||
|
|
||||||
/* load the binary into memory */
|
if (image.is_filetype("bin"))
|
||||||
if (z80bin_load_file(image, space, execute_address, start_address, end_address) != image_init_result::PASS)
|
|
||||||
return image_init_result::FAIL;
|
|
||||||
|
|
||||||
/* is this file executable? */
|
|
||||||
if (execute_address != 0xffff)
|
|
||||||
{
|
{
|
||||||
/* check to see if autorun is on */
|
u16 execute_address, start_address, end_address;
|
||||||
autorun = m_iop_config->read() & 1;
|
|
||||||
|
|
||||||
if ((execute_address >= 0xc000) && (execute_address <= 0xdfff) && (space.read_byte(0xdffa) != 0xc3))
|
// load the binary into memory
|
||||||
return image_init_result::FAIL; /* can't run a program if the cartridge isn't in */
|
if (z80bin_load_file(image, space, execute_address, start_address, end_address) != image_init_result::PASS)
|
||||||
|
return image_init_result::FAIL;
|
||||||
|
|
||||||
/* Since Exidy Basic is by Microsoft, it needs some preprocessing before it can be run.
|
// is this file executable?
|
||||||
1. A start address of 01D5 indicates a basic program which needs its pointers fixed up.
|
if (execute_address != 0xffff)
|
||||||
2. If autorunning, jump to C689 (command processor), else jump to C3DD (READY prompt).
|
|
||||||
Important addresses:
|
|
||||||
01D5 = start (load) address of a conventional basic program
|
|
||||||
C858 = an autorun basic program will have this exec address on the tape
|
|
||||||
C3DD = part of basic that displays READY and lets user enter input */
|
|
||||||
|
|
||||||
if (((start_address == 0x1d5) || (execute_address == 0xc858)) && (space.read_byte(0xdffa) == 0xc3))
|
|
||||||
{
|
{
|
||||||
static const u8 data[]={
|
|
||||||
0xcd, 0x26, 0xc4, // CALL C426 ;set up other pointers
|
|
||||||
0x21, 0xd4, 1, // LD HL,01D4 ;start of program address (used by C689)
|
|
||||||
0x36, 0, // LD (HL),00 ;make sure dummy end-of-line is there
|
|
||||||
0xc3, 0x89, 0xc6 // JP C689 ;run program
|
|
||||||
};
|
|
||||||
|
|
||||||
for (u8 i = 0; i < std::size(data); i++)
|
if ((execute_address >= 0xc000) && (execute_address <= 0xdfff) && (space.read_byte(0xdffa) != 0xc3))
|
||||||
space.write_byte(0xf01f + i, data[i]);
|
return image_init_result::FAIL; // can't run a program if the cartridge isn't in
|
||||||
|
|
||||||
if (!autorun)
|
/* Since Exidy Basic is by Microsoft, it needs some preprocessing before it can be run.
|
||||||
space.write_word(0xf028,0xc3dd);
|
1. A start address of 01D5 indicates a basic program which needs its pointers fixed up.
|
||||||
|
2. If autorunning, jump to C689 (command processor), else jump to C3DD (READY prompt).
|
||||||
|
Important addresses:
|
||||||
|
01D5 = start (load) address of a conventional basic program
|
||||||
|
C858 = an autorun basic program will have this exec address on the tape
|
||||||
|
C3DD = part of basic that displays READY and lets user enter input */
|
||||||
|
|
||||||
/* tell BASIC where program ends */
|
if (((start_address == 0x1d5) || (execute_address == 0xc858)) && (space.read_byte(0xdffa) == 0xc3))
|
||||||
space.write_byte(0x1b7, end_address & 0xff);
|
{
|
||||||
space.write_byte(0x1b8, (end_address >> 8) & 0xff);
|
static const u8 data[]={
|
||||||
|
0xcd, 0x26, 0xc4, // CALL C426 ;set up other pointers
|
||||||
|
0x21, 0xd4, 1, // LD HL,01D4 ;start of program address (used by C689)
|
||||||
|
0x36, 0, // LD (HL),00 ;make sure dummy end-of-line is there
|
||||||
|
0xc3, 0x89, 0xc6 // JP C689 ;run program
|
||||||
|
};
|
||||||
|
|
||||||
if ((execute_address != 0xc858) && autorun)
|
for (u8 i = 0; i < std::size(data); i++)
|
||||||
space.write_word(0xf028, execute_address);
|
space.write_byte(0xf01f + i, data[i]);
|
||||||
|
|
||||||
m_maincpu->set_pc(0xf01f);
|
if (!autorun)
|
||||||
|
space.write_word(0xf028,0xc3dd);
|
||||||
|
|
||||||
|
/* tell BASIC where program ends */
|
||||||
|
space.write_byte(0x1b7, end_address & 0xff);
|
||||||
|
space.write_byte(0x1b8, (end_address >> 8) & 0xff);
|
||||||
|
|
||||||
|
if ((execute_address != 0xc858) && autorun)
|
||||||
|
space.write_word(0xf028, execute_address);
|
||||||
|
|
||||||
|
m_maincpu->set_pc(0xf01f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (autorun)
|
||||||
|
m_maincpu->set_pc(execute_address);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// SNP extension
|
||||||
|
// check size
|
||||||
|
if (image.length() != 0x1001c)
|
||||||
{
|
{
|
||||||
if (autorun)
|
image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Snapshot must be 65564 bytes");
|
||||||
m_maincpu->set_pc(execute_address);
|
image.message("Snapshot must be 65564 bytes");
|
||||||
|
return image_init_result::FAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u8 header[28];
|
||||||
|
|
||||||
|
/* get the header */
|
||||||
|
image.fread( &header, sizeof(header));
|
||||||
|
|
||||||
|
// write it to ram, and skip roms
|
||||||
|
unsigned char s_byte;
|
||||||
|
for (int i = 0; i < 0xe000; i++)
|
||||||
|
{
|
||||||
|
image.fread( &s_byte, 1);
|
||||||
|
space.write_byte(i, s_byte); // ram
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0xe000; i < 0xf000; i++)
|
||||||
|
image.fread( &s_byte, 1);
|
||||||
|
|
||||||
|
for (int i = 0xf000; i < 0xf800; i++)
|
||||||
|
{
|
||||||
|
image.fread( &s_byte, 1);
|
||||||
|
space.write_byte(i, s_byte); // screen
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0xf800; i < 0xfc00; i++)
|
||||||
|
image.fread( &s_byte, 1);
|
||||||
|
|
||||||
|
for (int i = 0xfc00; i < 0x10000; i++)
|
||||||
|
{
|
||||||
|
image.fread( &s_byte, 1);
|
||||||
|
space.write_byte(i, s_byte); //pcg
|
||||||
|
}
|
||||||
|
|
||||||
|
// it's assumed if autorun was off that you wished to examine the image rather than to play it
|
||||||
|
if (autorun)
|
||||||
|
{
|
||||||
|
// patch CPU registers
|
||||||
|
m_maincpu->set_state_int(Z80_I, header[0]);
|
||||||
|
m_maincpu->set_state_int(Z80_HL2, header[1] | (header[2] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_DE2, header[3] | (header[4] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_BC2, header[5] | (header[6] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_AF2, header[7] | (header[8] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_HL, header[9] | (header[10] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_DE, header[11] | (header[12] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_BC, header[13] | (header[14] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_IY, header[15] | (header[16] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_IX, header[17] | (header[18] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_IFF1, header[19]&2 ? 1 : 0);
|
||||||
|
m_maincpu->set_state_int(Z80_IFF2, header[19]&4 ? 1 : 0);
|
||||||
|
m_maincpu->set_state_int(Z80_R, header[20]);
|
||||||
|
m_maincpu->set_state_int(Z80_AF, header[21] | (header[22] << 8));
|
||||||
|
m_maincpu->set_state_int(STATE_GENSP, header[23] | (header[24] << 8));
|
||||||
|
m_maincpu->set_state_int(Z80_IM, header[25]);
|
||||||
|
m_maincpu->set_pc(header[26] | (header[27] << 8));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return image_init_result::PASS;
|
return image_init_result::PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user