diff options
-rw-r--r-- | android-project/app/src/main/AndroidManifest.xml | 4 | ||||
-rw-r--r-- | language/Dutch/strings.po | 205 | ||||
-rw-r--r-- | makefile | 4 | ||||
-rw-r--r-- | src/devices/bus/interpro/sr/sr.cpp | 38 | ||||
-rw-r--r-- | src/devices/bus/interpro/sr/sr.h | 20 | ||||
-rw-r--r-- | src/devices/cpu/clipper/clipper.cpp | 934 | ||||
-rw-r--r-- | src/devices/cpu/clipper/clipper.h | 315 | ||||
-rw-r--r-- | src/devices/cpu/clipper/clipperd.h | 19 | ||||
-rw-r--r-- | src/devices/cpu/tlcs870/tlcs870d.cpp | 1 | ||||
-rw-r--r-- | src/mame/drivers/cyclemb.cpp | 4 | ||||
-rw-r--r-- | src/mame/drivers/hng64.cpp | 2 | ||||
-rw-r--r-- | src/mame/drivers/interpro.cpp | 94 | ||||
-rw-r--r-- | src/mame/drivers/namcos12.cpp | 156 | ||||
-rw-r--r-- | src/mame/drivers/rbmk.cpp | 310 | ||||
-rw-r--r-- | src/mame/drivers/taitotz.cpp | 4 | ||||
-rw-r--r-- | src/mame/drivers/vicdual.cpp | 13 | ||||
-rw-r--r-- | src/mame/includes/interpro.h | 29 | ||||
-rw-r--r-- | src/mame/machine/cammu.cpp | 548 | ||||
-rw-r--r-- | src/mame/machine/cammu.h | 404 | ||||
-rw-r--r-- | src/mame/machine/interpro_ioga.cpp | 20 | ||||
-rw-r--r-- | src/mame/machine/interpro_ioga.h | 7 | ||||
-rw-r--r-- | src/mame/mame.lst | 3 | ||||
-rw-r--r-- | src/osd/modules/file/winfile.cpp | 14 |
23 files changed, 1905 insertions, 1243 deletions
diff --git a/android-project/app/src/main/AndroidManifest.xml b/android-project/app/src/main/AndroidManifest.xml index b27d8c2025b..ec2e3cba682 100644 --- a/android-project/app/src/main/AndroidManifest.xml +++ b/android-project/app/src/main/AndroidManifest.xml @@ -4,8 +4,8 @@ --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.mamedev.mame" - android:versionCode="191" - android:versionName="0.191" + android:versionCode="192" + android:versionName="0.192" android:installLocation="auto"> <!-- Android 5.0 --> diff --git a/language/Dutch/strings.po b/language/Dutch/strings.po index 00f93902972..960e6b485b5 100644 --- a/language/Dutch/strings.po +++ b/language/Dutch/strings.po @@ -9,7 +9,7 @@ msgstr "" "Project-Id-Version: MAME\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-10-03 10:32+1100\n" -"PO-Revision-Date: 2017-09-02 21:31+0200\n" +"PO-Revision-Date: 2017-11-14 14:25+0100\n" "Last-Translator: Jos van Mourik\n" "Language-Team: MAME Language Team\n" "Language: nl\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 2.0.3\n" +"X-Generator: Poedit 2.0.4\n" #: src/frontend/mame/ui/slotopt.cpp:192 #, c-format @@ -835,7 +835,7 @@ msgid "" "\n" "Press any key to continue." msgstr "" -"Het geselecteerde spel mist één of meer benodigde ROM or CHD-bestanden. " +"Het geselecteerde spel mist één of meer benodigde ROM- of CHD-bestanden. " "Selecteer een ander spel.\n" "\n" "Druk op een toets om door te gaan." @@ -848,7 +848,7 @@ msgid "" "If this is your first time using %2$s, please see the config.txt file in the " "docs directory for information on configuring %2$s." msgstr "" -"Geen machines gevonden. Controleer de rom mapinstellingen in het bestand " +"Geen machines gevonden. Controleer de ROM-mapinstellingen in het bestand " "%1$s.ini.\n" "\n" "Als dit de eerste keer is dat je %2$s gebruikt, lees dan het bestand config." @@ -1324,29 +1324,31 @@ msgstr "Vereist CHD\tNee\n" #: src/frontend/mame/ui/selgame.cpp:974 msgid "ROM Audit Result\tOK\n" -msgstr "" +msgstr "ROM-controle Resultaat\tOK\n" #: src/frontend/mame/ui/selgame.cpp:976 msgid "ROM Audit Result\tBAD\n" -msgstr "" +msgstr "ROM-controle Resultaat\tSLECHT\n" #: src/frontend/mame/ui/selgame.cpp:979 msgid "Samples Audit Result\tNone Needed\n" -msgstr "" +msgstr "Samplecontrole Resultaat\tNiet Nodig\n" #: src/frontend/mame/ui/selgame.cpp:981 msgid "Samples Audit Result\tOK\n" -msgstr "" +msgstr "Samplecontrole Resultaat\tOK\n" #: src/frontend/mame/ui/selgame.cpp:983 msgid "Samples Audit Result\tBAD\n" -msgstr "" +msgstr "Samplecontrole Resultaat\tSLECHT\n" #: src/frontend/mame/ui/selgame.cpp:987 msgid "" "ROM Audit Disabled\t\n" "Samples Audit Disabled\t\n" msgstr "" +"ROM-controle Uitgeschakeld\t\n" +"Samplecontrole Uitgeschakeld\t\n" #: src/frontend/mame/ui/selgame.cpp:1171 #, c-format @@ -1379,7 +1381,7 @@ msgid "" "Please select a different machine.\n" "\n" msgstr "" -"De geselecteerde machine mist één of meerdere benodigde ROM of CHD-" +"De geselecteerde machine mist één of meerdere benodigde ROM- of CHD-" "bestanden. Druk op een toets om door te gaan.\n" "\n" @@ -1664,7 +1666,7 @@ msgid "" "The software selected is missing one or more required ROM or CHD images. " "Please select a different one." msgstr "" -"De geselecteerde software mist één of meerdere benodigde ROM of CHD-" +"De geselecteerde software mist één of meerdere benodigde ROM- of CHD-" "bestanden. Kies een andere." #: src/frontend/mame/ui/info_pty.cpp:30 src/frontend/mame/ui/mainmenu.cpp:99 @@ -1790,12 +1792,12 @@ msgstr " PENNEN" #: src/frontend/mame/ui/auditmenu.cpp:96 #, c-format msgid "Audit ROMs for %1$u machines marked unavailable?" -msgstr "Controleer ROMS voor %1$u onbeschikbaar gemarkeerde machines?" +msgstr "Controleer ROMs voor %1$u onbeschikbaar gemarkeerde machines?" #: src/frontend/mame/ui/auditmenu.cpp:99 #, c-format msgid "Audit ROMs for all %1$u machines?" -msgstr "Controleer ROMS voor alle %1$u machines?" +msgstr "Controleer ROMs voor alle %1$u machines?" #: src/frontend/mame/ui/auditmenu.cpp:104 #, c-format @@ -1808,7 +1810,7 @@ msgid "" "Auditing ROMs for machine %2$u of %3$u...\n" "%1$s" msgstr "" -"ROMS controleren voor machine %2$u van %3$u...\n" +"ROMs controleren voor machine %2$u van %3$u...\n" "%1$s" #: src/frontend/mame/ui/auditmenu.cpp:142 @@ -1953,7 +1955,7 @@ msgstr "Softwareonderdelen selectiemenu overslaan" #: src/frontend/mame/ui/submenu.cpp:33 msgid "Info auto audit" -msgstr "Info romcontrole" +msgstr "Info auto controle" #: src/frontend/mame/ui/submenu.cpp:34 msgid "Hide romless machine from available list" @@ -2476,27 +2478,27 @@ msgstr "Instellingen" #: plugins/timer/init.lua:94 msgid "Current time" -msgstr "" +msgstr "Huidige tijd" #: plugins/timer/init.lua:96 msgid "Total time" -msgstr "" +msgstr "Totale tijd" #: plugins/timer/init.lua:98 msgid "Play Count" -msgstr "" +msgstr "Speelteller" #: plugins/timer/init.lua:106 msgid "Timer" -msgstr "" +msgstr "Timer" #: plugins/cheat/init.lua:458 msgid "Select cheat to set hotkey" -msgstr "" +msgstr "Selecteer cheat om sneltoets te maken" #: plugins/cheat/init.lua:464 msgid "Press button for hotkey or wait to clear" -msgstr "" +msgstr "Druk op knop voor sneltoets of wacht om te herstellen" #: plugins/cheat/init.lua:476 msgid "None" @@ -2504,40 +2506,40 @@ msgstr "Geen" #: plugins/cheat/init.lua:481 msgid "Done" -msgstr "" +msgstr "Klaar" #: plugins/cheat/init.lua:495 plugins/cheat/init.lua:509 msgid "Set" -msgstr "" +msgstr "Kies" #: plugins/cheat/init.lua:528 msgid "Set hotkeys" -msgstr "" +msgstr "Kies sneltoets" #: plugins/cheat/init.lua:668 #, lua-format msgid "Activated: %s = %s" -msgstr "" +msgstr "Geactiveerd: %s = %s" #: plugins/cheat/init.lua:671 plugins/cheat/init.lua:729 #, lua-format msgid "Activated: %s" -msgstr "" +msgstr "Geactiveerd: %s" #: plugins/cheat/init.lua:733 #, lua-format msgid "Enabled: %s" -msgstr "" +msgstr "Ingeschakeld: %s" #: plugins/cheat/init.lua:738 #, lua-format msgid "Disabled: %s" -msgstr "" +msgstr "Uitgeschakeld: %s" #: plugins/cheat/init.lua:776 #, lua-format msgid "%s added" -msgstr "" +msgstr "%s toegevoegd" #: plugins/data/data_command.lua:19 msgid "Command" @@ -2562,6 +2564,10 @@ msgid "" "--- DRIVER INFO ---\n" "Driver: " msgstr "" +"\n" +"\n" +"--- DRIVER INFO ---\n" +"Driver: " #: plugins/data/data_mameinfo.lua:20 msgid "MAMEinfo" @@ -2585,244 +2591,205 @@ msgstr "MARPScore" #: plugins/cheatfind/init.lua:344 msgid "Save Cheat" -msgstr "" +msgstr "Sla cheat op" #: plugins/cheatfind/init.lua:347 msgid "Default" -msgstr "" +msgstr "Standaard" #: plugins/cheatfind/init.lua:347 msgid "Custom" -msgstr "" +msgstr "Eigen" #: plugins/cheatfind/init.lua:348 msgid "Cheat Name" -msgstr "" +msgstr "Cheatnaam" #: plugins/cheatfind/init.lua:354 #, lua-format msgid "Default name is %s" -msgstr "" +msgstr "Standaardnaam is %s" #: plugins/cheatfind/init.lua:362 msgid "Player" -msgstr "" +msgstr "Speler" #: plugins/cheatfind/init.lua:367 msgid "Type" -msgstr "" +msgstr "Type" #: plugins/cheatfind/init.lua:373 msgid "Save" -msgstr "" +msgstr "Opslaan" #: plugins/cheatfind/init.lua:399 #, lua-format msgid "Cheat written to %s and added to cheat.simple" -msgstr "" +msgstr "Cheat geschreven naar %s en toegevoegd aan cheat.simple" #: plugins/cheatfind/init.lua:407 msgid "Cheat added to cheat.simple" -msgstr "" +msgstr "Cheat toegevoegd aan cheat.simple" #: plugins/cheatfind/init.lua:412 msgid "" "Unable to write file\n" "Ensure that cheatpath folder exists" msgstr "" +"Niet in staat om bestand te schrijven\n" +"Zorg ervoor dat de cheatpath map bestaat" #: plugins/cheatfind/init.lua:421 msgid "Cancel" -msgstr "" +msgstr "Annuleer" #: plugins/cheatfind/init.lua:426 msgid "CPU or RAM" -msgstr "" +msgstr "CPU of RAM" #: plugins/cheatfind/init.lua:430 msgid "Changes to this only take effect when \"Start new search\" is selected" msgstr "" +"Veranderingen hieraan hebben alleen effect wanneer \"Start nieuwe " +"zoekopdracht\" is geselecteerd" #: plugins/cheatfind/init.lua:449 msgid "Data cleared and current state saved" -msgstr "" +msgstr "Data hersteld en huidige staat opgeslagen" #: plugins/cheatfind/init.lua:457 msgid "Start new search" -msgstr "" +msgstr "Start nieuwe zoekopdracht" #: plugins/cheatfind/init.lua:467 msgid "Current state saved" -msgstr "" +msgstr "Huidige staat opgeslagen" #: plugins/cheatfind/init.lua:474 msgid "Save current -- #" -msgstr "" +msgstr "Sla huidige -- # op" #: plugins/cheatfind/init.lua:506 msgid " total matches found" -msgstr "" +msgstr " totale overeenkomsten gevonden" #: plugins/cheatfind/init.lua:513 msgid "Compare" -msgstr "" +msgstr "Vergelijk" #: plugins/cheatfind/init.lua:516 msgid "Left operand" -msgstr "" +msgstr "Linkse operand" #: plugins/cheatfind/init.lua:519 msgid "Current" -msgstr "" +msgstr "Huidige" #: plugins/cheatfind/init.lua:524 msgid "Operator" -msgstr "" +msgstr "Operator" #: plugins/cheatfind/init.lua:531 msgid "Left less than right, value is difference" -msgstr "" +msgstr "Links kleiner dan rechts, waarde is verschil" #: plugins/cheatfind/init.lua:533 msgid "Left greater than right, value is difference" -msgstr "" +msgstr "Links groter dan rechts, waarde is verschil" #: plugins/cheatfind/init.lua:535 msgid "Left equal to right" -msgstr "" +msgstr "Links gelijk aan rechts" #: plugins/cheatfind/init.lua:537 msgid "Left not equal to right, value is difference" -msgstr "" +msgstr "Links niet gelijk aan rechts, waarde is verschil" #: plugins/cheatfind/init.lua:539 msgid "Left equal to right with bitmask" -msgstr "" +msgstr "Links gelijk aan rechts met bitmasker" #: plugins/cheatfind/init.lua:541 msgid "Left not equal to right with bitmask" -msgstr "" +msgstr "Links niet gelijk aan rechts met bitmasker" #: plugins/cheatfind/init.lua:543 msgid "Left less than value" -msgstr "" +msgstr "Links kleiner dan waarde" #: plugins/cheatfind/init.lua:545 msgid "Left greater than value" -msgstr "" +msgstr "Links groter dan waarde" #: plugins/cheatfind/init.lua:547 msgid "Left equal to value" -msgstr "" +msgstr "Links gelijk aan waarde" #: plugins/cheatfind/init.lua:549 msgid "Left not equal to value" -msgstr "" +msgstr "Links niet gelijk aan waarde" #: plugins/cheatfind/init.lua:560 msgid "Right operand" -msgstr "" +msgstr "Rechtse operand" #: plugins/cheatfind/init.lua:568 msgid "Value" -msgstr "" +msgstr "Waarde" #: plugins/cheatfind/init.lua:572 msgid "Any" -msgstr "" +msgstr "Willekeurige" #: plugins/cheatfind/init.lua:578 msgid "Data Format" -msgstr "" +msgstr "Data Format" #: plugins/cheatfind/init.lua:602 msgid "Undo last search -- #" -msgstr "" +msgstr "Laatste zoekopdracht ongedaan maken -- #" #: plugins/cheatfind/init.lua:606 msgid "Match block" -msgstr "" +msgstr "Paar blok" #: plugins/cheatfind/init.lua:609 msgid "All" -msgstr "" +msgstr "Alle" #: plugins/cheatfind/init.lua:660 #, lua-format msgid "Test cheat at addr %08X" -msgstr "" +msgstr "Test cheat op addr %08X" #: plugins/cheatfind/init.lua:692 msgid "Cheat engine not available" -msgstr "" +msgstr "Cheat engine niet beschikbaar" #: plugins/cheatfind/init.lua:718 msgid "Default name is " -msgstr "" +msgstr "Standaardnaam is " #: plugins/cheatfind/init.lua:741 msgid "Test" -msgstr "" +msgstr "Test" #: plugins/cheatfind/init.lua:741 msgid "Write" -msgstr "" +msgstr "Schrijf" #: plugins/cheatfind/init.lua:741 msgid "Watch" -msgstr "" +msgstr "Watch" #: plugins/cheatfind/init.lua:758 msgid "Page" -msgstr "" +msgstr "Pagina" #: plugins/cheatfind/init.lua:776 msgid "Clear Watches" -msgstr "" +msgstr "Herstel Watches" #: plugins/cheatfind/init.lua:786 msgid "Cheat Finder" -msgstr "" - -#~ msgid "Requires CHD\t%1$s\n" -#~ msgstr "Vereist CHD\t%1$s\n" - -#~ msgid "Roms Audit Pass\tOK\n" -#~ msgstr "Romcontrole geslaagd\tOK\n" - -#~ msgid "Roms Audit Pass\tBAD\n" -#~ msgstr "Romcontrole geslaagd\tSLECHT\n" - -#~ msgid "Samples Audit Pass\tNone Needed\n" -#~ msgstr "Samplecontrole geslaagd\tNiet nodig\n" - -#~ msgid "Samples Audit Pass\tOK\n" -#~ msgstr "Samplecontrole geslaagd\tOK\n" - -#~ msgid "Samples Audit Pass\tBAD\n" -#~ msgstr "Samplecontrole geslaagd\tSLECHT\n" - -#~ msgid "" -#~ "Roms Audit Pass\tDisabled\n" -#~ "Samples Audit Pass\tDisabled\n" -#~ msgstr "" -#~ "Romcontrole geslaagd\tUitgeschakeld\n" -#~ "Samplecontrole geslaagd\tUitgeschakeld\n" - -#~ msgid "Unimplemented" -#~ msgstr "Ongeïmplementeerd" - -#~ msgid "Imperfect" -#~ msgstr "Onvolledig" - -#~ msgid "OK" -#~ msgstr "OK" - -#~ msgid "No Infos Available" -#~ msgstr "Geen informatie beschikbaar" - -#~ msgid "Dummy" -#~ msgstr "Dummie" - -#~ msgid "Display Options" -#~ msgstr "Videoopties" +msgstr "Cheatzoeker" @@ -1547,14 +1547,14 @@ endif ifeq (posix,$(SHELLTYPE)) $(GENDIR)/version.cpp: $(GENDIR)/git_desc | $(GEN_FOLDERS) - @echo '#define BARE_BUILD_VERSION "0.191"' > $@ + @echo '#define BARE_BUILD_VERSION "0.192"' > $@ @echo 'extern const char bare_build_version[];' >> $@ @echo 'extern const char build_version[];' >> $@ @echo 'const char bare_build_version[] = BARE_BUILD_VERSION;' >> $@ @echo 'const char build_version[] = BARE_BUILD_VERSION " ($(NEW_GIT_VERSION))";' >> $@ else $(GENDIR)/version.cpp: $(GENDIR)/git_desc - @echo #define BARE_BUILD_VERSION "0.191" > $@ + @echo #define BARE_BUILD_VERSION "0.192" > $@ @echo extern const char bare_build_version[]; >> $@ @echo extern const char build_version[]; >> $@ @echo const char bare_build_version[] = BARE_BUILD_VERSION; >> $@ diff --git a/src/devices/bus/interpro/sr/sr.cpp b/src/devices/bus/interpro/sr/sr.cpp index 5a8f7d23a68..112aa582746 100644 --- a/src/devices/bus/interpro/sr/sr.cpp +++ b/src/devices/bus/interpro/sr/sr.cpp @@ -266,16 +266,16 @@ sr_slot_device::sr_slot_device(const machine_config &mconfig, const char *tag, d : device_t(mconfig, SR_SLOT, tag, owner, clock) , device_slot_interface(mconfig, *this) , m_sr_tag(nullptr) - , m_sr_slottag(nullptr) + , m_sr_slot_tag(nullptr) { } -void sr_slot_device::static_set_sr_slot(device_t &device, const char *tag, const char *slottag) +void sr_slot_device::static_set_sr_slot(device_t &device, const char *tag, const char *slot_tag) { sr_slot_device &sr_card = dynamic_cast<sr_slot_device &>(device); sr_card.m_sr_tag = tag; - sr_card.m_sr_slottag = slottag; + sr_card.m_sr_slot_tag = slot_tag; } void sr_slot_device::device_start() @@ -283,28 +283,38 @@ void sr_slot_device::device_start() device_sr_card_interface *dev = dynamic_cast<device_sr_card_interface *>(get_card_device()); if (dev) - device_sr_card_interface::static_set_sr_tag(*dev, m_sr_tag, m_sr_slottag); + device_sr_card_interface::static_set_sr_tag(*dev, m_sr_tag, m_sr_slot_tag); } DEFINE_DEVICE_TYPE(SR, sr_device, "sr", "InterPro SR bus") sr_device::sr_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : device_t(mconfig, SR, tag, owner, clock) - , m_data_space(nullptr) - , m_io_space(nullptr) , m_out_irq0_cb(*this) , m_out_irq1_cb(*this) , m_out_irq2_cb(*this) + , m_memory_tag(nullptr) { } +void sr_device::static_set_memory(device_t &device, const char *const tag, const int data_spacenum, const int io_spacenum) +{ + sr_device &sr = dynamic_cast<sr_device &>(device); + + sr.m_memory_tag = tag; + sr.m_data_spacenum = data_spacenum; + sr.m_io_spacenum = io_spacenum; +} + void sr_device::device_start() { - // grab the main memory space from the mmu - device_memory_interface *mmu; - siblingdevice("mmu")->interface(mmu); - m_data_space = &mmu->space(0); - m_io_space = &mmu->space(1); + assert_always(m_memory_tag != nullptr, "memory tag and address spaces must be configured"); + + // get the memory spaces + device_memory_interface *memory; + siblingdevice(m_memory_tag)->interface(memory); + m_data_space = &memory->space(m_data_spacenum); + m_io_space = &memory->space(m_io_spacenum); // resolve callbacks m_out_irq0_cb.resolve_safe(); @@ -325,7 +335,7 @@ device_sr_card_interface::device_sr_card_interface(const machine_config &mconfig : device_slot_card_interface(mconfig, device) , m_sr(nullptr) , m_sr_tag(nullptr) - , m_sr_slottag(nullptr) + , m_sr_slot_tag(nullptr) { } @@ -333,12 +343,12 @@ device_sr_card_interface::~device_sr_card_interface() { } -void device_sr_card_interface::static_set_sr_tag(device_t &device, const char *tag, const char *slottag) +void device_sr_card_interface::static_set_sr_tag(device_t &device, const char *tag, const char *slot_tag) { device_sr_card_interface &sr_card = dynamic_cast<device_sr_card_interface &>(device); sr_card.m_sr_tag = tag; - sr_card.m_sr_slottag = slottag; + sr_card.m_sr_slot_tag = slot_tag; } void device_sr_card_interface::set_sr_device() diff --git a/src/devices/bus/interpro/sr/sr.h b/src/devices/bus/interpro/sr/sr.h index 236b4ea674b..f51b7f6a946 100644 --- a/src/devices/bus/interpro/sr/sr.h +++ b/src/devices/bus/interpro/sr/sr.h @@ -23,6 +23,9 @@ #define MCFG_SR_SLOT_REMOVE(_tag) \ MCFG_DEVICE_REMOVE(_tag) +#define MCFG_SR_MEMORY(_tag, _data_spacenum, _io_spacenum) \ + sr_device::static_set_memory(*device, _tag, _data_spacenum, _io_spacenum); + class sr_slot_device : public device_t, public device_slot_interface { public: @@ -30,7 +33,8 @@ public: sr_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); // inline configuration - static void static_set_sr_slot(device_t &device, const char *tag, const char *slottag); + static void static_set_sr_slot(device_t &device, const char *tag, const char *slot_tag); + protected: sr_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); @@ -38,7 +42,8 @@ protected: virtual void device_start() override; // configuration - const char *m_sr_tag, *m_sr_slottag; + const char *m_sr_tag; + const char *m_sr_slot_tag; }; class device_sr_card_interface; @@ -54,6 +59,8 @@ public: template <class Object> static devcb_base &set_out_irq1_callback(device_t &device, Object &&cb) { return downcast<sr_device &>(device).m_out_irq1_cb.set_callback(std::forward<Object>(cb)); } template <class Object> static devcb_base &set_out_irq2_callback(device_t &device, Object &&cb) { return downcast<sr_device &>(device).m_out_irq2_cb.set_callback(std::forward<Object>(cb)); } + static void static_set_memory(device_t &device, const char *const tag, const int data_spacenum, const int io_spacenum); + static const u32 SR_BASE = 0x87000000; static const u32 SR_SIZE = 0x08000000; static const int SR_COUNT = 16; @@ -97,6 +104,10 @@ protected: private: device_sr_card_interface *m_slot[SR_COUNT]; int m_slot_count; + + const char *m_memory_tag; + int m_data_spacenum; + int m_io_spacenum; }; class device_sr_card_interface : public device_slot_card_interface @@ -110,13 +121,14 @@ public: void set_sr_device(); // inline configuration - static void static_set_sr_tag(device_t &device, const char *tag, const char *slottag); + static void static_set_sr_tag(device_t &device, const char *tag, const char *slot_tag); protected: device_sr_card_interface(const machine_config &mconfig, device_t &device); sr_device *m_sr; - const char *m_sr_tag, *m_sr_slottag; + const char *m_sr_tag; + const char *m_sr_slot_tag; }; class sr_card_device_base : public device_t, public device_sr_card_interface diff --git a/src/devices/cpu/clipper/clipper.cpp b/src/devices/cpu/clipper/clipper.cpp index c2f8c85dfd8..d9812b4a987 100644 --- a/src/devices/cpu/clipper/clipper.cpp +++ b/src/devices/cpu/clipper/clipper.cpp @@ -11,7 +11,6 @@ * - unimplemented C400 instructions * - correct boot logic * - condition codes for multiply instructions - * - most cpu traps/faults * - instruction timing * - big endian support (not present in the wild) */ @@ -22,9 +21,9 @@ #include "clipperd.h" #define LOG_GENERAL (1U << 0) -#define LOG_INTERRUPT (1U << 1) +#define LOG_EXCEPTION (1U << 1) -//#define VERBOSE (LOG_GENERAL | LOG_INTERRUPT) +//#define VERBOSE (LOG_GENERAL | LOG_EXCEPTION) #include "logmacro.h" @@ -57,25 +56,30 @@ DEFINE_DEVICE_TYPE(CLIPPER_C300, clipper_c300_device, "clipper_c300", "C300 CLIP DEFINE_DEVICE_TYPE(CLIPPER_C400, clipper_c400_device, "clipper_c400", "C400 CLIPPER") clipper_c100_device::clipper_c100_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : clipper_device(mconfig, CLIPPER_C100, tag, owner, clock, 0) { } + : clipper_device(mconfig, CLIPPER_C100, tag, owner, clock, ENDIANNESS_LITTLE, 0) +{ +} clipper_c300_device::clipper_c300_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : clipper_device(mconfig, CLIPPER_C300, tag, owner, clock, 0) { } + : clipper_device(mconfig, CLIPPER_C300, tag, owner, clock, ENDIANNESS_LITTLE, 0) +{ +} clipper_c400_device::clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) - : clipper_device(mconfig, CLIPPER_C400, tag, owner, clock, SSW_ID_C400R4) { } - -clipper_device::clipper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const u32 cpuid) - : cpu_device(mconfig, type, tag, owner, clock), - m_pc(0), - m_psw(0), - m_ssw(cpuid), - m_r(m_rs), - m_insn_config("insn", ENDIANNESS_LITTLE, 32, 32, 0), - m_data_config("data", ENDIANNESS_LITTLE, 32, 32, 0), - m_insn(nullptr), - m_data(nullptr), - m_icount(0) + : clipper_device(mconfig, CLIPPER_C400, tag, owner, clock, ENDIANNESS_LITTLE, SSW_ID_C400R4) +{ +} + +clipper_device::clipper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const endianness_t endianness, const u32 cpuid) + : cpu_device(mconfig, type, tag, owner, clock) + , m_insn_config("insn", endianness, 32, 32, 0) + , m_data_config("data", endianness, 32, 32, 0) + , m_insn(nullptr) + , m_data(nullptr) + , m_icount(0) + , m_psw(endianness == ENDIANNESS_BIG ? PSW_BIG : 0) + , m_ssw(cpuid) + , m_r(m_rs) { } @@ -126,53 +130,22 @@ void clipper_device::device_start() save_item(NAME(m_irq)); save_item(NAME(m_ivec)); - state_add(STATE_GENPC, "GENPC", m_pc).noshow(); - state_add(STATE_GENPCBASE, "CURPC", m_pc).noshow(); + state_add(STATE_GENPC, "GENPC", m_ip).noshow(); + state_add(STATE_GENPCBASE, "CURPC", m_ip).noshow(); state_add(STATE_GENSP, "GENSP", m_r[15]).noshow(); state_add(STATE_GENFLAGS, "GENFLAGS", m_psw).mask(0xf).formatstr("%4s").noshow(); - state_add(CLIPPER_PC, "pc", m_pc); + state_add(CLIPPER_PC, "pc", m_ip); state_add(CLIPPER_PSW, "psw", m_psw); state_add(CLIPPER_SSW, "ssw", m_ssw); - state_add(CLIPPER_R0, "r0", m_r[0]); - state_add(CLIPPER_R1, "r1", m_r[1]); - state_add(CLIPPER_R2, "r2", m_r[2]); - state_add(CLIPPER_R3, "r3", m_r[3]); - state_add(CLIPPER_R4, "r4", m_r[4]); - state_add(CLIPPER_R5, "r5", m_r[5]); - state_add(CLIPPER_R6, "r6", m_r[6]); - state_add(CLIPPER_R7, "r7", m_r[7]); - state_add(CLIPPER_R8, "r8", m_r[8]); - state_add(CLIPPER_R9, "r9", m_r[9]); - state_add(CLIPPER_R10, "r10", m_r[10]); - state_add(CLIPPER_R11, "r11", m_r[11]); - state_add(CLIPPER_R12, "r12", m_r[12]); - state_add(CLIPPER_R13, "r13", m_r[13]); - state_add(CLIPPER_R14, "r14", m_r[14]); - state_add(CLIPPER_R15, "r15", m_r[15]); - - state_add(CLIPPER_F0, "f0", m_f[0]); - state_add(CLIPPER_F1, "f1", m_f[1]); - state_add(CLIPPER_F2, "f2", m_f[2]); - state_add(CLIPPER_F3, "f3", m_f[3]); - state_add(CLIPPER_F4, "f4", m_f[4]); - state_add(CLIPPER_F5, "f5", m_f[5]); - state_add(CLIPPER_F6, "f6", m_f[6]); - state_add(CLIPPER_F7, "f7", m_f[7]); - - // C400 has 8 additional floating point registers - if (type() == CLIPPER_C400) - { - state_add(CLIPPER_F8, "f8", m_f[8]); - state_add(CLIPPER_F9, "f9", m_f[9]); - state_add(CLIPPER_F10, "f10", m_f[10]); - state_add(CLIPPER_F11, "f11", m_f[11]); - state_add(CLIPPER_F12, "f12", m_f[12]); - state_add(CLIPPER_F13, "f13", m_f[13]); - state_add(CLIPPER_F14, "f14", m_f[14]); - state_add(CLIPPER_F15, "f15", m_f[15]); - } + // integer regsters + for (int i = 0; i < get_ireg_count(); i++) + state_add(CLIPPER_IREG + i, util::string_format("r%d", i).c_str(), m_r[i]); + + // floating point registers + for (int i = 0; i < get_freg_count(); i++) + state_add(CLIPPER_FREG + i, util::string_format("f%d", i).c_str(), m_f[i]); } void clipper_device::device_reset() @@ -182,20 +155,19 @@ void clipper_device::device_reset() * psw: T cleared, BIG set from hardware, others undefined * ssw: EI, TP, M, U, K, KU, UU, P cleared, ID set from hardware, others undefined */ - m_psw = 0; - float_rounding_mode = float_round_nearest_even; - // clear the ssw + // clear the psw and ssw + set_psw(0); set_ssw(0); - // select the register file according to the ssw - m_r = SSW(U) ? m_ru : m_rs; - // FIXME: figure out how to branch to the boot code properly - m_pc = 0x7f100000; + m_pc = 0x6000; + m_ip = 0x7f100000; + m_irq = CLEAR_LINE; m_nmi = CLEAR_LINE; m_ivec = 0; + m_exception = 0; } void clipper_device::state_string_export(const device_state_entry &entry, std::string &str) const @@ -214,20 +186,18 @@ void clipper_device::state_string_export(const device_state_entry &entry, std::s void clipper_device::execute_run() { - u16 insn; - // check for non-maskable and prioritised interrupts if (m_nmi) { // acknowledge non-maskable interrupt standard_irq_callback(INPUT_LINE_NMI); - LOGMASKED(LOG_INTERRUPT, "non-maskable interrupt\n"); - m_pc = intrap(EXCEPTION_INTERRUPT_BASE, m_pc); + LOGMASKED(LOG_EXCEPTION, "non-maskable interrupt\n"); + m_ip = intrap(EXCEPTION_INTERRUPT_BASE, m_ip); } else if (SSW(EI) && m_irq) { - LOGMASKED(LOG_INTERRUPT, "received prioritised interrupt ivec 0x%02x\n", m_ivec); + LOGMASKED(LOG_EXCEPTION, "received prioritised interrupt ivec 0x%02x\n", m_ivec); // allow equal/higher priority interrupts if ((m_ivec & IVEC_LEVEL) <= SSW(IL)) @@ -235,30 +205,74 @@ void clipper_device::execute_run() // acknowledge interrupt standard_irq_callback(INPUT_LINE_IRQ0); - LOGMASKED(LOG_INTERRUPT, "transferring control to ivec 0x%02x\n", m_ivec); - m_pc = intrap(EXCEPTION_INTERRUPT_BASE + m_ivec * 8, m_pc); + LOGMASKED(LOG_EXCEPTION, "transferring control to ivec 0x%02x\n", m_ivec); + m_ip = intrap(EXCEPTION_INTERRUPT_BASE + m_ivec * 8, m_ip); } } - while (m_icount > 0) { + while (m_icount > 0) + { + debugger_instruction_hook(this, m_ip); - debugger_instruction_hook(this, m_pc); + // fetch and decode an instruction + if (decode_instruction()) + { + float_exception_flags = 0; - // fetch instruction word - insn = m_insn->read_word(m_pc + 0); + // execute instruction + execute_instruction(); - // decode instruction - decode_instruction(insn); + // check floating point exceptions + if (float_exception_flags) + fp_exception(); + } - // clear floating point exceptions - float_exception_flags = 0; + if (m_exception) + { + /* + * For traced instructions which are interrupted or cause traps, the TP + * flag is set by hardware when the interrupt or trap occurs to ensure + * that the trace trap will occur immediately after the interrupt or other + * trap has been serviced. + */ + // FIXME: don't know why/when the trace pending flag is needed + if (PSW(T)) + m_ssw |= SSW_TP; + + switch (m_exception) + { + // data memory trap group + case EXCEPTION_D_CORRECTED_MEMORY_ERROR: + case EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR: + case EXCEPTION_D_ALIGNMENT_FAULT: + case EXCEPTION_D_PAGE_FAULT: + case EXCEPTION_D_READ_PROTECT_FAULT: + case EXCEPTION_D_WRITE_PROTECT_FAULT: + + // instruction memory trap group + case EXCEPTION_I_CORRECTED_MEMORY_ERROR: + case EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR: + case EXCEPTION_I_ALIGNMENT_FAULT: + case EXCEPTION_I_PAGE_FAULT: + case EXCEPTION_I_EXECUTE_PROTECT_FAULT: + + // illegal operation trap group + case EXCEPTION_ILLEGAL_OPERATION: + case EXCEPTION_PRIVILEGED_INSTRUCTION: + // return address is faulting instruction + m_ip = intrap(m_exception, m_pc); + break; - // execute instruction, return next pc - m_pc = execute_instruction(); + default: + // return address is following instruction + m_ip = intrap(m_exception, m_ip); + break; + } + } - // handle floating point exceptions - if (float_exception_flags) - fp_exception(); + // FIXME: trace trap logic not working properly yet + //else if (PSW(T)) + // m_ip = intrap(EXCEPTION_TRACE, m_ip); // FIXME: some instructions take longer (significantly) than one cycle // and also the timings are often slower for the C100 and C300 @@ -292,13 +306,29 @@ device_memory_interface::space_config_vector clipper_device::memory_space_config }; } +WRITE16_MEMBER(clipper_device::set_exception) +{ + LOGMASKED(LOG_EXCEPTION, "external exception 0x%04x triggered\n", data); + + // check if corrected memory errors are masked + if (!SSW(ECM) && (data == EXCEPTION_D_CORRECTED_MEMORY_ERROR || data == EXCEPTION_I_CORRECTED_MEMORY_ERROR)) + return; + + m_exception = data; +} + /* - * This function decodes instruction operands and computes effective addresses (for + * Fetch and decode an instruction and compute an effective address (for * instructions with addressing modes). The results are contained in the m_info * structure to simplify passing between here and execute_instruction(). */ -void clipper_device::decode_instruction (u16 insn) +bool clipper_device::decode_instruction() { + // fetch instruction word + u16 insn = m_insn->read_word(m_ip + 0); + if (m_exception) + return false; + // decode the primary parcel m_info.opcode = insn >> 8; m_info.subopcode = insn & 0xff; @@ -308,16 +338,20 @@ void clipper_device::decode_instruction (u16 insn) // initialise the other fields m_info.imm = 0; m_info.macro = 0; - m_info.size = 0; m_info.address = 0; + // default instruction size is 2 bytes + int size = 2; + if ((insn & 0xf800) == 0x3800) { // instruction has a 16 bit immediate operand // fetch 16 bit immediate and sign extend - m_info.imm = (s16)m_insn->read_word(m_pc + 2); - m_info.size = 4; + m_info.imm = (s16)m_insn->read_word(m_ip + 2); + if (m_exception) + return false; + size = 4; } else if ((insn & 0xd300) == 0x8300) { @@ -325,14 +359,18 @@ void clipper_device::decode_instruction (u16 insn) if (insn & 0x0080) { // fetch 16 bit immediate and sign extend - m_info.imm = (s16)m_insn->read_word(m_pc + 2); - m_info.size = 4; + m_info.imm = (s16)m_insn->read_word(m_ip + 2); + if (m_exception) + return false; + size = 4; } else { // fetch 32 bit immediate - m_info.imm = m_insn->read_dword_unaligned(m_pc + 2); - m_info.size = 6; + m_info.imm = m_insn->read_dword_unaligned(m_ip + 2); + if (m_exception) + return false; + size = 6; } } else if ((insn & 0xc000) == 0x4000) @@ -346,87 +384,103 @@ void clipper_device::decode_instruction (u16 insn) switch (insn & 0x00f0) { case ADDR_MODE_PC32: - m_info.address = m_pc + m_insn->read_dword_unaligned(m_pc + 2); - m_info.size = 6; + m_info.address = m_ip + m_insn->read_dword_unaligned(m_ip + 2); + if (m_exception) + return false; + size = 6; break; case ADDR_MODE_ABS32: - m_info.address = m_insn->read_dword_unaligned(m_pc + 2); - m_info.size = 6; + m_info.address = m_insn->read_dword_unaligned(m_ip + 2); + if (m_exception) + return false; + size = 6; break; case ADDR_MODE_REL32: - m_info.r2 = m_insn->read_word(m_pc + 2) & 0xf; - m_info.address = m_r[insn & 0xf] + m_insn->read_dword_unaligned(m_pc + 4); - m_info.size = 8; + m_info.r2 = m_insn->read_word(m_ip + 2) & 0xf; + if (m_exception) + return false; + + m_info.address = m_r[insn & 0xf] + m_insn->read_dword_unaligned(m_ip + 4); + if (m_exception) + return false; + size = 8; break; case ADDR_MODE_PC16: - m_info.address = m_pc + (s16)m_insn->read_word(m_pc + 2); - m_info.size = 4; + m_info.address = m_ip + (s16)m_insn->read_word(m_ip + 2); + if (m_exception) + return false; + size = 4; break; case ADDR_MODE_REL12: - temp = m_insn->read_word(m_pc + 2); + temp = m_insn->read_word(m_ip + 2); + if (m_exception) + return false; m_info.r2 = temp & 0xf; m_info.address = m_r[insn & 0xf] + ((s16)temp >> 4); - m_info.size = 4; + size = 4; break; case ADDR_MODE_ABS16: - m_info.address = (s16)m_insn->read_word(m_pc + 2); - m_info.size = 4; + m_info.address = (s16)m_insn->read_word(m_ip + 2); + if (m_exception) + return false; + size = 4; break; case ADDR_MODE_PCX: - temp = m_insn->read_word(m_pc + 2); + temp = m_insn->read_word(m_ip + 2); + if (m_exception) + return false; m_info.r2 = temp & 0xf; - m_info.address = m_pc + m_r[(temp >> 4) & 0xf]; - m_info.size = 4; + m_info.address = m_ip + m_r[(temp >> 4) & 0xf]; + size = 4; break; case ADDR_MODE_RELX: - temp = m_insn->read_word(m_pc + 2); + temp = m_insn->read_word(m_ip + 2); + if (m_exception) + return false; m_info.r2 = temp & 0xf; m_info.address = m_r[insn & 0xf] + m_r[(temp >> 4) & 0xf]; - m_info.size = 4; + size = 4; break; default: - LOG("illegal addressing mode pc 0x%08x\n", m_pc); - machine().debug_break(); - break; + m_exception = EXCEPTION_ILLEGAL_OPERATION; + return false; } } else - { // relative addressing mode m_info.address = m_r[m_info.r1]; - m_info.size = 2; - } } else if ((insn & 0xfd00) == 0xb400) { // macro instructions - m_info.macro = m_insn->read_word(m_pc + 2); - m_info.size = 4; + m_info.macro = m_insn->read_word(m_ip + 2); + if (m_exception) + return false; + size = 4; } - else - // all other instruction formats are 16 bits - m_info.size = 2; + + // instruction fetch and decode complete + m_pc = m_ip; + m_ip = m_pc + size; + + return true; } -int clipper_device::execute_instruction () +void clipper_device::execute_instruction() { - // the address of the next instruction - u32 next_pc; - - // next instruction follows the current one by default, but - // may be changed for branch, call or trap instructions - next_pc = m_pc + m_info.size; + // memory fetch temporary + u64 temp; switch (m_info.opcode) { @@ -438,15 +492,9 @@ int clipper_device::execute_instruction () // treated as a noop if target ssw in user mode // R1 == 3 means "fast" mode - avoids pipeline flush if (R1 == 0) - { - m_psw = m_r[R2]; - fp_rounding(); - } + set_psw(m_r[R2]); else if (!SSW(U) && (R1 == 1 || R1 == 3)) - { set_ssw(m_r[R2]); - m_r = SSW(U) ? m_ru : m_rs; - } // FLAGS: CVZN break; case 0x11: @@ -459,12 +507,16 @@ int clipper_device::execute_instruction () break; case 0x12: // calls: call supervisor - next_pc = intrap(EXCEPTION_SUPERVISOR_CALL_BASE + (m_info.subopcode & 0x7f) * 8, next_pc); + m_exception = EXCEPTION_SUPERVISOR_CALL_BASE + (m_info.subopcode & 0x7f) * 8; break; case 0x13: // ret: return from subroutine - next_pc = m_data->read_dword(m_r[R2]); - m_r[R2] += 4; + temp = m_data->read_dword(m_r[R2]); + if (!m_exception) + { + m_ip = temp; + m_r[R2] += 4; + } // TRAPS: C,U,A,P,R break; case 0x14: @@ -477,79 +529,75 @@ int clipper_device::execute_instruction () case 0x16: // popw: pop word m_r[R1] += 4; - m_r[R2] = m_data->read_dword(m_r[R1] - 4); + temp = m_data->read_dword(m_r[R1] - 4); + if (!m_exception) + m_r[R2] = temp; // TRAPS: C,U,A,P,R break; case 0x20: // adds: add single floating - set_fp32(R2, float32_add(get_fp32(R2), get_fp32(R1))); + set_fp(R2, float32_add(get_fp32(R2), get_fp32(R1)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x21: // subs: subtract single floating - set_fp32(R2, float32_sub(get_fp32(R2), get_fp32(R1))); + set_fp(R2, float32_sub(get_fp32(R2), get_fp32(R1)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x22: // addd: add double floating - set_fp64(R2, float64_add(get_fp64(R2), get_fp64(R1))); + set_fp(R2, float64_add(get_fp64(R2), get_fp64(R1)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x23: // subd: subtract double floating - set_fp64(R2, float64_sub(get_fp64(R2), get_fp64(R1))); + set_fp(R2, float64_sub(get_fp64(R2), get_fp64(R1)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x24: // movs: move single floating - set_fp32(R2, get_fp32(R1)); + set_fp(R2, get_fp32(R1), F_NONE); break; case 0x25: // cmps: compare single floating FLAGS(0, 0, float32_eq(get_fp32(R2), get_fp32(R1)), float32_lt(get_fp32(R2), get_fp32(R1))) + // flag unordered if (float_exception_flags & float_flag_invalid) m_psw |= PSW_Z | PSW_N; - float_exception_flags &= (0); + float_exception_flags &= F_NONE; break; case 0x26: // movd: move double floating - set_fp64(R2, get_fp64(R1)); + set_fp(R2, get_fp64(R1), F_NONE); break; case 0x27: // cmpd: compare double floating FLAGS(0, 0, float64_eq(get_fp64(R2), get_fp64(R1)), float64_lt(get_fp64(R2), get_fp64(R1))) + // flag unordered if (float_exception_flags & float_flag_invalid) m_psw |= PSW_Z | PSW_N; - float_exception_flags &= (0); + float_exception_flags &= F_NONE; break; case 0x28: // muls: multiply single floating - set_fp32(R2, float32_mul(get_fp32(R2), get_fp32(R1))); + set_fp(R2, float32_mul(get_fp32(R2), get_fp32(R1)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x29: // divs: divide single floating - set_fp32(R2, float32_div(get_fp32(R2), get_fp32(R1))); + set_fp(R2, float32_div(get_fp32(R2), get_fp32(R1)), F_IVDUX); // TRAPS: F_IVDUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_divbyzero | float_flag_underflow | float_flag_inexact); break; case 0x2a: // muld: multiply double floating - set_fp64(R2, float64_mul(get_fp64(R2), get_fp64(R1))); + set_fp(R2, float64_mul(get_fp64(R2), get_fp64(R1)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x2b: // divd: divide double floating - set_fp64(R2, float64_div(get_fp64(R2), get_fp64(R1))); + set_fp(R2, float64_div(get_fp64(R2), get_fp64(R1)), F_IVDUX); // TRAPS: F_IVDUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_divbyzero | float_flag_underflow | float_flag_inexact); break; case 0x2c: // movsw: move single floating to word @@ -557,7 +605,7 @@ int clipper_device::execute_instruction () break; case 0x2d: // movws: move word to single floating - set_fp32(R2, m_r[R1]); + set_fp(R2, m_r[R1], F_NONE); break; case 0x2e: // movdl: move double floating to longword @@ -565,7 +613,7 @@ int clipper_device::execute_instruction () break; case 0x2f: // movld: move longword to double floating - set_fp64(R2, ((u64 *)m_r)[R1 >> 1]); + set_fp(R2, ((u64 *)m_r)[R1 >> 1], F_NONE); break; case 0x30: // shaw: shift arithmetic word @@ -726,53 +774,53 @@ int clipper_device::execute_instruction () case 0x44: case 0x45: // call: call subroutine - m_r[R2] -= 4; - m_data->write_dword(m_r[R2], next_pc); - next_pc = m_info.address; + m_data->write_dword(m_r[R2] - 4, m_ip); + if (!m_exception) + { + m_ip = m_info.address; + m_r[R2] -= 4; + } // TRAPS: A,P,W break; -#ifdef UNIMPLEMENTED_C400 - case 0x46: - case 0x47: - // loadd2: - break; -#endif + case 0x48: case 0x49: // b*: branch on condition if (evaluate_branch()) - next_pc = m_info.address; + m_ip = m_info.address; // TRAPS: A,I break; -#ifdef UNIMPLEMENTED_C400 - case 0x4a: - case 0x4b: - // cdb: - break; - case 0x4c: - case 0x4d: - // cdbeq: - break; - case 0x4e: - case 0x4f: - // cdbne: - break; - case 0x50: - case 0x51: - // db*: - break; -#endif -#ifdef UNIMPLEMENTED + case 0x4c: case 0x4d: - // bf*: + // bf*: branch on floating exception + // FIXME: documentation is not clear, implementation is guesswork + switch (R2) + { + case BF_ANY: + // bfany: floating any exception + if (m_psw & (PSW_FI | PSW_FV | PSW_FD | PSW_FU | PSW_FX)) + m_ip = m_info.address; + break; + case BF_BAD: + // bfbad: floating bad result + if (m_psw & (PSW_FI | PSW_FD)) + m_ip = m_info.address; + break; + default: + // reserved + // FIXME: not sure if this should trigger an exception? + m_exception = EXCEPTION_ILLEGAL_OPERATION; + break; + } break; -#endif case 0x60: case 0x61: // loadw: load word - m_r[R2] = m_data->read_dword(m_info.address); + temp = m_data->read_dword(m_info.address); + if (!m_exception) + m_r[R2] = temp; // TRAPS: C,U,A,P,R,I break; case 0x62: @@ -784,37 +832,49 @@ int clipper_device::execute_instruction () case 0x64: case 0x65: // loads: load single floating - set_fp32(R2, m_data->read_dword(m_info.address)); + temp = m_data->read_dword(m_info.address); + if (!m_exception) + set_fp(R2, (float32)temp, F_NONE); // TRAPS: C,U,A,P,R,I break; case 0x66: case 0x67: // loadd: load double floating - set_fp64(R2, m_data->read_qword(m_info.address)); + temp = m_data->read_qword(m_info.address); + if (!m_exception) + set_fp(R2, (float64)temp, F_NONE); // TRAPS: C,U,A,P,R,I break; case 0x68: case 0x69: // loadb: load byte - m_r[R2] = (s8)m_data->read_byte(m_info.address); + temp = s64(s8(m_data->read_byte(m_info.address))); + if (!m_exception) + m_r[R2] = temp; // TRAPS: C,U,A,P,R,I break; case 0x6a: case 0x6b: // loadbu: load byte unsigned - m_r[R2] = m_data->read_byte(m_info.address); + temp = m_data->read_byte(m_info.address); + if (!m_exception) + m_r[R2] = temp; // TRAPS: C,U,A,P,R,I break; case 0x6c: case 0x6d: // loadh: load halfword - m_r[R2] = (s16)m_data->read_word(m_info.address); + temp = s64(s16(m_data->read_word(m_info.address))); + if (!m_exception) + m_r[R2] = temp; // TRAPS: C,U,A,P,R,I break; case 0x6e: case 0x6f: // loadhu: load halfword unsigned - m_r[R2] = m_data->read_word(m_info.address); + temp = m_data->read_word(m_info.address); + if (!m_exception) + m_r[R2] = temp; // TRAPS: C,U,A,P,R,I break; case 0x70: @@ -826,8 +886,13 @@ int clipper_device::execute_instruction () case 0x72: case 0x73: // tsts: test and set - m_r[R2] = m_data->read_dword(m_info.address); - m_data->write_dword(m_info.address, m_r[R2] | 0x80000000); + temp = m_data->read_dword(m_info.address); + if (!m_exception) + { + m_data->write_dword(m_info.address, temp | 0x80000000U); + if (!m_exception) + m_r[R2] = temp; + } // TRAPS: C,U,A,P,R,W,I break; case 0x74: @@ -845,14 +910,14 @@ int clipper_device::execute_instruction () case 0x78: case 0x79: // storb: store byte - m_data->write_byte(m_info.address, (u8)m_r[R2]); + m_data->write_byte(m_info.address, m_r[R2]); // TRAPS: A,P,W,I break; case 0x7c: case 0x7d: // storh: store halfword - m_data->write_word(m_info.address, (u16)m_r[R2]); + m_data->write_word(m_info.address, m_r[R2]); // TRAPS: A,P,W,I break; @@ -974,45 +1039,49 @@ int clipper_device::execute_instruction () // divw: divide word if (m_r[R1] != 0) { + // FLAGS: 0V00 FLAGS(0, m_r[R2] == INT32_MIN && m_r[R1] == -1, 0, 0) m_r[R2] = (s32)m_r[R2] / (s32)m_r[R1]; } else - next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); - // FLAGS: 0V00 - // TRAPS: D + // TRAPS: D + m_exception = EXCEPTION_INTEGER_DIVIDE_BY_ZERO; break; case 0x9d: // modw: modulus word if (m_r[R1] != 0) { + // FLAGS: 0V00 FLAGS(0, m_r[R2] == INT32_MIN && m_r[R1] == -1, 0, 0) m_r[R2] = (s32)m_r[R2] % (s32)m_r[R1]; } else - next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); - // FLAGS: 0V00 - // TRAPS: D + // TRAPS: D + m_exception = EXCEPTION_INTEGER_DIVIDE_BY_ZERO; break; case 0x9e: // divwu: divide word unsigned if (m_r[R1] != 0) + { m_r[R2] = m_r[R2] / m_r[R1]; + // FLAGS: 0000 + FLAGS(0, 0, 0, 0) + } else - next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); - FLAGS(0, 0, 0, 0) - // FLAGS: 0000 - // TRAPS: D + // TRAPS: D + m_exception = EXCEPTION_INTEGER_DIVIDE_BY_ZERO; break; case 0x9f: // modwu: modulus word unsigned if (m_r[R1] != 0) + { m_r[R2] = m_r[R2] % m_r[R1]; + // FLAGS: 0000 + FLAGS(0, 0, 0, 0) + } else - next_pc = intrap(EXCEPTION_INTEGER_DIVIDE_BY_ZERO, next_pc, CTS_DIVIDE_BY_ZERO); - FLAGS(0, 0, 0, 0) - // FLAGS: 0000 - // TRAPS: D + // TRAPS: D + m_exception = EXCEPTION_INTEGER_DIVIDE_BY_ZERO; break; case 0xa0: // subw: subtract word @@ -1082,16 +1151,6 @@ int clipper_device::execute_instruction () // FLAGS: 0001 break; -#ifdef UNIMPLEMENTED_C400 - case 0xb0: - // abss: absolute value single floating? - break; - - case 0xb2: - // absd: absolute value double floating? - break; -#endif - case 0xb4: // unprivileged macro instructions switch (m_info.subopcode) @@ -1103,11 +1162,12 @@ int clipper_device::execute_instruction () // savew0..savew12: push registers rN:r14 // store ri at sp - 4 * (15 - i) - for (int i = R2; i < 15; i++) + for (int i = R2; i < 15 && !m_exception; i++) m_data->write_dword(m_r[15] - 4 * (15 - i), m_r[i]); // decrement sp after push to allow restart on exceptions - m_r[15] -= 4 * (15 - R2); + if (!m_exception) + m_r[15] -= 4 * (15 - R2); // TRAPS: A,P,W break; // NOTE: the movc, initc and cmpc macro instructions are implemented in a very basic way because @@ -1119,7 +1179,13 @@ int clipper_device::execute_instruction () while (m_r[0]) { - m_data->write_byte(m_r[2], m_data->read_byte(m_r[1])); + const u8 byte = m_data->read_byte(m_r[1]); + if (m_exception) + break; + + m_data->write_byte(m_r[2], byte); + if (m_exception) + break; m_r[0]--; m_r[1]++; @@ -1131,7 +1197,9 @@ int clipper_device::execute_instruction () // initc: initialise r0 bytes at r1 with value in r2 while (m_r[0]) { - m_data->write_byte(m_r[1], m_r[2] & 0xff); + m_data->write_byte(m_r[1], m_r[2]); + if (m_exception) + break; m_r[0]--; m_r[1]++; @@ -1148,8 +1216,12 @@ int clipper_device::execute_instruction () while (m_r[0]) { // set condition codes and abort the loop if the current byte does not match - s32 byte1 = (s8)m_data->read_byte(m_r[1]); - s32 byte2 = (s8)m_data->read_byte(m_r[2]); + s32 byte1 = s8(m_data->read_byte(m_r[1])); + if (m_exception) + break; + s32 byte2 = s8(m_data->read_byte(m_r[2])); + if (m_exception) + break; if (byte1 != byte2) { FLAGS(C_SUB(byte2, byte1), V_SUB(byte2, byte1), byte2 == byte1, byte2 < byte1) @@ -1170,10 +1242,16 @@ int clipper_device::execute_instruction () // load ri from sp + 4 * (i - N) for (int i = R2; i < 15; i++) - m_r[i] = m_data->read_dword(m_r[15] + 4 * (i - R2)); + { + temp = m_data->read_dword(m_r[15] + 4 * (i - R2)); + if (m_exception) + break; + m_r[i] = temp; + } // increment sp after pop to allow restart on exceptions - m_r[15] += 4 * (15 - R2); + if (!m_exception) + m_r[15] += 4 * (15 - R2); // TRAPS: C,U,A,P,R break; @@ -1182,11 +1260,12 @@ int clipper_device::execute_instruction () // saved0..saved7: push registers fN:f7 // store fi at sp - 8 * (8 - i) - for (int i = R2; i < 8; i++) + for (int i = R2; i < 8 && !m_exception; i++) m_data->write_qword(m_r[15] - 8 * (8 - i), get_fp64(i)); // decrement sp after push to allow restart on exceptions - m_r[15] -= 8 * (8 - R2); + if (!m_exception) + m_r[15] -= 8 * (8 - R2); // TRAPS: A,P,W break; case 0x28: case 0x29: case 0x2a: case 0x2b: @@ -1195,10 +1274,16 @@ int clipper_device::execute_instruction () // load fi from sp + 8 * (i - N) for (int i = R2; i < 8; i++) - set_fp64(i, m_data->read_qword(m_r[15] + 8 * (i - R2))); + { + temp = m_data->read_qword(m_r[15] + 8 * (i - R2)); + if (m_exception) + break; + set_fp(i, (float64)temp, F_NONE); + } // increment sp after pop to allow restart on exceptions - m_r[15] += 8 * (8 - R2); + if (!m_exception) + m_r[15] += 8 * (8 - R2); // TRAPS: C,U,A,P,R break; case 0x30: @@ -1207,7 +1292,7 @@ int clipper_device::execute_instruction () m_r[m_info.macro & 0xf] = float32_to_int32(get_fp32((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX - float_exception_flags &= (float_flag_invalid | float_flag_inexact); + float_exception_flags &= F_IX; break; case 0x31: // cnvrsw: convert rounding single floating to word (non-IEEE +0.5/-0.5 rounding) @@ -1220,7 +1305,7 @@ int clipper_device::execute_instruction () m_r[m_info.macro & 0xf] = float32_to_int32_round_to_zero(float32_add(get_fp32((m_info.macro >> 4) & 0xf), float32_div(int32_to_float32(1), int32_to_float32(2)))); // TRAPS: F_IX - float_exception_flags &= (float_flag_invalid | float_flag_inexact); + float_exception_flags &= F_IX; break; case 0x32: // cnvtsw: convert truncating single floating to word @@ -1228,13 +1313,12 @@ int clipper_device::execute_instruction () m_r[m_info.macro & 0xf] = float32_to_int32_round_to_zero(get_fp32((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX - float_exception_flags &= (float_flag_invalid | float_flag_inexact); + float_exception_flags &= F_IX; break; case 0x33: // cnvws: convert word to single floating - set_fp32(m_info.macro & 0xf, int32_to_float32(m_r[(m_info.macro >> 4) & 0xf])); + set_fp(m_info.macro & 0xf, int32_to_float32(m_r[(m_info.macro >> 4) & 0xf]), F_X); // TRAPS: F_X - float_exception_flags &= (float_flag_inexact); break; case 0x34: // cnvdw: convert double floating to word @@ -1242,7 +1326,7 @@ int clipper_device::execute_instruction () m_r[m_info.macro & 0xf] = float64_to_int32(get_fp64((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX - float_exception_flags &= (float_flag_invalid | float_flag_inexact); + float_exception_flags &= F_IX; break; case 0x35: // cnvrdw: convert rounding double floating to word (non-IEEE +0.5/-0.5 rounding) @@ -1255,7 +1339,7 @@ int clipper_device::execute_instruction () m_r[m_info.macro & 0xf] = float64_to_int32_round_to_zero(float64_add(get_fp64((m_info.macro >> 4) & 0xf), float64_div(int32_to_float64(1), int32_to_float64(2)))); // TRAPS: F_IX - float_exception_flags &= (float_flag_invalid | float_flag_inexact); + float_exception_flags &= F_IX; break; case 0x36: // cnvtdw: convert truncating double floating to word @@ -1263,67 +1347,61 @@ int clipper_device::execute_instruction () m_r[m_info.macro & 0xf] = float64_to_int32_round_to_zero(get_fp64((m_info.macro >> 4) & 0xf)); // TRAPS: F_IX - float_exception_flags &= (float_flag_invalid | float_flag_inexact); + float_exception_flags &= F_IX; break; case 0x37: // cnvwd: convert word to double floating - set_fp64(m_info.macro & 0xf, int32_to_float64(m_r[(m_info.macro >> 4) & 0xf])); - float_exception_flags &= (0); + set_fp(m_info.macro & 0xf, int32_to_float64(m_r[(m_info.macro >> 4) & 0xf]), F_NONE); break; case 0x38: // cnvsd: convert single to double floating - set_fp64(m_info.macro & 0xf, float32_to_float64(get_fp32((m_info.macro >> 4) & 0xf))); + set_fp(m_info.macro & 0xf, float32_to_float64(get_fp32((m_info.macro >> 4) & 0xf)), F_I); // TRAPS: F_I - float_exception_flags &= (float_flag_invalid); break; case 0x39: // cnvds: convert double to single floating - set_fp32(m_info.macro & 0xf, float64_to_float32(get_fp64((m_info.macro >> 4) & 0xf))); + set_fp(m_info.macro & 0xf, float64_to_float32(get_fp64((m_info.macro >> 4) & 0xf)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x3a: // negs: negate single floating - set_fp32(m_info.macro & 0xf, float32_mul(get_fp32((m_info.macro >> 4) & 0xf), int32_to_float32(-1))); - float_exception_flags &= (0); + set_fp(m_info.macro & 0xf, float32_mul(get_fp32((m_info.macro >> 4) & 0xf), int32_to_float32(-1)), F_NONE); break; case 0x3b: // negd: negate double floating - set_fp64(m_info.macro & 0xf, float64_mul(get_fp64((m_info.macro >> 4) & 0xf), int32_to_float64(-1))); - float_exception_flags &= (0); + set_fp(m_info.macro & 0xf, float64_mul(get_fp64((m_info.macro >> 4) & 0xf), int32_to_float64(-1)), F_NONE); break; case 0x3c: /* - * This implementation for scalbd and scalbs is a bit opaque, but - * essentially we check if the integer value is within range, and - * directly create a floating constant representing 2^n or NaN - * respectively, which is used as an input to a multiply, producing - * the desired result. While doing an actual multiply is both - * inefficient and unnecessary, it's a tidy way to ensure the - * correct exception flags are set. - */ + * This implementation for scalbd and scalbs is a bit opaque, but + * essentially we check if the integer value is within range, and + * directly create a floating constant representing 2^n or NaN + * respectively, which is used as an input to a multiply, producing + * the desired result. While doing an actual multiply is both + * inefficient and unnecessary, it's a tidy way to ensure the + * correct exception flags are set. + */ // scalbs: scale by, single floating - set_fp32(m_info.macro & 0xf, float32_mul(get_fp32(m_info.macro & 0xf), + set_fp(m_info.macro & 0xf, float32_mul(get_fp32(m_info.macro & 0xf), (((s32)m_r[(m_info.macro >> 4) & 0xf] > -127 && (s32)m_r[(m_info.macro >> 4) & 0xf] < 128) ? (float32)(((s32)m_r[(m_info.macro >> 4) & 0xf] + 127) << 23) - : (float32)~u32(0)))); + : (float32)~u32(0))), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x3d: // scalbd: scale by, double floating - set_fp64(m_info.macro & 0xf, float64_mul(get_fp64(m_info.macro & 0xf), + set_fp(m_info.macro & 0xf, float64_mul(get_fp64(m_info.macro & 0xf), ((s32)m_r[(m_info.macro >> 4) & 0xf] > -1023 && (s32)m_r[(m_info.macro >> 4) & 0xf] < 1024) ? (float64)((u64)((s32)m_r[(m_info.macro >> 4) & 0xf] + 1023) << 52) - : (float64)~u64(0))); + : (float64)~u64(0)), F_IVUX); // TRAPS: F_IVUX - float_exception_flags &= (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact); break; case 0x3e: // trapfn: trap floating unordered - if (PSW(Z) && PSW(N)) - next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); // TRAPS: I + if (PSW(Z) && PSW(N)) + m_exception = EXCEPTION_ILLEGAL_OPERATION; + break; case 0x3f: // loadfs: load floating status m_r[(m_info.macro >> 4) & 0xf] = m_fp_pc; @@ -1332,9 +1410,7 @@ int clipper_device::execute_instruction () break; default: - LOG("illegal unprivileged macro opcode at 0x%08x\n", m_pc); - next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); - machine().debug_break(); + m_exception = EXCEPTION_ILLEGAL_OPERATION; break; } break; @@ -1361,77 +1437,80 @@ int clipper_device::execute_instruction () break; case 0x02: // saveur: save user registers - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16 && !m_exception; i++) m_data->write_dword(m_rs[(m_info.macro >> 4) & 0xf] - 4 * (i + 1), m_ru[15 - i]); - m_rs[(m_info.macro >> 4) & 0xf] -= 64; + if (!m_exception) + m_rs[(m_info.macro >> 4) & 0xf] -= 64; // TRAPS: A,P,W,S break; case 0x03: // restur: restore user registers for (int i = 0; i < 16; i++) - m_ru[i] = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4 * i); + { + temp = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4 * i); + if (m_exception) + break; + m_ru[i] = temp; + } - m_rs[(m_info.macro >> 4) & 0xf] += 64; + if (!m_exception) + m_rs[(m_info.macro >> 4) & 0xf] += 64; // TRAPS: C,U,A,P,R,S break; case 0x04: // reti: restore psw, ssw and pc from supervisor stack - LOGMASKED(LOG_INTERRUPT, "reti r%d ssp 0x%08x pc 0x%08x next_pc 0x%08x\n", - (m_info.macro >> 4) & 0xf, m_rs[(m_info.macro >> 4) & 0xf], m_pc, m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8)); - - m_psw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 0); - set_ssw(m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4)); - next_pc = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8); - - m_rs[(m_info.macro >> 4) & 0xf] += 12; - - m_r = SSW(U) ? m_ru : m_rs; - - fp_rounding(); - + m_ip = reti(); // TRAPS: S break; case 0x05: // wait: wait for interrupt - next_pc = m_pc; + m_ip = m_pc; // TRAPS: S break; -#ifdef UNIMPLEMENTED_C400 - case 0x07: - // loadts: unknown? - break; -#endif default: - // illegal operation - LOG("illegal privileged macro opcode at 0x%08x\n", m_pc); - next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); - machine().debug_break(); + m_exception = EXCEPTION_ILLEGAL_OPERATION; break; } } else - next_pc = intrap(EXCEPTION_PRIVILEGED_INSTRUCTION, next_pc, CTS_PRIVILEGED_INSTRUCTION); - break; - -#ifdef UNIMPLEMENTED_C400 - case 0xbc: - // waitd: - break; - - case 0xc0: - // s*: + m_exception = EXCEPTION_PRIVILEGED_INSTRUCTION; break; -#endif default: - LOG("illegal opcode at 0x%08x\n", m_pc); - next_pc = intrap(EXCEPTION_ILLEGAL_OPERATION, next_pc, CTS_ILLEGAL_OPERATION); + m_exception = EXCEPTION_ILLEGAL_OPERATION; break; } +} + +u32 clipper_device::reti() +{ + // fetch the psw, ssw and pc from the supervisor stack + const u32 new_psw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 0); + if (m_exception) + fatalerror("reti unrecoverable fault 0x%04x read psw address 0x%08x pc 0x%08x\n", m_exception, m_rs[(m_info.macro >> 4) & 0xf] + 0, m_pc); - return next_pc; + const u32 new_ssw = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 4); + if (m_exception) + fatalerror("reti unrecoverable fault 0x%04x read ssw address 0x%08x pc 0x%08x\n", m_exception, m_rs[(m_info.macro >> 4) & 0xf] + 4, m_pc); + + const u32 new_pc = m_data->read_dword(m_rs[(m_info.macro >> 4) & 0xf] + 8); + if (m_exception) + fatalerror("reti unrecoverable fault 0x%04x read pc address 0x%08x pc 0x%08x\n", m_exception, m_rs[(m_info.macro >> 4) & 0xf] + 8, m_pc); + + LOGMASKED(LOG_EXCEPTION, "reti r%d ssp 0x%08x pc 0x%08x ssw 0x%08x psw 0x%08x new_pc 0x%08x new_ssw 0x%08x new_psw 0x%08x\n", + (m_info.macro >> 4) & 0xf, m_rs[(m_info.macro >> 4) & 0xf], m_pc, m_ssw, m_psw, new_pc, new_ssw, new_psw); + + // pop the stack + m_rs[(m_info.macro >> 4) & 0xf] += 12; + + // restore the psw and ssw + set_psw(new_psw); + set_ssw(new_ssw); + + // return the restored pc + return new_pc; } /* @@ -1439,74 +1518,90 @@ int clipper_device::execute_instruction () * exception. Reading between the lines, it appears this logic was implemented * using the macro instruction ROM and a special macro instruction (intrap). */ -u32 clipper_device::intrap(u16 vector, u32 pc, u32 cts, u32 mts) +u32 clipper_device::intrap(const u16 vector, const u32 old_pc) { - // fetch pc and ssw from interrupt vector - u32 next_pc = m_data->read_dword(vector + 0); - u32 next_ssw = m_data->read_dword(vector + 4); - - LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%04x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); + const u32 old_ssw = m_ssw; + const u32 old_psw = m_psw; - // set cts and mts to indicate source of exception - m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts; + // clear ssw bits to enable supervisor memory access + m_ssw &= ~(SSW_U | SSW_K | SSW_UU | SSW_KU); - // push pc, ssw and psw onto supervisor stack - m_data->write_dword(m_rs[15] - 0x4, pc); - m_data->write_dword(m_rs[15] - 0x8, m_ssw); - m_data->write_dword(m_rs[15] - 0xc, m_psw); + // clear exception state + m_exception = 0; - // decrement supervisor stack pointer - m_rs[15] -= 12; + // fetch next pc and ssw from interrupt vector + const u32 new_pc = m_data->read_dword(vector + get_evpc_offset()); + if (m_exception) + fatalerror("intrap unrecoverable fault 0x%04x read pc address 0x%08x pc 0x%08x\n", m_exception, vector + get_evpc_offset(), old_pc); - // load ssw from trap vector and set previous mode - set_ssw((next_ssw & ~(SSW(P))) | (SSW(U) << 1)); + const u32 new_ssw = m_data->read_dword(vector + get_evssw_offset()); + if (m_exception) + fatalerror("intrap unrecoverable fault 0x%04x read ssw address 0x%08x pc 0x%08x\n", m_exception, vector + get_evssw_offset(), old_pc); - // clear psw - m_psw = 0; - float_rounding_mode = float_round_nearest_even; + LOGMASKED(LOG_EXCEPTION, "intrap vector 0x%04x pc 0x%08x ssp 0x%08x new_pc 0x%08x new_ssw 0x%08x\n", vector, old_pc, m_rs[15], new_pc, new_ssw); - m_r = SSW(U) ? m_ru : m_rs; + // derive cts and mts from vector + u32 source = 0; + switch (vector) + { + // data memory trap group + case EXCEPTION_D_CORRECTED_MEMORY_ERROR: + case EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR: + case EXCEPTION_D_ALIGNMENT_FAULT: + case EXCEPTION_D_PAGE_FAULT: + case EXCEPTION_D_READ_PROTECT_FAULT: + case EXCEPTION_D_WRITE_PROTECT_FAULT: - // return new pc from trap vector - return next_pc; -} + // instruction memory trap group + case EXCEPTION_I_CORRECTED_MEMORY_ERROR: + case EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR: + case EXCEPTION_I_ALIGNMENT_FAULT: + case EXCEPTION_I_PAGE_FAULT: + case EXCEPTION_I_EXECUTE_PROTECT_FAULT: + source = (vector & MTS_VMASK) << (MTS_SHIFT - MTS_VSHIFT); + break; -u32 clipper_c400_device::intrap(u16 vector, u32 pc, u32 cts, u32 mts) -{ - // C400 reverses order of pc and ssw in interrupt vector - u32 next_pc = m_data->read_dword(vector + 4); - u32 next_ssw = m_data->read_dword(vector + 0); + // integer arithmetic trap group + case EXCEPTION_INTEGER_DIVIDE_BY_ZERO: + source = CTS_DIVIDE_BY_ZERO; + break; - LOGMASKED(LOG_INTERRUPT, "intrap vector 0x%04x pc 0x%08x next_pc 0x%08x ssp 0x%08x\n", vector, pc, next_pc, m_rs[15]); + // illegal operation trap group + case EXCEPTION_ILLEGAL_OPERATION: + source = CTS_ILLEGAL_OPERATION; + break; + case EXCEPTION_PRIVILEGED_INSTRUCTION: + source = CTS_PRIVILEGED_INSTRUCTION; + break; - // set cts and mts to indicate source of exception - m_psw = (m_psw & ~(PSW_CTS | PSW_MTS)) | mts | cts; + // diagnostic trap group + case EXCEPTION_TRACE: + source = CTS_TRACE_TRAP; + break; + } // push pc, ssw and psw onto supervisor stack - m_data->write_dword(m_rs[15] - 0x4, pc); - m_data->write_dword(m_rs[15] - 0x8, m_ssw); - m_data->write_dword(m_rs[15] - 0xc, m_psw); + m_data->write_dword(m_rs[15] - 0x4, old_pc); + if (m_exception) + fatalerror("intrap unrecoverable fault 0x%04x write pc address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x4, old_pc); + m_data->write_dword(m_rs[15] - 0x8, old_ssw); + if (m_exception) + fatalerror("intrap unrecoverable fault 0x%04x write ssw address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0x8, old_pc); + m_data->write_dword(m_rs[15] - 0xc, (old_psw & ~(PSW_CTS | PSW_MTS)) | source); + if (m_exception) + fatalerror("intrap unrecoverable fault 0x%04x write psw address 0x%08x pc 0x%08x\n", m_exception, m_rs[15] - 0xc, old_pc); // decrement supervisor stack pointer + m_rs[15] -= get_eframe_size(); - // NOTE: while not explicitly stated anywhere, it seems the InterPro C400 boot code has been - // developed with the assumption that the SSP is decremented by 24 bytes during an exception, - // rather than the 12 bytes for the InterPro C300 version. This means the exception handler - // code must explicitly increment the SSP by 12 prior to executing the RETI instruction, - // as otherwise the SSP will not be pointing at a valid return frame. - m_rs[15] -= 24; - - // load ssw from trap vector and set previous mode - set_ssw((next_ssw & ~(SSW(P))) | (SSW(U) << 1)); + // set ssw from vector and previous mode + set_ssw((new_ssw & ~SSW_P) | (old_ssw & SSW_U) << 1); // clear psw - m_psw = 0; - float_rounding_mode = float_round_nearest_even; - - m_r = SSW(U) ? m_ru : m_rs; + set_psw(0); // return new pc from trap vector - return next_pc; + return new_pc; } bool clipper_device::evaluate_branch() const @@ -1569,8 +1664,11 @@ bool clipper_device::evaluate_branch() const return false; } -void clipper_device::fp_rounding() +void clipper_device::set_psw(const u32 psw) { + // retain read-only endianness field + m_psw = (m_psw & PSW_BIG) | (psw & ~PSW_BIG); + // set the softfloat rounding mode based on the psw rounding mode switch (PSW(FR)) { @@ -1581,9 +1679,18 @@ void clipper_device::fp_rounding() } } +void clipper_device::set_ssw(const u32 ssw) +{ + // retain read-only id field + m_ssw = (m_ssw & SSW_ID) | (ssw & ~SSW_ID); + + // select the register file + m_r = SSW(U) ? m_ru : m_rs; +} + void clipper_device::fp_exception() { - u16 vector = 0; + u16 exception = 0; /* * Set the psw floating exception flags, and identify any enabled @@ -1595,62 +1702,99 @@ void clipper_device::fp_exception() { m_psw |= PSW_FX; if (PSW(EFX)) - vector = EXCEPTION_FLOATING_INEXACT; + exception = EXCEPTION_FLOATING_INEXACT; } if (float_exception_flags & float_flag_underflow) { m_psw |= PSW_FU; if (PSW(EFU)) - vector = EXCEPTION_FLOATING_UNDERFLOW; + exception = EXCEPTION_FLOATING_UNDERFLOW; } if (float_exception_flags & float_flag_overflow) { m_psw |= PSW_FV; if (PSW(EFV)) - vector = EXCEPTION_FLOATING_OVERFLOW; + exception = EXCEPTION_FLOATING_OVERFLOW; } if (float_exception_flags & float_flag_divbyzero) { m_psw |= PSW_FD; if (PSW(EFD)) - vector = EXCEPTION_FLOATING_DIVIDE_BY_ZERO; + exception = EXCEPTION_FLOATING_DIVIDE_BY_ZERO; } if (float_exception_flags & float_flag_invalid) { m_psw |= PSW_FI; if (PSW(EFI)) - vector = EXCEPTION_FLOATING_INVALID_OPERATION; + exception = EXCEPTION_FLOATING_INVALID_OPERATION; } // trigger a floating point exception - if (PSW(EFT) && vector) - m_pc = intrap(vector, m_pc); + if (PSW(EFT) && exception) + m_exception = exception; } -inline void clipper_device::set_fp32(const u8 reg, const float32 data) +void clipper_c400_device::execute_instruction() { - // save floating exception state - m_fp_pc = m_pc; - m_fp_dst = m_f[reg & 0xf]; + switch (m_info.opcode) + { +#ifdef UNIMPLEMENTED_C400 + case 0x46: + case 0x47: + // loadd2: + break; - // assign data - m_f[reg & 0xf] = data; + case 0x4a: + case 0x4b: + // cdb: + break; + case 0x4c: + case 0x4d: + // cdbeq: + break; + case 0x4e: + case 0x4f: + // cdbne: + break; + case 0x50: + case 0x51: + // db*: + break; - // set floating dirty flag - m_ssw |= SSW_FRD; -} + case 0xb0: + // abss: absolute value single floating? + break; -inline void clipper_device::set_fp64(const u8 reg, const float64 data) -{ - // save floating exception state - m_fp_pc = m_pc; - m_fp_dst = m_f[reg & 0xf]; + case 0xb2: + // absd: absolute value double floating? + break; + + case 0xb6: + // privileged macro instructions + if (!SSW(U)) + { + switch (m_info.subopcode) + { + case 0x07: + // loadts: unknown? + break; + } + } + break; + + case 0xbc: + // waitd: + break; - // assign data - m_f[reg & 0xf] = data; + case 0xc0: + // s*: + break; +#endif - // set floating dirty flag - m_ssw |= SSW_FRD; + default: + clipper_device::execute_instruction(); + break; + } } util::disasm_interface *clipper_device::create_disassembler() diff --git a/src/devices/cpu/clipper/clipper.h b/src/devices/cpu/clipper/clipper.h index 667e835d8c8..1781401fece 100644 --- a/src/devices/cpu/clipper/clipper.h +++ b/src/devices/cpu/clipper/clipper.h @@ -19,55 +19,48 @@ class clipper_device : public cpu_device public: DECLARE_READ32_MEMBER(get_ssw) const { return m_ssw; } DECLARE_WRITE8_MEMBER(set_ivec) { m_ivec = data; } + DECLARE_WRITE16_MEMBER(set_exception); -protected: - enum registers + enum addressing_modes : u8 { - CLIPPER_R0, CLIPPER_R1, CLIPPER_R2, CLIPPER_R3, CLIPPER_R4, CLIPPER_R5, CLIPPER_R6, CLIPPER_R7, - CLIPPER_R8, CLIPPER_R9, CLIPPER_R10, CLIPPER_R11, CLIPPER_R12, CLIPPER_R13, CLIPPER_R14, CLIPPER_R15, - - CLIPPER_F0, CLIPPER_F1, CLIPPER_F2, CLIPPER_F3, CLIPPER_F4, CLIPPER_F5, CLIPPER_F6, CLIPPER_F7, - CLIPPER_F8, CLIPPER_F9, CLIPPER_F10, CLIPPER_F11, CLIPPER_F12, CLIPPER_F13, CLIPPER_F14, CLIPPER_F15, - - CLIPPER_PSW, - CLIPPER_SSW, - CLIPPER_PC, + ADDR_MODE_PC32 = 0x10, // pc relative with 32 bit displacement + ADDR_MODE_ABS32 = 0x30, // 32 bit absolute + ADDR_MODE_REL32 = 0x60, // relative with 32 bit displacement + ADDR_MODE_PC16 = 0x90, // pc relative with 16 bit displacement + ADDR_MODE_REL12 = 0xa0, // relative with 12 bit displacement + ADDR_MODE_ABS16 = 0xb0, // 16 bit absolute + ADDR_MODE_PCX = 0xd0, // pc indexed + ADDR_MODE_RELX = 0xe0 // relative indexed }; - enum addressing_modes + // branch conditions (first description for comparison, second for move/logical) + enum branch_conditions : u8 { - ADDR_MODE_PC32 = 0x10, - ADDR_MODE_ABS32 = 0x30, - ADDR_MODE_REL32 = 0x60, - ADDR_MODE_PC16 = 0x90, - ADDR_MODE_REL12 = 0xa0, - ADDR_MODE_ABS16 = 0xb0, - ADDR_MODE_PCX = 0xd0, - ADDR_MODE_RELX = 0xe0, + BRANCH_T = 0x0, // always + BRANCH_LT = 0x1, // less than greater than + BRANCH_LE = 0x2, // less or equal greater or equal + BRANCH_EQ = 0x3, // equal + BRANCH_GT = 0x4, // greater than less than + BRANCH_GE = 0x5, // greater or equal less or equal + BRANCH_NE = 0x6, // not equal + BRANCH_LTU = 0x7, // less than unsigned greater than unsigned + BRANCH_LEU = 0x8, // less or equal unsigned greater or equal unsigned + BRANCH_GTU = 0x9, // greater than unsigned less than unsigned + BRANCH_GEU = 0xa, // greater or equal unsigned less or equal unsigned + BRANCH_V = 0xb, // overflow + BRANCH_NV = 0xc, // not overflow + BRANCH_N = 0xd, // negative + BRANCH_NN = 0xe, // not negative + BRANCH_FN = 0xf // floating unordered }; - // branch conditions - enum branch_conditions + enum bf_conditions : u8 { - BRANCH_T = 0x0, - BRANCH_LT = 0x1, - BRANCH_LE = 0x2, - BRANCH_EQ = 0x3, - BRANCH_GT = 0x4, - BRANCH_GE = 0x5, - BRANCH_NE = 0x6, - BRANCH_LTU = 0x7, - BRANCH_LEU = 0x8, - BRANCH_GTU = 0x9, - BRANCH_GEU = 0xa, - BRANCH_V = 0xb, - BRANCH_NV = 0xc, - BRANCH_N = 0xd, - BRANCH_NN = 0xe, - BRANCH_FN = 0xf, + BF_ANY = 0x0, // floating any exception + BF_BAD = 0x1 // floating bad result }; - enum psw + enum psw : u32 { PSW_N = 0x00000001, // negative PSW_Z = 0x00000002, // zero @@ -90,10 +83,10 @@ protected: PSW_BIG = 0x00400000, // c400 - big endian (hardware) PSW_T = 0x00800000, // trace trap PSW_CTS = 0x0f000000, // cpu trap status (4 bits) - PSW_MTS = 0xf0000000, // memory trap status (4 bits) + PSW_MTS = 0xf0000000 // memory trap status (4 bits) }; - enum psw_fr + enum psw_fr : u32 { FR_0 = 0x00000000, // round to nearest FR_1 = 0x00008000, // round toward + infinity @@ -101,7 +94,7 @@ protected: FR_3 = 0x00018000 // round toward zero }; - enum ssw + enum ssw : u32 { SSW_IN = 0x0000000f, // interrupt number (4 bits) SSW_IL = 0x000000f0, // interrupt level (4 bits) @@ -110,17 +103,17 @@ protected: // unused (5 bits) SSW_FRD = 0x00400000, // floating registers dirty SSW_TP = 0x00800000, // trace trap pending - SSW_ECM = 0x01000000, // enabled corrected memory error + SSW_ECM = 0x01000000, // enable corrected memory error SSW_DF = 0x02000000, // fpu disabled SSW_M = 0x04000000, // mapped mode SSW_KU = 0x08000000, // user protect key SSW_UU = 0x10000000, // user data mode SSW_K = 0x20000000, // protect key SSW_U = 0x40000000, // user mode - SSW_P = 0x80000000, // previous mode + SSW_P = 0x80000000 // previous mode }; - enum ssw_id + enum ssw_id : u32 { SSW_ID_C400R0 = 0x00000, SSW_ID_C400R1 = 0x04000, @@ -129,7 +122,7 @@ protected: SSW_ID_C400R4 = 0x10000 }; - enum exception_vectors + enum exception_vectors : u16 { // data memory trap group EXCEPTION_D_CORRECTED_MEMORY_ERROR = 0x108, @@ -167,37 +160,55 @@ protected: EXCEPTION_SUPERVISOR_CALL_BASE = 0x400, // prioritized interrupts (0x800-0xff8) - EXCEPTION_INTERRUPT_BASE = 0x800, + EXCEPTION_INTERRUPT_BASE = 0x800 }; // trap source values are shifted into the correct field in the psw - enum cpu_trap_sources + static const int CTS_SHIFT = 24; + enum cpu_trap_sources : u32 { - CTS_NO_CPU_TRAP = 0 << 24, - CTS_DIVIDE_BY_ZERO = 2 << 24, - CTS_ILLEGAL_OPERATION = 4 << 24, - CTS_PRIVILEGED_INSTRUCTION = 5 << 24, - CTS_TRACE_TRAP = 7 << 24, + CTS_NO_CPU_TRAP = 0 << CTS_SHIFT, + CTS_DIVIDE_BY_ZERO = 2 << CTS_SHIFT, + CTS_ILLEGAL_OPERATION = 4 << CTS_SHIFT, + CTS_PRIVILEGED_INSTRUCTION = 5 << CTS_SHIFT, + CTS_TRACE_TRAP = 7 << CTS_SHIFT }; - enum memory_trap_sources + static const int MTS_SHIFT = 28; + enum memory_trap_sources : u32 { - MTS_NO_MEMORY_TRAP = 0 << 28, - MTS_CORRECTED_MEMORY_ERROR = 1 << 28, - MTS_UNCORRECTABLE_MEMORY_ERROR = 2 << 28, - MTS_ALIGNMENT_FAULT = 4 << 28, - MTS_PAGE_FAULT = 5 << 28, - MTS_READ_OR_EXECUTE_PROTECT_FAULT = 6 << 28, - MTS_WRITE_PROTECT_FAULT = 7 << 28, + MTS_NO_MEMORY_TRAP = 0 << MTS_SHIFT, + MTS_CORRECTED_MEMORY_ERROR = 1 << MTS_SHIFT, + MTS_UNCORRECTABLE_MEMORY_ERROR = 2 << MTS_SHIFT, + MTS_ALIGNMENT_FAULT = 4 << MTS_SHIFT, + MTS_PAGE_FAULT = 5 << MTS_SHIFT, + MTS_READ_OR_EXECUTE_PROTECT_FAULT = 6 << MTS_SHIFT, + MTS_WRITE_PROTECT_FAULT = 7 << MTS_SHIFT }; - enum ivec_mask + // extract an mts code from a vector + static const u32 MTS_VMASK = 0x00000038; + static const int MTS_VSHIFT = 3; + + enum ivec_mask : u8 { IVEC_NUMBER = 0x0f, IVEC_LEVEL = 0xf0 }; - clipper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const u32 cpuid); + // combinations of floating point exceptions (from softfloat flags) + enum fp_exception_mask : u8 + { + F_NONE = (0), + F_I = (float_flag_invalid), + F_X = (float_flag_inexact), + F_IX = (float_flag_invalid | float_flag_inexact), + F_IVUX = (float_flag_invalid | float_flag_overflow | float_flag_underflow | float_flag_inexact), + F_IVDUX = (float_flag_invalid | float_flag_overflow | float_flag_divbyzero | float_flag_underflow | float_flag_inexact) + }; + +protected: + clipper_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, const endianness_t endianness, const u32 cpuid); // device-level overrides virtual void device_start() override; @@ -214,77 +225,147 @@ protected: virtual space_config_vector memory_space_config() const override; // device_state_interface overrides -#if 0 - virtual void state_import(const device_state_entry &entry) override; - virtual void state_export(const device_state_entry &entry) override; -#endif virtual void state_string_export(const device_state_entry &entry, std::string &str) const override; // device_disasm_interface overrides virtual util::disasm_interface *create_disassembler() override; - void set_ssw(u32 data) { m_ssw = (m_ssw & SSW(ID)) | (data & ~SSW(ID)); } + // cpu execution logic + bool decode_instruction(); + virtual void execute_instruction(); + bool evaluate_branch() const; - inline float32 get_fp32(const u8 reg) const { return m_f[reg & 0xf]; }; - inline float64 get_fp64(const u8 reg) const { return m_f[reg & 0xf]; }; - inline void set_fp32(const u8 reg, const float32 data); - inline void set_fp64(const u8 reg, const float64 data); + // exception entry and return helpers + u32 intrap(const u16 vector, const u32 old_pc); + u32 reti(); - // core registers - u32 m_pc; - u32 m_psw; - u32 m_ssw; + // cpu state helpers + void set_psw(const u32 psw); + void set_ssw(const u32 ssw); + void fp_exception(); - // integer registers - u32 *m_r; // active registers - u32 m_ru[16]; // user registers - u32 m_rs[16]; // supervisor registers + // register count helpers + virtual int get_ireg_count() const { return 16; } + virtual int get_freg_count() const { return 8; } - // floating point registers - u64 m_f[16]; + // exception vector and frame helpers + virtual int get_eframe_size() const { return 12; } + virtual int get_evpc_offset() const { return 0; } + virtual int get_evssw_offset() const { return 4; } - u32 m_fp_pc; // address of floating point instruction causing exception - u64 m_fp_dst; // original value of destination register during fp exception + // floating point helpers + float32 get_fp32(const u8 reg) const { return m_f[reg & 0xf]; } + float64 get_fp64(const u8 reg) const { return m_f[reg & 0xf]; } + template <typename T> void set_fp(const u8 reg, const T data, const fp_exception_mask exception_mask) + { + // suppress unexpected exceptions + float_exception_flags &= exception_mask; + + // save floating exception state + m_fp_pc = m_pc; + m_fp_dst = m_f[reg & 0xf]; + + // assign data + if (float_exception_flags & float_flag_overflow && PSW(EFV)) + { + /* + * If the EFV flag is set, the computed result is delivered to the + * destination with the normalized rounded fraction of the true + * result (though the delivered exponent is usually wrong because + * of missing additional leading bits in the exponent field). For + * single-precision overflows, if the biased exponent of the true + * result is 255, then biased exponent 255 is delivered to the + * destination. If the true biased exponent of the result is + * 256..408, then the true biased exponent minus 256 is delivered + * to the destination. Note that this is not the exponent wrapped + * result called for by the IEEE 754 specification; the wrap must + * be adjusted by system software before delivery to a user's trap + * handler. This is done to allow the user to provide software that + * handles traps in an application-specific way. For double- + * precision, the overflow exponents (biased) lie in the range + * 2047..3120. These are mapped to 2047 and 0..1072 respectively. + * These must be adjusted by (3/4)x2^11 (1536) to obtain the IEEE + * Standard wrapped exponent. + */ + // FIXME: implement non-IEEE behaviour described above + m_f[reg & 0xf] = data; + } + else if (float_exception_flags & float_flag_underflow && PSW(EFU)) + { + /* + * If EFU is set, the floating underflow exception is signalled + * when the result of an operation (before rounding) has a biased + * exponent less than the minimum representable biased exponent for + * a normalized number. If the true biased exponent of the result + * is zero, then biased exponent zero is delivered to the + * destination. If the true biased exponent is less than zero, then + * the exponent delivered to the destination is true biased + * exponent plus 256 (2048 for double). The exponent must be + * adjusted by system software before delivery to the program's + * trap handler in order to conform to the IEEE 754 specification. + * The range of underflowed biased exponents for single-precision + * is 0..-275; for double-precision the range is 0..-1125. + */ + // FIXME: implement non-IEEE behaviour described above + m_f[reg & 0xf] = data; + } + else + m_f[reg & 0xf] = data; + + // set floating dirty flag + m_ssw |= SSW_FRD; + }; + // emulation state address_space_config m_insn_config; address_space_config m_data_config; address_space *m_insn; address_space *m_data; -private: - int m_icount; + enum registers + { + CLIPPER_IREG = 0, + CLIPPER_FREG = 16, + CLIPPER_PSW = 32, + CLIPPER_SSW = 33, + CLIPPER_PC = 34, + }; - int m_irq; - int m_nmi; - u8 m_ivec; + int m_icount; // instruction cycle count + + // program-visible cpu state + u32 m_pc; // current instruction address + u32 m_psw; // program status word + u32 m_ssw; // system status word + + u32 *m_r; // active registers + u32 m_ru[16]; // user registers + u32 m_rs[16]; // supervisor registers + + u64 m_f[16]; // floating point registers + u32 m_fp_pc; // address of floating point instruction causing exception + u64 m_fp_dst; // original value of destination register during fp exception + + // non-visible cpu state + u32 m_ip; // next instruction address + int m_irq; // interrupt request state + int m_nmi; // non-maskable interrupt state + u8 m_ivec; // interrupt vector + u16 m_exception; // pending exception // decoded instruction information struct decode { - // various decoded instruction fields - u8 opcode, subopcode; - u8 r1, r2; - u32 imm; - u16 macro; - - // total size of instruction in bytes - u32 size; - - // computed effective address - u32 address; + u8 opcode; // primary instruction opcode + u8 subopcode; // secondary instruction opcode + u8 r1; // r1 instruction operand + u8 r2; // r2 instruction operand + u32 imm; // immediate value operand + u16 macro; // macro instruction operands + u32 address; // computed effective address } m_info; - - void decode_instruction(u16 insn); - int execute_instruction(); - bool evaluate_branch() const; - - void fp_rounding(); - void fp_exception(); - -protected: - virtual u32 intrap(u16 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP); }; class clipper_c100_device : public clipper_device @@ -305,7 +386,19 @@ public: clipper_c400_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); protected: - virtual u32 intrap(u16 vector, u32 pc, u32 cts = CTS_NO_CPU_TRAP, u32 mts = MTS_NO_MEMORY_TRAP) override; + // C400 has additional 8 floating point registers + virtual int get_freg_count() const override { return 16; } + + // C400 creates a 24 byte exception frame (C100/C300 is 12 bytes), but the + // service routine must increment sp by 12 prior to executing reti + // exception frame size + virtual int get_eframe_size() const override { return 24; } + + // C400 pc and ssw are reversed in exception vector compared to C100/C300 + virtual int get_evpc_offset() const override { return 4; } + virtual int get_evssw_offset() const override { return 0; } + + virtual void execute_instruction() override; }; DECLARE_DEVICE_TYPE(CLIPPER_C100, clipper_c100_device) diff --git a/src/devices/cpu/clipper/clipperd.h b/src/devices/cpu/clipper/clipperd.h index cad59a490de..1dd757fde63 100644 --- a/src/devices/cpu/clipper/clipperd.h +++ b/src/devices/cpu/clipper/clipperd.h @@ -16,17 +16,16 @@ public: virtual offs_t disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) override; private: - // the CLIPPER addressing modes (unshifted) - enum + enum addressing_modes : u8 { - ADDR_MODE_PC32 = 0x10, - ADDR_MODE_ABS32 = 0x30, - ADDR_MODE_REL32 = 0x60, - ADDR_MODE_PC16 = 0x90, - ADDR_MODE_REL12 = 0xa0, - ADDR_MODE_ABS16 = 0xb0, - ADDR_MODE_PCX = 0xd0, - ADDR_MODE_RELX = 0xe0 + ADDR_MODE_PC32 = 0x10, // pc relative with 32 bit displacement + ADDR_MODE_ABS32 = 0x30, // 32 bit absolute + ADDR_MODE_REL32 = 0x60, // relative with 32 bit displacement + ADDR_MODE_PC16 = 0x90, // pc relative with 16 bit displacement + ADDR_MODE_REL12 = 0xa0, // relative with 12 bit displacement + ADDR_MODE_ABS16 = 0xb0, // 16 bit absolute + ADDR_MODE_PCX = 0xd0, // pc indexed + ADDR_MODE_RELX = 0xe0 // relative indexed }; static const char *const cc[]; diff --git a/src/devices/cpu/tlcs870/tlcs870d.cpp b/src/devices/cpu/tlcs870/tlcs870d.cpp index 3c3448863c2..0017caab950 100644 --- a/src/devices/cpu/tlcs870/tlcs870d.cpp +++ b/src/devices/cpu/tlcs870/tlcs870d.cpp @@ -2241,6 +2241,7 @@ void tlcs870_disassembler::disassemble_param(std::ostream &stream, offs_t pc, co offs_t tlcs870_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms) { m_addr = pc; + m_opcodes = &opcodes; decode(); diff --git a/src/mame/drivers/cyclemb.cpp b/src/mame/drivers/cyclemb.cpp index c28056d0417..65d6b3fa6fb 100644 --- a/src/mame/drivers/cyclemb.cpp +++ b/src/mame/drivers/cyclemb.cpp @@ -856,7 +856,7 @@ static INPUT_PORTS_START( skydest ) PORT_DIPNAME( 0x04, 0x04, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x18, 0x10, "Lives" ) + PORT_DIPNAME( 0x18, 0x10, DEF_STR( Lives ) ) PORT_DIPSETTING( 0x00, "4" ) PORT_DIPSETTING( 0x08, "3" ) PORT_DIPSETTING( 0x10, "2" ) @@ -882,7 +882,7 @@ static INPUT_PORTS_START( skydest ) PORT_BIT( 0xe0, IP_ACTIVE_HIGH, IPT_UNUSED ) PORT_START("DSW3") - PORT_DIPNAME( 0x01, 0x01, "Demo_Sounds" ) + PORT_DIPNAME( 0x01, 0x01, DEF_STR( Demo_Sounds ) ) PORT_DIPSETTING( 0x01, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x02, 0x00, DEF_STR( Free_Play ) ) diff --git a/src/mame/drivers/hng64.cpp b/src/mame/drivers/hng64.cpp index 9e7eabf078a..d083b926654 100644 --- a/src/mame/drivers/hng64.cpp +++ b/src/mame/drivers/hng64.cpp @@ -219,7 +219,7 @@ The actual carts are mostly only about 1/3rd to 1/2 populated. Some of the IC locations between DG1 and DG2 are different also. See the source code below for the exact number of ROMs used per game and ROM placements. -Games that use the LVS-DG1 cart: Road's Edge +Games that use the LVS-DG1 cart: Road's Edge, Samurai Shodown 64 / Samurai Spirits 64 Games that use the LVS-DG2 cart: Fatal Fury: Wild Ambition, Buriki One, SS 64 II diff --git a/src/mame/drivers/interpro.cpp b/src/mame/drivers/interpro.cpp index 2445c9285b2..a1a80215321 100644 --- a/src/mame/drivers/interpro.cpp +++ b/src/mame/drivers/interpro.cpp @@ -182,8 +182,14 @@ void interpro_state::machine_reset() m_sreg_ctrl1 = CTRL1_FLOPLOW; } -DRIVER_INIT_MEMBER(interpro_state, interpro) +DRIVER_INIT_MEMBER(interpro_state, common) { +} + +DRIVER_INIT_MEMBER(turquoise_state, turquoise) +{ + interpro_state::init_common(); + // FIXME: not all memory sizes are reported properly using fdm "5 inqhw" and // "optimum_memory" commands @@ -193,11 +199,26 @@ DRIVER_INIT_MEMBER(interpro_state, interpro) // 128 = reports 128M, 16x8 // 256 = reports 256M, 32x8 - // grab the main memory space from the mmu - address_space &space = m_mmu->space(0); + // map the configured ram + m_d_cammu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer()); + m_i_cammu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer()); +} + +DRIVER_INIT_MEMBER(sapphire_state, sapphire) +{ + interpro_state::init_common(); + + // FIXME: not all memory sizes are reported properly using fdm "5 inqhw" and + // "optimum_memory" commands + + // 16 = reports 16M, banks empty? + // 32 = reports 16M, banks empty? + // 64 = reports 128M, 16x8 + // 128 = reports 128M, 16x8 + // 256 = reports 256M, 32x8 // map the configured ram - space.install_ram(0, m_ram->mask(), m_ram->pointer()); + m_mmu->space(0).install_ram(0, m_ram->mask(), m_ram->pointer()); } WRITE16_MEMBER(interpro_state::sreg_led_w) @@ -299,12 +320,20 @@ READ8_MEMBER(interpro_state::nodeid_r) } // these maps connect the cpu virtual addresses to the mmu -static ADDRESS_MAP_START(clipper_insn_map, AS_PROGRAM, 32, interpro_state) - AM_RANGE(0x00000000, 0xffffffff) AM_DEVREAD32(INTERPRO_MMU_TAG, cammu_device, insn_r, 0xffffffff) +static ADDRESS_MAP_START(c300_insn_map, AS_PROGRAM, 32, interpro_state) + AM_RANGE(0x00000000, 0xffffffff) AM_DEVREAD(INTERPRO_MMU_TAG "_i", cammu_device, read) +ADDRESS_MAP_END + +static ADDRESS_MAP_START(c300_data_map, AS_DATA, 32, interpro_state) + AM_RANGE(0x00000000, 0xffffffff) AM_DEVREADWRITE(INTERPRO_MMU_TAG "_d", cammu_device, read, write) ADDRESS_MAP_END -static ADDRESS_MAP_START(clipper_data_map, AS_DATA, 32, interpro_state) - AM_RANGE(0x00000000, 0xffffffff) AM_DEVREADWRITE32(INTERPRO_MMU_TAG, cammu_device, data_r, data_w, 0xffffffff) +static ADDRESS_MAP_START(c400_insn_map, AS_PROGRAM, 32, interpro_state) + AM_RANGE(0x00000000, 0xffffffff) AM_DEVREAD(INTERPRO_MMU_TAG, cammu_device, read) +ADDRESS_MAP_END + +static ADDRESS_MAP_START(c400_data_map, AS_DATA, 32, interpro_state) + AM_RANGE(0x00000000, 0xffffffff) AM_DEVREADWRITE(INTERPRO_MMU_TAG, cammu_device, read, write) ADDRESS_MAP_END static ADDRESS_MAP_START(interpro_common_map, 0, 32, interpro_state) @@ -381,13 +410,15 @@ static ADDRESS_MAP_START(sapphire_main_map, 0, 32, sapphire_state) ADDRESS_MAP_END static ADDRESS_MAP_START(turquoise_io_map, 1, 32, interpro_state) - AM_RANGE(0x00000000, 0x00001fff) AM_DEVICE(INTERPRO_MMU_TAG, cammu_device, map) + AM_RANGE(0x00000800, 0x000009ff) AM_DEVICE(INTERPRO_MMU_TAG "_d", cammu_c3_device, map) + AM_RANGE(0x00000a00, 0x00000bff) AM_DEVICE(INTERPRO_MMU_TAG "_i", cammu_c3_device, map) + AM_RANGE(0x00000c00, 0x00000dff) AM_DEVICE(INTERPRO_MMU_TAG "_d", cammu_c3_device, map_global) AM_IMPORT_FROM(turquoise_base_map) ADDRESS_MAP_END static ADDRESS_MAP_START(sapphire_io_map, 1, 32, interpro_state) - AM_RANGE(0x00000000, 0x00001fff) AM_DEVICE(INTERPRO_MMU_TAG, cammu_device, map) + AM_RANGE(0x00000000, 0x00001fff) AM_DEVICE(INTERPRO_MMU_TAG, cammu_c4_device, map) AM_IMPORT_FROM(sapphire_base_map) ADDRESS_MAP_END @@ -486,8 +517,6 @@ static MACHINE_CONFIG_START(ioga) // ioga floppy terminal count, ethernet channel attention MCFG_INTERPRO_IOGA_FDCTC_CB(DEVWRITELINE(INTERPRO_FDC_TAG, upd765_family_device, tc_line_w)) MCFG_INTERPRO_IOGA_ETH_CA_CB(DEVWRITELINE(INTERPRO_ETH_TAG, i82586_base_device, ca)) - - MCFG_INTERPRO_IOGA_DMA_BUS(INTERPRO_CAMMU_TAG, 0) MACHINE_CONFIG_END static INPUT_PORTS_START(interpro) @@ -541,15 +570,24 @@ MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED(turquoise, interpro) MCFG_CPU_ADD(INTERPRO_CPU_TAG, CLIPPER_C300, XTAL_12_5MHz) - MCFG_CPU_PROGRAM_MAP(clipper_insn_map) - MCFG_CPU_DATA_MAP(clipper_data_map) + MCFG_CPU_PROGRAM_MAP(c300_insn_map) + MCFG_CPU_DATA_MAP(c300_data_map) MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, acknowledge_interrupt) - MCFG_DEVICE_ADD(INTERPRO_MMU_TAG, CAMMU_C3, 0) + MCFG_DEVICE_ADD(INTERPRO_MMU_TAG "_i", CAMMU_C3, 0) MCFG_DEVICE_ADDRESS_MAP(0, turquoise_main_map) MCFG_DEVICE_ADDRESS_MAP(1, turquoise_io_map) MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map) MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw)) + MCFG_CAMMU_EXCEPTION_CB(DEVWRITE16(INTERPRO_CPU_TAG, clipper_device, set_exception)) + + MCFG_DEVICE_ADD(INTERPRO_MMU_TAG "_d", CAMMU_C3, 0) + MCFG_DEVICE_ADDRESS_MAP(0, turquoise_main_map) + MCFG_DEVICE_ADDRESS_MAP(1, turquoise_io_map) + MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map) + MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw)) + MCFG_CAMMU_EXCEPTION_CB(DEVWRITE16(INTERPRO_CPU_TAG, clipper_device, set_exception)) + MCFG_CAMMU_LINK(INTERPRO_MMU_TAG "_i") // boot fails memory test without this MCFG_DEVICE_MODIFY(RAM_TAG) @@ -587,13 +625,17 @@ static MACHINE_CONFIG_DERIVED(turquoise, interpro) // i/o gate array MCFG_DEVICE_ADD(INTERPRO_IOGA_TAG, TURQUOISE_IOGA, 0) + MCFG_INTERPRO_IOGA_MEMORY(INTERPRO_MMU_TAG "_d", 0) MCFG_FRAGMENT_ADD(ioga) + + MCFG_DEVICE_MODIFY(INTERPRO_SRBUS_TAG) + MCFG_SR_MEMORY(INTERPRO_MMU_TAG "_d", 0, 1) MACHINE_CONFIG_END static MACHINE_CONFIG_DERIVED(sapphire, interpro) MCFG_CPU_ADD(INTERPRO_CPU_TAG, CLIPPER_C400, XTAL_12_5MHz) - MCFG_CPU_PROGRAM_MAP(clipper_insn_map) - MCFG_CPU_DATA_MAP(clipper_data_map) + MCFG_CPU_PROGRAM_MAP(c400_insn_map) + MCFG_CPU_DATA_MAP(c400_data_map) MCFG_CPU_IRQ_ACKNOWLEDGE_DEVICE(INTERPRO_IOGA_TAG, interpro_ioga_device, acknowledge_interrupt) MCFG_DEVICE_ADD(INTERPRO_MMU_TAG, CAMMU_C4T, 0) @@ -601,6 +643,7 @@ static MACHINE_CONFIG_DERIVED(sapphire, interpro) MCFG_DEVICE_ADDRESS_MAP(1, sapphire_io_map) MCFG_DEVICE_ADDRESS_MAP(2, interpro_boot_map) MCFG_CAMMU_SSW_CB(DEVREAD32(INTERPRO_CPU_TAG, clipper_device, get_ssw)) + MCFG_CAMMU_EXCEPTION_CB(DEVWRITE16(INTERPRO_CPU_TAG, clipper_device, set_exception)) // memory control gate array MCFG_DEVICE_ADD(INTERPRO_MCGA_TAG, INTERPRO_FMCC, 0) @@ -632,11 +675,16 @@ static MACHINE_CONFIG_DERIVED(sapphire, interpro) // i/o gate array MCFG_DEVICE_ADD(INTERPRO_IOGA_TAG, SAPPHIRE_IOGA, 0) + MCFG_INTERPRO_IOGA_MEMORY(INTERPRO_MMU_TAG, 0) MCFG_FRAGMENT_ADD(ioga) // flash memory MCFG_DEVICE_ADD(INTERPRO_FLASH_TAG "_lo", INTEL_28F010, 0) MCFG_DEVICE_ADD(INTERPRO_FLASH_TAG "_hi", INTEL_28F010, 0) + + // sr bus address spaces + MCFG_DEVICE_MODIFY(INTERPRO_SRBUS_TAG) + MCFG_SR_MEMORY(INTERPRO_MMU_TAG, 0, 1) MACHINE_CONFIG_END MACHINE_CONFIG_DERIVED(ip2000, turquoise) @@ -734,9 +782,9 @@ ROM_START(ip2800) ROM_LOAD_OPTIONAL("y226.u67", 0x00000, 0x20000, CRC(54d95730) SHA1(a4e114dee1567d8aa31eed770f7cc366588f395c)) ROM_END -/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ -COMP( 1989, ip2000, 0, 0, ip2000, interpro, turquoise_state, interpro, "Intergraph", "InterPro 2000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) -COMP( 1991?, ip2400, 0, 0, ip2400, interpro, sapphire_state, interpro, "Intergraph", "InterPro 2400", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) -COMP( 1993?, ip2500, 0, 0, ip2500, interpro, sapphire_state, interpro, "Intergraph", "InterPro 2500", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) -COMP( 1992, ip2700, 0, 0, ip2700, interpro, sapphire_state, interpro, "Intergraph", "InterPro 2700", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) -COMP( 1994, ip2800, 0, 0, ip2800, interpro, sapphire_state, interpro, "Intergraph", "InterPro 2800", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +/* YEAR NAME PARENT COMPAT MACHINE INPUT CLASS INIT COMPANY FULLNAME FLAGS */ +COMP( 1989, ip2000, 0, 0, ip2000, interpro, turquoise_state, turquoise, "Intergraph", "InterPro 2000", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1991?, ip2400, 0, 0, ip2400, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2400", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1993?, ip2500, 0, 0, ip2500, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2500", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1992, ip2700, 0, 0, ip2700, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2700", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) +COMP( 1994, ip2800, 0, 0, ip2800, interpro, sapphire_state, sapphire, "Intergraph", "InterPro 2800", MACHINE_NOT_WORKING | MACHINE_NO_SOUND) diff --git a/src/mame/drivers/namcos12.cpp b/src/mame/drivers/namcos12.cpp index 1b174a1ebf6..198bb9e6f64 100644 --- a/src/mame/drivers/namcos12.cpp +++ b/src/mame/drivers/namcos12.cpp @@ -1173,6 +1173,16 @@ protected: }; +class namcos12_boothack_state : public namcos12_state +{ +public: + using namcos12_state::namcos12_state; + +protected: + virtual void machine_reset() override; +}; + + inline void ATTR_PRINTF(3,4) namcos12_state::verboselog( int n_level, const char *s_fmt, ... ) { if( VERBOSE_LEVEL >= n_level ) @@ -1487,41 +1497,17 @@ void namcos12_state::machine_reset() m_tssio_port_4 = 0; m_has_tektagt_dma = 0; +} - if( strcmp( machine().system().name, "tektagt" ) == 0 || - strcmp( machine().system().name, "tektagtc1" ) == 0 || - strcmp( machine().system().name, "tektagtuc1" ) == 0 || - strcmp( machine().system().name, "tektagtub" ) == 0 || - strcmp( machine().system().name, "tektagtjc1" ) == 0 || - strcmp( machine().system().name, "tektagtjb" ) == 0 || - strcmp( machine().system().name, "tektagtja" ) == 0 || - strcmp( machine().system().name, "fgtlayer" ) == 0 || - strcmp( machine().system().name, "golgo13" ) == 0 || - strcmp( machine().system().name, "g13knd" ) == 0 || - strcmp( machine().system().name, "mrdrillr" ) == 0 || - strcmp( machine().system().name, "mrdrillrj" ) == 0 || - strcmp( machine().system().name, "pacapp" ) == 0 || - strcmp( machine().system().name, "pacappsp" ) == 0 || - strcmp( machine().system().name, "pacapp2" ) == 0 || - strcmp( machine().system().name, "tenkomor" ) == 0 || - strcmp( machine().system().name, "tenkomorja" ) == 0 || - strcmp( machine().system().name, "ptblank2" ) == 0 || - strcmp( machine().system().name, "gunbarl" ) == 0 || - strcmp( machine().system().name, "sws2000" ) == 0 || - strcmp( machine().system().name, "sws2001" ) == 0 || - strcmp( machine().system().name, "truckk" ) == 0 || - strcmp( machine().system().name, "technodr" ) == 0 || - strcmp( machine().system().name, "aplarail" ) == 0 || - strcmp( machine().system().name, "kartduel" ) == 0 || - strcmp( machine().system().name, "ohbakyuun" ) == 0 || - strcmp( machine().system().name, "ghlpanic" ) == 0 ) - { - /* HACK: this is based on guesswork, it might not even be keycus. */ - uint8_t *rom = memregion( "maincpu:rom" )->base() + 0x20280; - uint8_t *ram = m_ram->pointer() + 0x10000; +void namcos12_boothack_state::machine_reset() +{ + namcos12_state::machine_reset(); - memcpy( ram, rom, 12 ); - } + /* HACK: this is based on guesswork, it might not even be keycus. */ + uint8_t *rom = memregion( "maincpu:rom" )->base() + 0x20280; + uint8_t *ram = m_ram->pointer() + 0x10000; + + memcpy( ram, rom, 12 ); } /* H8/3002 MCU stuff */ @@ -3182,55 +3168,55 @@ ROM_START( aplarail ) ROM_LOAD( "at28c16", 0x000000, 0x000800, CRC(db1b63c5) SHA1(01fc3386a2d1cb1bed1b7fd9bd2fd59e503832d3) ) ROM_END -GAME( 1996, tekken3, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (World, TET2/VER.E1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ -GAME( 1996, tekken3b, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (World, TET2/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ -GAME( 1996, tekken3a, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (World, TET2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ -GAME( 1996, tekken3ud, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (US, TET3/VER.D)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ -GAME( 1996, tekken3ua, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (US, TET3/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ -GAME( 1996, tekken3je1,tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (Japan, TET1/VER.E1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ -GAME( 1996, tekken3ja, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (Japan, TET1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC014 */ -GAME( 1997, lbgrande, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Libero Grande (World, LG2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC014 */ -GAME( 1997, lbgrandeja,lbgrande, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Libero Grande (Japan, LG1/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC014 */ -GAME( 1997, toukon3, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco / Tomy", "Shin Nihon Pro Wrestling Toukon Retsuden 3 Arcade Edition (Japan, TR1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC019 */ -GAME( 1998, soulclbr, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (World, SOC14/VER.C)", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1998, soulclbrwb,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (World, SOC14/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1998, soulclbruc,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (US, SOC13/VER.C)", MACHINE_IMPERFECT_GRAPHICS ) -GAME( 1998, soulclbrub,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (US, SOC13/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ -GAME( 1998, soulclbrjc,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (Japan, SOC11/VER.C)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ -GAME( 1998, soulclbrjb,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (Japan, SOC11/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ -GAME( 1998, soulclbrja,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (Japan, SOC11/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ -GAME( 1998, ehrgeiz, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Square / Namco", "Ehrgeiz (World, EG2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC021 */ -GAME( 1998, ehrgeizua, ehrgeiz, coh700, namcos12, namcos12_state, namcos12, ROT0, "Square / Namco", "Ehrgeiz (US, EG3/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC021 */ -GAME( 1998, ehrgeizja, ehrgeiz, coh700, namcos12, namcos12_state, namcos12, ROT0, "Square / Namco", "Ehrgeiz (Japan, EG1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC021 */ -GAME( 1998, mdhorse, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "MOSS / Namco", "Derby Quiz My Dream Horse (Japan, MDH1/VER.A2)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC035 */ -GAME( 1998, aplarail, 0, aplarail, aplarail, namcos12_state, namcos12, ROT0, "Namco / Tomy", "Attack Pla Rail (Japan, AP1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC032 */ -GAME( 1998, sws98, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Super World Stadium '98 (Japan, SS81/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC0?? */ -GAME( 1998, technodr, 0, technodr, technodr, namcos12_state, technodr, ROT0, "Namco", "Techno Drive (Japan, TD2/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC056 */ -GAME( 1998, tenkomor, 0, coh700, namcos12, namcos12_state, namcos12, ROT90,"Namco", "Tenkomori Shooting (World, TKM2/VER.A1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC036 */ -GAME( 1998, tenkomorja,tenkomor, coh700, namcos12, namcos12_state, namcos12, ROT90,"Namco", "Tenkomori Shooting (Japan, TKM1/VER.A1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC036 */ -GAME( 1998, fgtlayer, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Arika / Namco", "Fighting Layer (Japan, FTL1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC037 */ -GAME( 1999, pacapp, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Produce / Namco", "Paca Paca Passion (Japan, PPP1/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC038 */ -GAME( 1999, ptblank2, 0, ptblank2, ptblank2, namcos12_state, ptblank2, ROT0, "Namco", "Point Blank 2 (GNB5/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC042 */ -GAME( 1999, gunbarl, ptblank2, ptblank2, ptblank2, namcos12_state, ptblank2, ROT0, "Namco", "Gunbarl (Japan, GNB4/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC042 */ -GAME( 1999, sws99, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Super World Stadium '99 (Japan, SS91/VER.A3)", MACHINE_IMPERFECT_GRAPHICS ) /* KC043 */ -GAME( 1999, tektagt, 0, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (World, TEG2/VER.C1, set 1)", 0 ) /* KC044 */ -GAME( 1999, tektagtc1, tektagt, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (World, TEG2/VER.C1, set 2)", 0 ) /* KC044 */ -GAME( 1999, tektagtuc1,tektagt, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (US, TEG3/VER.C1)", 0 ) /* KC044 */ -GAME( 1999, tektagtub, tektagt, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (US, TEG3/VER.B)", 0 ) /* KC044 */ -GAME( 1999, tektagtjc1,tektagt, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (Japan, TEG1/VER.C1)", MACHINE_NOT_WORKING ) /* KC044 */ -GAME( 1999, tektagtjb, tektagt, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (Japan, TEG1/VER.B)", MACHINE_NOT_WORKING ) /* KC044 */ -GAME( 1999, tektagtja, tektagt, tektagt, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (Japan, TEG1/VER.A3)", MACHINE_NOT_WORKING ) /* KC044 */ -GAME( 1999, ghlpanic, 0, ptblank2, ghlpanic, namcos12_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Ghoul Panic (World, OB2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC045 */ -GAME( 1999, ohbakyuun, ghlpanic, ptblank2, ghlpanic, namcos12_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Oh! Bakyuuun (Japan, OB1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC045 */ -GAME( 1999, pacapp2, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Produce / Namco", "Paca Paca Passion 2 (Japan, PKS1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC046 */ -GAME( 1999, mrdrillr, 0, coh700, namcos124w,namcos12_state,namcos12, ROT0, "Namco", "Mr. Driller (US, DRI3/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC048 */ -GAME( 1999, mrdrillrj, mrdrillr, coh700, namcos124w,namcos12_state,namcos12, ROT0, "Namco", "Mr. Driller (Japan, DRI1/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC048 */ -GAME( 1999, kaiunqz, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Kaiun Quiz (Japan, KW1/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC050 */ -GAME( 1999, pacappsp, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Produce / Namco", "Paca Paca Passion Special (Japan, PSP1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC052 */ -GAME( 1999, aquarush, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Aqua Rush (Japan, AQ1/VER.A1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC053 */ -GAME( 1999, golgo13, 0, golgo13, golgo13, namcos12_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Golgo 13 (Japan, GLG1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC054 */ -GAME( 2000, g13knd, 0, golgo13, golgo13, namcos12_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Golgo 13 Kiseki no Dandou (Japan, GLS1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC059 */ -GAME( 2000, sws2000, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Super World Stadium 2000 (Japan, SS01/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC055 */ -GAME( 2000, truckk, 0, truckk, namcos12, namcos12_state, namcos12, ROT0, "Metro / Namco", "Truck Kyosokyoku (Japan, TKK2/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* KC056 */ -GAME( 2000, kartduel, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Kart Duel (Japan, KTD1/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC057 */ -GAME( 2001, sws2001, sws2000, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Super World Stadium 2001 (Japan, SS11/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC061 */ +GAME( 1996, tekken3, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (World, TET2/VER.E1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ +GAME( 1996, tekken3b, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (World, TET2/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ +GAME( 1996, tekken3a, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (World, TET2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ +GAME( 1996, tekken3ud, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (US, TET3/VER.D)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ +GAME( 1996, tekken3ua, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (US, TET3/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ +GAME( 1996, tekken3je1,tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (Japan, TET1/VER.E1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC006 */ +GAME( 1996, tekken3ja, tekken3, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Tekken 3 (Japan, TET1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC014 */ +GAME( 1997, lbgrande, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Libero Grande (World, LG2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC014 */ +GAME( 1997, lbgrandeja,lbgrande, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Libero Grande (Japan, LG1/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC014 */ +GAME( 1997, toukon3, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco / Tomy", "Shin Nihon Pro Wrestling Toukon Retsuden 3 Arcade Edition (Japan, TR1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC019 */ +GAME( 1998, soulclbr, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (World, SOC14/VER.C)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1998, soulclbrwb,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (World, SOC14/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1998, soulclbruc,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (US, SOC13/VER.C)", MACHINE_IMPERFECT_GRAPHICS ) +GAME( 1998, soulclbrub,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (US, SOC13/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ +GAME( 1998, soulclbrjc,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (Japan, SOC11/VER.C)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ +GAME( 1998, soulclbrjb,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (Japan, SOC11/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ +GAME( 1998, soulclbrja,soulclbr, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Soul Calibur (Japan, SOC11/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC020 */ +GAME( 1998, ehrgeiz, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Square / Namco", "Ehrgeiz (World, EG2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC021 */ +GAME( 1998, ehrgeizua, ehrgeiz, coh700, namcos12, namcos12_state, namcos12, ROT0, "Square / Namco", "Ehrgeiz (US, EG3/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC021 */ +GAME( 1998, ehrgeizja, ehrgeiz, coh700, namcos12, namcos12_state, namcos12, ROT0, "Square / Namco", "Ehrgeiz (Japan, EG1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC021 */ +GAME( 1998, mdhorse, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "MOSS / Namco", "Derby Quiz My Dream Horse (Japan, MDH1/VER.A2)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC035 */ +GAME( 1998, aplarail, 0, aplarail, aplarail, namcos12_boothack_state, namcos12, ROT0, "Namco / Tomy", "Attack Pla Rail (Japan, AP1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC032 */ +GAME( 1998, sws98, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Super World Stadium '98 (Japan, SS81/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC0?? */ +GAME( 1998, technodr, 0, technodr, technodr, namcos12_boothack_state, technodr, ROT0, "Namco", "Techno Drive (Japan, TD2/VER.B)", MACHINE_IMPERFECT_GRAPHICS ) /* KC056 */ +GAME( 1998, tenkomor, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT90,"Namco", "Tenkomori Shooting (World, TKM2/VER.A1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC036 */ +GAME( 1998, tenkomorja,tenkomor, coh700, namcos12, namcos12_boothack_state, namcos12, ROT90,"Namco", "Tenkomori Shooting (Japan, TKM1/VER.A1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC036 */ +GAME( 1998, fgtlayer, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Arika / Namco", "Fighting Layer (Japan, FTL1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC037 */ +GAME( 1999, pacapp, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Produce / Namco", "Paca Paca Passion (Japan, PPP1/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC038 */ +GAME( 1999, ptblank2, 0, ptblank2, ptblank2, namcos12_boothack_state, ptblank2, ROT0, "Namco", "Point Blank 2 (GNB5/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC042 */ +GAME( 1999, gunbarl, ptblank2, ptblank2, ptblank2, namcos12_boothack_state, ptblank2, ROT0, "Namco", "Gunbarl (Japan, GNB4/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC042 */ +GAME( 1999, sws99, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Super World Stadium '99 (Japan, SS91/VER.A3)", MACHINE_IMPERFECT_GRAPHICS ) /* KC043 */ +GAME( 1999, tektagt, 0, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (World, TEG2/VER.C1, set 1)", 0 ) /* KC044 */ +GAME( 1999, tektagtc1, tektagt, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (World, TEG2/VER.C1, set 2)", 0 ) /* KC044 */ +GAME( 1999, tektagtuc1,tektagt, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (US, TEG3/VER.C1)", 0 ) /* KC044 */ +GAME( 1999, tektagtub, tektagt, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (US, TEG3/VER.B)", 0 ) /* KC044 */ +GAME( 1999, tektagtjc1,tektagt, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (Japan, TEG1/VER.C1)", MACHINE_NOT_WORKING ) /* KC044 */ +GAME( 1999, tektagtjb, tektagt, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (Japan, TEG1/VER.B)", MACHINE_NOT_WORKING ) /* KC044 */ +GAME( 1999, tektagtja, tektagt, tektagt, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Tekken Tag Tournament (Japan, TEG1/VER.A3)", MACHINE_NOT_WORKING ) /* KC044 */ +GAME( 1999, ghlpanic, 0, ptblank2, ghlpanic, namcos12_boothack_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Ghoul Panic (World, OB2/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC045 */ +GAME( 1999, ohbakyuun, ghlpanic, ptblank2, ghlpanic, namcos12_boothack_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Oh! Bakyuuun (Japan, OB1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC045 */ +GAME( 1999, pacapp2, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Produce / Namco", "Paca Paca Passion 2 (Japan, PKS1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC046 */ +GAME( 1999, mrdrillr, 0, coh700, namcos124w,namcos12_boothack_state, namcos12, ROT0, "Namco", "Mr. Driller (US, DRI3/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC048 */ +GAME( 1999, mrdrillrj, mrdrillr, coh700, namcos124w,namcos12_boothack_state, namcos12, ROT0, "Namco", "Mr. Driller (Japan, DRI1/VER.A2)", MACHINE_IMPERFECT_GRAPHICS ) /* KC048 */ +GAME( 1999, kaiunqz, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Kaiun Quiz (Japan, KW1/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC050 */ +GAME( 1999, pacappsp, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Produce / Namco", "Paca Paca Passion Special (Japan, PSP1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC052 */ +GAME( 1999, aquarush, 0, coh700, namcos12, namcos12_state, namcos12, ROT0, "Namco", "Aqua Rush (Japan, AQ1/VER.A1)", MACHINE_IMPERFECT_GRAPHICS ) /* KC053 */ +GAME( 1999, golgo13, 0, golgo13, golgo13, namcos12_boothack_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Golgo 13 (Japan, GLG1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC054 */ +GAME( 2000, g13knd, 0, golgo13, golgo13, namcos12_boothack_state, namcos12, ROT0, "Eighting / Raizing / Namco", "Golgo 13 Kiseki no Dandou (Japan, GLS1/VER.A)", MACHINE_IMPERFECT_GRAPHICS ) /* KC059 */ +GAME( 2000, sws2000, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Super World Stadium 2000 (Japan, SS01/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC055 */ +GAME( 2000, truckk, 0, truckk, namcos12, namcos12_boothack_state, namcos12, ROT0, "Metro / Namco", "Truck Kyosokyoku (Japan, TKK2/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* KC056 */ +GAME( 2000, kartduel, 0, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Kart Duel (Japan, KTD1/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC057 */ +GAME( 2001, sws2001, sws2000, coh700, namcos12, namcos12_boothack_state, namcos12, ROT0, "Namco", "Super World Stadium 2001 (Japan, SS11/VER.A)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_NOT_WORKING ) /* KC061 */ diff --git a/src/mame/drivers/rbmk.cpp b/src/mame/drivers/rbmk.cpp index b97c0d16dd8..67ad1b99107 100644 --- a/src/mame/drivers/rbmk.cpp +++ b/src/mame/drivers/rbmk.cpp @@ -39,7 +39,7 @@ Notes: * - Unpopulated position for PIC16F84 3.6V_BATT - Purpose of battery unknown, does not appear to be used for backup of suicide RAM, and there's no RTC on the board. - 93C46 - 128 x8 EEPROM. This chip was covered by a plactic cover. There's nothing else under + 93C46 - 128 x8 EEPROM. This chip was covered by a plastic cover. There's nothing else under the cover, but there was an unpopulated position for a PIC16F84 89C51 - Atmel 89C51 Microcontroller (protected) @@ -49,6 +49,8 @@ Notes: A1 - Atmel AT27C080 (GFX) B1 - Macronix MX261000 (GFX?? or PRG/data for 89C51?) S1 - Macronix MX27C2000 (OKI samples) + +Keep pressed 9 and press reset to enter service mode. */ #include "emu.h" @@ -68,53 +70,78 @@ class rbmk_state : public driver_device public: rbmk_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag), - m_gms_vidram2(*this, "gms_vidram2"), - m_gms_vidram(*this, "gms_vidram"), + m_vidram2(*this, "vidram2"), + m_vidram(*this, "vidram"), m_maincpu(*this, "maincpu"), m_mcu(*this, "mcu"), m_eeprom(*this, "eeprom"), m_gfxdecode(*this, "gfxdecode"), m_palette(*this, "palette") { } - required_shared_ptr<uint16_t> m_gms_vidram2; - required_shared_ptr<uint16_t> m_gms_vidram; - uint16_t m_tilebank; - uint8_t m_mux_data; - DECLARE_READ16_MEMBER(gms_read); - DECLARE_WRITE16_MEMBER(gms_write1); - DECLARE_WRITE16_MEMBER(gms_write2); - DECLARE_WRITE16_MEMBER(gms_write3); - DECLARE_READ8_MEMBER(rbmk_mcu_io_r); - DECLARE_WRITE8_MEMBER(rbmk_mcu_io_w); + DECLARE_READ16_MEMBER(unk_r); + DECLARE_READ16_MEMBER(dip_mux_r); + DECLARE_WRITE16_MEMBER(dip_mux_w); + DECLARE_WRITE16_MEMBER(unk_w); + DECLARE_WRITE16_MEMBER(tilebank_w); + DECLARE_READ8_MEMBER(mcu_io_r); + DECLARE_WRITE8_MEMBER(mcu_io_w); DECLARE_WRITE8_MEMBER(mcu_io_mux_w); DECLARE_WRITE16_MEMBER(eeprom_w); - virtual void video_start() override; - uint32_t screen_update_rbmk(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); INTERRUPT_GEN_MEMBER(mcu_irq); + +protected: + virtual void video_start() override; + +private: + required_shared_ptr<uint16_t> m_vidram2; + required_shared_ptr<uint16_t> m_vidram; + required_device<cpu_device> m_maincpu; required_device<cpu_device> m_mcu; required_device<eeprom_serial_93cxx_device> m_eeprom; required_device<gfxdecode_device> m_gfxdecode; required_device<palette_device> m_palette; + + uint16_t m_tilebank; + uint8_t m_mux_data; + uint16_t m_dip_mux; }; -READ16_MEMBER(rbmk_state::gms_read) +READ16_MEMBER(rbmk_state::unk_r) { return machine().rand(); } +READ16_MEMBER(rbmk_state::dip_mux_r) +{ +/* +definitely muxed dips. See switch test in test mode. This implementation doesn't work properly, though. For now use the old one. + +uint16_t res = 0xffff; +switch(m_dip_mux) +{ +case 0x1000: res = ioport("DSW1")->read(); break; +case 0x2000: res = ioport("DSW2")->read(); break; +case 0x4000: res = ioport("DSW3")->read(); break; +} +return res;*/ + return ioport("DSW1")->read(); +} -WRITE16_MEMBER(rbmk_state::gms_write1) +WRITE16_MEMBER(rbmk_state::tilebank_w) { + m_tilebank = data; } -WRITE16_MEMBER(rbmk_state::gms_write2) +WRITE16_MEMBER(rbmk_state::dip_mux_w) { - m_tilebank=data; + m_dip_mux = data; } -WRITE16_MEMBER(rbmk_state::gms_write3) +WRITE16_MEMBER(rbmk_state::unk_w) { } @@ -132,28 +159,43 @@ WRITE16_MEMBER(rbmk_state::eeprom_w) static ADDRESS_MAP_START( rbmk_mem, AS_PROGRAM, 16, rbmk_state ) - AM_RANGE(0x000000, 0x07ffff) AM_ROM + AM_RANGE(0x000000, 0x07ffff) AM_ROM AM_WRITENOP AM_RANGE(0x100000, 0x10ffff) AM_RAM AM_RANGE(0x500000, 0x50ffff) AM_RAM - AM_RANGE(0x940000, 0x940fff) AM_RAM AM_SHARE("gms_vidram2") + AM_RANGE(0x940000, 0x940fff) AM_RAM AM_SHARE("vidram2") AM_RANGE(0x980300, 0x983fff) AM_RAM // 0x2048 words ???, byte access AM_RANGE(0x900000, 0x900fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette") - AM_RANGE(0x9c0000, 0x9c0fff) AM_RAM AM_SHARE("gms_vidram") + AM_RANGE(0x9c0000, 0x9c0fff) AM_RAM AM_SHARE("vidram") AM_RANGE(0xb00000, 0xb00001) AM_WRITE(eeprom_w) - AM_RANGE(0xC00000, 0xC00001) AM_READ_PORT("IN0") AM_WRITE(gms_write1) - AM_RANGE(0xC08000, 0xC08001) AM_READ_PORT("IN1") AM_WRITE(gms_write2) - AM_RANGE(0xC10000, 0xC10001) AM_READ_PORT("IN3") - AM_RANGE(0xC18080, 0xC18081) AM_READ(gms_read) - AM_RANGE(0xC20000, 0xC20001) AM_READ_PORT("IN2") - AM_RANGE(0xC28000, 0xC28001) AM_WRITE(gms_write3) + AM_RANGE(0xc00000, 0xc00001) AM_READWRITE(dip_mux_r, dip_mux_w) + AM_RANGE(0xc08000, 0xc08001) AM_READ_PORT("IN1") AM_WRITE(tilebank_w) + AM_RANGE(0xc10000, 0xc10001) AM_READ_PORT("IN2") + AM_RANGE(0xc18080, 0xc18081) AM_READ(unk_r) + AM_RANGE(0xc20000, 0xc20001) AM_READ_PORT("IN3") + AM_RANGE(0xc28000, 0xc28001) AM_WRITE(unk_w) ADDRESS_MAP_END +static ADDRESS_MAP_START( rbspm_mem, AS_PROGRAM, 16, rbmk_state ) + AM_RANGE(0x000000, 0x07ffff) AM_ROM + AM_RANGE(0x200000, 0x200001) AM_WRITE(eeprom_w) // wrong + AM_RANGE(0x300000, 0x300001) AM_READWRITE(dip_mux_r, dip_mux_w) + AM_RANGE(0x308000, 0x308001) AM_READ_PORT("IN1") AM_WRITE(tilebank_w) // ok + AM_RANGE(0x310000, 0x310001) AM_READ_PORT("IN2") + AM_RANGE(0x318080, 0x318081) AM_READ(unk_r) + AM_RANGE(0x320000, 0x320001) AM_READ_PORT("IN3") + AM_RANGE(0x328000, 0x328001) AM_WRITE(unk_w) + AM_RANGE(0x500000, 0x50ffff) AM_RAM + AM_RANGE(0x900000, 0x900fff) AM_RAM_DEVWRITE("palette", palette_device, write) AM_SHARE("palette") // if removed fails gfx test? + AM_RANGE(0x940000, 0x940fff) AM_RAM AM_SHARE("vidram2") // if removed fails palette test? + AM_RANGE(0x980300, 0x983fff) AM_RAM // 0x2048 words ???, byte access, u25 and u26 according to test mode + AM_RANGE(0x9c0000, 0x9c0fff) AM_RAM AM_SHARE("vidram") +ADDRESS_MAP_END -static ADDRESS_MAP_START( rbmk_mcu_mem, AS_PROGRAM, 8, rbmk_state ) +static ADDRESS_MAP_START( mcu_mem, AS_PROGRAM, 8, rbmk_state ) // AM_RANGE(0x0000, 0x0fff) AM_ROM ADDRESS_MAP_END -READ8_MEMBER(rbmk_state::rbmk_mcu_io_r) +READ8_MEMBER(rbmk_state::mcu_io_r) { if(m_mux_data & 8) { @@ -171,7 +213,7 @@ READ8_MEMBER(rbmk_state::rbmk_mcu_io_r) return 0xff; } -WRITE8_MEMBER(rbmk_state::rbmk_mcu_io_w) +WRITE8_MEMBER(rbmk_state::mcu_io_w) { if(m_mux_data & 8) { machine().device<ym2151_device>("ymsnd")->write(space, offset & 1, data); } else if(m_mux_data & 4) @@ -188,99 +230,52 @@ WRITE8_MEMBER(rbmk_state::mcu_io_mux_w) m_mux_data = ~data; } -static ADDRESS_MAP_START( rbmk_mcu_io, AS_IO, 8, rbmk_state ) - AM_RANGE(0x0ff00, 0x0ffff) AM_READWRITE(rbmk_mcu_io_r, rbmk_mcu_io_w ) +static ADDRESS_MAP_START( mcu_io, AS_IO, 8, rbmk_state ) + AM_RANGE(0x0ff00, 0x0ffff) AM_READWRITE(mcu_io_r, mcu_io_w ) AM_RANGE(MCS51_PORT_P3, MCS51_PORT_P3) AM_WRITE(mcu_io_mux_w ) ADDRESS_MAP_END static INPUT_PORTS_START( rbmk ) - PORT_START("IN0") - PORT_DIPNAME( 0x0001, 0x0001, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0002, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0004, 0x0004, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0004, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0008, 0x0008, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0008, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0010, 0x0010, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0010, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0040, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Controls ) ) - PORT_DIPSETTING( 0x0080, DEF_STR( Joystick ) ) - PORT_DIPSETTING( 0x0000, "Keyboard" ) - - PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0200, 0x0200, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0200, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0400, 0x0400, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0400, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0800, 0x0800, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0800, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Version ) ) - PORT_DIPSETTING( 0x4000, "8.8" ) - PORT_DIPSETTING( 0x0000, "8.8-" ) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_START("IN1") /* 16bit */ - PORT_DIPNAME( 0x0001, 0x0001, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_SERVICE1 ) PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_COIN1 ) PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_START1 ) PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_MAHJONG_DOUBLE_UP ) - - PORT_DIPNAME( 0x0020, 0x0020, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0020, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_MAHJONG_BET ) PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_BUTTON2 ) - - PORT_DIPNAME( 0x1000, 0x1000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x1000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x8000, IP_ACTIVE_LOW, IPT_UNKNOWN ) PORT_START("IN2") /* 16bit */ - PORT_DIPNAME( 0x0001, 0x0001, DEF_STR( Unknown ) ) + PORT_BIT( 0x0001, IP_ACTIVE_LOW, IPT_GAMBLE_BOOK ) PORT_TOGGLE + PORT_BIT( 0x0002, IP_ACTIVE_LOW, IPT_MEMORY_RESET ) PORT_TOGGLE + PORT_BIT( 0x0004, IP_ACTIVE_LOW, IPT_COIN2 ) + PORT_BIT( 0x0008, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0010, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0020, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0040, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0080, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0100, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0200, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0400, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x0800, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x1000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x2000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x4000, IP_ACTIVE_LOW, IPT_UNKNOWN ) + PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, do_read) + + + PORT_START("DSW1") /* 16bit, in test mode first 8 are recognised as dsw1, second 8 as dsw4*/ + PORT_DIPNAME( 0x0001, 0x0001, "DSW1" ) PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) ) @@ -301,9 +296,10 @@ static INPUT_PORTS_START( rbmk ) PORT_DIPNAME( 0x0040, 0x0040, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x0040, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x0080, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x0080, 0x0080, DEF_STR( Controls ) ) + PORT_DIPSETTING( 0x0080, DEF_STR( Joystick ) ) + PORT_DIPSETTING( 0x0000, "Keyboard" ) + PORT_DIPNAME( 0x0100, 0x0100, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x0100, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) @@ -322,16 +318,15 @@ static INPUT_PORTS_START( rbmk ) PORT_DIPNAME( 0x2000, 0x2000, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x2000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) - PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) - PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) + PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Version ) ) + PORT_DIPSETTING( 0x4000, "8.8" ) + PORT_DIPSETTING( 0x0000, "8.8-" ) PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - - PORT_START("IN3") /* 16bit */ - PORT_DIPNAME( 0x0001, 0x0001, DEF_STR( Unknown ) ) + PORT_START("DSW2") /* 16bit, in test mode first 8 are recognised as dsw2, second 8 as dsw5*/ + PORT_DIPNAME( 0x0001, 0x0001, "DSW2" ) // 1,2,3 should be coinage PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) ) @@ -376,10 +371,12 @@ static INPUT_PORTS_START( rbmk ) PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x4000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_BIT( 0x8000, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_READ_LINE_DEVICE_MEMBER("eeprom", eeprom_serial_93cxx_device, do_read) + PORT_DIPNAME( 0x8000, 0x8000, DEF_STR( Unknown ) ) + PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_START("IN4") /* 16bit */ - PORT_DIPNAME( 0x0001, 0x0001, DEF_STR( Unknown ) ) + PORT_START("DSW3") /* 16bit, in test mode first 8 are recognised as dsw3, second 8 as dsw6*/ + PORT_DIPNAME( 0x0001, 0x0001, "DSW3" ) PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) ) @@ -428,8 +425,8 @@ static INPUT_PORTS_START( rbmk ) PORT_DIPSETTING( 0x8000, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) - PORT_START("IN5") /* 16bit */ - PORT_DIPNAME( 0x0001, 0x0001, DEF_STR( Unknown ) ) + PORT_START("IN3") /* 16bit, not verified in test mode? */ + PORT_DIPNAME( 0x0001, 0x0001, "IN3" ) PORT_DIPSETTING( 0x0001, DEF_STR( Off ) ) PORT_DIPSETTING( 0x0000, DEF_STR( On ) ) PORT_DIPNAME( 0x0002, 0x0002, DEF_STR( Unknown ) ) @@ -480,6 +477,15 @@ static INPUT_PORTS_START( rbmk ) INPUT_PORTS_END +static INPUT_PORTS_START( rbspm ) + PORT_INCLUDE( rbmk ) + + PORT_MODIFY("DSW1") + PORT_DIPNAME( 0x4000, 0x4000, DEF_STR( Version ) ) + PORT_DIPSETTING( 0x4000, "4.1" ) + PORT_DIPSETTING( 0x0000, "4.2" ) +INPUT_PORTS_END + static const gfx_layout rbmk32_layout = { 8,32, @@ -511,9 +517,12 @@ GFXDECODE_END void rbmk_state::video_start() { + save_item(NAME(m_tilebank)); + save_item(NAME(m_mux_data)); + save_item(NAME(m_dip_mux)); } -uint32_t rbmk_state::screen_update_rbmk(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) +uint32_t rbmk_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect) { int x,y; int count = 0; @@ -522,7 +531,7 @@ uint32_t rbmk_state::screen_update_rbmk(screen_device &screen, bitmap_ind16 &bit { for (x=0;x<64;x++) { - int tile = m_gms_vidram2[count+0x600]; + int tile = m_vidram2[count+0x600]; m_gfxdecode->gfx(0)->opaque(bitmap,cliprect,(tile&0xfff)+((m_tilebank&0x10)>>4)*0x1000,tile>>12,0,0,x*8,y*32); count++; } @@ -534,7 +543,7 @@ uint32_t rbmk_state::screen_update_rbmk(screen_device &screen, bitmap_ind16 &bit { for (x=0;x<64;x++) { - int tile = m_gms_vidram[count]; + int tile = m_vidram[count]; m_gfxdecode->gfx(1)->transpen(bitmap,cliprect,(tile&0xfff)+((m_tilebank>>1)&3)*0x1000,tile>>12,0,0,x*8,y*8,0); count++; } @@ -553,19 +562,18 @@ static MACHINE_CONFIG_START( rbmk ) MCFG_CPU_VBLANK_INT_DRIVER("screen", rbmk_state, irq1_line_hold) MCFG_CPU_ADD("mcu", AT89C4051, 22000000 / 4) // frequency isn't right - MCFG_CPU_PROGRAM_MAP(rbmk_mcu_mem) - MCFG_CPU_IO_MAP(rbmk_mcu_io) + MCFG_CPU_PROGRAM_MAP(mcu_mem) + MCFG_CPU_IO_MAP(mcu_io) MCFG_CPU_VBLANK_INT_DRIVER("screen", rbmk_state, mcu_irq) MCFG_GFXDECODE_ADD("gfxdecode", "palette", rbmk) - MCFG_SCREEN_ADD("screen", RASTER) MCFG_SCREEN_REFRESH_RATE(58) MCFG_SCREEN_VBLANK_TIME(ATTOSECONDS_IN_USEC(0)) MCFG_SCREEN_SIZE(64*8, 32*8) MCFG_SCREEN_VISIBLE_AREA(0*8, 64*8-1, 0*8, 32*8-1) - MCFG_SCREEN_UPDATE_DRIVER(rbmk_state, screen_update_rbmk) + MCFG_SCREEN_UPDATE_DRIVER(rbmk_state, screen_update) MCFG_SCREEN_PALETTE("palette") MCFG_PALETTE_ADD("palette", 0x800) @@ -585,6 +593,16 @@ static MACHINE_CONFIG_START( rbmk ) MCFG_SOUND_ROUTE(1, "rspeaker", 0.60) MACHINE_CONFIG_END +static MACHINE_CONFIG_DERIVED( rbspm, rbmk ) + MCFG_CPU_MODIFY("maincpu") + MCFG_CPU_PROGRAM_MAP(rbspm_mem) + + MCFG_CPU_MODIFY("mcu") + MCFG_DEVICE_DISABLE() // until decapped + + // PIC16F84 if decapped +MACHINE_CONFIG_END + ROM_START( rbmk ) ROM_REGION( 0x80000, "maincpu", 0 ) /* 68000 Code */ ROM_LOAD( "p1.u64", 0x00000, 0x80000, CRC(83b3c505) SHA1(b943d7312dacdf46d4a55f9dc3cf92e291c40ce7) ) @@ -608,5 +626,37 @@ ROM_START( rbmk ) ROM_LOAD16_WORD_SWAP( "93c46.u51", 0x00, 0x080, CRC(4ca6ff01) SHA1(66c456eac5b0d1176ef9130baf2e746efdf30152) ) ROM_END +/* +Gameplay videos: +http://youtu.be/pPk-6N1wXoE +http://youtu.be/VGbrR7GfDck +*/ + +ROM_START( rbspm ) + ROM_REGION( 0x80000, "maincpu", 0 ) /* 68000 Code */ + ROM_LOAD( "MJ-DFMJ-P1.bin", 0x00000, 0x80000, CRC(8f81f154) SHA1(50a9a373dec96b0265907f053d068d636bdabd61) ) + + ROM_REGION( 0x1000, "mcu", 0 ) /* protected MCU */ + ROM_LOAD( "89c51.bin", 0x0, 0x1000, NO_DUMP ) // reads as all 0xff + + ROM_REGION( 0x1000, "pic", 0 ) /* pic was populated on this board */ + ROM_LOAD( "pic16f84.bin", 0x0, 0x1000, NO_DUMP ) + + ROM_REGION( 0x20000, "user1", 0 ) /* ??? mcu data / code */ + ROM_LOAD( "MJ-DFMJ-2.2-XX.bin", 0x00000, 0x20000, CRC(58a9eea2) SHA1(1a251e9b049bc8dafbc0728b3d876fdd5a1c8dd9) ) + + ROM_REGION( 0x080000, "oki", 0 ) /* Samples */ + ROM_LOAD( "MJ-DFMJ-2.2-S1.bin", 0x00000, 0x80000, CRC(2410bb61) SHA1(54e258e4af089841a63e45f25aad70310a28d76b) ) // 1st and 2nd half identical + + ROM_REGION( 0x80000, "gfx1", 0 ) /* 8x32 tiles, lots of girls etc. */ + ROM_LOAD( "MJ-DFMJ-4.2-A1.bin", 0x00000, 0x80000, CRC(b0a3a866) SHA1(cc950532160a066fc6ce427f6df9d58ee4589821) ) + + ROM_REGION( 0x80000, "gfx2", 0 ) /* 8x8 tiles? cards etc */ + ROM_LOAD( "MJ-DFMJ-4.8-T1.bin", 0x00000, 0x80000, CRC(2b8b689d) SHA1(65ab643fac1e734af8b3a86caa06b532baafa0fe) ) + + ROM_REGION16_BE( 0x80, "eeprom", 0 ) /* eeprom */ + ROM_LOAD16_WORD_SWAP( "93c46.u51", 0x00, 0x080, NO_DUMP ) +ROM_END -GAME( 1998, rbmk, 0, rbmk, rbmk, rbmk_state, 0, ROT0, "GMS", "Real Battle Mahjong King", MACHINE_NOT_WORKING ) +GAME( 1998, rbmk, 0, rbmk, rbmk, rbmk_state, 0, ROT0, "GMS", "Real Battle Mahjong King (Version 8.8)", MACHINE_NOT_WORKING ) +GAME( 1998, rbspm, 0, rbspm, rbspm, rbmk_state, 0, ROT0, "GMS", "Real Battle Super Phoenix Mahjong (Version 4.1)", MACHINE_NOT_WORKING ) diff --git a/src/mame/drivers/taitotz.cpp b/src/mame/drivers/taitotz.cpp index cac175fee84..7a04f0da8e0 100644 --- a/src/mame/drivers/taitotz.cpp +++ b/src/mame/drivers/taitotz.cpp @@ -2949,8 +2949,8 @@ ROM_START( styphp ) ROM_END GAME( 1999, taitotz, 0, taitotz, taitotz, taitotz_state, 0, ROT0, "Taito", "Type Zero BIOS", MACHINE_NO_SOUND|MACHINE_NOT_WORKING|MACHINE_IS_BIOS_ROOT) -GAME( 1999, landhigh, taitotz, landhigh, landhigh, taitotz_state, landhigh, ROT0, "Taito", "Landing High Japan (Ver 2.01 OK)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) -GAME( 1999, landhigha, landhigh, landhigh, landhigh, taitotz_state, landhigha,ROT0, "Taito", "Landing High Japan (Ver 2.02 O)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +GAME( 1999, landhigh, taitotz, landhigh, landhigh, taitotz_state, landhigh, ROT0, "Taito", "Landing High Japan (Ver 2.01 OK)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) +GAME( 1999, landhigha, landhigh, landhigh, landhigh, taitotz_state, landhigha,ROT0, "Taito", "Landing High Japan (Ver 2.02 O)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) GAME( 1999, batlgear, taitotz, taitotz, batlgr2, taitotz_state, batlgear, ROT0, "Taito", "Battle Gear (Ver 2.40 A)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) GAME( 1999, pwrshovl, taitotz, taitotz, pwrshovl, taitotz_state, pwrshovl, ROT0, "Taito", "Power Shovel ni Norou!! - Power Shovel Simulator (v2.07J)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // 1999/8/5 19:13:35 GAME( 1999, pwrshovla, pwrshovl, taitotz, pwrshovl, taitotz_state, pwrshovl, ROT0, "Taito", "Power Shovel ni Norou!! - Power Shovel Simulator (v2.07J, alt)", MACHINE_NOT_WORKING | MACHINE_NO_SOUND ) // seem to be some differences in drive content, but identifies as the same revision, is it just user data changes?? diff --git a/src/mame/drivers/vicdual.cpp b/src/mame/drivers/vicdual.cpp index 87cccad6ab1..e8564c07243 100644 --- a/src/mame/drivers/vicdual.cpp +++ b/src/mame/drivers/vicdual.cpp @@ -676,23 +676,26 @@ static INPUT_PORTS_START( supcrash ) PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_4WAY PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_4WAY PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_BUTTON1 ) - PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) + PORT_DIPNAME( 0x10, 0x10, DEF_STR( Unknown ) ) // both this and the following switch seem to select between 5 and 6 lives? but in combination with 0x02 of IN1 you can get 3 and 4 lives? PORT_DIPSETTING( 0x10, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x20, 0x20, DEF_STR( Unknown ) ) PORT_DIPSETTING( 0x20, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_DIPNAME( 0x40, 0x40, DEF_STR( Unknown ) ) + PORT_DIPNAME( 0x40, 0x00, DEF_STR( Demo_Sounds ) ) PORT_DIPSETTING( 0x40, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_4WAY PORT_START("IN1") PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, vicdual_state, get_timer_value, nullptr) + PORT_DIPNAME( 0x02, 0x02, DEF_STR( Unknown ) ) // see comment above + PORT_DIPSETTING( 0x02, DEF_STR( Off ) ) + PORT_DIPSETTING( 0x00, DEF_STR( On ) ) PORT_DIPNAME( 0x04, 0x04, "Rom Test" ) PORT_DIPSETTING( 0x04, DEF_STR( Off ) ) PORT_DIPSETTING( 0x00, DEF_STR( On ) ) - PORT_BIT( 0x7a, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */ + PORT_BIT( 0x78, IP_ACTIVE_LOW, IPT_UNKNOWN ) /* probably unused */ PORT_BIT( 0x80, IP_ACTIVE_HIGH, IPT_SPECIAL ) PORT_CUSTOM_MEMBER(DEVICE_SELF, vicdual_state, read_coin_status, nullptr) PORT_COIN_DEFAULT @@ -3781,7 +3784,7 @@ GAME( 1979, headonn, headon, headonn, headonn, vicdual_state, 0, ROT270 GAME( 1979, headons, headon, headons, headons, vicdual_state, 0, ROT0, "bootleg (Sidam)", "Head On (Sidam bootleg, set 1)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1979, headonsa, headon, headons, headons, vicdual_state, 0, ROT0, "bootleg (Sidam)", "Head On (Sidam bootleg, set 2)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // won't coin up? GAME( 1979, headonmz, headon, headon, headonmz, vicdual_state, 0, ROT0, "bootleg", "Head On (bootleg, alt maze)", MACHINE_SUPPORTS_SAVE ) -GAME( 1979, supcrash, headon, headons, supcrash, vicdual_state, 0, ROT0, "bootleg", "Super Crash (bootleg of Head On)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) +GAME( 1979, supcrash, headon, headons, supcrash, vicdual_state, 0, ROT0, "bootleg (VGG)", "Super Crash (bootleg of Head On)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1979, hocrash, headon, headons, headons, vicdual_state, 0, ROT0, "bootleg (Fraber)", "Crash (bootleg of Head On)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1979, headon2, 0, headon2, headon2, vicdual_state, 0, ROT0, "Sega", "Head On 2", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1979, headon2s, headon2, headon2bw, car2, vicdual_state, 0, ROT0, "bootleg (Sidam)", "Head On 2 (Sidam bootleg)", MACHINE_NOT_WORKING | MACHINE_SUPPORTS_SAVE ) // won't coin up? @@ -3803,7 +3806,7 @@ GAME( 1981, brdrline, 0, brdrline, brdrline, vicdual_state, 0, ROT270 GAME( 1981, starrkr, brdrline, brdrline, starrkr, vicdual_state, 0, ROT270, "Sega", "Star Raker", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, brdrlins, brdrline, brdrline, brdrline, vicdual_state, 0, ROT270, "bootleg (Sidam)", "Borderline (Sidam bootleg)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, brdrlinb, brdrline, brdrline, brdrline, vicdual_state, 0, ROT270, "bootleg (Karateco)", "Borderline (Karateco bootleg)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) -GAME( 1981, brdrlinet, brdrline, tranqgun, tranqgun, vicdual_state, 0, ROT270, "Sega", "Borderline (Tranquillizer Gun conversion)", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) // official factory conversion +GAME( 1981, brdrlinet, brdrline, tranqgun, tranqgun, vicdual_state, 0, ROT270, "Sega", "Borderline (Tranquillizer Gun conversion)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) // official factory conversion GAME( 198?, startrks, 0, headons, headons, vicdual_state, 0, ROT0, "bootleg (Sidam)", "Star Trek (Head On hardware)", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1980, digger, 0, digger, digger, vicdual_state, 0, ROT270, "Sega", "Digger", MACHINE_NO_SOUND | MACHINE_SUPPORTS_SAVE ) GAME( 1981, pulsar, 0, pulsar, pulsar, vicdual_state, 0, ROT270, "Sega", "Pulsar", MACHINE_IMPERFECT_SOUND | MACHINE_SUPPORTS_SAVE ) diff --git a/src/mame/includes/interpro.h b/src/mame/includes/interpro.h index f65bcbb0c1f..e40969ad172 100644 --- a/src/mame/includes/interpro.h +++ b/src/mame/includes/interpro.h @@ -65,7 +65,6 @@ public: interpro_state(const machine_config &mconfig, device_type type, const char *tag) : driver_device(mconfig, type, tag) , m_maincpu(*this, INTERPRO_CPU_TAG) - , m_mmu(*this, INTERPRO_MMU_TAG) , m_ram(*this, RAM_TAG) , m_mcga(*this, INTERPRO_MCGA_TAG) , m_sga(*this, INTERPRO_SGA_TAG) @@ -78,10 +77,10 @@ public: , m_scsi(*this, INTERPRO_SCSI_DEVICE_TAG) , m_eth(*this, INTERPRO_ETH_TAG) , m_ioga(*this, INTERPRO_IOGA_TAG) - { } + { + } required_device<clipper_device> m_maincpu; - required_device<cammu_device> m_mmu; required_device<ram_device> m_ram; required_device<interpro_mcga_device> m_mcga; @@ -96,7 +95,7 @@ public: required_device<i82586_base_device> m_eth; required_device<interpro_ioga_device> m_ioga; - DECLARE_DRIVER_INIT(interpro); + DECLARE_DRIVER_INIT(common); enum sreg_error_mask { @@ -180,9 +179,17 @@ class turquoise_state : public interpro_state public: turquoise_state(const machine_config &mconfig, device_type type, const char *tag) : interpro_state(mconfig, type, tag) - {} + , m_d_cammu(*this, INTERPRO_MMU_TAG "_d") + , m_i_cammu(*this, INTERPRO_MMU_TAG "_i") + { + } + + DECLARE_DRIVER_INIT(turquoise); DECLARE_WRITE8_MEMBER(sreg_error_w) { m_sreg_error = data; } + + required_device<cammu_c3_device> m_d_cammu; + required_device<cammu_c3_device> m_i_cammu; }; class sapphire_state : public interpro_state @@ -190,14 +197,20 @@ class sapphire_state : public interpro_state public: sapphire_state(const machine_config &mconfig, device_type type, const char *tag) : interpro_state(mconfig, type, tag) + , m_mmu(*this, INTERPRO_MMU_TAG) , m_flash_lo(*this, INTERPRO_FLASH_TAG "_lo") , m_flash_hi(*this, INTERPRO_FLASH_TAG "_hi") - {} + { + } - required_device<intel_28f010_device> m_flash_lo; - required_device<intel_28f010_device> m_flash_hi; + DECLARE_DRIVER_INIT(sapphire); virtual DECLARE_WRITE16_MEMBER(sreg_ctrl2_w) override; + + required_device<cammu_c4_device> m_mmu; + + required_device<intel_28f010_device> m_flash_lo; + required_device<intel_28f010_device> m_flash_hi; }; #endif // MAME_INCLUDES_INTERPRO_H diff --git a/src/mame/machine/cammu.cpp b/src/mame/machine/cammu.cpp index 4e1d86b2076..5686cfa7d2e 100644 --- a/src/mame/machine/cammu.cpp +++ b/src/mame/machine/cammu.cpp @@ -2,28 +2,43 @@ // copyright-holders:Patrick Mackinlay /* - * An implementation of the Fairchild/Intergraph Cache and Memory Management Unit (CAMMU) designed for use with the CLIPPER CPU family. + * An implementation of the Fairchild/Intergraph Cache and Memory Management + * Unit (CAMMU) designed for use with the CLIPPER CPU family. * - * Primary reference: http://bitsavers.trailing-edge.com/pdf/fairchild/clipper/CLIPPER%20C300%2032-Bit%20Compute%20Engine.pdf - * Another reference: http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/CSD-86-289.pdf + * The C100 and C300 designs used a pair of identical CAMMU devices, each + * containing a cache, TLB and dynamic translation unit. One device was + * configured and used for instruction memory, the other for data. It is + * possible to write to multiple CAMMU devices sharing a common system bus by + * using "global" register addresses. + * + * C400 designs initially implemented the memory management and cache functions + * using discrete logic, later using a more highly integrated memory management + * implementation, but still using discrete cache memory. In these systems, the + * mmu is consolidated into a single logical unit handling both instruction and + * data memory, with distinctly different program-visible architectures on the + * C4I and C4E/T devices. Almost no documentation for these has been located. * - * This implementation is currently at a very early stage, and is only sufficient to handle the bare minimum of boot/diagnostic code. + * Primary reference: http://bitsavers.org/pdf/fairchild/clipper/CLIPPER%20C300%2032-Bit%20Compute%20Engine.pdf + * Another reference: http://www.eecs.berkeley.edu/Pubs/TechRpts/1986/CSD-86-289.pdf * * TODO - * - almost everything - * - refactor hardware tlb - * - faults - * - tlb + * - fault register values + * - alignment faults + * - c3 protection faults + * - hard-wired and dynamic tlb * - cache * - bus errors */ #include "emu.h" +#include "cammu.h" -#define VERBOSE 0 -#define DTU 1 // enable preliminary/incomplete address translation +#define LOG_GENERAL (1U << 0) +#define LOG_ACCESS (1U << 1) +#define LOG_DTU (1U << 2) -#include "cammu.h" +//#define VERBOSE (LOG_GENERAL | LOG_ACCESS | LOG_DTU) +#include "logmacro.h" // each variant of the cammu has different registers and a different addressing map DEVICE_ADDRESS_MAP_START(map, 32, cammu_c4t_device) @@ -75,28 +90,21 @@ DEVICE_ADDRESS_MAP_START(map, 32, cammu_c4i_device) ADDRESS_MAP_END DEVICE_ADDRESS_MAP_START(map, 32, cammu_c3_device) - // the first AM_NOP in each range is in fact the TLB in the C3 CAMMU - - AM_RANGE(0x800, 0x8ff) AM_NOP - AM_RANGE(0x904, 0x907) AM_READWRITE(d_s_pdo_r, d_s_pdo_w) - AM_RANGE(0x908, 0x90b) AM_READWRITE(d_u_pdo_r, d_u_pdo_w) - AM_RANGE(0x910, 0x913) AM_READWRITE(d_fault_r, d_fault_w) - AM_RANGE(0x940, 0x943) AM_READWRITE(d_control_r, d_control_w) - AM_RANGE(0x980, 0x983) AM_READWRITE(d_reset_r, d_reset_w) - - AM_RANGE(0xa00, 0xaff) AM_NOP - AM_RANGE(0xb04, 0xb07) AM_READWRITE(i_s_pdo_r, i_s_pdo_w) - AM_RANGE(0xb08, 0xb0b) AM_READWRITE(i_u_pdo_r, i_u_pdo_w) - AM_RANGE(0xb10, 0xb13) AM_READWRITE(i_fault_r, i_fault_w) - AM_RANGE(0xb40, 0xb43) AM_READWRITE(i_control_r, i_control_w) - AM_RANGE(0xb80, 0xb83) AM_READWRITE(i_reset_r, i_reset_w) - - AM_RANGE(0xc00, 0xcff) AM_NOP - AM_RANGE(0xd04, 0xd07) AM_WRITE(g_s_pdo_w) - AM_RANGE(0xd08, 0xd0b) AM_WRITE(g_u_pdo_w) - AM_RANGE(0xd10, 0xd13) AM_WRITE(g_fault_w) - AM_RANGE(0xd40, 0xd43) AM_WRITE(g_control_w) - AM_RANGE(0xd80, 0xd83) AM_WRITE(g_reset_w) + AM_RANGE(0x000, 0x0ff) AM_NOP // tlb + AM_RANGE(0x104, 0x107) AM_READWRITE(s_pdo_r, s_pdo_w) + AM_RANGE(0x108, 0x10b) AM_READWRITE(u_pdo_r, u_pdo_w) + AM_RANGE(0x110, 0x113) AM_READWRITE(fault_r, fault_w) + AM_RANGE(0x140, 0x143) AM_READWRITE(control_r, control_w) + AM_RANGE(0x180, 0x183) AM_READWRITE(reset_r, reset_w) +ADDRESS_MAP_END + +DEVICE_ADDRESS_MAP_START(map_global, 32, cammu_c3_device) + AM_RANGE(0x000, 0x0ff) AM_NOP // global tlb + AM_RANGE(0x104, 0x107) AM_WRITE(g_s_pdo_w) + AM_RANGE(0x108, 0x10b) AM_WRITE(g_u_pdo_w) + AM_RANGE(0x110, 0x113) AM_WRITE(g_fault_w) + AM_RANGE(0x140, 0x143) AM_WRITE(g_control_w) + AM_RANGE(0x180, 0x183) AM_WRITE(g_reset_w) ADDRESS_MAP_END DEFINE_DEVICE_TYPE(CAMMU_C4T, cammu_c4t_device, "c4t", "C4E/C4T CAMMU") @@ -104,41 +112,62 @@ DEFINE_DEVICE_TYPE(CAMMU_C4I, cammu_c4i_device, "c4i", "C4I CAMMU") DEFINE_DEVICE_TYPE(CAMMU_C3, cammu_c3_device, "c3", "C1/C3 CAMMU") cammu_c4t_device::cammu_c4t_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : cammu_c4_device(mconfig, CAMMU_C4T, tag, owner, clock) + : cammu_c4_device(mconfig, CAMMU_C4T, tag, owner, clock, CID_C4T) { } cammu_c4i_device::cammu_c4i_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : cammu_c4_device(mconfig, CAMMU_C4I, tag, owner, clock) + : cammu_c4_device(mconfig, CAMMU_C4I, tag, owner, clock, CID_C4I) { } -cammu_c4_device::cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) +cammu_c4_device::cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u32 cammu_id) : cammu_device(mconfig, type, tag, owner, clock) + , m_control(cammu_id) { } cammu_c3_device::cammu_c3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : cammu_device(mconfig, CAMMU_C3, tag, owner, clock) + , m_control(CID_C3) + , m_linked{ this } { } cammu_device::cammu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) - , device_memory_interface(mconfig, *this), - m_main_space_config("main", ENDIANNESS_LITTLE, 32, 32, 0), - m_io_space_config("io", ENDIANNESS_LITTLE, 32, 32, 0), - m_boot_space_config("boot", ENDIANNESS_LITTLE, 32, 32, 0), - m_main_space(nullptr), - m_io_space(nullptr), - m_boot_space(nullptr), - m_ssw_func(*this) + , device_memory_interface(mconfig, *this) + , m_main_space_config("main", ENDIANNESS_LITTLE, 32, 32, 0) + , m_io_space_config("io", ENDIANNESS_LITTLE, 32, 32, 0) + , m_boot_space_config("boot", ENDIANNESS_LITTLE, 32, 32, 0) + , m_main_space(nullptr) + , m_io_space(nullptr) + , m_boot_space(nullptr) + , m_ssw_func(*this) + , m_exception_func(*this) +{ +} + +device_memory_interface::space_config_vector cammu_device::memory_space_config() const { + return space_config_vector { + std::make_pair(0, &m_main_space_config), + std::make_pair(1, &m_io_space_config), + std::make_pair(2, &m_boot_space_config) + }; +} + +void cammu_c3_device::static_add_linked(device_t &device, const char *const tag) +{ + cammu_c3_device &parent = downcast<cammu_c3_device &>(device); + + parent.m_linked.push_back(downcast<cammu_c3_device *>(parent.siblingdevice(tag))); } void cammu_device::device_start() { m_ssw_func.resolve(); + m_exception_func.resolve(); m_main_space = &space(0); m_io_space = &space(1); @@ -149,268 +178,321 @@ void cammu_device::device_reset() { } -device_memory_interface::space_config_vector cammu_device::memory_space_config() const +void cammu_c4_device::device_start() { - return space_config_vector { - std::make_pair(0, &m_main_space_config), - std::make_pair(1, &m_io_space_config), - std::make_pair(2, &m_boot_space_config) - }; + cammu_device::device_start(); + + save_item(NAME(m_s_pdo)); + save_item(NAME(m_u_pdo)); + save_item(NAME(m_control)); + + save_item(NAME(m_i_fault)); + save_item(NAME(m_fault_address_1)); + save_item(NAME(m_fault_address_2)); + save_item(NAME(m_fault_data_1_lo)); + save_item(NAME(m_fault_data_1_hi)); + save_item(NAME(m_fault_data_2_lo)); + save_item(NAME(m_fault_data_2_hi)); } -READ32_MEMBER(cammu_device::insn_r) +void cammu_c4i_device::device_start() { - u32 ssw = m_ssw_func(); - u32 va = offset << 2; + cammu_c4_device::device_start(); + + save_item(NAME(m_reset)); + save_item(NAME(m_clr_s_data_tlb)); + save_item(NAME(m_clr_u_data_tlb)); + save_item(NAME(m_clr_s_insn_tlb)); + save_item(NAME(m_clr_u_insn_tlb)); + save_item(NAME(m_test_data)); + save_item(NAME(m_test_address)); +} - // in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb - if ((ssw & 0x40000000) == 0 && (va & ~0x7fff) == 0) - { - switch (va & 0xf000) - { - case 0x0000: - case 0x1000: - case 0x2000: - case 0x3000: - // pages 0-3: main space pages 0-3 - return m_main_space->read_dword(va, mem_mask); +void cammu_c4t_device::device_start() +{ + cammu_c4_device::device_start(); + + save_item(NAME(m_ram_line)); + save_item(NAME(m_htlb_offset)); + save_item(NAME(m_c4_bus_poll)); + save_item(NAME(m_bio_control)); + save_item(NAME(m_bio_address_tag)); + + save_item(NAME(m_cache_data_lo)); + save_item(NAME(m_cache_data_hi)); + save_item(NAME(m_cache_cpu_tag)); + save_item(NAME(m_cache_system_tag_valid)); + save_item(NAME(m_cache_system_tag)); + save_item(NAME(m_tlb_va_line)); + save_item(NAME(m_tlb_ra_line)); +} - case 0x4000: - case 0x5000: - // pages 4-5: i/o space pages 0-1 - return m_io_space->read_dword(va & 0x1fff, mem_mask); +void cammu_c3_device::device_start() +{ + cammu_device::device_start(); - case 0x6000: - case 0x7000: - // pages 6-7: boot space pages 0-1 - return m_boot_space->read_dword(va & 0x1fff, mem_mask); - } - } + save_item(NAME(m_s_pdo)); + save_item(NAME(m_u_pdo)); + save_item(NAME(m_fault)); + save_item(NAME(m_control)); + save_item(NAME(m_reset)); +} - // if not in mapped mode, default to main memory space - if ((ssw & 0x04000000) == 0) - return m_main_space->read_dword(va); +void cammu_c3_device::device_reset() +{ + cammu_device::device_reset(); -#if DTU - // get the page table entry - u32 pte = get_pte(va, ssw & 0x40000000, false); + m_control = (m_control & CNTL_CID) | (CNTL_ATE | UST_3 | CNTL_EWIR | CNTL_EWIW | CNTL_EWCW | CNTL_EP); + m_reset = 0; +} - // translate the address - u32 ra = (pte & 0xfffff000) | (va & 0xfff); +READ32_MEMBER(cammu_device::read) +{ + const u32 virtual_address = (offset << 2) | ( + (mem_mask & 0x00ffffff) == 0 ? 0x3 : + (mem_mask & 0x0000ffff) == 0 ? 0x2 : + (mem_mask & 0x000000ff) == 0 ? 0x1 : 0x0); + offs_t physical_address; - // execute the read based on the system tag - switch ((pte & 0xe00) >> 9) - { - case 0: - case 1: - case 2: - case 3: - return m_main_space->read_dword(ra, mem_mask); + LOGMASKED(LOG_ACCESS, "%s read address 0x%08x mem_mask 0x%08x (%s)\n", + space.name(), virtual_address, mem_mask, machine().describe_context()); - case 4: - return m_io_space->read_dword(ra, mem_mask); + address_space *physical_space = translate_address(virtual_address, space.spacenum() == AS_PROGRAM ? ACCESS_X : ACCESS_R, &physical_address); - case 5: - return m_boot_space->read_dword(ra, mem_mask); + if (physical_space != nullptr) + return physical_space->read_dword(physical_address, mem_mask); + else + return space.unmap(); +} - case 6: // cache purge - case 7: // main memory, slave mode - fatalerror("system tag %d not supported %s\n", (pte & 0xe00) >> 9, machine().describe_context().c_str()); - } +WRITE32_MEMBER(cammu_device::write) +{ + const u32 virtual_address = (offset << 2) | ( + (mem_mask & 0x00ffffff) == 0 ? 0x3 : + (mem_mask & 0x0000ffff) == 0 ? 0x2 : + (mem_mask & 0x000000ff) == 0 ? 0x1 : 0x0); + offs_t physical_address; - return 0; -#else - // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O - if ((va & 0xff000000) == 0x00000000 || (va & 0xfff00000) == 0x7f100000) - return m_main_space->read_dword(va, mem_mask); - else - return m_io_space->read_dword(va, mem_mask); -#endif + LOGMASKED(LOG_ACCESS, "%s write address 0x%08x data 0x%08x mem_mask 0x%08x (%s)\n", + space.name(), virtual_address, data, mem_mask, machine().describe_context()); + + address_space *physical_space = translate_address(virtual_address, ACCESS_W, &physical_address); + + if (physical_space != nullptr) + physical_space->write_dword(physical_address, data, mem_mask); } -READ32_MEMBER(cammu_device::data_r) +address_space *cammu_device::translate_address(const offs_t virtual_address, const access_t mode, offs_t *physical_address) { - u32 ssw = m_ssw_func(); - u32 va = offset << 2; + // get ssw and user/supervisor mode + const u32 ssw = m_ssw_func(); + const bool user = mode == ACCESS_X ? ssw & SSW_U : ssw & (SSW_U | SSW_UU); + + // TODO: check for alignment faults - // in supervisor mode (and not user data mode), the first 8 pages are always mapped via the hard-wired tlb - if (((ssw & 0x50000000) == 0) && ((va & ~0x7fff) == 0)) + // in supervisor mode, the first 8 pages are always mapped via the hard-wired tlb + if (!user && (virtual_address & ~0x7fff) == 0) { - switch (va & 0xf000) + switch (virtual_address & 0x7000) { case 0x0000: case 0x1000: case 0x2000: case 0x3000: // pages 0-3: main space pages 0-3 - return m_main_space->read_dword(va, mem_mask); + *physical_address = virtual_address & 0x3fff; + return m_main_space; case 0x4000: case 0x5000: // pages 4-5: i/o space pages 0-1 - return m_io_space->read_dword(va & 0x1fff, mem_mask); + *physical_address = virtual_address & 0x1fff; + return m_io_space; case 0x6000: case 0x7000: // pages 6-7: boot space pages 0-1 - return m_boot_space->read_dword(va & 0x1fff, mem_mask); + *physical_address = virtual_address & 0x1fff; + return m_boot_space; } } - // if not in mapped mode, default to main memory space - if ((ssw & 0x04000000) == 0) - return m_main_space->read_dword(va); + // if not in mapped mode, use unmapped system tag + if ((ssw & SSW_M) == 0) + { + *physical_address = virtual_address; + + return get_ust_space(); + } -#if DTU // get the page table entry - u32 pte = get_pte(va, ssw & 0x50000000, space.spacenum() == AS_DATA); + const u32 pte = get_pte(virtual_address, user); - // translate the address - u32 ra = (pte & 0xfffff000) | (va & 0xfff); + // check for page faults + if (pte & PTE_F) + { + if (!machine().side_effect_disabled()) + { + LOG("%s page fault address 0x%08x ssw 0x%08x pte 0x%08x (%s)\n", + mode == ACCESS_X ? "instruction" : "data", + virtual_address, ssw, pte, machine().describe_context()); + + set_fault_address(virtual_address); + m_exception_func(mode == ACCESS_X ? EXCEPTION_I_PAGE_FAULT : EXCEPTION_D_PAGE_FAULT); + } + + return nullptr; + } - // execute the read based on the system tag - switch ((pte & 0xe00) >> 9) + // check for protection level faults + if (!machine().side_effect_disabled() && !get_access(mode, pte, ssw)) { - case 0: - case 1: - case 2: - case 3: - return m_main_space->read_dword(ra, mem_mask); + LOG("%s protection fault address 0x%08x ssw 0x%08x pte 0x%08x (%s)\n", + mode == ACCESS_X ? "execute" : mode == ACCESS_R ? "read" : "write", + virtual_address, ssw, pte, machine().describe_context()); + + set_fault_address(virtual_address); + m_exception_func( + mode == ACCESS_X ? EXCEPTION_I_EXECUTE_PROTECT_FAULT : + mode == ACCESS_R ? EXCEPTION_D_READ_PROTECT_FAULT : + EXCEPTION_D_WRITE_PROTECT_FAULT); - case 4: - return m_io_space->read_dword(ra, mem_mask); + return nullptr; + } - case 5: - return m_boot_space->read_dword(ra, mem_mask); + // translate the address + *physical_address = (pte & ~CAMMU_PAGE_MASK) | (virtual_address & CAMMU_PAGE_MASK); + LOGMASKED(LOG_DTU, "%s address translated 0x%08x\n", mode == ACCESS_X ? "instruction" : "data", *physical_address); - case 6: // cache purge - case 7: // main memory, slave mode - fatalerror("data_r: system tag %d not supported at %s\n", (pte & 0xe00) >> 9, machine().describe_context().c_str()); + // return the physical space based on the system tag + switch (pte & PTE_ST) + { + case ST_0: + case ST_1: + case ST_2: + case ST_3: + // main memory space + return m_main_space; + + case ST_4: + // i/o space + return m_io_space; + + case ST_5: + // boot space + return m_boot_space; + + case ST_6: + // cache purge + case ST_7: + // main memory, slave mode + if (!machine().side_effect_disabled()) + fatalerror("%s page table entry system tag %d not supported\n", + mode == ACCESS_X ? "instruction" : "data", (pte & PTE_ST) >> 9); + break; } - return 0; -#else - // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O - if ((va & 0xff000000) == 0x00000000 || (va & 0xfff00000) == 0x7f100000) - return m_main_space->read_dword(va, mem_mask); - else - return m_io_space->read_dword(va, mem_mask); -#endif + return nullptr; } -WRITE32_MEMBER(cammu_device::data_w) +// return the page table entry for a given virtual address +u32 cammu_device::get_pte(const u32 va, const bool user) { - u32 ssw = m_ssw_func(); - u32 va = offset << 2; - - // in supervisor mode (and not user data mode), the first 8 pages are always mapped via the hard-wired tlb - if (((ssw & 0x50000000) == 0) && ((va & ~0x7fff) == 0)) + const u32 tlb_index = user ? 1 : 0; + if ((va & ~CAMMU_PAGE_MASK) != m_tlb[tlb_index].va) { - switch (va & 0xf000) - { - case 0x0000: - case 0x1000: - case 0x2000: - case 0x3000: - // pages 0-3: main space pages 0-3 - m_main_space->write_dword(va, data, mem_mask); - return; + // get page table directory origin from user or supervisor pdo register + const u32 pdo = get_pdo(user); - case 0x4000: - case 0x5000: - // pages 4-5: i/o space pages 0-1 - m_io_space->write_dword(va & 0x1fff, data, mem_mask); - return; + // get page table directory index from top 12 bits of virtual address + const u32 ptdi = (va & VA_PTDI) >> 20; - case 0x6000: - case 0x7000: - // pages 6-7: boot space pages 0-1 - m_boot_space->write_dword(va & 0x1fff, data, mem_mask); - return; - } - } + // fetch page table directory entry + const u32 ptde = m_main_space->read_dword(pdo | ptdi); - // if not in mapped mode, default to main memory space - if ((ssw & 0x04000000) == 0) - { - m_main_space->write_dword(va, data, mem_mask); - return; - } + LOGMASKED(LOG_DTU, "get_pte pdo 0x%08x ptdi 0x%08x ptde 0x%08x\n", pdo, ptdi, ptde); -#if DTU - // get the page table entry - u32 pte = get_pte(va, ssw & 0x50000000, space.spacenum() == AS_DATA); + // check for page table directory entry fault + if (ptde & PTDE_F) + return PTE_F; - // translate the address - u32 ra = (pte & 0xfffff000) | (va & 0xfff); + // get the page table origin from the page table directory entry + const u32 pto = ptde & PTDE_PTO; - // execute the read based on the system tag - switch ((pte & 0xe00) >> 9) - { - case 0: - case 1: - case 2: - case 3: - m_main_space->write_dword(ra, data, mem_mask); - break; + // get the page table index from the middle 12 bits of the virtual address + const u32 pti = (va & VA_PTI) >> 10; - case 4: - m_io_space->write_dword(ra, data, mem_mask); - break; + // fetch page table entry + const u32 pte = m_main_space->read_dword(pto | pti); - case 5: - m_boot_space->write_dword(ra, data, mem_mask); - break; + LOGMASKED(LOG_DTU, "get_pte pto 0x%08x pti 0x%08x pte 0x%08x\n", pto, pti, pte); - case 6: // cache purge - case 7: // main memory, slave mode - fatalerror("data_w: system tag %d not supported at %s\n", (pte & 0xe00) >> 9, machine().describe_context().c_str()); - break; + // check for page table entry fault + if (pte & PTE_F) + return PTE_F; + + // add the pte to the tlb + m_tlb[tlb_index].va = va & ~CAMMU_PAGE_MASK; + m_tlb[tlb_index].pte = pte; + + LOGMASKED(LOG_DTU, "get_pte address 0x%08x pte 0x%08x (%s)\n", va, pte, machine().describe_context()); } -#else - // FIXME: currently maps addresses with upper bits 0x00 or 0x7f1 to main memory and everything else to I/O - if ((va & 0xff000000) == 0x00000000 || (va & 0xfff00000) == 0x7f100000) - m_main_space->write_dword(va, data, mem_mask); - else - m_io_space->write_dword(va, data, mem_mask); -#endif + + return m_tlb[tlb_index].pte; } -u32 cammu_c4_device::get_pte(u32 va, int user, bool data) +address_space *cammu_c4i_device::get_ust_space() const { - u32 tlb_index = (user ? 2 : 0) + (data ? 1 : 0); - if ((va & 0xfffff000) != m_tlb[tlb_index].va) + switch (m_control & CNTL_UMM) { - // return the page table entry for a given virtual address - u32 pdo = user ? m_u_pdo : m_s_pdo; - - u32 pto = m_main_space->read_dword(pdo | (va & 0xffc00000) >> 20); - if (pto & 0x1) - fatalerror("can't deal with pto faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + case UMM_MM: return m_main_space; + case UMM_MMRIO: return m_main_space; // FIXME: what determines main or i/o? + case UMM_IO: return m_io_space; + } - u32 pte = m_main_space->read_dword((pto & 0xfffff000) | (va & 0x003ff000) >> 10); - if (pte & 0x1) - fatalerror("can't deal with pte faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + return m_main_space; +} - m_tlb[tlb_index].va = va & 0xfffff000; - m_tlb[tlb_index].pte = pte; +bool cammu_c4_device::get_access(const access_t mode, const u32 pte, const u32 ssw) const +{ + switch (mode) + { + case ACCESS_R: return pte & 0x20; + case ACCESS_W: return pte & 0x10; + case ACCESS_X: return pte & 0x08; } - return m_tlb[tlb_index].pte; + return false; } -u32 cammu_c3_device::get_pte(u32 va, int user, bool data) +bool cammu_c3_device::get_access(const access_t mode, const u32 pte, const u32 ssw) const { - // return the page table entry for a given virtual address - u32 pdo = user ? (data ? m_d_u_pdo : m_i_u_pdo) : (data ? m_d_s_pdo : m_i_s_pdo); + // FIXME: logic is not correct yet + return true; - u32 pto = m_main_space->read_dword(pdo | (va & 0xffc00000) >> 20); - if (pto & 0x1) - fatalerror("can't deal with pto faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + const u8 column = (mode == ACCESS_X ? i_cammu_column : d_cammu_column)[(ssw & SSW_PL) >> 9]; + const u8 access = cammu_matrix[column][(pte & PTE_PL) >> 3]; - u32 pte = m_main_space->read_dword((pto & 0xfffff000) | (va & 0x003ff000) >> 10); - if (pte & 0x1) - fatalerror("can't deal with pte faults va 0x%08x %s\n", va, machine().describe_context().c_str()); + switch (mode) + { + case ACCESS_R: return access & R; + case ACCESS_W: return access & W; + case ACCESS_X: return access & E; + } - return pte; + return false; } + +// C100/C300 CAMMU protection level matrix +const u8 cammu_c3_device::i_cammu_column[] = { 1, 1, 0, 0, 1, 1, 0, 0, 3, 3, 2, 2, 3, 3, 2, 2 }; +const u8 cammu_c3_device::d_cammu_column[] = { 1, 1, 0, 0, 3, 2, 3, 2, 3, 3, 2, 2, 3, 3, 2, 2 }; + +const cammu_c3_device::c3_access_t cammu_c3_device::cammu_matrix[][16] = +{ + { RW, RW, RW, RW, RW, RW, RW, RWE, RE, R, R, R, N, N, N, N }, + { N, RW, RW, RW, RW, RW, R, RWE, N, RE, R, R, RE, N, N, N }, + { N, N, RW, RW, RW, R, R, RWE, N, N, RE, RE, N, RE, N, N }, + { N, N, N, RW, R, R, R, RWE, N, N, N, RE, RE, N, RE, N } +}; + + diff --git a/src/mame/machine/cammu.h b/src/mame/machine/cammu.h index 9ea301f6896..28eb32f07ad 100644 --- a/src/mame/machine/cammu.h +++ b/src/mame/machine/cammu.h @@ -9,17 +9,99 @@ #define MCFG_CAMMU_SSW_CB(_sswcb) \ devcb = &cammu_device::static_set_ssw_callback(*device, DEVCB_##_sswcb); +#define MCFG_CAMMU_EXCEPTION_CB(_exceptioncb) \ + devcb = &cammu_device::static_set_exception_callback(*device, DEVCB_##_exceptioncb); + +#define MCFG_CAMMU_LINK(_tag) \ + cammu_c3_device::static_add_linked(*device, _tag); + class cammu_device : public device_t, public device_memory_interface { public: template <class Object> static devcb_base &static_set_ssw_callback(device_t &device, Object &&cb) { return downcast<cammu_device &>(device).m_ssw_func.set_callback(std::forward<Object>(cb)); } + template <class Object> static devcb_base &static_set_exception_callback(device_t &device, Object &&cb) { return downcast<cammu_device &>(device).m_exception_func.set_callback(std::forward<Object>(cb)); } - virtual DECLARE_ADDRESS_MAP(map, 32) = 0; + static const u32 CAMMU_PAGE_SIZE = 0x1000; + static const u32 CAMMU_PAGE_MASK = (CAMMU_PAGE_SIZE - 1); + + enum ssw_mask : u32 + { + SSW_M = 0x04000000, // mapped mode + SSW_KU = 0x08000000, // user protect key + SSW_UU = 0x10000000, // user data mode + SSW_K = 0x20000000, // protect key + SSW_U = 0x40000000, // user mode + + SSW_PL = 0x78000000 // protection level relevant bits + }; + + enum exception_vectors : u16 + { + // data memory trap group + EXCEPTION_D_CORRECTED_MEMORY_ERROR = 0x108, + EXCEPTION_D_UNCORRECTABLE_MEMORY_ERROR = 0x110, + EXCEPTION_D_ALIGNMENT_FAULT = 0x120, + EXCEPTION_D_PAGE_FAULT = 0x128, + EXCEPTION_D_READ_PROTECT_FAULT = 0x130, + EXCEPTION_D_WRITE_PROTECT_FAULT = 0x138, + + // instruction memory trap group + EXCEPTION_I_CORRECTED_MEMORY_ERROR = 0x288, + EXCEPTION_I_UNCORRECTABLE_MEMORY_ERROR = 0x290, + EXCEPTION_I_ALIGNMENT_FAULT = 0x2a0, + EXCEPTION_I_PAGE_FAULT = 0x2a8, + EXCEPTION_I_EXECUTE_PROTECT_FAULT = 0x2b0, + }; + + enum pdo_mask : u32 + { + PDO_MASK = 0xfffff000 + }; - DECLARE_READ32_MEMBER(insn_r); + enum ptde_mask : u32 + { + PTDE_F = 0x00000001, // page fault + PTDE_PTO = 0xfffff000 // page table origin + }; - DECLARE_READ32_MEMBER(data_r); - DECLARE_WRITE32_MEMBER(data_w); + enum pte_mask : u32 + { + PTE_F = 0x00000001, // page fault + PTE_R = 0x00000002, // referenced flag + PTE_D = 0x00000004, // dirty flag + PTE_PL = 0x00000078, // protection level + PTE_S = 0x00000180, // system reserved + PTE_ST = 0x00000e00, // system tag + PTE_RA = 0xfffff000, // real address + + PTE_CW = 0x00000040, // copy on write (c400) + PTE_NDREF = 0x00000080, // secondary reference (software) / copy on write (fault)? + PTE_LOCK = 0x00000100 // page lock (software) + }; + + enum pte_st_mask : u32 + { + ST_0 = 0x00000000, // private, write-through, main memory space + ST_1 = 0x00000200, // shared, write-through, main memory space + ST_2 = 0x00000400, // private, copy-back, main memory space + ST_3 = 0x00000600, // noncacheable, main memory space + ST_4 = 0x00000800, // noncacheable, i/o space + ST_5 = 0x00000a00, // noncacheable, boot space + ST_6 = 0x00000c00, // cache purge + ST_7 = 0x00000e00 // slave i/o + }; + + enum va_mask : u32 + { + VA_POFS = 0x00000fff, // page offset + VA_PTI = 0x003ff000, // page table index + VA_PTDI = 0xffc00000 // page table directory index + }; + + virtual DECLARE_ADDRESS_MAP(map, 32) = 0; + + DECLARE_READ32_MEMBER(read); + DECLARE_WRITE32_MEMBER(write); protected: cammu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); @@ -30,59 +112,82 @@ protected: // device_memory_interface overrides virtual space_config_vector memory_space_config() const override; + //virtual bool memory_translate(int spacenum, int intention, offs_t &address) override; - virtual u32 get_pte(u32 va, int user, bool data) = 0; + enum access_t + { + ACCESS_R = 1, + ACCESS_W = 2, + ACCESS_X = 3 + }; + + address_space *translate_address(const offs_t virtual_address, const access_t mode, offs_t *physical_address); + + u32 get_pte(const u32 va, const bool user); + + virtual bool get_access(const access_t mode, const u32 pte, const u32 ssw) const = 0; + virtual bool get_alignment() const = 0; + virtual u32 get_pdo(const bool user) const = 0; + virtual address_space *get_ust_space() const = 0; + + virtual void set_fault_address(const u32 va) = 0; -private: address_space_config m_main_space_config; address_space_config m_io_space_config; address_space_config m_boot_space_config; -protected: address_space *m_main_space; address_space *m_io_space; address_space *m_boot_space; + devcb_read32 m_ssw_func; + devcb_write16 m_exception_func; + struct { u32 va; u32 pte; - } m_tlb[4]; + } + m_tlb[2]; private: - devcb_read32 m_ssw_func; }; class cammu_c4_device : public cammu_device { public: - cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - - DECLARE_READ32_MEMBER(s_pdo_r) { return m_s_pdo; } - DECLARE_WRITE32_MEMBER(s_pdo_w) { m_s_pdo = data; } - DECLARE_READ32_MEMBER(u_pdo_r) { return m_u_pdo; } - DECLARE_WRITE32_MEMBER(u_pdo_w) { m_u_pdo = data; } + DECLARE_READ32_MEMBER(s_pdo_r) const { return m_s_pdo; } + DECLARE_WRITE32_MEMBER(s_pdo_w) { m_s_pdo = ((m_s_pdo & ~mem_mask) | (data & mem_mask)) & PDO_MASK; } + DECLARE_READ32_MEMBER(u_pdo_r) const { return m_u_pdo; } + DECLARE_WRITE32_MEMBER(u_pdo_w) { m_u_pdo = ((m_u_pdo & ~mem_mask) | (data & mem_mask)) & PDO_MASK; } - virtual DECLARE_READ32_MEMBER(control_r) = 0; + virtual DECLARE_READ32_MEMBER(control_r) const = 0; virtual DECLARE_WRITE32_MEMBER(control_w) = 0; - DECLARE_READ32_MEMBER(i_fault_r) { return m_i_fault; } + DECLARE_READ32_MEMBER(i_fault_r) const { return m_i_fault; } DECLARE_WRITE32_MEMBER(i_fault_w) { m_i_fault = data; } - DECLARE_READ32_MEMBER(fault_address_1_r) { return m_fault_address_1; } + DECLARE_READ32_MEMBER(fault_address_1_r) const { return m_fault_address_1; } DECLARE_WRITE32_MEMBER(fault_address_1_w) { m_fault_address_1 = data; } - DECLARE_READ32_MEMBER(fault_address_2_r) { return m_fault_address_2; } + DECLARE_READ32_MEMBER(fault_address_2_r) const { return m_fault_address_2; } DECLARE_WRITE32_MEMBER(fault_address_2_w) { m_fault_address_2 = data; } - DECLARE_READ32_MEMBER(fault_data_1_lo_r) { return m_fault_data_1_lo; } + DECLARE_READ32_MEMBER(fault_data_1_lo_r) const { return m_fault_data_1_lo; } DECLARE_WRITE32_MEMBER(fault_data_1_lo_w) { m_fault_data_1_lo = data; } - DECLARE_READ32_MEMBER(fault_data_1_hi_r) { return m_fault_data_1_hi; } + DECLARE_READ32_MEMBER(fault_data_1_hi_r) const { return m_fault_data_1_hi; } DECLARE_WRITE32_MEMBER(fault_data_1_hi_w) { m_fault_data_1_hi = data; } - DECLARE_READ32_MEMBER(fault_data_2_lo_r) { return m_fault_data_2_lo; } + DECLARE_READ32_MEMBER(fault_data_2_lo_r) const { return m_fault_data_2_lo; } DECLARE_WRITE32_MEMBER(fault_data_2_lo_w) { m_fault_data_2_lo = data; } - DECLARE_READ32_MEMBER(fault_data_2_hi_r) { return m_fault_data_2_hi; } + DECLARE_READ32_MEMBER(fault_data_2_hi_r) const { return m_fault_data_2_hi; } DECLARE_WRITE32_MEMBER(fault_data_2_hi_w) { m_fault_data_2_hi = data; } protected: - u32 get_pte(u32 va, int user, bool data) override; + cammu_c4_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, u32 cammu_id); + + virtual void device_start() override; + + virtual bool get_access(const access_t mode, const u32 pte, const u32 ssw) const override; + virtual u32 get_pdo(const bool user) const override { return user ? m_u_pdo : m_s_pdo; } + + virtual void set_fault_address(const u32 va) override { m_fault_address_1 = va; } u32 m_s_pdo; u32 m_u_pdo; @@ -104,36 +209,73 @@ public: virtual DECLARE_ADDRESS_MAP(map, 32) override; - DECLARE_READ32_MEMBER(ram_line_r) { return m_ram_line; } + DECLARE_READ32_MEMBER(ram_line_r) const { return m_ram_line; } DECLARE_WRITE32_MEMBER(ram_line_w) { m_ram_line = data; } - DECLARE_READ32_MEMBER(htlb_offset_r) { return m_htlb_offset; } + DECLARE_READ32_MEMBER(htlb_offset_r) const { return m_htlb_offset; } DECLARE_WRITE32_MEMBER(htlb_offset_w) { m_htlb_offset = data; } - DECLARE_READ32_MEMBER(c4_bus_poll_r) { return m_c4_bus_poll; } + DECLARE_READ32_MEMBER(c4_bus_poll_r) const { return m_c4_bus_poll; } DECLARE_WRITE32_MEMBER(c4_bus_poll_w) { m_c4_bus_poll = data; } - virtual DECLARE_READ32_MEMBER(control_r) override { return m_control | 0x00000000; } - virtual DECLARE_WRITE32_MEMBER(control_w) override { m_control = data & 0x00ffffff; } - DECLARE_READ32_MEMBER(bio_control_r) { return m_bio_control; } + + enum control_mask : u32 + { + CNTL_RUV = 0x00000001, // reset user valid + CNTL_RSV = 0x00000002, // reset supervisor valid + CNTL_DBWR = 0x00000004, // disable bus watch read + CNTL_ATD = 0x00000008, // alignment trap disable + CNTL_UST = 0x00000030, // unmapped system tag + CNTL_IOTS = 0x00000040, // i/o tag select + CNTL_UVS = 0x00000080, // user valid status + CNTL_PB = 0x00000100, // purge busy + CNTL_CICT = 0x00000200, // clear i-side cache tags + CNTL_CFR = 0x00000400, // clear trap registers + CNTL_HTLBD = 0x00000800, // htlb disable + CNTL_CDCT = 0x00001000, // clear d-side cache tags + CNTL_CID = 0xff000000 // cammu id + }; + + enum control_ust_mask : u32 + { + UST_NCA = 0x00, // unmapped system tag, noncacheable + UST_PWT = 0x10, // unmapped system tag, write through + UST_PCB = 0x20, // unmapped system tag, copy back + UST_PGE = 0x30 // unmapped system tag, purge mode + }; + + enum control_cid_mask : u32 + { + CID_C4T = 0x00000000 // unknown + }; + + virtual DECLARE_READ32_MEMBER(control_r) const override { return m_control; } + virtual DECLARE_WRITE32_MEMBER(control_w) override { m_control = ((m_control & (~mem_mask | CNTL_CID)) | (data & (mem_mask & ~CNTL_CID))); } + DECLARE_READ32_MEMBER(bio_control_r) const { return m_bio_control; } DECLARE_WRITE32_MEMBER(bio_control_w) { m_bio_control = data; } - DECLARE_READ32_MEMBER(bio_address_tag_r) { return m_bio_address_tag; } + DECLARE_READ32_MEMBER(bio_address_tag_r) const { return m_bio_address_tag; } DECLARE_WRITE32_MEMBER(bio_address_tag_w) { m_bio_address_tag = data; } - DECLARE_READ32_MEMBER(cache_data_lo_r) { return m_cache_data_lo; } + DECLARE_READ32_MEMBER(cache_data_lo_r) const { return m_cache_data_lo; } DECLARE_WRITE32_MEMBER(cache_data_lo_w) { m_cache_data_lo = data; } - DECLARE_READ32_MEMBER(cache_data_hi_r) { return m_cache_data_hi; } + DECLARE_READ32_MEMBER(cache_data_hi_r) const { return m_cache_data_hi; } DECLARE_WRITE32_MEMBER(cache_data_hi_w) { m_cache_data_hi = data; } - DECLARE_READ32_MEMBER(cache_cpu_tag_r) { return m_cache_cpu_tag; } + DECLARE_READ32_MEMBER(cache_cpu_tag_r) const { return m_cache_cpu_tag; } DECLARE_WRITE32_MEMBER(cache_cpu_tag_w) { m_cache_cpu_tag = data; } - DECLARE_READ32_MEMBER(cache_system_tag_valid_r) { return m_cache_system_tag_valid; } + DECLARE_READ32_MEMBER(cache_system_tag_valid_r) const { return m_cache_system_tag_valid; } DECLARE_WRITE32_MEMBER(cache_system_tag_valid_w) { m_cache_system_tag_valid = data; } - DECLARE_READ32_MEMBER(cache_system_tag_r) { return m_cache_system_tag; } + DECLARE_READ32_MEMBER(cache_system_tag_r) const { return m_cache_system_tag; } DECLARE_WRITE32_MEMBER(cache_system_tag_w) { m_cache_system_tag = data; } - DECLARE_READ32_MEMBER(tlb_va_line_r) { return m_tlb_va_line; } + DECLARE_READ32_MEMBER(tlb_va_line_r) const { return m_tlb_va_line; } DECLARE_WRITE32_MEMBER(tlb_va_line_w) { m_tlb_va_line = data; } - DECLARE_READ32_MEMBER(tlb_ra_line_r) { return m_tlb_ra_line; } + DECLARE_READ32_MEMBER(tlb_ra_line_r) const { return m_tlb_ra_line; } DECLARE_WRITE32_MEMBER(tlb_ra_line_w) { m_tlb_ra_line = data; } +protected: + virtual void device_start() override; + + virtual bool get_alignment() const override { return (m_control & CNTL_ATD) == 0; } + virtual address_space *get_ust_space() const override { return (m_control & CNTL_IOTS) ? m_io_space : m_main_space; } + private: u32 m_ram_line; u32 m_htlb_offset; @@ -157,27 +299,83 @@ public: virtual DECLARE_ADDRESS_MAP(map, 32) override; - virtual DECLARE_READ32_MEMBER(control_r) override { return m_control | 0x02000000; } - virtual DECLARE_WRITE32_MEMBER(control_w) override { m_control = data & 0x00ffffff; } + enum control_mask : u32 + { + CNTL_LRAS = 0x00000001, // tlb line replacement + CNTL_BWWD = 0x00000002, // buswatch write disable + CNTL_BWRD = 0x00000004, // buswatch read disable + CNTL_FSR = 0x00000010, // fake system response + CNTL_ATD = 0x00000100, // alignment trap disable + CNTL_UMM = 0x00003000, // unmapped mode address space select + CNTL_POLL = 0x00030000, // poll bus signals + CNTL_BM = 0x00040000, // burst mode address space select + CNTL_PZBS = 0x00080000, // page 0 boot select + CNTL_CRR = 0x00700000, // cache memory refresh rate + CNTL_CID = 0xff000000 // cammu identification + }; + + enum control_umm_mask : u32 + { + UMM_MM = 0x00000000, // mm space, noncacheable + UMM_MMRIO = 0x00001000, // mm or i/o space, noncacheable + UMM_IO = 0x00002000 // i/o space noncacheable + }; + + enum control_crr_mask : u32 + { + CRR_GT131 = 0x00000000, // clock rate over 131 MHz + CRR_GT66 = 0x00100000, // clock rate over 66 MHz + CRR_GT33 = 0x00200000, // clock rate over 33 MHz + CRR_GT8 = 0x00300000, // clock rate over 8 MHz + CRR_GT2 = 0x00400000, // clock rate over 2 MHz + CRR_GT1 = 0x00500000, // clock rate over 1 MHz + CRR_GTHALF = 0x00600000, // clock rate over 0.5 MHz + CRR_OFF = 0x00700000, // refresh off + }; + + enum control_cid_mask : u32 + { + CID_C4I = 0x02000000 // c4i cammu identification + }; + + virtual DECLARE_READ32_MEMBER(control_r) const override { return m_control; } + virtual DECLARE_WRITE32_MEMBER(control_w) override { m_control = ((m_control & (~mem_mask | CNTL_CID)) | (data & (mem_mask & ~CNTL_CID))); } - DECLARE_READ32_MEMBER(reset_r) { return m_reset; } + enum reset_mask : u32 + { + RESET_CDCT = 0x00000001, // clear data cache tags + RESET_RDUV = 0x00000100, // reset all d-side uv flags + RESET_RDSV = 0x00001000, // reset all d-side sv flags + RESET_CICT = 0x00010000, // clear ins. cache tags + RESET_RIUV = 0x01000000, // reset all i-side uv flags + RESET_RISV = 0x10000000, // reset all i-side sv flags + RESET_FLUSH = 0x40000000, // flush out burst io buffer + RESET_CFR = 0x80000000 // clear fault registers + }; + DECLARE_READ32_MEMBER(reset_r) const { return m_reset; } DECLARE_WRITE32_MEMBER(reset_w) { m_reset = data; } - DECLARE_READ32_MEMBER(clr_s_data_tlb_r) { return m_clr_s_data_tlb; } + DECLARE_READ32_MEMBER(clr_s_data_tlb_r) const { return m_clr_s_data_tlb; } DECLARE_WRITE32_MEMBER(clr_s_data_tlb_w) { m_clr_s_data_tlb = data; } - DECLARE_READ32_MEMBER(clr_u_data_tlb_r) { return m_clr_u_data_tlb; } + DECLARE_READ32_MEMBER(clr_u_data_tlb_r) const { return m_clr_u_data_tlb; } DECLARE_WRITE32_MEMBER(clr_u_data_tlb_w) { m_clr_u_data_tlb = data; } - DECLARE_READ32_MEMBER(clr_s_insn_tlb_r) { return m_clr_s_insn_tlb; } + DECLARE_READ32_MEMBER(clr_s_insn_tlb_r) const { return m_clr_s_insn_tlb; } DECLARE_WRITE32_MEMBER(clr_s_insn_tlb_w) { m_clr_s_insn_tlb = data; } - DECLARE_READ32_MEMBER(clr_u_insn_tlb_r) { return m_clr_u_insn_tlb; } + DECLARE_READ32_MEMBER(clr_u_insn_tlb_r) const { return m_clr_u_insn_tlb; } DECLARE_WRITE32_MEMBER(clr_u_insn_tlb_w) { m_clr_u_insn_tlb = data; } - DECLARE_READ32_MEMBER(test_data_r) { return m_test_data; } + DECLARE_READ32_MEMBER(test_data_r) const { return m_test_data; } DECLARE_WRITE32_MEMBER(test_data_w) { m_test_data = data; } - DECLARE_READ32_MEMBER(test_address_r) { return m_test_address; } + DECLARE_READ32_MEMBER(test_address_r) const { return m_test_address; } DECLARE_WRITE32_MEMBER(test_address_w) { m_test_address = data; } +protected: + virtual void device_start() override; + + virtual bool get_alignment() const override { return (m_control & CNTL_ATD) == 0; } + virtual address_space *get_ust_space() const override; + private: u32 m_reset; u32 m_clr_s_data_tlb; @@ -193,50 +391,88 @@ class cammu_c3_device : public cammu_device public: cammu_c3_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + static void static_add_linked(device_t &device, const char *const tag); + virtual DECLARE_ADDRESS_MAP(map, 32) override; + virtual DECLARE_ADDRESS_MAP(map_global, 32); - DECLARE_READ32_MEMBER(d_s_pdo_r) { return m_d_s_pdo; } - DECLARE_WRITE32_MEMBER(d_s_pdo_w) { m_d_s_pdo = data; } - DECLARE_READ32_MEMBER(d_u_pdo_r) { return m_d_u_pdo; } - DECLARE_WRITE32_MEMBER(d_u_pdo_w) { m_d_u_pdo = data; } - DECLARE_READ32_MEMBER(d_fault_r) { return m_d_fault; } - DECLARE_WRITE32_MEMBER(d_fault_w) { m_d_fault = data; } - DECLARE_READ32_MEMBER(d_control_r) { return m_d_control; } - DECLARE_WRITE32_MEMBER(d_control_w) { m_d_control = data; } - DECLARE_READ32_MEMBER(d_reset_r) { return m_d_reset; } - DECLARE_WRITE32_MEMBER(d_reset_w) { m_d_reset = data; } - - DECLARE_READ32_MEMBER(i_s_pdo_r) { return m_i_s_pdo; } - DECLARE_WRITE32_MEMBER(i_s_pdo_w) { m_i_s_pdo = data; } - DECLARE_READ32_MEMBER(i_u_pdo_r) { return m_i_u_pdo; } - DECLARE_WRITE32_MEMBER(i_u_pdo_w) { m_i_u_pdo = data; } - DECLARE_READ32_MEMBER(i_fault_r) { return m_i_fault; } - DECLARE_WRITE32_MEMBER(i_fault_w) { m_i_fault = data; } - DECLARE_READ32_MEMBER(i_control_r) { return m_i_control; } - DECLARE_WRITE32_MEMBER(i_control_w) { m_i_control = data; } - DECLARE_READ32_MEMBER(i_reset_r) { return m_i_reset; } - DECLARE_WRITE32_MEMBER(i_reset_w) { m_i_reset = data; } + enum control_mask : u32 + { + CNTL_EP = 0x00000001, // enable prefetch + CNTL_EWCW = 0x00000002, // enable watch cpu writes + CNTL_EWIW = 0x00000004, // enable watch i/o writes + CNTL_EWIR = 0x00000008, // enable watch i/o reads + CNTL_UST = 0x00000030, // unmapped system tag + CNTL_CV = 0x00000100, // clear valid + CNTL_ATE = 0x00000200, // alignment trap enable + CNTL_CID = 0xff000000 // cammu id + }; + + enum ust_mask : u32 + { + UST_0 = 0x00000000, // private, write-through, main memory space + UST_1 = 0x00000010, // shared, write-through, main memory space + UST_2 = 0x00000020, // private, copy-back, main memory space + UST_3 = 0x00000030 // noncacheable, main memory space + }; + + enum control_cid_mask : u32 + { + CID_C3 = 0x00000000 // unknown + }; + + DECLARE_READ32_MEMBER(s_pdo_r) const { return m_s_pdo; } + DECLARE_WRITE32_MEMBER(s_pdo_w) { m_s_pdo = ((m_s_pdo & ~mem_mask) | (data & mem_mask)) & PDO_MASK; } + DECLARE_READ32_MEMBER(u_pdo_r) const { return m_u_pdo; } + DECLARE_WRITE32_MEMBER(u_pdo_w) { m_u_pdo = ((m_u_pdo & ~mem_mask) | (data & mem_mask)) & PDO_MASK; } + DECLARE_READ32_MEMBER(fault_r) const { return m_fault; } + DECLARE_WRITE32_MEMBER(fault_w) { m_fault = data; } + DECLARE_READ32_MEMBER(control_r) const { return m_control; } + DECLARE_WRITE32_MEMBER(control_w) { m_control = ((m_control & (~mem_mask | CNTL_CID)) | (data & (mem_mask & ~CNTL_CID))); } + DECLARE_READ32_MEMBER(reset_r) const { return m_reset; } + DECLARE_WRITE32_MEMBER(reset_w) { m_reset = data; } - DECLARE_WRITE32_MEMBER(g_s_pdo_w) { d_s_pdo_w(space, offset, data, mem_mask); i_s_pdo_w(space, offset, data, mem_mask); } - DECLARE_WRITE32_MEMBER(g_u_pdo_w) { d_u_pdo_w(space, offset, data, mem_mask); i_u_pdo_w(space, offset, data, mem_mask); } - DECLARE_WRITE32_MEMBER(g_fault_w) { d_fault_w(space, offset, data, mem_mask); i_fault_w(space, offset, data, mem_mask); } - DECLARE_WRITE32_MEMBER(g_control_w) { d_control_w(space, offset, data, mem_mask); i_control_w(space, offset, data, mem_mask); } - DECLARE_WRITE32_MEMBER(g_reset_w) { d_reset_w(space, offset, data, mem_mask); i_reset_w(space, offset, data, mem_mask); } + // global methods - relay to each linked device + DECLARE_WRITE32_MEMBER(g_s_pdo_w) { for (cammu_c3_device *dev : m_linked) dev->s_pdo_w(space, offset, data, mem_mask); } + DECLARE_WRITE32_MEMBER(g_u_pdo_w) { for (cammu_c3_device *dev : m_linked) dev->u_pdo_w(space, offset, data, mem_mask); } + DECLARE_WRITE32_MEMBER(g_fault_w) { for (cammu_c3_device *dev : m_linked) dev->fault_w(space, offset, data, mem_mask); } + DECLARE_WRITE32_MEMBER(g_control_w) { for (cammu_c3_device *dev : m_linked) dev->control_w(space, offset, data, mem_mask); } + DECLARE_WRITE32_MEMBER(g_reset_w) { for (cammu_c3_device *dev : m_linked) dev->reset_w(space, offset, data, mem_mask); } protected: - u32 get_pte(u32 va, int user, bool data) override; + virtual void device_reset() override; + virtual void device_start() override; + + virtual bool get_access(const access_t mode, const u32 pte, const u32 ssw) const override; + virtual bool get_alignment() const override { return m_control & CNTL_ATE; } + virtual u32 get_pdo(const bool user) const override { return user ? m_u_pdo : m_s_pdo; } + virtual address_space *get_ust_space() const override { return m_main_space; } + + virtual void set_fault_address(const u32 va) override { m_fault = va; } private: - u32 m_d_s_pdo; - u32 m_d_u_pdo; - u32 m_d_fault; - u32 m_d_control; - u32 m_d_reset; - u32 m_i_s_pdo; - u32 m_i_u_pdo; - u32 m_i_fault; - u32 m_i_control; - u32 m_i_reset; + enum c3_access_t : u8 + { + N = 0, // no access + R = 1, // read permitted + W = 2, // write permitted + RW = 3, // read and write permitted + E = 4, // execute permitted + RE = 5, // read and execute permitted + RWE = 7 // read, write and execute permitted + }; + + static const u8 i_cammu_column[]; + static const u8 d_cammu_column[]; + static const c3_access_t cammu_matrix[][16]; + + u32 m_s_pdo; + u32 m_u_pdo; + u32 m_fault; + u32 m_control; + u32 m_reset; + + std::vector<cammu_c3_device *> m_linked; }; // device type definitions diff --git a/src/mame/machine/interpro_ioga.cpp b/src/mame/machine/interpro_ioga.cpp index e790a3ab269..0d6a0dccfbb 100644 --- a/src/mame/machine/interpro_ioga.cpp +++ b/src/mame/machine/interpro_ioga.cpp @@ -165,6 +165,7 @@ DEFINE_DEVICE_TYPE(SAPPHIRE_IOGA, sapphire_ioga_device, "ioga_s", "I/O Gate Arra interpro_ioga_device::interpro_ioga_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, type, tag, owner, clock) + , m_memory_tag(nullptr) , m_memory_space(nullptr) , m_out_nmi_func(*this) , m_out_irq_func(*this) @@ -192,13 +193,22 @@ sapphire_ioga_device::sapphire_ioga_device(const machine_config &mconfig, const { } +void interpro_ioga_device::static_set_memory(device_t &device, const char *const tag, const int spacenum) +{ + interpro_ioga_device &ioga = dynamic_cast<interpro_ioga_device &>(device); + + ioga.m_memory_tag = tag; + ioga.m_memory_spacenum = spacenum; +} + void interpro_ioga_device::device_start() { - // TODO: parameterise the cammu name and space number - // grab the main memory space from the mmu so we can do DMA to/from it - device_memory_interface *mmu; - siblingdevice("mmu")->interface(mmu); - m_memory_space = &mmu->space(0); + assert_always(m_memory_tag != nullptr, "memory tag and address space number must be configured"); + + // get the memory space + device_memory_interface *memory; + siblingdevice(m_memory_tag)->interface(memory); + m_memory_space = &memory->space(m_memory_spacenum); // resolve callbacks m_out_nmi_func.resolve(); diff --git a/src/mame/machine/interpro_ioga.h b/src/mame/machine/interpro_ioga.h index 55573a1d6ee..3d7795cd259 100644 --- a/src/mame/machine/interpro_ioga.h +++ b/src/mame/machine/interpro_ioga.h @@ -29,7 +29,8 @@ #define MCFG_INTERPRO_IOGA_ETH_CA_CB(_ca) \ devcb = &interpro_ioga_device::static_set_eth_ca_callback(*device, DEVCB_##_ca); -#define MCFG_INTERPRO_IOGA_DMA_BUS(_mmu, _space) +#define MCFG_INTERPRO_IOGA_MEMORY(_tag, _spacenum) \ + interpro_ioga_device::static_set_memory(*device, _tag, _spacenum); class interpro_ioga_device : public device_t { @@ -115,6 +116,8 @@ public: template<class _Object> static devcb_base &static_set_fdc_tc_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_fdc_tc_func.set_callback(object); } template<class _Object> static devcb_base &static_set_eth_ca_callback(device_t &device, _Object object) { return downcast<interpro_ioga_device &>(device).m_eth_ca_func.set_callback(object); } + static void static_set_memory(device_t &device, const char *const tag, const int spacenum); + virtual DECLARE_ADDRESS_MAP(map, 32) = 0; // interrupt request lines @@ -317,6 +320,8 @@ protected: virtual void device_reset() override; virtual ioport_constructor device_input_ports() const override; + const char *m_memory_tag; + int m_memory_spacenum; address_space *m_memory_space; // callbacks diff --git a/src/mame/mame.lst b/src/mame/mame.lst index af06e13b360..92b75cdc74e 100644 --- a/src/mame/mame.lst +++ b/src/mame/mame.lst @@ -32390,7 +32390,8 @@ rbislande // B39 (c) 1988 Taito Corporation rbislando // B22 (c) 1987 Taito Corporation @source:rbmk.cpp -rbmk // (c) 1995 GMS +rbmk // (c) 1998 GMS +rbspm // (c) 1998 GMS @source:rc702.cpp rc702 // 1979 RC702 diff --git a/src/osd/modules/file/winfile.cpp b/src/osd/modules/file/winfile.cpp index e62382a92ab..66281d08b4a 100644 --- a/src/osd/modules/file/winfile.cpp +++ b/src/osd/modules/file/winfile.cpp @@ -231,21 +231,23 @@ osd_file::error osd_file::open(std::string const &orig_path, uint32_t openflags, // get the file size DWORD upper, lower; - if (is_path_to_physical_drive(path.c_str())) { - + if (is_path_to_physical_drive(path.c_str())) + { GET_LENGTH_INFORMATION gli; DWORD ret; - int getsize = DeviceIoControl(h, IOCTL_DISK_GET_LENGTH_INFO, 0, 0, &gli, sizeof(gli), &ret, 0); - if (getsize==0) { + if (!DeviceIoControl(h, IOCTL_DISK_GET_LENGTH_INFO, nullptr, 0, &gli, sizeof(gli), &ret, nullptr)) + { upper = 0; lower = INVALID_FILE_SIZE; } - else { + else + { lower = gli.Length.LowPart; upper = gli.Length.HighPart; } } - else { + else + { lower = GetFileSize(h, &upper); } if (INVALID_FILE_SIZE == lower) |