amiga.cpp: modernization changes (#9263)

Structural changes:

- amiga_copper.cpp: convert to device, added copins implementation as debugging mailbox, convert to logmacro.h;
- 8364_paula.cpp: convert audio implementation accessors from switch-case to per-channel maps;
- amiga.cpp: convert OCS/ECS/AGA chipset flavours to address_map_bank_device, currently using the older custom_chip_r/_w as a legacy trampoline that will be progressively removed once that we have working implementations of Agnus/Denise and derivatives;
- akiko.cpp: convert to logmacro.h;
- amigafdc.cpp: better elaborate QA notes, add "Trackdisk" to device long name as officially referred by Amiga SDK:
- amiga.cpp: kicked off an amiga_demos.xml SW list hookup;

Adds the following implementation detail changes:
- amigaaga.cpp: fix sprites and bitplanes in dualpf modes, fixes at very least cd32:dstreets on gameplay;
- amigaaga.cpp: fix BPLCON0 when planes == 7 is set, fixes title screen GFXs in surfninj;
- amigaaga.cpp: use HAM6 when not in AGA mode, fixes colors in cdtv:townona when run with CD32 system;
- amigaaga.cpp: fix sprite control fetches when FMODE != 0, fixes at very least Digger AGA sprites display;
- amigaaga.cpp: add extended bitplane delay hooks;
- amigaaga.cpp: fix HAM8 when in HIRES mode, fixes at least roadkill title and car screens;
- amiga.cpp: allow LOF bit to be set by writing bit 15 on VPOSW, fix roadkill AGA boot;
- amigaaga.cpp: implement Extra Half-Brite mode, used by bblow_a main menu
- amiga.cpp: disallow blitter address writes to go beyond the allocated chip RAM, fixes OCS sockid and AGA sockid_a drawing spurious filled tiles on playfield;
- amiga.cpp, amigaaga.cpp: workaround most GFX pitch corruptions, caused by implicit DDFSTOP overrunning width loop;
- amiga.cpp: allow DDFSTRT and DDFSTOP to read bit 2 in lores mode, fix swordsod GFX pitch in gameplay;
- amiga.cpp: use pf2pri for non-dual playfield, fixes alfred player sprite visibility;
- akiko.cpp: subq command adds +2 in command buffer, fixes cdtv:defcrown hardlock emulation;
- amigaaga.cpp: implement bscan2;
- amiga.cpp: disable floppy drive default for CD32;
- cubo.cpp: add inputs to eldoralg/odeontw/odeontw2;
- amiga.cpp: allow CD32 to read CDTV titles from SW list;

New NOT_WORKING software list additions
---------------------------------------
cdtv.xml: 17 Bit - Collection for Amiga CDTV, 17 Bit - Continuation Disc,
A Bun for Barney (USA), Advanced Military Systems (Europe),
American Heritage Illustrated Encyclopedic Dictionary (USA, 1991a Edition),
Barney Bear Goes to School (USA), Cinderella - The Original Fairy Tale (USA),
Defender of the Crown CDTV (Europe), Deutschland Kompakt (Germany),
Fantastic Voyage (USA), Garden Fax - Garden Plants (USA),
Garden Fax - Trees, Shrubs, Roses, and Conifers (USA),
Language TV - English (France), Lemmings (Europe), Log!cal (Europe),
Mud Puddle (USA, Multi 5), Pandora's CD v1.0 (alt), Psycho Killer (U2A2020UA),
CDTV Demo Disc (Europe), Raffles (Sweden),
Snoopy - The Case of the Missing Blanket (Sweden), Team Yankee (Europe),
The Curse of Ra (Germany),
The Demo Collection for Amiga CDTV (Europe, Black Disc),
The Hutchinson Encyclopedia (Europe),
The New Basics Electronic Cookbook (USA, 1991a Edition),
Time Table of History - Business, Politics & Media (USA, 1991a Edition),
Trivial Pursuit - The CDTV Edition (Europe, v1.0a),
Turrican (Germany, alt), Turrican II: The Final Fight (Germany, alt),
Welcome to CDTV Multimedia (USA, CDRM-499000), Wrath of the Demon (USA),
Xenon 2 - Megablast (Eng, Fra, Ger, Ita), Ten on Ten Compilation [redump.org]
This commit is contained in:
Angelo Salese 2022-02-22 00:20:36 +01:00 committed by GitHub
parent 1b3409de9b
commit deff4306c5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 13628 additions and 4121 deletions

60
hash/amiga_demos.xml Normal file
View File

@ -0,0 +1,60 @@
<?xml version="1.0"?>
<!DOCTYPE softwarelist SYSTEM "softwarelist.dtd">
<!--
license:CC0
General purpose Amiga demos collection
The idea here is to collect Public Domain demos that can be run without any user intervention and
be run with in a side-by-side fashion.
TODO:
- Add filter by unsupported chipset;
- Add estimate wall-clock times in seconds, by platform;
-->
<softwarelist name="amiga_demos" description="Commodore Amiga demos">
<software name="drgnmega" supported="no">
<description>Dragons Megademo I (Demo)</description>
<year>1990</year>
<publisher>&lt;homebrew&gt;</publisher>
<info name="developer" value="Dragons"/>
<!-- OCS/ECS -->
<part name="flop1" interface="floppy_3_5">
<dataarea name="flop" size="901120">
<rom name="dragons megademo (19xx)(dragons).adf" size="901120" crc="f15010ec" sha1="07c47185534f127bf21a9fe013d71a2250c7a037"/>
</dataarea>
</part>
</software>
<software name="miseryd2" supported="no">
<description>Misery Dentro 2 (Demo)</description>
<year>1993</year>
<publisher>&lt;homebrew&gt;</publisher>
<info name="developer" value="Masque of TRSI, Tristar and Red Sector Inc."/>
<info name="release" value="19930328"/>
<!-- 2nd place in CeBIT 1993 Amiga Demo Competition in Germany -->
<!-- OCS/ECS -->
<part name="flop1" interface="floppy_3_5">
<dataarea name="flop" size="901120">
<rom name="misery dentro 2 (1992)(trsi).adf" size="901120" crc="c61f8f60" sha1="25a16e354931f2050dffb5b945a9210b59e9be08"/>
</dataarea>
</part>
</software>
<software name="elysium" supported="no">
<description>Sanity Elysium (Demo)</description>
<year>1991</year>
<publisher>&lt;homebrew&gt;</publisher>
<info name="developer" value="Sanity"/>
<info name="release" value="19910428"/>
<!-- 3rd place in Amiga Summit Convention 1991 in Denmark -->
<!-- OCS/ECS -->
<part name="flop1" interface="floppy_3_5">
<dataarea name="flop" size="901120">
<rom name="elysium (1991)(sanity).adf" size="901120" crc="5311a737" sha1="dba662f8f21d37916d978fe370e24b5c567d7846"/>
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -506,8 +506,8 @@ license:CC0
<description>AmigaOS 3.5</description>
<year>1999</year>
<publisher>Haage &amp; Partner</publisher>
<part name="disc" interface="cdrom">
<diskarea name="disc">
<part name="cdrom" interface="cdrom">
<diskarea name="cdrom">
<disk name="amigaos35" sha1="6dcf1e5821717128ac2e763064f1ef31dee3ce8c"/>
</diskarea>
</part>

File diff suppressed because it is too large Load Diff

View File

@ -19,7 +19,12 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1997</year>
<publisher>Eidos Interactive</publisher>
<info name="usage" value="Requires ECS" /> <!-- This was sold as A1200 game, but it only requires ECS -->
<notes><![CDATA[
black screen, [FDC] dsksync
Throws a "please insert disk 4" error while creating a disk 4
]]></notes>
<!-- This was sold as A1200 game, but it only requires ECS -->
<info name="usage" value="Requires ECS, requires 2 Megs of RAM, requires 2 blank disks" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
<dataarea name="flop" size="1032864">
@ -41,25 +46,34 @@ license:CC0
<!-- (Amiga, ECS,AGA, PAL) -->
<year>1995</year>
<publisher>Empire Interactive</publisher>
<info name="usage" value="Requires ECS" />
<notes><![CDATA[
Throws a coala/coala "Program error #80000004" on login screen (a500p, a600)
Crashing into land draws missing polygons for heli (a1200), [Blitter] lines?
]]></notes>
<!-- find 0,0x100000,"Supervisor" once login screen appears -->
<!-- wpset <first entry>,0xa00,r -->
<!-- Insert Supervisor as password (a wrong word may make the game to crash) -->
<!-- Checkout offset at last three entries, wpdis then memory view the pointer and insert it as password -->
<info name="usage" value="Requires ECS, sports login copy-protection (username password match)" />
<!-- Omake: has green tone color setup by pressing backslash during gameplay -->
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Program Disk" />
<dataarea name="flop" size="1049180">
<rom name="(sps242)coala_programdisk.ipf" size="1049180" crc="60ec0f35" sha1="226951589bef83a368d9961f70d83fbc4d674d35"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<feature name="part_id" value="Disk AGA" />
<dataarea name="flop" size="1049180">
<rom name="(sps242)coala_datadiskaga.ipf" size="1049180" crc="4eea11cb" sha1="ba37c92d89901e1244790597362c992118fc940c"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<part name="flop3" interface="floppy_3_5">
<feature name="part_id" value="Disk ECS" />
<dataarea name="flop" size="1049180">
<rom name="(sps242)coala_datadiskecs.ipf" size="1049180" crc="6db4cc54" sha1="6506666c04371255b52e45fe35a547b4177d9973"/>
</dataarea>
</part>
<part name="flop3" interface="floppy_3_5">
<feature name="part_id" value="Program Disk" />
<dataarea name="flop" size="1049180">
<rom name="(sps242)coala_programdisk.ipf" size="1049180" crc="60ec0f35" sha1="226951589bef83a368d9961f70d83fbc4d674d35"/>
</dataarea>
</part>
</software>
<software name="epic" supported="no">
@ -69,6 +83,11 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1992</year>
<publisher>Ocean</publisher>
<notes><![CDATA[
Very unresponsive keyboard control on login system [CIA] (a500p), keyboard is too responsive on (a1200)
Does not draw status bars for throttle etc. during gameplay
]]></notes>
<!-- CHECKME: Sports a login system after title screen, doesn't seem to be copy protection? -->
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -97,6 +116,9 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1995</year>
<publisher>Domark</publisher>
<notes><![CDATA[
Flashing "IO Error: 4; Disk May Be Corrupt" at initial boot, [FDC] dsksync
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<dataarea name="flop" size="1049180">
@ -105,13 +127,17 @@ license:CC0
</part>
</software>
<software name="fatman" supported="no">
<software name="fatman" supported="partial">
<!-- SPS (CAPS) release 943 -->
<description>Fatman - The Caped Consumer (Euro)</description>
<!-- retail, standalone -->
<!-- (Amiga, ECS, PAL) -->
<year>1994</year>
<publisher>Black Legend</publisher>
<notes><![CDATA[
Grandslam logo has wrong [Denise] colors (a600)
Doesn't show cursor on main menu [Lisa]
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -146,19 +172,28 @@ license:CC0
<!-- (Amiga, ECS,AGA, PAL) -->
<year>1996</year>
<publisher>Guildhall</publisher>
<info name="usage" value="Requires ECS" />
<notes><![CDATA[
Throws a Recoverable Alert when loaded from stand-alone then throws a ramlib "Program failed #80000004" (a500p, btanb)
Throws a playgloom "Program failed #80000004" when is launched from HDD Workbench (a600, btanb)
Crashes when attempting to save configuration from floppy (a1200)
Cutoff [Denise] DDFSTOP portion on intermission and gameplay screens (a1200)
Unemulated link option
Unemulated I-Glasses support
]]></notes>
<!-- cfr. read.me.eventually file (de facto this is an AGA game ...) -->
<info name="usage" value="Requires ECS, requires 68020, requires 2 megs RAM" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Data Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps1330)gloomdeluxe_datadisk.ipf" size="1049612" crc="fb9287b6" sha1="6410c550ab20e9adf09d364d52323ba4b00a70d3"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<feature name="part_id" value="Program Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps1330)gloomdeluxe_programdisk.ipf" size="1049612" crc="bff6d892" sha1="4310358ed992038523b4cbbb29f4ef811ba4954e"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<feature name="part_id" value="Data Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps1330)gloomdeluxe_datadisk.ipf" size="1049612" crc="fb9287b6" sha1="6410c550ab20e9adf09d364d52323ba4b00a70d3"/>
</dataarea>
</part>
</software>
<software name="his1418" supported="no">
@ -168,7 +203,10 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1993</year>
<publisher>Blue Byte</publisher>
<info name="usage" value="Requires ECS" />
<notes><![CDATA[
No mouse cursor on gameplay (a500p, a600), single long vertical line on (a1200)
]]></notes>
<info name="usage" value="Requires ECS, insert disk 7 to skip intro" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
<dataarea name="flop" size="1049612">
@ -324,6 +362,9 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1994</year>
<publisher>Silmarils</publisher>
<notes><![CDATA[
Mouse cursor is uncontrollable, [joytest] reset counter
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk A" />
@ -403,36 +444,44 @@ license:CC0
</part>
</software>
<software name="mandoubl" supported="no">
<software name="mandoubl" supported="partial">
<!-- SPS (CAPS) release 1851 -->
<description>Manchester United - The Double (Euro)</description>
<!-- retail, standalone -->
<!-- (Amiga, ECS, PAL) -->
<year>1995</year>
<publisher>Krisalis</publisher>
<notes><![CDATA[
Has GFX small glitch on main menu, [Denise] sprite
May draw a garbage line on gameplay (emu unthrottled?), [Denise] sprite
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Data Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps1851)manchesterunited-thedouble_datadisk.ipf" size="1049612" crc="32055500" sha1="1bb97b89ce7e2f4b27c44986be65a45c19bfea70"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<feature name="part_id" value="Program Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps1851)manchesterunited-thedouble_programdisk.ipf" size="1049612" crc="ee64a3cd" sha1="12aa705ba33b1b2db23e430c560705752eb60b49"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<feature name="part_id" value="Data Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps1851)manchesterunited-thedouble_datadisk.ipf" size="1049612" crc="32055500" sha1="1bb97b89ce7e2f4b27c44986be65a45c19bfea70"/>
</dataarea>
</part>
</software>
<software name="produzen" supported="no">
<software name="produzen" supported="partial">
<!-- SPS (CAPS) release 558 -->
<description>Der Produzent - Die Welt des Films (Ger)</description>
<!-- retail, standalone -->
<!-- (Amiga, ECS, PAL) -->
<year>1996</year>
<publisher>Games 4 Europe</publisher>
<notes><![CDATA[
Has sprite garbage strips on right portions at random times (title screen, gameplay)
Not extensively tested (German language)
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -458,6 +507,7 @@ license:CC0
<rom name="(sps558)produzent,der_disk4.ipf" size="1049612" crc="05579db3" sha1="588c06dcafeb5d3723bb1bccb1216b0007d1a835"/>
</dataarea>
</part>
<!-- Spielstandsdiskette -->
<part name="flop5" interface="floppy_3_5">
<feature name="part_id" value="Disk 5" />
<dataarea name="flop" size="1049612">
@ -473,6 +523,11 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1994</year>
<publisher>Flair Software</publisher>
<notes><![CDATA[
Black screen, [FDC] in-flight DMAs with adkcon set
Returns a [FDC] disk block 1730 error
Stalls at now loading screen
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -500,50 +555,53 @@ license:CC0
</part>
</software>
<software name="reunion" supported="no">
<software name="reunion" supported="partial">
<!-- SPS (CAPS) release 569 -->
<description>Reunion (Ger)</description>
<!-- retail, standalone -->
<!-- (Amiga, ECS, PAL) -->
<year>1994</year>
<publisher>Grandslam</publisher>
<notes><![CDATA[
boot OK, not extensively tested (German language)
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Main Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_maindisk.ipf" size="1049612" crc="7d25a6b8" sha1="45e0f1ec6a12bde7fe5f43bc11366e9c7c74b3fc"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_disk1.ipf" size="1049612" crc="1744c014" sha1="bc41d2592854c864556d1bd8bba892003abae202"/>
</dataarea>
</part>
<part name="flop2" interface="floppy_3_5">
<part name="flop3" interface="floppy_3_5">
<feature name="part_id" value="Disk 2" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_disk2.ipf" size="1049612" crc="96b49ab9" sha1="035fe6a4353eaddb2e9f73fbe65e44e814af27aa"/>
</dataarea>
</part>
<part name="flop3" interface="floppy_3_5">
<part name="flop4" interface="floppy_3_5">
<feature name="part_id" value="Disk 3" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_disk3.ipf" size="1049612" crc="caf5a44b" sha1="88505a7ce593043cdd12f611750389f9c4bbc7f7"/>
</dataarea>
</part>
<part name="flop4" interface="floppy_3_5">
<part name="flop5" interface="floppy_3_5">
<feature name="part_id" value="Disk 4" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_disk4.ipf" size="1049612" crc="73ddb39d" sha1="bc84ceb391f1f70fd56d2fbe7988dce00c3896ad"/>
</dataarea>
</part>
<part name="flop5" interface="floppy_3_5">
<part name="flop6" interface="floppy_3_5">
<feature name="part_id" value="Disk 5" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_disk5.ipf" size="1049612" crc="0577609d" sha1="4ced88302024ca4e36c90fc901e4264f72057550"/>
</dataarea>
</part>
<part name="flop6" interface="floppy_3_5">
<feature name="part_id" value="Main Disk" />
<dataarea name="flop" size="1049612">
<rom name="(sps569)reunion_maindisk.ipf" size="1049612" crc="7d25a6b8" sha1="45e0f1ec6a12bde7fe5f43bc11366e9c7c74b3fc"/>
</dataarea>
</part>
</software>
<software name="rotr" supported="no">
@ -553,6 +611,10 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1994</year>
<publisher>Mirage</publisher>
<notes><![CDATA[
Red screen when SmartDos logo displays, [FDC] dsksync
Empty stripes on player sprite when it hits left edge of screen, [Denise] DDFSTRT
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -624,6 +686,9 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1992</year>
<publisher>System 3</publisher>
<notes><![CDATA[
Black screen, [FDC] dsksync
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -645,7 +710,6 @@ license:CC0
</part>
</software>
<!-- boot OK -->
<software name="snapper" supported="yes">
<!-- SPS (CAPS) release 2534 -->
<description>Snapperazzi (Euro)</description>
@ -653,6 +717,9 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1993</year>
<publisher>Alternative Software</publisher>
<notes><![CDATA[
boot OK
]]></notes>
<!-- TODO: is this truly a ECS exclusive game? Reports indicates this being OCS as well, it also works on vanilla a500 -->
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
@ -676,7 +743,11 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1992</year>
<publisher>Domark</publisher>
<info name="usage" value="Requires ECS, includes Amiga Text" />
<notes><![CDATA[
Doesn't show mouse pointer (a600)
boot OK (a1200)
]]></notes>
<info name="usage" value="Requires ECS, requires HDD install, includes AmigaText" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
<dataarea name="flop" size="1049612">
@ -698,6 +769,11 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1995</year>
<publisher>Arcane Entertainment</publisher>
<notes><![CDATA[
Black screen on garage screen (a500p only)
Doesn't draw player sprite on gameplay (a500, a500p), works in a1200
Unemulated link option
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />
@ -726,6 +802,9 @@ license:CC0
<!-- (Amiga, ECS, PAL) -->
<year>1995</year>
<publisher>Flair Software</publisher>
<notes><![CDATA[
Doesn't surpass the initial Whizz logo screen, [FDC] dsksync
]]></notes>
<info name="usage" value="Requires ECS" />
<part name="flop1" interface="floppy_3_5">
<feature name="part_id" value="Disk 1" />

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -162,6 +162,18 @@ if (MACHINES["AM2901B"]~=null) then
}
end
---------------------------------------------------
--
--@src/devices/machine/amiga_copper.h,MACHINES["AMIGA_COPPER"] = true
---------------------------------------------------
if (MACHINES["AMIGA_COPPER"]~=null) then
files {
MAME_DIR .. "src/devices/machine/amiga_copper.cpp",
MAME_DIR .. "src/devices/machine/amiga_copper.h",
}
end
--------------------------------------------------
--
--@src/devices/machine/arm_iomd.h,MACHINES["ARM_IOMD"] = true

View File

@ -459,6 +459,7 @@ MACHINES["AM79C90"] = true
--MACHINES["AM9513"] = true
MACHINES["AM9517A"] = true
MACHINES["AMIGAFDC"] = true
MACHINES["AMIGA_COPPER"] = true
--MACHINES["APPLEPIC"] = true
MACHINES["AT_KEYBC"] = true
MACHINES["AT28C16"] = true

View File

@ -482,6 +482,7 @@ MACHINES["AM9513"] = true
MACHINES["AM9517A"] = true
MACHINES["AM9519"] = true
MACHINES["AMIGAFDC"] = true
MACHINES["AMIGA_COPPER"] = true
MACHINES["APPLEPIC"] = true
MACHINES["ARM_IOMD"] = true
MACHINES["AT_KEYBC"] = true

View File

@ -58,6 +58,16 @@
appear to include the addition of an onboard power-on reset. It
is unknown what other differences these devices have.
TODO:
- For some reason most if not all Amiga MCU programs accesses arbitrary
zero page 0x90-0xff with a back-to-back cmp($00, x) opcode at
PC=c06-c08 with the actual result discarded. X can be any value in
the 0x90-0xff range, depending on the last user keypress row source
e.g. 0xdf-0xe0 for 'A', 0xef-0xf0 for 'Q', 0xfb-0xfc for function
keys.
This can be extremely verbose in the logging facility so we currently
nop it out for the time being.
***************************************************************************/
#include "emu.h"
@ -504,5 +514,8 @@ void m6500_1_device::memory_map(address_map &map)
map(0x008f, 0x008f).rw(FUNC(m6500_1_device::read_control_register), FUNC(m6500_1_device::write_control_register));
// TODO: mirror or actually unmapped?
map(0x0090, 0x00ff).nopr();
map(0x0800, 0x0fff).rom().region(DEVICE_SELF, 0);
}

View File

@ -1,6 +1,6 @@
// license: BSD-3-Clause
// copyright-holders: Aaron Giles, Dirk Best
/***************************************************************************
/******************************************************************************
MOS Technology 8364 "Paula"
@ -10,12 +10,14 @@
- low-pass filter;
- convert volume values to non-linear dB scale (cfr. )
- Verify ADKCON modulation;
- Verify manual mode;
- Verify manual mode:
\- AGA roadkill during gameplay, which also has very long period setups,
extremely aliased;
- When a DMA stop occurs, is the correlated channel playback stopped
at the end of the current cycle or as soon as possible like current
implementation?
***************************************************************************/
******************************************************************************/
#include "emu.h"
#include "8364_paula.h"
@ -43,11 +45,11 @@ DEFINE_DEVICE_TYPE(PAULA_8364, paula_8364_device, "paula_8364", "MOS 8364 \"Paul
//-------------------------------------------------
paula_8364_device::paula_8364_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, PAULA_8364, tag, owner, clock),
device_sound_interface(mconfig, *this),
m_mem_r(*this), m_int_w(*this),
m_dmacon(0), m_adkcon(0),
m_stream(nullptr)
: device_t(mconfig, PAULA_8364, tag, owner, clock)
, device_sound_interface(mconfig, *this)
, m_chipmem_r(*this)
, m_int_w(*this)
, m_stream(nullptr)
{
}
@ -58,7 +60,7 @@ paula_8364_device::paula_8364_device(const machine_config &mconfig, const char *
void paula_8364_device::device_start()
{
// resolve callbacks
m_mem_r.resolve_safe(0);
m_chipmem_r.resolve_safe(0);
m_int_w.resolve_safe();
// initialize channels
@ -74,8 +76,7 @@ void paula_8364_device::device_start()
void paula_8364_device::device_reset()
{
m_dmacon = 0;
m_adkcon = 0;
m_dma_master_enable = false;
for (auto &chan : m_channel)
{
chan.loc = 0;
@ -87,6 +88,8 @@ void paula_8364_device::device_reset()
chan.curlocation = 0;
chan.curlength = 0;
chan.dma_enabled = false;
chan.atper = false;
chan.atvol = false;
}
}
@ -104,76 +107,91 @@ void paula_8364_device::update()
// IMPLEMENTATION
//**************************************************************************
uint16_t paula_8364_device::reg_r(offs_t offset)
template <u8 ch> void paula_8364_device::audio_channel_map(address_map &map)
{
switch (offset)
{
case REG_DMACONR:
return m_dmacon;
case REG_ADKCONR:
return m_adkcon;
}
return 0xffff;
// TODO: location addresses belongs to Agnus
map(0x00, 0x01).w(FUNC(paula_8364_device::audxlch_w<ch>));
map(0x02, 0x03).w(FUNC(paula_8364_device::audxlcl_w<ch>));
map(0x04, 0x05).w(FUNC(paula_8364_device::audxlen_w<ch>));
map(0x06, 0x07).w(FUNC(paula_8364_device::audxper_w<ch>));
map(0x08, 0x09).w(FUNC(paula_8364_device::audxvol_w<ch>));
map(0x0a, 0x0b).w(FUNC(paula_8364_device::audxdat_w<ch>));
}
void paula_8364_device::reg_w(offs_t offset, uint16_t data)
// Instantiate channel maps
template void paula_8364_device::audio_channel_map<0>(address_map &map);
template void paula_8364_device::audio_channel_map<1>(address_map &map);
template void paula_8364_device::audio_channel_map<2>(address_map &map);
template void paula_8364_device::audio_channel_map<3>(address_map &map);
template <u8 ch> void paula_8364_device::audxlch_w(u16 data)
{
m_stream->update();
// TODO: chipmem mask
m_channel[ch].loc = (m_channel[ch].loc & 0x0000ffff) | ((data & 0x001f) << 16);
}
template <u8 ch> void paula_8364_device::audxlcl_w(u16 data)
{
m_stream->update();
m_channel[ch].loc = (m_channel[ch].loc & 0xffff0000) | ((data & 0xfffe) << 0);
}
template <u8 ch> void paula_8364_device::audxlen_w(u16 data)
{
m_stream->update();
m_channel[ch].len = data;
}
template <u8 ch> void paula_8364_device::audxper_w(u16 data)
{
m_stream->update();
m_channel[ch].per = data;
}
template <u8 ch> void paula_8364_device::audxvol_w(u16 data)
{
m_stream->update();
m_channel[ch].vol = data & 0x7f;
}
template <u8 ch> void paula_8364_device::audxdat_w(u16 data)
{
m_stream->update();
m_channel[ch].dat = data;
m_channel[ch].manualmode = true;
}
void paula_8364_device::dmacon_set(u16 data)
{
if (offset >= 0xa0 && offset <= 0xdf)
m_stream->update();
switch (offset)
{
case REG_DMACON:
m_stream->update();
m_dmacon = (data & 0x8000) ? (m_dmacon | (data & 0x021f)) : (m_dmacon & ~(data & 0x021f)); // only bits 15, 9 and 5 to 0
m_dma_master_enable = bool(BIT(data, 9));
// update the DMA latches on each channel and reload if fresh
// This holds true particularly for Ocean games (bchvolly, lostpatr, pang) and waylildr:
// they sets a DMA length for a channel then enable DMA then resets that length to 1
// they sets a DMA length for a channel then enable DMA finally resets that length to 1
// after a short delay loop.
for (int channum = 0; channum < 4; channum++)
{
audio_channel *chan = &m_channel[channum];
if (!chan->dma_enabled && ((m_dmacon >> channum) & 1))
if (!chan->dma_enabled && ((data >> channum) & 1))
dma_reload(chan, true);
chan->dma_enabled = BIT(m_dmacon, channum);
chan->dma_enabled = bool(BIT(data, channum));
}
break;
}
case REG_ADKCON:
void paula_8364_device::adkcon_set(u16 data)
{
m_stream->update();
m_adkcon = (data & 0x8000) ? (m_adkcon | (data & 0x7fff)) : (m_adkcon & ~(data & 0x7fff));
break;
// FIXME: location belongs to Agnus
case REG_AUD0LCL: m_channel[CHAN_0].loc = (m_channel[CHAN_0].loc & 0xffff0000) | ((data & 0xfffe) << 0); break; // 15-bit
case REG_AUD0LCH: m_channel[CHAN_0].loc = (m_channel[CHAN_0].loc & 0x0000ffff) | ((data & 0x001f) << 16); break; // 3-bit on ocs, 5-bit ecs
case REG_AUD1LCL: m_channel[CHAN_1].loc = (m_channel[CHAN_1].loc & 0xffff0000) | ((data & 0xfffe) << 0); break; // 15-bit
case REG_AUD1LCH: m_channel[CHAN_1].loc = (m_channel[CHAN_1].loc & 0x0000ffff) | ((data & 0x001f) << 16); break; // 3-bit on ocs, 5-bit ecs
case REG_AUD2LCL: m_channel[CHAN_2].loc = (m_channel[CHAN_2].loc & 0xffff0000) | ((data & 0xfffe) << 0); break; // 15-bit
case REG_AUD2LCH: m_channel[CHAN_2].loc = (m_channel[CHAN_2].loc & 0x0000ffff) | ((data & 0x001f) << 16); break; // 3-bit on ocs, 5-bit ecs
case REG_AUD3LCL: m_channel[CHAN_3].loc = (m_channel[CHAN_3].loc & 0xffff0000) | ((data & 0xfffe) << 0); break; // 15-bit
case REG_AUD3LCH: m_channel[CHAN_3].loc = (m_channel[CHAN_3].loc & 0x0000ffff) | ((data & 0x001f) << 16); break; // 3-bit on ocs, 5-bit ecs
for (int channum = 0; channum < 4; channum++)
{
audio_channel *chan = &m_channel[channum];
// audio data
case REG_AUD0LEN: m_channel[CHAN_0].len = data; break;
case REG_AUD0PER: m_channel[CHAN_0].per = data; break;
case REG_AUD0VOL: m_channel[CHAN_0].vol = data & 0x7f; break;
case REG_AUD0DAT: m_channel[CHAN_0].dat = data; m_channel[CHAN_0].manualmode = true; break;
case REG_AUD1LEN: m_channel[CHAN_1].len = data; break;
case REG_AUD1PER: m_channel[CHAN_1].per = data; break;
case REG_AUD1VOL: m_channel[CHAN_1].vol = data & 0x7f; break;
case REG_AUD1DAT: m_channel[CHAN_1].dat = data; m_channel[CHAN_1].manualmode = true; break;
case REG_AUD2LEN: m_channel[CHAN_2].len = data; break;
case REG_AUD2PER: m_channel[CHAN_2].per = data; break;
case REG_AUD2VOL: m_channel[CHAN_2].vol = data & 0x7f; break;
case REG_AUD2DAT: m_channel[CHAN_2].dat = data; m_channel[CHAN_2].manualmode = true; break;
case REG_AUD3LEN: m_channel[CHAN_3].len = data; break;
case REG_AUD3PER: m_channel[CHAN_3].per = data; break;
case REG_AUD3VOL: m_channel[CHAN_3].vol = data & 0x7f; break;
case REG_AUD3DAT: m_channel[CHAN_3].dat = data; m_channel[CHAN_3].manualmode = true; break;
chan->atper = bool(BIT(data, channum + 4));
chan->atvol = bool(BIT(data, channum));
}
}
@ -208,14 +226,14 @@ std::string paula_8364_device::print_audio_state()
{
std::ostringstream outbuffer;
util::stream_format(outbuffer, "DMACON: %04x (%d) ADKCON %04x\n", m_dmacon, BIT(m_dmacon, 9), m_adkcon);
util::stream_format(outbuffer, "DMA master %d\n", m_dma_master_enable);
for (auto &chan : m_channel)
{
util::stream_format(outbuffer, "%d (%d) (%d%d) REGS: %06x %04x %03x %02x %d LIVE: %06x %04x %d\n"
util::stream_format(outbuffer, "%d DMA (%d) ADK (%d%d) REGS: %06x %04x %03x %02x %d LIVE: %06x %04x %d\n"
, chan.index
, BIT(m_dmacon, chan.index)
, BIT(m_adkcon, chan.index+4)
, BIT(m_adkcon, chan.index)
, chan.dma_enabled
, chan.atper
, chan.atvol
, chan.loc
, chan.len
, chan.per
@ -239,7 +257,7 @@ void paula_8364_device::sound_stream_update(sound_stream &stream, std::vector<re
int channum, sampoffs = 0;
// if all DMA off, disable all channels
if (BIT(m_dmacon, 9) == 0)
if (m_dma_master_enable == false)
{
m_channel[0].dma_enabled =
m_channel[1].dma_enabled =
@ -289,7 +307,7 @@ void paula_8364_device::sound_stream_update(sound_stream &stream, std::vector<re
volume *= 4;
// are we modulating the period of the next channel?
if ((m_adkcon >> channum) & 0x10)
if (chan->atper)
{
nextper = chan->dat;
nextvol = -1;
@ -297,7 +315,7 @@ void paula_8364_device::sound_stream_update(sound_stream &stream, std::vector<re
}
// are we modulating the volume of the next channel?
else if ((m_adkcon >> channum) & 0x01)
else if (chan->atvol)
{
nextper = -1;
nextvol = chan->dat;
@ -329,7 +347,7 @@ void paula_8364_device::sound_stream_update(sound_stream &stream, std::vector<re
chan->curlocation++;
if (chan->dma_enabled && !(chan->curlocation & 1))
{
chan->dat = m_mem_r(chan->curlocation);
chan->dat = m_chipmem_r(chan->curlocation);
if (chan->curlength != 0)
chan->curlength--;
@ -344,7 +362,7 @@ void paula_8364_device::sound_stream_update(sound_stream &stream, std::vector<re
// For example: Xenon 2 sets up location=0x63298 length=0x20
// for silencing channels on-the-fly without relying on irqs.
// Without this the location will read at 0x632d8 (data=0x7a7d), causing annoying buzzing.
chan->dat = m_mem_r(chan->curlocation);
chan->dat = m_chipmem_r(chan->curlocation);
}
}

View File

@ -55,14 +55,15 @@ public:
paula_8364_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration
auto mem_read_cb() { return m_mem_r.bind(); }
auto mem_read_cb() { return m_chipmem_r.bind(); }
auto int_cb() { return m_int_w.bind(); }
uint16_t reg_r(offs_t offset);
void reg_w(offs_t offset, uint16_t data);
void update();
template <u8 ch> void audio_channel_map(address_map &map);
void dmacon_set(u16 data);
void adkcon_set(u16 data);
protected:
// device-level overrides
virtual void device_start() override;
@ -72,46 +73,12 @@ protected:
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
private:
enum
{
CHAN_0 = 0,
CHAN_1 = 1,
CHAN_2 = 2,
CHAN_3 = 3
};
enum
{
REG_DMACONR = 0x02/2,
REG_ADKCONR = 0x10/2,
REG_DMACON = 0x96/2,
REG_INTREQ = 0x9c/2,
REG_ADKCON = 0x9e/2,
REG_AUD0LCH = 0xa0/2, // to be moved, not part of paula
REG_AUD0LCL = 0xa2/2, // to be moved, not part of paula
REG_AUD0LEN = 0xa4/2,
REG_AUD0PER = 0xa6/2,
REG_AUD0VOL = 0xa8/2,
REG_AUD0DAT = 0xaa/2,
REG_AUD1LCH = 0xb0/2, // to be moved, not part of paula
REG_AUD1LCL = 0xb2/2, // to be moved, not part of paula
REG_AUD1LEN = 0xb4/2,
REG_AUD1PER = 0xb6/2,
REG_AUD1VOL = 0xb8/2,
REG_AUD1DAT = 0xba/2,
REG_AUD2LCH = 0xc0/2, // to be moved, not part of paula
REG_AUD2LCL = 0xc2/2, // to be moved, not part of paula
REG_AUD2LEN = 0xc4/2,
REG_AUD2PER = 0xc6/2,
REG_AUD2VOL = 0xc8/2,
REG_AUD2DAT = 0xca/2,
REG_AUD3LCH = 0xd0/2, // to be moved, not part of paula
REG_AUD3LCL = 0xd2/2, // to be moved, not part of paula
REG_AUD3LEN = 0xd4/2,
REG_AUD3PER = 0xd6/2,
REG_AUD3VOL = 0xd8/2,
REG_AUD3DAT = 0xda/2
};
template <u8 ch> void audxlch_w(u16 data);
template <u8 ch> void audxlcl_w(u16 data);
template <u8 ch> void audxlen_w(u16 data);
template <u8 ch> void audxper_w(u16 data);
template <u8 ch> void audxvol_w(u16 data);
template <u8 ch> void audxdat_w(u16 data);
static constexpr int CLOCK_DIVIDER = 16;
@ -132,18 +99,18 @@ private:
uint16_t per;
uint16_t vol;
uint16_t dat;
bool atper;
bool atvol;
};
bool m_dma_master_enable;
void dma_reload(audio_channel *chan, bool startup);
// callbacks
devcb_read16 m_mem_r;
devcb_read16 m_chipmem_r;
devcb_write8 m_int_w;
// internal state
uint16_t m_dmacon;
uint16_t m_adkcon;
audio_channel m_channel[4];
sound_stream *m_stream;

View File

@ -11,6 +11,14 @@
- Chunky to planar converter
- 2x CIA chips
TODO:
- Reportedly the CD drive should be a Sony KSM-2101BAM,
schematics shows Akiko connected to a laconic "26-pin CD connector"
- NVRAM needs inheriting from i2c_24c08_device;
- Handle tray open/close events, needed at very least by:
\- cdtv:cdremix2 load sequences;
\- kangfu on cd32 as "out of memory" workaround;
***************************************************************************/
#include "emu.h"
@ -18,13 +26,18 @@
#include "coreutil.h"
#include "romload.h"
#define LOG_WARN (1U << 1) // Show warnings
#define LOG_REGS (1U << 2) // Show register r/w
#define LOG_CD (1U << 3) // Show CD interactions and commands
//**************************************************************************
// CONSTANTS / MACROS
//**************************************************************************
#define VERBOSE (LOG_WARN)
//#define LOG_OUTPUT_STREAM std::cout
#define LOG_AKIKO 0
#define LOG_AKIKO_CD 0
#include "logmacro.h"
#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
#define LOGREGS(...) LOGMASKED(LOG_REGS, __VA_ARGS__)
#define LOGCD(...) LOGMASKED(LOG_CD, __VA_ARGS__)
//**************************************************************************
@ -51,33 +64,33 @@ void akiko_device::device_add_mconfig(machine_config &config)
//-------------------------------------------------
akiko_device::akiko_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AKIKO, tag, owner, clock),
m_c2p_input_index(0),
m_c2p_output_index(0),
m_i2c_scl_out(0),
m_i2c_scl_dir(0),
m_i2c_sda_out(0),
m_i2c_sda_dir(0),
m_cdrom_track_index(0),
m_cdrom_lba_start(0),
m_cdrom_lba_end(0),
m_cdrom_lba_cur(0),
m_cdrom_readmask(0),
m_cdrom_readreqmask(0),
m_cdrom_dmacontrol(0),
m_cdrom_numtracks(0),
m_cdrom_speed(0),
m_cdrom_cmd_start(0),
m_cdrom_cmd_end(0),
m_cdrom_cmd_resp(0),
m_cdda(*this, "^cdda"),
m_cddevice(*this, "^cdrom"),
m_cdrom(nullptr),
m_cdrom_toc(nullptr),
m_dma_timer(nullptr),
m_frame_timer(nullptr),
m_mem_r(*this), m_mem_w(*this), m_int_w(*this),
m_scl_w(*this), m_sda_r(*this), m_sda_w(*this)
: device_t(mconfig, AKIKO, tag, owner, clock)
, m_c2p_input_index(0)
, m_c2p_output_index(0)
, m_i2c_scl_out(0)
, m_i2c_scl_dir(0)
, m_i2c_sda_out(0)
, m_i2c_sda_dir(0)
, m_cdrom_track_index(0)
, m_cdrom_lba_start(0)
, m_cdrom_lba_end(0)
, m_cdrom_lba_cur(0)
, m_cdrom_readmask(0)
, m_cdrom_readreqmask(0)
, m_cdrom_dmacontrol(0)
, m_cdrom_numtracks(0)
, m_cdrom_speed(0)
, m_cdrom_cmd_start(0)
, m_cdrom_cmd_end(0)
, m_cdrom_cmd_resp(0)
, m_cdda(*this, "^cdda")
, m_cddevice(*this, "^cdrom")
, m_cdrom(nullptr)
, m_cdrom_toc(nullptr)
, m_dma_timer(nullptr)
, m_frame_timer(nullptr)
, m_mem_r(*this), m_mem_w(*this), m_int_w(*this)
, m_scl_w(*this), m_sda_r(*this), m_sda_w(*this)
{
for (int i = 0; i < 8; i++)
{
@ -340,7 +353,7 @@ void akiko_device::cdda_stop()
if (m_cdda != nullptr)
{
m_cdda->stop_audio();
m_frame_timer->reset( );
m_frame_timer->reset();
}
}
@ -407,8 +420,7 @@ void akiko_device::set_cd_status(uint32_t status)
if ( m_cdrom_status[0] & m_cdrom_status[1] )
{
if (LOG_AKIKO_CD)
logerror("Akiko CD IRQ\n");
LOGCD("Akiko CD IRQ\n");
m_int_w(1);
}
@ -475,7 +487,7 @@ TIMER_CALLBACK_MEMBER(akiko_device::dma_proc)
datasize = 2048;
if ( !cdrom_read_data( m_cdrom, m_cdrom_lba_cur, &buf[16], CD_TRACK_MODE1 ) )
{
logerror( "AKIKO: Read error trying to read sector %08x!\n", m_cdrom_lba_cur );
LOGWARN( "AKIKO: Read error trying to read sector %08x!\n", m_cdrom_lba_cur );
return;
}
@ -483,12 +495,12 @@ TIMER_CALLBACK_MEMBER(akiko_device::dma_proc)
{
if ( !cdrom_read_subcode( m_cdrom, m_cdrom_lba_cur, &buf[16+datasize] ) )
{
logerror( "AKIKO: Read error trying to read subcode for sector %08x!\n", m_cdrom_lba_cur );
LOGWARN( "AKIKO: Read error trying to read subcode for sector %08x!\n", m_cdrom_lba_cur );
return;
}
}
if (LOG_AKIKO_CD) logerror( "DMA: sector %d - address %08x\n", m_cdrom_lba_cur, m_cdrom_address[0] + (index*4096) );
LOGCD( "DMA: sector %d - address %08x\n", m_cdrom_lba_cur, m_cdrom_address[0] + (index*4096) );
// write sector data to host memory
for (int i = 0; i < 2352; i++)
@ -569,7 +581,7 @@ TIMER_CALLBACK_MEMBER( akiko_device::cd_delayed_cmd )
if ( param == 0x05 )
{
if (LOG_AKIKO_CD) logerror( "AKIKO: Completing Command %d\n", param );
LOGCD( "AKIKO: Completing Command %d\n", param );
resp[0] = 0x06;
@ -607,7 +619,7 @@ void akiko_device::update_cdrom()
cmd &= 0x0f;
if (LOG_AKIKO_CD) logerror( "CDROM command: %02X\n", cmd );
LOGCD( "CDROM command: %02X\n", cmd );
if ( cmd == 0x02 ) /* pause audio */
{
@ -618,7 +630,7 @@ void akiko_device::update_cdrom()
cdda_pause(1);
m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff;
m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
setup_response( 2, resp );
}
@ -631,7 +643,7 @@ void akiko_device::update_cdrom()
cdda_pause(0);
m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff;
m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
setup_response( 2, resp );
}
@ -647,7 +659,7 @@ void akiko_device::update_cdrom()
cmd_addr += ( m_cdrom_cmd_start + i + 1 ) & 0xff;
}
m_cdrom_cmd_start = (m_cdrom_cmd_start+13) & 0xff;
m_cdrom_cmd_start = (m_cdrom_cmd_start + 13) & 0xff;
if ( m_cdrom == nullptr || m_cdrom_numtracks == 0 )
{
@ -665,8 +677,8 @@ void akiko_device::update_cdrom()
if ( cmdbuf[7] == 0x80 )
{
if (LOG_AKIKO_CD) logerror( "%s:AKIKO CD: Data read - start lba: %08x - end lba: %08x\n", machine().describe_context(), startpos, endpos );
m_cdrom_speed = (cmdbuf[8] & 0x40) ? 2 : 1;
LOGCD("AKIKO CD: Data read - start lba: %08x - end lba: %08x - divider speed: %d\n", startpos, endpos, m_cdrom_speed );
m_cdrom_lba_start = startpos;
m_cdrom_lba_end = endpos;
@ -674,13 +686,13 @@ void akiko_device::update_cdrom()
}
else if ( cmdbuf[10] & 0x04 )
{
logerror( "AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos );
LOGCD("AKIKO CD: Audio Play - start lba: %08x - end lba: %08x\n", startpos, endpos );
cdda_play(startpos, endpos - startpos);
resp[1] = 0x08;
}
else
{
if (LOG_AKIKO_CD) logerror( "AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos );
LOGCD("AKIKO CD: Seek - start lba: %08x - end lba: %08x\n", startpos, endpos );
m_cdrom_track_index = 0;
for( i = 0; i < cdrom_get_last_track(m_cdrom); i++ )
@ -700,7 +712,7 @@ void akiko_device::update_cdrom()
}
else if ( cmd == 0x05 ) /* read toc */
{
m_cdrom_cmd_start = (m_cdrom_cmd_start+3) & 0xff;
m_cdrom_cmd_start = (m_cdrom_cmd_start + 3) & 0xff;
machine().scheduler().timer_set( attotime::from_msec(1), timer_expired_delegate(FUNC(akiko_device::cd_delayed_cmd ), this), resp[0]);
@ -748,13 +760,16 @@ void akiko_device::update_cdrom()
resp[1] = 0x80;
}
// needed by cdtv:defcrown (would otherwise hardlock emulation)
m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
setup_response( 15, resp );
}
else if ( cmd == 0x07 ) /* check door status */
{
resp[1] = 0x01;
m_cdrom_cmd_start = (m_cdrom_cmd_start+2) & 0xff;
m_cdrom_cmd_start = (m_cdrom_cmd_start + 2) & 0xff;
if ( m_cdrom == nullptr || m_cdrom_numtracks == 0 )
resp[1] = 0x80;
@ -773,10 +788,8 @@ uint32_t akiko_device::read(offs_t offset)
{
uint32_t retval;
if ( LOG_AKIKO && offset < (0x30/4) )
{
logerror( "Reading AKIKO reg %0x [%s] at %s\n", offset, get_akiko_reg_name(offset), machine().describe_context());
}
if ( offset < (0x30/4) )
LOGREGS("Reading AKIKO reg %0x [%s] at %s\n", offset, get_akiko_reg_name(offset), machine().describe_context());
switch( offset )
{
@ -833,10 +846,8 @@ uint32_t akiko_device::read(offs_t offset)
void akiko_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
{
if ( LOG_AKIKO && offset < (0x30/4) )
{
logerror( "Writing AKIKO reg %0x [%s] with %08x at %s\n", offset, get_akiko_reg_name(offset), data, machine().describe_context());
}
if ( offset < (0x30/4) )
LOGREGS("Writing AKIKO reg %0x [%s] with %08x at %s\n", offset, get_akiko_reg_name(offset), data, machine().describe_context());
switch( offset )
{
@ -875,7 +886,7 @@ void akiko_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
break;
case 0x20/4: /* CDROM DMA SECTOR READ REQUEST WRITE */
if (LOG_AKIKO_CD) logerror( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask );
LOGCD( "Read Req mask W: data %08x - mem mask %08x\n", data, mem_mask );
if ( ACCESSING_BITS_16_31 )
{
m_cdrom_readreqmask = (data >> 16);
@ -884,7 +895,7 @@ void akiko_device::write(offs_t offset, uint32_t data, uint32_t mem_mask)
break;
case 0x24/4: /* CDROM DMA ENABLE? */
if (LOG_AKIKO_CD) logerror( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask );
LOGCD( "DMA enable W: data %08x - mem mask %08x\n", data, mem_mask );
if ( ( m_cdrom_dmacontrol ^ data ) & 0x04000000 )
{
if ( data & 0x04000000 )

View File

@ -0,0 +1,391 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Angelo Salese
/**************************************************************************************************
Amiga Copper
"Co-processor" contained inside Agnus,
it's a finite-state machine that either wait to a h/v video beam position or direct writes to
the Amiga chipset registers via program lists, ranging from "simple" video mode/color changes
to override sprite structures and beyond ...
TODO:
- Current handling is horizontally offset by several pixels, also cfr. amiga video notes
(screen geometry slightly incorrect?);
- Fix Bitplane offset corruption in some games (e.g. exile, zoola, AGA games).
Same as above?
- Fix missing/corrupt sprites in known nasty examples
(e.g. zoola status bar, parasol score layer on top, riskyw backgrounds);
- Find & verify cdang examples (especially for ECS/AGA);
- Find & verify examples that uses this non-canonically,
i.e. anything that may use this for controlling Paula, FDC or Blitter;
- Add debugger command for printing the current disassembler structure;
**************************************************************************************************/
#include "emu.h"
#include "amiga_copper.h"
#define LOG_WARN (1U << 1) // Show warnings
#define LOG_COPINS (1U << 2) // Show instruction fetches thru COPINS
#define LOG_INST (1U << 3) // Show live instruction fetches
#define LOG_PC (1U << 4) // Show PC fetches
#define LOG_CHIPSET (1U << 5) // Show custom chipset writes
#define VERBOSE (LOG_WARN)
#include "logmacro.h"
#define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__)
#define LOGCOPINS(...) LOGMASKED(LOG_COPINS, __VA_ARGS__)
#define LOGINST(...) LOGMASKED(LOG_INST, __VA_ARGS__)
#define LOGPC(...) LOGMASKED(LOG_PC, __VA_ARGS__)
#define LOGCHIPSET(...) LOGMASKED(LOG_CHIPSET, __VA_ARGS__)
// TODO: legacy inheritance, to be verified
#define COPPER_CYCLES_TO_PIXELS(x) (4 * (x))
//**************************************************************************
// GLOBAL VARIABLES
//**************************************************************************
// device type definition
DEFINE_DEVICE_TYPE(AMIGA_COPPER, amiga_copper_device, "amiga_copper", "Amiga Copper")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
//-------------------------------------------------
// amiga_copper_device - constructor
//-------------------------------------------------
amiga_copper_device::amiga_copper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AMIGA_COPPER, tag, owner, clock)
, m_host_cpu(*this, finder_base::DUMMY_TAG)
, m_chipmem_r(*this)
{
}
//-------------------------------------------------
// device_start - device-specific startup
//-------------------------------------------------
void amiga_copper_device::device_start()
{
m_host_space = &m_host_cpu->space(AS_PROGRAM);
m_chipmem_r.resolve_safe(0);
save_item(NAME(m_cdang_setting));
save_item(NAME(m_cdang_min_reg));
save_item(NAME(m_dma_master_enable));
save_item(NAME(m_dma_copen));
save_pointer(NAME(m_lc), 2);
save_item(NAME(m_pc));
save_item(NAME(m_state_waiting));
save_item(NAME(m_state_waitblit));
save_item(NAME(m_waitval));
save_item(NAME(m_waitmask));
// save_item(NAME(m_wait_offset));
save_item(NAME(m_pending_data));
save_item(NAME(m_pending_offset));
}
//-------------------------------------------------
// device_reset - device-specific reset
//-------------------------------------------------
void amiga_copper_device::device_reset()
{
m_cdang_setting = 0x40;
m_dma_master_enable = false;
m_dma_copen = false;
// TODO: latches states on soft reset
}
//**************************************************************************
// I/Os
//**************************************************************************
// $dff080-8d memory map
void amiga_copper_device::regs_map(address_map &map)
{
// TODO: location addresses belongs to Agnus
map(0x00, 0x01).w(FUNC(amiga_copper_device::copxlch_w<0>));
map(0x02, 0x03).w(FUNC(amiga_copper_device::copxlcl_w<0>));
map(0x04, 0x05).w(FUNC(amiga_copper_device::copxlch_w<1>));
map(0x06, 0x07).w(FUNC(amiga_copper_device::copxlcl_w<1>));
map(0x08, 0x09).rw(FUNC(amiga_copper_device::copjmpx_r<0>), FUNC(amiga_copper_device::copjmpx_w<0>));
map(0x0a, 0x0b).rw(FUNC(amiga_copper_device::copjmpx_r<1>), FUNC(amiga_copper_device::copjmpx_w<1>));
// map(0x0c, 0x0d).w(FUNC(amiga_copper_device::copins_w));
}
void amiga_copper_device::dmacon_set(u16 data)
{
m_dma_master_enable = bool(BIT(data, 9));
m_dma_copen = bool(BIT(data, 7));
}
/*
* COPCON 02E W A Copper Control Register
*
* ---- ---- ---- --x- CDANG (Copper Danger Mode) setting
*
* Documentation is quite contradictory here.
* This bit is supposed to allow Copper access of the
* lowest registers. OriginaL HRM states that it gives
* access to the blitter HW therefore $dff080 is the
* minimum for non-cdang and $dff040 for cdang mode.
*
* In ECS and AGA the latter limitation is lifted so Copper
* can access $dff000-$dff03f too, which basically means the
* possibility of accessing disk block regs.
* (i.e. the other regs are either r/o or wouldn't have much
* sense to write via Copper).
*
*/
void amiga_copper_device::copcon_w(u16 data)
{
bool cdang = bool(BIT(data, 1));
// TODO: is min_reg working even with BPLCON0 bit 0 unset?
m_cdang_setting = cdang ? m_cdang_min_reg : 0x40;
if (cdang)
LOGWARN("%s: cdang enabled\n", machine().describe_context());
if (data & 0xfffd)
LOGWARN("%s: COPCON undocumented setting write %04x\n", machine().describe_context(), data);
}
template <u8 ch> void amiga_copper_device::copxlch_w(u16 data)
{
// TODO: chipmem mask
m_lc[ch] = (m_lc[ch] & 0x0000ffff) | ((data & 0x001f) << 16);
}
template <u8 ch> void amiga_copper_device::copxlcl_w(u16 data)
{
m_lc[ch] = (m_lc[ch] & 0xffff0000) | ((data & 0xfffe) << 0);
}
/*
* COPJMP1 088 S A Copper restart at first location
* COPJMP2 08a S A Copper restart at second location
*
* Strobe register that loads the new PC into Copper.
* NB: Copper can use this to control its program flow and even
* do conditional branching by clever use of the skip opcode.
*
*/
template <u8 ch> void amiga_copper_device::copjmpx_w(u16 data)
{
set_pc(ch, false);
}
template <u8 ch> u16 amiga_copper_device::copjmpx_r()
{
if (!machine().side_effects_disabled())
set_pc(ch, false);
return m_host_space->unmap();
}
inline void amiga_copper_device::set_pc(u8 ch, bool is_sync)
{
m_pc = m_lc[ch];
m_state_waiting = false;
LOGPC("%s: COPJMP%d new PC = %08x%s\n"
, machine().describe_context()
, ch + 1
, m_pc
, is_sync ? " (resync)" : ""
);
}
/*
* COPINS 08c W A Copper instruction fetch identify
*
* Apparently this register is pinged every time that
* the Copper internally decodes an instruction value.
* Shouldn't have any implementation detail connected,
* de-facto it's a mailbox that can be listened by external HW
* (such as our debugger ;=).
*
*/
void amiga_copper_device::copins_w(u16 data)
{
LOGCOPINS("%s: COPINS %04x\n", machine().describe_context(), data);
}
//**************************************************************************
// Implementation getters/setters
//**************************************************************************
// executed on scanline == 0
void amiga_copper_device::vblank_sync()
{
set_pc(0, true);
}
int amiga_copper_device::execute_next(int xpos, int ypos, bool is_blitter_busy)
{
int word0, word1;
/* bail if not enabled */
if (!m_dma_master_enable || !m_dma_copen)
return 511;
/* flush any pending writes */
if (m_pending_offset)
{
//LOGCHIPSET("%02X.%02X: Write to %s = %04x\n", ypos, xpos / 2, s_custom_reg_names[m_copper_pending_offset & 0xff], m_copper_pending_data);
LOGCHIPSET("%02X.%02X: Write to %s = %04x\n",
ypos,
xpos / 2,
m_pending_offset << 1,
m_pending_data
);
m_host_space->write_word(0xdff000 | (m_pending_offset << 1), m_pending_data);
m_pending_offset = 0;
}
/* if we're waiting, check for a breakthrough */
if (m_state_waiting)
{
int curpos = (ypos << 8) | (xpos >> 1);
/* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & m_waitmask) >= (m_waitval & m_waitmask) &&
(!m_state_waitblit || !(is_blitter_busy)))
{
m_state_waiting = false;
//#if GUESS_COPPER_OFFSET
// return xpos + COPPER_CYCLES_TO_PIXELS(1 + m_wait_offset);
//#else
return xpos + COPPER_CYCLES_TO_PIXELS(1 + 3);
//#endif
}
/* otherwise, see if this line is even a possibility; if not, punt */
if (((curpos | 0xff) & m_waitmask) < (m_waitval & m_waitmask))
return 511;
/* else just advance another pixel */
xpos += COPPER_CYCLES_TO_PIXELS(1);
return xpos;
}
/* fetch the first data word */
// TODO: swap between ir0 and ir1 is controlled thru a selins latch
// (which can't be this instant too)
word0 = m_chipmem_r(m_pc);
m_host_space->write_word(0xdff08c, word0);
m_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
/* fetch the second data word */
word1 = m_chipmem_r(m_pc);
m_host_space->write_word(0xdff08c, word1);
m_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
LOGINST("%02X.%02X: Copper inst @ %06x = %04x %04x\n",
ypos,
xpos / 2,
m_pc - 4,
word0,
word1
);
/* handle a move */
if ((word0 & 1) == 0)
{
/* do the write if we're allowed */
word0 = (word0 >> 1) & 0xff;
if (word0 >= m_cdang_setting)
{
if (delay[word0] == 0)
{
//LOGCHIPSET("%02X.%02X: Write to %s = %04x\n", ypos, xpos / 2, s_custom_reg_names[word0 & 0xff], word1);
LOGCHIPSET("%02X.%02X: Write to %s = %04x\n",
ypos,
xpos / 2,
word0 << 1,
word1
);
m_host_space->write_word(0xdff000 | (word0 << 1), word1);
}
else // additional 2 cycles needed for non-Agnus registers
{
m_pending_offset = word0;
m_pending_data = word1;
}
}
/* illegal writes suspend until next frame */
else
{
LOGWARN("%02X.%02X: Aborting copper on illegal write\n", ypos, xpos / 2);
m_waitval = 0xffff;
m_waitmask = 0xffff;
m_state_waitblit = false;
m_state_waiting = true;
return 511;
}
}
else
{
/* extract common wait/skip values */
m_waitval = word0 & 0xfffe;
m_waitmask = word1 | 0x8001;
m_state_waitblit = (~word1 >> 15) & 1;
/* handle a wait */
if ((word1 & 1) == 0)
{
LOGINST(" Waiting for %04x & %04x (currently %04x)\n",
m_waitval,
m_waitmask,
(ypos << 8) | (xpos >> 1)
);
m_state_waiting = true;
}
/* handle a skip */
else
{
int curpos = (ypos << 8) | (xpos >> 1);
LOGINST(" Skipping if %04x & %04x (currently %04x)\n",
m_waitval,
m_waitmask,
(ypos << 8) | (xpos >> 1)
);
/* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & m_waitmask) >= (m_waitval & m_waitmask) &&
(!m_state_waitblit || !(is_blitter_busy)))
{
LOGINST(" Skipped\n");
/* count the cycles it out have taken to fetch the next instruction */
m_pc += 4;
xpos += COPPER_CYCLES_TO_PIXELS(2);
}
}
}
/* advance and consume 8 cycles */
return xpos;
}

View File

@ -0,0 +1,102 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Angelo Salese
/***************************************************************************
Amiga Copper
***************************************************************************/
#ifndef MAME_MACHINE_AMIGA_COPPER_H
#define MAME_MACHINE_AMIGA_COPPER_H
#pragma once
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
class amiga_copper_device : public device_t
{
public:
// construction/destruction
amiga_copper_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// config
template<class T> void set_host_cpu_tag(T &&tag) { m_host_cpu.set_tag(std::forward<T>(tag)); }
auto mem_read_cb() { return m_chipmem_r.bind(); }
void set_ecs_mode(bool ecs_mode) { m_cdang_min_reg = ecs_mode ? 0x00 : 0x20; }
// I/O operations
void regs_map(address_map &map);
void dmacon_set(u16 data);
void copcon_w(u16 data);
// getters/setters
void vblank_sync();
int execute_next(int xpos, int ypos, bool is_blitter_busy);
protected:
// device-level overrides
//virtual void device_validity_check(validity_checker &valid) const override;
//virtual void device_add_mconfig(machine_config &config) override;
virtual void device_start() override;
virtual void device_reset() override;
private:
required_device <cpu_device> m_host_cpu;
address_space *m_host_space = nullptr;
// callbacks
devcb_read16 m_chipmem_r;
bool m_dma_master_enable, m_dma_copen;
u16 m_cdang_setting, m_cdang_min_reg;
u32 m_lc[2], m_pc;
template <u8 ch> void copxlch_w(u16 data);
template <u8 ch> void copxlcl_w(u16 data);
template <u8 ch> void copjmpx_w(u16 data);
template <u8 ch> u16 copjmpx_r();
public:
void copins_w(u16 data);
private:
void set_pc(u8 ch, bool is_sync);
// internal state
bool m_state_waiting;
bool m_state_waitblit;
u16 m_waitval;
u16 m_waitmask;
u16 m_pending_offset;
u16 m_pending_data;
// int m_wait_offset;
// waitstate delays for copper
// basically anything that doesn't belong to Angus has a penalty for Copper
static constexpr u16 delay[256] =
{
1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 0x000 - 0x03e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x040 - 0x05e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x060 - 0x07e */
0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x080 - 0x09e */
1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 0x0a0 - 0x0de */
/* BPLxPTH/BPLxPTL */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x0e0 - 0x0fe */
/* BPLCON0-3,BPLMOD1-2 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x100 - 0x11e */
/* SPRxPTH/SPRxPTL */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x120 - 0x13e */
/* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x140 - 0x17e */
/* COLORxx */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x180 - 0x1be */
/* RESERVED */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0x1c0 - 0x1fe */
};
};
// device type definition
DECLARE_DEVICE_TYPE(AMIGA_COPPER, amiga_copper_device)
#endif // MAME_MACHINE_AMIGA_COPPER_H

View File

@ -1,10 +1,29 @@
// license:BSD-3-Clause
// copyright-holders:Olivier Galibert
/***************************************************************************
/**************************************************************************************************
Amiga floppy disk controller emulation
Amiga floppy disk controller emulation "Trackdisk"
***************************************************************************/
Contained inside MOS 8364 Paula device
TODO:
- Some games currently writes 2+ dsksync to the buffer (marked as "[FDC] dsksync" in SW list):
Current workaround:
1. comment out dma_write in DMA_WAIT_START handling and change the dma_state *only*;
2. remove all of the non-DMA_WAIT_START phase inside the dsksync sub-section;
NB: according to documentation syncing doesn't really write anything on the bus,
so technically this "workaround" is more correct.
However it unfortunately causes other SW regressions, most notably in Workbench.
- Other games trashes memory or refuses to boot, in a few instances randomly
(marked as "[FDC] with adkcon=1100", implies dsksync disabled):
they often uses the AmigaDOS trackdisk BIOS functions, which may be expecting a
different timing. May be worth testing this out with the SDK;
- "[FDC] format" or in general writing to disks doesn't work properly.
i.e. formatting a disk in any Workbench version will cause a system crash once it completes.
- Fix ready line read handling;
- FDC LED output callback;
**************************************************************************************************/
#include "emu.h"
@ -24,7 +43,7 @@
#define LOGDMA(...) LOGMASKED(LOG_DMA, __VA_ARGS__)
#define LOGSYNC(...) LOGMASKED(LOG_SYNC, __VA_ARGS__)
DEFINE_DEVICE_TYPE(AMIGA_FDC, amiga_fdc_device, "amiga_fdc", "Amiga FDC")
DEFINE_DEVICE_TYPE(AMIGA_FDC, amiga_fdc_device, "amiga_fdc", "Amiga \"Trackdisk\" FDC")
void amiga_fdc_device::floppy_formats(format_registration &fr)
{
@ -33,16 +52,16 @@ void amiga_fdc_device::floppy_formats(format_registration &fr)
fr.add(FLOPPY_IPF_FORMAT);
}
amiga_fdc_device::amiga_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
device_t(mconfig, AMIGA_FDC, tag, owner, clock),
m_write_index(*this),
m_read_dma(*this),
m_write_dma(*this),
m_write_dskblk(*this),
m_write_dsksyn(*this),
m_leds(*this, "led%u", 1U),
m_fdc_led(*this, "fdc_led"),
floppy(nullptr), t_gen(nullptr), dsklen(0), pre_dsklen(0), dsksync(0), dskbyt(0), adkcon(0), dmacon(0), dskpt(0), dma_value(0), dma_state(0)
amiga_fdc_device::amiga_fdc_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: device_t(mconfig, AMIGA_FDC, tag, owner, clock)
, m_write_index(*this)
, m_read_dma(*this)
, m_write_dma(*this)
, m_write_dskblk(*this)
, m_write_dsksyn(*this)
, m_leds(*this, "led%u", 1U)
, m_fdc_led(*this, "fdc_led")
, floppy(nullptr), t_gen(nullptr), dsklen(0), pre_dsklen(0), dsksync(0), dskbyt(0), adkcon(0), dmacon(0), dskpt(0), dma_value(0), dma_state(0)
{
}
@ -70,7 +89,6 @@ void amiga_fdc_device::device_start()
t_gen = timer_alloc(0);
}
void amiga_fdc_device::device_reset()
{
floppy = nullptr;
@ -267,14 +285,7 @@ void amiga_fdc_device::live_run(const attotime &limit)
if(!(dskbyt & 0x2000)) {
if(cur_live.shift_reg == dsksync) {
if(adkcon & 0x0400) {
// FIXME: exact dsksync behaviour
// - Some games currently writes two dsksync to the buffer (marked as "[FDC] dsksync"),
// removing one will make most of them happy.
// This is reported as 0-lower cylinder good and everything else as bad in the ATK suite;
// - Some games trashes memory, mostly the ones with "[FDC] dsksync bootblock":
// they attempt to load the tracks in AmigaDOS in the same way that's done by the
// Kickstart to check if the disk is bootable.
// This is reported as 0-upper cylinder bad in the ATK suite;
// FIXME: exact dsksync behaviour, cfr. note at top
if(dma_state == DMA_WAIT_START) {
cur_live.bit_counter = 0;
@ -298,8 +309,6 @@ void amiga_fdc_device::live_run(const attotime &limit)
} else if(cur_live.bit_counter != 8)
cur_live.bit_counter = 0;
}
//else
// LOGSYNC("%s: no DSKSYNC\n", this->tag());
dskbyt |= 0x1000;
m_write_dsksyn(1);
@ -320,13 +329,12 @@ void amiga_fdc_device::live_run(const attotime &limit)
dma_state = DMA_RUNNING_BYTE_1;
break;
case DMA_RUNNING_BYTE_1: {
case DMA_RUNNING_BYTE_1:
dma_value |= cur_live.shift_reg & 0xff;
dma_write(dma_value);
break;
}
}
}
} else {
if(cur_live.bit_counter != 8)
fatalerror("amiga_fdc_device::live_run - cur_live.bit_counter != 8\n");
@ -366,9 +374,9 @@ void amiga_fdc_device::dma_check()
bool was_writing = dskbyt & 0x2000;
dskbyt &= 0x9fff;
if(dma_enabled()) {
LOGDMA("%s: DMA start dskpt=%08x dsklen=%04x dir=%s adkcon=%04x dsksync=%04x\n",
LOGDMA("%s: DMA start dskpt=%08x dsklen=%04x dir=%s adkcon=%04x dsksync=%04x state=%d\n",
machine().describe_context(),
dskpt, dsklen & 0x3fff, BIT(dsklen, 14) ? "RAM->disk" : "disk->RAM", adkcon, dsksync
dskpt, dsklen & 0x3fff, BIT(dsklen, 14) ? "RAM->disk" : "disk->RAM", adkcon, dsksync, dma_state
);
if(dma_state == IDLE) {
@ -454,6 +462,9 @@ void amiga_fdc_device::dsksync_w(uint16_t data)
void amiga_fdc_device::dmacon_set(uint16_t data)
{
live_sync();
// log changes only
// FIXME: needs better boilerplate code on top level
if ((data & 0x210) != (dmacon & 0x210))
LOGDMA("%s: DMACON set DSKEN %d DMAEN %d (%04x)\n", machine().describe_context(), BIT(data, 4), BIT(data, 9), data);
dmacon = data;
dma_check();

View File

@ -60,14 +60,14 @@ namespace {
class alg_state : public amiga_state
{
public:
alg_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_laserdisc(*this, "laserdisc"),
m_gun1x(*this, "GUN1X"),
m_gun1y(*this, "GUN1Y"),
m_gun2x(*this, "GUN2X"),
m_gun2y(*this, "GUN2Y"),
m_triggers(*this, "TRIGGERS")
alg_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_laserdisc(*this, "laserdisc")
, m_gun1x(*this, "GUN1X")
, m_gun1y(*this, "GUN1Y")
, m_gun2x(*this, "GUN2X")
, m_gun2y(*this, "GUN2Y")
, m_triggers(*this, "TRIGGERS")
{ }
DECLARE_CUSTOM_INPUT_MEMBER(lightgun_pos_r);
@ -210,10 +210,10 @@ void alg_state::a500_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(alg_state::cia_r), FUNC(alg_state::cia_w));
map(0xc00000, 0xd7ffff).rw(FUNC(alg_state::custom_chip_r), FUNC(alg_state::custom_chip_w));
map(0xc00000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(alg_state::custom_chip_r), FUNC(alg_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(alg_state::custom_chip_r), FUNC(alg_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(alg_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -332,13 +332,19 @@ void alg_state::alg_r1(machine_config &config)
M68000(config, m_maincpu, amiga_state::CLK_7M_NTSC);
m_maincpu->set_addrmap(AS_PROGRAM, &alg_state::main_map_r1);
ADDRESS_MAP_BANK(config, "overlay").set_map(&alg_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&alg_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&alg_state::ocs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
// Video hardware
ntsc_video(config);
AMIGA_COPPER(config, m_copper, amiga_state::CLK_7M_NTSC);
m_copper->set_host_cpu_tag(m_maincpu);
m_copper->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_copper->set_ecs_mode(false);
SONY_LDP1450(config, m_laserdisc, 9600);
m_laserdisc->set_screen("screen");
m_laserdisc->set_overlay(512*2, 262, FUNC(amiga_state::screen_update_amiga));

View File

@ -4,6 +4,12 @@
Commodore Amiga
Notes:
- On Kickstart 2.0 onward holding down both port 1 fire buttons
will bring you to the Amiga Early Startup Control Screen.
This gives you several diagnostic options, including booting from
non-DF0 drive, switch video modes and test expansion boards.
***************************************************************************/
#include "emu.h"
@ -227,10 +233,10 @@ DEFINE_DEVICE_TYPE(A1000_KBRESET, a1000_kbreset_device, "a1000kbrst", "Amiga 100
class a1000_state : public amiga_state
{
public:
a1000_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_bootrom(*this, "bootrom"),
m_wom(*this, "wom")
a1000_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_bootrom(*this, "bootrom")
, m_wom(*this, "wom")
{ }
void init_pal();
@ -256,12 +262,12 @@ private:
class a2000_state : public amiga_state
{
public:
a2000_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_rtc(*this, "u65"),
m_zorro(*this, "zorrobus"),
m_zorro2_int2(0),
m_zorro2_int6(0)
a2000_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_rtc(*this, "u65")
, m_zorro(*this, "zorrobus")
, m_zorro2_int2(0)
, m_zorro2_int6(0)
{ }
void init_pal();
@ -296,11 +302,11 @@ private:
class a500_state : public amiga_state
{
public:
a500_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_side(*this, EXP_SLOT_TAG),
m_side_int2(0),
m_side_int6(0)
a500_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_side(*this, EXP_SLOT_TAG)
, m_side_int2(0)
, m_side_int6(0)
{ }
void init_pal();
@ -331,14 +337,14 @@ private:
class cdtv_state : public amiga_state
{
public:
cdtv_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_rtc(*this, "u61"),
m_dmac(*this, "u36"),
m_tpi(*this, "u32"),
m_cdrom(*this, "cdrom"),
m_dmac_irq(0),
m_tpi_irq(0)
cdtv_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_rtc(*this, "u61")
, m_dmac(*this, "u36")
, m_tpi(*this, "u32")
, m_cdrom(*this, "cdrom")
, m_dmac_irq(0)
, m_tpi_irq(0)
{ }
void init_pal();
@ -381,8 +387,8 @@ private:
class a3000_state : public amiga_state
{
public:
a3000_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag)
a3000_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
{ }
u32 scsi_r(offs_t offset, u32 mem_mask = ~0);
@ -404,12 +410,12 @@ private:
class a500p_state : public amiga_state
{
public:
a500p_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_rtc(*this, "u9"),
m_side(*this, EXP_SLOT_TAG),
m_side_int2(0),
m_side_int6(0)
a500p_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_rtc(*this, "u9")
, m_side(*this, EXP_SLOT_TAG)
, m_side_int2(0)
, m_side_int6(0)
{ }
u16 clock_r(offs_t offset);
@ -441,9 +447,9 @@ private:
class a600_state : public amiga_state
{
public:
a600_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_gayle_int2(0)
a600_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_gayle_int2(0)
{ }
DECLARE_WRITE_LINE_MEMBER( gayle_int2_w );
@ -466,9 +472,9 @@ private:
class a1200_state : public amiga_state
{
public:
a1200_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_gayle_int2(0)
a1200_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_gayle_int2(0)
{ }
DECLARE_WRITE_LINE_MEMBER( gayle_int2_w );
@ -491,14 +497,14 @@ private:
class a4000_state : public amiga_state
{
public:
a4000_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_ata(*this, "ata"),
m_ramsey_config(0),
m_gary_coldboot(1),
m_gary_timeout(0),
m_gary_toenb(0),
m_ide_interrupt(0)
a4000_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_ata(*this, "ata")
, m_ramsey_config(0)
, m_gary_coldboot(1)
, m_gary_timeout(0)
, m_gary_toenb(0)
, m_ide_interrupt(0)
{ }
u32 scsi_r(offs_t offset, u32 mem_mask = ~0);
@ -536,10 +542,10 @@ private:
class cd32_state : public amiga_state
{
public:
cd32_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_player_ports(*this, {"p1_cd32_buttons", "p2_cd32_buttons"}),
m_cdda(*this, "cdda")
cd32_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_player_ports(*this, {"p1_cd32_buttons", "p2_cd32_buttons"})
, m_cdda(*this, "cdda")
{ }
DECLARE_WRITE_LINE_MEMBER( akiko_int_w );
@ -1192,7 +1198,7 @@ void a1000_state::a1000_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(a1000_state::cia_r), FUNC(a1000_state::cia_w));
map(0xc00000, 0xdfffff).rw(FUNC(a1000_state::custom_chip_r), FUNC(a1000_state::custom_chip_w));
map(0xc00000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(a1000_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf80000, 0xfbffff).m(m_bootrom, FUNC(address_map_bank_device::amap16));
@ -1246,12 +1252,12 @@ void a2000_state::a2000_mem(address_map &map)
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(a2000_state::cia_r), FUNC(a2000_state::cia_w));
map(0xc00000, 0xc7ffff).ram();
map(0xc80000, 0xd7ffff).rw(FUNC(a2000_state::custom_chip_r), FUNC(a2000_state::custom_chip_w));
map(0xc80000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xdbffff).noprw();
map(0xdc0000, 0xdc7fff).rw(FUNC(a2000_state::clock_r), FUNC(a2000_state::clock_w));
map(0xdc8000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(a2000_state::custom_chip_r), FUNC(a2000_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(a2000_state::custom_chip_r), FUNC(a2000_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(a2000_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf00000, 0xf7ffff).noprw(); // cartridge space
@ -1264,10 +1270,10 @@ void a500_state::a500_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(a500_state::cia_r), FUNC(a500_state::cia_w));
map(0xc00000, 0xd7ffff).rw(FUNC(a500_state::custom_chip_r), FUNC(a500_state::custom_chip_w));
map(0xc00000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(a500_state::custom_chip_r), FUNC(a500_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(a500_state::custom_chip_r), FUNC(a500_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(a500_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf00000, 0xf7ffff).noprw(); // cartridge space
@ -1280,13 +1286,13 @@ void cdtv_state::cdtv_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(cdtv_state::cia_r), FUNC(cdtv_state::cia_w));
map(0xc00000, 0xd7ffff).rw(FUNC(cdtv_state::custom_chip_r), FUNC(cdtv_state::custom_chip_w));
map(0xc00000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xdbffff).noprw();
map(0xdc0000, 0xdc7fff).rw(FUNC(cdtv_state::clock_r), FUNC(cdtv_state::clock_w));
map(0xdc8000, 0xdc87ff).mirror(0x7800).ram().share("sram");
map(0xdd0000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(cdtv_state::custom_chip_r), FUNC(cdtv_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(cdtv_state::custom_chip_r), FUNC(cdtv_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe3ffff).mirror(0x40000).ram().share("memcard");
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf00000, 0xf3ffff).mirror(0x40000).rom().region("cdrom", 0);
@ -1303,12 +1309,12 @@ void a3000_state::a3000_mem(address_map &map)
map.unmap_value_high();
map(0x00000000, 0x001fffff).m(m_overlay, FUNC(address_map_bank_device::amap32));
map(0x00b80000, 0x00bfffff).rw(FUNC(a3000_state::cia_r), FUNC(a3000_state::cia_w));
map(0x00c00000, 0x00cfffff).rw(FUNC(a3000_state::custom_chip_r), FUNC(a3000_state::custom_chip_w));
map(0x00c00000, 0x00cfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0x00d00000, 0x00dbffff).noprw();
map(0x00dc0000, 0x00dcffff).rw("rtc", FUNC(rp5c01_device::read), FUNC(rp5c01_device::write)).umask32(0x000000ff);
map(0x00dd0000, 0x00ddffff).rw(FUNC(a3000_state::scsi_r), FUNC(a3000_state::scsi_w));
map(0x00de0000, 0x00deffff).rw(FUNC(a3000_state::motherboard_r), FUNC(a3000_state::motherboard_w));
map(0x00df0000, 0x00dfffff).rw(FUNC(a3000_state::custom_chip_r), FUNC(a3000_state::custom_chip_w));
map(0x00df0000, 0x00dfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0x00e80000, 0x00efffff).noprw(); // autoconfig space (installed by devices)
map(0x00f00000, 0x00f7ffff).noprw(); // cartridge space
map(0x00f80000, 0x00ffffff).rom().region("kickstart", 0);
@ -1323,12 +1329,12 @@ void a500p_state::a500p_mem(address_map &map)
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(a500p_state::cia_r), FUNC(a500p_state::cia_w));
map(0xc00000, 0xc7ffff).ram();
map(0xc80000, 0xd7ffff).rw(FUNC(a500p_state::custom_chip_r), FUNC(a500p_state::custom_chip_w));
map(0xc80000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xdbffff).noprw();
map(0xdc0000, 0xdc7fff).rw(FUNC(a500p_state::clock_r), FUNC(a500p_state::clock_w));
map(0xdc8000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(a500p_state::custom_chip_r), FUNC(a500p_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(a500p_state::custom_chip_r), FUNC(a500p_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(a500p_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -1352,7 +1358,7 @@ void a600_state::a600_mem(address_map &map)
map(0xdc0000, 0xdcffff).noprw(); // rtc
map(0xdd0000, 0xddffff).noprw(); // reserved (dma controller)
map(0xde0000, 0xdeffff).rw("gayle", FUNC(gayle_device::gayle_id_r), FUNC(gayle_device::gayle_id_w));
map(0xdf0000, 0xdfffff).rw(FUNC(a600_state::custom_chip_r), FUNC(a600_state::custom_chip_w));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(a600_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf00000, 0xf7ffff).noprw(); // cartridge space
@ -1377,7 +1383,7 @@ void a1200_state::a1200_mem(address_map &map)
map(0xdc0000, 0xdcffff).noprw(); // rtc
map(0xdd0000, 0xddffff).noprw(); // reserved (dma controller)
map(0xde0000, 0xdeffff).rw("gayle", FUNC(gayle_device::gayle_id_r), FUNC(gayle_device::gayle_id_w));
map(0xdf0000, 0xdfffff).rw(FUNC(a1200_state::custom_chip_r), FUNC(a1200_state::custom_chip_w));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap32));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(a1200_state::rom_mirror32_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf00000, 0xf7ffff).noprw(); // cartridge space
@ -1393,7 +1399,7 @@ void a4000_state::a4000_mem(address_map &map)
map(0x00a00000, 0x00b7ffff).noprw();
map(0x00b80000, 0x00beffff).noprw();
map(0x00bf0000, 0x00bfffff).rw(FUNC(a4000_state::cia_r), FUNC(a4000_state::cia_w));
map(0x00c00000, 0x00cfffff).rw(FUNC(a4000_state::custom_chip_r), FUNC(a4000_state::custom_chip_w));
map(0x00c00000, 0x00cfffff).m(m_chipset, FUNC(address_map_bank_device::amap32));
map(0x00d00000, 0x00d9ffff).noprw();
map(0x00da0000, 0x00dbffff).noprw();
map(0x00dc0000, 0x00dcffff).rw("rtc", FUNC(rp5c01_device::read), FUNC(rp5c01_device::write)).umask32(0x000000ff);
@ -1401,7 +1407,7 @@ void a4000_state::a4000_mem(address_map &map)
map(0x00dd1000, 0x00dd3fff).rw(FUNC(a4000_state::ide_r), FUNC(a4000_state::ide_w));
map(0x00dd4000, 0x00ddffff).noprw();
map(0x00de0000, 0x00deffff).rw(FUNC(a4000_state::motherboard_r), FUNC(a4000_state::motherboard_w));
map(0x00df0000, 0x00dfffff).rw(FUNC(a4000_state::custom_chip_r), FUNC(a4000_state::custom_chip_w));
map(0x00df0000, 0x00dfffff).m(m_chipset, FUNC(address_map_bank_device::amap32));
map(0x00e00000, 0x00e7ffff).nopw().r(FUNC(a4000_state::rom_mirror32_r));
map(0x00e80000, 0x00efffff).noprw(); // zorro2 autoconfig space (installed by devices)
map(0x00f00000, 0x00f7ffff).noprw(); // cartridge space
@ -1428,7 +1434,7 @@ void cd32_state::cd32_mem(address_map &map)
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap32));
map(0xb80000, 0xb8003f).rw("akiko", FUNC(akiko_device::read), FUNC(akiko_device::write));
map(0xbf0000, 0xbfffff).rw(FUNC(cd32_state::cia_r), FUNC(cd32_state::gayle_cia_w));
map(0xc00000, 0xdfffff).rw(FUNC(cd32_state::custom_chip_r), FUNC(cd32_state::custom_chip_w));
map(0xc00000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap32));
map(0xe00000, 0xe7ffff).rom().region("kickstart", 0x80000);
map(0xe80000, 0xf7ffff).noprw();
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -1617,6 +1623,13 @@ void amiga_state::amiga_base(machine_config &config)
FLOPPY_CONNECTOR(config, "fdc:2", amiga_floppies, nullptr, amiga_fdc_device::floppy_formats).enable_sound(true);
FLOPPY_CONNECTOR(config, "fdc:3", amiga_floppies, nullptr, amiga_fdc_device::floppy_formats).enable_sound(true);
// TODO: shouldn't have a clock
// (finite state machine, controlled by Agnus beams)
AMIGA_COPPER(config, m_copper, amiga_state::CLK_7M_PAL);
m_copper->set_host_cpu_tag(m_maincpu);
m_copper->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_copper->set_ecs_mode(false);
// rs232
rs232_port_device &rs232(RS232_PORT(config, "rs232", default_rs232_devices, nullptr));
rs232.rxd_handler().set(FUNC(amiga_state::rs232_rx_w));
@ -1641,6 +1654,7 @@ void amiga_state::amiga_base(machine_config &config)
SOFTWARE_LIST(config, "apps_list").set_original("amiga_apps");
SOFTWARE_LIST(config, "flop_list").set_original("amiga_flop");
SOFTWARE_LIST(config, "ocs_list").set_original("amigaocs_flop");
SOFTWARE_LIST(config, "demos_list").set_original("amiga_demos");
}
void a1000_state::a1000(machine_config &config)
@ -1661,8 +1675,9 @@ void a1000_state::a1000(machine_config &config)
.set_delays(attotime::from_msec(152), attotime::from_usec(176), attotime::from_msec(704))
.kbrst_cb().set(FUNC(a1000_state::kbreset_w));
ADDRESS_MAP_BANK(config, "overlay").set_map(&a1000_state::a1000_overlay_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a1000_state::a1000_overlay_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, "bootrom").set_map(&a1000_state::a1000_bootrom_map).set_options(ENDIANNESS_BIG, 16, 19, 0x40000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a1000_state::ocs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
SOFTWARE_LIST(config, "a1000_list").set_original("amiga_a1000");
}
@ -1698,7 +1713,9 @@ void a2000_state::a2000(machine_config &config)
.set_delays(attotime::from_msec(112), attotime::from_msec(74), attotime::from_msec(1294))
.kbrst_cb().set(FUNC(a2000_state::kbreset_w));
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a2000_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a2000_state::ecs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
m_copper->set_ecs_mode(true);
// real-time clock
MSM6242(config, m_rtc, XTAL(32'768));
@ -1747,7 +1764,8 @@ void a500_state::a500(machine_config &config)
kbd.kdat_handler().set("cia_0", FUNC(mos8520_device::sp_w));
kbd.krst_handler().set(FUNC(amiga_state::kbreset_w));
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_1mb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a500_state::overlay_1mb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a500_state::ocs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
// cpu slot
EXP_SLOT(config, m_side, 0).set_space(m_maincpu, AS_PROGRAM);
@ -1797,7 +1815,10 @@ void cdtv_state::cdtv(machine_config &config)
u62.set_addrmap(AS_PROGRAM, &cdtv_state::lcd_mem);
#endif
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_1mb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&cdtv_state::overlay_1mb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
// FIXME: CDTV is actually ECS Agnus but OCS Denise
ADDRESS_MAP_BANK(config, m_chipset).set_map(&cdtv_state::ecs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
m_copper->set_ecs_mode(true);
// standard sram
NVRAM(config, "sram", nvram_device::DEFAULT_ALL_0);
@ -1860,7 +1881,9 @@ void a3000_state::a3000(machine_config &config)
kbd.kclk_handler().set("cia_0", FUNC(mos8520_device::cnt_w));
kbd.kdat_handler().set("cia_0", FUNC(mos8520_device::sp_w));
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_1mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a3000_state::overlay_1mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a3000_state::ecs_map).set_options(ENDIANNESS_BIG, 32, 9, 0x200);
m_copper->set_ecs_mode(true);
// real-time clock
RP5C01(config, "rtc", XTAL(32'768));
@ -1895,9 +1918,11 @@ void a500p_state::a500p(machine_config &config)
auto &kbd(AMIGA_KEYBOARD_INTERFACE(config, "kbd", a500_keyboard_devices, "a500_us"));
kbd.kclk_handler().set("cia_0", FUNC(mos8520_device::cnt_w));
kbd.kdat_handler().set("cia_0", FUNC(mos8520_device::sp_w));
kbd.krst_handler().set(FUNC(amiga_state::kbreset_w));
kbd.krst_handler().set(FUNC(a500p_state::kbreset_w));
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_1mb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a500p_state::overlay_1mb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a500p_state::ecs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
m_copper->set_ecs_mode(true);
// real-time clock
MSM6242(config, m_rtc, XTAL(32'768));
@ -1935,9 +1960,11 @@ void a600_state::a600(machine_config &config)
auto &kbd(AMIGA_KEYBOARD_INTERFACE(config, "kbd", a600_keyboard_devices, "a600_us"));
kbd.kclk_handler().set("cia_0", FUNC(mos8520_device::cnt_w));
kbd.kdat_handler().set("cia_0", FUNC(mos8520_device::sp_w));
kbd.krst_handler().set(FUNC(amiga_state::kbreset_w));
kbd.krst_handler().set(FUNC(a600_state::kbreset_w));
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_2mb_map16).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a600_state::overlay_2mb_map16).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a600_state::ecs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
m_copper->set_ecs_mode(true);
gayle_device &gayle(GAYLE(config, "gayle", amiga_state::CLK_28M_PAL / 2));
gayle.set_id(a600_state::GAYLE_ID);
@ -1977,20 +2004,21 @@ void a1200_state::a1200(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &a1200_state::a1200_mem);
m_maincpu->set_cpu_space(AS_PROGRAM);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
amiga_base(config);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a1200_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a1200_state::aga_map).set_options(ENDIANNESS_BIG, 32, 9, 0x200);
m_copper->set_ecs_mode(true);
// keyboard
auto &kbd(AMIGA_KEYBOARD_INTERFACE(config, "kbd", amiga_keyboard_devices, "a1200_us")); // FIXME: replace with Amiga 1200 devices when we have mask ROM dump
// FIXME: replace with Amiga 1200 devices when we have mask ROM dump
auto &kbd(AMIGA_KEYBOARD_INTERFACE(config, "kbd", amiga_keyboard_devices, "a1200_us"));
kbd.kclk_handler().set("cia_0", FUNC(mos8520_device::cnt_w));
kbd.kdat_handler().set("cia_0", FUNC(mos8520_device::sp_w));
kbd.krst_handler().set(FUNC(amiga_state::kbreset_w));
kbd.krst_handler().set(FUNC(a1200_state::kbreset_w));
m_screen->set_screen_update(FUNC(amiga_state::screen_update_amiga_aga));
config.device_remove("palette");
MCFG_VIDEO_START_OVERRIDE(amiga_state, amiga_aga)
gayle_device &gayle(GAYLE(config, "gayle", amiga_state::CLK_28M_PAL / 2));
@ -2038,10 +2066,12 @@ void a4000_state::a4000(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &a4000_state::a4000_mem);
m_maincpu->set_cpu_space(AS_PROGRAM);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
amiga_base(config);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&a4000_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&a4000_state::aga_map).set_options(ENDIANNESS_BIG, 32, 9, 0x200);
m_copper->set_ecs_mode(true);
// keyboard
auto &kbd(AMIGA_KEYBOARD_INTERFACE(config, "kbd", amiga_keyboard_devices, "a2000_us"));
kbd.kclk_handler().set("cia_0", FUNC(mos8520_device::cnt_w));
@ -2049,8 +2079,6 @@ void a4000_state::a4000(machine_config &config)
m_screen->set_screen_update(FUNC(amiga_state::screen_update_amiga_aga));
config.device_remove("palette");
MCFG_VIDEO_START_OVERRIDE(amiga_state, amiga_aga)
// real-time clock
@ -2111,10 +2139,15 @@ void cd32_state::cd32(machine_config &config)
m_maincpu->set_addrmap(AS_PROGRAM, &cd32_state::cd32_mem);
m_maincpu->set_cpu_space(AS_PROGRAM);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
amiga_base(config);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&cd32_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&cd32_state::aga_map).set_options(ENDIANNESS_BIG, 32, 9, 0x200);
m_copper->set_ecs_mode(true);
// disable floppy as default (available only via back port as expansion)
subdevice<floppy_connector>("fdc:0")->set_default_option(nullptr);
I2C_24C08(config, "i2cmem", 0); // AT24C08N
akiko_device &akiko(AKIKO(config, "akiko", 0));
@ -2127,8 +2160,6 @@ void cd32_state::cd32(machine_config &config)
m_screen->set_screen_update(FUNC(amiga_state::screen_update_amiga_aga));
config.device_remove("palette");
MCFG_VIDEO_START_OVERRIDE(amiga_state, amiga_aga)
CDDA(config, m_cdda);
@ -2138,8 +2169,9 @@ void cd32_state::cd32(machine_config &config)
m_cia_0->pa_wr_callback().set(FUNC(cd32_state::akiko_cia_0_port_a_write));
m_cia_0->sp_wr_callback().set_nop();
CDROM(config, "cdrom").set_interface("cd32_cdrom");
SOFTWARE_LIST(config, "cd_list").set_original("cd32");
CDROM(config, "cdrom").set_interface("cdrom");
SOFTWARE_LIST(config, "cd32_list").set_original("cd32");
SOFTWARE_LIST(config, "cd_list").set_original("cdtv");
}
void cd32_state::cd32n(machine_config &config)

View File

@ -67,8 +67,7 @@ public:
: amiga_state(mconfig, type, tag)
, m_bios_region(*this, "user2")
, m_rom_board(*this, "user3")
{
}
{ }
void arcadia(machine_config &config);
void argh(machine_config &config);
@ -212,10 +211,10 @@ void arcadia_amiga_state::a500_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(arcadia_amiga_state::cia_r), FUNC(arcadia_amiga_state::cia_w));
map(0xc00000, 0xd7ffff).rw(FUNC(arcadia_amiga_state::custom_chip_r), FUNC(arcadia_amiga_state::custom_chip_w));
map(0xc00000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(arcadia_amiga_state::custom_chip_r), FUNC(arcadia_amiga_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(arcadia_amiga_state::custom_chip_r), FUNC(arcadia_amiga_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(arcadia_amiga_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -294,7 +293,22 @@ static INPUT_PORTS_START( arcadia )
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_COIN2 ) PORT_CHANGED_MEMBER(DEVICE_SELF, arcadia_amiga_state,coin_changed_callback, 1)
INPUT_PORTS_END
// ar_ldrb manual specifically claims to have 4-way gate sticks.
static INPUT_PORTS_START( arcadia_4way )
PORT_INCLUDE( arcadia )
PORT_MODIFY("p1_joy")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(1) PORT_4WAY
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(1) PORT_4WAY
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(1) PORT_4WAY
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(1) PORT_4WAY
PORT_MODIFY("p2_joy")
PORT_BIT( 0x01, IP_ACTIVE_HIGH, IPT_JOYSTICK_UP ) PORT_PLAYER(2) PORT_4WAY
PORT_BIT( 0x02, IP_ACTIVE_HIGH, IPT_JOYSTICK_DOWN ) PORT_PLAYER(2) PORT_4WAY
PORT_BIT( 0x04, IP_ACTIVE_HIGH, IPT_JOYSTICK_LEFT ) PORT_PLAYER(2) PORT_4WAY
PORT_BIT( 0x08, IP_ACTIVE_HIGH, IPT_JOYSTICK_RIGHT ) PORT_PLAYER(2) PORT_4WAY
INPUT_PORTS_END
/*************************************
*
@ -308,7 +322,13 @@ void arcadia_amiga_state::arcadia(machine_config &config)
M68000(config, m_maincpu, amiga_state::CLK_7M_NTSC);
m_maincpu->set_addrmap(AS_PROGRAM, &arcadia_amiga_state::arcadia_map);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&arcadia_amiga_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&arcadia_amiga_state::ocs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
AMIGA_COPPER(config, m_copper, amiga_state::CLK_7M_NTSC);
m_copper->set_host_cpu_tag(m_maincpu);
m_copper->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_copper->set_ecs_mode(false);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
@ -1005,9 +1025,9 @@ GAME( 1987, ar_dart2, ar_dart, arcadia, arcadia, arcadia_amiga_state, init_dart,
GAME( 1988, ar_fast, ar_bios, arcadia, arcadia, arcadia_amiga_state, init_arcadia, ROT0, "Arcadia Systems", "Magic Johnson's Fast Break (Arcadia, V 2.8)", 0 )
GAME( 1988, ar_fasta, ar_fast, arcadia, arcadia, arcadia_amiga_state, init_arcadia, ROT0, "Arcadia Systems", "Magic Johnson's Fast Break (Arcadia, V 2.7)", 0 )
GAME( 1988, ar_ldrb, ar_bios, arcadia, arcadia, arcadia_amiga_state, init_ldrb, ROT0, "Arcadia Systems", "Leader Board (Arcadia, set 1, V 2.5)", 0 )
GAME( 1988, ar_ldrba, ar_ldrb, arcadia, arcadia, arcadia_amiga_state, init_arcadia, ROT0, "Arcadia Systems", "Leader Board (Arcadia, set 2, V 2.4)", 0 )
GAME( 1988, ar_ldrbb, ar_ldrb, arcadia, arcadia, arcadia_amiga_state, init_arcadia, ROT0, "Arcadia Systems", "Leader Board (Arcadia, set 3)", 0 )
GAME( 1988, ar_ldrb, ar_bios, arcadia, arcadia_4way, arcadia_amiga_state, init_ldrb, ROT0, "Arcadia Systems", "Leader Board Golf (Arcadia, set 1, V 2.5)", 0 )
GAME( 1988, ar_ldrba, ar_ldrb, arcadia, arcadia_4way, arcadia_amiga_state, init_arcadia, ROT0, "Arcadia Systems", "Leader Board Golf (Arcadia, set 2, V 2.4)", 0 )
GAME( 1988, ar_ldrbb, ar_ldrb, arcadia, arcadia_4way, arcadia_amiga_state, init_arcadia, ROT0, "Arcadia Systems", "Leader Board Golf (Arcadia, set 3)", 0 )
GAME( 1987, ar_ninj, ar_bios, arcadia, arcadia, arcadia_amiga_state, init_ninj, ROT0, "Arcadia Systems", "Ninja Mission (Arcadia, set 1, V 2.5)", 0 )
GAME( 1987, ar_ninj2, ar_ninj, arcadia, arcadia, arcadia_amiga_state, init_ninj, ROT0, "Arcadia Systems", "Ninja Mission (Arcadia, set 2)", 0 )

View File

@ -1,5 +1,5 @@
// license:BSD-3-Clause
// copyright-holders:Aaron Giles, Mariusz Wojcieszek, Ernesto Corvi, Dirk Best,Stephane Humbert
// copyright-holders:Aaron Giles, Mariusz Wojcieszek, Ernesto Corvi, Dirk Best, Stephane Humbert
/*
Cubo CD32 (additional hardware and games by CD Express, Milan, Italy)
@ -7,6 +7,13 @@
The CuboCD32 is a stock retail CD32 unit with additional hardware to adapt it
for JAMMA use.
TODO:
- remove m_input_hack functions, needed to make inputs working
- lsrquiz2i, lsrquizg: access violation on microtouch_device destructor when exiting emulation
Caused by microtouch_device::rcv_complete() overrunning the m_rx_buffer
array space with 149 (array size=16).
Known Games:
Dumped | Title | Rev. | Year | Notes
----------------------------------------------------
@ -17,7 +24,7 @@
YES | Harem Challenge | | 1995 |
| Laser Quiz | | 1995 |
| Laser Quiz France | 1.0 | 1995 |
| Laser Quiz Greece | | 1995 | May exist
YES | Laser Quiz Greece | | 1995 |
YES | Laser Quiz Italy | | 1995 |
YES | Laser Quiz 2 Greece | | 1995 |
YES | Laser Quiz 2 Italy | 1.0 | 1995 |
@ -29,10 +36,6 @@
YES | Odeon Twister | 1.4| 199x |
YES | Odeon Twister 2 | 202.19| 1999 |
ToDo:
- remove the hack needed to make inputs working
Stephh's notes (based on the game M68EC020 code and some tests) :
@ -328,11 +331,11 @@ routines :
class cubo_state : public amiga_state
{
public:
cubo_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_player_ports(*this, {"P1", "P2"}),
m_microtouch(*this, "microtouch"),
m_cdda(*this, "cdda")
cubo_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_player_ports(*this, {"P1", "P2"})
, m_microtouch(*this, "microtouch")
, m_cdda(*this, "cdda")
{ }
void handle_joystick_cia(uint8_t pra, uint8_t dra);
@ -435,7 +438,7 @@ void cubo_state::cubo_mem(address_map &map)
map(0xa80000, 0xb7ffff).noprw();
map(0xb80000, 0xb8003f).rw("akiko", FUNC(akiko_device::read), FUNC(akiko_device::write));
map(0xbf0000, 0xbfffff).rw(FUNC(cubo_state::cia_r), FUNC(cubo_state::gayle_cia_w));
map(0xc00000, 0xdfffff).rw(FUNC(cubo_state::custom_chip_r), FUNC(cubo_state::custom_chip_w));
map(0xc00000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap32));
map(0xe00000, 0xe7ffff).rom().region("kickstart", 0x80000);
map(0xe80000, 0xf7ffff).noprw();
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -651,7 +654,6 @@ static INPUT_PORTS_START( cubo )
PORT_DIPNAME( 0x80, 0x80, "DSW2 8" )
PORT_DIPSETTING( 0x80, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
INPUT_PORTS_END
static INPUT_PORTS_START( cndypuzl )
@ -1030,9 +1032,36 @@ static INPUT_PORTS_START( mgprem11 )
PORT_DIPSETTING( 0x00, "OK" )
PORT_DIPSETTING( 0x01, "ERROR!" )
PORT_BIT( 0x00fe, IP_ACTIVE_HIGH, IPT_UNKNOWN )
INPUT_PORTS_END
static INPUT_PORTS_START( eldoralg )
PORT_INCLUDE( cubo )
// TODO: verify layout
PORT_MODIFY("P1")
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("P1 G") PORT_PLAYER(1)
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P1 F") PORT_PLAYER(1)
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P1 C") PORT_PLAYER(1)
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P1 D") PORT_PLAYER(1)
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P1 A") PORT_PLAYER(1)
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P1 E") PORT_PLAYER(1)
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P1 B") PORT_PLAYER(1)
PORT_MODIFY("P2")
PORT_BIT( 0x0001, IP_ACTIVE_HIGH, IPT_BUTTON7 ) PORT_NAME("P2 G") PORT_PLAYER(2)
PORT_BIT( 0x0002, IP_ACTIVE_HIGH, IPT_BUTTON6 ) PORT_NAME("P2 F") PORT_PLAYER(2)
PORT_BIT( 0x0004, IP_ACTIVE_HIGH, IPT_BUTTON3 ) PORT_NAME("P2 C") PORT_PLAYER(2)
PORT_BIT( 0x0008, IP_ACTIVE_HIGH, IPT_BUTTON4 ) PORT_NAME("P2 D") PORT_PLAYER(2)
PORT_BIT( 0x0010, IP_ACTIVE_HIGH, IPT_BUTTON1 ) PORT_NAME("P2 A") PORT_PLAYER(2)
PORT_BIT( 0x0020, IP_ACTIVE_HIGH, IPT_BUTTON5 ) PORT_NAME("P2 E") PORT_PLAYER(2)
PORT_BIT( 0x0040, IP_ACTIVE_HIGH, IPT_BUTTON2 ) PORT_NAME("P2 B") PORT_PLAYER(2)
PORT_MODIFY("DIPSW1")
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_COIN1 ) /* Hold at boot for test mode */
PORT_MODIFY("DIPSW2")
PORT_BIT( 0x0080, IP_ACTIVE_HIGH, IPT_COIN2 )
INPUT_PORTS_END
void cubo_state::cubo(machine_config &config)
{
@ -1040,7 +1069,13 @@ void cubo_state::cubo(machine_config &config)
M68EC020(config, m_maincpu, amiga_state::CLK_28M_PAL / 2);
m_maincpu->set_addrmap(AS_PROGRAM, &cubo_state::cubo_mem);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&cubo_state::overlay_2mb_map32).set_options(ENDIANNESS_BIG, 32, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&cubo_state::aga_map).set_options(ENDIANNESS_BIG, 32, 9, 0x200);
AMIGA_COPPER(config, m_copper, amiga_state::CLK_28M_PAL / 2);
m_copper->set_host_cpu_tag(m_maincpu);
m_copper->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_copper->set_ecs_mode(true);
I2C_24C08(config, "i2cmem", 0); // AT24C08N
@ -1055,6 +1090,7 @@ void cubo_state::cubo(machine_config &config)
// video hardware
pal_video(config);
m_screen->set_screen_update(FUNC(amiga_state::screen_update_amiga_aga));
PALETTE(config, m_palette, FUNC(amiga_state::amiga_palette), 4096);
MCFG_VIDEO_START_OVERRIDE(amiga_state, amiga_aga)
@ -1062,13 +1098,13 @@ void cubo_state::cubo(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
paula_8364_device &paula(PAULA_8364(config, "amiga", amiga_state::CLK_C1_PAL));
paula.add_route(0, "lspeaker", 0.25);
paula.add_route(1, "rspeaker", 0.25);
paula.add_route(2, "rspeaker", 0.25);
paula.add_route(3, "lspeaker", 0.25);
paula.mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
paula.int_cb().set(FUNC(amiga_state::paula_int_w));
PAULA_8364(config, m_paula, amiga_state::CLK_C1_PAL);
m_paula->add_route(0, "lspeaker", 0.25);
m_paula->add_route(1, "rspeaker", 0.25);
m_paula->add_route(2, "rspeaker", 0.25);
m_paula->add_route(3, "lspeaker", 0.25);
m_paula->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_paula->int_cb().set(FUNC(amiga_state::paula_int_w));
CDDA(config, m_cdda);
m_cdda->add_route(0, "lspeaker", 0.50);
@ -1327,82 +1363,20 @@ void cubo_state::init_mgprem11()
m_input_hack = &cubo_state::mgprem11_input_hack;
}
static INPUT_PORTS_START( odeontw2 )
// PORT_INCLUDE( cd32 )
PORT_START("CIA0PORTA")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("CIA0PORTB")
PORT_BIT( 0xff, IP_ACTIVE_LOW, IPT_UNKNOWN )
PORT_START("DIPSW1")
PORT_DIPNAME( 0x01, 0x01, "DSW1 1" )
PORT_DIPSETTING( 0x01, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x02, 0x02, "DSW1 2" )
PORT_DIPSETTING( 0x02, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x04, 0x04, "DSW1 3" )
PORT_DIPSETTING( 0x04, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x08, 0x08, "DSW1 4" )
PORT_DIPSETTING( 0x08, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x10, 0x10, "DSW1 5" )
PORT_DIPSETTING( 0x10, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x20, 0x20, "DSW1 6" )
PORT_DIPSETTING( 0x20, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x40, 0x40, "DSW1 7" )
PORT_DIPSETTING( 0x40, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x80, 0x80, "DSW1 8" )
PORT_DIPSETTING( 0x80, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_START("DIPSW2")
PORT_DIPNAME( 0x01, 0x01, "DSW2 1" )
PORT_DIPSETTING( 0x01, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x02, 0x02, "DSW2 2" )
PORT_DIPSETTING( 0x02, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x04, 0x04, "DSW2 3" )
PORT_DIPSETTING( 0x04, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x08, 0x08, "DSW2 4" )
PORT_DIPSETTING( 0x08, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x10, 0x10, "DSW2 5" )
PORT_DIPSETTING( 0x10, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x20, 0x20, "DSW2 6" )
PORT_DIPSETTING( 0x20, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x40, 0x40, "DSW2 7" )
PORT_DIPSETTING( 0x40, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
PORT_DIPNAME( 0x80, 0x80, "DSW2 8" )
PORT_DIPSETTING( 0x80, "Reset" )
PORT_DIPSETTING( 0x00, "Set" )
INPUT_PORTS_END
GAME( 1993, cubo, 0, cubo, cubo, cubo_state, init_cubo, ROT0, "Commodore", "Cubo BIOS", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_IS_BIOS_ROOT )
GAME( 1995, cndypuzl, cubo, cubo, cndypuzl, cubo_state, init_cndypuzl, ROT0, "CD Express", "Candy Puzzle (v1.0)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
GAME( 1995, haremchl, cubo, cubo, haremchl, cubo_state, init_haremchl, ROT0, "CD Express", "Harem Challenge", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
GAME( 1995, lsrquiz, cubo, cubo, lsrquiz, cubo_state, init_lsrquiz, ROT0, "CD Express", "Laser Quiz Italy", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* no player 2 inputs (ingame), wrong pitch for most gfxs */
GAME( 1995, lsrquizg, cubo, cubo, lsrquiz, cubo_state, init_lsrquiz, ROT0, "CD Express", "Laser Quiz Greece", MACHINE_NOT_WORKING )
GAME( 1995, lsrquiz2i, cubo, cubo, lsrquiz2, cubo_state, init_lsrquiz2, ROT0, "CD Express", "Laser Quiz 2 Italy (v1.0)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND | MACHINE_NOT_WORKING ) /* wrong pitch for some gfxs, crashes during gameplay */
GAME( 1995, lsrquiz, cubo, cubo, lsrquiz, cubo_state, init_lsrquiz, ROT0, "CD Express", "Laser Quiz Italy", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // no player 2 inputs (ingame), wrong pitch for most gfxs, access violation during gameplay or on emu exit (microtouch?)
GAME( 1995, lsrquizg, cubo, cubo, lsrquiz, cubo_state, init_lsrquiz, ROT0, "CD Express", "Laser Quiz Greece", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // doesn't accept coins, no player 2 inputs (ingame), wrong pitch for most gfxs, access violation during gameplay or on emu exit (microtouch?)
GAME( 1995, lsrquiz2i, cubo, cubo, lsrquiz2, cubo_state, init_lsrquiz2, ROT0, "CD Express", "Laser Quiz 2 Italy (v1.0)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // wrong pitch for some gfxs, access violation during gameplay (microtouch?)
GAME( 1995, lasstixx, cubo, cubo, lasstixx, cubo_state, init_lasstixx, ROT0, "CD Express", "Laser Strixx 2", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
GAME( 1995, mgnumber, cubo, cubo, mgnumber, cubo_state, init_mgnumber, ROT0, "CD Express", "Magic Number", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
GAME( 1996, mgprem11, cubo, cubo, mgprem11, cubo_state, init_mgprem11, ROT0, "CD Express", "Magic Premium (v1.1)", MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND )
GAME( 19??, odeontw, cubo, cubo, odeontw2, cubo_state, init_cubo, ROT0, "CD Express", "Odeon Twister (v1.4)", MACHINE_NOT_WORKING )
GAME( 1999, odeontw2, cubo, cubo, odeontw2, cubo_state, init_cubo, ROT0, "CD Express", "Odeon Twister 2 (v202.19)", MACHINE_NOT_WORKING )
// Laser Gate 2
GAME( 19??, eldoralg, cubo, cubo, cubo, cubo_state, init_cubo, ROT0, "CD Express", "Eldorado (4.2)", MACHINE_NOT_WORKING )
GAME( 1997, eldoralg, cubo, cubo, eldoralg, cubo_state, init_cubo, ROT0, "Shangai Games", "Eldorado (4.2)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // touchscreen is offset and cannot be calibrated, joystick buttons aren't recognized properly, has slight GFX bug with roulette ball
GAME( 1998, odeontw, cubo, cubo, eldoralg, cubo_state, init_cubo, ROT0, "CD Express", "Odeon Twister (v1.4)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // "Invalid NVRAM", accesses area $6xxxxx and claims invalid RAM config if bypassed
GAME( 1998, odeontw2, cubo, cubo, eldoralg, cubo_state, init_cubo, ROT0, "CD Express", "Odeon Twister 2 (v202.19)", MACHINE_NOT_WORKING | MACHINE_IMPERFECT_GRAPHICS | MACHINE_IMPERFECT_SOUND ) // Resets halfway thru "please wait" in service mode, therefore NVRAM cannot be inited
// Laser Gate 2, alt title for Eldorado?
// Lucky Five
// Greyhound Race
// Double Strixx

View File

@ -47,10 +47,10 @@
class mquake_state : public amiga_state
{
public:
mquake_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_es5503(*this, "es5503"),
m_es5503_rom(*this, "es5503")
mquake_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_es5503(*this, "es5503")
, m_es5503_rom(*this, "es5503")
{ }
void mquake(machine_config &config);
@ -137,10 +137,10 @@ void mquake_state::a500_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(mquake_state::cia_r), FUNC(mquake_state::cia_w));
map(0xc00000, 0xd7ffff).rw(FUNC(mquake_state::custom_chip_r), FUNC(mquake_state::custom_chip_w));
map(0xc00000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(mquake_state::custom_chip_r), FUNC(mquake_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(mquake_state::custom_chip_r), FUNC(mquake_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(mquake_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -319,7 +319,13 @@ void mquake_state::mquake(machine_config &config)
M68000(config, m_maincpu, amiga_state::CLK_7M_NTSC);
m_maincpu->set_addrmap(AS_PROGRAM, &mquake_state::main_map);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&mquake_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&mquake_state::ocs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
AMIGA_COPPER(config, m_copper, amiga_state::CLK_7M_NTSC);
m_copper->set_host_cpu_tag(m_maincpu);
m_copper->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_copper->set_ecs_mode(false);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
@ -334,13 +340,13 @@ void mquake_state::mquake(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
paula_8364_device &paula(PAULA_8364(config, "amiga", amiga_state::CLK_C1_NTSC));
paula.add_route(0, "lspeaker", 0.50);
paula.add_route(1, "rspeaker", 0.50);
paula.add_route(2, "rspeaker", 0.50);
paula.add_route(3, "lspeaker", 0.50);
paula.mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
paula.int_cb().set(FUNC(amiga_state::paula_int_w));
PAULA_8364(config, m_paula, amiga_state::CLK_C1_NTSC);
m_paula->add_route(0, "lspeaker", 0.50);
m_paula->add_route(1, "rspeaker", 0.50);
m_paula->add_route(2, "rspeaker", 0.50);
m_paula->add_route(3, "lspeaker", 0.50);
m_paula->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_paula->int_cb().set(FUNC(amiga_state::paula_int_w));
ES5503(config, m_es5503, amiga_state::CLK_7M_NTSC); /* ES5503 is likely mono due to channel strobe used as bank select */
m_es5503->set_channels(1);

View File

@ -37,11 +37,11 @@
class upscope_state : public amiga_state
{
public:
upscope_state(const machine_config &mconfig, device_type type, const char *tag) :
amiga_state(mconfig, type, tag),
m_prev_cia1_porta(0xff),
m_parallel_data(0xff),
m_ppi(*this, "ppi")
upscope_state(const machine_config &mconfig, device_type type, const char *tag)
: amiga_state(mconfig, type, tag)
, m_prev_cia1_porta(0xff)
, m_parallel_data(0xff)
, m_ppi(*this, "ppi")
{ }
void upscope(machine_config &config);
@ -221,10 +221,10 @@ void upscope_state::a500_mem(address_map &map)
map.unmap_value_high();
map(0x000000, 0x1fffff).m(m_overlay, FUNC(address_map_bank_device::amap16));
map(0xa00000, 0xbfffff).rw(FUNC(upscope_state::cia_r), FUNC(upscope_state::cia_w));
map(0xc00000, 0xd7ffff).rw(FUNC(upscope_state::custom_chip_r), FUNC(upscope_state::custom_chip_w));
map(0xc00000, 0xd7ffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xd80000, 0xddffff).noprw();
map(0xde0000, 0xdeffff).rw(FUNC(upscope_state::custom_chip_r), FUNC(upscope_state::custom_chip_w));
map(0xdf0000, 0xdfffff).rw(FUNC(upscope_state::custom_chip_r), FUNC(upscope_state::custom_chip_w));
map(0xde0000, 0xdeffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xdf0000, 0xdfffff).m(m_chipset, FUNC(address_map_bank_device::amap16));
map(0xe00000, 0xe7ffff).nopw().r(FUNC(upscope_state::rom_mirror_r));
map(0xe80000, 0xefffff).noprw(); // autoconfig space (installed by devices)
map(0xf80000, 0xffffff).rom().region("kickstart", 0);
@ -271,7 +271,13 @@ void upscope_state::upscope(machine_config &config)
M68000(config, m_maincpu, amiga_state::CLK_7M_NTSC);
m_maincpu->set_addrmap(AS_PROGRAM, &upscope_state::main_map);
ADDRESS_MAP_BANK(config, "overlay").set_map(&amiga_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_overlay).set_map(&upscope_state::overlay_512kb_map).set_options(ENDIANNESS_BIG, 16, 22, 0x200000);
ADDRESS_MAP_BANK(config, m_chipset).set_map(&upscope_state::ocs_map).set_options(ENDIANNESS_BIG, 16, 9, 0x200);
AMIGA_COPPER(config, m_copper, amiga_state::CLK_7M_NTSC);
m_copper->set_host_cpu_tag(m_maincpu);
m_copper->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_copper->set_ecs_mode(false);
NVRAM(config, "nvram", nvram_device::DEFAULT_ALL_0);
@ -286,13 +292,13 @@ void upscope_state::upscope(machine_config &config)
SPEAKER(config, "lspeaker").front_left();
SPEAKER(config, "rspeaker").front_right();
paula_8364_device &paula(PAULA_8364(config, "amiga", amiga_state::CLK_C1_NTSC));
paula.add_route(0, "rspeaker", 0.50);
paula.add_route(1, "lspeaker", 0.50);
paula.add_route(2, "lspeaker", 0.50);
paula.add_route(3, "rspeaker", 0.50);
paula.mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
paula.int_cb().set(FUNC(amiga_state::paula_int_w));
PAULA_8364(config, m_paula, amiga_state::CLK_C1_NTSC);
m_paula->add_route(0, "rspeaker", 0.50);
m_paula->add_route(1, "lspeaker", 0.50);
m_paula->add_route(2, "lspeaker", 0.50);
m_paula->add_route(3, "rspeaker", 0.50);
m_paula->mem_read_cb().set(FUNC(amiga_state::chip_ram_r));
m_paula->int_cb().set(FUNC(amiga_state::paula_int_w));
/* cia */
MOS8520(config, m_cia_0, amiga_state::CLK_E_NTSC);
@ -322,7 +328,6 @@ void upscope_state::upscope(machine_config &config)
}
/*************************************
*
* ROM definitions

View File

@ -20,6 +20,7 @@ Ernesto Corvi & Mariusz Wojcieszek
#include "bus/centronics/ctronics.h"
#include "machine/mos6526.h"
#include "machine/amigafdc.h"
#include "machine/amiga_copper.h"
#include "machine/msm6242.h"
#include "machine/akiko.h"
#include "machine/i2cmem.h"
@ -94,7 +95,7 @@ Ernesto Corvi & Mariusz Wojcieszek
#define REG_BLTCDAT (0x070/2) /* W A Blitter source C data register */
#define REG_BLTBDAT (0x072/2) /* W A Blitter source B data reglster */
#define REG_BLTADAT (0x074/2) /* W A Blitter source A data register */
#define REG_DENISEID (0x07C/2) /* R D Denise ID: OCS = 0xFF, ECS = 0xFC, AGA = 0xF8 */
#define REG_DENISEID (0x07C/2) /* R D Denise ID: OCS = <open bus>, ECS = 0xFC, AGA = 0xF8 */
#define REG_DSKSYNC (0x07E/2) /* W P Disk sync pattern register for disk read */
#define REG_COP1LCH (0x080/2) /* W A Coprocessor first location register (high 3 bits) */
#define REG_COP1LCL (0x082/2) /* W A Coprocessor first location register (low 15 bits) */
@ -307,51 +308,56 @@ Ernesto Corvi & Mariusz Wojcieszek
class amiga_state : public driver_device
{
public:
amiga_state(const machine_config &mconfig, device_type type, const char *tag) :
driver_device(mconfig, type, tag),
m_agnus_id(AGNUS_NTSC),
m_denise_id(DENISE),
m_maincpu(*this, "maincpu"),
m_cia_0(*this, "cia_0"),
m_cia_1(*this, "cia_1"),
m_rs232(*this, "rs232"),
m_centronics(*this, "centronics"),
m_paula(*this, "amiga"),
m_fdc(*this, "fdc"),
m_screen(*this, "screen"),
m_palette(*this, "palette"),
m_overlay(*this, "overlay"),
m_input_device(*this, "input"),
m_joy0dat_port(*this, "joy_0_dat"),
m_joy1dat_port(*this, "joy_1_dat"),
m_potgo_port(*this, "potgo"),
m_pot0dat_port(*this, "POT0DAT"),
m_pot1dat_port(*this, "POT1DAT"),
m_joy_ports(*this, "p%u_joy", 1),
m_p1_mouse_x(*this, "p1_mouse_x"),
m_p1_mouse_y(*this, "p1_mouse_y"),
m_p2_mouse_x(*this, "p2_mouse_x"),
m_p2_mouse_y(*this, "p2_mouse_y"),
m_hvpos(*this, "HVPOS"),
m_power_led(*this, "power_led"),
m_chip_ram_mask(0),
m_cia_0_irq(0),
m_cia_1_irq(0),
m_pot0x(0), m_pot1x(0), m_pot0y(0), m_pot1y(0),
m_pot0dat(0x0000),
m_pot1dat(0x0000),
m_centronics_busy(0),
m_centronics_perror(0),
m_centronics_select(0),
m_gayle_reset(false),
m_diw(),
m_diwhigh_valid(false),
m_previous_lof(true),
m_rx_shift(0),
m_tx_shift(0),
m_rx_state(0),
m_tx_state(0),
m_rx_previous(1)
amiga_state(const machine_config &mconfig, device_type type, const char *tag)
: driver_device(mconfig, type, tag)
, m_agnus_id(AGNUS_NTSC)
, m_denise_id(DENISE)
, m_maincpu(*this, "maincpu")
, m_cia_0(*this, "cia_0")
, m_cia_1(*this, "cia_1")
, m_rs232(*this, "rs232")
, m_centronics(*this, "centronics")
// , m_agnus(*this, "agnus")
// , m_denise(*this, "denise")
, m_copper(*this, "copper")
// , m_blitter(*this, "blitter")
, m_paula(*this, "paula")
, m_fdc(*this, "fdc")
, m_screen(*this, "screen")
, m_palette(*this, "palette")
, m_overlay(*this, "overlay")
, m_chipset(*this, "chipset")
, m_input_device(*this, "input")
, m_joy0dat_port(*this, "joy_0_dat")
, m_joy1dat_port(*this, "joy_1_dat")
, m_potgo_port(*this, "potgo")
, m_pot0dat_port(*this, "POT0DAT")
, m_pot1dat_port(*this, "POT1DAT")
, m_joy_ports(*this, "p%u_joy", 1)
, m_p1_mouse_x(*this, "p1_mouse_x")
, m_p1_mouse_y(*this, "p1_mouse_y")
, m_p2_mouse_x(*this, "p2_mouse_x")
, m_p2_mouse_y(*this, "p2_mouse_y")
, m_hvpos(*this, "HVPOS")
, m_power_led(*this, "power_led")
, m_chip_ram_mask(0)
, m_cia_0_irq(0)
, m_cia_1_irq(0)
, m_pot0x(0), m_pot1x(0), m_pot0y(0), m_pot1y(0)
, m_pot0dat(0x0000)
, m_pot1dat(0x0000)
, m_centronics_busy(0)
, m_centronics_perror(0)
, m_centronics_select(0)
, m_gayle_reset(false)
, m_diw()
, m_diwhigh_valid(false)
, m_previous_lof(true)
, m_rx_shift(0)
, m_tx_shift(0)
, m_rx_state(0)
, m_tx_state(0)
, m_rx_previous(1)
{
std::fill(std::begin(m_custom_regs), std::end(m_custom_regs), 0);
}
@ -359,7 +365,10 @@ public:
/* chip RAM access */
uint16_t read_chip_ram(offs_t byteoffs)
{
return EXPECTED(byteoffs < m_chip_ram.bytes()) ? m_chip_ram.read(byteoffs >> 1) : 0xffff;
// We use rand() here so that an attempt to go beyond the allocated chip RAM
// (hopefully) doesn't go unnoticed.
// FIXME: most likely open bus instead.
return EXPECTED(byteoffs < m_chip_ram.bytes()) ? m_chip_ram.read(byteoffs >> 1) : machine().rand();
}
void write_chip_ram(offs_t byteoffs, uint16_t data)
@ -405,11 +414,13 @@ public:
uint16_t m_genlock_color;
/* separate 6 in-order bitplanes into 2 x 3-bit bitplanes in two nibbles */
uint8_t m_separate_bitplanes[2][64];
// FIXME: we instantiate 256 entries so that it pleases AGA
uint8_t m_separate_bitplanes[2][256];
/* aga */
int m_aga_diwhigh_written;
rgb_t m_aga_palette[256];
rgb_t m_aga_ehb_palette[32 + 32];
uint64_t m_aga_bpldat[8];
uint16_t m_aga_sprdata[8][4];
uint16_t m_aga_sprdatb[8][4];
@ -536,7 +547,7 @@ protected:
};
// chipset
bool IS_OCS() const { return m_denise_id == 0xff; }
bool IS_OCS() const { return m_denise_id == 0xffff; }
bool IS_ECS() const { return m_denise_id == 0xfc; }
bool IS_AGA() const { return m_denise_id == 0xf8; }
@ -573,12 +584,13 @@ protected:
required_device<mos8520_device> m_cia_1;
optional_device<rs232_port_device> m_rs232;
optional_device<centronics_device> m_centronics;
required_device<amiga_copper_device> m_copper;
required_device<paula_8364_device> m_paula;
optional_device<amiga_fdc_device> m_fdc;
required_device<screen_device> m_screen;
optional_device<palette_device> m_palette;
required_device<address_map_bank_device> m_overlay;
required_device<address_map_bank_device> m_chipset;
// i/o ports
optional_ioport m_input_device;
@ -604,6 +616,16 @@ protected:
uint16_t m_custom_regs[256];
static const char *const s_custom_reg_names[0x100];
void ocs_map(address_map &map);
void ecs_map(address_map &map);
void aga_map(address_map &map);
// TODO: move to Agnus/Alice
u16 vposr_r();
void vposw_w(u16 data);
void bplcon0_w(u16 data);
void aga_bplcon0_w(u16 data);
private:
// blitter helpers
uint32_t blit_ascending();
@ -614,8 +636,6 @@ private:
protected:
void set_genlock_color(uint16_t color);
private:
void copper_setpc(uint32_t pc);
int copper_execute_next(int xpos);
void sprite_dma_reset(int which);
void sprite_enable_comparitor(int which, int enable);
void fetch_sprite_data(int scanline, int sprite);
@ -637,8 +657,8 @@ private:
int aga_get_sprite_pixel(int x);
uint8_t aga_assemble_odd_bitplanes(int planes, int obitoffs);
uint8_t aga_assemble_even_bitplanes(int planes, int ebitoffs);
void aga_fetch_bitplane_data(int plane);
rgb_t aga_update_ham(int newpix);
void aga_fetch_bitplane_data(int plane, u8 bitplane_fmode);
rgb_t aga_update_ham(int newpix, int plane);
enum
{

View File

@ -142,7 +142,6 @@ constexpr XTAL amiga_state::CLK_7M_NTSC;
constexpr XTAL amiga_state::CLK_C1_NTSC;
constexpr XTAL amiga_state::CLK_E_NTSC;
/*************************************
*
* Machine reset
@ -444,7 +443,6 @@ uint32_t amiga_state::blit_ascending()
/* fetch data for A */
if (CUSTOM_REG(REG_BLTCON0) & 0x0800)
{
//CUSTOM_REG(REG_BLTADAT) = m_maincpu->space(AS_PROGRAM).read_word(CUSTOM_REG_LONG(REG_BLTAPTH));
CUSTOM_REG(REG_BLTADAT) = read_chip_ram(CUSTOM_REG_LONG(REG_BLTAPTH));
CUSTOM_REG_LONG(REG_BLTAPTH) += 2;
}
@ -917,6 +915,8 @@ TIMER_CALLBACK_MEMBER( amiga_state::amiga_blitter_proc )
/* clear the zero flag if we actually wrote data */
if (blitsum)
CUSTOM_REG(REG_DMACON) &= ~0x2000;
if (LOG_BLITS)
logerror("%04x ZF=%d\n", blitsum, bool(BIT(CUSTOM_REG(REG_DMACON), 13)));
/* no longer busy */
CUSTOM_REG(REG_DMACON) &= ~0x4000;
@ -970,9 +970,15 @@ void amiga_state::blitter_setup()
height = CUSTOM_REG(REG_BLTSIZV);
/* compute the blit time */
// TODO: verify timings
// According to https://github.com/alpine9000/amiga_examples test 010,
// blitting is currently taking half the time than necessary.
// Is it expecting to account for RAM access waitstates or ...?
blittime = ticks * height * width;
/* if 'blitter-nasty' is set, then the blitter takes over the bus. Make the blit semi-immediate */
// TODO: blitter nasty doesn't seem to work as intended.
// cfr. spinwrld
if ( CUSTOM_REG(REG_DMACON) & 0x0400 )
{
/* simulate the 68k not running while the blit is going */
@ -1132,6 +1138,141 @@ WRITE_LINE_MEMBER( amiga_state::cia_1_irq )
// CUSTOM CHIPS
//**************************************************************************
void amiga_state::ocs_map(address_map &map)
{
// In progress: remove this catch-all trampoline, move almost everything into devices
map(0x000, 0x1ff).rw(FUNC(amiga_state::custom_chip_r), FUNC(amiga_state::custom_chip_w));
// Reading state section
// map(0x000, 0x001).r(FUNC(amiga_state::bltddat_r));
// map(0x002, 0x003).r(FUNC(amiga_state::dmaconr_r));
map(0x004, 0x005).r(FUNC(amiga_state::vposr_r));
// map(0x006, 0x007).r(FUNC(amiga_state::vhposr_r));
// map(0x008, 0x009).r(FUNC(amiga_state::dskdatr_r));
// TODO: verify if JOYxDAT really belongs to Denise (???)
// map(0x00a, 0x00b).r(FUNC(amiga_state::joydat_r<0>));
// map(0x00c, 0x00d).r(FUNC(amiga_state::joydat_r<1>));
// map(0x00e, 0x00f).r(FUNC(amiga_state::clxdat_r));
map(0x010, 0x011).r(m_fdc, FUNC(amiga_fdc_device::adkcon_r));
// map(0x012, 0x013).r(FUNC(amiga_state::potdat_r<0>)); // POT0DAT
// map(0x014, 0x015).r(FUNC(amiga_state::potdat_r<1>));
// map(0x016, 0x017).r(FUNC(amiga_state::potgor_r)); // a.k.a. POTINP
// map(0x018, 0x019).r(FUNC(amiga_state::serdat_r));
map(0x01a, 0x01b).r(m_fdc, FUNC(amiga_fdc_device::dskbytr_r));
// map(0x01c, 0x01d).r(m_paula, FUNC(paula_8364_device::intenar_r));
// map(0x01e, 0x01f).r(m_paula, FUNC(paula_8364_device::intreqr_r));
// FDC writes
// FIXME: these two belongs to Agnus, also shouldn't be readable
map(0x020, 0x021).rw(m_fdc, FUNC(amiga_fdc_device::dskpth_r), FUNC(amiga_fdc_device::dskpth_w));
map(0x022, 0x023).rw(m_fdc, FUNC(amiga_fdc_device::dskptl_r), FUNC(amiga_fdc_device::dskptl_w));
map(0x024, 0x025).w(m_fdc, FUNC(amiga_fdc_device::dsklen_w));
// map(0x026, 0x027).w(m_fdc, FUNC(amiga_fdc_device::dskdat_w));
// map(0x028, 0x029).w(FUNC(amiga_state::refptr_w));
map(0x02a, 0x02b).w(FUNC(amiga_state::vposw_w));
// map(0x02c, 0x02d).w(FUNC(amiga_state::vhposw_w));
map(0x02e, 0x02f).w(m_copper, FUNC(amiga_copper_device::copcon_w));
// input strobes
// map(0x030, 0x031).w(FUNC(amiga_state::serdat_w));
// map(0x032, 0x033).w(FUNC(amiga_state::serper_w));
// map(0x034, 0x035).w(FUNC(amiga_state::potgo_w));
// map(0x036, 0x037).w(FUNC(amiga_state::joytest_w));
// video beam strobes
// map(0x038, 0x039).w(FUNC(amiga_state::strequ_w));
// map(0x03a, 0x03b).w(FUNC(amiga_state::strvbl_w));
// map(0x03c, 0x03d).w(FUNC(amiga_state::strhor_w));
// map(0x040, 0x075).m(m_blitter, FUNC(amiga_blitter_device::regs_map));
// map(0x07c, 0x07d).r <open bus for OCS>
map(0x07e, 0x07f).w(m_fdc, FUNC(amiga_fdc_device::dsksync_w));
// Copper
map(0x080, 0x08b).m(m_copper, FUNC(amiga_copper_device::regs_map));
map(0x08c, 0x08d).w(m_copper, FUNC(amiga_copper_device::copins_w));
// Display window
// map(0x08e, 0x08f).w(FUNC(amiga_state::diwstrt_w));
// map(0x090, 0x091).w(FUNC(amiga_state::diwstop_w));
// Display horizontal fetch
// map(0x092, 0x093).w(FUNC(amiga_state::ddfstrt_w));
// map(0x094, 0x095).w(FUNC(amiga_state::ddfstop_w));
// map(0x096, 0x097).w(FUNC(amiga_state::dmacon_w));
// map(0x098, 0x099).w(FUNC(amiga_state::clxcon_w));
// map(0x09a, 0x09b).w(m_paula, FUNC(paula_8364_device::intena_w));
// map(0x09c, 0x09d).w(m_paula, FUNC(paula_8364_device::intreq_w));
// map(0x09e, 0x09f).w(m_paula, FUNC(paula_8364_device::adkcon_w));
// Audio section
map(0x0a0, 0x0ab).m(m_paula, FUNC(paula_8364_device::audio_channel_map<0>));
map(0x0b0, 0x0bb).m(m_paula, FUNC(paula_8364_device::audio_channel_map<1>));
map(0x0c0, 0x0cb).m(m_paula, FUNC(paula_8364_device::audio_channel_map<2>));
map(0x0d0, 0x0db).m(m_paula, FUNC(paula_8364_device::audio_channel_map<3>));
// Bitplane pointer section
// map(0x0e0, 0x0ff).m(amiga_state::bplxptr_map));
// Video bitplane registers
map(0x100, 0x101).w(FUNC(amiga_state::bplcon0_w));
// map(0x102, 0x103).w(FUNC(amiga_state::bplcon1_w));
// map(0x104, 0x105).w(FUNC(amiga_state::bplcon2_w));
// map(0x108, 0x109).w(FUNC(amiga_state::bpl1mod_w));
// map(0x10a, 0x10b).w(FUNC(amiga_state::bpl2mod_w));
// map(0x110, 0x11f).m(amiga_state::bplxdat_map));
// Sprite section
// map(0x120, 0x17f).m(amiga_state::sprxpt_map));
// Color section
// map(0x180, 0x1bf).m(amiga_state::colorxx_map));
}
void amiga_state::ecs_map(address_map &map)
{
ocs_map(map);
// map(0x03e, 0x03f).w(FUNC(amiga_state::strlong_w));
// map(0x078, 0x079).w(FUNC(amiga_state::sprhdat_w));
// map(0x07c, 0x07d).r(FUNC(amiga_state::deniseid_r));
// map(0x106, 0x107).w(FUNC(amiga_state::bplcon3_w));
// Extended ECS registers
// video geometry regs
// map(0x1c0, 0x1c7).m(FUNC(amiga_state::horz_screen_map));
// map(0x1c8, 0x1cf).m(FUNC(amiga_state::vert_screen_map));
// map(0x1dc, 0x1dd).w(FUNC(amiga_state::beamcon0_w));
// Screen sync regs, VARHSY / VARVSY
// map(0x1de, 0x1df).w(FUNC(amiga_state::hsstrt_w));
// map(0x1e0, 0x1e1).w(FUNC(amiga_state::vsstrt_w));
// map(0x1e2, 0x1e3).w(FUNC(amiga_state::hcenter_w));
// map(0x1e4, 0x1e5).w(FUNC(amiga_state::diwhigh_w));
// dummy, either related to copper lockup restart or "last N refresh cycles"
// map(0x1fe, 0x1ff).?(FUNC(amiga_state::no_op_*));
}
void amiga_state::aga_map(address_map &map)
{
ecs_map(map);
// map(0x078, 0x079).w(FUNC(amiga_state::sprhdat_w));
map(0x100, 0x101).w(FUNC(amiga_state::aga_bplcon0_w));
// UHRES regs
// TODO: may be shared with ECS?
// map(0x1e6, 0x1e7).w(FUNC(amiga_state::bplhmod_w));
// map(0x1e8, 0x1e9).w(FUNC(amiga_state::sprhpth_w));
// map(0x1ea, 0x1eb).w(FUNC(amiga_state::sprhptl_w));
// map(0x1ec, 0x1ed).w(FUNC(amiga_state::bplhpth_w));
// map(0x1ed, 0x1ef).w(FUNC(amiga_state::bplhptl_w));
// map(0x1fc, 0x1fd).w(FUNC(amiga_state::fmode_w));
}
void amiga_state::custom_chip_reset()
{
CUSTOM_REG(REG_DENISEID) = m_denise_id;
@ -1143,6 +1284,42 @@ void amiga_state::custom_chip_reset()
CUSTOM_REG(REG_BEAMCON0) = (m_agnus_id & 0x10) ? 0x0000 : 0x0020;
}
u16 amiga_state::vposr_r()
{
u16 res = CUSTOM_REG(REG_VPOSR) & VPOSR_LOF;
res |= m_agnus_id << 8;
res |= ((amiga_gethvpos() >> 16) & 0xff);
return res;
}
void amiga_state::vposw_w(u16 data)
{
// TODO: data actually resync the screen?
// TODO: ECS always resets the LOF no matter the setting
CUSTOM_REG(REG_VPOSR) = (data & VPOSR_LOF) | (data & 7);
// TODO: high bits of screen height
// if (data & 7)
// popmessage("Upper VPOSW set %02x", data);
}
void amiga_state::bplcon0_w(u16 data)
{
// FIXME: verify OCS / ECS games trying to set this up
if ((data & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) == (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2))
{
/* planes go from 0 to 6, inclusive */
popmessage( "This game is doing funky planes stuff. (planes > 6, %04x)", data );
data &= ~BPLCON0_BPU0;
}
CUSTOM_REG(REG_BPLCON0) = data;
}
void amiga_state::aga_bplcon0_w(u16 data)
{
// just allow all (AGA surfninj title screen relies on this)
CUSTOM_REG(REG_BPLCON0) = data;
}
uint16_t amiga_state::custom_chip_r(offs_t offset)
{
uint16_t temp;
@ -1158,12 +1335,6 @@ uint16_t amiga_state::custom_chip_r(offs_t offset)
case REG_DMACONR:
return CUSTOM_REG(REG_DMACON);
case REG_VPOSR:
CUSTOM_REG(REG_VPOSR) &= 0xff00;
CUSTOM_REG(REG_VPOSR) |= amiga_gethvpos() >> 16;
return CUSTOM_REG(REG_VPOSR);
case REG_VHPOSR:
return amiga_gethvpos() & 0xffff;
@ -1223,14 +1394,6 @@ uint16_t amiga_state::custom_chip_r(offs_t offset)
case REG_INTREQR:
return CUSTOM_REG(REG_INTREQ);
case REG_COPJMP1:
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
break;
case REG_COPJMP2:
copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
break;
case REG_CLXDAT:
temp = CUSTOM_REG(REG_CLXDAT);
CUSTOM_REG(REG_CLXDAT) = 0;
@ -1249,7 +1412,7 @@ uint16_t amiga_state::custom_chip_r(offs_t offset)
return m_fdc->adkcon_r();
case REG_DSKDATR:
popmessage("DSKDAT R, contact MESSdev");
popmessage("DSKDAT R, contact MAMEdev");
break;
}
@ -1264,9 +1427,6 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
if (LOG_CUSTOM)
logerror("%06X:write to custom %s = %04X\n", m_maincpu->pc(), s_custom_reg_names[offset & 0xff], data);
// paula will handle some of those registers
m_paula->reg_w(offset, data);
switch (offset)
{
case REG_BLTDDAT: case REG_DMACONR: case REG_VPOSR: case REG_VHPOSR:
@ -1277,7 +1437,7 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
return;
case REG_DSKDAT:
popmessage("DSKDAT W %04x, contact MESSdev",data);
popmessage("DSKDAT W %04x, contact MAMEdev",data);
break;
case REG_DSKSYNC:
@ -1377,6 +1537,13 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
}
break;
// OCS and AGA versions of Soccer Kid explicitly writes blitter addresses way beyond chip RAM
// This is clearly deterministic: it draws an individual empty tile scattered across playfield
// (which also collides on top of it)
case REG_BLTAPTH: case REG_BLTBPTH: case REG_BLTCPTH: case REG_BLTDPTH:
data &= ( m_chip_ram_mask >> 16 );
break;
case REG_SPR0PTH: case REG_SPR1PTH: case REG_SPR2PTH: case REG_SPR3PTH:
case REG_SPR4PTH: case REG_SPR5PTH: case REG_SPR6PTH: case REG_SPR7PTH:
data &= ( m_chip_ram_mask >> 16 );
@ -1399,31 +1566,24 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
sprite_enable_comparitor((offset - REG_SPR0DATA) / 4, true);
break;
case REG_COP1LCH:
case REG_COP2LCH:
data &= ( m_chip_ram_mask >> 16 );
break;
case REG_COPJMP1:
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
break;
case REG_COPJMP2:
copper_setpc(CUSTOM_REG_LONG(REG_COP2LCH));
break;
case REG_DDFSTRT:
/* impose hardware limits ( HRM, page 75 ) */
data &= 0xfe;
data &= (IS_AGA() || IS_ECS()) ? 0xfe : 0xfc;
if (data < 0x18)
{
logerror("%s: Attempt to underrun DDFSTRT with %04x\n", machine().describe_context(), data);
data = 0x18;
}
break;
case REG_DDFSTOP:
/* impose hardware limits ( HRM, page 75 ) */
data &= 0xfe;
data &= (IS_AGA() || IS_ECS()) ? 0xfe : 0xfc;
if (data > 0xd8)
{
logerror("%s: Attempt to overrun DDFSTOP with %04x\n", machine().describe_context(), data);
data = 0xd8;
}
break;
case REG_DMACON:
@ -1431,6 +1591,8 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
data &= 0x9fff;
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
m_fdc->dmacon_set(data);
m_paula->dmacon_set(data);
m_copper->dmacon_set(data);
/* if 'blitter-nasty' has been turned on and we have a blit pending, reschedule it */
if ( ( data & 0x400 ) && ( CUSTOM_REG(REG_DMACON) & 0x4000 ) )
@ -1479,6 +1641,7 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
case REG_ADKCON:
data = (data & 0x8000) ? (CUSTOM_REG(offset) | (data & 0x7fff)) : (CUSTOM_REG(offset) & ~(data & 0x7fff));
m_fdc->adkcon_set(data);
m_paula->adkcon_set(data);
break;
case REG_BPL1PTH: case REG_BPL2PTH: case REG_BPL3PTH: case REG_BPL4PTH:
@ -1486,16 +1649,6 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
data &= ( m_chip_ram_mask >> 16 );
break;
case REG_BPLCON0:
if ((data & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) == (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2))
{
/* planes go from 0 to 6, inclusive */
logerror( "This game is doing funky planes stuff. (planes > 6)\n" );
data &= ~BPLCON0_BPU0;
}
CUSTOM_REG(offset) = data;
break;
case REG_BPL1MOD: case REG_BPL2MOD:
// bit 0 is implicitly ignored on writes,
// and wouldn't otherwise make sense with 68k inability of word reading with odd addresses.
@ -1518,6 +1671,7 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
else
{
data &= 0xfff;
// Extra Half-Brite
CUSTOM_REG(offset + 32) = (data >> 1) & 0x777;
}
break;
@ -1550,6 +1704,7 @@ void amiga_state::custom_chip_w(offs_t offset, uint16_t data)
break;
}
// FIXME: no ECS?
if (IS_AGA())
CUSTOM_REG(offset) = data;
else

View File

@ -19,22 +19,8 @@
*
*************************************/
#define LOG_COPPER 0
#define GUESS_COPPER_OFFSET 0
#define LOG_SPRITE_DMA 0
/*************************************
*
* Macros
*
*************************************/
#define COPPER_CYCLES_TO_PIXELS(x) (4 * (x))
/*************************************
*
* Tables
@ -79,29 +65,6 @@ const uint16_t amiga_state::s_expand_byte[256] =
0x5540, 0x5541, 0x5544, 0x5545, 0x5550, 0x5551, 0x5554, 0x5555
};
const uint16_t delay[256] =
{
1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,1,1,0,0,0,0,0,0,0,0, /* 0x000 - 0x03e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x040 - 0x05e */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x060 - 0x07e */
0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0, /* 0x080 - 0x09e */
1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0, /* 0x0a0 - 0x0de */
/* BPLxPTH/BPLxPTL */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x0e0 - 0x0fe */
/* BPLCON0-3,BPLMOD1-2 */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x100 - 0x11e */
/* SPRxPTH/SPRxPTL */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x120 - 0x13e */
/* SPRxPOS/SPRxCTL/SPRxDATA/SPRxDATB */
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, /* 0x140 - 0x17e */
/* COLORxx */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 0x180 - 0x1be */
/* RESERVED */
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* 0x1c0 - 0x1fe */
};
/*************************************
*
* 4-4-4 palette init
@ -124,10 +87,8 @@ void amiga_state::amiga_palette(palette_device &palette) const
VIDEO_START_MEMBER( amiga_state, amiga )
{
int j;
/* generate tables that produce the correct playfield color for dual playfield mode */
for (j = 0; j < 64; j++)
for (int j = 0; j < 64; j++)
{
int pf1pix = ((j >> 0) & 1) | ((j >> 1) & 2) | ((j >> 2) & 4);
int pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4);
@ -135,12 +96,8 @@ VIDEO_START_MEMBER( amiga_state, amiga )
m_separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 8);
m_separate_bitplanes[1][j] = pf2pix ? (pf2pix + 8) : pf1pix;
}
#if GUESS_COPPER_OFFSET
m_wait_offset = 3;
#else
(void)m_wait_offset;
#endif
// TODO: verify usage of values in the 64-255 range
// (should black out pf1 if j & 0x40, pf2 if j & 0x80)
/* reset the genlock color */
m_genlock_color = 0xffff;
@ -158,6 +115,12 @@ VIDEO_START_MEMBER( amiga_state, amiga )
*
*************************************/
// TODO: sync writes (VPOSW, VHPOSW), strobe beams (STR* class regs at 0x38-0x3e), ECS/AGA BEAMCON0
// A good chunk of copy protected games uses this timing as RNG seed,
// optionally syncing the beam to a known state (TBD find examples of this).
// In case of pbprel_a (AGA), it uses this to check if system has AGA equipped chipset.
// We may also need a "temporary" screen beam disable until a VBLANK occurs:
// for instance is dubious that beams are in a known state if a strobe happens ...
uint32_t amiga_state::amiga_gethvpos()
{
uint32_t hvpos = (m_last_scanline << 8) | (m_screen->hpos() >> 2);
@ -168,7 +131,7 @@ uint32_t amiga_state::amiga_gethvpos()
if ((CUSTOM_REG(REG_BPLCON0) & 0x0008) == 0 || latchedpos == 0 || (m_last_scanline >= 20 && hvpos < latchedpos))
return hvpos;
/* otherwise, return the latched position */
/* otherwise, return the latched position (cfr. lightgun input in alg.cpp, lightpen) */
return latchedpos;
}
@ -185,167 +148,6 @@ void amiga_state::set_genlock_color(uint16_t color)
m_genlock_color = color;
}
/*************************************
*
* Copper emulation
*
*************************************/
void amiga_state::copper_setpc(uint32_t pc)
{
if (LOG_COPPER)
logerror("copper_setpc(%06x)\n", pc);
m_copper_pc = pc;
m_copper_waiting = false;
}
int amiga_state::copper_execute_next(int xpos)
{
uint8_t ypos = m_last_scanline & 0xff;
int word0, word1;
/* bail if not enabled */
if ((CUSTOM_REG(REG_DMACON) & (DMACON_COPEN | DMACON_DMAEN)) != (DMACON_COPEN | DMACON_DMAEN))
return 511;
/* flush any pending writes */
if (m_copper_pending_offset)
{
if (LOG_COPPER)
logerror("%02X.%02X: Write to %s = %04x\n", m_last_scanline, xpos / 2, s_custom_reg_names[m_copper_pending_offset & 0xff], m_copper_pending_data);
custom_chip_w(m_copper_pending_offset, m_copper_pending_data);
m_copper_pending_offset = 0;
}
/* if we're waiting, check for a breakthrough */
if (m_copper_waiting)
{
int curpos = (ypos << 8) | (xpos >> 1);
/* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & m_copper_waitmask) >= (m_copper_waitval & m_copper_waitmask) &&
(!m_copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{
m_copper_waiting = false;
#if GUESS_COPPER_OFFSET
return xpos + COPPER_CYCLES_TO_PIXELS(1 + m_wait_offset);
#else
return xpos + COPPER_CYCLES_TO_PIXELS(1 + 3);
#endif
}
/* otherwise, see if this line is even a possibility; if not, punt */
if (((curpos | 0xff) & m_copper_waitmask) < (m_copper_waitval & m_copper_waitmask))
return 511;
/* else just advance another pixel */
xpos += COPPER_CYCLES_TO_PIXELS(1);
return xpos;
}
/* fetch the first data word */
word0 = read_chip_ram(m_copper_pc);
m_copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
/* fetch the second data word */
word1 = read_chip_ram(m_copper_pc);
m_copper_pc += 2;
xpos += COPPER_CYCLES_TO_PIXELS(1);
if (LOG_COPPER)
logerror("%02X.%02X: Copper inst @ %06x = %04x %04x\n", m_last_scanline, xpos / 2, m_copper_pc, word0, word1);
/* handle a move */
if ((word0 & 1) == 0)
{
int min = (CUSTOM_REG(REG_COPCON) & 2) ? 0x20 : 0x40;
/* do the write if we're allowed */
word0 = (word0 >> 1) & 0xff;
if (word0 >= min)
{
if (delay[word0] == 0)
{
if (LOG_COPPER)
logerror("%02X.%02X: Write to %s = %04x\n", m_last_scanline, xpos / 2, s_custom_reg_names[word0 & 0xff], word1);
custom_chip_w(word0, word1);
}
else // additional 2 cycles needed for non-Agnus registers
{
m_copper_pending_offset = word0;
m_copper_pending_data = word1;
}
}
/* illegal writes suspend until next frame */
else
{
if (LOG_COPPER)
logerror("%02X.%02X: Aborting copper on illegal write\n", m_last_scanline, xpos / 2);
m_copper_waitval = 0xffff;
m_copper_waitmask = 0xffff;
m_copper_waitblit = false;
m_copper_waiting = true;
return 511;
}
}
else
{
/* extract common wait/skip values */
m_copper_waitval = word0 & 0xfffe;
#if 0
if (m_copper_waitval != 0xfffe)
m_copper_waitval = (word0 & 0x00fe) | ((((word0 >> 8) & 0xff) + 1) << 8);
#endif
m_copper_waitmask = word1 | 0x8001;
m_copper_waitblit = (~word1 >> 15) & 1;
/* handle a wait */
if ((word1 & 1) == 0)
{
if (LOG_COPPER)
logerror(" Waiting for %04x & %04x (currently %04x)\n", m_copper_waitval, m_copper_waitmask, (m_last_scanline << 8) | (xpos >> 1));
m_copper_waiting = true;
}
/* handle a skip */
else
{
int curpos = (ypos << 8) | (xpos >> 1);
if (LOG_COPPER)
logerror(" Skipping if %04x & %04x (currently %04x)\n", m_copper_waitval, m_copper_waitmask, (m_last_scanline << 8) | (xpos >> 1));
/* if we're past the wait time, stop it and hold up 2 cycles */
if ((curpos & m_copper_waitmask) >= (m_copper_waitval & m_copper_waitmask) &&
(!m_copper_waitblit || !(CUSTOM_REG(REG_DMACON) & DMACON_BBUSY)))
{
if (LOG_COPPER)
logerror(" Skipped\n");
/* count the cycles it out have taken to fetch the next instruction */
m_copper_pc += 4;
xpos += COPPER_CYCLES_TO_PIXELS(2);
}
}
}
/* advance and consume 8 cycles */
return xpos;
}
/*************************************
*
* External sprite controls
@ -693,7 +495,7 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
CUSTOM_REG(REG_VPOSR) ^= VPOSR_LOF;
// reset copper and ham color
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
m_copper->vblank_sync();
m_ham_color = CUSTOM_REG(REG_COLOR00);
}
@ -736,7 +538,14 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
/* loop over the line */
next_copper_x = 0;
for (int x = 0; x < amiga_state::SCREEN_WIDTH / 2; x++)
// FIXME: without the add this increment will skip bitplane ops
// ddf_stop_pixel_max = 0xd8 * 2 = 432 + 17 + 15 + 1(*) = 465 > width / 2 (455)
// (*) because there's a comparison with <= in the bitplane code.
// There are various root causes about why this happens:
// - no separation of video and logic models;
// - the offsets we are applying to DDFSTRT and DDFSTOP, they mustn't be right (copper timings?);
// - ditto for DIW related values, they are offset in far too many places;
for (int x = 0; x < (amiga_state::SCREEN_WIDTH / 2) + 10; x++)
{
int sprpix;
@ -745,7 +554,11 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
{
/* execute the next batch, restoring and re-saving color 0 around it */
CUSTOM_REG(REG_COLOR00) = save_color0;
next_copper_x = copper_execute_next(x);
next_copper_x = m_copper->execute_next(
x,
m_last_scanline & 0xff,
bool(BIT(CUSTOM_REG(REG_DMACON), 14)) // BBUSY
);
save_color0 = CUSTOM_REG(REG_COLOR00);
if (m_genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = m_genlock_color;
@ -757,12 +570,19 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
dualpf = CUSTOM_REG(REG_BPLCON0) & BPLCON0_DBLPF;
/* compute the pixel fetch parameters */
ddf_start_pixel = (CUSTOM_REG(REG_DDFSTRT) & (hires ? 0xfc : 0xf8)) * 2;
// lastbtle sets 0x34-0xd0, lores
// swordsod sets 0x38-0xd6 (on gameplay), lores
// TODO: verify hires, fix mask for ECS (which can set bit 1 too)
// ddf_start_pixel = (CUSTOM_REG(REG_DDFSTRT) & (hires ? 0xfc : 0xf8)) * 2;
ddf_start_pixel = (CUSTOM_REG(REG_DDFSTRT) & 0xfc) * 2;
ddf_start_pixel += hires ? 9 : 17;
ddf_stop_pixel = (CUSTOM_REG(REG_DDFSTOP) & (hires ? 0xfc : 0xf8)) * 2;
// ddf_stop_pixel = (CUSTOM_REG(REG_DDFSTOP) & (hires ? 0xfc : 0xf8)) * 2;
ddf_stop_pixel = (CUSTOM_REG(REG_DDFSTOP) & 0xfc) * 2;
ddf_stop_pixel += hires ? (9 + defbitoffs) : (17 + defbitoffs);
if ( ( CUSTOM_REG(REG_DDFSTRT) ^ CUSTOM_REG(REG_DDFSTOP) ) & 0x04 )
// TODO: verify this one on actual hires mode
// lastbtle definitely don't need this (enables bit 2 of ddfstrt while in lores mode)
if ( ( CUSTOM_REG(REG_DDFSTRT) ^ CUSTOM_REG(REG_DDFSTOP) ) & 0x04 && hires )
ddf_stop_pixel += 8;
// display window
@ -934,6 +754,8 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
pri = (sprpix >> 10);
/* sprite has priority */
// TODO: verify if PF2Px priority applies to HAM too
// (technically it's a non-dual too?)
if (sprpix && pf1pri > pri)
{
dst[x*2+0] =
@ -992,7 +814,10 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
pri = (sprpix >> 10);
/* sprite has priority */
if (sprpix && pf1pri > pri)
// alfred OCS won't draw player sprite if PF1Px is used here
// (writes $0038 to bplcon2)
// According to HRM PF2Px is used there for non-dual playfield
if (sprpix && pf2pri > pri)
{
dst[x*2+0] =
dst[x*2+1] = m_palette->pen(CUSTOM_REG(REG_COLOR00 + pix));
@ -1001,6 +826,9 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
/* playfield has priority */
else
{
// TODO: fix SWIV wrong colors for text layer
// Abuses of an undocumented OCS/ECS HW bug where priority >= 5 (7 in the specific case)
// makes the bitplanes to only output bit 4 discarding the other pixels
dst[x*2+0] = m_palette->pen(CUSTOM_REG(REG_COLOR00 + pfpix0));
dst[x*2+1] = m_palette->pen(CUSTOM_REG(REG_COLOR00 + pfpix1));
}
@ -1027,16 +855,6 @@ void amiga_state::render_scanline(bitmap_rgb32 &bitmap, int scanline)
// save
if (dst != nullptr)
std::copy_n(dst, amiga_state::SCREEN_WIDTH, &m_flickerfixer.pix(save_scanline));
#if GUESS_COPPER_OFFSET
if (m_screen->frame_number() % 64 == 0 && scanline == 0)
{
if (machine().input().code_pressed(KEYCODE_Q))
popmessage("%d", m_wait_offset -= 1);
if (machine().input().code_pressed(KEYCODE_W))
popmessage("%d", m_wait_offset += 1);
}
#endif
}

View File

@ -1,8 +1,8 @@
// license:BSD-3-Clause
// copyright-holders:Ernesto Corvi, Mariusz Wojcieszek, Aaron Giles
/***************************************************************************
/**************************************************************************************************
Amiga AGA hardware
Amiga AGA hardware "Lisa"
Driver by: Ernesto Corvi, Mariusz Wojcieszek, Aaron Giles
@ -13,11 +13,16 @@ Done:
- HAM8 mode
- preliminary sprites
To do:
- incorrect hstart/hstop values in CD32 logo, lsrquiz & lsrquiz2
- sprite collisions
TODO:
- Merge with base OCS/ECS Denise video emulation, use virtual overrides where applicable;
- High bits sprite collisions;
- SHRES video mode;
- Confirm diwstrt/diwstop values;
- Add custom screen geometry registers (specific to AGA chipset, $1c0-$1ef, most are shared
with Agnus/Alice really);
- Remaining unemulated new registers (ZD pin, SOG pin, SSCAN2, BRDRBLNK, BRDRSPRT, BPLAMx);
***************************************************************************/
**************************************************************************************************/
#include "emu.h"
#include "includes/amiga.h"
@ -30,7 +35,6 @@ To do:
*
*************************************/
#define GUESS_COPPER_OFFSET 0
#define LOG_SPRITE_DMA 0
@ -46,14 +50,16 @@ void amiga_state::aga_palette_write(int color_reg, uint16_t data)
int r,g,b;
int cr,cg,cb;
int color;
u8 pal_bank = (CUSTOM_REG(REG_BPLCON3) >> 13) & 0x07;
color = ((CUSTOM_REG(REG_BPLCON3) >> 13) & 0x07)*32 + color_reg;
color = (pal_bank * 32) + color_reg;
r = (data & 0xf00) >> 8;
g = (data & 0x0f0) >> 4;
b = (data & 0x00f) >> 0;
cr = m_aga_palette[color].r();
cg = m_aga_palette[color].g();
cb = m_aga_palette[color].b();
// LOCT bit
if (BIT(CUSTOM_REG(REG_BPLCON3),9))
{
// load low nibbles
@ -67,7 +73,13 @@ void amiga_state::aga_palette_write(int color_reg, uint16_t data)
cg = (g << 4) | g;
cb = (b << 4) | b;
}
m_aga_palette[color] = rgb_t(cr,cg,cb);
m_aga_palette[color] = rgb_t(cr, cg, cb);
// make a copy for Extra Half Brite mode
if (pal_bank == 0)
{
m_aga_ehb_palette[color_reg] = rgb_t(cr, cg, cb);
m_aga_ehb_palette[color_reg + 32] = rgb_t(cr >> 1, cg >> 1, cb >> 1);
}
}
/*************************************
@ -80,6 +92,15 @@ VIDEO_START_MEMBER(amiga_state,amiga_aga)
{
VIDEO_START_CALL_MEMBER( amiga );
for (int j = 0; j < 256; j++)
{
int pf1pix = ((j >> 0) & 1) | ((j >> 1) & 2) | ((j >> 2) & 4) | ((j >> 3) & 8);
int pf2pix = ((j >> 1) & 1) | ((j >> 2) & 2) | ((j >> 3) & 4) | ((j >> 4) & 8);
m_separate_bitplanes[0][j] = (pf1pix || !pf2pix) ? pf1pix : (pf2pix + 16);
m_separate_bitplanes[1][j] = pf2pix ? (pf2pix + 16) : pf1pix;
}
m_aga_diwhigh_written = 0;
}
@ -142,6 +163,8 @@ void amiga_state::aga_update_sprite_dma(int scanline)
{
int dmaenable = (CUSTOM_REG(REG_DMACON) & (DMACON_SPREN | DMACON_DMAEN)) == (DMACON_SPREN | DMACON_DMAEN);
int num, maxdma;
const u16 sprctl_offs[4] = {2, 4, 4, 8};
const u16 spr_fmode_inc = sprctl_offs[(CUSTOM_REG(REG_FMODE) >> 2) & 0x03];
/* channels are limited by DDFSTART */
maxdma = (CUSTOM_REG(REG_DDFSTRT) - 0x14) / 4;
@ -163,27 +186,24 @@ void amiga_state::aga_update_sprite_dma(int scanline)
/* fetch data into the control words */
CUSTOM_REG(REG_SPR0POS + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 0);
CUSTOM_REG(REG_SPR0CTL + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + 2);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
/* fetch additional words */
switch((CUSTOM_REG(REG_FMODE) >> 2) & 0x03)
{
case 0:
break;
case 1:
case 2:
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 4;
break;
case 3:
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 3*4;
break;
}
// diggers AGA suggests that the fmode increments with ctl are interleaved,
// otherwise no sprites are drawn.
// (it enables sprite 0 only, and +8 for the vstop values)
CUSTOM_REG(REG_SPR0CTL + 4 * num) = read_chip_ram(CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) + spr_fmode_inc);
CUSTOM_REG_LONG(REG_SPR0PTH + 2 * num) += 2 * spr_fmode_inc;
if (LOG_SPRITE_DMA) logerror("%3d:sprite %d fetch: pos=%04X ctl=%04X\n", scanline, num, CUSTOM_REG(REG_SPR0POS + 4 * num), CUSTOM_REG(REG_SPR0CTL + 4 * num));
}
u16 spr0ctl = CUSTOM_REG(REG_SPR0CTL + 4 * num);
/* compute vstart/vstop */
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 6) & 0x100);
vstop = (CUSTOM_REG(REG_SPR0CTL + 4 * num) >> 8) | ((CUSTOM_REG(REG_SPR0CTL + 4 * num) << 7) & 0x100);
// bits 6 and 5 are respectively vstart bit 9 and vstop bit 9
// TODO: do they disable with non-AGA modes?
vstart = (CUSTOM_REG(REG_SPR0POS + 4 * num) >> 8);
vstart |= (spr0ctl & 0x04) ? 0x100 : 0;
vstart |= (spr0ctl & 0x40) ? 0x200 : 0;
vstop = (spr0ctl >> 8);
vstop |= (spr0ctl & 0x02) ? 0x100 : 0;
vstop |= (spr0ctl & 0x20) ? 0x200 : 0;
/* if we hit vstart, enable the comparitor */
if (scanline == vstart)
@ -366,11 +386,11 @@ uint8_t amiga_state::aga_assemble_even_bitplanes(int planes, int ebitoffs)
return pix;
}
void amiga_state::aga_fetch_bitplane_data(int plane)
void amiga_state::aga_fetch_bitplane_data(int plane, u8 bitplane_fmode)
{
uint64_t *aga_bpldat = m_aga_bpldat;
switch (CUSTOM_REG(REG_FMODE) & 0x03)
switch (bitplane_fmode)
{
case 0:
aga_bpldat[plane] = (uint64_t)read_chip_ram(CUSTOM_REG_LONG(REG_BPL1PTH + plane * 2));
@ -404,8 +424,14 @@ void amiga_state::aga_fetch_bitplane_data(int plane)
*
*************************************/
rgb_t amiga_state::aga_update_ham(int newpix)
rgb_t amiga_state::aga_update_ham(int newpix, int planes)
{
// if not in AGA mode just return the legacy HAM6 mode
// CD32 would otherwise have ... interesting result with CDTV townona
if (!(planes & 8))
return m_palette->pen(amiga_state::update_ham(newpix));
// HAM8
switch (newpix & 0x03)
{
case 0:
@ -439,7 +465,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
{
uint16_t save_color0 = CUSTOM_REG(REG_COLOR00);
int ddf_start_pixel = 0, ddf_stop_pixel = 0;
int hires = 0, dualpf = 0, ham = 0;
int hires = 0, dualpf = 0, ham = 0, ehb = 0;
int pf1pri = 0, pf2pri = 0;
int planes = 0;
@ -463,7 +489,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
if (CUSTOM_REG(REG_BPLCON0) & BPLCON0_LACE)
CUSTOM_REG(REG_VPOSR) ^= VPOSR_LOF;
copper_setpc(CUSTOM_REG_LONG(REG_COP1LCH));
m_copper->vblank_sync();
m_ham_color = CUSTOM_REG(REG_COLOR00);
}
@ -505,8 +531,25 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
CUSTOM_REG(REG_COLOR00) = m_genlock_color;
/* loop over the line */
next_copper_x = 2; /* copper runs on odd timeslots */
for (int x = 0; x < amiga_state::SCREEN_WIDTH / 2; x++)
/* copper runs on odd timeslots */
// TODO: diverges wrt OCS, is this right?
next_copper_x = 2;
// TODO: verify where we're missing pixels here for the GFX pitch bitplane corruptions
// - wbenc30 scrolling in lores mode (fmode=3, expects a +58!, verify ddfstrt)
// - roadkill title (fmode=3, max +14), gameplay uses fmode=1
// - sockid_a, alfred gameplay (fmode=1)
// - virocp_a (fmode=1, +26)
// - ssf2t (fmode=3, wants >+100, scrolling is very offset)
// - turbojam gameplay
// (fmode=3, unaffected here, may be missing ddfstop bits given the screen masking)
// - watchtow gameplay (fmode=3, copper timings)
// - cd32 cdtv:insidino copyright screen (fmode=3)
// - cd32 cdtv:labytime intro/tutorial screens
// (swaps between fmode=1 and 3, verify ddfstrt / ddfstop)
const int offset_hack[] = { 10, 11, 11, 13 };
const u8 bitplane_fmode = CUSTOM_REG(REG_FMODE) & 0x3;
for (int x = 0; x < (amiga_state::SCREEN_WIDTH / 2) + offset_hack[bitplane_fmode]; x++)
{
int sprpix;
@ -515,22 +558,40 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
{
/* execute the next batch, restoring and re-saving color 0 around it */
CUSTOM_REG(REG_COLOR00) = save_color0;
next_copper_x = copper_execute_next(x);
next_copper_x = m_copper->execute_next(
x,
m_last_scanline & 0xff,
bool(BIT(CUSTOM_REG(REG_DMACON), 14)) // BBUSY
);
save_color0 = CUSTOM_REG(REG_COLOR00);
if (m_genlock_color != 0xffff)
CUSTOM_REG(REG_COLOR00) = m_genlock_color;
/* compute update-related register values */
planes = (CUSTOM_REG(REG_BPLCON0) & (BPLCON0_BPU0 | BPLCON0_BPU1 | BPLCON0_BPU2)) >> 12;
// TODO: verify number of planes that doesn't go beyond 8
if ( CUSTOM_REG(REG_BPLCON0) & BPLCON0_BPU3 )
planes |= 8;
hires = CUSTOM_REG(REG_BPLCON0) & BPLCON0_HIRES;
ham = CUSTOM_REG(REG_BPLCON0) & BPLCON0_HOMOD;
dualpf = CUSTOM_REG(REG_BPLCON0) & BPLCON0_DBLPF;
// TODO: emulate SHRES mode
// cfr. a1200 -bios logica2,
// press any key when prompted, select A1200 (5) -> Display Menu (9) -> Super HIRES HAM mode (8)
// In theory it's simple: maps bitplanes in 35ns resolution, offsetting where needed.
// In practice we need to separate bitplane delays & drawing first.
//shres = CUSTOM_REG(REG_BPLCON0) & 0x0040;
// In AGA Extra Half-Brite applies if this condition is satisfied
// (bit 9 of BPLCON2 is KILLEHB)
// cfr. bblow_a main menu
// TODO: verify if it needs no hires and no shres too
//ehb = !ham && !dualpf && planes == 6 && !bool(BIT(CUSTOM_REG(REG_BPLCON2), 9));
ehb = (CUSTOM_REG(REG_BPLCON0) & 0x7c10) == 0x6000 && !bool(BIT(CUSTOM_REG(REG_BPLCON2), 9));
/* get default bitoffset */
switch(CUSTOM_REG(REG_FMODE) & 0x3)
switch(bitplane_fmode)
{
case 0: defbitoffs = 15; break;
case 1:
@ -539,9 +600,13 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
}
/* compute the pixel fetch parameters */
// FIXME: offsets applied are definitely not right
// does ddf_start_pixel offsets with fmode != 0?
// wbenc30 expects a +8 to align the screen with fmode == 3, which may or may not be right
ddf_start_pixel = ( CUSTOM_REG(REG_DDFSTRT) & 0xfc ) * 2 + (hires ? 9 : 17);
ddf_stop_pixel = ( CUSTOM_REG(REG_DDFSTOP) & 0xfc ) * 2 + (hires ? (9 + defbitoffs - ((defbitoffs >= 31) ? 16 : 0)) : (17 + defbitoffs));
// FIXME: as like OCS/ECS Amiga verify this one
if ( ( CUSTOM_REG(REG_DDFSTRT) ^ CUSTOM_REG(REG_DDFSTOP) ) & 0x04 )
ddf_stop_pixel += 8;
@ -567,6 +632,26 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
{
odelay = CUSTOM_REG(REG_BPLCON1) & 0xf;
edelay = ( CUSTOM_REG(REG_BPLCON1) >> 4 ) & 0x0f;
// extended delays for AGA
// FIXME: check above table for implications about this
switch( bitplane_fmode )
{
case 1:
case 2:
odelay += (CUSTOM_REG(REG_BPLCON1) & 0x0400) >> 6;
edelay += (CUSTOM_REG(REG_BPLCON1) & 0x4000) >> 10;
odelay ^= 0x10;
edelay ^= 0x10;
break;
case 3:
odelay += (CUSTOM_REG(REG_BPLCON1) & 0x0400) >> 6;
edelay += (CUSTOM_REG(REG_BPLCON1) & 0x4000) >> 10;
if (CUSTOM_REG(REG_BPLCON1) & 0x0800)
odelay ^= 0x20;
if (CUSTOM_REG(REG_BPLCON1) & 0x8000)
edelay ^= 0x20;
break;
}
if ( hires )
{
@ -607,7 +692,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
{
for (pl = 0; pl < planes; pl += 2)
{
aga_fetch_bitplane_data(pl);
aga_fetch_bitplane_data(pl, bitplane_fmode);
}
}
@ -625,7 +710,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
for (pl = 0; pl < planes; pl += 2)
{
aga_fetch_bitplane_data(pl);
aga_fetch_bitplane_data(pl, bitplane_fmode);
}
}
@ -648,7 +733,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
{
for (pl = 1; pl < planes; pl += 2)
{
aga_fetch_bitplane_data(pl);
aga_fetch_bitplane_data(pl, bitplane_fmode);
}
}
@ -666,7 +751,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
for (pl = 1; pl < planes; pl += 2)
{
aga_fetch_bitplane_data(pl);
aga_fetch_bitplane_data(pl, bitplane_fmode);
}
}
@ -698,20 +783,22 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
CUSTOM_REG(REG_CLXDAT) |= (sprpix >> 1) & 0x1e0;
if ((collide & (ecolmask | ocolmask)) == 0)
CUSTOM_REG(REG_CLXDAT) |= 0x001;
// TODO: CLXCON2
/* if we are within the display region, render */
if (dst != nullptr && x >= m_diw.left() && x < m_diw.right())
{
int pix, pri;
/* hold-and-modify mode -- assume low-res (hi-res not supported by the hardware) */
/* hold-and-modify mode -- hires and shres supported (cfr. roadkill) */
if (ham)
{
/* update the HAM color */
pfpix0 = aga_update_ham(pfpix0);
const rgb_t pfpix0_rgb = aga_update_ham(pfpix0, planes);
const rgb_t pfpix1_rgb = (hires) ? aga_update_ham(pfpix1, planes) : pfpix0_rgb;
pix = sprpix & 0xff;
pri = (sprpix >> 10);
pri = (sprpix >> 12);
/* sprite has priority */
if (sprpix && pf1pri > pri)
@ -723,8 +810,8 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
/* playfield has priority */
else
{
dst[x*2+0] =
dst[x*2+1] = pfpix0;
dst[x*2+0] = pfpix0_rgb;
dst[x*2+1] = pfpix1_rgb;
}
}
@ -732,7 +819,7 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
else if (dualpf)
{
/* mask out the sprite if it doesn't have priority */
pix = sprpix & 0x1f;
pix = sprpix & 0xff;
pri = (sprpix >> 12);
if (pix)
{
@ -781,8 +868,10 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
/* playfield has priority */
else
{
dst[x*2+0] = aga_palette[pfpix0];
dst[x*2+1] = aga_palette[pfpix1];
// TODO: does it applies to sprites too?
rgb_t *dst_palette = ehb ? m_aga_ehb_palette : aga_palette;
dst[x*2+0] = dst_palette[pfpix0];
dst[x*2+1] = dst_palette[pfpix1];
}
}
}
@ -814,14 +903,29 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
/* end of the line: time to add the modulos */
if (scanline >= m_diw.top() && scanline < m_diw.bottom())
{
int16_t odd_modulo = CUSTOM_REG_SIGNED(REG_BPL1MOD);
int16_t even_modulo = CUSTOM_REG_SIGNED(REG_BPL2MOD);
// bscan2, vkart AGA
if (CUSTOM_REG(REG_FMODE) & 0x4000)
{
int vstart = CUSTOM_REG(REG_DIWSTRT) >> 8;
vstart |= (CUSTOM_REG(REG_DIWHIGH) & 7) << 8;
int16_t current_modulo = ((vstart ^ (scanline ^ 1)) & 1) ? odd_modulo : even_modulo;
for (pl = 0; pl < planes; pl ++)
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += current_modulo;
}
else
{
/* update odd planes */
for (pl = 0; pl < planes; pl += 2)
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += CUSTOM_REG_SIGNED(REG_BPL1MOD);
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += odd_modulo;
/* update even planes */
for (pl = 1; pl < planes; pl += 2)
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += CUSTOM_REG_SIGNED(REG_BPL2MOD);
CUSTOM_REG_LONG(REG_BPL1PTH + pl * 2) += even_modulo;
}
}
/* restore color00 */
@ -830,16 +934,6 @@ void amiga_state::aga_render_scanline(bitmap_rgb32 &bitmap, int scanline)
// save
if (dst != nullptr)
std::copy_n(dst, amiga_state::SCREEN_WIDTH, &m_flickerfixer.pix(save_scanline));
#if GUESS_COPPER_OFFSET
if (m_screen->frame_number() % 64 == 0 && scanline == 0)
{
if (machine.input().code_pressed(KEYCODE_Q))
popmessage("%d", wait_offset -= 1);
if (machine.input().code_pressed(KEYCODE_W))
popmessage("%d", wait_offset += 1);
}
#endif
}