mirror of
https://github.com/holub/mame
synced 2025-04-22 00:11:58 +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)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
map(0x0000, 0xbfff).ram();
|
||||
map(0x0000, 0xffff).ram();
|
||||
//map(0xc000, 0xdfff).rom(); // mapped by the cartslot
|
||||
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(0xfc00, 0xffff).ram().share("pcg"); // PCG
|
||||
}
|
||||
|
||||
void sorcerer_state::sorcererb_mem(address_map &map)
|
||||
{
|
||||
map.unmap_value_high();
|
||||
sorcerer_mem(map);
|
||||
map(0xc000, 0xdfff).ram();
|
||||
map(0xfc00, 0xffff).share("pcg"); // PCG
|
||||
}
|
||||
|
||||
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");
|
||||
|
||||
/* quickload */
|
||||
SNAPSHOT(config, "snapshot", "snp", attotime::from_seconds(4)).set_load_callback(FUNC(sorcerer_state::snapshot_cb));
|
||||
QUICKLOAD(config, "quickload", "bin", attotime::from_seconds(4)).set_load_callback(FUNC(sorcerer_state::quickload_cb));
|
||||
quickload_image_device &quickload(QUICKLOAD(config, "quickload", "bin,snp", attotime::from_seconds(4)));
|
||||
quickload.set_load_callback(FUNC(sorcerer_state::quickload_cb));
|
||||
quickload.set_interface("sorcerer_quik");
|
||||
|
||||
CASSETTE(config, m_cassette1);
|
||||
m_cassette1->set_formats(sorcerer_cassette_formats);
|
||||
@ -498,6 +491,7 @@ void sorcerer_state::sorcerer(machine_config &config)
|
||||
/* software lists */
|
||||
SOFTWARE_LIST(config, "cart_list").set_original("sorcerer_cart");
|
||||
SOFTWARE_LIST(config, "cass_list").set_original("sorcerer_cass");
|
||||
SOFTWARE_LIST(config, "quik_list").set_original("sorcerer_quik");
|
||||
|
||||
// internal ram
|
||||
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)
|
||||
{
|
||||
sorcerer(config);
|
||||
m_maincpu->set_addrmap(AS_PROGRAM, &sorcerer_state::sorcererb_mem);
|
||||
m_maincpu->set_addrmap(AS_IO, &sorcerer_state::sorcererb_io);
|
||||
|
||||
Z80DMA(config, m_dma, ES_CPU_CLOCK);
|
||||
|
@ -97,7 +97,6 @@ protected:
|
||||
void portff_w(u8 data);
|
||||
TIMER_CALLBACK_MEMBER(cassette_tc);
|
||||
TIMER_CALLBACK_MEMBER(serial_tc);
|
||||
DECLARE_SNAPSHOT_LOAD_MEMBER(snapshot_cb);
|
||||
DECLARE_QUICKLOAD_LOAD_MEMBER(quickload_cb);
|
||||
void machine_start_common(offs_t endmem);
|
||||
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 )
|
||||
Handles BIN and SNP extensions.
|
||||
-------------------------------------------------*/
|
||||
|
||||
QUICKLOAD_LOAD_MEMBER(sorcerer_state::quickload_cb)
|
||||
{
|
||||
uint16_t execute_address, start_address, end_address;
|
||||
int autorun;
|
||||
// get autorun setting
|
||||
bool autorun = BIT(m_iop_config->read(), 0);
|
||||
address_space &space = m_maincpu->space(AS_PROGRAM);
|
||||
|
||||
/* load the binary into memory */
|
||||
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)
|
||||
if (image.is_filetype("bin"))
|
||||
{
|
||||
/* check to see if autorun is on */
|
||||
autorun = m_iop_config->read() & 1;
|
||||
u16 execute_address, start_address, end_address;
|
||||
|
||||
if ((execute_address >= 0xc000) && (execute_address <= 0xdfff) && (space.read_byte(0xdffa) != 0xc3))
|
||||
return image_init_result::FAIL; /* can't run a program if the cartridge isn't in */
|
||||
// load the binary into memory
|
||||
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.
|
||||
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 */
|
||||
|
||||
if (((start_address == 0x1d5) || (execute_address == 0xc858)) && (space.read_byte(0xdffa) == 0xc3))
|
||||
// is this file executable?
|
||||
if (execute_address != 0xffff)
|
||||
{
|
||||
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++)
|
||||
space.write_byte(0xf01f + i, data[i]);
|
||||
if ((execute_address >= 0xc000) && (execute_address <= 0xdfff) && (space.read_byte(0xdffa) != 0xc3))
|
||||
return image_init_result::FAIL; // can't run a program if the cartridge isn't in
|
||||
|
||||
if (!autorun)
|
||||
space.write_word(0xf028,0xc3dd);
|
||||
/* Since Exidy Basic is by Microsoft, it needs some preprocessing before it can be run.
|
||||
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 */
|
||||
space.write_byte(0x1b7, end_address & 0xff);
|
||||
space.write_byte(0x1b8, (end_address >> 8) & 0xff);
|
||||
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
|
||||
};
|
||||
|
||||
if ((execute_address != 0xc858) && autorun)
|
||||
space.write_word(0xf028, execute_address);
|
||||
for (u8 i = 0; i < std::size(data); i++)
|
||||
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)
|
||||
m_maincpu->set_pc(execute_address);
|
||||
image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Snapshot must be 65564 bytes");
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user