summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Robbbert <Robbbert@users.noreply.github.com>2021-05-16 20:21:16 +1000
committer Robbbert <Robbbert@users.noreply.github.com>2021-05-16 20:21:16 +1000
commitc54f6940d55eb378199a34f82d754dcd597e3e8d (patch)
tree3929e346fca3637375bf0307e2ab5bd96d07ef43
parent6fb35fced8e114cc8c9e51d1b53695f318ed0812 (diff)
sorcerer: quickload changes
- merged snapshot and quickload; - fixed snapshot which had been broken by the memory system upgrade; - added interface to future software list.
-rw-r--r--src/mame/drivers/sorcerer.cpp19
-rw-r--r--src/mame/includes/sorcerer.h1
-rw-r--r--src/mame/machine/sorcerer.cpp194
3 files changed, 111 insertions, 103 deletions
diff --git a/src/mame/drivers/sorcerer.cpp b/src/mame/drivers/sorcerer.cpp
index 75e3b6fca95..1bffa307d8c 100644
--- a/src/mame/drivers/sorcerer.cpp
+++ b/src/mame/drivers/sorcerer.cpp
@@ -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);
diff --git a/src/mame/includes/sorcerer.h b/src/mame/includes/sorcerer.h
index c23f65589d7..75dc96390f2 100644
--- a/src/mame/includes/sorcerer.h
+++ b/src/mame/includes/sorcerer.h
@@ -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();
diff --git a/src/mame/machine/sorcerer.cpp b/src/mame/machine/sorcerer.cpp
index cdb9ed0782c..06071372f7d 100644
--- a/src/mame/machine/sorcerer.cpp
+++ b/src/mame/machine/sorcerer.cpp
@@ -529,121 +529,137 @@ void sorcererd_state::machine_reset()
}
-/******************************************************************************
- Snapshot Handling
-******************************************************************************/
+/*-------------------------------------------------
+ QUICKLOAD_LOAD_MEMBER( sorcerer_state, sorcerer )
+ Handles BIN and SNP extensions.
+-------------------------------------------------*/
-SNAPSHOT_LOAD_MEMBER(sorcerer_state::snapshot_cb)
+QUICKLOAD_LOAD_MEMBER(sorcerer_state::quickload_cb)
{
- u8 *RAM = memregion(m_maincpu->tag())->base();
+ // get autorun setting
+ bool autorun = BIT(m_iop_config->read(), 0);
address_space &space = m_maincpu->space(AS_PROGRAM);
- u8 header[28];
- unsigned char s_byte;
- /* check size */
- if (image.length() != 0x1001c)
+ if (image.is_filetype("bin"))
{
- image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Snapshot must be 65564 bytes");
- image.message("Snapshot must be 65564 bytes");
- return image_init_result::FAIL;
- }
+ u16 execute_address, start_address, end_address;
- /* get the header */
- image.fread( &header, sizeof(header));
+ // 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;
- /* 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));
+ // is this file executable?
+ if (execute_address != 0xffff)
+ {
- return image_init_result::PASS;
-}
+ 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
+ /* 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 */
-/*-------------------------------------------------
- QUICKLOAD_LOAD_MEMBER( sorcerer_state, sorcerer )
--------------------------------------------------*/
+ 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
+ };
-QUICKLOAD_LOAD_MEMBER(sorcerer_state::quickload_cb)
-{
- uint16_t execute_address, start_address, end_address;
- int autorun;
- address_space &space = m_maincpu->space(AS_PROGRAM);
+ for (u8 i = 0; i < std::size(data); i++)
+ space.write_byte(0xf01f + i, data[i]);
- /* 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;
+ if (!autorun)
+ space.write_word(0xf028,0xc3dd);
- /* is this file executable? */
- if (execute_address != 0xffff)
- {
- /* check to see if autorun is on */
- autorun = m_iop_config->read() & 1;
+ /* tell BASIC where program ends */
+ space.write_byte(0x1b7, end_address & 0xff);
+ space.write_byte(0x1b8, (end_address >> 8) & 0xff);
- 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 ((execute_address != 0xc858) && autorun)
+ space.write_word(0xf028, execute_address);
- /* 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))
+ m_maincpu->set_pc(0xf01f);
+ }
+ else
+ {
+ if (autorun)
+ m_maincpu->set_pc(execute_address);
+ }
+ }
+ }
+ else
+ {
+ // SNP extension
+ // check size
+ if (image.length() != 0x1001c)
{
- 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
- };
+ image.seterror(IMAGE_ERROR_INVALIDIMAGE, "Snapshot must be 65564 bytes");
+ image.message("Snapshot must be 65564 bytes");
+ return image_init_result::FAIL;
+ }
- for (u8 i = 0; i < std::size(data); i++)
- space.write_byte(0xf01f + i, data[i]);
+ u8 header[28];
- if (!autorun)
- space.write_word(0xf028,0xc3dd);
+ /* get the header */
+ image.fread( &header, sizeof(header));
- /* tell BASIC where program ends */
- space.write_byte(0x1b7, end_address & 0xff);
- space.write_byte(0x1b8, (end_address >> 8) & 0xff);
+ // 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
+ }
- if ((execute_address != 0xc858) && autorun)
- space.write_word(0xf028, execute_address);
+ for (int i = 0xe000; i < 0xf000; i++)
+ image.fread( &s_byte, 1);
- m_maincpu->set_pc(0xf01f);
+ for (int i = 0xf000; i < 0xf800; i++)
+ {
+ image.fread( &s_byte, 1);
+ space.write_byte(i, s_byte); // screen
}
- else
+
+ for (int i = 0xf800; i < 0xfc00; i++)
+ image.fread( &s_byte, 1);
+
+ for (int i = 0xfc00; i < 0x10000; i++)
{
- if (autorun)
- m_maincpu->set_pc(execute_address);
+ 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;
}
+