From 0855900dedd4ef7a20fd577b23a01d65074deb89 Mon Sep 17 00:00:00 2001 From: Angelo Salese Date: Mon, 12 Jun 2023 01:51:23 +0200 Subject: [PATCH] bus/a800: modernize cart slot interface (#10528) - use address_maps instead of catch-all handlers; - implement rd4 and rd5 line views; - converted a800_rom_williams_device to the new system, make almost every entry in mega* and prisma* SW to actually boot; - bus/a800: implement maxflash_1mb / maxflash_8mb devices. * This allows loading arbitrary collection of .xex files built thru Maxflash Cartridge Studio program as flash ROM binaries; - bus/a800: implement sic_128kb / sic_256kb / sic_512kb flash ROM devices; - bus/a800: implement ast2k, atrax, Blizzard 32kb, Adawliah, SpartaDOS 128KB, A5200 Super Cart variants; - bus/a800: implement Super Charger math unit device; - a800_slot.cpp: fix xegs cart default slot for loose cart loading; - a800_carts.h: merge a800_turbo64 and a800_turbo128 into single a800_turbo slot option; - bus/a800/a800_slot: split a5200 to own interface New working software list additions ----------------------------------- a800.xml: Maxflash Cartridge Studio - Demonstration Workbook [Atarimax Team], SIC! 31-in-1 Demonstration [SIC! Team] a800.xml: Atrax 01, Atrax 02, Atrax 03, Atrax 04, Atrax 05, Atrax 06, Atrax 08, Atrax 09, Atrax 10, Atrax 11, Atrax 12, Atrax 13, Atrax 15 [Atarimania] a800.xml: Prince of Persia (AtariMAX i/f), Prince of Persia (SIC! i/f) [AtariAge] New software list items marked not working ------------------------------------------ a800.xml: Atrax 14, Atrax 16 [Atarimania], Turbo Hit (Blizzard 32kb) [atari.area] a5200.xml: Bosconian 5200 - Star Destroyer (Ultimate Version) [AtariAge] --- hash/a5200.xml | 227 ++-- hash/a800.xml | 1240 ++++++++++++++++++---- hash/a800_flop.xml | 23 +- hash/xegs.xml | 80 +- scripts/src/bus.lua | 23 + src/devices/bus/a800/a5200_supercart.cpp | 73 ++ src/devices/bus/a800/a5200_supercart.h | 32 + src/devices/bus/a800/a800_carts.cpp | 108 ++ src/devices/bus/a800/a800_carts.h | 61 +- src/devices/bus/a800/a800_slot.cpp | 533 +++++++--- src/devices/bus/a800/a800_slot.h | 174 +-- src/devices/bus/a800/a8sio.cpp | 2 +- src/devices/bus/a800/atari1050.h | 1 - src/devices/bus/a800/atari810.h | 1 - src/devices/bus/a800/atrax.cpp | 54 + src/devices/bus/a800/atrax.h | 34 + src/devices/bus/a800/bbsb.cpp | 136 +++ src/devices/bus/a800/bbsb.h | 52 + src/devices/bus/a800/cassette.cpp | 2 +- src/devices/bus/a800/corina.cpp | 135 +++ src/devices/bus/a800/corina.h | 59 + src/devices/bus/a800/maxflash.cpp | 123 +++ src/devices/bus/a800/maxflash.h | 53 + src/devices/bus/a800/oss.cpp | 357 ++++--- src/devices/bus/a800/oss.h | 77 +- src/devices/bus/a800/phoenix.cpp | 176 +++ src/devices/bus/a800/phoenix.h | 70 ++ src/devices/bus/a800/rom.cpp | 624 +++-------- src/devices/bus/a800/rom.h | 234 +--- src/devices/bus/a800/rtime8.cpp | 24 +- src/devices/bus/a800/rtime8.h | 9 +- src/devices/bus/a800/sic.cpp | 114 ++ src/devices/bus/a800/sic.h | 64 ++ src/devices/bus/a800/sparta.cpp | 180 +++- src/devices/bus/a800/sparta.h | 49 +- src/devices/bus/a800/supercharger.cpp | 94 ++ src/devices/bus/a800/supercharger.h | 35 + src/devices/bus/a800/telelink2.cpp | 64 ++ src/devices/bus/a800/telelink2.h | 34 + src/devices/bus/a800/ultracart.cpp | 130 +++ src/devices/bus/a800/ultracart.h | 55 + src/devices/bus/a800/williams.cpp | 160 +++ src/devices/bus/a800/williams.h | 69 ++ src/mame/atari/antic.cpp | 18 +- src/mame/atari/atari400.cpp | 524 ++++----- src/mame/atari/atari400.h | 2 +- src/mame/atari/gtia.cpp | 5 +- 47 files changed, 4454 insertions(+), 1940 deletions(-) create mode 100644 src/devices/bus/a800/a5200_supercart.cpp create mode 100644 src/devices/bus/a800/a5200_supercart.h create mode 100644 src/devices/bus/a800/a800_carts.cpp create mode 100644 src/devices/bus/a800/atrax.cpp create mode 100644 src/devices/bus/a800/atrax.h create mode 100644 src/devices/bus/a800/bbsb.cpp create mode 100644 src/devices/bus/a800/bbsb.h create mode 100644 src/devices/bus/a800/corina.cpp create mode 100644 src/devices/bus/a800/corina.h create mode 100644 src/devices/bus/a800/maxflash.cpp create mode 100644 src/devices/bus/a800/maxflash.h create mode 100644 src/devices/bus/a800/phoenix.cpp create mode 100644 src/devices/bus/a800/phoenix.h create mode 100644 src/devices/bus/a800/sic.cpp create mode 100644 src/devices/bus/a800/sic.h create mode 100644 src/devices/bus/a800/supercharger.cpp create mode 100644 src/devices/bus/a800/supercharger.h create mode 100644 src/devices/bus/a800/telelink2.cpp create mode 100644 src/devices/bus/a800/telelink2.h create mode 100644 src/devices/bus/a800/ultracart.cpp create mode 100644 src/devices/bus/a800/ultracart.h create mode 100644 src/devices/bus/a800/williams.cpp create mode 100644 src/devices/bus/a800/williams.h diff --git a/hash/a5200.xml b/hash/a5200.xml index 0a7d139d41e..acc44aa179c 100644 --- a/hash/a5200.xml +++ b/hash/a5200.xml @@ -102,7 +102,7 @@ Possible Undumped protos: - 1983 Atari - + @@ -114,7 +114,7 @@ Possible Undumped protos: - 1982 Brøderbund Software Inc - + @@ -127,7 +127,7 @@ Possible Undumped protos: - Activision - + @@ -140,7 +140,7 @@ Possible Undumped protos: - Atari - + @@ -167,7 +167,7 @@ Possible Undumped protos: - - + @@ -180,7 +180,7 @@ Possible Undumped protos: - Atari / Lucasfilm - + @@ -188,7 +188,7 @@ Possible Undumped protos: - + Baseball. While this functions in an Atari 5200 as a cartridge image, it is not a home cartridge. Handled in atari/bartop52.cpp --> @@ -239,7 +239,7 @@ Possible Undumped protos: - Activision - + @@ -251,7 +251,7 @@ Possible Undumped protos: - 1984 Atari / Lucasfilm - + @@ -267,7 +267,7 @@ Possible Undumped protos: - Atari - + @@ -278,9 +278,13 @@ Possible Undumped protos: - Black Belt (prototype) 1983 Atari + + - + @@ -292,7 +296,7 @@ Possible Undumped protos: - 1984 Atari - + @@ -305,13 +309,32 @@ Possible Undumped protos: - CBS Electronics / Bally Midway MFG. Co. - + + + + Bosconian 5200 - Star Destroyer (Ultimate Version) + 2019 + <homebrew> + + + + + + + + + Bounty Bob Strikes Back! 1984 @@ -360,7 +383,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -400,7 +423,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -439,7 +462,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -452,7 +475,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -477,7 +500,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Parker Brothers - + @@ -497,13 +520,17 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Galaxian 1982 Atari + - + @@ -517,7 +544,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) CBS Electronics / Bally Midway MFG. Co. - + @@ -530,7 +557,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -556,7 +583,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -621,7 +648,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) CBS Electronics / Kay Enterprizes Co. - + @@ -634,7 +661,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -661,7 +688,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -674,7 +701,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -699,19 +726,24 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + - + Meebzork (prototype) 1983 Atari + - + @@ -724,7 +756,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -736,7 +768,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1983 Electra Concepts - + @@ -761,7 +793,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -769,13 +801,16 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Miner 2049er 1983 Big Five Software + - + @@ -801,7 +836,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -828,7 +863,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -841,7 +876,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) CBS Electronics - + @@ -854,7 +889,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Parker Brothers - + @@ -893,7 +928,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -906,7 +941,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -932,7 +967,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1983 Atari - + @@ -959,7 +994,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Parker Brothers - + @@ -979,13 +1014,16 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Quest for Quintana Roo 1984 Sunrise + - + @@ -998,7 +1036,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1012,7 +1050,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1025,7 +1063,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1060,11 +1098,14 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + RealSports Soccer 1982 Atari + @@ -1095,7 +1136,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari / Lucasfilm - + @@ -1108,7 +1149,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -1134,7 +1175,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1160,7 +1201,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1174,7 +1215,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -1186,7 +1227,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1983 Atari - + @@ -1238,7 +1279,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Parker Brothers - + @@ -1277,7 +1318,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1291,7 +1332,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Parker Brothers - + @@ -1303,7 +1344,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1984 Atari - + @@ -1317,7 +1358,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + @@ -1330,7 +1371,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1343,7 +1384,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1356,17 +1397,20 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) CBS Electronics - + - + Xari Arena (prototype) 1983 Atari + @@ -1381,7 +1425,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Atari - + @@ -1393,7 +1437,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1983 Atari - + @@ -1406,7 +1450,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Sega - + @@ -1419,7 +1463,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -1432,7 +1476,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Activision - + @@ -1444,17 +1488,20 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1982 Atari - + - + PAM Diag 2.0 1982 Atari + @@ -1463,10 +1510,14 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Atari PAM Diagnostics (rev 2.3) 1983 Atari + @@ -1480,7 +1531,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1982 Atari - + @@ -1492,33 +1543,39 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) 1982 Atari - + - + Castle Blast 2002 - <unlicensed> + <homebrew> + - + - + Castle Crisis 2004 - <unlicensed> + <homebrew> + - + @@ -1528,10 +1585,10 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) Koffi: Yellow Kopter 2002 - <unlicensed> + <homebrew> - + @@ -1544,7 +1601,7 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) AtariAge - + diff --git a/hash/a800.xml b/hash/a800.xml index a50b65231ff..06ac5d18cf2 100644 --- a/hash/a800.xml +++ b/hash/a800.xml @@ -65,61 +65,7 @@ Compiled by K1W1 - Video Easel - Worm War 1 - * Cartridge Types : - - - Standard 8k map to address area $A000-$BFFF. - - Standard 16k cartridges map to address area $8000-$BFFF. - - - Right slot 8k cartridges are run in the address area from $8000-$9FFF. Atari 800 only. - - - Phoenix 8k cartridges occupy 8k of address space between $A000 and $BFFF, and can be disabled by an access to $D500-$D5FF. - - - Blizzard 16k cartridges occupy 16k of address space between $8000 and $BFFF, and can be disabled by an access to $D500-$D5FF. - - - MegaCart 16k cartridges occupy 16k of address space between $8000 and $BFFF, and can be disabled by writing a byte with bit 7 set to $D500-$D5FF. - - MegaCart 32k are bank-switched cartridges that occupy 16k of address space between $8000 and $BFFF. It is controlled by a byte written to $D500-$D5FF. - Bit 0 selects one of two available banks, bit 7 disables the cartridge. - - - Williams 32k cartridges have 4 banks mapped to $A000-$BFFF. An access to $D500 selects bank A, $D501 - bank B, etc. An access to $D508-$D50F disables the cartridge. - - Williams 64k cartridges have 8 banks mapped to $A000-$BFFF. An access to $D507 selects bank A, $D506 - bank B, etc. An access to $D508-$D50F disables the cartridge. - - - DB 32k bank-switched cartridges have 4 banks. Bank D is mapped to $A000-$BFFF. Bank in $8000-$9FFF is selected by an access to $D500-$D5FF. - Two lowest bits of address select bank A, B, C or D. - - - Express 64k cartridges have 8 banks mapped to $A000-$BFFF. An access to $D577 selects bank A, $D576 - bank B, etc. An access to $D578-$D57F disables the cartridge. - - - Diamond 64k cartridges have 8 banks mapped to $A000-$BFFF. An access to $D5D7 selects bank A, $D5D6 - bank B, etc. An access to $D5D8-$D5DF disables the cartridge. - - - SpartaDOS X cartridges have 8 banks mapped to $A000-$BFFF. An access to $D5E7 selects bank A, $D5E6 - bank B, etc. An access to $D5E8-$D5EF disables the cartridge. - - - BBSB Contains main bank at $A000-$BFFF. From $8000-$8FFF is first bank, $9000-$9FFF is second bank. They are switched by accessing $8FF6-$8FF9 & $9FF6-$9FF9 respectively. - In each bank there's 4 x 4 KBs. Totally, it's 2 x 4 x 4 + 8 = 40 KBs. This switching technique is only used with the "Bounty Bob Strikes Back" cartridge. - - - OSS Cartridge: - - - There are two types of OSS cartridges. Both are 16 KB and occupy 8 KB of address space between $A000 and $BFFF. - The cartridge memory is divided into 4 banks, 4 KB each. One bank ('main') is always mapped to $B000-$BFFF. - The other 3 banks are mapped to $A000-$AFFF. The current bank is selected by accessing a byte in $D500-$D5FF. - Only 4 lowest bits of address are significant. - - 034M = This scheme is the more complicated of the two. The main bank is D. An access to: - - $D5x0 or $D5x1 selects bank A. - $D5x3 or $D5x7 selects bank B. - $D5x4 or $D5x5 selects bank C. - $D5x2 or $D5x6 is not useful. It disables ROM (there're $FF bytes in $A000-$AFFF). - $D5x8-$D5xF disables whole cartridge (enables computer's memory in address space between $A000 and $BFFF). - - MO91 = This is the simpler one of OSS schemes. It uses only A0 and A3 address lines: - - A3=0, A0=0 - $A000-$AFFF: bank B, $B000-$BFFF: bank A. - A3=0, A0=1 - $A000-$AFFF: bank D, $B000-$BFFF: bank A. - A3=1, A0=0 - disable cartridge. - A3=1, A0=1 - $A000-$AFFF: bank C, $B000-$BFFF: bank A. - - 043M = Not much is known about this mapping scheme. It is only used in the "MAC/65 v1.0" & "Action! v3.5" cartridges. - - 8k OSS = Not much is known about this mapping scheme. It is only used in the "The Writers Tool" cartridge. - - - Corina cartridge designed by GR8 Software + * For Cartridge Types please refer to bus/a800 folder. * Copy Protection - Some cartridges were produced that utilised a form of copy protection by writing data back to the ROM area in memory. There are many versions of these ROM's available that have been altered to circumvent this protection. This collection where possible has used original unaltered ROM's, those that have been @@ -177,22 +123,7 @@ Compiled by K1W1 - Atari RAM Extension Module Test Rev 1.0 - Atari Mexico U LOGO Computing Language - - Atrax ER Atrax (#01) - - Atrax ER Atrax (#02) - - Atrax ER Atrax (#03) - - Atrax ER Atrax (#04) - - Atrax ER Atrax (#05) - - Atrax ER Atrax (#06) - Atrax ER Atrax (#07) - - Atrax ER Atrax (#08) - - Atrax ER Atrax (#09) - - Atrax ER Atrax (#10) - - Atrax ER Atrax (#11) - - Atrax ER Atrax (#12) - - Atrax ER Atrax (#13) - - Atrax ER Atrax (#14) - - Atrax ER Atrax (#15) - - Atrax ER Atrax (#16) - Beaumont ER PUP (Primary Utility Pack) @@ -384,10 +315,16 @@ Compiled by K1W1 - + 600xl/800xl SALT Diagnostic Cartridge vSE.02 1983 Atari + @@ -512,7 +449,7 @@ Align test never completes, burn-in test requires a test disk and writing to flo - + @@ -542,13 +479,14 @@ Align test never completes, burn-in test requires a test disk and writing to flo - + Alf in the Color Caves 1984 Spinnaker @@ -592,10 +530,13 @@ Unsupported [AtariLab] module - + Alien Ambush 1983 DANA + @@ -729,14 +670,11 @@ Title screen has masking artifact and wrong color (should be green) on mode sele 19?? <unknown> - + @@ -1026,6 +964,287 @@ a certain time, and this isn't currently emulated. + + + + + Atrax #01 (Poland) + 1993? + Atrax + + + + + + + + + + + + Atrax #02 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #03 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #04 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #05 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #06 (Poland) + 1993? + Atrax + + + + + + + + + + + + Atrax #08 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #09 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #10 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #11 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #12 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #13 (Poland) + 1993? + Atrax + + + + + + + + + + + Atrax #14 (Poland) + 199? + Atrax + + + + + + + + + + + + Atrax #15 (Poland) + 199? + Atrax + + + + + + + + + + + + Atrax #16 (Poland) + 199? + Atrax + + + + + + + + + + Attack at EP-CYG-4 1982 @@ -1039,8 +1258,10 @@ a certain time, and this isn't currently emulated. + + - Attack of the Mutant Camels + Attack of the Mutant Camels (US) 1983 HES @@ -1126,7 +1347,7 @@ a certain time, and this isn't currently emulated. - + @@ -1397,10 +1618,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Turbo Blizzard 199? <unknown> + @@ -1410,10 +1634,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Cartridge Turbo 2000 v3.16 199? Info-Cell + @@ -1424,10 +1651,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Cartridge dla Turbo 2000 v1.0 1991 DOMAIN SOFT + @@ -1438,10 +1668,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Cartridge dla Turbo 2000 v1.0 (alt) 1991 DOMAIN SOFT + @@ -1452,10 +1685,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Cartridge Systemowy Turbo 2000 (v.1) 1991 ROBOsoft + @@ -1466,10 +1702,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Cartridge Systemowy Turbo 2000 (v.2) 1991 ROBOsoft + @@ -1480,10 +1719,29 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + + + Turbo Hit (Blizzard 32kb) + 199? + <unknown> + + + + + + + + + + Cartridge System Turbo 2000 (JK Soft) 1991 JK Soft + @@ -1494,10 +1752,13 @@ Sometimes it throws [GTIA] glitchy frames (noticeable on player deaths) - + Cartridge System Turbo 2000 1991 Bartek Selinger + @@ -1755,10 +2016,13 @@ It was meant to help point a satellite dish in the right direction to receive TV - + Computer War 1983 Thorn EMI + @@ -2005,7 +2269,8 @@ Bottom GFX text box doesn't mask properly, also flickers 1989 Reeve Software @@ -2015,25 +2280,30 @@ Continously prints "BOOT ERROR" - + - + - + + Diamond Graphic OS v1.0 1989 Reeve Software + @@ -2046,7 +2316,11 @@ Continously prints "BOOT ERROR" Diamond Graphic OS v1.0 (earlier release) 1988 Reeve Software - + + @@ -2082,10 +2356,13 @@ Continously prints "BOOT ERROR" - + Dig Dug (earlier release) 1982 Atari + @@ -3408,7 +3685,7 @@ Offset sprites on specific rows [GTIA] mixing - + @@ -3451,16 +3728,56 @@ Offset sprites on specific rows [GTIA] mixing - + + + Maxflash Cartridge Studio - Demonstration Workbook + 2015 + <homebrew> + + + + + + + + + - - Mega Cartridge 01 (Spain, pirate) + + Mega Cartridge 01 (Chile, pirate) 2004 Willysoft + @@ -3469,12 +3786,15 @@ Riveraid: doesn't boot - - Mega Cartridge 02 (Spain, pirate) + + Mega Cartridge 02 (Chile, pirate) 2004 Willysoft @@ -3484,13 +3804,14 @@ Rambo: doesn't boot - - Mega Cartridge 03 (Spain, pirate) + + Mega Cartridge 03 (Chile, pirate) 2004 Willysoft @@ -3502,12 +3823,14 @@ Hot Lips: doesn't boot, possibly bad dump (crashes in Altirra too) - Mega Cartridge 04 (Spain, pirate) + Mega Cartridge 04 (Chile, pirate) 2004 Willysoft @@ -3517,13 +3840,15 @@ Rally Spedway: black screen - - Mega Cartridge 05 (Spain, pirate) + + Mega Cartridge 05 (Chile, pirate) 2004 Willysoft @@ -3533,12 +3858,14 @@ Keystone Kapers: doesn't boot - - Mega Cartridge 06 (Spain, pirate) + + Mega Cartridge 06 (Chile, pirate) 2004 Willysoft @@ -3548,13 +3875,15 @@ Outlaw: doesn't display any sprite - - Mega Cartridge 07 (Spain, pirate) + + Mega Cartridge 07 (Chile, pirate) 2004 Willysoft @@ -3564,12 +3893,15 @@ Space Invaders: doesn't boot - - Mega Cartridge 08 (Spain, pirate) + + Mega Cartridge 08 (Chile, pirate) 2004 Willysoft @@ -3579,15 +3911,16 @@ Choplifter: black screen - - Mega Cartridge 09 (Spain, pirate) + + Mega Cartridge 09 (Chile, pirate) 2004 Willysoft + @@ -3596,13 +3929,15 @@ The Empire Strikes B.: doesn't boot - - Mega Cartridge 10 (Spain, pirate) + + Mega Cartridge 10 (Chile, pirate) 2004 Willysoft @@ -3613,13 +3948,14 @@ River Raid: black screen - Mega Cartridge 11 (Spain, pirate) + Mega Cartridge 11 (Chile, pirate) 2004 Willysoft @@ -3629,12 +3965,14 @@ Kaboom: black screen - - Mega Cartridge 12 (Spain, pirate) + + Mega Cartridge 12 (Chile, pirate) 2004 Willysoft @@ -3645,14 +3983,17 @@ Rescue on Fractalus: doesn't boot, possibly bad dump - - Mega Cartridge 13 (Spain, pirate) + + Mega Cartridge 13 (Chile, pirate) 2004 Willysoft + @@ -3661,13 +4002,15 @@ Wargames: black screen - - Mega Cartridge 14 (Spain, pirate) + + Mega Cartridge 14 (Chile, pirate) 2004 Willysoft @@ -3677,13 +4020,15 @@ Star Raiders: draws glitchy [GTIA] sprites - - Mega Cartridge 15 (pirate) + + Mega Cartridge 15 (Chile, pirate) 2004 Willysoft @@ -3885,7 +4230,7 @@ Enemy playfield has strip glitch on topmost row 19?? Grupo SITSA - + @@ -4560,6 +4905,40 @@ Activision logo glitches out on vertical scrolls + + Prince of Persia (AtariMAX i/f) + 2021 + <homebrew> + + + + + + + + + + + + Prince of Persia (SIC! i/f) + 2021 + <homebrew> + + + + + + + + + + Porky's 1983 @@ -4637,16 +5016,21 @@ Attract mode has glitchy text - - - - - Prisma 1 (Spain, pirate) + + Prisma 1 (Chile, pirate) 199? Prismasoft + @@ -4655,13 +5039,21 @@ No game in list boots - - Prisma 2 (Spain, pirate) + + Prisma 2 (Chile, pirate) 199? Prismasoft + @@ -4670,13 +5062,19 @@ No game in list boots - - Prisma 3 (Spain, pirate) - + + Prisma 3 (Chile, pirate) 1992 Prismasoft @@ -4686,22 +5084,45 @@ No game in list boots - - Prisma 4 (Spain, pirate) + + + Prisma 4 (Chile, pirate) 1992 Prismasoft + + - + - - Prisma 5 (Spain, pirate) + + Prisma 5 (Chile, pirate) 1992 Prismasoft + + @@ -4710,10 +5131,21 @@ No game in list boots - - Prisma 6 (Spain, pirate) + + Prisma 6 (Chile, pirate) 1992 Prismasoft + + @@ -4722,10 +5154,27 @@ No game in list boots - - Prisma Super 15-2 (Spain, pirate) + + Prisma Super 15-2 (Chile, pirate) 1992 Prismasoft + @@ -5002,6 +5451,51 @@ Score bar glitches out when player dies + + + SIC! 31-in-1 Demonstration + 2012? + <homebrew> + + + + + + + + + Silicon Warrior 1983 @@ -5109,11 +5603,14 @@ Unresponsive inputs [GTIA] latch trigger - + Space Invaders 1980 Atari + @@ -5241,7 +5738,7 @@ Glitched rows, glitched gear GFX 2006 DLT - + @@ -5253,7 +5750,7 @@ Glitched rows, glitched gear GFX 2008 DLT - + @@ -5265,7 +5762,7 @@ Glitched rows, glitched gear GFX 2008 DLT - + @@ -5277,7 +5774,7 @@ Glitched rows, glitched gear GFX 2011 DLT - + @@ -5289,7 +5786,7 @@ Glitched rows, glitched gear GFX 2011 DLT - + @@ -5301,7 +5798,7 @@ Glitched rows, glitched gear GFX 2011 DLT - + @@ -5313,7 +5810,7 @@ Glitched rows, glitched gear GFX 2013 DLT - + @@ -5325,7 +5822,7 @@ Glitched rows, glitched gear GFX 2015 DLT - + @@ -5345,7 +5842,7 @@ https://forums.atariage.com/topic/146490-spectraview-1-and-2-info/ - + @@ -5575,6 +6072,9 @@ Glitched text and graphics displays Super Cartridge 199? Unerring Master + @@ -5913,19 +6413,27 @@ Requires PLATO dial-up modem connection - - The Writer's Tool (Dongle) + + The Writer's Tool 1985 OSS - + + + + + + + + + + + @@ -5971,10 +6479,23 @@ Has garbage row strip on top of active playfield during hammer throw event - - Turbo Cartridge C1 (Spain, pirate) + + + + Turbo Cartridge C1 (Chile, pirate) 19?? Turbosoft + @@ -5983,22 +6504,44 @@ Has garbage row strip on top of active playfield during hammer throw event - - Turbo Cartridge C2 (Spain, pirate) + + Turbo Cartridge C2 (Chile, pirate) 19?? Turbosoft + - + - - Turbo Cartridge C3 (Spain, pirate) + + Turbo Cartridge C3 (Chile, pirate) 19?? Turbosoft + @@ -6007,10 +6550,21 @@ Has garbage row strip on top of active playfield during hammer throw event - - Turbo Cartridge C4 (Spain, pirate) + + Turbo Cartridge C4 (Chile, pirate) 19?? Turbosoft + @@ -6020,9 +6574,20 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge C5 (Spain, pirate) + Turbo Cartridge C5 (Chile, pirate) 19?? Turbosoft + @@ -6032,9 +6597,20 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge C6 (Spain, pirate) + Turbo Cartridge C6 (Chile, pirate) 19?? Turbosoft + @@ -6044,11 +6620,28 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D1 (Spain, pirate) + Turbo Cartridge D1 (Chile, pirate) 19?? Turbosoft + - + @@ -6056,11 +6649,28 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D2 (Spain, pirate) + Turbo Cartridge D2 (Chile, pirate) 19?? Turbosoft + - + @@ -6068,11 +6678,28 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D3 (Spain, pirate) + Turbo Cartridge D3 (Chile, pirate) 19?? Turbosoft + - + @@ -6080,12 +6707,29 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D4 (Spain, pirate) - + Turbo Cartridge D4 (Chile, pirate) 19?? Turbosoft + + - + @@ -6093,11 +6737,28 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D5 (Spain, pirate) + Turbo Cartridge D5 (Chile, pirate) 19?? Turbosoft + - + @@ -6105,11 +6766,28 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D6 (Spain, pirate) + Turbo Cartridge D6 (Chile, pirate) 19?? Turbosoft + - + @@ -6117,11 +6795,28 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D7 (Spain, pirate) + Turbo Cartridge D7 (Chile, pirate) 19?? Turbosoft + - + @@ -6129,9 +6824,27 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge D8 (Spain, pirate) + + Turbo Cartridge D8 (Chile, pirate) 19?? Turbosoft + @@ -6141,11 +6854,39 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge E1 (Spain, pirate) + + Turbo Cartridge E1 (Chile, pirate) 19?? Turbosoft + - + @@ -6153,33 +6894,73 @@ Has garbage row strip on top of active playfield during hammer throw event - Turbo Cartridge E2 (Spain, pirate) + Turbo Cartridge E2 (Chile, pirate) 19?? Turbosoft + - + - - Turbo Cartridge X1 (Spain, pirate) + + Turbo Cartridge X1 (Chile, pirate) 19?? Turbosoft + - + - - Turbo Cartridge X2 (Spain, pirate) + + + Turbo Cartridge X2 (Chile, pirate) 19?? Turbosoft + @@ -6192,6 +6973,9 @@ Has garbage row strip on top of active playfield during hammer throw event Turbo System 1993 Dadok + diff --git a/hash/a800_flop.xml b/hash/a800_flop.xml index 71cae0ee24a..8af8bb502ef 100644 --- a/hash/a800_flop.xml +++ b/hash/a800_flop.xml @@ -887,7 +887,7 @@ Tested with marsmis2, fails - + Yoomp! (v.1.1) 2007 @@ -948,28 +948,15 @@ Garbage row strip at bottom of screen - - The Writer's Tool - 1985 - OSS - - - - - - - - - - - - - Spectraview II Demo Disk 198? Display Systems International + diff --git a/hash/xegs.xml b/hash/xegs.xml index 289496962d3..0597a3fee7c 100644 --- a/hash/xegs.xml +++ b/hash/xegs.xml @@ -76,10 +76,13 @@ Compiled by K1W1 - + Barnyard Blaster 1987 Atari + @@ -92,9 +95,13 @@ Compiled by K1W1 Beef Drop - + 2005 <homebrew> + @@ -142,10 +149,13 @@ Compiled by K1W1 - + Bug Hunt 1987 Atari + @@ -156,10 +166,13 @@ Compiled by K1W1 - + Castle Crisis 2003 - Atari Age + AtariAge + @@ -193,10 +206,13 @@ Compiled by K1W1 - + Crime Buster 1988 Atari + @@ -207,10 +223,13 @@ Compiled by K1W1 - + Crossbow 1988 Atari + @@ -234,10 +253,13 @@ Compiled by K1W1 - + Dark Chambers 1988 Atari + @@ -272,10 +294,13 @@ Compiled by K1W1 - + Desert Falcon 1988 Atari + @@ -285,10 +310,13 @@ Compiled by K1W1 - + Fight Night 1987 Atari + @@ -298,10 +326,13 @@ Compiled by K1W1 - + Flight Simulator 2 1987 Atari + @@ -363,10 +394,13 @@ Compiled by K1W1 - + Into the Eagle's Nest 1988 Atari + @@ -376,10 +410,13 @@ Compiled by K1W1 - + Karateka 1988 Atari + @@ -427,10 +464,15 @@ Compiled by K1W1 - - MIDI Maze (Reproduction) + + + + MIDI Maze (v1.00, reproduction) 199? Video 61 / Atari + @@ -443,6 +485,9 @@ Compiled by K1W1 MIDI Maze (Prototype) 1988 Atari + @@ -540,10 +585,13 @@ Compiled by K1W1 - + Thunderfox 1988 Atari + diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua index 59d5daa9e5d..6a8a3735a29 100644 --- a/scripts/src/bus.lua +++ b/scripts/src/bus.lua @@ -48,15 +48,38 @@ if (BUSES["A800"]~=null) then MAME_DIR .. "src/devices/bus/a800/cassette.h", MAME_DIR .. "src/devices/bus/a800/a800_slot.cpp", MAME_DIR .. "src/devices/bus/a800/a800_slot.h", + MAME_DIR .. "src/devices/bus/a800/a800_carts.cpp", MAME_DIR .. "src/devices/bus/a800/a800_carts.h", MAME_DIR .. "src/devices/bus/a800/rom.cpp", MAME_DIR .. "src/devices/bus/a800/rom.h", + MAME_DIR .. "src/devices/bus/a800/a5200_supercart.cpp", + MAME_DIR .. "src/devices/bus/a800/a5200_supercart.h", + MAME_DIR .. "src/devices/bus/a800/atrax.cpp", + MAME_DIR .. "src/devices/bus/a800/atrax.h", + MAME_DIR .. "src/devices/bus/a800/bbsb.cpp", + MAME_DIR .. "src/devices/bus/a800/bbsb.h", + MAME_DIR .. "src/devices/bus/a800/corina.cpp", + MAME_DIR .. "src/devices/bus/a800/corina.h", + MAME_DIR .. "src/devices/bus/a800/maxflash.cpp", + MAME_DIR .. "src/devices/bus/a800/maxflash.h", MAME_DIR .. "src/devices/bus/a800/oss.cpp", MAME_DIR .. "src/devices/bus/a800/oss.h", + MAME_DIR .. "src/devices/bus/a800/phoenix.cpp", + MAME_DIR .. "src/devices/bus/a800/phoenix.h", MAME_DIR .. "src/devices/bus/a800/rtime8.cpp", MAME_DIR .. "src/devices/bus/a800/rtime8.h", + MAME_DIR .. "src/devices/bus/a800/sic.cpp", + MAME_DIR .. "src/devices/bus/a800/sic.h", MAME_DIR .. "src/devices/bus/a800/sparta.cpp", MAME_DIR .. "src/devices/bus/a800/sparta.h", + MAME_DIR .. "src/devices/bus/a800/supercharger.cpp", + MAME_DIR .. "src/devices/bus/a800/supercharger.h", + MAME_DIR .. "src/devices/bus/a800/telelink2.cpp", + MAME_DIR .. "src/devices/bus/a800/telelink2.h", + MAME_DIR .. "src/devices/bus/a800/ultracart.cpp", + MAME_DIR .. "src/devices/bus/a800/ultracart.h", + MAME_DIR .. "src/devices/bus/a800/williams.cpp", + MAME_DIR .. "src/devices/bus/a800/williams.h", } end diff --git a/src/devices/bus/a800/a5200_supercart.cpp b/src/devices/bus/a800/a5200_supercart.cpp new file mode 100644 index 00000000000..430bb7e7662 --- /dev/null +++ b/src/devices/bus/a800/a5200_supercart.cpp @@ -0,0 +1,73 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +/************************************************************************************************** + +A5200 Bryan Edewaard's Super Cart + +Maps on the full A5200 cart space, uses $bfc0-$bfff reading for banking. +A5200 BIOS will read to $bfe0-$bfff range, this will automatically fallback to the last +available bank for convenience. + +TODO: +- Checkout if support for non-512K carts works right, supposedly M.U.L.E. conversion + runs on a 64K ROM version, should be right in theory. + +**************************************************************************************************/ + +#include "a5200_supercart.h" + +DEFINE_DEVICE_TYPE(A5200_ROM_SUPERCART, a5200_rom_supercart_device, "a5200_supercart", "Atari 5200 Super Cart") + + +a5200_rom_supercart_device::a5200_rom_supercart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a5200_rom_device(mconfig, A5200_ROM_SUPERCART, tag, owner, clock) + , m_bank(0) +{ +} + +void a5200_rom_supercart_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a5200_rom_supercart_device::device_reset() +{ + m_bank_mask = (m_rom_size / 0x8000) - 1; + m_bank = m_bank_mask; +} + +/* + * --1- ---- fallback to last available bank + * ---1 xx-- selects lower banks + * ---0 xx-- selects upper banks + * + * On non-512K carts upper lines will just be ignored + * i.e. a 64K will only respond to bits 5 or 4 high, with bit 2 as bank selector for latter. + */ +u8 a5200_rom_supercart_device::bank_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + { + if (BIT(offset, 5)) + m_bank = m_bank_mask; + else + { + if (BIT(offset, 4)) + m_bank = (m_bank & 0xc) | ((offset & 0xc) >> 2); + else + m_bank = (m_bank & 3) | (offset & 0xc); + } + + m_bank &= m_bank_mask; + } + + return m_rom[(offset & 0x3f) + (m_bank * 0x8000) + 0x7fc0]; +} + +void a5200_rom_supercart_device::cart_map(address_map &map) +{ + map(0x0000, 0x7fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x7fff) + (m_bank * 0x8000)]; }) + ); + map(0x7fc0, 0x7fff).r(FUNC(a5200_rom_supercart_device::bank_r)); +} diff --git a/src/devices/bus/a800/a5200_supercart.h b/src/devices/bus/a800/a5200_supercart.h new file mode 100644 index 00000000000..cc9baead23b --- /dev/null +++ b/src/devices/bus/a800/a5200_supercart.h @@ -0,0 +1,32 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A5200_SUPERCART_H +#define MAME_BUS_A5200_SUPERCART_H + +#pragma once + +#include "rom.h" + + +class a5200_rom_supercart_device : public a5200_rom_device +{ +public: + a5200_rom_supercart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + u8 m_bank; + u8 m_bank_mask; + + u8 bank_r(offs_t offset); +}; + +DECLARE_DEVICE_TYPE(A5200_ROM_SUPERCART, a5200_rom_supercart_device) + +#endif // MAME_BUS_A5200_SUPERCART_H + diff --git a/src/devices/bus/a800/a800_carts.cpp b/src/devices/bus/a800/a800_carts.cpp new file mode 100644 index 00000000000..5d7ad883bb4 --- /dev/null +++ b/src/devices/bus/a800/a800_carts.cpp @@ -0,0 +1,108 @@ +// license:BSD-3-Clause +// copyright-holders:Fabio Priuli, Angelo Salese + +#include "a800_carts.h" + +// (#num) denotes the canonical number from .car specs for unemulated/undumped variants +void a800_left(device_slot_interface &device) +{ + device.option_add_internal("a800_8k", A800_ROM); + device.option_add_internal("a800_8k_right", A800_ROM_RIGHT); + device.option_add_internal("a800_16k", A800_ROM_16KB); + device.option_add_internal("a800_phoenix", A800_ROM_PHOENIX); + device.option_add_internal("a800_blizzard", A800_ROM_BLIZZARD_16KB); + device.option_add_internal("a800_phoenix_ast2k", A800_ROM_PHOENIX_AST2K); + device.option_add_internal("a800_bbsb", A800_ROM_BBSB); + device.option_add_internal("a800_oss8k", A800_ROM_OSS8K); + device.option_add_internal("a800_oss034m", A800_ROM_OSS34); + device.option_add_internal("a800_oss043m", A800_ROM_OSS43); + device.option_add_internal("a800_ossm091", A800_ROM_OSS91); + // OSS cart with subslot +// device.option_add_internal("a800_mddos", A800_ROM_MDDOS); + device.option_add_internal("a800_williams", A800_ROM_WILLIAMS); + device.option_add_internal("a800_diamond", A800_ROM_DIAMOND); + device.option_add_internal("a800_express", A800_ROM_EXPRESS); + device.option_add_internal("a800_turbo", A800_ROM_TURBO); + device.option_add_internal("a800_tlink2", A800_ROM_TELELINK2); + device.option_add_internal("a800_ultracart", A800_ROM_ULTRACART); + device.option_add_internal("a800_blizzard_32kb", A800_ROM_BLIZZARD_32KB); + device.option_add_internal("a800_adawliah", A800_ROM_ADAWLIAH); + device.option_add_internal("a800_atrax", A800_ROM_ATRAX); + device.option_add_internal("a800_sparta", A800_ROM_SPARTADOS); + device.option_add_internal("a800_sparta_128kb", A800_ROM_SPARTADOS_128KB); + // (#48-#49 / #68) SDX 64KB/128KB variants +// device.option_add_internal("a800_sdx_atrax_64kb", A800_ROM_SDX_ATRAX_64KB); +// device.option_add_internal("a800_sdx_atrax_128kb", A800_ROM_SDX_ATRAX_128KB); + // (#5) DB "Dave Bennett" homebrew cartridge, vaporware? cfr. https://forums.atariage.com/topic/307663-32k-db-cart/ +// device.option_add_internal("a800_db", A800_ROM_DB); + // (#47) "Atari Super Turbo" 32 KB Polish cart with exotic banking scheme (256 bytes at a time) that maps to CCTL +// device.option_add_internal("a800_ast", A800_ROM_AST); + // TOOLBOX III / RAMBOX 2 Polish carts with additional 256KB RAM +// device.option_add_internal("a800_jrc", A800_ROM_JRC); + // Czech cart, some kind of toolkit with bankswitch that rolls back after set time +// device.option_add_internal("a800_cos32", A800_ROM_COS32); + + // XEGS carts + device.option_add_internal("xegs", XEGS_ROM); + // "XEGS demo cartridge", 4 games in 1 with binary counter applied at reset for each reboot +// device.option_add_internal("xegs_demo", XEGS_ROM_DEMO); + // (#33-#38) Carts sold by Nir Dary in the '90s, has fixed last bank to RD5 and selectable RD4 bank. 32KB to 1MB ROM size options +// device.option_add_internal("xegs_switch", XEGS_ROM_SWITCHABLE); + + // flash carts + device.option_add_internal("a800_corina", A800_ROM_CORINA); + device.option_add_internal("a800_corina_sram", A800_ROM_CORINA_SRAM); + device.option_add( "maxflash_128kb", A800_MAXFLASH_128KB); + device.option_add( "maxflash_1mb", A800_MAXFLASH_1MB); + // (#61) MegaMax, has switch that toggles between Atarimax 1MB mode and 2MB +// device.option_add( "megamax", A800_MEGAMAX); + device.option_add( "sic_128kb", A800_SIC_128KB); + device.option_add( "sic_256kb", A800_SIC_256KB); + device.option_add( "sic_512kb", A800_SIC_512KB); + // (#26-#32 / #63-#64) MegaCart 16KB up to 4MB variant too +// device.option_add( "megacart", A800_MEGACART); + // Atarimax MyIDE-II, 512 KB flash ROM + 512 KB RAM + CompactFlash i/f, requires DIY MyBIOS ROM installation into main system +// device.option_add( "myideii", A800_MYIDE_II); + // 512KB flash + CompactFlash, emulates a Sparta DOS X, has DS1305 RTC hooked up thru SPI bus, SIDE 2 is an upgraded variant with slightly different CCTL mapping +// device.option_add( "side1", A800_SIDE1); +// device.option_add( "side2", A800_SIDE2); + // Upgrades SIDE 2 with SD card instead of CF, MX29LV640ET NOR flash chip, 2MB RAM, DMA with various OPs, ROM bank emulation modes with relocatable CCTL ... +// device.option_add( "side3", A800_SIDE3); + // STM32 coprocessor with SD card, cfr. https://github.com/robinhedwards/UnoCart +// device.option_add( "unocart", A800_UNOCART); + // earlier variant of above running on FPGA, cfr. https://github.com/robinhedwards/UltimateCart +// device.option_add( "ultimatecart", A800_ULTIMATECART); + // (#62 / #65) The!Cart, 32/64/128MB + 512KB RAM, emulation modes +// device.option_add( "thecart", A800_THECART); + + // non-ROM types + device.option_add( "rtime8", A800_RTIME8); + // adds extra 65C816 coprocessor. No firmware, runs on code uploaded by main CPU, also two rev variants (V1 and V2) + // NB: SDX documentation calls this Weronika, which just seems a Polish alias +// device.option_add( "veronica", A800_VERONICA); + // 128 or 256 KB additional RAM, schematics available at atarimax +// device.option_add( "ramcart", A800_RAM_CART); + // converts analog mono sound to digital by reading $d500 low 4 bitset +// device.option_add( "ad_converter", A800_AD_CONVERTER); + device.option_add( "supercharger", A800_SUPER_CHARGER); + // The PILL! / Super PILL! / Super Cart with RD4/RD5 held high and that's about it (lolwut) +// device.option_add( "pill", A800_PILL); + // Thompson Proburner, EPROM burner +// device.option_add( "proburner", A800_PROBURNER); + // The Multiplexer! (MUX!), PBI bus between 1 master and 8 slaves + // cfr. https://sdx.atari8.info/sdx_files/muxsdx.txt & http://realdos.net/mux.html +// device.option_add( "mux", A800_MUX); +} + +void a800_right(device_slot_interface &device) +{ + device.option_add_internal("a800_8k_right", A800_ROM_RIGHT); +} + +void a5200_carts(device_slot_interface &device) +{ + device.option_add_internal("a5200_rom", A5200_ROM); + device.option_add_internal("a5200_2chips", A5200_ROM_2CHIPS); + device.option_add_internal("a5200_bbsb", A5200_ROM_BBSB); + device.option_add_internal("a5200_supercart", A5200_ROM_SUPERCART); +} diff --git a/src/devices/bus/a800/a800_carts.h b/src/devices/bus/a800/a800_carts.h index d5ec2f32081..6bbe9691e8a 100644 --- a/src/devices/bus/a800/a800_carts.h +++ b/src/devices/bus/a800/a800_carts.h @@ -1,57 +1,28 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Fabio Priuli, Angelo Salese #ifndef MAME_BUS_A800_A800_CARTS_H #define MAME_BUS_A800_A800_CARTS_H #pragma once - #include "rom.h" -#include "rtime8.h" +#include "a5200_supercart.h" +#include "atrax.h" +#include "bbsb.h" +#include "corina.h" +#include "maxflash.h" #include "oss.h" +#include "phoenix.h" +#include "rtime8.h" +#include "sic.h" #include "sparta.h" +#include "supercharger.h" +#include "telelink2.h" +#include "ultracart.h" +#include "williams.h" -static void a800_left(device_slot_interface &device) -{ - device.option_add_internal("a800_8k", A800_ROM); - device.option_add_internal("a800_8k_right", A800_ROM); - device.option_add_internal("a800_16k", A800_ROM); - device.option_add_internal("a800_phoenix", A800_ROM); // not really emulated at this stage - device.option_add_internal("a800_bbsb", A800_ROM_BBSB); - device.option_add_internal("a800_oss8k", A800_ROM_OSS8K); - device.option_add_internal("a800_oss034m", A800_ROM_OSS34); - device.option_add_internal("a800_oss043m", A800_ROM_OSS43); - device.option_add_internal("a800_ossm091", A800_ROM_OSS91); - device.option_add_internal("a800_williams", A800_ROM_WILLIAMS); - device.option_add_internal("a800_diamond", A800_ROM_EXPRESS); - device.option_add_internal("a800_express", A800_ROM_EXPRESS); - device.option_add_internal("a800_sparta", A800_ROM_SPARTADOS); // this is a passthru cart with unemulated (atm) subslot - device.option_add_internal("a800_blizzard", A800_ROM); - device.option_add_internal("a800_turbo64", A800_ROM_TURBO); - device.option_add_internal("a800_turbo128", A800_ROM_TURBO); - device.option_add_internal("a800_tlink2", A800_ROM_TELELINK2); - device.option_add_internal("a800_sitsa", A800_ROM_MICROCALC); - device.option_add_internal("a800_corina", A800_ROM_CORINA); - device.option_add_internal("a800_corina_sram", A800_ROM_CORINA_SRAM); - device.option_add( "rtime8", A800_RTIME8); // not a ROM cartridge - device.option_add_internal("xegs", XEGS_ROM); -} - -static void a800_right(device_slot_interface &device) -{ - device.option_add_internal("a800_8k_right", A800_ROM); -} - -static void xegs_carts(device_slot_interface &device) -{ - device.option_add_internal("xegs", XEGS_ROM); -} - -static void a5200_carts(device_slot_interface &device) -{ - device.option_add_internal("a5200", A800_ROM); - device.option_add_internal("a5200_2chips", A5200_ROM_2CHIPS); - device.option_add_internal("a5200_bbsb", A5200_ROM_BBSB); -} +void a800_left(device_slot_interface &device); +void a800_right(device_slot_interface &device); +void a5200_carts(device_slot_interface &device); #endif // MAME_BUS_A800_A800_CARTS_H diff --git a/src/devices/bus/a800/a800_slot.cpp b/src/devices/bus/a800/a800_slot.cpp index d333c417958..e72308c4565 100644 --- a/src/devices/bus/a800/a800_slot.cpp +++ b/src/devices/bus/a800/a800_slot.cpp @@ -1,24 +1,17 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli -/*********************************************************************************************************** +// copyright-holders:Fabio Priuli, Angelo Salese +/************************************************************************************************** +Atari A800/A5200/XEGS cart slot emulation - Atari 8 bit cart emulation - (through slot devices) + - Emulation of the cartslot(s) for Atari 8bit series of home computers +References: +- Altirra HW reference manual 2022-07-07 edition, chapter 8; +- https://github.com/atari800/atari800/blob/master/DOC/cart.txt +- https://www.atarimax.com/jindroush.atari.org/acarts.html - Accessors to ROM are typically given in the area 0xa000-0xbfff, but some - carts (and the right slot in A800) maps ROM to 0x8000-0x9fff too - Bankswitch typically happens by accessing addresses in 0xd500-0xd5ff - - Accordingly, this device offers the following handlers - - read_80xx/write_80xx - - read_d5xx/write_d5xx - Notice that these are installed in different ranges at machine start by - the drivers, so that it might well be that offs=0 for read_80xx is 0xa000! - - ***********************************************************************************************************/ +**************************************************************************************************/ #include "emu.h" #include "a800_slot.h" @@ -30,21 +23,30 @@ // GLOBAL VARIABLES //************************************************************************** -DEFINE_DEVICE_TYPE(A800_CART_SLOT, a800_cart_slot_device, "a800_cart_slot", "Atari 8bit Cartridge Slot") +DEFINE_DEVICE_TYPE(A800_CART_SLOT, a800_cart_slot_device, "a800_cart_slot", "Atari 8-bit Cartridge Slot") DEFINE_DEVICE_TYPE(A5200_CART_SLOT, a5200_cart_slot_device, "a5200_cart_slot", "Atari 5200 Cartridge Slot") -DEFINE_DEVICE_TYPE(XEGS_CART_SLOT, xegs_cart_slot_device, "xegs_cart_slot", "Atari XEGS Cartridge Slot") //------------------------------------------------- -// device_vcs_cart_interface - constructor +// device_a800_cart_interface - constructor //------------------------------------------------- -device_a800_cart_interface::device_a800_cart_interface (const machine_config &mconfig, device_t &device) : - device_interface(device, "a800cart"), - m_rom(nullptr), - m_rom_size(0), - m_bank_mask(0) +device_a800_cart_interface::device_a800_cart_interface (const machine_config &mconfig, device_t &device) + : device_interface(device, "a800cart") + , m_rom(nullptr) + , m_rom_size(0) + , m_bank_mask(0) { + m_slot = dynamic_cast(device.owner()); +} + +device_a5200_cart_interface::device_a5200_cart_interface (const machine_config &mconfig, device_t &device) + : device_interface(device, "a5200cart") + , m_rom(nullptr) + , m_rom_size(0) + , m_bank_mask(0) +{ + m_slot = dynamic_cast(device.owner()); } @@ -56,6 +58,10 @@ device_a800_cart_interface::~device_a800_cart_interface () { } +device_a5200_cart_interface::~device_a5200_cart_interface () +{ +} + //------------------------------------------------- // rom_alloc - alloc the space for the cart //------------------------------------------------- @@ -64,36 +70,77 @@ void device_a800_cart_interface::rom_alloc(uint32_t size) { if (m_rom == nullptr) { + // TODO: shouldn't really load from fixed tag + // (particularly inconvenient for stuff like flash ROM hookups) m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base(); m_rom_size = size; // setup other helpers + // TODO: unusable for SIC! and any other mapping that maps over 0x4000 rather than 0x2000 m_bank_mask = (size / 0x2000) - 1; // code for XEGS carts makes use of this to simplify banking } } -//------------------------------------------------- -// ram_alloc - alloc the space for the on-cart RAM -//------------------------------------------------- - -void device_a800_cart_interface::ram_alloc(uint32_t size) +void device_a800_cart_interface::interface_pre_start() { - m_ram.resize(size); - device().save_item(NAME(m_ram)); + if (!m_slot->started()) + throw device_missing_dependencies(); } - -//------------------------------------------------- -// ram_alloc - alloc the space for the on-cart RAM -//------------------------------------------------- - -void device_a800_cart_interface::nvram_alloc(uint32_t size) +void device_a800_cart_interface::interface_post_start() { - m_nvram.resize(size); - device().save_item(NAME(m_nvram)); + m_slot->m_space_mem->install_device(0x0000, 0x3fff, *this, &device_a800_cart_interface::cart_map); + m_slot->m_space_io->install_device(0x0000, 0x00ff, *this, &device_a800_cart_interface::cctl_map); } +void device_a800_cart_interface::cart_map(address_map &map) +{ + map(0x0000, 0x3fff).unmaprw(); +} +void device_a800_cart_interface::cctl_map(address_map &map) +{ + map(0x0000, 0x00ff).unmaprw(); +} + +void device_a800_cart_interface::rd4_w(int state) { m_slot->m_rd4_cb(state); } +void device_a800_cart_interface::rd5_w(int state) { m_slot->m_rd5_cb(state); } +// helper to call both lines at same time, for anything banking on the full range. +void device_a800_cart_interface::rd_both_w(int state) { rd4_w(state); rd5_w(state); } + + +// a5200 + +void device_a5200_cart_interface::rom_alloc(uint32_t size) +{ + if (m_rom == nullptr) + { + // TODO: shouldn't really load from fixed tag + // (particularly inconvenient for stuff like flash ROM hookups) + m_rom = device().machine().memory().region_alloc(device().subtag("^cart:rom"), size, 1, ENDIANNESS_LITTLE)->base(); + m_rom_size = size; + + // setup other helpers + // TODO: unusable for SIC! and any other mapping that maps over 0x4000 rather than 0x2000 + m_bank_mask = (size / 0x2000) - 1; // code for XEGS carts makes use of this to simplify banking + } +} + +void device_a5200_cart_interface::cart_map(address_map &map) +{ + map(0x0000, 0x7fff).unmaprw(); +} + +void device_a5200_cart_interface::interface_pre_start() +{ + if (!m_slot->started()) + throw device_missing_dependencies(); +} + +void device_a5200_cart_interface::interface_post_start() +{ + m_slot->m_space_mem->install_device(0x0000, 0x7fff, *this, &device_a5200_cart_interface::cart_map); +} //************************************************************************** // LIVE DEVICE @@ -102,29 +149,28 @@ void device_a800_cart_interface::nvram_alloc(uint32_t size) //------------------------------------------------- // ****_cart_slot_device - constructor //------------------------------------------------- -a800_cart_slot_device::a800_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : device_t(mconfig, type, tag, owner, clock) + +a800_cart_slot_device::a800_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, A800_CART_SLOT, tag, owner, clock) + , device_memory_interface(mconfig, *this) , device_cartrom_image_interface(mconfig, *this) , device_single_card_slot_interface(mconfig, *this) , m_cart(nullptr) - , m_type(0) + , m_rd4_cb(*this) + , m_rd5_cb(*this) + , m_space_mem_config("cart_mem", ENDIANNESS_LITTLE, 8, 14, 0, address_map_constructor()) + , m_space_io_config("cart_io", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor()) + , m_is_xegs(false) { } -a800_cart_slot_device::a800_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - a800_cart_slot_device(mconfig, A800_CART_SLOT, tag, owner, clock) -{ -} - - -a5200_cart_slot_device::a5200_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - a800_cart_slot_device(mconfig, A5200_CART_SLOT, tag, owner, clock) -{ -} - - -xegs_cart_slot_device::xegs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : - a800_cart_slot_device(mconfig, XEGS_CART_SLOT, tag, owner, clock) +a5200_cart_slot_device::a5200_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : device_t(mconfig, A5200_CART_SLOT, tag, owner, clock) + , device_memory_interface(mconfig, *this) + , device_cartrom_image_interface(mconfig, *this) + , device_single_card_slot_interface(mconfig, *this) + , m_cart(nullptr) + , m_space_mem_config("cart_mem", ENDIANNESS_LITTLE, 8, 15, 0, address_map_constructor()) { } @@ -141,10 +187,6 @@ a5200_cart_slot_device::~a5200_cart_slot_device() { } -xegs_cart_slot_device::~xegs_cart_slot_device() -{ -} - //------------------------------------------------- // device_start - device-specific startup //------------------------------------------------- @@ -152,6 +194,20 @@ xegs_cart_slot_device::~xegs_cart_slot_device() void a800_cart_slot_device::device_start() { m_cart = get_card_device(); + m_space_io = &space(AS_IO); + m_space_mem = &space(AS_PROGRAM); +} + +void a800_cart_slot_device::device_resolve_objects() +{ + m_rd4_cb.resolve_safe(); + m_rd5_cb.resolve_safe(); +} + +void a5200_cart_slot_device::device_start() +{ + m_cart = get_card_device(); + m_space_mem = &space(AS_PROGRAM); } /*------------------------------------------------- @@ -178,26 +234,33 @@ static const a800_slot slot_list[] = { A800_OSSM091, "a800_ossm091" }, { A800_OSS8K, "a800_oss8k" }, { A800_PHOENIX, "a800_phoenix" }, + { A800_BLIZZARD, "a800_blizzard" }, { A800_XEGS, "xegs" }, { A800_BBSB, "a800_bbsb" }, { A800_DIAMOND, "a800_diamond" }, { A800_WILLIAMS, "a800_williams" }, { A800_EXPRESS, "a800_express" }, { A800_SPARTADOS, "a800_sparta" }, - { A800_TURBO64, "a800_turbo64" }, - { A800_TURBO128, "a800_turbo128" }, + { A800_SPARTADOS_128KB, "a800_sparta_128kb" }, + { A800_TURBO, "a800_turbo" }, { A800_BLIZZARD, "a800_blizzard" }, { A800_TELELINK2, "a800_tlink2" }, - { A800_MICROCALC, "a800_sitsa" }, + { A800_ULTRACART, "a800_ultracart" }, + { A800_ATRAX, "a800_atrax" }, { A800_CORINA, "a800_corina" }, { A800_CORINA_SRAM, "a800_corina_sram" }, + { SIC_128KB, "sic_128kb" }, + { SIC_256KB, "sic_256kb" }, + { SIC_512KB, "sic_512kb" }, + { ATARIMAX_MAXFLASH_128KB, "maxflash_128kb" }, + { ATARIMAX_MAXFLASH_1MB, "maxflash_1mb" }, + { A800_ADAWLIAH, "a800_adawliah" }, { A800_8K_RIGHT, "a800_8k_right" }, - { A5200_4K, "a5200" }, - { A5200_8K, "a5200" }, - { A5200_16K, "a5200" }, - { A5200_32K, "a5200" }, + { A5200_4K, "a5200_rom" }, + { A5200_8K, "a5200_rom" }, + { A5200_16K, "a5200_rom" }, + { A5200_32K, "a5200_rom" }, { A5200_16K_2CHIPS, "a5200_2chips" }, - { A5200_32K, "a5200" }, { A5200_BBSB, "a5200_bbsb" } }; @@ -274,29 +337,77 @@ std::pair a800_cart_slot_device::call_load() m_cart->rom_alloc(len); fread(m_cart->get_rom_base(), len); } - if (m_type == A800_TELELINK2) - m_cart->nvram_alloc(0x100); - if (m_type == A800_CORINA || m_type == A800_CORINA_SRAM) - m_cart->nvram_alloc(0x2000); - if (m_type == A800_CORINA) - m_cart->ram_alloc(0x4000); - if (m_type == A800_CORINA_SRAM) - m_cart->ram_alloc(0x80000); logerror("%s loaded cartridge '%s' size %dK\n", machine().system().name, filename(), len/1024); } return std::make_pair(std::error_condition(), std::string()); } +std::pair a5200_cart_slot_device::call_load() +{ + if (m_cart) + { + uint32_t len; -/*------------------------------------------------- - call_unload - -------------------------------------------------*/ + if (loaded_through_softlist()) + { + const char *pcb_name; + len = get_software_region_length("rom"); + + m_cart->rom_alloc(len); + memcpy(m_cart->get_rom_base(), get_software_region("rom"), len); + + if ((pcb_name = get_feature("slot")) != nullptr) + m_type = a800_get_pcb_id(pcb_name); + else + m_type = A800_8K; + } + else + { + len = length(); + + // check whether there is an header, to identify the cart type + if ((len % 0x1000) == 0x10) + { + uint8_t header[16]; + fread(header, 0x10); + m_type = identify_cart_type(header); + len -= 0x10; // in identify_cart_type the first 0x10 bytes are read, so we need to adjust here + } + else // otherwise try to guess based on size + { + if (len == 0x8000) + m_type = A5200_32K; + if (len == 0x4000) + m_type = A800_16K; + if (len == 0x2000) + m_type = A800_8K; + if (len == 0x1000) + m_type = A5200_4K; + // also make a try with .hsi file (for .a52 files) + std::string info; + if (hashfile_extrainfo(*this, info) && info.compare("A13MIRRORING")==0) + m_type = A5200_16K_2CHIPS; + } + + m_cart->rom_alloc(len); + fread(m_cart->get_rom_base(), len); + } + + logerror("%s loaded cartridge '%s' size %dK\n", machine().system().name, filename(), len/1024); + } + return std::make_pair(std::error_condition(), std::string()); +} void a800_cart_slot_device::call_unload() { } +void a5200_cart_slot_device::call_unload() +{ +} + + /*------------------------------------------------- identify_cart_type - code to detect cart type from fullpath @@ -306,6 +417,8 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const { int type = A800_8K; + // TODO: canonically applies to .car extension only, have 10 bytes extra header on top + // check CART format if (strncmp((const char *)header, "CART", 4)) fatalerror("Invalid header detected!\n"); @@ -339,6 +452,9 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const case 15: type = A800_OSSM091; break; + case 17: + type = A800_ATRAX; + break; case 18: type = A800_BBSB; break; @@ -351,19 +467,154 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const case 40: type = A800_BLIZZARD; break; + case 41: + type = ATARIMAX_MAXFLASH_128KB; + break; + case 42: + type = ATARIMAX_MAXFLASH_1MB; + break; + case 43: + type = A800_SPARTADOS_128KB; + break; case 44: type = A800_OSS8K; break; case 50: - type = A800_TURBO64; + type = A800_TURBO; break; case 51: - type = A800_TURBO128; + type = A800_TURBO; break; case 52: - type = A800_MICROCALC; + type = A800_ULTRACART; break; - // Atari 5200 CART files + case 54: + type = SIC_128KB; + break; + case 55: + type = SIC_256KB; + break; + case 56: + type = SIC_512KB; + break; + case 69: + type = A800_ADAWLIAH; + break; + // Atari 5200 CART files + case 4: + type = A5200_32K; + break; + case 16: + type = A5200_16K; + break; + case 19: + type = A5200_8K; + break; + case 20: + type = A5200_4K; + break; + case 6: + type = A5200_16K_2CHIPS; + break; + case 7: + type = A5200_BBSB; + break; + default: + osd_printf_info("Cart type \"%d\" is currently unsupported.\n", (header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0)); + break; + } + + return type; +} + +int a5200_cart_slot_device::identify_cart_type(const uint8_t *header) const +{ + int type = A800_8K; + + // TODO: canonically applies to .car extension only, have 10 bytes extra header on top + + // check CART format + if (strncmp((const char *)header, "CART", 4)) + fatalerror("Invalid header detected!\n"); + + switch ((header[4] << 24) + (header[5] << 16) + (header[6] << 8) + (header[7] << 0)) + { + case 1: + type = A800_8K; + break; + case 2: + type = A800_16K; + break; + case 3: + type = A800_OSS034M; + break; + case 8: + type = A800_WILLIAMS; + break; + case 9: + type = A800_DIAMOND; + break; + case 10: + type = A800_EXPRESS; + break; + case 11: + type = A800_SPARTADOS; + break; + case 12: + type = A800_XEGS; + break; + case 15: + type = A800_OSSM091; + break; + case 17: + type = A800_ATRAX; + break; + case 18: + type = A800_BBSB; + break; + case 21: + type = A800_8K_RIGHT; + break; + case 39: + type = A800_PHOENIX; + break; + case 40: + type = A800_BLIZZARD; + break; + case 41: + type = ATARIMAX_MAXFLASH_128KB; + break; + case 42: + type = ATARIMAX_MAXFLASH_1MB; + break; + case 43: + type = A800_SPARTADOS_128KB; + break; + case 44: + type = A800_OSS8K; + break; + case 50: + type = A800_TURBO; + break; + case 51: + type = A800_TURBO; + break; + case 52: + type = A800_ULTRACART; + break; + case 54: + type = SIC_128KB; + break; + case 55: + type = SIC_256KB; + break; + case 56: + type = SIC_512KB; + break; + case 69: + type = A800_ADAWLIAH; + break; + // Atari 5200 CART files case 4: type = A5200_32K; break; @@ -396,13 +647,17 @@ int a800_cart_slot_device::identify_cart_type(const uint8_t *header) const std::string a800_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const { + // Nope, will crash when mounting the SDX subslot +// std::string slot_default_option = default_option(); + const bool is_xegs = m_is_xegs; + if (hook.image_file()) { uint64_t len; hook.image_file()->length(len); // FIXME: check error return + int type = is_xegs ? A800_XEGS : A800_8K; // check whether there is an header, to identify the cart type - int type = A800_8K; if ((len % 0x1000) == 0x10) { size_t actual; @@ -412,13 +667,23 @@ std::string a800_cart_slot_device::get_default_card_software(get_default_card_so } else // otherwise try to guess based on size { + if (is_xegs) + return std::string("xegs"); + // TODO: very incomplete, is it also worth it? + // Altirra sports a very complex scoring analysis (including code binary patterns), + // and it still grants to the user multiple options if (len == 0x4000) type = A800_16K; if (len == 0x2000) type = A800_8K; } - if (type >= A5200_4K) + if (is_xegs && type != A800_XEGS) + { + osd_printf_info("This game is not designed for XEGS.\n"); + osd_printf_info("You might want to run it in %s.\n", type >= A5200_4K ? "A5200" : "A800"); + } + else if (type >= A5200_4K) osd_printf_info("This game is not designed for A800. You might want to run it in A5200.\n"); char const *const slot_string = a800_get_slot(type); @@ -426,7 +691,7 @@ std::string a800_cart_slot_device::get_default_card_software(get_default_card_so return std::string(slot_string); } - return software_get_default_slot("a800_8k"); + return software_get_default_slot(is_xegs ? "xegs" : "a800_8k"); } @@ -460,41 +725,7 @@ std::string a5200_cart_slot_device::get_default_card_software(get_default_card_s return std::string(slot_string); } - return software_get_default_slot("a5200"); -} - - -std::string xegs_cart_slot_device::get_default_card_software(get_default_card_software_hook &hook) const -{ - if (hook.image_file()) - { - uint64_t len; - hook.image_file()->length(len); // FIXME: check error return - - // check whether there is an header, to identify the cart type - int type = A800_8K; - if ((len % 0x1000) == 0x10) - { - size_t actual; - uint8_t head[0x10]; - hook.image_file()->read(&head[0], 0x10, actual); // FIXME: check error return or read returning short - type = identify_cart_type(&head[0]); - } - if (type != A800_XEGS) - { - osd_printf_info("This game is not designed for XEGS. "); - if (type >= A5200_4K) - osd_printf_info("You might want to run it in A5200.\n"); - else - osd_printf_info("You might want to run it in A800 or A800XL.\n"); - } - - char const *const slot_string = a800_get_slot(type); - - return std::string(slot_string); - } - - return software_get_default_slot("xegs"); + return software_get_default_slot("a5200_rom"); } @@ -502,35 +733,53 @@ std::string xegs_cart_slot_device::get_default_card_software(get_default_card_so read -------------------------------------------------*/ -uint8_t a800_cart_slot_device::read_80xx(offs_t offset) +device_memory_interface::space_config_vector a800_cart_slot_device::memory_space_config() const { - if (m_cart) - return m_cart->read_80xx(offset); - else - return 0xff; + return space_config_vector{ + std::make_pair(AS_PROGRAM, &m_space_mem_config), + std::make_pair(AS_IO, &m_space_io_config) + }; } -uint8_t a800_cart_slot_device::read_d5xx(offs_t offset) +template uint8_t a800_cart_slot_device::read_cart(offs_t offset) { - if (m_cart) - return m_cart->read_d5xx(offset); - else - return 0xff; + return m_space_mem->read_byte(offset | Bank << 13); } - -/*------------------------------------------------- - write - -------------------------------------------------*/ - -void a800_cart_slot_device::write_80xx(offs_t offset, uint8_t data) +template void a800_cart_slot_device::write_cart(offs_t offset, uint8_t data) { - if (m_cart) - m_cart->write_80xx(offset, data); + return m_space_mem->write_byte(offset | Bank << 13, data); } -void a800_cart_slot_device::write_d5xx(offs_t offset, uint8_t data) +// Instantiate maps +template uint8_t a800_cart_slot_device::read_cart<0>(offs_t offset); +template uint8_t a800_cart_slot_device::read_cart<1>(offs_t offset); +template void a800_cart_slot_device::write_cart<0>(offs_t offset, uint8_t data); +template void a800_cart_slot_device::write_cart<1>(offs_t offset, uint8_t data); + +uint8_t a800_cart_slot_device::read_cctl(offs_t offset) { - if (m_cart) - m_cart->write_d5xx(offset, data); + return m_space_io->read_byte(offset); +} + +void a800_cart_slot_device::write_cctl(offs_t offset, uint8_t data) +{ + m_space_io->write_byte(offset, data); +} + +device_memory_interface::space_config_vector a5200_cart_slot_device::memory_space_config() const +{ + return space_config_vector{ + std::make_pair(AS_PROGRAM, &m_space_mem_config) + }; +} + +uint8_t a5200_cart_slot_device::read_cart(offs_t offset) +{ + return m_space_mem->read_byte(offset); +} + +void a5200_cart_slot_device::write_cart(offs_t offset, uint8_t data) +{ + return m_space_mem->write_byte(offset, data); } diff --git a/src/devices/bus/a800/a800_slot.h b/src/devices/bus/a800/a800_slot.h index f5c9de95e19..53de7be11ff 100644 --- a/src/devices/bus/a800/a800_slot.h +++ b/src/devices/bus/a800/a800_slot.h @@ -1,5 +1,5 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Fabio Priuli, Angelo Salese #ifndef MAME_BUS_A800_A800_SLOT_H #define MAME_BUS_A800_A800_SLOT_H @@ -13,6 +13,7 @@ ***************************************************************************/ /* PCB */ +// TODO: make this enum to actually follow up the .car specs, not the other way around enum { A800_8K = 0, @@ -23,19 +24,26 @@ enum A800_OSSM091, A800_OSS8K, A800_PHOENIX, + A800_BLIZZARD, A800_XEGS, A800_BBSB, A800_DIAMOND, A800_WILLIAMS, A800_EXPRESS, A800_SPARTADOS, - A800_BLIZZARD, - A800_TURBO64, - A800_TURBO128, + A800_SPARTADOS_128KB, + A800_TURBO, A800_TELELINK2, - A800_MICROCALC, + A800_ULTRACART, + A800_ADAWLIAH, + A800_ATRAX, A800_CORINA, A800_CORINA_SRAM, + ATARIMAX_MAXFLASH_128KB, + ATARIMAX_MAXFLASH_1MB, + SIC_128KB, + SIC_256KB, + SIC_512KB, A5200_4K, A5200_8K, A5200_16K, @@ -44,8 +52,7 @@ enum A5200_BBSB }; - -// ======================> device_a800_cart_interface +class a800_cart_slot_device; class device_a800_cart_interface : public device_interface { @@ -53,41 +60,49 @@ public: // construction/destruction virtual ~device_a800_cart_interface(); - // memory accessor - virtual uint8_t read_80xx(offs_t offset) { return 0xff; } - virtual uint8_t read_d5xx(offs_t offset) { return 0xff; } - virtual void write_80xx(offs_t offset, uint8_t data) {} - virtual void write_d5xx(offs_t offset, uint8_t data) {} + virtual void cart_map(address_map &map); + virtual void cctl_map(address_map &map); + // TODO: remove all of this void rom_alloc(uint32_t size); - void ram_alloc(uint32_t size); - void nvram_alloc(uint32_t size); uint8_t* get_rom_base() { return m_rom; } - uint8_t* get_ram_base() { return &m_ram[0]; } - uint8_t* get_nvram_base() { return &m_nvram[0]; } uint32_t get_rom_size() { return m_rom_size; } - uint32_t get_ram_size() { return m_ram.size(); } - uint32_t get_nvram_size() { return m_nvram.size(); } + + /// + /// Carts can either init RD4/RD5 at startup or not, depending on if they have + /// reset circuitry or not. Future expansion of this getter will return a third value, + /// giving back the timing value where the initialization should happen. + /// + /// \return RD4, RD5 initial state + virtual std::tuple get_initial_rd_state() { return std::make_tuple(0, 0); } protected: device_a800_cart_interface(const machine_config &mconfig, device_t &device); + virtual void interface_pre_start() override; + virtual void interface_post_start() override; + a800_cart_slot_device *m_slot; + // internal state uint8_t *m_rom; uint32_t m_rom_size; - std::vector m_ram; - std::vector m_nvram; // HiScore cart can save scores! // helpers int m_bank_mask; + + void rd4_w( int state ); + void rd5_w( int state ); + void rd_both_w ( int state ); }; // ======================> a800_cart_slot_device class a800_cart_slot_device : public device_t, + public device_memory_interface, public device_cartrom_image_interface, public device_single_card_slot_interface { + friend class device_a800_cart_interface; public: // construction/destruction template @@ -102,46 +117,87 @@ public: a800_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); virtual ~a800_cart_slot_device(); - // device_image_interface implementation - virtual std::pair call_load() override; - virtual void call_unload() override; - virtual bool is_reset_on_load() const noexcept override { return true; } virtual const char *image_interface() const noexcept override { return "a8bit_cart"; } virtual const char *file_extensions() const noexcept override { return "bin,rom,car"; } // slot interface overrides virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; - - int get_cart_type() { return m_type; } int identify_cart_type(const uint8_t *header) const; - bool has_cart() { return m_cart != nullptr; } + virtual std::pair call_load() override; + virtual void call_unload() override; - // reading and writing - uint8_t read_80xx(offs_t offset); - uint8_t read_d5xx(offs_t offset); - void write_80xx(offs_t offset, uint8_t data); - void write_d5xx(offs_t offset, uint8_t data); + bool has_cart() { return m_cart != nullptr; } + auto rd4_callback() { return m_rd4_cb.bind(); } + auto rd5_callback() { return m_rd5_cb.bind(); } + void set_is_xegs(bool is_xegs) { m_is_xegs = is_xegs; } + + template uint8_t read_cart(offs_t offset); + template void write_cart(offs_t offset, uint8_t data); + uint8_t read_cctl(offs_t offset); + void write_cctl(offs_t offset, uint8_t data); + auto get_initial_rd_state() { return m_cart->get_initial_rd_state(); } protected: - a800_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + //a800_cart_slot_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); // device_t implementation virtual void device_start() override; + virtual void device_resolve_objects() override; + virtual space_config_vector memory_space_config() const override; private: - device_a800_cart_interface *m_cart; - int m_type; + device_a800_cart_interface* m_cart; + + devcb_write_line m_rd4_cb; + devcb_write_line m_rd5_cb; + + address_space_config m_space_mem_config; + address_space_config m_space_io_config; + + address_space *m_space_mem; + address_space *m_space_io; + + int m_type = 0; + bool m_is_xegs = false; +}; + +class a5200_cart_slot_device; + +class device_a5200_cart_interface : public device_interface +{ +public: + // construction/destruction + virtual ~device_a5200_cart_interface(); + + virtual void cart_map(address_map &map); + + // TODO: remove all of this + void rom_alloc(uint32_t size); + uint8_t* get_rom_base() { return m_rom; } + uint32_t get_rom_size() { return m_rom_size; } + +protected: + device_a5200_cart_interface(const machine_config &mconfig, device_t &device); + + virtual void interface_pre_start() override; + virtual void interface_post_start() override; + a5200_cart_slot_device *m_slot; + + // internal state + uint8_t *m_rom; + uint32_t m_rom_size; + // helpers + int m_bank_mask; }; -// The variants below are added to handle the additional formats for a5200, and to give more -// clear error messages if you try to load an A5200 game into an A800 or a XEGS, etc. - -// ======================> a5200_cart_slot_device - -class a5200_cart_slot_device : public a800_cart_slot_device +class a5200_cart_slot_device : public device_t, + public device_memory_interface, + public device_cartrom_image_interface, + public device_single_card_slot_interface { + friend class device_a5200_cart_interface; public: // construction/destruction template @@ -156,39 +212,33 @@ public: a5200_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); virtual ~a5200_cart_slot_device(); + virtual bool is_reset_on_load() const noexcept override { return true; } + virtual const char *image_interface() const noexcept override { return "a8bit_cart"; } virtual const char *file_extensions() const noexcept override { return "bin,rom,car,a52"; } // slot interface overrides virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; -}; + int identify_cart_type(const uint8_t *header) const; + virtual std::pair call_load() override; + virtual void call_unload() override; -// ======================> xegs_cart_slot_device + u8 read_cart(offs_t offset); + void write_cart(offs_t offset, u8 data); -class xegs_cart_slot_device : public a800_cart_slot_device -{ -public: - // construction/destruction - template - xegs_cart_slot_device(machine_config const &mconfig, char const *tag, device_t *owner, T &&opts, char const *dflt) - : xegs_cart_slot_device(mconfig, tag, owner, (uint32_t)0) - { - option_reset(); - opts(*this); - set_default_option(dflt); - set_fixed(false); - } - xegs_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual ~xegs_cart_slot_device(); +protected: + virtual void device_start() override; + virtual space_config_vector memory_space_config() const override; - virtual const char *file_extensions() const noexcept override { return "bin,rom,car"; } +private: + device_a5200_cart_interface* m_cart; + address_space_config m_space_mem_config; - // slot interface overrides - virtual std::string get_default_card_software(get_default_card_software_hook &hook) const override; + address_space *m_space_mem; + int m_type; }; // device type definition DECLARE_DEVICE_TYPE(A800_CART_SLOT, a800_cart_slot_device) DECLARE_DEVICE_TYPE(A5200_CART_SLOT, a5200_cart_slot_device) -DECLARE_DEVICE_TYPE(XEGS_CART_SLOT, xegs_cart_slot_device) #endif // MAME_BUS_A800_A800_SLOT_H diff --git a/src/devices/bus/a800/a8sio.cpp b/src/devices/bus/a800/a8sio.cpp index 9a4dca9187b..65f52308e26 100644 --- a/src/devices/bus/a800/a8sio.cpp +++ b/src/devices/bus/a800/a8sio.cpp @@ -41,7 +41,7 @@ // GLOBAL VARIABLES //************************************************************************** -DEFINE_DEVICE_TYPE(A8SIO, a8sio_device, "a8sio", "Atari 8 bit SIO Slot") +DEFINE_DEVICE_TYPE(A8SIO, a8sio_device, "a8sio", "Atari 8-bit SIO Slot") //************************************************************************** // LIVE DEVICE diff --git a/src/devices/bus/a800/atari1050.h b/src/devices/bus/a800/atari1050.h index 413e7bb5560..6605d05e6a4 100644 --- a/src/devices/bus/a800/atari1050.h +++ b/src/devices/bus/a800/atari1050.h @@ -42,7 +42,6 @@ private: required_device m_fdc; }; -// device type declaration DECLARE_DEVICE_TYPE(ATARI1050, atari1050_device) #endif // MAME_BUS_A800_ATARI1050 diff --git a/src/devices/bus/a800/atari810.h b/src/devices/bus/a800/atari810.h index 3ff1b402a39..983161a3d2f 100644 --- a/src/devices/bus/a800/atari810.h +++ b/src/devices/bus/a800/atari810.h @@ -42,7 +42,6 @@ private: required_device m_fdc; }; -// device type declaration DECLARE_DEVICE_TYPE(ATARI810, atari810_device) #endif // MAME_BUS_A800_ATARI810 diff --git a/src/devices/bus/a800/atrax.cpp b/src/devices/bus/a800/atrax.cpp new file mode 100644 index 00000000000..bdf815c8074 --- /dev/null +++ b/src/devices/bus/a800/atrax.cpp @@ -0,0 +1,54 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +/************************************************************************************************** + +Atrax 128KB cart ROM + +Not to be confused with the Sparta DOS X variants, this one is just a standalone cart with +single CCTL register that covers RD5 and bank. + +**************************************************************************************************/ + +#include "emu.h" +#include "atrax.h" + +DEFINE_DEVICE_TYPE(A800_ROM_ATRAX, a800_rom_atrax_device, "a800_atrax", "Atari 8-bit Atrax 128KB cart") + + +a800_rom_atrax_device::a800_rom_atrax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, A800_ROM_ATRAX, tag, owner, clock) + , m_bank(0) +{ +} + +void a800_rom_atrax_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_atrax_device::device_reset() +{ + m_bank = 0; +} + +void a800_rom_atrax_device::cart_map(address_map &map) +{ + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; }) + ); +} + +void a800_rom_atrax_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).w(FUNC(a800_rom_atrax_device::config_bank_w)); +} + +/* + * x--- ---- RD5 disabled (1) enabled (0) + * ---- xxxx bank number + */ +void a800_rom_atrax_device::config_bank_w(offs_t offset, u8 data) +{ + rd5_w(!BIT(data, 7)); + m_bank = data & 0xf; +} diff --git a/src/devices/bus/a800/atrax.h b/src/devices/bus/a800/atrax.h new file mode 100644 index 00000000000..943d4587452 --- /dev/null +++ b/src/devices/bus/a800/atrax.h @@ -0,0 +1,34 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A800_ATRAX_H +#define MAME_BUS_A800_ATRAX_H + +#pragma once + +#include "rom.h" + + +class a800_rom_atrax_device : public a800_rom_device +{ +public: + a800_rom_atrax_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + void config_bank_w(offs_t offset, u8 data); + +private: + int m_bank; +}; + + +DECLARE_DEVICE_TYPE(A800_ROM_ATRAX, a800_rom_atrax_device) + +#endif // MAME_BUS_A800_ATRAX_H diff --git a/src/devices/bus/a800/bbsb.cpp b/src/devices/bus/a800/bbsb.cpp new file mode 100644 index 00000000000..bd57367bca3 --- /dev/null +++ b/src/devices/bus/a800/bbsb.cpp @@ -0,0 +1,136 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese +/************************************************************************************************** + +A800/A5200 Bounty Bob Strikes Back ROM schemes + +Dual banking overlay access mapped in cart_map rd4 space at $xff6-$xff9, +A12 select bank window, bank bases are different. +rd5 just points to the last bank. + +A5200 BBSB is mostly similar to the A800 version but with shuffled around data banks +i.e. fixed bank is actually the first one, and the overlay banks comes afterwards in the ROM space. + +TODO: +- It's unknown if rd4 and rd5 can even be disabled from software (probably not); + +**************************************************************************************************/ + +#include "emu.h" +#include "bbsb.h" + +DEFINE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device, "a800_bbsb", "Atari 8-bit Bounty Bob Strikes Back cart") +DEFINE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device, "a5200_bbsb", "Atari 5200 ROM Bounty Bob Strikes Back cart") + + +a800_rom_bbsb_device::a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, A800_ROM_BBSB, tag, owner, clock) +{ +} + + +void a800_rom_bbsb_device::device_start() +{ + // TODO: m_banks should be an extra interface for a5200 + save_item(NAME(m_banks)); +} + +void a800_rom_bbsb_device::device_reset() +{ + m_banks[0] = 0; + m_banks[1] = 0; +} + +template u8 a800_rom_bbsb_device::read_bank(offs_t offset) +{ + return m_rom[(offset & 0xfff) + (m_banks[BankNum] * 0x1000) + (BankNum * 0x4000)]; +} + +void a800_rom_bbsb_device::cart_map(address_map &map) +{ + map(0x0000, 0x0fff).r(FUNC(a800_rom_bbsb_device::read_bank<0>)); + map(0x1000, 0x1fff).r(FUNC(a800_rom_bbsb_device::read_bank<1>)); + map(0x0ff6, 0x0ff9).select(0x1000).rw(FUNC(a800_rom_bbsb_device::bank_r), FUNC(a800_rom_bbsb_device::bank_w)); + + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + 0x8000]; } ) + ); +} + +uint8_t a800_rom_bbsb_device::bank_r(offs_t offset) +{ + const u8 bank_window = (offset & ~3) != 0; + const u8 bank_num = offset & 3; + if (!machine().side_effects_disabled()) + m_banks[bank_window] = bank_num; + + // TODO: unconfirmed, all $xff6-$xff9 just points to 0xff values + // Real cart overlay may return floating bus or the contents of the previous bank instead, + // needs to be tested by trying to execute code from there. + return 0xff; +} + +void a800_rom_bbsb_device::bank_w(offs_t offset, uint8_t data) +{ + const u8 bank_window = (offset & ~3) != 0; + const u8 bank_num = offset & 3; + m_banks[bank_window] = bank_num; +} + +/*------------------------------------------------- + + A5200 Bounty Bob Strikes Back! cart + + -------------------------------------------------*/ + +a5200_rom_bbsb_device::a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a5200_rom_device(mconfig, A5200_ROM_BBSB, tag, owner, clock) +{ +} + +void a5200_rom_bbsb_device::device_start() +{ + save_item(NAME(m_banks)); +} + +void a5200_rom_bbsb_device::device_reset() +{ + m_banks[0] = 0; + m_banks[1] = 0; +} + +template u8 a5200_rom_bbsb_device::read_bank(offs_t offset) +{ + return m_rom[(offset & 0xfff) + (m_banks[BankNum] * 0x1000) + (BankNum ? 0x6000 : 0x2000)]; +} + +void a5200_rom_bbsb_device::cart_map(address_map &map) +{ + map(0x0000, 0x0fff).r(FUNC(a5200_rom_bbsb_device::read_bank<0>)); + map(0x1000, 0x1fff).r(FUNC(a5200_rom_bbsb_device::read_bank<1>)); + map(0x0ff6, 0x0ff9).select(0x1000).rw(FUNC(a5200_rom_bbsb_device::bank_r), FUNC(a5200_rom_bbsb_device::bank_w)); + + map(0x4000, 0x7fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & 0x1fff]; } ) + ); +} + +uint8_t a5200_rom_bbsb_device::bank_r(offs_t offset) +{ + const u8 bank_window = (offset & ~3) != 0; + const u8 bank_num = offset & 3; + if (!machine().side_effects_disabled()) + m_banks[bank_window] = bank_num; + + // TODO: unconfirmed, all $xff6-$xff9 just points to 0xff values + // Real cart overlay may return floating bus or the contents of the previous bank instead, + // needs to be tested by trying to execute code from there. + return 0xff; +} + +void a5200_rom_bbsb_device::bank_w(offs_t offset, uint8_t data) +{ + const u8 bank_window = (offset & ~3) != 0; + const u8 bank_num = offset & 3; + m_banks[bank_window] = bank_num; +} diff --git a/src/devices/bus/a800/bbsb.h b/src/devices/bus/a800/bbsb.h new file mode 100644 index 00000000000..c96a1a70420 --- /dev/null +++ b/src/devices/bus/a800/bbsb.h @@ -0,0 +1,52 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese + +#ifndef MAME_BUS_A800_BBSB_H +#define MAME_BUS_A800_BBSB_H + +#pragma once + +#include "rom.h" + + +class a800_rom_bbsb_device : public a800_rom_device +{ +public: + a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 1); } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + int m_banks[2]; + + template u8 read_bank(offs_t offset); + u8 bank_r(offs_t offset); + void bank_w(offs_t offset, u8 data); +}; + +class a5200_rom_bbsb_device : public a5200_rom_device +{ +public: + a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + int m_banks[2]; + + template u8 read_bank(offs_t offset); + u8 bank_r(offs_t offset); + void bank_w(offs_t offset, u8 data); +}; + +DECLARE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device) +DECLARE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device) + +#endif // MAME_BUS_A800_BBSB_H diff --git a/src/devices/bus/a800/cassette.cpp b/src/devices/bus/a800/cassette.cpp index ca5486ac7cd..50feed49c5c 100644 --- a/src/devices/bus/a800/cassette.cpp +++ b/src/devices/bus/a800/cassette.cpp @@ -25,7 +25,7 @@ TODO: // GLOBAL VARIABLES //************************************************************************** -DEFINE_DEVICE_TYPE(A8SIO_CASSETTE, a8sio_cassette_device, "a8sio_cass", "Atari 8 bit cassette") +DEFINE_DEVICE_TYPE(A8SIO_CASSETTE, a8sio_cassette_device, "a8sio_cass", "Atari 8-bit cassette") void a8sio_cassette_device::device_add_mconfig(machine_config &config) { diff --git a/src/devices/bus/a800/corina.cpp b/src/devices/bus/a800/corina.cpp new file mode 100644 index 00000000000..451e6e31462 --- /dev/null +++ b/src/devices/bus/a800/corina.cpp @@ -0,0 +1,135 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +/************************************************************************************************** + +Corina + +Known configs: +- 1MB Flash ROM (yakungfu) +- 512KB Flash ROM + 512KB SRAM (bombjake) + +Both contains 8KB NVRAM + +TODO: +- Pinpoint and convert to flash interface; +- Unknown behaviour when accessing the "reserved" view; + +**************************************************************************************************/ + +#include "emu.h" +#include "corina.h" + +DEFINE_DEVICE_TYPE(A800_ROM_CORINA, a800_rom_corina_device, "a800_corina", "Atari 8-bit Corina 1MB flash ROM cart") +DEFINE_DEVICE_TYPE(A800_ROM_CORINA_SRAM, a800_rom_corina_sram_device, "a800_corina_sram", "Atari 8-bit Corina 512KB flash ROM + 512KB RAM cart") + +a800_rom_corina_device::a800_rom_corina_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_nvram(*this, "nvram") + , m_view(*this, "corina_view") + , m_rom_bank(0) +{ +} + +a800_rom_corina_device::a800_rom_corina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_corina_device(mconfig, A800_ROM_CORINA, tag, owner, clock) +{ +} + +void a800_rom_corina_device::device_add_mconfig(machine_config &config) +{ + NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1); +} + +void a800_rom_corina_device::device_start() +{ + const u32 nvram_size = 0x2000; + m_nvram_ptr = std::make_unique(nvram_size); + m_nvram->set_base(m_nvram_ptr.get(), nvram_size); + + save_pointer(NAME(m_nvram_ptr), nvram_size); + save_item(NAME(m_rom_bank)); +} + +void a800_rom_corina_device::device_reset() +{ + m_rom_bank = 0; + m_view.select(0); +} + +void a800_rom_corina_device::cart_map(address_map &map) +{ + map.unmap_value_high(); + map(0x0000, 0x3fff).view(m_view); + // TODO: spam writes during loading, flash commands? + m_view[0](0x0000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x3fff) + (m_rom_bank * 0x4000)]; }) + ); + m_view[1](0x0000, 0x3fff).rw(FUNC(a800_rom_corina_device::read_view_1), FUNC(a800_rom_corina_device::write_view_1)); + m_view[2](0x0000, 0x3fff).lrw8( + NAME([this](offs_t offset) { return m_nvram_ptr[offset & 0x1fff]; }), + NAME([this](offs_t offset, uint8_t data) { m_nvram_ptr[offset & 0x1fff] = data; }) + ); + m_view[3](0x0000, 0x3fff).unmaprw(); +} + +void a800_rom_corina_device::cctl_map(address_map &map) +{ + map(0x00, 0x00).w(FUNC(a800_rom_corina_device::ctrl_w)); +} + +uint8_t a800_rom_corina_device::read_view_1(offs_t offset) +{ + return m_rom[(offset & 0x3fff) + (m_rom_bank * 0x4000) + 0x80000]; +} + +void a800_rom_corina_device::write_view_1(offs_t offset, u8 data) +{ +} + +/* + * 0--- ---- enable Corina window + * 1--- ---- disable Corina and select main unit 8000-bfff window instead + * -xx- ---- view select + * -00- ---- first half of ROM + * -01- ---- second half of ROM or RAM (^ depending on PCB config) + * -10- ---- NVRAM + * -11- ---- + * ---x xxxx ROM/RAM lower bank value, + * ignored if view select is not in ROM/RAM mode + * or Corina window is disabled + */ +void a800_rom_corina_device::ctrl_w(offs_t offset, uint8_t data) +{ + m_rom_bank = data & 0x1f; + m_view.select((data & 0x60) >> 5); + rd_both_w(!BIT(data, 7)); +} + +/*------------------------------------------------- + + SRAM variant overrides + + -------------------------------------------------*/ + +a800_rom_corina_sram_device::a800_rom_corina_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_corina_device(mconfig, A800_ROM_CORINA_SRAM, tag, owner, clock) +{ +} + +void a800_rom_corina_sram_device::device_start() +{ + a800_rom_corina_device::device_start(); + + m_ram.resize(0x80000); + save_item(NAME(m_ram)); +} + +uint8_t a800_rom_corina_sram_device::read_view_1(offs_t offset) +{ + return m_ram[(offset & 0x3fff) + (m_rom_bank * 0x4000)]; +} + +void a800_rom_corina_sram_device::write_view_1(offs_t offset, u8 data) +{ + m_ram[(offset & 0x3fff) + (m_rom_bank * 0x4000)] = data; +} diff --git a/src/devices/bus/a800/corina.h b/src/devices/bus/a800/corina.h new file mode 100644 index 00000000000..1bd4fae2ba8 --- /dev/null +++ b/src/devices/bus/a800/corina.h @@ -0,0 +1,59 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A800_CORINA_H +#define MAME_BUS_A800_CORINA_H + +#pragma once + +#include "rom.h" +//#include "machine/intelfsh.h" + +class a800_rom_corina_device : public a800_rom_device +{ +public: + a800_rom_corina_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_rom_corina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 1); } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + std::unique_ptr m_nvram_ptr; + + virtual uint8_t read_view_1(offs_t offset); + virtual void write_view_1(offs_t offset, u8 data); + + void ctrl_w(offs_t offset, u8 data); + + required_device m_nvram; + memory_view m_view; + u8 m_rom_bank; +}; + +class a800_rom_corina_sram_device : public a800_rom_corina_device +{ +public: + // construction/destruction + a800_rom_corina_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + +protected: + virtual void device_start() override; + + virtual uint8_t read_view_1(offs_t offset) override; + virtual void write_view_1(offs_t offset, u8 data) override; + +private: + std::vector m_ram; +}; + +DECLARE_DEVICE_TYPE(A800_ROM_CORINA, a800_rom_corina_device) +DECLARE_DEVICE_TYPE(A800_ROM_CORINA_SRAM, a800_rom_corina_sram_device) + +#endif // MAME_BUS_A800_CORINA_H diff --git a/src/devices/bus/a800/maxflash.cpp b/src/devices/bus/a800/maxflash.cpp new file mode 100644 index 00000000000..583f2991570 --- /dev/null +++ b/src/devices/bus/a800/maxflash.cpp @@ -0,0 +1,123 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +/************************************************************************************************** + +Maxflash + +TODO: +- alt flash configs; +- alt buggy revision of 1MB version, with m_bank starting at 0x7f; + +**************************************************************************************************/ + +#include "emu.h" +#include "maxflash.h" + +// device type definition +DEFINE_DEVICE_TYPE(A800_MAXFLASH_128KB, a800_maxflash_128kb_device, "maxflash_128kb", "Atari 8-bit Atarimax Maxflash 128K flash ROM cart") +DEFINE_DEVICE_TYPE(A800_MAXFLASH_1MB, a800_maxflash_1mb_device, "maxflash_1mb", "Atari 8-bit Atarimax Maxflash 1MB flash ROM cart") + +a800_maxflash_128kb_device::a800_maxflash_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_flash(*this, "flash") + , m_bank(0) +{ +} + +a800_maxflash_128kb_device::a800_maxflash_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : a800_maxflash_128kb_device(mconfig, A800_MAXFLASH_128KB, tag, owner, clock) +{ +} + +void a800_maxflash_128kb_device::device_add_mconfig(machine_config &config) +{ + AMD_29F010(config, m_flash); + + // TODO: alt config with Micron M29F010B ($20/$20) +} + +void a800_maxflash_128kb_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_maxflash_128kb_device::device_reset() +{ + // TODO: ugly assignment, and shouldn't happen in device_reset + // TODO: assert against intended size for slot + memcpy(m_flash->base(), m_rom, get_rom_size()); + + // NB: this starts with 0x7f in the older Atarimax 1MB version + m_bank = 0; +} + +void a800_maxflash_128kb_device::cart_map(address_map &map) +{ + map(0x2000, 0x3fff).lrw8( + NAME([this](offs_t offset) { + return m_flash->read((offset & 0x1fff) + (m_bank * 0x2000)); + }), + NAME([this](offs_t offset, u8 data) { + m_flash->write((offset & 0x1fff) + (m_bank * 0x2000), data); + }) + ); +} + +void a800_maxflash_128kb_device::cctl_map(address_map &map) +{ + map(0x00, 0x0f).rw(FUNC(a800_maxflash_128kb_device::rom_bank_r), FUNC(a800_maxflash_128kb_device::rom_bank_w)); + map(0x10, 0x1f).rw(FUNC(a800_maxflash_128kb_device::disable_rom_r), FUNC(a800_maxflash_128kb_device::disable_rom_w)); +} + +uint8_t a800_maxflash_128kb_device::disable_rom_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + rd5_w(0); + + return 0xff; +} + +void a800_maxflash_128kb_device::disable_rom_w(offs_t offset, uint8_t data) +{ + rd5_w(0); +} + +uint8_t a800_maxflash_128kb_device::rom_bank_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + { + rd5_w(1); + m_bank = (offset & m_bank_mask); + } + return 0xff; +} + +void a800_maxflash_128kb_device::rom_bank_w(offs_t offset, uint8_t data) +{ + rd5_w(1); + m_bank = (offset & m_bank_mask); +} + +// 8MB overrides + +a800_maxflash_1mb_device::a800_maxflash_1mb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : a800_maxflash_128kb_device(mconfig, A800_MAXFLASH_1MB, tag, owner, clock) +{ +} + +void a800_maxflash_1mb_device::device_add_mconfig(machine_config &config) +{ + // TODO: AMD_29F040B according to Altirra? + // AMD_29F040 doesn't match 0x100000 size requirement, 'B is still 4 megabits? + // replace it with a suitable flash device for now + INTEL_E28F008SA(config, m_flash); + + // TODO: alt config with Bright BM29F040 ($ad/$40) +} + + +void a800_maxflash_1mb_device::cctl_map(address_map &map) +{ + map(0x00, 0x7f).rw(FUNC(a800_maxflash_1mb_device::rom_bank_r), FUNC(a800_maxflash_1mb_device::rom_bank_w)); + map(0x80, 0xff).rw(FUNC(a800_maxflash_1mb_device::disable_rom_r), FUNC(a800_maxflash_1mb_device::disable_rom_w)); +} diff --git a/src/devices/bus/a800/maxflash.h b/src/devices/bus/a800/maxflash.h new file mode 100644 index 00000000000..63c4843d913 --- /dev/null +++ b/src/devices/bus/a800/maxflash.h @@ -0,0 +1,53 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A800_MAXFLASH_H +#define MAME_BUS_A800_MAXFLASH_H + +#pragma once + +#include "rom.h" +#include "machine/intelfsh.h" + +class a800_maxflash_128kb_device : public a800_rom_device +{ +public: + a800_maxflash_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_maxflash_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } + +protected: + virtual void device_add_mconfig(machine_config &config) override; + + virtual void device_start() override; + virtual void device_reset() override; + + required_device m_flash; + + uint8_t disable_rom_r(offs_t offset); + void disable_rom_w(offs_t offset, uint8_t data); + uint8_t rom_bank_r(offs_t offset); + void rom_bank_w(offs_t offset, uint8_t data); + +private: + int m_bank; +}; + +class a800_maxflash_1mb_device : public a800_maxflash_128kb_device +{ +public: + a800_maxflash_1mb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + virtual void cctl_map(address_map &map) override; + +protected: + virtual void device_add_mconfig(machine_config &config) override; +}; + +DECLARE_DEVICE_TYPE(A800_MAXFLASH_128KB, a800_maxflash_128kb_device) +DECLARE_DEVICE_TYPE(A800_MAXFLASH_1MB, a800_maxflash_1mb_device) + +#endif // MAME_BUS_A800_MAXFLASH_H diff --git a/src/devices/bus/a800/oss.cpp b/src/devices/bus/a800/oss.cpp index f25dfcce130..bd1cf4025a6 100644 --- a/src/devices/bus/a800/oss.cpp +++ b/src/devices/bus/a800/oss.cpp @@ -1,10 +1,17 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli -/*********************************************************************************************************** +// copyright-holders:Fabio Priuli, Angelo Salese +/************************************************************************************************** - A800 ROM cart emulation + "Optimized System Software" OSS ROM cart emulation -***********************************************************************************************************/ +https://en.wikipedia.org/wiki/Optimized_Systems_Software + +Running on similar non-linear but incompatible banking schemes. + +TODO: +- OSS034M doesn't really exist, it's an OSS043M with wrong ROM contents. + +**************************************************************************************************/ #include "emu.h" @@ -15,37 +22,30 @@ // constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(A800_ROM_OSS8K, a800_rom_oss8k_device, "a800_oss8k", "Atari 800 ROM Carts OSS 8K") -DEFINE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss34_device, "a800_034m", "Atari 800 ROM Carts OSS-034M") -DEFINE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss43_device, "a800_043m", "Atari 800 ROM Carts OSS-043M") -DEFINE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss91_device, "a800_m091", "Atari 800 ROM Carts OSS-M091") +DEFINE_DEVICE_TYPE(A800_ROM_OSS8K, a800_rom_oss8k_device, "a800_oss8k", "Atari 8-bit OSS 8K cart") +DEFINE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss034m_device, "a800_034m", "Atari 8-bit OSS-034M cart") +DEFINE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss043m_device, "a800_043m", "Atari 8-bit OSS-043M cart") +DEFINE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss091m_device, "a800_m091", "Atari 8-bit OSS-M091 cart") +/*------------------------------------------------- + + OSS 8K + + This is used by The Writer's Tool only. + + -------------------------------------------------*/ + +a800_rom_oss8k_device::a800_rom_oss8k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_bank(0) +{ +} a800_rom_oss8k_device::a800_rom_oss8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_OSS8K, tag, owner, clock), m_bank(0) + : a800_rom_oss8k_device(mconfig, A800_ROM_OSS8K, tag, owner, clock) { } - -a800_rom_oss34_device::a800_rom_oss34_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_OSS34, tag, owner, clock), m_bank(0) -{ -} - - -a800_rom_oss43_device::a800_rom_oss43_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_OSS43, tag, owner, clock), m_bank(0) -{ -} - - -a800_rom_oss91_device::a800_rom_oss91_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_OSS91, tag, owner, clock), m_bank(0) -{ -} - - - void a800_rom_oss8k_device::device_start() { save_item(NAME(m_bank)); @@ -56,197 +56,200 @@ void a800_rom_oss8k_device::device_reset() m_bank = 0; } - -void a800_rom_oss34_device::device_start() +void a800_rom_oss8k_device::cart_map(address_map &map) { - save_item(NAME(m_bank)); + map(0x2000, 0x2fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank * 0x1000]; }) + ); + map(0x3000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & 0x0fff]; }) + ); } -void a800_rom_oss34_device::device_reset() +/* + * ---- 0--x selects bank 1 + * ---- 1--0 RD5 clear + * ---- 1--1 selects bank 0 + */ +inline void a800_rom_oss8k_device::bank_config_access(offs_t offset) { - m_bank = 1; -} - - -void a800_rom_oss43_device::device_start() -{ - save_item(NAME(m_bank)); -} - -void a800_rom_oss43_device::device_reset() -{ - m_bank = 0; -} - - -void a800_rom_oss91_device::device_start() -{ - save_item(NAME(m_bank)); -} - -void a800_rom_oss91_device::device_reset() -{ - m_bank = 0; -} - - -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ - -/*------------------------------------------------- - - OSS 8K - - This is used by The Writer's Tool only. - - -------------------------------------------------*/ - -uint8_t a800_rom_oss8k_device::read_80xx(offs_t offset) -{ - if (offset >= 0x1000) - return m_rom[offset & 0xfff]; - else - return m_rom[(offset & 0xfff) + (m_bank * 0x1000)]; -} - -void a800_rom_oss8k_device::write_d5xx(offs_t offset, uint8_t data) -{ - switch (offset & 0x09) + if (!(BIT(offset, 3))) { - case 0: - case 1: - m_bank = 1; - break; - case 9: - m_bank = 0; - break; - default: - break; + rd5_w(1); + m_bank = 1; + } + else + { + rd5_w(BIT(offset, 0)); + m_bank = 0; } } +u8 a800_rom_oss8k_device::rom_bank_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + bank_config_access(offset); + return 0xff; +} + +void a800_rom_oss8k_device::rom_bank_w(offs_t offset, u8 data) +{ + bank_config_access(offset); +} + +void a800_rom_oss8k_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).rw(FUNC(a800_rom_oss8k_device::rom_bank_r), FUNC(a800_rom_oss8k_device::rom_bank_w)); +} /*------------------------------------------------- - OSS 034M + OSS 091M - This apparently comes from a dump with the wrong bank order... - investigate whether we should remove it! + Later variant of OSS 8k -------------------------------------------------*/ -uint8_t a800_rom_oss34_device::read_80xx(offs_t offset) +a800_rom_oss091m_device::a800_rom_oss091m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_oss8k_device(mconfig, A800_ROM_OSS91, tag, owner, clock) { - if (offset >= 0x1000) - return m_rom[(offset & 0xfff) + 0x3000]; - else if (m_bank == 3) - return 0xff; - else - return m_rom[(offset & 0xfff) + (m_bank * 0x1000)]; } -void a800_rom_oss34_device::write_d5xx(offs_t offset, uint8_t data) +/* + * ---- 0--0 bank 1 + * ---- 0--1 bank 3 + * ---- 1--0 RD5 clear + * ---- 1--1 bank 2 + */ +inline void a800_rom_oss091m_device::bank_config_access(offs_t offset) { - switch (offset & 0x0f) + const u8 a0 = BIT(offset, 0); + if (!(BIT(offset, 3))) { - case 0: - case 1: - m_bank = 0; - break; - case 2: - case 6: - m_bank = 3; // in this case the ROM gets disabled and 0xff is returned in 0xa000-0xafff - break; - case 3: - case 7: - m_bank = 1; - break; - case 4: - case 5: - m_bank = 2; - break; - default: - break; + rd5_w(1); + m_bank = 1 | (a0 << 1); + } + else + { + rd5_w(a0); + m_bank = 2; } } - /*------------------------------------------------- OSS 043M - Same as above but with correct bank order - -------------------------------------------------*/ -uint8_t a800_rom_oss43_device::read_80xx(offs_t offset) +a800_rom_oss043m_device::a800_rom_oss043m_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_bankdev(*this, "bankdev") + , m_bank_base1(0) + , m_bank_base2(0) { - if (offset >= 0x1000) - return m_rom[(offset & 0xfff) + 0x3000]; - else if (m_bank == 3) - return 0xff; - else - return m_rom[(offset & 0xfff) + (m_bank * 0x1000)]; } -void a800_rom_oss43_device::write_d5xx(offs_t offset, uint8_t data) +a800_rom_oss043m_device::a800_rom_oss043m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_oss043m_device(mconfig, A800_ROM_OSS43, tag, owner, clock) { - switch (offset & 0x0f) - { - case 0: - case 1: - m_bank = 0; - break; - case 2: - case 6: - m_bank = 3; // in this case the ROM gets disabled and 0xff is returned in 0xa000-0xafff - break; - case 3: - case 7: - m_bank = 2; - break; - case 4: - case 5: - m_bank = 1; - break; - default: - break; - } } +void a800_rom_oss043m_device::device_add_mconfig(machine_config &config) +{ + ADDRESS_MAP_BANK(config, m_bankdev).set_map(&a800_rom_oss043m_device::bankdev_map).set_options(ENDIANNESS_LITTLE, 8, 12 + 3, 0x1000); +} + +void a800_rom_oss043m_device::device_start() +{ + m_bank_base1 = 0x2000; + m_bank_base2 = 0x1000; +} + +void a800_rom_oss043m_device::device_reset() +{ + m_bankdev->set_bank(0); + + rd4_w(0); + rd5_w(1); +} + +void a800_rom_oss043m_device::bankdev_map(address_map &map) +{ + map(0x0000, 0x0fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & 0x0fff]; }) + ); + map(0x1000, 0x1fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & 0x0fff] & m_rom[(offset & 0x0fff) | m_bank_base1]; }) + ); + map(0x2000, 0x2fff).mirror(0x4000).lr8( + NAME([]() { return 0xff; }) + ); + map(0x3000, 0x3fff).mirror(0x4000).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank_base1]; }) + ); + map(0x4000, 0x4fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank_base2]; }) + ); + map(0x5000, 0x5fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | m_bank_base1] & m_rom[(offset & 0x0fff) | m_bank_base2]; }) + ); +} + +void a800_rom_oss043m_device::cart_map(address_map &map) +{ + map(0x2000, 0x2fff).m(m_bankdev, FUNC(address_map_bank_device::amap8)); + map(0x3000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x0fff) | 0x3000]; }) + ); +} + +void a800_rom_oss043m_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).rw(FUNC(a800_rom_oss043m_device::rom_bank_r), FUNC(a800_rom_oss043m_device::rom_bank_w)); +} + +/* + * 0000 bank 0 + * 0001 returns AND-ed contents of banks 0 & 2 + * 0x10 returns 0xff to window (i.e. RD5 is still asserted) + * 0x11 bank 2 + * 0100 bank 1 + * 0101 returns AND-ed contents of banks 1 & 2 + * 1000 RD5 clear + */ +inline void a800_rom_oss043m_device::bank_config_access(offs_t offset) +{ + rd5_w(!(BIT(offset, 3))); + m_bankdev->set_bank(offset & 7); +} + +u8 a800_rom_oss043m_device::rom_bank_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + bank_config_access(offset); + return 0xff; +} + +void a800_rom_oss043m_device::rom_bank_w(offs_t offset, u8 data) +{ + bank_config_access(offset); +} /*------------------------------------------------- - OSS M091 - - Simplified banking system which only uses two - address lines (A0 & A3) + OSS 034M (fake) -------------------------------------------------*/ -uint8_t a800_rom_oss91_device::read_80xx(offs_t offset) +a800_rom_oss034m_device::a800_rom_oss034m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_oss043m_device(mconfig, A800_ROM_OSS34, tag, owner, clock) { - if (offset >= 0x1000) - return m_rom[offset & 0xfff]; - else - return m_rom[(offset & 0xfff) + (m_bank * 0x1000)]; } -void a800_rom_oss91_device::write_d5xx(offs_t offset, uint8_t data) +void a800_rom_oss034m_device::device_start() { - switch (offset & 0x09) - { - case 0: - m_bank = 1; - break; - case 1: - m_bank = 3; - break; - case 9: - m_bank = 2; - break; - default: - break; - } + a800_rom_oss043m_device::device_start(); + m_bank_base1 = 0x1000; + m_bank_base2 = 0x2000; } diff --git a/src/devices/bus/a800/oss.h b/src/devices/bus/a800/oss.h index 65527039825..c8511d62abc 100644 --- a/src/devices/bus/a800/oss.h +++ b/src/devices/bus/a800/oss.h @@ -1,99 +1,86 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Fabio Priuli, Angelo Salese #ifndef MAME_BUS_A800_OSS_H #define MAME_BUS_A800_OSS_H #pragma once #include "rom.h" +#include "machine/bankdev.h" -// ======================> a800_rom_oss8k_device - class a800_rom_oss8k_device : public a800_rom_device { public: - // construction/destruction a800_rom_oss8k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + a800_rom_oss8k_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } protected: - // device-level overrides virtual void device_start() override; virtual void device_reset() override; int m_bank; + virtual void bank_config_access(offs_t offset); + u8 rom_bank_r(offs_t offset); + void rom_bank_w(offs_t offset, u8 data); }; -// ======================> a800_rom_oss34_device - -class a800_rom_oss34_device : public a800_rom_device +class a800_rom_oss043m_device : public a800_rom_device { public: - // construction/destruction - a800_rom_oss34_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + a800_rom_oss043m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + a800_rom_oss043m_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } protected: - // device-level overrides virtual void device_start() override; virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; - int m_bank; + void bankdev_map(address_map &map); + void bank_config_access(offs_t offset); + u8 rom_bank_r(offs_t offset); + void rom_bank_w(offs_t offset, u8 data); + + required_device m_bankdev; + + u16 m_bank_base1, m_bank_base2; }; -// ======================> a800_rom_oss43_device - -class a800_rom_oss43_device : public a800_rom_device +class a800_rom_oss034m_device : public a800_rom_oss043m_device { public: - // construction/destruction - a800_rom_oss43_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; + a800_rom_oss034m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: - // device-level overrides virtual void device_start() override; - virtual void device_reset() override; - - int m_bank; }; -// ======================> a800_rom_oss91_device - -class a800_rom_oss91_device : public a800_rom_device +class a800_rom_oss091m_device : public a800_rom_oss8k_device { public: - // construction/destruction - a800_rom_oss91_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; + a800_rom_oss091m_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - int m_bank; + virtual void bank_config_access(offs_t offset) override; }; -// device type definition DECLARE_DEVICE_TYPE(A800_ROM_OSS8K, a800_rom_oss8k_device) -DECLARE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss34_device) -DECLARE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss43_device) -DECLARE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss91_device) +DECLARE_DEVICE_TYPE(A800_ROM_OSS34, a800_rom_oss034m_device) +DECLARE_DEVICE_TYPE(A800_ROM_OSS43, a800_rom_oss043m_device) +DECLARE_DEVICE_TYPE(A800_ROM_OSS91, a800_rom_oss091m_device) #endif // MAME_BUS_A800_OSS_H diff --git a/src/devices/bus/a800/phoenix.cpp b/src/devices/bus/a800/phoenix.cpp new file mode 100644 index 00000000000..5f8e734e88f --- /dev/null +++ b/src/devices/bus/a800/phoenix.cpp @@ -0,0 +1,176 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +/************************************************************************************************** + +Phoenix/Blizzard cart schemes + +RD5 is special here: once disarmed it cannot be armed again from software. + +TODO: +- Reset button optionally located on cart allows RD5 to be rearmed; + +Notes: +- "Blizzard 4KB" note from .car specs suggests being a Phoenix in disguise, + they are definitely a better suit to use the a800_phoenix def rather than blizzard_device + given the RD4 access of latter. +- For "Blizzard 32KB" cfr. ultracart.cpp +- "Phoenix AST2K" is an oddity, according to Kr0tki on AtariAge forums: + "AST 2000 was two cartridges in one - it contained an AST Utility cartridge, + and a cartridge for Turbo 2000 (another turbo system popular in Poland). + The "AST 2000" contained a 16KB ROM and a two-position switch, which allowed to choose between + one of two 8KB banks. [...] the second half (Turbo 2000) [...] contained a capacitor that + automatically switched off the cartridge from memory after a certain time [...]" + https://forums.atariage.com/topic/169199-mess-a800-cartridge-software-list/#comment-2136371 + + + +**************************************************************************************************/ + +#include "emu.h" +#include "phoenix.h" + +DEFINE_DEVICE_TYPE(A800_ROM_PHOENIX, a800_rom_phoenix_device, "a800_phoenix", "Atari 8-bit Phoenix cart") +DEFINE_DEVICE_TYPE(A800_ROM_BLIZZARD_16KB, a800_rom_blizzard_16kb_device, "a800_blizzard", "Atari 8-bit Blizzard 16KB ROM cart") +DEFINE_DEVICE_TYPE(A800_ROM_PHOENIX_AST2K, a800_rom_phoenix_ast2k_device, "a800_phoenix_ast2k", "Atari 8-bit Phoenix AST2K 2-in-1 cart") + +a800_rom_phoenix_device::a800_rom_phoenix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) +{ +} + +a800_rom_phoenix_device::a800_rom_phoenix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_phoenix_device(mconfig, A800_ROM_PHOENIX, tag, owner, clock) +{ +} + +void a800_rom_phoenix_device::device_start() +{ + m_rom_mask = get_rom_size() - 1; +} + +void a800_rom_phoenix_device::device_reset() +{ + +} + +void a800_rom_phoenix_device::cart_map(address_map &map) +{ + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & m_rom_mask)]; }) + ); +} + +u8 a800_rom_phoenix_device::disable_rom_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + rd5_w(0); + + return 0xff; +} + +void a800_rom_phoenix_device::disable_rom_w(offs_t offset, u8 data) +{ + rd5_w(0); +} + +void a800_rom_phoenix_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).rw(FUNC(a800_rom_phoenix_device::disable_rom_r), FUNC(a800_rom_phoenix_device::disable_rom_w)); +} + +/*------------------------------------------------- + + Blizzard 16KB carts + + -------------------------------------------------*/ + +a800_rom_blizzard_16kb_device::a800_rom_blizzard_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_phoenix_device(mconfig, A800_ROM_BLIZZARD_16KB, tag, owner, clock) +{ +} + +void a800_rom_blizzard_16kb_device::device_reset() +{ +} + +void a800_rom_blizzard_16kb_device::cart_map(address_map &map) +{ + map(0x0000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & m_rom_mask)]; }) + ); +} + +u8 a800_rom_blizzard_16kb_device::disable_rom_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + rd_both_w(0); + + return 0xff; +} + +void a800_rom_blizzard_16kb_device::disable_rom_w(offs_t offset, u8 data) +{ + rd_both_w(0); +} + +/*------------------------------------------------- + + Phoenix AST2K variant + + -------------------------------------------------*/ + +a800_rom_phoenix_ast2k_device::a800_rom_phoenix_ast2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_phoenix_device(mconfig, A800_ROM_PHOENIX_AST2K, tag, owner, clock) + , m_dsw(*this, "DSW") + , m_rom_select(0) +{ +} + +static INPUT_PORTS_START(ast2k) + PORT_START("DSW") + // two position switch located on cart + // we default to Turbo 2000 mode since it's a bit more worth in regtest scenarios + PORT_DIPNAME(0x01, 0x01, "Boot mode" ) + PORT_DIPSETTING(0x00, "AST Utility" ) + PORT_DIPSETTING(0x01, "Turbo 2000" ) +INPUT_PORTS_END + +ioport_constructor a800_rom_phoenix_ast2k_device::device_input_ports() const +{ + return INPUT_PORTS_NAME(ast2k); +} + +void a800_rom_phoenix_ast2k_device::device_start() +{ +// a800_rom_phoenix_device::device_start(); + // FIXME: not initing this properly, needs memory_region + m_rom_mask = 0x1fff; + m_rd5_disarm_timer = timer_alloc(FUNC(a800_rom_phoenix_ast2k_device::rd5_disarm_cb), this); + save_item(NAME(m_rom_select)); +} + +void a800_rom_phoenix_ast2k_device::device_reset() +{ + a800_rom_phoenix_device::device_reset(); + + m_rom_select = BIT(m_dsw->read(), 0) << 13; + + // TODO: unknown RD5 disarm time details + // - frame 137 is the first attempt of Turbo 2k software that tries to write to RD5 space; + // - is the disarm mechanic really disabled in AST Utility mode? + // - 4 seconds is a very lax time so that it doesn't backfire in case of atari400 driver timing changes; + m_rd5_disarm_timer->adjust((m_rom_select) ? attotime::from_seconds(4) : attotime::never); +} + +TIMER_CALLBACK_MEMBER(a800_rom_phoenix_ast2k_device::rd5_disarm_cb) +{ + logerror("RD5 disarmed thru timer\n"); + rd5_w(0); +} + +void a800_rom_phoenix_ast2k_device::cart_map(address_map &map) +{ + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & m_rom_mask) | m_rom_select]; }) + ); +} diff --git a/src/devices/bus/a800/phoenix.h b/src/devices/bus/a800/phoenix.h new file mode 100644 index 00000000000..56f790d9061 --- /dev/null +++ b/src/devices/bus/a800/phoenix.h @@ -0,0 +1,70 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A800_PHOENIX_H +#define MAME_BUS_A800_PHOENIX_H + +#pragma once + +#include "rom.h" + +class a800_rom_phoenix_device : public a800_rom_device +{ +public: + a800_rom_phoenix_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_rom_phoenix_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + u32 m_rom_mask; + virtual u8 disable_rom_r(offs_t offset); + virtual void disable_rom_w(offs_t offset, u8 data); +}; + +class a800_rom_blizzard_16kb_device : public a800_rom_phoenix_device +{ +public: + a800_rom_blizzard_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 1); } + +protected: + virtual void device_reset() override; + + virtual u8 disable_rom_r(offs_t offset) override; + virtual void disable_rom_w(offs_t offset, u8 data) override; +}; + +class a800_rom_phoenix_ast2k_device : public a800_rom_phoenix_device +{ + public: + a800_rom_phoenix_ast2k_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + virtual ioport_constructor device_input_ports() const override; + +private: + required_ioport m_dsw; + u32 m_rom_select; + + emu_timer *m_rd5_disarm_timer; + + TIMER_CALLBACK_MEMBER(rd5_disarm_cb); +}; + +DECLARE_DEVICE_TYPE(A800_ROM_PHOENIX, a800_rom_phoenix_device) +DECLARE_DEVICE_TYPE(A800_ROM_BLIZZARD_16KB, a800_rom_blizzard_16kb_device) +DECLARE_DEVICE_TYPE(A800_ROM_PHOENIX_AST2K, a800_rom_phoenix_ast2k_device) + +#endif // MAME_BUS_A800_PHOENIX_H diff --git a/src/devices/bus/a800/rom.cpp b/src/devices/bus/a800/rom.cpp index 4ea7729c909..532a5cf609e 100644 --- a/src/devices/bus/a800/rom.cpp +++ b/src/devices/bus/a800/rom.cpp @@ -1,35 +1,25 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli -/*********************************************************************************************************** +// copyright-holders:Fabio Priuli, Angelo Salese +/************************************************************************************************** - A800/A5200/XEGS ROM cart emulation - - Basic carts work the same (in addition of being mostly compatible) for all these systems - and thus we deal with them in a single file - -***********************************************************************************************************/ + A800/A5200/XEGS ROM base cart emulation +**************************************************************************************************/ #include "emu.h" #include "rom.h" - //------------------------------------------------- // constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(A800_ROM, a800_rom_device, "a800_rom", "Atari 800 ROM Carts") -DEFINE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device, "a800_bbsb", "Atari 800 ROM Carts BBSB") -DEFINE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device, "a800_williams", "Atari 800 64K ROM Carts Williams") -DEFINE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device, "a800_express", "Atari 800 64K ROM Carts Express/Diamond") -DEFINE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device, "a800_turbo", "Atari 800 64K ROM Carts Turbosoft") -DEFINE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device, "a800_tlink2", "Atari 800 64K ROM Cart Telelink II") -DEFINE_DEVICE_TYPE(A800_ROM_MICROCALC, a800_rom_microcalc_device, "a800_sitsa", "Atari 800 64K ROM Carts SITSA MicroCalc") -DEFINE_DEVICE_TYPE(A800_ROM_CORINA, a800_rom_corina_device, "a800_corina", "Atari 800 ROM Carts Corina 1MB Flash ROM") -DEFINE_DEVICE_TYPE(A800_ROM_CORINA_SRAM, a800_rom_corina_sram_device, "a800_corina_sram", "Atari 800 ROM Carts Corina 512KB Flash ROM + 512KB RAM") -DEFINE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device, "a800_xegs", "Atari XEGS 64K ROM Carts") -DEFINE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device, "a5200_16k2c", "Atari 5200 ROM Cart 16K in 2 Chips") -DEFINE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device, "a5200_bbsb", "Atari 5200 ROM Cart BBSB") +DEFINE_DEVICE_TYPE(A800_ROM, a800_rom_device, "a800_rom", "Atari 8-bit ROM cart") +DEFINE_DEVICE_TYPE(A800_ROM_16KB, a800_rom_16kb_device, "a800_rom_16kb", "Atari 8-bit ROM 16kb cart") +DEFINE_DEVICE_TYPE(A800_ROM_RIGHT, a800_rom_right_device, "a800_rom_right","Atari 8-bit ROM Right cart") +DEFINE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device, "a800_xegs", "Atari XEGS 64K cart") + +DEFINE_DEVICE_TYPE(A5200_ROM, a5200_rom_device, "a5200_rom", "Atari 5200 ROM cart") +DEFINE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device, "a5200_16k2c", "Atari 5200 ROM cart 16K in 2 Chips") a800_rom_device::a800_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) @@ -38,90 +28,17 @@ a800_rom_device::a800_rom_device(const machine_config &mconfig, device_type type { } +/*------------------------------------------------- + + Generic left cart 8kb + + -------------------------------------------------*/ + a800_rom_device::a800_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : a800_rom_device(mconfig, A800_ROM, tag, owner, clock) { } - -a800_rom_bbsb_device::a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_BBSB, tag, owner, clock) -{ -} - - - -xegs_rom_device::xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, XEGS_ROM, tag, owner, clock) - , m_bank(0) -{ -} - - -a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_WILLIAMS, tag, owner, clock) - , m_bank(0) -{ -} - - -a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_EXPRESS, tag, owner, clock) - , m_bank(0) -{ -} - - -a800_rom_turbo_device::a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_TURBO, tag, owner, clock) - , m_bank(0) -{ -} - - -a800_rom_telelink2_device::a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_TELELINK2, tag, owner, clock) -{ -} - - -a800_rom_microcalc_device::a800_rom_microcalc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_MICROCALC, tag, owner, clock) - , m_bank(0) -{ -} - -a800_rom_corina_device::a800_rom_corina_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, type, tag, owner, clock) - , m_rom_bank(0) - , m_view_select(0) -{ -} - -a800_rom_corina_device::a800_rom_corina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_CORINA, tag, owner, clock) -{ -} - -a800_rom_corina_sram_device::a800_rom_corina_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_corina_device(mconfig, A800_ROM_CORINA_SRAM, tag, owner, clock) -{ -} - -a5200_rom_2chips_device::a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A5200_ROM_2CHIPS, tag, owner, clock) -{ -} - - -a5200_rom_bbsb_device::a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A5200_ROM_BBSB, tag, owner, clock) -{ -} - - - - void a800_rom_device::device_start() { } @@ -130,18 +47,79 @@ void a800_rom_device::device_reset() { } - -void a800_rom_bbsb_device::device_start() +void a800_rom_device::cart_map(address_map &map) { - save_item(NAME(m_banks)); + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & (m_rom_size - 1)]; }) + ); } -void a800_rom_bbsb_device::device_reset() +/*------------------------------------------------- + + Generic right cart 8kb + + -------------------------------------------------*/ + +a800_rom_right_device::a800_rom_right_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, A800_ROM_RIGHT, tag, owner, clock) { - m_banks[0] = 0; - m_banks[1] = 0; } +void a800_rom_right_device::device_start() +{ +} + +void a800_rom_right_device::device_reset() +{ + rd4_w(1); + rd5_w(0); +} + +void a800_rom_right_device::cart_map(address_map &map) +{ + map(0x0000, 0x1fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & (m_rom_size - 1)]; }) + ); +} + +/*------------------------------------------------- + + Generic 16kb RD4 + RD5 cart + + -------------------------------------------------*/ + +a800_rom_16kb_device::a800_rom_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, A800_ROM_16KB, tag, owner, clock) +{ +} + +void a800_rom_16kb_device::device_start() +{ +} + +void a800_rom_16kb_device::device_reset() +{ + rd_both_w(1); +} + +void a800_rom_16kb_device::cart_map(address_map &map) +{ + map(0x0000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & (m_rom_size - 1)]; }) + ); +} + +/*------------------------------------------------- + + XEGS carts (32K, 64K or 128K) + + -------------------------------------------------*/ + +xegs_rom_device::xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, XEGS_ROM, tag, owner, clock) + , m_bank(0) +{ +} void xegs_rom_device::device_start() { @@ -150,362 +128,29 @@ void xegs_rom_device::device_start() void xegs_rom_device::device_reset() { + // TODO: random m_bank = 0; } - -void a800_rom_williams_device::device_start() +// RD5 always maps to the last bank +void xegs_rom_device::cart_map(address_map &map) { - save_item(NAME(m_bank)); + map(0x0000, 0x1fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; }) + ); + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank_mask * 0x2000)]; }) + ); } -void a800_rom_williams_device::device_reset() +void xegs_rom_device::cctl_map(address_map &map) { - m_bank = 0; + map(0x00, 0xff).lw8( + NAME([this](offs_t offset, u8 data) { m_bank = data & m_bank_mask; }) + ); } -void a800_rom_express_device::device_start() -{ - save_item(NAME(m_bank)); -} - -void a800_rom_express_device::device_reset() -{ - m_bank = 0; -} - - -void a800_rom_turbo_device::device_start() -{ - save_item(NAME(m_bank)); -} - -void a800_rom_turbo_device::device_reset() -{ - m_bank = 0; -} - - -void a800_rom_microcalc_device::device_start() -{ - save_item(NAME(m_bank)); -} - -void a800_rom_microcalc_device::device_reset() -{ - m_bank = 0; -} - - -void a800_rom_corina_device::device_start() -{ - save_item(NAME(m_rom_bank)); - save_item(NAME(m_view_select)); -} - -void a800_rom_corina_device::device_reset() -{ - m_rom_bank = 0; - m_view_select = 0; -} - - -void a5200_rom_bbsb_device::device_start() -{ - save_item(NAME(m_banks)); -} - -void a5200_rom_bbsb_device::device_reset() -{ - m_banks[0] = 0; - m_banks[1] = 0; -} - - - -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ - -/*------------------------------------------------- - - Carts with no bankswitch (8K, 16K) - - The cart accessors are mapped in the correct - range at driver start - - -------------------------------------------------*/ - -uint8_t a800_rom_device::read_80xx(offs_t offset) -{ - return m_rom[offset & (m_rom_size - 1)]; -} - - - -/*------------------------------------------------- - - Bounty Bob Strikes Back! cart (40K) - - Area 0xa000-0xbfff always point to last 8K bank - Areas 0x8000-0x8fff and 0x9000-0x9fff are - separate banks of 4K mapped either in the first - 16K chunk or in the second 16K chunk - Bankswitch is controlled by data written in - 0x8000-0x8fff and 0x9000-0x9fff respectively - - -------------------------------------------------*/ - -uint8_t a800_rom_bbsb_device::read_80xx(offs_t offset) -{ - if ((offset & 0x2000) == 0 && !machine().side_effects_disabled()) - { - uint16_t addr = offset & 0xfff; - - if (addr >= 0xff6 && addr <= 0xff9) - m_banks[BIT(offset, 12)] = (addr - 0xff6); - } - - if (offset < 0x1000) - return m_rom[(offset & 0xfff) + (m_banks[0] * 0x1000) + 0]; - else if (offset < 0x2000) - return m_rom[(offset & 0xfff) + (m_banks[1] * 0x1000) + 0x4000]; - else - return m_rom[(offset & 0x1fff) + 0x8000]; -} - -void a800_rom_bbsb_device::write_80xx(offs_t offset, uint8_t data) -{ - uint16_t addr = offset & 0xfff; - if (addr >= 0xff6 && addr <= 0xff9) - m_banks[BIT(offset, 12)] = (addr - 0xff6); -} - -/*------------------------------------------------- - - XEGS carts (32K, 64K or 128K) - - Bankswitch is controlled by data written in - 0xd500-0xd5ff - - -------------------------------------------------*/ - -uint8_t xegs_rom_device::read_80xx(offs_t offset) -{ - if (offset < 0x2000) - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; - else - return m_rom[(offset & 0x1fff) + (m_bank_mask * 0x2000)]; // always last 8K bank - -} - -void xegs_rom_device::write_d5xx(offs_t offset, uint8_t data) -{ - m_bank = data & m_bank_mask; -} - - -/*------------------------------------------------- - - Williams 64K - - The rom is accessed in 8K chunks at 0xa000-0xbfff - Bankswitch is controlled by writing to 7 diff - offsets (their location varies with the cart type): - offs 0 points to bank 0, offs 1 points to bank 1, - and so on... the rom can be disabled by writing to - the offsets 0x8-0xf of the same range as the bankswitch - - -------------------------------------------------*/ - -uint8_t a800_rom_williams_device::read_80xx(offs_t offset) -{ - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; -} - -void a800_rom_williams_device::write_d5xx(offs_t offset, uint8_t data) -{ - m_bank = (offset & 0x07); -} - -/*------------------------------------------------- - - Express 64K / Diamond 64K carts - - The rom is accessed in 8K chunks at 0xa000-0xbfff - Bankswitch is the same as above, but writes trigger - banks in reverse order: offs 7 points to bank 0, offs 6 - points to bank 1, and so on... the rom can be disabled - by writing to the offsets 0x8-0xf of the same range - as the bankswitch - - -------------------------------------------------*/ - -uint8_t a800_rom_express_device::read_80xx(offs_t offset) -{ - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; -} - -void a800_rom_express_device::write_d5xx(offs_t offset, uint8_t data) -{ - m_bank = (offset ^ 0x07) & 0x0f; -} - - -/*------------------------------------------------- - - Turbosoft 64K / 128K - - - -------------------------------------------------*/ - -uint8_t a800_rom_turbo_device::read_80xx(offs_t offset) -{ - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; -} - -void a800_rom_turbo_device::write_d5xx(offs_t offset, uint8_t data) -{ - m_bank = offset & m_bank_mask; -} - - -/*------------------------------------------------- - - Telelink II - - - -------------------------------------------------*/ - -uint8_t a800_rom_telelink2_device::read_80xx(offs_t offset) -{ - if (offset >= 0x2000) - return m_rom[offset & 0x1fff]; - if (offset >= 0x1000 && offset < 0x1100) - return m_nvram[offset & 0xff]; - - return 0xff; -} - -void a800_rom_telelink2_device::write_80xx(offs_t offset, uint8_t data) -{ - m_nvram[offset & 0xff] = data | 0xf0; // low 4bits only -} - -uint8_t a800_rom_telelink2_device::read_d5xx(offs_t offset) -{ - // this should affect NVRAM enable / save - return 0xff; -} - -void a800_rom_telelink2_device::write_d5xx(offs_t offset, uint8_t data) -{ - // this should affect NVRAM enable / save -} - - - -/*------------------------------------------------- - - SITSA Microcalc - - - -------------------------------------------------*/ - -uint8_t a800_rom_microcalc_device::read_80xx(offs_t offset) -{ - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; -} - -void a800_rom_microcalc_device::write_d5xx(offs_t offset, uint8_t data) -{ - m_bank = data; -} - -/*------------------------------------------------- - - Corina - - Comes in two configs: - - 1MB Flash ROM (yakungfu) - - 512KB Flash ROM + 512KB SRAM (bombjake) - - Both contains 8KB NVRAM - -------------------------------------------------*/ - -uint8_t a800_rom_corina_device::read_view_1(offs_t offset) -{ - return m_rom[(offset & 0x3fff) + (m_rom_bank * 0x4000) + 0x80000]; -} - -void a800_rom_corina_device::write_view_1(offs_t offset, u8 data) -{ -} - -uint8_t a800_rom_corina_sram_device::read_view_1(offs_t offset) -{ - return m_ram[(offset & 0x3fff) + (m_rom_bank * 0x4000)]; -} - -void a800_rom_corina_sram_device::write_view_1(offs_t offset, u8 data) -{ - m_ram[(offset & 0x3fff) + (m_rom_bank * 0x4000)] = data; -} - -uint8_t a800_rom_corina_device::read_80xx(offs_t offset) -{ - switch( m_view_select ) - { - case 0: - return m_rom[(offset & 0x3fff) + (m_rom_bank * 0x4000)]; - case 1: - return read_view_1(offset); - case 2: - return m_nvram[offset & 0x1fff]; - } - - logerror("view select R=3 [%04x]\n", offset); - return 0xff; -} - -void a800_rom_corina_device::write_80xx(offs_t offset, uint8_t data) -{ - switch( m_view_select ) - { - case 1: - write_view_1(offset, data); - return; - case 2: - m_nvram[offset & 0x1fff] = data; - return; - } - // view 0: flash ROM commands? - // TODO: identify - logerror("view select W=%d [%04x, %02x] -> %02x\n", m_view_select, offset, m_rom_bank, data); -} - -/* - * 0--- ---- enable Corina window - * 1--- ---- disable Corina and select main unit 8000-bfff window instead - * -xx- ---- view select - * -00- ---- first half of ROM - * -01- ---- second half of ROM or RAM (^ depending on PCB config) - * -10- ---- NVRAM - * -11- ---- - * ---x xxxx ROM/RAM lower bank value, - * ignored if view select is not in ROM/RAM mode - * or Corina window is disabled - */ -void a800_rom_corina_device::write_d5xx(offs_t offset, uint8_t data) -{ - m_rom_bank = data & 0x1f; - m_view_select = (data & 0x60) >> 5; - // TODO: bit 7, currently handled in a400_state -} - - - // Atari 5200 @@ -517,6 +162,28 @@ void a800_rom_corina_device::write_d5xx(offs_t offset, uint8_t data) -------------------------------------------------*/ +a5200_rom_device::a5200_rom_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_a5200_cart_interface( mconfig, *this ) +{ +} + +a5200_rom_device::a5200_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a5200_rom_device(mconfig, A5200_ROM, tag, owner, clock) +{ +} + +void a5200_rom_device::cart_map(address_map &map) +{ + map(0x0000, 0x7fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & (m_rom_size - 1))]; }) + ); +} + +void a5200_rom_device::device_start() +{ +} + /*------------------------------------------------- Carts with 2x8K (16K) with A13 line not connected @@ -527,52 +194,17 @@ void a800_rom_corina_device::write_d5xx(offs_t offset, uint8_t data) -------------------------------------------------*/ -uint8_t a5200_rom_2chips_device::read_80xx(offs_t offset) +a5200_rom_2chips_device::a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, A5200_ROM_2CHIPS, tag, owner, clock) { - if (offset < 0x4000) - return m_rom[offset & 0x1fff]; - else - return m_rom[(offset & 0x1fff) + 0x2000]; } - -/*------------------------------------------------- - - Bounty Bob Strikes Back! cart (40K) - - Similar to the A800 version, but: - Area 0x8000-0xbfff always point to last 8K bank - (repeated twice) - Areas 0x4000-0x4fff and 0x5000-0x5fff are - separate banks of 4K mapped either in the first - 16K chunk or in the second 16K chunk - Bankswitch is controlled by data written in - 0x4000-0x4fff and 0x5000-0x5fff respectively - - -------------------------------------------------*/ - -uint8_t a5200_rom_bbsb_device::read_80xx(offs_t offset) +void a5200_rom_2chips_device::cart_map(address_map &map) { - if ((offset & 0xe000) == 0 && !machine().side_effects_disabled()) - { - uint16_t addr = offset & 0xfff; - if (addr >= 0xff6 && addr <= 0xff9) - m_banks[BIT(offset, 12)] = (addr - 0xff6); - } - - if (offset < 0x1000) - return m_rom[(offset & 0xfff) + (m_banks[0] * 0x1000) + 0x2000]; - else if (offset < 0x2000) - return m_rom[(offset & 0xfff) + (m_banks[1] * 0x1000) + 0x6000]; - else if (offset >= 0x4000) - return m_rom[(offset & 0x1fff) + 0x0000]; - else - return 0; -} - -void a5200_rom_bbsb_device::write_80xx(offs_t offset, uint8_t data) -{ - uint16_t addr = offset & 0xfff; - if (addr >= 0xff6 && addr <= 0xff9) - m_banks[BIT(offset, 12)] = (addr - 0xff6); + map(0x0000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & 0x1fff]; }) + ); + map(0x4000, 0x7fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + 0x2000]; }) + ); } diff --git a/src/devices/bus/a800/rom.h b/src/devices/bus/a800/rom.h index 759cb5a7854..320dc5bb2f5 100644 --- a/src/devices/bus/a800/rom.h +++ b/src/devices/bus/a800/rom.h @@ -1,268 +1,102 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Fabio Priuli, Angelo Salese + #ifndef MAME_BUS_A800_ROM_H #define MAME_BUS_A800_ROM_H #pragma once #include "a800_slot.h" +#include "machine/nvram.h" -// ======================> a800_rom_device - class a800_rom_device : public device_t, public device_a800_cart_interface { public: - // construction/destruction a800_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; + virtual void cart_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } protected: a800_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - // device-level overrides virtual void device_start() override; virtual void device_reset() override; }; - -// ======================> a800_rom_bbsb_device - -class a800_rom_bbsb_device : public a800_rom_device +class a800_rom_right_device : public a800_rom_device { public: - // construction/destruction - a800_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + a800_rom_right_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_80xx(offs_t offset, uint8_t data) override; + virtual void cart_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 0); } protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - int m_banks[2]; -}; - - -// ======================> a800_rom_williams_device - -class a800_rom_williams_device : public a800_rom_device -{ -public: - // construction/destruction - a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - int m_bank; -}; - - -// ======================> a800_rom_express_device - -class a800_rom_express_device : public a800_rom_device -{ -public: - // construction/destruction - a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - int m_bank; -}; - - -// ======================> a800_rom_blizzard_device - -class a800_rom_blizzard_device : public a800_rom_device -{ -public: - // construction/destruction - a800_rom_blizzard_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - -protected: - // device-level overrides virtual void device_start() override; virtual void device_reset() override; }; - -// ======================> a800_rom_turbo_device - -class a800_rom_turbo_device : public a800_rom_device +class a800_rom_16kb_device : public a800_rom_device { public: - // construction/destruction - a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + a800_rom_16kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; + virtual void cart_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 1); } protected: - // device-level overrides virtual void device_start() override; virtual void device_reset() override; - - int m_bank; }; -// ======================> a800_rom_telelink2_device - -class a800_rom_telelink2_device : public a800_rom_device -{ -public: - // construction/destruction - a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_80xx(offs_t offset, uint8_t data) override; - virtual uint8_t read_d5xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; -}; - - -// ======================> a800_rom_microcalc_device - -class a800_rom_microcalc_device : public a800_rom_device -{ -public: - // construction/destruction - a800_rom_microcalc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - int m_bank; -}; - -// ======================> a800_rom_corina_device - -class a800_rom_corina_device : public a800_rom_device -{ -public: - // construction/destruction - a800_rom_corina_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); - a800_rom_corina_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_80xx(offs_t offset, uint8_t data) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - virtual uint8_t read_view_1(offs_t offset); - virtual void write_view_1(offs_t offset, u8 data); - - u8 m_rom_bank; - u8 m_view_select; -}; - -class a800_rom_corina_sram_device : public a800_rom_corina_device -{ -public: - // construction/destruction - a800_rom_corina_sram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - -protected: - - virtual uint8_t read_view_1(offs_t offset) override; - virtual void write_view_1(offs_t offset, u8 data) override; -}; - -// ======================> xegs_rom_device - class xegs_rom_device : public a800_rom_device { public: - // construction/destruction xegs_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - // device-level overrides + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 1); } + +protected: virtual void device_start() override; virtual void device_reset() override; - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; - -protected: int m_bank; }; +class a5200_rom_device : public device_t, + public device_a5200_cart_interface +{ +public: + a5200_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); -// ======================> a5200_rom_2chips_device + virtual void cart_map(address_map &map) override; + +protected: + a5200_rom_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + + virtual void device_start() override; +}; class a5200_rom_2chips_device : public a800_rom_device { public: - // construction/destruction a5200_rom_2chips_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; + virtual void cart_map(address_map &map) override; }; - -// ======================> a5200_rom_bbsb_device - -class a5200_rom_bbsb_device : public a800_rom_device -{ -public: - // construction/destruction - a5200_rom_bbsb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_80xx(offs_t offset, uint8_t data) override; - -protected: - // device-level overrides - virtual void device_start() override; - virtual void device_reset() override; - - int m_banks[2]; -}; - - - -// device type definition DECLARE_DEVICE_TYPE(A800_ROM, a800_rom_device) -DECLARE_DEVICE_TYPE(A800_ROM_BBSB, a800_rom_bbsb_device) -DECLARE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device) -DECLARE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device) -DECLARE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device) -DECLARE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device) -DECLARE_DEVICE_TYPE(A800_ROM_MICROCALC, a800_rom_microcalc_device) -DECLARE_DEVICE_TYPE(A800_ROM_CORINA, a800_rom_corina_device) -DECLARE_DEVICE_TYPE(A800_ROM_CORINA_SRAM, a800_rom_corina_sram_device) +DECLARE_DEVICE_TYPE(A800_ROM_RIGHT, a800_rom_right_device) +DECLARE_DEVICE_TYPE(A800_ROM_16KB, a800_rom_16kb_device) DECLARE_DEVICE_TYPE(XEGS_ROM, xegs_rom_device) +DECLARE_DEVICE_TYPE(A5200_ROM, a5200_rom_device) DECLARE_DEVICE_TYPE(A5200_ROM_2CHIPS, a5200_rom_2chips_device) -DECLARE_DEVICE_TYPE(A5200_ROM_BBSB, a5200_rom_bbsb_device) #endif // MAME_BUS_A800_ROM_H diff --git a/src/devices/bus/a800/rtime8.cpp b/src/devices/bus/a800/rtime8.cpp index d65a5d6dde2..88f133941b6 100644 --- a/src/devices/bus/a800/rtime8.cpp +++ b/src/devices/bus/a800/rtime8.cpp @@ -6,8 +6,7 @@ The circuitry in this clock cartridge is very simple, containing the RTC itself, oscillator and battery, and a 74HCT138 to decode the $D5B8-$D5BF address range from the /CCTL and A7-A3 pins. No ROM - is included; however, the cartridge can be placed in the (currently unemulated) passthrough slot of the - SpartaDOS X cartridge. + is included; the cartridge can be placed in the passthrough slot of the SpartaDOS X cartridge. ***********************************************************************************************************/ @@ -51,20 +50,11 @@ void a800_rtime8_device::device_start() // read_d5xx - handle reads from $D500-$D5FF //------------------------------------------------- -u8 a800_rtime8_device::read_d5xx(offs_t offset) +// TODO: 4-bit access, D7-D4 returns open bus +void a800_rtime8_device::cctl_map(address_map &map) { - if ((offset & 0xf8) == 0xb8) - return m_rtc->read(); // TODO: D7-D4 is open bus, in case this matters - else - return 0xff; -} - -//------------------------------------------------- -// write_d5xx - handle writes to $D500-$D5FF -//------------------------------------------------- - -void a800_rtime8_device::write_d5xx(offs_t offset, u8 data) -{ - if ((offset & 0xf8) == 0xb8) - m_rtc->write(data & 0x0f); + map(0xb8, 0xbf).lrw8( + NAME([this](offs_t offset) { return m_rtc->read() | 0xf0; }), + NAME([this](offs_t offset, u8 data) { m_rtc->write(data & 0x0f); }) + ); } diff --git a/src/devices/bus/a800/rtime8.h b/src/devices/bus/a800/rtime8.h index 713c3c9ef72..ba37059c705 100644 --- a/src/devices/bus/a800/rtime8.h +++ b/src/devices/bus/a800/rtime8.h @@ -15,23 +15,18 @@ class a800_rtime8_device : public device_t, public device_a800_cart_interface { public: - // construction/destruction a800_rtime8_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + virtual void cctl_map(address_map &map) override; + protected: - // device-level overrides virtual void device_add_mconfig(machine_config &config) override; virtual void device_start() override; - // device_a800_cart_interface overrides - virtual u8 read_d5xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, u8 data) override; - private: required_device m_rtc; }; -// device type declaration DECLARE_DEVICE_TYPE(A800_RTIME8, a800_rtime8_device) #endif // MAME_BUS_A800_RTIME8_H diff --git a/src/devices/bus/a800/sic.cpp b/src/devices/bus/a800/sic.cpp new file mode 100644 index 00000000000..fa5aaadb802 --- /dev/null +++ b/src/devices/bus/a800/sic.cpp @@ -0,0 +1,114 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +/************************************************************************************************** + +SIC! "Super Inexpensive Cartridge!" + +TODO: +- Unknown flash types used, Altirra just observed a Winbond 29C020; +- Customizable Jumper/switch handling for pin signals; + +**************************************************************************************************/ + +#include "emu.h" +#include "sic.h" + +// device type definition +DEFINE_DEVICE_TYPE(A800_SIC_128KB, a800_sic_128kb_device, "a800_siccart_128kb", "Atari 8-bit SIC! 128KB flash ROM cart") +DEFINE_DEVICE_TYPE(A800_SIC_256KB, a800_sic_256kb_device, "a800_siccart_256kb", "Atari 8-bit SIC! 256KB flash ROM cart") +DEFINE_DEVICE_TYPE(A800_SIC_512KB, a800_sic_512kb_device, "a800_siccart_512kb", "Atari 8-bit SIC! 512KB flash ROM cart") + +a800_sic_128kb_device::a800_sic_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_flash(*this, "flash") + , m_bank(0) + , m_write_protect(true) +{ +} + +a800_sic_128kb_device::a800_sic_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : a800_sic_128kb_device(mconfig, A800_SIC_128KB, tag, owner, clock) +{ +} + +void a800_sic_128kb_device::device_add_mconfig(machine_config &config) +{ + AMD_29F010(config, m_flash); +} + +void a800_sic_128kb_device::device_start() +{ + save_item(NAME(m_bank)); + save_item(NAME(m_write_protect)); +} + +void a800_sic_128kb_device::device_reset() +{ + // TODO: ugly assignment, and shouldn't happen in device_reset + // TODO: assert against intended size for slot + memcpy(m_flash->base(), m_rom, get_rom_size()); + m_bank_mask = (get_rom_size() / 0x4000) - 1; + + // value of 0 for config_bank_w confirmed + m_bank = 0; + m_write_protect = true; +} + +// SIC! maps rd4 and rd5 linearly +// so that 0x8000 maps to 0 and 0xa000 to 0x2000 +u8 a800_sic_128kb_device::read(offs_t offset) +{ + return m_flash->read((offset & 0x3fff) | (m_bank * 0x4000)); +} + +void a800_sic_128kb_device::write(offs_t offset, u8 data) +{ + if (!m_write_protect) + m_flash->write((offset & 0x3fff) | (m_bank * 0x4000), data); +} + +void a800_sic_128kb_device::cart_map(address_map &map) +{ + map(0x0000, 0x3fff).rw(FUNC(a800_sic_128kb_device::read), FUNC(a800_sic_128kb_device::write)); +} + +/* + * 1--- ---- enable flash write + * -1-- ---- RD4 enable + * --0- ---- RD5 enable + * ---x xxxx ROM bank, where upper bits are unused for 128KB and 256KB versions + */ +void a800_sic_128kb_device::config_bank_w(offs_t offset, u8 data) +{ + m_bank = (data & m_bank_mask); + rd4_w(BIT(data, 5)); + rd5_w(!(BIT(data, 6))); + m_write_protect = !(BIT(data, 7)); +} + +void a800_sic_128kb_device::cctl_map(address_map &map) +{ + map(0x00, 0x1f).w(FUNC(a800_sic_128kb_device::config_bank_w)); +} + +// 256/512KB variants + +a800_sic_256kb_device::a800_sic_256kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : a800_sic_128kb_device(mconfig, A800_SIC_256KB, tag, owner, clock) +{ +} + +void a800_sic_256kb_device::device_add_mconfig(machine_config &config) +{ + AMD_29LV200T(config, m_flash); +} + +a800_sic_512kb_device::a800_sic_512kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : a800_sic_128kb_device(mconfig, A800_SIC_512KB, tag, owner, clock) +{ +} + +void a800_sic_512kb_device::device_add_mconfig(machine_config &config) +{ + AMD_29F040(config, m_flash); +} diff --git a/src/devices/bus/a800/sic.h b/src/devices/bus/a800/sic.h new file mode 100644 index 00000000000..52dba880bae --- /dev/null +++ b/src/devices/bus/a800/sic.h @@ -0,0 +1,64 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A800_SIC_H +#define MAME_BUS_A800_SIC_H + +#pragma once + +#include "rom.h" +#include "machine/intelfsh.h" + +class a800_sic_128kb_device : public a800_rom_device +{ +public: + a800_sic_128kb_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_sic_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } + +protected: + virtual void device_add_mconfig(machine_config &config) override; + + virtual void device_start() override; + virtual void device_reset() override; + + required_device m_flash; + +private: + int m_bank; + bool m_write_protect; + int m_bank_mask; + + u8 read(offs_t offset); + void write(offs_t offset, u8 data); + + u8 config_bank_r(offs_t offset); + void config_bank_w(offs_t offset, u8 data); +}; + +class a800_sic_256kb_device : public a800_sic_128kb_device +{ +public: + a800_sic_256kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual void device_add_mconfig(machine_config &config) override; +}; + +class a800_sic_512kb_device : public a800_sic_128kb_device +{ +public: + a800_sic_512kb_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + +protected: + virtual void device_add_mconfig(machine_config &config) override; +}; + +DECLARE_DEVICE_TYPE(A800_SIC_128KB, a800_sic_128kb_device) +DECLARE_DEVICE_TYPE(A800_SIC_256KB, a800_sic_256kb_device) +DECLARE_DEVICE_TYPE(A800_SIC_512KB, a800_sic_512kb_device) + +#endif // MAME_BUS_A800_SIC_H diff --git a/src/devices/bus/a800/sparta.cpp b/src/devices/bus/a800/sparta.cpp index 8b8242d8dad..f4e6e69e25f 100644 --- a/src/devices/bus/a800/sparta.cpp +++ b/src/devices/bus/a800/sparta.cpp @@ -1,73 +1,189 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli -/*********************************************************************************************************** +// copyright-holders:Fabio Priuli, Angelo Salese +/************************************************************************************************** - A800 SpartaDOS cart emulation +SpartaDOS X (SDX) cart emulation -***********************************************************************************************************/ +https://sdx.atari8.info/index.php?show=en_introduction +SDX 128KB a newer format used by the 200x releases: adds an extra bank access to $d5f0-$d5f7. +Should mirror $e8-$ef to $fx by logic. + +**************************************************************************************************/ #include "emu.h" #include "sparta.h" - +#include "a800_carts.h" //------------------------------------------------- // constructor //------------------------------------------------- -DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device, "a800_sparta", "Atari 800 SpartaDOS ROM Carts") +DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device, "a800_sparta", "Atari 8-bit SpartaDOS X cart") +DEFINE_DEVICE_TYPE(A800_ROM_SPARTADOS_128KB, a800_rom_spartados_128kb_device, "a800_sparta_128kb", "Atari 8-bit SpartaDOS X 128KB cart") +a800_rom_spartados_device::a800_rom_spartados_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_bank(0) + , m_subcart(*this, "subcart") + , m_cart_view(*this, "cart_view") +{ + +} a800_rom_spartados_device::a800_rom_spartados_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : a800_rom_device(mconfig, A800_ROM_SPARTADOS, tag, owner, clock) - , m_bank(0) - , m_subslot_enabled(0) + : a800_rom_spartados_device(mconfig, A800_ROM_SPARTADOS, tag, owner, clock) { } +static void spartados_carts(device_slot_interface &device) +{ + // NB: game carts will usually override SDX boot, meaning that they aren't all that useful to hook up here. + // also a SDX attached to another SDX just produces a black screen. + // we just hook them all up for the sake of completeness. + a800_left(device); +} +void a800_rom_spartados_device::subcart_rd4_w(int state) +{ + m_subcart_rd4_enabled = state; + if (m_subcart_enabled) + { + rd4_w(m_subcart_rd4_enabled); + rd5_w(m_subcart_rd5_enabled); + } +} + +void a800_rom_spartados_device::subcart_rd5_w(int state) +{ + m_subcart_rd5_enabled = state; + if (m_subcart_enabled) + { + rd4_w(m_subcart_rd4_enabled); + rd5_w(m_subcart_rd5_enabled); + } +} + +void a800_rom_spartados_device::device_add_mconfig(machine_config &config) +{ + A800_CART_SLOT(config, m_subcart, spartados_carts, nullptr); + m_subcart->rd4_callback().set(FUNC(a800_rom_spartados_device::subcart_rd4_w)); + m_subcart->rd5_callback().set(FUNC(a800_rom_spartados_device::subcart_rd5_w)); +} void a800_rom_spartados_device::device_start() { save_item(NAME(m_bank)); - save_item(NAME(m_subslot_enabled)); + save_item(NAME(m_subcart_enabled)); } void a800_rom_spartados_device::device_reset() { - m_bank = 0; - m_subslot_enabled = 0; + m_bank = 7; + m_subcart_enabled = false; + if (!m_subcart->exists()) + m_subcart_rd4_enabled = m_subcart_rd5_enabled = 0; + else + std::tie(m_subcart_rd4_enabled, m_subcart_rd5_enabled) = m_subcart->get_initial_rd_state(); + + m_cart_view.select(0); } -/*------------------------------------------------- - mapper specific handlers - -------------------------------------------------*/ +void a800_rom_spartados_device::cart_map(address_map &map) +{ + map(0x0000, 0x3fff).view(m_cart_view); + m_cart_view[0](0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; }) + ); + m_cart_view[1](0x0000, 0x1fff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cart<0>), FUNC(a800_cart_slot_device::write_cart<0>)); + m_cart_view[1](0x2000, 0x3fff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cart<1>), FUNC(a800_cart_slot_device::write_cart<1>)); +} + +void a800_rom_spartados_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).rw(m_subcart, FUNC(a800_cart_slot_device::read_cctl), FUNC(a800_cart_slot_device::write_cctl)); + map(0xe0, 0xe7).rw(FUNC(a800_rom_spartados_device::rom_bank_r), FUNC(a800_rom_spartados_device::rom_bank_w)); + map(0xe8, 0xef).rw(FUNC(a800_rom_spartados_device::subslot_r), FUNC(a800_rom_spartados_device::subslot_w)); +} + +inline void a800_rom_spartados_device::bank_config_access(offs_t offset) +{ + rd4_w(0); + rd5_w(1); + m_cart_view.select(0); + m_bank = ((offset ^ m_bank_mask) & m_bank_mask); + m_subcart_enabled = false; +} + +uint8_t a800_rom_spartados_device::rom_bank_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + bank_config_access(offset); + + return m_subcart->read_cctl(offset | 0xe0); +} + +void a800_rom_spartados_device::rom_bank_w(offs_t offset, uint8_t data) +{ + bank_config_access(offset); + m_subcart->write_cctl(offset | 0xe0, data); +} + +inline void a800_rom_spartados_device::subslot_config_access(offs_t offset) +{ + if (!BIT(offset, 2)) + { + m_subcart_enabled = true; + rd4_w(m_subcart_rd4_enabled); + rd5_w(m_subcart_rd5_enabled); + m_cart_view.select(1); + } + else + { + m_subcart_enabled = false; + rd4_w(0); + rd5_w(0); + } +} + +u8 a800_rom_spartados_device::subslot_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + subslot_config_access(offset); + + return m_subcart->read_cctl(offset | 0xe8); +} + +void a800_rom_spartados_device::subslot_w(offs_t offset, u8 data) +{ + subslot_config_access(offset); + + return m_subcart->write_cctl(offset | 0xe8, data); +} /*------------------------------------------------- - SpartaDOS 64K carts - - Similar to Express / Diamond carts, because - bankswitch is controlled by writing to 7 diff - offsets in reverse order, but writes to offsets - 0x8-0xf also enable/disable subslot + SpartaDOS 128KB variant -------------------------------------------------*/ -uint8_t a800_rom_spartados_device::read_80xx(offs_t offset) +a800_rom_spartados_128kb_device::a800_rom_spartados_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_spartados_device(mconfig, A800_ROM_SPARTADOS_128KB, tag, owner, clock) { - if (!m_subslot_enabled) - return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; - else - return 0xff; // subslot, currently not implemented } -void a800_rom_spartados_device::write_d5xx(offs_t offset, uint8_t data) +// NB: .select not .mirror, we need the offset to propagate to sub cart cctl +void a800_rom_spartados_128kb_device::cctl_map(address_map &map) { - if (offset & 0x08) - m_subslot_enabled = !BIT(offset, 2); - else - m_bank = (offset ^ 0x07) & 0x0f; - + a800_rom_spartados_device::cctl_map(map); + map(0xe0, 0xe7).select(0x10).rw(FUNC(a800_rom_spartados_128kb_device::rom_bank_r), FUNC(a800_rom_spartados_128kb_device::rom_bank_w)); + map(0xe8, 0xef).select(0x10).rw(FUNC(a800_rom_spartados_128kb_device::subslot_r), FUNC(a800_rom_spartados_128kb_device::subslot_w)); +} + +inline void a800_rom_spartados_128kb_device::bank_config_access(offs_t offset) +{ + a800_rom_spartados_device::bank_config_access(offset); + const u8 upper_bank = !BIT(offset, 4); + m_bank = ((offset ^ 7) & 7) | (upper_bank << 3); } diff --git a/src/devices/bus/a800/sparta.h b/src/devices/bus/a800/sparta.h index ea211472f31..31c4c439a28 100644 --- a/src/devices/bus/a800/sparta.h +++ b/src/devices/bus/a800/sparta.h @@ -1,36 +1,63 @@ // license:BSD-3-Clause -// copyright-holders:Fabio Priuli +// copyright-holders:Fabio Priuli, Angelo Salese #ifndef MAME_BUS_A800_SPARTA_H #define MAME_BUS_A800_SPARTA_H #pragma once #include "rom.h" - - -// ======================> a800_rom_spartados_device +#include "a800_slot.h" class a800_rom_spartados_device : public a800_rom_device { public: - // construction/destruction + a800_rom_spartados_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); a800_rom_spartados_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); - virtual uint8_t read_80xx(offs_t offset) override; - virtual void write_d5xx(offs_t offset, uint8_t data) override; + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } protected: - // device-level overrides virtual void device_start() override; virtual void device_reset() override; - int m_bank, m_subslot_enabled; + virtual void device_add_mconfig(machine_config &config) override; + + virtual void bank_config_access(offs_t offset); + + int m_bank; + + u8 rom_bank_r(offs_t offset); + void rom_bank_w(offs_t offset, u8 data); + + u8 subslot_r(offs_t offset); + void subslot_w(offs_t offset, u8 data); +private: + required_device m_subcart; + memory_view m_cart_view; + + void subslot_config_access(offs_t offset); + void subcart_rd4_w( int state ); + void subcart_rd5_w( int state ); + + bool m_subcart_enabled; + int m_subcart_rd4_enabled = 0, m_subcart_rd5_enabled = 0; }; +class a800_rom_spartados_128kb_device : public a800_rom_spartados_device +{ +public: + a800_rom_spartados_128kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + virtual void cctl_map(address_map &map) override; -// device type definition -DECLARE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device) +protected: + virtual void bank_config_access(offs_t offset) override; +}; + +DECLARE_DEVICE_TYPE(A800_ROM_SPARTADOS, a800_rom_spartados_device) +DECLARE_DEVICE_TYPE(A800_ROM_SPARTADOS_128KB, a800_rom_spartados_128kb_device) #endif // MAME_BUS_A800_SPARTA_H diff --git a/src/devices/bus/a800/supercharger.cpp b/src/devices/bus/a800/supercharger.cpp new file mode 100644 index 00000000000..88f721dd35f --- /dev/null +++ b/src/devices/bus/a800/supercharger.cpp @@ -0,0 +1,94 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese +// thanks-to: Jindroush, HiassofT +/************************************************************************************************** + +"SuperCharger" + +multiply/divide math unit (unknown 18-pins chip type, scratched on PCB) +used by "Assault Force" floppy disk. +Not to be confused with Starpath SuperCharger, which is for Atari VCS. + +**************************************************************************************************/ + +#include "emu.h" +#include "supercharger.h" + +// device type definition +DEFINE_DEVICE_TYPE(A800_SUPER_CHARGER, a800_supercharger_device, "a800_supercharger", "Atari 8-bit SuperCharger 3D math unit cart") + +a800_supercharger_device::a800_supercharger_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) + : device_t(mconfig, A800_SUPER_CHARGER, tag, owner, clock) + , device_a800_cart_interface(mconfig, *this) + , m_status(0) +{ +} + +void a800_supercharger_device::device_start() +{ + save_pointer(NAME(m_data), 3); + save_item(NAME(m_status)); +} + +void a800_supercharger_device::device_reset() +{ + std::fill(std::begin(m_data), std::end(m_data), 0); + m_status = 1; +} + +void a800_supercharger_device::cctl_map(address_map &map) +{ + map(0x00, 0x02).mirror(0xfc).lrw8( + NAME([this](offs_t offset) { return m_data[offset]; }), + NAME([this](offs_t offset, u8 data) { m_data[offset] = data; }) + ); + map(0x03, 0x03).mirror(0xfc).rw(FUNC(a800_supercharger_device::status_r), FUNC(a800_supercharger_device::command_w)); +} + +/* + * ---- ---x last command status + * (0) valid + * (1) error (division by zero, result == 0 or unsupported command) + */ +u8 a800_supercharger_device::status_r(offs_t offset) +{ + return m_status; +} + +// TODO: not instant +// (program sets four NOPs after each call) +void a800_supercharger_device::command_w(offs_t offset, u8 data) +{ + switch (data) + { + // division + case 1: + { + const u32 numerator = (m_data[1] << 8) | (m_data[2] & 0xff); + const u32 denominator = m_data[0]; + + if (m_data[0] < m_data[1] || denominator == 0) + m_status = 1; + else + { + m_data[1] = (u8)(numerator % denominator); + m_data[2] = (u8)(numerator / denominator); + m_status = 0; + } + break; + } + // multiplication + case 2: + { + const u32 result = m_data[0] * m_data[2]; + + m_data[1] = (u8)(result >> 8); + m_data[2] = (u8)(result & 0xff); + m_status = 0; + break; + } + default: + m_status = 1; + break; + } +} diff --git a/src/devices/bus/a800/supercharger.h b/src/devices/bus/a800/supercharger.h new file mode 100644 index 00000000000..cca2ea30236 --- /dev/null +++ b/src/devices/bus/a800/supercharger.h @@ -0,0 +1,35 @@ +// license: BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_BUS_A800_SUPERCHARGER_H +#define MAME_BUS_A800_SUPERCHARGER_H + +#pragma once + +#include "a800_slot.h" + + +// ======================> a800_rtime8_device + +class a800_supercharger_device : public device_t, + public device_a800_cart_interface +{ +public: + a800_supercharger_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + + virtual void cctl_map(address_map &map) override; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + u8 m_data[3]{}; + u8 m_status; + + u8 status_r(offs_t offset); + void command_w(offs_t offset, u8 data); +}; + +DECLARE_DEVICE_TYPE(A800_SUPER_CHARGER, a800_supercharger_device) + +#endif // MAME_BUS_A800_SUPERCHARGER_H diff --git a/src/devices/bus/a800/telelink2.cpp b/src/devices/bus/a800/telelink2.cpp new file mode 100644 index 00000000000..eb4238258f2 --- /dev/null +++ b/src/devices/bus/a800/telelink2.cpp @@ -0,0 +1,64 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese +/************************************************************************************************** + +Telelink II + +4-bit X2212 NVRAM and other stuff not known at current stage. +RD4 hardwired to +5V + +TODO: +- CCTL mapping details are unknown; +- Requires modem i/f to work; + +**************************************************************************************************/ + +#include "emu.h" +#include "telelink2.h" + +DEFINE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device, "a800_tlink2", "Atari 8-bit Telelink II cart") + + +a800_rom_telelink2_device::a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, A800_ROM_TELELINK2, tag, owner, clock) + , m_nvram(*this, "nvram") +{ +} + +void a800_rom_telelink2_device::device_add_mconfig(machine_config &config) +{ + NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_1); +} + +void a800_rom_telelink2_device::device_start() +{ + const u32 nvram_size = 0x100; + + m_nvram_ptr = std::make_unique(nvram_size); + m_nvram->set_base(m_nvram_ptr.get(), nvram_size); + + save_pointer(NAME(m_nvram_ptr), nvram_size); +} + +void a800_rom_telelink2_device::device_reset() +{ +} + + +void a800_rom_telelink2_device::cart_map(address_map &map) +{ + // 4-bit NVRAM + map(0x1000, 0x10ff).lrw8( + NAME([this](offs_t offset) { return m_nvram_ptr[offset & 0xff]; }), + NAME([this](offs_t offset, u8 data) { m_nvram_ptr[offset & 0xff] = data | 0xf0; }) + ); + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[offset & 0x1fff]; }) + ); +} + +void a800_rom_telelink2_device::cctl_map(address_map &map) +{ +// map(0x01, 0x01) read before reading NVRAM, value discarded +// map(0x02, 0x02) written before writing NVRAM when changing stored information +} diff --git a/src/devices/bus/a800/telelink2.h b/src/devices/bus/a800/telelink2.h new file mode 100644 index 00000000000..a3b30da0a87 --- /dev/null +++ b/src/devices/bus/a800/telelink2.h @@ -0,0 +1,34 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese + +#ifndef MAME_BUS_A800_TELELINK2_H +#define MAME_BUS_A800_TELELINK2_H + +#pragma once + +#include "rom.h" + +class a800_rom_telelink2_device : public a800_rom_device +{ +public: + // construction/destruction + a800_rom_telelink2_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + + // RD4 tied to +5V, assume always enabled + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(1, 1); } + +private: + virtual void device_start() override; + virtual void device_reset() override; + virtual void device_add_mconfig(machine_config &config) override; + + required_device m_nvram; + std::unique_ptr m_nvram_ptr; +}; + +DECLARE_DEVICE_TYPE(A800_ROM_TELELINK2, a800_rom_telelink2_device) + +#endif // MAME_BUS_A800_TELELINK2_H diff --git a/src/devices/bus/a800/ultracart.cpp b/src/devices/bus/a800/ultracart.cpp new file mode 100644 index 00000000000..fa8c4cd2d4c --- /dev/null +++ b/src/devices/bus/a800/ultracart.cpp @@ -0,0 +1,130 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese +/************************************************************************************************** + +Ultracart ROM scheme + +Observed in SITSA MicroCalc SW (Altirra calls it this way), +PCB label pic has clear "ULTRACART" with an unreadable sub-title from available pic +("PIGNY MEXICO"?) +Sports extra SN74LS169BN (synchronous 4-bit up/down binary counter), any access to CCTL +bankswitch to the next index, disarms RD5 after bank 3, re-enables from bank 0 if accessed again. + +"Blizzard 32KB" looks a derived design of Ultracart, it joins a binary counter with RD5 disarm +once it goes past 3rd bank index. + +"aDawliah" scheme is again very similar but without any RD5 disarm (just loops back to index 0) +PCB marking "A-NA0002" + +TODO: +- exact interface with SN74LS169; + +**************************************************************************************************/ + +#include "emu.h" +#include "ultracart.h" + +DEFINE_DEVICE_TYPE(A800_ROM_ULTRACART, a800_rom_ultracart_device, "a800_ultracart", "Atari 8-bit Ultracart \"MicroCalc\" cart") +DEFINE_DEVICE_TYPE(A800_ROM_BLIZZARD_32KB, a800_rom_blizzard_32kb_device, "a800_blizzard_32kb", "Atari 8-bit Blizzard 32KB cart") +DEFINE_DEVICE_TYPE(A800_ROM_ADAWLIAH, a800_rom_adawliah_device, "a800_adawliah", "Atari 8-bit aDawliah 32KB cart") + + +a800_rom_ultracart_device::a800_rom_ultracart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_bank(0) +{ +} + +a800_rom_ultracart_device::a800_rom_ultracart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_ultracart_device(mconfig, A800_ROM_ULTRACART, tag, owner, clock) +{ +} + +void a800_rom_ultracart_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_ultracart_device::device_reset() +{ + m_bank = 0; +} + +void a800_rom_ultracart_device::cart_map(address_map &map) +{ + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; }) + ); +} + +void a800_rom_ultracart_device::cctl_map(address_map &map) +{ + map(0x00, 0xff).rw(FUNC(a800_rom_ultracart_device::config_bank_r), FUNC(a800_rom_ultracart_device::config_bank_w)); +} + +inline void a800_rom_ultracart_device::binary_counter_access() +{ + // TODO: simplification, the real counter has several config options + m_bank = (m_bank + 1) & 0xf; + + if (m_bank & 0xc) + { + rd5_w(0); + m_bank = 0xf; + } + else + rd5_w(1); +} + +u8 a800_rom_ultracart_device::config_bank_r(offs_t offset) +{ + if (!machine().side_effects_disabled()) + binary_counter_access(); + + return 0xff; +} + +void a800_rom_ultracart_device::config_bank_w(offs_t offset, u8 data) +{ + binary_counter_access(); +} + + +/*------------------------------------------------- + + Blizzard 32KB carts + + -------------------------------------------------*/ + +a800_rom_blizzard_32kb_device::a800_rom_blizzard_32kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_ultracart_device(mconfig, A800_ROM_BLIZZARD_32KB, tag, owner, clock) +{ +} + +inline void a800_rom_blizzard_32kb_device::binary_counter_access() +{ + // TODO: simplification, the real counter has several config options + m_bank = (m_bank + 1) & 0xf; + + // as per phoenix carts RD5 can only be re-enabled by restarting the machine + // it's unknown about how the binary counter behaves once this event occurs + if (m_bank & 0xc) + rd5_w(0); +} + +/*------------------------------------------------- + + aDawliah 32KB carts + + -------------------------------------------------*/ + +a800_rom_adawliah_device::a800_rom_adawliah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_ultracart_device(mconfig, A800_ROM_ADAWLIAH, tag, owner, clock) +{ +} + +inline void a800_rom_adawliah_device::binary_counter_access() +{ + // TODO: simplification, the real counter has several config options + m_bank = (m_bank + 1) & 0x3; +} diff --git a/src/devices/bus/a800/ultracart.h b/src/devices/bus/a800/ultracart.h new file mode 100644 index 00000000000..2e5b45d8d4d --- /dev/null +++ b/src/devices/bus/a800/ultracart.h @@ -0,0 +1,55 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese + +#ifndef MAME_BUS_A800_ULTRACART_H +#define MAME_BUS_A800_ULTRACART_H + +#pragma once + +#include "rom.h" + +class a800_rom_ultracart_device : public a800_rom_device +{ +public: + a800_rom_ultracart_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_rom_ultracart_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); } + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + int m_bank; + + virtual void binary_counter_access(); + u8 config_bank_r(offs_t offset); + void config_bank_w(offs_t offset, u8 data); +}; + +class a800_rom_blizzard_32kb_device : public a800_rom_ultracart_device +{ +public: + a800_rom_blizzard_32kb_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void binary_counter_access() override; +}; + +class a800_rom_adawliah_device : public a800_rom_ultracart_device +{ +public: + a800_rom_adawliah_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void binary_counter_access() override; +}; + +DECLARE_DEVICE_TYPE(A800_ROM_ULTRACART, a800_rom_ultracart_device) +DECLARE_DEVICE_TYPE(A800_ROM_BLIZZARD_32KB, a800_rom_blizzard_32kb_device) +DECLARE_DEVICE_TYPE(A800_ROM_ADAWLIAH, a800_rom_adawliah_device) + + +#endif // MAME_BUS_A800_ULTRACART_H diff --git a/src/devices/bus/a800/williams.cpp b/src/devices/bus/a800/williams.cpp new file mode 100644 index 00000000000..83d8edb66a1 --- /dev/null +++ b/src/devices/bus/a800/williams.cpp @@ -0,0 +1,160 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese +/************************************************************************************************** + +Williams cart scheme and variants + +- Regular Williams cart maps ROM bankswitch to $x0 - $x7, RD5 disables with A3. x is mirrored. +- Express carts maps x = $7x, bank map is xor-ed +- Diamond carts maps x = $dx, bank map is xor-ed +- Turbosoft carts raises number of banks to 16, moves RD5 disable to A4 instead of A3 +- All CCTL accesses works both on reading and writing. + +**************************************************************************************************/ + +#include "emu.h" +#include "williams.h" + +DEFINE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device, "a800_williams", "Atari 8-bit Williams cart") +DEFINE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device, "a800_express", "Atari 8-bit Express cart") +DEFINE_DEVICE_TYPE(A800_ROM_DIAMOND, a800_rom_diamond_device, "a800_diamond", "Atari 8-bit Diamond cart") +DEFINE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device, "a800_turbo", "Atari 8-bit Turbosoft 64KB/128KB cart") + +a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_device(mconfig, type, tag, owner, clock) + , m_bank(0) +{ +} + +a800_rom_williams_device::a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_williams_device(mconfig, A800_ROM_WILLIAMS, tag, owner, clock) +{ +} + +void a800_rom_williams_device::device_start() +{ + save_item(NAME(m_bank)); +} + +void a800_rom_williams_device::device_reset() +{ + // turboc1 (at least) reads ROM window without setting bank first, + // any non-zero value will make it to punt + m_bank = 0; +} + +void a800_rom_williams_device::cart_map(address_map &map) +{ + map(0x2000, 0x3fff).lr8( + NAME([this](offs_t offset) { return m_rom[(offset & 0x1fff) + (m_bank * 0x2000)]; }) + ); +} + +void a800_rom_williams_device::cctl_map(address_map &map) +{ + map(0x00, 0x07).mirror(0xf0).rw(FUNC(a800_rom_williams_device::rom_bank_r), FUNC(a800_rom_williams_device::rom_bank_w)); + map(0x08, 0x0f).mirror(0xf0).rw(FUNC(a800_rom_williams_device::disable_rom_r), FUNC(a800_rom_williams_device::disable_rom_w)); +} + +uint8_t a800_rom_williams_device::disable_rom_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + rd5_w(0); + + return 0xff; +} + +void a800_rom_williams_device::disable_rom_w(offs_t offset, uint8_t data) +{ + rd5_w(0); +} + +// m_bank_mask necessary for turbo128 carts +uint8_t a800_rom_williams_device::rom_bank_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + { + rd5_w(1); + m_bank = (offset & m_bank_mask); + } + return 0xff; +} + +void a800_rom_williams_device::rom_bank_w(offs_t offset, uint8_t data) +{ + rd5_w(1); + m_bank = (offset & m_bank_mask); +} + +/*------------------------------------------------- + + Express 64K carts + + -------------------------------------------------*/ + +a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_williams_device(mconfig, type, tag, owner, clock) +{ +} + +a800_rom_express_device::a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_williams_device(mconfig, A800_ROM_EXPRESS, tag, owner, clock) +{ +} + +void a800_rom_express_device::cctl_map(address_map &map) +{ + map(0x70, 0x77).rw(FUNC(a800_rom_express_device::rom_bank_r), FUNC(a800_rom_express_device::rom_bank_w)); + map(0x78, 0x7f).rw(FUNC(a800_rom_express_device::disable_rom_r), FUNC(a800_rom_express_device::disable_rom_w)); +} + +uint8_t a800_rom_express_device::rom_bank_r(offs_t offset) +{ + if(!machine().side_effects_disabled()) + { + rd5_w(1); + m_bank = ((offset ^ m_bank_mask) & m_bank_mask); + } + return 0xff; +} + +void a800_rom_express_device::rom_bank_w(offs_t offset, uint8_t data) +{ + rd5_w(1); + m_bank = ((offset ^ m_bank_mask) & m_bank_mask); +} + +/*------------------------------------------------- + + Diamond 64K carts + + -------------------------------------------------*/ + + +a800_rom_diamond_device::a800_rom_diamond_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_express_device(mconfig, A800_ROM_DIAMOND, tag, owner, clock) +{ +} + +void a800_rom_diamond_device::cctl_map(address_map &map) +{ + map(0xd0, 0xd7).rw(FUNC(a800_rom_diamond_device::rom_bank_r), FUNC(a800_rom_diamond_device::rom_bank_w)); + map(0xd8, 0xdf).rw(FUNC(a800_rom_diamond_device::disable_rom_r), FUNC(a800_rom_diamond_device::disable_rom_w)); +} + +/*------------------------------------------------- + + Turbosoft 64K / 128K + + -------------------------------------------------*/ + +a800_rom_turbo_device::a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : a800_rom_williams_device(mconfig, A800_ROM_TURBO, tag, owner, clock) +{ +} + +void a800_rom_turbo_device::cctl_map(address_map &map) +{ + map(0x00, 0x0f).mirror(0xe0).rw(FUNC(a800_rom_turbo_device::rom_bank_r), FUNC(a800_rom_turbo_device::rom_bank_w)); + map(0x10, 0x1f).mirror(0xe0).rw(FUNC(a800_rom_turbo_device::disable_rom_r), FUNC(a800_rom_turbo_device::disable_rom_w)); +} diff --git a/src/devices/bus/a800/williams.h b/src/devices/bus/a800/williams.h new file mode 100644 index 00000000000..24d8542eb26 --- /dev/null +++ b/src/devices/bus/a800/williams.h @@ -0,0 +1,69 @@ +// license: BSD-3-Clause +// copyright-holders: Fabio Priuli, Angelo Salese + +#ifndef MAME_BUS_A800_WILLIAMS_H +#define MAME_BUS_A800_WILLIAMS_H + +#pragma once + +#include "rom.h" + +class a800_rom_williams_device : public a800_rom_device +{ +public: + a800_rom_williams_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_rom_williams_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cart_map(address_map &map) override; + virtual void cctl_map(address_map &map) override; + virtual std::tuple get_initial_rd_state() override { return std::make_tuple(0, 1); }; + +protected: + virtual void device_start() override; + virtual void device_reset() override; + + int m_bank; + + uint8_t disable_rom_r(offs_t offset); + void disable_rom_w(offs_t offset, uint8_t data); + virtual uint8_t rom_bank_r(offs_t offset); + virtual void rom_bank_w(offs_t offset, uint8_t data); +}; + + +class a800_rom_express_device : public a800_rom_williams_device +{ +public: + a800_rom_express_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock); + a800_rom_express_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +protected: + virtual void cctl_map(address_map &map) override; + + virtual uint8_t rom_bank_r(offs_t offset) override; + virtual void rom_bank_w(offs_t offset, uint8_t data) override; +}; + +class a800_rom_diamond_device : public a800_rom_express_device +{ +public: + a800_rom_diamond_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + +private: + virtual void cctl_map(address_map &map) override; +}; + +class a800_rom_turbo_device : public a800_rom_williams_device +{ +public: + a800_rom_turbo_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + + virtual void cctl_map(address_map &map) override; +}; + +DECLARE_DEVICE_TYPE(A800_ROM_WILLIAMS, a800_rom_williams_device) +DECLARE_DEVICE_TYPE(A800_ROM_EXPRESS, a800_rom_express_device) +DECLARE_DEVICE_TYPE(A800_ROM_DIAMOND, a800_rom_diamond_device) +DECLARE_DEVICE_TYPE(A800_ROM_TURBO, a800_rom_turbo_device) + +#endif // MAME_BUS_A800_WILLIAMS_H diff --git a/src/mame/atari/antic.cpp b/src/mame/atari/antic.cpp index 93b482ff19d..ac8dc198877 100644 --- a/src/mame/atari/antic.cpp +++ b/src/mame/atari/antic.cpp @@ -2242,12 +2242,18 @@ void antic_device::scanline_dma(int param) /* bits 6+7 of the priority select register determine */ /* if newer GTIA or plain graphics modes are used */ switch (m_gtia->get_w_prior() >> 6) - { - case 0: break; - case 1: m_render2 = 16; break; - case 2: m_render2 = 17; break; - case 3: m_render2 = 18; break; - } + { + case 0: break; + case 1: m_render2 = 16; break; + case 2: m_render2 = 17; break; + case 3: m_render2 = 18; break; + } + // TODO: implement GTIA 9++ Mode + // This is an artifact of abusing VSCROL so that scanlines gets 4x the normal height. + // Abused by 20xx homebrew releases such as: + // - Avery Breakout 2012 + // - Final Assault + // - Numen m_modelines = 1; break; } diff --git a/src/mame/atari/atari400.cpp b/src/mame/atari/atari400.cpp index 7f70d334307..30fd33bb4ca 100644 --- a/src/mame/atari/atari400.cpp +++ b/src/mame/atari/atari400.cpp @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Juergen Buchmueller +// copyright-holders:Juergen Buchmueller, Angelo Salese /****************************************************************************** Atari 400/800 @@ -7,8 +7,6 @@ Juergen Buchmueller, June 1998 TODO (generic): - - modernize memory maps; - - modernize cart handling; - add cassette support; - add floppy .atx support; - Investigate supported RAM sizes and OS versions in different models; @@ -16,14 +14,26 @@ - Freddy emulation for 800XLF? - Add support for proto boards and expansions (a1400xl, C/PM board, etc.) - a130xe: support extended bank readback for Antic; - - a1200xl: boots to self-test ROM the first time around, fixes on - soft reset; - a1200xl: requires reading TRIG3 high for detecting a cart inserted, depends on above; - - a600xl, a800xl, a1200xl: crashes on MMU test in Acid800; - - eventually support unofficial mod for dual Pokey, - either make it a specific franken-machine with a130xe as base or use - slots. + - a600xl, a1200xl: crashes on MMU test in Acid800; + - slot support for PBI/ECI bus; + - slot support for overlay DIY HW mods: + \- PokeyMAX + (with stereo support via second Pokey alias accessed to $d280-$d2ff, + cfr. yoomp); + \- Ultimate1MB; + \- Covox; + \- VBXE "VideoBoard XE"; + \- Incognito; + \- Rapidus; + \- AKI PS/2 keyboard inteface; + \- RAMBO XL and COMPY RAM expansion; + \- APE Warp+ OS 32-in-1; + \- MyBIOS for MyIDE-II; + \- Bit-3 Full-View 80 + (technically maps in cart CCTL space, but installs in RAM card slot 3 + and overrides ANTIC+GTIA layer when enabled); 2009-05 FP changes: Factored out MESS specific code from MAME @@ -268,6 +278,8 @@ public: , m_dac(*this, "dac") , m_region_maincpu(*this, "maincpu") , m_cartleft(*this, "cartleft") + , m_cart_rd4_view(*this, "cart_rd4_view") + , m_cart_rd5_view(*this, "cart_rd5_view") , m_ctrl(*this, "ctrl%u", 1U) { } @@ -304,6 +316,8 @@ protected: m_ram->pointer()[memory_offset] = data; } + virtual uint8_t djoy_b_r(); + private: void a400_palette(palette_device &palette) const; @@ -313,37 +327,24 @@ private: void djoy_0_1_w(uint8_t data); uint8_t djoy_2_3_r(); void djoy_2_3_w(uint8_t data); - uint8_t djoy_b_r(); - - uint8_t read_d5xx(offs_t offset); // at least one cart type can enable/disable roms when reading - void disable_cart(offs_t offset, uint8_t data); - - // these are needed to handle carts which can disable ROM without - // installing/disinstalling continuously RAM and ROM (with e.g. big - // performance hit in Williams carts) - uint8_t special_read_8000(offs_t offset); - void special_write_8000(offs_t offset, uint8_t data); - uint8_t special_read_a000(offs_t offset); - void special_write_a000(offs_t offset, uint8_t data); - uint8_t read_corina_overlay(offs_t offset); - void write_corina_overlay(offs_t offset, uint8_t data); - void write_corina_d5xx(offs_t offset, uint8_t data); protected: - //required_device m_maincpu; // maincpu is already contained in atari_common_state optional_device m_ram; optional_device m_pia; optional_device m_dac; required_memory_region m_region_maincpu; - required_device m_cartleft; + optional_device m_cartleft; + memory_view m_cart_rd4_view, m_cart_rd5_view; optional_device_array m_ctrl; - int m_cart_disabled, m_cart_helper; - int m_last_offs; - - void setup_cart(a800_cart_slot_device *slot); - void hw_iomap(address_map &map); + + int m_cart_rd4_enabled = 0, m_cart_rd5_enabled = 0; + void cart_rd4_w( int state ); + void cart_rd5_w( int state ); + + virtual void area_8000_map(address_map &map); + virtual void area_a000_map(address_map &map); }; class a800_state : public a400_state @@ -358,7 +359,8 @@ public: void a800pal(machine_config &config); protected: - virtual void machine_start() override; +// virtual void machine_start() override; + virtual void machine_reset() override; private: required_device m_cartright; @@ -391,6 +393,7 @@ protected: memory_view m_selftest_view; virtual void portb_cb(uint8_t data); + virtual uint8_t djoy_b_r() override; void selftest_map(memory_view::memory_view_entry &block, bool is_rom_mapping); private: @@ -417,6 +420,8 @@ protected: void a800xl_mem(address_map &map); + virtual void area_a000_map(address_map &map) override; + memory_view m_basic_view; }; @@ -479,15 +484,19 @@ private: class a5200_state : public a400_state { public: - a5200_state(const machine_config &mconfig, device_type type, const char *tag) : - a400_state(mconfig, type, tag) + a5200_state(const machine_config &mconfig, device_type type, const char *tag) + : a400_state(mconfig, type, tag) + , m_cart(*this, "cart") { } void a5200(machine_config &config); void a5200a(machine_config &config); private: -// virtual void machine_start() override; + virtual void machine_start() override; + virtual void machine_reset() override; + + required_device m_cart; TIMER_DEVICE_CALLBACK_MEMBER(a5200_interrupt); @@ -500,28 +509,41 @@ private: * **************************************************************/ -// TODO: better memory map inheritance -// TODO: transparent support for cart window & cart rd5 line (active_high) for enable/disable -// (applies to 0xa000-0xbfff only?) -// TODO: transparent support for cart CCTL at 0xd500 // TODO: transparent support for PBI (XL) / ECI (XE series), at 0xd1xx, 0xd6xx, 0xd7xx + ROM at 0xd800-0xdfff void a400_state::hw_iomap(address_map &map) { map(0x0000, 0x00ff).rw(m_gtia, FUNC(gtia_device::read), FUNC(gtia_device::write)); - map(0x0100, 0x01ff).noprw(); +// map(0x0100, 0x01ff).noprw(); map(0x0200, 0x02ff).rw(m_pokey, FUNC(pokey_device::read), FUNC(pokey_device::write)); map(0x0300, 0x03ff).rw(m_pia, FUNC(pia6821_device::read_alt), FUNC(pia6821_device::write_alt)); map(0x0400, 0x04ff).rw(m_antic, FUNC(antic_device::read), FUNC(antic_device::write)); - map(0x0500, 0x05ff).noprw(); - map(0x0600, 0x07ff).noprw(); + map(0x0500, 0x05ff).rw(m_cartleft, FUNC(a800_cart_slot_device::read_cctl), FUNC(a800_cart_slot_device::write_cctl)); +// map(0x0600, 0x07ff).noprw(); } +void a400_state::area_8000_map(address_map &map) +{ + map(0x8000, 0x9fff).view(m_cart_rd4_view); + m_cart_rd4_view[0](0x8000, 0x9fff).rw(FUNC(a400_state::ram_r<0x8000>), FUNC(a400_state::ram_w<0x8000>)); + m_cart_rd4_view[1](0x8000, 0x9fff).rw(m_cartleft, FUNC(a800_cart_slot_device::read_cart<0>), FUNC(a800_cart_slot_device::write_cart<0>)); +} + +void a400_state::area_a000_map(address_map &map) +{ + map(0xa000, 0xbfff).view(m_cart_rd5_view); + m_cart_rd5_view[0](0xa000, 0xbfff).rw(FUNC(a400_state::ram_r<0xa000>), FUNC(a400_state::ram_w<0xa000>)); + m_cart_rd5_view[1](0xa000, 0xbfff).rw(m_cartleft, FUNC(a800_cart_slot_device::read_cart<1>), FUNC(a800_cart_slot_device::write_cart<1>)); +} + + // a400/a800 explicitly expects floating bus for unmapped ranges, will punt with value_low() void a400_state::a400_mem(address_map &map) { map.unmap_value_high(); - map(0x0000, 0xbfff).rw(FUNC(a400_state::ram_r<0x0000>), FUNC(a400_state::ram_w<0x0000>)); + map(0x0000, 0x7fff).rw(FUNC(a400_state::ram_r<0x0000>), FUNC(a400_state::ram_w<0x0000>)); + area_8000_map(map); + area_a000_map(map); map(0xc000, 0xcfff).rom(); map(0xd000, 0xd7ff).m(*this, FUNC(a400_state::hw_iomap)); map(0xd800, 0xffff).rom(); @@ -557,21 +579,36 @@ void a1200xl_state::a1200xl_mem(address_map &map) map(0x4000, 0x7fff).view(m_selftest_view); selftest_map(m_selftest_view[0], false); selftest_map(m_selftest_view[1], true); - map(0x8000, 0x9fff).rw(FUNC(a1200xl_state::ram_r<0x8000>), FUNC(a1200xl_state::ram_w<0x8000>)); - map(0xa000, 0xbfff).rw(FUNC(a1200xl_state::ram_r<0xa000>), FUNC(a1200xl_state::ram_w<0xa000>)); + area_8000_map(map); + area_a000_map(map); map(0xc000, 0xffff).view(m_kernel_view); m_kernel_view[0](0xc000, 0xffff).rw(FUNC(a1200xl_state::ram_r<0xc000>), FUNC(a1200xl_state::ram_w<0xc000>)); m_kernel_view[1](0xc000, 0xffff).rom().region("maincpu", 0xc000); map(0xd000, 0xd7ff).m(*this, FUNC(a1200xl_state::hw_iomap)); } +void a800xl_state::area_a000_map(address_map &map) +{ + map(0xa000, 0xbfff).view(m_cart_rd5_view); + m_cart_rd5_view[0](0xa000, 0xbfff).view(m_basic_view); + m_basic_view[0](0xa000, 0xbfff).rw(FUNC(a800xl_state::ram_r<0xa000>), FUNC(a800xl_state::ram_w<0xa000>)); + m_basic_view[1](0xa000, 0xbfff).rom().region("maincpu", 0xa000); + m_cart_rd5_view[1](0xa000, 0xbfff).rw(m_cartleft, FUNC(a800_cart_slot_device::read_cart<1>), FUNC(a800_cart_slot_device::write_cart<1>)); +} + void a800xl_state::a800xl_mem(address_map &map) { map.unmap_value_high(); - a1200xl_mem(map); - map(0xa000, 0xbfff).view(m_basic_view); - m_basic_view[0](0xa000, 0xbfff).rw(FUNC(a800xl_state::ram_r<0xa000>), FUNC(a800xl_state::ram_w<0xa000>)); - m_basic_view[1](0xa000, 0xbfff).rom().region("maincpu", 0xa000); + map(0x0000, 0x3fff).rw(FUNC(a800xl_state::ram_r<0x0000>), FUNC(a800xl_state::ram_w<0x0000>)); + map(0x4000, 0x7fff).view(m_selftest_view); + selftest_map(m_selftest_view[0], false); + selftest_map(m_selftest_view[1], true); + area_8000_map(map); + area_a000_map(map); + map(0xc000, 0xffff).view(m_kernel_view); + m_kernel_view[0](0xc000, 0xffff).rw(FUNC(a800xl_state::ram_r<0xc000>), FUNC(a800xl_state::ram_w<0xc000>)); + m_kernel_view[1](0xc000, 0xffff).rom().region("maincpu", 0xc000); + map(0xd000, 0xd7ff).m(*this, FUNC(a800xl_state::hw_iomap)); } // selftest ROM has still priority over regular a130xe extended RAM @@ -591,10 +628,8 @@ void a130xe_state::a130xe_mem(address_map &map) selftest_map(m_selftest_view[0], false); selftest_map(m_selftest_view[1], true); m_ext_view[1](0x4000, 0x7fff).m(m_ext_bank, FUNC(address_map_bank_device::amap8)); - map(0x8000, 0x9fff).rw(FUNC(a130xe_state::ram_r<0x8000>), FUNC(a130xe_state::ram_w<0x8000>)); - map(0xa000, 0xbfff).view(m_basic_view); - m_basic_view[0](0xa000, 0xbfff).rw(FUNC(a130xe_state::ram_r<0xa000>), FUNC(a130xe_state::ram_w<0xa000>)); - m_basic_view[1](0xa000, 0xbfff).rom().region("maincpu", 0xa000); + area_8000_map(map); + area_a000_map(map); map(0xc000, 0xffff).view(m_kernel_view); m_kernel_view[0](0xc000, 0xffff).rw(FUNC(a130xe_state::ram_r<0xc000>), FUNC(a130xe_state::ram_w<0xc000>)); m_kernel_view[1](0xc000, 0xffff).rom().region("maincpu", 0xc000); @@ -610,11 +645,17 @@ void xegs_state::xegs_mem(address_map &map) m_selftest_view[0](0x5000, 0x57ff).ram(); m_selftest_view[1](0x5000, 0x57ff).rom().region("maincpu", 0xd000); map(0x5800, 0x7fff).ram(); - // TODO: map cart space overlays - map(0x8000, 0x9fff).ram(); - map(0xa000, 0xbfff).view(m_basic_view); + + map(0x8000, 0x9fff).view(m_cart_rd4_view); + m_cart_rd4_view[0](0x8000, 0x9fff).ram(); + m_cart_rd4_view[1](0x8000, 0x9fff).rw(m_cartleft, FUNC(a800_cart_slot_device::read_cart<0>), FUNC(a800_cart_slot_device::write_cart<0>)); + + map(0xa000, 0xbfff).view(m_cart_rd5_view); + m_cart_rd5_view[0](0xa000, 0xbfff).view(m_basic_view); m_basic_view[0](0xa000, 0xbfff).ram(); m_basic_view[1](0xa000, 0xbfff).bankr(m_bank); + m_cart_rd5_view[1](0xa000, 0xbfff).rw(m_cartleft, FUNC(a800_cart_slot_device::read_cart<1>), FUNC(a800_cart_slot_device::write_cart<1>)); + map(0xc000, 0xffff).view(m_kernel_view); m_kernel_view[0](0xc000, 0xffff).ram(); m_kernel_view[1](0xc000, 0xffff).rom().region("maincpu", 0xc000); @@ -625,7 +666,7 @@ void xegs_state::xegs_mem(address_map &map) void a5200_state::a5200_mem(address_map &map) { map(0x0000, 0x3fff).ram(); - map(0x4000, 0xbfff).noprw(); // ROM installed at machine start + map(0x4000, 0xbfff).rw(m_cart, FUNC(a5200_cart_slot_device::read_cart), FUNC(a5200_cart_slot_device::write_cart)); map(0xc000, 0xcfff).rw(m_gtia, FUNC(gtia_device::read), FUNC(gtia_device::write)); map(0xd400, 0xd4ff).rw(m_antic, FUNC(antic_device::read), FUNC(antic_device::write)); // 0xe000-0xe7ff - Expansion? @@ -1658,282 +1699,18 @@ LIGHT-ORANGE * **************************************************************/ -// these handle cart enable/disable without calling setup_ram thousands of times -// TODO: this should really live in a800_slot file -uint8_t a400_state::special_read_8000(offs_t offset) +void a400_state::cart_rd4_w(int state) { - if (!m_cart_disabled) - return m_cartleft->read_80xx(offset); - else - { - offset += 0x8000; - if (m_ram->size() < offset) - return 0; - else - return m_ram->pointer()[offset]; - } + m_cart_rd4_enabled = state; + m_cart_rd4_view.select(m_cart_rd4_enabled); } -void a400_state::special_write_8000(offs_t offset, uint8_t data) +void a400_state::cart_rd5_w(int state) { - if (m_cart_disabled) - { - offset += 0x8000; - if (m_ram->size() >= offset) - m_ram->pointer()[offset] = data; - } + m_cart_rd5_enabled = state; + m_cart_rd5_view.select(m_cart_rd5_enabled); } -uint8_t a400_state::special_read_a000(offs_t offset) -{ - if (!m_cart_disabled) - return m_cartleft->read_80xx(offset); - else - { - offset += 0xa000; - if (m_ram->size() < offset) - return 0; - else - return m_ram->pointer()[offset]; - } -} - -void a400_state::special_write_a000(offs_t offset, uint8_t data) -{ - if (m_cart_disabled) - { - offset += 0xa000; - if (m_ram->size() >= offset) - m_ram->pointer()[offset] = data; - } -} - - -uint8_t a400_state::read_d5xx(offs_t offset) -{ - if (!machine().side_effects_disabled()) - disable_cart(offset, 0); - return 0xff; -} - -uint8_t a400_state::read_corina_overlay(offs_t offset) -{ - if (!m_cart_disabled) - return m_cartleft->read_80xx(offset); - offset += 0x8000; - if (m_ram->size() < offset) - return 0; - else - return m_ram->pointer()[offset]; -} - -void a400_state::write_corina_overlay(offs_t offset, uint8_t data) -{ - if (!m_cart_disabled) - { - m_cartleft->write_80xx(offset, data); - return; - } - - offset += 0x8000; - if (m_ram->size() >= offset) - m_ram->pointer()[offset] = data; -} - -void a400_state::write_corina_d5xx(offs_t offset, uint8_t data) -{ - m_cart_disabled = BIT(data, 7); - m_cartleft->write_d5xx(offset, data); -} - -void a400_state::disable_cart(offs_t offset, uint8_t data) -{ - if (m_cartleft->exists()) - { - switch (m_cartleft->get_cart_type()) - { - case A800_PHOENIX: - case A800_BLIZZARD: - if (!m_cart_disabled) - m_cart_disabled = 1; - break; - case A800_OSS034M: - case A800_OSS043M: - case A800_EXPRESS: - case A800_DIAMOND: - case A800_WILLIAMS: - // use m_cart_disabled & m_last_offs to avoid continuous remapping of - // the memory space in some games (e.g. dropzone) - if (offset & 0x8 && !m_cart_disabled) - m_cart_disabled = 1; - else if (!(offset & 0x8)) - { - if (m_cart_disabled) - m_cart_disabled = 0; - - if ((offset & 0x7) != m_last_offs) - { - // we enter here only if we are writing to a different offset than last time - m_last_offs = offset & 0x7; - m_cartleft->write_d5xx(offset, data); - } - } - break; - case A800_TURBO64: - case A800_TURBO128: - if (offset & 0x10 && !m_cart_disabled) - m_cart_disabled = 1; - else if (!(offset & 0x10)) - { - if (m_cart_disabled) - m_cart_disabled = 0; - - if ((offset & 0x0f) != m_last_offs) - { - // we enter here only if we are writing to a different offset than last time - m_last_offs = offset & 0x0f; - m_cartleft->write_d5xx(offset & 0x0f, data); - } - } - break; - case A800_SPARTADOS: - // writes with offset & 8 are also used to enable/disable the subcart, so they go through! - m_cartleft->write_d5xx(offset, data); - break; - case A800_OSSM091: - case A800_OSS8K: - if ((offset & 0x9) == 0x08) - m_cart_disabled = 1; - else - { - m_cart_disabled = 0; - m_cartleft->write_d5xx(offset, data); - } - break; - case A800_MICROCALC: - m_cart_helper = (m_cart_helper + 1) % 5; - if (m_cart_helper == 4) - m_cart_disabled = 1; - else - { - m_cart_disabled = 0; - m_cartleft->write_d5xx(offset, m_cart_helper); - } - break; - default: - break; - } - } -} - -void a400_state::setup_cart(a800_cart_slot_device *slot) -{ - m_cart_disabled = 0; - m_last_offs = -1; - - // FIXME: this driver should not have to differentiate between cartridge types - if (slot->exists()) - { - switch (slot->get_cart_type()) - { - case A800_8K: - m_maincpu->space(AS_PROGRAM).install_read_handler(0xa000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0xa000, 0xbfff); - break; - case A800_8K_RIGHT: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0x9fff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0x8000, 0x9fff); - break; - case A800_16K: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0x8000, 0xbfff); - break; - case A800_BBSB: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0x9fff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0xa000, 0xbfff); - break; - case A800_OSS034M: - case A800_OSS043M: - case A800_OSSM091: - case A800_OSS8K: - case A800_TURBO64: - case A800_TURBO128: - case A800_PHOENIX: - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_a000)), write8sm_delegate(*this, FUNC(a400_state::special_write_a000))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd5ff, write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_EXPRESS: - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_a000)), write8sm_delegate(*this, FUNC(a400_state::special_write_a000))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd570, 0xd57f, write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_DIAMOND: - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_a000)), write8sm_delegate(*this, FUNC(a400_state::special_write_a000))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd5d0, 0xd5df, write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_WILLIAMS: - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_a000)), write8sm_delegate(*this, FUNC(a400_state::special_write_a000))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd50f, write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_SPARTADOS: - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_a000)), write8sm_delegate(*this, FUNC(a400_state::special_write_a000))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd5e0, 0xd5ef, write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_BLIZZARD: - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0x8000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_8000)), write8sm_delegate(*this, FUNC(a400_state::special_write_8000))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd5ff, write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_MICROCALC: - // this can also disable ROM when reading in 0xd500-0xd5ff - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xa000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::special_read_a000)), write8sm_delegate(*this, FUNC(a400_state::special_write_a000))); - m_maincpu->space(AS_PROGRAM).install_readwrite_handler(0xd500, 0xd5ff, read8sm_delegate(*this, FUNC(a400_state::read_d5xx)), write8sm_delegate(*this, FUNC(a400_state::disable_cart))); - break; - case A800_TELELINK2: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x9000, 0x90ff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0xa000, 0xbfff); - m_maincpu->space(AS_PROGRAM).install_read_handler(0xd501, 0xd501, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_d5xx))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd502, 0xd502, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_d5xx))); - break; - case A800_XEGS: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0x8000, 0xbfff); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd5ff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_d5xx))); - break; - case A800_CORINA: - case A800_CORINA_SRAM: - //m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - //m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xbfff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_80xx))); - //m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd500, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_d5xx))); - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*this, FUNC(a400_state::read_corina_overlay))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xbfff, write8sm_delegate(*this, FUNC(a400_state::write_corina_overlay))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd500, write8sm_delegate(*this, FUNC(a400_state::write_corina_d5xx))); - break; - case A5200_4K: - case A5200_8K: - case A5200_16K: - case A5200_32K: - case A5200_16K_2CHIPS: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x4000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0x4000, 0xbfff); - break; - case A5200_BBSB: - m_maincpu->space(AS_PROGRAM).install_read_handler(0x4000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x4000, 0x5fff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_80xx))); - m_maincpu->space(AS_PROGRAM).unmap_write(0x6000, 0xbfff); - break; - } - } - else if (slot->get_card_device() != nullptr) - { - m_maincpu->space(AS_PROGRAM).install_read_handler(0x8000, 0xbfff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_80xx))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0x8000, 0xbfff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_80xx))); - m_maincpu->space(AS_PROGRAM).install_read_handler(0xd500, 0xd5ff, read8sm_delegate(*slot, FUNC(a800_cart_slot_device::read_d5xx))); - m_maincpu->space(AS_PROGRAM).install_write_handler(0xd500, 0xd5ff, write8sm_delegate(*slot, FUNC(a800_cart_slot_device::write_d5xx))); - } -} - - TIMER_DEVICE_CALLBACK_MEMBER( a400_state::a400_interrupt ) { m_antic->generic_interrupt(4); @@ -1951,17 +1728,8 @@ TIMER_DEVICE_CALLBACK_MEMBER( a5200_state::a5200_interrupt ) void a400_state::machine_start() { - setup_cart(m_cartleft); - - save_item(NAME(m_cart_disabled)); - save_item(NAME(m_cart_helper)); - save_item(NAME(m_last_offs)); -} - -void a800_state::machine_start() -{ - a400_state::machine_start(); - setup_cart(m_cartright); + save_item(NAME(m_cart_rd4_enabled)); + save_item(NAME(m_cart_rd5_enabled)); } void a1200xl_state::machine_start() @@ -1979,6 +1747,31 @@ void xegs_state::machine_start() void a400_state::machine_reset() { m_pokey->write(15, 0); + + // TODO: stub reset state + if (!m_cartleft->exists()) + { + m_cart_rd4_enabled = 0; + m_cart_rd5_enabled = 0; + } + else + std::tie(m_cart_rd4_enabled, m_cart_rd5_enabled) = m_cartleft->get_initial_rd_state(); + + m_cart_rd4_view.select(m_cart_rd4_enabled); + m_cart_rd5_view.select(m_cart_rd5_enabled); +} + +void a800_state::machine_reset() +{ + a400_state::machine_reset(); + + // TODO: stub reset state, verify if any can be run stand-alone +/* + if (!m_cartright->exists()) + { + m_cart_rd4_enabled = false; + m_cart_rd4_view.select(0); + }*/ } void a1200xl_state::machine_reset() @@ -2008,6 +1801,14 @@ void a130xe_state::machine_reset() m_ext_bank->set_bank(3); } +void a5200_state::machine_start() +{ +} + +void a5200_state::machine_reset() +{ + m_pokey->write(15, 0); +} /************************************************************** * @@ -2057,12 +1858,31 @@ uint8_t a400_state::djoy_b_r() return b; } +uint8_t a1200xl_state::djoy_b_r() +{ + uint8_t b = 0; + for (int i = 0; i < 2; i++) + if (!m_ctrl[i].found() || BIT(m_ctrl[i]->read_joy(), 5)) + b |= 1 << i; + + // TODO: TRIG2 (0) for XEGS keyboard disconnected, always 1 otherwise + b |= 1 << 2; + // TODO: TRIG3 should really read from RD5 instead + // - non-64KB SDX boot (will hang in kernel during POST by boot conflict with BASIC if not handled properly) + // - a1200xl cart boot (expects this to be reversed) + // - returning m_cartleft->exists() makes BASIC disable thru OPTION to not work and makes maxflash to fail loading most .xex +// b |= m_cart_rd5_enabled << 3; + b |= !m_cartleft->exists() << 3; + + return b; +} + void a1200xl_state::pia_portb_w(uint8_t data) { const u8 dir = m_pia->port_b_z_mask(); // On a1200xl BIOS jumps from PC=0xc550, expecting ROM to be still - // enabled at PC=0xe40c, expecting the dir to work properly. + // enabled at PC=0xe40c, needing direction to work properly. const u8 new_mmu = (data & ~dir) | (m_mmu & dir); if (m_mmu != new_mmu) @@ -2136,6 +1956,10 @@ void a130xe_state::portb_cb(uint8_t data) } else m_ext_view.select(0); + + // TODO: ANTIC extended memory access enable + // Prince of Persia homebrew has it always on. + // May be used for the intro screen (where text don't draw at the time of this writing) } // TODO: propagate portb to RAMBO XL and COMPY sub-devices for a800xl and onward @@ -2243,12 +2067,14 @@ void a400_state::atari_common(machine_config &config) ATARI_FDC(config, "fdc", 0); A800_CART_SLOT(config, m_cartleft, a800_left, nullptr); + m_cartleft->rd4_callback().set(FUNC(a400_state::cart_rd4_w)); + m_cartleft->rd5_callback().set(FUNC(a400_state::cart_rd5_w)); /* software lists */ SOFTWARE_LIST(config, "flop_list").set_original("a800_flop"); - SOFTWARE_LIST(config, "cart_list").set_original("a800"); SOFTWARE_LIST(config, "cass_list").set_original("a800_cass"); - SOFTWARE_LIST(config, "xegs_list").set_original("xegs"); + SOFTWARE_LIST(config, "cart_list").set_original("a800"); + SOFTWARE_LIST(config, "xegs_list").set_compatible("xegs"); VCS_CONTROL_PORT(config, m_ctrl[0], a800_control_port_devices, "joy"); VCS_CONTROL_PORT(config, m_ctrl[1], a800_control_port_devices, "joy"); @@ -2342,6 +2168,10 @@ void a1200xl_state::a1200xl(machine_config &config) m_pokey->pot_r<6>().set_ioport("J3"); m_pokey->pot_r<7>().set_ioport("J4"); // TODO: console LEDs for this model only + + // retail has 64KB minimum + m_ram->set_default_size("64K"); +// m_ram->set_extra_options("16K,32K,48K"); } // memory map A800XL + NTSC screen + MMU via PIA portB @@ -2395,13 +2225,15 @@ void xegs_state::xegs(machine_config &config) m_maincpu->set_addrmap(AS_PROGRAM, &xegs_state::xegs_mem); - config.device_remove("cartleft"); - config.device_remove("cart_list"); - // not installable unless with DIY mods config.device_remove("ram"); - XEGS_CART_SLOT(config, m_cartleft, xegs_carts, nullptr); +// m_cartleft->set_default_option("xegs"); + m_cartleft->set_is_xegs(true); + + // uses exact same slot connector + SOFTWARE_LIST(config.replace(), "cart_list").set_compatible("a800"); + SOFTWARE_LIST(config.replace(), "xegs_list").set_original("xegs"); } // memory map A5200, different ports, less RAM @@ -2434,7 +2266,7 @@ void a5200_state::a5200(machine_config &config) config_ntsc_screen(config); - A5200_CART_SLOT(config, m_cartleft, a5200_carts, nullptr); + A5200_CART_SLOT(config, m_cart, a5200_carts, nullptr); /* Software lists */ SOFTWARE_LIST(config, "cart_list").set_original("a5200"); diff --git a/src/mame/atari/atari400.h b/src/mame/atari/atari400.h index 7b551ff1f6f..e9509eb9b61 100644 --- a/src/mame/atari/atari400.h +++ b/src/mame/atari/atari400.h @@ -1,5 +1,5 @@ // license:GPL-2.0+ -// copyright-holders:Juergen Buchmueller +// copyright-holders:Juergen Buchmueller, Angelo Salese /****************************************************************************** Atari 400/800 diff --git a/src/mame/atari/gtia.cpp b/src/mame/atari/gtia.cpp index f2a557783bb..51713be74e4 100644 --- a/src/mame/atari/gtia.cpp +++ b/src/mame/atari/gtia.cpp @@ -317,12 +317,13 @@ void gtia_device::button_interrupt(int button_count) } /* button registers for xl/xe */ + // these don't really unregister on latch but are instant if (button_count == 2) { // TRIG2: unused on xl/xe (1), xegs keyboard (1) connected (0) disconnected - m_r.but[2] = 1; + m_r.but[2] = BIT(button_port, 2); // TRIG3: RD5 external cart readback (1) present (0) disabled thru bankswitch or absent - m_r.but[3] = 0; + m_r.but[3] = BIT(button_port, 3); } }