mirror of
https://github.com/libretro/mame2003-plus-libretro.git
synced 2026-11-07 18:36:31 -10:00
Compare commits
166
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
38d906cb98 | ||
|
|
e49db47d7d | ||
|
|
d87508ce4f | ||
|
|
4fd1c76422 | ||
|
|
c262d4a4b6 | ||
|
|
c47cda1f40 | ||
|
|
bc75df8087 | ||
|
|
ea58c97b57 | ||
|
|
14e3abc89f | ||
|
|
ac620b3686 | ||
|
|
bd64b9de5e | ||
|
|
196f1d69d3 | ||
|
|
2173c6021d | ||
|
|
ab56912e49 | ||
|
|
bf0dc9c8c0 | ||
|
|
03fc843ad8 | ||
|
|
652fd97a6d | ||
|
|
b79eb3e9fa | ||
|
|
c0de8d54ba | ||
|
|
ce92716fca | ||
|
|
453b679c80 | ||
|
|
ffc68e38d9 | ||
|
|
080e2f8916 | ||
|
|
65d2272c9b | ||
|
|
db6bffdae0 | ||
|
|
c6a547a379 | ||
|
|
17c28f93c1 | ||
|
|
da65b34feb | ||
|
|
d53b244990 | ||
|
|
5865842962 | ||
|
|
9525caa7e8 | ||
|
|
483d854518 | ||
|
|
4e96962446 | ||
|
|
67e99574d4 | ||
|
|
ca0dc1a147 | ||
|
|
45d3576576 | ||
|
|
8ff668596c | ||
|
|
1c23227c79 | ||
|
|
39fcb104e2 | ||
|
|
d8ddd5b9f5 | ||
|
|
a514e1f0ac | ||
|
|
d0dd053834 | ||
|
|
73fcfe418d | ||
|
|
e36928faac | ||
|
|
7d9da4e99a | ||
|
|
0f2695d091 | ||
|
|
b96cd8c43a | ||
|
|
76a64e85dd | ||
|
|
d9ef30cf14 | ||
|
|
1a3ae77e39 | ||
|
|
d483d33314 | ||
|
|
3c9fe3a43b | ||
|
|
81fac8a81a | ||
|
|
b3cf0a37d2 | ||
|
|
4f83ca25f1 | ||
|
|
a275f8dfc4 | ||
|
|
2df7f7b29d | ||
|
|
8ed414a1f5 | ||
|
|
d708f399f7 | ||
|
|
dc3148e25a | ||
|
|
ee687592a7 | ||
|
|
5e0aeb4cb4 | ||
|
|
620c7ba7d1 | ||
|
|
4a9ed46a7b | ||
|
|
969075a5ae | ||
|
|
440a6dc232 | ||
|
|
3234504360 | ||
|
|
7ebb758a6a | ||
|
|
ffc7666884 | ||
|
|
da3a90f659 | ||
|
|
0f88b8feae | ||
|
|
1624990be3 | ||
|
|
25900bae57 | ||
|
|
8343ab6b0e | ||
|
|
38a7da6eac | ||
|
|
f1abec1d1a | ||
|
|
59f7ca7c30 | ||
|
|
9aece938b6 | ||
|
|
505733a2df | ||
|
|
23a56e6afe | ||
|
|
28bb883273 | ||
|
|
149c6e2640 | ||
|
|
5bd572a2b8 | ||
|
|
5262c77700 | ||
|
|
a27a08f661 | ||
|
|
2a14d0c3f8 | ||
|
|
f32b6d8a95 | ||
|
|
0aaf055d11 | ||
|
|
c53f2b4206 | ||
|
|
0b06ca52dc | ||
|
|
7b46a717d8 | ||
|
|
ce908de1c1 | ||
|
|
fbd9882765 | ||
|
|
1d96012a6f | ||
|
|
a6087d4e1a | ||
|
|
fdb7a57451 | ||
|
|
b2855ef3b1 | ||
|
|
98ea5e6469 | ||
|
|
6b20b595a4 | ||
|
|
804b9baabc | ||
|
|
5443426940 | ||
|
|
94ee7d65ee | ||
|
|
f61aa3a0b5 | ||
|
|
c797619396 | ||
|
|
9029a8abec | ||
|
|
5563d70290 | ||
|
|
23c1680f56 | ||
|
|
f518b40918 | ||
|
|
521a327dd9 | ||
|
|
8a9224a9a6 | ||
|
|
cfac240042 | ||
|
|
c5233bcb58 | ||
|
|
a5e5261093 | ||
|
|
92c7b8e475 | ||
|
|
62eca3b507 | ||
|
|
b8df278931 | ||
|
|
d3d8defb48 | ||
|
|
bf6a7455d7 | ||
|
|
89a47488e9 | ||
|
|
b12d6012b5 | ||
|
|
2decddc0b5 | ||
|
|
fd01c495ad | ||
|
|
eb611beff8 | ||
|
|
4a79de6337 | ||
|
|
7b1ad60b94 | ||
|
|
b5ca65f5fd | ||
|
|
5f39e722a5 | ||
|
|
74a1af5baf | ||
|
|
ccaebab82e | ||
|
|
aa2b32f913 | ||
|
|
b0068b501e | ||
|
|
3277597377 | ||
|
|
da8c86f159 | ||
|
|
e05caba0aa | ||
|
|
9d9d1ed901 | ||
|
|
155d68254c | ||
|
|
0fe5665808 | ||
|
|
97cb277199 | ||
|
|
d73ba22c26 | ||
|
|
64de9b21ed | ||
|
|
1104e225f9 | ||
|
|
21c9f8ffd4 | ||
|
|
10315f744e | ||
|
|
b52156ee5d | ||
|
|
a0ab0427b9 | ||
|
|
c620bfebef | ||
|
|
f073a5af73 | ||
|
|
0d9a325c96 | ||
|
|
31419303cb | ||
|
|
0077ef7e41 | ||
|
|
546424f3cd | ||
|
|
8393e124af | ||
|
|
0f72193fcc | ||
|
|
5da0428c7f | ||
|
|
e059bb0fe8 | ||
|
|
6e6f19aa43 | ||
|
|
9bbb94cf6d | ||
|
|
d3ac6c95f2 | ||
|
|
3a2f7f39b1 | ||
|
|
07a41088de | ||
|
|
21256d2412 | ||
|
|
a045126dad | ||
|
|
6c514a3242 | ||
|
|
dc1f391a83 | ||
|
|
93159c0ce9 | ||
|
|
5bbb84086c |
No files matched your search
+27
-1
@@ -29,6 +29,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Bare Knuckle II (chinese bootleg of Megadrive version)
|
||||
* Bare Knuckle III (bootleg of Megadrive version)
|
||||
* Baryon: Future Assault
|
||||
* Beastie Feastie (Epos Tristar 9000) - Romset `beastf`; the Pac-Man conversion is now `beastfp`, as in current MAME
|
||||
* Big Fight - Big Trouble In The Atlantic Ocean
|
||||
* Bomb Kick
|
||||
* Boogie Wings
|
||||
@@ -155,6 +156,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Ms. Pacman Twin
|
||||
* Mrs. Dynamite
|
||||
* Multi Champ Deluxe * Mature *
|
||||
* New Zero Team
|
||||
* Ninja Kazan
|
||||
* Oo Parts (Japan, Prototype)
|
||||
* Opa Opa (Rev A Unprotected)
|
||||
@@ -186,7 +188,11 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Racing Beat
|
||||
* Racing Hero
|
||||
* Rage Of The Dragons
|
||||
* Raiden II
|
||||
* Raiden DX
|
||||
* Raiden II / Raiden DX New
|
||||
* Recalhorn (prototype)
|
||||
* Revenger '84 (newer) - Romset `revngr84`; the older set `revenger` is a bad dump and stays not working
|
||||
* Riot
|
||||
* Rolling Crush
|
||||
* Round Up 5 - Super Delta Force
|
||||
@@ -218,8 +224,11 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Space Raider
|
||||
* Spectrum 2000 (Euro)
|
||||
* Squash
|
||||
* Stadium Cross (World, linkable) and (US) - Romsets `scrossa`, `scrossu`; `scross` now uses the ROM names of current MAME
|
||||
* Star Fire 2
|
||||
* Steel Worker
|
||||
* Street Fighter III 3rd Strike: Fight for the Future (Widescreen 20220908, Bank Bank hack) - Romset `sfiii3ws`
|
||||
* Street Fighter Zero 3 Mix v0.32 (Zero800 hack, CPS2Turbo) - Romset `sfz3mix`, optional music samples `sfz3mix.zip`
|
||||
* Success Joe
|
||||
* Super Bishi Bashi Championship (ver JAA, 2 Players)
|
||||
* Super Bubble Bobble (Sun Mixing, Megadrive clone hardware)
|
||||
@@ -268,11 +277,13 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Woodpecker
|
||||
* World Cup Volley 95
|
||||
* Xeno Crisis
|
||||
* Zero Team 2000
|
||||
* Zintrick
|
||||
* Zupapa
|
||||
|
||||
## New Clones
|
||||
|
||||
* Asura Buster - Eternal Warriors (USA), (Japan, set 2) and (Japan) (ARCADIA review build) - Romsets `asurabus`, `asurabusja`, `asurabusjr`; the Japan set 1 is now `asurabusj`, as in current MAME
|
||||
* Battle Shark (Japan, Joystick)
|
||||
* Botanic (French version)
|
||||
* Bubble Bobble (prototype on tokio hardware)
|
||||
@@ -452,11 +463,13 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Phantasm - Romset `phantasm`
|
||||
* Photo Y2k - Romset `photoy2k`
|
||||
* Pigskin 621AD - Romset `pigskin`
|
||||
* Princess Clara Daisakusen - Romset `prikura`
|
||||
* Power Drive - Romset `powerdrv`
|
||||
* Prebillian - `pbillian`
|
||||
* Pro Baseball Skill Tryout - `tryout`
|
||||
* Puzzle King (PacMan 2 with Tetris & HyperMan 2 & Snow Bros - `4in1boot`
|
||||
* Rabbit - Romset `rabbit` - no sound
|
||||
* Raiden II - Romset `raiden2`
|
||||
* Rampage - Romsets `rampage` and `rampage2`
|
||||
* Risky Challenge - Romset `riskchal`
|
||||
* Rohga Armor Force - Romsets `rohga`, `rohgah`, `rohgau`
|
||||
@@ -487,6 +500,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Tapper - Romset `tapper`
|
||||
* Target Ball (Nude) - Romset `tgtball`
|
||||
* Task Force Harrier - Romsets `tharrier` and `tharierj`
|
||||
* The Dealer - Romset `dealer` - Epos Tristar 9000 board from current MAME
|
||||
* Thunder Blade - Romsets `thndrbld` and `thndrbld1`
|
||||
* Thunder Dragon - Romset `tdragon` - Minor sound issues remaining
|
||||
* Thunder Strike - Romset `tstrike`
|
||||
@@ -575,6 +589,7 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
* Air Buster
|
||||
* Ashita no Joe
|
||||
* Asterix
|
||||
* Asura Blade, Asura Buster (no more repeated voices and sound effects)
|
||||
* Athena
|
||||
* Bandito
|
||||
* Big Event Golf
|
||||
@@ -692,6 +707,8 @@ The list of direct contributors to the MAME 2003-Plus github repository can be f
|
||||
|
||||
## New and/or Recommended Input Options and Settings
|
||||
|
||||
* Ikari (joystick hack bootleg): dual stick aiming. Set the 'Aim with Right Stick' DIP switch to On (Tab menu, Dip Switches): the player walks with the left stick and aims and fires with the right stick; with the right stick released he fires where he walks, as before. Off by default.
|
||||
|
||||
* Added 'X-Way Joystick' Option to Analog Controls Menu only for IPT_DIAL and IPT_DIAL_V devices. This option is for use with x-way rotary joysticks (where the joystick can rotate X discrete steps, 8 or 12 appears to be most common). The joystick can still move up, down, left, right and diagonally. The most famous game to use this control scheme is Ikari Warriors.
|
||||
Notes on this option:
|
||||
- When on, prevents the character from rotating two discrete steps sometimes when the rotary joystick is just rotated one step.
|
||||
@@ -1159,6 +1176,15 @@ could crash on the score calc between levels is sorted [amadvance, arcadez]
|
||||
* Ported across from FBL dink's fix for the broken text gfx layer in the Japanese version Of Cameltry [dink, arcadez]
|
||||
* Added support for Jammin a rare Atari prototype music game to the Donkey Kong driver [arcadez]
|
||||
* Added Saurian Front a super rare Williams prototype of Midway's Strike Force to the midyunit driver [arcadez]
|
||||
* Added Adventure Canoe to the taitosj driver [arcadez, jackphilippi, dink]
|
||||
* Added Adventure Canoe to the taitosj driver [arcadez, jackphilippi, dink]
|
||||
* Added support for Ketsui: Kizuna Jigoku Tachi - IKD 2007 Special Version to pgm.c [arcadez]
|
||||
* Fixed a protection related problem with powerups in Burning Force [MAMEDev, arcadez]
|
||||
* Extended IREM Drum sample support to Lode Runner 3 and 4 [dink, arcadez]
|
||||
* Improved the dip switch options for Data East's Break Thru [arcadez]
|
||||
* Fixed BG GFX colours for Crater Raider [MAMEDev, arcadez]
|
||||
* Fixed multiple sound sample issues in TAD CORP's Toki [MAMEDev, arcadez]
|
||||
* Fixed sound sample playing for SEGA's Zaxxon [MAMEDev, arcadez]
|
||||
* Fixed Palette banking problems for Pleiads [MAMEDev, arcadez]
|
||||
* Added fixes from later MAME so that Princess Clara Daisakusen now works [MAMEDev, arcadez]
|
||||
* Ported a new raiden2.c driver Raiden II Raiden DX and Zero Team etc etc now playable [Salvia, MAMEDev, FBN, vanni and claude, arcadez]
|
||||
|
||||
@@ -462,6 +462,7 @@ else ifeq ($(platform), psp1)
|
||||
AR = psp-ar$(EXE_EXT)
|
||||
PLATCFLAGS += -DPSP
|
||||
CFLAGS += -G0
|
||||
CFLAGS += -Wno-incompatible-pointer-types
|
||||
STATIC_LINKING = 1
|
||||
|
||||
# Vita
|
||||
|
||||
+143
-3
@@ -79,6 +79,9 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/machine/8255ppi.c \
|
||||
$(CORE_DIR)/machine/eeprom.c \
|
||||
$(CORE_DIR)/machine/idectrl.c \
|
||||
$(CORE_DIR)/machine/intelfsh.c \
|
||||
$(CORE_DIR)/machine/ds2404.c \
|
||||
$(CORE_DIR)/machine/ataflash.c \
|
||||
$(CORE_DIR)/machine/mathbox.c \
|
||||
$(CORE_DIR)/machine/mb87078.c \
|
||||
$(CORE_DIR)/machine/random.c \
|
||||
@@ -134,6 +137,7 @@ CPUS+=I8039@
|
||||
CPUS+=I8048@
|
||||
CPUS+=N7751@
|
||||
CPUS+=I8X41@
|
||||
CPUS+=I8051@
|
||||
CPUS+=M6800@
|
||||
CPUS+=M6801@
|
||||
CPUS+=M6802@
|
||||
@@ -167,17 +171,27 @@ CPUS+=Z8000@
|
||||
CPUS+=TMS32010@
|
||||
CPUS+=TMS32025@
|
||||
CPUS+=TMS32031@
|
||||
CPUS+=I960@
|
||||
CPUS+=MB86233@
|
||||
CPUS+=MB86235@
|
||||
CPUS+=ADSP21062@
|
||||
CPUS+=CCPU@
|
||||
CPUS+=ADSP2100@
|
||||
CPUS+=ADSP2101@
|
||||
CPUS+=ADSP2104@
|
||||
CPUS+=ADSP2105@
|
||||
CPUS+=ADSP2115@
|
||||
CPUS+=ADSP2181@
|
||||
CPUS+=PSXCPU@
|
||||
CPUS+=H83002@
|
||||
CPUS+=I386@
|
||||
CPUS+=MN10200@
|
||||
CPUS+=M37702@
|
||||
CPUS+=ASAP@
|
||||
CPUS+=UPD7810@
|
||||
CPUS+=UPD7807@
|
||||
CPUS+=ARM@
|
||||
CPUS+=ARM7@
|
||||
CPUS+=JAGUAR@
|
||||
CPUS+=R3000@
|
||||
CPUS+=R4600@
|
||||
@@ -243,6 +257,7 @@ SOUNDS+=SEGAPCM@
|
||||
SOUNDS+=RF5C68@
|
||||
SOUNDS+=CEM3394@
|
||||
SOUNDS+=C140@
|
||||
SOUNDS+=C352@
|
||||
SOUNDS+=QSOUND@
|
||||
SOUNDS+=SAA1099@
|
||||
SOUNDS+=IREMGA20@
|
||||
@@ -367,7 +382,7 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/gridlee_vidhrdw.c $(CORE_DIR)/sndhrdw/gridlee_sndhrdw.c $(CORE_DIR)/drivers/gridlee.c \
|
||||
$(CORE_DIR)/drivers/seattle.c $(CORE_DIR)/vidhrdw/voodoo_vidhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/exterm_vidhrdw.c $(CORE_DIR)/drivers/exterm.c \
|
||||
$(CORE_DIR)/machine/midwayic.c $(CORE_DIR)/sndhrdw/dcs.c \
|
||||
$(CORE_DIR)/machine/midwayic.c $(CORE_DIR)/machine/smc91c9x.c $(CORE_DIR)/sndhrdw/dcs.c \
|
||||
$(CORE_DIR)/machine/midyunit_machine.c $(CORE_DIR)/vidhrdw/midyunit_vidhrdw.c $(CORE_DIR)/drivers/midyunit.c \
|
||||
$(CORE_DIR)/drivers/midxunit.c \
|
||||
$(CORE_DIR)/machine/midwunit_machine.c $(CORE_DIR)/drivers/midwunit.c \
|
||||
@@ -481,7 +496,8 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/mitchell_vidhrdw.c $(CORE_DIR)/drivers/mitchell.c \
|
||||
$(CORE_DIR)/vidhrdw/cbasebal_vidhrdw.c $(CORE_DIR)/drivers/cbasebal.c \
|
||||
$(CORE_DIR)/vidhrdw/cps1_vidhrdw.c $(CORE_DIR)/drivers/cps1.c $(CORE_DIR)/drivers/cps2.c $(CORE_DIR)/machine/cps2crypt.c\
|
||||
$(CORE_DIR)/drivers/zn.c \
|
||||
$(CORE_DIR)/drivers/zn.c $(CORE_DIR)/sndhrdw/taitozoom.c $(CORE_DIR)/sound/zsg2.c $(CORE_DIR)/cpu/tms57002/tms57002.c \
|
||||
$(CORE_DIR)/drivers/cps3.c $(CORE_DIR)/sndhrdw/cps3_sndhrdw.c \
|
||||
$(CORE_DIR)/vidhrdw/tms34061_vidhrdw.c \
|
||||
$(CORE_DIR)/machine/capbowl_machine.c $(CORE_DIR)/vidhrdw/capbowl_vidhrdw.c $(CORE_DIR)/drivers/capbowl.c \
|
||||
$(CORE_DIR)/vidhrdw/itech8_vidhrdw.c $(CORE_DIR)/drivers/itech8.c \
|
||||
@@ -805,6 +821,7 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/vidhrdw/raiden_vidhrdw.c $(CORE_DIR)/drivers/raiden.c $(CORE_DIR)/drivers/raiden2.c \
|
||||
$(CORE_DIR)/vidhrdw/dcon_vidhrdw.c $(CORE_DIR)/drivers/dcon.c \
|
||||
$(CORE_DIR)/vidhrdw/sengokmj_vidhrdw.c $(CORE_DIR)/drivers/sengokmj.c \
|
||||
$(CORE_DIR)/machine/seibuspi_machine.c $(CORE_DIR)/vidhrdw/seibuspi_vidhrdw.c $(CORE_DIR)/drivers/seibuspi.c \
|
||||
$(CORE_DIR)/sndhrdw/t5182.c \
|
||||
$(CORE_DIR)/vidhrdw/mustache_vidhrdw.c $(CORE_DIR)/drivers/mustache.c \
|
||||
$(CORE_DIR)/vidhrdw/darkmist_vidhrdw.c $(CORE_DIR)/drivers/darkmist.c \
|
||||
@@ -1042,7 +1059,11 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/drivers/n8080.c \
|
||||
$(CORE_DIR)/drivers/mirax.c \
|
||||
$(CORE_DIR)/machine/model1_machine.c $(CORE_DIR)/vidhrdw/model1_vidhrdw.c $(CORE_DIR)/drivers/model1.c \
|
||||
$(CORE_DIR)/machine/model2_machine.c $(CORE_DIR)/vidhrdw/model2_vidhrdw.c $(CORE_DIR)/drivers/model2.c \
|
||||
$(CORE_DIR)/sndhrdw/segadsb.c $(CORE_DIR)/sound/mpeg_audio.c \
|
||||
$(CORE_DIR)/machine/sega315_5881.c $(CORE_DIR)/machine/sega315_5838.c \
|
||||
$(CORE_DIR)/drivers/calorie.c \
|
||||
$(CORE_DIR)/drivers/hvyunit.c \
|
||||
$(CORE_DIR)/machine/mc8123.c \
|
||||
$(CORE_DIR)/machine/namcoio_machine.c \
|
||||
$(CORE_DIR)/drivers/tatsumi.c $(CORE_DIR)/vidhrdw/tatsumi.c $(CORE_DIR)/machine/tatsumi.c
|
||||
@@ -1092,6 +1113,14 @@ else
|
||||
CPUDEFS += -DHAS_ADSP2115=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ADSP2181@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
CPUDEFS += -DHAS_ADSP2181=1
|
||||
HAS_ADSP2100 = 1
|
||||
else
|
||||
CPUDEFS += -DHAS_ADSP2181=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring Z80@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
CPUDEFS += -DHAS_Z80=1
|
||||
@@ -1432,6 +1461,15 @@ else
|
||||
CPUDEFS += -DHAS_I8X41=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I8051@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i8051
|
||||
CPUDEFS += -DHAS_I8051=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i8051/i8051.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I8051=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring M6800@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/m6800
|
||||
@@ -1825,6 +1863,42 @@ else
|
||||
CPUDEFS += -DHAS_TMS32025=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MB86233@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mb86233
|
||||
CPUDEFS += -DHAS_MB86233=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mb86233/mb86233.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MB86233=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MB86235@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mb86235
|
||||
CPUDEFS += -DHAS_MB86235=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mb86235/mb86235.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MB86235=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ADSP21062@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/sharc
|
||||
CPUDEFS += -DHAS_ADSP21062=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/sharc/sharc.c
|
||||
else
|
||||
CPUDEFS += -DHAS_ADSP21062=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I960@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i960
|
||||
CPUDEFS += -DHAS_I960=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i960/i960.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I960=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring TMS32031@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/tms32031
|
||||
@@ -1862,6 +1936,42 @@ else
|
||||
CPUDEFS += -DHAS_PSXCPU=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring H83002@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/h83002
|
||||
CPUDEFS += -DHAS_H83002=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/h83002/h83002.c
|
||||
else
|
||||
CPUDEFS += -DHAS_H83002=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I386@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i386
|
||||
CPUDEFS += -DHAS_I386=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i386/i386.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I386=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MN10200@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mn10200
|
||||
CPUDEFS += -DHAS_MN10200=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mn10200/mn10200.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MN10200=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring M37702@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/m37710
|
||||
CPUDEFS += -DHAS_M37702=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/m37710/m37710.c $(CORE_DIR)/cpu/m37710/m37710o0.c $(CORE_DIR)/cpu/m37710/m37710o1.c $(CORE_DIR)/cpu/m37710/m37710o2.c $(CORE_DIR)/cpu/m37710/m37710o3.c
|
||||
else
|
||||
CPUDEFS += -DHAS_M37702=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ASAP@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/asap
|
||||
@@ -1911,6 +2021,15 @@ else
|
||||
CPUDEFS += -DHAS_ARM=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ARM7@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/arm7
|
||||
CPUDEFS += -DHAS_ARM7=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/arm7/arm7.c
|
||||
else
|
||||
CPUDEFS += -DHAS_ARM7=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring JAGUAR@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/jaguar
|
||||
@@ -2507,6 +2626,14 @@ else
|
||||
SOUNDDEFS += -DHAS_C140=0
|
||||
endif
|
||||
|
||||
SOUND=$(strip $(findstring C352@,$(SOUNDS)))
|
||||
ifneq ($(SOUND),)
|
||||
SOUNDDEFS += -DHAS_C352=1
|
||||
SOURCES_C += $(CORE_DIR)/sound/c352.c
|
||||
else
|
||||
SOUNDDEFS += -DHAS_C352=0
|
||||
endif
|
||||
|
||||
SOUND=$(strip $(findstring QSOUND@,$(SOUNDS)))
|
||||
ifneq ($(SOUND),)
|
||||
SOUNDDEFS += -DHAS_QSOUND=1
|
||||
@@ -2660,9 +2787,19 @@ SOUNDDEFS += -DHAS_ICS2115=0
|
||||
endif
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/mame-chd/chd.c \
|
||||
$(CORE_DIR)/lib/mame-chd/mame_sha1.c
|
||||
|
||||
# libchdr: reads the hard disk CHDs (every version, zlib/LZMA/Huffman/FLAC)
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_bitstream.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_cdrom.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_chd.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_flac.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_huffman.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzFind.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzmaDec.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzmaEnc.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/bitreader.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/cpu.c \
|
||||
@@ -2689,6 +2826,9 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/lib/zlib/unzip.c \
|
||||
$(CORE_DIR)/lib/zlib/zutil.c
|
||||
|
||||
# sljit: run-time code generator of the MIPS recompilers (empty where they are not supported)
|
||||
SOURCES_C += $(CORE_DIR)/lib/sljit/sljit_mame.c
|
||||
|
||||
ifeq ($(STATIC_LINKING),1)
|
||||
else
|
||||
SOURCES_C += \
|
||||
|
||||
+76
-1
@@ -624,6 +624,7 @@ endif
|
||||
|
||||
ifneq (,$(filter $(INCLUDE_DRV),drv_backfire core_none))
|
||||
CPUS+=ARM@
|
||||
CPUS+=ARM7@
|
||||
SOUNDS+=YMZ280B@
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/machine/decocrpt.c \
|
||||
@@ -1072,6 +1073,14 @@ else
|
||||
CPUDEFS += -DHAS_ADSP2115=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ADSP2181@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
CPUDEFS += -DHAS_ADSP2181=1
|
||||
HAS_ADSP2100 = 1
|
||||
else
|
||||
CPUDEFS += -DHAS_ADSP2181=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring Z80@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
CPUDEFS += -DHAS_Z80=1
|
||||
@@ -1412,6 +1421,15 @@ else
|
||||
CPUDEFS += -DHAS_I8X41=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring I8051@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/i8051
|
||||
CPUDEFS += -DHAS_I8051=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/i8051/i8051.c
|
||||
else
|
||||
CPUDEFS += -DHAS_I8051=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring M6800@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/m6800
|
||||
@@ -1842,6 +1860,33 @@ else
|
||||
CPUDEFS += -DHAS_PSXCPU=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring H83002@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/h83002
|
||||
CPUDEFS += -DHAS_H83002=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/h83002/h83002.c
|
||||
else
|
||||
CPUDEFS += -DHAS_H83002=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring MN10200@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/mn10200
|
||||
CPUDEFS += -DHAS_MN10200=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/mn10200/mn10200.c
|
||||
else
|
||||
CPUDEFS += -DHAS_MN10200=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring M37702@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/m37710
|
||||
CPUDEFS += -DHAS_M37702=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/m37710/m37710.c $(CORE_DIR)/cpu/m37710/m37710o0.c $(CORE_DIR)/cpu/m37710/m37710o1.c $(CORE_DIR)/cpu/m37710/m37710o2.c $(CORE_DIR)/cpu/m37710/m37710o3.c
|
||||
else
|
||||
CPUDEFS += -DHAS_M37702=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ASAP@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/asap
|
||||
@@ -1891,6 +1936,15 @@ else
|
||||
CPUDEFS += -DHAS_ARM=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring ARM7@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/arm7
|
||||
CPUDEFS += -DHAS_ARM7=1
|
||||
SOURCES_C += $(CORE_DIR)/cpu/arm7/arm7.c
|
||||
else
|
||||
CPUDEFS += -DHAS_ARM7=0
|
||||
endif
|
||||
|
||||
CPU=$(strip $(findstring JAGUAR@,$(CPUS)))
|
||||
ifneq ($(CPU),)
|
||||
OBJDIRS += $(CORE_DIR)/cpu/jaguar
|
||||
@@ -2487,6 +2541,14 @@ else
|
||||
SOUNDDEFS += -DHAS_C140=0
|
||||
endif
|
||||
|
||||
SOUND=$(strip $(findstring C352@,$(SOUNDS)))
|
||||
ifneq ($(SOUND),)
|
||||
SOUNDDEFS += -DHAS_C352=1
|
||||
SOURCES_C += $(CORE_DIR)/sound/c352.c
|
||||
else
|
||||
SOUNDDEFS += -DHAS_C352=0
|
||||
endif
|
||||
|
||||
SOUND=$(strip $(findstring QSOUND@,$(SOUNDS)))
|
||||
ifneq ($(SOUND),)
|
||||
SOUNDDEFS += -DHAS_QSOUND=1
|
||||
@@ -2640,9 +2702,19 @@ SOUNDDEFS += -DHAS_ICS2115=0
|
||||
endif
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/mame-chd/chd.c \
|
||||
$(CORE_DIR)/lib/mame-chd/mame_sha1.c
|
||||
|
||||
# libchdr: reads the hard disk CHDs (every version, zlib/LZMA/Huffman/FLAC)
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_bitstream.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_cdrom.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_chd.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_flac.c \
|
||||
$(CORE_DIR)/lib/libchdr/src/libchdr_huffman.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzFind.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzmaDec.c \
|
||||
$(CORE_DIR)/lib/libchdr/deps/lzma/LzmaEnc.c
|
||||
|
||||
SOURCES_C += \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/bitreader.c \
|
||||
$(CORE_DIR)/libretro-deps/libFLAC/cpu.c \
|
||||
@@ -2692,6 +2764,9 @@ SOURCES_C += \
|
||||
$(CORE_DIR)/lib/zlib/uncompr.c \
|
||||
$(CORE_DIR)/lib/zlib/unzip.c \
|
||||
$(CORE_DIR)/lib/zlib/zutil.c
|
||||
|
||||
# sljit: run-time code generator of the MIPS recompilers (empty where they are not supported)
|
||||
SOURCES_C += $(CORE_DIR)/lib/sljit/sljit_mame.c
|
||||
endif
|
||||
|
||||
ifeq ($(ZLIB_UNCOMPRESS), 1)
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# Capcom CPS-3: how the driver works and where it differs from the hardware
|
||||
|
||||
Sets: `redearth`, `warzard`, `sfiii`, `sfiii2`, `jojo`, `sfiii3`, `jojoba`
|
||||
and their clones (53 in all, MAME's list without the multi-game bootlegs),
|
||||
plus `sfiii4n`, the "4rd Arrange Edition 2013" hack of 3rd Strike that
|
||||
FBNeo has and MAME does not.
|
||||
|
||||
Files: `src/drivers/cps3.c` (memory map, flash SIMMs, video, DMA, sets),
|
||||
`src/sndhrdw/cps3_sndhrdw.c` (the 16 voice sample chip). A C89 port of
|
||||
current MAME's `cps3.cpp` and `cps3_a.cpp`.
|
||||
|
||||
## The board
|
||||
|
||||
- A custom Hitachi SH-2 at 25 MHz that decrypts what it reads from the BIOS,
|
||||
the program SIMMs and its cache RAM, with a per-game key stored in the
|
||||
cartridge.
|
||||
- The game in flash SIMMs: two SIMMs of 4 Fujitsu 29F016A chips (2 MB each)
|
||||
for the program, up to four SIMMs of 8 chips for graphics and samples.
|
||||
- 2D video: sprites with zoom, tilemaps drawn as sprites, a text layer,
|
||||
palette DMA with fades, character DMA with RLE decompression.
|
||||
- 16 voices of 8-bit samples read from the graphics SIMMs.
|
||||
- A SCSI CD-ROM drive: the BIOS writes the game from the CD into the SIMMs.
|
||||
|
||||
## No CD drive
|
||||
|
||||
The CD drive is not emulated. All sets run from SIMMs already written:
|
||||
|
||||
- The "NO CD" sets come with their SIMMs and a BIOS that does not look for a
|
||||
drive, as in MAME.
|
||||
- The CD sets (Europe, USA, Japan, Asia, Hispanic versions) get the SIMM data
|
||||
of their version, the same as the NO CD set of that date (the SIMM
|
||||
contents do not depend on the region, the BIOS does). As in FBNeo, which
|
||||
plays them the same way. MAME needs the CD image instead.
|
||||
- The CD BIOSes would stop on the missing drive. The BIOS has a flag the
|
||||
no-CD BIOSes have set (byte 0x1fecc, bit 0); the driver sets it, and the
|
||||
game runs from the SIMMs.
|
||||
- The Red Earth / Warzard CD BIOSes have no such flag: the driver starts the
|
||||
game from the SIMMs as the BIOS would (PC and SP from the program's vector
|
||||
table, VBR on it), as FBNeo does.
|
||||
|
||||
The flash chips answer the Fujitsu command set (ID, program, erase), but
|
||||
what is written to them is not saved: no set writes them while playing.
|
||||
|
||||
## Region
|
||||
|
||||
The region is not a switch on the board: it is a byte in the cart's flash
|
||||
(the low nibble of the BIOS byte 0x1fecb, 0x1fedb on Red Earth / Warzard),
|
||||
which the BIOS and the games read. A fake DIP switch, "Region", patches it at
|
||||
reset, as in FBNeo: Japan, Asia, Europe, USA, Hispanic, Brazil, Oceania or
|
||||
the second Asia code, or "As BIOS" to keep the dumped value. The default is
|
||||
Europe for every set, whatever region its BIOS has; 2nd Impact, which had no
|
||||
European release, defaults to USA. It changes the boot screen colour, the
|
||||
warnings, the coin settings, the language and the title (Warzard in Japan,
|
||||
Red Earth elsewhere). Change it, then reset.
|
||||
|
||||
The game options (coins, difficulty, monitor flip, language...) are in the
|
||||
games' own test menu (F2) and kept in the cart's EEPROM, saved as NVRAM.
|
||||
|
||||
## Encryption
|
||||
|
||||
The BIOS is decrypted at load. The program SIMMs are kept as dumped and also
|
||||
decrypted into a copy the CPU fetches opcodes from; data reads come out
|
||||
decrypted, as the custom CPU reads them. Two hooks in the SH-2 core (both
|
||||
optional, unused by the other SH-2 drivers) do this:
|
||||
|
||||
- `opcode_read`: the opcode fetch, from the BIOS, the decrypted program copy
|
||||
or the decrypted copy of the cache RAM.
|
||||
- `dma_read_hook`: the SH-2 DMA bypasses the decryption on the real board;
|
||||
the hook re-encrypts what the handlers decrypted.
|
||||
|
||||
`sfiii2` runs off a "dead" cartridge: the key is gone and its program is
|
||||
stored with code encrypted and data not, as in MAME.
|
||||
|
||||
## Video
|
||||
|
||||
The renderer is MAME's: sprites and tilemaps go to a render buffer of
|
||||
palette indexes (with the shadow/highlight blend bits), which is copied to the
|
||||
screen through the full screen zoom; the text layer is drawn on top. Tiles
|
||||
are read straight from the character RAM (no gfx elements to keep dirty).
|
||||
Colours are 15-bit with no extension of the low bits, as on the board (its
|
||||
video DAC has them grounded). The screen width follows the CRTC registers, as
|
||||
in MAME (384 pixels in the games checked).
|
||||
|
||||
## Idle loop
|
||||
|
||||
Each game waits for the vblank interrupt by reading a word of the main RAM
|
||||
in a loop. When the loop reads it, the CPU skips to the next event (the
|
||||
addresses are FBNeo's, one per game and version). Speed goes from about
|
||||
4.5x to 12-16x real time on an x86 core. The games run the same; only the
|
||||
attract mode can pick other fighters, since the games draw random numbers
|
||||
from the time spent in that loop.
|
||||
|
||||
## Sound
|
||||
|
||||
MAME's sound device: 16 voices, signed 8-bit samples, the board clock / 3 /
|
||||
384 (37.3 kHz), loop and end addresses, a volume per side. Levels checked
|
||||
against MAME's WAV output of the same attract mode.
|
||||
|
||||
## ROM loading of merged sets
|
||||
|
||||
Merged sets keep the files of the clones in subfolders of the parent's zip,
|
||||
with the same names (`sfiii3n/sfiii3-simm1.0`, `sfiii3nr1/sfiii3-simm1.0`).
|
||||
The ROM loader of this core matched by name only and took the first one.
|
||||
It now looks for the expected CRC first, then for the name, so merged,
|
||||
split and non-merged sets all load.
|
||||
|
||||
## Checked
|
||||
|
||||
- Attract mode of `sfiii3n`, `jojoba`, `sfiii2n`, `jojon`, `sfiiin`,
|
||||
`redearthn` against MAME 0.264 at the same frames: the same screens.
|
||||
- A game of 3rd Strike (coin, character select, fight).
|
||||
- CD sets: the regional warning screens, then the game (`sfiii3`, `sfiii3u`,
|
||||
`sfiiih`, `sfiii2`, `jojor2`, `jojobaner2`, `warzard`).
|
||||
- Save states: loaded in a new process, the game goes on frame for frame.
|
||||
- Big-endian: the PowerPC build renders as x86.
|
||||
@@ -0,0 +1,203 @@
|
||||
# Sega Model 1: how the driver works and where it differs from the hardware
|
||||
|
||||
Sets: `vr`, `vformula`, `vf`, `swa`, `swaj`, `wingwar`, `wingwaru`,
|
||||
`wingwarj`, `wingwar360`, `netmerc`.
|
||||
|
||||
Files: `src/drivers/model1.c` (boards, maps, ROMs), `src/machine/model1_machine.c`
|
||||
(the TGP), `src/vidhrdw/model1_vidhrdw.c` (the renderer, ported from current
|
||||
MAME), `src/sndhrdw/segadsb.c` (the Digital Sound Board of Star Wars Arcade).
|
||||
|
||||
## The TGP (geometry coprocessor)
|
||||
|
||||
The TGP is a Fujitsu MB86233 DSP running a program from a 315-xxxx ROM:
|
||||
315-5573 (Virtua Racing, Virtua Formula), 315-5724 (Virtua Fighter), 315-5711
|
||||
(Star Wars Arcade, Wing War, NetMerc). The V60 sends it commands (a function
|
||||
number and its arguments) through a FIFO and reads the results back.
|
||||
|
||||
The driver runs the TGP functions in C (high level emulation, HLE), started
|
||||
from MAME 0.215, the last MAME with an HLE TGP. In MAME 0.215 Virtua Racing had
|
||||
no HLE at all and Star Wars Arcade and Wing War did not work.
|
||||
|
||||
### Checked against the real program
|
||||
|
||||
The core also contains the MB86233 (from the Model 2 work), so the real TGP
|
||||
program can run next to the HLE. A development build (`-DMODEL1_TGP_DEV`)
|
||||
reads `MODEL1_TGP` from the environment:
|
||||
|
||||
- `lle`: the game runs on the real TGP program only.
|
||||
- `oracle`: the game runs on the real TGP program, the HLE gets the same
|
||||
input, and every call is compared: function, arguments, the results of
|
||||
both. The pairing follows the input stream (a call ends when the DSP takes
|
||||
the next function word), so a function giving a wrong number of results
|
||||
does not shift the others. The TGP RAM both sides keep is compared every
|
||||
frame. Every 600 frames it prints, for each function, the calls that were
|
||||
exact, near (rounding), wrong, or gave a wrong number of results.
|
||||
|
||||
With this, every function the games call was rewritten from the DSP program
|
||||
until the results match bit for bit: same table lookups (sine, 1/x, 1/sqrt,
|
||||
atan come from the TGP's table ROM through its I/O ports, with one
|
||||
multiply-subtract step), same order of the sums, same comparisons (the ALU's
|
||||
`-0` is neither negative nor positive). Checked on attract and play of
|
||||
`vr` (three tracks), `vformula`, `vf`, `swa`, `wingwar`, `wingwar360` and
|
||||
`netmerc`: no call differs and the TGP RAM stays identical.
|
||||
|
||||
Virtua Fighter's program (315-5724) is marked as a bad dump in MAME, but it
|
||||
runs the game on the MB86233 core, so it is checked the same way. About half
|
||||
of its functions differ from 315-5573 (matrix stack and saved matrices at
|
||||
other addresses, the camera, collision bitmaps, ground box test, list walks
|
||||
in the copro RAM), so it has its own table. MAME 0.215 used the Virtua Racing
|
||||
table for it, with guessed camera functions (one returned random numbers),
|
||||
which put the camera far from the fighters. For Virtua Fighter the oracle
|
||||
also compares the TGP's internal RAM after every call. Over 9000 frames of
|
||||
attract and fights, 55 functions and 3.8 million calls give the same results
|
||||
and the same RAM.
|
||||
|
||||
The table lookups, the copro RAM (0x2000 words; with address bit 0x40000 set
|
||||
the address steps by 4) and the list functions follow current MAME.
|
||||
|
||||
### Program bugs reproduced
|
||||
|
||||
The HLE reproduces what the real programs do, bugs included, because the
|
||||
games run with them on the real boards:
|
||||
|
||||
- 315-5711 `roty` starts its first sum from the DSP's `d` register, which
|
||||
still holds the dispatch address (a denormal): the first matrix element
|
||||
gets `0x6c` added to it.
|
||||
- 315-5711 `normalize` never loads y; it uses whatever the scratch word at
|
||||
`$71` holds from an earlier function (tracked by the HLE).
|
||||
- 315-5711 `f47` starts its sum of squares from the z difference.
|
||||
- 315-5711 `fsqrt` skips the mantissa step and does not return a square root.
|
||||
- The matrix stack keeps 7 levels; past them the depth only counts (315-5711
|
||||
pushes again past 8, while its pops past 7 only count). The matrix slots
|
||||
and the 315-5711 accumulator stack sit in the same TGP RAM, as on the
|
||||
board.
|
||||
- 315-5711 `f52` (0x34, matrix inverse; Star Wars Arcade calls it) works
|
||||
by cofactors, never reads the first element, ORs two elements where a
|
||||
subtract is expected, and adds in the second element the scratch word
|
||||
`$11` an earlier function left (push, multiply and read leave a matrix
|
||||
element or argument there; tracked by the HLE).
|
||||
- 315-5711 `f56` (0x38, segment against a polygon list) stops at the first
|
||||
polygon hit, not the nearest one.
|
||||
- The 315-5711 games use the current matrix before setting it: the HLE starts
|
||||
from what the TGP RAM holds at power on (zeros in the emulated TGP).
|
||||
|
||||
### What is not emulated
|
||||
|
||||
- Table entries a program leaves empty (it returns at once) take no
|
||||
arguments and give no results; 315-5724 functions no game was seen calling
|
||||
are not emulated, except the simple ones (normalize, divide, set the
|
||||
translation).
|
||||
- 315-5711 functions no game was seen calling: self tests 0x04, 0x3d, 0x3e
|
||||
(results 0), 0x42 (matrix stack pop and multiply, with bugs overwriting the
|
||||
stack), 0x21 (the program jumps into the middle of another function). They
|
||||
take and give the right number of words so the command stream stays in step.
|
||||
|
||||
### ROMs
|
||||
|
||||
The TGP program ROM stays in the sets as in current MAME. For Star Wars
|
||||
Arcade, Wing War and NetMerc the HLE follows 315-5711 with CRC 6a21f304, as
|
||||
current MAME. An older dump (CRC c5ddb8fc) differs in two words: the entry
|
||||
of `f52` (which then reads the wrong RAM and gives NaNs) and the end test
|
||||
of `f56`. It loads with a checksum warning; the HLE does not use the ROM.
|
||||
|
||||
The V60 reaches the TGP in its I/O space as well as in memory, with the
|
||||
same mirrors as current MAME: Wing War sends its boot command (8, clear the
|
||||
matrix stack) with an OUT to a mirror of the FIFO, and the real program
|
||||
waits for it before taking any other command.
|
||||
|
||||
## I/O board
|
||||
|
||||
The Model 1 I/O board (model1io, model1io2: a Z80 with its own BIOS) is
|
||||
simulated: inputs, DIP switches, analog channels and the backup are put where
|
||||
the games read them in the 2 KB dual port RAM:
|
||||
|
||||
00-07 analog channels
|
||||
08-0a IN0 - IN2 (active low)
|
||||
0b-0d DSW1 - DSW3 (active low, all off)
|
||||
0e board switches
|
||||
0f outputs (lamps, coin counters)
|
||||
11 drive board / motion base output
|
||||
20 command (2 store the backup 0x100-0x1ff, 3 load it), 21 status
|
||||
|
||||
The DIP switches must read as off: 0 turned on the debug displays of Virtua
|
||||
Racing and NetMerc. The backup is saved in the NVRAM file.
|
||||
|
||||
## Sound
|
||||
|
||||
Model 1 sound board (68000, two MultiPCM, YM3438) behind an i8251 UART at
|
||||
31250 baud, as current MAME. Star Wars Arcade also has the Digital Sound
|
||||
Board (Z80 + MPEG audio), which listens to the sound board's UART.
|
||||
|
||||
The simulated I/O board answers at once, so the V60 sends its first sound
|
||||
commands before the 68000 has finished its init. The real UART holds one byte
|
||||
and would lose the others; Virtua Fighter then stayed silent. The bytes for
|
||||
the 68000 are kept in a queue.
|
||||
|
||||
Virtua Racing and Virtua Fighter play no sound in attract mode with their
|
||||
default settings, as on the board.
|
||||
|
||||
## Save states
|
||||
|
||||
Besides the RAMs and registers, a save state keeps what MAME 0.78 does not
|
||||
save by itself and what a game sets only once: the TGP FIFOs (a state can
|
||||
fall between the words of a command, or before the V60 read the results),
|
||||
the data ROM bank, the time left of the interval and UART timers, and the
|
||||
renderer's view (viewport, light, light parameters: Virtua Fighter sends
|
||||
them only when a stage starts, and without them a loaded state drew the
|
||||
fighters black). Checked by loading in a new process: Virtua Fighter and
|
||||
Virtua Racing's attract mode go on frame for frame as in a straight run
|
||||
(analog controls: see Open questions).
|
||||
|
||||
## Other boards
|
||||
|
||||
- Link board (Virtua Racing, Virtua Formula, Wing War): not emulated; the
|
||||
games see it with its CPU in reset and run stand-alone.
|
||||
- R360 motion base (`wingwar360`): the game states it sends are answered as
|
||||
the real base does, so a game starts. No motion.
|
||||
- Polhemus tracker (`netmerc`): the board (a 386 with its own program) that
|
||||
tracks the visor is not emulated. As in current MAME, the visor pose the
|
||||
game reads at dual port RAM 0x80-0x8b (x, y, z, then three angles in
|
||||
radians * 8192) is set once at reset, looking ahead. The gun on its mount
|
||||
is not tracked: it uses the stick (analog channels 0 and 2), and moving
|
||||
goes where the gun points.
|
||||
- NetMerc gun mount calibration: the ends of both axes are kept in the
|
||||
backup RAM (0x38 / 0x3c horizontal, 0x40 / 0x44 vertical). At boot the
|
||||
game sets its factory calibration (0x46-0xc4, 0x21-0x69) only when one of
|
||||
them is zero, so a new NetMerc backup RAM is 0-filled (the other games
|
||||
get 1s, which Virtua Fighter needs): with 1s it kept them, divided by
|
||||
zero, spun the gun, failed its checksum and stayed on one attract
|
||||
screen. The stick covers the same range as the factory calibration.
|
||||
- NetMerc sound: `mpr-18134` (the first sample ROM of the first MultiPCM)
|
||||
is a bad dump, all 0xff, in the only set known (MAME has the same one).
|
||||
That MultiPCM has no sample table, so the music it plays is silent; the
|
||||
effects, on the second MultiPCM, play.
|
||||
- NetMerc defaults (test menu, GAME ASSIGNMENTS): country Japan, attract
|
||||
sound off, so attract mode is silent and starts with the Japan warning.
|
||||
|
||||
## Video
|
||||
|
||||
`model1_vidhrdw.c` is a C port of current MAME's `model1_v.cpp`. Two choices
|
||||
keep the output the same on every CPU: float to int conversions follow x86
|
||||
(out of range gives `INT_MIN`, other CPUs saturate), and the files of the TGP
|
||||
and the renderer are compiled without fused multiply-add (GCC and clang fuse
|
||||
`a*b+c` on PowerPC and ARM64). Big-endian PowerPC renders pixel for pixel as
|
||||
x86.
|
||||
|
||||
Polygons with the moire flag (Virtua Fighter's shadows) are drawn as a
|
||||
checkerboard, every other pixel, as in current MAME; a 720p capture of a
|
||||
real Virtua Fighter board shows the same pattern.
|
||||
|
||||
Compared with captures of real boards: Virtua Fighter (the stages up to
|
||||
Akira's: backgrounds, floors, colours, lighting, camera, shadows), Virtua
|
||||
Racing (Bay Bridge: start grid, bridge, HUD), Star Wars Arcade (attract:
|
||||
Star Destroyer, cockpit battle, hangar), Wing War and NetMerc.
|
||||
|
||||
## Open questions
|
||||
|
||||
- Virtua Fighter: the eight stages up to Akira's were compared with a
|
||||
capture of a real board (backgrounds, floors, colours, camera); Dural's
|
||||
stage and the bonus stage were not.
|
||||
- After loading a state during play, an analog control (Virtua Racing's
|
||||
accelerator) starts again from its rest position: the core's input
|
||||
system does not save it. Digital inputs and attract mode go on as in a
|
||||
straight run.
|
||||
@@ -0,0 +1,501 @@
|
||||
# Sega Model 2: choices that differ from the hardware
|
||||
|
||||
The Model 2 driver (`src/drivers/model2.c`) emulates the boards as the games
|
||||
see them. In a few places the hardware is not available or not emulated, and
|
||||
the driver does something simpler. Each of those choices is listed here, with
|
||||
the reason and its consequences.
|
||||
|
||||
## Communication board (network link)
|
||||
|
||||
The communication board links cabinets for multi-player games over a network.
|
||||
It is not emulated: there is no network.
|
||||
|
||||
For most games the board reads as **absent** (the CN register reads 0xff).
|
||||
The games that look for it then run as single machines.
|
||||
|
||||
### Virtual-On: board present, link always stand-alone
|
||||
|
||||
Sets: `von`, `vonu`, `vonj`.
|
||||
|
||||
**Why.** Virtual-On does not start a game without the board, even on a
|
||||
machine set to stand-alone. At boot (addresses from `von`):
|
||||
|
||||
1. `0x185d0` sets the defaults: role stand-alone, link mode 0.
|
||||
2. `0x18920` reads the link ID from the backup RAM (byte `0x1d00028`:
|
||||
0 slave, 1 master, other values stand-alone; the factory setting is 2).
|
||||
3. `0xc6480` initialises the link. It reads the board's CN register first.
|
||||
Without a board it prints "THERE IS NO COMMUNICATION BOARD!", sets the
|
||||
link mode to 0xff and returns, without looking at the link ID.
|
||||
|
||||
With link mode 0xff the game never leaves the attract mode: after a coin the
|
||||
screen stays black and silent (game mode 4, sub-state 0 waits on a status
|
||||
word that stays 0xff).
|
||||
|
||||
With a board present, step 3 enables it (CN=1) and waits for the board's
|
||||
firmware to report ready (ZFG=1, read as bit 7 of the FG register going to
|
||||
0). With the link ID on stand-alone it then returns at once and the game never
|
||||
uses the link. A board that is present but never ready stops the game at boot;
|
||||
this is also what the current MAME device does without its network
|
||||
simulation, and MAME lists these sets as not working.
|
||||
|
||||
**What the driver does.**
|
||||
|
||||
- The board reads as present and reports ready as soon as the game enables
|
||||
it (`m2comm_ctrl_w`, CN=1 sets ZFG=1). Its shared RAM is plain RAM.
|
||||
- The link ID always reads as stand-alone (`von_linkid_r`, installed over the
|
||||
backup RAM dword at `0x1d00028`). Writes still go to the backup RAM.
|
||||
|
||||
**Consequences.**
|
||||
|
||||
- Master and slave are not available. The test menu always shows
|
||||
stand-alone, whatever is chosen there.
|
||||
- The game computes the backup RAM checksum by reading through the same
|
||||
handler, so the checksum stays valid and the other settings are kept.
|
||||
- An NVRAM from another emulator with the link set to master or slave fails
|
||||
the checksum once: the game then restores its factory settings.
|
||||
|
||||
**How it was checked.** A valid NVRAM with the link ID on slave (checksum
|
||||
recomputed with the game's own CRC, table at `0x2f20` in `von`) stops at boot
|
||||
on "THIS IS SLAVE SITE" without the override. With the override, the same
|
||||
NVRAM boots, plays a game, and keeps its other settings.
|
||||
|
||||
**Not added: `vonr` (Virtual-On Relay).** That version always sets its role
|
||||
to relay (`0xf1cf0` writes 0) before the link is initialised, and then waits
|
||||
for the network. It cannot run as a single machine.
|
||||
|
||||
### Daytona USA: factory link ID forced to single at start-up
|
||||
|
||||
Sets: `daytona`, `daytonase`, `daytona93`, `daytonas`.
|
||||
|
||||
**Why.** Daytona USA runs without the board, but its factory settings in the
|
||||
program ROM set the link ID to master. On a new NVRAM (or after a factory
|
||||
reset) the game uses those settings and keeps looking for the other cabinets
|
||||
("NETWORK CHECKING"), so a game never starts.
|
||||
|
||||
**What the driver does.** When the game is loaded, `DRIVER_INIT( daytona )`
|
||||
finds the factory settings table in the program ROM (it starts with
|
||||
`SEGA@\x82`) and changes the link ID at offset 0x0b from 1 (master) to
|
||||
0 (single). The board reads as absent.
|
||||
|
||||
| Set | Table | Factory link ID | Patched |
|
||||
|---|---|---|---|
|
||||
| `daytona` | `0x39d60` | 1 (master) | yes |
|
||||
| `daytonase` | `0x3ab20` | 1 (master) | yes |
|
||||
| `daytonas` | `0x3c570` | 1 (master) | yes |
|
||||
| `daytona93` | `0x3c150` | 0 (single) | no, already single |
|
||||
|
||||
**Consequences.**
|
||||
|
||||
- Only the factory value changes. A link ID already saved in the NVRAM is
|
||||
kept, and the setting can still be changed in the test menu. Set to master
|
||||
or slave, the game waits for the network as on the real hardware; set it
|
||||
back to single to play.
|
||||
- Restoring the factory settings from the test menu gives single, not
|
||||
master.
|
||||
|
||||
### Motor Raid
|
||||
|
||||
Sets: `motoraid`.
|
||||
|
||||
The game has link code ("Network Check"), but with the board absent it
|
||||
starts and plays with its factory settings. Nothing is changed.
|
||||
|
||||
## Model 1 I/O board (original Model 2)
|
||||
|
||||
Sets: `daytona` and clones, `vcop`, `vcopa`.
|
||||
|
||||
The original Model 2 reads its inputs through a Model 1 I/O board: a Z80
|
||||
with its own BIOS, behind a dual-port RAM at `0x1c00000`.
|
||||
|
||||
- With the BIOS (`model1io.zip` for Daytona USA, `model1io2.zip` for Virtua
|
||||
Cop), the board runs its own firmware on an emulated Z80.
|
||||
- Without it, the board's firmware is simulated: the driver writes the
|
||||
inputs, the analog channels and the light guns where the games read them,
|
||||
and handles the backup commands. Both BIOS files are optional ROMs.
|
||||
|
||||
## INDY 500 and Over Rev (Model 2B, `indy500` machine)
|
||||
|
||||
Sets: `indy500`, `indy500d`, `indy500to`, `overrevb`, `overrevba`.
|
||||
|
||||
- **Drive board (force feedback).** The games write their commands to it
|
||||
through port E of the 315-5649 and never wait for an answer. It is not
|
||||
emulated: the writes are ignored, as in MAME when no drive board program
|
||||
is loaded.
|
||||
- **Communication board program.** The Over Rev sets list the communication
|
||||
board program (`epr-18643.7`) as in MAME. Its CPU is not run, so the ROM
|
||||
is optional: the sets load with or without it.
|
||||
- **Over Rev parent.** As in MAME, the parent `overrev` is the Model 2C
|
||||
version (see the Model 2C sections), so `overrevb` and `overrevba` load
|
||||
from `overrev.zip`. The I/O board BIOS entries (`model1io`, `model1io2`),
|
||||
like the other BIOS sets of the core, are not in the game list: loading
|
||||
their zip reports that there is no such game instead of starting a
|
||||
machine without a program.
|
||||
- **Inverted pedals.** Over Rev reads its pedals inverted (0xff released), as
|
||||
`PORT_REVERSE` in MAME. The driver inverts those channels itself.
|
||||
|
||||
Super GT 24h (`sgt24h`) runs on the same machine. Its pedals are read
|
||||
inverted too, and it uses the same driver init as Over Rev.
|
||||
|
||||
## Sound link (MIDI input of the SCSP)
|
||||
|
||||
On Model 2A and later the i960 sends its sound commands through a UART to the
|
||||
MIDI input of the SCSP. The driver sends a byte only when the SCSP input
|
||||
queue has room, so no command is lost; while the queue is full the UART
|
||||
reports itself busy and the game waits.
|
||||
|
||||
The SCSP input queue holds 32 bytes, as in current MAME (the original MAME
|
||||
0.78 code had 8). With 8 bytes Super GT 24h hung at the end of its boot: the
|
||||
sound program does not read the queue for a while, and the game sends sound
|
||||
commands from its vertical blank interrupt, so it waited there for several
|
||||
frames. Its frame timer (same interrupt priority) expired meanwhile; the
|
||||
i960 records such an interrupt in its interrupt table, which this game keeps
|
||||
in ROM, so the interrupt was lost and the main loop waited for the timer
|
||||
forever (black screen after "STAND ALONE"). With 32 bytes the commands fit
|
||||
and the game plays.
|
||||
|
||||
## Rail Chase 2: mirrored sample ROMs
|
||||
|
||||
Sets: `rchase2`.
|
||||
|
||||
The sound board takes either four 16 Mbit sample ROMs (IC32, IC33, IC34,
|
||||
IC35) or two 32 Mbit ones (IC32, IC34). Rail Chase 2 has two 16 Mbit ROMs in
|
||||
the 32 Mbit positions IC32 and IC34. A 16 Mbit ROM there ignores the top
|
||||
address line, so it shows up twice: the region at 0x200000 mirrors IC32 and
|
||||
the one at 0x600000 mirrors IC34.
|
||||
|
||||
The sound program streams some effects through the 68000 into ring buffers
|
||||
in sound RAM, reading them from those mirrors (the title screen animation
|
||||
reads its stream from 0xa1e97c, inside the mirror of IC32). MAME loads the
|
||||
ROMs at 0x000000 and 0x400000 and leaves the mirrors empty, so those effects
|
||||
play silence: the title animation is silent and some in-game effects are
|
||||
missing, as reported for MAME (mametesters 09393).
|
||||
|
||||
The ROM definition loads each ROM a second time into its mirror (`ROM_RELOAD`), as the same fix proposed to MAME.
|
||||
|
||||
**How it was checked.** Current MAME (built from source, October 2026), with
|
||||
no input, plays nothing during the title animation (22-30 s, 56-62 s and
|
||||
90-96 s of the attract mode), as this core did before the change. With the
|
||||
same mirroring added to MAME's `init_rchase2`, MAME plays the title
|
||||
animation sound at the same points as this core. The billboard ROM
|
||||
(`segabill`), not dumped here, was an empty placeholder in that MAME test; it
|
||||
drives the score display only. With it the title
|
||||
animation has its sound and the in-game sound is about a third louder (the
|
||||
effects that were missing). The video is unchanged. The other Model 2 sets
|
||||
fill every ROM position they use, or (`dynabb`) use the four-ROM layout, where
|
||||
an empty socket is not a mirror.
|
||||
|
||||
## Sound: the SCSP effect DSP
|
||||
|
||||
Sets: every SCSP game that loads a DSP program (Dead or Alive among them).
|
||||
|
||||
The SCSP has a small DSP for effects (reverb, echo). The slots send their
|
||||
output to it (ISEL, IMXL), it runs its microprogram once per sample with its
|
||||
delay lines in the sound RAM (RBP, RBL), and its 16 outputs are mixed with
|
||||
the EFSDL and EFPAN of slots 0-15. The SCSP of this core did not emulate it,
|
||||
so those effects were missing, and the sounds a game sends only to the DSP
|
||||
were silent. The DSP is now the one of current MAME (`src/sound/scspdsp.c`),
|
||||
compared with MAME's on the Dead or Alive program and on random programs:
|
||||
same outputs, registers and delay RAM, sample by sample.
|
||||
|
||||
**Dead or Alive and the MADRS registers.** The DSP reads its delay line
|
||||
addresses from the MADRS registers (`0x780-0x7bf`). MAME also writes the
|
||||
range `0x7c0-0x7ff` to MADRS, as a mirror. Dead or Alive loads MADRS and then
|
||||
clears `0x7c0-0x7ff`, so in MAME every delay line address becomes 0: the
|
||||
reverb feeds back into one word, its output drifts to a DC level and
|
||||
saturates, and the sound breaks up and then goes silent (listed in MAME's
|
||||
known issues for `doa`). The mirror is not from the hardware: it replaced an
|
||||
out-of-bounds write in 2014, and Mednafen (checked on Saturn hardware) maps
|
||||
MADRS at `0x780-0x7bf` only. Here `0x7c0-0x7ff` is ignored and reads as 0.
|
||||
|
||||
**Master volume.** The SCSP master volume (MVOL) now scales the output once
|
||||
the game has written it, as in MAME. Dead or Alive keeps it at 0 for the
|
||||
first seconds while its DSP starts on an uninitialised delay RAM; without
|
||||
MVOL that start was audible as a burst of noise. The games that use 15 (the
|
||||
maximum) sound exactly as before.
|
||||
|
||||
**How it was checked.** MAME with the mirror removed plays the Dead or Alive
|
||||
attract mode for over 11 minutes without the DC drift (it saturated within
|
||||
the first minute before). In this core the games that do not start the DSP
|
||||
produce exactly the same audio as before.
|
||||
|
||||
## Video: tile layers and polygons
|
||||
|
||||
The tile layers (System 24 tilemaps A and B) are mixed among themselves
|
||||
first, A over B whatever their priority bits; the priority bit of the
|
||||
pixel that wins then puts it behind or in front of the polygons. MAME draws
|
||||
each priority on its own (the low tiles of A and B, the polygons, the high
|
||||
tiles of A and B), so a high tile of B covers a low tile of A: on the
|
||||
Virtua Cop 2 stage select the city map (tilemap B, priority set) hid
|
||||
"SHOOT TO SELECT" (tilemap A), as listed in MAME's known issues for
|
||||
`vcop2`. The other Model 2 games checked look the same as before.
|
||||
|
||||
## Video: black polygon pixels
|
||||
|
||||
The polygons are drawn into their own buffer, then laid over the tile
|
||||
layers. MAME's buffer holds `rgb_t` pixels, whose alpha byte makes a drawn
|
||||
black pixel (0xff000000) different from an empty one (0). This core stored
|
||||
plain RGB and took every black pixel as empty, so wherever a polygon was
|
||||
pure black the layer behind showed through: blue car shadows and missing
|
||||
dust in Sega Rally, blue tyres and shadows in INDY 500 and Super GT, the
|
||||
sky behind black clothes in Dead or Alive, the attract backgrounds of Motor
|
||||
Raid. Drawn pixels now carry the same opaque marker in the top byte. All the
|
||||
Model 2 games were compared before and after; the changed pixels are the
|
||||
black ones, and they now match MAME.
|
||||
|
||||
## Sega Rally Championship (Model 2A)
|
||||
|
||||
Sets: `srallyc`, `srallycb`, `srallycc`, `srallycdx`, `srallycdxa`.
|
||||
|
||||
- **Gear lever.** The H-pattern lever is read on port C bits 4-6. As for
|
||||
Daytona USA it is built from two buttons, shift up and shift down.
|
||||
- **Drive board.** The force feedback board is written to through port E and
|
||||
never answers; it is not emulated. Its program (`epr-17891`) and the
|
||||
communication board program (`epr-16726`) are not listed.
|
||||
- **Start grid.** MAME lists the initial placement of a few opponent cars as
|
||||
slightly wrong, depending on the i960 clock. Here, with the i960 at half
|
||||
and at double its clock, only one of the 8 start grid objects moves, by
|
||||
about 0.3 units (it is still settling when the race starts). Compared with
|
||||
a video of a real Model 2A-CRX, aligned on the race clock (chase view,
|
||||
full throttle): same speed (220 km/h at 0'04"0), same course, and the
|
||||
first opponent appears at the end of the village at 0'05"0 in both, at the
|
||||
same distance up to 0'06"0. Nothing is changed.
|
||||
|
||||
## Manx TT Superbike (Model 2A)
|
||||
|
||||
Sets: `manxtt` (DX/Twin, Revision D), `manxttc` (DX/Twin, Revision C),
|
||||
`manxttdx` (DX).
|
||||
|
||||
- **Cabinet type.** The MAME sets include an EEPROM image that sets the
|
||||
cabinet type: DX for `manxtt`, Twin for `manxttc`. A new NVRAM starts from
|
||||
it (`REGION_PROMS`, 16-bit little-endian as in MAME). The type can still be
|
||||
changed in the test menu.
|
||||
- **Motion slider (DX).** The DX bike moves; its drive board takes commands
|
||||
on port E of the 315-5649 and answers on port D. At boot the game shows
|
||||
"ACTIVE MOTION SLIDER / NOW CHECKING SYSTEM" (code at `0x5f580` in
|
||||
`manxtt`): after command `0x3d` it waits up to 846 frames for status
|
||||
`0xce`, sends the bike center value, then waits for `0xcd`. Without an
|
||||
answer it shows "Error! ... Not Respond" and never starts; MAME stops
|
||||
there (its known issue "no escape from active motion slider tutorial").
|
||||
The board is simulated with those two answers: `0xce` while the command is
|
||||
`0x3d`, `0xcd` otherwise. The board's error codes (`0xb0`-`0xb7`: first
|
||||
setting, encoder, overcurrent, overheat, bank volume, ROM, RAM, centering)
|
||||
are never sent. The bike does not move, of course.
|
||||
- **Model 1 sound board (DX).** The DX cabinet has a Model 1 sound board
|
||||
(68000, YM3438, two MultiPCM) next to the SCSP, for extra sounds. It runs as
|
||||
a fourth CPU (`REGION_CPU4`, samples in `REGION_SOUND2`/`REGION_SOUND3`)
|
||||
and gets the same sound commands from the i960 UART, as in MAME. Its replies
|
||||
are not passed back: the i960 reads the SCSP's.
|
||||
- **Communication board.** Its program (`epr-18643a`) is not listed; the
|
||||
board is not emulated and the game runs as a single machine.
|
||||
|
||||
## Sky Target (Model 2A)
|
||||
|
||||
Sets: `skytargt`.
|
||||
|
||||
The stick is on analog channels 0 (Y) and 2 (X, reversed), as in MAME.
|
||||
Machine gun, missile and view change are buttons 1-3.
|
||||
|
||||
## Air Walkers (Model 2A)
|
||||
|
||||
Sets: `airwlkrs`.
|
||||
|
||||
Up to four players on two input ports: port F bit 7 selects players 1-2 or
|
||||
3-4 on ports C and D, and the matching start buttons on IN0 bits 4-5, as in
|
||||
MAME.
|
||||
|
||||
## Hanguk Pro Yagu 98 (Model 2A)
|
||||
|
||||
Sets: `hpyagu98`.
|
||||
|
||||
The game stops with "Error #1" unless the NVRAM holds what its boot code
|
||||
checks: EEPROM words 4-5, the string "98KOREA PRO B.B." at the start of the
|
||||
backup RAM, a magic dword at `0x398` (`v * 3 + 0x3e82 == 0xf0c891a2`), and the
|
||||
settings block at `0x10` with its CRC (a copy at `0x1d4` restores it when
|
||||
only one is valid). MAME lists two hand-made images, EEPROM and backup RAM,
|
||||
with the settings of Dynamite Baseball 97. A new NVRAM starts from them, as in
|
||||
MAME (`REGION_PROMS` and `REGION_GFX1`); older sets without these two files
|
||||
stop on "Error #1".
|
||||
|
||||
## Desert Tank (original Model 2)
|
||||
|
||||
Sets: `desert`.
|
||||
|
||||
Model 1 I/O board as Daytona USA (its BIOS runs when `model1io.zip` is
|
||||
present). Steering, accelerator and brake on the I/O board analog inputs,
|
||||
the shift lever as a toggle, as in MAME.
|
||||
|
||||
## Model 2C: the TGPx4 (MB86235)
|
||||
|
||||
The Model 2C boards replace the TGP with a Fujitsu MB86235 "TGPx4". Its
|
||||
interpreter comes from current MAME (`src/cpu/mb86235`, in C89), with the
|
||||
program memory, the external bus (buffer RAM at `0x400000`, the copro data
|
||||
ROM at `0x800000`) and the two FIFOs as driver callbacks. As in MAME, the
|
||||
CPU waits in halt until the i960 has sent its program, and a read from the
|
||||
empty input FIFO repeats the instruction once the i960 pushes a value. Two
|
||||
places differ from MAME, where its code is plainly a slip:
|
||||
|
||||
- **FEA/FES** (exponent add/subtract) keep the sign and the mantissa and
|
||||
change only the exponent field; MAME keeps only the exponent field.
|
||||
- **EBL** (the low 14 bits of the external base register) is written as the
|
||||
low bits; MAME shifts the value up as for EBU.
|
||||
|
||||
None of the games checked showed a difference from either change.
|
||||
|
||||
The 2C games run faster than real time here, where MAME runs them at about
|
||||
70%.
|
||||
|
||||
## Video: polygon clipping
|
||||
|
||||
A polygon is clipped against four planes, and a convex one gains at most one
|
||||
vertex for each, so MAME's buffers hold 8. A bad polygon (self-crossing, or
|
||||
with NaN coordinates) can double its vertices at each plane: Top Skater's
|
||||
models drawn with the standard object format overflowed the buffers and
|
||||
crashed the core. The buffers now hold 64 vertices and only polygons that
|
||||
still fit in 8 are kept.
|
||||
|
||||
## Top Skater (Model 2C)
|
||||
|
||||
Sets: `topskatr`, `topskatru`, `topskatruo`, `topskatrj`.
|
||||
|
||||
The game uploads its own geometrizer program (MAME's notes: "a slightly
|
||||
different geometry code"), and MAME shows no 3D. Its object data command
|
||||
(`0x11`, the second bank of command numbers) reads a compact polygon list:
|
||||
the attribute word, then only the points, three words for a triangle and
|
||||
six for a quad. The standard format (no normals) also has three unused
|
||||
normal words and, for triangles, an unused point. Read with the standard
|
||||
format, every polygon after the first was garbage. The driver reads the
|
||||
compact format for command `0x11` in this game only; the skaters, the
|
||||
board, the ramps and the crowd are all drawn. The command word also carries the
|
||||
center select in bits 6-7, as the rasterizer command does: the speed meter
|
||||
is drawn around the window's second vanishing point, in the bottom left
|
||||
corner. Compared with a video of the arcade game: the course, the HUD and
|
||||
the speed meter are in the same places.
|
||||
|
||||
The program's command `0x1b` loads a second matrix and `0x1c` copies the
|
||||
first matrix's translation into it; a vertex whose x has the lowest bit set
|
||||
goes through the second matrix (the skinned joints of the skaters). MAME
|
||||
pull request #16444 (jkind73, open) found the compact format and the second
|
||||
matrix too.
|
||||
|
||||
The board has two foot sensors (front and tail), on while a foot stands on
|
||||
it. MAME reads them active low, so with no input both feet are off the
|
||||
board: the skater always jumps, floats 16 units above the ground with the
|
||||
camera close behind, and its shadow (which the game puts on the ground
|
||||
under the light) is far below, off screen. Here they are on at rest and a
|
||||
button lifts a foot. Compared with a video of the arcade game at the same
|
||||
race time, the skater now rides crouched, the camera is at the same
|
||||
distance and the shadow is under the board. The attract demos, played by
|
||||
the game, matched the video before already (shadows included).
|
||||
|
||||
The analog inputs are curving (channel 0, stick X) and slide (channel 1);
|
||||
MAME puts both on the same axis, here slide is on stick Y so a pad can
|
||||
reach both.
|
||||
|
||||
The music is on the DSB2 MPEG board (see the music board section).
|
||||
|
||||
## Sega Ski Super G (Model 2C)
|
||||
|
||||
Sets: `skisuprg`.
|
||||
|
||||
The drive board answers on port D to the commands on port E. At boot the
|
||||
game shows "CHECK DRIVE BOARD" (code at `0x88b10`): it clears port E and
|
||||
waits for `0xce` (ready), sends the inclining center and waits for `0xff`
|
||||
(taken), within 479 frames; without an answer it stops on "DRIVE BOARD
|
||||
TROUBLE CODE: FF", as in MAME. In game, `0xb0`-`0xb7` are board errors
|
||||
(init, encoder, overload, overheat, bank volume, ROM...). The board is
|
||||
simulated: `0xce` while port E is 0, `0xff` otherwise. The game then runs
|
||||
through the World Series and the races.
|
||||
|
||||
Swing is on analog channel 0 (stick Y), inclining on channel 1 (stick X),
|
||||
the foot sensors on port D are not read (port D is the drive board).
|
||||
|
||||
## Sega Touring Car Championship and Top Skater: music board (DSB)
|
||||
|
||||
Sets: `stcc`, `stccb`, `stcca`, `stcco` (DSB, Z80) and the Top Skater sets
|
||||
(DSB2, 68000).
|
||||
|
||||
Their music is MPEG audio (layer II, 32 kHz stereo) on a Digital Sound
|
||||
Board, from current MAME (`dsbz80.cpp`, `dsb2.cpp` and the decoder
|
||||
`mpeg_audio.cpp`, in C89: `src/sndhrdw/segadsb.c`, `src/sound/mpeg_audio.c`).
|
||||
The board's CPU gets the game's sound commands on its i8251, from the same
|
||||
line as the SCSP (each byte the i960 sends goes to both), and drives the
|
||||
decoder: start and end addresses, play, loop, stop, volume and stereo mode
|
||||
for the DSB; a command FIFO and a 1 kHz timer interrupt for the DSB2. The
|
||||
decoded audio is its own stream, mixed 9 dB under the SCSP's full level
|
||||
(MAME mixes both at full level). The level was measured on two recordings
|
||||
of Top Skater cabinets: with the music and the sound effects of the core as
|
||||
separate tracks of the same run, aligned on the attract mode, the
|
||||
recordings came out with the music 9 dB lower against the effects (within
|
||||
1 dB, both recordings); at full level the music also clipped. The decoded
|
||||
music itself matches the recordings (spectral correlation 0.9-0.97). The
|
||||
recordings play the music about 0.45% faster than the core's 32 kHz
|
||||
(emulated time); not changed, it may be the recordings. Touring Car's DSB
|
||||
uses the same level (no recording checked).
|
||||
|
||||
The decoder never reads past the MPEG ROM (MAME guards this on the DSB2
|
||||
only). The drive board and the communication board programs are not
|
||||
listed.
|
||||
|
||||
## The House of the Dead (Model 2C)
|
||||
|
||||
Sets: `hotd`, `hotdo`.
|
||||
|
||||
The guns work as in Virtua Cop 2 (the 315-5649 serial channel), with the
|
||||
ranges of MAME's `hotd` ports. MAME's prototype `hotdp` is not listed: one
|
||||
of its texture ROMs was never dumped.
|
||||
|
||||
## Other Model 2C sets
|
||||
|
||||
`waverunr`, `bel`, `segawski`, `dynamcopc` and `overrev` (now the Model 2C
|
||||
parent of the Model 2B sets) run with the inputs of MAME.
|
||||
|
||||
## Motor Raid - Twin/DX (Model 2A)
|
||||
|
||||
Sets: `motoraiddx`.
|
||||
|
||||
The DX cabinet has a moving bike, run by a drive board on the 315-5649
|
||||
ports: the game writes commands to port E (inverted) and reads the board's
|
||||
status on port D. The drive board's program is not dumped and MAME lists the
|
||||
set as not working: the game stops at "DRIVEBOARD NOT RESPONSE ERROR".
|
||||
|
||||
The board is simulated, as for Manx TT DX. From the cabinet check (code
|
||||
copied to RAM at `0x2158d0`, ROM `0xc58d0`):
|
||||
|
||||
- port D reads `0xcd` when the board is ready; the check then skips the
|
||||
initialisation and centring steps (which wait for `0xcf` and `0xce`);
|
||||
- the wire test sends commands `0xe0`-`0xef` and expects bit `n & 7`
|
||||
cleared (table at ROM `0xc5720`); the simulation answers the same.
|
||||
|
||||
The bike does not move, the game runs as on a working cabinet.
|
||||
|
||||
## Rail Chase 2 (`rchase2a`)
|
||||
|
||||
A second program for Rail Chase 2 that reads the guns the other way round
|
||||
(maybe a factory conversion). The guns are centred at `0x80` over the full
|
||||
range, as MAME's `rchase2a` ports.
|
||||
|
||||
## Daytona USA hacks
|
||||
|
||||
Sets: `daytonat`, `daytonata` (Turbo hack), `daytonam` (To The MAXX),
|
||||
`daytonagtx` (GTX 2004 Edition). Hacks by Kyle Hodgetts, listed by MAME as
|
||||
not working; here they play.
|
||||
|
||||
- **To The MAXX**: the kit has a PIC 16F84 in socket IC15. It answers at
|
||||
`0x240000`, where the third program ROM (`maxx.14`) is seen. As MAME:
|
||||
16-bit reads of the first 32 bytes step a 4-bit counter and return the
|
||||
PIC's answer.
|
||||
- **GTX 2004**: a banked ROM over the data ROMs at `0x2c00000`. Reads of
|
||||
some bytes switch the bank, as MAME (`0xff00c` and `0xf0003` bank 0,
|
||||
`0xff000` bank 1, `0xffffc` the empty bank 2).
|
||||
|
||||
## Not added
|
||||
|
||||
- **Royal Ascot II** (`rascot2`): a horse racing terminal made for the
|
||||
SegaNet network. It waits for the network ("SegaNet Wait Status" in MAME)
|
||||
and never starts a race as a single machine.
|
||||
|
||||
- **Power Sled** (`powsled`, `powsledr`, `powsledm`): a network of
|
||||
cabinets run by a Main unit, whose program was never dumped (MAME's
|
||||
`powsledm` is a hack of the Relay program). Every version waits on the
|
||||
network ("NETWORK: NG") in MAME, and would need the whole network to be
|
||||
simulated.
|
||||
Binary file not shown.
+5396
-5295
File diff suppressed because it is too large.
Load diff
+293
-293
@@ -1654,100 +1654,100 @@
|
||||
40love:0:8546:03:001:"Game" Score = 30 Now! CPU
|
||||
|
||||
; [ Idol Janshi Su-Chi-Pie 2 (v1.1) ]
|
||||
47pie2:0:FEE00118:63:000:Infinite Credits
|
||||
:47pie2:00000020:FEE00B01:00000005:FFFFFFFF:Infinite Time
|
||||
:47pie2:00010020:FEE00B97:00000000:FFFFFFFF:Infinite Time (2/2)
|
||||
:47pie2:00000000:FEE01788:00000009:FFFFFFFF:Infinite Bonus Game Left
|
||||
:47pie2:00000101:FEE01784:00000020:FFFFFFFF:Select Change Point
|
||||
:47pie2:60000000:00000000:00000000:00000000:[ The winning hand cheat must be activated when ]
|
||||
:47pie2:60000000:00000000:00000000:00000000:[ there are 14 tiles in your hand, then press ]
|
||||
:47pie2:60000000:00000000:00000000:00000000:[ the RON key ('Z' by default). The tiles do not ]
|
||||
:47pie2:60000000:00000000:00000000:00000000:[ visually change until you make a move. ]
|
||||
:47pie2:00300001:FEE00868:34000000:FFFFFFFF:Get winning hand Now!
|
||||
:47pie2:00310001:FEE0086C:34000000:FFFFFFFF:Get winning hand Now! (02/14)
|
||||
:47pie2:00310001:FEE00870:34000000:FFFFFFFF:Get winning hand Now! (03/14)
|
||||
:47pie2:00310001:FEE00874:34000001:FFFFFFFF:Get winning hand Now! (04/14)
|
||||
:47pie2:00310001:FEE00878:34000001:FFFFFFFF:Get winning hand Now! (05/14)
|
||||
:47pie2:00310001:FEE0087C:34000001:FFFFFFFF:Get winning hand Now! (06/14)
|
||||
:47pie2:00310001:FEE00880:34000002:FFFFFFFF:Get winning hand Now! (07/14)
|
||||
:47pie2:00310001:FEE00884:34000002:FFFFFFFF:Get winning hand Now! (08/14)
|
||||
:47pie2:00310001:FEE00888:34000002:FFFFFFFF:Get winning hand Now! (09/14)
|
||||
:47pie2:00310001:FEE0088C:34000003:FFFFFFFF:Get winning hand Now! (10/14)
|
||||
:47pie2:00310001:FEE00890:34000003:FFFFFFFF:Get winning hand Now! (11/14)
|
||||
:47pie2:00310001:FEE00894:34000003:FFFFFFFF:Get winning hand Now! (12/14)
|
||||
:47pie2:00310001:FEE00898:34000004:FFFFFFFF:Get winning hand Now! (13/14)
|
||||
:47pie2:00310001:FEE0089C:34000004:FFFFFFFF:Get winning hand Now! (14/14)
|
||||
:47pie2:00300000:FEE00868:34000000:FFFFFFFF:Always winning hand
|
||||
:47pie2:00310000:FEE0086C:34000000:FFFFFFFF:Always winning hand (02/14)
|
||||
:47pie2:00310000:FEE00870:34000000:FFFFFFFF:Always winning hand (03/14)
|
||||
:47pie2:00310000:FEE00874:34000001:FFFFFFFF:Always winning hand (04/14)
|
||||
:47pie2:00310000:FEE00878:34000001:FFFFFFFF:Always winning hand (05/14)
|
||||
:47pie2:00310000:FEE0087C:34000001:FFFFFFFF:Always winning hand (06/14)
|
||||
:47pie2:00310000:FEE00880:34000002:FFFFFFFF:Always winning hand (07/14)
|
||||
:47pie2:00310000:FEE00884:34000002:FFFFFFFF:Always winning hand (08/14)
|
||||
:47pie2:00310000:FEE00888:34000002:FFFFFFFF:Always winning hand (09/14)
|
||||
:47pie2:00310000:FEE0088C:34000003:FFFFFFFF:Always winning hand (10/14)
|
||||
:47pie2:00310000:FEE00890:34000003:FFFFFFFF:Always winning hand (11/14)
|
||||
:47pie2:00310000:FEE00894:34000003:FFFFFFFF:Always winning hand (12/14)
|
||||
:47pie2:00310000:FEE00898:34000004:FFFFFFFF:Always winning hand (13/14)
|
||||
:47pie2:00310000:FEE0089C:34000004:FFFFFFFF:Always winning hand (14/14)
|
||||
:47pie2:00000000:FEE00F48:00000009:FFFFFFFF:Infinite "Sue-Chi Stick"
|
||||
:47pie2:00000000:FEE00F4C:00000009:FFFFFFFF:Infinite "Fire Sekkan"
|
||||
:47pie2:00000000:FEE00F50:00000009:FFFFFFFF:Infinite "Special Syoukan"
|
||||
:47pie2:00000000:FEE00F54:00000009:FFFFFFFF:Infinite "Helper"
|
||||
:47pie2:00000000:FEE00F58:00000009:FFFFFFFF:Infinite "Hyper Eye"
|
||||
:47pie2:00000000:FEE00B08:0000001F:FFFFFFFF:Always Join All Associates:If you don't join associates who Peach Pie, Lemon Pie, Cherry Pie and Milky Pie the game's end is the bad one.
|
||||
:47pie2:00000000:FEE00AF8:00000004:FFFFFFFF:Start on Shiho Katagiri:Turn this cheat OFF after you've started the game
|
||||
:47pie2:00000000:FEE00AF8:00000005:FFFFFFFF:Start on Sesir.D:Turn this cheat OFF after you've started the game
|
||||
:47pie2:00000000:FEE00AF8:00000006:FFFFFFFF:Start on Sesir.D (Final):Turn this cheat OFF after you've started the game
|
||||
suchie2:0:FEE00118:63:000:Infinite Credits
|
||||
:suchie2:00000020:FEE00B01:00000005:FFFFFFFF:Infinite Time
|
||||
:suchie2:00010020:FEE00B97:00000000:FFFFFFFF:Infinite Time (2/2)
|
||||
:suchie2:00000000:FEE01788:00000009:FFFFFFFF:Infinite Bonus Game Left
|
||||
:suchie2:00000101:FEE01784:00000020:FFFFFFFF:Select Change Point
|
||||
:suchie2:60000000:00000000:00000000:00000000:[ The winning hand cheat must be activated when ]
|
||||
:suchie2:60000000:00000000:00000000:00000000:[ there are 14 tiles in your hand, then press ]
|
||||
:suchie2:60000000:00000000:00000000:00000000:[ the RON key ('Z' by default). The tiles do not ]
|
||||
:suchie2:60000000:00000000:00000000:00000000:[ visually change until you make a move. ]
|
||||
:suchie2:00300001:FEE00868:34000000:FFFFFFFF:Get winning hand Now!
|
||||
:suchie2:00310001:FEE0086C:34000000:FFFFFFFF:Get winning hand Now! (02/14)
|
||||
:suchie2:00310001:FEE00870:34000000:FFFFFFFF:Get winning hand Now! (03/14)
|
||||
:suchie2:00310001:FEE00874:34000001:FFFFFFFF:Get winning hand Now! (04/14)
|
||||
:suchie2:00310001:FEE00878:34000001:FFFFFFFF:Get winning hand Now! (05/14)
|
||||
:suchie2:00310001:FEE0087C:34000001:FFFFFFFF:Get winning hand Now! (06/14)
|
||||
:suchie2:00310001:FEE00880:34000002:FFFFFFFF:Get winning hand Now! (07/14)
|
||||
:suchie2:00310001:FEE00884:34000002:FFFFFFFF:Get winning hand Now! (08/14)
|
||||
:suchie2:00310001:FEE00888:34000002:FFFFFFFF:Get winning hand Now! (09/14)
|
||||
:suchie2:00310001:FEE0088C:34000003:FFFFFFFF:Get winning hand Now! (10/14)
|
||||
:suchie2:00310001:FEE00890:34000003:FFFFFFFF:Get winning hand Now! (11/14)
|
||||
:suchie2:00310001:FEE00894:34000003:FFFFFFFF:Get winning hand Now! (12/14)
|
||||
:suchie2:00310001:FEE00898:34000004:FFFFFFFF:Get winning hand Now! (13/14)
|
||||
:suchie2:00310001:FEE0089C:34000004:FFFFFFFF:Get winning hand Now! (14/14)
|
||||
:suchie2:00300000:FEE00868:34000000:FFFFFFFF:Always winning hand
|
||||
:suchie2:00310000:FEE0086C:34000000:FFFFFFFF:Always winning hand (02/14)
|
||||
:suchie2:00310000:FEE00870:34000000:FFFFFFFF:Always winning hand (03/14)
|
||||
:suchie2:00310000:FEE00874:34000001:FFFFFFFF:Always winning hand (04/14)
|
||||
:suchie2:00310000:FEE00878:34000001:FFFFFFFF:Always winning hand (05/14)
|
||||
:suchie2:00310000:FEE0087C:34000001:FFFFFFFF:Always winning hand (06/14)
|
||||
:suchie2:00310000:FEE00880:34000002:FFFFFFFF:Always winning hand (07/14)
|
||||
:suchie2:00310000:FEE00884:34000002:FFFFFFFF:Always winning hand (08/14)
|
||||
:suchie2:00310000:FEE00888:34000002:FFFFFFFF:Always winning hand (09/14)
|
||||
:suchie2:00310000:FEE0088C:34000003:FFFFFFFF:Always winning hand (10/14)
|
||||
:suchie2:00310000:FEE00890:34000003:FFFFFFFF:Always winning hand (11/14)
|
||||
:suchie2:00310000:FEE00894:34000003:FFFFFFFF:Always winning hand (12/14)
|
||||
:suchie2:00310000:FEE00898:34000004:FFFFFFFF:Always winning hand (13/14)
|
||||
:suchie2:00310000:FEE0089C:34000004:FFFFFFFF:Always winning hand (14/14)
|
||||
:suchie2:00000000:FEE00F48:00000009:FFFFFFFF:Infinite "Sue-Chi Stick"
|
||||
:suchie2:00000000:FEE00F4C:00000009:FFFFFFFF:Infinite "Fire Sekkan"
|
||||
:suchie2:00000000:FEE00F50:00000009:FFFFFFFF:Infinite "Special Syoukan"
|
||||
:suchie2:00000000:FEE00F54:00000009:FFFFFFFF:Infinite "Helper"
|
||||
:suchie2:00000000:FEE00F58:00000009:FFFFFFFF:Infinite "Hyper Eye"
|
||||
:suchie2:00000000:FEE00B08:0000001F:FFFFFFFF:Always Join All Associates:If you don't join associates who Peach Pie, Lemon Pie, Cherry Pie and Milky Pie the game's end is the bad one.
|
||||
:suchie2:00000000:FEE00AF8:00000004:FFFFFFFF:Start on Shiho Katagiri:Turn this cheat OFF after you've started the game
|
||||
:suchie2:00000000:FEE00AF8:00000005:FFFFFFFF:Start on Sesir.D:Turn this cheat OFF after you've started the game
|
||||
:suchie2:00000000:FEE00AF8:00000006:FFFFFFFF:Start on Sesir.D (Final):Turn this cheat OFF after you've started the game
|
||||
|
||||
; [ Idol Janshi Su-Chi-Pie 2 (v1.0) ]
|
||||
47pie2o:0:FEE00118:63:000:Infinite Credits
|
||||
:47pie2o:00000020:FEE00B01:00000005:FFFFFFFF:Infinite Time
|
||||
:47pie2o:00010020:FEE00B97:00000000:FFFFFFFF:Infinite Time (2/2)
|
||||
:47pie2o:00000000:FEE01788:00000009:FFFFFFFF:Infinite Bonus Game Left
|
||||
:47pie2o:00000101:FEE01784:00000020:FFFFFFFF:Select Change Point
|
||||
:47pie2o:60000000:00000000:00000000:00000000:[ The winning hand cheat must be activated when ]
|
||||
:47pie2o:60000000:00000000:00000000:00000000:[ there are 14 tiles in your hand, then press ]
|
||||
:47pie2o:60000000:00000000:00000000:00000000:[ the RON key ('Z' by default). The tiles do not ]
|
||||
:47pie2o:60000000:00000000:00000000:00000000:[ visually change until you make a move. ]
|
||||
:47pie2o:00300001:FEE00868:34000000:FFFFFFFF:Get winning hand Now!
|
||||
:47pie2o:00310001:FEE0086C:34000000:FFFFFFFF:Get winning hand Now! (02/14)
|
||||
:47pie2o:00310001:FEE00870:34000000:FFFFFFFF:Get winning hand Now! (03/14)
|
||||
:47pie2o:00310001:FEE00874:34000001:FFFFFFFF:Get winning hand Now! (04/14)
|
||||
:47pie2o:00310001:FEE00878:34000001:FFFFFFFF:Get winning hand Now! (05/14)
|
||||
:47pie2o:00310001:FEE0087C:34000001:FFFFFFFF:Get winning hand Now! (06/14)
|
||||
:47pie2o:00310001:FEE00880:34000002:FFFFFFFF:Get winning hand Now! (07/14)
|
||||
:47pie2o:00310001:FEE00884:34000002:FFFFFFFF:Get winning hand Now! (08/14)
|
||||
:47pie2o:00310001:FEE00888:34000002:FFFFFFFF:Get winning hand Now! (09/14)
|
||||
:47pie2o:00310001:FEE0088C:34000003:FFFFFFFF:Get winning hand Now! (10/14)
|
||||
:47pie2o:00310001:FEE00890:34000003:FFFFFFFF:Get winning hand Now! (11/14)
|
||||
:47pie2o:00310001:FEE00894:34000003:FFFFFFFF:Get winning hand Now! (12/14)
|
||||
:47pie2o:00310001:FEE00898:34000004:FFFFFFFF:Get winning hand Now! (13/14)
|
||||
:47pie2o:00310001:FEE0089C:34000004:FFFFFFFF:Get winning hand Now! (14/14)
|
||||
:47pie2o:00300000:FEE00868:34000000:FFFFFFFF:Always winning hand
|
||||
:47pie2o:00310000:FEE0086C:34000000:FFFFFFFF:Always winning hand (02/14)
|
||||
:47pie2o:00310000:FEE00870:34000000:FFFFFFFF:Always winning hand (03/14)
|
||||
:47pie2o:00310000:FEE00874:34000001:FFFFFFFF:Always winning hand (04/14)
|
||||
:47pie2o:00310000:FEE00878:34000001:FFFFFFFF:Always winning hand (05/14)
|
||||
:47pie2o:00310000:FEE0087C:34000001:FFFFFFFF:Always winning hand (06/14)
|
||||
:47pie2o:00310000:FEE00880:34000002:FFFFFFFF:Always winning hand (07/14)
|
||||
:47pie2o:00310000:FEE00884:34000002:FFFFFFFF:Always winning hand (08/14)
|
||||
:47pie2o:00310000:FEE00888:34000002:FFFFFFFF:Always winning hand (09/14)
|
||||
:47pie2o:00310000:FEE0088C:34000003:FFFFFFFF:Always winning hand (10/14)
|
||||
:47pie2o:00310000:FEE00890:34000003:FFFFFFFF:Always winning hand (11/14)
|
||||
:47pie2o:00310000:FEE00894:34000003:FFFFFFFF:Always winning hand (12/14)
|
||||
:47pie2o:00310000:FEE00898:34000004:FFFFFFFF:Always winning hand (13/14)
|
||||
:47pie2o:00310000:FEE0089C:34000004:FFFFFFFF:Always winning hand (14/14)
|
||||
:47pie2o:00000000:FEE00F48:00000009:FFFFFFFF:Infinite "Sue-Chi Stick"
|
||||
:47pie2o:00000000:FEE00F4C:00000009:FFFFFFFF:Infinite "Fire Sekkan"
|
||||
:47pie2o:00000000:FEE00F50:00000009:FFFFFFFF:Infinite "Special Syoukan"
|
||||
:47pie2o:00000000:FEE00F54:00000009:FFFFFFFF:Infinite "Helper"
|
||||
:47pie2o:00000000:FEE00F58:00000009:FFFFFFFF:Infinite "Hyper Eye"
|
||||
:47pie2o:00000000:FEE00B08:0000001F:FFFFFFFF:Always Join All Associates:If you don't join associates who Peach Pie, Lemon Pie, Cherry Pie and Milky Pie the game's end is the bad one.
|
||||
:47pie2o:00000000:FEE00AF8:00000004:FFFFFFFF:Start on Shiho Katagiri:Turn this cheat OFF after you've started the game
|
||||
:47pie2o:00000000:FEE00AF8:00000005:FFFFFFFF:Start on Sesir.D:Turn this cheat OFF after you've started the game
|
||||
:47pie2o:00000000:FEE00AF8:00000006:FFFFFFFF:Start on Sesir.D (Final):Turn this cheat OFF after you've started the game
|
||||
suchie2o:0:FEE00118:63:000:Infinite Credits
|
||||
:suchie2o:00000020:FEE00B01:00000005:FFFFFFFF:Infinite Time
|
||||
:suchie2o:00010020:FEE00B97:00000000:FFFFFFFF:Infinite Time (2/2)
|
||||
:suchie2o:00000000:FEE01788:00000009:FFFFFFFF:Infinite Bonus Game Left
|
||||
:suchie2o:00000101:FEE01784:00000020:FFFFFFFF:Select Change Point
|
||||
:suchie2o:60000000:00000000:00000000:00000000:[ The winning hand cheat must be activated when ]
|
||||
:suchie2o:60000000:00000000:00000000:00000000:[ there are 14 tiles in your hand, then press ]
|
||||
:suchie2o:60000000:00000000:00000000:00000000:[ the RON key ('Z' by default). The tiles do not ]
|
||||
:suchie2o:60000000:00000000:00000000:00000000:[ visually change until you make a move. ]
|
||||
:suchie2o:00300001:FEE00868:34000000:FFFFFFFF:Get winning hand Now!
|
||||
:suchie2o:00310001:FEE0086C:34000000:FFFFFFFF:Get winning hand Now! (02/14)
|
||||
:suchie2o:00310001:FEE00870:34000000:FFFFFFFF:Get winning hand Now! (03/14)
|
||||
:suchie2o:00310001:FEE00874:34000001:FFFFFFFF:Get winning hand Now! (04/14)
|
||||
:suchie2o:00310001:FEE00878:34000001:FFFFFFFF:Get winning hand Now! (05/14)
|
||||
:suchie2o:00310001:FEE0087C:34000001:FFFFFFFF:Get winning hand Now! (06/14)
|
||||
:suchie2o:00310001:FEE00880:34000002:FFFFFFFF:Get winning hand Now! (07/14)
|
||||
:suchie2o:00310001:FEE00884:34000002:FFFFFFFF:Get winning hand Now! (08/14)
|
||||
:suchie2o:00310001:FEE00888:34000002:FFFFFFFF:Get winning hand Now! (09/14)
|
||||
:suchie2o:00310001:FEE0088C:34000003:FFFFFFFF:Get winning hand Now! (10/14)
|
||||
:suchie2o:00310001:FEE00890:34000003:FFFFFFFF:Get winning hand Now! (11/14)
|
||||
:suchie2o:00310001:FEE00894:34000003:FFFFFFFF:Get winning hand Now! (12/14)
|
||||
:suchie2o:00310001:FEE00898:34000004:FFFFFFFF:Get winning hand Now! (13/14)
|
||||
:suchie2o:00310001:FEE0089C:34000004:FFFFFFFF:Get winning hand Now! (14/14)
|
||||
:suchie2o:00300000:FEE00868:34000000:FFFFFFFF:Always winning hand
|
||||
:suchie2o:00310000:FEE0086C:34000000:FFFFFFFF:Always winning hand (02/14)
|
||||
:suchie2o:00310000:FEE00870:34000000:FFFFFFFF:Always winning hand (03/14)
|
||||
:suchie2o:00310000:FEE00874:34000001:FFFFFFFF:Always winning hand (04/14)
|
||||
:suchie2o:00310000:FEE00878:34000001:FFFFFFFF:Always winning hand (05/14)
|
||||
:suchie2o:00310000:FEE0087C:34000001:FFFFFFFF:Always winning hand (06/14)
|
||||
:suchie2o:00310000:FEE00880:34000002:FFFFFFFF:Always winning hand (07/14)
|
||||
:suchie2o:00310000:FEE00884:34000002:FFFFFFFF:Always winning hand (08/14)
|
||||
:suchie2o:00310000:FEE00888:34000002:FFFFFFFF:Always winning hand (09/14)
|
||||
:suchie2o:00310000:FEE0088C:34000003:FFFFFFFF:Always winning hand (10/14)
|
||||
:suchie2o:00310000:FEE00890:34000003:FFFFFFFF:Always winning hand (11/14)
|
||||
:suchie2o:00310000:FEE00894:34000003:FFFFFFFF:Always winning hand (12/14)
|
||||
:suchie2o:00310000:FEE00898:34000004:FFFFFFFF:Always winning hand (13/14)
|
||||
:suchie2o:00310000:FEE0089C:34000004:FFFFFFFF:Always winning hand (14/14)
|
||||
:suchie2o:00000000:FEE00F48:00000009:FFFFFFFF:Infinite "Sue-Chi Stick"
|
||||
:suchie2o:00000000:FEE00F4C:00000009:FFFFFFFF:Infinite "Fire Sekkan"
|
||||
:suchie2o:00000000:FEE00F50:00000009:FFFFFFFF:Infinite "Special Syoukan"
|
||||
:suchie2o:00000000:FEE00F54:00000009:FFFFFFFF:Infinite "Helper"
|
||||
:suchie2o:00000000:FEE00F58:00000009:FFFFFFFF:Infinite "Hyper Eye"
|
||||
:suchie2o:00000000:FEE00B08:0000001F:FFFFFFFF:Always Join All Associates:If you don't join associates who Peach Pie, Lemon Pie, Cherry Pie and Milky Pie the game's end is the bad one.
|
||||
:suchie2o:00000000:FEE00AF8:00000004:FFFFFFFF:Start on Shiho Katagiri:Turn this cheat OFF after you've started the game
|
||||
:suchie2o:00000000:FEE00AF8:00000005:FFFFFFFF:Start on Sesir.D:Turn this cheat OFF after you've started the game
|
||||
:suchie2o:00000000:FEE00AF8:00000006:FFFFFFFF:Start on Sesir.D (Final):Turn this cheat OFF after you've started the game
|
||||
|
||||
; [ 4-D Warriors ]
|
||||
4dwarrio:0:C028:09:000:Infinite Credits
|
||||
@@ -8368,9 +8368,9 @@ bcstry:0:0000:00:999:[ forums. ]:REASON 1
|
||||
beaminv:0:1847:08:000:Infinite Lives
|
||||
|
||||
; [ Beastie Feastie ]
|
||||
beastf:0:4C96:05:000:Infinite Lives PL1
|
||||
beastf:0:4C98:05:000:Infinite Lives PL2
|
||||
beastf:0:4C9D:A8:000:Infinite Energy
|
||||
beastfp:0:4C96:05:000:Infinite Lives PL1
|
||||
beastfp:0:4C98:05:000:Infinite Lives PL2
|
||||
beastfp:0:4C9D:A8:000:Infinite Energy
|
||||
|
||||
; [ Beastorizer (bootleg) ]
|
||||
beastrzb:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
@@ -14897,34 +14897,34 @@ chopperb:0:E409:AA:000:Infinite Circle Bombs PL2
|
||||
chopperb:0:E409:FF:000:Infinite Atomic Bombs PL2
|
||||
|
||||
; [ Choplifter ]
|
||||
chplft:0:C02D:95:000:Infinite Lives
|
||||
chplft:0:E118:C8:000:Infinite Fuel
|
||||
chplft:0:C303:41:000:Invincibility
|
||||
chplft:0:C084:01:000:Always Have Prisoners
|
||||
chplft:0:C085:20:001:Finish Level Level Now!
|
||||
chplft:0:C083:00:001:No dead hostages
|
||||
chplft:0:C084:08:001:Max. load hostages = 08
|
||||
chplft:0:C084:20:001:Max. load hostages = 20
|
||||
choplift:0:C02D:95:000:Infinite Lives
|
||||
choplift:0:E118:C8:000:Infinite Fuel
|
||||
choplift:0:C303:41:000:Invincibility
|
||||
choplift:0:C084:01:000:Always Have Prisoners
|
||||
choplift:0:C085:20:001:Finish Level Level Now!
|
||||
choplift:0:C083:00:001:No dead hostages
|
||||
choplift:0:C084:08:001:Max. load hostages = 08
|
||||
choplift:0:C084:20:001:Max. load hostages = 20
|
||||
|
||||
; [ Choplifter (alternate) ]
|
||||
chplftb:0:C02D:95:000:Infinite Lives
|
||||
chplftb:0:E118:C8:000:Infinite Fuel
|
||||
chplftb:0:C303:41:000:Invincibility
|
||||
chplftb:0:C084:01:000:Always Have Prisoners
|
||||
chplftb:0:C085:20:001:Finish Level Level Now!
|
||||
chplftb:0:C083:00:001:No dead hostages
|
||||
chplftb:0:C084:08:001:Max. load hostages = 08
|
||||
chplftb:0:C084:20:001:Max. load hostages = 20
|
||||
chopliftu:0:C02D:95:000:Infinite Lives
|
||||
chopliftu:0:E118:C8:000:Infinite Fuel
|
||||
chopliftu:0:C303:41:000:Invincibility
|
||||
chopliftu:0:C084:01:000:Always Have Prisoners
|
||||
chopliftu:0:C085:20:001:Finish Level Level Now!
|
||||
chopliftu:0:C083:00:001:No dead hostages
|
||||
chopliftu:0:C084:08:001:Max. load hostages = 08
|
||||
chopliftu:0:C084:20:001:Max. load hostages = 20
|
||||
|
||||
; [ Choplifter (bootleg) ]
|
||||
chplftbl:0:C02D:95:000:Infinite Lives PL1
|
||||
chplftbl:0:E118:C8:000:Infinite Fuel
|
||||
chplftbl:0:C303:41:000:Invincibility
|
||||
chplftbl:0:C084:01:000:Always Have Prisoners
|
||||
chplftbl:0:C085:20:001:Finish Level Level Now!
|
||||
chplftbl:0:C083:00:001:No dead hostages
|
||||
chplftbl:0:C084:08:001:Max. load hostages = 08
|
||||
chplftbl:0:C084:20:001:Max. load hostages = 20
|
||||
chopliftbl:0:C02D:95:000:Infinite Lives PL1
|
||||
chopliftbl:0:E118:C8:000:Infinite Fuel
|
||||
chopliftbl:0:C303:41:000:Invincibility
|
||||
chopliftbl:0:C084:01:000:Always Have Prisoners
|
||||
chopliftbl:0:C085:20:001:Finish Level Level Now!
|
||||
chopliftbl:0:C083:00:001:No dead hostages
|
||||
chopliftbl:0:C084:08:001:Max. load hostages = 08
|
||||
chopliftbl:0:C084:20:001:Max. load hostages = 20
|
||||
|
||||
; [ Chequered Flag ]
|
||||
chqflag:0:05C6:63:000:Infinite Credits
|
||||
@@ -19027,9 +19027,9 @@ dakkochn:0:0000:00:999:[ for it on the cheat ]:REASON 1
|
||||
dakkochn:0:0000:00:999:[ forums. ]:REASON 1
|
||||
|
||||
; [ Dancing Eyes (DC1/VER.A) ]
|
||||
danceyes:0:002B51DC:09:000:Infinite Credits
|
||||
danceyes:0:002B51A0:01:000:Always See Through Mode
|
||||
:danceyes:00000500:0021F064:0000000E:FFFFFFFF:Select Stage
|
||||
danceyesj:0:002B51DC:09:000:Infinite Credits
|
||||
danceyesj:0:002B51A0:01:000:Always See Through Mode
|
||||
:danceyesj:00000500:0021F064:0000000E:FFFFFFFF:Select Stage
|
||||
|
||||
; [ Danchi de Hanafuoda ]
|
||||
danchih:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
@@ -31430,24 +31430,24 @@ dungeonm:0:0FFFFF:02:100:Region Switch = US:Dungeon Magic
|
||||
dungeonm:0:0FFFFF:03:100:Region Switch = World:Dungeon Magic
|
||||
|
||||
; [ Dunk Mania (DM1/VER.C) ]
|
||||
dunkmnia:0:001DD096:FF:000:Infinite Time
|
||||
dunkmnia:0:001DD095:FF:500:Infinite Time (2/3)
|
||||
dunkmnia:0:001DD094:FF:500:Infinite Time (3/3)
|
||||
dunkmnia:0:001DD096:00:001:Finish this Period Now!
|
||||
dunkmnia:0:001DD095:00:501:Finish this Period Now! (2/3)
|
||||
dunkmnia:0:001DD094:01:501:Finish this Period Now! (3/3)
|
||||
:dunkmnia:00300060:001DD098:00012875:FFFFFFFF:Infinite Shot Time
|
||||
:dunkmnia:00300001:001DD098:00000001:FFFFFFFF:No Shot Time Left Now!:For the best effect assign this cheat an activation key and use it whenever the other side has the ball!
|
||||
dunkmnia:0:001DD4E8:00:000:Score always = 0 PL1
|
||||
dunkmnia:0:001DD4E8:7F:000:Score always = 127 PL1
|
||||
dunkmnia:0:001DD4E8:00:001:Set score = 0 Now! PL1
|
||||
dunkmnia:0:001DD4E8:32:001:Set score = 50 Now! PL1
|
||||
dunkmnia:0:001DD4E8:7F:070:Select score Now! PL1
|
||||
dunkmnia:0:001DD4F4:00:000:Score always = 0 PL2
|
||||
dunkmnia:0:001DD4F4:7F:000:Score always = 127 PL2
|
||||
dunkmnia:0:001DD4F4:00:001:Set score = 0 Now! PL2
|
||||
dunkmnia:0:001DD4F4:32:001:Set score = 50 Now! PL2
|
||||
dunkmnia:0:001DD4F4:7F:070:Select score Now! PL2
|
||||
dunkmniajc:0:001DD096:FF:000:Infinite Time
|
||||
dunkmniajc:0:001DD095:FF:500:Infinite Time (2/3)
|
||||
dunkmniajc:0:001DD094:FF:500:Infinite Time (3/3)
|
||||
dunkmniajc:0:001DD096:00:001:Finish this Period Now!
|
||||
dunkmniajc:0:001DD095:00:501:Finish this Period Now! (2/3)
|
||||
dunkmniajc:0:001DD094:01:501:Finish this Period Now! (3/3)
|
||||
:dunkmniajc:00300060:001DD098:00012875:FFFFFFFF:Infinite Shot Time
|
||||
:dunkmniajc:00300001:001DD098:00000001:FFFFFFFF:No Shot Time Left Now!:For the best effect assign this cheat an activation key and use it whenever the other side has the ball!
|
||||
dunkmniajc:0:001DD4E8:00:000:Score always = 0 PL1
|
||||
dunkmniajc:0:001DD4E8:7F:000:Score always = 127 PL1
|
||||
dunkmniajc:0:001DD4E8:00:001:Set score = 0 Now! PL1
|
||||
dunkmniajc:0:001DD4E8:32:001:Set score = 50 Now! PL1
|
||||
dunkmniajc:0:001DD4E8:7F:070:Select score Now! PL1
|
||||
dunkmniajc:0:001DD4F4:00:000:Score always = 0 PL2
|
||||
dunkmniajc:0:001DD4F4:7F:000:Score always = 127 PL2
|
||||
dunkmniajc:0:001DD4F4:00:001:Set score = 0 Now! PL2
|
||||
dunkmniajc:0:001DD4F4:32:001:Set score = 50 Now! PL2
|
||||
dunkmniajc:0:001DD4F4:7F:070:Select score Now! PL2
|
||||
|
||||
; [ Dunk Shot ]
|
||||
dunkshot:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
@@ -31844,19 +31844,19 @@ eggvntdx:0:000680C8:05:000:Infinite Lives PL2
|
||||
eggvntdx:0:000680BA:63:000:Always have 99 hits PL2
|
||||
|
||||
; [ Ehrgeiz (EG3/VER.A) ]
|
||||
ehrgeiz:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ been looked at due to ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ time constraints - Too]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ many games and so ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ little time. It is ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ even possible that ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ this game may be a ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ clone of an existing ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ game which may have ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ cheats. Please search ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ the cheat forums ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ before posting cheat ]:REASON 11
|
||||
ehrgeiz:0:0000:00:999:[ requests/cheat finding]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ been looked at due to ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ time constraints - Too]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ many games and so ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ little time. It is ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ even possible that ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ this game may be a ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ clone of an existing ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ game which may have ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ cheats. Please search ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ the cheat forums ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ before posting cheat ]:REASON 11
|
||||
ehrgeizua:0:0000:00:999:[ requests/cheat finding]:REASON 11
|
||||
|
||||
; [ Eight Forces ]
|
||||
eightfrc:0:201D50:07:000:Infinite Lives PL1
|
||||
@@ -33676,19 +33676,19 @@ fghthstw:0:001005DD:00:001:Drain All Energy Now! PL2
|
||||
fghthstw:0:00100B00:00:501:Drain All Energy Now! PL2 (2/2)
|
||||
|
||||
; [ Fighting Layer (FTL0/VER.A) ]
|
||||
fgtlayer:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ been looked at due to ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ time constraints - Too]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ many games and so ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ little time. It is ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ even possible that ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ this game may be a ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ clone of an existing ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ game which may have ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ cheats. Please search ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ the cheat forums ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ before posting cheat ]:REASON 11
|
||||
fgtlayer:0:0000:00:999:[ requests/cheat finding]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ been looked at due to ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ time constraints - Too]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ many games and so ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ little time. It is ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ even possible that ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ this game may be a ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ clone of an existing ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ game which may have ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ cheats. Please search ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ the cheat forums ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ before posting cheat ]:REASON 11
|
||||
fgtlayerja:0:0000:00:999:[ requests/cheat finding]:REASON 11
|
||||
|
||||
; [ Fighting Hawk (World) ]
|
||||
fhawk:0:9012:09:000:Infinite Bombs
|
||||
@@ -42660,25 +42660,25 @@ hattrick:0:015F:99:073:Select Score RED TEAM
|
||||
hattrick:0:013A:99:073:Select Score BLUE TEAM
|
||||
|
||||
; [ Hayaoshi Quiz Ouza Ketteisen ]
|
||||
hayaosi1:0:0000:00:999:[ This game should be ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ quite straighforward ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ enough to find cheats ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ for. But no cheats ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ have been submitted ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ at the time this cheat]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ file was compiled ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ due to the game ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ generating zero ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ interest from cheat ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ finders. If you have ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ made some cheats for ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ this game please post ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ them on the cheat ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ forums. Don't forget ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ to search the cheat ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ forums first though as]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ cheats may have been ]:REASON 10
|
||||
hayaosi1:0:0000:00:999:[ found in the meanwhile]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ This game should be ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ quite straighforward ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ enough to find cheats ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ for. But no cheats ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ have been submitted ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ at the time this cheat]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ file was compiled ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ due to the game ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ generating zero ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ interest from cheat ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ finders. If you have ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ made some cheats for ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ this game please post ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ them on the cheat ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ forums. Don't forget ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ to search the cheat ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ forums first though as]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ cheats may have been ]:REASON 10
|
||||
hayaosi2:0:0000:00:999:[ found in the meanwhile]:REASON 10
|
||||
|
||||
; [ Heavy Barrel (US) ]
|
||||
hbarrel:0:FF8032:80:000:Invincibility PL1
|
||||
@@ -67783,9 +67783,9 @@ mrdoy:0:E0F3:01:000:One red monster PL2
|
||||
mrdoy:0:E0F3:00:000:NO red monsters PL2
|
||||
|
||||
; [ Mr Driller (DRI1/VER.A2) ]
|
||||
mrdrillr:0:002C4560:09:000:Infinite Credits
|
||||
mrdrillr:0:0021D5F8:0A:000:Infinite Lives
|
||||
mrdrillr:0:0029EBF9:4A:000:Infinite Air
|
||||
mrdrillrja2:0:002C4560:09:000:Infinite Credits
|
||||
mrdrillrja2:0:0021D5F8:0A:000:Infinite Lives
|
||||
mrdrillrja2:0:0029EBF9:4A:000:Infinite Air
|
||||
|
||||
; [ Mr Driller 2 ]
|
||||
mrdrilr2:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
@@ -117379,38 +117379,38 @@ soulclba:0:0000:00:999:[ for it on the cheat ]:REASON 1
|
||||
soulclba:0:0000:00:999:[ forums. ]:REASON 1
|
||||
|
||||
; [ Soul Calibur (SOC14/VER.C) ]
|
||||
soulclbr:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ for this game as it ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ didn't work the last ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ time it was tested. ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ If the game now works ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ please request cheats ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ for it on the cheat ]:REASON 1
|
||||
soulclbr:0:0000:00:999:[ forums. ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ for this game as it ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ didn't work the last ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ time it was tested. ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ If the game now works ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ please request cheats ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ for it on the cheat ]:REASON 1
|
||||
soulclbrja2:0:0000:00:999:[ forums. ]:REASON 1
|
||||
|
||||
; [ Soul Edge (SO3/VER.A) ]
|
||||
souledga:0:000EFFD4:63:000:Infinite Time
|
||||
souledga:0:000EFFD4:00:001:Finish this Round Now!
|
||||
souledga:0:002D602E:F0:000:Infinite Energy PL1
|
||||
souledga:0:002D602E:00:001:Drain All Energy Now! PL1
|
||||
souledga:0:002D6160:60:000:Always have Maximum Power PL1
|
||||
souledga:0:002D6160:00:001:Drain All Power Now! PL1
|
||||
souledga:0:002D9D72:F0:000:Infinite Energy PL2
|
||||
souledga:0:002D9D72:00:001:Drain All Energy Now! PL2
|
||||
souledga:0:002D9EA4:60:000:Always have Maximum Power PL2
|
||||
souledga:0:002D9EA4:00:001:Drain All Power Now! PL2
|
||||
souledgeua:0:000EFFD4:63:000:Infinite Time
|
||||
souledgeua:0:000EFFD4:00:001:Finish this Round Now!
|
||||
souledgeua:0:002D602E:F0:000:Infinite Energy PL1
|
||||
souledgeua:0:002D602E:00:001:Drain All Energy Now! PL1
|
||||
souledgeua:0:002D6160:60:000:Always have Maximum Power PL1
|
||||
souledgeua:0:002D6160:00:001:Drain All Power Now! PL1
|
||||
souledgeua:0:002D9D72:F0:000:Infinite Energy PL2
|
||||
souledgeua:0:002D9D72:00:001:Drain All Energy Now! PL2
|
||||
souledgeua:0:002D9EA4:60:000:Always have Maximum Power PL2
|
||||
souledgeua:0:002D9EA4:00:001:Drain All Power Now! PL2
|
||||
|
||||
; [ Soul Edge (SO1/VER.A) ]
|
||||
souledgb:0:000EFFD4:63:000:Infinite Time
|
||||
souledgb:0:000EFFD4:00:001:Finish this Round Now!
|
||||
souledgb:0:002D602E:F0:000:Infinite Energy PL1
|
||||
souledgb:0:002D602E:00:001:Drain All Energy Now! PL1
|
||||
souledgb:0:002D6160:60:000:Always have Maximum Power PL1
|
||||
souledgb:0:002D6160:00:001:Drain All Power Now! PL1
|
||||
souledgb:0:002D9D72:F0:000:Infinite Energy PL2
|
||||
souledgb:0:002D9D72:00:001:Drain All Energy Now! PL2
|
||||
souledgb:0:002D9EA4:60:000:Always have Maximum Power PL2
|
||||
souledgb:0:002D9EA4:00:001:Drain All Power Now! PL2
|
||||
souledgeja:0:000EFFD4:63:000:Infinite Time
|
||||
souledgeja:0:000EFFD4:00:001:Finish this Round Now!
|
||||
souledgeja:0:002D602E:F0:000:Infinite Energy PL1
|
||||
souledgeja:0:002D602E:00:001:Drain All Energy Now! PL1
|
||||
souledgeja:0:002D6160:60:000:Always have Maximum Power PL1
|
||||
souledgeja:0:002D6160:00:001:Drain All Power Now! PL1
|
||||
souledgeja:0:002D9D72:F0:000:Infinite Energy PL2
|
||||
souledgeja:0:002D9D72:00:001:Drain All Energy Now! PL2
|
||||
souledgeja:0:002D9EA4:60:000:Always have Maximum Power PL2
|
||||
souledgeja:0:002D9EA4:00:001:Drain All Power Now! PL2
|
||||
|
||||
; [ Soul Edge Ver. II (SO4/VER.C) ]
|
||||
souledge:0:00121F44:63:000:Infinite Time
|
||||
@@ -124535,19 +124535,19 @@ starshpp:0:0083:99:000:Infinite Fuel
|
||||
starshpp:0:00A0:0A:000:Infinite Torpedos
|
||||
|
||||
; [ Star Sweep (STP1/VER.A) ]
|
||||
starswep:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
starswep:0:0000:00:999:[ been looked at due to ]:REASON 11
|
||||
starswep:0:0000:00:999:[ time constraints - Too]:REASON 11
|
||||
starswep:0:0000:00:999:[ many games and so ]:REASON 11
|
||||
starswep:0:0000:00:999:[ little time. It is ]:REASON 11
|
||||
starswep:0:0000:00:999:[ even possible that ]:REASON 11
|
||||
starswep:0:0000:00:999:[ this game may be a ]:REASON 11
|
||||
starswep:0:0000:00:999:[ clone of an existing ]:REASON 11
|
||||
starswep:0:0000:00:999:[ game which may have ]:REASON 11
|
||||
starswep:0:0000:00:999:[ cheats. Please search ]:REASON 11
|
||||
starswep:0:0000:00:999:[ the cheat forums ]:REASON 11
|
||||
starswep:0:0000:00:999:[ before posting cheat ]:REASON 11
|
||||
starswep:0:0000:00:999:[ requests/cheat finding]:REASON 11
|
||||
starswepj:0:0000:00:999:[ This game hasn't even ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ been looked at due to ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ time constraints - Too]:REASON 11
|
||||
starswepj:0:0000:00:999:[ many games and so ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ little time. It is ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ even possible that ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ this game may be a ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ clone of an existing ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ game which may have ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ cheats. Please search ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ the cheat forums ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ before posting cheat ]:REASON 11
|
||||
starswepj:0:0000:00:999:[ requests/cheat finding]:REASON 11
|
||||
|
||||
; [ Star Trek ]
|
||||
startrek:0:CE17:04:000:Infinite Shield
|
||||
@@ -126978,61 +126978,52 @@ tekipaki:0:080C07:FF:070:Select current level PL1
|
||||
tekipaki:0:081C07:FF:070:Select current level PL2
|
||||
|
||||
; [ Tekken (TE4/VER.C) ]
|
||||
tekken:0:00267038:09:000:Infinite Credits
|
||||
:tekken:00100000:002648BC:00001730:FFFFFFFF:Infinite Time
|
||||
:tekken:00100001:002648BC:00000001:FFFFFFFF:Finish this Round Now!
|
||||
:tekken:00000000:00264AF6:0000007D:FFFFFFFF:Infinite Energy PL1
|
||||
:tekken:00000001:00264AF6:00000000:FFFFFFFF:Drain all Energy Now! PL1
|
||||
:tekken:00000000:00265B2E:0000007D:FFFFFFFF:Infinite Energy PL2
|
||||
:tekken:00000001:00265B2E:00000000:FFFFFFFF:Drain all Energy Now! PL2
|
||||
tekkenac:0:00267038:09:000:Infinite Credits
|
||||
:tekkenac:00100000:002648BC:00001730:FFFFFFFF:Infinite Time
|
||||
:tekkenac:00100001:002648BC:00000001:FFFFFFFF:Finish this Round Now!
|
||||
:tekkenac:00000000:00264AF6:0000007D:FFFFFFFF:Infinite Energy PL1
|
||||
:tekkenac:00000001:00264AF6:00000000:FFFFFFFF:Drain all Energy Now! PL1
|
||||
:tekkenac:00000000:00265B2E:0000007D:FFFFFFFF:Infinite Energy PL2
|
||||
:tekkenac:00000001:00265B2E:00000000:FFFFFFFF:Drain all Energy Now! PL2
|
||||
|
||||
; [ Tekken 2 Ver.B (TES3/VER.B) ]
|
||||
tekken2:0:00301CEC:09:000:Infinite Credits
|
||||
:tekken2:00100000:0030F174:00001732:FFFFFFFF:Infinite Time
|
||||
:tekken2:00100001:0030F174:00000001:FFFFFFFF:Finish this Round Now!
|
||||
tekken2:0:0030CA6A:7E:000:Infinite Energy PL1
|
||||
tekken2:0:0030CA6A:00:001:Drain All Energy Now! PL1
|
||||
tekken2:0:0030DEEA:7E:000:Infinite Energy PL2
|
||||
tekken2:0:0030DEEA:00:001:Drain All Energy Now! PL2
|
||||
tekken2ub:0:00301CEC:09:000:Infinite Credits
|
||||
:tekken2ub:00100000:0030F174:00001732:FFFFFFFF:Infinite Time
|
||||
:tekken2ub:00100001:0030F174:00000001:FFFFFFFF:Finish this Round Now!
|
||||
tekken2ub:0:0030CA6A:7E:000:Infinite Energy PL1
|
||||
tekken2ub:0:0030CA6A:00:001:Drain All Energy Now! PL1
|
||||
tekken2ub:0:0030DEEA:7E:000:Infinite Energy PL2
|
||||
tekken2ub:0:0030DEEA:00:001:Drain All Energy Now! PL2
|
||||
|
||||
; [ Tekken 2 Ver.B (TES2/VER.B) ]
|
||||
tekken2a:0:00301CEC:09:000:Infinite Credits
|
||||
:tekken2a:00100000:0030F174:00001732:FFFFFFFF:Infinite Time
|
||||
:tekken2a:00100001:0030F174:00000001:FFFFFFFF:Finish this Round Now!
|
||||
tekken2a:0:0030CA6A:7E:000:Infinite Energy PL1
|
||||
tekken2a:0:0030CA6A:00:001:Drain All Energy Now! PL1
|
||||
tekken2a:0:0030DEEA:7E:000:Infinite Energy PL2
|
||||
tekken2a:0:0030DEEA:00:001:Drain All Energy Now! PL2
|
||||
tekken2b:0:00301CEC:09:000:Infinite Credits
|
||||
:tekken2b:00100000:0030F174:00001732:FFFFFFFF:Infinite Time
|
||||
:tekken2b:00100001:0030F174:00000001:FFFFFFFF:Finish this Round Now!
|
||||
tekken2b:0:0030CA6A:7E:000:Infinite Energy PL1
|
||||
tekken2b:0:0030CA6A:00:001:Drain All Energy Now! PL1
|
||||
tekken2b:0:0030DEEA:7E:000:Infinite Energy PL2
|
||||
tekken2b:0:0030DEEA:00:001:Drain All Energy Now! PL2
|
||||
|
||||
; [ Tekken 2 (TES2/VER.A) ]
|
||||
tekken2b:0:002FA4A0:09:000:Infinite Credits
|
||||
:tekken2b:00100000:00307928:00001732:FFFFFFFF:Infinite Time
|
||||
:tekken2b:00100001:00307928:00000001:FFFFFFFF:Finish this Round Now!
|
||||
tekken2b:0:0030521E:7E:000:Infinite Energy PL1
|
||||
tekken2b:0:0030521E:00:001:Drain All Energy Now! PL1
|
||||
tekken2b:0:0030669E:7E:000:Infinite Energy PL2
|
||||
tekken2b:0:0030669E:00:001:Drain All Energy Now! PL2
|
||||
tekken2a:0:002FA4A0:09:000:Infinite Credits
|
||||
:tekken2a:00100000:00307928:00001732:FFFFFFFF:Infinite Time
|
||||
:tekken2a:00100001:00307928:00000001:FFFFFFFF:Finish this Round Now!
|
||||
tekken2a:0:0030521E:7E:000:Infinite Energy PL1
|
||||
tekken2a:0:0030521E:00:001:Drain All Energy Now! PL1
|
||||
tekken2a:0:0030669E:7E:000:Infinite Energy PL2
|
||||
tekken2a:0:0030669E:00:001:Drain All Energy Now! PL2
|
||||
|
||||
; [ Tekken 3 (TET1/VER.E1) ]
|
||||
tekken3:0:0021FB8C:32:000:Infinite Time
|
||||
tekken3:0:0021FB8D:17:500:Infinite Time (2/2)
|
||||
tekken3:0:0021FB8C:01:001:Finish this Round Now!
|
||||
tekken3:0:0021FB8D:00:501:Finish this Round Now! (2/2)
|
||||
tekken3:0:0031E492:82:000:Infinite Energy PL1
|
||||
tekken3:0:0031E492:00:001:Drain All Energy Now! PL1
|
||||
tekken3:0:0031FF76:82:000:Infinite Energy PL2
|
||||
tekken3:0:0031FF76:00:001:Drain All Energy Now! PL2
|
||||
tekken3je1:0:0021FB8C:32:000:Infinite Time
|
||||
tekken3je1:0:0021FB8D:17:500:Infinite Time (2/2)
|
||||
tekken3je1:0:0021FB8C:01:001:Finish this Round Now!
|
||||
tekken3je1:0:0021FB8D:00:501:Finish this Round Now! (2/2)
|
||||
tekken3je1:0:0031E492:82:000:Infinite Energy PL1
|
||||
tekken3je1:0:0031E492:00:001:Drain All Energy Now! PL1
|
||||
tekken3je1:0:0031FF76:82:000:Infinite Energy PL2
|
||||
tekken3je1:0:0031FF76:00:001:Drain All Energy Now! PL2
|
||||
|
||||
; [ Tekken (TE2/VER.B) ]
|
||||
tekkena:0:00266CE0:09:000:Infinite Credits
|
||||
:tekkena:00100000:00264564:00001730:FFFFFFFF:Infinite Time
|
||||
:tekkena:00100001:00264564:00000001:FFFFFFFF:Finish this Round Now!
|
||||
:tekkena:00000000:0026479E:0000007D:FFFFFFFF:Infinite Energy PL1
|
||||
:tekkena:00000001:0026479E:00000000:FFFFFFFF:Drain all Energy Now! PL1
|
||||
:tekkena:00000000:002657D6:0000007D:FFFFFFFF:Infinite Energy PL2
|
||||
:tekkena:00000001:002657D6:00000000:FFFFFFFF:Drain all Energy Now! PL2
|
||||
|
||||
; [ Tekken (TE1/VER.B) ]
|
||||
tekkenb:0:00266CE0:09:000:Infinite Credits
|
||||
:tekkenb:00100000:00264564:00001730:FFFFFFFF:Infinite Time
|
||||
:tekkenb:00100001:00264564:00000001:FFFFFFFF:Finish this Round Now!
|
||||
@@ -127041,15 +127032,24 @@ tekkenb:0:00266CE0:09:000:Infinite Credits
|
||||
:tekkenb:00000000:002657D6:0000007D:FFFFFFFF:Infinite Energy PL2
|
||||
:tekkenb:00000001:002657D6:00000000:FFFFFFFF:Drain all Energy Now! PL2
|
||||
|
||||
; [ Tekken (TE1/VER.B) ]
|
||||
tekkenjb:0:00266CE0:09:000:Infinite Credits
|
||||
:tekkenjb:00100000:00264564:00001730:FFFFFFFF:Infinite Time
|
||||
:tekkenjb:00100001:00264564:00000001:FFFFFFFF:Finish this Round Now!
|
||||
:tekkenjb:00000000:0026479E:0000007D:FFFFFFFF:Infinite Energy PL1
|
||||
:tekkenjb:00000001:0026479E:00000000:FFFFFFFF:Drain all Energy Now! PL1
|
||||
:tekkenjb:00000000:002657D6:0000007D:FFFFFFFF:Infinite Energy PL2
|
||||
:tekkenjb:00000001:002657D6:00000000:FFFFFFFF:Drain all Energy Now! PL2
|
||||
|
||||
; [ Tekken Tag Tournament (TEG3/VER.B) ]
|
||||
tekkentt:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ for this game as it ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ didn't work the last ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ time it was tested. ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ If the game now works ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ please request cheats ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ for it on the cheat ]:REASON 1
|
||||
tekkentt:0:0000:00:999:[ forums. ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ There are no cheats ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ for this game as it ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ didn't work the last ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ time it was tested. ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ If the game now works ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ please request cheats ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ for it on the cheat ]:REASON 1
|
||||
tektagtub:0:0000:00:999:[ forums. ]:REASON 1
|
||||
|
||||
; [ Tel Jan ]
|
||||
teljan:0:06002FD7:09:000:Infinite Credits
|
||||
@@ -138936,17 +138936,17 @@ xenophob:0:0607ED:FF:000:Infinite Health PL2
|
||||
xenophob:0:0608AD:FF:000:Infinite Health PL3
|
||||
|
||||
; [ Xevious 3D/G (XV31/VER.A) ]
|
||||
xevi3dg:0:000EE8C0:09:000:Infinite Credits
|
||||
xevi3dg:0:00150DC8:06:000:Infinite Lives PL1
|
||||
xevi3dg:0:00126358:01:000:Invincibility PL1
|
||||
xevi3dg:0:00150DB0:01:000:Always have Laser Gun PL1
|
||||
xevi3dg:0:00150DB0:02:000:Always have Homing Weapon PL1
|
||||
xevi3dg:0:00115BDC:02:000:Maximum Fire Power PL1
|
||||
xevi3dg:0:00150DCC:06:000:Infinite Lives PL2
|
||||
xevi3dg:0:00126204:01:000:Invincibility PL2
|
||||
xevi3dg:0:00150DB4:01:000:Always have Laser Gun PL2
|
||||
xevi3dg:0:00150DB4:02:000:Always have Homing Weapon PL2
|
||||
xevi3dg:0:001171B0:02:000:Maximum Fire Power PL2
|
||||
xevi3dgj:0:000EE8C0:09:000:Infinite Credits
|
||||
xevi3dgj:0:00150DC8:06:000:Infinite Lives PL1
|
||||
xevi3dgj:0:00126358:01:000:Invincibility PL1
|
||||
xevi3dgj:0:00150DB0:01:000:Always have Laser Gun PL1
|
||||
xevi3dgj:0:00150DB0:02:000:Always have Homing Weapon PL1
|
||||
xevi3dgj:0:00115BDC:02:000:Maximum Fire Power PL1
|
||||
xevi3dgj:0:00150DCC:06:000:Infinite Lives PL2
|
||||
xevi3dgj:0:00126204:01:000:Invincibility PL2
|
||||
xevi3dgj:0:00150DB4:01:000:Always have Laser Gun PL2
|
||||
xevi3dgj:0:00150DB4:02:000:Always have Homing Weapon PL2
|
||||
xevi3dgj:0:001171B0:02:000:Maximum Fire Power PL2
|
||||
|
||||
; [ Xevios ]
|
||||
xevios:0:8183:09:000:Infinite Lives
|
||||
|
||||
@@ -1688,6 +1688,7 @@ batriderhk:
|
||||
|
||||
mrdrillrj:
|
||||
mrdrillr:
|
||||
mrdrillrja2:
|
||||
0:201038:288:76:76
|
||||
|
||||
sfiii3:
|
||||
@@ -1829,6 +1830,7 @@ spf2xjd:
|
||||
spf2ta:
|
||||
spf2th:
|
||||
spf2td:
|
||||
spf2xpri:
|
||||
0:ffd7aa:4e:00:02
|
||||
0:ff8081:1:01:01
|
||||
|
||||
@@ -2775,7 +2777,9 @@ chinhero3:
|
||||
0:e12a:1:03:03
|
||||
|
||||
asurabus:
|
||||
asurabusa:
|
||||
asurabusj:
|
||||
asurabusja:
|
||||
asurabusjr:
|
||||
0:40326d:132:05:14
|
||||
|
||||
dynabomb:
|
||||
@@ -3270,7 +3274,7 @@ theglob2:
|
||||
0:7c4b:1:01:01
|
||||
0:7c51:1:80:80
|
||||
|
||||
beastf:
|
||||
beastfp:
|
||||
0:4c46:3c:4d:00
|
||||
0:4c8a:1:01:01
|
||||
0:4cb0:1:15:15
|
||||
|
||||
+24
-24
@@ -20586,7 +20586,7 @@ Commodore Amiga (1990)
|
||||
$end
|
||||
|
||||
|
||||
$info=beastf,
|
||||
$info=beastf,beastfp,
|
||||
$bio
|
||||
|
||||
Beastie Feastie (c) 1984 Epos Corporation.
|
||||
@@ -39674,7 +39674,7 @@ Graphic : Kim Eun Ae, Hong Young Joo, Whang O-Sik, Hong Dae Hyun
|
||||
$end
|
||||
|
||||
|
||||
$info=chplft,chplftb,chplftbl,
|
||||
$info=choplift,chopliftu,chopliftbl,
|
||||
$bio
|
||||
|
||||
Choplifter (c) 1985 Sega.
|
||||
@@ -49927,7 +49927,7 @@ The title of this game translates from Japanese as 'Hanafuda at the Apartments'.
|
||||
$end
|
||||
|
||||
|
||||
$info=danceyes,
|
||||
$info=danceyes,danceyesu,danceyesj,
|
||||
$bio
|
||||
|
||||
Dancing Eyes (c) 08/1996 Namco.
|
||||
@@ -63256,7 +63256,7 @@ This game is also known as "Dataeast's Hoops".
|
||||
$end
|
||||
|
||||
|
||||
$info=dunkmnia,dunkmnic,
|
||||
$info=dunkmnia,dunkmniajc,
|
||||
$bio
|
||||
|
||||
Dunk Mania (c) 1995 Namco.
|
||||
@@ -68525,7 +68525,7 @@ Designed by : Luis Sanchez
|
||||
$end
|
||||
|
||||
|
||||
$info=ehrgeiz,ehrgeiza,
|
||||
$info=ehrgeiz,ehrgeizua,ehrgeizja,
|
||||
$bio
|
||||
|
||||
EZ : Ehrgeiz - God Bless The Ring (c) 1998 Square / Namco.
|
||||
@@ -71900,7 +71900,7 @@ Buttons : 2
|
||||
$end
|
||||
|
||||
|
||||
$info=fgtlayer,
|
||||
$info=fgtlayer,fgtlayerja,
|
||||
$bio
|
||||
|
||||
Fighting Layer (c) 12/1998 Arika.
|
||||
@@ -95537,7 +95537,7 @@ King Records released a limited-edition soundtrack album for this game (Konami G
|
||||
$end
|
||||
|
||||
|
||||
$info=hayaosi1,
|
||||
$info=hayaosi2,
|
||||
$bio
|
||||
|
||||
Hayaoshi Quiz Ouza Ketteisen (c) 1994 Jaleco.
|
||||
@@ -100624,7 +100624,7 @@ Sega Saturn (1996, "Sega Ages : Rouka ni Ichidant-R")
|
||||
$end
|
||||
|
||||
|
||||
$info=47pie2,47pie2o,
|
||||
$info=suchie2,suchie2o,
|
||||
$bio
|
||||
|
||||
Idol Janshi Suchi-Pai II (c) 1994 Jaleco.
|
||||
@@ -146695,7 +146695,7 @@ MSX (1985)
|
||||
$end
|
||||
|
||||
|
||||
$info=mrdrillr,
|
||||
$info=mrdrillr,mrdrillrja2,
|
||||
$bio
|
||||
|
||||
Mr. Driller (c) 1999 Namco.
|
||||
@@ -153222,7 +153222,7 @@ PC [MS Windows] (2005, "Taito Legends")
|
||||
$end
|
||||
|
||||
|
||||
$info=nzerotea,
|
||||
$info=nzeroteam,nzeroteama,nzeroteamb,zerotm2k,
|
||||
$bio
|
||||
|
||||
New Zero Team (c) 1993 Seibu Kaihatsu.
|
||||
@@ -168550,7 +168550,7 @@ Sony PlayStation 2 (2002, "Gunvari Collection + Time Crisis")
|
||||
$end
|
||||
|
||||
|
||||
$info=ptblank2,
|
||||
$info=ptblank2,ptblank2a,ptblank2b,ptblank2c,ptblank2ua,gunbarla,
|
||||
$bio
|
||||
|
||||
Point Blank 2 (c) 1999 Namco.
|
||||
@@ -182610,7 +182610,7 @@ PC [MS-DOS, CD-ROM]
|
||||
$end
|
||||
|
||||
|
||||
$info=raidndx,raidndxa,raidndxb,raidndxj,raidndxm,
|
||||
$info=raidendx,raidendxg,raidendxpt,raidendxa1,raidendxa2,raidendxk,raidendxu,raidendxnl,raidendxj,raidendxja,raidendxch,r2dx_v33,r2dx_v33_r2,
|
||||
$bio
|
||||
|
||||
Raiden DX (c) 1994 Seibu Kaihatsu.
|
||||
@@ -183143,7 +183143,7 @@ Level 15 : Before the boss appears, do not shoot any small tanks. Two small tank
|
||||
$end
|
||||
|
||||
|
||||
$info=raiden2,raiden2a,raiden2b,raiden2c,raiden2e,
|
||||
$info=raiden2,raiden2g,raiden2gb,raiden2hk,raiden2j,raiden2sw,raiden2u,raiden2f,raiden2nl,raiden2es,raiden2i,raiden2au,raiden2e,raiden2eub,raiden2eua,raiden2eg,raiden2eup,raiden2ea,raiden2eu,raiden2k,raiden2dx,
|
||||
$bio
|
||||
|
||||
Raiden II (c) 1993 Seibu Kaihatsu.
|
||||
@@ -187724,7 +187724,7 @@ Total planner / Total cordinator : The Alive
|
||||
$end
|
||||
|
||||
|
||||
$info=revenger,
|
||||
$info=revenger,revngr84,
|
||||
$bio
|
||||
|
||||
Revenger (c) 1984 Epos.
|
||||
@@ -210976,7 +210976,7 @@ Sega Saturn (1997)
|
||||
$end
|
||||
|
||||
|
||||
$info=soulclbr,soulclba,soulclbb,
|
||||
$info=soulclbr,soulclbrab,soulclbrac,soulclbrub,soulclbruc,soulclbrja2,soulclbrjb,soulclbrjc,
|
||||
$bio
|
||||
|
||||
Soul Calibur (c) 07/1998 Namco.
|
||||
@@ -211061,7 +211061,7 @@ Sega Dreamcast (1999) : The new Weapon Master mode made it's debut in this versi
|
||||
$end
|
||||
|
||||
|
||||
$info=souledga,souledgb,souledgc,
|
||||
$info=souledgea,souledgeua,souledgeja,
|
||||
$bio
|
||||
|
||||
Soul Edge (c) 1995 Namco.
|
||||
@@ -211188,7 +211188,7 @@ Sony PlayStation (1996)
|
||||
$end
|
||||
|
||||
|
||||
$info=souledge,
|
||||
$info=souledge,souledgeuc,
|
||||
$bio
|
||||
|
||||
Soul Edge Ver. II (c) 1996 Namco.
|
||||
@@ -219296,7 +219296,7 @@ Sega Saturn (1997, "Sega Memorial Selection Vol.2")
|
||||
$end
|
||||
|
||||
|
||||
$info=starswep,
|
||||
$info=starswep,starswepj,
|
||||
$bio
|
||||
|
||||
Star Sweep (c) 07/1997 Axela.
|
||||
@@ -243474,7 +243474,7 @@ Music composed by : Tomoaki Takanohashi
|
||||
$end
|
||||
|
||||
|
||||
$info=tekken,tekkena,tekkenb,tekkenc,
|
||||
$info=tekken,tekkenac,tekkenb,tekkenjb,
|
||||
$bio
|
||||
|
||||
Tekken (c) 12/1994 Namco.
|
||||
@@ -243635,7 +243635,7 @@ Sony PlayStation 2 (2005, "NamCollection") : Japan release only.
|
||||
$end
|
||||
|
||||
|
||||
$info=tekken2,tekken2a,tekken2b,
|
||||
$info=tekken2,tekken2b,tekken2ud,tekken2ub,tekken2jc,tekken2jb,tekken2a,tekken2ua,
|
||||
$bio
|
||||
|
||||
Tekken 2 (c) 08/1995 Namco.
|
||||
@@ -243867,7 +243867,7 @@ Sony PlayStation 2 (2005, "Tekken 5 Ultimate Collectors Edition")
|
||||
$end
|
||||
|
||||
|
||||
$info=tekken3,tekken3a,
|
||||
$info=tekken3,tekken3je1,
|
||||
$bio
|
||||
|
||||
Tekken 3 (c) 1996 Namco.
|
||||
@@ -244067,7 +244067,7 @@ Sony PlayStation 2 (2005, "Tekken 5 Ultimate Collectors Edition")
|
||||
$end
|
||||
|
||||
|
||||
$info=tektagt,tektagta,
|
||||
$info=tektagt,tektagtub,tektagtuc1,tektagtjc1,
|
||||
$bio
|
||||
|
||||
Tekken Tag Tournament (c) 1999 Namco.
|
||||
@@ -275757,7 +275757,7 @@ F.A.Q. by Kevin Butler A.K.A. War Doc
|
||||
$end
|
||||
|
||||
|
||||
$info=xevi3dg,
|
||||
$info=xevi3dg,xevi3dga,xevi3dgj,
|
||||
$bio
|
||||
|
||||
Xevious 3D/G (c) 04/1995 Namco.
|
||||
@@ -278372,7 +278372,7 @@ This game is known in Japan as "Gekitsui Oh".
|
||||
$end
|
||||
|
||||
|
||||
$info=zeroteam,zeroteaa,zeroteab,
|
||||
$info=zeroteam,zeroteama,zeroteamb,zeroteamc,zeroteamd,zeroteame,zeroteams,zeroteamsr,
|
||||
$bio
|
||||
|
||||
Zero Team (c) 1993 Seibu Kaihatsu.
|
||||
|
||||
+27178
-2918
File diff suppressed because it is too large.
Load diff
+119
-32
@@ -377,6 +377,7 @@ struct artwork_piece
|
||||
struct mame_bitmap * yrgbbitmap;
|
||||
UINT32 * scanlinehint;
|
||||
UINT8 blendflags;
|
||||
const struct overlay_piece *overlay_data; /* a driver's overlay: drawn again on a resize */
|
||||
|
||||
/* derived/dynamic data */
|
||||
int intersects_game;
|
||||
@@ -408,6 +409,9 @@ static int gamescale;
|
||||
static struct mame_bitmap *uioverlay;
|
||||
static UINT32 *uioverlayhint;
|
||||
static struct rectangle uibounds, last_uibounds;
|
||||
static struct rectangle ui_changed_bounds;
|
||||
static int ui_changed;
|
||||
static int full_render_pending; /* after a resize: draw the whole game, not the vector dirty pixels */
|
||||
|
||||
static UINT32 *palette_lookup;
|
||||
|
||||
@@ -446,6 +450,7 @@ static void alpha_blend_intersecting_rect(struct mame_bitmap *dstbitmap, const s
|
||||
static void add_intersecting_rect(struct mame_bitmap *dstbitmap, const struct rectangle *dstbounds, struct mame_bitmap *srcbitmap, const struct rectangle *srcbounds);
|
||||
static void cmy_blend_intersecting_rect(struct mame_bitmap *dstbitmap, struct mame_bitmap *dstyrgbbitmap, const struct rectangle *dstbounds, struct mame_bitmap *srcbitmap, struct mame_bitmap *srcyrgbbitmap, const struct rectangle *srcbounds, UINT8 blendflags);
|
||||
static int generate_overlay(const struct overlay_piece *list, int width, int height);
|
||||
static int generate_overlay_bitmap(struct artwork_piece *piece, int width, int height);
|
||||
static void add_range_to_hint(UINT32 *hintbase, int scanline, int startx, int endx);
|
||||
|
||||
|
||||
@@ -596,7 +601,89 @@ static INLINE UINT32 blend_over(UINT32 game, UINT32 pre, UINT32 yrgb)
|
||||
to osd_create_display
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int artwork_setup_display(struct osd_create_params *params, UINT32 *rgb_components);
|
||||
|
||||
int artwork_create_display(struct osd_create_params *params, UINT32 *rgb_components, const struct artwork_callbacks *callbacks)
|
||||
{
|
||||
/* reset UI */
|
||||
uioverlay = NULL;
|
||||
uioverlayhint = NULL;
|
||||
palette_lookup = NULL;
|
||||
|
||||
/* first load the artwork; if none, quit now */
|
||||
artwork_list = NULL;
|
||||
if (!artwork_load(Machine->gamedrv, params->width, params->height, callbacks))
|
||||
return 1;
|
||||
if (!artwork_list && (!callbacks->activate_artwork || !callbacks->activate_artwork(params)))
|
||||
return osd_create_display(params, rgb_components);
|
||||
|
||||
return artwork_setup_display(params, rgb_components);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
artwork_resize_display - the game's display
|
||||
changes size while it runs (the vector
|
||||
resolution): the loaded artwork is kept, the
|
||||
bitmaps that depend on the size are made again
|
||||
-------------------------------------------------*/
|
||||
|
||||
int artwork_resize_display(struct osd_create_params *params, UINT32 *rgb_components)
|
||||
{
|
||||
struct artwork_piece *piece;
|
||||
|
||||
if (!artwork_list && !uioverlay)
|
||||
{
|
||||
osd_close_display();
|
||||
return osd_create_display(params, rgb_components);
|
||||
}
|
||||
|
||||
/* free what was made for the old size */
|
||||
auto_bitmap_free(underlay);
|
||||
auto_bitmap_free(overlay);
|
||||
auto_bitmap_free(overlay_yrgb);
|
||||
auto_bitmap_free(bezel);
|
||||
auto_bitmap_free(final);
|
||||
auto_bitmap_free(uioverlay);
|
||||
auto_free_ptr(uioverlayhint);
|
||||
underlay = overlay = overlay_yrgb = bezel = final = uioverlay = NULL;
|
||||
uioverlayhint = NULL;
|
||||
for (piece = artwork_list; piece; piece = piece->next)
|
||||
{
|
||||
auto_bitmap_free(piece->prebitmap);
|
||||
auto_bitmap_free(piece->yrgbbitmap);
|
||||
auto_free_ptr(piece->scanlinehint);
|
||||
piece->prebitmap = piece->yrgbbitmap = NULL;
|
||||
piece->scanlinehint = NULL;
|
||||
|
||||
/* a driver's overlay is drawn at the game's size: draw it again */
|
||||
if (piece->overlay_data)
|
||||
{
|
||||
auto_bitmap_free(piece->rawbitmap);
|
||||
piece->rawbitmap = NULL;
|
||||
if (!generate_overlay_bitmap(piece, params->width, params->height))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* the UI areas were on the old size */
|
||||
memset(&uibounds, 0, sizeof(uibounds));
|
||||
memset(&last_uibounds, 0, sizeof(last_uibounds));
|
||||
memset(&ui_changed_bounds, 0, sizeof(ui_changed_bounds));
|
||||
ui_changed = 0;
|
||||
full_render_pending = 1;
|
||||
|
||||
osd_close_display();
|
||||
return artwork_setup_display(params, rgb_components);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
artwork_setup_display - size the artwork
|
||||
bitmaps for the display and create it
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int artwork_setup_display(struct osd_create_params *params, UINT32 *rgb_components)
|
||||
{
|
||||
int original_width = params->width;
|
||||
int original_height = params->height;
|
||||
@@ -605,17 +692,6 @@ int artwork_create_display(struct osd_create_params *params, UINT32 *rgb_compone
|
||||
UINT32 rgb32_components[3];
|
||||
struct artwork_piece *piece;
|
||||
|
||||
/* reset UI */
|
||||
uioverlay = NULL;
|
||||
uioverlayhint = NULL;
|
||||
|
||||
/* first load the artwork; if none, quit now */
|
||||
artwork_list = NULL;
|
||||
if (!artwork_load(Machine->gamedrv, original_width, original_height, callbacks))
|
||||
return 1;
|
||||
if (!artwork_list && (!callbacks->activate_artwork || !callbacks->activate_artwork(params)))
|
||||
return osd_create_display(params, rgb_components);
|
||||
|
||||
/* determine the game bitmap scale factor */
|
||||
gamescale = options.artwork_res;
|
||||
if (gamescale < 1 || (params->video_attributes & VIDEO_TYPE_VECTOR))
|
||||
@@ -798,8 +874,6 @@ void artwork_update_visible_area(struct mame_display *display)
|
||||
|
||||
void artwork_update_video_and_audio(struct mame_display *display)
|
||||
{
|
||||
static struct rectangle ui_changed_bounds;
|
||||
static int ui_changed;
|
||||
int artwork_changed = 0, ui_visible = 0;
|
||||
|
||||
/* do nothing if no artwork */
|
||||
@@ -824,6 +898,13 @@ void artwork_update_video_and_audio(struct mame_display *display)
|
||||
/* process the artwork and UI only if we're not frameskipping */
|
||||
if (display->changed_flags & GAME_BITMAP_CHANGED)
|
||||
{
|
||||
if (full_render_pending)
|
||||
{
|
||||
display->changed_flags &= ~VECTOR_PIXELS_CHANGED;
|
||||
display->vector_dirty_pixels = NULL;
|
||||
full_render_pending = 0;
|
||||
}
|
||||
|
||||
/* see if there's any UI to display this frame */
|
||||
ui_visible = (uibounds.max_x != 0);
|
||||
|
||||
@@ -3349,6 +3430,25 @@ static int generate_right_triangle_piece(struct artwork_piece *piece, const stru
|
||||
the given pieces
|
||||
-------------------------------------------------*/
|
||||
|
||||
static int generate_overlay_bitmap(struct artwork_piece *piece, int width, int height)
|
||||
{
|
||||
const struct overlay_piece *list = piece->overlay_data;
|
||||
|
||||
/* switch off the type */
|
||||
switch (list->type & ~OVERLAY_FLAG_MASK)
|
||||
{
|
||||
case OVERLAY_TYPE_RECTANGLE:
|
||||
return generate_rect_piece(piece, list, width, height);
|
||||
|
||||
case OVERLAY_TYPE_DISK:
|
||||
return generate_disk_piece(piece, list, width, height);
|
||||
|
||||
case OVERLAY_TYPE_RIGHT_TRIANGLE:
|
||||
return generate_right_triangle_piece(piece, list, width, height);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int generate_overlay(const struct overlay_piece *list, int width, int height)
|
||||
{
|
||||
struct artwork_piece *piece;
|
||||
@@ -3368,24 +3468,10 @@ static int generate_overlay(const struct overlay_piece *list, int width, int hei
|
||||
piece->priority = priority++;
|
||||
piece->blendflags = list->type & OVERLAY_FLAG_MASK;
|
||||
piece->tag = list->tag; /* Handle someone using a different tag, for example, cocktail mode */
|
||||
piece->overlay_data = list;
|
||||
|
||||
/* switch off the type */
|
||||
switch (list->type & ~OVERLAY_FLAG_MASK)
|
||||
{
|
||||
case OVERLAY_TYPE_RECTANGLE:
|
||||
if (!generate_rect_piece(piece, list, width, height))
|
||||
return 0;
|
||||
break;
|
||||
|
||||
case OVERLAY_TYPE_DISK:
|
||||
if (!generate_disk_piece(piece, list, width, height))
|
||||
return 0;
|
||||
break;
|
||||
case OVERLAY_TYPE_RIGHT_TRIANGLE:
|
||||
if (!generate_right_triangle_piece(piece, list, width, height))
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
if (!generate_overlay_bitmap(piece, width, height))
|
||||
return 0;
|
||||
|
||||
/* next */
|
||||
list++;
|
||||
@@ -3582,8 +3668,9 @@ static int compute_rgb_components(int depth, UINT32 rgb_components[3], UINT32 rg
|
||||
/* compute a transparent color; this is in the premultiplied space, so alpha is inverted */
|
||||
transparent_color = ASSEMBLE_ARGB(0xff,0x00,0x00,0x00);
|
||||
|
||||
/* allocate a palette lookup */
|
||||
palette_lookup = auto_malloc(65536 * sizeof(palette_lookup[0]));
|
||||
/* allocate a palette lookup (once per game: a resize keeps it, as the depth and palette stay) */
|
||||
if (!palette_lookup)
|
||||
palette_lookup = auto_malloc(65536 * sizeof(palette_lookup[0]));
|
||||
|
||||
|
||||
/* switch off the depth */
|
||||
|
||||
@@ -163,6 +163,7 @@ struct overlay_piece
|
||||
***************************************************************************/
|
||||
|
||||
int artwork_create_display(struct osd_create_params *params, UINT32 *rgb_components, const struct artwork_callbacks *callbacks);
|
||||
int artwork_resize_display(struct osd_create_params *params, UINT32 *rgb_components);
|
||||
void artwork_update_video_and_audio(struct mame_display *display);
|
||||
void artwork_override_screenshot_params(struct mame_bitmap **bitmap, struct rectangle *rect, UINT32 *rgb_components);
|
||||
|
||||
|
||||
+137
-87
@@ -16,31 +16,6 @@
|
||||
/*#define LOG_LOAD */
|
||||
|
||||
|
||||
const char *chd_error_text[] =
|
||||
{
|
||||
"CHDERR_NONE",
|
||||
"CHDERR_NO_INTERFACE",
|
||||
"CHDERR_OUT_OF_MEMORY",
|
||||
"CHDERR_INVALID_FILE",
|
||||
"CHDERR_INVALID_PARAMETER",
|
||||
"CHDERR_INVALID_DATA",
|
||||
"CHDERR_FILE_NOT_FOUND",
|
||||
"CHDERR_REQUIRES_PARENT",
|
||||
"CHDERR_FILE_NOT_WRITEABLE",
|
||||
"CHDERR_READ_ERROR",
|
||||
"CHDERR_WRITE_ERROR",
|
||||
"CHDERR_CODEC_ERROR",
|
||||
"CHDERR_INVALID_PARENT",
|
||||
"CHDERR_HUNK_OUT_OF_RANGE",
|
||||
"CHDERR_DECOMPRESSION_ERROR",
|
||||
"CHDERR_COMPRESSION_ERROR",
|
||||
"CHDERR_CANT_CREATE_FILE",
|
||||
"CHDERR_CANT_VERIFY",
|
||||
"CHDERR_NOT_SUPPORTED",
|
||||
"CHDERR_METADATA_NOT_FOUND",
|
||||
"CHDERR_INVALID_METADATA_SIZE",
|
||||
"CHDERR_UNSUPPORTED_VERSION"
|
||||
};
|
||||
/***************************************************************************
|
||||
Constants
|
||||
***************************************************************************/
|
||||
@@ -182,7 +157,7 @@ size_t generic_nvram_size;
|
||||
data8_t *generic_nvram;
|
||||
|
||||
/* disks */
|
||||
static struct chd_file *disk_handle[4];
|
||||
static struct hard_disk_file *disk_handle[4];
|
||||
|
||||
/* system BIOS */
|
||||
static int system_bios;
|
||||
@@ -996,6 +971,47 @@ void auto_free(void)
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
auto_free_ptr - free one auto_malloc block
|
||||
before its tag ends, and stop tracking it
|
||||
(for the buffers that are reallocated while
|
||||
a game runs, as the vector bitmap)
|
||||
-------------------------------------------------*/
|
||||
|
||||
void auto_free_ptr(void *ptr)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
for (i = malloc_list_index - 1; i >= 0; i--)
|
||||
if (malloc_list[i].ptr == ptr)
|
||||
{
|
||||
free(ptr);
|
||||
memmove(&malloc_list[i], &malloc_list[i + 1], (malloc_list_index - i - 1) * sizeof(malloc_list[0]));
|
||||
malloc_list_index--;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
auto_bitmap_free - free an auto_bitmap_alloc
|
||||
bitmap before its tag ends
|
||||
-------------------------------------------------*/
|
||||
|
||||
void auto_bitmap_free(struct mame_bitmap *bitmap)
|
||||
{
|
||||
if (!bitmap)
|
||||
return;
|
||||
|
||||
/* the line array was allocated before the safety rows were skipped */
|
||||
auto_free_ptr(bitmap->line - BITMAP_SAFETY);
|
||||
auto_free_ptr(bitmap);
|
||||
}
|
||||
|
||||
|
||||
/*-------------------------------------------------
|
||||
bitmap_alloc - allocate a bitmap at the
|
||||
current screen depth
|
||||
@@ -1051,7 +1067,7 @@ void end_resource_tracking(void)
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
struct chd_file *get_disk_handle(int diskindex)
|
||||
struct hard_disk_file *get_disk_handle(int diskindex)
|
||||
{
|
||||
return disk_handle[diskindex];
|
||||
}
|
||||
@@ -1824,11 +1840,14 @@ static int process_disk_entries(struct rom_load_data *romdata, const struct RomM
|
||||
/* handle files */
|
||||
if (ROMENTRY_ISFILE(romp))
|
||||
{
|
||||
struct chd_file *source, *diff = NULL;
|
||||
struct chd_header header;
|
||||
const struct GameDriver *drv;
|
||||
struct hard_disk_file *disk;
|
||||
mame_file *source = NULL, *diff = NULL;
|
||||
UINT8 *legacydata = NULL;
|
||||
UINT32 legacysize = 0;
|
||||
char filename[1024], *c;
|
||||
char acthash[HASH_BUF_SIZE];
|
||||
int err;
|
||||
char datahash[HASH_BUF_SIZE], imagehash[HASH_BUF_SIZE];
|
||||
const char *error;
|
||||
|
||||
/* make the filename of the source */
|
||||
strcpy(filename, ROM_GETNAME(romp));
|
||||
@@ -1838,83 +1857,114 @@ static int process_disk_entries(struct rom_load_data *romdata, const struct RomM
|
||||
else
|
||||
strcat(filename, ".chd");
|
||||
|
||||
/* first open the source drive */
|
||||
/* look for it in the ROM path, up the chain through the parents */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening disk image: %s\n", filename);
|
||||
source = chd_open(filename, 0, NULL);
|
||||
for (drv = Machine->gamedrv; drv != NULL && source == NULL; drv = drv->clone_of)
|
||||
source = mame_fopen(drv->name, filename, FILETYPE_IMAGE, 0);
|
||||
if (!source)
|
||||
{
|
||||
if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s UNSUPPORTED CHD VERSION\n", filename);
|
||||
else
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s NOT FOUND\n", filename);
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s NOT FOUND\n", filename);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* get the header and extract the MD5/SHA1 */
|
||||
header = *chd_get_header(source);
|
||||
hash_data_clear(acthash);
|
||||
hash_data_insert_binary_checksum(acthash, HASH_MD5, header.md5);
|
||||
hash_data_insert_binary_checksum(acthash, HASH_SHA1, header.sha1);
|
||||
|
||||
/* verify the MD5 */
|
||||
if (!hash_data_is_equal(ROM_GETHASHDATA(romp), acthash, 0))
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s WRONG CHECKSUMS:\n", filename);
|
||||
dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), acthash);
|
||||
romdata->warnings++;
|
||||
}
|
||||
|
||||
/* if not read-only, make the diff file */
|
||||
/* if not read-only, open or create the differencing file */
|
||||
if (!DISK_ISREADONLY(romp))
|
||||
{
|
||||
/* make the filename of the diff */
|
||||
strcpy(filename, ROM_GETNAME(romp));
|
||||
c = strrchr(filename, '.');
|
||||
char diffname[1024];
|
||||
|
||||
strcpy(diffname, ROM_GETNAME(romp));
|
||||
c = strrchr(diffname, '.');
|
||||
if (c)
|
||||
strcpy(c, ".dif");
|
||||
else
|
||||
strcat(filename, ".dif");
|
||||
strcat(diffname, ".dif");
|
||||
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening differencing image: %s\n", diffname);
|
||||
diff = mame_fopen(NULL, diffname, FILETYPE_IMAGE_DIFF, 1);
|
||||
|
||||
/* one made by older versions of the core (a CHD v3): keep its */
|
||||
/* contents to import them, and the file itself as <name>.dif.old */
|
||||
if (diff)
|
||||
{
|
||||
UINT8 tag[8];
|
||||
UINT64 size = mame_fsize(diff);
|
||||
|
||||
mame_fseek(diff, 0, SEEK_SET);
|
||||
if (size >= sizeof(tag) && size < 0x80000000 &&
|
||||
mame_fread(diff, tag, sizeof(tag)) == sizeof(tag) && memcmp(tag, "MComprHD", 8) == 0)
|
||||
{
|
||||
char oldname[1024 + 4];
|
||||
|
||||
legacydata = malloc((size_t)size);
|
||||
if (legacydata)
|
||||
{
|
||||
mame_fseek(diff, 0, SEEK_SET);
|
||||
if (mame_fread(diff, legacydata, (UINT32)size) == size)
|
||||
legacysize = (UINT32)size;
|
||||
else
|
||||
{
|
||||
free(legacydata);
|
||||
legacydata = NULL;
|
||||
}
|
||||
}
|
||||
mame_fclose(diff);
|
||||
|
||||
/* keep the file even if it could not be read, so nothing is lost */
|
||||
sprintf(oldname, "%s.old", diffname);
|
||||
if (osd_rename(FILETYPE_IMAGE_DIFF, diffname, oldname))
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Old-format differencing image kept as %s\n", oldname);
|
||||
else
|
||||
log_cb(RETRO_LOG_WARN, LOGPRE "Old-format differencing image could not be kept as %s\n", oldname);
|
||||
diff = mame_fopen(NULL, diffname, FILETYPE_IMAGE_DIFF, 1);
|
||||
}
|
||||
mame_fseek(diff, 0, SEEK_SET);
|
||||
}
|
||||
|
||||
/* try to open the diff */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening differencing image: %s\n", filename);
|
||||
diff = chd_open(filename, 1, source);
|
||||
if (!diff)
|
||||
{
|
||||
/* didn't work; try creating it instead */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Creating differencing image: %s\n", filename);
|
||||
err = chd_create(filename, 0, 0, CHDCOMPRESSION_NONE, source);
|
||||
if (err != CHDERR_NONE)
|
||||
{
|
||||
if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s UNSUPPORTED CHD VERSION\n", filename);
|
||||
else
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T CREATE DIFF FILE Error code %s\n", filename, chd_error_text[err]);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* open the newly-created diff file */
|
||||
log_cb(RETRO_LOG_INFO, LOGPRE "Opening new differencing image: %s\n", filename);
|
||||
diff = chd_open(filename, 1, source);
|
||||
if (!diff)
|
||||
{
|
||||
if (chd_get_last_error() == CHDERR_UNSUPPORTED_VERSION)
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s UNSUPPORTED CHD VERSION\n", filename);
|
||||
else
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T OPEN DIFF FILE Error code %s\n", filename, chd_error_text[err]);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T OPEN OR CREATE DIFF FILE\n", diffname);
|
||||
free(legacydata);
|
||||
mame_fclose(source);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* open the disk */
|
||||
disk = hard_disk_open(source, diff, &error);
|
||||
if (!disk)
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s: CAN'T OPEN DISK IMAGE (%s)\n", filename, error);
|
||||
free(legacydata);
|
||||
romdata->errors++;
|
||||
romp++;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* bring over what the game wrote with older versions of the core */
|
||||
if (legacydata)
|
||||
{
|
||||
hard_disk_import_legacy_diff(disk, legacydata, legacysize);
|
||||
free(legacydata);
|
||||
}
|
||||
|
||||
/* verify the checksums: older sets list those of the data (the same for */
|
||||
/* every CHD version of a dump), current MAME the one of a v5 image */
|
||||
hard_disk_get_hashes(disk, datahash, imagehash);
|
||||
if (!hash_data_is_equal(ROM_GETHASHDATA(romp), datahash, 0) &&
|
||||
!hash_data_is_equal(ROM_GETHASHDATA(romp), imagehash, 0))
|
||||
{
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%-12s WRONG CHECKSUMS:\n", filename);
|
||||
dump_wrong_and_correct_checksums(romdata, ROM_GETHASHDATA(romp), datahash);
|
||||
romdata->warnings++;
|
||||
}
|
||||
|
||||
/* we're okay, set the handle */
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "Assigning to handle %d\n", DISK_GETINDEX(romp));
|
||||
disk_handle[DISK_GETINDEX(romp)] = DISK_ISREADONLY(romp) ? source : diff;
|
||||
disk_handle[DISK_GETINDEX(romp)] = disk;
|
||||
romp++;
|
||||
}
|
||||
}
|
||||
|
||||
+5
-1
@@ -452,12 +452,16 @@ static INLINE int get_resource_tag(void)
|
||||
|
||||
/* automatically-freeing memory */
|
||||
void *auto_malloc(size_t size);
|
||||
|
||||
/* free one auto_malloc block (or auto bitmap) before its tag ends */
|
||||
void auto_free_ptr(void *ptr);
|
||||
void auto_bitmap_free(struct mame_bitmap *bitmap);
|
||||
char *auto_strdup(const char *str);
|
||||
struct mame_bitmap *auto_bitmap_alloc(int width,int height);
|
||||
struct mame_bitmap *auto_bitmap_alloc_depth(int width,int height,int depth);
|
||||
|
||||
/* disk handling */
|
||||
struct chd_file *get_disk_handle(int diskindex);
|
||||
struct hard_disk_file *get_disk_handle(int diskindex);
|
||||
|
||||
/* ROM processing */
|
||||
int rom_load(const struct RomModule *romp);
|
||||
|
||||
@@ -14699,6 +14699,37 @@ const char *sf_get_ctrl_name(int type)
|
||||
return "";
|
||||
}
|
||||
|
||||
const struct ControlInfo sfrush_ctrl =
|
||||
{
|
||||
false, /* 45_degree_rotation for joystick(s) */
|
||||
false, /* alternating_controls */
|
||||
false, /* mirrored_controls */
|
||||
"Wheel, accelerator and brake on player 1 (the shifter stays in the last gear chosen). Clutch, music and the four track buttons are on player 2.", /* control_details */
|
||||
&sfrush_get_ctrl_name
|
||||
};
|
||||
|
||||
const char *sfrush_get_ctrl_name(int type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case IPT_BUTTON1: return BTN1 "1st Gear / Music";
|
||||
case IPT_BUTTON2: return BTN2 "2nd Gear / Track 1";
|
||||
case IPT_BUTTON3: return BTN3 "3rd Gear / Track 2";
|
||||
case IPT_BUTTON4: return BTN4 "4th Gear / Track 3";
|
||||
case IPT_BUTTON5: return BTN5 "Track 4";
|
||||
case IPT_BUTTON7: return BTN7 "View 1";
|
||||
case IPT_BUTTON8: return BTN8 "View 2";
|
||||
case IPT_BUTTON9: return "B9: View 3";
|
||||
case IPT_BUTTON10: return "B10: Reverse";
|
||||
case IPT_PEDAL: return "Accelerator / Clutch";
|
||||
case IPT_PEDAL2: return "Brake";
|
||||
case IPT_PADDLE: return "Steer Left";
|
||||
case (IPT_PADDLE + IPT_EXTENSION): return "Steer Right";
|
||||
} /* end of switch */
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const struct ControlInfo sfa2_ctrl =
|
||||
{
|
||||
false, /* 45_degree_rotation for joystick(s) */
|
||||
|
||||
@@ -2440,6 +2440,9 @@ const char *stratgyx_get_ctrl_name(int type);
|
||||
extern const struct ControlInfo sf_ctrl;
|
||||
const char *sf_get_ctrl_name(int type);
|
||||
|
||||
extern const struct ControlInfo sfrush_ctrl;
|
||||
const char *sfrush_get_ctrl_name(int type);
|
||||
|
||||
extern const struct ControlInfo sfa2_ctrl;
|
||||
const char *sfa2_get_ctrl_name(int type);
|
||||
|
||||
|
||||
+789
-45
@@ -368,6 +368,27 @@ static void wr_px(INT32 val) { adsp2100.px = val; }
|
||||
static void wr_ifc(INT32 val)
|
||||
{
|
||||
adsp2100.ifc = val;
|
||||
#if (HAS_ADSP2181)
|
||||
if (chip_type == CHIP_TYPE_ADSP2181)
|
||||
{
|
||||
if (val & 0x0002) adsp2100.irq_latch[ADSP2181_IRQ0] = 0;
|
||||
if (val & 0x0004) adsp2100.irq_latch[ADSP2181_IRQ1] = 0;
|
||||
if (val & 0x0008) adsp2100.irq_latch[ADSP2181_BDMA] = 0;
|
||||
if (val & 0x0010) adsp2100.irq_latch[ADSP2181_IRQE] = 0;
|
||||
if (val & 0x0020) adsp2100.irq_latch[ADSP2181_SPORT0_RX] = 0;
|
||||
if (val & 0x0040) adsp2100.irq_latch[ADSP2181_SPORT0_TX] = 0;
|
||||
if (val & 0x0080) adsp2100.irq_latch[ADSP2181_IRQ2] = 0;
|
||||
if (val & 0x0200) adsp2100.irq_latch[ADSP2181_IRQ0] = 1;
|
||||
if (val & 0x0400) adsp2100.irq_latch[ADSP2181_IRQ1] = 1;
|
||||
if (val & 0x0800) adsp2100.irq_latch[ADSP2181_BDMA] = 1;
|
||||
if (val & 0x1000) adsp2100.irq_latch[ADSP2181_IRQE] = 1;
|
||||
if (val & 0x2000) adsp2100.irq_latch[ADSP2181_SPORT0_RX] = 1;
|
||||
if (val & 0x4000) adsp2100.irq_latch[ADSP2181_SPORT0_TX] = 1;
|
||||
if (val & 0x8000) adsp2100.irq_latch[ADSP2181_IRQ2] = 1;
|
||||
check_irqs();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
if (val & 0x002) adsp2100.irq_latch[ADSP2101_IRQ0] = 0;
|
||||
if (val & 0x004) adsp2100.irq_latch[ADSP2101_IRQ1] = 0;
|
||||
if (val & 0x008) adsp2100.irq_latch[ADSP2101_SPORT0_RX] = 0;
|
||||
@@ -384,6 +405,25 @@ static void wr_tx0(INT32 val) { if (sport_tx_callback) (*sport_tx_callback)(0, v
|
||||
static void wr_tx1(INT32 val) { if (sport_tx_callback) (*sport_tx_callback)(1, val); }
|
||||
static void wr_owrctr(INT32 val) { adsp2100.cntr = val & 0x3fff; }
|
||||
static void wr_topstack(INT32 val) { pc_stack_push_val(val & 0x3fff); }
|
||||
/* ADSP-2181: the memory overlay registers (group 1, 14 and 15) */
|
||||
static void wr_pmovlay(INT32 val)
|
||||
{
|
||||
#if (HAS_ADSP2181)
|
||||
if (chip_type == CHIP_TYPE_ADSP2181)
|
||||
adsp2100.pmovlay = val & 0x3fff;
|
||||
#endif
|
||||
}
|
||||
static void wr_dmovlay(INT32 val)
|
||||
{
|
||||
#if (HAS_ADSP2181)
|
||||
if (chip_type == CHIP_TYPE_ADSP2181)
|
||||
{
|
||||
adsp2100.dmovlay = val & 0x3fff;
|
||||
if (dmovlay_callback)
|
||||
(*dmovlay_callback)(adsp2100.dmovlay);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#define WRITE_REG(grp,reg,val) ((*wr_reg[grp][reg])(val))
|
||||
|
||||
@@ -395,7 +435,7 @@ static void (*wr_reg[4][16])(INT32) =
|
||||
},
|
||||
{
|
||||
wr_i0, wr_i1, wr_i2, wr_i3, wr_m0, wr_m1, wr_m2, wr_m3,
|
||||
wr_l0, wr_l1, wr_l2, wr_l3, wr_inval, wr_inval, wr_inval, wr_inval
|
||||
wr_l0, wr_l1, wr_l2, wr_l3, wr_inval, wr_inval, wr_pmovlay, wr_dmovlay
|
||||
},
|
||||
{
|
||||
wr_i4, wr_i5, wr_i6, wr_i7, wr_m4, wr_m5, wr_m6, wr_m7,
|
||||
@@ -469,6 +509,13 @@ static INT32 rd_px(void) { return adsp2100.px; }
|
||||
static INT32 rd_rx0(void) { if (sport_rx_callback) return (*sport_rx_callback)(0); else return 0; }
|
||||
static INT32 rd_rx1(void) { if (sport_rx_callback) return (*sport_rx_callback)(1); else return 0; }
|
||||
static INT32 rd_stacktop(void) { return pc_stack_pop_val(); }
|
||||
#if (HAS_ADSP2181)
|
||||
static INT32 rd_pmovlay(void) { return (chip_type == CHIP_TYPE_ADSP2181) ? adsp2100.pmovlay : 0; }
|
||||
static INT32 rd_dmovlay(void) { return (chip_type == CHIP_TYPE_ADSP2181) ? adsp2100.dmovlay : 0; }
|
||||
#else
|
||||
#define rd_pmovlay rd_inval
|
||||
#define rd_dmovlay rd_inval
|
||||
#endif
|
||||
|
||||
#define READ_REG(grp,reg) ((*rd_reg[grp][reg])())
|
||||
|
||||
@@ -480,7 +527,7 @@ static INT32 (*rd_reg[4][16])(void) =
|
||||
},
|
||||
{
|
||||
rd_i0, rd_i1, rd_i2, rd_i3, rd_m0, rd_m1, rd_m2, rd_m3,
|
||||
rd_l0, rd_l1, rd_l2, rd_l3, rd_inval, rd_inval, rd_inval, rd_inval
|
||||
rd_l0, rd_l1, rd_l2, rd_l3, rd_inval, rd_inval, rd_pmovlay, rd_dmovlay
|
||||
},
|
||||
{
|
||||
rd_i4, rd_i5, rd_i6, rd_i7, rd_m4, rd_m5, rd_m6, rd_m7,
|
||||
@@ -498,16 +545,23 @@ static INT32 (*rd_reg[4][16])(void) =
|
||||
Modulus addressing logic
|
||||
===========================================================================*/
|
||||
|
||||
static INLINE void modify_address(UINT32 ireg, UINT32 mreg)
|
||||
/* index register 'i' plus 'm', kept in its circular buffer; 'wrap14' (a
|
||||
constant, set only in the ADSP-2181 interpreter loop) first keeps the
|
||||
sum to 14 bits, as in current MAME: an index that steps below 0 wraps
|
||||
to the top of memory instead of going out of the address space */
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 dag_step(UINT32 i, INT32 m, UINT32 base, UINT32 l, int wrap14)
|
||||
{
|
||||
UINT32 base = adsp2100.base[ireg];
|
||||
UINT32 i = adsp2100.i[ireg];
|
||||
UINT32 l = adsp2100.l[ireg];
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
i += m;
|
||||
if (wrap14)
|
||||
i &= 0x3fff;
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static INLINE ADSP_ALWAYS_INLINE void modify_address(UINT32 ireg, UINT32 mreg, int wrap14)
|
||||
{
|
||||
adsp2100.i[ireg] = dag_step(adsp2100.i[ireg], adsp2100.m[mreg], adsp2100.base[ireg], adsp2100.l[ireg], wrap14);
|
||||
}
|
||||
|
||||
|
||||
@@ -516,7 +570,7 @@ static INLINE void modify_address(UINT32 ireg, UINT32 mreg)
|
||||
Data memory accessors
|
||||
===========================================================================*/
|
||||
|
||||
static INLINE void data_write_dag1(UINT32 op, INT32 val)
|
||||
static INLINE ADSP_ALWAYS_INLINE void data_write_dag1_f(UINT32 op, INT32 val, int fast)
|
||||
{
|
||||
UINT32 ireg = (op >> 2) & 3;
|
||||
UINT32 mreg = op & 3;
|
||||
@@ -527,19 +581,16 @@ static INLINE void data_write_dag1(UINT32 op, INT32 val)
|
||||
if ( adsp2100.mstat & MSTAT_REVERSE )
|
||||
{
|
||||
UINT32 ir = reverse_table[ i & 0x3fff ];
|
||||
WWORD_DATA(ir, val);
|
||||
WWORD_DATA_F(ir, val, fast);
|
||||
}
|
||||
else
|
||||
WWORD_DATA(i, val);
|
||||
WWORD_DATA_F(i, val, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
}
|
||||
|
||||
|
||||
static INLINE UINT32 data_read_dag1(UINT32 op)
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 data_read_dag1_f(UINT32 op, int fast)
|
||||
{
|
||||
UINT32 ireg = (op >> 2) & 3;
|
||||
UINT32 mreg = op & 3;
|
||||
@@ -551,20 +602,17 @@ static INLINE UINT32 data_read_dag1(UINT32 op)
|
||||
if (adsp2100.mstat & MSTAT_REVERSE)
|
||||
{
|
||||
UINT32 ir = reverse_table[i & 0x3fff];
|
||||
res = RWORD_DATA(ir);
|
||||
res = RWORD_DATA_F(ir, fast);
|
||||
}
|
||||
else
|
||||
res = RWORD_DATA(i);
|
||||
res = RWORD_DATA_F(i, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static INLINE void data_write_dag2(UINT32 op, INT32 val)
|
||||
static INLINE ADSP_ALWAYS_INLINE void data_write_dag2_f(UINT32 op, INT32 val, int fast)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -572,16 +620,13 @@ static INLINE void data_write_dag2(UINT32 op, INT32 val)
|
||||
UINT32 i = adsp2100.i[ireg];
|
||||
UINT32 l = adsp2100.l[ireg];
|
||||
|
||||
WWORD_DATA(i, val);
|
||||
WWORD_DATA_F(i, val, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
}
|
||||
|
||||
|
||||
static INLINE UINT32 data_read_dag2(UINT32 op)
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 data_read_dag2_f(UINT32 op, int fast)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -589,21 +634,25 @@ static INLINE UINT32 data_read_dag2(UINT32 op)
|
||||
UINT32 i = adsp2100.i[ireg];
|
||||
UINT32 l = adsp2100.l[ireg];
|
||||
|
||||
UINT32 res = RWORD_DATA(i);
|
||||
UINT32 res = RWORD_DATA_F(i, fast);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, fast & 2);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/* the interpreter's accessors; 'fast': bit 0 for the recompiler (direct
|
||||
pointers), bit 1 for the ADSP-2181 (14-bit index wrap) */
|
||||
#define data_write_dag1(op, val) data_write_dag1_f(op, val, 0)
|
||||
#define data_read_dag1(op) data_read_dag1_f(op, 0)
|
||||
#define data_write_dag2(op, val) data_write_dag2_f(op, val, 0)
|
||||
#define data_read_dag2(op) data_read_dag2_f(op, 0)
|
||||
|
||||
/*===========================================================================
|
||||
Program memory accessors
|
||||
===========================================================================*/
|
||||
|
||||
static INLINE void pgm_write_dag2(UINT32 op, INT32 val)
|
||||
static INLINE ADSP_ALWAYS_INLINE void pgm_write_dag2(UINT32 op, INT32 val, int wrap14)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -613,14 +662,11 @@ static INLINE void pgm_write_dag2(UINT32 op, INT32 val)
|
||||
|
||||
WWORD_PGM(i, (val << 8) | adsp2100.px);
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, wrap14);
|
||||
}
|
||||
|
||||
|
||||
static INLINE UINT32 pgm_read_dag2(UINT32 op)
|
||||
static INLINE ADSP_ALWAYS_INLINE UINT32 pgm_read_dag2(UINT32 op, int wrap14)
|
||||
{
|
||||
UINT32 ireg = 4 + ((op >> 2) & 3);
|
||||
UINT32 mreg = 4 + (op & 3);
|
||||
@@ -633,10 +679,7 @@ static INLINE UINT32 pgm_read_dag2(UINT32 op)
|
||||
adsp2100.px = res;
|
||||
res >>= 8;
|
||||
|
||||
i += adsp2100.m[mreg];
|
||||
if (i < base) i += l;
|
||||
else if (i >= base + l) i -= l;
|
||||
adsp2100.i[ireg] = i;
|
||||
adsp2100.i[ireg] = dag_step(i, adsp2100.m[mreg], base, l, wrap14);
|
||||
|
||||
return res;
|
||||
}
|
||||
@@ -1326,6 +1369,707 @@ void mac_op_mf(int op)
|
||||
|
||||
|
||||
|
||||
#if (HAS_ADSP2181)
|
||||
|
||||
/*===========================================================================
|
||||
ADSP-2181 only: ALU with a constant as Y, ALU with no result (NONE =),
|
||||
MAC with X as both operands (X * X); the operations above, with
|
||||
the other operand
|
||||
===========================================================================*/
|
||||
|
||||
static const INT32 alu_constants[32] =
|
||||
{
|
||||
0x0001, 0xfffe, 0x0002, 0xfffd, 0x0004, 0xfffb, 0x0008, 0xfff7,
|
||||
0x0010, 0xffef, 0x0020, 0xffdf, 0x0040, 0xffbf, 0x0080, 0xff7f,
|
||||
0x0100, 0xfeff, 0x0200, 0xfdff, 0x0400, 0xfbff, 0x0800, 0xf7ff,
|
||||
0x1000, 0xefff, 0x2000, 0xdfff, 0x4000, 0xbfff, 0x8000, 0x7fff
|
||||
};
|
||||
|
||||
static void alu_op_ar_const(int op)
|
||||
{
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop = alu_constants[((op >> 5) & 7) | (((op >> 11) & 3) << 3)];
|
||||
INT32 res;
|
||||
|
||||
/*switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* Y Clear when y = 0 */
|
||||
res = yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x01<<13:
|
||||
/* Y + 1 PASS 1 when y = 0 */
|
||||
res = yop + 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x7fff) SET_V;
|
||||
else if (yop == 0xffff) SET_C;
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* X + Y + C */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop += GET_C >> 3;
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* X + Y X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* NOT Y */
|
||||
res = yop ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* -Y */
|
||||
res = -yop;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X - Y + C - 1 X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X - Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* Y - 1 PASS -1 when y = 0 */
|
||||
res = yop - 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
else if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* Y - X -X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* Y - X + C - 1 -X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* NOT X */
|
||||
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* X AND Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop & yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* X OR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop | yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* X XOR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop ^ yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* ABS X */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = (xop & 0x8000) ? -xop : xop;
|
||||
if (xop == 0) SET_Z;
|
||||
if (xop == 0x8000) SET_N, SET_V;
|
||||
CLR_S;
|
||||
if (xop & 0x8000) SET_S;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* saturate */
|
||||
if ((adsp2100.mstat & MSTAT_SATURATE) && GET_V) res = GET_C ? -32768 : 32767;
|
||||
|
||||
/* set the final value */
|
||||
adsp2100.core.ar.u = res;
|
||||
}
|
||||
|
||||
static void alu_op_af_const(int op)
|
||||
{
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop = alu_constants[((op >> 5) & 7) | (((op >> 11) & 3) << 3)];
|
||||
INT32 res;
|
||||
|
||||
/* switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* Y Clear when y = 0 */
|
||||
res = yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x01<<13:
|
||||
/* Y + 1 PASS 1 when y = 0 */
|
||||
res = yop + 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x7fff) SET_V;
|
||||
else if (yop == 0xffff) SET_C;
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* X + Y + C */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop += GET_C >> 3;
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* X + Y X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* NOT Y */
|
||||
res = yop ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* -Y */
|
||||
res = -yop;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X - Y + C - 1 X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X - Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop - yop;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* Y - 1 PASS -1 when y = 0 */
|
||||
res = yop - 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
else if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* Y - X -X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* Y - X + C - 1 -X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = yop - xop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* NOT X */
|
||||
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* X AND Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop & yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* X OR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop | yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* X XOR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = xop ^ yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* ABS X */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = (xop & 0x8000) ? -xop : xop;
|
||||
if (xop == 0) SET_Z;
|
||||
if (xop == 0x8000) SET_N, SET_V;
|
||||
CLR_S;
|
||||
if (xop & 0x8000) SET_S;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the final value */
|
||||
adsp2100.core.af.u = res;
|
||||
}
|
||||
|
||||
static void alu_op_none(int op)
|
||||
{
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop = (op >> 11) & 3;
|
||||
INT32 res;
|
||||
|
||||
/*switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* Y Clear when y = 0 */
|
||||
res = ALU_GETYREG_UNSIGNED(yop);
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x01<<13:
|
||||
/* Y + 1 PASS 1 when y = 0 */
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop + 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x7fff) SET_V;
|
||||
else if (yop == 0xffff) SET_C;
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* X + Y + C */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
yop += GET_C >> 3;
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* X + Y X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop + yop;
|
||||
CALC_NZVC(xop, yop, res);
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* NOT Y */
|
||||
res = ALU_GETYREG_UNSIGNED(yop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* -Y */
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = -yop;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X - Y + C - 1 X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop - yop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X - Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop - yop;
|
||||
CALC_NZVC_SUB(xop, yop, res);
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* Y - 1 PASS -1 when y = 0 */
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop - 1;
|
||||
CALC_NZ(res);
|
||||
if (yop == 0x8000) SET_V;
|
||||
else if (yop == 0x0000) SET_C;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* Y - X -X when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop - xop;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* Y - X + C - 1 -X + C - 1 when y = 0 */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = yop - xop + (GET_C >> 3) - 1;
|
||||
CALC_NZVC_SUB(yop, xop, res);
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* NOT X */
|
||||
res = ALU_GETXREG_UNSIGNED(xop) ^ 0xffff;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* X AND Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop & yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* X OR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop | yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* X XOR Y */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
yop = ALU_GETYREG_UNSIGNED(yop);
|
||||
res = xop ^ yop;
|
||||
CALC_NZ(res);
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* ABS X */
|
||||
xop = ALU_GETXREG_UNSIGNED(xop);
|
||||
res = (xop & 0x8000) ? -xop : xop;
|
||||
if (xop == 0) SET_Z;
|
||||
if (xop == 0x8000) SET_N, SET_V;
|
||||
CLR_S;
|
||||
if (xop & 0x8000) SET_S;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* no result: only the flags */
|
||||
(void)res;
|
||||
}
|
||||
|
||||
static void mac_op_mr_xop(int op)
|
||||
{
|
||||
INT8 shift = ((adsp2100.mstat & MSTAT_INTEGER) >> 4) ^ 1;
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop;
|
||||
INT32 temp;
|
||||
INT64 res;
|
||||
|
||||
/* switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* no-op */
|
||||
return;
|
||||
case 0x01<<13:
|
||||
/* X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* MR + X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* MR - X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* X * Y (SS) Clear when y = 0 */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* MR + X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* MR + X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* MR + X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* MR + X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* MR - X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* MR - X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* MR - X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* MR - X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the final value */
|
||||
temp = (res >> 31) & 0x1ff;
|
||||
CLR_MV;
|
||||
if (temp != 0x000 && temp != 0x1ff) SET_MV;
|
||||
adsp2100.core.mr.mr = res;
|
||||
}
|
||||
|
||||
static void mac_op_mf_xop(int op)
|
||||
{
|
||||
INT8 shift = ((adsp2100.mstat & MSTAT_INTEGER) >> 4) ^ 1;
|
||||
INT32 xop = (op >> 8) & 7;
|
||||
INT32 yop;
|
||||
INT32 temp;
|
||||
INT64 res;
|
||||
|
||||
/* switch ((op >> 13) & 15)*/
|
||||
switch (op & (15<<13)) /*JB*/
|
||||
{
|
||||
case 0x00<<13:
|
||||
/* no-op */
|
||||
return;
|
||||
case 0x01<<13:
|
||||
/* X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x02<<13:
|
||||
/* MR + X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x03<<13:
|
||||
/* MR - X * Y (RND) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
#ifdef ADSP_TWEAK
|
||||
if ((res & 0xffff) == 0x8000) res &= ~((UINT64)0x10000);
|
||||
else res += (res & 0x8000) << 1;
|
||||
#else
|
||||
temp &= 0xffff;
|
||||
res += 0x8000;
|
||||
if ( temp == 0x8000 )
|
||||
res &= ~((UINT64)0x10000);
|
||||
#endif
|
||||
break;
|
||||
case 0x04<<13:
|
||||
/* X * Y (SS) Clear when y = 0 */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x05<<13:
|
||||
/* X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x06<<13:
|
||||
/* X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x07<<13:
|
||||
/* X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = (INT64)temp;
|
||||
break;
|
||||
case 0x08<<13:
|
||||
/* MR + X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x09<<13:
|
||||
/* MR + X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0a<<13:
|
||||
/* MR + X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0b<<13:
|
||||
/* MR + X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr + (INT64)temp;
|
||||
break;
|
||||
case 0x0c<<13:
|
||||
/* MR - X * Y (SS) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0d<<13:
|
||||
/* MR - X * Y (SU) */
|
||||
xop = MAC_GETXREG_SIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0e<<13:
|
||||
/* MR - X * Y (US) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
case 0x0f<<13:
|
||||
/* MR - X * Y (UU) */
|
||||
xop = MAC_GETXREG_UNSIGNED(xop);
|
||||
yop = xop;
|
||||
temp = (xop * yop) << shift;
|
||||
res = adsp2100.core.mr.mr - (INT64)temp;
|
||||
break;
|
||||
default:
|
||||
res = 0; /* just to keep the compiler happy */
|
||||
break;
|
||||
}
|
||||
|
||||
/* set the final value */
|
||||
adsp2100.core.mf.u = (UINT32)res >> 16;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*===========================================================================
|
||||
SHIFT operations (result in SR/SE/SB)
|
||||
===========================================================================*/
|
||||
|
||||
+1201
-686
File diff suppressed because it is too large.
Load diff
@@ -92,6 +92,13 @@ extern unsigned adsp2100_get_reg(int regnum);
|
||||
extern void adsp2100_set_reg(int regnum, unsigned val);
|
||||
extern void adsp2100_set_irq_line(int irqline, int state);
|
||||
extern void adsp2100_set_irq_callback(int (*callback)(int irqline));
|
||||
/* exact skip of one-instruction NOP delay loops: off unless a driver enables it */
|
||||
extern void adsp2100_set_nop_loop_skip(int enable);
|
||||
/* optional recompiler (adsp2100jit.c): off unless a driver enables it */
|
||||
extern int adsp2100_jit_available(void);
|
||||
extern void adsp2100_set_jit(int enable);
|
||||
/* data memory words [start, end] read through a handler with no side effects */
|
||||
extern void adsp2100_jit_pure_read(UINT32 start, UINT32 end);
|
||||
extern const char *adsp2100_info(void *context, int regnum);
|
||||
extern unsigned adsp2100_dasm(char *buffer, unsigned pc);
|
||||
|
||||
@@ -262,4 +269,56 @@ extern void adsp2115_set_tx_callback( TX_CALLBACK cb );
|
||||
extern void adsp2115_load_boot_data(data8_t *srcdata, data32_t *dstdata);
|
||||
#endif
|
||||
|
||||
#if (HAS_ADSP2181)
|
||||
/**************************************************************************
|
||||
* ADSP2181 section
|
||||
*
|
||||
* 16K words of program RAM and 16K words of data RAM on the chip: the
|
||||
* driver maps them (program memory at ADSP2181_PGM_OFFSET, data memory
|
||||
* at ADSP2181_DATA_OFFSET), with its control registers at 0x3fe0-0x3fff
|
||||
* of data memory. The I/O space (IO(x) instructions) and the data memory
|
||||
* overlay (DMOVLAY) go through the callbacks below
|
||||
**************************************************************************/
|
||||
|
||||
#define ADSP2181_DATA_OFFSET ADSP2100_DATA_OFFSET
|
||||
#define ADSP2181_PGM_OFFSET ADSP2100_PGM_OFFSET
|
||||
#define ADSP2181_SIZE ADSP2100_SIZE
|
||||
|
||||
#define adsp2181_icount adsp2100_icount
|
||||
|
||||
#define ADSP2181_IRQ0 0 /* IRQ0 */
|
||||
#define ADSP2181_SPORT1_RX 0 /* SPORT1 receive IRQ */
|
||||
#define ADSP2181_IRQ1 1 /* IRQ1 */
|
||||
#define ADSP2181_SPORT1_TX 1 /* SPORT1 transmit IRQ */
|
||||
#define ADSP2181_IRQ2 2 /* IRQ2 */
|
||||
#define ADSP2181_SPORT0_RX 3 /* SPORT0 receive IRQ */
|
||||
#define ADSP2181_SPORT0_TX 4 /* SPORT0 transmit IRQ */
|
||||
#define ADSP2181_TIMER 5 /* internal timer IRQ */
|
||||
#define ADSP2181_IRQE 6 /* IRQE */
|
||||
#define ADSP2181_BDMA 7 /* BDMA */
|
||||
#define ADSP2181_IRQL1 8 /* IRQL1 */
|
||||
#define ADSP2181_IRQL0 9 /* IRQL0 */
|
||||
|
||||
typedef UINT16 (*ADSP2181_IO_READ)( UINT32 offset );
|
||||
typedef void (*ADSP2181_IO_WRITE)( UINT32 offset, UINT16 data );
|
||||
typedef void (*ADSP2181_DMOVLAY)( UINT32 dmovlay );
|
||||
|
||||
extern void adsp2181_init(void);
|
||||
extern void adsp2181_reset(void *param);
|
||||
extern void adsp2181_exit(void);
|
||||
extern int adsp2181_execute(int cycles);
|
||||
extern unsigned adsp2181_get_context(void *dst);
|
||||
extern void adsp2181_set_context(void *src);
|
||||
extern unsigned adsp2181_get_reg(int regnum);
|
||||
extern void adsp2181_set_reg(int regnum, unsigned val);
|
||||
extern void adsp2181_set_irq_line(int irqline, int state);
|
||||
extern void adsp2181_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *adsp2181_info(void *context, int regnum);
|
||||
extern unsigned adsp2181_dasm(char *buffer, unsigned pc);
|
||||
extern void adsp2181_set_rx_callback( RX_CALLBACK cb );
|
||||
extern void adsp2181_set_tx_callback( TX_CALLBACK cb );
|
||||
extern void adsp2181_set_io_callbacks( ADSP2181_IO_READ rd, ADSP2181_IO_WRITE wr );
|
||||
extern void adsp2181_set_dmovlay_callback( ADSP2181_DMOVLAY cb );
|
||||
#endif
|
||||
|
||||
#endif /* _ADSP2100_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,235 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* arm7.c
|
||||
* Portable CPU Emulator for 32-bit ARM v3/4/5/6
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
* Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz.
|
||||
*
|
||||
* - This source code is released as freeware for non-commercial purposes.
|
||||
* - You are free to use and redistribute this code in modified or
|
||||
* unmodified form, provided you list me in the credits.
|
||||
* - If you modify this source code, you must add a notice to each modified
|
||||
* source file that it has been changed. If you're a nice person, you
|
||||
* will clearly mark each change too. :)
|
||||
* - If you wish to use this for commercial purposes, please contact me at
|
||||
* sellenoff@hotmail.com
|
||||
* - The author of this copywritten work reserves the right to change the
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* This work is based on:
|
||||
* #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
|
||||
* #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
|
||||
*
|
||||
*****************************************************************************
|
||||
|
||||
mame2003-plus: modified. The core files (arm7core.c/h, arm7exec.c) are
|
||||
those of MAME 0.139, with the memory accesses going through this
|
||||
version's 32-bit little endian memory system (cpu_readmem32ledw...) and
|
||||
the state in one static structure; this file is the cpu interface of
|
||||
this version. ARMv4T (ARM7TDMI): no MMU, no coprocessors.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "arm7.h"
|
||||
#include "arm7core.h"
|
||||
|
||||
#define LOG(x) logerror x
|
||||
#define fatalerror logerror
|
||||
#define ENDIANNESS_BIG 1
|
||||
|
||||
/* the memory handlers of the core (arm7core.c) */
|
||||
#define READ8(addr) arm7_cpu_read8(cpustate, addr)
|
||||
#define WRITE8(addr,data) arm7_cpu_write8(cpustate, addr,data)
|
||||
#define READ16(addr) arm7_cpu_read16(cpustate, addr)
|
||||
#define WRITE16(addr,data) arm7_cpu_write16(cpustate, addr,data)
|
||||
#define READ32(addr) arm7_cpu_read32(cpustate, addr)
|
||||
#define WRITE32(addr,data) arm7_cpu_write32(cpustate, addr,data)
|
||||
#define PTR_READ32 &arm7_cpu_read32
|
||||
#define PTR_WRITE32 &arm7_cpu_write32
|
||||
|
||||
#define ARM7REG(reg) cpustate->sArmRegister[reg]
|
||||
#define ARM7_ICOUNT arm7_ICount
|
||||
|
||||
static arm_state arm7_state;
|
||||
int arm7_ICount;
|
||||
|
||||
/* the core's inline functions are local to this file */
|
||||
#undef INLINE
|
||||
#if defined( _MSC_VER )
|
||||
#define INLINE static __inline
|
||||
#elif defined( __GNUC__ )
|
||||
#define INLINE static __inline__
|
||||
#else
|
||||
#define INLINE static
|
||||
#endif
|
||||
|
||||
/* ARMv5 helpers the core refers to (CLZ, QADD...): not reached on the ARMv4T */
|
||||
INLINE UINT32 count_leading_zeros(UINT32 val)
|
||||
{
|
||||
UINT32 count = 0;
|
||||
if (val == 0)
|
||||
return 32;
|
||||
while (!(val & 0x80000000))
|
||||
{
|
||||
count++;
|
||||
val <<= 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
INLINE INT64 saturate_qbit_overflow(arm_state *cpustate, INT64 res)
|
||||
{
|
||||
if (res > 2147483647) /* INT32_MAX */
|
||||
{
|
||||
res = 2147483647;
|
||||
SET_CPSR(GET_CPSR | Q_MASK);
|
||||
}
|
||||
else if (res < (-2147483647-1)) /* INT32_MIN */
|
||||
{
|
||||
res = (-2147483647-1);
|
||||
SET_CPSR(GET_CPSR | Q_MASK);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* no MMU on the ARM7TDMI: the core only calls this when one is enabled */
|
||||
INLINE UINT32 arm7_tlb_translate(arm_state *cpustate, UINT32 vaddr)
|
||||
{
|
||||
return vaddr;
|
||||
}
|
||||
|
||||
#include "arm7core.c"
|
||||
|
||||
void arm7_init(void)
|
||||
{
|
||||
arm_state *cpustate = &arm7_state;
|
||||
|
||||
memset(cpustate, 0, sizeof(*cpustate));
|
||||
cpustate->archRev = 4;
|
||||
cpustate->archFlags = eARM_ARCHFLAGS_T;
|
||||
arm7_core_init(cpustate, "arm7", cpu_getactivecpu());
|
||||
}
|
||||
|
||||
void arm7_reset(void *param)
|
||||
{
|
||||
arm7_core_reset(&arm7_state);
|
||||
}
|
||||
|
||||
void arm7_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int arm7_execute(int cycles)
|
||||
{
|
||||
arm7_ICount = cycles;
|
||||
#include "arm7exec.c"
|
||||
return cycles - arm7_ICount;
|
||||
}
|
||||
|
||||
unsigned arm7_get_context(void *dst)
|
||||
{
|
||||
if (dst)
|
||||
memcpy(dst, &arm7_state, sizeof(arm7_state));
|
||||
return sizeof(arm7_state);
|
||||
}
|
||||
|
||||
void arm7_set_context(void *src)
|
||||
{
|
||||
if (src)
|
||||
memcpy(&arm7_state, src, sizeof(arm7_state));
|
||||
}
|
||||
|
||||
unsigned arm7_get_reg(int regnum)
|
||||
{
|
||||
arm_state *cpustate = &arm7_state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case ARM7_PC: return R15;
|
||||
case REG_SP: return GetRegister(cpustate, 13);
|
||||
case REG_PREVIOUSPC: return 0;
|
||||
case ARM7_CPSR: return GET_CPSR;
|
||||
}
|
||||
if (regnum >= ARM7_R0 && regnum <= ARM7_R15)
|
||||
return GetRegister(cpustate, regnum - ARM7_R0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void arm7_set_reg(int regnum, unsigned val)
|
||||
{
|
||||
arm_state *cpustate = &arm7_state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case ARM7_PC: R15 = val; return;
|
||||
case REG_SP: SetRegister(cpustate, 13, val); return;
|
||||
case ARM7_CPSR: SET_CPSR(val); return;
|
||||
}
|
||||
if (regnum >= ARM7_R0 && regnum <= ARM7_R15)
|
||||
SetRegister(cpustate, regnum - ARM7_R0, val);
|
||||
}
|
||||
|
||||
void arm7_set_irq_line(int irqline, int state)
|
||||
{
|
||||
arm7_core_set_irq_line(&arm7_state, irqline, state);
|
||||
}
|
||||
|
||||
void arm7_set_irq_callback(int (*callback)(int irqline))
|
||||
{
|
||||
arm7_state.irq_callback = callback;
|
||||
}
|
||||
|
||||
const char *arm7_info(void *context, int regnum)
|
||||
{
|
||||
static char buffer[16][64];
|
||||
static int which = 0;
|
||||
arm_state *cpustate = context ? (arm_state *)context : &arm7_state;
|
||||
|
||||
which = (which + 1) % 16;
|
||||
buffer[which][0] = '\0';
|
||||
|
||||
if (regnum >= CPU_INFO_REG + ARM7_R0 && regnum <= CPU_INFO_REG + ARM7_R15)
|
||||
{
|
||||
sprintf(buffer[which], "R%-3d:%08x", regnum - CPU_INFO_REG - ARM7_R0, GetRegister(cpustate, regnum - CPU_INFO_REG - ARM7_R0));
|
||||
return buffer[which];
|
||||
}
|
||||
switch (regnum)
|
||||
{
|
||||
case CPU_INFO_REG + ARM7_PC: sprintf(buffer[which], "PC :%08x", R15); break;
|
||||
case CPU_INFO_REG + ARM7_CPSR: sprintf(buffer[which], "CPSR:%08x", GET_CPSR); break;
|
||||
case CPU_INFO_FLAGS:
|
||||
sprintf(buffer[which], "%c%c%c%c%c%c%c %s",
|
||||
(GET_CPSR & N_MASK) ? 'N' : '-',
|
||||
(GET_CPSR & Z_MASK) ? 'Z' : '-',
|
||||
(GET_CPSR & C_MASK) ? 'C' : '-',
|
||||
(GET_CPSR & V_MASK) ? 'V' : '-',
|
||||
(GET_CPSR & I_MASK) ? 'I' : '-',
|
||||
(GET_CPSR & F_MASK) ? 'F' : '-',
|
||||
(GET_CPSR & T_MASK) ? 'T' : '-',
|
||||
GetModeText(GET_CPSR));
|
||||
break;
|
||||
case CPU_INFO_NAME: return "ARM7";
|
||||
case CPU_INFO_FAMILY: return "Acorn Risc Machine";
|
||||
case CPU_INFO_VERSION: return "2.0 (MAME 0.139 core)";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "Copyright Steve Ellenoff, [email protected]";
|
||||
}
|
||||
return buffer[which];
|
||||
}
|
||||
|
||||
unsigned arm7_dasm(char *buffer, unsigned pc)
|
||||
{
|
||||
if (T_IS_SET(arm7_state.sArmRegister[eCPSR]))
|
||||
{
|
||||
sprintf(buffer, "$%04x", cpu_readmem32ledw_word(pc & ~1));
|
||||
return 2;
|
||||
}
|
||||
sprintf(buffer, "$%08x", cpu_readmem32ledw_dword(pc & ~3));
|
||||
return 4;
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* arm7.h
|
||||
* Portable ARM7TDMI CPU Emulator
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
* Thumb, DSP, and MMU support and many bugfixes by R. Belmont and Ryan Holtz.
|
||||
* (see arm7core.c for the full notice)
|
||||
*
|
||||
* mame2003-plus: the MAME 0.139 core with the cpu interface of this
|
||||
* version (one ARM7 at a time, 32-bit little endian bus).
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef ARM7_H
|
||||
#define ARM7_H
|
||||
|
||||
#include "driver.h"
|
||||
|
||||
/* interrupt lines and exceptions */
|
||||
#define ARM7_IRQ_LINE 0
|
||||
#define ARM7_FIRQ_LINE 1
|
||||
#define ARM7_ABORT_EXCEPTION 2
|
||||
#define ARM7_ABORT_PREFETCH_EXCEPTION 3
|
||||
#define ARM7_UNDEFINE_EXCEPTION 4
|
||||
|
||||
|
||||
extern int arm7_ICount;
|
||||
|
||||
extern void arm7_init(void);
|
||||
extern void arm7_reset(void *param);
|
||||
extern void arm7_exit(void);
|
||||
extern int arm7_execute(int cycles);
|
||||
extern unsigned arm7_get_context(void *dst);
|
||||
extern void arm7_set_context(void *src);
|
||||
extern unsigned arm7_get_reg(int regnum);
|
||||
extern void arm7_set_reg(int regnum, unsigned val);
|
||||
extern void arm7_set_irq_line(int irqline, int state);
|
||||
extern void arm7_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *arm7_info(void *context, int regnum);
|
||||
extern unsigned arm7_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif /* ARM7_H */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,488 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* arm7core.h
|
||||
* Portable ARM7TDMI Core Emulator
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
*
|
||||
* - This source code is released as freeware for non-commercial purposes.
|
||||
* - You are free to use and redistribute this code in modified or
|
||||
* unmodified form, provided you list me in the credits.
|
||||
* - If you modify this source code, you must add a notice to each modified
|
||||
* source file that it has been changed. If you're a nice person, you
|
||||
* will clearly mark each change too. :)
|
||||
* - If you wish to use this for commercial purposes, please contact me at
|
||||
* sellenoff@hotmail.com
|
||||
* - The author of this copywritten work reserves the right to change the
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* This work is based on:
|
||||
* #1) 'Atmel Corporation ARM7TDMI (Thumb) Datasheet - January 1999'
|
||||
* #2) Arm 2/3/6 emulator By Bryan McPhail (bmcphail@tendril.co.uk) and Phil Stroffolino (MAME CORE 0.76)
|
||||
*
|
||||
*****************************************************************************
|
||||
|
||||
This file contains everything related to the arm7 core itself, and is presumed
|
||||
to be cpu implementation non-specific, ie, applies to only the core.
|
||||
|
||||
******************************************************************************/
|
||||
|
||||
|
||||
#ifndef __ARM7CORE_H__
|
||||
#define __ARM7CORE_H__
|
||||
|
||||
|
||||
/****************************************************************************************************
|
||||
* INTERRUPT LINES/EXCEPTIONS
|
||||
***************************************************************************************************/
|
||||
/* ARM7_IRQ_LINE .. ARM7_UNDEFINE_EXCEPTION: in arm7.h */
|
||||
#define ARM7_NUM_LINES 5
|
||||
/* Really there's only 1 ABORT Line.. and cpu decides whether it's during data fetch or prefetch, but we let the user specify */
|
||||
|
||||
/****************************************************************************************************
|
||||
* ARM7 CORE REGISTERS
|
||||
***************************************************************************************************/
|
||||
enum
|
||||
{
|
||||
ARM7_PC = 0,
|
||||
ARM7_R0, ARM7_R1, ARM7_R2, ARM7_R3, ARM7_R4, ARM7_R5, ARM7_R6, ARM7_R7,
|
||||
ARM7_R8, ARM7_R9, ARM7_R10, ARM7_R11, ARM7_R12, ARM7_R13, ARM7_R14, ARM7_R15,
|
||||
ARM7_FR8, ARM7_FR9, ARM7_FR10, ARM7_FR11, ARM7_FR12, ARM7_FR13, ARM7_FR14,
|
||||
ARM7_IR13, ARM7_IR14, ARM7_SR13, ARM7_SR14, ARM7_FSPSR, ARM7_ISPSR, ARM7_SSPSR,
|
||||
ARM7_CPSR, ARM7_AR13, ARM7_AR14, ARM7_ASPSR, ARM7_UR13, ARM7_UR14, ARM7_USPSR
|
||||
};
|
||||
|
||||
/* There are 36 Unique - 32 bit processor registers */
|
||||
/* Each mode has 17 registers (except user & system, which have 16) */
|
||||
/* This is a list of each *unique* register */
|
||||
enum
|
||||
{
|
||||
/* All modes have the following */
|
||||
eR0 = 0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13, /* Stack Pointer */
|
||||
eR14, /* Link Register (holds return address) */
|
||||
eR15, /* Program Counter */
|
||||
eCPSR, /* Current Status Program Register */
|
||||
|
||||
/* Fast Interrupt - Bank switched registers */
|
||||
eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ, eR13_FIQ, eR14_FIQ, eSPSR_FIQ,
|
||||
|
||||
/* IRQ - Bank switched registers */
|
||||
eR13_IRQ, eR14_IRQ, eSPSR_IRQ,
|
||||
|
||||
/* Supervisor/Service Mode - Bank switched registers */
|
||||
eR13_SVC, eR14_SVC, eSPSR_SVC,
|
||||
|
||||
/* Abort Mode - Bank switched registers */
|
||||
eR13_ABT, eR14_ABT, eSPSR_ABT,
|
||||
|
||||
/* Undefined Mode - Bank switched registers */
|
||||
eR13_UND, eR14_UND, eSPSR_UND,
|
||||
|
||||
kNumRegisters
|
||||
};
|
||||
|
||||
/* Coprocessor-related macros */
|
||||
#define COPRO_TLB_BASE cpustate->tlbBase
|
||||
#define COPRO_TLB_BASE_MASK 0xffffc000
|
||||
#define COPRO_TLB_VADDR_FLTI_MASK 0xfff00000
|
||||
#define COPRO_TLB_VADDR_FLTI_MASK_SHIFT 18
|
||||
#define COPRO_TLB_VADDR_CSLTI_MASK 0x000ff000
|
||||
#define COPRO_TLB_VADDR_CSLTI_MASK_SHIFT 10
|
||||
#define COPRO_TLB_VADDR_FSLTI_MASK 0x000ffc00
|
||||
#define COPRO_TLB_VADDR_FSLTI_MASK_SHIFT 8
|
||||
#define COPRO_TLB_CFLD_ADDR_MASK 0xfffffc00
|
||||
#define COPRO_TLB_CFLD_ADDR_MASK_SHIFT 10
|
||||
#define COPRO_TLB_SECTION_PAGE_MASK 0xfff00000
|
||||
#define COPRO_TLB_LARGE_PAGE_MASK 0xffff0000
|
||||
#define COPRO_TLB_SMALL_PAGE_MASK 0xfffff000
|
||||
#define COPRO_TLB_TINY_PAGE_MASK 0xfffffc00
|
||||
#define COPRO_TLB_UNMAPPED 0
|
||||
#define COPRO_TLB_LARGE_PAGE 1
|
||||
#define COPRO_TLB_SMALL_PAGE 2
|
||||
#define COPRO_TLB_TINY_PAGE 3
|
||||
#define COPRO_TLB_COARSE_TABLE 1
|
||||
#define COPRO_TLB_SECTION_TABLE 2
|
||||
#define COPRO_TLB_FINE_TABLE 3
|
||||
|
||||
#define COPRO_CTRL cpustate->control
|
||||
#define COPRO_CTRL_MMU_EN 0x00000001
|
||||
#define COPRO_CTRL_ADDRFAULT_EN 0x00000002
|
||||
#define COPRO_CTRL_DCACHE_EN 0x00000004
|
||||
#define COPRO_CTRL_WRITEBUF_EN 0x00000008
|
||||
#define COPRO_CTRL_ENDIAN 0x00000080
|
||||
#define COPRO_CTRL_SYSTEM 0x00000100
|
||||
#define COPRO_CTRL_ROM 0x00000200
|
||||
#define COPRO_CTRL_ICACHE_EN 0x00001000
|
||||
#define COPRO_CTRL_INTVEC_ADJUST 0x00002000
|
||||
#define COPRO_CTRL_ADDRFAULT_EN_SHIFT 1
|
||||
#define COPRO_CTRL_DCACHE_EN_SHIFT 2
|
||||
#define COPRO_CTRL_WRITEBUF_EN_SHIFT 3
|
||||
#define COPRO_CTRL_ENDIAN_SHIFT 7
|
||||
#define COPRO_CTRL_SYSTEM_SHIFT 8
|
||||
#define COPRO_CTRL_ROM_SHIFT 9
|
||||
#define COPRO_CTRL_ICACHE_EN_SHIFT 12
|
||||
#define COPRO_CTRL_INTVEC_ADJUST_SHIFT 13
|
||||
#define COPRO_CTRL_LITTLE_ENDIAN 0
|
||||
#define COPRO_CTRL_BIG_ENDIAN 1
|
||||
#define COPRO_CTRL_INTVEC_0 0
|
||||
#define COPRO_CTRL_INTVEC_F 1
|
||||
#define COPRO_CTRL_MASK 0x0000338f
|
||||
|
||||
/* Coprocessor Registers */
|
||||
#define ARM7COPRO_REGS \
|
||||
UINT32 control; \
|
||||
UINT32 tlbBase;
|
||||
|
||||
enum
|
||||
{
|
||||
eARM_ARCHFLAGS_T = 1, /* Thumb present */
|
||||
eARM_ARCHFLAGS_E = 2, /* extended DSP operations present (only for v5+) */
|
||||
eARM_ARCHFLAGS_J = 4, /* "Jazelle" (direct execution of Java bytecode) */
|
||||
eARM_ARCHFLAGS_MMU = 8, /* has on-board MMU (traditional ARM style like the SA1110) */
|
||||
eARM_ARCHFLAGS_SA = 16, /* StrongARM extensions (enhanced TLB) */
|
||||
eARM_ARCHFLAGS_XSCALE = 32 /* XScale extensions (CP14, enhanced TLB) */
|
||||
};
|
||||
|
||||
#define ARM7CORE_REGS \
|
||||
UINT32 sArmRegister[kNumRegisters]; \
|
||||
UINT8 pendingIrq; \
|
||||
UINT8 pendingFiq; \
|
||||
UINT8 pendingAbtD; \
|
||||
UINT8 pendingAbtP; \
|
||||
UINT8 pendingUnd; \
|
||||
UINT8 pendingSwi; \
|
||||
INT32 iCount; \
|
||||
int endian; \
|
||||
int (*irq_callback)(int irqline);
|
||||
|
||||
|
||||
/* CPU state struct */
|
||||
typedef struct
|
||||
{
|
||||
ARM7CORE_REGS /* these must be included in your cpu specific register implementation */
|
||||
ARM7COPRO_REGS
|
||||
|
||||
UINT8 archRev; /* ARM architecture revision (3, 4, and 5 are valid) */
|
||||
UINT8 archFlags; /* architecture flags */
|
||||
|
||||
} arm_state;
|
||||
|
||||
/****************************************************************************************************
|
||||
* VARIOUS INTERNAL STRUCS/DEFINES/ETC..
|
||||
***************************************************************************************************/
|
||||
/* Mode values come from bit 4-0 of CPSR, but we are ignoring bit 4 here, since bit 4 always = 1 for valid modes */
|
||||
enum
|
||||
{
|
||||
eARM7_MODE_USER = 0x0, /* Bit: 4-0 = 10000 */
|
||||
eARM7_MODE_FIQ = 0x1, /* Bit: 4-0 = 10001 */
|
||||
eARM7_MODE_IRQ = 0x2, /* Bit: 4-0 = 10010 */
|
||||
eARM7_MODE_SVC = 0x3, /* Bit: 4-0 = 10011 */
|
||||
eARM7_MODE_ABT = 0x7, /* Bit: 4-0 = 10111 */
|
||||
eARM7_MODE_UND = 0xb, /* Bit: 4-0 = 11011 */
|
||||
eARM7_MODE_SYS = 0xf /* Bit: 4-0 = 11111 */
|
||||
};
|
||||
|
||||
#define ARM7_NUM_MODES 0x10
|
||||
|
||||
static const int thumbCycles[256] =
|
||||
{
|
||||
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 0 */
|
||||
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, 1, /* 2 */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 3 */
|
||||
1, 1, 1, 1, 1, 1, 1, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 4 */
|
||||
2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* 5 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 6 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 7 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 8 */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, /* 9 */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* a */
|
||||
1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 4, 1, 1, /* b */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, /* c */
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, /* d */
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, /* e */
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 /* f */
|
||||
};
|
||||
|
||||
/* 17 processor registers are visible at any given time,
|
||||
* banked depending on processor mode.
|
||||
*/
|
||||
|
||||
static const int sRegisterTable[ARM7_NUM_MODES][18] =
|
||||
{
|
||||
{ /* USR */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13, eR14,
|
||||
eR15, eCPSR /* No SPSR in this mode */
|
||||
},
|
||||
{ /* FIQ */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8_FIQ, eR9_FIQ, eR10_FIQ, eR11_FIQ, eR12_FIQ,
|
||||
eR13_FIQ, eR14_FIQ,
|
||||
eR15, eCPSR, eSPSR_FIQ
|
||||
},
|
||||
{ /* IRQ */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_IRQ, eR14_IRQ,
|
||||
eR15, eCPSR, eSPSR_IRQ
|
||||
},
|
||||
{ /* SVC */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_SVC, eR14_SVC,
|
||||
eR15, eCPSR, eSPSR_SVC
|
||||
},
|
||||
{0}, {0}, {0}, /* values for modes 4,5,6 are not valid */
|
||||
{ /* ABT */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_ABT, eR14_ABT,
|
||||
eR15, eCPSR, eSPSR_ABT
|
||||
},
|
||||
{0}, {0}, {0}, /* values for modes 8,9,a are not valid! */
|
||||
{ /* UND */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13_UND, eR14_UND,
|
||||
eR15, eCPSR, eSPSR_UND
|
||||
},
|
||||
{0}, {0}, {0}, /* values for modes c,d, e are not valid! */
|
||||
{ /* SYS */
|
||||
eR0, eR1, eR2, eR3, eR4, eR5, eR6, eR7,
|
||||
eR8, eR9, eR10, eR11, eR12,
|
||||
eR13, eR14,
|
||||
eR15, eCPSR /* No SPSR in this mode */
|
||||
}
|
||||
};
|
||||
|
||||
#define N_BIT 31
|
||||
#define Z_BIT 30
|
||||
#define C_BIT 29
|
||||
#define V_BIT 28
|
||||
#define Q_BIT 27
|
||||
#define I_BIT 7
|
||||
#define F_BIT 6
|
||||
#define T_BIT 5 /* Thumb mode */
|
||||
|
||||
#define N_MASK ((UINT32)(1 << N_BIT)) /* Negative flag */
|
||||
#define Z_MASK ((UINT32)(1 << Z_BIT)) /* Zero flag */
|
||||
#define C_MASK ((UINT32)(1 << C_BIT)) /* Carry flag */
|
||||
#define V_MASK ((UINT32)(1 << V_BIT)) /* oVerflow flag */
|
||||
#define Q_MASK ((UINT32)(1 << Q_BIT)) /* signed overflow for QADD, MAC */
|
||||
#define I_MASK ((UINT32)(1 << I_BIT)) /* Interrupt request disable */
|
||||
#define F_MASK ((UINT32)(1 << F_BIT)) /* Fast interrupt request disable */
|
||||
#define T_MASK ((UINT32)(1 << T_BIT)) /* Thumb Mode flag */
|
||||
|
||||
#define N_IS_SET(pc) ((pc) & N_MASK)
|
||||
#define Z_IS_SET(pc) ((pc) & Z_MASK)
|
||||
#define C_IS_SET(pc) ((pc) & C_MASK)
|
||||
#define V_IS_SET(pc) ((pc) & V_MASK)
|
||||
#define Q_IS_SET(pc) ((pc) & Q_MASK)
|
||||
#define I_IS_SET(pc) ((pc) & I_MASK)
|
||||
#define F_IS_SET(pc) ((pc) & F_MASK)
|
||||
#define T_IS_SET(pc) ((pc) & T_MASK)
|
||||
|
||||
#define N_IS_CLEAR(pc) (!N_IS_SET(pc))
|
||||
#define Z_IS_CLEAR(pc) (!Z_IS_SET(pc))
|
||||
#define C_IS_CLEAR(pc) (!C_IS_SET(pc))
|
||||
#define V_IS_CLEAR(pc) (!V_IS_SET(pc))
|
||||
#define Q_IS_CLEAR(pc) (!Q_IS_SET(pc))
|
||||
#define I_IS_CLEAR(pc) (!I_IS_SET(pc))
|
||||
#define F_IS_CLEAR(pc) (!F_IS_SET(pc))
|
||||
#define T_IS_CLEAR(pc) (!T_IS_SET(pc))
|
||||
|
||||
/* Deconstructing an instruction */
|
||||
/* todo: use these in all places (including dasm file) */
|
||||
#define INSN_COND ((UINT32)0xf0000000u)
|
||||
#define INSN_SDT_L ((UINT32)0x00100000u)
|
||||
#define INSN_SDT_W ((UINT32)0x00200000u)
|
||||
#define INSN_SDT_B ((UINT32)0x00400000u)
|
||||
#define INSN_SDT_U ((UINT32)0x00800000u)
|
||||
#define INSN_SDT_P ((UINT32)0x01000000u)
|
||||
#define INSN_BDT_L ((UINT32)0x00100000u)
|
||||
#define INSN_BDT_W ((UINT32)0x00200000u)
|
||||
#define INSN_BDT_S ((UINT32)0x00400000u)
|
||||
#define INSN_BDT_U ((UINT32)0x00800000u)
|
||||
#define INSN_BDT_P ((UINT32)0x01000000u)
|
||||
#define INSN_BDT_REGS ((UINT32)0x0000ffffu)
|
||||
#define INSN_SDT_IMM ((UINT32)0x00000fffu)
|
||||
#define INSN_MUL_A ((UINT32)0x00200000u)
|
||||
#define INSN_MUL_RM ((UINT32)0x0000000fu)
|
||||
#define INSN_MUL_RS ((UINT32)0x00000f00u)
|
||||
#define INSN_MUL_RN ((UINT32)0x0000f000u)
|
||||
#define INSN_MUL_RD ((UINT32)0x000f0000u)
|
||||
#define INSN_I ((UINT32)0x02000000u)
|
||||
#define INSN_OPCODE ((UINT32)0x01e00000u)
|
||||
#define INSN_S ((UINT32)0x00100000u)
|
||||
#define INSN_BL ((UINT32)0x01000000u)
|
||||
#define INSN_BRANCH ((UINT32)0x00ffffffu)
|
||||
#define INSN_SWI ((UINT32)0x00ffffffu)
|
||||
#define INSN_RN ((UINT32)0x000f0000u)
|
||||
#define INSN_RD ((UINT32)0x0000f000u)
|
||||
#define INSN_OP2 ((UINT32)0x00000fffu)
|
||||
#define INSN_OP2_SHIFT ((UINT32)0x00000f80u)
|
||||
#define INSN_OP2_SHIFT_TYPE ((UINT32)0x00000070u)
|
||||
#define INSN_OP2_RM ((UINT32)0x0000000fu)
|
||||
#define INSN_OP2_ROTATE ((UINT32)0x00000f00u)
|
||||
#define INSN_OP2_IMM ((UINT32)0x000000ffu)
|
||||
#define INSN_OP2_SHIFT_TYPE_SHIFT 4
|
||||
#define INSN_OP2_SHIFT_SHIFT 7
|
||||
#define INSN_OP2_ROTATE_SHIFT 8
|
||||
#define INSN_MUL_RS_SHIFT 8
|
||||
#define INSN_MUL_RN_SHIFT 12
|
||||
#define INSN_MUL_RD_SHIFT 16
|
||||
#define INSN_OPCODE_SHIFT 21
|
||||
#define INSN_RN_SHIFT 16
|
||||
#define INSN_RD_SHIFT 12
|
||||
#define INSN_COND_SHIFT 28
|
||||
|
||||
#define INSN_COPRO_N ((UINT32) 0x00100000u)
|
||||
#define INSN_COPRO_CREG ((UINT32) 0x000f0000u)
|
||||
#define INSN_COPRO_AREG ((UINT32) 0x0000f000u)
|
||||
#define INSN_COPRO_CPNUM ((UINT32) 0x00000f00u)
|
||||
#define INSN_COPRO_OP2 ((UINT32) 0x000000e0u)
|
||||
#define INSN_COPRO_OP3 ((UINT32) 0x0000000fu)
|
||||
#define INSN_COPRO_N_SHIFT 20
|
||||
#define INSN_COPRO_CREG_SHIFT 16
|
||||
#define INSN_COPRO_AREG_SHIFT 12
|
||||
#define INSN_COPRO_CPNUM_SHIFT 8
|
||||
#define INSN_COPRO_OP2_SHIFT 5
|
||||
|
||||
#define THUMB_INSN_TYPE ((UINT16)0xf000)
|
||||
#define THUMB_COND_TYPE ((UINT16)0x0f00)
|
||||
#define THUMB_GROUP4_TYPE ((UINT16)0x0c00)
|
||||
#define THUMB_GROUP5_TYPE ((UINT16)0x0e00)
|
||||
#define THUMB_GROUP5_RM ((UINT16)0x01c0)
|
||||
#define THUMB_GROUP5_RN ((UINT16)0x0038)
|
||||
#define THUMB_GROUP5_RD ((UINT16)0x0007)
|
||||
#define THUMB_ADDSUB_RNIMM ((UINT16)0x01c0)
|
||||
#define THUMB_ADDSUB_RS ((UINT16)0x0038)
|
||||
#define THUMB_ADDSUB_RD ((UINT16)0x0007)
|
||||
#define THUMB_INSN_ADDSUB ((UINT16)0x0800)
|
||||
#define THUMB_INSN_CMP ((UINT16)0x0800)
|
||||
#define THUMB_INSN_SUB ((UINT16)0x0800)
|
||||
#define THUMB_INSN_IMM_RD ((UINT16)0x0700)
|
||||
#define THUMB_INSN_IMM_S ((UINT16)0x0080)
|
||||
#define THUMB_INSN_IMM ((UINT16)0x00ff)
|
||||
#define THUMB_ADDSUB_TYPE ((UINT16)0x0600)
|
||||
#define THUMB_HIREG_OP ((UINT16)0x0300)
|
||||
#define THUMB_HIREG_H ((UINT16)0x00c0)
|
||||
#define THUMB_HIREG_RS ((UINT16)0x0038)
|
||||
#define THUMB_HIREG_RD ((UINT16)0x0007)
|
||||
#define THUMB_STACKOP_TYPE ((UINT16)0x0f00)
|
||||
#define THUMB_STACKOP_L ((UINT16)0x0800)
|
||||
#define THUMB_STACKOP_RD ((UINT16)0x0700)
|
||||
#define THUMB_ALUOP_TYPE ((UINT16)0x03c0)
|
||||
#define THUMB_BLOP_LO ((UINT16)0x0800)
|
||||
#define THUMB_BLOP_OFFS ((UINT16)0x07ff)
|
||||
#define THUMB_SHIFT_R ((UINT16)0x0800)
|
||||
#define THUMB_SHIFT_AMT ((UINT16)0x07c0)
|
||||
#define THUMB_HALFOP_L ((UINT16)0x0800)
|
||||
#define THUMB_HALFOP_OFFS ((UINT16)0x07c0)
|
||||
#define THUMB_BRANCH_OFFS ((UINT16)0x07ff)
|
||||
#define THUMB_LSOP_L ((UINT16)0x0800)
|
||||
#define THUMB_LSOP_OFFS ((UINT16)0x07c0)
|
||||
#define THUMB_MULTLS ((UINT16)0x0800)
|
||||
#define THUMB_MULTLS_BASE ((UINT16)0x0700)
|
||||
#define THUMB_RELADDR_SP ((UINT16)0x0800)
|
||||
#define THUMB_RELADDR_RD ((UINT16)0x0700)
|
||||
#define THUMB_INSN_TYPE_SHIFT 12
|
||||
#define THUMB_COND_TYPE_SHIFT 8
|
||||
#define THUMB_GROUP4_TYPE_SHIFT 10
|
||||
#define THUMB_GROUP5_TYPE_SHIFT 9
|
||||
#define THUMB_ADDSUB_TYPE_SHIFT 9
|
||||
#define THUMB_INSN_IMM_RD_SHIFT 8
|
||||
#define THUMB_STACKOP_TYPE_SHIFT 8
|
||||
#define THUMB_HIREG_OP_SHIFT 8
|
||||
#define THUMB_STACKOP_RD_SHIFT 8
|
||||
#define THUMB_MULTLS_BASE_SHIFT 8
|
||||
#define THUMB_RELADDR_RD_SHIFT 8
|
||||
#define THUMB_HIREG_H_SHIFT 6
|
||||
#define THUMB_HIREG_RS_SHIFT 3
|
||||
#define THUMB_ALUOP_TYPE_SHIFT 6
|
||||
#define THUMB_SHIFT_AMT_SHIFT 6
|
||||
#define THUMB_HALFOP_OFFS_SHIFT 6
|
||||
#define THUMB_LSOP_OFFS_SHIFT 6
|
||||
#define THUMB_GROUP5_RM_SHIFT 6
|
||||
#define THUMB_GROUP5_RN_SHIFT 3
|
||||
#define THUMB_GROUP5_RD_SHIFT 0
|
||||
#define THUMB_ADDSUB_RNIMM_SHIFT 6
|
||||
#define THUMB_ADDSUB_RS_SHIFT 3
|
||||
#define THUMB_ADDSUB_RD_SHIFT 0
|
||||
|
||||
enum
|
||||
{
|
||||
OPCODE_AND, /* 0000 */
|
||||
OPCODE_EOR, /* 0001 */
|
||||
OPCODE_SUB, /* 0010 */
|
||||
OPCODE_RSB, /* 0011 */
|
||||
OPCODE_ADD, /* 0100 */
|
||||
OPCODE_ADC, /* 0101 */
|
||||
OPCODE_SBC, /* 0110 */
|
||||
OPCODE_RSC, /* 0111 */
|
||||
OPCODE_TST, /* 1000 */
|
||||
OPCODE_TEQ, /* 1001 */
|
||||
OPCODE_CMP, /* 1010 */
|
||||
OPCODE_CMN, /* 1011 */
|
||||
OPCODE_ORR, /* 1100 */
|
||||
OPCODE_MOV, /* 1101 */
|
||||
OPCODE_BIC, /* 1110 */
|
||||
OPCODE_MVN /* 1111 */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
COND_EQ = 0, /* Z equal */
|
||||
COND_NE, /* ~Z not equal */
|
||||
COND_CS, COND_HS = 2, /* C unsigned higher or same */
|
||||
COND_CC, COND_LO = 3, /* ~C unsigned lower */
|
||||
COND_MI, /* N negative */
|
||||
COND_PL, /* ~N positive or zero */
|
||||
COND_VS, /* V overflow */
|
||||
COND_VC, /* ~V no overflow */
|
||||
COND_HI, /* C && ~Z unsigned higher */
|
||||
COND_LS, /* ~C || Z unsigned lower or same */
|
||||
COND_GE, /* N == V greater or equal */
|
||||
COND_LT, /* N != V less than */
|
||||
COND_GT, /* ~Z && N == V greater than */
|
||||
COND_LE, /* Z || N != V less than or equal */
|
||||
COND_AL, /* 1 always */
|
||||
COND_NV /* 0 never */
|
||||
};
|
||||
|
||||
#define LSL(v, s) ((v) << (s))
|
||||
#define LSR(v, s) ((v) >> (s))
|
||||
#define ROL(v, s) (LSL((v), (s)) | (LSR((v), 32u - (s))))
|
||||
#define ROR(v, s) (LSR((v), (s)) | (LSL((v), 32u - (s))))
|
||||
|
||||
/* Convenience Macros */
|
||||
#define R15 ARM7REG(eR15)
|
||||
#define SPSR 17 /* SPSR is always the 18th register in our 0 based array sRegisterTable[][18] */
|
||||
#define GET_CPSR ARM7REG(eCPSR)
|
||||
#define SET_CPSR(v) (GET_CPSR = (v))
|
||||
#define MODE_FLAG 0xF /* Mode bits are 4:0 of CPSR, but we ignore bit 4. */
|
||||
#define GET_MODE (GET_CPSR & MODE_FLAG)
|
||||
#define SIGN_BIT ((UINT32)(1 << 31))
|
||||
#define SIGN_BITS_DIFFER(a, b) (((a) ^ (b)) >> 31)
|
||||
/* I really don't know why these were set to 16-bit, the thumb registers are still 32-bit ... */
|
||||
#define THUMB_SIGN_BIT ((UINT32)(1 << 31))
|
||||
#define THUMB_SIGN_BITS_DIFFER(a, b) (((a)^(b)) >> 31)
|
||||
|
||||
/* At one point I thought these needed to be cpu implementation specific, but they don't.. */
|
||||
#define GET_REGISTER(state, reg) GetRegister(state, reg)
|
||||
#define SET_REGISTER(state, reg, val) SetRegister(state, reg, val)
|
||||
#define ARM7_CHECKIRQ arm7_check_irq_state(cpustate)
|
||||
|
||||
#ifdef UNUSED_DEFINITION
|
||||
extern char *(*arm7_dasm_cop_dt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
|
||||
extern char *(*arm7_dasm_cop_rt_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
|
||||
extern char *(*arm7_dasm_cop_do_callback)(arm_state *cpustate, char *pBuf, UINT32 opcode, char *pConditionCode, char *pBuf0);
|
||||
#endif
|
||||
|
||||
#endif /* __ARM7CORE_H__ */
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,930 @@
|
||||
/***************************************************************************
|
||||
|
||||
h83002.c: Hitachi H8/3002 microcontroller emulator
|
||||
|
||||
Original by The_Author & DynaChicken for the ZiNc emulator.
|
||||
MAME changes by R. Belmont, Luca Elia, and Tomasz Slanina.
|
||||
|
||||
TS 20060412 Added exts.l, sub.l, divxs.w (buggy), jsr @reg, rotxl.l reg, mov.l @(adr, reg), reg
|
||||
LE 20070903 Added divxu.b shal.l extu.w dec.l #Imm,Rd subx.b
|
||||
LE 20080202 Separated 3002/3044/3007, Added or.l shal.l rotl.l not.l neg.l exts.w
|
||||
sub/or/xor.l #Imm:32,ERd bset/bnot/bclr.b Rn,@ERd bst/bist.b #Imm:3,@ERd bnot.b #Imm:3,@ERd
|
||||
LE 20090128 Added mov.l ers,@aa:16; bild #xx:3,rd; eepmov.b; bnot #xx:3,@aa:8
|
||||
|
||||
mame2003-plus: backported from the legacy H8/3xx core of MAME 0.152
|
||||
(h8_16.c, h8ops.h, h8periph.c) to the MAME 0.78 CPU interface.
|
||||
Only the H8/3002 model is kept. The on-chip RAM and peripheral
|
||||
registers are handled inside the core, the on-chip I/O ports are
|
||||
routed to the driver through h8_3002_set_io_handlers().
|
||||
|
||||
This core keeps a single global context: get/set_context are no-ops,
|
||||
so only one H8/3002 can exist in a machine (System 12 uses one).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "cpuintrf.h"
|
||||
#include "memory.h"
|
||||
#include "mamedbg.h"
|
||||
#include "state.h"
|
||||
#include "timer.h"
|
||||
#include "mame.h"
|
||||
#include "driver.h"
|
||||
#include "h83002.h"
|
||||
|
||||
/* H8_LOG((fmt, ...)): debug log, compiled out */
|
||||
#define H8_LOG(x) do { } while (0)
|
||||
|
||||
#define H8_SP (7)
|
||||
|
||||
/* on-chip resources of the H8/3002 */
|
||||
#define H8_IRAM_START 0xfffd10
|
||||
#define H8_IRAM_END 0xffff0f
|
||||
#define H8_REG_START 0xffff10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* main CPU stuff */
|
||||
UINT32 h8err;
|
||||
UINT32 regs[8];
|
||||
UINT32 pc, ppc;
|
||||
|
||||
UINT32 irq_req[3];
|
||||
|
||||
UINT8 ccr, exr;
|
||||
UINT8 h8nflag, h8vflag, h8cflag, h8zflag, h8iflag, h8hflag;
|
||||
UINT8 h8uflag, h8uiflag;
|
||||
UINT8 incheckirqs;
|
||||
|
||||
UINT8 has_exr;
|
||||
int mode_8bit;
|
||||
|
||||
int (*irq_cb)(int irqline);
|
||||
|
||||
/* onboard peripherals stuff */
|
||||
UINT8 per_regs[0x100];
|
||||
UINT8 iram[H8_IRAM_END - H8_IRAM_START + 1];
|
||||
|
||||
UINT16 h8TCNT[5];
|
||||
UINT8 h8TSTR;
|
||||
|
||||
mame_timer *timer[5];
|
||||
int timer_running[5]; /* timer[] armed (not TIME_NEVER / disabled) */
|
||||
UINT16 tcnt_start[5]; /* TCNT when the timer was last armed */
|
||||
double tcnt_offset[5]; /* time counted before the timer was last armed by a state load */
|
||||
double save_left[5], save_elapsed[5]; /* saved timer state (time left < 0: not armed) */
|
||||
int clock;
|
||||
} h83xx_state;
|
||||
|
||||
static h83xx_state h8state;
|
||||
|
||||
/* cycles left in the timeslice: cpuexec reads and adjusts it (abort,
|
||||
cycles run), so the core counts down this very variable */
|
||||
int h8_3002_ICount;
|
||||
|
||||
static h8_io_read_func h8_io_read = NULL;
|
||||
static h8_io_write_func h8_io_write = NULL;
|
||||
|
||||
void h8_3002_set_io_handlers(h8_io_read_func readfn, h8_io_write_func writefn)
|
||||
{
|
||||
h8_io_read = readfn;
|
||||
h8_io_write = writefn;
|
||||
}
|
||||
|
||||
static data8_t h8_io_read_byte(int port)
|
||||
{
|
||||
return h8_io_read ? h8_io_read(port) : 0;
|
||||
}
|
||||
|
||||
static void h8_io_write_byte(int port, data8_t data)
|
||||
{
|
||||
if (h8_io_write)
|
||||
h8_io_write(port, data);
|
||||
}
|
||||
|
||||
static UINT8 h8_register_read8(h83xx_state *h8, UINT32 address);
|
||||
static void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val);
|
||||
void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state);
|
||||
|
||||
/***************************************************************************
|
||||
memory access (external bus via the 0.78 memory system, on-chip
|
||||
RAM/registers handled here)
|
||||
***************************************************************************/
|
||||
|
||||
static UINT8 h8_read8(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
address &= 0xffffff;
|
||||
if (address >= H8_IRAM_START)
|
||||
{
|
||||
if (address <= H8_IRAM_END)
|
||||
return h8->iram[address - H8_IRAM_START];
|
||||
return h8_register_read8(h8, address);
|
||||
}
|
||||
return cpu_readmem24bew(address);
|
||||
}
|
||||
|
||||
static void h8_write8(h83xx_state *h8, UINT32 address, UINT8 data)
|
||||
{
|
||||
address &= 0xffffff;
|
||||
if (address >= H8_IRAM_START)
|
||||
{
|
||||
if (address <= H8_IRAM_END)
|
||||
h8->iram[address - H8_IRAM_START] = data;
|
||||
else
|
||||
h8_register_write8(h8, address, data);
|
||||
return;
|
||||
}
|
||||
cpu_writemem24bew(address, data);
|
||||
}
|
||||
|
||||
static UINT16 h8_read16(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
address &= 0xfffffe;
|
||||
if (address >= H8_IRAM_START)
|
||||
return (h8_read8(h8, address) << 8) | h8_read8(h8, address + 1);
|
||||
return cpu_readmem24bew_word(address);
|
||||
}
|
||||
|
||||
static void h8_write16(h83xx_state *h8, UINT32 address, UINT16 data)
|
||||
{
|
||||
address &= 0xfffffe;
|
||||
if (address >= H8_IRAM_START)
|
||||
{
|
||||
h8_write8(h8, address, data >> 8);
|
||||
h8_write8(h8, address + 1, data & 0xff);
|
||||
return;
|
||||
}
|
||||
cpu_writemem24bew_word(address, data);
|
||||
}
|
||||
|
||||
static UINT16 h8_readop16(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
address &= 0xfffffe;
|
||||
if (address >= H8_IRAM_START)
|
||||
return h8_read16(h8, address);
|
||||
return cpu_readop16(address);
|
||||
}
|
||||
|
||||
#define h8_mem_read8(x) h8_read8(h8, x)
|
||||
#define h8_mem_read16(z, x) h8_read16(h8, x)
|
||||
#define h8_mem_write8(x, y) h8_write8(h8, x, y)
|
||||
#define h8_mem_write16(z, x, y) h8_write16(h8, x, y)
|
||||
|
||||
/* timing macros
|
||||
note: we assume a system 12 - type setup where external access is 3+1 states
|
||||
timing will be off somewhat for other configurations. */
|
||||
#define H8_IFETCH_TIMING(x) h8_3002_ICount -= (x) * 4;
|
||||
#define H8_BRANCH_TIMING(x) h8_3002_ICount -= (x) * 4;
|
||||
#define H8_STACK_TIMING(x) h8_3002_ICount -= (x) * 4;
|
||||
#define H8_BYTE_TIMING(x, adr) if (address24 >= 0xffff10) h8_3002_ICount -= (x) * 3; else h8_3002_ICount -= (x) * 4;
|
||||
#define H8_WORD_TIMING(x, adr) if (address24 >= 0xffff10) h8_3002_ICount -= (x) * 3; else h8_3002_ICount -= (x) * 4;
|
||||
#define H8_IOP_TIMING(x) h8_3002_ICount -= (x);
|
||||
|
||||
static UINT32 h8_mem_read32(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
UINT32 result = h8_read16(h8, address) << 16;
|
||||
return result | h8_read16(h8, address + 2);
|
||||
}
|
||||
|
||||
static void h8_mem_write32(h83xx_state *h8, UINT32 address, UINT32 data)
|
||||
{
|
||||
h8_write16(h8, address, data >> 16);
|
||||
h8_write16(h8, address + 2, data);
|
||||
}
|
||||
|
||||
static void h8_check_irqs(h83xx_state *h8);
|
||||
|
||||
/***************************************************************************
|
||||
implementation
|
||||
***************************************************************************/
|
||||
|
||||
void h8_3002_InterruptRequest(h83xx_state *h8, UINT8 source, UINT8 state)
|
||||
{
|
||||
int request = source / 32;
|
||||
int bit = source % 32;
|
||||
|
||||
/* don't allow clear on external interrupts */
|
||||
if ((source <= 17) && (state == 0)) return;
|
||||
|
||||
if (state)
|
||||
h8->irq_req[request] |= (1<<bit);
|
||||
else
|
||||
h8->irq_req[request] &= ~(1<<bit);
|
||||
}
|
||||
|
||||
static UINT8 h8_get_ccr(h83xx_state *h8)
|
||||
{
|
||||
h8->ccr = 0;
|
||||
if(h8->h8nflag)h8->ccr |= H8_NFLAG;
|
||||
if(h8->h8zflag)h8->ccr |= H8_ZFLAG;
|
||||
if(h8->h8vflag)h8->ccr |= H8_VFLAG;
|
||||
if(h8->h8cflag)h8->ccr |= H8_CFLAG;
|
||||
if(h8->h8uflag)h8->ccr |= H8_UFLAG;
|
||||
if(h8->h8hflag)h8->ccr |= H8_HFLAG;
|
||||
if(h8->h8uiflag)h8->ccr |= H8_UIFLAG;
|
||||
if(h8->h8iflag)h8->ccr |= H8_IFLAG;
|
||||
return h8->ccr;
|
||||
}
|
||||
|
||||
static UINT8 h8_get_exr(h83xx_state *h8)
|
||||
{
|
||||
return h8->exr;
|
||||
}
|
||||
|
||||
/* CCR into the flag bytes, without taking interrupts */
|
||||
static void h8_unpack_ccr(h83xx_state *h8, UINT8 data)
|
||||
{
|
||||
h8->ccr = data;
|
||||
|
||||
h8->h8nflag = (data & H8_NFLAG) ? 1 : 0;
|
||||
h8->h8zflag = (data & H8_ZFLAG) ? 1 : 0;
|
||||
h8->h8vflag = (data & H8_VFLAG) ? 1 : 0;
|
||||
h8->h8cflag = (data & H8_CFLAG) ? 1 : 0;
|
||||
h8->h8hflag = (data & H8_HFLAG) ? 1 : 0;
|
||||
h8->h8iflag = (data & H8_IFLAG) ? 1 : 0;
|
||||
h8->h8uflag = (data & H8_UFLAG) ? 1 : 0;
|
||||
h8->h8uiflag = (data & H8_UIFLAG) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void h8_set_ccr(h83xx_state *h8, UINT8 data)
|
||||
{
|
||||
h8_unpack_ccr(h8, data);
|
||||
|
||||
if (!h8->incheckirqs) h8_check_irqs(h8);
|
||||
}
|
||||
|
||||
static void h8_set_exr(h83xx_state *h8, UINT8 data)
|
||||
{
|
||||
h8->exr = data;
|
||||
}
|
||||
|
||||
/* register numbers come from opcode bits: keep them inside regs[] */
|
||||
static INT16 h8_getreg16(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
return h8->regs[reg-8]>>16;
|
||||
else
|
||||
return h8->regs[reg];
|
||||
}
|
||||
|
||||
static void h8_setreg16(h83xx_state *h8, UINT8 reg, UINT16 data)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
{
|
||||
h8->regs[reg-8] &= 0xffff;
|
||||
h8->regs[reg-8] |= data<<16;
|
||||
}
|
||||
else
|
||||
{
|
||||
h8->regs[reg] &= 0xffff0000;
|
||||
h8->regs[reg] |= data;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 h8_getreg8(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
return h8->regs[reg-8];
|
||||
else
|
||||
return h8->regs[reg]>>8;
|
||||
}
|
||||
|
||||
static void h8_setreg8(h83xx_state *h8, UINT8 reg, UINT8 data)
|
||||
{
|
||||
reg &= 15;
|
||||
if(reg > 7)
|
||||
{
|
||||
h8->regs[reg-8] &= 0xffffff00;
|
||||
h8->regs[reg-8] |= data;
|
||||
}
|
||||
else
|
||||
{
|
||||
h8->regs[reg] &= 0xffff00ff;
|
||||
h8->regs[reg] |= data<<8;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 h8_getreg32(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
return h8->regs[reg & 7];
|
||||
}
|
||||
|
||||
static void h8_setreg32(h83xx_state *h8, UINT8 reg, UINT32 data)
|
||||
{
|
||||
h8->regs[reg & 7] = data;
|
||||
}
|
||||
|
||||
static void h8_GenException(h83xx_state *h8, UINT8 vectornr)
|
||||
{
|
||||
/* push PC on stack (extended mode stack push!) */
|
||||
h8_setreg32(h8, H8_SP, h8_getreg32(h8, H8_SP)-4);
|
||||
h8_mem_write32(h8, h8_getreg32(h8, H8_SP), h8->pc | (h8_get_ccr(h8)<<24));
|
||||
|
||||
/* generate address from vector */
|
||||
h8_set_ccr(h8, h8_get_ccr(h8) | 0x80);
|
||||
if (h8->h8uiflag == 0)
|
||||
h8_set_ccr(h8, h8_get_ccr(h8) | 0x40);
|
||||
h8->pc = h8_mem_read32(h8, vectornr * 4) & 0xffffff;
|
||||
|
||||
/* I couldn't find timing info for exceptions, so this is a guess (based on JSR/BSR) */
|
||||
H8_IFETCH_TIMING(2);
|
||||
H8_STACK_TIMING(2);
|
||||
}
|
||||
|
||||
static int h8_get_priority(h83xx_state *h8, UINT8 bit)
|
||||
{
|
||||
int res = 0;
|
||||
switch(bit)
|
||||
{
|
||||
case 12: /* IRQ0 */
|
||||
if (h8->per_regs[0xF8]&0x80) res = 1;
|
||||
break;
|
||||
case 13: /* IRQ1 */
|
||||
if (h8->per_regs[0xF8]&0x40) res = 1;
|
||||
break;
|
||||
case 14: /* IRQ2 */
|
||||
case 15: /* IRQ3 */
|
||||
if (h8->per_regs[0xF8]&0x20) res = 1;
|
||||
break;
|
||||
case 16: /* IRQ4 */
|
||||
case 17: /* IRQ5 */
|
||||
if (h8->per_regs[0xF8]&0x10) res = 1;
|
||||
break;
|
||||
case 53: /* SCI0 Rx */
|
||||
if (!(h8->per_regs[0xB2]&0x40)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x08) res = 1;
|
||||
break;
|
||||
case 54: /* SCI0 Tx Empty */
|
||||
if (!(h8->per_regs[0xB2]&0x80)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x08) res = 1;
|
||||
break;
|
||||
case 55: /* SCI0 Tx End */
|
||||
if (!(h8->per_regs[0xB2]&0x04)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x08) res = 1;
|
||||
break;
|
||||
case 57: /* SCI1 Rx */
|
||||
if (!(h8->per_regs[0xBA]&0x40)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x04) res = 1;
|
||||
break;
|
||||
case 58: /* SCI1 Tx Empty */
|
||||
if (!(h8->per_regs[0xBA]&0x80)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x04) res = 1;
|
||||
break;
|
||||
case 59: /* SCI1 Tx End */
|
||||
if (!(h8->per_regs[0xBA]&0x04)) res = -2;
|
||||
else if (h8->per_regs[0xF9]&0x04) res = 1;
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static void h8_check_irqs(h83xx_state *h8)
|
||||
{
|
||||
int lv = -1;
|
||||
|
||||
h8->incheckirqs = 1;
|
||||
|
||||
if (h8->has_exr)
|
||||
{
|
||||
lv = (h8->exr & 7);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (h8->h8iflag == 0)
|
||||
{
|
||||
lv = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((h8->per_regs[0xF2]&0x08)/*SYSCR*/ == 0)
|
||||
{
|
||||
if (h8->h8uiflag == 0)
|
||||
lv = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* any interrupts wanted and can accept ? */
|
||||
if(((h8->irq_req[0] != 0) || (h8->irq_req[1]!= 0) || (h8->irq_req[2] != 0)) && (lv >= 0))
|
||||
{
|
||||
UINT8 bit, source;
|
||||
/* which one ? */
|
||||
for(bit = 0, source = 0xff; source == 0xff && bit < 32; bit++)
|
||||
{
|
||||
if( h8->irq_req[0] & (1<<bit) )
|
||||
{
|
||||
if (h8_get_priority(h8, bit) >= lv)
|
||||
{
|
||||
h8->irq_req[0] &= ~(1<<bit);
|
||||
source = bit;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(bit = 0; source == 0xff && bit < 32; bit++)
|
||||
{
|
||||
if( h8->irq_req[1] & (1<<bit) )
|
||||
{
|
||||
if (h8_get_priority(h8, bit + 32) >= lv)
|
||||
{
|
||||
h8->irq_req[1] &= ~(1<<bit);
|
||||
source = bit + 32;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(bit = 0; source == 0xff && bit < 32; bit++)
|
||||
{
|
||||
if( h8->irq_req[2] & (1<<bit) )
|
||||
{
|
||||
if (h8_get_priority(h8, bit + 64) >= lv)
|
||||
{
|
||||
h8->irq_req[2] &= ~(1<<bit);
|
||||
source = bit + 64;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* call the MAME callback if it's one of the 6 external IRQs */
|
||||
if (source >= 12 && source <= 17)
|
||||
{
|
||||
if (h8->irq_cb)
|
||||
(*h8->irq_cb)(source - 12 + H8_IRQ0);
|
||||
}
|
||||
|
||||
if (source != 0xff)
|
||||
h8_GenException(h8, source);
|
||||
}
|
||||
|
||||
h8->incheckirqs = 0;
|
||||
}
|
||||
|
||||
#define H8_ADDR_MASK 0xffffff
|
||||
static UINT32 h8_idle_start, h8_idle_end; /* polled memory (end 0 = off) */
|
||||
static UINT32 h8_idle_pc; /* loop start last reached */
|
||||
static int h8_idle_since; /* instructions since then */
|
||||
static int h8_idle_cycles; /* h8_3002_ICount then */
|
||||
|
||||
void h8_3002_set_idle_poll(UINT32 start, UINT32 end)
|
||||
{
|
||||
h8_idle_start = start;
|
||||
h8_idle_end = end;
|
||||
}
|
||||
|
||||
/* at "mov.b @aa:24, Rd": the start of a polling loop? skip passes */
|
||||
static void h8_idle_check(h83xx_state *h8)
|
||||
{
|
||||
UINT32 address = ((UINT32)h8_readop16(h8, h8->pc + 2) << 16) | h8_readop16(h8, h8->pc + 4);
|
||||
UINT16 branch = h8_readop16(h8, h8->pc + 6);
|
||||
|
||||
address &= 0xffffff;
|
||||
if (address < h8_idle_start || address > h8_idle_end || (branch != 0x46f8 && branch != 0x47f8))
|
||||
{
|
||||
h8_idle_since = -1;
|
||||
return;
|
||||
}
|
||||
/* one whole pass just ran: skip the passes that still fit */
|
||||
if (h8->pc == h8_idle_pc && h8_idle_since == 2)
|
||||
{
|
||||
int pass = h8_idle_cycles - h8_3002_ICount;
|
||||
if (pass > 0 && h8_3002_ICount > pass)
|
||||
h8_3002_ICount -= ((h8_3002_ICount - 1) / pass) * pass;
|
||||
}
|
||||
h8_idle_pc = h8->pc;
|
||||
h8_idle_since = 0;
|
||||
h8_idle_cycles = h8_3002_ICount;
|
||||
}
|
||||
|
||||
#include "h8ops.h"
|
||||
|
||||
/***************************************************************************
|
||||
on-chip peripherals (ITU timers, ports, serial, ADC)
|
||||
***************************************************************************/
|
||||
|
||||
/* timer registers */
|
||||
#define TSTR (0x60)
|
||||
#define TIER0 (0x66)
|
||||
#define TIER1 (0x70)
|
||||
#define TIER2 (0x7a)
|
||||
#define TIER3 (0x84)
|
||||
#define TIER4 (0x94)
|
||||
#define TSR0 (0x67)
|
||||
#define TSR1 (0x71)
|
||||
#define TSR2 (0x7b)
|
||||
#define TSR3 (0x85)
|
||||
#define TSR4 (0x95)
|
||||
#define TCR0 (0x64)
|
||||
#define TCR1 (0x6e)
|
||||
#define TCR2 (0x78)
|
||||
#define TCR3 (0x82)
|
||||
#define TCR4 (0x92)
|
||||
|
||||
static const UINT8 tsr[5] = { TSR0, TSR1, TSR2, TSR3, TSR4 };
|
||||
static const UINT8 tier[5] = { TIER0, TIER1, TIER2, TIER3, TIER4 };
|
||||
static const UINT8 tcr[5] = { TCR0, TCR1, TCR2, TCR3, TCR4 };
|
||||
static const int tscales[4] = { 1, 2, 4, 8 };
|
||||
|
||||
static void h8itu_timer_expire(int which)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
timer_adjust(h8->timer[which], TIME_NEVER, 0, 0);
|
||||
h8->timer_running[which] = 0;
|
||||
h8->tcnt_offset[which] = 0;
|
||||
h8->tcnt_start[which] = 0;
|
||||
h8->h8TCNT[which] = 0;
|
||||
h8->per_regs[tsr[which]] |= 4;
|
||||
/* interrupt on overflow ? */
|
||||
if(h8->per_regs[tier[which]] & 4)
|
||||
{
|
||||
h8_3002_InterruptRequest(h8, 26 + 4*which, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void h8_itu_refresh_timer(h83xx_state *h8, int tnum)
|
||||
{
|
||||
int ourTCR = h8->per_regs[tcr[tnum]];
|
||||
int ourTVAL = h8->h8TCNT[tnum];
|
||||
double period;
|
||||
|
||||
period = TIME_IN_HZ(h8->clock) * tscales[ourTCR & 3] * (65536 - ourTVAL);
|
||||
|
||||
if (ourTCR & 4)
|
||||
H8_LOG(("H8/3002: Timer %d is using an external clock. Unsupported!\n", tnum));
|
||||
|
||||
timer_adjust(h8->timer[tnum], period, tnum, 0);
|
||||
h8->timer_running[tnum] = 1;
|
||||
h8->tcnt_start[tnum] = ourTVAL;
|
||||
h8->tcnt_offset[tnum] = 0;
|
||||
}
|
||||
|
||||
static void h8_itu_sync_timers(h83xx_state *h8, int tnum)
|
||||
{
|
||||
int ourTCR = h8->per_regs[tcr[tnum]];
|
||||
double cycle_time, cur;
|
||||
|
||||
/* get the time per unit */
|
||||
cycle_time = TIME_IN_HZ(h8->clock) * tscales[ourTCR & 3];
|
||||
cur = timer_timeelapsed(h8->timer[tnum]) + h8->tcnt_offset[tnum];
|
||||
|
||||
/* counted from the TCNT value the timer was armed with */
|
||||
h8->h8TCNT[tnum] = (UINT16)(h8->tcnt_start[tnum] + (UINT32)(cur / cycle_time));
|
||||
}
|
||||
|
||||
static UINT8 h8_itu_read8(h83xx_state *h8, UINT8 reg)
|
||||
{
|
||||
switch(reg)
|
||||
{
|
||||
case 0x60: return h8->h8TSTR;
|
||||
case 0x68: h8_itu_sync_timers(h8, 0); return h8->h8TCNT[0]>>8;
|
||||
case 0x69: h8_itu_sync_timers(h8, 0); return h8->h8TCNT[0]&0xff;
|
||||
case 0x72: h8_itu_sync_timers(h8, 1); return h8->h8TCNT[1]>>8;
|
||||
case 0x73: h8_itu_sync_timers(h8, 1); return h8->h8TCNT[1]&0xff;
|
||||
case 0x7c: h8_itu_sync_timers(h8, 2); return h8->h8TCNT[2]>>8;
|
||||
case 0x7d: h8_itu_sync_timers(h8, 2); return h8->h8TCNT[2]&0xff;
|
||||
case 0x86: h8_itu_sync_timers(h8, 3); return h8->h8TCNT[3]>>8;
|
||||
case 0x87: h8_itu_sync_timers(h8, 3); return h8->h8TCNT[3]&0xff;
|
||||
default: return h8->per_regs[reg];
|
||||
}
|
||||
}
|
||||
|
||||
static void h8_itu_write8(h83xx_state *h8, UINT8 reg, UINT8 val)
|
||||
{
|
||||
int t;
|
||||
|
||||
h8->per_regs[reg] = val;
|
||||
switch(reg)
|
||||
{
|
||||
case 0x60:
|
||||
for (t = 0; t < 5; t++)
|
||||
if ((val & (1 << t)) && !(h8->h8TSTR & (1 << t)))
|
||||
h8_itu_refresh_timer(h8, t);
|
||||
h8->h8TSTR = val;
|
||||
break;
|
||||
case 0x68: h8->h8TCNT[0] = (val<<8) | (h8->h8TCNT[0] & 0xff); if (h8->h8TSTR & 0x01) h8_itu_refresh_timer(h8, 0); break;
|
||||
case 0x69: h8->h8TCNT[0] = (val) | (h8->h8TCNT[0] & 0xff00); if (h8->h8TSTR & 0x01) h8_itu_refresh_timer(h8, 0); break;
|
||||
case 0x72: h8->h8TCNT[1] = (val<<8) | (h8->h8TCNT[1] & 0xff); if (h8->h8TSTR & 0x02) h8_itu_refresh_timer(h8, 1); break;
|
||||
case 0x73: h8->h8TCNT[1] = (val) | (h8->h8TCNT[1] & 0xff00); if (h8->h8TSTR & 0x02) h8_itu_refresh_timer(h8, 1); break;
|
||||
case 0x7c: h8->h8TCNT[2] = (val<<8) | (h8->h8TCNT[2] & 0xff); if (h8->h8TSTR & 0x04) h8_itu_refresh_timer(h8, 2); break;
|
||||
case 0x7d: h8->h8TCNT[2] = (val) | (h8->h8TCNT[2] & 0xff00); if (h8->h8TSTR & 0x04) h8_itu_refresh_timer(h8, 2); break;
|
||||
case 0x86: h8->h8TCNT[3] = (val<<8) | (h8->h8TCNT[3] & 0xff); if (h8->h8TSTR & 0x08) h8_itu_refresh_timer(h8, 3); break;
|
||||
case 0x87: h8->h8TCNT[3] = (val) | (h8->h8TCNT[3] & 0xff00); if (h8->h8TSTR & 0x08) h8_itu_refresh_timer(h8, 3); break;
|
||||
case 0x96: h8->h8TCNT[4] = (val<<8) | (h8->h8TCNT[4] & 0xff); if (h8->h8TSTR & 0x10) h8_itu_refresh_timer(h8, 4); break;
|
||||
case 0x97: h8->h8TCNT[4] = (val) | (h8->h8TCNT[4] & 0xff00); if (h8->h8TSTR & 0x10) h8_itu_refresh_timer(h8, 4); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 h8_ISR_r(h83xx_state *h8)
|
||||
{
|
||||
UINT8 res = 0;
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
if (h8->irq_req[0] & (1 << (12+i))) res |= (1 << i);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void h8_ISR_w(h83xx_state *h8, UINT8 val)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
if ((~val) & (1 << i)) h8->irq_req[0] &= ~(1 << (12+i));
|
||||
}
|
||||
|
||||
static UINT8 h8_register_read8(h83xx_state *h8, UINT32 address)
|
||||
{
|
||||
UINT8 val;
|
||||
UINT8 reg = address & 0xff;
|
||||
|
||||
if(reg >= 0x60 && reg <= 0x9f)
|
||||
return h8_itu_read8(h8, reg);
|
||||
|
||||
switch(reg)
|
||||
{
|
||||
case 0xb4: /* serial port A status */
|
||||
val = h8->per_regs[reg];
|
||||
val |= 0xc4; /* transmit finished, receive ready, no errors */
|
||||
break;
|
||||
case 0xb5: val = h8_io_read_byte(H8_SERIAL_0); break; /* serial port A receive */
|
||||
case 0xbc: /* serial port B status */
|
||||
val = h8->per_regs[reg];
|
||||
val |= 0xc4; /* transmit finished, receive ready, no errors */
|
||||
break;
|
||||
case 0xbd: val = h8_io_read_byte(H8_SERIAL_1); break; /* serial port B receive */
|
||||
case 0xe0: val = h8_io_read_byte(H8_ADC_0_H); break;
|
||||
case 0xe1: val = h8_io_read_byte(H8_ADC_0_L); break;
|
||||
case 0xe2: val = h8_io_read_byte(H8_ADC_1_H); break;
|
||||
case 0xe3: val = h8_io_read_byte(H8_ADC_1_L); break;
|
||||
case 0xe4: val = h8_io_read_byte(H8_ADC_2_H); break;
|
||||
case 0xe5: val = h8_io_read_byte(H8_ADC_2_L); break;
|
||||
case 0xe6: val = h8_io_read_byte(H8_ADC_3_H); break;
|
||||
case 0xe7: val = h8_io_read_byte(H8_ADC_3_L); break;
|
||||
case 0xe8: val = 0x80; break; /* adc status */
|
||||
case 0xc7: val = h8_io_read_byte(H8_PORT_4); break; /* port 4 data */
|
||||
case 0xcb: val = h8_io_read_byte(H8_PORT_6); break; /* port 6 data */
|
||||
case 0xce: val = h8_io_read_byte(H8_PORT_7); break; /* port 7 data */
|
||||
case 0xcf: val = h8_io_read_byte(H8_PORT_8); break; /* port 8 data */
|
||||
case 0xd2: val = h8_io_read_byte(H8_PORT_9); break; /* port 9 data */
|
||||
case 0xd3: val = h8_io_read_byte(H8_PORT_A); break; /* port a data */
|
||||
case 0xd6: val = h8_io_read_byte(H8_PORT_B); break; /* port b data */
|
||||
case 0xf6: val = h8_ISR_r(h8); break;
|
||||
default: val = h8->per_regs[reg]; break;
|
||||
}
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void h8_register_write8(h83xx_state *h8, UINT32 address, UINT8 val)
|
||||
{
|
||||
UINT8 reg = address & 0xff;
|
||||
|
||||
if(reg >= 0x60 && reg <= 0x9f)
|
||||
h8_itu_write8(h8, reg, val);
|
||||
|
||||
switch (reg)
|
||||
{
|
||||
case 0xb3: /* serial 0 send */
|
||||
h8_io_write_byte(H8_SERIAL_0, val);
|
||||
h8_3002_InterruptRequest(h8, 54, 1);
|
||||
h8_3002_InterruptRequest(h8, 55, 1);
|
||||
break;
|
||||
case 0xbb: /* serial 1 send */
|
||||
h8_io_write_byte(H8_SERIAL_1, val);
|
||||
h8_3002_InterruptRequest(h8, 58, 1);
|
||||
h8_3002_InterruptRequest(h8, 59, 1);
|
||||
break;
|
||||
case 0xc7: h8_io_write_byte(H8_PORT_4, val); break;
|
||||
case 0xcb: h8_io_write_byte(H8_PORT_6, val); break;
|
||||
case 0xce: h8_io_write_byte(H8_PORT_7, val); break;
|
||||
case 0xcf: h8_io_write_byte(H8_PORT_8, val); break;
|
||||
case 0xd2: h8_io_write_byte(H8_PORT_9, val); break;
|
||||
case 0xd3: h8_io_write_byte(H8_PORT_A, val); break;
|
||||
case 0xd6: h8_io_write_byte(H8_PORT_B, val); break;
|
||||
case 0xf6: h8_ISR_w(h8, val); break;
|
||||
}
|
||||
|
||||
h8->per_regs[reg] = val;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
MAME 0.78 interface
|
||||
***************************************************************************/
|
||||
|
||||
/* the ITU timers are MAME timers, which a state does not hold: save how
|
||||
long each one has run and how long it has left, and re-arm them on load */
|
||||
static void h8_onstatesave(void)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int i;
|
||||
|
||||
/* the live flags are the flag bytes: ccr holds them in the state */
|
||||
h8_get_ccr(h8);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
h8->save_left[i] = h8->timer_running[i] ? timer_timeleft(h8->timer[i]) : -1;
|
||||
h8->save_elapsed[i] = timer_timeelapsed(h8->timer[i]) + h8->tcnt_offset[i];
|
||||
}
|
||||
}
|
||||
|
||||
static void h8_onstateload(void)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int i;
|
||||
|
||||
/* flags only: a load must not take an interrupt */
|
||||
h8_unpack_ccr(h8, h8->ccr);
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
if (h8->save_left[i] >= 0)
|
||||
{
|
||||
timer_adjust(h8->timer[i], h8->save_left[i], i, 0);
|
||||
h8->timer_running[i] = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
timer_adjust(h8->timer[i], TIME_NEVER, 0, 0);
|
||||
timer_enable(h8->timer[i], 0);
|
||||
h8->timer_running[i] = 0;
|
||||
}
|
||||
h8->tcnt_offset[i] = h8->save_elapsed[i];
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_init(void)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int cpu = cpu_getactivecpu();
|
||||
int i;
|
||||
|
||||
memset(h8, 0, sizeof(*h8));
|
||||
h8->h8iflag = 1;
|
||||
h8->mode_8bit = 0;
|
||||
|
||||
for (i = 0; i < 5; i++)
|
||||
h8->timer[i] = timer_alloc(h8itu_timer_expire);
|
||||
|
||||
state_save_register_UINT32("h8_3002", cpu, "h8err", &h8->h8err, 1);
|
||||
state_save_register_UINT32("h8_3002", cpu, "regs", h8->regs, 8);
|
||||
state_save_register_UINT32("h8_3002", cpu, "pc", &h8->pc, 1);
|
||||
state_save_register_UINT32("h8_3002", cpu, "ppc", &h8->ppc, 1);
|
||||
state_save_register_UINT32("h8_3002", cpu, "irq_req", h8->irq_req, 3);
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "ccr", &h8->ccr, 1);
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "per_regs", h8->per_regs, 0x100);
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "iram", h8->iram, sizeof(h8->iram));
|
||||
state_save_register_UINT8 ("h8_3002", cpu, "h8TSTR", &h8->h8TSTR, 1);
|
||||
state_save_register_UINT16("h8_3002", cpu, "h8TCNT", h8->h8TCNT, 5);
|
||||
state_save_register_UINT16("h8_3002", cpu, "tcnt_start", h8->tcnt_start, 5);
|
||||
state_save_register_double("h8_3002", cpu, "timer_left", h8->save_left, 5);
|
||||
state_save_register_double("h8_3002", cpu, "timer_elapsed", h8->save_elapsed, 5);
|
||||
state_save_register_func_presave(h8_onstatesave);
|
||||
state_save_register_func_postload(h8_onstateload);
|
||||
}
|
||||
|
||||
void h8_3002_reset(void *param)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int i;
|
||||
|
||||
h8->clock = Machine->drv->cpu[cpu_getactivecpu()].cpu_clock;
|
||||
|
||||
h8->h8err = 0;
|
||||
memset(h8->regs, 0, sizeof(h8->regs));
|
||||
memset(h8->irq_req, 0, sizeof(h8->irq_req));
|
||||
memset(h8->per_regs, 0, sizeof(h8->per_regs));
|
||||
h8->incheckirqs = 0;
|
||||
h8->exr = 0;
|
||||
h8->has_exr = 0;
|
||||
h8_set_ccr(h8, H8_IFLAG);
|
||||
|
||||
h8->pc = h8_mem_read32(h8, 0) & 0xffffff;
|
||||
h8->ppc = h8->pc;
|
||||
|
||||
/* disable timers */
|
||||
h8->h8TSTR = 0;
|
||||
for (i = 0; i < 5; i++)
|
||||
{
|
||||
h8->h8TCNT[i] = 0;
|
||||
timer_adjust(h8->timer[i], TIME_NEVER, 0, 0);
|
||||
h8->timer_running[i] = 0;
|
||||
h8->tcnt_start[i] = 0;
|
||||
h8->tcnt_offset[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_exit(void)
|
||||
{
|
||||
h8_idle_end = 0;
|
||||
}
|
||||
|
||||
/* single instance (one H8/3002 per machine): the state lives in h8state,
|
||||
contexts are not swapped */
|
||||
unsigned h8_3002_get_context(void *dst)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
void h8_3002_set_context(void *src)
|
||||
{
|
||||
}
|
||||
|
||||
unsigned h8_3002_get_reg(int regnum)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case H8_PC: return h8->pc;
|
||||
case REG_PREVIOUSPC: return h8->ppc;
|
||||
case REG_SP: return h8->regs[7];
|
||||
case H8_CCR: return h8_get_ccr(h8);
|
||||
case H8_E0: case H8_E1: case H8_E2: case H8_E3:
|
||||
case H8_E4: case H8_E5: case H8_E6: case H8_E7:
|
||||
return h8->regs[regnum - H8_E0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void h8_3002_set_reg(int regnum, unsigned val)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
case H8_PC: h8->pc = val & 0xffffff; break;
|
||||
case REG_SP: h8->regs[7] = val; break;
|
||||
case H8_CCR: h8_set_ccr(h8, val); break;
|
||||
case H8_E0: case H8_E1: case H8_E2: case H8_E3:
|
||||
case H8_E4: case H8_E5: case H8_E6: case H8_E7:
|
||||
h8->regs[regnum - H8_E0] = val; break;
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_set_irq_line(int irqline, int state)
|
||||
{
|
||||
h83xx_state *h8 = &h8state;
|
||||
int asserted = (state != CLEAR_LINE && state != INTERNAL_CLEAR_LINE);
|
||||
|
||||
switch (irqline)
|
||||
{
|
||||
case H8_IRQ0: case H8_IRQ1: case H8_IRQ2:
|
||||
case H8_IRQ3: case H8_IRQ4: case H8_IRQ5:
|
||||
h8_3002_InterruptRequest(h8, 12 + irqline - H8_IRQ0, asserted);
|
||||
break;
|
||||
case H8_SCI_0_RX: h8_3002_InterruptRequest(h8, 53, asserted); break;
|
||||
case H8_SCI_1_RX: h8_3002_InterruptRequest(h8, 57, asserted); break;
|
||||
}
|
||||
}
|
||||
|
||||
void h8_3002_set_irq_callback(int (*callback)(int irqline))
|
||||
{
|
||||
h8state.irq_cb = callback;
|
||||
}
|
||||
|
||||
const char *h8_3002_info(void *context, int regnum)
|
||||
{
|
||||
static char buffer[16][47+1];
|
||||
static int which = 0;
|
||||
h83xx_state *h8 = &h8state;
|
||||
|
||||
which = (which+1) % 16;
|
||||
buffer[which][0] = '\0';
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case CPU_INFO_REG+H8_PC: sprintf(buffer[which], "PC :%06X", h8->pc); break;
|
||||
case CPU_INFO_REG+H8_CCR: sprintf(buffer[which], "CCR :%02X", h8_get_ccr(h8)); break;
|
||||
case CPU_INFO_REG+H8_E0: sprintf(buffer[which], "ER0 :%08X", h8->regs[0]); break;
|
||||
case CPU_INFO_REG+H8_E1: sprintf(buffer[which], "ER1 :%08X", h8->regs[1]); break;
|
||||
case CPU_INFO_REG+H8_E2: sprintf(buffer[which], "ER2 :%08X", h8->regs[2]); break;
|
||||
case CPU_INFO_REG+H8_E3: sprintf(buffer[which], "ER3 :%08X", h8->regs[3]); break;
|
||||
case CPU_INFO_REG+H8_E4: sprintf(buffer[which], "ER4 :%08X", h8->regs[4]); break;
|
||||
case CPU_INFO_REG+H8_E5: sprintf(buffer[which], "ER5 :%08X", h8->regs[5]); break;
|
||||
case CPU_INFO_REG+H8_E6: sprintf(buffer[which], "ER6 :%08X", h8->regs[6]); break;
|
||||
case CPU_INFO_REG+H8_E7: sprintf(buffer[which], " SP :%08X", h8->regs[7]); break;
|
||||
case CPU_INFO_FLAGS:
|
||||
sprintf(buffer[which], "%c%c%c%c%c%c%c%c",
|
||||
h8->h8iflag ? 'I':'i', h8->h8uiflag ? 'U':'u',
|
||||
h8->h8hflag ? 'H':'h', h8->h8uflag ? 'U':'u',
|
||||
h8->h8nflag ? 'N':'n', h8->h8zflag ? 'Z':'z',
|
||||
h8->h8vflag ? 'V':'v', h8->h8cflag ? 'C':'c');
|
||||
break;
|
||||
case CPU_INFO_NAME: return "H8/3002";
|
||||
case CPU_INFO_FAMILY: return "Hitachi H8/300";
|
||||
case CPU_INFO_VERSION: return "1.0";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "The_Author & DynaChicken (ZiNc), R. Belmont, Luca Elia, Tomasz Slanina";
|
||||
}
|
||||
return buffer[which];
|
||||
}
|
||||
|
||||
unsigned h8_3002_dasm(char *buffer, unsigned pc)
|
||||
{
|
||||
sprintf(buffer, "$%04X", h8_read16(&h8state, pc));
|
||||
return 2;
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/***************************************************************************
|
||||
|
||||
h83002.h : Public constants and function defs for the H8/3002 emulator.
|
||||
|
||||
Backported to the MAME 0.78 CPU interface (mame2003-plus) from the legacy
|
||||
H8/3xx core of MAME 0.152 (original by The_Author & DynaChicken for ZiNc,
|
||||
MAME changes by R. Belmont, Luca Elia, Tomasz Slanina, Tim Schuerewegen,
|
||||
O. Galibert).
|
||||
|
||||
Only the H8/3002 (16-bit, advanced mode, 24-bit address space) is
|
||||
supported. On-chip RAM (0xfffd10-0xffff0f) and the on-chip peripheral
|
||||
registers (0xffff10-0xffffff) are handled inside the core.
|
||||
|
||||
The 0.78 I/O port space is sized after the data bus (16 bit), so the
|
||||
H8 on-chip ports, ADC and serial channels are routed to the driver
|
||||
through the callbacks below instead of a PORT map.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _H83002_H_
|
||||
#define _H83002_H_
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
#define H8_IFLAG 0x80
|
||||
#define H8_UIFLAG 0x40
|
||||
#define H8_HFLAG 0x20
|
||||
#define H8_UFLAG 0x10
|
||||
#define H8_NFLAG 0x08
|
||||
#define H8_ZFLAG 0x04
|
||||
#define H8_VFLAG 0x02
|
||||
#define H8_CFLAG 0x01
|
||||
|
||||
/* registers */
|
||||
enum
|
||||
{
|
||||
H8_E0 = 1,
|
||||
H8_E1,
|
||||
H8_E2,
|
||||
H8_E3,
|
||||
H8_E4,
|
||||
H8_E5,
|
||||
H8_E6,
|
||||
H8_E7,
|
||||
|
||||
H8_PC,
|
||||
H8_CCR
|
||||
};
|
||||
|
||||
/* external interrupt lines */
|
||||
enum
|
||||
{
|
||||
H8_IRQ0 = 0,
|
||||
H8_IRQ1,
|
||||
H8_IRQ2,
|
||||
H8_IRQ3,
|
||||
H8_IRQ4,
|
||||
H8_IRQ5,
|
||||
|
||||
H8_SCI_0_RX, /* incoming character on SCI 0 */
|
||||
H8_SCI_1_RX /* incoming character on SCI 1 */
|
||||
};
|
||||
|
||||
/* I/O "ports" passed to the driver callbacks */
|
||||
enum
|
||||
{
|
||||
/* digital I/O ports */
|
||||
H8_PORT_4 = 3,
|
||||
H8_PORT_6 = 5,
|
||||
H8_PORT_7,
|
||||
H8_PORT_8,
|
||||
H8_PORT_9,
|
||||
H8_PORT_A,
|
||||
H8_PORT_B,
|
||||
|
||||
/* analog inputs */
|
||||
H8_ADC_0_H = 0x20,
|
||||
H8_ADC_0_L,
|
||||
H8_ADC_1_H,
|
||||
H8_ADC_1_L,
|
||||
H8_ADC_2_H,
|
||||
H8_ADC_2_L,
|
||||
H8_ADC_3_H,
|
||||
H8_ADC_3_L,
|
||||
|
||||
/* serial ports */
|
||||
H8_SERIAL_0 = 0x30,
|
||||
H8_SERIAL_1
|
||||
};
|
||||
|
||||
typedef data8_t (*h8_io_read_func)(int port);
|
||||
typedef void (*h8_io_write_func)(int port, data8_t data);
|
||||
|
||||
/* hook the on-chip ports/ADC/serial to the driver (call before reset) */
|
||||
void h8_3002_set_io_handlers(h8_io_read_func readfn, h8_io_write_func writefn);
|
||||
/*
|
||||
Speedup (end 0 = off): memory in start-end only changes outside the
|
||||
H8's timeslice (other CPUs, the H8's own interrupts) and reading it has
|
||||
no side effects. A polling loop on it, "mov.b @aa:24, Rd / bne (or
|
||||
beq) back", leaves the same state on every pass, so once one pass has
|
||||
run in a timeslice the whole passes that still fit are skipped:
|
||||
registers, memory and cycles end up exactly as if they had run.
|
||||
*/
|
||||
void h8_3002_set_idle_poll(UINT32 start, UINT32 end);
|
||||
|
||||
extern int h8_3002_ICount;
|
||||
|
||||
void h8_3002_init(void);
|
||||
void h8_3002_reset(void *param);
|
||||
void h8_3002_exit(void);
|
||||
int h8_3002_execute(int cycles);
|
||||
unsigned h8_3002_get_context(void *dst);
|
||||
void h8_3002_set_context(void *src);
|
||||
unsigned h8_3002_get_reg(int regnum);
|
||||
void h8_3002_set_reg(int regnum, unsigned val);
|
||||
void h8_3002_set_irq_line(int irqline, int state);
|
||||
void h8_3002_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *h8_3002_info(void *context, int regnum);
|
||||
unsigned h8_3002_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,674 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __CYCLES_H__
|
||||
#define __CYCLES_H__
|
||||
|
||||
typedef enum
|
||||
{
|
||||
CYCLES_MOV_REG_REG,
|
||||
CYCLES_MOV_REG_MEM,
|
||||
CYCLES_MOV_MEM_REG,
|
||||
CYCLES_MOV_IMM_REG,
|
||||
CYCLES_MOV_IMM_MEM,
|
||||
CYCLES_MOV_ACC_MEM,
|
||||
CYCLES_MOV_MEM_ACC,
|
||||
CYCLES_MOV_REG_SREG,
|
||||
CYCLES_MOV_MEM_SREG,
|
||||
CYCLES_MOV_SREG_REG,
|
||||
CYCLES_MOV_SREG_MEM,
|
||||
CYCLES_MOVSX_REG_REG,
|
||||
CYCLES_MOVSX_MEM_REG,
|
||||
CYCLES_MOVZX_REG_REG,
|
||||
CYCLES_MOVZX_MEM_REG,
|
||||
CYCLES_PUSH_RM,
|
||||
CYCLES_PUSH_REG_SHORT,
|
||||
CYCLES_PUSH_SREG,
|
||||
CYCLES_PUSH_IMM,
|
||||
CYCLES_PUSHA,
|
||||
CYCLES_POP_RM,
|
||||
CYCLES_POP_REG_SHORT,
|
||||
CYCLES_POP_SREG,
|
||||
CYCLES_POPA,
|
||||
CYCLES_XCHG_REG_REG,
|
||||
CYCLES_XCHG_REG_MEM,
|
||||
CYCLES_IN,
|
||||
CYCLES_IN_VAR,
|
||||
CYCLES_OUT,
|
||||
CYCLES_OUT_VAR,
|
||||
CYCLES_LEA,
|
||||
CYCLES_LDS,
|
||||
CYCLES_LES,
|
||||
CYCLES_LFS,
|
||||
CYCLES_LGS,
|
||||
CYCLES_LSS,
|
||||
CYCLES_CLC,
|
||||
CYCLES_CLD,
|
||||
CYCLES_CLI,
|
||||
CYCLES_CLTS,
|
||||
CYCLES_CMC,
|
||||
CYCLES_LAHF,
|
||||
CYCLES_POPF,
|
||||
CYCLES_PUSHF,
|
||||
CYCLES_SAHF,
|
||||
CYCLES_STC,
|
||||
CYCLES_STD,
|
||||
CYCLES_STI,
|
||||
CYCLES_ALU_REG_REG,
|
||||
CYCLES_ALU_REG_MEM,
|
||||
CYCLES_ALU_MEM_REG,
|
||||
CYCLES_ALU_IMM_REG,
|
||||
CYCLES_ALU_IMM_MEM,
|
||||
CYCLES_ALU_IMM_ACC,
|
||||
CYCLES_INC_REG,
|
||||
CYCLES_INC_MEM,
|
||||
CYCLES_DEC_REG,
|
||||
CYCLES_DEC_MEM,
|
||||
CYCLES_CMP_REG_REG,
|
||||
CYCLES_CMP_REG_MEM,
|
||||
CYCLES_CMP_MEM_REG,
|
||||
CYCLES_CMP_IMM_REG,
|
||||
CYCLES_CMP_IMM_MEM,
|
||||
CYCLES_CMP_IMM_ACC,
|
||||
CYCLES_TEST_REG_REG,
|
||||
CYCLES_TEST_REG_MEM,
|
||||
CYCLES_TEST_IMM_REG,
|
||||
CYCLES_TEST_IMM_MEM,
|
||||
CYCLES_TEST_IMM_ACC,
|
||||
CYCLES_NEG_REG,
|
||||
CYCLES_NEG_MEM,
|
||||
CYCLES_AAA,
|
||||
CYCLES_AAS,
|
||||
CYCLES_DAA,
|
||||
CYCLES_DAS,
|
||||
CYCLES_MUL8_ACC_REG,
|
||||
CYCLES_MUL8_ACC_MEM,
|
||||
CYCLES_MUL16_ACC_REG,
|
||||
CYCLES_MUL16_ACC_MEM,
|
||||
CYCLES_MUL32_ACC_REG,
|
||||
CYCLES_MUL32_ACC_MEM,
|
||||
CYCLES_IMUL8_ACC_REG,
|
||||
CYCLES_IMUL8_ACC_MEM,
|
||||
CYCLES_IMUL16_ACC_REG,
|
||||
CYCLES_IMUL16_ACC_MEM,
|
||||
CYCLES_IMUL32_ACC_REG,
|
||||
CYCLES_IMUL32_ACC_MEM,
|
||||
CYCLES_IMUL8_REG_REG,
|
||||
CYCLES_IMUL8_REG_MEM,
|
||||
CYCLES_IMUL16_REG_REG,
|
||||
CYCLES_IMUL16_REG_MEM,
|
||||
CYCLES_IMUL32_REG_REG,
|
||||
CYCLES_IMUL32_REG_MEM,
|
||||
CYCLES_IMUL16_REG_IMM_REG,
|
||||
CYCLES_IMUL16_MEM_IMM_REG,
|
||||
CYCLES_IMUL32_REG_IMM_REG,
|
||||
CYCLES_IMUL32_MEM_IMM_REG,
|
||||
CYCLES_DIV8_ACC_REG,
|
||||
CYCLES_DIV8_ACC_MEM,
|
||||
CYCLES_DIV16_ACC_REG,
|
||||
CYCLES_DIV16_ACC_MEM,
|
||||
CYCLES_DIV32_ACC_REG,
|
||||
CYCLES_DIV32_ACC_MEM,
|
||||
CYCLES_IDIV8_ACC_REG,
|
||||
CYCLES_IDIV8_ACC_MEM,
|
||||
CYCLES_IDIV16_ACC_REG,
|
||||
CYCLES_IDIV16_ACC_MEM,
|
||||
CYCLES_IDIV32_ACC_REG,
|
||||
CYCLES_IDIV32_ACC_MEM,
|
||||
CYCLES_AAD,
|
||||
CYCLES_AAM,
|
||||
CYCLES_CBW,
|
||||
CYCLES_CWD,
|
||||
CYCLES_ROTATE_REG,
|
||||
CYCLES_ROTATE_MEM,
|
||||
CYCLES_ROTATE_CARRY_REG,
|
||||
CYCLES_ROTATE_CARRY_MEM,
|
||||
CYCLES_SHLD_REG,
|
||||
CYCLES_SHLD_MEM,
|
||||
CYCLES_SHRD_REG,
|
||||
CYCLES_SHRD_MEM,
|
||||
CYCLES_NOT_REG,
|
||||
CYCLES_NOT_MEM,
|
||||
CYCLES_CMPS,
|
||||
CYCLES_INS,
|
||||
CYCLES_LODS,
|
||||
CYCLES_MOVS,
|
||||
CYCLES_OUTS,
|
||||
CYCLES_SCAS,
|
||||
CYCLES_STOS,
|
||||
CYCLES_XLAT,
|
||||
CYCLES_REP_CMPS_BASE,
|
||||
CYCLES_REP_INS_BASE,
|
||||
CYCLES_REP_LODS_BASE,
|
||||
CYCLES_REP_MOVS_BASE,
|
||||
CYCLES_REP_OUTS_BASE,
|
||||
CYCLES_REP_SCAS_BASE,
|
||||
CYCLES_REP_STOS_BASE,
|
||||
CYCLES_REP_CMPS,
|
||||
CYCLES_REP_INS,
|
||||
CYCLES_REP_LODS,
|
||||
CYCLES_REP_MOVS,
|
||||
CYCLES_REP_OUTS,
|
||||
CYCLES_REP_SCAS,
|
||||
CYCLES_REP_STOS,
|
||||
CYCLES_BSF_BASE,
|
||||
CYCLES_BSF,
|
||||
CYCLES_BSR_BASE,
|
||||
CYCLES_BSR,
|
||||
CYCLES_BT_IMM_REG,
|
||||
CYCLES_BT_IMM_MEM,
|
||||
CYCLES_BT_REG_REG,
|
||||
CYCLES_BT_REG_MEM,
|
||||
CYCLES_BTC_IMM_REG,
|
||||
CYCLES_BTC_IMM_MEM,
|
||||
CYCLES_BTC_REG_REG,
|
||||
CYCLES_BTC_REG_MEM,
|
||||
CYCLES_BTR_IMM_REG,
|
||||
CYCLES_BTR_IMM_MEM,
|
||||
CYCLES_BTR_REG_REG,
|
||||
CYCLES_BTR_REG_MEM,
|
||||
CYCLES_BTS_IMM_REG,
|
||||
CYCLES_BTS_IMM_MEM,
|
||||
CYCLES_BTS_REG_REG,
|
||||
CYCLES_BTS_REG_MEM,
|
||||
CYCLES_CALL, /* E8 */
|
||||
CYCLES_CALL_REG, /* FF /2 */
|
||||
CYCLES_CALL_MEM, /* FF /2 */
|
||||
CYCLES_CALL_INTERSEG, /* 9A */
|
||||
CYCLES_CALL_REG_INTERSEG, /* FF /3 */
|
||||
CYCLES_CALL_MEM_INTERSEG, /* FF /3 */
|
||||
CYCLES_JMP_SHORT, /* EB */
|
||||
CYCLES_JMP, /* E9 */
|
||||
CYCLES_JMP_REG, /* FF /4 */
|
||||
CYCLES_JMP_MEM, /* FF /4 */
|
||||
CYCLES_JMP_INTERSEG, /* EA */
|
||||
CYCLES_JMP_REG_INTERSEG, /* FF /5 */
|
||||
CYCLES_JMP_MEM_INTERSEG, /* FF /5 */
|
||||
CYCLES_RET, /* C3 */
|
||||
CYCLES_RET_IMM, /* C2 */
|
||||
CYCLES_RET_INTERSEG, /* CB */
|
||||
CYCLES_RET_IMM_INTERSEG, /* CA */
|
||||
CYCLES_JCC_DISP8,
|
||||
CYCLES_JCC_FULL_DISP,
|
||||
CYCLES_JCC_DISP8_NOBRANCH,
|
||||
CYCLES_JCC_FULL_DISP_NOBRANCH,
|
||||
CYCLES_JCXZ,
|
||||
CYCLES_JCXZ_NOBRANCH,
|
||||
CYCLES_LOOP,
|
||||
CYCLES_LOOPZ,
|
||||
CYCLES_LOOPNZ,
|
||||
CYCLES_SETCC_REG,
|
||||
CYCLES_SETCC_MEM,
|
||||
CYCLES_ENTER,
|
||||
CYCLES_LEAVE,
|
||||
CYCLES_INT,
|
||||
CYCLES_INT3,
|
||||
CYCLES_INTO_OF1,
|
||||
CYCLES_INTO_OF0,
|
||||
CYCLES_BOUND_IN_RANGE,
|
||||
CYCLES_BOUND_OUT_RANGE,
|
||||
CYCLES_IRET,
|
||||
CYCLES_HLT,
|
||||
CYCLES_MOV_REG_CR0,
|
||||
CYCLES_MOV_REG_CR2,
|
||||
CYCLES_MOV_REG_CR3,
|
||||
CYCLES_MOV_CR_REG,
|
||||
CYCLES_MOV_REG_DR0_3,
|
||||
CYCLES_MOV_REG_DR6_7,
|
||||
CYCLES_MOV_DR6_7_REG,
|
||||
CYCLES_MOV_DR0_3_REG,
|
||||
CYCLES_MOV_REG_TR6_7,
|
||||
CYCLES_MOV_TR6_7_REG,
|
||||
CYCLES_NOP,
|
||||
CYCLES_WAIT,
|
||||
CYCLES_ARPL_REG,
|
||||
CYCLES_ARPL_MEM,
|
||||
CYCLES_LAR_REG,
|
||||
CYCLES_LAR_MEM,
|
||||
CYCLES_LGDT,
|
||||
CYCLES_LIDT,
|
||||
CYCLES_LLDT_REG,
|
||||
CYCLES_LLDT_MEM,
|
||||
CYCLES_LMSW_REG,
|
||||
CYCLES_LMSW_MEM,
|
||||
CYCLES_LSL_REG,
|
||||
CYCLES_LSL_MEM,
|
||||
CYCLES_LTR_REG,
|
||||
CYCLES_LTR_MEM,
|
||||
CYCLES_SGDT,
|
||||
CYCLES_SIDT,
|
||||
CYCLES_SLDT_REG,
|
||||
CYCLES_SLDT_MEM,
|
||||
CYCLES_SMSW_REG,
|
||||
CYCLES_SMSW_MEM,
|
||||
CYCLES_STR_REG,
|
||||
CYCLES_STR_MEM,
|
||||
CYCLES_VERR_REG,
|
||||
CYCLES_VERR_MEM,
|
||||
CYCLES_VERW_REG,
|
||||
CYCLES_VERW_MEM,
|
||||
CYCLES_LOCK,
|
||||
|
||||
CYCLES_BSWAP,
|
||||
CYCLES_CMPXCHG8B,
|
||||
CYCLES_CMPXCHG,
|
||||
CYCLES_CPUID,
|
||||
CYCLES_CPUID_EAX1,
|
||||
CYCLES_INVD,
|
||||
CYCLES_XADD,
|
||||
CYCLES_RDTSC,
|
||||
CYCLES_RSM,
|
||||
CYCLES_RDMSR,
|
||||
|
||||
CYCLES_FABS,
|
||||
CYCLES_FADD,
|
||||
CYCLES_FBLD,
|
||||
CYCLES_FBSTP,
|
||||
CYCLES_FCHS,
|
||||
CYCLES_FCLEX,
|
||||
CYCLES_FCOM,
|
||||
CYCLES_FCOS,
|
||||
CYCLES_FDECSTP,
|
||||
CYCLES_FDISI,
|
||||
CYCLES_FDIV,
|
||||
CYCLES_FDIVR,
|
||||
CYCLES_FENI,
|
||||
CYCLES_FFREE,
|
||||
CYCLES_FIADD,
|
||||
CYCLES_FICOM,
|
||||
CYCLES_FIDIV,
|
||||
CYCLES_FILD,
|
||||
CYCLES_FIMUL,
|
||||
CYCLES_FINCSTP,
|
||||
CYCLES_FINIT,
|
||||
CYCLES_FIST,
|
||||
CYCLES_FISUB,
|
||||
CYCLES_FLD,
|
||||
CYCLES_FLDZ,
|
||||
CYCLES_FLD1,
|
||||
CYCLES_FLDL2E,
|
||||
CYCLES_FLDL2T,
|
||||
CYCLES_FLDLG2,
|
||||
CYCLES_FLDLN2,
|
||||
CYCLES_FLDPI,
|
||||
CYCLES_FLDCW,
|
||||
CYCLES_FLDENV,
|
||||
CYCLES_FMUL,
|
||||
CYCLES_FNOP,
|
||||
CYCLES_FPATAN,
|
||||
CYCLES_FPREM,
|
||||
CYCLES_FPREM1,
|
||||
CYCLES_FPTAN,
|
||||
CYCLES_FRNDINT,
|
||||
CYCLES_FRSTOR,
|
||||
CYCLES_FSAVE,
|
||||
CYCLES_FSCALE,
|
||||
CYCLES_FSETPM,
|
||||
CYCLES_FSIN,
|
||||
CYCLES_FSINCOS,
|
||||
CYCLES_FSQRT,
|
||||
CYCLES_FST,
|
||||
CYCLES_FSTCW,
|
||||
CYCLES_FSTENV,
|
||||
CYCLES_FSTSW,
|
||||
CYCLES_FSUB,
|
||||
CYCLES_FSUBR,
|
||||
CYCLES_FTST,
|
||||
CYCLES_FUCOM,
|
||||
CYCLES_FXAM,
|
||||
CYCLES_FXCH,
|
||||
CYCLES_FXTRACT,
|
||||
CYCLES_FYL2X,
|
||||
CYCLES_FYL2XPI,
|
||||
CYCLES_CMPXCHG_REG_REG_T,
|
||||
CYCLES_CMPXCHG_REG_REG_F,
|
||||
CYCLES_CMPXCHG_REG_MEM_T,
|
||||
CYCLES_CMPXCHG_REG_MEM_F,
|
||||
CYCLES_XADD_REG_REG,
|
||||
CYCLES_XADD_REG_MEM,
|
||||
|
||||
CYCLES_NUM_OPCODES
|
||||
} X86_CYCLES;
|
||||
|
||||
|
||||
#define X86_NUM_CPUS 4
|
||||
#define CPU_CYCLES_I386 0
|
||||
#define CPU_CYCLES_I486 1
|
||||
#define CPU_CYCLES_PENTIUM 2
|
||||
#define CPU_CYCLES_MEDIAGX 3
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
X86_CYCLES op;
|
||||
UINT8 cpu_cycles[X86_NUM_CPUS][2];
|
||||
} X86_CYCLE_TABLE;
|
||||
|
||||
static const X86_CYCLE_TABLE x86_cycle_table[] =
|
||||
{
|
||||
/* opcode rm/pmode */
|
||||
/* i386 i486 pentium mediagx */
|
||||
{ CYCLES_MOV_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_REG_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_MEM_REG, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_IMM_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_ACC_MEM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_MEM_ACC, { { 4, 4 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_MOV_REG_SREG, { { 2, 18 }, { 3, 3 }, { 2, 2 }, { 1, 6 } } },
|
||||
{ CYCLES_MOV_MEM_SREG, { { 5, 19 }, { 9, 9 }, { 3, 3 }, { 1, 6 } } },
|
||||
{ CYCLES_MOV_SREG_REG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } },
|
||||
{ CYCLES_MOV_SREG_MEM, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 6 } } },
|
||||
{ CYCLES_MOVSX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_MOVSX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_MOVZX_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_MOVZX_MEM_REG, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSH_RM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_PUSH_REG_SHORT, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSH_SREG, { { 2, 2 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSH_IMM, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_PUSHA, { { 18, 18 }, { 11, 11 }, { 5, 5 }, { 11, 11 } } },
|
||||
{ CYCLES_POP_RM, { { 5, 5 }, { 4, 4 }, { 3, 3 }, { 4, 4 } } },
|
||||
{ CYCLES_POP_REG_SHORT, { { 4, 4 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_POP_SREG, { { 7, 21 }, { 3, 3 }, { 3, 3 }, { 1, 6 } } },
|
||||
{ CYCLES_POPA, { { 24, 24 }, { 9, 9 }, { 5, 5 }, { 9, 9 } } },
|
||||
{ CYCLES_XCHG_REG_REG, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_XCHG_REG_MEM, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_IN, { { 12, 26 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } },
|
||||
{ CYCLES_IN_VAR, { { 13, 27 }, { 14, 27 }, { 7, 19 }, { 8, 8 } } },
|
||||
{ CYCLES_OUT, { { 10, 24 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } },
|
||||
{ CYCLES_OUT_VAR, { { 11, 25 }, { 16, 29 }, { 12, 24 }, { 14, 14 } } },
|
||||
{ CYCLES_LEA, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_LDS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LES, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LFS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LGS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 9 } } },
|
||||
{ CYCLES_LSS, { { 7, 22 }, { 6, 12 }, { 4, 4 }, { 4, 10 } } },
|
||||
{ CYCLES_CLC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CLD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } },
|
||||
{ CYCLES_CLI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } },
|
||||
{ CYCLES_CLTS, { { 6, 6 }, { 7, 7 }, { 10, 10 }, { 7, 7 } } },
|
||||
{ CYCLES_CMC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_LAHF, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } },
|
||||
{ CYCLES_POPF, { { 5, 5 }, { 9, 9 }, { 6, 6 }, { 8, 8 } } },
|
||||
{ CYCLES_PUSHF, { { 4, 4 }, { 4, 4 }, { 9, 9 }, { 2, 2 } } },
|
||||
{ CYCLES_SAHF, { { 3, 3 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_STC, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_STD, { { 2, 2 }, { 2, 2 }, { 2, 2 }, { 4, 4 } } },
|
||||
{ CYCLES_STI, { { 8, 8 }, { 5, 5 }, { 7, 7 }, { 6, 6 } } },
|
||||
{ CYCLES_ALU_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_REG_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_IMM_MEM, { { 7, 7 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_ALU_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_INC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_INC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_DEC_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_DEC_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_MEM_REG, { { 6, 6 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_CMP_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_REG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_REG_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_IMM_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_IMM_MEM, { { 5, 5 }, { 2, 2 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_TEST_IMM_ACC, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_NEG_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_NEG_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_AAA, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_AAS, { { 4, 4 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_DAA, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_DAS, { { 4, 4 }, { 2, 2 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_MUL8_ACC_REG, { { 17, 17 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_MUL8_ACC_MEM, { { 20, 20 }, { 13, 13 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_MUL16_ACC_REG, { { 25, 25 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_MUL16_ACC_MEM, { { 28, 28 }, { 13, 13 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_MUL32_ACC_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_MUL32_ACC_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL8_ACC_REG, { { 17, 17 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL8_ACC_MEM, { { 20, 20 }, { 18, 18 }, { 11, 11 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL16_ACC_REG, { { 25, 25 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL16_ACC_MEM, { { 28, 28 }, { 26, 26 }, { 11, 11 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL32_ACC_REG, { { 41, 41 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL32_ACC_MEM, { { 44, 44 }, { 42, 42 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL8_REG_REG, { { 17, 17 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL8_REG_MEM, { { 20, 20 }, { 13, 13 }, { 10, 10 }, { 4, 4 } } },
|
||||
{ CYCLES_IMUL16_REG_REG, { { 25, 25 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL16_REG_MEM, { { 28, 28 }, { 13, 13 }, { 10, 10 }, { 5, 5 } } },
|
||||
{ CYCLES_IMUL32_REG_REG, { { 41, 41 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL32_REG_MEM, { { 44, 44 }, { 13, 13 }, { 10, 10 }, { 15, 15 } } },
|
||||
{ CYCLES_IMUL16_REG_IMM_REG,{ { 26, 26 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } },
|
||||
{ CYCLES_IMUL16_MEM_IMM_REG,{ { 27, 27 }, { 26, 26 }, { 10, 10 }, { 6, 6 } } },
|
||||
{ CYCLES_IMUL32_REG_IMM_REG,{ { 42, 42 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } },
|
||||
{ CYCLES_IMUL32_MEM_IMM_REG,{ { 43, 43 }, { 42, 42 }, { 10, 10 }, { 16, 16 } } },
|
||||
{ CYCLES_DIV8_ACC_REG, { { 14, 14 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } },
|
||||
{ CYCLES_DIV8_ACC_MEM, { { 17, 17 }, { 16, 16 }, { 17, 17 }, { 20, 20 } } },
|
||||
{ CYCLES_DIV16_ACC_REG, { { 22, 22 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } },
|
||||
{ CYCLES_DIV16_ACC_MEM, { { 25, 25 }, { 24, 24 }, { 25, 25 }, { 29, 29 } } },
|
||||
{ CYCLES_DIV32_ACC_REG, { { 38, 38 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } },
|
||||
{ CYCLES_DIV32_ACC_MEM, { { 41, 41 }, { 40, 40 }, { 41, 41 }, { 45, 45 } } },
|
||||
{ CYCLES_IDIV8_ACC_REG, { { 19, 19 }, { 19, 19 }, { 22, 22 }, { 20, 20 } } },
|
||||
{ CYCLES_IDIV8_ACC_MEM, { { 22, 22 }, { 20, 20 }, { 22, 22 }, { 20, 20 } } },
|
||||
{ CYCLES_IDIV16_ACC_REG, { { 27, 27 }, { 27, 27 }, { 30, 30 }, { 29, 29 } } },
|
||||
{ CYCLES_IDIV16_ACC_MEM, { { 30, 30 }, { 28, 28 }, { 30, 30 }, { 29, 29 } } },
|
||||
{ CYCLES_IDIV32_ACC_REG, { { 43, 43 }, { 43, 43 }, { 46, 46 }, { 45, 45 } } },
|
||||
{ CYCLES_IDIV32_ACC_MEM, { { 46, 46 }, { 44, 44 }, { 46, 46 }, { 45, 45 } } },
|
||||
{ CYCLES_AAD, { { 19, 19 }, { 14, 14 }, { 10, 10 }, { 7, 7 } } },
|
||||
{ CYCLES_AAM, { { 17, 17 }, { 15, 15 }, { 18, 18 }, { 19, 19 } } },
|
||||
{ CYCLES_CBW, { { 3, 3 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_CWD, { { 2, 2 }, { 3, 3 }, { 2, 2 }, { 2, 2 } } },
|
||||
{ CYCLES_ROTATE_REG, { { 3, 3 }, { 3, 3 }, { 1, 1 }, { 2, 2 } } },
|
||||
{ CYCLES_ROTATE_MEM, { { 7, 7 }, { 4, 4 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_ROTATE_CARRY_REG, { { 9, 9 }, { 8, 8 }, { 7, 7 }, { 8, 8 } } },
|
||||
{ CYCLES_ROTATE_CARRY_MEM, { { 10, 10 }, { 9, 9 }, { 8, 8 }, { 8, 8 } } },
|
||||
{ CYCLES_SHLD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } },
|
||||
{ CYCLES_SHLD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_SHRD_REG, { { 3, 3 }, { 2, 2 }, { 4, 4 }, { 3, 3 } } },
|
||||
{ CYCLES_SHRD_MEM, { { 7, 7 }, { 3, 3 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_NOT_REG, { { 2, 2 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_NOT_MEM, { { 6, 6 }, { 3, 3 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_CMPS, { { 10, 10 }, { 8, 8 }, { 5, 5 }, { 6, 6 } } },
|
||||
{ CYCLES_INS, { { 15, 29 }, { 17, 30 }, { 9, 22 }, { 11, 11 } } },
|
||||
{ CYCLES_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_OUTS, { { 14, 28 }, { 17, 30 }, { 13, 25 }, { 15, 15 } } },
|
||||
{ CYCLES_SCAS, { { 8, 8 }, { 6, 6 }, { 4, 4 }, { 2, 2 } } },
|
||||
{ CYCLES_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_XLAT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } },
|
||||
{ CYCLES_REP_CMPS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 11, 11 } } },
|
||||
{ CYCLES_REP_INS_BASE, { { 14, 8 }, { 0, 0 }, { 0, 0 }, { 17, 17 } } },
|
||||
{ CYCLES_REP_LODS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
|
||||
{ CYCLES_REP_MOVS_BASE, { { 8, 8 }, { 0, 0 }, { 0, 0 }, { 12, 12 } } },
|
||||
{ CYCLES_REP_OUTS_BASE, { { 12, 6 }, { 0, 0 }, { 0, 0 }, { 24, 24 } } },
|
||||
{ CYCLES_REP_SCAS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
|
||||
{ CYCLES_REP_STOS_BASE, { { 5, 5 }, { 0, 0 }, { 0, 0 }, { 9, 9 } } },
|
||||
{ CYCLES_REP_CMPS, { { 5, 5 }, { 8, 8 }, { 5, 5 }, { 4, 4 } } },
|
||||
{ CYCLES_REP_INS, { { 14, 8 }, { 17, 30 }, { 9, 22 }, { 4, 4 } } },
|
||||
{ CYCLES_REP_LODS, { { 5, 5 }, { 5, 5 }, { 2, 2 }, { 2, 2 } } },
|
||||
{ CYCLES_REP_MOVS, { { 8, 8 }, { 7, 7 }, { 4, 4 }, { 2, 2 } } },
|
||||
{ CYCLES_REP_OUTS, { { 12, 6 }, { 17, 30 }, { 13, 25 }, { 4, 4 } } },
|
||||
{ CYCLES_REP_SCAS, { { 5, 5 }, { 6, 6 }, { 4, 4 }, { 3, 3 } } },
|
||||
{ CYCLES_REP_STOS, { { 5, 5 }, { 5, 5 }, { 3, 3 }, { 2, 2 } } },
|
||||
{ CYCLES_BSF_BASE, { { 11, 11 }, { 6, 6 }, { 6, 6 }, { 4, 4 } } },
|
||||
{ CYCLES_BSF, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_BSR_BASE, { { 9, 9 }, { 6, 6 }, { 7, 7 }, { 4, 4 } } },
|
||||
{ CYCLES_BSR, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_IMM_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_IMM_MEM, { { 6, 6 }, { 6, 6 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_REG_REG, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_BT_REG_MEM, { { 12, 12 }, { 12, 12 }, { 9, 9 }, { 7, 7 } } },
|
||||
{ CYCLES_BTC_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTC_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_BTC_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTC_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
|
||||
{ CYCLES_BTR_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTR_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_BTR_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTR_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
|
||||
{ CYCLES_BTS_IMM_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTS_IMM_MEM, { { 8, 8 }, { 8, 8 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_BTS_REG_REG, { { 6, 6 }, { 6, 6 }, { 7, 7 }, { 2, 2 } } },
|
||||
{ CYCLES_BTS_REG_MEM, { { 13, 13 }, { 13, 13 }, { 13, 13 }, { 8, 8 } } },
|
||||
{ CYCLES_CALL, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 3, 3 } } },
|
||||
{ CYCLES_CALL_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_CALL_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 4, 4 } } },
|
||||
{ CYCLES_CALL_INTERSEG, { { 17, 34 }, { 18, 20 }, { 4, 13 }, { 9, 14 } } },
|
||||
{ CYCLES_CALL_REG_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } },
|
||||
{ CYCLES_CALL_MEM_INTERSEG, { { 22, 38 }, { 17, 20 }, { 4, 14 }, { 11, 15 } } },
|
||||
{ CYCLES_JMP_SHORT, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JMP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JMP_REG, { { 7, 7 }, { 5, 5 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_JMP_MEM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_JMP_INTERSEG, { { 12, 27 }, { 17, 19 }, { 3, 3 }, { 8, 12 } } },
|
||||
{ CYCLES_JMP_REG_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 10 } } },
|
||||
{ CYCLES_JMP_MEM_INTERSEG, { { 17, 31 }, { 13, 18 }, { 4, 4 }, { 10, 13 } } },
|
||||
{ CYCLES_RET, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_RET_IMM, { { 10, 10 }, { 5, 5 }, { 2, 2 }, { 3, 3 } } },
|
||||
{ CYCLES_RET_INTERSEG, { { 18, 32 }, { 13, 13 }, { 4, 4 }, { 10, 13 } } },
|
||||
{ CYCLES_RET_IMM_INTERSEG, { { 18, 32 }, { 14, 14 }, { 4, 4 }, { 10, 13 } } },
|
||||
{ CYCLES_JCC_DISP8, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCC_FULL_DISP, { { 7, 7 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCC_DISP8_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCC_FULL_DISP_NOBRANCH,{ { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_JCXZ, { { 9, 9 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } },
|
||||
{ CYCLES_JCXZ_NOBRANCH, { { 5, 5 }, { 1, 1 }, { 1, 1 }, { 2, 2 } } },
|
||||
{ CYCLES_LOOP, { { 11, 11 }, { 6, 6 }, { 5, 5 }, { 2, 2 } } },
|
||||
{ CYCLES_LOOPZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_LOOPNZ, { { 11, 11 }, { 9, 9 }, { 8, 8 }, { 2, 2 } } },
|
||||
{ CYCLES_SETCC_REG, { { 4, 4 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_SETCC_MEM, { { 5, 5 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_ENTER, { { 10, 10 }, { 14, 14 }, { 11, 11 }, { 13, 13 } } },
|
||||
{ CYCLES_LEAVE, { { 4, 4 }, { 5, 5 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_INT, { { 37, 37 }, { 30, 30 }, { 16, 16 }, { 19, 19 } } },
|
||||
{ CYCLES_INT3, { { 33, 33 }, { 26, 26 }, { 13, 13 }, { 19, 19 } } },
|
||||
{ CYCLES_INTO_OF1, { { 35, 35 }, { 28, 28 }, { 13, 13 }, { 19, 19 } } },
|
||||
{ CYCLES_INTO_OF0, { { 3, 3 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } },
|
||||
{ CYCLES_BOUND_IN_RANGE, { { 10, 10 }, { 7, 7 }, { 8, 8 }, { 7, 7 } } },
|
||||
{ CYCLES_BOUND_OUT_RANGE, { { 44, 44 }, { 7, 7 }, { 8, 8 }, { 8, 8 } } },
|
||||
{ CYCLES_IRET, { { 22, 22 }, { 15, 15 }, { 8, 8 }, { 13, 13 } } },
|
||||
{ CYCLES_HLT, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 10, 10 } } },
|
||||
{ CYCLES_MOV_REG_CR0, { { 11, 11 }, { 16, 16 }, { 16, 16 }, { 20, 18 } } },
|
||||
{ CYCLES_MOV_REG_CR2, { { 4, 4 }, { 4, 4 }, { 4, 4 }, { 5, 5 } } },
|
||||
{ CYCLES_MOV_REG_CR3, { { 5, 5 }, { 4, 4 }, { 4, 4 }, { 5, 6 } } },
|
||||
{ CYCLES_MOV_CR_REG, { { 6, 6 }, { 4, 4 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_MOV_REG_DR0_3, { { 22, 22 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
|
||||
{ CYCLES_MOV_REG_DR6_7, { { 16, 16 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
|
||||
{ CYCLES_MOV_DR6_7_REG, { { 14, 14 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } },
|
||||
{ CYCLES_MOV_DR0_3_REG, { { 22, 22 }, { 11, 11 }, { 11, 11 }, { 9, 9 } } },
|
||||
{ CYCLES_MOV_REG_TR6_7, { { 12, 12 }, { 4, 4 }, { 4, 4 }, { 11, 11 } } },
|
||||
{ CYCLES_MOV_TR6_7_REG, { { 12, 12 }, { 3, 3 }, { 3, 3 }, { 3, 3 } } },
|
||||
{ CYCLES_NOP, { { 3, 3 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_WAIT, { { 7, 7 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_ARPL_REG, { { 0, 20 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } },
|
||||
{ CYCLES_ARPL_MEM, { { 0, 21 }, { 0, 9 }, { 0, 7 }, { 0, 9 } } },
|
||||
{ CYCLES_LAR_REG, { { 0, 15 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LAR_MEM, { { 0, 16 }, { 11, 11 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LGDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } },
|
||||
{ CYCLES_LIDT, { { 11, 11 }, { 11, 11 }, { 6, 6 }, { 10, 10 } } },
|
||||
{ CYCLES_LLDT_REG, { { 0, 20 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } },
|
||||
{ CYCLES_LLDT_MEM, { { 0, 24 }, { 11, 11 }, { 9, 9 }, { 0, 8 } } },
|
||||
{ CYCLES_LMSW_REG, { { 11, 11 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } },
|
||||
{ CYCLES_LMSW_MEM, { { 14, 14 }, { 13, 13 }, { 8, 8 }, { 11, 11 } } },
|
||||
{ CYCLES_LSL_REG, { { 0, 21 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LSL_MEM, { { 0, 22 }, { 10, 10 }, { 8, 8 }, { 0, 9 } } },
|
||||
{ CYCLES_LTR_REG, { { 0, 23 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } },
|
||||
{ CYCLES_LTR_MEM, { { 0, 27 }, { 20, 20 }, { 10, 10 }, { 0, 9 } } },
|
||||
{ CYCLES_SGDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_SIDT, { { 9, 9 }, { 10, 10 }, { 4, 4 }, { 6, 6 } } },
|
||||
{ CYCLES_SLDT_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 1 } } },
|
||||
{ CYCLES_SLDT_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 1 } } },
|
||||
{ CYCLES_SMSW_REG, { { 2, 2 }, { 2, 2 }, { 4, 4 }, { 4, 4 } } },
|
||||
{ CYCLES_SMSW_MEM, { { 2, 2 }, { 3, 3 }, { 4, 4 }, { 4, 4 } } },
|
||||
{ CYCLES_STR_REG, { { 0, 2 }, { 2, 2 }, { 2, 2 }, { 0, 3 } } },
|
||||
{ CYCLES_STR_MEM, { { 0, 2 }, { 3, 3 }, { 2, 2 }, { 0, 3 } } },
|
||||
{ CYCLES_VERR_REG, { { 0, 10 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_VERR_MEM, { { 0, 11 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_VERW_REG, { { 0, 15 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_VERW_MEM, { { 0, 16 }, { 11, 11 }, { 7, 7 }, { 0, 8 } } },
|
||||
{ CYCLES_LOCK, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 1, 1 } } },
|
||||
|
||||
/* i486+ */
|
||||
{ CYCLES_BSWAP, { { 0, 0 }, { 1, 1 }, { 1, 1 }, { 6, 6 } } },
|
||||
{ CYCLES_CMPXCHG, { { 0, 0 }, { 6, 6 }, { 5, 5 }, { 6, 6 } } },
|
||||
{ CYCLES_INVD, { { 0, 0 }, { 4, 4 }, { 15, 15 }, { 20, 20 } } },
|
||||
{ CYCLES_XADD, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 2, 2 } } },
|
||||
|
||||
/* Pentium+ */
|
||||
{ CYCLES_CMPXCHG8B, { { 0, 0 }, { 0, 0 }, { 10, 10 }, { 6, 6 } } },
|
||||
{ CYCLES_CPUID, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } },
|
||||
{ CYCLES_CPUID_EAX1, { { 0, 0 }, { 0, 0 }, { 14, 14 }, { 12, 12 } } },
|
||||
{ CYCLES_RDTSC, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } },
|
||||
{ CYCLES_RSM, { { 0, 0 }, { 0, 0 }, { 82, 82 }, { 57, 57 } } },
|
||||
{ CYCLES_RDMSR, { { 0, 0 }, { 0, 0 }, { 20, 20 }, { 1, 1 } } },
|
||||
|
||||
/* FPU */
|
||||
{ CYCLES_FABS, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FADD, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FBLD, { { 0, 0 }, { 70, 70 }, { 48, 48 }, { 1, 1 } } },
|
||||
{ CYCLES_FBSTP, { { 0, 0 }, {172,172 }, {148,148 }, { 1, 1 } } },
|
||||
{ CYCLES_FCHS, { { 0, 0 }, { 6, 6 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FCLEX, { { 0, 0 }, { 7, 7 }, { 9, 9 }, { 1, 1 } } },
|
||||
{ CYCLES_FCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_FCOS, { { 0, 0 }, {255,255 }, {124,124 }, { 1, 1 } } },
|
||||
{ CYCLES_FDECSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FDISI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FDIV, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } },
|
||||
{ CYCLES_FDIVR, { { 0, 0 }, { 73, 73 }, { 39, 39 }, { 1, 1 } } },
|
||||
{ CYCLES_FENI, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FFREE, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FIADD, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FICOM, { { 0, 0 }, { 16, 16 }, { 8, 8 }, { 1, 1 } } },
|
||||
{ CYCLES_FIDIV, { { 0, 0 }, { 85, 85 }, { 42, 42 }, { 1, 1 } } },
|
||||
{ CYCLES_FILD, { { 0, 0 }, { 13, 13 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FIMUL, { { 0, 0 }, { 23, 23 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FINCSTP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FINIT, { { 0, 0 }, { 17, 17 }, { 16, 16 }, { 1, 1 } } },
|
||||
{ CYCLES_FIST, { { 0, 0 }, { 29, 29 }, { 6, 6 }, { 1, 1 } } },
|
||||
{ CYCLES_FISUB, { { 0, 0 }, { 20, 20 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FLD, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDZ, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FLD1, { { 0, 0 }, { 4, 4 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDL2E, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDL2T, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDLG2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDLN2, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDPI, { { 0, 0 }, { 8, 8 }, { 5, 5 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDCW, { { 0, 0 }, { 4, 4 }, { 7, 7 }, { 1, 1 } } },
|
||||
{ CYCLES_FLDENV, { { 0, 0 }, { 44, 44 }, { 37, 37 }, { 1, 1 } } },
|
||||
{ CYCLES_FMUL, { { 0, 0 }, { 16, 16 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FNOP, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FPATAN, { { 0, 0 }, {218,218 }, {173,173 }, { 1, 1 } } },
|
||||
{ CYCLES_FPREM, { { 0, 0 }, { 70, 70 }, { 16, 16 }, { 1, 1 } } },
|
||||
{ CYCLES_FPREM1, { { 0, 0 }, { 72, 72 }, { 20, 20 }, { 1, 1 } } },
|
||||
{ CYCLES_FPTAN, { { 0, 0 }, {200,200 }, {173,173 }, { 1, 1 } } },
|
||||
{ CYCLES_FRNDINT, { { 0, 0 }, { 21, 21 }, { 9, 9 }, { 1, 1 } } },
|
||||
{ CYCLES_FRSTOR, { { 0, 0 }, {131,131 }, { 75, 75 }, { 1, 1 } } },
|
||||
{ CYCLES_FSAVE, { { 0, 0 }, {154,154 }, {127,127 }, { 1, 1 } } },
|
||||
{ CYCLES_FSCALE, { { 0, 0 }, { 30, 30 }, { 20, 20 }, { 1, 1 } } },
|
||||
{ CYCLES_FSETPM, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FSIN, { { 0, 0 }, {255,255 }, {126,126 }, { 1, 1 } } },
|
||||
{ CYCLES_FSINCOS, { { 0, 0 }, {255,255 }, {137,137 }, { 1, 1 } } },
|
||||
{ CYCLES_FSQRT, { { 0, 0 }, { 83, 83 }, { 70, 70 }, { 1, 1 } } },
|
||||
{ CYCLES_FST, { { 0, 0 }, { 3, 3 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FSTCW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FSTENV, { { 0, 0 }, { 67, 67 }, { 48, 48 }, { 1, 1 } } },
|
||||
{ CYCLES_FSTSW, { { 0, 0 }, { 3, 3 }, { 2, 2 }, { 1, 1 } } },
|
||||
{ CYCLES_FSUB, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FSUBR, { { 0, 0 }, { 8, 8 }, { 3, 3 }, { 1, 1 } } },
|
||||
{ CYCLES_FTST, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_FUCOM, { { 0, 0 }, { 4, 4 }, { 4, 4 }, { 1, 1 } } },
|
||||
{ CYCLES_FXAM, { { 0, 0 }, { 8, 8 }, { 21, 21 }, { 1, 1 } } },
|
||||
{ CYCLES_FXCH, { { 0, 0 }, { 4, 4 }, { 1, 1 }, { 1, 1 } } },
|
||||
{ CYCLES_FXTRACT, { { 0, 0 }, { 16, 16 }, { 13, 13 }, { 1, 1 } } },
|
||||
{ CYCLES_FYL2X, { { 0, 0 }, {196,196 }, {111,111 }, { 1, 1 } } },
|
||||
{ CYCLES_FYL2XPI, { { 0, 0 }, {171,171 }, {103,103 }, { 1, 1 } } },
|
||||
{ CYCLES_CMPXCHG_REG_REG_T, { { 0, 0 }, { 6, 6 }, { 6, 6 }, { 6, 6 } } },
|
||||
{ CYCLES_CMPXCHG_REG_REG_F, { { 0, 0 }, { 9, 9 }, { 9, 9 }, { 9, 9 } } },
|
||||
{ CYCLES_CMPXCHG_REG_MEM_T, { { 0, 0 }, { 7, 7 }, { 7, 7 }, { 7, 7 } } },
|
||||
{ CYCLES_CMPXCHG_REG_MEM_F, { { 0, 0 }, { 10, 10 }, { 10, 10 }, { 10, 10 } } },
|
||||
};
|
||||
|
||||
#endif /* __CYCLES_H__ */
|
||||
@@ -0,0 +1,868 @@
|
||||
/*
|
||||
Intel 386 emulator
|
||||
|
||||
Written by Ville Linde
|
||||
|
||||
Currently supports:
|
||||
Intel 386
|
||||
Intel 486
|
||||
Intel Pentium
|
||||
Cyrix MediaGX
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "i386priv.h"
|
||||
#include "i386.h"
|
||||
#include "mamedbg.h"
|
||||
|
||||
int i386_ICount;
|
||||
|
||||
/* the 0.139 core stops on what it does not implement; here it is logged once */
|
||||
static void i386_fatal(const char *fmt, ...)
|
||||
{
|
||||
static int reported;
|
||||
if (!reported)
|
||||
{
|
||||
char buf[256];
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
vsprintf(buf, fmt, va);
|
||||
va_end(va);
|
||||
log_cb(RETRO_LOG_ERROR, LOGPRE "%s\n", buf);
|
||||
reported = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* seems to be defined on mingw-gcc */
|
||||
#undef i386
|
||||
|
||||
int i386_parity_table[256];
|
||||
MODRM_TABLE i386_MODRM_table[256];
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
#define INT_DEBUG 1
|
||||
|
||||
static void i386_load_protected_mode_segment(i386_state *cpustate, I386_SREG *seg )
|
||||
{
|
||||
UINT32 v1,v2;
|
||||
UINT32 base, limit;
|
||||
int entry;
|
||||
|
||||
if ( seg->selector & 0x4 )
|
||||
{
|
||||
base = cpustate->ldtr.base;
|
||||
limit = cpustate->ldtr.limit;
|
||||
} else {
|
||||
base = cpustate->gdtr.base;
|
||||
limit = cpustate->gdtr.limit;
|
||||
}
|
||||
|
||||
if (limit == 0 || seg->selector + 7 > limit)
|
||||
return;
|
||||
entry = seg->selector & ~0x7;
|
||||
|
||||
v1 = READ32(cpustate, base + entry );
|
||||
v2 = READ32(cpustate, base + entry + 4 );
|
||||
|
||||
seg->flags = (v2 >> 8) & 0xf0ff;
|
||||
seg->base = (v2 & 0xff000000) | ((v2 & 0xff) << 16) | ((v1 >> 16) & 0xffff);
|
||||
seg->limit = (v2 & 0xf0000) | (v1 & 0xffff);
|
||||
if (seg->flags & 0x8000)
|
||||
seg->limit = (seg->limit << 12) | 0xfff;
|
||||
seg->d = (seg->flags & 0x4000) ? 1 : 0;
|
||||
}
|
||||
|
||||
static void i386_load_segment_descriptor(i386_state *cpustate, int segment )
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
if (!V8086_MODE)
|
||||
i386_load_protected_mode_segment(cpustate, &cpustate->sreg[segment] );
|
||||
else
|
||||
{
|
||||
cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
|
||||
cpustate->sreg[segment].limit = 0xffff;
|
||||
cpustate->sreg[segment].flags = (segment == CS) ? 0x009a : 0x0092;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cpustate->sreg[segment].base = cpustate->sreg[segment].selector << 4;
|
||||
|
||||
if( segment == CS && !cpustate->performed_intersegment_jump )
|
||||
cpustate->sreg[segment].base |= 0xfff00000;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 get_flags(i386_state *cpustate)
|
||||
{
|
||||
UINT32 f = 0x2;
|
||||
f |= cpustate->CF;
|
||||
f |= cpustate->PF << 2;
|
||||
f |= cpustate->AF << 4;
|
||||
f |= cpustate->ZF << 6;
|
||||
f |= cpustate->SF << 7;
|
||||
f |= cpustate->TF << 8;
|
||||
f |= cpustate->IF << 9;
|
||||
f |= cpustate->DF << 10;
|
||||
f |= cpustate->OF << 11;
|
||||
f |= cpustate->IOP1 << 12;
|
||||
f |= cpustate->IOP2 << 13;
|
||||
f |= cpustate->NT << 14;
|
||||
return (cpustate->eflags & cpustate->eflags_mask) | (f & 0xffff);
|
||||
}
|
||||
|
||||
static void set_flags(i386_state *cpustate, UINT32 f )
|
||||
{
|
||||
cpustate->CF = (f & 0x1) ? 1 : 0;
|
||||
cpustate->PF = (f & 0x4) ? 1 : 0;
|
||||
cpustate->AF = (f & 0x10) ? 1 : 0;
|
||||
cpustate->ZF = (f & 0x40) ? 1 : 0;
|
||||
cpustate->SF = (f & 0x80) ? 1 : 0;
|
||||
cpustate->TF = (f & 0x100) ? 1 : 0;
|
||||
cpustate->IF = (f & 0x200) ? 1 : 0;
|
||||
cpustate->DF = (f & 0x400) ? 1 : 0;
|
||||
cpustate->OF = (f & 0x800) ? 1 : 0;
|
||||
cpustate->IOP1 = (f & 0x1000) ? 1 : 0;
|
||||
cpustate->IOP2 = (f & 0x2000) ? 1 : 0;
|
||||
cpustate->NT = (f & 0x4000) ? 1 : 0;
|
||||
cpustate->eflags = f & cpustate->eflags_mask;
|
||||
}
|
||||
|
||||
static void sib_byte(i386_state *cpustate,UINT8 mod, UINT32* out_ea, UINT8* out_segment)
|
||||
{
|
||||
UINT32 ea = 0;
|
||||
UINT8 segment = 0;
|
||||
UINT8 scale, i, base;
|
||||
UINT8 sib = FETCH(cpustate);
|
||||
scale = (sib >> 6) & 0x3;
|
||||
i = (sib >> 3) & 0x7;
|
||||
base = sib & 0x7;
|
||||
|
||||
switch( base )
|
||||
{
|
||||
case 0: ea = REG32(EAX); segment = DS; break;
|
||||
case 1: ea = REG32(ECX); segment = DS; break;
|
||||
case 2: ea = REG32(EDX); segment = DS; break;
|
||||
case 3: ea = REG32(EBX); segment = DS; break;
|
||||
case 4: ea = REG32(ESP); segment = SS; break;
|
||||
case 5:
|
||||
if( mod == 0 ) {
|
||||
ea = FETCH32(cpustate);
|
||||
segment = DS;
|
||||
} else if( mod == 1 ) {
|
||||
ea = REG32(EBP);
|
||||
segment = SS;
|
||||
} else if( mod == 2 ) {
|
||||
ea = REG32(EBP);
|
||||
segment = SS;
|
||||
}
|
||||
break;
|
||||
case 6: ea = REG32(ESI); segment = DS; break;
|
||||
case 7: ea = REG32(EDI); segment = DS; break;
|
||||
}
|
||||
switch( i )
|
||||
{
|
||||
case 0: ea += REG32(EAX) * (1 << scale); break;
|
||||
case 1: ea += REG32(ECX) * (1 << scale); break;
|
||||
case 2: ea += REG32(EDX) * (1 << scale); break;
|
||||
case 3: ea += REG32(EBX) * (1 << scale); break;
|
||||
case 4: break;
|
||||
case 5: ea += REG32(EBP) * (1 << scale); break;
|
||||
case 6: ea += REG32(ESI) * (1 << scale); break;
|
||||
case 7: ea += REG32(EDI) * (1 << scale); break;
|
||||
}
|
||||
*out_ea = ea;
|
||||
*out_segment = segment;
|
||||
}
|
||||
|
||||
static void modrm_to_EA(i386_state *cpustate,UINT8 mod_rm, UINT32* out_ea, UINT8* out_segment)
|
||||
{
|
||||
INT8 disp8;
|
||||
INT16 disp16;
|
||||
INT32 disp32;
|
||||
UINT8 mod = (mod_rm >> 6) & 0x3;
|
||||
UINT8 rm = mod_rm & 0x7;
|
||||
UINT32 ea;
|
||||
UINT8 segment;
|
||||
|
||||
if( mod_rm >= 0xc0 )
|
||||
i386_fatal("i386: Called modrm_to_EA with modrm value %02X !",mod_rm);
|
||||
|
||||
if( cpustate->address_size ) {
|
||||
switch( rm )
|
||||
{
|
||||
default:
|
||||
case 0: ea = REG32(EAX); segment = DS; break;
|
||||
case 1: ea = REG32(ECX); segment = DS; break;
|
||||
case 2: ea = REG32(EDX); segment = DS; break;
|
||||
case 3: ea = REG32(EBX); segment = DS; break;
|
||||
case 4: sib_byte(cpustate, mod, &ea, &segment ); break;
|
||||
case 5:
|
||||
if( mod == 0 ) {
|
||||
ea = FETCH32(cpustate); segment = DS;
|
||||
} else {
|
||||
ea = REG32(EBP); segment = SS;
|
||||
}
|
||||
break;
|
||||
case 6: ea = REG32(ESI); segment = DS; break;
|
||||
case 7: ea = REG32(EDI); segment = DS; break;
|
||||
}
|
||||
if( mod == 1 ) {
|
||||
disp8 = FETCH(cpustate);
|
||||
ea += (INT32)disp8;
|
||||
} else if( mod == 2 ) {
|
||||
disp32 = FETCH32(cpustate);
|
||||
ea += disp32;
|
||||
}
|
||||
|
||||
if( cpustate->segment_prefix )
|
||||
segment = cpustate->segment_override;
|
||||
|
||||
*out_ea = ea;
|
||||
*out_segment = segment;
|
||||
|
||||
} else {
|
||||
switch( rm )
|
||||
{
|
||||
default:
|
||||
case 0: ea = REG16(BX) + REG16(SI); segment = DS; break;
|
||||
case 1: ea = REG16(BX) + REG16(DI); segment = DS; break;
|
||||
case 2: ea = REG16(BP) + REG16(SI); segment = SS; break;
|
||||
case 3: ea = REG16(BP) + REG16(DI); segment = SS; break;
|
||||
case 4: ea = REG16(SI); segment = DS; break;
|
||||
case 5: ea = REG16(DI); segment = DS; break;
|
||||
case 6:
|
||||
if( mod == 0 ) {
|
||||
ea = FETCH16(cpustate); segment = DS;
|
||||
} else {
|
||||
ea = REG16(BP); segment = SS;
|
||||
}
|
||||
break;
|
||||
case 7: ea = REG16(BX); segment = DS; break;
|
||||
}
|
||||
if( mod == 1 ) {
|
||||
disp8 = FETCH(cpustate);
|
||||
ea += (INT32)disp8;
|
||||
} else if( mod == 2 ) {
|
||||
disp16 = FETCH16(cpustate);
|
||||
ea += (INT32)disp16;
|
||||
}
|
||||
|
||||
if( cpustate->segment_prefix )
|
||||
segment = cpustate->segment_override;
|
||||
|
||||
*out_ea = ea & 0xffff;
|
||||
*out_segment = segment;
|
||||
}
|
||||
}
|
||||
|
||||
static UINT32 GetNonTranslatedEA(i386_state *cpustate,UINT8 modrm)
|
||||
{
|
||||
UINT8 segment;
|
||||
UINT32 ea;
|
||||
modrm_to_EA(cpustate, modrm, &ea, &segment );
|
||||
return ea;
|
||||
}
|
||||
|
||||
static UINT32 GetEA(i386_state *cpustate,UINT8 modrm)
|
||||
{
|
||||
UINT8 segment;
|
||||
UINT32 ea;
|
||||
modrm_to_EA(cpustate, modrm, &ea, &segment );
|
||||
return i386_translate(cpustate, segment, ea );
|
||||
}
|
||||
|
||||
static void i386_trap(i386_state *cpustate,int irq, int irq_gate)
|
||||
{
|
||||
/* I386 Interrupts/Traps/Faults:
|
||||
*
|
||||
* 0x00 Divide by zero
|
||||
* 0x01 Debug exception
|
||||
* 0x02 NMI
|
||||
* 0x03 Int3
|
||||
* 0x04 Overflow
|
||||
* 0x05 Array bounds check
|
||||
* 0x06 Illegal Opcode
|
||||
* 0x07 FPU not available
|
||||
* 0x08 Double fault
|
||||
* 0x09 Coprocessor segment overrun
|
||||
* 0x0a Invalid task state
|
||||
* 0x0b Segment not present
|
||||
* 0x0c Stack exception
|
||||
* 0x0d General Protection Fault
|
||||
* 0x0e Page fault
|
||||
* 0x0f Reserved
|
||||
* 0x10 Coprocessor error
|
||||
*/
|
||||
UINT32 v1, v2;
|
||||
UINT32 offset;
|
||||
UINT16 segment;
|
||||
int entry = irq * (PROTECTED_MODE ? 8 : 4);
|
||||
|
||||
/* Check if IRQ is out of IDTR's bounds */
|
||||
if( entry > cpustate->idtr.limit ) {
|
||||
i386_fatal("I386 Interrupt: IRQ out of IDTR bounds (IRQ: %d, IDTR Limit: %d)", irq, cpustate->idtr.limit);
|
||||
}
|
||||
|
||||
if( !(PROTECTED_MODE) )
|
||||
{
|
||||
/* 16-bit */
|
||||
PUSH16(cpustate, get_flags(cpustate) & 0xffff );
|
||||
PUSH16(cpustate, cpustate->sreg[CS].selector );
|
||||
PUSH16(cpustate, cpustate->eip );
|
||||
|
||||
cpustate->sreg[CS].selector = READ16(cpustate, cpustate->idtr.base + entry + 2 );
|
||||
cpustate->eip = READ16(cpustate, cpustate->idtr.base + entry );
|
||||
|
||||
/* Interrupts that vector through either interrupt gates or trap gates cause TF */
|
||||
/* (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS. */
|
||||
cpustate->TF = 0;
|
||||
|
||||
if (irq_gate)
|
||||
{
|
||||
cpustate->IF = 0;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
int type;
|
||||
/* 32-bit */
|
||||
|
||||
v1 = READ32(cpustate, cpustate->idtr.base + entry );
|
||||
v2 = READ32(cpustate, cpustate->idtr.base + entry + 4 );
|
||||
offset = (v2 & 0xffff0000) | (v1 & 0xffff);
|
||||
segment = (v1 >> 16) & 0xffff;
|
||||
type = (v2>>8) & 0x1F;
|
||||
|
||||
if(type != 0x0e && type != 0x0f) /* if not 386 interrupt or trap gate */
|
||||
{
|
||||
PUSH16(cpustate, get_flags(cpustate) & 0xffff );
|
||||
PUSH16(cpustate, cpustate->sreg[CS].selector );
|
||||
PUSH16(cpustate, cpustate->eip );
|
||||
}
|
||||
else
|
||||
{
|
||||
PUSH32(cpustate, get_flags(cpustate) & 0x00fcffff );
|
||||
PUSH32(cpustate, cpustate->sreg[CS].selector );
|
||||
PUSH32(cpustate, cpustate->eip );
|
||||
}
|
||||
|
||||
cpustate->sreg[CS].selector = segment;
|
||||
cpustate->eip = offset;
|
||||
|
||||
/* Interrupts that vector through either interrupt gates or trap gates cause TF */
|
||||
/* (the trap flag) to be reset after the current value of TF is saved on the stack as part of EFLAGS. */
|
||||
if ((type == 14) || (type==15))
|
||||
cpustate->TF = 0;
|
||||
|
||||
if (type == 14)
|
||||
{
|
||||
cpustate->IF = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
i386_load_segment_descriptor(cpustate,CS);
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
|
||||
}
|
||||
|
||||
static void i386_check_irq_line(i386_state *cpustate)
|
||||
{
|
||||
/* Check if the interrupts are enabled */
|
||||
if ( (cpustate->irq_state) && cpustate->IF )
|
||||
{
|
||||
i386_ICount -= 2;
|
||||
i386_trap(cpustate,cpustate->irq_callback(0), 1);
|
||||
}
|
||||
}
|
||||
|
||||
#include "cycles.h"
|
||||
|
||||
static UINT8 *cycle_table_rm[X86_NUM_CPUS];
|
||||
static UINT8 *cycle_table_pm[X86_NUM_CPUS];
|
||||
|
||||
#define CYCLES_NUM(x) (i386_ICount -= (x))
|
||||
|
||||
static INLINE void CYCLES(i386_state *cpustate,int x)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_pm[x];
|
||||
}
|
||||
else
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_rm[x];
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE void CYCLES_RM(i386_state *cpustate,int modrm, int r, int m)
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_pm[r];
|
||||
}
|
||||
else
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_rm[r];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (PROTECTED_MODE)
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_pm[m];
|
||||
}
|
||||
else
|
||||
{
|
||||
i386_ICount -= cpustate->cycle_table_rm[m];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static UINT8 cycle_tables[X86_NUM_CPUS][2][CYCLES_NUM_OPCODES];
|
||||
|
||||
static void build_cycle_table(void)
|
||||
{
|
||||
int i, j;
|
||||
for (j=0; j < X86_NUM_CPUS; j++)
|
||||
{
|
||||
cycle_table_rm[j] = cycle_tables[j][0];
|
||||
cycle_table_pm[j] = cycle_tables[j][1];
|
||||
|
||||
for (i=0; i < sizeof(x86_cycle_table)/sizeof(X86_CYCLE_TABLE); i++)
|
||||
{
|
||||
int opcode = x86_cycle_table[i].op;
|
||||
cycle_table_rm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][0];
|
||||
cycle_table_pm[j][opcode] = x86_cycle_table[i].cpu_cycles[j][1];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Forward declarations */
|
||||
static void I386OP(decode_opcode)(i386_state *cpustate);
|
||||
static void I386OP(decode_two_byte)(i386_state *cpustate);
|
||||
|
||||
|
||||
|
||||
#include "i386ops.c"
|
||||
#include "i386op16.c"
|
||||
#include "i386op32.c"
|
||||
#include "i486ops.c"
|
||||
#include "pentops.c"
|
||||
#include "x87ops.c"
|
||||
#include "i386ops.h"
|
||||
|
||||
static void I386OP(decode_opcode)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table1_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table1_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/* Two-byte opcode prefix */
|
||||
static void I386OP(decode_two_byte)(i386_state *cpustate)
|
||||
{
|
||||
cpustate->opcode = FETCH(cpustate);
|
||||
if( cpustate->operand_size )
|
||||
cpustate->opcode_table2_32[cpustate->opcode](cpustate);
|
||||
else
|
||||
cpustate->opcode_table2_16[cpustate->opcode](cpustate);
|
||||
}
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
static void build_opcode_table(i386_state *cpustate, UINT32 features)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i < 256; i++)
|
||||
{
|
||||
cpustate->opcode_table1_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table1_32[i] = I386OP(invalid);
|
||||
cpustate->opcode_table2_16[i] = I386OP(invalid);
|
||||
cpustate->opcode_table2_32[i] = I386OP(invalid);
|
||||
}
|
||||
|
||||
for (i=0; i < sizeof(x86_opcode_table)/sizeof(X86_OPCODE); i++)
|
||||
{
|
||||
const X86_OPCODE *op = &x86_opcode_table[i];
|
||||
|
||||
if ((op->flags & features))
|
||||
{
|
||||
if (op->flags & OP_2BYTE)
|
||||
{
|
||||
cpustate->opcode_table2_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table2_16[op->opcode] = op->handler16;
|
||||
}
|
||||
else
|
||||
{
|
||||
cpustate->opcode_table1_32[op->opcode] = op->handler32;
|
||||
cpustate->opcode_table1_16[op->opcode] = op->handler16;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************************
|
||||
|
||||
The interface of the CPU core (MAME 0.78 style): one context, copied
|
||||
in and out by the CPU switch
|
||||
|
||||
*************************************************************************/
|
||||
|
||||
static i386_state I;
|
||||
|
||||
static void i386_postload(void)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
int i;
|
||||
for (i = 0; i < 6; i++)
|
||||
i386_load_segment_descriptor(cpustate,i);
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
}
|
||||
|
||||
/* the fast memory regions of the driver */
|
||||
static struct
|
||||
{
|
||||
UINT32 start, end;
|
||||
UINT8 *base;
|
||||
int flags;
|
||||
} i386_fastmem[I386_FASTMEM_MAX];
|
||||
static int i386_fastmem_count;
|
||||
|
||||
void i386_set_fastmem(UINT32 start, UINT32 end, UINT8 *base, int flags)
|
||||
{
|
||||
if (i386_fastmem_count < I386_FASTMEM_MAX)
|
||||
{
|
||||
i386_fastmem[i386_fastmem_count].start = start;
|
||||
i386_fastmem[i386_fastmem_count].end = end;
|
||||
i386_fastmem[i386_fastmem_count].base = base;
|
||||
i386_fastmem[i386_fastmem_count].flags = flags;
|
||||
i386_fastmem_count++;
|
||||
}
|
||||
/* empty the caches */
|
||||
memset(I.fast_size, 0, sizeof(I.fast_size));
|
||||
}
|
||||
|
||||
/* a miss of the cache: the region of the address, cached; NULL if none */
|
||||
static UINT8 *i386_fast_lookup(i386_state *cpustate, UINT32 address, UINT32 len, int kind)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < i386_fastmem_count; i++)
|
||||
{
|
||||
if ((i386_fastmem[i].flags & (1 << kind)) && address >= i386_fastmem[i].start &&
|
||||
address <= i386_fastmem[i].end && i386_fastmem[i].end - address >= len - 1)
|
||||
{
|
||||
cpustate->fast_start[kind] = i386_fastmem[i].start;
|
||||
cpustate->fast_size[kind] = i386_fastmem[i].end - i386_fastmem[i].start + 1;
|
||||
cpustate->fast_base[kind] = i386_fastmem[i].base;
|
||||
return i386_fastmem[i].base + (address - i386_fastmem[i].start);
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void i386_init(void)
|
||||
{
|
||||
int i, j;
|
||||
static const int regs8[8] = {AL,CL,DL,BL,AH,CH,DH,BH};
|
||||
static const int regs16[8] = {AX,CX,DX,BX,SP,BP,SI,DI};
|
||||
static const int regs32[8] = {EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI};
|
||||
int cpu = cpu_getactivecpu();
|
||||
i386_state *cpustate = &I;
|
||||
static const char *const sregname[6] = { "es", "cs", "ss", "ds", "fs", "gs" };
|
||||
|
||||
i386_fastmem_count = 0;
|
||||
memset(I.fast_size, 0, sizeof(I.fast_size));
|
||||
build_cycle_table();
|
||||
|
||||
for( i=0; i < 256; i++ ) {
|
||||
int c=0;
|
||||
for( j=0; j < 8; j++ ) {
|
||||
if( i & (1 << j) )
|
||||
c++;
|
||||
}
|
||||
i386_parity_table[i] = ~(c & 0x1) & 0x1;
|
||||
}
|
||||
|
||||
for( i=0; i < 256; i++ ) {
|
||||
i386_MODRM_table[i].reg.b = regs8[(i >> 3) & 0x7];
|
||||
i386_MODRM_table[i].reg.w = regs16[(i >> 3) & 0x7];
|
||||
i386_MODRM_table[i].reg.d = regs32[(i >> 3) & 0x7];
|
||||
|
||||
i386_MODRM_table[i].rm.b = regs8[i & 0x7];
|
||||
i386_MODRM_table[i].rm.w = regs16[i & 0x7];
|
||||
i386_MODRM_table[i].rm.d = regs32[i & 0x7];
|
||||
}
|
||||
|
||||
state_save_register_UINT32("i386", cpu, "reg", cpustate->reg.d, 8);
|
||||
for (i = 0; i < 6; i++)
|
||||
{
|
||||
char name[16];
|
||||
sprintf(name, "%s_sel", sregname[i]);
|
||||
state_save_register_UINT16("i386", cpu, name, &cpustate->sreg[i].selector, 1);
|
||||
sprintf(name, "%s_flags", sregname[i]);
|
||||
state_save_register_UINT16("i386", cpu, name, &cpustate->sreg[i].flags, 1);
|
||||
sprintf(name, "%s_base", sregname[i]);
|
||||
state_save_register_UINT32("i386", cpu, name, &cpustate->sreg[i].base, 1);
|
||||
sprintf(name, "%s_limit", sregname[i]);
|
||||
state_save_register_UINT32("i386", cpu, name, &cpustate->sreg[i].limit, 1);
|
||||
sprintf(name, "%s_d", sregname[i]);
|
||||
state_save_register_int("i386", cpu, name, &cpustate->sreg[i].d);
|
||||
}
|
||||
state_save_register_UINT32("i386", cpu, "eip", &cpustate->eip, 1);
|
||||
state_save_register_UINT32("i386", cpu, "pc", &cpustate->pc, 1);
|
||||
state_save_register_UINT32("i386", cpu, "prev_eip", &cpustate->prev_eip, 1);
|
||||
state_save_register_UINT32("i386", cpu, "eflags", &cpustate->eflags, 1);
|
||||
state_save_register_UINT32("i386", cpu, "eflags_mask", &cpustate->eflags_mask, 1);
|
||||
state_save_register_UINT8("i386", cpu, "CF", &cpustate->CF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "DF", &cpustate->DF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "SF", &cpustate->SF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "OF", &cpustate->OF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "ZF", &cpustate->ZF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "PF", &cpustate->PF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "AF", &cpustate->AF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "IF", &cpustate->IF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "TF", &cpustate->TF, 1);
|
||||
state_save_register_UINT8("i386", cpu, "IOP1", &cpustate->IOP1, 1);
|
||||
state_save_register_UINT8("i386", cpu, "IOP2", &cpustate->IOP2, 1);
|
||||
state_save_register_UINT8("i386", cpu, "NT", &cpustate->NT, 1);
|
||||
state_save_register_UINT32("i386", cpu, "cr", cpustate->cr, 5);
|
||||
state_save_register_UINT32("i386", cpu, "dr", cpustate->dr, 8);
|
||||
state_save_register_UINT32("i386", cpu, "tr", cpustate->tr, 8);
|
||||
state_save_register_UINT32("i386", cpu, "idtr_base", &cpustate->idtr.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "idtr_limit", &cpustate->idtr.limit, 1);
|
||||
state_save_register_UINT32("i386", cpu, "gdtr_base", &cpustate->gdtr.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "gdtr_limit", &cpustate->gdtr.limit, 1);
|
||||
state_save_register_UINT32("i386", cpu, "task_base", &cpustate->task.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "task_segment", &cpustate->task.segment, 1);
|
||||
state_save_register_UINT32("i386", cpu, "task_limit", &cpustate->task.limit, 1);
|
||||
state_save_register_UINT16("i386", cpu, "task_flags", &cpustate->task.flags, 1);
|
||||
state_save_register_UINT32("i386", cpu, "ldtr_base", &cpustate->ldtr.base, 1);
|
||||
state_save_register_UINT16("i386", cpu, "ldtr_segment", &cpustate->ldtr.segment, 1);
|
||||
state_save_register_UINT32("i386", cpu, "ldtr_limit", &cpustate->ldtr.limit, 1);
|
||||
state_save_register_UINT16("i386", cpu, "ldtr_flags", &cpustate->ldtr.flags, 1);
|
||||
state_save_register_int("i386", cpu, "halted", &cpustate->halted);
|
||||
state_save_register_UINT8("i386", cpu, "irq_state", &cpustate->irq_state, 1);
|
||||
state_save_register_UINT8("i386", cpu, "performed_intersegment_jump", &cpustate->performed_intersegment_jump, 1);
|
||||
state_save_register_UINT32("i386", cpu, "a20_mask", &cpustate->a20_mask, 1);
|
||||
state_save_register_func_postload(i386_postload);
|
||||
}
|
||||
|
||||
void i386_reset(void *param)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
int (*save_irqcallback)(int);
|
||||
|
||||
save_irqcallback = cpustate->irq_callback;
|
||||
memset( cpustate, 0, sizeof(*cpustate) );
|
||||
cpustate->irq_callback = save_irqcallback;
|
||||
|
||||
cpustate->sreg[CS].selector = 0xf000;
|
||||
cpustate->sreg[CS].base = 0xffff0000;
|
||||
cpustate->sreg[CS].limit = 0xffff;
|
||||
|
||||
cpustate->sreg[DS].base = cpustate->sreg[ES].base = cpustate->sreg[FS].base = cpustate->sreg[GS].base = cpustate->sreg[SS].base = 0x00000000;
|
||||
cpustate->sreg[DS].limit = cpustate->sreg[ES].limit = cpustate->sreg[FS].limit = cpustate->sreg[GS].limit = cpustate->sreg[SS].limit = 0xffff;
|
||||
cpustate->sreg[DS].flags = cpustate->sreg[ES].flags = cpustate->sreg[FS].flags = cpustate->sreg[GS].flags = cpustate->sreg[SS].flags = 0x0092;
|
||||
|
||||
cpustate->idtr.base = 0;
|
||||
cpustate->idtr.limit = 0x3ff;
|
||||
|
||||
cpustate->a20_mask = ~0;
|
||||
|
||||
cpustate->cr[0] = 0x7ffffff0; /* reserved bits set to 1 */
|
||||
cpustate->eflags = 0;
|
||||
cpustate->eflags_mask = 0x00030000;
|
||||
cpustate->eip = 0xfff0;
|
||||
|
||||
/* Family 3 (386), Model 0 (DX), Stepping 8 (D1) */
|
||||
REG32(EAX) = 0;
|
||||
REG32(EDX) = (3 << 8) | (0 << 4) | (8);
|
||||
|
||||
build_opcode_table(cpustate, OP_I386);
|
||||
cpustate->cycle_table_rm = cycle_table_rm[CPU_CYCLES_I386];
|
||||
cpustate->cycle_table_pm = cycle_table_pm[CPU_CYCLES_I386];
|
||||
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
}
|
||||
|
||||
void i386_exit(void)
|
||||
{
|
||||
}
|
||||
|
||||
int i386_execute(int cycles)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
i386_ICount = cycles;
|
||||
cpustate->base_cycles = cycles;
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
|
||||
if (cpustate->halted)
|
||||
{
|
||||
cpustate->tsc += cycles;
|
||||
i386_ICount = 0;
|
||||
return cycles;
|
||||
}
|
||||
|
||||
while( i386_ICount > 0 )
|
||||
{
|
||||
cpustate->operand_size = cpustate->sreg[CS].d;
|
||||
cpustate->address_size = cpustate->sreg[CS].d;
|
||||
|
||||
cpustate->segment_prefix = 0;
|
||||
cpustate->prev_eip = cpustate->eip;
|
||||
|
||||
CALL_MAME_DEBUG;
|
||||
|
||||
i386_check_irq_line(cpustate);
|
||||
I386OP(decode_opcode)(cpustate);
|
||||
}
|
||||
cpustate->tsc += (cycles - i386_ICount);
|
||||
return cycles - i386_ICount;
|
||||
}
|
||||
|
||||
unsigned i386_get_context(void *dst)
|
||||
{
|
||||
if (dst)
|
||||
*(i386_state *)dst = I;
|
||||
return sizeof(i386_state);
|
||||
}
|
||||
|
||||
void i386_set_context(void *src)
|
||||
{
|
||||
if (src)
|
||||
I = *(i386_state *)src;
|
||||
}
|
||||
|
||||
unsigned i386_get_reg(int regnum)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC: return cpustate->pc;
|
||||
case REG_PREVIOUSPC: return cpustate->sreg[CS].base + cpustate->prev_eip;
|
||||
case REG_SP: return cpustate->sreg[SS].base + REG32(ESP);
|
||||
case I386_EIP: return cpustate->eip;
|
||||
case I386_EAX: return REG32(EAX);
|
||||
case I386_EBX: return REG32(EBX);
|
||||
case I386_ECX: return REG32(ECX);
|
||||
case I386_EDX: return REG32(EDX);
|
||||
case I386_ESI: return REG32(ESI);
|
||||
case I386_EDI: return REG32(EDI);
|
||||
case I386_EBP: return REG32(EBP);
|
||||
case I386_ESP: return REG32(ESP);
|
||||
case I386_EFLAGS: return get_flags(cpustate);
|
||||
case I386_CS: return cpustate->sreg[CS].selector;
|
||||
case I386_SS: return cpustate->sreg[SS].selector;
|
||||
case I386_DS: return cpustate->sreg[DS].selector;
|
||||
case I386_ES: return cpustate->sreg[ES].selector;
|
||||
case I386_FS: return cpustate->sreg[FS].selector;
|
||||
case I386_GS: return cpustate->sreg[GS].selector;
|
||||
case I386_CR0: return cpustate->cr[0];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i386_set_reg(int regnum, unsigned val)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
switch (regnum)
|
||||
{
|
||||
case REG_PC:
|
||||
cpustate->eip = val - cpustate->sreg[CS].base;
|
||||
CHANGE_PC(cpustate,cpustate->eip);
|
||||
break;
|
||||
case REG_SP: REG32(ESP) = val - cpustate->sreg[SS].base; break;
|
||||
case I386_EIP: cpustate->eip = val; CHANGE_PC(cpustate,cpustate->eip); break;
|
||||
case I386_EAX: REG32(EAX) = val; break;
|
||||
case I386_EBX: REG32(EBX) = val; break;
|
||||
case I386_ECX: REG32(ECX) = val; break;
|
||||
case I386_EDX: REG32(EDX) = val; break;
|
||||
case I386_ESI: REG32(ESI) = val; break;
|
||||
case I386_EDI: REG32(EDI) = val; break;
|
||||
case I386_EBP: REG32(EBP) = val; break;
|
||||
case I386_ESP: REG32(ESP) = val; break;
|
||||
case I386_EFLAGS: set_flags(cpustate, val); break;
|
||||
}
|
||||
}
|
||||
|
||||
void i386_set_irq_line(int irqline, int state)
|
||||
{
|
||||
i386_state *cpustate = &I;
|
||||
|
||||
if (state != CLEAR_LINE && cpustate->halted)
|
||||
{
|
||||
cpustate->halted = 0;
|
||||
}
|
||||
|
||||
if ( irqline == IRQ_LINE_NMI )
|
||||
{
|
||||
/* NMI (I do not think that this is 100% right) */
|
||||
if ( state )
|
||||
i386_trap(cpustate,2, 1);
|
||||
}
|
||||
else if ( irqline == I386_INPUT_LINE_A20 )
|
||||
{
|
||||
cpustate->a20_mask = state ? ~0 : ~(1 << 20);
|
||||
}
|
||||
else
|
||||
{
|
||||
cpustate->irq_state = state;
|
||||
}
|
||||
}
|
||||
|
||||
void i386_set_irq_callback(int (*callback)(int irqline))
|
||||
{
|
||||
I.irq_callback = callback;
|
||||
}
|
||||
|
||||
const char *i386_info(void *context, int regnum)
|
||||
{
|
||||
static char buffer[16][47+1];
|
||||
static int which = 0;
|
||||
i386_state *r = context ? (i386_state *)context : &I;
|
||||
|
||||
which = (which + 1) % 16;
|
||||
buffer[which][0] = '\0';
|
||||
|
||||
switch( regnum )
|
||||
{
|
||||
case CPU_INFO_REG+I386_EIP: sprintf(buffer[which], "EIP:%08X", r->eip); break;
|
||||
case CPU_INFO_REG+I386_EAX: sprintf(buffer[which], "EAX:%08X", r->reg.d[EAX]); break;
|
||||
case CPU_INFO_REG+I386_EBX: sprintf(buffer[which], "EBX:%08X", r->reg.d[EBX]); break;
|
||||
case CPU_INFO_REG+I386_ECX: sprintf(buffer[which], "ECX:%08X", r->reg.d[ECX]); break;
|
||||
case CPU_INFO_REG+I386_EDX: sprintf(buffer[which], "EDX:%08X", r->reg.d[EDX]); break;
|
||||
case CPU_INFO_REG+I386_ESI: sprintf(buffer[which], "ESI:%08X", r->reg.d[ESI]); break;
|
||||
case CPU_INFO_REG+I386_EDI: sprintf(buffer[which], "EDI:%08X", r->reg.d[EDI]); break;
|
||||
case CPU_INFO_REG+I386_EBP: sprintf(buffer[which], "EBP:%08X", r->reg.d[EBP]); break;
|
||||
case CPU_INFO_REG+I386_ESP: sprintf(buffer[which], "ESP:%08X", r->reg.d[ESP]); break;
|
||||
case CPU_INFO_FLAGS: sprintf(buffer[which], "%08X", r->eflags); break;
|
||||
case CPU_INFO_NAME: return "I386";
|
||||
case CPU_INFO_FAMILY: return "Intel 386";
|
||||
case CPU_INFO_VERSION: return "1.0";
|
||||
case CPU_INFO_FILE: return __FILE__;
|
||||
case CPU_INFO_CREDITS: return "Copyright Ville Linde";
|
||||
}
|
||||
return buffer[which];
|
||||
}
|
||||
|
||||
unsigned i386_dasm(char *buffer, unsigned pc)
|
||||
{
|
||||
sprintf(buffer, "$%02X", cpu_readmem32ledw(pc));
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/***************************************************************************
|
||||
|
||||
Intel 386 emulator (Ville Linde), from MAME 0.139
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef I386INTF_H
|
||||
#define I386INTF_H
|
||||
|
||||
#include "cpuintrf.h"
|
||||
|
||||
/* the A20 gate, as an input line */
|
||||
#define I386_INPUT_LINE_A20 1
|
||||
|
||||
extern int i386_ICount;
|
||||
|
||||
/* the fast memory: a range of plain RAM or ROM at base, which the CPU */
|
||||
/* fetches, reads or writes directly (flags), without the memory handlers; */
|
||||
/* set from DRIVER_INIT, emptied at the CPU init. Little endian hosts only */
|
||||
#define I386_FASTMEM_MAX 8
|
||||
#define I386_FASTMEM_FETCH 1
|
||||
#define I386_FASTMEM_READ 2
|
||||
#define I386_FASTMEM_WRITE 4
|
||||
void i386_set_fastmem(UINT32 start, UINT32 end, UINT8 *base, int flags);
|
||||
|
||||
void i386_init(void);
|
||||
void i386_reset(void *param);
|
||||
void i386_exit(void);
|
||||
int i386_execute(int cycles);
|
||||
unsigned i386_get_context(void *dst);
|
||||
void i386_set_context(void *src);
|
||||
unsigned i386_get_reg(int regnum);
|
||||
void i386_set_reg(int regnum, unsigned val);
|
||||
void i386_set_irq_line(int irqline, int state);
|
||||
void i386_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *i386_info(void *context, int regnum);
|
||||
unsigned i386_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
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
@@ -0,0 +1,377 @@
|
||||
typedef struct {
|
||||
UINT8 opcode;
|
||||
UINT32 flags;
|
||||
void (*handler16)(i386_state *cpustate);
|
||||
void (*handler32)(i386_state *cpustate);
|
||||
} X86_OPCODE;
|
||||
|
||||
#define OP_I386 0x1
|
||||
#define OP_FPU 0x2
|
||||
#define OP_I486 0x4
|
||||
#define OP_PENTIUM 0x8
|
||||
#define OP_MMX 0x10
|
||||
#define OP_PPRO 0x20
|
||||
#define OP_SSE 0x40
|
||||
#define OP_SSE2 0x80
|
||||
#define OP_SSE3 0x100
|
||||
#define OP_CYRIX 0x8000
|
||||
#define OP_2BYTE 0x80000000
|
||||
|
||||
static const X86_OPCODE x86_opcode_table[] =
|
||||
{
|
||||
/* Opcode Flags 16-bit handler 32-bit handler */
|
||||
{ 0x00, OP_I386, I386OP(add_rm8_r8), I386OP(add_rm8_r8), },
|
||||
{ 0x01, OP_I386, I386OP(add_rm16_r16), I386OP(add_rm32_r32), },
|
||||
{ 0x02, OP_I386, I386OP(add_r8_rm8), I386OP(add_r8_rm8), },
|
||||
{ 0x03, OP_I386, I386OP(add_r16_rm16), I386OP(add_r32_rm32), },
|
||||
{ 0x04, OP_I386, I386OP(add_al_i8), I386OP(add_al_i8), },
|
||||
{ 0x05, OP_I386, I386OP(add_ax_i16), I386OP(add_eax_i32), },
|
||||
{ 0x06, OP_I386, I386OP(push_es16), I386OP(push_es32), },
|
||||
{ 0x07, OP_I386, I386OP(pop_es16), I386OP(pop_es32), },
|
||||
{ 0x08, OP_I386, I386OP(or_rm8_r8), I386OP(or_rm8_r8), },
|
||||
{ 0x09, OP_I386, I386OP(or_rm16_r16), I386OP(or_rm32_r32), },
|
||||
{ 0x0A, OP_I386, I386OP(or_r8_rm8), I386OP(or_r8_rm8), },
|
||||
{ 0x0B, OP_I386, I386OP(or_r16_rm16), I386OP(or_r32_rm32), },
|
||||
{ 0x0C, OP_I386, I386OP(or_al_i8), I386OP(or_al_i8), },
|
||||
{ 0x0D, OP_I386, I386OP(or_ax_i16), I386OP(or_eax_i32), },
|
||||
{ 0x0E, OP_I386, I386OP(push_cs16), I386OP(push_cs32), },
|
||||
{ 0x0F, OP_I386, I386OP(decode_two_byte), I386OP(decode_two_byte), },
|
||||
{ 0x10, OP_I386, I386OP(adc_rm8_r8), I386OP(adc_rm8_r8), },
|
||||
{ 0x11, OP_I386, I386OP(adc_rm16_r16), I386OP(adc_rm32_r32), },
|
||||
{ 0x12, OP_I386, I386OP(adc_r8_rm8), I386OP(adc_r8_rm8), },
|
||||
{ 0x13, OP_I386, I386OP(adc_r16_rm16), I386OP(adc_r32_rm32), },
|
||||
{ 0x14, OP_I386, I386OP(adc_al_i8), I386OP(adc_al_i8), },
|
||||
{ 0x15, OP_I386, I386OP(adc_ax_i16), I386OP(adc_eax_i32), },
|
||||
{ 0x16, OP_I386, I386OP(push_ss16), I386OP(push_ss32), },
|
||||
{ 0x17, OP_I386, I386OP(pop_ss16), I386OP(pop_ss32), },
|
||||
{ 0x18, OP_I386, I386OP(sbb_rm8_r8), I386OP(sbb_rm8_r8), },
|
||||
{ 0x19, OP_I386, I386OP(sbb_rm16_r16), I386OP(sbb_rm32_r32), },
|
||||
{ 0x1A, OP_I386, I386OP(sbb_r8_rm8), I386OP(sbb_r8_rm8), },
|
||||
{ 0x1B, OP_I386, I386OP(sbb_r16_rm16), I386OP(sbb_r32_rm32), },
|
||||
{ 0x1C, OP_I386, I386OP(sbb_al_i8), I386OP(sbb_al_i8), },
|
||||
{ 0x1D, OP_I386, I386OP(sbb_ax_i16), I386OP(sbb_eax_i32), },
|
||||
{ 0x1E, OP_I386, I386OP(push_ds16), I386OP(push_ds32), },
|
||||
{ 0x1F, OP_I386, I386OP(pop_ds16), I386OP(pop_ds32), },
|
||||
{ 0x20, OP_I386, I386OP(and_rm8_r8), I386OP(and_rm8_r8), },
|
||||
{ 0x21, OP_I386, I386OP(and_rm16_r16), I386OP(and_rm32_r32), },
|
||||
{ 0x22, OP_I386, I386OP(and_r8_rm8), I386OP(and_r8_rm8), },
|
||||
{ 0x23, OP_I386, I386OP(and_r16_rm16), I386OP(and_r32_rm32), },
|
||||
{ 0x24, OP_I386, I386OP(and_al_i8), I386OP(and_al_i8), },
|
||||
{ 0x25, OP_I386, I386OP(and_ax_i16), I386OP(and_eax_i32), },
|
||||
{ 0x26, OP_I386, I386OP(segment_ES), I386OP(segment_ES), },
|
||||
{ 0x27, OP_I386, I386OP(daa), I386OP(daa), },
|
||||
{ 0x28, OP_I386, I386OP(sub_rm8_r8), I386OP(sub_rm8_r8), },
|
||||
{ 0x29, OP_I386, I386OP(sub_rm16_r16), I386OP(sub_rm32_r32), },
|
||||
{ 0x2A, OP_I386, I386OP(sub_r8_rm8), I386OP(sub_r8_rm8), },
|
||||
{ 0x2B, OP_I386, I386OP(sub_r16_rm16), I386OP(sub_r32_rm32), },
|
||||
{ 0x2C, OP_I386, I386OP(sub_al_i8), I386OP(sub_al_i8), },
|
||||
{ 0x2D, OP_I386, I386OP(sub_ax_i16), I386OP(sub_eax_i32), },
|
||||
{ 0x2E, OP_I386, I386OP(segment_CS), I386OP(segment_CS), },
|
||||
{ 0x2F, OP_I386, I386OP(das), I386OP(das), },
|
||||
{ 0x30, OP_I386, I386OP(xor_rm8_r8), I386OP(xor_rm8_r8), },
|
||||
{ 0x31, OP_I386, I386OP(xor_rm16_r16), I386OP(xor_rm32_r32), },
|
||||
{ 0x32, OP_I386, I386OP(xor_r8_rm8), I386OP(xor_r8_rm8), },
|
||||
{ 0x33, OP_I386, I386OP(xor_r16_rm16), I386OP(xor_r32_rm32), },
|
||||
{ 0x34, OP_I386, I386OP(xor_al_i8), I386OP(xor_al_i8), },
|
||||
{ 0x35, OP_I386, I386OP(xor_ax_i16), I386OP(xor_eax_i32), },
|
||||
{ 0x36, OP_I386, I386OP(segment_SS), I386OP(segment_SS), },
|
||||
{ 0x37, OP_I386, I386OP(aaa), I386OP(aaa), },
|
||||
{ 0x38, OP_I386, I386OP(cmp_rm8_r8), I386OP(cmp_rm8_r8), },
|
||||
{ 0x39, OP_I386, I386OP(cmp_rm16_r16), I386OP(cmp_rm32_r32), },
|
||||
{ 0x3A, OP_I386, I386OP(cmp_r8_rm8), I386OP(cmp_r8_rm8), },
|
||||
{ 0x3B, OP_I386, I386OP(cmp_r16_rm16), I386OP(cmp_r32_rm32), },
|
||||
{ 0x3C, OP_I386, I386OP(cmp_al_i8), I386OP(cmp_al_i8), },
|
||||
{ 0x3D, OP_I386, I386OP(cmp_ax_i16), I386OP(cmp_eax_i32), },
|
||||
{ 0x3E, OP_I386, I386OP(segment_DS), I386OP(segment_DS), },
|
||||
{ 0x3F, OP_I386, I386OP(aas), I386OP(aas), },
|
||||
{ 0x40, OP_I386, I386OP(inc_ax), I386OP(inc_eax), },
|
||||
{ 0x41, OP_I386, I386OP(inc_cx), I386OP(inc_ecx), },
|
||||
{ 0x42, OP_I386, I386OP(inc_dx), I386OP(inc_edx), },
|
||||
{ 0x43, OP_I386, I386OP(inc_bx), I386OP(inc_ebx), },
|
||||
{ 0x44, OP_I386, I386OP(inc_sp), I386OP(inc_esp), },
|
||||
{ 0x45, OP_I386, I386OP(inc_bp), I386OP(inc_ebp), },
|
||||
{ 0x46, OP_I386, I386OP(inc_si), I386OP(inc_esi), },
|
||||
{ 0x47, OP_I386, I386OP(inc_di), I386OP(inc_edi), },
|
||||
{ 0x48, OP_I386, I386OP(dec_ax), I386OP(dec_eax), },
|
||||
{ 0x49, OP_I386, I386OP(dec_cx), I386OP(dec_ecx), },
|
||||
{ 0x4A, OP_I386, I386OP(dec_dx), I386OP(dec_edx), },
|
||||
{ 0x4B, OP_I386, I386OP(dec_bx), I386OP(dec_ebx), },
|
||||
{ 0x4C, OP_I386, I386OP(dec_sp), I386OP(dec_esp), },
|
||||
{ 0x4D, OP_I386, I386OP(dec_bp), I386OP(dec_ebp), },
|
||||
{ 0x4E, OP_I386, I386OP(dec_si), I386OP(dec_esi), },
|
||||
{ 0x4F, OP_I386, I386OP(dec_di), I386OP(dec_edi), },
|
||||
{ 0x50, OP_I386, I386OP(push_ax), I386OP(push_eax), },
|
||||
{ 0x51, OP_I386, I386OP(push_cx), I386OP(push_ecx), },
|
||||
{ 0x52, OP_I386, I386OP(push_dx), I386OP(push_edx), },
|
||||
{ 0x53, OP_I386, I386OP(push_bx), I386OP(push_ebx), },
|
||||
{ 0x54, OP_I386, I386OP(push_sp), I386OP(push_esp), },
|
||||
{ 0x55, OP_I386, I386OP(push_bp), I386OP(push_ebp), },
|
||||
{ 0x56, OP_I386, I386OP(push_si), I386OP(push_esi), },
|
||||
{ 0x57, OP_I386, I386OP(push_di), I386OP(push_edi), },
|
||||
{ 0x58, OP_I386, I386OP(pop_ax), I386OP(pop_eax), },
|
||||
{ 0x59, OP_I386, I386OP(pop_cx), I386OP(pop_ecx), },
|
||||
{ 0x5A, OP_I386, I386OP(pop_dx), I386OP(pop_edx), },
|
||||
{ 0x5B, OP_I386, I386OP(pop_bx), I386OP(pop_ebx), },
|
||||
{ 0x5C, OP_I386, I386OP(pop_sp), I386OP(pop_esp), },
|
||||
{ 0x5D, OP_I386, I386OP(pop_bp), I386OP(pop_ebp), },
|
||||
{ 0x5E, OP_I386, I386OP(pop_si), I386OP(pop_esi), },
|
||||
{ 0x5F, OP_I386, I386OP(pop_di), I386OP(pop_edi), },
|
||||
{ 0x60, OP_I386, I386OP(pusha), I386OP(pushad), },
|
||||
{ 0x61, OP_I386, I386OP(popa), I386OP(popad), },
|
||||
{ 0x62, OP_I386, I386OP(bound_r16_m16_m16), I386OP(bound_r32_m32_m32), },
|
||||
{ 0x63, OP_I386, I386OP(arpl), I386OP(arpl), },
|
||||
{ 0x64, OP_I386, I386OP(segment_FS), I386OP(segment_FS), },
|
||||
{ 0x65, OP_I386, I386OP(segment_GS), I386OP(segment_GS), },
|
||||
{ 0x66, OP_I386, I386OP(operand_size), I386OP(operand_size), },
|
||||
{ 0x67, OP_I386, I386OP(address_size), I386OP(address_size), },
|
||||
{ 0x68, OP_I386, I386OP(push_i16), I386OP(push_i32), },
|
||||
{ 0x69, OP_I386, I386OP(imul_r16_rm16_i16), I386OP(imul_r32_rm32_i32), },
|
||||
{ 0x6A, OP_I386, I386OP(push_i8), I386OP(push_i8), },
|
||||
{ 0x6B, OP_I386, I386OP(imul_r16_rm16_i8), I386OP(imul_r32_rm32_i8), },
|
||||
{ 0x6C, OP_I386, I386OP(insb), I386OP(insb), },
|
||||
{ 0x6D, OP_I386, I386OP(insw), I386OP(insd), },
|
||||
{ 0x6E, OP_I386, I386OP(outsb), I386OP(outsb), },
|
||||
{ 0x6F, OP_I386, I386OP(outsw), I386OP(outsd), },
|
||||
{ 0x70, OP_I386, I386OP(jo_rel8), I386OP(jo_rel8), },
|
||||
{ 0x71, OP_I386, I386OP(jno_rel8), I386OP(jno_rel8), },
|
||||
{ 0x72, OP_I386, I386OP(jc_rel8), I386OP(jc_rel8), },
|
||||
{ 0x73, OP_I386, I386OP(jnc_rel8), I386OP(jnc_rel8), },
|
||||
{ 0x74, OP_I386, I386OP(jz_rel8), I386OP(jz_rel8), },
|
||||
{ 0x75, OP_I386, I386OP(jnz_rel8), I386OP(jnz_rel8), },
|
||||
{ 0x76, OP_I386, I386OP(jbe_rel8), I386OP(jbe_rel8), },
|
||||
{ 0x77, OP_I386, I386OP(ja_rel8), I386OP(ja_rel8), },
|
||||
{ 0x78, OP_I386, I386OP(js_rel8), I386OP(js_rel8), },
|
||||
{ 0x79, OP_I386, I386OP(jns_rel8), I386OP(jns_rel8), },
|
||||
{ 0x7A, OP_I386, I386OP(jp_rel8), I386OP(jp_rel8), },
|
||||
{ 0x7B, OP_I386, I386OP(jnp_rel8), I386OP(jnp_rel8), },
|
||||
{ 0x7C, OP_I386, I386OP(jl_rel8), I386OP(jl_rel8), },
|
||||
{ 0x7D, OP_I386, I386OP(jge_rel8), I386OP(jge_rel8), },
|
||||
{ 0x7E, OP_I386, I386OP(jle_rel8), I386OP(jle_rel8), },
|
||||
{ 0x7F, OP_I386, I386OP(jg_rel8), I386OP(jg_rel8), },
|
||||
{ 0x80, OP_I386, I386OP(group80_8), I386OP(group80_8), },
|
||||
{ 0x81, OP_I386, I386OP(group81_16), I386OP(group81_32), },
|
||||
{ 0x82, OP_I386, I386OP(group80_8), I386OP(group80_8), },
|
||||
{ 0x83, OP_I386, I386OP(group83_16), I386OP(group83_32), },
|
||||
{ 0x84, OP_I386, I386OP(test_rm8_r8), I386OP(test_rm8_r8), },
|
||||
{ 0x85, OP_I386, I386OP(test_rm16_r16), I386OP(test_rm32_r32), },
|
||||
{ 0x86, OP_I386, I386OP(xchg_r8_rm8), I386OP(xchg_r8_rm8), },
|
||||
{ 0x87, OP_I386, I386OP(xchg_r16_rm16), I386OP(xchg_r32_rm32), },
|
||||
{ 0x88, OP_I386, I386OP(mov_rm8_r8), I386OP(mov_rm8_r8), },
|
||||
{ 0x89, OP_I386, I386OP(mov_rm16_r16), I386OP(mov_rm32_r32), },
|
||||
{ 0x8A, OP_I386, I386OP(mov_r8_rm8), I386OP(mov_r8_rm8), },
|
||||
{ 0x8B, OP_I386, I386OP(mov_r16_rm16), I386OP(mov_r32_rm32), },
|
||||
{ 0x8C, OP_I386, I386OP(mov_rm16_sreg), I386OP(mov_rm16_sreg), },
|
||||
{ 0x8D, OP_I386, I386OP(lea16), I386OP(lea32), },
|
||||
{ 0x8E, OP_I386, I386OP(mov_sreg_rm16), I386OP(mov_sreg_rm16), },
|
||||
{ 0x8F, OP_I386, I386OP(pop_rm16), I386OP(pop_rm32), },
|
||||
{ 0x90, OP_I386, I386OP(nop), I386OP(nop), },
|
||||
{ 0x91, OP_I386, I386OP(xchg_ax_cx), I386OP(xchg_eax_ecx), },
|
||||
{ 0x92, OP_I386, I386OP(xchg_ax_dx), I386OP(xchg_eax_edx), },
|
||||
{ 0x93, OP_I386, I386OP(xchg_ax_bx), I386OP(xchg_eax_ebx), },
|
||||
{ 0x94, OP_I386, I386OP(xchg_ax_sp), I386OP(xchg_eax_esp), },
|
||||
{ 0x95, OP_I386, I386OP(xchg_ax_bp), I386OP(xchg_eax_ebp), },
|
||||
{ 0x96, OP_I386, I386OP(xchg_ax_si), I386OP(xchg_eax_esi), },
|
||||
{ 0x97, OP_I386, I386OP(xchg_ax_di), I386OP(xchg_eax_edi), },
|
||||
{ 0x98, OP_I386, I386OP(cbw), I386OP(cwde), },
|
||||
{ 0x99, OP_I386, I386OP(cwd), I386OP(cdq), },
|
||||
{ 0x9A, OP_I386, I386OP(call_abs16), I386OP(call_abs32), },
|
||||
{ 0x9B, OP_I386, I386OP(wait), I386OP(wait), },
|
||||
{ 0x9C, OP_I386, I386OP(pushf), I386OP(pushfd), },
|
||||
{ 0x9D, OP_I386, I386OP(popf), I386OP(popfd), },
|
||||
{ 0x9E, OP_I386, I386OP(sahf), I386OP(sahf), },
|
||||
{ 0x9F, OP_I386, I386OP(lahf), I386OP(lahf), },
|
||||
{ 0xA0, OP_I386, I386OP(mov_al_m8), I386OP(mov_al_m8), },
|
||||
{ 0xA1, OP_I386, I386OP(mov_ax_m16), I386OP(mov_eax_m32), },
|
||||
{ 0xA2, OP_I386, I386OP(mov_m8_al), I386OP(mov_m8_al), },
|
||||
{ 0xA3, OP_I386, I386OP(mov_m16_ax), I386OP(mov_m32_eax), },
|
||||
{ 0xA4, OP_I386, I386OP(movsb), I386OP(movsb), },
|
||||
{ 0xA5, OP_I386, I386OP(movsw), I386OP(movsd), },
|
||||
{ 0xA6, OP_I386, I386OP(cmpsb), I386OP(cmpsb), },
|
||||
{ 0xA7, OP_I386, I386OP(cmpsw), I386OP(cmpsd), },
|
||||
{ 0xA8, OP_I386, I386OP(test_al_i8), I386OP(test_al_i8), },
|
||||
{ 0xA9, OP_I386, I386OP(test_ax_i16), I386OP(test_eax_i32), },
|
||||
{ 0xAA, OP_I386, I386OP(stosb), I386OP(stosb), },
|
||||
{ 0xAB, OP_I386, I386OP(stosw), I386OP(stosd), },
|
||||
{ 0xAC, OP_I386, I386OP(lodsb), I386OP(lodsb), },
|
||||
{ 0xAD, OP_I386, I386OP(lodsw), I386OP(lodsd), },
|
||||
{ 0xAE, OP_I386, I386OP(scasb), I386OP(scasb), },
|
||||
{ 0xAF, OP_I386, I386OP(scasw), I386OP(scasd), },
|
||||
{ 0xB0, OP_I386, I386OP(mov_al_i8), I386OP(mov_al_i8), },
|
||||
{ 0xB1, OP_I386, I386OP(mov_cl_i8), I386OP(mov_cl_i8), },
|
||||
{ 0xB2, OP_I386, I386OP(mov_dl_i8), I386OP(mov_dl_i8), },
|
||||
{ 0xB3, OP_I386, I386OP(mov_bl_i8), I386OP(mov_bl_i8), },
|
||||
{ 0xB4, OP_I386, I386OP(mov_ah_i8), I386OP(mov_ah_i8), },
|
||||
{ 0xB5, OP_I386, I386OP(mov_ch_i8), I386OP(mov_ch_i8), },
|
||||
{ 0xB6, OP_I386, I386OP(mov_dh_i8), I386OP(mov_dh_i8), },
|
||||
{ 0xB7, OP_I386, I386OP(mov_bh_i8), I386OP(mov_bh_i8), },
|
||||
{ 0xB8, OP_I386, I386OP(mov_ax_i16), I386OP(mov_eax_i32), },
|
||||
{ 0xB9, OP_I386, I386OP(mov_cx_i16), I386OP(mov_ecx_i32), },
|
||||
{ 0xBA, OP_I386, I386OP(mov_dx_i16), I386OP(mov_edx_i32), },
|
||||
{ 0xBB, OP_I386, I386OP(mov_bx_i16), I386OP(mov_ebx_i32), },
|
||||
{ 0xBC, OP_I386, I386OP(mov_sp_i16), I386OP(mov_esp_i32), },
|
||||
{ 0xBD, OP_I386, I386OP(mov_bp_i16), I386OP(mov_ebp_i32), },
|
||||
{ 0xBE, OP_I386, I386OP(mov_si_i16), I386OP(mov_esi_i32), },
|
||||
{ 0xBF, OP_I386, I386OP(mov_di_i16), I386OP(mov_edi_i32), },
|
||||
{ 0xC0, OP_I386, I386OP(groupC0_8), I386OP(groupC0_8), },
|
||||
{ 0xC1, OP_I386, I386OP(groupC1_16), I386OP(groupC1_32), },
|
||||
{ 0xC2, OP_I386, I386OP(ret_near16_i16), I386OP(ret_near32_i16), },
|
||||
{ 0xC3, OP_I386, I386OP(ret_near16), I386OP(ret_near32), },
|
||||
{ 0xC4, OP_I386, I386OP(les16), I386OP(les32), },
|
||||
{ 0xC5, OP_I386, I386OP(lds16), I386OP(lds32), },
|
||||
{ 0xC6, OP_I386, I386OP(mov_rm8_i8), I386OP(mov_rm8_i8), },
|
||||
{ 0xC7, OP_I386, I386OP(mov_rm16_i16), I386OP(mov_rm32_i32), },
|
||||
{ 0xC8, OP_I386, I386OP(enter16), I386OP(enter32), },
|
||||
{ 0xC9, OP_I386, I386OP(leave16), I386OP(leave32), },
|
||||
{ 0xCA, OP_I386, I386OP(retf_i16), I386OP(retf_i32), },
|
||||
{ 0xCB, OP_I386, I386OP(retf16), I386OP(retf32), },
|
||||
{ 0xCC, OP_I386, I386OP(int3), I386OP(int3), },
|
||||
{ 0xCD, OP_I386, I386OP(int), I386OP(int), },
|
||||
{ 0xCE, OP_I386, I386OP(into), I386OP(into), },
|
||||
{ 0xCF, OP_I386, I386OP(iret16), I386OP(iret32), },
|
||||
{ 0xD0, OP_I386, I386OP(groupD0_8), I386OP(groupD0_8), },
|
||||
{ 0xD1, OP_I386, I386OP(groupD1_16), I386OP(groupD1_32), },
|
||||
{ 0xD2, OP_I386, I386OP(groupD2_8), I386OP(groupD2_8), },
|
||||
{ 0xD3, OP_I386, I386OP(groupD3_16), I386OP(groupD3_32), },
|
||||
{ 0xD4, OP_I386, I386OP(aam), I386OP(aam), },
|
||||
{ 0xD5, OP_I386, I386OP(aad), I386OP(aad), },
|
||||
{ 0xD6, OP_I386, I386OP(setalc), I386OP(setalc), },
|
||||
{ 0xD7, OP_I386, I386OP(xlat16), I386OP(xlat32), },
|
||||
{ 0xD8, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xD9, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDA, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDB, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDC, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDD, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDE, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xDF, OP_I386, I386OP(escape), I386OP(escape), },
|
||||
{ 0xD8, OP_FPU, I386OP(fpu_group_d8), I386OP(fpu_group_d8), },
|
||||
{ 0xD9, OP_FPU, I386OP(fpu_group_d9), I386OP(fpu_group_d9), },
|
||||
{ 0xDA, OP_FPU, I386OP(fpu_group_da), I386OP(fpu_group_da), },
|
||||
{ 0xDB, OP_FPU, I386OP(fpu_group_db), I386OP(fpu_group_db), },
|
||||
{ 0xDC, OP_FPU, I386OP(fpu_group_dc), I386OP(fpu_group_dc), },
|
||||
{ 0xDD, OP_FPU, I386OP(fpu_group_dd), I386OP(fpu_group_dd), },
|
||||
{ 0xDE, OP_FPU, I386OP(fpu_group_de), I386OP(fpu_group_de), },
|
||||
{ 0xDF, OP_FPU, I386OP(fpu_group_df), I386OP(fpu_group_df), },
|
||||
{ 0xE0, OP_I386, I386OP(loopne16), I386OP(loopne32), },
|
||||
{ 0xE1, OP_I386, I386OP(loopz16), I386OP(loopz32), },
|
||||
{ 0xE2, OP_I386, I386OP(loop16), I386OP(loop32), },
|
||||
{ 0xE3, OP_I386, I386OP(jcxz16), I386OP(jcxz32), },
|
||||
{ 0xE4, OP_I386, I386OP(in_al_i8), I386OP(in_al_i8), },
|
||||
{ 0xE5, OP_I386, I386OP(in_ax_i8), I386OP(in_eax_i8), },
|
||||
{ 0xE6, OP_I386, I386OP(out_al_i8), I386OP(out_al_i8), },
|
||||
{ 0xE7, OP_I386, I386OP(out_ax_i8), I386OP(out_eax_i8), },
|
||||
{ 0xE8, OP_I386, I386OP(call_rel16), I386OP(call_rel32), },
|
||||
{ 0xE9, OP_I386, I386OP(jmp_rel16), I386OP(jmp_rel32), },
|
||||
{ 0xEA, OP_I386, I386OP(jmp_abs16), I386OP(jmp_abs32), },
|
||||
{ 0xEB, OP_I386, I386OP(jmp_rel8), I386OP(jmp_rel8), },
|
||||
{ 0xEC, OP_I386, I386OP(in_al_dx), I386OP(in_al_dx), },
|
||||
{ 0xED, OP_I386, I386OP(in_ax_dx), I386OP(in_eax_dx), },
|
||||
{ 0xEE, OP_I386, I386OP(out_al_dx), I386OP(out_al_dx), },
|
||||
{ 0xEF, OP_I386, I386OP(out_ax_dx), I386OP(out_eax_dx), },
|
||||
{ 0xF0, OP_I386, I386OP(lock), I386OP(lock), },
|
||||
{ 0xF1, OP_I386, I386OP(invalid), I386OP(invalid), },
|
||||
{ 0xF2, OP_I386, I386OP(repne), I386OP(repne), },
|
||||
{ 0xF3, OP_I386, I386OP(rep), I386OP(rep), },
|
||||
{ 0xF4, OP_I386, I386OP(hlt), I386OP(hlt), },
|
||||
{ 0xF5, OP_I386, I386OP(cmc), I386OP(cmc), },
|
||||
{ 0xF6, OP_I386, I386OP(groupF6_8), I386OP(groupF6_8), },
|
||||
{ 0xF7, OP_I386, I386OP(groupF7_16), I386OP(groupF7_32), },
|
||||
{ 0xF8, OP_I386, I386OP(clc), I386OP(clc), },
|
||||
{ 0xF9, OP_I386, I386OP(stc), I386OP(stc), },
|
||||
{ 0xFA, OP_I386, I386OP(cli), I386OP(cli), },
|
||||
{ 0xFB, OP_I386, I386OP(sti), I386OP(sti), },
|
||||
{ 0xFC, OP_I386, I386OP(cld), I386OP(cld), },
|
||||
{ 0xFD, OP_I386, I386OP(std), I386OP(std), },
|
||||
{ 0xFE, OP_I386, I386OP(groupFE_8), I386OP(groupFE_8), },
|
||||
{ 0xFF, OP_I386, I386OP(groupFF_16), I386OP(groupFF_32), },
|
||||
{ 0x00, OP_2BYTE|OP_I386, I386OP(group0F00_16), I386OP(group0F00_32), },
|
||||
{ 0x01, OP_2BYTE|OP_I386, I386OP(group0F01_16), I386OP(group0F01_32), },
|
||||
{ 0x01, OP_2BYTE|OP_I486, I486OP(group0F01_16), I486OP(group0F01_32), },
|
||||
{ 0x02, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
|
||||
{ 0x03, OP_2BYTE|OP_I386, I386OP(lsl_r16_rm16), I386OP(lsl_r32_rm32), },
|
||||
{ 0x06, OP_2BYTE|OP_I386, I386OP(clts), I386OP(clts), },
|
||||
{ 0x08, OP_2BYTE|OP_I486, I486OP(invd), I486OP(invd), },
|
||||
{ 0x09, OP_2BYTE|OP_I486, I486OP(wbinvd), I486OP(wbinvd), },
|
||||
{ 0x0B, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
|
||||
{ 0x20, OP_2BYTE|OP_I386, I386OP(mov_r32_cr), I386OP(mov_r32_cr), },
|
||||
{ 0x21, OP_2BYTE|OP_I386, I386OP(mov_r32_dr), I386OP(mov_r32_dr), },
|
||||
{ 0x22, OP_2BYTE|OP_I386, I386OP(mov_cr_r32), I386OP(mov_cr_r32), },
|
||||
{ 0x23, OP_2BYTE|OP_I386, I386OP(mov_dr_r32), I386OP(mov_dr_r32), },
|
||||
{ 0x24, OP_2BYTE|OP_I386, I386OP(mov_r32_tr), I386OP(mov_r32_tr), },
|
||||
{ 0x26, OP_2BYTE|OP_I386, I386OP(mov_tr_r32), I386OP(mov_tr_r32), },
|
||||
{ 0x30, OP_2BYTE|OP_PENTIUM, PENTIUMOP(wrmsr), PENTIUMOP(wrmsr), },
|
||||
{ 0x31, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdtsc), PENTIUMOP(rdtsc), },
|
||||
{ 0x32, OP_2BYTE|OP_PENTIUM, PENTIUMOP(rdmsr), PENTIUMOP(rdmsr), },
|
||||
{ 0x74, OP_2BYTE|OP_CYRIX, I386OP(cyrix_unknown), I386OP(cyrix_unknown), },
|
||||
{ 0x80, OP_2BYTE|OP_I386, I386OP(jo_rel16), I386OP(jo_rel32), },
|
||||
{ 0x81, OP_2BYTE|OP_I386, I386OP(jno_rel16), I386OP(jno_rel32), },
|
||||
{ 0x82, OP_2BYTE|OP_I386, I386OP(jc_rel16), I386OP(jc_rel32), },
|
||||
{ 0x83, OP_2BYTE|OP_I386, I386OP(jnc_rel16), I386OP(jnc_rel32), },
|
||||
{ 0x84, OP_2BYTE|OP_I386, I386OP(jz_rel16), I386OP(jz_rel32), },
|
||||
{ 0x85, OP_2BYTE|OP_I386, I386OP(jnz_rel16), I386OP(jnz_rel32), },
|
||||
{ 0x86, OP_2BYTE|OP_I386, I386OP(jbe_rel16), I386OP(jbe_rel32), },
|
||||
{ 0x87, OP_2BYTE|OP_I386, I386OP(ja_rel16), I386OP(ja_rel32), },
|
||||
{ 0x88, OP_2BYTE|OP_I386, I386OP(js_rel16), I386OP(js_rel32), },
|
||||
{ 0x89, OP_2BYTE|OP_I386, I386OP(jns_rel16), I386OP(jns_rel32), },
|
||||
{ 0x8A, OP_2BYTE|OP_I386, I386OP(jp_rel16), I386OP(jp_rel32), },
|
||||
{ 0x8B, OP_2BYTE|OP_I386, I386OP(jnp_rel16), I386OP(jnp_rel32), },
|
||||
{ 0x8C, OP_2BYTE|OP_I386, I386OP(jl_rel16), I386OP(jl_rel32), },
|
||||
{ 0x8D, OP_2BYTE|OP_I386, I386OP(jge_rel16), I386OP(jge_rel32), },
|
||||
{ 0x8E, OP_2BYTE|OP_I386, I386OP(jle_rel16), I386OP(jle_rel32), },
|
||||
{ 0x8F, OP_2BYTE|OP_I386, I386OP(jg_rel16), I386OP(jg_rel32), },
|
||||
{ 0x90, OP_2BYTE|OP_I386, I386OP(seto_rm8), I386OP(seto_rm8), },
|
||||
{ 0x91, OP_2BYTE|OP_I386, I386OP(setno_rm8), I386OP(setno_rm8), },
|
||||
{ 0x92, OP_2BYTE|OP_I386, I386OP(setc_rm8), I386OP(setc_rm8), },
|
||||
{ 0x93, OP_2BYTE|OP_I386, I386OP(setnc_rm8), I386OP(setnc_rm8), },
|
||||
{ 0x94, OP_2BYTE|OP_I386, I386OP(setz_rm8), I386OP(setz_rm8), },
|
||||
{ 0x95, OP_2BYTE|OP_I386, I386OP(setnz_rm8), I386OP(setnz_rm8), },
|
||||
{ 0x96, OP_2BYTE|OP_I386, I386OP(setbe_rm8), I386OP(setbe_rm8), },
|
||||
{ 0x97, OP_2BYTE|OP_I386, I386OP(seta_rm8), I386OP(seta_rm8), },
|
||||
{ 0x98, OP_2BYTE|OP_I386, I386OP(sets_rm8), I386OP(sets_rm8), },
|
||||
{ 0x99, OP_2BYTE|OP_I386, I386OP(setns_rm8), I386OP(setns_rm8), },
|
||||
{ 0x9A, OP_2BYTE|OP_I386, I386OP(setp_rm8), I386OP(setp_rm8), },
|
||||
{ 0x9B, OP_2BYTE|OP_I386, I386OP(setnp_rm8), I386OP(setnp_rm8), },
|
||||
{ 0x9C, OP_2BYTE|OP_I386, I386OP(setl_rm8), I386OP(setl_rm8), },
|
||||
{ 0x9D, OP_2BYTE|OP_I386, I386OP(setge_rm8), I386OP(setge_rm8), },
|
||||
{ 0x9E, OP_2BYTE|OP_I386, I386OP(setle_rm8), I386OP(setle_rm8), },
|
||||
{ 0x9F, OP_2BYTE|OP_I386, I386OP(setg_rm8), I386OP(setg_rm8), },
|
||||
{ 0xA0, OP_2BYTE|OP_I386, I386OP(push_fs16), I386OP(push_fs32), },
|
||||
{ 0xA1, OP_2BYTE|OP_I386, I386OP(pop_fs16), I386OP(pop_fs32), },
|
||||
{ 0xA2, OP_2BYTE|OP_I486, I486OP(cpuid), I486OP(cpuid), },
|
||||
{ 0xA3, OP_2BYTE|OP_I386, I386OP(bt_rm16_r16), I386OP(bt_rm32_r32), },
|
||||
{ 0xA4, OP_2BYTE|OP_I386, I386OP(shld16_i8), I386OP(shld32_i8), },
|
||||
{ 0xA5, OP_2BYTE|OP_I386, I386OP(shld16_cl), I386OP(shld32_cl), },
|
||||
{ 0xA8, OP_2BYTE|OP_I386, I386OP(push_gs16), I386OP(push_gs32), },
|
||||
{ 0xA9, OP_2BYTE|OP_I386, I386OP(pop_gs16), I386OP(pop_gs32), },
|
||||
{ 0xAA, OP_2BYTE|OP_I386, I386OP(unimplemented), I386OP(unimplemented), },
|
||||
{ 0xAB, OP_2BYTE|OP_I386, I386OP(bts_rm16_r16), I386OP(bts_rm32_r32), },
|
||||
{ 0xAC, OP_2BYTE|OP_I386, I386OP(shrd16_i8), I386OP(shrd32_i8), },
|
||||
{ 0xAD, OP_2BYTE|OP_I386, I386OP(shrd16_cl), I386OP(shrd32_cl), },
|
||||
{ 0xAE, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(invalid), },
|
||||
{ 0xAF, OP_2BYTE|OP_I386, I386OP(imul_r16_rm16), I386OP(imul_r32_rm32), },
|
||||
{ 0xB0, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm8_r8), I486OP(cmpxchg_rm8_r8), },
|
||||
{ 0xB1, OP_2BYTE|OP_I486, I486OP(cmpxchg_rm16_r16), I486OP(cmpxchg_rm32_r32), },
|
||||
{ 0xB2, OP_2BYTE|OP_I386, I386OP(lss16), I386OP(lss32), },
|
||||
{ 0xB3, OP_2BYTE|OP_I386, I386OP(btr_rm16_r16), I386OP(btr_rm32_r32), },
|
||||
{ 0xB4, OP_2BYTE|OP_I386, I386OP(lfs16), I386OP(lfs32), },
|
||||
{ 0xB5, OP_2BYTE|OP_I386, I386OP(lgs16), I386OP(lgs32), },
|
||||
{ 0xB6, OP_2BYTE|OP_I386, I386OP(movzx_r16_rm8), I386OP(movzx_r32_rm8), },
|
||||
{ 0xB7, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movzx_r32_rm16), },
|
||||
{ 0xBA, OP_2BYTE|OP_I386, I386OP(group0FBA_16), I386OP(group0FBA_32), },
|
||||
{ 0xBB, OP_2BYTE|OP_I386, I386OP(btc_rm16_r16), I386OP(btc_rm32_r32), },
|
||||
{ 0xBC, OP_2BYTE|OP_I386, I386OP(bsf_r16_rm16), I386OP(bsf_r32_rm32), },
|
||||
{ 0xBD, OP_2BYTE|OP_I386, I386OP(bsr_r16_rm16), I386OP(bsr_r32_rm32), },
|
||||
{ 0xBE, OP_2BYTE|OP_I386, I386OP(movsx_r16_rm8), I386OP(movsx_r32_rm8), },
|
||||
{ 0xBF, OP_2BYTE|OP_I386, I386OP(invalid), I386OP(movsx_r32_rm16), },
|
||||
{ 0xC0, OP_2BYTE|OP_I486, I486OP(xadd_rm8_r8), I486OP(xadd_rm8_r8), },
|
||||
{ 0xC1, OP_2BYTE|OP_I486, I486OP(xadd_rm16_r16), I486OP(xadd_rm32_r32), },
|
||||
{ 0xC7, OP_2BYTE|OP_PENTIUM, PENTIUMOP(cmpxchg8b_m64), PENTIUMOP(cmpxchg8b_m64), },
|
||||
{ 0xC8, OP_2BYTE|OP_I486, I486OP(bswap_eax), I486OP(bswap_eax), },
|
||||
{ 0xC9, OP_2BYTE|OP_I486, I486OP(bswap_ecx), I486OP(bswap_ecx), },
|
||||
{ 0xCA, OP_2BYTE|OP_I486, I486OP(bswap_edx), I486OP(bswap_edx), },
|
||||
{ 0xCB, OP_2BYTE|OP_I486, I486OP(bswap_ebx), I486OP(bswap_ebx), },
|
||||
{ 0xCC, OP_2BYTE|OP_I486, I486OP(bswap_esp), I486OP(bswap_esp), },
|
||||
{ 0xCD, OP_2BYTE|OP_I486, I486OP(bswap_ebp), I486OP(bswap_ebp), },
|
||||
{ 0xCE, OP_2BYTE|OP_I486, I486OP(bswap_esi), I486OP(bswap_esi), },
|
||||
{ 0xCF, OP_2BYTE|OP_I486, I486OP(bswap_edi), I486OP(bswap_edi), }
|
||||
};
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,424 @@
|
||||
/* Intel 486+ specific opcodes */
|
||||
|
||||
static void I486OP(cpuid)(i386_state *cpustate) /* Opcode 0x0F A2 */
|
||||
{
|
||||
if (cpustate->cpuid_id0 == 0)
|
||||
{
|
||||
/* this 486 doesn't support the CPUID instruction */
|
||||
logerror("CPUID not supported at %08x!\n", cpustate->eip);
|
||||
i386_trap(cpustate, 6, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (REG32(EAX))
|
||||
{
|
||||
case 0:
|
||||
{
|
||||
REG32(EAX) = cpustate->cpuid_max_input_value_eax;
|
||||
REG32(EBX) = cpustate->cpuid_id0;
|
||||
REG32(ECX) = cpustate->cpuid_id2;
|
||||
REG32(EDX) = cpustate->cpuid_id1;
|
||||
CYCLES(cpustate,CYCLES_CPUID);
|
||||
break;
|
||||
}
|
||||
|
||||
case 1:
|
||||
{
|
||||
REG32(EAX) = cpustate->cpu_version;
|
||||
REG32(EDX) = cpustate->feature_flags;
|
||||
CYCLES(cpustate,CYCLES_CPUID_EAX1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(invd)(i386_state *cpustate) /* Opcode 0x0f 08 */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
CYCLES(cpustate,CYCLES_INVD);
|
||||
}
|
||||
|
||||
static void I486OP(wbinvd)(i386_state *cpustate) /* Opcode 0x0f 09 */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
}
|
||||
|
||||
static void I486OP(cmpxchg_rm8_r8)(i386_state *cpustate) /* Opcode 0x0f b0 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT8 dst = LOAD_RM8(modrm);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
|
||||
if( REG8(AL) == dst ) {
|
||||
STORE_RM8(modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
|
||||
} else {
|
||||
REG8(AL) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
|
||||
}
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT8 dst = READ8(cpustate,ea);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
|
||||
if( REG8(AL) == dst ) {
|
||||
WRITE8(cpustate,modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG8(AL) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(cmpxchg_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f b1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT16 dst = LOAD_RM16(modrm);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
|
||||
if( REG16(AX) == dst ) {
|
||||
STORE_RM16(modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
|
||||
} else {
|
||||
REG16(AX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
|
||||
}
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT16 dst = READ16(cpustate,ea);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
|
||||
if( REG16(AX) == dst ) {
|
||||
WRITE16(cpustate,modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG16(AX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(cmpxchg_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f b1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT32 dst = LOAD_RM32(modrm);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
|
||||
if( REG32(EAX) == dst ) {
|
||||
STORE_RM32(modrm, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_T);
|
||||
} else {
|
||||
REG32(EAX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_REG_F);
|
||||
}
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT32 dst = READ32(cpustate,ea);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
|
||||
if( REG32(EAX) == dst ) {
|
||||
WRITE32(cpustate,ea, src);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG32(EAX) = dst;
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(xadd_rm8_r8)(i386_state *cpustate) /* Opcode 0x0f c0 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT8 dst = LOAD_RM8(modrm);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
STORE_RM16(modrm, dst + src);
|
||||
STORE_REG16(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_REG);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT8 dst = READ8(cpustate,ea);
|
||||
UINT8 src = LOAD_REG8(modrm);
|
||||
WRITE8(cpustate,ea, dst + src);
|
||||
STORE_REG8(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(xadd_rm16_r16)(i386_state *cpustate) /* Opcode 0x0f c1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT16 dst = LOAD_RM16(modrm);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
STORE_RM16(modrm, dst + src);
|
||||
STORE_REG16(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_REG);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT16 dst = READ16(cpustate,ea);
|
||||
UINT16 src = LOAD_REG16(modrm);
|
||||
WRITE16(cpustate,ea, dst + src);
|
||||
STORE_REG16(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(xadd_rm32_r32)(i386_state *cpustate) /* Opcode 0x0f c1 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
if( modrm >= 0xc0 ) {
|
||||
UINT32 dst = LOAD_RM32(modrm);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
STORE_RM32(modrm, dst + src);
|
||||
STORE_REG32(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_REG);
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
UINT32 dst = READ32(cpustate,ea);
|
||||
UINT32 src = LOAD_REG32(modrm);
|
||||
WRITE32(cpustate,ea, dst + src);
|
||||
STORE_REG32(modrm, dst);
|
||||
CYCLES(cpustate,CYCLES_XADD_REG_MEM);
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(group0F01_16)(i386_state *cpustate) /* Opcode 0x0f 01 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT16 address;
|
||||
UINT32 ea;
|
||||
|
||||
switch( (modrm >> 3) & 0x7 )
|
||||
{
|
||||
case 0: /* SGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->gdtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->gdtr.base & 0xffffff);
|
||||
CYCLES(cpustate,CYCLES_SGDT);
|
||||
break;
|
||||
}
|
||||
case 1: /* SIDT */
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->idtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->idtr.base & 0xffffff);
|
||||
CYCLES(cpustate,CYCLES_SIDT);
|
||||
break;
|
||||
}
|
||||
case 2: /* LGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->gdtr.limit = READ16(cpustate,ea);
|
||||
cpustate->gdtr.base = READ32(cpustate,ea + 2) & 0xffffff;
|
||||
CYCLES(cpustate,CYCLES_LGDT);
|
||||
break;
|
||||
}
|
||||
case 3: /* LIDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM16(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->idtr.limit = READ16(cpustate,ea);
|
||||
cpustate->idtr.base = READ32(cpustate,ea + 2) & 0xffffff;
|
||||
CYCLES(cpustate,CYCLES_LIDT);
|
||||
break;
|
||||
}
|
||||
case 4: /* SMSW */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
STORE_RM16(modrm, cpustate->cr[0]);
|
||||
CYCLES(cpustate,CYCLES_SMSW_REG);
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
WRITE16(cpustate,ea, cpustate->cr[0]);
|
||||
CYCLES(cpustate,CYCLES_SMSW_MEM);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 6: /* LMSW */
|
||||
{
|
||||
/* TODO: Check for protection fault */
|
||||
UINT8 b;
|
||||
if( modrm >= 0xc0 ) {
|
||||
b = LOAD_RM8(modrm);
|
||||
CYCLES(cpustate,CYCLES_LMSW_REG);
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
CYCLES(cpustate,CYCLES_LMSW_MEM);
|
||||
b = READ8(cpustate,ea);
|
||||
}
|
||||
cpustate->cr[0] &= ~0x03;
|
||||
cpustate->cr[0] |= b & 0x03;
|
||||
break;
|
||||
}
|
||||
case 7: /* INVLPG */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
i386_fatal("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(group0F01_32)(i386_state *cpustate) /* Opcode 0x0f 01 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
UINT32 address, ea;
|
||||
|
||||
switch( (modrm >> 3) & 0x7 )
|
||||
{
|
||||
case 0: /* SGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->gdtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->gdtr.base);
|
||||
CYCLES(cpustate,CYCLES_SGDT);
|
||||
break;
|
||||
}
|
||||
case 1: /* SIDT */
|
||||
{
|
||||
if (modrm >= 0xc0)
|
||||
{
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
}
|
||||
else
|
||||
{
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
WRITE16(cpustate,ea, cpustate->idtr.limit);
|
||||
WRITE32(cpustate,ea + 2, cpustate->idtr.base);
|
||||
CYCLES(cpustate,CYCLES_SIDT);
|
||||
break;
|
||||
}
|
||||
case 2: /* LGDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->gdtr.limit = READ16(cpustate,ea);
|
||||
cpustate->gdtr.base = READ32(cpustate,ea + 2);
|
||||
CYCLES(cpustate,CYCLES_LGDT);
|
||||
break;
|
||||
}
|
||||
case 3: /* LIDT */
|
||||
{
|
||||
if( modrm >= 0xc0 ) {
|
||||
address = LOAD_RM32(modrm);
|
||||
ea = i386_translate( cpustate, CS, address );
|
||||
} else {
|
||||
ea = GetEA(cpustate,modrm);
|
||||
}
|
||||
cpustate->idtr.limit = READ16(cpustate,ea);
|
||||
cpustate->idtr.base = READ32(cpustate,ea + 2);
|
||||
CYCLES(cpustate,CYCLES_LIDT);
|
||||
break;
|
||||
}
|
||||
case 7: /* INVLPG */
|
||||
{
|
||||
/* Nothing to do ? */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
i386_fatal("i486: unimplemented opcode 0x0f 01 /%d at %08X", (modrm >> 3) & 0x7, cpustate->eip - 2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void I486OP(bswap_eax)(i386_state *cpustate) /* Opcode 0x0f 38 */
|
||||
{
|
||||
REG32(EAX) = SWITCH_ENDIAN_32(REG32(EAX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_ecx)(i386_state *cpustate) /* Opcode 0x0f 39 */
|
||||
{
|
||||
REG32(ECX) = SWITCH_ENDIAN_32(REG32(ECX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_edx)(i386_state *cpustate) /* Opcode 0x0f 3A */
|
||||
{
|
||||
REG32(EDX) = SWITCH_ENDIAN_32(REG32(EDX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_ebx)(i386_state *cpustate) /* Opcode 0x0f 3B */
|
||||
{
|
||||
REG32(EBX) = SWITCH_ENDIAN_32(REG32(EBX));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_esp)(i386_state *cpustate) /* Opcode 0x0f 3C */
|
||||
{
|
||||
REG32(ESP) = SWITCH_ENDIAN_32(REG32(ESP));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_ebp)(i386_state *cpustate) /* Opcode 0x0f 3D */
|
||||
{
|
||||
REG32(EBP) = SWITCH_ENDIAN_32(REG32(EBP));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_esi)(i386_state *cpustate) /* Opcode 0x0f 3E */
|
||||
{
|
||||
REG32(ESI) = SWITCH_ENDIAN_32(REG32(ESI));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
|
||||
static void I486OP(bswap_edi)(i386_state *cpustate) /* Opcode 0x0f 3F */
|
||||
{
|
||||
REG32(EDI) = SWITCH_ENDIAN_32(REG32(EDI));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/* Pentium+ specific opcodes */
|
||||
|
||||
static void PENTIUMOP(rdmsr)(i386_state *cpustate) /* Opcode 0x0f 32 */
|
||||
{
|
||||
/* TODO */
|
||||
CYCLES(cpustate,CYCLES_RDMSR);
|
||||
}
|
||||
|
||||
static void PENTIUMOP(wrmsr)(i386_state *cpustate) /* Opcode 0x0f 30 */
|
||||
{
|
||||
/* TODO */
|
||||
CYCLES(cpustate,1); /* TODO: correct cycle count */
|
||||
}
|
||||
|
||||
static void PENTIUMOP(rdtsc)(i386_state *cpustate) /* Opcode 0x0f 31 */
|
||||
{
|
||||
UINT64 ts = cpustate->tsc + (cpustate->base_cycles - i386_ICount);
|
||||
REG32(EAX) = (UINT32)(ts);
|
||||
REG32(EDX) = (UINT32)(ts >> 32);
|
||||
|
||||
CYCLES(cpustate,CYCLES_RDTSC);
|
||||
}
|
||||
|
||||
static void I386OP(cyrix_unknown)(i386_state *cpustate) /* Opcode 0x0f 74 */
|
||||
{
|
||||
CYCLES(cpustate,1);
|
||||
}
|
||||
|
||||
static void PENTIUMOP(cmpxchg8b_m64)(i386_state *cpustate) /* Opcode 0x0f c7 */
|
||||
{
|
||||
UINT8 modm = FETCH(cpustate);
|
||||
if( modm >= 0xc0 ) {
|
||||
i386_fatal("pentium: cmpxchg8b_m64 - invalid modm");
|
||||
} else {
|
||||
UINT32 ea = GetEA(cpustate,modm);
|
||||
UINT64 value = READ64(cpustate,ea);
|
||||
UINT64 edx_eax = (((UINT64) REG32(EDX)) << 32) | REG32(EAX);
|
||||
UINT64 ecx_ebx = (((UINT64) REG32(ECX)) << 32) | REG32(EBX);
|
||||
|
||||
if( value == edx_eax ) {
|
||||
WRITE64(cpustate,ea, ecx_ebx);
|
||||
cpustate->ZF = 1;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_T);
|
||||
} else {
|
||||
REG32(EDX) = (UINT32) (value >> 32);
|
||||
REG32(EAX) = (UINT32) (value >> 0);
|
||||
cpustate->ZF = 0;
|
||||
CYCLES(cpustate,CYCLES_CMPXCHG_REG_MEM_F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,352 @@
|
||||
/* Intel x87 FPU opcodes */
|
||||
|
||||
#define ST(x) (cpustate->fpu_reg[(cpustate->fpu_top + (x)) & 7])
|
||||
#define FPU_INFINITY_DOUBLE COMBINE_64_32_32(0x7ff00000, 0x00000000)
|
||||
#define FPU_INFINITY_SINGLE (0x7f800000)
|
||||
#define FPU_SIGN_BIT_DOUBLE COMBINE_64_32_32(0x80000000, 0x00000000)
|
||||
#define FPU_SIGN_BIT_SINGLE (0x80000000)
|
||||
|
||||
/* FPU control word flags */
|
||||
#define FPU_MASK_INVALID_OP 0x0001
|
||||
#define FPU_MASK_DENORMAL_OP 0x0002
|
||||
#define FPU_MASK_ZERO_DIVIDE 0x0004
|
||||
#define FPU_MASK_OVERFLOW 0x0008
|
||||
#define FPU_MASK_UNDERFLOW 0x0010
|
||||
#define FPU_MASK_PRECISION 0x0020
|
||||
|
||||
/* FPU status word flags */
|
||||
#define FPU_BUSY 0x8000
|
||||
#define FPU_C3 0x4000
|
||||
#define FPU_STACK_TOP_MASK 0x3800
|
||||
#define FPU_C2 0x0400
|
||||
#define FPU_C1 0x0200
|
||||
#define FPU_C0 0x0100
|
||||
#define FPU_ERROR_SUMMARY 0x0080
|
||||
#define FPU_STACK_FAULT 0x0040
|
||||
#define FPU_EXCEPTION_PRECISION 0x0020
|
||||
#define FPU_EXCEPTION_UNDERFLOW 0x0010
|
||||
#define FPU_EXCEPTION_OVERFLOW 0x0008
|
||||
#define FPU_EXCEPTION_ZERO_DIVIDE 0x0004
|
||||
#define FPU_EXCEPTION_DENORMAL_OP 0x0002
|
||||
#define FPU_EXCEPTION_INVALID_OP 0x0001
|
||||
|
||||
static INLINE void FPU_PUSH(i386_state *cpustate, X87_REG value)
|
||||
{
|
||||
cpustate->fpu_top--;
|
||||
if (cpustate->fpu_top < 0)
|
||||
{
|
||||
cpustate->fpu_top = 7;
|
||||
}
|
||||
|
||||
cpustate->fpu_reg[cpustate->fpu_top] = value;
|
||||
}
|
||||
|
||||
static INLINE X87_REG FPU_POP(i386_state *cpustate)
|
||||
{
|
||||
X87_REG value = cpustate->fpu_reg[cpustate->fpu_top];
|
||||
|
||||
cpustate->fpu_tag_word |= 3 << (cpustate->fpu_top * 2); /* set FPU register tag to 3 (empty) */
|
||||
|
||||
cpustate->fpu_top++;
|
||||
if (cpustate->fpu_top > 7)
|
||||
{
|
||||
cpustate->fpu_top = 0;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_d8)(i386_state *cpustate) /* Opcode 0xd8 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
i386_fatal("I386: FPU Op D8 %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_d9)(i386_state *cpustate) /* Opcode 0xd9 */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
case 5: /* FLDCW */
|
||||
{
|
||||
cpustate->fpu_control_word = READ16(cpustate,ea);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 7: /* FSTCW */
|
||||
{
|
||||
WRITE16(cpustate,ea, cpustate->fpu_control_word);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
/* FLD */
|
||||
case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07:
|
||||
{
|
||||
X87_REG t = ST(modrm & 7);
|
||||
FPU_PUSH(cpustate,t);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x20: /* FCHS */
|
||||
{
|
||||
ST(0).i ^= FPU_SIGN_BIT_DOUBLE;
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x28: /* FLD1 */
|
||||
{
|
||||
X87_REG t;
|
||||
t.f = 1.0;
|
||||
FPU_PUSH(cpustate,t);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x2e: /* FLDZ */
|
||||
{
|
||||
X87_REG t;
|
||||
t.f = 0.0;
|
||||
FPU_PUSH(cpustate,t);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
default:
|
||||
i386_fatal("I386: FPU Op D9 %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_da)(i386_state *cpustate) /* Opcode 0xda */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
i386_fatal("I386: FPU Op DA %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_db)(i386_state *cpustate) /* Opcode 0xdb */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
i386_fatal("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x23: /* FINIT */
|
||||
{
|
||||
cpustate->fpu_control_word = 0x37f;
|
||||
cpustate->fpu_status_word = 0;
|
||||
cpustate->fpu_tag_word = 0xffff;
|
||||
cpustate->fpu_data_ptr = 0;
|
||||
cpustate->fpu_inst_ptr = 0;
|
||||
cpustate->fpu_opcode = 0;
|
||||
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
case 0x24: /* FSETPM (treated as nop on 387+) */
|
||||
{
|
||||
CYCLES(cpustate,1);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DB %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_dc)(i386_state *cpustate) /* Opcode 0xdc */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
/*UINT32 ea = GetEA(cpustate,modrm); */
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
{
|
||||
/* FDIVR */
|
||||
if ((ST(modrm & 7).i & COMBINE_64_32_32(0x7fffffff, 0xffffffff)) == 0)
|
||||
{
|
||||
/* set result as infinity if zero divide is masked */
|
||||
if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
|
||||
{
|
||||
ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ST(modrm & 7).f = ST(0).f / ST(modrm & 7).f;
|
||||
}
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DC %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_dd)(i386_state *cpustate) /* Opcode 0xdd */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
UINT32 ea = GetEA(cpustate,modrm);
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
case 7: /* FSTSW */
|
||||
{
|
||||
WRITE16(cpustate,ea, (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10));
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DD %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_de)(i386_state *cpustate) /* Opcode 0xde */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
/* UINT32 ea = GetEA(cpustate,modrm); */
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x19: /* FCOMPP */
|
||||
{
|
||||
cpustate->fpu_status_word &= ~(FPU_C3 | FPU_C2 | FPU_C0);
|
||||
if (ST(0).f > ST(1).f)
|
||||
{
|
||||
/* C3 = 0, C2 = 0, C0 = 0 */
|
||||
}
|
||||
else if (ST(0).f < ST(1).f)
|
||||
{
|
||||
cpustate->fpu_status_word |= FPU_C0;
|
||||
}
|
||||
else if (ST(0).f == ST(1).f)
|
||||
{
|
||||
cpustate->fpu_status_word |= FPU_C3;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* unordered */
|
||||
cpustate->fpu_status_word |= (FPU_C3 | FPU_C2 | FPU_C0);
|
||||
}
|
||||
FPU_POP(cpustate);
|
||||
FPU_POP(cpustate);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
/* FDIVP */
|
||||
case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||
{
|
||||
if ((ST(0).i & COMBINE_64_32_32(0x7fffffff, 0xffffffff)) == 0)
|
||||
{
|
||||
/* set result as infinity if zero divide is masked */
|
||||
if (cpustate->fpu_control_word & FPU_MASK_ZERO_DIVIDE)
|
||||
{
|
||||
ST(modrm & 7).i |= FPU_INFINITY_DOUBLE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ST(modrm & 7).f = ST(modrm & 7).f / ST(0).f;
|
||||
}
|
||||
FPU_POP(cpustate);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DE %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void I386OP(fpu_group_df)(i386_state *cpustate) /* Opcode 0xdf */
|
||||
{
|
||||
UINT8 modrm = FETCH(cpustate);
|
||||
|
||||
if (modrm < 0xc0)
|
||||
{
|
||||
/* UINT32 ea = GetEA(cpustate,modrm); */
|
||||
|
||||
switch ((modrm >> 3) & 0x7)
|
||||
{
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (modrm & 0x3f)
|
||||
{
|
||||
case 0x20: /* FSTSW AX */
|
||||
{
|
||||
REG16(AX) = (cpustate->fpu_status_word & ~FPU_STACK_TOP_MASK) | (cpustate->fpu_top << 10);
|
||||
CYCLES(cpustate,1); /* TODO */
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
i386_fatal("I386: FPU Op DF %02X at %08X", modrm, cpustate->pc-2);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,104 @@
|
||||
/*****************************************************************************
|
||||
*
|
||||
* i8051.h
|
||||
* Portable MCS-51 Family Emulator
|
||||
*
|
||||
* Copyright Steve Ellenoff, all rights reserved.
|
||||
*
|
||||
* - This source code is released as freeware for non-commercial purposes.
|
||||
* - You are free to use and redistribute this code in modified or
|
||||
* unmodified form, provided you list me in the credits.
|
||||
* - If you modify this source code, you must add a notice to each modified
|
||||
* source file that it has been changed. If you're a nice person, you
|
||||
* will clearly mark each change too. :)
|
||||
* - If you wish to use this for commercial purposes, please contact me at
|
||||
* sellenoff@hotmail.com
|
||||
* - The author of this copywritten work reserves the right to change the
|
||||
* terms of its usage and license at any time, including retroactively
|
||||
* - This entire notice must remain in the source code.
|
||||
*
|
||||
* October 2008, Couriersud: Major rewrite (MAME 0.128-0.139 mcs51 core)
|
||||
*
|
||||
* MODIFIED for mame2003-plus: backported from MAME 0.139 src/emu/cpu/mcs51
|
||||
* to the MAME 0.78 cpu_interface. DS5002FP and 80C52 variants removed,
|
||||
* internal RAM/SFRs kept inside the CPU context, MOVX routed through
|
||||
* per-CPU driver handlers (the 0.78 core has no DATA address space).
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
#ifndef _I8051_H
|
||||
#define _I8051_H
|
||||
|
||||
#include "cpuintrf.h"
|
||||
#include "osd_cpu.h"
|
||||
#include "memory.h"
|
||||
|
||||
/* The MCS-51 runs one machine cycle every 12 oscillator clocks.
|
||||
Give the CPU clock in the machine driver as XTAL / I8051_CLOCK_DIVIDER. */
|
||||
#define I8051_CLOCK_DIVIDER 12
|
||||
|
||||
/****************************************************************************
|
||||
* Input lines (use with cpu_set_irq_line)
|
||||
* INT0/INT1 follow the TCON IT0/IT1 setting (edge or level);
|
||||
* T0/T1 count 0->1 transitions when the timer is in counter mode,
|
||||
* so drive them with PULSE_LINE.
|
||||
****************************************************************************/
|
||||
enum
|
||||
{
|
||||
I8051_INT0_LINE = 0, /* P3.2: External Interrupt 0 */
|
||||
I8051_INT1_LINE, /* P3.3: External Interrupt 1 */
|
||||
I8051_RX_LINE, /* P3.0: Serial Port Receive Line */
|
||||
I8051_T0_LINE, /* P3.4: Timer 0 External Input */
|
||||
I8051_T1_LINE, /* P3.5: Timer 1 External Input */
|
||||
I8051_INPUT_LINES
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Port space: the four parallel ports. Map them in the MCU's
|
||||
* PORT_READ/PORT_WRITE tables, e.g. { I8051_P1, I8051_P1, mcu_p1_w }
|
||||
****************************************************************************/
|
||||
#define I8051_P0 0x00
|
||||
#define I8051_P1 0x01
|
||||
#define I8051_P2 0x02
|
||||
#define I8051_P3 0x03
|
||||
|
||||
/****************************************************************************
|
||||
* Registers
|
||||
****************************************************************************/
|
||||
enum
|
||||
{
|
||||
I8051_PC=1, I8051_SP, I8051_PSW, I8051_ACC, I8051_B, I8051_DPH, I8051_DPL, I8051_IE,
|
||||
I8051_R0, I8051_R1, I8051_R2, I8051_R3, I8051_R4, I8051_R5, I8051_R6, I8051_R7, I8051_RB
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Public functions
|
||||
****************************************************************************/
|
||||
extern int i8051_ICount;
|
||||
|
||||
extern void i8051_init(void);
|
||||
extern void i8051_reset(void *param);
|
||||
extern void i8051_exit(void);
|
||||
extern int i8051_execute(int cycles);
|
||||
extern unsigned i8051_get_context(void *dst);
|
||||
extern void i8051_set_context(void *src);
|
||||
extern unsigned i8051_get_reg(int regnum);
|
||||
extern void i8051_set_reg(int regnum, unsigned val);
|
||||
extern void i8051_set_irq_line(int irqline, int state);
|
||||
extern void i8051_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *i8051_info(void *context, int regnum);
|
||||
extern unsigned i8051_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* External data memory (MOVX). Called from MACHINE_INIT; cpunum is the MCU's
|
||||
CPU index. Unmapped reads return 0xff, unmapped writes are dropped. */
|
||||
extern void i8051_set_movx_handlers(int cpunum, read8_handler rd, write8_handler wr);
|
||||
|
||||
/* Serial port hooks (optional). */
|
||||
extern void i8051_set_serial_tx_callback(int cpunum, void (*callback)(int data));
|
||||
extern void i8051_set_serial_rx_callback(int cpunum, int (*callback)(void));
|
||||
|
||||
/* The 8751 is an 8051 with internal EPROM: the driver loads the dump in the
|
||||
MCU's CPU region exactly as for the 8051. */
|
||||
#define CPU_I8751 CPU_I8051
|
||||
|
||||
#endif /* _I8051_H */
|
||||
@@ -0,0 +1,981 @@
|
||||
/* MODIFIED for mame2003-plus: C89 comments, device reference removed (backport of MAME 0.139 mcs51ops.c) */
|
||||
/*******************************************************************************************
|
||||
NOTE: All registers are accessed directly, instead of using the SFR_R() function for speed
|
||||
Direct register access is availabe from the R_(register name) macros.. ex: ACC for the ACC
|
||||
with the exception of the PC
|
||||
********************************************************************************************/
|
||||
|
||||
/*ACALL code addr 1: aaa1 0001 */
|
||||
OPHANDLER( acall )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab code address byte */
|
||||
PUSH_PC(); /*Save PC to the stack */
|
||||
/*Thanks Gerrit for help with this! :) */
|
||||
PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
|
||||
}
|
||||
|
||||
/*ADD A, #data 1: 0010 0100 */
|
||||
OPHANDLER( add_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADD A, data addr 1: 0010 0101 */
|
||||
OPHANDLER( add_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADD A, @R0/@R1 1: 0010 011i */
|
||||
OPHANDLER( add_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from memory pointed to by R0 or R1 */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADD A, R0 to R7 1: 0010 1rrr */
|
||||
OPHANDLER( add_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
UINT8 result = ACC + data; /*Add data to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,0); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, #data 1: 0011 0100 */
|
||||
OPHANDLER( addc_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, data addr 1: 0011 0101 */
|
||||
OPHANDLER( addc_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, @R0/@R1 1: 0011 011i */
|
||||
OPHANDLER( addc_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from memory pointed to by R0 or R1 */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*ADDC A, R0 to R7 1: 0011 1rrr */
|
||||
OPHANDLER( addc_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
UINT8 result = ACC + data + GET_CY; /*Add data + carry flag to accumulator */
|
||||
DO_ADD_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*AJMP code addr 1: aaa0 0001 */
|
||||
OPHANDLER( ajmp )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab code address byte */
|
||||
/*Thanks Gerrit for help with this! :) */
|
||||
PC = (PC & 0xf800) | ((r & 0xe0) << 3) | addr;
|
||||
}
|
||||
|
||||
/*ANL data addr, A 1: 0101 0010 */
|
||||
OPHANDLER( anl_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,data & ACC); /*Set data address value to it's value Logical AND with ACC */
|
||||
}
|
||||
|
||||
/*ANL data addr, #data 1: 0101 0011 */
|
||||
OPHANDLER( anl_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 srcdata = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,srcdata & data); /*Set data address value to it's value Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, #data 1: 0101 0100 */
|
||||
OPHANDLER( anl_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, data addr 1: 0101 0101 */
|
||||
OPHANDLER( anl_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, @RO/@R1 1: 0101 011i */
|
||||
OPHANDLER( anl_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from address R0 or R1 points to */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL A, RO to R7 1: 0101 1rrr */
|
||||
OPHANDLER( anl_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
SET_ACC(ACC & data); /*Set ACC to value of ACC Logical AND with Data */
|
||||
}
|
||||
|
||||
/*ANL C, bit addr 1: 1000 0010 */
|
||||
OPHANDLER( anl_c_bitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
SET_CY( (cy & bit) ); /*Set Carry flag to Carry Flag Value Logical AND with Bit */
|
||||
}
|
||||
|
||||
/*ANL C,/bit addr 1: 1011 0000 */
|
||||
OPHANDLER( anl_c_nbitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
bit = ((~bit)&1); /*Complement bit */
|
||||
SET_CY( (cy & bit) ); /*Set Carry flag to Carry Flag Value Logical AND with Complemented Bit */
|
||||
}
|
||||
|
||||
/*CJNE A, #data, code addr 1: 1011 0100 */
|
||||
OPHANDLER( cjne_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
|
||||
if(ACC != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (ACC < data) );
|
||||
}
|
||||
|
||||
/*CJNE A, data addr, code addr 1: 1011 0101 */
|
||||
OPHANDLER( cjne_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
UINT8 data = IRAM_R(addr); /*Pull value from data address */
|
||||
|
||||
if(ACC != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (ACC < data) );
|
||||
}
|
||||
|
||||
/*CJNE @R0/@R1, #data, code addr 1: 1011 011i */
|
||||
OPHANDLER( cjne_ir_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
UINT8 srcdata = IRAM_IR(R_REG(r)); /*Grab value pointed to by R0 or R1 */
|
||||
|
||||
if(srcdata != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (srcdata < data) );
|
||||
}
|
||||
|
||||
/*CJNE R0 to R7, #data, code addr 1: 1011 1rrr */
|
||||
OPHANDLER( cjne_r_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
UINT8 srcdata = R_REG(r); /*Grab value of R0 - R7 */
|
||||
|
||||
if(srcdata != data) /*Jump if values are not equal */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
|
||||
/*Set carry flag to 1 if 1st compare value is < 2nd compare value */
|
||||
SET_CY( (srcdata < data) );
|
||||
}
|
||||
|
||||
/*CLR bit addr 1: 1100 0010 */
|
||||
OPHANDLER( clr_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
BIT_W(addr,0); /*Clear bit at specified bit address */
|
||||
}
|
||||
|
||||
/*CLR C 1: 1100 0011 */
|
||||
OPHANDLER( clr_c )
|
||||
{
|
||||
SET_CY(0); /*Clear Carry Flag */
|
||||
}
|
||||
|
||||
/*CLR A 1: 1110 0100 */
|
||||
OPHANDLER( clr_a )
|
||||
{
|
||||
SET_ACC(0); /*Clear Accumulator */
|
||||
}
|
||||
|
||||
/*CPL bit addr 1: 1011 0010 */
|
||||
OPHANDLER( cpl_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 data = (~BIT_R(addr))&1;
|
||||
BIT_W(addr,data); /*Complement bit at specified bit address */
|
||||
}
|
||||
|
||||
/*CPL C 1: 1011 0011 */
|
||||
OPHANDLER( cpl_c )
|
||||
{
|
||||
UINT8 bit = (~GET_CY)&1; /*Complement Carry Flag */
|
||||
SET_CY(bit);
|
||||
}
|
||||
|
||||
/*CPL A 1: 1111 0100 */
|
||||
OPHANDLER( cpl_a )
|
||||
{
|
||||
UINT8 data = ((~ACC)&0xff);
|
||||
SET_ACC(data); /*Complement Accumulator */
|
||||
}
|
||||
|
||||
/*DA A 1: 1101 0100 */
|
||||
OPHANDLER( da_a )
|
||||
{
|
||||
/*From several sources, since none said the same thing:
|
||||
The decimal adjust instruction is associated with the use of the ADD and ADDC instructions.
|
||||
The eight-bit value in the accumulator is adjusted to form two BCD digits of four bits each.
|
||||
If the accumulator contents bits 0-3 are greater than 9, OR the AC flag is set, then six is added to
|
||||
produce a proper BCD digit.
|
||||
If the carry is set, OR the four high bits 4-7 exceed nine, six is added to the value of these bits.
|
||||
The carry flag will be set if the result is > 0x99, but not cleared otherwise */
|
||||
|
||||
UINT16 new_acc = ACC & 0xff;
|
||||
if(GET_AC || (new_acc & 0x0f) > 0x09)
|
||||
new_acc += 0x06;
|
||||
if(GET_CY || ((new_acc & 0xf0) > 0x90) || (new_acc & ~0xff))
|
||||
new_acc += 0x60;
|
||||
SET_ACC(new_acc&0xff);
|
||||
if(new_acc & ~0xff)
|
||||
SET_CY(1);
|
||||
}
|
||||
|
||||
/*DEC A 1: 0001 0100 */
|
||||
OPHANDLER( dec_a )
|
||||
{
|
||||
SET_ACC(ACC-1);
|
||||
}
|
||||
|
||||
/*DEC data addr 1: 0001 0101 */
|
||||
OPHANDLER( dec_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr);
|
||||
IRAM_W(addr,data-1);
|
||||
}
|
||||
|
||||
/*DEC @R0/@R1 1: 0001 011i */
|
||||
OPHANDLER( dec_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r));
|
||||
IRAM_W(R_REG(r),data-1);
|
||||
}
|
||||
|
||||
/*DEC R0 to R7 1: 0001 1rrr */
|
||||
OPHANDLER( dec_r )
|
||||
{
|
||||
SET_REG(r, R_REG(r) - 1);
|
||||
}
|
||||
|
||||
/*DIV AB 1: 1000 0100 */
|
||||
OPHANDLER( div_ab )
|
||||
{
|
||||
if( B == 0 ) {
|
||||
/*Overflow flag is set! */
|
||||
SET_OV(1);
|
||||
/*Really the values are undefined according to the manual, but we'll just leave them as is.. */
|
||||
/*SET_ACC(0xff); */
|
||||
/*SFR_W(B,0xff); */
|
||||
}
|
||||
else {
|
||||
int a = (int)ACC / B;
|
||||
int b = (int)ACC % B;
|
||||
/*A gets quotient byte, B gets remainder byte */
|
||||
SET_ACC(a);
|
||||
B = b;
|
||||
/*Overflow flag is cleared */
|
||||
SET_OV(0);
|
||||
}
|
||||
/*Carry Flag is always cleared */
|
||||
SET_CY(0);
|
||||
}
|
||||
|
||||
/*DJNZ data addr, code addr 1: 1101 0101 */
|
||||
OPHANDLER( djnz_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
IRAM_W(addr,IRAM_R(addr) - 1); /*Decrement value contained at data address */
|
||||
if(IRAM_R(addr) != 0) /*Branch if contents of data address is not 0 */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*DJNZ R0 to R7,code addr 1: 1101 1rrr */
|
||||
OPHANDLER( djnz_r )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
SET_REG(r ,R_REG(r) - 1); /*Decrement value */
|
||||
if(R_REG(r) != 0) /*Branch if contents of R0 - R7 is not 0 */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*INC A 1: 0000 0100 */
|
||||
OPHANDLER( inc_a )
|
||||
{
|
||||
SET_ACC(ACC+1);
|
||||
}
|
||||
|
||||
/*INC data addr 1: 0000 0101 */
|
||||
OPHANDLER( inc_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr);
|
||||
IRAM_W(addr,data+1);
|
||||
}
|
||||
|
||||
/*INC @R0/@R1 1: 0000 011i */
|
||||
OPHANDLER( inc_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r));
|
||||
IRAM_W(R_REG(r),data+1);
|
||||
}
|
||||
|
||||
/*INC R0 to R7 1: 0000 1rrr */
|
||||
OPHANDLER( inc_r )
|
||||
{
|
||||
UINT8 data = R_REG(r);
|
||||
SET_REG(r, data + 1);
|
||||
}
|
||||
|
||||
/*INC DPTR 1: 1010 0011 */
|
||||
OPHANDLER( inc_dptr )
|
||||
{
|
||||
UINT16 dptr = (DPTR)+1;
|
||||
SET_DPTR(dptr);
|
||||
}
|
||||
|
||||
/*JB bit addr, code addr 1: 0010 0000 */
|
||||
OPHANDLER( jb )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(BIT_R(addr)) /*If bit set at specified bit address, jump */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JBC bit addr, code addr 1: 0001 0000 */
|
||||
OPHANDLER( jbc )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(BIT_R(addr)) { /*If bit set at specified bit address, jump */
|
||||
PC = PC + rel_addr;
|
||||
BIT_W(addr,0); /*Clear Bit also */
|
||||
}
|
||||
}
|
||||
|
||||
/*JC code addr 1: 0100 0000 */
|
||||
OPHANDLER( jc )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(GET_CY) /*Jump if Carry Flag Set */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JMP @A+DPTR 1: 0111 0011 */
|
||||
OPHANDLER( jmp_iadptr )
|
||||
{
|
||||
PC = ACC + DPTR;
|
||||
}
|
||||
|
||||
/*JNB bit addr, code addr 1: 0011 0000 */
|
||||
OPHANDLER( jnb )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(!BIT_R(addr)) /*If bit NOT set at specified bit address, jump */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JNC code addr 1: 0101 0000 */
|
||||
OPHANDLER( jnc )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(!GET_CY) /*Jump if Carry Flag not set */
|
||||
{
|
||||
PC = PC + rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JNZ code addr 1: 0111 0000 */
|
||||
OPHANDLER( jnz )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(ACC != 0) /*Branch if ACC is not 0 */
|
||||
{
|
||||
PC = PC+rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*JZ code addr 1: 0110 0000 */
|
||||
OPHANDLER( jz )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
if(ACC == 0) /*Branch if ACC is 0 */
|
||||
{
|
||||
PC = PC+rel_addr;
|
||||
}
|
||||
}
|
||||
|
||||
/*LCALL code addr 1: 0001 0010 */
|
||||
OPHANDLER( lcall )
|
||||
{
|
||||
UINT8 addr_hi, addr_lo;
|
||||
addr_hi = ROP_ARG(PC++);
|
||||
addr_lo = ROP_ARG(PC++);
|
||||
PUSH_PC();
|
||||
PC = (UINT16)((addr_hi<<8) | addr_lo);
|
||||
}
|
||||
|
||||
/*LJMP code addr 1: 0000 0010 */
|
||||
OPHANDLER( ljmp )
|
||||
{
|
||||
UINT8 addr_hi, addr_lo;
|
||||
addr_hi = ROP_ARG(PC++);
|
||||
addr_lo = ROP_ARG(PC++);
|
||||
PC = (UINT16)((addr_hi<<8) | addr_lo);
|
||||
}
|
||||
|
||||
/*MOV A, #data 1: 0111 0100 */
|
||||
OPHANDLER( mov_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(data); /*Store data to ACC */
|
||||
}
|
||||
|
||||
/*MOV A, data addr 1: 1110 0101 */
|
||||
OPHANDLER( mov_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
SET_ACC(IRAM_R(addr)); /*Store contents of data address to ACC */
|
||||
}
|
||||
|
||||
/*MOV A,@RO/@R1 1: 1110 011i */
|
||||
OPHANDLER( mov_a_ir )
|
||||
{
|
||||
SET_ACC(IRAM_IR(R_REG(r))); /*Store contents of address pointed by R0 or R1 to ACC */
|
||||
}
|
||||
|
||||
/*MOV A,R0 to R7 1: 1110 1rrr */
|
||||
OPHANDLER( mov_a_r )
|
||||
{
|
||||
SET_ACC(R_REG(r)); /*Store contents of R0 - R7 to ACC */
|
||||
}
|
||||
|
||||
/*MOV data addr, #data 1: 0111 0101 */
|
||||
OPHANDLER( mov_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
IRAM_W(addr,data); /*Store data to data address location */
|
||||
}
|
||||
|
||||
/*MOV data addr, data addr 1: 1000 0101 */
|
||||
OPHANDLER( mov_mem_mem )
|
||||
{
|
||||
/*1st address is src, 2nd is dst, but the mov command works as mov dst,src) */
|
||||
UINT8 src,dst;
|
||||
src = ROP_ARG(PC++); /*Grab source data address */
|
||||
dst = ROP_ARG(PC++); /*Grab destination data address */
|
||||
IRAM_W(dst,IRAM_R(src)); /*Read source address contents and store to destination address */
|
||||
}
|
||||
|
||||
/*MOV @R0/@R1, #data 1: 0111 011i */
|
||||
OPHANDLER( mov_ir_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
IRAM_IW(R_REG(r),data); /*Store data to address pointed by R0 or R1 */
|
||||
}
|
||||
|
||||
/*MOV R0 to R7, #data 1: 0111 1rrr */
|
||||
OPHANDLER( mov_r_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_REG(r, data); /*Store to R0 - R7 */
|
||||
}
|
||||
|
||||
/*MOV data addr, @R0/@R1 1: 1000 011i */
|
||||
OPHANDLER( mov_mem_ir )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr,IRAM_IR(R_REG(r))); /*Store contents pointed to by R0 or R1 to data address */
|
||||
}
|
||||
|
||||
/*MOV data addr,R0 to R7 1: 1000 1rrr */
|
||||
OPHANDLER( mov_mem_r )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr,R_REG(r)); /*Store contents of R0 - R7 to data address */
|
||||
}
|
||||
|
||||
/*MOV DPTR, #data16 1: 1001 0000 */
|
||||
OPHANDLER( mov_dptr_byte )
|
||||
{
|
||||
UINT8 data_hi, data_lo;
|
||||
data_hi = ROP_ARG(PC++); /*Grab hi byte */
|
||||
data_lo = ROP_ARG(PC++); /*Grab lo byte */
|
||||
SET_DPTR((UINT16)((data_hi<<8)|data_lo)); /*Store to DPTR */
|
||||
}
|
||||
|
||||
/*MOV bit addr, C 1: 1001 0010 */
|
||||
OPHANDLER( mov_bitaddr_c )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
BIT_W(addr,GET_CY); /*Store Carry Flag to Bit Address */
|
||||
}
|
||||
|
||||
/*MOV @R0/@R1, data addr 1: 1010 011i */
|
||||
OPHANDLER( mov_ir_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_IW(R_REG(r),IRAM_R(addr)); /*Store data from data address to address pointed to by R0 or R1 */
|
||||
}
|
||||
|
||||
/*MOV R0 to R7, data addr 1: 1010 1rrr */
|
||||
OPHANDLER( mov_r_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
SET_REG(r, IRAM_R(addr)); /*Store to R0 - R7 */
|
||||
}
|
||||
|
||||
/*MOV data addr, A 1: 1111 0101 */
|
||||
OPHANDLER( mov_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr,ACC); /*Store A to data address */
|
||||
}
|
||||
|
||||
/*MOV @R0/@R1, A 1: 1111 011i */
|
||||
OPHANDLER( mov_ir_a )
|
||||
{
|
||||
IRAM_IW(R_REG(r),ACC); /*Store A to location pointed to by R0 or R1 */
|
||||
}
|
||||
|
||||
/*MOV R0 to R7, A 1: 1111 1rrr */
|
||||
OPHANDLER( mov_r_a )
|
||||
{
|
||||
SET_REG(r, ACC); /*Store A to R0-R7 */
|
||||
}
|
||||
|
||||
/*MOVC A, @A + PC 1: 1000 0011 */
|
||||
OPHANDLER( movc_a_iapc )
|
||||
{
|
||||
UINT8 data;
|
||||
data = CODEMEM_R(ACC+PC); /*Move a byte from CODE(Program) Memory and store to ACC */
|
||||
SET_ACC(data);
|
||||
}
|
||||
|
||||
/*MOV C, bit addr 1: 1010 0010 */
|
||||
OPHANDLER( mov_c_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
SET_CY( (BIT_R(addr)) ); /*Store Bit from Bit Address to Carry Flag */
|
||||
}
|
||||
|
||||
/*MOVC A, @A + DPTR 1: 1001 0011 */
|
||||
OPHANDLER( movc_a_iadptr )
|
||||
{
|
||||
UINT8 data;
|
||||
data = CODEMEM_R(ACC + DPTR); /*Move a byte from CODE(Program) Memory and store to ACC */
|
||||
SET_ACC(data);
|
||||
}
|
||||
|
||||
/*MOVX A,@DPTR 1: 1110 0000 */
|
||||
/*(Move External Ram 16 bit address to A) */
|
||||
OPHANDLER( movx_a_idptr )
|
||||
{
|
||||
/* UINT8 byte = DATAMEM_R(R_DPTR); //Grab 1 byte from External DATA memory pointed to by dptr */
|
||||
UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
|
||||
UINT8 byte = DATAMEM_R(addr); /*Grab 1 byte from External DATA memory pointed to by dptr */
|
||||
SET_ACC(byte); /*Store to ACC */
|
||||
}
|
||||
|
||||
/*MOVX A, @R0/@R1 1: 1110 001i */
|
||||
/*(Move External Ram 8 bit address to A) */
|
||||
OPHANDLER( movx_a_ir )
|
||||
{
|
||||
UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); /*Grab address by reading location pointed to by R0 or R1 */
|
||||
UINT8 byte = DATAMEM_R(addr); /*Grab 1 byte from External DATA memory pointed to by address */
|
||||
SET_ACC(byte); /*Store to ACC */
|
||||
}
|
||||
|
||||
/*MOVX @DPTR,A 1: 1111 0000 */
|
||||
/*(Move A to External Ram 16 bit address) */
|
||||
OPHANDLER( movx_idptr_a )
|
||||
{
|
||||
/* DATAMEM_W(R_DPTR, ACC); //Store ACC to External DATA memory address pointed to by DPTR */
|
||||
UINT32 addr = ERAM_ADDR(DPTR, 0xFFFF);
|
||||
DATAMEM_W(addr, ACC); /*Store ACC to External DATA memory address pointed to by DPTR */
|
||||
}
|
||||
|
||||
/*MOVX @R0/@R1,A 1: 1111 001i */
|
||||
/*(Move A to External Ram 8 bit address) */
|
||||
OPHANDLER( movx_ir_a )
|
||||
{
|
||||
UINT32 addr = ERAM_ADDR(R_REG(r),0xFF); /*Grab address by reading location pointed to by R0 or R1 */
|
||||
DATAMEM_W(addr, ACC); /*Store ACC to External DATA memory address */
|
||||
}
|
||||
|
||||
/*MUL AB 1: 1010 0100 */
|
||||
OPHANDLER( mul_ab )
|
||||
{
|
||||
UINT16 result = ACC * B;
|
||||
/*A gets lo bits, B gets hi bits of result */
|
||||
B = (UINT8) ((result & 0xFF00) >> 8);
|
||||
SET_ACC((UINT8)(result & 0x00FF));
|
||||
/*Set flags */
|
||||
SET_OV( ((result & 0x100) >> 8) ); /*Set/Clear Overflow Flag if result > 255 */
|
||||
SET_CY(0); /*Carry Flag always cleared */
|
||||
}
|
||||
|
||||
/*NOP 1: 0000 0000 */
|
||||
OPHANDLER( nop )
|
||||
{
|
||||
}
|
||||
|
||||
/*ORL data addr, A 1: 0100 0010 */
|
||||
OPHANDLER( orl_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,data | ACC); /*Set data address value to it's value Logical OR with ACC */
|
||||
}
|
||||
|
||||
/*ORL data addr, #data 1: 0100 0011 */
|
||||
OPHANDLER( orl_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 srcdata = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,srcdata | data); /*Set data address value to it's value Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, #data 1: 0100 0100 */
|
||||
OPHANDLER( orl_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, data addr 1: 0100 0101 */
|
||||
OPHANDLER( orl_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, @RO/@R1 1: 0100 011i */
|
||||
OPHANDLER( orl_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from address R0 or R1 points to */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL A, RO to R7 1: 0100 1rrr */
|
||||
OPHANDLER( orl_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
SET_ACC(ACC | data); /*Set ACC to value of ACC Logical OR with Data */
|
||||
}
|
||||
|
||||
/*ORL C, bit addr 1: 0111 0010 */
|
||||
OPHANDLER( orl_c_bitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
SET_CY( (cy | bit) ); /*Set Carry flag to Carry Flag Value Logical OR with Bit */
|
||||
}
|
||||
|
||||
/*ORL C, /bit addr 1: 1010 0000 */
|
||||
OPHANDLER( orl_c_nbitaddr )
|
||||
{
|
||||
int cy = GET_CY;
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
UINT8 bit = BIT_R(addr); /*Grab bit data from bit address */
|
||||
bit = ((~bit)&1); /*Complement bit */
|
||||
SET_CY( (cy | bit) ); /*Set Carry flag to Carry Flag Value Logical OR with Complemented Bit */
|
||||
}
|
||||
|
||||
/*POP data addr 1: 1101 0000 */
|
||||
OPHANDLER( pop )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
IRAM_W(addr, IRAM_IR(SP)); /*Store to contents of data addr, data pointed to by Stack - IRAM_IR needed to access upper 128 bytes of stack */
|
||||
/*IRAM_IW(addr, IRAM_IR(R_SP)); //Store to contents of data addr, data pointed to by Stack - doesn't work, sfr's are not restored this way and it's not an indirect access anyway */
|
||||
SP = SP-1; /*Decrement SP */
|
||||
}
|
||||
|
||||
/*PUSH data addr 1: 1100 0000 */
|
||||
OPHANDLER( push )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 tmpSP = SP+1; /*Grab and Increment Stack Pointer */
|
||||
SP = tmpSP; /* "" */
|
||||
IRAM_IW(tmpSP, IRAM_R(addr)); /*Store to stack contents of data address - IRAM_IW needed to store to upper 128 bytes of stack, however, can't use IRAM_IR because that won't store the sfrs and it's not an indirect access anyway */
|
||||
}
|
||||
|
||||
/*RET 1: 0010 0010 */
|
||||
OPHANDLER( ret )
|
||||
{
|
||||
POP_PC();
|
||||
}
|
||||
|
||||
/*RETI 1: 0011 0010 */
|
||||
OPHANDLER( reti )
|
||||
{
|
||||
POP_PC();
|
||||
CLEAR_CURRENT_IRQ();
|
||||
}
|
||||
|
||||
/*RL A 1: 0010 0011 */
|
||||
OPHANDLER( rl_a )
|
||||
{
|
||||
/*Left Shift A, Bit 7 carries to Bit 0 */
|
||||
int carry = ((ACC & 0x80) >> 7);
|
||||
int data = (ACC<<1) & 0xfe;
|
||||
SET_ACC( data | carry);
|
||||
}
|
||||
|
||||
/*RLC A 1: 0011 0011 */
|
||||
OPHANDLER( rlc_a )
|
||||
{
|
||||
/*Left Shift A, Bit 7 goes to Carry Flag, Original Carry Flag goes to Bit 0 of ACC */
|
||||
int carry = ((ACC & 0x80) >> 7);
|
||||
int data = ((ACC<<1) & 0xfe) | GET_CY;
|
||||
SET_ACC( data);
|
||||
SET_CY(carry);
|
||||
}
|
||||
|
||||
/*RR A 1: 0000 0011 */
|
||||
OPHANDLER( rr_a )
|
||||
{
|
||||
/*Right Shift A, Bit 0 carries to Bit 7 */
|
||||
int carry = ((ACC & 1) << 7);
|
||||
int data = (ACC>>1) & 0x7f;
|
||||
SET_ACC( data | carry);
|
||||
}
|
||||
|
||||
/*RRC A 1: 0001 0011 */
|
||||
OPHANDLER( rrc_a )
|
||||
{
|
||||
/*Right Shift A, Bit 0 goes to Carry Flag, Bit 7 of ACC gets set to original Carry Flag */
|
||||
int carry = (ACC & 1);
|
||||
int data = ((ACC>>1) & 0x7f) | (GET_CY<<7);
|
||||
SET_ACC( data);
|
||||
SET_CY(carry);
|
||||
}
|
||||
|
||||
/*SETB C 1: 1101 0011 */
|
||||
OPHANDLER( setb_c )
|
||||
{
|
||||
SET_CY(1); /*Set Carry Flag */
|
||||
}
|
||||
|
||||
/*SETB bit addr 1: 1101 0010 */
|
||||
OPHANDLER( setb_bitaddr )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab bit address */
|
||||
BIT_W(addr,1); /*Set Bit at Bit Address */
|
||||
}
|
||||
|
||||
/*SJMP code addr 1: 1000 0000 */
|
||||
OPHANDLER( sjmp )
|
||||
{
|
||||
INT8 rel_addr = ROP_ARG(PC++); /*Grab relative code address */
|
||||
PC = PC + rel_addr; /*Update PC */
|
||||
}
|
||||
|
||||
/*SUBB A, #data 1: 1001 0100 */
|
||||
OPHANDLER( subb_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
|
||||
}
|
||||
|
||||
/*SUBB A, data addr 1: 1001 0101 */
|
||||
OPHANDLER( subb_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*SUBB A, @R0/@R1 1: 1001 011i */
|
||||
OPHANDLER( subb_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from memory pointed to by R0 or R1 */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*SUBB A, R0 to R7 1: 1001 1rrr */
|
||||
OPHANDLER( subb_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
UINT8 result = ACC - data - GET_CY; /*Subtract data & carry flag from accumulator */
|
||||
DO_SUB_FLAGS(ACC,data,GET_CY); /*Set Flags */
|
||||
SET_ACC(result); /*Store 8 bit result of addtion in ACC */
|
||||
}
|
||||
|
||||
/*SWAP A 1: 1100 0100 */
|
||||
OPHANDLER( swap_a )
|
||||
{
|
||||
UINT8 a_nib_lo, a_nib_hi;
|
||||
a_nib_hi = (ACC & 0x0f) << 4; /*Grab lo byte of ACC and move to hi */
|
||||
a_nib_lo = (ACC & 0xf0) >> 4; /*Grab hi byte of ACC and move to lo */
|
||||
SET_ACC( a_nib_hi | a_nib_lo);
|
||||
}
|
||||
|
||||
/*XCH A, data addr 1: 1100 0101 */
|
||||
OPHANDLER( xch_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data */
|
||||
UINT8 oldACC = ACC; /*Hold value of ACC */
|
||||
SET_ACC(data); /*Sets ACC to data */
|
||||
IRAM_W(addr,oldACC); /*Sets data address to old value of ACC */
|
||||
}
|
||||
|
||||
/*XCH A, @RO/@R1 1: 1100 011i */
|
||||
OPHANDLER( xch_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data pointed to by R0 or R1 */
|
||||
UINT8 oldACC = ACC; /*Hold value of ACC */
|
||||
SET_ACC(data); /*Sets ACC to data */
|
||||
IRAM_W(R_REG(r),oldACC); /*Sets data address to old value of ACC */
|
||||
}
|
||||
|
||||
/*XCH A, RO to R7 1: 1100 1rrr */
|
||||
OPHANDLER( xch_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0-R7 */
|
||||
UINT8 oldACC = ACC; /*Hold value of ACC */
|
||||
SET_ACC(data); /*Sets ACC to data */
|
||||
SET_REG(r, oldACC); /*Sets data address to old value of ACC */
|
||||
}
|
||||
|
||||
/*XCHD A, @R0/@R1 1: 1101 011i */
|
||||
OPHANDLER( xchd_a_ir )
|
||||
{
|
||||
UINT8 acc, ir_data;
|
||||
ir_data = IRAM_IR(R_REG(r)); /*Grab data pointed to by R0 or R1 */
|
||||
acc = ACC; /*Grab ACC value */
|
||||
SET_ACC( (acc & 0xf0) | (ir_data & 0x0f) ); /*Set ACC to lower nibble of data pointed to by R0 or R1 */
|
||||
IRAM_W(R_REG(r), (ir_data & 0xf0) | (acc & 0x0f) ); /*Set data pointed to by R0 or R1 to lower nibble of ACC */
|
||||
}
|
||||
|
||||
/*XRL data addr, A 1: 0110 0010 */
|
||||
OPHANDLER( xrl_mem_a )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,data ^ ACC); /*Set data address value to it's value Logical XOR with ACC */
|
||||
}
|
||||
|
||||
/*XRL data addr, #data 1: 0110 0011 */
|
||||
OPHANDLER( xrl_mem_byte )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
UINT8 srcdata = IRAM_R(addr); /*Grab data from data address */
|
||||
IRAM_W(addr,srcdata ^ data); /*Set data address value to it's value Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, #data 1: 0110 0100 */
|
||||
OPHANDLER( xrl_a_byte )
|
||||
{
|
||||
UINT8 data = ROP_ARG(PC++); /*Grab data */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, data addr 1: 0110 0101 */
|
||||
OPHANDLER( xrl_a_mem )
|
||||
{
|
||||
UINT8 addr = ROP_ARG(PC++); /*Grab data address */
|
||||
UINT8 data = IRAM_R(addr); /*Grab data from data address */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, @R0/@R1 1: 0110 011i */
|
||||
OPHANDLER( xrl_a_ir )
|
||||
{
|
||||
UINT8 data = IRAM_IR(R_REG(r)); /*Grab data from address R0 or R1 points to */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*XRL A, R0 to R7 1: 0110 1rrr */
|
||||
OPHANDLER( xrl_a_r )
|
||||
{
|
||||
UINT8 data = R_REG(r); /*Grab data from R0 - R7 */
|
||||
SET_ACC(ACC ^ data); /*Set ACC to value of ACC Logical XOR with Data */
|
||||
}
|
||||
|
||||
/*illegal opcodes */
|
||||
OPHANDLER( illegal )
|
||||
{
|
||||
LOG(("i8051 #%d: illegal opcode at 0x%03x: %02x\n", cpu_getactivecpu(), PC-1, r));
|
||||
}
|
||||
+2783
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
|
||||
Intel 80960KA/KB, from current MAME (src/devices/cpu/i960,
|
||||
copyright Farfetch'd, R. Belmont, BSD-3-Clause), in C for MAME 2003.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef I960_H
|
||||
#define I960_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum
|
||||
{
|
||||
I960_PFP = 0,
|
||||
I960_SP = 1,
|
||||
I960_RIP = 2,
|
||||
I960_FP = 31
|
||||
};
|
||||
|
||||
/* register numbers for get_reg / set_reg */
|
||||
enum
|
||||
{
|
||||
I960_IPREG = 1, I960_PIPREG, I960_SATREG, I960_PRCBREG, I960_PCREG, I960_ACREG,
|
||||
I960_R0REG
|
||||
/* I960_R0REG + n: r0..r15 g0..g15 */
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
I960_IRQ0 = 0,
|
||||
I960_IRQ1 = 1,
|
||||
I960_IRQ2 = 2,
|
||||
I960_IRQ3 = 3
|
||||
};
|
||||
|
||||
extern int i960_icount;
|
||||
|
||||
extern void i960_init(void);
|
||||
extern void i960_reset(void *param);
|
||||
extern void i960_exit(void);
|
||||
extern int i960_execute(int cycles);
|
||||
extern unsigned i960_get_context(void *dst);
|
||||
extern void i960_set_context(void *src);
|
||||
extern unsigned i960_get_reg(int regnum);
|
||||
extern void i960_set_reg(int regnum, unsigned val);
|
||||
extern void i960_set_irq_line(int irqline, int state);
|
||||
extern void i960_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *i960_info(void *context, int regnum);
|
||||
extern unsigned i960_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* Model 2: a FIFO access that cannot complete now (copro FIFO empty or
|
||||
full) repeats the instruction later; a multi-word access already half
|
||||
done resumes where it stopped (current MAME, i960_stall) */
|
||||
extern void i960_stall(void);
|
||||
/* the regions where ldl/ldt/ldq/stl/stt/stq step through the addresses
|
||||
(current MAME's BURST flag); elsewhere (FIFOs, registers) every word
|
||||
goes to the same address. NULL: everywhere. */
|
||||
extern void i960_set_burst_callback(int (*is_burst)(UINT32 address));
|
||||
|
||||
/* the addresses an idle loop may read: reading them has no side effect
|
||||
and their contents change only between timeslices (RAM, a status
|
||||
register updated by an interrupt). NULL (default): idle loops are not
|
||||
skipped. */
|
||||
extern void i960_set_idle_read_callback(int (*read_ok)(UINT32 address));
|
||||
|
||||
#endif
|
||||
@@ -470,6 +470,19 @@ void konami_set_reg(int regnum, unsigned val)
|
||||
/****************************************************************************/
|
||||
void konami_init(void)
|
||||
{
|
||||
int cpu = cpu_getactivecpu();
|
||||
state_save_register_UINT16("konami", cpu, "PC", &PC, 1);
|
||||
state_save_register_UINT16("konami", cpu, "U", &U, 1);
|
||||
state_save_register_UINT16("konami", cpu, "S", &S, 1);
|
||||
state_save_register_UINT16("konami", cpu, "X", &X, 1);
|
||||
state_save_register_UINT16("konami", cpu, "Y", &Y, 1);
|
||||
state_save_register_UINT16("konami", cpu, "D", &D, 1);
|
||||
state_save_register_UINT8("konami", cpu, "DP", &DP, 1);
|
||||
state_save_register_UINT8("konami", cpu, "CC", &CC, 1);
|
||||
state_save_register_UINT8("konami", cpu, "INT", &konami.int_state, 1);
|
||||
state_save_register_UINT8("konami", cpu, "NMI", &konami.nmi_state, 1);
|
||||
state_save_register_UINT8("konami", cpu, "IRQ", &konami.irq_state[0], 1);
|
||||
state_save_register_UINT8("konami", cpu, "FIRQ", &konami.irq_state[1], 1);
|
||||
}
|
||||
|
||||
void konami_reset(void *param)
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,165 @@
|
||||
#ifndef HEADER__M37710
|
||||
#define HEADER__M37710
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== COPYRIGHT ============================== */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
|
||||
M37710 CPU Emulator v0.1
|
||||
|
||||
mame2003-plus: backported from MAME 0.121 to the 0.78 CPU interface.
|
||||
The on-chip registers (0x00-0x7f), on-chip RAM (0x80-0x27f) and, for the
|
||||
M37702 with internal mask ROM, the internal ROM (0xc000-0xffff) are
|
||||
handled inside the core. The on-chip I/O ports and ADC are routed to the
|
||||
driver through m37710_set_io_handlers(). Single instance only.
|
||||
|
||||
*/
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
/* ======================================================================== */
|
||||
/* =============================== DEFINES ================================ */
|
||||
/* ======================================================================== */
|
||||
/*
|
||||
Input lines - used with cpu_set_irq_line() and the like.
|
||||
WARNING: these are in the same order as the vector table for simplicity.
|
||||
Do not alter this order!
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
/* these interrupts are maskable */
|
||||
M37710_LINE_ADC = 0,
|
||||
M37710_LINE_UART1XMIT,
|
||||
M37710_LINE_UART1RECV,
|
||||
M37710_LINE_UART0XMIT,
|
||||
M37710_LINE_UART0RECV,
|
||||
M37710_LINE_TIMERB2,
|
||||
M37710_LINE_TIMERB1,
|
||||
M37710_LINE_TIMERB0,
|
||||
M37710_LINE_TIMERA4,
|
||||
M37710_LINE_TIMERA3,
|
||||
M37710_LINE_TIMERA2,
|
||||
M37710_LINE_TIMERA1,
|
||||
M37710_LINE_TIMERA0,
|
||||
M37710_LINE_IRQ2,
|
||||
M37710_LINE_IRQ1,
|
||||
M37710_LINE_IRQ0,
|
||||
/* these interrupts are non-maskable */
|
||||
M37710_LINE_WATCHDOG,
|
||||
M37710_LINE_DEBUG,
|
||||
M37710_LINE_BRK,
|
||||
M37710_LINE_ZERODIV,
|
||||
M37710_LINE_RESET,
|
||||
|
||||
/* these are not interrupts, they're signals external hardware can send */
|
||||
M37710_LINE_TIMERA0TICK,
|
||||
M37710_LINE_TIMERA1TICK,
|
||||
M37710_LINE_TIMERA2TICK,
|
||||
M37710_LINE_TIMERA3TICK,
|
||||
M37710_LINE_TIMERA4TICK,
|
||||
M37710_LINE_TIMERB0TICK,
|
||||
M37710_LINE_TIMERB1TICK,
|
||||
M37710_LINE_TIMERB2TICK,
|
||||
|
||||
M37710_LINE_MAX
|
||||
};
|
||||
|
||||
/* Registers - used by m37710_set_reg() and m37710_get_reg() */
|
||||
enum
|
||||
{
|
||||
M37710_PC=1, M37710_S, M37710_P, M37710_A, M37710_B, M37710_X, M37710_Y,
|
||||
M37710_PB, M37710_DB, M37710_D, M37710_E,
|
||||
M37710_NMI_STATE, M37710_IRQ_STATE
|
||||
};
|
||||
|
||||
|
||||
/* I/O ports */
|
||||
enum
|
||||
{
|
||||
M37710_PORT0 = 0,
|
||||
M37710_PORT1, M37710_PORT2, M37710_PORT3, M37710_PORT4,
|
||||
M37710_PORT5, M37710_PORT6, M37710_PORT7, M37710_PORT8,
|
||||
|
||||
M37710_ADC0_L = 0x10, M37710_ADC0_H,
|
||||
M37710_ADC1_L, M37710_ADC1_H, M37710_ADC2_L, M37710_ADC2_H, M37710_ADC3_L, M37710_ADC3_H,
|
||||
M37710_ADC4_L, M37710_ADC4_H, M37710_ADC5_L, M37710_ADC5_H, M37710_ADC6_L, M37710_ADC6_H,
|
||||
M37710_ADC7_L, M37710_ADC7_H,
|
||||
|
||||
M37710_SER0_REC = 0x20,
|
||||
M37710_SER0_XMIT, M37710_SER1_REC, M37710_SER1_XMIT
|
||||
};
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== PROTOTYPES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
typedef data8_t (*m37710_io_read_func)(int port);
|
||||
typedef void (*m37710_io_write_func)(int port, data8_t data);
|
||||
|
||||
/* hook the on-chip ports/ADC to the driver */
|
||||
void m37710_set_io_handlers(m37710_io_read_func readfn, m37710_io_write_func writefn);
|
||||
/* M37702 with internal mask ROM: 16KB mapped at 0xc000-0xffff (NULL = external) */
|
||||
void m37710_set_internal_rom(const UINT8 *rom);
|
||||
/*
|
||||
Speedup (0 = off): 'pc' (bank | address) starts a loop of 'count'
|
||||
instructions that only polls memory written by interrupts (such as
|
||||
"lda dp / beq loop"), so every pass leaves the same state. Once one
|
||||
pass has run inside a timeslice, the whole passes that still fit in
|
||||
it are skipped: registers, memory and cycles end up exactly as if
|
||||
they had run.
|
||||
*/
|
||||
void m37710_set_idle_loop(UINT32 pc, int count);
|
||||
|
||||
extern int m37710_ICount; /* cycle count */
|
||||
|
||||
void m37710_init(void);
|
||||
void m37710_reset(void *param);
|
||||
void m37710_exit(void);
|
||||
int m37710_execute(int cycles);
|
||||
unsigned m37710_get_context(void *dst);
|
||||
void m37710_set_context(void *src);
|
||||
unsigned m37710_get_reg(int regnum);
|
||||
void m37710_set_reg(int regnum, unsigned val);
|
||||
void m37710_set_irq_line(int irqline, int state);
|
||||
void m37710_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *m37710_info(void *context, int regnum);
|
||||
unsigned m37710_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#define m37702_ICount m37710_ICount
|
||||
#define m37702_init m37710_init
|
||||
#define m37702_reset m37710_reset
|
||||
#define m37702_exit m37710_exit
|
||||
#define m37702_execute m37710_execute
|
||||
#define m37702_get_context m37710_get_context
|
||||
#define m37702_set_context m37710_set_context
|
||||
#define m37702_get_reg m37710_get_reg
|
||||
#define m37702_set_reg m37710_set_reg
|
||||
#define m37702_set_irq_line m37710_set_irq_line
|
||||
#define m37702_set_irq_callback m37710_set_irq_callback
|
||||
#define m37702_info m37710_info
|
||||
#define m37702_dasm m37710_dasm
|
||||
|
||||
/* memory access, including the on-chip resources */
|
||||
UINT8 m37710_mem_read8(UINT32 address);
|
||||
UINT16 m37710_mem_read16(UINT32 address);
|
||||
void m37710_mem_write8(UINT32 address, UINT8 data);
|
||||
void m37710_mem_write16(UINT32 address, UINT16 data);
|
||||
|
||||
#undef M37710_CALL_DEBUGGER
|
||||
|
||||
#define M37710_CALL_DEBUGGER CALL_MAME_DEBUG
|
||||
#define m37710_read_8(addr) m37710_mem_read8(addr)
|
||||
#define m37710_write_8(addr,data) m37710_mem_write8(addr,data)
|
||||
#define m37710_read_8_immediate(A) m37710_mem_read8(A)
|
||||
#define m37710_read_16(addr) m37710_mem_read16(addr)
|
||||
#define m37710_write_16(addr,data) m37710_mem_write16(addr,data)
|
||||
#define m37710_jumping(A)
|
||||
#define m37710_branching(A)
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================== END OF FILE ============================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
#endif /* HEADER__M37710 */
|
||||
@@ -0,0 +1,323 @@
|
||||
/* M37710/M37702 core internals: from MAME 0.121 (MAME license; R. Belmont,
|
||||
based on the G65816 core by Karl Stenerud) */
|
||||
|
||||
#ifndef HEADER__M37710CM
|
||||
#define HEADER__M37710CM
|
||||
|
||||
#define m37710i_branching(A)
|
||||
#define m37710i_jumping(A)
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ INCLUDES ============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
#include <limits.h>
|
||||
#include "driver.h"
|
||||
#include "cpuintrf.h"
|
||||
#include "mamedbg.h"
|
||||
#include "m37710.h"
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================ GENERAL =============================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Fallback on static if we don't have inline */
|
||||
|
||||
|
||||
/* This should be set to the default size of your processor (min 16 bit) */
|
||||
#undef uint
|
||||
#define uint unsigned int
|
||||
|
||||
#undef uint8
|
||||
#define uint8 unsigned char
|
||||
|
||||
#undef int8
|
||||
|
||||
/* Allow for architectures that don't have 8-bit sizes */
|
||||
#if UCHAR_MAX == 0xff
|
||||
#define int8 char
|
||||
#define MAKE_INT_8(A) (int8)((A)&0xff)
|
||||
#else
|
||||
#define int8 int
|
||||
static INLINE int MAKE_INT_8(int A) {return (A & 0x80) ? A | ~0xff : A & 0xff;}
|
||||
#endif /* UCHAR_MAX == 0xff */
|
||||
|
||||
#define MAKE_UINT_8(A) ((A)&0xff)
|
||||
#define MAKE_UINT_16(A) ((A)&0xffff)
|
||||
#define MAKE_UINT_24(A) ((A)&0xffffff)
|
||||
|
||||
/* Bits */
|
||||
#define BIT_0 0x01
|
||||
#define BIT_1 0x02
|
||||
#define BIT_2 0x04
|
||||
#define BIT_3 0x08
|
||||
#define BIT_4 0x10
|
||||
#define BIT_5 0x20
|
||||
#define BIT_6 0x40
|
||||
#define BIT_7 0x80
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================== CPU ================================= */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* CPU Structure */
|
||||
typedef struct
|
||||
{
|
||||
uint a; /* Accumulator */
|
||||
uint b; /* holds high byte of accumulator */
|
||||
uint ba; /* Secondary Accumulator */
|
||||
uint bb; /* holds high byte of secondary accumulator */
|
||||
uint x; /* Index Register X */
|
||||
uint y; /* Index Register Y */
|
||||
uint s; /* Stack Pointer */
|
||||
uint pc; /* Program Counter */
|
||||
uint ppc; /* Previous Program Counter */
|
||||
uint pb; /* Program Bank (shifted left 16) */
|
||||
uint db; /* Data Bank (shifted left 16) */
|
||||
uint d; /* Direct Register */
|
||||
uint flag_e; /* Emulation Mode Flag */
|
||||
uint flag_m; /* Memory/Accumulator Select Flag */
|
||||
uint flag_x; /* Index Select Flag */
|
||||
uint flag_n; /* Negative Flag */
|
||||
uint flag_v; /* Overflow Flag */
|
||||
uint flag_d; /* Decimal Mode Flag */
|
||||
uint flag_i; /* Interrupt Mask Flag */
|
||||
uint flag_z; /* Zero Flag (inverted) */
|
||||
uint flag_c; /* Carry Flag */
|
||||
uint line_irq; /* Bitmask of pending IRQs */
|
||||
uint ipl; /* Interrupt priority level (top of PSW) */
|
||||
uint ir; /* Instruction Register */
|
||||
uint im; /* Immediate load value */
|
||||
uint im2; /* Immediate load target */
|
||||
uint im3; /* Immediate load target */
|
||||
uint im4; /* Immediate load target */
|
||||
uint irq_delay; /* delay 1 instruction before checking irq */
|
||||
uint irq_level; /* irq level */
|
||||
int (*int_ack)(int); /* Interrupt Acknowledge */
|
||||
uint stopped; /* Sets how the CPU is stopped */
|
||||
void (**opcodes)(void); /* opcodes with no prefix */
|
||||
void (**opcodes42)(void); /* opcodes with 0x42 prefix */
|
||||
void (**opcodes89)(void); /* opcodes with 0x89 prefix */
|
||||
uint (*get_reg)(int regnum);
|
||||
void (*set_reg)(int regnum, uint val);
|
||||
void (*set_line)(int line, int state);
|
||||
int (*execute)(int cycles);
|
||||
|
||||
/* on-board peripheral stuff */
|
||||
UINT8 m37710_regs[128];
|
||||
double reload[8];
|
||||
mame_timer *timers[8];
|
||||
double timer_left[8]; /* saved: time left of each timer (< 0: not armed) */
|
||||
} m37710i_cpu_struct;
|
||||
|
||||
extern m37710i_cpu_struct m37710i_cpu;
|
||||
extern UINT32 m37710_idle_pc;
|
||||
extern int m37710_idle_count, m37710_idle_since, m37710_idle_clocks;
|
||||
extern int m37710_ICount;
|
||||
extern uint m37710i_source;
|
||||
extern uint m37710i_destination;
|
||||
extern uint m37710i_adc_tbl[];
|
||||
extern uint m37710i_sbc_tbl[];
|
||||
|
||||
extern void (**m37710i_opcodes[])(void);
|
||||
extern void (**m37710i_opcodes2[])(void);
|
||||
extern void (**m37710i_opcodes3[])(void);
|
||||
extern uint (*m37710i_get_reg[])(int regnum);
|
||||
extern void (*m37710i_set_reg[])(int regnum, uint val);
|
||||
extern void (*m37710i_set_line[])(int line, int state);
|
||||
extern int (*m37710i_execute[])(int cycles);
|
||||
|
||||
#define REG_A m37710i_cpu.a /* Accumulator */
|
||||
#define REG_B m37710i_cpu.b /* Accumulator hi byte */
|
||||
#define REG_BA m37710i_cpu.ba /* Secondary Accumulator */
|
||||
#define REG_BB m37710i_cpu.bb /* Secondary Accumulator hi byte */
|
||||
#define REG_X m37710i_cpu.x /* Index X Register */
|
||||
#define REG_Y m37710i_cpu.y /* Index Y Register */
|
||||
#define REG_S m37710i_cpu.s /* Stack Pointer */
|
||||
#define REG_PC m37710i_cpu.pc /* Program Counter */
|
||||
#define REG_PPC m37710i_cpu.ppc /* Previous Program Counter */
|
||||
#define REG_PB m37710i_cpu.pb /* Program Bank */
|
||||
#define REG_DB m37710i_cpu.db /* Data Bank */
|
||||
#define REG_D m37710i_cpu.d /* Direct Register */
|
||||
#define FLAG_M m37710i_cpu.flag_m /* Memory/Accumulator Select Flag */
|
||||
#define FLAG_X m37710i_cpu.flag_x /* Index Select Flag */
|
||||
#define FLAG_N m37710i_cpu.flag_n /* Negative Flag */
|
||||
#define FLAG_V m37710i_cpu.flag_v /* Overflow Flag */
|
||||
#define FLAG_D m37710i_cpu.flag_d /* Decimal Mode Flag */
|
||||
#define FLAG_I m37710i_cpu.flag_i /* Interrupt Mask Flag */
|
||||
#define FLAG_Z m37710i_cpu.flag_z /* Zero Flag (inverted) */
|
||||
#define FLAG_C m37710i_cpu.flag_c /* Carry Flag */
|
||||
#define LINE_IRQ m37710i_cpu.line_irq /* Status of the IRQ line */
|
||||
#define REG_IR m37710i_cpu.ir /* Instruction Register */
|
||||
#define REG_IM m37710i_cpu.im /* Immediate load value */
|
||||
#define REG_IM2 m37710i_cpu.im2 /* Immediate load target */
|
||||
#define REG_IM3 m37710i_cpu.im3 /* Immediate load target */
|
||||
#define REG_IM4 m37710i_cpu.im4 /* Immediate load target */
|
||||
#define INT_ACK m37710i_cpu.int_ack /* Interrupt Acknowledge function pointer */
|
||||
#define CLOCKS m37710_ICount /* Clock cycles remaining */
|
||||
#define IRQ_DELAY m37710i_cpu.irq_delay /* Delay 1 instruction before checking IRQ */
|
||||
#define CPU_STOPPED m37710i_cpu.stopped /* Stopped status of the CPU */
|
||||
|
||||
#define FTABLE_OPCODES m37710i_cpu.opcodes
|
||||
#define FTABLE_OPCODES2 m37710i_cpu.opcodes42
|
||||
#define FTABLE_OPCODES3 m37710i_cpu.opcodes89
|
||||
#define FTABLE_GET_REG m37710i_cpu.get_reg
|
||||
#define FTABLE_SET_REG m37710i_cpu.set_reg
|
||||
#define FTABLE_SET_LINE m37710i_cpu.set_line
|
||||
#define FTABLE_EXECUTE m37710i_cpu.execute
|
||||
|
||||
#define SRC m37710i_source /* Source Operand */
|
||||
#define DST m37710i_destination /* Destination Operand */
|
||||
|
||||
#define STOP_LEVEL_WAI 1
|
||||
#define STOP_LEVEL_STOP 2
|
||||
|
||||
#define EXECUTION_MODE_M0X0 0
|
||||
#define EXECUTION_MODE_M0X1 1
|
||||
#define EXECUTION_MODE_M1X0 2
|
||||
#define EXECUTION_MODE_M1X1 3
|
||||
|
||||
static INLINE void m37710i_set_execution_mode(uint mode)
|
||||
{
|
||||
FTABLE_OPCODES = m37710i_opcodes[mode];
|
||||
FTABLE_OPCODES2 = m37710i_opcodes2[mode];
|
||||
FTABLE_OPCODES3 = m37710i_opcodes3[mode];
|
||||
FTABLE_GET_REG = m37710i_get_reg[mode];
|
||||
FTABLE_SET_REG = m37710i_set_reg[mode];
|
||||
FTABLE_SET_LINE = m37710i_set_line[mode];
|
||||
FTABLE_EXECUTE = m37710i_execute[mode];
|
||||
}
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================= CLOCK ================================ */
|
||||
/* ======================================================================== */
|
||||
|
||||
#define CLK_OP 1
|
||||
#define CLK_R8 1
|
||||
#define CLK_R16 2
|
||||
#define CLK_R24 3
|
||||
#define CLK_W8 1
|
||||
#define CLK_W16 2
|
||||
#define CLK_W24 3
|
||||
#define CLK_RMW8 3
|
||||
#define CLK_RMW16 5
|
||||
|
||||
#define CLK_IMPLIED 1
|
||||
#define CLK_IMPLIED 1
|
||||
#define CLK_RELATIVE_8 1
|
||||
#define CLK_RELATIVE_16 2
|
||||
#define CLK_IMM 0
|
||||
#define CLK_AI 4
|
||||
#define CLK_AXI 4
|
||||
#define CLK_A 2
|
||||
#define CLK_AL 3
|
||||
#define CLK_ALX 3
|
||||
#define CLK_AX 2
|
||||
#define CLK_AY 2
|
||||
#define CLK_D 1
|
||||
#define CLK_DI 3
|
||||
#define CLK_DIY 3
|
||||
#define CLK_DLI 4
|
||||
#define CLK_DLIY 4
|
||||
#define CLK_DX 2
|
||||
#define CLK_DXI 4
|
||||
#define CLK_DY 2
|
||||
#define CLK_S 2
|
||||
#define CLK_SIY 5
|
||||
|
||||
/* AX and AY addressing modes take 1 extra cycle when writing */
|
||||
#define CLK_W_IMM 0
|
||||
#define CLK_W_AI 4
|
||||
#define CLK_W_AXI 4
|
||||
#define CLK_W_A 2
|
||||
#define CLK_W_AL 3
|
||||
#define CLK_W_ALX 3
|
||||
#define CLK_W_AX 3
|
||||
#define CLK_W_AY 3
|
||||
#define CLK_W_D 1
|
||||
#define CLK_W_DI 3
|
||||
#define CLK_W_DIY 3
|
||||
#define CLK_W_DLI 4
|
||||
#define CLK_W_DLIY 4
|
||||
#define CLK_W_DX 2
|
||||
#define CLK_W_DXI 4
|
||||
#define CLK_W_DY 2
|
||||
#define CLK_W_S 2
|
||||
#define CLK_W_SIY 5
|
||||
|
||||
#define CLK(A) CLOCKS -= (A)
|
||||
#define USE_ALL_CLKS() CLOCKS = 0
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ============================ STATUS REGISTER =========================== */
|
||||
/* ======================================================================== */
|
||||
|
||||
/* Flag positions in Processor Status Register */
|
||||
/* common */
|
||||
#define FLAGPOS_N BIT_7 /* Negative */
|
||||
#define FLAGPOS_V BIT_6 /* Overflow */
|
||||
#define FLAGPOS_D BIT_3 /* Decimal Mode */
|
||||
#define FLAGPOS_I BIT_2 /* Interrupt Mask */
|
||||
#define FLAGPOS_Z BIT_1 /* Zero */
|
||||
#define FLAGPOS_C BIT_0 /* Carry */
|
||||
/* emulation */
|
||||
#define FLAGPOS_R BIT_5 /* Reserved */
|
||||
#define FLAGPOS_B BIT_4 /* BRK Instruction */
|
||||
/* native */
|
||||
#define FLAGPOS_M BIT_5 /* Mem/Reg Select */
|
||||
#define FLAGPOS_X BIT_4 /* Index Select */
|
||||
|
||||
#define EFLAG_SET 1
|
||||
#define EFLAG_CLEAR 0
|
||||
#define MFLAG_SET FLAGPOS_M
|
||||
#define MFLAG_CLEAR 0
|
||||
#define XFLAG_SET FLAGPOS_X
|
||||
#define XFLAG_CLEAR 0
|
||||
#define NFLAG_SET 0x80
|
||||
#define NFLAG_CLEAR 0
|
||||
#define VFLAG_SET 0x80
|
||||
#define VFLAG_CLEAR 0
|
||||
#define DFLAG_SET FLAGPOS_D
|
||||
#define DFLAG_CLEAR 0
|
||||
#define IFLAG_SET FLAGPOS_I
|
||||
#define IFLAG_CLEAR 0
|
||||
#define BFLAG_SET FLAGPOS_B
|
||||
#define BFLAG_CLEAR 0
|
||||
#define ZFLAG_SET 0
|
||||
#define ZFLAG_CLEAR 1
|
||||
#define CFLAG_SET 0x100
|
||||
#define CFLAG_CLEAR 0
|
||||
|
||||
/* Codition code tests */
|
||||
#define COND_CC() (!(FLAG_C&0x100)) /* Carry Clear */
|
||||
#define COND_CS() (FLAG_C&0x100) /* Carry Set */
|
||||
#define COND_EQ() (!FLAG_Z) /* Equal */
|
||||
#define COND_NE() FLAG_Z /* Not Equal */
|
||||
#define COND_MI() (FLAG_N&0x80) /* Minus */
|
||||
#define COND_PL() (!(FLAG_N&0x80)) /* Plus */
|
||||
#define COND_VC() (!(FLAG_V&0x80)) /* Overflow Clear */
|
||||
#define COND_VS() (FLAG_V&0x80) /* Overflow Set */
|
||||
|
||||
/* Set Overflow flag in math operations */
|
||||
#define VFLAG_ADD_8(S, D, R) ((S^R) & (D^R))
|
||||
#define VFLAG_ADD_16(S, D, R) (((S^R) & (D^R))>>8)
|
||||
#define VFLAG_SUB_8(S, D, R) ((S^D) & (R^D))
|
||||
#define VFLAG_SUB_16(S, D, R) (((S^D) & (R^D))>>8)
|
||||
|
||||
#define CFLAG_8(A) (A)
|
||||
#define CFLAG_16(A) ((A)>>8)
|
||||
#define NFLAG_8(A) (A)
|
||||
#define NFLAG_16(A) ((A)>>8)
|
||||
|
||||
#define CFLAG_AS_1() ((FLAG_C>>8)&1)
|
||||
|
||||
/* update IRQ state (internal use only) */
|
||||
void m37710i_update_irqs(void);
|
||||
|
||||
/* ======================================================================== */
|
||||
/* ================================== CPU ================================= */
|
||||
/* ======================================================================== */
|
||||
#endif /* HEADER__M37710CM */
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M0X0
|
||||
#include "m37710op.h"
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M0X1
|
||||
#include "m37710op.h"
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M1X0
|
||||
#include "m37710op.h"
|
||||
@@ -0,0 +1,4 @@
|
||||
/* M37710 opcode table instance: from MAME 0.121 (MAME license; R. Belmont) */
|
||||
#include "m37710cm.h"
|
||||
#define EXECUTION_MODE EXECUTION_MODE_M1X1
|
||||
#include "m37710op.h"
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,46 @@
|
||||
/***************************************************************************
|
||||
|
||||
Fujitsu MB86233/MB86234 (TGP), from current MAME
|
||||
(src/devices/cpu/mb86233, copyright Olivier Galibert, BSD-3-Clause),
|
||||
in C for MAME 2003. The four address spaces (program, data, io and
|
||||
register file) are driver callbacks.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MB86233_H
|
||||
#define MB86233_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
struct mb86233_config
|
||||
{
|
||||
UINT32 (*prog_r)( UINT32 offset );
|
||||
UINT32 (*data_r)( UINT32 offset );
|
||||
void (*data_w)( UINT32 offset, UINT32 data );
|
||||
UINT32 (*io_r)( UINT32 offset );
|
||||
void (*io_w)( UINT32 offset, UINT32 data );
|
||||
UINT32 (*rf_r)( UINT32 offset );
|
||||
void (*rf_w)( UINT32 offset, UINT32 data );
|
||||
};
|
||||
|
||||
extern int mb86233_icount;
|
||||
|
||||
extern void mb86233_init(void);
|
||||
extern void mb86233_reset(void *param);
|
||||
extern void mb86233_exit(void);
|
||||
extern int mb86233_execute(int cycles);
|
||||
extern unsigned mb86233_get_context(void *dst);
|
||||
extern void mb86233_set_context(void *src);
|
||||
extern unsigned mb86233_get_reg(int regnum);
|
||||
extern void mb86233_set_reg(int regnum, unsigned val);
|
||||
extern void mb86233_set_irq_line(int irqline, int state);
|
||||
extern void mb86233_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *mb86233_info(void *context, int regnum);
|
||||
extern unsigned mb86233_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* a memory callback that cannot complete now (FIFO empty or full):
|
||||
the instruction is repeated */
|
||||
extern void mb86233_stall(void);
|
||||
extern void mb86233_gpio_w(int pin, int state);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,50 @@
|
||||
/***************************************************************************
|
||||
|
||||
Fujitsu MB86235 "TGPx4", from current MAME
|
||||
(src/devices/cpu/mb86235; copyright Angelo Salese, ElSemi, Ville Linde,
|
||||
Matthew Daniels, BSD-3-Clause), the interpreter in C for MAME 2003.
|
||||
Program memory, the external bus and the FIFOs are driver callbacks;
|
||||
the internal A and B bus RAMs are part of the CPU.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MB86235_H
|
||||
#define MB86235_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
#define MB86235_FIFO_IFF 0 /* input FIFO full */
|
||||
#define MB86235_FIFO_IFE 1 /* input FIFO empty */
|
||||
#define MB86235_FIFO_OFF 2 /* output FIFO full */
|
||||
#define MB86235_FIFO_OFE 3 /* output FIFO empty */
|
||||
|
||||
struct mb86235_config
|
||||
{
|
||||
UINT64 (*prog_r)( UINT32 offset ); /* 64-bit words, 12-bit address */
|
||||
UINT32 (*ext_r)( UINT32 offset ); /* external bus, dword address */
|
||||
void (*ext_w)( UINT32 offset, UINT32 data );
|
||||
UINT32 (*fifoin_r)( void ); /* calls mb86235_stall() when empty */
|
||||
void (*fifoout_w)( UINT32 data );
|
||||
int (*fifo_flag)( int which );
|
||||
void (*fifo_clear)( int which ); /* 0: input, 1: output */
|
||||
};
|
||||
|
||||
extern int mb86235_icount;
|
||||
|
||||
extern void mb86235_init(void);
|
||||
extern void mb86235_reset(void *param);
|
||||
extern void mb86235_exit(void);
|
||||
extern int mb86235_execute(int cycles);
|
||||
extern unsigned mb86235_get_context(void *dst);
|
||||
extern void mb86235_set_context(void *src);
|
||||
extern unsigned mb86235_get_reg(int regnum);
|
||||
extern void mb86235_set_reg(int regnum, unsigned val);
|
||||
extern void mb86235_set_irq_line(int irqline, int state);
|
||||
extern void mb86235_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *mb86235_info(void *context, int regnum);
|
||||
extern unsigned mb86235_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* a FIFO read that cannot complete now: the instruction is repeated */
|
||||
extern void mb86235_stall(void);
|
||||
|
||||
#endif
|
||||
+457
-1
@@ -13,6 +13,7 @@
|
||||
**
|
||||
**#################################################################################################*/
|
||||
|
||||
#include "mips3jit.h"
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
@@ -21,6 +22,7 @@
|
||||
#include "driver.h"
|
||||
#include "mamedbg.h"
|
||||
#include "mips3.h"
|
||||
#include "state.h"
|
||||
|
||||
|
||||
#define ENABLE_OVERFLOWS 0
|
||||
@@ -292,6 +294,193 @@ static const memory_handlers le_memory =
|
||||
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** OPTIONAL SPEEDUPS
|
||||
**
|
||||
** Off unless a driver enables them (currently only Killer Instinct):
|
||||
** - fast RAM: plain RAM regions read and written through a direct pointer
|
||||
** instead of the memory system, including instruction fetch;
|
||||
** - idle loop: a loop that polls the COP0 Cause register for an interrupt
|
||||
** gives up the rest of its timeslice instead of spinning.
|
||||
** They live outside the CPU context and are cleared by mips3_init().
|
||||
**#################################################################################################*/
|
||||
|
||||
#define MIPS3_MAX_FASTRAM 8
|
||||
|
||||
struct mips3_fastram
|
||||
{
|
||||
offs_t start;
|
||||
offs_t end;
|
||||
UINT8 * base;
|
||||
UINT8 readonly;
|
||||
int wait; /* cycles each data read costs (wait states), 0 = none */
|
||||
};
|
||||
|
||||
static struct mips3_fastram fastram[MIPS3_MAX_FASTRAM];
|
||||
static int fastram_count;
|
||||
static offs_t fastram_byte_xor, fastram_word_xor;
|
||||
static memory_handlers fastram_slow; /* handlers for everything else */
|
||||
static int fastram_has_wait; /* a region with read wait states exists */
|
||||
|
||||
/* exact skip of the loops that poll Cause for an interrupt (see cause_poll_skip) */
|
||||
#define MIPS3_MAX_POLLREAD 4
|
||||
static int cause_poll_enabled;
|
||||
static struct { offs_t start, end; } pollread[MIPS3_MAX_POLLREAD];
|
||||
static int pollread_count;
|
||||
|
||||
|
||||
void mips3_add_fastram(offs_t start, offs_t end, int readonly, void *base)
|
||||
{
|
||||
mips3_add_fastram_wait(start, end, readonly, base, 0);
|
||||
}
|
||||
|
||||
/* the same, with wait states: each data read (not instruction fetch) costs */
|
||||
/* wait cycles, as a slow ROM does (instruction fetch and translation stay direct) */
|
||||
void mips3_add_fastram_wait(offs_t start, offs_t end, int readonly, void *base, int wait)
|
||||
{
|
||||
if (fastram_count < MIPS3_MAX_FASTRAM)
|
||||
{
|
||||
fastram[fastram_count].start = start;
|
||||
fastram[fastram_count].end = end;
|
||||
fastram[fastram_count].base = (UINT8 *)base;
|
||||
fastram[fastram_count].readonly = readonly;
|
||||
fastram[fastram_count].wait = wait;
|
||||
if (wait)
|
||||
fastram_has_wait = 1;
|
||||
fastram_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mips3_set_cause_poll_skip(int enable)
|
||||
{
|
||||
cause_poll_enabled = enable;
|
||||
}
|
||||
|
||||
|
||||
void mips3_add_poll_read(offs_t start, offs_t end)
|
||||
{
|
||||
if (pollread_count < MIPS3_MAX_POLLREAD)
|
||||
{
|
||||
pollread[pollread_count].start = start;
|
||||
pollread[pollread_count].end = end;
|
||||
pollread_count++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static struct mips3_fastram *fastram_last = &fastram[0];
|
||||
|
||||
/* recompiler hook (mips3jit.c): a write may hit translated code */
|
||||
static INLINE void jit_check_write(const void *host);
|
||||
|
||||
static INLINE struct mips3_fastram *find_fastram(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = fastram_last;
|
||||
int i;
|
||||
|
||||
/* most accesses hit the same region as the previous one */
|
||||
if (address - r->start <= r->end - r->start)
|
||||
return r;
|
||||
for (i = 0; i < fastram_count; i++)
|
||||
if (address - fastram[i].start <= fastram[i].end - fastram[i].start)
|
||||
return fastram_last = &fastram[i];
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static data8_t fastram_readbyte(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r) { mips3_icount -= r->wait; return r->base[(address - r->start) ^ fastram_byte_xor]; }
|
||||
return (*fastram_slow.readbyte)(address);
|
||||
}
|
||||
|
||||
static data16_t fastram_readword(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r) { mips3_icount -= r->wait; return *(data16_t *)&r->base[(address - r->start) ^ fastram_word_xor]; }
|
||||
return (*fastram_slow.readword)(address);
|
||||
}
|
||||
|
||||
static data32_t fastram_readlong(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r) { mips3_icount -= r->wait; return *(data32_t *)&r->base[address - r->start]; }
|
||||
return (*fastram_slow.readlong)(address);
|
||||
}
|
||||
|
||||
static UINT64 fastram_readdouble(offs_t address)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && address + 7 <= r->end)
|
||||
{
|
||||
UINT64 first;
|
||||
UINT64 second;
|
||||
mips3_icount -= r->wait;
|
||||
first = *(data32_t *)&r->base[address - r->start];
|
||||
second = *(data32_t *)&r->base[address + 4 - r->start];
|
||||
return mips3.bigendian ? ((first << 32) | second) : (first | (second << 32));
|
||||
}
|
||||
return (*fastram_slow.readdouble)(address);
|
||||
}
|
||||
|
||||
static void fastram_writebyte(offs_t address, data8_t data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly) { jit_check_write(&r->base[address - r->start]); r->base[(address - r->start) ^ fastram_byte_xor] = data; return; }
|
||||
(*fastram_slow.writebyte)(address, data);
|
||||
}
|
||||
|
||||
static void fastram_writeword(offs_t address, data16_t data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly) { jit_check_write(&r->base[address - r->start]); *(data16_t *)&r->base[(address - r->start) ^ fastram_word_xor] = data; return; }
|
||||
(*fastram_slow.writeword)(address, data);
|
||||
}
|
||||
|
||||
static void fastram_writelong(offs_t address, data32_t data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly) { jit_check_write(&r->base[address - r->start]); *(data32_t *)&r->base[address - r->start] = data; return; }
|
||||
(*fastram_slow.writelong)(address, data);
|
||||
}
|
||||
|
||||
static void fastram_writedouble(offs_t address, UINT64 data)
|
||||
{
|
||||
struct mips3_fastram *r = find_fastram(address);
|
||||
if (r && !r->readonly && address + 7 <= r->end)
|
||||
{
|
||||
jit_check_write(&r->base[address - r->start]);
|
||||
jit_check_write(&r->base[address + 4 - r->start]);
|
||||
*(data32_t *)&r->base[address - r->start] = mips3.bigendian ? (data32_t)(data >> 32) : (data32_t)data;
|
||||
*(data32_t *)&r->base[address + 4 - r->start] = mips3.bigendian ? (data32_t)data : (data32_t)(data >> 32);
|
||||
return;
|
||||
}
|
||||
(*fastram_slow.writedouble)(address, data);
|
||||
}
|
||||
|
||||
static const memory_handlers fastram_memory =
|
||||
{
|
||||
fastram_readbyte, fastram_readword, fastram_readlong, fastram_readdouble,
|
||||
fastram_writebyte, fastram_writeword, fastram_writelong, fastram_writedouble
|
||||
};
|
||||
|
||||
/* switch the memory handlers when fast RAM is in use */
|
||||
static void fastram_attach(void)
|
||||
{
|
||||
if (!fastram_count || mips3.memory.readlong == fastram_readlong)
|
||||
return;
|
||||
fastram_slow = mips3.bigendian ? be_memory : le_memory;
|
||||
fastram_byte_xor = mips3.bigendian ? BYTE4_XOR_BE(0) : BYTE4_XOR_LE(0);
|
||||
fastram_word_xor = mips3.bigendian ? WORD_XOR_BE(0) : WORD_XOR_LE(0);
|
||||
mips3.memory = fastram_memory;
|
||||
}
|
||||
|
||||
|
||||
#include "mips3jit.c"
|
||||
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** MEMORY ACCESSORS
|
||||
**#################################################################################################*/
|
||||
@@ -439,9 +628,66 @@ static void compare_int_callback(int cpu)
|
||||
}
|
||||
|
||||
|
||||
/* the Compare interrupt timer is not saved by the core: whether it is set
|
||||
is. After a load it is set again from Count and Compare, in cycles of
|
||||
this CPU, as a write to Compare sets it (both functions run in the
|
||||
context of this CPU) */
|
||||
static UINT8 compare_timer_set;
|
||||
|
||||
static void mips3_presave(void)
|
||||
{
|
||||
compare_timer_set = (timer_timeleft(mips3.compare_int_timer) < TIME_NEVER / 2);
|
||||
}
|
||||
|
||||
static void mips3_postload(void)
|
||||
{
|
||||
int cpunum = cpu_getactivecpu();
|
||||
|
||||
timer_adjust(mips3.compare_int_timer, TIME_NEVER, cpunum, 0);
|
||||
if (compare_timer_set)
|
||||
{
|
||||
UINT32 count = (cpu_gettotalcycles64(cpunum) - mips3.count_zero_time) / 2;
|
||||
UINT32 cyclesleft = (UINT32)mips3.cpr[0][COP0_Compare] - count;
|
||||
timer_adjust(mips3.compare_int_timer, TIME_IN_CYCLES(((UINT64)cyclesleft * 2), cpunum), cpunum, 0);
|
||||
}
|
||||
|
||||
if (mips3.bigendian)
|
||||
change_pc32bedw(mips3.pc);
|
||||
else
|
||||
change_pc32ledw(mips3.pc);
|
||||
}
|
||||
|
||||
void mips3_init(void)
|
||||
{
|
||||
int cpunum = cpu_getactivecpu();
|
||||
|
||||
/* optional speedups are off until a driver asks for them */
|
||||
fastram_count = 0;
|
||||
fastram_has_wait = 0;
|
||||
fastram_last = &fastram[0];
|
||||
mips3_set_jit(0);
|
||||
cause_poll_enabled = 0;
|
||||
pollread_count = 0;
|
||||
|
||||
mips3.compare_int_timer = timer_alloc(compare_int_callback);
|
||||
|
||||
/* save states: the registers of the active context, swapped in per CPU
|
||||
when the state is saved; the 64-bit registers as pairs of 32 bits */
|
||||
state_save_register_UINT32("mips3", cpunum, "pc", &mips3.pc, 1);
|
||||
state_save_register_UINT32("mips3", cpunum, "hi", (UINT32 *)&mips3.hi, 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "lo", (UINT32 *)&mips3.lo, 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "r", (UINT32 *)mips3.r, 32 * 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "cpr", (UINT32 *)mips3.cpr, 4 * 32 * 2);
|
||||
state_save_register_UINT32("mips3", cpunum, "ccr", (UINT32 *)mips3.ccr, 4 * 32 * 2);
|
||||
state_save_register_UINT8 ("mips3", cpunum, "cf", mips3.cf, 4);
|
||||
state_save_register_UINT32("mips3", cpunum, "ppc", &mips3.ppc, 1);
|
||||
state_save_register_UINT32("mips3", cpunum, "nextpc", &mips3.nextpc, 1);
|
||||
state_save_register_int ("mips3", cpunum, "op", &mips3.op);
|
||||
state_save_register_int ("mips3", cpunum, "interrupt_cycles", &mips3.interrupt_cycles);
|
||||
state_save_register_UINT32("mips3", cpunum, "count_zero_time", (UINT32 *)&mips3.count_zero_time, 2);
|
||||
state_save_register_UINT8 ("mips3", cpunum, "compare_timer_set", &compare_timer_set, 1);
|
||||
state_save_register_func_presave(mips3_presave);
|
||||
state_save_register_func_postload(mips3_postload);
|
||||
}
|
||||
|
||||
|
||||
@@ -535,6 +781,8 @@ void r5000le_reset(void *param)
|
||||
|
||||
void mips3_exit(void)
|
||||
{
|
||||
mips3_set_jit(0);
|
||||
|
||||
/* free cache memory */
|
||||
if (mips3.icache)
|
||||
free(mips3.icache);
|
||||
@@ -624,6 +872,9 @@ static INLINE void set_cop0_reg(int idx, UINT64 val)
|
||||
mips3.cpr[0][idx] = val;
|
||||
if (diff & 0x8000)
|
||||
update_cycle_counting();
|
||||
/* the recompiler translates FPU instructions only while COP1 is usable */
|
||||
if (diff & SR_COP1)
|
||||
jit_flush();
|
||||
check_irqs();
|
||||
break;
|
||||
}
|
||||
@@ -682,6 +933,155 @@ static void logtlbentry(void)
|
||||
logonetlbentry(1);
|
||||
}
|
||||
|
||||
/*
|
||||
Exact skip of the loops that wait for an interrupt by polling Cause.
|
||||
|
||||
Within a timeslice nothing changes Cause: interrupt lines and the
|
||||
Count/Compare timer only change between timeslices. So every pass of
|
||||
such a loop leaves the same state, except for counters, and the whole
|
||||
passes that still fit in the timeslice can be skipped: registers and
|
||||
cycles end up exactly as if they had run. The last passes always run
|
||||
normally. Called by the MFC0 of Cause (mips3.ppc), after its read.
|
||||
|
||||
The loop, from the branch target L to the backward branch and its
|
||||
delay slot, may only hold:
|
||||
mfc0 rt, Cause (this instruction, once)
|
||||
andi rt, rt, mask (Cause & mask is 0 now)
|
||||
nop
|
||||
lw/lh/lb $zero, off(rb) (rb + off in a range declared free of
|
||||
side effects, mips3_add_poll_read)
|
||||
beq rc, $zero, outside (a timeout counter)
|
||||
beq rt, $zero, L (the loop branch, last)
|
||||
delay slot: nop, or addi/addiu rc, rc, imm (a counter)
|
||||
A timeout counter must count down by 1 and stays at 1 or more.
|
||||
*/
|
||||
static void cause_poll_skip(UINT32 mfc0_op)
|
||||
{
|
||||
UINT32 pc = mips3.ppc, a, op, branch_pc = 0, rt = (mfc0_op >> 16) & 31, mask = 0;
|
||||
int count, i, n, cost, rc = -1, timeout = 0;
|
||||
INT32 imm = 0;
|
||||
UINT32 body[16];
|
||||
|
||||
if (rt == 0 || mips3.nextpc != ~0)
|
||||
return;
|
||||
|
||||
/* find the backward branch beq rt, $zero, L with L <= pc */
|
||||
for (a = pc + 4; a < pc + 4 * 12; a += 4)
|
||||
{
|
||||
op = ROPCODE(a);
|
||||
if ((op >> 26) == 0x04 && ((op >> 21) & 31) == rt && ((op >> 16) & 31) == 0)
|
||||
{
|
||||
UINT32 target = a + 4 + ((INT32)(INT16)op << 2);
|
||||
if (target <= pc && pc - target < 4 * 8)
|
||||
{
|
||||
branch_pc = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!branch_pc)
|
||||
return;
|
||||
{
|
||||
UINT32 target = branch_pc + 4 + ((INT32)(INT16)ROPCODE(branch_pc) << 2);
|
||||
count = (branch_pc + 8 - target) / 4;
|
||||
if (count > 16)
|
||||
return;
|
||||
for (i = 0; i < count; i++)
|
||||
body[i] = ROPCODE(target + i * 4);
|
||||
a = target;
|
||||
}
|
||||
|
||||
/* check every instruction of the loop */
|
||||
for (i = 0; i < count; i++)
|
||||
{
|
||||
UINT32 ia = a + i * 4;
|
||||
op = body[i];
|
||||
if (ia == pc)
|
||||
continue;
|
||||
if (ia == branch_pc)
|
||||
continue;
|
||||
if (op == 0)
|
||||
continue;
|
||||
if (ia == branch_pc + 4)
|
||||
{
|
||||
/* delay slot: a counter */
|
||||
if (((op >> 26) == 0x08 || (op >> 26) == 0x09) && ((op >> 21) & 31) == ((op >> 16) & 31) &&
|
||||
((op >> 16) & 31) != 0 && ((op >> 16) & 31) != rt)
|
||||
{
|
||||
rc = (op >> 16) & 31;
|
||||
imm = (INT16)op;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if ((op >> 26) == 0x0c && ((op >> 21) & 31) == rt && ((op >> 16) & 31) == rt)
|
||||
{
|
||||
/* the mask, between the mfc0 and the branch */
|
||||
if (ia < pc || ia > branch_pc)
|
||||
return;
|
||||
mask |= op & 0xffff;
|
||||
continue;
|
||||
}
|
||||
if (((op >> 26) == 0x23 || (op >> 26) == 0x21 || (op >> 26) == 0x20) && ((op >> 16) & 31) == 0)
|
||||
{
|
||||
UINT32 address = (UINT32)mips3.r[(op >> 21) & 31] + (INT16)op;
|
||||
int p, ok = 0;
|
||||
for (p = 0; p < pollread_count; p++)
|
||||
if (address >= pollread[p].start && address <= pollread[p].end)
|
||||
ok = 1;
|
||||
if (ok)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
if ((op >> 26) == 0x04 && ((op >> 16) & 31) == 0 && ((op >> 21) & 31) != rt)
|
||||
{
|
||||
/* a timeout: beq rc, $zero, out of the loop */
|
||||
UINT32 target = ia + 4 + ((INT32)(INT16)op << 2);
|
||||
if (target >= a && target <= branch_pc + 4)
|
||||
return;
|
||||
if (timeout)
|
||||
return;
|
||||
timeout = (op >> 21) & 31;
|
||||
continue;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!mask || (CAUSE & mask))
|
||||
return;
|
||||
if (timeout && (timeout != rc || imm != -1))
|
||||
return;
|
||||
|
||||
/* whole passes that fit, leaving at least two to run normally */
|
||||
cost = count + 25;
|
||||
n = mips3_icount / cost - 2;
|
||||
if (n <= 0)
|
||||
return;
|
||||
if (rc >= 0)
|
||||
{
|
||||
INT64 value = (INT32)(UINT32)mips3.r[rc];
|
||||
if (timeout)
|
||||
{
|
||||
if (value <= 1)
|
||||
return;
|
||||
if (n > value - 1)
|
||||
n = (int)(value - 1);
|
||||
}
|
||||
else if ((body[(branch_pc + 4 - a) / 4] >> 26) == 0x08)
|
||||
{
|
||||
/* ADDI traps on overflow: stop before it */
|
||||
INT64 limit = imm > 0 ? ((INT64)0x7fffffff - value) / imm : (value + (INT64)0x80000000) / -imm;
|
||||
if (imm == 0)
|
||||
limit = n;
|
||||
if (n > limit)
|
||||
n = (int)limit;
|
||||
}
|
||||
if (n <= 0)
|
||||
return;
|
||||
mips3.r[rc] = (INT64)(INT32)((UINT32)value + (UINT32)(imm * n));
|
||||
}
|
||||
mips3_icount -= n * cost;
|
||||
}
|
||||
|
||||
static INLINE void handle_cop0(UINT32 op)
|
||||
{
|
||||
if ((SR & SR_KSU_MASK) != SR_KSU_KERNEL && !(SR & SR_COP0))
|
||||
@@ -689,7 +1089,11 @@ static INLINE void handle_cop0(UINT32 op)
|
||||
|
||||
switch (RSREG)
|
||||
{
|
||||
case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_reg(RDREG); break;
|
||||
case 0x00: /* MFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_reg(RDREG);
|
||||
/* optional: whole passes of a loop waiting for an interrupt in Cause */
|
||||
if (cause_poll_enabled && RDREG == COP0_Cause)
|
||||
cause_poll_skip(op);
|
||||
break;
|
||||
case 0x01: /* DMFCz */ if (RTREG) RTVAL64 = get_cop0_reg(RDREG); break;
|
||||
case 0x02: /* CFCz */ if (RTREG) RTVAL64 = (INT32)get_cop0_creg(RDREG); break;
|
||||
case 0x04: /* MTCz */ set_cop0_reg(RDREG, RTVAL32); break;
|
||||
@@ -1119,6 +1523,14 @@ static INLINE void handle_cop1(UINT32 op)
|
||||
|
||||
|
||||
|
||||
/* a COP1 instruction (not a branch) from translated code: exactly the interpreter's */
|
||||
static void jit_cop1_helper(UINT32 op)
|
||||
{
|
||||
handle_cop1(op);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** COP1X (FPU EXTRA) EXECUTION HANDLING
|
||||
**#################################################################################################*/
|
||||
@@ -1283,6 +1695,9 @@ int mips3_execute(int cycles)
|
||||
change_pc32bedw(mips3.pc);
|
||||
|
||||
|
||||
/* optional fast RAM (see mips3_add_fastram) */
|
||||
fastram_attach();
|
||||
|
||||
/* check for IRQs */
|
||||
check_irqs();
|
||||
|
||||
@@ -1297,6 +1712,47 @@ int mips3_execute(int cycles)
|
||||
mips3.ppc = mips3.pc;
|
||||
CALL_MAME_DEBUG;
|
||||
|
||||
#if MIPS3_JIT_SUPPORTED
|
||||
/* recompiled block, when there are enough cycles left for all of it */
|
||||
if (jit_enabled && mips3.nextpc == ~0)
|
||||
{
|
||||
struct jit_block *block = jit_lookup(mips3.pc);
|
||||
if (block && (int)block->len <= mips3_icount)
|
||||
{
|
||||
/* run blocks back to back while they fit in the timeslice; */
|
||||
/* each takes its own cycles, and none taken means a side exit */
|
||||
/* before its first instruction, which the interpreter then runs */
|
||||
int ran = 0, stalled = 0;
|
||||
for (;;)
|
||||
{
|
||||
int before = mips3_icount;
|
||||
mips3.pc = ((jit_func)block->code)();
|
||||
if (mips3_icount == before)
|
||||
{
|
||||
stalled = 1;
|
||||
break;
|
||||
}
|
||||
ran = 1;
|
||||
if (mips3_icount <= 0)
|
||||
break;
|
||||
block = jit_lookup(mips3.pc);
|
||||
if (!block || (int)block->len > mips3_icount)
|
||||
break;
|
||||
}
|
||||
if (ran)
|
||||
{
|
||||
change_pc32bedw(mips3.pc);
|
||||
if (!stalled)
|
||||
{
|
||||
mips3.ppc = mips3.pc - 4;
|
||||
continue;
|
||||
}
|
||||
mips3.ppc = mips3.pc;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* instruction fetch */
|
||||
op = ROPCODE(mips3.pc);
|
||||
|
||||
|
||||
@@ -183,6 +183,20 @@ extern void r5000le_reset(void *param);
|
||||
|
||||
void mips3drc_set_options(UINT8 cpunum, UINT32 opts);
|
||||
|
||||
/* optional speedups for a single MIPS3 CPU, off by default; set them up in DRIVER_INIT */
|
||||
/* plain RAM accessed through a direct pointer (no handlers may sit in the range) */
|
||||
void mips3_add_fastram(offs_t start, offs_t end, int readonly, void *base);
|
||||
void mips3_add_fastram_wait(offs_t start, offs_t end, int readonly, void *base, int wait);
|
||||
/* skip, exactly, the whole passes of loops waiting for an interrupt in Cause (see mips3.c) */
|
||||
void mips3_set_cause_poll_skip(int enable);
|
||||
/* loads from this range, into $zero, have no side effects (they may sit in such a loop) */
|
||||
void mips3_add_poll_read(offs_t start, offs_t end);
|
||||
/* recompile integer code in fast RAM with sljit, where supported (x86 and ARM, 32 and 64-bit) */
|
||||
void mips3_set_jit(int enable);
|
||||
void mips3_ram_written(offs_t address, UINT32 bytes);
|
||||
/* nonzero when this build has the recompiler (x86/ARM hosts that allow run-time code) */
|
||||
int mips3_jit_available(void);
|
||||
|
||||
|
||||
|
||||
#endif /* _MIPS3_H */
|
||||
@@ -5830,3 +5830,49 @@ unsigned mips3_dasm(char *buffer, unsigned pc)
|
||||
return 4;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*###################################################################################################
|
||||
** OPTIONAL SPEEDUPS (see mips3.h)
|
||||
**
|
||||
** This x86 recompiler is built instead of mips3.c when X86_MIPS3_DRC is set (32-bit x86 hosts).
|
||||
** The speedups declared in mips3.h live in mips3.c; here they are accepted and ignored, so
|
||||
** drivers that request them (Killer Instinct) still link and run, just without them.
|
||||
**#################################################################################################*/
|
||||
|
||||
void mips3_add_fastram(offs_t start, offs_t end, int readonly, void *base)
|
||||
{
|
||||
(void)start; (void)end; (void)readonly; (void)base;
|
||||
}
|
||||
|
||||
void mips3_add_fastram_wait(offs_t start, offs_t end, int readonly, void *base, int wait)
|
||||
{
|
||||
(void)start; (void)end; (void)readonly; (void)base; (void)wait;
|
||||
}
|
||||
|
||||
void mips3_set_cause_poll_skip(int enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
void mips3_add_poll_read(offs_t start, offs_t end)
|
||||
{
|
||||
(void)start; (void)end;
|
||||
}
|
||||
|
||||
void mips3_set_jit(int enable)
|
||||
{
|
||||
(void)enable;
|
||||
}
|
||||
|
||||
int mips3_jit_available(void)
|
||||
{
|
||||
/* no sljit recompiler in this build: the "MIPS Dynarec" core option stays hidden */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mips3_ram_written(offs_t address, UINT32 bytes)
|
||||
{
|
||||
/* no translations to drop in this build */
|
||||
(void)address; (void)bytes;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,18 @@
|
||||
/***************************************************************************
|
||||
|
||||
mips3jit.h
|
||||
|
||||
Host support of the MIPS3 recompiler: the bundled sljit, configured
|
||||
and built once for all the recompilers (src/lib/sljit/sljit_mame.h).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MIPS3JIT_H
|
||||
#define MIPS3JIT_H
|
||||
|
||||
/* the sljit build shared by the recompilers decides where they run */
|
||||
#include "../../lib/sljit/sljit_mame.h"
|
||||
|
||||
#define MIPS3_JIT_SUPPORTED SLJIT_MAME_SUPPORTED
|
||||
|
||||
#endif /* MIPS3JIT_H */
|
||||
@@ -213,6 +213,20 @@ extern void mips_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *mips_info(void *context, int regnum);
|
||||
extern unsigned mips_dasm(char *buffer, UINT32 pc);
|
||||
|
||||
/* optional speedups, off unless a driver enables them */
|
||||
/* loads and stores in a plain RAM region use a direct pointer */
|
||||
extern void psxcpu_add_fastram(offs_t start, offs_t end, int readonly, void *base);
|
||||
/* fast RAM written behind the CPU's back (DMA, driver patches) */
|
||||
extern void psxcpu_ram_written(const void *host, UINT32 bytes);
|
||||
/* recompiler (sljit), where supported. The fast RAM table and the
|
||||
recompiler state are global, not part of the CPU context: one PSXCPU
|
||||
per machine. */
|
||||
extern int psxcpu_jit_available(void);
|
||||
extern void psxcpu_set_jit(int enable);
|
||||
/* fn is called before the instruction at pc runs (NULL: none); set at */
|
||||
/* machine init, cleared at the CPU init */
|
||||
extern void psxcpu_set_pc_hook(UINT32 pc, void (*fn)(void));
|
||||
|
||||
#ifdef MAME_DEBUG
|
||||
extern unsigned DasmMIPS(char *buff, unsigned _pc);
|
||||
#endif
|
||||
|
||||
+1353
-1923
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,941 @@
|
||||
/***************************************************************************
|
||||
|
||||
PlayStation Geometry Transformation Engine, as current MAME
|
||||
(src/devices/cpu/psx/gte.cpp, copyright smf, BSD-3-Clause), in C.
|
||||
|
||||
The hardware divide (reciprocal table, result capped at 0x1ffff and
|
||||
flagged), the 44-bit accumulators with their overflow flags, the
|
||||
register moves (IRGB/ORGB, LZCS/LZCR, the sign extended control
|
||||
registers, FLAG) of current MAME.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define GTE_SF( op ) ( ( op >> 19 ) & 1 )
|
||||
#define GTE_MX( op ) ( ( op >> 17 ) & 3 )
|
||||
#define GTE_V( op ) ( ( op >> 15 ) & 3 )
|
||||
#define GTE_CV( op ) ( ( op >> 13 ) & 3 )
|
||||
#define GTE_LM( op ) ( ( op >> 10 ) & 1 )
|
||||
#define GTE_FUNCT( op ) ( op & 63 )
|
||||
|
||||
static int m_sf;
|
||||
static INT64 m_mac0;
|
||||
static INT64 m_mac1;
|
||||
static INT64 m_mac2;
|
||||
static INT64 m_mac3;
|
||||
|
||||
static INLINE int count_leading_zeros32( UINT32 v )
|
||||
{
|
||||
int n = 0;
|
||||
if( v == 0 )
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
while( ( v & 0x80000000 ) == 0 )
|
||||
{
|
||||
v <<= 1;
|
||||
n++;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/* a 44-bit accumulator with sticky overflow flags (MAME's int44) */
|
||||
typedef struct
|
||||
{
|
||||
INT64 value;
|
||||
int pos;
|
||||
int neg;
|
||||
} int44;
|
||||
|
||||
static INLINE int44 i44( INT64 value )
|
||||
{
|
||||
int44 r;
|
||||
r.value = value;
|
||||
r.pos = value > ( ( (INT64)1 << 43 ) - 1 );
|
||||
r.neg = value < -( (INT64)1 << 43 );
|
||||
return r;
|
||||
}
|
||||
|
||||
static INLINE int44 i44_add( int44 a, INT64 add )
|
||||
{
|
||||
int44 r;
|
||||
INT64 value = (INT64)( (UINT64)( a.value + add ) << 20 ) >> 20;
|
||||
r.value = value;
|
||||
r.pos = a.pos || ( value < 0 && a.value >= 0 && add >= 0 );
|
||||
r.neg = a.neg || ( value >= 0 && a.value < 0 && add < 0 );
|
||||
return r;
|
||||
}
|
||||
|
||||
#define VX0 ( (*(INT16 *)&mipscpu.cp2dr[ 0 ].w.l) )
|
||||
#define VY0 ( (*(INT16 *)&mipscpu.cp2dr[ 0 ].w.h) )
|
||||
#define VZ0 ( (*(INT16 *)&mipscpu.cp2dr[ 1 ].w.l) )
|
||||
#define VX1 ( mipscpu.cp2dr[ 2 ].w.l )
|
||||
#define VY1 ( mipscpu.cp2dr[ 2 ].w.h )
|
||||
#define VZ1 ( mipscpu.cp2dr[ 3 ].w.l )
|
||||
#define VX2 ( mipscpu.cp2dr[ 4 ].w.l )
|
||||
#define VY2 ( mipscpu.cp2dr[ 4 ].w.h )
|
||||
#define VZ2 ( mipscpu.cp2dr[ 5 ].w.l )
|
||||
#define R ( mipscpu.cp2dr[ 6 ].b.l )
|
||||
#define G ( mipscpu.cp2dr[ 6 ].b.h )
|
||||
#define B ( mipscpu.cp2dr[ 6 ].b.h2 )
|
||||
#define CODE ( mipscpu.cp2dr[ 6 ].b.h3 )
|
||||
#define OTZ ( mipscpu.cp2dr[ 7 ].w.l )
|
||||
#define IR0 ( (*(INT16 *)&mipscpu.cp2dr[ 8 ].w.l) )
|
||||
#define IR1 ( (*(INT16 *)&mipscpu.cp2dr[ 9 ].w.l) )
|
||||
#define IR2 ( (*(INT16 *)&mipscpu.cp2dr[ 10 ].w.l) )
|
||||
#define IR3 ( (*(INT16 *)&mipscpu.cp2dr[ 11 ].w.l) )
|
||||
#define SXY0 ( mipscpu.cp2dr[ 12 ].d )
|
||||
#define SX0 ( (*(INT16 *)&mipscpu.cp2dr[ 12 ].w.l) )
|
||||
#define SY0 ( (*(INT16 *)&mipscpu.cp2dr[ 12 ].w.h) )
|
||||
#define SXY1 ( mipscpu.cp2dr[ 13 ].d )
|
||||
#define SX1 ( (*(INT16 *)&mipscpu.cp2dr[ 13 ].w.l) )
|
||||
#define SY1 ( (*(INT16 *)&mipscpu.cp2dr[ 13 ].w.h) )
|
||||
#define SXY2 ( mipscpu.cp2dr[ 14 ].d )
|
||||
#define SX2 ( (*(INT16 *)&mipscpu.cp2dr[ 14 ].w.l) )
|
||||
#define SY2 ( (*(INT16 *)&mipscpu.cp2dr[ 14 ].w.h) )
|
||||
#define SXYP ( mipscpu.cp2dr[ 15 ].d )
|
||||
#define SXP ( (*(INT16 *)&mipscpu.cp2dr[ 15 ].w.l) )
|
||||
#define SYP ( (*(INT16 *)&mipscpu.cp2dr[ 15 ].w.h) )
|
||||
#define SZ0 ( mipscpu.cp2dr[ 16 ].w.l )
|
||||
#define SZ1 ( mipscpu.cp2dr[ 17 ].w.l )
|
||||
#define SZ2 ( mipscpu.cp2dr[ 18 ].w.l )
|
||||
#define SZ3 ( mipscpu.cp2dr[ 19 ].w.l )
|
||||
#define RGB0 ( mipscpu.cp2dr[ 20 ].d )
|
||||
#define R0 ( mipscpu.cp2dr[ 20 ].b.l )
|
||||
#define G0 ( mipscpu.cp2dr[ 20 ].b.h )
|
||||
#define B0 ( mipscpu.cp2dr[ 20 ].b.h2 )
|
||||
#define CD0 ( mipscpu.cp2dr[ 20 ].b.h3 )
|
||||
#define RGB1 ( mipscpu.cp2dr[ 21 ].d )
|
||||
#define R1 ( mipscpu.cp2dr[ 21 ].b.l )
|
||||
#define G1 ( mipscpu.cp2dr[ 21 ].b.h )
|
||||
#define B1 ( mipscpu.cp2dr[ 21 ].b.h2 )
|
||||
#define CD1 ( mipscpu.cp2dr[ 21 ].b.h3 )
|
||||
#define RGB2 ( mipscpu.cp2dr[ 22 ].d )
|
||||
#define R2 ( mipscpu.cp2dr[ 22 ].b.l )
|
||||
#define G2 ( mipscpu.cp2dr[ 22 ].b.h )
|
||||
#define B2 ( mipscpu.cp2dr[ 22 ].b.h2 )
|
||||
#define CD2 ( mipscpu.cp2dr[ 22 ].b.h3 )
|
||||
#define RES1 ( mipscpu.cp2dr[ 23 ].d )
|
||||
#define MAC0 ( (*(INT32 *)&mipscpu.cp2dr[ 24 ].d) )
|
||||
#define MAC1 ( (*(INT32 *)&mipscpu.cp2dr[ 25 ].d) )
|
||||
#define MAC2 ( (*(INT32 *)&mipscpu.cp2dr[ 26 ].d) )
|
||||
#define MAC3 ( (*(INT32 *)&mipscpu.cp2dr[ 27 ].d) )
|
||||
#define IRGB ( mipscpu.cp2dr[ 28 ].d )
|
||||
#define ORGB ( mipscpu.cp2dr[ 29 ].d )
|
||||
#define LZCS ( mipscpu.cp2dr[ 30 ].d )
|
||||
#define LZCR ( mipscpu.cp2dr[ 31 ].d )
|
||||
|
||||
#define R11 ( (*(INT16 *)&mipscpu.cp2cr[ 0 ].w.l) )
|
||||
#define R12 ( (*(INT16 *)&mipscpu.cp2cr[ 0 ].w.h) )
|
||||
#define R13 ( (*(INT16 *)&mipscpu.cp2cr[ 1 ].w.l) )
|
||||
#define R21 ( (*(INT16 *)&mipscpu.cp2cr[ 1 ].w.h) )
|
||||
#define R22 ( (*(INT16 *)&mipscpu.cp2cr[ 2 ].w.l) )
|
||||
#define R23 ( (*(INT16 *)&mipscpu.cp2cr[ 2 ].w.h) )
|
||||
#define R31 ( (*(INT16 *)&mipscpu.cp2cr[ 3 ].w.l) )
|
||||
#define R32 ( (*(INT16 *)&mipscpu.cp2cr[ 3 ].w.h) )
|
||||
#define R33 ( (*(INT16 *)&mipscpu.cp2cr[ 4 ].w.l) )
|
||||
#define TRX ( (*(INT32 *)&mipscpu.cp2cr[ 5 ].d) )
|
||||
#define TRY ( (*(INT32 *)&mipscpu.cp2cr[ 6 ].d) )
|
||||
#define TRZ ( (*(INT32 *)&mipscpu.cp2cr[ 7 ].d) )
|
||||
#define L11 ( (*(INT16 *)&mipscpu.cp2cr[ 8 ].w.l) )
|
||||
#define L12 ( (*(INT16 *)&mipscpu.cp2cr[ 8 ].w.h) )
|
||||
#define L13 ( (*(INT16 *)&mipscpu.cp2cr[ 9 ].w.l) )
|
||||
#define L21 ( (*(INT16 *)&mipscpu.cp2cr[ 9 ].w.h) )
|
||||
#define L22 ( (*(INT16 *)&mipscpu.cp2cr[ 10 ].w.l) )
|
||||
#define L23 ( (*(INT16 *)&mipscpu.cp2cr[ 10 ].w.h) )
|
||||
#define L31 ( (*(INT16 *)&mipscpu.cp2cr[ 11 ].w.l) )
|
||||
#define L32 ( (*(INT16 *)&mipscpu.cp2cr[ 11 ].w.h) )
|
||||
#define L33 ( (*(INT16 *)&mipscpu.cp2cr[ 12 ].w.l) )
|
||||
#define RBK ( (*(INT32 *)&mipscpu.cp2cr[ 13 ].d) )
|
||||
#define GBK ( (*(INT32 *)&mipscpu.cp2cr[ 14 ].d) )
|
||||
#define BBK ( (*(INT32 *)&mipscpu.cp2cr[ 15 ].d) )
|
||||
#define LR1 ( (*(INT16 *)&mipscpu.cp2cr[ 16 ].w.l) )
|
||||
#define LR2 ( (*(INT16 *)&mipscpu.cp2cr[ 16 ].w.h) )
|
||||
#define LR3 ( (*(INT16 *)&mipscpu.cp2cr[ 17 ].w.l) )
|
||||
#define LG1 ( (*(INT16 *)&mipscpu.cp2cr[ 17 ].w.h) )
|
||||
#define LG2 ( (*(INT16 *)&mipscpu.cp2cr[ 18 ].w.l) )
|
||||
#define LG3 ( (*(INT16 *)&mipscpu.cp2cr[ 18 ].w.h) )
|
||||
#define LB1 ( (*(INT16 *)&mipscpu.cp2cr[ 19 ].w.l) )
|
||||
#define LB2 ( (*(INT16 *)&mipscpu.cp2cr[ 19 ].w.h) )
|
||||
#define LB3 ( (*(INT16 *)&mipscpu.cp2cr[ 20 ].w.l) )
|
||||
#define RFC ( (*(INT32 *)&mipscpu.cp2cr[ 21 ].d) )
|
||||
#define GFC ( (*(INT32 *)&mipscpu.cp2cr[ 22 ].d) )
|
||||
#define BFC ( (*(INT32 *)&mipscpu.cp2cr[ 23 ].d) )
|
||||
#define OFX ( (*(INT32 *)&mipscpu.cp2cr[ 24 ].d) )
|
||||
#define OFY ( (*(INT32 *)&mipscpu.cp2cr[ 25 ].d) )
|
||||
#define H ( (*(INT16 *)&mipscpu.cp2cr[ 26 ].w.l) )
|
||||
#define DQA ( (*(INT16 *)&mipscpu.cp2cr[ 27 ].w.l) )
|
||||
#define DQB ( (*(INT32 *)&mipscpu.cp2cr[ 28 ].d) )
|
||||
#define ZSF3 ( (*(INT16 *)&mipscpu.cp2cr[ 29 ].w.l) )
|
||||
#define ZSF4 ( (*(INT16 *)&mipscpu.cp2cr[ 30 ].w.l) )
|
||||
#define FLAG ( mipscpu.cp2cr[ 31 ].d )
|
||||
|
||||
#define VX( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2dr[ n << 1 ].w.l) : IR1 )
|
||||
#define VY( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2dr[ n << 1 ].w.h) : IR2 )
|
||||
#define VZ( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2dr[ ( n << 1 ) + 1 ].w.l) : IR3 )
|
||||
#define MX11( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) ].w.l) : -R << 4 )
|
||||
#define MX12( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) ].w.h) : R << 4 )
|
||||
#define MX13( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 1 ].w.l) : IR0 )
|
||||
#define MX21( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 1 ].w.h) : R13 )
|
||||
#define MX22( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 2 ].w.l) : R13 )
|
||||
#define MX23( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 2 ].w.h) : R13 )
|
||||
#define MX31( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 3 ].w.l) : R22 )
|
||||
#define MX32( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 3 ].w.h) : R22 )
|
||||
#define MX33( n ) ( n < 3 ? (*(INT16 *)&mipscpu.cp2cr[ ( n << 3 ) + 4 ].w.l) : R22 )
|
||||
#define CV1( n ) ( n < 3 ? (*(INT32 *)&mipscpu.cp2cr[ ( n << 3 ) + 5 ].d) : 0 )
|
||||
#define CV2( n ) ( n < 3 ? (*(INT32 *)&mipscpu.cp2cr[ ( n << 3 ) + 6 ].d) : 0 )
|
||||
#define CV3( n ) ( n < 3 ? (*(INT32 *)&mipscpu.cp2cr[ ( n << 3 ) + 7 ].d) : 0 )
|
||||
|
||||
static INT32 LIM( INT32 value, INT32 max, INT32 min, UINT32 flag )
|
||||
{
|
||||
if( value > max )
|
||||
{
|
||||
FLAG |= flag;
|
||||
return max;
|
||||
}
|
||||
else if( value < min )
|
||||
{
|
||||
FLAG |= flag;
|
||||
return min;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
static UINT32 getcp2dr( int reg )
|
||||
{
|
||||
switch( reg )
|
||||
{
|
||||
case 1:
|
||||
case 3:
|
||||
case 5:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
mipscpu.cp2dr[ reg ].d = (INT32)(*(INT16 *)&mipscpu.cp2dr[ reg ].w.l);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
case 16:
|
||||
case 17:
|
||||
case 18:
|
||||
case 19:
|
||||
mipscpu.cp2dr[ reg ].d = (UINT32)mipscpu.cp2dr[ reg ].w.l;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
mipscpu.cp2dr[ reg ].d = SXY2;
|
||||
break;
|
||||
|
||||
case 28:
|
||||
case 29:
|
||||
mipscpu.cp2dr[ reg ].d = LIM( IR1 >> 7, 0x1f, 0, 0 ) | ( LIM( IR2 >> 7, 0x1f, 0, 0 ) << 5 ) | ( LIM( IR3 >> 7, 0x1f, 0, 0 ) << 10 );
|
||||
break;
|
||||
}
|
||||
return mipscpu.cp2dr[ reg ].d;
|
||||
}
|
||||
|
||||
static void setcp2dr( int reg, UINT32 value )
|
||||
{
|
||||
|
||||
switch( reg )
|
||||
{
|
||||
case 15:
|
||||
SXY0 = SXY1;
|
||||
SXY1 = SXY2;
|
||||
SXY2 = value;
|
||||
break;
|
||||
|
||||
case 28:
|
||||
IR1 = ( value & 0x1f ) << 7;
|
||||
IR2 = ( value & 0x3e0 ) << 2;
|
||||
IR3 = ( value & 0x7c00 ) >> 3;
|
||||
break;
|
||||
|
||||
case 30:
|
||||
LZCR = ( value & 0x80000000 ) == 0 ? count_leading_zeros32( value ) : count_leading_zeros32( ~value );
|
||||
break;
|
||||
|
||||
case 31:
|
||||
return;
|
||||
}
|
||||
|
||||
mipscpu.cp2dr[ reg ].d = value;
|
||||
}
|
||||
|
||||
static UINT32 getcp2cr( int reg )
|
||||
{
|
||||
|
||||
return mipscpu.cp2cr[ reg ].d;
|
||||
}
|
||||
|
||||
static void setcp2cr( int reg, UINT32 value )
|
||||
{
|
||||
|
||||
switch( reg )
|
||||
{
|
||||
case 4:
|
||||
case 12:
|
||||
case 20:
|
||||
case 26:
|
||||
case 27:
|
||||
case 29:
|
||||
case 30:
|
||||
value = (INT32)(INT16) value;
|
||||
break;
|
||||
|
||||
case 31:
|
||||
value = value & 0x7ffff000;
|
||||
if( ( value & 0x7f87e000 ) != 0 )
|
||||
{
|
||||
value |= 0x80000000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
mipscpu.cp2cr[ reg ].d = value;
|
||||
}
|
||||
|
||||
static INLINE INT64 gte_shift( INT64 a, int sf )
|
||||
{
|
||||
if( sf > 0 )
|
||||
{
|
||||
return a >> 12;
|
||||
}
|
||||
else if( sf < 0 )
|
||||
{
|
||||
return a << 12;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 BOUNDS( int44 value, UINT32 max_flag, UINT32 min_flag )
|
||||
{
|
||||
if( value.pos )
|
||||
{
|
||||
FLAG |= max_flag;
|
||||
}
|
||||
|
||||
if( value.neg )
|
||||
{
|
||||
FLAG |= min_flag;
|
||||
}
|
||||
|
||||
return gte_shift( value.value, m_sf );
|
||||
}
|
||||
|
||||
static INLINE UINT32 gte_divide( UINT16 numerator, UINT16 denominator )
|
||||
{
|
||||
if( numerator < ( denominator * 2 ) )
|
||||
{
|
||||
static const UINT8 table[] =
|
||||
{
|
||||
0xff, 0xfd, 0xfb, 0xf9, 0xf7, 0xf5, 0xf3, 0xf1, 0xef, 0xee, 0xec, 0xea, 0xe8, 0xe6, 0xe4, 0xe3,
|
||||
0xe1, 0xdf, 0xdd, 0xdc, 0xda, 0xd8, 0xd6, 0xd5, 0xd3, 0xd1, 0xd0, 0xce, 0xcd, 0xcb, 0xc9, 0xc8,
|
||||
0xc6, 0xc5, 0xc3, 0xc1, 0xc0, 0xbe, 0xbd, 0xbb, 0xba, 0xb8, 0xb7, 0xb5, 0xb4, 0xb2, 0xb1, 0xb0,
|
||||
0xae, 0xad, 0xab, 0xaa, 0xa9, 0xa7, 0xa6, 0xa4, 0xa3, 0xa2, 0xa0, 0x9f, 0x9e, 0x9c, 0x9b, 0x9a,
|
||||
0x99, 0x97, 0x96, 0x95, 0x94, 0x92, 0x91, 0x90, 0x8f, 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x87, 0x86,
|
||||
0x85, 0x84, 0x83, 0x82, 0x81, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0x77, 0x75, 0x74,
|
||||
0x73, 0x72, 0x71, 0x70, 0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x69, 0x68, 0x67, 0x66, 0x65, 0x64,
|
||||
0x63, 0x62, 0x61, 0x60, 0x5f, 0x5e, 0x5d, 0x5d, 0x5c, 0x5b, 0x5a, 0x59, 0x58, 0x57, 0x56, 0x55,
|
||||
0x54, 0x53, 0x53, 0x52, 0x51, 0x50, 0x4f, 0x4e, 0x4d, 0x4d, 0x4c, 0x4b, 0x4a, 0x49, 0x48, 0x48,
|
||||
0x47, 0x46, 0x45, 0x44, 0x43, 0x43, 0x42, 0x41, 0x40, 0x3f, 0x3f, 0x3e, 0x3d, 0x3c, 0x3c, 0x3b,
|
||||
0x3a, 0x39, 0x39, 0x38, 0x37, 0x36, 0x36, 0x35, 0x34, 0x33, 0x33, 0x32, 0x31, 0x31, 0x30, 0x2f,
|
||||
0x2e, 0x2e, 0x2d, 0x2c, 0x2c, 0x2b, 0x2a, 0x2a, 0x29, 0x28, 0x28, 0x27, 0x26, 0x26, 0x25, 0x24,
|
||||
0x24, 0x23, 0x22, 0x22, 0x21, 0x20, 0x20, 0x1f, 0x1e, 0x1e, 0x1d, 0x1d, 0x1c, 0x1b, 0x1b, 0x1a,
|
||||
0x19, 0x19, 0x18, 0x18, 0x17, 0x16, 0x16, 0x15, 0x15, 0x14, 0x14, 0x13, 0x12, 0x12, 0x11, 0x11,
|
||||
0x10, 0x0f, 0x0f, 0x0e, 0x0e, 0x0d, 0x0d, 0x0c, 0x0c, 0x0b, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08,
|
||||
0x07, 0x07, 0x06, 0x06, 0x05, 0x05, 0x04, 0x04, 0x03, 0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00,
|
||||
0x00
|
||||
};
|
||||
|
||||
int shift = ( count_leading_zeros32( denominator ) - 16 );
|
||||
int r1 = ( denominator << shift ) & 0x7fff;
|
||||
int r2 = table[ ( ( r1 + 0x40 ) >> 7 ) ] + 0x101;
|
||||
int r3 = ( ( 0x80 - ( r2 * ( r1 + 0x8000 ) ) ) >> 8 ) & 0x1ffff;
|
||||
UINT32 reciprocal = ( ( r2 * r3 ) + 0x80 ) >> 8;
|
||||
|
||||
return (UINT32)( ( ( (UINT64)reciprocal * ( (UINT32)numerator << shift ) ) + 0x8000 ) >> 16 );
|
||||
}
|
||||
|
||||
return 0xffffffff;
|
||||
}
|
||||
|
||||
/* Setting bits 12 & 19-22 in FLAG does not set bit 31 */
|
||||
|
||||
static INT32 A1i( int44 a ) { m_mac1 = a.value; return BOUNDS( a, ( 1U << 31 ) | ( 1 << 30 ), ( 1U << 31 ) | ( 1 << 27 ) ); }
|
||||
static INT32 A1( INT64 a ) { return A1i( i44( a ) ); }
|
||||
static INT32 A2i( int44 a ) { m_mac2 = a.value; return BOUNDS( a, ( 1U << 31 ) | ( 1 << 29 ), ( 1U << 31 ) | ( 1 << 26 ) ); }
|
||||
static INT32 A2( INT64 a ) { return A2i( i44( a ) ); }
|
||||
static INT32 A3i( int44 a ) { m_mac3 = a.value; return BOUNDS( a, ( 1U << 31 ) | ( 1 << 28 ), ( 1U << 31 ) | ( 1 << 25 ) ); }
|
||||
static INT32 A3( INT64 a ) { return A3i( i44( a ) ); }
|
||||
static INT32 Lm_B1( INT32 a, int lm ) { return LIM( a, 0x7fff, -0x8000 * !lm, ( 1U << 31 ) | ( 1 << 24 ) ); }
|
||||
static INT32 Lm_B2( INT32 a, int lm ) { return LIM( a, 0x7fff, -0x8000 * !lm, ( 1U << 31 ) | ( 1 << 23 ) ); }
|
||||
static INT32 Lm_B3( INT32 a, int lm ) { return LIM( a, 0x7fff, -0x8000 * !lm, ( 1 << 22 ) ); }
|
||||
|
||||
static INT32 Lm_B3_sf( INT64 value, int sf, int lm )
|
||||
{
|
||||
INT32 value_sf = (INT32)gte_shift( value, sf );
|
||||
INT32 value_12 = (INT32)gte_shift( value, 1 );
|
||||
int max = 0x7fff;
|
||||
int min = 0;
|
||||
if( lm == 0 )
|
||||
{
|
||||
min = -0x8000;
|
||||
}
|
||||
|
||||
if( value_12 < -0x8000 || value_12 > 0x7fff )
|
||||
{
|
||||
FLAG |= ( 1 << 22 );
|
||||
}
|
||||
|
||||
if( value_sf > max )
|
||||
{
|
||||
return max;
|
||||
}
|
||||
else if( value_sf < min )
|
||||
{
|
||||
return min;
|
||||
}
|
||||
|
||||
return value_sf;
|
||||
}
|
||||
|
||||
static INT32 Lm_C1( INT32 a ) { return LIM( a, 0x00ff, 0x0000, ( 1 << 21 ) ); }
|
||||
static INT32 Lm_C2( INT32 a ) { return LIM( a, 0x00ff, 0x0000, ( 1 << 20 ) ); }
|
||||
static INT32 Lm_C3( INT32 a ) { return LIM( a, 0x00ff, 0x0000, ( 1 << 19 ) ); }
|
||||
static INT32 Lm_D( INT64 a, int sf ) { return LIM( gte_shift( a, sf ), 0xffff, 0x0000, ( 1U << 31 ) | ( 1 << 18 ) ); }
|
||||
|
||||
static UINT32 Lm_E( UINT32 result )
|
||||
{
|
||||
if( result == 0xffffffff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 17 );
|
||||
return 0x1ffff;
|
||||
}
|
||||
|
||||
if( result > 0x1ffff )
|
||||
{
|
||||
return 0x1ffff;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static INT64 F( INT64 a )
|
||||
{
|
||||
m_mac0 = a;
|
||||
|
||||
if( a > 0x7fffffff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 16 );
|
||||
}
|
||||
|
||||
if( a < -( (INT64)1 << 31 ) )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 15 );
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 Lm_G1( INT64 a )
|
||||
{
|
||||
if( a > 0x3ff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 14 );
|
||||
return 0x3ff;
|
||||
}
|
||||
|
||||
if( a < -0x400 )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 14 );
|
||||
return -0x400;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 Lm_G2( INT64 a )
|
||||
{
|
||||
if( a > 0x3ff )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 13 );
|
||||
return 0x3ff;
|
||||
}
|
||||
|
||||
if( a < -0x400 )
|
||||
{
|
||||
FLAG |= ( 1U << 31 ) | ( 1 << 13 );
|
||||
return -0x400;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
static INT32 Lm_H( INT64 value, int sf )
|
||||
{
|
||||
INT64 value_sf = gte_shift( value, sf );
|
||||
INT32 value_12 = (INT32)gte_shift( value, 1 );
|
||||
int max = 0x1000;
|
||||
int min = 0x0000;
|
||||
|
||||
if( value_sf < min || value_sf > max )
|
||||
{
|
||||
FLAG |= ( 1 << 12 );
|
||||
}
|
||||
|
||||
if( value_12 > max )
|
||||
{
|
||||
return max;
|
||||
}
|
||||
|
||||
if( value_12 < min )
|
||||
{
|
||||
return min;
|
||||
}
|
||||
|
||||
return value_12;
|
||||
}
|
||||
|
||||
static int gte_docop2( int gteop )
|
||||
{
|
||||
int v;
|
||||
int lm;
|
||||
int cv;
|
||||
int mx;
|
||||
INT32 h_over_sz3 = 0;
|
||||
|
||||
lm = GTE_LM( gteop );
|
||||
m_sf = GTE_SF( gteop );
|
||||
|
||||
FLAG = 0;
|
||||
|
||||
switch( GTE_FUNCT( gteop ) )
|
||||
{
|
||||
case 0x00: /* drop through to RTPS */
|
||||
case 0x01:
|
||||
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) TRX << 12 ), ( R11 * VX0 ) ), ( R12 * VY0 ) ), ( R13 * VZ0 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) TRY << 12 ), ( R21 * VX0 ) ), ( R22 * VY0 ) ), ( R23 * VZ0 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) TRZ << 12 ), ( R31 * VX0 ) ), ( R32 * VY0 ) ), ( R33 * VZ0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3_sf( m_mac3, m_sf, lm );
|
||||
SZ0 = SZ1;
|
||||
SZ1 = SZ2;
|
||||
SZ2 = SZ3;
|
||||
SZ3 = Lm_D( m_mac3, 1 );
|
||||
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
||||
SXY0 = SXY1;
|
||||
SXY1 = SXY2;
|
||||
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
||||
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
||||
MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
||||
IR0 = Lm_H( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x06:
|
||||
|
||||
MAC0 = F( (INT64) ( SX0 * SY1 ) + ( SX1 * SY2 ) + ( SX2 * SY0 ) - ( SX0 * SY2 ) - ( SX1 * SY0 ) - ( SX2 * SY1 ) );
|
||||
return 1;
|
||||
|
||||
case 0x0c:
|
||||
|
||||
MAC1 = A1( (INT64) ( R22 * IR3 ) - ( R33 * IR2 ) );
|
||||
MAC2 = A2( (INT64) ( R33 * IR1 ) - ( R11 * IR3 ) );
|
||||
MAC3 = A3( (INT64) ( R11 * IR2 ) - ( R22 * IR1 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
return 1;
|
||||
|
||||
case 0x10:
|
||||
|
||||
MAC1 = A1( ( R << 16 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( R << 16 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( G << 16 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( G << 16 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( B << 16 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( B << 16 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x11:
|
||||
|
||||
MAC1 = A1( ( IR1 << 12 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( IR1 << 12 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( IR2 << 12 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( IR2 << 12 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( IR3 << 12 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( IR3 << 12 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x12:
|
||||
|
||||
mx = GTE_MX( gteop );
|
||||
v = GTE_V( gteop );
|
||||
cv = GTE_CV( gteop );
|
||||
|
||||
switch( cv )
|
||||
{
|
||||
case 2:
|
||||
MAC1 = A1( (INT64) ( MX12( mx ) * VY( v ) ) + ( MX13( mx ) * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( MX22( mx ) * VY( v ) ) + ( MX23( mx ) * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( MX32( mx ) * VY( v ) ) + ( MX33( mx ) * VZ( v ) ) );
|
||||
Lm_B1( A1( ( (INT64) CV1( cv ) << 12 ) + ( MX11( mx ) * VX( v ) ) ), 0 );
|
||||
Lm_B2( A2( ( (INT64) CV2( cv ) << 12 ) + ( MX21( mx ) * VX( v ) ) ), 0 );
|
||||
Lm_B3( A3( ( (INT64) CV3( cv ) << 12 ) + ( MX31( mx ) * VX( v ) ) ), 0 );
|
||||
break;
|
||||
|
||||
default:
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) CV1( cv ) << 12 ), ( MX11( mx ) * VX( v ) ) ), ( MX12( mx ) * VY( v ) ) ), ( MX13( mx ) * VZ( v ) ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) CV2( cv ) << 12 ), ( MX21( mx ) * VX( v ) ) ), ( MX22( mx ) * VY( v ) ) ), ( MX23( mx ) * VZ( v ) ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) CV3( cv ) << 12 ), ( MX31( mx ) * VX( v ) ) ), ( MX32( mx ) * VY( v ) ) ), ( MX33( mx ) * VZ( v ) ) ) );
|
||||
break;
|
||||
}
|
||||
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
return 1;
|
||||
|
||||
case 0x13:
|
||||
|
||||
MAC1 = A1( (INT64) ( L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x14:
|
||||
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x16:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 0x1b:
|
||||
|
||||
MAC1 = A1( (INT64) ( L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( R << 4 ) * IR1 );
|
||||
MAC2 = A2( ( G << 4 ) * IR2 );
|
||||
MAC3 = A3( ( B << 4 ) * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x1c:
|
||||
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( ( (INT64) RBK ) << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( ( (INT64) GBK ) << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( ( (INT64) BBK ) << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( R << 4 ) * IR1 );
|
||||
MAC2 = A2( ( G << 4 ) * IR2 );
|
||||
MAC3 = A3( ( B << 4 ) * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x1e:
|
||||
|
||||
MAC1 = A1( (INT64) ( L11 * VX0 ) + ( L12 * VY0 ) + ( L13 * VZ0 ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX0 ) + ( L22 * VY0 ) + ( L23 * VZ0 ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX0 ) + ( L32 * VY0 ) + ( L33 * VZ0 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x20:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 0x28:
|
||||
|
||||
MAC1 = A1( IR1 * IR1 );
|
||||
MAC2 = A2( IR2 * IR2 );
|
||||
MAC3 = A3( IR3 * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
return 1;
|
||||
|
||||
case 0x1a: /* end of NCDT */
|
||||
case 0x29:
|
||||
|
||||
MAC1 = A1( ( ( R << 4 ) * IR1 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( ( R << 4 ) * IR1 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( ( G << 4 ) * IR2 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( ( G << 4 ) * IR2 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( ( B << 4 ) * IR3 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( ( B << 4 ) * IR3 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x2a:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( ( R0 << 16 ) + ( IR0 * Lm_B1( A1( ( (INT64) RFC << 12 ) - ( R0 << 16 ) ), 0 ) ) );
|
||||
MAC2 = A2( ( G0 << 16 ) + ( IR0 * Lm_B2( A2( ( (INT64) GFC << 12 ) - ( G0 << 16 ) ), 0 ) ) );
|
||||
MAC3 = A3( ( B0 << 16 ) + ( IR0 * Lm_B3( A3( ( (INT64) BFC << 12 ) - ( B0 << 16 ) ), 0 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
|
||||
case 0x2d:
|
||||
|
||||
MAC0 = F( (INT64) ( ZSF3 * SZ1 ) + ( ZSF3 * SZ2 ) + ( ZSF3 * SZ3 ) );
|
||||
OTZ = Lm_D( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x2e:
|
||||
|
||||
MAC0 = F( (INT64) ( ZSF4 * SZ0 ) + ( ZSF4 * SZ1 ) + ( ZSF4 * SZ2 ) + ( ZSF4 * SZ3 ) );
|
||||
OTZ = Lm_D( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x30:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) TRX << 12 ), ( R11 * VX( v ) ) ), ( R12 * VY( v ) ) ), ( R13 * VZ( v ) ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) TRY << 12 ), ( R21 * VX( v ) ) ), ( R22 * VY( v ) ) ), ( R23 * VZ( v ) ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) TRZ << 12 ), ( R31 * VX( v ) ) ), ( R32 * VY( v ) ) ), ( R33 * VZ( v ) ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3_sf( m_mac3, m_sf, lm );
|
||||
SZ0 = SZ1;
|
||||
SZ1 = SZ2;
|
||||
SZ2 = SZ3;
|
||||
SZ3 = Lm_D( m_mac3, 1 );
|
||||
h_over_sz3 = Lm_E( gte_divide( H, SZ3 ) );
|
||||
SXY0 = SXY1;
|
||||
SXY1 = SXY2;
|
||||
SX2 = Lm_G1( F( (INT64) OFX + ( (INT64) IR1 * h_over_sz3 ) ) >> 16 );
|
||||
SY2 = Lm_G2( F( (INT64) OFY + ( (INT64) IR2 * h_over_sz3 ) ) >> 16 );
|
||||
}
|
||||
|
||||
MAC0 = F( (INT64) DQB + ( (INT64) DQA * h_over_sz3 ) );
|
||||
IR0 = Lm_H( m_mac0, 1 );
|
||||
return 1;
|
||||
|
||||
case 0x3d:
|
||||
|
||||
MAC1 = A1( IR0 * IR1 );
|
||||
MAC2 = A2( IR0 * IR2 );
|
||||
MAC3 = A3( IR0 * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x3e:
|
||||
|
||||
MAC1 = A1( gte_shift( MAC1, -m_sf ) + ( IR0 * IR1 ) );
|
||||
MAC2 = A2( gte_shift( MAC2, -m_sf ) + ( IR0 * IR2 ) );
|
||||
MAC3 = A3( gte_shift( MAC3, -m_sf ) + ( IR0 * IR3 ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
return 1;
|
||||
|
||||
case 0x3f:
|
||||
|
||||
for( v = 0; v < 3; v++ )
|
||||
{
|
||||
MAC1 = A1( (INT64) ( L11 * VX( v ) ) + ( L12 * VY( v ) ) + ( L13 * VZ( v ) ) );
|
||||
MAC2 = A2( (INT64) ( L21 * VX( v ) ) + ( L22 * VY( v ) ) + ( L23 * VZ( v ) ) );
|
||||
MAC3 = A3( (INT64) ( L31 * VX( v ) ) + ( L32 * VY( v ) ) + ( L33 * VZ( v ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1i( i44_add( i44_add( i44_add( i44( (INT64) RBK << 12 ), ( LR1 * IR1 ) ), ( LR2 * IR2 ) ), ( LR3 * IR3 ) ) );
|
||||
MAC2 = A2i( i44_add( i44_add( i44_add( i44( (INT64) GBK << 12 ), ( LG1 * IR1 ) ), ( LG2 * IR2 ) ), ( LG3 * IR3 ) ) );
|
||||
MAC3 = A3i( i44_add( i44_add( i44_add( i44( (INT64) BBK << 12 ), ( LB1 * IR1 ) ), ( LB2 * IR2 ) ), ( LB3 * IR3 ) ) );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
MAC1 = A1( ( R << 4 ) * IR1 );
|
||||
MAC2 = A2( ( G << 4 ) * IR2 );
|
||||
MAC3 = A3( ( B << 4 ) * IR3 );
|
||||
IR1 = Lm_B1( MAC1, lm );
|
||||
IR2 = Lm_B2( MAC2, lm );
|
||||
IR3 = Lm_B3( MAC3, lm );
|
||||
RGB0 = RGB1;
|
||||
RGB1 = RGB2;
|
||||
CD2 = CODE;
|
||||
R2 = Lm_C1( MAC1 >> 4 );
|
||||
G2 = Lm_C2( MAC2 >> 4 );
|
||||
B2 = Lm_C3( MAC3 >> 4 );
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,588 @@
|
||||
/***************************************************************************
|
||||
|
||||
psxloop.c
|
||||
|
||||
Exact skip of the PSX CPU's wait loops (included by psx_cpu.c).
|
||||
|
||||
Within a timeslice nothing but the CPU itself changes main RAM or the
|
||||
CPU state: interrupts, timers, DMA and the other CPUs only act between
|
||||
timeslices. A loop that waits for an interrupt therefore repeats the
|
||||
same work until the timeslice ends, and the whole passes that still fit
|
||||
can be done at once: registers, memory and cycles end up exactly as if
|
||||
they had run (one cycle per instruction, as the interpreter counts),
|
||||
and the last pass runs normally. Three kinds of loops are recognised:
|
||||
|
||||
LOOP_PURE a short loop of loads and register arithmetic, no stores, no
|
||||
other branch, where no register is read before the pass
|
||||
writes it: every pass leaves the same state (for example
|
||||
"lhu v0,x(v1); nop; beqz v0,loop"). The recompiler has its
|
||||
own version of this one (jit_is_idle_loop).
|
||||
LOOP_COUNT "b<cond> r,self" with "addiu r,r,-1" in the delay slot: a
|
||||
plain countdown.
|
||||
LOOP_VSYNC the wait in the PsyQ libraries' VSync(): a timeout counter on
|
||||
the stack, decremented and stored every pass, and a RAM word
|
||||
compared with a target (used by most System 11/12 games).
|
||||
LOOP_RNG the VBLANK wait of Tekken 3 / Tekken Tag Tournament: every pass
|
||||
steps two random number generators in RAM (x = 5x + 1 and
|
||||
x = (x + 1) * 69069) while a flag in RAM stays 0.
|
||||
|
||||
The loop's code is checked word by word every time before a skip, so
|
||||
a changed program is never skipped by mistake. Main RAM and the BIOS
|
||||
must be fast RAM (psxcpu_add_fastram) for any of this to apply; loads
|
||||
from anything else (I/O, shared RAM) are never skipped over.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define LOOP_PURE 1
|
||||
#define LOOP_COUNT 2
|
||||
#define LOOP_VSYNC 3
|
||||
#define LOOP_RNG 4
|
||||
|
||||
/* build with -DPSX_LOOPSKIP=0 to compare against the plain interpreter */
|
||||
#ifndef PSX_LOOPSKIP
|
||||
#define PSX_LOOPSKIP 1
|
||||
#endif
|
||||
static int loopskip_enabled = PSX_LOOPSKIP;
|
||||
|
||||
/* a word of code or data in fast RAM, or 0 if it is not there */
|
||||
static int loop_word( UINT32 address, UINT32 *word )
|
||||
{
|
||||
struct psx_fastram *r = find_fastram( address, 4 );
|
||||
if( r == NULL || ( address & 3 ) != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*word = *(UINT32 *)&r->base[ address - r->start ];
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* host pointer of a writable RAM word away from translated code, or NULL */
|
||||
static UINT32 *loop_data( UINT32 address )
|
||||
{
|
||||
struct psx_fastram *r = find_fastram( address, 4 );
|
||||
UINT8 *host;
|
||||
if( r == NULL || r->readonly || ( address & 3 ) != 0 )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
host = &r->base[ address - r->start ];
|
||||
#if PSXJIT_SUPPORTED
|
||||
if( jit_code_present && jit_codemap[ jit_codemap_index( host ) ] )
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
return (UINT32 *)host;
|
||||
}
|
||||
|
||||
static UINT32 loop_branch_target( UINT32 op, UINT32 pc )
|
||||
{
|
||||
return pc + 4 + ( (INT32)(INT16)op << 2 );
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_PURE
|
||||
*************************************/
|
||||
|
||||
/* registers read and written by an allowed loop instruction; 0 if not allowed */
|
||||
static int loop_pure_op( UINT32 op, UINT32 *reads, UINT32 *writes, int *load )
|
||||
{
|
||||
UINT32 rs = INS_RS( op ), rt = INS_RT( op ), rd = INS_RD( op );
|
||||
|
||||
*reads = 0; *writes = 0; *load = 0;
|
||||
switch( INS_OP( op ) )
|
||||
{
|
||||
case 0x00: /* SPECIAL */
|
||||
switch( op & 63 )
|
||||
{
|
||||
case 0x00: case 0x02: case 0x03: /* SLL SRL SRA */
|
||||
*reads = 1 << rt; *writes = 1 << rd; return 1;
|
||||
case 0x04: case 0x06: case 0x07: /* SLLV SRLV SRAV */
|
||||
case 0x21: case 0x23: case 0x24: case 0x25: /* ADDU SUBU AND OR */
|
||||
case 0x26: case 0x27: case 0x2a: case 0x2b: /* XOR NOR SLT SLTU */
|
||||
*reads = ( 1 << rs ) | ( 1 << rt ); *writes = 1 << rd; return 1;
|
||||
}
|
||||
return 0;
|
||||
case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: /* ADDIU SLTI SLTIU ANDI ORI XORI */
|
||||
*reads = 1 << rs; *writes = 1 << rt; return 1;
|
||||
case 0x0f: /* LUI */
|
||||
*writes = 1 << rt; return 1;
|
||||
case 0x20: case 0x21: case 0x23: case 0x24: case 0x25: /* LB LH LW LBU LHU */
|
||||
*reads = 1 << rs; *writes = 1 << rt; *load = 1; return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* registers read by the closing branch, or -1 if 'op' is not a usable branch to 'target' */
|
||||
static int loop_pure_branch( UINT32 op, UINT32 pc, UINT32 target, UINT32 *reads )
|
||||
{
|
||||
UINT32 rs = INS_RS( op ), rt = INS_RT( op );
|
||||
switch( INS_OP( op ) )
|
||||
{
|
||||
case 0x01: /* BLTZ BGEZ */
|
||||
if( rt != 0x00 && rt != 0x01 ) return -1;
|
||||
*reads = 1 << rs;
|
||||
break;
|
||||
case 0x04: case 0x05: /* BEQ BNE */
|
||||
*reads = ( 1 << rs ) | ( 1 << rt );
|
||||
break;
|
||||
case 0x06: case 0x07: /* BLEZ BGTZ */
|
||||
if( rt != 0 ) return -1;
|
||||
*reads = 1 << rs;
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
return loop_branch_target( op, pc ) == target ? 0 : -1;
|
||||
}
|
||||
|
||||
/*
|
||||
The loop at 'l' as LOOP_PURE: the branch closing it in *branch, or 0.
|
||||
Same rules as the recompiler's jit_is_idle_loop, plus no instruction
|
||||
may use a register loaded by the one before it (the load delay would
|
||||
make it see the previous pass's value).
|
||||
*/
|
||||
static int loop_is_pure( UINT32 l, UINT32 *branch )
|
||||
{
|
||||
UINT32 ops[ 18 ], reads[ 18 ], writes[ 18 ], all = 0, written = 0, b;
|
||||
int load[ 18 ], n, i, found = -1;
|
||||
|
||||
for( n = 0; n < 16; n++ )
|
||||
{
|
||||
UINT32 r;
|
||||
if( !loop_word( l + n * 4, &ops[ n ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( loop_pure_branch( ops[ n ], l + n * 4, l, &r ) == 0 )
|
||||
{
|
||||
found = n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if( found < 0 || !loop_word( l + ( found + 1 ) * 4, &ops[ found + 1 ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
b = l + found * 4;
|
||||
for( i = 0; i <= found + 1; i++ )
|
||||
{
|
||||
if( i == found )
|
||||
{
|
||||
loop_pure_branch( ops[ i ], b, l, &reads[ i ] );
|
||||
writes[ i ] = 0;
|
||||
load[ i ] = 0;
|
||||
}
|
||||
else if( !loop_pure_op( ops[ i ], &reads[ i ], &writes[ i ], &load[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
all |= writes[ i ];
|
||||
}
|
||||
for( i = 0; i <= found + 1; i++ )
|
||||
{
|
||||
if( reads[ i ] & all & ~written & ~1 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( i > 0 && load[ i - 1 ] && ( reads[ i ] & writes[ i - 1 ] & ~1 ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
written |= writes[ i ];
|
||||
}
|
||||
/* the slot's load must not reach into the next pass */
|
||||
if( load[ found + 1 ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*branch = b;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_COUNT
|
||||
*************************************/
|
||||
|
||||
/* "b<cond> r,self" + "addiu r,r,-1": the register, or -1 */
|
||||
static int loop_is_count( UINT32 l )
|
||||
{
|
||||
UINT32 op, slot, r;
|
||||
if( !loop_word( l, &op ) || !loop_word( l + 4, &slot ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if( loop_branch_target( op, l ) != l )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
r = INS_RS( op );
|
||||
if( r == 0 || slot != ( 0x24000000 | ( r << 21 ) | ( r << 16 ) | 0xffff ) )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
if( ( INS_OP( op ) == 0x01 && INS_RT( op ) == 0x01 ) || /* BGEZ */
|
||||
( INS_OP( op ) == 0x07 && INS_RT( op ) == 0x00 ) || /* BGTZ */
|
||||
( INS_OP( op ) == 0x05 && INS_RT( op ) == 0x00 ) ) /* BNE r,zero */
|
||||
{
|
||||
return (int)r;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_VSYNC
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
L+0 lw v0,16(sp) X+0 lui v0,hi
|
||||
L+1 nop X+1 lw v0,lo(v0)
|
||||
L+2 addiu v0,v0,-1 X+2 nop
|
||||
L+3 sw v0,16(sp) X+3 slt v0,v0,a0
|
||||
L+4 lw v0,16(sp) X+4 bnez v0,L
|
||||
L+5 nop X+5 nop
|
||||
L+6 bne v0,v1,X
|
||||
L+7 nop
|
||||
One pass is 14 instructions; the RAM word at hi:lo is in *global.
|
||||
*/
|
||||
static int loop_is_vsync( UINT32 l, UINT32 *global )
|
||||
{
|
||||
static const UINT32 head[ 8 ] = { 0x8fa20010, 0, 0x2442ffff, 0xafa20010, 0x8fa20010, 0, 0, 0 };
|
||||
UINT32 w[ 8 ], x, lui, lw, i;
|
||||
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
if( !loop_word( l + i * 4, &w[ i ] ) || ( i != 6 && w[ i ] != head[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( ( w[ 6 ] & 0xffff0000 ) != 0x14430000 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
x = loop_branch_target( w[ 6 ], l + 24 );
|
||||
if( x <= l + 28 || x - l > 64 * 4 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if( !loop_word( x, &lui ) || ( lui & 0xffff0000 ) != 0x3c020000 ||
|
||||
!loop_word( x + 4, &lw ) || ( lw & 0xffff0000 ) != 0x8c420000 ||
|
||||
!loop_word( x + 8, &w[ 0 ] ) || w[ 0 ] != 0 ||
|
||||
!loop_word( x + 12, &w[ 1 ] ) || w[ 1 ] != 0x0044102a ||
|
||||
!loop_word( x + 16, &w[ 2 ] ) || ( w[ 2 ] & 0xffff0000 ) != 0x14400000 || loop_branch_target( w[ 2 ], x + 16 ) != l ||
|
||||
!loop_word( x + 20, &w[ 3 ] ) || w[ 3 ] != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
*global = ( ( lui & 0xffff ) << 16 ) + (INT32)(INT16)lw;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* LOOP_RNG
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
L+0 jal F F+0 lw v1,o1(gp)
|
||||
L+1 nop F+1 nop
|
||||
L+2 lui v1,h2 F+2 sll v0,v1,2
|
||||
L+3 lw v1,o2(v1) F+3 addu v0,v0,v1
|
||||
L+4 lw a0,o3(gp) F+4 addiu v0,v0,1
|
||||
L+5 addiu v1,v1,1 F+5 sw v0,o1(gp)
|
||||
L+6.. v0 = v1 * 69069 F+6 jr ra
|
||||
L+16 lui at,h2 F+7 nop
|
||||
L+17 sw v0,o2(at)
|
||||
L+18 beqz a0,L
|
||||
L+19 lui v0,slot
|
||||
One pass is 28 instructions.
|
||||
*/
|
||||
static const UINT32 loop_rng_mul[ 10 ] =
|
||||
{
|
||||
0x00031140, 0x00431021, 0x00021080, 0x00431023, 0x00021080,
|
||||
0x00431023, 0x00021080, 0x00431021, 0x00021940, 0x00431021
|
||||
};
|
||||
|
||||
struct loop_rng
|
||||
{
|
||||
UINT32 x1, x2, flag; /* addresses: generator 1 (5x + 1), generator 2, flag */
|
||||
UINT32 at, v0; /* the values left in at and v0 */
|
||||
};
|
||||
|
||||
static int loop_is_rng( UINT32 l, struct loop_rng *g )
|
||||
{
|
||||
UINT32 w[ 20 ], f[ 8 ], fa, i, gp = mipscpu.r[ 28 ];
|
||||
|
||||
for( i = 0; i < 20; i++ )
|
||||
{
|
||||
if( !loop_word( l + i * 4, &w[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( INS_OP( w[ 0 ] ) != 0x03 || w[ 1 ] != 0 ||
|
||||
( w[ 2 ] & 0xffff0000 ) != 0x3c030000 || ( w[ 3 ] & 0xffff0000 ) != 0x8c630000 ||
|
||||
( w[ 4 ] & 0xffff0000 ) != 0x8f840000 || w[ 5 ] != 0x24630001 ||
|
||||
( w[ 16 ] & 0xffff0000 ) != 0x3c010000 || ( w[ 16 ] & 0xffff ) != ( w[ 2 ] & 0xffff ) ||
|
||||
( w[ 17 ] & 0xffff0000 ) != 0xac220000 || ( w[ 17 ] & 0xffff ) != ( w[ 3 ] & 0xffff ) ||
|
||||
( w[ 18 ] & 0xffff0000 ) != 0x10800000 || loop_branch_target( w[ 18 ], l + 72 ) != l ||
|
||||
( w[ 19 ] & 0xffff0000 ) != 0x3c020000 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
for( i = 0; i < 10; i++ )
|
||||
{
|
||||
if( w[ 6 + i ] != loop_rng_mul[ i ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
fa = ( ( l + 4 ) & 0xf0000000 ) | ( ( w[ 0 ] & 0x03ffffff ) << 2 );
|
||||
for( i = 0; i < 8; i++ )
|
||||
{
|
||||
if( !loop_word( fa + i * 4, &f[ i ] ) )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if( ( f[ 0 ] & 0xffff0000 ) != 0x8f830000 || f[ 1 ] != 0 || f[ 2 ] != 0x00031080 || f[ 3 ] != 0x00431021 ||
|
||||
f[ 4 ] != 0x24420001 || ( f[ 5 ] & 0xffff0000 ) != 0xaf820000 || ( f[ 5 ] & 0xffff ) != ( f[ 0 ] & 0xffff ) ||
|
||||
f[ 6 ] != 0x03e00008 || f[ 7 ] != 0 )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
g->x1 = gp + (INT32)(INT16)f[ 0 ];
|
||||
g->x2 = ( ( w[ 2 ] & 0xffff ) << 16 ) + (INT32)(INT16)w[ 3 ];
|
||||
g->flag = gp + (INT32)(INT16)w[ 4 ];
|
||||
g->at = ( w[ 16 ] & 0xffff ) << 16;
|
||||
g->v0 = ( w[ 19 ] & 0xffff ) << 16;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Skipping
|
||||
*************************************/
|
||||
|
||||
/* whole passes of 'pass' cycles that fit, leaving between 1 and 'pass' cycles */
|
||||
static INLINE UINT32 loop_passes( UINT32 pass )
|
||||
{
|
||||
if( mips_ICount <= (int)pass )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return ( (UINT32)mips_ICount - 1 ) / pass;
|
||||
}
|
||||
|
||||
static int loop_state_ok( void )
|
||||
{
|
||||
return loopskip_enabled && mipscpu.delayr == 0 && ( mipscpu.cp0r[ CP0_SR ] & ( SR_ISC | SR_KUC ) ) == 0;
|
||||
}
|
||||
|
||||
/* LOOP_COUNT, LOOP_VSYNC and LOOP_RNG at 'l' (the start of a pass) */
|
||||
static void loop_skip_at( UINT32 l )
|
||||
{
|
||||
UINT32 n, global;
|
||||
int r;
|
||||
struct loop_rng g;
|
||||
|
||||
if( !loop_state_ok() )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( ( r = loop_is_count( l ) ) > 0 )
|
||||
{
|
||||
/* passes still taking the branch, counting the one starting now */
|
||||
UINT32 op = 0, v = mipscpu.r[ r ], left;
|
||||
loop_word( l, &op );
|
||||
if( INS_OP( op ) == 0x01 ) /* BGEZ: while v >= 0 */
|
||||
left = (INT32)v >= 0 ? v + 1 : 0;
|
||||
else /* BGTZ, BNE zero: while v > 0 */
|
||||
left = (INT32)v > 0 ? v : 0;
|
||||
n = loop_passes( 2 );
|
||||
if( left < 1 )
|
||||
return;
|
||||
if( n > left - 1 )
|
||||
n = left - 1;
|
||||
if( n == 0 )
|
||||
return;
|
||||
mipscpu.r[ r ] = v - n;
|
||||
mips_ICount -= n * 2;
|
||||
return;
|
||||
}
|
||||
|
||||
if( loop_is_vsync( l, &global ) )
|
||||
{
|
||||
UINT32 *counter = loop_data( mipscpu.r[ 29 ] + 16 ), value, until;
|
||||
if( counter == NULL || !loop_word( global, &value ) || global == mipscpu.r[ 29 ] + 16 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* the RAM word must keep the loop going */
|
||||
if( !( (INT32)value < (INT32)mipscpu.r[ 4 ] ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* passes before the counter reaches v1 (the timeout), that pass not included */
|
||||
until = *counter - mipscpu.r[ 3 ];
|
||||
n = loop_passes( 14 );
|
||||
if( until != 0 && n > until - 1 )
|
||||
{
|
||||
n = until - 1;
|
||||
}
|
||||
if( n == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
*counter -= n;
|
||||
mipscpu.r[ 2 ] = 1;
|
||||
mips_ICount -= n * 14;
|
||||
return;
|
||||
}
|
||||
|
||||
if( loop_is_rng( l, &g ) )
|
||||
{
|
||||
UINT32 *x1 = loop_data( g.x1 ), *x2 = loop_data( g.x2 ), flag, a, b, k, last = 0;
|
||||
if( x1 == NULL || x2 == NULL || !loop_word( g.flag, &flag ) || flag != 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
/* the three words must be distinct, so the stores leave the flag alone */
|
||||
if( g.x1 == g.x2 || g.flag == g.x1 || g.flag == g.x2 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
n = loop_passes( 28 );
|
||||
if( n == 0 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
a = *x1;
|
||||
b = *x2;
|
||||
for( k = 0; k < n; k++ )
|
||||
{
|
||||
a = a * 5 + 1;
|
||||
last = b;
|
||||
b = ( b + 1 ) * 69069;
|
||||
}
|
||||
*x1 = a;
|
||||
*x2 = b;
|
||||
mipscpu.r[ 1 ] = g.at;
|
||||
mipscpu.r[ 2 ] = g.v0;
|
||||
mipscpu.r[ 3 ] = last + 1;
|
||||
mipscpu.r[ 4 ] = 0;
|
||||
mipscpu.r[ 31 ] = l + 8;
|
||||
mips_ICount -= n * 28;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* the kind of loop starting at 'l', for the recompiler (LOOP_PURE is not reported) */
|
||||
static int loop_kind( UINT32 l )
|
||||
{
|
||||
UINT32 global;
|
||||
struct loop_rng g;
|
||||
if( !loopskip_enabled )
|
||||
{
|
||||
return LOOP_NONE;
|
||||
}
|
||||
if( loop_is_count( l ) > 0 )
|
||||
{
|
||||
return LOOP_COUNT;
|
||||
}
|
||||
if( loop_is_vsync( l, &global ) )
|
||||
{
|
||||
return LOOP_VSYNC;
|
||||
}
|
||||
if( loop_is_rng( l, &g ) )
|
||||
{
|
||||
return LOOP_RNG;
|
||||
}
|
||||
return LOOP_NONE;
|
||||
}
|
||||
|
||||
|
||||
/*************************************
|
||||
* Interpreter hook
|
||||
*************************************/
|
||||
|
||||
/*
|
||||
Called by the interpreter when the PC moves back to 'l' (a taken
|
||||
backward branch or jump) from the instruction at 'from'. LOOP_PURE
|
||||
needs one whole pass seen first: from the previous arrival at 'l' to
|
||||
the loop's own branch, touching nothing but fast RAM (psx_slow_access).
|
||||
*/
|
||||
#define LOOP_CACHE_SIZE 1024
|
||||
|
||||
static struct
|
||||
{
|
||||
UINT32 pc, op, branch;
|
||||
UINT8 kind;
|
||||
} loop_cache[ LOOP_CACHE_SIZE ];
|
||||
|
||||
static UINT32 loop_pure_pc;
|
||||
|
||||
static void loop_arrive( UINT32 l, UINT32 from )
|
||||
{
|
||||
UINT32 op, idx = ( l >> 2 ) & ( LOOP_CACHE_SIZE - 1 );
|
||||
int armed = loop_pure_armed && loop_pure_pc == l && !psx_slow_access;
|
||||
|
||||
loop_pure_armed = 0;
|
||||
if( !loop_word( l, &op ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
if( loop_cache[ idx ].pc != l || loop_cache[ idx ].op != op )
|
||||
{
|
||||
UINT32 branch;
|
||||
loop_cache[ idx ].pc = l;
|
||||
loop_cache[ idx ].op = op;
|
||||
loop_cache[ idx ].kind = loop_is_pure( l, &branch ) ? LOOP_PURE : LOOP_NONE;
|
||||
loop_cache[ idx ].branch = branch;
|
||||
if( loop_cache[ idx ].kind == LOOP_NONE )
|
||||
{
|
||||
/* the other kinds are told by their first words */
|
||||
UINT32 global;
|
||||
struct loop_rng g;
|
||||
if( loop_is_count( l ) > 0 || loop_is_vsync( l, &global ) || loop_is_rng( l, &g ) )
|
||||
{
|
||||
loop_cache[ idx ].kind = LOOP_COUNT; /* "one of the checked kinds" */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
switch( loop_cache[ idx ].kind )
|
||||
{
|
||||
case LOOP_PURE:
|
||||
{
|
||||
UINT32 branch;
|
||||
/* a whole pass ran since the last arrival: back here from the slot of the loop's own branch */
|
||||
if( armed && from == loop_cache[ idx ].branch + 4 && loop_state_ok() &&
|
||||
loop_is_pure( l, &branch ) && branch == loop_cache[ idx ].branch )
|
||||
{
|
||||
UINT32 pass = ( branch + 8 - l ) / 4;
|
||||
mips_ICount -= loop_passes( pass ) * pass;
|
||||
}
|
||||
loop_pure_pc = l;
|
||||
loop_pure_armed = 1;
|
||||
psx_slow_access = 0;
|
||||
}
|
||||
break;
|
||||
case LOOP_COUNT:
|
||||
loop_skip_at( l );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* recompiled code: the skip at a loop head inside a block */
|
||||
#if PSXJIT_SUPPORTED
|
||||
static void SLJIT_FUNC loop_skip_helper( sljit_u32 l )
|
||||
{
|
||||
loop_skip_at( l );
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,67 @@
|
||||
/***************************************************************************
|
||||
|
||||
mn10200.h : Panasonic MN10200 (MN1020012A) emulator
|
||||
|
||||
Backported to the MAME 0.78 CPU interface (mame2003-plus) from current
|
||||
MAME (Olivier Galibert, R. Belmont, hap). The on-chip peripherals
|
||||
(interrupt controller, 8-bit timers, ports) are at 0xfc00-0xffff and
|
||||
handled inside the core; the four ports go to the driver through the
|
||||
callbacks below.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _MN10200_H_
|
||||
#define _MN10200_H_
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum
|
||||
{
|
||||
MN10200_PC = 1,
|
||||
MN10200_PSW,
|
||||
MN10200_MDR,
|
||||
MN10200_D0,
|
||||
MN10200_D1,
|
||||
MN10200_D2,
|
||||
MN10200_D3,
|
||||
MN10200_A0,
|
||||
MN10200_A1,
|
||||
MN10200_A2,
|
||||
MN10200_A3,
|
||||
MN10200_NMICR,
|
||||
MN10200_IAGR
|
||||
};
|
||||
|
||||
/* external interrupt pins */
|
||||
enum
|
||||
{
|
||||
MN10200_IRQ0 = 0,
|
||||
MN10200_IRQ1,
|
||||
MN10200_IRQ2,
|
||||
MN10200_IRQ3,
|
||||
|
||||
MN10200_MAX_EXT_IRQ
|
||||
};
|
||||
|
||||
typedef data8_t (*mn10200_port_read_func)(int port);
|
||||
typedef void (*mn10200_port_write_func)(int port, data8_t data);
|
||||
|
||||
/* hook the ports 0-3 to the driver (call before reset; NULL: open bus) */
|
||||
void mn10200_set_port_handlers(mn10200_port_read_func readfn, mn10200_port_write_func writefn);
|
||||
|
||||
extern int mn10200_ICount;
|
||||
|
||||
void mn10200_init(void);
|
||||
void mn10200_reset(void *param);
|
||||
void mn10200_exit(void);
|
||||
int mn10200_execute(int cycles);
|
||||
unsigned mn10200_get_context(void *dst);
|
||||
void mn10200_set_context(void *src);
|
||||
unsigned mn10200_get_reg(int regnum);
|
||||
void mn10200_set_reg(int regnum, unsigned val);
|
||||
void mn10200_set_irq_line(int irqline, int state);
|
||||
void mn10200_set_irq_callback(int (*callback)(int irqline));
|
||||
const char *mn10200_info(void *context, int regnum);
|
||||
unsigned mn10200_dasm(char *buffer, unsigned pc);
|
||||
|
||||
#endif
|
||||
+54
-33
@@ -145,6 +145,8 @@ typedef struct
|
||||
int dma_timer_active[2];
|
||||
|
||||
int is_slave, cpu_number;
|
||||
data16_t (*opcode_read)(offs_t pc);
|
||||
data32_t (*dma_read_hook)(UINT32 src, UINT32 dst, data32_t data, int size);
|
||||
} SH2;
|
||||
|
||||
int sh2_icount;
|
||||
@@ -152,8 +154,8 @@ static SH2 sh2;
|
||||
|
||||
/* Atrocious hack that makes the soldivid music correct*/
|
||||
|
||||
/*static const int div_tab[4] = { 3, 5, 7, 0 };*/
|
||||
static const int div_tab[4] = { 3, 5, 3, 0 };
|
||||
/* FRT clock: internal clock / 8, / 32, / 128, external */
|
||||
static const int div_tab[4] = { 3, 5, 7, 0 };
|
||||
|
||||
enum {
|
||||
ICF = 0x00800000,
|
||||
@@ -1143,22 +1145,20 @@ static INLINE void MAC_L(UINT32 m, UINT32 n)
|
||||
}
|
||||
if (sh2.sr & S)
|
||||
{
|
||||
Res0 = sh2.macl + Res0;
|
||||
if (sh2.macl > Res0)
|
||||
Res2++;
|
||||
Res2 += (sh2.mach & 0x0000ffff);
|
||||
if (((INT32) Res2 < 0) && (Res2 < 0xffff8000))
|
||||
/* full 64-bit accumulate, saturated to the 48-bit range with the sign of the product (as MAME) */
|
||||
UINT64 sum = ((((UINT64)sh2.mach) << 32) | sh2.macl) + ((((UINT64)Res2) << 32) | Res0);
|
||||
UINT32 sum_hi = (UINT32)(sum >> 32);
|
||||
|
||||
/* outside 0xffff800000000000 .. 0x00007fffffffffff */
|
||||
if (sum_hi > 0x00007fff && sum_hi < 0xffff8000)
|
||||
{
|
||||
Res2 = 0x00008000;
|
||||
Res0 = 0x00000000;
|
||||
if (fnLmL < 0)
|
||||
sum = ((UINT64)0xffff8000) << 32;
|
||||
else
|
||||
sum = (((UINT64)0x00007fff) << 32) | 0xffffffff;
|
||||
}
|
||||
else if (((INT32) Res2 > 0) && (Res2 > 0x00007fff))
|
||||
{
|
||||
Res2 = 0x00007fff;
|
||||
Res0 = 0xffffffff;
|
||||
}
|
||||
sh2.mach = Res2;
|
||||
sh2.macl = Res0;
|
||||
sh2.mach = (UINT32)(sum >> 32);
|
||||
sh2.macl = (UINT32)sum;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1208,12 +1208,19 @@ static INLINE void MAC_W(UINT32 m, UINT32 n)
|
||||
if (sh2.sr & S)
|
||||
{
|
||||
if (ans == 1)
|
||||
{
|
||||
/* both addends with the same sign: the sign change is an overflow */
|
||||
if (src == 0)
|
||||
{
|
||||
if (src == 0)
|
||||
sh2.macl = 0x7fffffff;
|
||||
if (src == 2)
|
||||
sh2.macl = 0x80000000;
|
||||
sh2.macl = 0x7fffffff;
|
||||
sh2.mach |= 1;
|
||||
}
|
||||
else if (src == 2)
|
||||
{
|
||||
sh2.macl = 0x80000000;
|
||||
sh2.mach |= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2307,7 +2314,11 @@ void sh2_reset(void *param)
|
||||
memset(sh2.m, 0, 0x200);
|
||||
|
||||
if(conf)
|
||||
{
|
||||
sh2.is_slave = conf->is_slave;
|
||||
sh2.opcode_read = conf->opcode_read;
|
||||
sh2.dma_read_hook = conf->dma_read_hook;
|
||||
}
|
||||
else
|
||||
sh2.is_slave = 0;
|
||||
|
||||
@@ -2343,12 +2354,12 @@ int sh2_execute(int cycles)
|
||||
|
||||
if (sh2.delay)
|
||||
{
|
||||
opcode = RW(sh2.delay & AM);
|
||||
opcode = sh2.opcode_read ? sh2.opcode_read(sh2.delay) : RW(sh2.delay & AM);
|
||||
change_pc32bedw(sh2.pc & AM);
|
||||
sh2.pc -= 2;
|
||||
}
|
||||
else
|
||||
opcode = RW(sh2.pc & AM);
|
||||
opcode = sh2.opcode_read ? sh2.opcode_read(sh2.pc) : RW(sh2.pc & AM);
|
||||
|
||||
CALL_MAME_DEBUG;
|
||||
|
||||
@@ -2407,9 +2418,15 @@ static void sh2_timer_resync(void)
|
||||
int divider = div_tab[(sh2.m[5] >> 8) & 3];
|
||||
UINT32 cur_time = cpunum_gettotalcycles(sh2.cpu_number);
|
||||
|
||||
if(divider)
|
||||
sh2.frc += (cur_time - sh2.frc_base) >> divider;
|
||||
sh2.frc_base = cur_time;
|
||||
UINT32 add = (cur_time - sh2.frc_base) >> divider;
|
||||
|
||||
/* keep the cycles that don't make a whole count yet (as MAME) */
|
||||
if (add > 0)
|
||||
{
|
||||
if (divider)
|
||||
sh2.frc += add;
|
||||
sh2.frc_base = cur_time;
|
||||
}
|
||||
}
|
||||
|
||||
static void sh2_timer_activate(void)
|
||||
@@ -2536,6 +2553,10 @@ static void sh2_dmac_callback(int dma)
|
||||
cpuintrf_pop_context();
|
||||
}
|
||||
|
||||
/* a unit read by the internal DMA, through the optional hook */
|
||||
#define DMA_READ(src, dst, data, size) \
|
||||
(sh2.dma_read_hook ? sh2.dma_read_hook((src), (dst), (data), (size)) : (data))
|
||||
|
||||
static void sh2_dmac_check(int dma)
|
||||
{
|
||||
if(sh2.m[0x63+4*dma] & sh2.m[0x6c] & 1)
|
||||
@@ -2575,7 +2596,7 @@ static void sh2_dmac_check(int dma)
|
||||
src --;
|
||||
if(incd == 2)
|
||||
dst --;
|
||||
cpu_writemem32bedw(dst, cpu_readmem32bedw(src));
|
||||
cpu_writemem32bedw(dst, DMA_READ(src, dst, cpu_readmem32bedw(src), 0));
|
||||
if(incs == 1)
|
||||
src ++;
|
||||
if(incd == 1)
|
||||
@@ -2591,7 +2612,7 @@ static void sh2_dmac_check(int dma)
|
||||
src -= 2;
|
||||
if(incd == 2)
|
||||
dst -= 2;
|
||||
cpu_writemem32bedw_word(dst, cpu_readmem32bedw_word(src));
|
||||
cpu_writemem32bedw_word(dst, DMA_READ(src, dst, cpu_readmem32bedw_word(src), 1));
|
||||
if(incs == 1)
|
||||
src += 2;
|
||||
if(incd == 1)
|
||||
@@ -2607,7 +2628,7 @@ static void sh2_dmac_check(int dma)
|
||||
src -= 4;
|
||||
if(incd == 2)
|
||||
dst -= 4;
|
||||
cpu_writemem32bedw_dword(dst, cpu_readmem32bedw_dword(src));
|
||||
cpu_writemem32bedw_dword(dst, DMA_READ(src, dst, cpu_readmem32bedw_dword(src), 2));
|
||||
if(incs == 1)
|
||||
src += 4;
|
||||
if(incd == 1)
|
||||
@@ -2622,10 +2643,10 @@ static void sh2_dmac_check(int dma)
|
||||
{
|
||||
if(incd == 2)
|
||||
dst -= 16;
|
||||
cpu_writemem32bedw_dword(dst, cpu_readmem32bedw_dword(src));
|
||||
cpu_writemem32bedw_dword(dst+4, cpu_readmem32bedw_dword(src+4));
|
||||
cpu_writemem32bedw_dword(dst+8, cpu_readmem32bedw_dword(src+8));
|
||||
cpu_writemem32bedw_dword(dst+12, cpu_readmem32bedw_dword(src+12));
|
||||
cpu_writemem32bedw_dword(dst, DMA_READ(src, dst, cpu_readmem32bedw_dword(src), 2));
|
||||
cpu_writemem32bedw_dword(dst+4, DMA_READ(src+4, dst+4, cpu_readmem32bedw_dword(src+4), 2));
|
||||
cpu_writemem32bedw_dword(dst+8, DMA_READ(src+8, dst+8, cpu_readmem32bedw_dword(src+8), 2));
|
||||
cpu_writemem32bedw_dword(dst+12, DMA_READ(src+12, dst+12, cpu_readmem32bedw_dword(src+12), 2));
|
||||
src += 16;
|
||||
if(incd == 1)
|
||||
dst += 16;
|
||||
@@ -2739,7 +2760,7 @@ WRITE32_HANDLER( sh2_internal_w )
|
||||
{
|
||||
INT64 a = sh2.m[0x45] | ((UINT64)(sh2.m[0x44]) << 32);
|
||||
INT64 b = sh2.m[0x40];
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %lld/%lld\n", cpu_getactivecpu(), a, b);
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "SH2 #%d div+mod %08x%08x/%08x\n", cpu_getactivecpu(), sh2.m[0x44], sh2.m[0x45], sh2.m[0x40]);
|
||||
if (b)
|
||||
{
|
||||
INT64 q = a / b;
|
||||
|
||||
@@ -60,6 +60,13 @@ extern int sh2_icount; /* cycle count */
|
||||
struct sh2_config
|
||||
{
|
||||
int is_slave;
|
||||
/* optional: opcode fetch, for CPUs that decrypt opcodes (CPS-3);
|
||||
NULL fetches opcodes as data */
|
||||
data16_t (*opcode_read)(offs_t pc);
|
||||
/* optional: called for each unit an internal DMA transfer reads, can
|
||||
change the data (CPS-3: the DMA bypasses the decryption);
|
||||
size 0 byte, 1 word, 2 long */
|
||||
data32_t (*dma_read_hook)(UINT32 src, UINT32 dst, data32_t data, int size);
|
||||
};
|
||||
|
||||
extern void sh2_init(void);
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,98 @@
|
||||
/***************************************************************************
|
||||
|
||||
Analog Devices ADSP-21062 "SHARC", from current MAME
|
||||
(src/devices/cpu/sharc, copyright Ville Linde, BSD-3-Clause),
|
||||
translated to C for MAME 2003. Interpreter only (no recompiler).
|
||||
|
||||
The internal memory (two 32K x 32-bit blocks, with the 48-bit program
|
||||
and 16-bit short-word views) and the IOP registers live inside the
|
||||
core. External data memory (and external program memory, if any)
|
||||
is reached through driver callbacks in the config passed to the CPU
|
||||
with MDRV_CPU_CONFIG; the mame2003 memory system is not used.
|
||||
|
||||
Only one SHARC per machine is supported (the state is static).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SHARC_H
|
||||
#define SHARC_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
enum
|
||||
{
|
||||
SHARC_BOOT_MODE_EPROM = 0,
|
||||
SHARC_BOOT_MODE_HOST,
|
||||
SHARC_BOOT_MODE_LINK,
|
||||
SHARC_BOOT_MODE_NOBOOT
|
||||
};
|
||||
|
||||
/* interrupt lines for set_irq_line (IRQ0-2 pins) */
|
||||
enum
|
||||
{
|
||||
SHARC_IRQ0 = 0,
|
||||
SHARC_IRQ1 = 1,
|
||||
SHARC_IRQ2 = 2
|
||||
};
|
||||
|
||||
/* register numbers for get_reg / set_reg (also CPU_INFO_REG + n) */
|
||||
enum
|
||||
{
|
||||
SHARC_PC = 1, SHARC_PCSTK, SHARC_PCSTKP, SHARC_LSTKP, SHARC_FADDR, SHARC_DADDR,
|
||||
SHARC_MODE1, SHARC_MODE2, SHARC_ASTAT, SHARC_STKY, SHARC_IRPTL, SHARC_IMASK,
|
||||
SHARC_USTAT1, SHARC_USTAT2, SHARC_LCNTR, SHARC_CURLCNTR, SHARC_STSTKP,
|
||||
SHARC_R0,
|
||||
SHARC_R15 = SHARC_R0 + 15,
|
||||
SHARC_I0,
|
||||
SHARC_I15 = SHARC_I0 + 15
|
||||
};
|
||||
|
||||
struct sharc_config
|
||||
{
|
||||
int boot_mode; /* SHARC_BOOT_MODE_xxx (MAME default: HOST) */
|
||||
UINT32 (*data_r)(UINT32 address); /* external DM, 32-bit words, word address */
|
||||
void (*data_w)(UINT32 address, UINT32 data);
|
||||
void (*flag_out)(int flag, int state); /* FLAG0-3 outputs, may be NULL */
|
||||
/* optional, may be NULL (unmapped: reads 0): external program memory,
|
||||
48-bit words in the low bits, word address */
|
||||
UINT64 (*pgm_r)(UINT32 address);
|
||||
void (*pgm_w)(UINT32 address, UINT64 data);
|
||||
};
|
||||
|
||||
extern int sharc_icount;
|
||||
|
||||
/* CPU interface */
|
||||
extern void sharc_init(void);
|
||||
extern void sharc_reset(void *param);
|
||||
extern void sharc_exit(void);
|
||||
extern int sharc_execute(int cycles);
|
||||
extern unsigned sharc_get_context(void *dst);
|
||||
extern void sharc_set_context(void *src);
|
||||
extern unsigned sharc_get_reg(int regnum);
|
||||
extern void sharc_set_reg(int regnum, unsigned val);
|
||||
extern void sharc_set_irq_line(int irqline, int state);
|
||||
extern void sharc_set_irq_callback(int (*callback)(int irqline));
|
||||
extern const char *sharc_info(void *context, int regnum);
|
||||
extern unsigned sharc_dasm(char *buffer, unsigned pc);
|
||||
|
||||
/* helpers acting on the (single) SHARC; safe to call while another CPU
|
||||
is executing, e.g. from the host CPU's memory handlers */
|
||||
|
||||
/* MAME external_iop_write: host write to an IOP register */
|
||||
extern void sharc_external_iop_write(UINT32 address, UINT32 data);
|
||||
/* MAME external_dma_write: host write to the external port DMA buffer
|
||||
(host boot); with 16/48 packing, address % 3 selects the 16-bit piece */
|
||||
extern void sharc_external_dma_write(UINT32 address, UINT64 data);
|
||||
/* MAME set_flag_input: FLAG0-3 pins configured as inputs */
|
||||
extern void sharc_set_flag_input(int flag_num, int state);
|
||||
/* MAME write_stall: while asserted, the core does not execute */
|
||||
extern void sharc_write_stall(int state);
|
||||
|
||||
/* to be called from a data_r/data_w callback that cannot complete now
|
||||
(FIFO empty/full): the access must not be committed by the driver
|
||||
(the value returned by data_r is ignored); the core ends the
|
||||
timeslice and executes the same instruction again next time, with no
|
||||
side effects committed. A stalled DMA transfer cycle is retried. */
|
||||
extern void sharc_stall(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,335 @@
|
||||
/***************************************************************************
|
||||
|
||||
ADSP-21062 SHARC DMA operations, from current MAME
|
||||
(src/devices/cpu/sharc/sharcdma.hxx, copyright Ville Linde,
|
||||
BSD-3-Clause), translated to C for MAME 2003.
|
||||
Included from sharc.c, not compiled on its own.
|
||||
|
||||
Only the interpreter paths are translated: MAME uses the DMA timer
|
||||
(sharc_dma_callback) with the recompiler only; the interpreter
|
||||
transfers one DMA word per instruction (dma_run_cycle).
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#define DMA_PMODE_NO_PACKING 0
|
||||
#define DMA_PMODE_16_32 1
|
||||
#define DMA_PMODE_16_48 2
|
||||
#define DMA_PMODE_32_48 3
|
||||
#define DMA_PMODE_8_48 4
|
||||
|
||||
static void schedule_chained_dma_op(int channel, UINT32 dma_chain_ptr, int chained_direction)
|
||||
{
|
||||
UINT32 op_ptr = 0x20000 + (dma_chain_ptr & 0x1ffff);
|
||||
|
||||
UINT32 int_index = dm_read32(op_ptr - 0);
|
||||
UINT32 int_modifier = dm_read32(op_ptr - 1);
|
||||
UINT32 int_count = dm_read32(op_ptr - 2);
|
||||
UINT32 chain_ptr = dm_read32(op_ptr - 3);
|
||||
/*UINT32 gen_purpose = dm_read32(op_ptr - 4);*/
|
||||
UINT32 ext_index = dm_read32(op_ptr - 5);
|
||||
UINT32 ext_modifier = dm_read32(op_ptr - 6);
|
||||
UINT32 ext_count = dm_read32(op_ptr - 7);
|
||||
|
||||
if (m_core->dma_op[channel].active)
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: schedule_chained_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc);
|
||||
}
|
||||
|
||||
if (chained_direction) /* Transmit to external */
|
||||
{
|
||||
m_core->dma_op[channel].dst = ext_index;
|
||||
m_core->dma_op[channel].dst_modifier = (INT32)ext_modifier;
|
||||
m_core->dma_op[channel].dst_count = (INT32)ext_count;
|
||||
m_core->dma_op[channel].src = int_index;
|
||||
m_core->dma_op[channel].src_modifier = (INT32)int_modifier;
|
||||
m_core->dma_op[channel].src_count = (INT32)int_count;
|
||||
}
|
||||
else /* Receive from external */
|
||||
{
|
||||
m_core->dma_op[channel].src = ext_index;
|
||||
m_core->dma_op[channel].src_modifier = (INT32)ext_modifier;
|
||||
m_core->dma_op[channel].src_count = (INT32)ext_count;
|
||||
m_core->dma_op[channel].dst = int_index;
|
||||
m_core->dma_op[channel].dst_modifier = (INT32)int_modifier;
|
||||
m_core->dma_op[channel].dst_count = (INT32)int_count;
|
||||
}
|
||||
|
||||
m_core->dma_op[channel].pmode = 0;
|
||||
m_core->dma_op[channel].chain_ptr = chain_ptr;
|
||||
m_core->dma_op[channel].chained_direction = chained_direction;
|
||||
|
||||
m_core->dma_op[channel].chained = 1;
|
||||
m_core->dma_op[channel].active = 1;
|
||||
|
||||
/* enable busy flag */
|
||||
m_core->dma_status |= (1 << channel);
|
||||
}
|
||||
|
||||
static void schedule_dma_op(int channel, UINT32 src, UINT32 dst, int src_modifier, int dst_modifier, int src_count, int dst_count, int pmode)
|
||||
{
|
||||
if (m_core->dma_op[channel].active)
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: schedule_dma_op: DMA operation already scheduled at %08X!\n", m_core->pc);
|
||||
}
|
||||
|
||||
m_core->dma_op[channel].src = src;
|
||||
m_core->dma_op[channel].dst = dst;
|
||||
m_core->dma_op[channel].src_modifier = src_modifier;
|
||||
m_core->dma_op[channel].dst_modifier = dst_modifier;
|
||||
m_core->dma_op[channel].src_count = src_count;
|
||||
m_core->dma_op[channel].dst_count = dst_count;
|
||||
m_core->dma_op[channel].pmode = pmode;
|
||||
m_core->dma_op[channel].chain_ptr = 0;
|
||||
|
||||
m_core->dma_op[channel].chained = 0;
|
||||
m_core->dma_op[channel].active = 1;
|
||||
|
||||
/* enable busy flag */
|
||||
m_core->dma_status |= (1 << channel);
|
||||
}
|
||||
|
||||
/* one DMA transfer; returns 1 if a driver callback stalled it (port:
|
||||
nothing is committed then, and the same transfer is retried later) */
|
||||
static int dma_run_cycle(int channel)
|
||||
{
|
||||
if (m_core->dma_status & (1 << channel))
|
||||
{
|
||||
UINT32 src = m_core->dma_op[channel].src;
|
||||
UINT32 dst = m_core->dma_op[channel].dst;
|
||||
int src_modifier = m_core->dma_op[channel].src_modifier;
|
||||
int dst_modifier = m_core->dma_op[channel].dst_modifier;
|
||||
int src_count = m_core->dma_op[channel].src_count;
|
||||
int pmode = m_core->dma_op[channel].pmode;
|
||||
|
||||
m_core->stalled = 0;
|
||||
|
||||
switch (pmode)
|
||||
{
|
||||
case DMA_PMODE_NO_PACKING:
|
||||
{
|
||||
UINT32 data = dm_read32(src);
|
||||
if (m_core->stalled) break;
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier;
|
||||
dst += dst_modifier;
|
||||
src_count--;
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_16_32:
|
||||
{
|
||||
UINT32 data = (dm_read32(src + 0) & 0xffff) << 16;
|
||||
data |= dm_read32(src + 1) & 0xffff;
|
||||
if (m_core->stalled) break;
|
||||
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier * 2;
|
||||
dst += dst_modifier;
|
||||
src_count -= 2;
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_8_48:
|
||||
{
|
||||
UINT64 data = ((UINT64)(dm_read32(src + 0) & 0xff) << 0);
|
||||
data |= ((UINT64)(dm_read32(src + 1) & 0xff) << 8);
|
||||
data |= ((UINT64)(dm_read32(src + 2) & 0xff) << 16);
|
||||
data |= ((UINT64)(dm_read32(src + 3) & 0xff) << 24);
|
||||
data |= ((UINT64)(dm_read32(src + 4) & 0xff) << 32);
|
||||
data |= ((UINT64)(dm_read32(src + 5) & 0xff) << 40);
|
||||
if (m_core->stalled) break;
|
||||
|
||||
pm_write48(dst, data);
|
||||
src += src_modifier * 6;
|
||||
dst += dst_modifier;
|
||||
src_count -= 6;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
|
||||
/* drop the transfer instead of looping on it forever */
|
||||
src_count = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_core->stalled)
|
||||
{
|
||||
m_core->stalled = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
m_core->dma_op[channel].src_count = src_count;
|
||||
m_core->dma_op[channel].src = src;
|
||||
m_core->dma_op[channel].dst = dst;
|
||||
|
||||
if (src_count <= 0)
|
||||
{
|
||||
/* clear busy flag */
|
||||
m_core->dma_status &= ~(1 << channel);
|
||||
|
||||
m_core->dma_op[channel].active = 0;
|
||||
|
||||
/* raise interrupt if
|
||||
* non-chained DMA
|
||||
* chained-DMA with PCI set in the next chain pointer */
|
||||
if (!m_core->dma_op[channel].chained || (m_core->dma_op[channel].chained && (m_core->dma_op[channel].chain_ptr & 0x20000)))
|
||||
{
|
||||
m_core->irptl |= (1 << (channel + 10));
|
||||
|
||||
/* DMA interrupt */
|
||||
if (m_core->imask & (1 << (channel + 10)))
|
||||
{
|
||||
m_core->irq_pending |= 1 << (channel + 10);
|
||||
}
|
||||
}
|
||||
|
||||
/* schedule chained op if chaining */
|
||||
if ((m_core->dma_op[channel].chain_ptr & 0x1ffff) != 0)
|
||||
{
|
||||
schedule_chained_dma_op(channel, m_core->dma_op[channel].chain_ptr, m_core->dma_op[channel].chained_direction);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* whole transfer at once (used by the EPROM boot) */
|
||||
static void dma_op(int channel)
|
||||
{
|
||||
int i;
|
||||
UINT32 src = m_core->dma_op[channel].src;
|
||||
UINT32 dst = m_core->dma_op[channel].dst;
|
||||
int src_modifier = m_core->dma_op[channel].src_modifier;
|
||||
int dst_modifier = m_core->dma_op[channel].dst_modifier;
|
||||
int src_count = m_core->dma_op[channel].src_count;
|
||||
int pmode = m_core->dma_op[channel].pmode;
|
||||
|
||||
switch (pmode)
|
||||
{
|
||||
case DMA_PMODE_NO_PACKING:
|
||||
{
|
||||
for (i=0; i < src_count; i++)
|
||||
{
|
||||
UINT32 data = dm_read32(src);
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier;
|
||||
dst += dst_modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_16_32:
|
||||
{
|
||||
int length = src_count/2;
|
||||
for (i=0; i < length; i++)
|
||||
{
|
||||
UINT32 data = (dm_read32(src+0) & 0xffff) << 16;
|
||||
data |= dm_read32(src+1) & 0xffff;
|
||||
|
||||
dm_write32(dst, data);
|
||||
src += src_modifier * 2;
|
||||
dst += dst_modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DMA_PMODE_8_48:
|
||||
{
|
||||
int length = src_count/6;
|
||||
for (i=0; i < length; i++)
|
||||
{
|
||||
UINT64 data = ((UINT64)(dm_read32(src+0) & 0xff) << 0);
|
||||
data |= ((UINT64)(dm_read32(src+1) & 0xff) << 8);
|
||||
data |= ((UINT64)(dm_read32(src+2) & 0xff) << 16);
|
||||
data |= ((UINT64)(dm_read32(src+3) & 0xff) << 24);
|
||||
data |= ((UINT64)(dm_read32(src+4) & 0xff) << 32);
|
||||
data |= ((UINT64)(dm_read32(src+5) & 0xff) << 40);
|
||||
|
||||
pm_write48(dst, data);
|
||||
src += src_modifier * 6;
|
||||
dst += dst_modifier;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
/* MAME: fatal error */
|
||||
sharc_error("SHARC: dma_op: unimplemented packing mode %d\n", pmode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (channel == 6)
|
||||
{
|
||||
m_core->irptl |= (1 << (channel+10));
|
||||
|
||||
/* DMA interrupt */
|
||||
if (m_core->imask & (1 << (channel+10)))
|
||||
{
|
||||
m_core->irq_pending |= 1 << (channel+10);
|
||||
}
|
||||
}
|
||||
|
||||
/* clear busy flag */
|
||||
m_core->dma_status &= ~(1 << channel);
|
||||
|
||||
m_core->dma_op[channel].active = 0;
|
||||
}
|
||||
|
||||
static void sharc_dma_exec(int channel)
|
||||
{
|
||||
UINT32 src, dst;
|
||||
UINT32 src_count, dst_count;
|
||||
UINT32 src_modifier, dst_modifier;
|
||||
int chen, tran, dtype, pmode, ishake, intio;
|
||||
|
||||
chen = (m_core->dma[channel].control >> 1) & 0x1;
|
||||
tran = (m_core->dma[channel].control >> 2) & 0x1;
|
||||
dtype = (m_core->dma[channel].control >> 5) & 0x1;
|
||||
pmode = (m_core->dma[channel].control >> 6) & 0x3;
|
||||
ishake = (m_core->dma[channel].control >> 10) & 0x1;
|
||||
intio = (m_core->dma[channel].control >> 11) & 0x1;
|
||||
|
||||
/* MAME: fatal errors */
|
||||
if (ishake)
|
||||
sharc_error("SHARC: dma_exec: handshake not supported\n");
|
||||
if (intio)
|
||||
sharc_error("SHARC: dma_exec: single-word interrupt enable not supported\n");
|
||||
|
||||
|
||||
if (chen) /* Chained DMA */
|
||||
{
|
||||
UINT32 dma_chain_ptr = m_core->dma[channel].chain_ptr & 0x1ffff;
|
||||
|
||||
schedule_chained_dma_op(channel, dma_chain_ptr, tran);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tran) /* Transmit to external */
|
||||
{
|
||||
dst = m_core->dma[channel].ext_index;
|
||||
dst_modifier = m_core->dma[channel].ext_modifier;
|
||||
dst_count = m_core->dma[channel].ext_count;
|
||||
src = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
|
||||
src_modifier = m_core->dma[channel].int_modifier;
|
||||
src_count = m_core->dma[channel].int_count;
|
||||
}
|
||||
else /* Receive from external */
|
||||
{
|
||||
src = m_core->dma[channel].ext_index;
|
||||
src_modifier = m_core->dma[channel].ext_modifier;
|
||||
src_count = m_core->dma[channel].ext_count;
|
||||
dst = (m_core->dma[channel].int_index & 0x1ffff) | 0x20000;
|
||||
dst_modifier = m_core->dma[channel].int_modifier;
|
||||
dst_count = m_core->dma[channel].int_count;
|
||||
}
|
||||
|
||||
if (dtype)
|
||||
{
|
||||
pmode = DMA_PMODE_8_48;
|
||||
}
|
||||
|
||||
schedule_dma_op(channel, src, dst, (INT32)src_modifier, (INT32)dst_modifier, (INT32)src_count, (INT32)dst_count, pmode);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -617,7 +617,9 @@ static void mmfm_b(void) { MMFM(B,0x10); }
|
||||
COUNT_CYCLES(2); \
|
||||
{ \
|
||||
INT32 rd = R##DSTREG; \
|
||||
SET_N(R##REG(rd)^0x80000000); \
|
||||
/* only the 34020 sets N; on the 34010 MMTM leaves it */ \
|
||||
if (state.is_34020) \
|
||||
SET_N(R##REG(rd)^0x80000000); \
|
||||
for (i = 0; i < 16; i++) \
|
||||
{ \
|
||||
if (l & 0x8000) \
|
||||
|
||||
+52
-10
@@ -153,6 +153,13 @@ static UINT8 external_host_access;
|
||||
static void * dpyint_timer[MAX_CPU]; /* Display interrupt timer */
|
||||
static void * vsblnk_timer[MAX_CPU]; /* VBLANK start timer */
|
||||
|
||||
/* internal interrupts are delivered through TIME_NOW timers, which the */
|
||||
/* core does not save; remember the queued ones so a save state taken */
|
||||
/* while one is pending does not lose it */
|
||||
static UINT32 pending_internal[MAX_CPU];
|
||||
static int pending_generation[MAX_CPU];
|
||||
|
||||
|
||||
/* default configuration */
|
||||
static struct tms34010_config default_config =
|
||||
{
|
||||
@@ -843,6 +850,12 @@ void tms34010_init(void)
|
||||
vsblnk_timer[i] = timer_alloc(vsblnk_callback);
|
||||
}
|
||||
|
||||
/* allocate the shiftreg here rather than in reset, so the pointer */
|
||||
/* registered below is valid (a NULL entry zeroes the state size) */
|
||||
state.shiftreg = malloc(SHIFTREG_SIZE);
|
||||
if (state.shiftreg)
|
||||
memset(state.shiftreg, 0, SHIFTREG_SIZE);
|
||||
|
||||
cpunum = cpu_getactivecpu();
|
||||
state_save_register_UINT32("tms34010", cpunum, "OP", &state.op, 1);
|
||||
state_save_register_UINT32("tms34010", cpunum, "PC", &state.pc, 1);
|
||||
@@ -871,6 +884,9 @@ void tms34010_init(void)
|
||||
state_save_register_int("tms34010", cpunum, "gfxcycles", &state.gfxcycles);
|
||||
state_save_register_int("tms34010", cpunum, "luvcount", &state.last_update_vcount);
|
||||
state_save_register_int("tms34010", cpunum, "ICount", &tms34010_ICount);
|
||||
pending_internal[cpunum] = 0;
|
||||
pending_generation[cpunum] = 0;
|
||||
state_save_register_UINT32("tms34010", cpunum, "PENDINT", &pending_internal[cpunum], 1);
|
||||
state_save_register_func_presave(tms34010_state_presave);
|
||||
state_save_register_func_postload(tms34010_state_postload);
|
||||
}
|
||||
@@ -878,13 +894,13 @@ void tms34010_init(void)
|
||||
void tms34010_reset(void *param)
|
||||
{
|
||||
struct tms34010_config *config = param ? param : &default_config;
|
||||
UINT16 *shiftreg = state.shiftreg;
|
||||
|
||||
/* zap the state and copy in the config pointer */
|
||||
/* zap the state and copy in the config pointer; keep the shiftreg */
|
||||
/* allocated in init, it is registered for save states */
|
||||
memset(&state, 0, sizeof(state));
|
||||
state.config = config;
|
||||
|
||||
/* allocate the shiftreg */
|
||||
state.shiftreg = malloc(SHIFTREG_SIZE);
|
||||
state.shiftreg = shiftreg;
|
||||
|
||||
/* fetch the initial PC and reset the state */
|
||||
PC = RLONG(0xffffffe0) & 0xfffffff0;
|
||||
@@ -1198,10 +1214,23 @@ void tms34020_set_irq_callback(int (*callback)(int irqline))
|
||||
** Generate internal interrupt
|
||||
*#################################################################################################*/
|
||||
|
||||
static void internal_interrupt_callback(int param);
|
||||
|
||||
static void queue_internal_interrupt(int cpunum, int type)
|
||||
{
|
||||
pending_internal[cpunum] |= type;
|
||||
timer_set(TIME_NOW, cpunum | (type << 8) | ((pending_generation[cpunum] & 0x7f) << 24), internal_interrupt_callback);
|
||||
}
|
||||
|
||||
static void internal_interrupt_callback(int param)
|
||||
{
|
||||
int cpunum = param & 0xff;
|
||||
int type = param >> 8;
|
||||
int type = (param >> 8) & 0xffff;
|
||||
|
||||
/* ignore interrupts queued before a state load, they were re-queued */
|
||||
if (((param >> 24) & 0x7f) != (pending_generation[cpunum] & 0x7f))
|
||||
return;
|
||||
pending_internal[cpunum] &= ~type;
|
||||
|
||||
/* call through to the CPU to generate the int */
|
||||
cpuintrf_push_context(cpunum);
|
||||
@@ -1553,7 +1582,7 @@ static void dpyint_callback(int cpunum)
|
||||
|
||||
/* set the CPU's context and queue an interrupt */
|
||||
cpuintrf_push_context(cpunum);
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_DI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_DI);
|
||||
|
||||
/* allow a callback so we can update before they are likely to do nasty things */
|
||||
if (state.config->display_int_callback)
|
||||
@@ -1678,7 +1707,7 @@ WRITE16_HANDLER( tms34010_io_register_w )
|
||||
|
||||
/* NMI issued? */
|
||||
if (data & 0x0100)
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_NMI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_NMI);
|
||||
break;
|
||||
|
||||
case REG_HSTCTLL:
|
||||
@@ -1715,7 +1744,7 @@ WRITE16_HANDLER( tms34010_io_register_w )
|
||||
|
||||
/* input interrupt? (should really be state-based, but the functions don't exist!) */
|
||||
if (!(oldreg & 0x0008) && (newreg & 0x0008))
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_HI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_HI);
|
||||
else if ((oldreg & 0x0008) && !(newreg & 0x0008))
|
||||
IOREG(REG_INTPEND) &= ~TMS34010_HI;
|
||||
break;
|
||||
@@ -1845,7 +1874,7 @@ WRITE16_HANDLER( tms34020_io_register_w )
|
||||
|
||||
/* NMI issued? */
|
||||
if (data & 0x0100)
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_NMI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_NMI);
|
||||
break;
|
||||
|
||||
case REG020_HSTCTLL:
|
||||
@@ -1880,7 +1909,7 @@ WRITE16_HANDLER( tms34020_io_register_w )
|
||||
|
||||
/* input interrupt? (should really be state-based, but the functions don't exist!) */
|
||||
if (!(oldreg & 0x0008) && (newreg & 0x0008))
|
||||
timer_set(TIME_NOW, cpunum | (TMS34010_HI << 8), internal_interrupt_callback);
|
||||
queue_internal_interrupt(cpunum, TMS34010_HI);
|
||||
else if ((oldreg & 0x0008) && !(newreg & 0x0008))
|
||||
IOREG(REG020_INTPEND) &= ~TMS34010_HI;
|
||||
break;
|
||||
@@ -2150,6 +2179,19 @@ static void tms34010_state_postload(void)
|
||||
tms34010_io_register_w(REG_DPYINT,IOREG(REG_DPYINT),0);
|
||||
set_raster_op();
|
||||
set_pixel_function();
|
||||
|
||||
/* re-queue the internal interrupts that were pending at save time */
|
||||
{
|
||||
int cpunum = cpu_getactivecpu();
|
||||
UINT32 pending = pending_internal[cpunum];
|
||||
int bit;
|
||||
|
||||
pending_generation[cpunum]++;
|
||||
pending_internal[cpunum] = 0;
|
||||
for (bit = 0; bit < 16; bit++)
|
||||
if (pending & (1 << bit))
|
||||
queue_internal_interrupt(cpunum, 1 << bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,38 @@
|
||||
/***************************************************************************
|
||||
|
||||
TMS57002 "DASP" emulator
|
||||
|
||||
Backported to mame2003-plus from current MAME src/devices/cpu/tms57002
|
||||
(Olivier Galibert). Not a scheduled CPU here: it runs one sample period
|
||||
at a time from the sound stream of the board that has it, as in MAME
|
||||
where each stream sample syncs it.
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef TMS57002_H
|
||||
#define TMS57002_H
|
||||
|
||||
#include "osd_cpu.h"
|
||||
|
||||
void tms57002dsp_init( void );
|
||||
void tms57002dsp_reset( void );
|
||||
void tms57002dsp_state_register( void );
|
||||
|
||||
/* host port */
|
||||
UINT8 tms57002dsp_data_r( void );
|
||||
void tms57002dsp_data_w( UINT8 data );
|
||||
void tms57002dsp_pload_w( int state );
|
||||
void tms57002dsp_cload_w( int state );
|
||||
int tms57002dsp_empty_r( void );
|
||||
int tms57002dsp_fifo_count( void ); /* coefficient updates waiting */
|
||||
/* called with the "update FIFO empty" line when it changes */
|
||||
void tms57002dsp_set_empty_callback( void (*callback)( int state ) );
|
||||
|
||||
/*
|
||||
One sample period: the four inputs (16-bit samples), the four outputs
|
||||
of the previous period (16-bit), then the DSP runs its program for the
|
||||
next one (cycles: instruction clock / sample rate).
|
||||
*/
|
||||
void tms57002dsp_sample( const INT32 *in, INT32 *out, int cycles );
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large.
Load diff
@@ -360,6 +360,7 @@ static void base_init(const char *type)
|
||||
|
||||
v60.irq_cb = v60_default_irq_cb;
|
||||
v60.irq_line = CLEAR_LINE;
|
||||
v60_set_idle_loops(NULL, 0);
|
||||
v60.nmi_line = CLEAR_LINE;
|
||||
|
||||
state_save_register_UINT32(type, cpu, "reg", v60.reg, 68);
|
||||
@@ -410,6 +411,7 @@ void v60_reset(void *param)
|
||||
|
||||
void v60_exit(void)
|
||||
{
|
||||
v60_set_idle_loops(NULL, 0);
|
||||
}
|
||||
|
||||
static void v60_do_irq(int vector)
|
||||
@@ -485,9 +487,73 @@ void v60_set_irq_callback(int (*irq_cb)(int irqline))
|
||||
|
||||
/* Actual cycles/instruction is unknown*/
|
||||
|
||||
/*
|
||||
Idle loop fast-forward (opt-in, set by the driver with v60_set_idle_loops)
|
||||
|
||||
A game that waits for an interrupt by polling RAM spends most of its time
|
||||
in a loop like "[inc counter] / test mem / branch back". Only the CPU
|
||||
itself can change that RAM, and the interrupt line does not change while
|
||||
the CPU runs its slice. So once a whole iteration has run without an
|
||||
interrupt (the branch back came exactly one iteration of cycles after the
|
||||
previous one), every further iteration of the slice is the same: the
|
||||
counter goes up by one and 8 cycles are spent per instruction. This runs
|
||||
those iterations at once, leaving the last one and the end of the slice
|
||||
to the interpreter, so the CPU state, the counter and the cycle count are
|
||||
exactly what the instruction-by-instruction run gives.
|
||||
|
||||
The whole uninterrupted iteration is needed: an interrupt taken between
|
||||
the test and the branch returns to the branch with the flags of the old
|
||||
test, so a branch back alone does not prove that the loop goes on.
|
||||
*/
|
||||
|
||||
static const struct v60_idle_loop *v60_idle;
|
||||
static int v60_idle_count;
|
||||
static int v60_idle_armed; /* index + 1 of the loop seen at the last branch back in this slice */
|
||||
static int v60_idle_icount; /* v60_ICount at that branch back */
|
||||
|
||||
void v60_set_idle_loops(const struct v60_idle_loop *loops, int count)
|
||||
{
|
||||
v60_idle = loops;
|
||||
v60_idle_count = loops ? count : 0;
|
||||
v60_idle_armed = 0;
|
||||
}
|
||||
|
||||
static void v60_idle_fast_forward(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < v60_idle_count; i++)
|
||||
{
|
||||
const struct v60_idle_loop *l = &v60_idle[i];
|
||||
if (PC == l->start && PPC == l->branch)
|
||||
{
|
||||
int iteration = 8 * l->instructions;
|
||||
if (v60_idle_armed == i + 1 && v60_idle_icount - v60_ICount == iteration)
|
||||
{
|
||||
int k = v60_ICount / iteration - 1;
|
||||
if (k > 0)
|
||||
{
|
||||
v60_ICount -= k * iteration;
|
||||
switch (l->counter)
|
||||
{
|
||||
case V60_IDLE_COUNTER_REG: v60.reg[l->counter_addr] += k; break;
|
||||
case V60_IDLE_COUNTER_MEM8: MemWrite8(l->counter_addr, (UINT8)(MemRead8(l->counter_addr) + k)); break;
|
||||
case V60_IDLE_COUNTER_MEM16: MemWrite16(l->counter_addr, (UINT16)(MemRead16(l->counter_addr) + k)); break;
|
||||
case V60_IDLE_COUNTER_MEM32: MemWrite32(l->counter_addr, MemRead32(l->counter_addr) + k); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
v60_idle_armed = i + 1;
|
||||
v60_idle_icount = v60_ICount;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int v60_execute(int cycles)
|
||||
{
|
||||
v60_ICount = cycles;
|
||||
v60_idle_armed = 0;
|
||||
if(v60.irq_line != CLEAR_LINE)
|
||||
v60_try_irq();
|
||||
while(v60_ICount >= 0) {
|
||||
@@ -497,6 +563,8 @@ int v60_execute(int cycles)
|
||||
PC += OpCodeTable[OpRead8(PC)]();
|
||||
if(v60.irq_line != CLEAR_LINE)
|
||||
v60_try_irq();
|
||||
if(v60_idle_count)
|
||||
v60_idle_fast_forward();
|
||||
}
|
||||
|
||||
return cycles - v60_ICount;
|
||||
|
||||
@@ -112,4 +112,27 @@ const char *v70_info(void *context, int regnum);
|
||||
#define v70_set_reg v60_set_reg
|
||||
#define v70_set_irq_line v60_set_irq_line
|
||||
#define v70_set_irq_callback v60_set_irq_callback
|
||||
/* idle loop fast-forward: a loop of "instructions" instructions from "start"
|
||||
to the branch back at "branch", that only polls RAM and optionally counts
|
||||
its iterations in a register or in memory (see v60.c) */
|
||||
enum
|
||||
{
|
||||
V60_IDLE_COUNTER_NONE = 0,
|
||||
V60_IDLE_COUNTER_REG,
|
||||
V60_IDLE_COUNTER_MEM8,
|
||||
V60_IDLE_COUNTER_MEM16,
|
||||
V60_IDLE_COUNTER_MEM32
|
||||
};
|
||||
|
||||
struct v60_idle_loop
|
||||
{
|
||||
UINT32 start;
|
||||
UINT32 branch;
|
||||
int instructions;
|
||||
int counter;
|
||||
UINT32 counter_addr; /* register number or address */
|
||||
};
|
||||
|
||||
void v60_set_idle_loops(const struct v60_idle_loop *loops, int count);
|
||||
|
||||
#endif
|
||||
@@ -4117,6 +4117,8 @@ void z80_init(void)
|
||||
state_save_register_UINT8("z80", cpu, "int_state", Z80.int_state, 4);
|
||||
state_save_register_UINT8("z80", cpu, "nmi_state", &Z80.nmi_state, 1);
|
||||
state_save_register_UINT8("z80", cpu, "irq_state", &Z80.irq_state, 1);
|
||||
/* the cycles of an interrupt taken outside of z80_execute, counted at the next one */
|
||||
state_save_register_INT32("z80", cpu, "extra_cycles", (INT32 *)&Z80.extra_cycles, 1);
|
||||
/* daisy chain needs to be saved by z80ctc.c somehow */
|
||||
}
|
||||
|
||||
|
||||
+125
-3
@@ -163,11 +163,99 @@ struct cpuinfo
|
||||
|
||||
static struct cpuinfo cpu[MAX_CPU];
|
||||
|
||||
/* The lasting suspend reasons of each CPU (held in reset, halted or
|
||||
disabled), kept for save states. Without them a loaded save state keeps
|
||||
the suspend state of the board that loads it: a sound CPU that was held
|
||||
in reset at that moment is reset again when the game releases its reset
|
||||
line, and it restarts its program while the main CPU does not. The
|
||||
short-lived reasons (spin, trigger) are not kept: the loaded CPU simply
|
||||
runs until it waits again. */
|
||||
#define SUSPEND_LASTING_REASONS (SUSPEND_REASON_HALT | SUSPEND_REASON_RESET | SUSPEND_REASON_DISABLE)
|
||||
static INT32 saved_suspend[MAX_CPU];
|
||||
|
||||
/* Each CPU's local time (how far it ran past the timer system's time) and
|
||||
cycle count, kept with a save: without them a loaded CPU keeps the offset
|
||||
it had when the save was loaded, a few cycles off, and a game that polls
|
||||
another CPU drifts from the run it was saved from. */
|
||||
static double saved_localtime[MAX_CPU];
|
||||
static UINT32 saved_cycles[MAX_CPU * 2];
|
||||
|
||||
/* With the timer system in the save state (timer_state_loaded()), the
|
||||
rest of the scheduling is loaded exactly too: all the suspend reasons
|
||||
and the triggers they wait for, the interrupts left in the frame, the
|
||||
VBLANK countdowns and the frame number. The timers they depend on (spin,
|
||||
trigger time, VBLANK) are then the ones of the save. */
|
||||
#define EXACT_PER_CPU 7
|
||||
static INT32 saved_exact[MAX_CPU * EXACT_PER_CPU];
|
||||
static INT32 saved_exact_globals[3];
|
||||
static int vblank;
|
||||
static int current_frame;
|
||||
static int vblank_countdown;
|
||||
|
||||
static void cpu_suspend_presave(void)
|
||||
{
|
||||
int cpunum;
|
||||
|
||||
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
|
||||
{
|
||||
INT32 *e = &saved_exact[cpunum * EXACT_PER_CPU];
|
||||
e[0] = cpu[cpunum].suspend;
|
||||
e[1] = cpu[cpunum].nextsuspend;
|
||||
e[2] = cpu[cpunum].eatcycles;
|
||||
e[3] = cpu[cpunum].nexteatcycles;
|
||||
e[4] = cpu[cpunum].trigger;
|
||||
e[5] = cpu[cpunum].iloops;
|
||||
e[6] = cpu[cpunum].vblankint_countdown;
|
||||
}
|
||||
saved_exact_globals[0] = vblank;
|
||||
saved_exact_globals[1] = current_frame;
|
||||
saved_exact_globals[2] = vblank_countdown;
|
||||
|
||||
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
|
||||
{
|
||||
saved_suspend[cpunum] = cpu[cpunum].nextsuspend & SUSPEND_LASTING_REASONS;
|
||||
saved_localtime[cpunum] = cpu[cpunum].localtime;
|
||||
saved_cycles[cpunum * 2] = (UINT32)cpu[cpunum].totalcycles;
|
||||
saved_cycles[cpunum * 2 + 1] = (UINT32)(cpu[cpunum].totalcycles >> 32);
|
||||
}
|
||||
}
|
||||
|
||||
static void cpu_suspend_postload(void)
|
||||
{
|
||||
int cpunum;
|
||||
|
||||
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
|
||||
{
|
||||
cpu[cpunum].suspend = cpu[cpunum].nextsuspend = saved_suspend[cpunum] & SUSPEND_LASTING_REASONS;
|
||||
if (saved_suspend[cpunum])
|
||||
cpu[cpunum].eatcycles = cpu[cpunum].nexteatcycles = 1;
|
||||
cpu[cpunum].localtime = saved_localtime[cpunum];
|
||||
cpu[cpunum].totalcycles = ((UINT64)saved_cycles[cpunum * 2 + 1] << 32) | saved_cycles[cpunum * 2];
|
||||
|
||||
if (timer_state_loaded())
|
||||
{
|
||||
INT32 *e = &saved_exact[cpunum * EXACT_PER_CPU];
|
||||
cpu[cpunum].suspend = e[0];
|
||||
cpu[cpunum].nextsuspend = e[1];
|
||||
cpu[cpunum].eatcycles = e[2];
|
||||
cpu[cpunum].nexteatcycles = e[3];
|
||||
cpu[cpunum].trigger = e[4];
|
||||
cpu[cpunum].iloops = e[5];
|
||||
cpu[cpunum].vblankint_countdown = e[6];
|
||||
}
|
||||
}
|
||||
|
||||
if (timer_state_loaded())
|
||||
{
|
||||
vblank = saved_exact_globals[0];
|
||||
current_frame = saved_exact_globals[1];
|
||||
vblank_countdown = saved_exact_globals[2];
|
||||
}
|
||||
}
|
||||
|
||||
static int time_to_reset;
|
||||
static int time_to_quit;
|
||||
|
||||
static int vblank;
|
||||
static int current_frame;
|
||||
static INT32 watchdog_counter;
|
||||
|
||||
static int cycles_running;
|
||||
@@ -182,7 +270,6 @@ static int cycles_stolen;
|
||||
*************************************/
|
||||
|
||||
static void *vblank_timer;
|
||||
static int vblank_countdown;
|
||||
static int vblank_multiplier;
|
||||
static double vblank_period;
|
||||
|
||||
@@ -269,11 +356,22 @@ int cpu_init(void)
|
||||
/* save some stuff in tag 0 */
|
||||
state_save_set_current_tag(0);
|
||||
state_save_register_INT32("cpu", 0, "watchdog count", &watchdog_counter, 1);
|
||||
state_save_register_INT32("cpu", 0, "suspend", saved_suspend, cpu_gettotalcpu());
|
||||
state_save_register_double("cpu", 0, "localtime", saved_localtime, cpu_gettotalcpu());
|
||||
state_save_register_UINT32("cpu", 0, "totalcycles", saved_cycles, cpu_gettotalcpu() * 2);
|
||||
state_save_register_INT32("cpu", 0, "exact", saved_exact, cpu_gettotalcpu() * EXACT_PER_CPU);
|
||||
state_save_register_INT32("cpu", 0, "exact globals", saved_exact_globals, 3);
|
||||
state_save_register_func_presave(cpu_suspend_presave);
|
||||
state_save_register_func_postload(cpu_suspend_postload);
|
||||
|
||||
/* reset the IRQ lines and save those */
|
||||
if (cpuint_init())
|
||||
return 1;
|
||||
|
||||
/* the timer system, in the save states: registered after the CPU and
|
||||
interrupt state, so its postload runs before theirs */
|
||||
timer_save_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -797,6 +895,30 @@ int cpunum_is_suspended(int cpunum, int reason)
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Trigger suspension helpers for
|
||||
* save states
|
||||
*
|
||||
*************************************/
|
||||
|
||||
int cpunum_get_suspend_trigger(int cpunum)
|
||||
{
|
||||
VERIFY_CPUNUM(0, cpunum_get_suspend_trigger);
|
||||
if (!(cpu[cpunum].nextsuspend & SUSPEND_REASON_TRIGGER))
|
||||
return 0;
|
||||
return cpu[cpunum].trigger;
|
||||
}
|
||||
|
||||
void cpunum_suspend_until_trigger(int cpunum, int trigger, int eatcycles)
|
||||
{
|
||||
VERIFY_CPUNUM_VOID(cpunum_suspend_until_trigger);
|
||||
cpunum_suspend(cpunum, SUSPEND_REASON_TRIGGER, eatcycles);
|
||||
cpu[cpunum].trigger = trigger;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
*
|
||||
* Returns the current scaling factor
|
||||
|
||||
@@ -162,6 +162,11 @@ void cpunum_resume(int cpunum, int reason);
|
||||
/* Returns true if the given CPU is suspended for any of the given reasons */
|
||||
int cpunum_is_suspended(int cpunum, int reason);
|
||||
|
||||
/* Trigger a CPU is waiting for (0 if none), and suspend a CPU until a
|
||||
trigger; used by drivers to keep a trigger wait across save states */
|
||||
int cpunum_get_suspend_trigger(int cpunum);
|
||||
void cpunum_suspend_until_trigger(int cpunum, int trigger, int eatcycles);
|
||||
|
||||
/* Aborts the timeslice for the active CPU */
|
||||
void activecpu_abort_timeslice(void);
|
||||
|
||||
|
||||
@@ -62,6 +62,28 @@ static INT32 irq_line_vector[MAX_CPU][MAX_IRQ_LINES];
|
||||
static INT32 irq_event_queue[MAX_CPU][MAX_IRQ_EVENTS];
|
||||
static int irq_event_index[MAX_CPU];
|
||||
|
||||
static void cpu_empty_event_queue(int cpunum);
|
||||
|
||||
/* A save made at the end of a frame finds the VBLANK interrupt still in the
|
||||
queue (it is emptied by a timer at the same time, which runs in the next
|
||||
frame). The queue is saved with the game, and a load sets that timer again,
|
||||
or the CPU misses that interrupt: a game that does its work every other
|
||||
frame then runs one frame late after loading. */
|
||||
static void cpuint_postload(void)
|
||||
{
|
||||
int cpunum;
|
||||
|
||||
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
|
||||
{
|
||||
if (irq_event_index[cpunum] > MAX_IRQ_EVENTS)
|
||||
irq_event_index[cpunum] = MAX_IRQ_EVENTS;
|
||||
/* the timer that empties the queue is in the state, when the
|
||||
timers are */
|
||||
if (irq_event_index[cpunum] > 0 && !timer_state_loaded())
|
||||
timer_set(TIME_NOW, cpunum, cpu_empty_event_queue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*************************************
|
||||
@@ -131,6 +153,10 @@ int cpuint_init(void)
|
||||
state_save_register_INT32("cpu", 0, "irq vector", &interrupt_vector[0][0],cpu_gettotalcpu() * MAX_IRQ_LINES);
|
||||
state_save_register_UINT8("cpu", 0, "irqline state", &irq_line_state[0][0], cpu_gettotalcpu() * MAX_IRQ_LINES);
|
||||
state_save_register_INT32("cpu", 0, "irqline vector", &irq_line_vector[0][0], cpu_gettotalcpu() * MAX_IRQ_LINES);
|
||||
state_save_register_INT32("cpu", 0, "irq event queue", &irq_event_queue[0][0], cpu_gettotalcpu() * MAX_IRQ_EVENTS);
|
||||
for (cpunum = 0; cpunum < cpu_gettotalcpu(); cpunum++)
|
||||
state_save_register_int("cpu", cpunum, "irq events", &irq_event_index[cpunum]);
|
||||
state_save_register_func_postload(cpuint_postload);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+96
-1
@@ -76,6 +76,9 @@
|
||||
#if (HAS_I8X41)
|
||||
#include "cpu/i8x41/i8x41.h"
|
||||
#endif
|
||||
#if (HAS_I8051)
|
||||
#include "cpu/i8051/i8051.h"
|
||||
#endif
|
||||
#if (HAS_M6800 || HAS_M6801 || HAS_M6802 || HAS_M6803 || HAS_M6808 || HAS_HD63701)
|
||||
#include "cpu/m6800/m6800.h"
|
||||
#endif
|
||||
@@ -118,18 +121,42 @@
|
||||
#if (HAS_TMS32025)
|
||||
#include "cpu/tms32025/tms32025.h"
|
||||
#endif
|
||||
#if (HAS_I960)
|
||||
#include "cpu/i960/i960.h"
|
||||
#endif
|
||||
#if (HAS_MB86233)
|
||||
#include "cpu/mb86233/mb86233.h"
|
||||
#endif
|
||||
#if (HAS_MB86235)
|
||||
#include "cpu/mb86235/mb86235.h"
|
||||
#endif
|
||||
#if (HAS_ADSP21062)
|
||||
#include "cpu/sharc/sharc.h"
|
||||
#endif
|
||||
#if (HAS_TMS32031)
|
||||
#include "cpu/tms32031/tms32031.h"
|
||||
#endif
|
||||
#if (HAS_CCPU)
|
||||
#include "cpu/ccpu/ccpu.h"
|
||||
#endif
|
||||
#if (HAS_ADSP2100 || HAS_ADSP2101 || HAS_ADSP2104 || HAS_ADSP2105 || HAS_ADSP2115)
|
||||
#if (HAS_ADSP2100 || HAS_ADSP2101 || HAS_ADSP2104 || HAS_ADSP2105 || HAS_ADSP2115 || HAS_ADSP2181)
|
||||
#include "cpu/adsp2100/adsp2100.h"
|
||||
#endif
|
||||
#if (HAS_PSXCPU)
|
||||
#include "cpu/mips/psx.h"
|
||||
#endif
|
||||
#if (HAS_MN10200)
|
||||
#include "cpu/mn10200/mn10200.h"
|
||||
#endif
|
||||
#if (HAS_H83002)
|
||||
#include "cpu/h83002/h83002.h"
|
||||
#endif
|
||||
#if (HAS_I386)
|
||||
#include "cpu/i386/i386.h"
|
||||
#endif
|
||||
#if (HAS_M37702)
|
||||
#include "cpu/m37710/m37710.h"
|
||||
#endif
|
||||
#if (HAS_ASAP)
|
||||
#include "cpu/asap/asap.h"
|
||||
#endif
|
||||
@@ -148,6 +175,9 @@
|
||||
#if (HAS_ARM)
|
||||
#include "cpu/arm/arm.h"
|
||||
#endif
|
||||
#if (HAS_ARM7)
|
||||
#include "cpu/arm7/arm7.h"
|
||||
#endif
|
||||
#if (HAS_SH2)
|
||||
#include "cpu/sh2/sh2.h"
|
||||
#endif
|
||||
@@ -429,6 +459,9 @@ const struct cpu_interface cpuintrf[] =
|
||||
#if (HAS_I8X41)
|
||||
CPU0(I8X41, i8x41, 1, 0,1.00, 8, 16, 0,16,LE,1, 2 ),
|
||||
#endif
|
||||
#if (HAS_I8051)
|
||||
CPU0(I8051, i8051, 5, 0,1.00, 8, 16, 0,16,LE,1, 3 ),
|
||||
#endif
|
||||
#if (HAS_M6800)
|
||||
CPU0(M6800, m6800, 1, 0,1.00, 8, 16, 0,16,BE,1, 4 ),
|
||||
#endif
|
||||
@@ -553,9 +586,26 @@ const struct cpu_interface cpuintrf[] =
|
||||
#if (HAS_ADSP2115)
|
||||
CPU3(ADSP2115, adsp2115, 4, 0,1.00,16,17lew, -1,15,LE,2, 4 ),
|
||||
#endif
|
||||
#if (HAS_ADSP2181)
|
||||
CPU3(ADSP2181, adsp2181, 10, 0,1.00,16,17lew, -1,15,LE,2, 4 ),
|
||||
#endif
|
||||
#if (HAS_PSXCPU)
|
||||
CPU0(PSXCPU, mips, 1, 0,1.00,32,32ledw, 0,32,LE,4, 4 ),
|
||||
#endif
|
||||
#if (HAS_H83002)
|
||||
CPU0(H83002, h8_3002, 8, 0,1.00,16,24bew, 0,24,BE,2,10 ),
|
||||
#endif
|
||||
#if (HAS_I386)
|
||||
CPU0(I386, i386, 1, 0,1.00,32,32ledw, 0,32,LE,1,15 ),
|
||||
#endif
|
||||
#if (HAS_MN10200)
|
||||
CPU0(MN10200, mn10200, 4, 0,1.00,16,24lew, 0,24,LE,1, 6 ),
|
||||
#endif
|
||||
#if (HAS_M37702)
|
||||
/* 16 cpuint lines: the maskable ones (M37710_LINE_ADC..IRQ0); the
|
||||
non-maskable and timer tick lines are raised by the core itself */
|
||||
CPU0(M37702, m37702, 16, 0,1.00,16,24lew, 0,24,LE,1, 6 ),
|
||||
#endif
|
||||
#if (HAS_ASAP)
|
||||
#define asap_ICount asap_icount
|
||||
CPU0(ASAP, asap, 1, 0,1.00,32,32ledw, 0,32,LE,4, 12 ),
|
||||
@@ -595,6 +645,9 @@ const struct cpu_interface cpuintrf[] =
|
||||
#if (HAS_ARM)
|
||||
CPU0(ARM, arm, 2, 0,1.00,32,26ledw, 0,26,LE,4, 4 ),
|
||||
#endif
|
||||
#if (HAS_ARM7)
|
||||
CPU0(ARM7, arm7, 5, 0,1.00,32,32ledw, 0,32,LE,2, 4 ),
|
||||
#endif
|
||||
#if (HAS_SH2)
|
||||
CPU4(SH2, sh2, 16, 0,1.00,32,32bedw, 0,32,BE,2, 2 ),
|
||||
#endif
|
||||
@@ -626,6 +679,22 @@ const struct cpu_interface cpuintrf[] =
|
||||
#if (HAS_E132XS)
|
||||
CPU0(E132XS, e132xs, 1,0,1.00, 32, 32bedw, 0,32,BE,2, 6 ),
|
||||
#endif
|
||||
#if (HAS_I960)
|
||||
#define i960_ICount i960_icount
|
||||
CPU0(I960, i960, 4, 0,1.00,32,32ledw, 0,32,LE,4,12 ),
|
||||
#endif
|
||||
#if (HAS_MB86233)
|
||||
#define mb86233_ICount mb86233_icount
|
||||
CPU0(MB86233, mb86233, 0, 0,1.00,32,32ledw, 0,32,LE,4, 4 ),
|
||||
#endif
|
||||
#if (HAS_MB86235)
|
||||
#define mb86235_ICount mb86235_icount
|
||||
CPU0(MB86235, mb86235, 0, 0,1.00,32,32ledw, 0,32,LE,8, 8 ),
|
||||
#endif
|
||||
#if (HAS_ADSP21062)
|
||||
#define sharc_ICount sharc_icount
|
||||
CPU0(ADSP21062, sharc, 3, 0,1.00,32,32ledw, 0,32,LE,4, 8 ),
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -1169,6 +1238,32 @@ void cpunum_write_byte(int cpunum, offs_t address, data8_t data)
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Read/write a run of bytes
|
||||
(as cpunum_read_byte/
|
||||
cpunum_write_byte on each,
|
||||
one context switch)
|
||||
--------------------------*/
|
||||
|
||||
void cpunum_read_bytes(int cpunum, offs_t address, UINT8 *data, UINT32 count)
|
||||
{
|
||||
VERIFY_CPUNUM_VOID(cpunum_read_bytes);
|
||||
cpuintrf_push_context(cpunum);
|
||||
while (count--)
|
||||
*data++ = (*cpu[cpunum].intf.memory_read)(address++);
|
||||
cpuintrf_pop_context();
|
||||
}
|
||||
|
||||
void cpunum_write_bytes(int cpunum, offs_t address, const UINT8 *data, UINT32 count)
|
||||
{
|
||||
VERIFY_CPUNUM_VOID(cpunum_write_bytes);
|
||||
cpuintrf_push_context(cpunum);
|
||||
while (count--)
|
||||
(*cpu[cpunum].intf.memory_write)(address++, *data++);
|
||||
cpuintrf_pop_context();
|
||||
}
|
||||
|
||||
|
||||
/*--------------------------
|
||||
Get context pointer
|
||||
--------------------------*/
|
||||
|
||||
@@ -127,6 +127,9 @@ enum
|
||||
#if (HAS_I8X41)
|
||||
CPU_I8X41,
|
||||
#endif
|
||||
#if (HAS_I8051)
|
||||
CPU_I8051,
|
||||
#endif
|
||||
#if (HAS_M6800)
|
||||
CPU_M6800,
|
||||
#endif
|
||||
@@ -250,9 +253,24 @@ enum
|
||||
#if (HAS_ADSP2115)
|
||||
CPU_ADSP2115,
|
||||
#endif
|
||||
#if (HAS_ADSP2181)
|
||||
CPU_ADSP2181,
|
||||
#endif
|
||||
#if (HAS_PSXCPU)
|
||||
CPU_PSXCPU,
|
||||
#endif
|
||||
#if (HAS_H83002)
|
||||
CPU_H83002,
|
||||
#endif
|
||||
#if (HAS_I386)
|
||||
CPU_I386,
|
||||
#endif
|
||||
#if (HAS_MN10200)
|
||||
CPU_MN10200,
|
||||
#endif
|
||||
#if (HAS_M37702)
|
||||
CPU_M37702,
|
||||
#endif
|
||||
#if (HAS_ASAP)
|
||||
CPU_ASAP,
|
||||
#endif
|
||||
@@ -281,6 +299,9 @@ enum
|
||||
#if (HAS_ARM)
|
||||
CPU_ARM,
|
||||
#endif
|
||||
#if (HAS_ARM7)
|
||||
CPU_ARM7,
|
||||
#endif
|
||||
#if (HAS_SH2)
|
||||
CPU_SH2,
|
||||
#endif
|
||||
@@ -311,6 +332,18 @@ enum
|
||||
#if (HAS_E132XS)
|
||||
CPU_E132XS,
|
||||
#endif
|
||||
#if (HAS_I960)
|
||||
CPU_I960,
|
||||
#endif
|
||||
#if (HAS_MB86233)
|
||||
CPU_MB86233,
|
||||
#endif
|
||||
#if (HAS_MB86235)
|
||||
CPU_MB86235,
|
||||
#endif
|
||||
#if (HAS_ADSP21062)
|
||||
CPU_ADSP21062,
|
||||
#endif
|
||||
|
||||
CPU_COUNT
|
||||
};
|
||||
@@ -590,6 +623,10 @@ data8_t cpunum_read_byte(int cpunum, offs_t address);
|
||||
/* write a byte from another CPU's memory space */
|
||||
void cpunum_write_byte(int cpunum, offs_t address, data8_t data);
|
||||
|
||||
/* read/write 'count' consecutive bytes of another CPU's memory space (one context switch) */
|
||||
void cpunum_read_bytes(int cpunum, offs_t address, UINT8 *data, UINT32 count);
|
||||
void cpunum_write_bytes(int cpunum, offs_t address, const UINT8 *data, UINT32 count);
|
||||
|
||||
/* return a pointer to the saved context of a given CPU, or NULL if the
|
||||
context is active (and contained within the CPU core */
|
||||
void *cpunum_get_context_ptr(int cpunum);
|
||||
|
||||
+656
-104
@@ -121,7 +121,7 @@ const struct GameDriver *test_drivers[] =
|
||||
DRIVER( ponpokov ) /* (c) 1982 Sigma Ent. Inc. + Venture Line license */
|
||||
DRIVER( lizwiz ) /* (c) 1985 Techstar + "Sunn presents" */
|
||||
DRIVER( theglobp ) /* (c) 1983 Epos Corporation */
|
||||
DRIVER( beastf ) /* (c) 1984 Epos Corporation */
|
||||
DRIVER( beastfp ) /* (c) 1984 Epos Corporation */
|
||||
DRIVER( acitya ) /* (c) 1983 Epos Corporation */
|
||||
DRIVER( bwcasino ) /* (c) 1983 Epos Coropration */
|
||||
DRIVER( dremshpr ) /* (c) 1982 Sanritsu */
|
||||
@@ -158,7 +158,10 @@ const struct GameDriver *test_drivers[] =
|
||||
DRIVER( theglob2 ) /* (c) 1983 */
|
||||
DRIVER( theglob3 ) /* (c) 1983 */
|
||||
DRIVER( igmo ) /* (c) 1984 */
|
||||
DRIVER( dealer ) /* (c) 198? */
|
||||
DRIVER( dealer ) /* (c) 1984 */
|
||||
DRIVER( revngr84 ) /* (c) 1984 */
|
||||
DRIVER( revenger ) /* (c) 1984 */
|
||||
DRIVER( beastf ) /* (c) 1984 */
|
||||
|
||||
/* "Galaxian hardware" games */
|
||||
DRIVER( galaxian ) /* (c) Namco */
|
||||
@@ -2050,24 +2053,51 @@ V-V TP-027
|
||||
DRIVER( makaimuc ) /* 9/1985 (c) 1985 */
|
||||
DRIVER( makaimug ) /* 9/1985 (c) 1985 */
|
||||
DRIVER( diamond ) /* (c) 1989 KH Video (NOT A CAPCOM GAME but runs on GnG hardware) */
|
||||
DRIVER( gngknight ) /* Hack */
|
||||
DRIVER( gngknighta ) /* Hack */
|
||||
DRIVER( gngknightb ) /* Hack */
|
||||
DRIVER( gngknightc ) /* Hack */
|
||||
DRIVER( gngknightt ) /* Hack */
|
||||
DRIVER( gngenh ) /* Hack */
|
||||
DRIVER( gngaenh ) /* Hack */
|
||||
DRIVER( gngbenh ) /* Hack */
|
||||
DRIVER( gngcenh ) /* Hack */
|
||||
DRIVER( gngtenh ) /* Hack */
|
||||
DRIVER( makaimurenh ) /* Hack */
|
||||
DRIVER( makaimurbenh ) /* Hack */
|
||||
DRIVER( makaimurcenh ) /* Hack */
|
||||
DRIVER( makaimurgenh ) /* Hack */
|
||||
DRIVER( gngmaiden ) /* Hack */
|
||||
DRIVER( gngmaidenenh ) /* Hack */
|
||||
DRIVER( gngmaidena ) /* Hack */
|
||||
DRIVER( gngmaidenaenh ) /* Hack */
|
||||
DRIVER( gngmaidenb ) /* Hack */
|
||||
DRIVER( gngmaidenbenh ) /* Hack */
|
||||
DRIVER( gngmaidenc ) /* Hack */
|
||||
DRIVER( gngmaidencenh ) /* Hack */
|
||||
DRIVER( gngmaident ) /* Hack */
|
||||
DRIVER( makknight ) /* Hack */
|
||||
DRIVER( makknightb ) /* Hack */
|
||||
DRIVER( makknightc ) /* Hack */
|
||||
DRIVER( makknightg ) /* Hack */
|
||||
DRIVER( gngmaidentenh ) /* Hack */
|
||||
DRIVER( gngknight ) /* Hack */
|
||||
DRIVER( gngknightenh ) /* Hack */
|
||||
DRIVER( gngknighta ) /* Hack */
|
||||
DRIVER( gngknightaenh ) /* Hack */
|
||||
DRIVER( gngknightb ) /* Hack */
|
||||
DRIVER( gngknightbenh ) /* Hack */
|
||||
DRIVER( gngknightc ) /* Hack */
|
||||
DRIVER( gngknightcenh ) /* Hack */
|
||||
DRIVER( gngknightt ) /* Hack */
|
||||
DRIVER( gngknighttenh ) /* Hack */
|
||||
DRIVER( makmaiden ) /* Hack */
|
||||
DRIVER( makmaidenenh ) /* Hack */
|
||||
DRIVER( makmaidenb ) /* Hack */
|
||||
DRIVER( makmaidenbenh ) /* Hack */
|
||||
DRIVER( makmaidenc ) /* Hack */
|
||||
DRIVER( makmaidencenh ) /* Hack */
|
||||
DRIVER( makmaideng ) /* Hack */
|
||||
DRIVER( makmaidengenh ) /* Hack */
|
||||
DRIVER( makknight ) /* Hack */
|
||||
DRIVER( makknightenh ) /* Hack */
|
||||
DRIVER( makknightb ) /* Hack */
|
||||
DRIVER( makknightbenh ) /* Hack */
|
||||
DRIVER( makknightc ) /* Hack */
|
||||
DRIVER( makknightcenh ) /* Hack */
|
||||
DRIVER( makknightg ) /* Hack */
|
||||
DRIVER( makknightgenh ) /* Hack */
|
||||
DRIVER( gunsmoke ) /* 11/1985 (c) 1985 (World) */
|
||||
DRIVER( gunsmoku ) /* 11/1985 (c) 1985 + Romstar (US) */
|
||||
DRIVER( gunsmoka ) /* 11/1985 (c) 1985 (US) */
|
||||
@@ -2138,6 +2168,12 @@ V-V TP-027
|
||||
DRIVER( ghouls ) /* 12/1988 (c) 1988 (World) */
|
||||
DRIVER( ghoulsu ) /* 12/1988 (c) 1988 (US) */
|
||||
DRIVER( daimakai ) /* 12/1988 (c) 1988 (Japan) */
|
||||
DRIVER( ghoulsmaiden ) /* Hack */
|
||||
DRIVER( ghoulsknight ) /* Hack */
|
||||
DRIVER( ghoulsumaiden ) /* Hack */
|
||||
DRIVER( ghoulsuknight ) /* Hack */
|
||||
DRIVER( daimakaimaiden ) /* Hack */
|
||||
DRIVER( daimakaiknight ) /* Hack */
|
||||
DRIVER( strider ) /* 3/1989 (c) 1989 (not explicitly stated but should be US) */
|
||||
DRIVER( stridrua ) /* 3/1989 (c) 1989 (not explicitly stated but should be US) */
|
||||
DRIVER( striderj ) /* 3/1989 (c) 1989 */
|
||||
@@ -2418,6 +2454,7 @@ V-V TP-027
|
||||
DRIVER( spf2xj ) /* Capcom, Super Puzzle Fighter II X (Japan 960531) */
|
||||
DRIVER( spf2ta ) /* Capcom, Super Puzzle Fighter II Turbo (Asia 960529) */
|
||||
DRIVER( spf2th ) /* Capcom, Super Puzzle Fighter II Turbo (Hispanic 960531) */
|
||||
DRIVER( spf2xpri ) /* hack, Super Puzzle Fighter 2 X' (X Prime rebalance of Euro 960529) */
|
||||
DRIVER( megaman2 ) /* Capcom, Mega Man 2: The Power Fighters (USA 960708) */
|
||||
DRIVER( megaman2a ) /* Capcom, Mega Man 2: The Power Fighters (Asia 960708) */
|
||||
DRIVER( rockman2j ) /* Capcom, Rockman 2: The Power Fighters (Japan 960708) */
|
||||
@@ -2494,6 +2531,7 @@ V-V TP-027
|
||||
DRIVER( sfz3jr2 ) /* Capcom, Street Fighter Zero 3 (Japan 980629) */
|
||||
DRIVER( sfz3a ) /* Capcom, Street Fighter Zero 3 (Asia 980904) */
|
||||
DRIVER( sfz3ar1 ) /* Capcom, Street Fighter Zero 3 (Asia 980701) */
|
||||
DRIVER( sfz3mix ) /* hack, Street Fighter Zero 3 Mix v0.32 (CPS2Turbo, Zero800) */
|
||||
DRIVER( jyangoku ) /* Capcom, Jyangokushi: Haoh no Saihai (Japan 990527) */
|
||||
DRIVER( hsf2 ) /* Capcom, Hyper Street Fighter II: The Anniversary Edition (USA 040202) */
|
||||
DRIVER( hsf2a ) /* Capcom, Hyper Street Fighter II: The Anniversary Edition (Asia 040202) */
|
||||
@@ -2574,103 +2612,333 @@ V-V TP-027
|
||||
DRIVER( hsf2d ) /* bootleg, Hyper Street Fighter II: The Anniversary Edition (Asia 040202 Phoenix Edition) (bootleg) */
|
||||
#endif
|
||||
/* Capcom CPS3 games */
|
||||
/* 10/1996 Warzard */
|
||||
/* 2/1997 Street Fighter III - New Generation */
|
||||
/* ???? Jojo's Bizarre Adventure */
|
||||
/* ???? Street Fighter 3: Second Impact ~giant attack~ */
|
||||
/* ???? Street Fighter 3: Third Strike ~fight to the finish~ */
|
||||
DRIVER( redearth )
|
||||
DRIVER( warzard )
|
||||
DRIVER( redearthn )
|
||||
DRIVER( redearthr1 )
|
||||
DRIVER( warzardr1 )
|
||||
DRIVER( redearthnr1 )
|
||||
DRIVER( sfiii )
|
||||
DRIVER( sfiiiu )
|
||||
DRIVER( sfiiia )
|
||||
DRIVER( sfiiij )
|
||||
DRIVER( sfiiih )
|
||||
DRIVER( sfiiin )
|
||||
DRIVER( sfiiina )
|
||||
DRIVER( sfiii2 )
|
||||
DRIVER( sfiii2j )
|
||||
DRIVER( sfiii2h )
|
||||
DRIVER( sfiii2a )
|
||||
DRIVER( sfiii2n )
|
||||
DRIVER( jojo )
|
||||
DRIVER( jojou )
|
||||
DRIVER( jojoa )
|
||||
DRIVER( jojoj )
|
||||
DRIVER( jojon )
|
||||
DRIVER( jojor1 )
|
||||
DRIVER( jojour1 )
|
||||
DRIVER( jojoar1 )
|
||||
DRIVER( jojojr1 )
|
||||
DRIVER( jojonr1 )
|
||||
DRIVER( jojor2 )
|
||||
DRIVER( jojour2 )
|
||||
DRIVER( jojoar2 )
|
||||
DRIVER( jojojr2 )
|
||||
DRIVER( jojonr2 )
|
||||
DRIVER( sfiii3 )
|
||||
DRIVER( sfiii3u )
|
||||
DRIVER( sfiii3j )
|
||||
DRIVER( sfiii3n )
|
||||
DRIVER( sfiii3na )
|
||||
DRIVER( sfiii3r1 )
|
||||
DRIVER( sfiii3ur1 )
|
||||
DRIVER( sfiii3jr1 )
|
||||
DRIVER( sfiii3nr1 )
|
||||
DRIVER( sfiii3nar1 )
|
||||
DRIVER( jojoba )
|
||||
DRIVER( jojoban )
|
||||
DRIVER( jojobar1 )
|
||||
DRIVER( jojobajr1 )
|
||||
DRIVER( jojobanr1 )
|
||||
DRIVER( jojobaner1 )
|
||||
DRIVER( jojobar2 )
|
||||
DRIVER( jojobajr2 )
|
||||
DRIVER( jojobanr2 )
|
||||
DRIVER( jojobaner2 )
|
||||
DRIVER( sfiii4n )
|
||||
DRIVER( sfiii3ws ) /* hack, Street Fighter III 3rd Strike: Fight for the Future (Widescreen 20220908) */
|
||||
|
||||
/* Capcom ZN1 */
|
||||
DRIVER( ts2 ) /* Battle Arena Toshinden 2 (USA 951124) */
|
||||
DRIVER( ts2j ) /* Battle Arena Toshinden 2 (JAPAN 951124) */
|
||||
DRIVER( starglad ) /* Star Gladiator (USA 960627) */
|
||||
DRIVER( sfex ) /* Street Fighter EX (ASIA 961219) */
|
||||
DRIVER( sfexj ) /* Street Fighter EX (JAPAN 961130) */
|
||||
DRIVER( glpracr ) /* Gallop Racer (JAPAN Ver 9.01.12) */
|
||||
DRIVER( sfexp ) /* Street Fighter EX Plus (USA 970311) */
|
||||
DRIVER( sfexpj ) /* Street Fighter EX Plus (JAPAN 970311) */
|
||||
DRIVER( rvschool ) /* Rival Schools (ASIA 971117) */
|
||||
DRIVER( jgakuen ) /* Justice Gakuen (JAPAN 971117) */
|
||||
DRIVER( tgmj ) /* Tetris The Grand Master (JAPAN 980710) */
|
||||
/* Capcom ZN-1 */
|
||||
DRIVER( ts2 ) /* Battle Arena Toshinden 2 (Europe 951124) */
|
||||
DRIVER( ts2u ) /* Battle Arena Toshinden 2 (USA 951124) */
|
||||
DRIVER( ts2ua ) /* Battle Arena Toshinden 2 (USA 951124, 32Mb mask ROMs) */
|
||||
DRIVER( ts2j ) /* Battle Arena Toshinden 2 (Japan 951124) */
|
||||
DRIVER( ts2ja ) /* Battle Arena Toshinden 2 (Japan 951124, 32Mb mask ROMs) */
|
||||
DRIVER( starglad ) /* Star Gladiator Episode I: Final Crusade (USA 960627) */
|
||||
DRIVER( stargladj ) /* Star Gladiator Episode I: Final Crusade (Japan 960627) */
|
||||
DRIVER( glpracr ) /* Gallop Racer (English Ver 10.17.K) */
|
||||
DRIVER( glpracrj ) /* Gallop Racer (Japanese Ver 9.01.12) */
|
||||
DRIVER( sfex ) /* Street Fighter EX (Europe 961219) */
|
||||
DRIVER( sfexu ) /* Street Fighter EX (USA 961219) */
|
||||
DRIVER( sfexa ) /* Street Fighter EX (Asia 961219) */
|
||||
DRIVER( sfexj ) /* Street Fighter EX (Japan 961130) */
|
||||
DRIVER( sfexp ) /* Street Fighter EX Plus (USA 970407) */
|
||||
DRIVER( sfexpu1 ) /* Street Fighter EX Plus (USA 970311) */
|
||||
DRIVER( sfexpj ) /* Street Fighter EX Plus (Japan 970407) */
|
||||
|
||||
/* Capcom ZN2 */
|
||||
DRIVER( sfex2 ) /* Street Fighter EX 2 (JAPAN 980312) */
|
||||
DRIVER( sg2j ) /* Star Gladiator 2 (JAPAN 980316) */
|
||||
DRIVER( techromn ) /* Tech Romancer (USA 980914) */
|
||||
DRIVER( kikaioh ) /* Kikaioh (JAPAN 980914) */
|
||||
DRIVER( sfex2p ) /* Street Fighter EX 2 Plus (JAPAN 990611) */
|
||||
DRIVER( strider2 ) /* Strider 2 (USA 991213) */
|
||||
DRIVER( stridr2a ) /* Strider 2 (ASIA 991213) */
|
||||
DRIVER( shiryu2 ) /* Strider Hiryu 2 (JAPAN 991213) */
|
||||
/* Rival Schools 2 */
|
||||
/* Capcom ZN-2 */
|
||||
DRIVER( sfexpj1 ) /* Street Fighter EX Plus (Japan 970311) */
|
||||
DRIVER( rvschool ) /* Rival Schools: United By Fate (Europe 971117) */
|
||||
DRIVER( rvschoolu ) /* Rival Schools: United By Fate (USA 971117) */
|
||||
DRIVER( rvschoola ) /* Rival Schools: United By Fate (Asia 971117) */
|
||||
DRIVER( jgakuen ) /* Shiritsu Justice Gakuen: Legion of Heroes (Japan 971216) */
|
||||
DRIVER( jgakuen1 ) /* Shiritsu Justice Gakuen: Legion of Heroes (Japan 971117) */
|
||||
DRIVER( sfex2 ) /* Street Fighter EX2 (Europe 980312) */
|
||||
DRIVER( sfex2u ) /* Street Fighter EX2 (USA 980526) */
|
||||
DRIVER( sfex2u1 ) /* Street Fighter EX2 (USA 980312) */
|
||||
DRIVER( sfex2a ) /* Street Fighter EX2 (Asia 980312) */
|
||||
DRIVER( sfex2h ) /* Street Fighter EX2 (Hispanic 980312) */
|
||||
DRIVER( sfex2j ) /* Street Fighter EX2 (Japan 980312) */
|
||||
DRIVER( plsmaswd ) /* Plasma Sword: Nightmare of Bilstein (USA 980316) */
|
||||
DRIVER( plsmaswda ) /* Plasma Sword: Nightmare of Bilstein (Asia 980316) */
|
||||
DRIVER( stargld2 ) /* Star Gladiator 2: Nightmare of Bilstein (Japan 980316) */
|
||||
DRIVER( tgmj ) /* Tetris: The Grand Master (Japan 980710) */
|
||||
DRIVER( techromn ) /* Tech Romancer (Europe 980914) */
|
||||
DRIVER( techromnu ) /* Tech Romancer (USA 980914) */
|
||||
DRIVER( techromna ) /* Tech Romancer (Asia 980914) */
|
||||
DRIVER( kikaioh ) /* Choukou Senki Kikaioh (Japan 980914) */
|
||||
DRIVER( sfex2p ) /* Street Fighter EX2 Plus (Europe 990611) */
|
||||
DRIVER( sfex2pu ) /* Street Fighter EX2 Plus (USA 990611) */
|
||||
DRIVER( sfex2pa ) /* Street Fighter EX2 Plus (Asia 990611) */
|
||||
DRIVER( sfex2ph ) /* Street Fighter EX2 Plus (Hispanic 990611) */
|
||||
DRIVER( sfex2pj ) /* Street Fighter EX2 Plus (Japan 990611) */
|
||||
DRIVER( strider2 ) /* Strider 2 (Europe 991213) */
|
||||
DRIVER( strider2u ) /* Strider 2 (USA 991213) */
|
||||
DRIVER( strider2a ) /* Strider 2 (Asia 991213) */
|
||||
DRIVER( shiryu2 ) /* Strider Hiryu 2 (Japan 991213) */
|
||||
|
||||
/* Tecmo ZN1 */
|
||||
DRIVER( glpracr2 ) /* Gallop Racer 2 (USA) */
|
||||
DRIVER( glprac2j ) /* Gallop Racer 2 (JAPAN) */
|
||||
DRIVER( glprac2l ) /* Gallop Racer 2 Link HW (JAPAN) */
|
||||
DRIVER( doapp ) /* Dead Or Alive ++ (JAPAN) */
|
||||
DRIVER( tondemo ) /* Tondemo Crisis (JAPAN) */
|
||||
/* Tecmo TPS (ZN1) */
|
||||
DRIVER( glpracr2 ) /* Gallop Racer 2 (Export) */
|
||||
DRIVER( glpracr2j ) /* Gallop Racer 2 (Japan) */
|
||||
DRIVER( glpracr2l ) /* Gallop Racer 2 Link HW (Japan) */
|
||||
DRIVER( doapp ) /* Dead Or Alive ++ (Japan/USA/Export) */
|
||||
DRIVER( doappk ) /* Dead Or Alive ++ (Korea) */
|
||||
DRIVER( cbaj ) /* Cool Boarders Arcade Jam (Export) */
|
||||
DRIVER( cbajbl ) /* Cool Boarders Arcade Jam (Export bootleg) */
|
||||
DRIVER( shngmtkb ) /* Shanghai Matekibuyuu (Japan) */
|
||||
DRIVER( tondemo ) /* Tondemo Crisis (Japan) */
|
||||
DRIVER( glpracr3 ) /* Gallop Racer 3 (Export) */
|
||||
DRIVER( glpracr3j ) /* Gallop Racer 3 (Japan) */
|
||||
DRIVER( flamegun ) /* Flame Gunner (Export) */
|
||||
DRIVER( flamegunj ) /* Flame Gunner (Japan) */
|
||||
DRIVER( lpadv ) /* Logic Pro Adventure (Japan) */
|
||||
DRIVER( tblkkuzu ) /* The Block Kuzushi (Japan) */
|
||||
DRIVER( 1on1gov ) /* 1 on 1 Government (Japan) */
|
||||
DRIVER( twcupmil ) /* Tecmo World Cup Millennium (Japan) */
|
||||
DRIVER( mfjump ) /* Monster Farm Jump (Japan) */
|
||||
|
||||
/* PS Arcade 95 */
|
||||
DRIVER( brvblade ) /* Brave Blade */
|
||||
DRIVER( beastrzr ) /* Beastorizer */
|
||||
/* Eighting / Raizing (COH-1002E) */
|
||||
DRIVER( beastrzr ) /* Beastorizer (USA, Sep 22 1997) */
|
||||
DRIVER( beastrzra ) /* Beastorizer (USA, Jun 21 1997) */
|
||||
DRIVER( beastrzrb ) /* Beastorizer (USA bootleg) */
|
||||
DRIVER( bldyroar ) /* Bloody Roar (Japan, Jun 21 1997) */
|
||||
DRIVER( bldyror2 ) /* Bloody Roar 2 (World) */
|
||||
DRIVER( bldyror2u ) /* Bloody Roar 2 (USA) */
|
||||
DRIVER( bldyror2a ) /* Bloody Roar 2 (Asia) */
|
||||
DRIVER( bldyror2j ) /* Bloody Roar 2 (Japan) */
|
||||
DRIVER( brvblade ) /* Brave Blade (World) */
|
||||
DRIVER( brvbladeu ) /* Brave Blade (USA) */
|
||||
DRIVER( brvbladea ) /* Brave Blade (Asia) */
|
||||
DRIVER( brvbladej ) /* Brave Blade (Japan) */
|
||||
|
||||
/* Atari PSX */
|
||||
DRIVER( primrag2 ) /* Primal Rage 2 */
|
||||
DRIVER( primrag2 ) /* Primal Rage II (Test Version 0.36a) */
|
||||
|
||||
/* Acclaim PSX */
|
||||
DRIVER( nbajamex ) /* NBA Jam Extreme */
|
||||
DRIVER( jdredd ) /* Judge Dredd (Rev C) */
|
||||
DRIVER( jdreddb ) /* Judge Dredd (Rev B) */
|
||||
DRIVER( jdredd ) /* Judge Dredd (Rev C Dec. 17 1997) */
|
||||
DRIVER( jdreddb ) /* Judge Dredd (Rev B Nov. 26 1997) */
|
||||
DRIVER( nbajamex ) /* NBA Jam Extreme (ver. 1.10I) */
|
||||
DRIVER( nbajamexa ) /* NBA Jam Extreme (ver. 1.04) */
|
||||
|
||||
/* Video System ZN1 */
|
||||
DRIVER( sncwgltd ) /* Sonic Wings Limited (JAPAN) */
|
||||
DRIVER( aerofgts ) /* Aero Fighters Special (USA) */
|
||||
DRIVER( aerofgtst ) /* Aero Fighters Special (Taiwan) */
|
||||
DRIVER( sncwgltd ) /* Sonic Wings Limited (Japan) */
|
||||
|
||||
/* Taito FX1a */
|
||||
DRIVER( psyforce ) /* Psychic Force (JAPAN) */
|
||||
DRIVER( sfchamp ) /* Super Football Champ (JAPAN) */
|
||||
DRIVER( mgcldate ) /* Magical Date (JAPAN) */
|
||||
DRIVER( mgcldtea ) /* Magical Date (JAPAN) */
|
||||
/* Atlus ZN1 */
|
||||
DRIVER( hvnsgate ) /* Heaven's Gate */
|
||||
|
||||
/* Taito FX1b */
|
||||
DRIVER( raystorm ) /* Ray Storm (JAPAN) */
|
||||
DRIVER( ftimpcta ) /* Fighter's Impact Ace (JAPAN) */
|
||||
DRIVER( gdarius ) /* G-Darius (JAPAN) */
|
||||
DRIVER( gdarius2 ) /* G-Darius Ver.2 (JAPAN) */
|
||||
DRIVER( beastrzb ) /* Beastorizer (bootleg)*/
|
||||
/* Taito FX-1A */
|
||||
DRIVER( sfchamp ) /* Super Football Champ (Ver 2.5O) */
|
||||
DRIVER( sfchampo ) /* Super Football Champ (Ver 2.4O) */
|
||||
DRIVER( sfchampu ) /* Super Football Champ (Ver 2.4A) */
|
||||
DRIVER( sfchampj ) /* Super Football Champ (Ver 2.4J) */
|
||||
DRIVER( psyforce ) /* Psychic Force (Ver 2.4O) */
|
||||
DRIVER( psyforcej ) /* Psychic Force (Ver 2.4J) */
|
||||
DRIVER( psyforcex ) /* Psychic Force EX (Ver 2.0J) */
|
||||
DRIVER( mgcldtex ) /* Magical Date EX (Ver 2.01J) */
|
||||
DRIVER( mgcldate ) /* Magical Date (Ver 2.02J) */
|
||||
|
||||
/* Taito FX-1B */
|
||||
DRIVER( raystorm ) /* RayStorm (Ver 2.06A) */
|
||||
DRIVER( raystormo ) /* RayStorm (Ver 2.05O) */
|
||||
DRIVER( raystormu ) /* RayStorm (Ver 2.05A) */
|
||||
DRIVER( raystormj ) /* RayStorm (Ver 2.05J) */
|
||||
DRIVER( chaoshea ) /* Chaos Heat (V2.09O 1998/10/02 17:00) */
|
||||
DRIVER( chaosheaj ) /* Chaos Heat (V2.08J 1998/09/25 17:00) */
|
||||
DRIVER( raycris ) /* RayCrisis (V2.03O 1998/11/15 15:43) */
|
||||
DRIVER( raycrisj ) /* RayCrisis (V2.03J 1998/11/15 15:43) */
|
||||
DRIVER( spuzbobl ) /* Super Puzzle Bobble (V2.05O 1999/2/24 18:00) */
|
||||
DRIVER( spuzboblj ) /* Super Puzzle Bobble (V2.04J 1999/2/17 02:10) */
|
||||
DRIVER( gobyrc ) /* Go By RC (V2.03O 1999/05/25 13:31) */
|
||||
DRIVER( rcdego ) /* RC De Go (V2.03J 1999/05/22 19:29) */
|
||||
DRIVER( flipmaze ) /* Flip Maze (V2.04J 1999/09/02 20:00) */
|
||||
DRIVER( mawasunda ) /* Mawasunda!! (V2.08J 2000/02/01 11:02:54) */
|
||||
DRIVER( shikigam ) /* Shikigami no Shiro (V2.03J 2001/08/07 18:11) */
|
||||
DRIVER( shikigama ) /* Shikigami no Shiro - internal build (V1.02J 2001/09/27 18:45) */
|
||||
DRIVER( sianniv ) /* Space Invaders Anniversary (V2.02J 2003/09/12 20:00) */
|
||||
DRIVER( kollon ) /* Kollon (V2.04JA 2003/11/01 12:00) */
|
||||
DRIVER( kollonc ) /* Kollon (V2.04JC 2003/11/01 12:00) */
|
||||
DRIVER( otenamih ) /* Otenami Haiken (V2.04J 1999/02/01 18:00:00) */
|
||||
DRIVER( psyvaria ) /* Psyvariar -Medium Unit- (V2.02O 2000/02/22 13:00) */
|
||||
DRIVER( psyvarij ) /* Psyvariar -Medium Unit- (V2.04J 2000/02/15 11:00) */
|
||||
DRIVER( psyvarrv ) /* Psyvariar -Revision- (V2.04J 2000/08/11 22:00) */
|
||||
DRIVER( zokuoten ) /* Zoku Otenamihaiken (V2.05J 2003/05/12 18:00) */
|
||||
DRIVER( zokuotena ) /* Zoku Otenamihaiken (V2.03J 2001/02/16 16:00) */
|
||||
DRIVER( zooo ) /* Zooo (V2.01JA 2004/04/13 12:00) */
|
||||
DRIVER( otenamhf ) /* Otenami Haiken Final (V2.07JC 2005/04/20 15:36) */
|
||||
DRIVER( mahjngoh ) /* Mahjong Oh (V2.06J 1999/11/23 08:52:22) */
|
||||
DRIVER( shanghss ) /* Shanghai Shoryu Sairin (V2.03J 2000/05/26 12:45:28) */
|
||||
DRIVER( soutenry ) /* Soutenryu (V2.07J 2000/12/14 11:13:02) */
|
||||
DRIVER( usagi ) /* Usagi (V2.02J 2001/10/02 12:41:19) */
|
||||
DRIVER( shangtou ) /* Shanghai Sangokuhai Tougi (Ver 2.01J 2002/01/18 18:26:58) */
|
||||
DRIVER( nightrai ) /* Night Raid (V2.03J 2001/02/26 17:00) */
|
||||
DRIVER( otenki ) /* Otenki Kororin (V2.01J 2001/07/02 10:00) */
|
||||
DRIVER( xiistag ) /* XII Stag (V2.01J 2002/6/26 22:27) */
|
||||
DRIVER( aerofgtsg ) /* Aero Fighters Special (VER 1.00G) */
|
||||
DRIVER( brvbladeg ) /* Brave Blade (VER 1.40G) */
|
||||
DRIVER( flamegung ) /* Flame Gunner (VER 1.40G) */
|
||||
DRIVER( ftimpactg ) /* Fighters' Impact (VER 2.10G) */
|
||||
DRIVER( gdariusg ) /* G-Darius (VER 2.70G) */
|
||||
DRIVER( raystormg ) /* RayStorm (VER 2.60G) */
|
||||
DRIVER( shngmtkbg ) /* Shanghai Matekibuyuu (VER 1.20G) */
|
||||
DRIVER( tblkkuzug ) /* The Block Kuzushi (VER 1.10G) */
|
||||
DRIVER( ftimpcta ) /* Fighters' Impact A (Ver 2.00J) */
|
||||
DRIVER( ftimpact ) /* Fighters' Impact (Ver 2.02O) */
|
||||
DRIVER( ftimpactu ) /* Fighters' Impact (Ver 2.02A) */
|
||||
DRIVER( ftimpactj ) /* Fighters' Impact (Ver 2.02J) */
|
||||
DRIVER( gdarius2 ) /* G-Darius Ver.2 (Ver 2.03J) */
|
||||
DRIVER( gdarius ) /* G-Darius (Ver 2.02O) */
|
||||
DRIVER( gdariusu ) /* G-Darius (Ver 2.02A) */
|
||||
DRIVER( gdariusj ) /* G-Darius (Ver 2.01J) */
|
||||
|
||||
/* Namco System 11 */
|
||||
DRIVER( tekken ) /* Tekken (TE4/VER.C) */
|
||||
DRIVER( tekkena ) /* Tekken (TE2/VER.B) */
|
||||
DRIVER( tekkenb ) /* Tekken (TE1/VER.B) */
|
||||
DRIVER( tekken2 ) /* Tekken 2 Ver.B (TES3/VER.B) */
|
||||
DRIVER( tekken2a ) /* Tekken 2 Ver.B (TES2/VER.B) */
|
||||
DRIVER( tekken2b ) /* Tekken 2 (TES2/VER.A) */
|
||||
DRIVER( souledge ) /* Soul Edge Ver. II (SO4/VER.C) */
|
||||
DRIVER( souledga ) /* Soul Edge (SO3/VER.A) */
|
||||
DRIVER( souledgb ) /* Soul Edge (SO1/VER.A) */
|
||||
DRIVER( dunkmnia ) /* Dunk Mania (DM1/VER.C) */
|
||||
DRIVER( xevi3dg ) /* Xevious 3D/G (XV31/VER.A) */
|
||||
DRIVER( primglex ) /* Prime Goal EX (PG1/VER.A) */
|
||||
DRIVER( danceyes ) /* Dancing Eyes (DC1/VER.A) */
|
||||
DRIVER( starswep ) /* Star Sweep (STP1/VER.A) */
|
||||
DRIVER( myangel3 ) /* Kosodate Quiz My Angel 3 (KQT1/VER.A) */
|
||||
DRIVER( tekken ) /* Tekken (World, TE2/VER.C) */
|
||||
DRIVER( tekkenac ) /* Tekken (Asia, TE4/VER.C) */
|
||||
DRIVER( tekkenb ) /* Tekken (World, TE2/VER.B) */
|
||||
DRIVER( tekkenjb ) /* Tekken (Japan, TE1/VER.B) */
|
||||
DRIVER( tekken2 ) /* Tekken 2 Ver.B (World, TES2/VER.D) */
|
||||
DRIVER( tekken2b ) /* Tekken 2 Ver.B (World, TES2/VER.B) */
|
||||
DRIVER( tekken2ud ) /* Tekken 2 Ver.B (US, TES3/VER.D) */
|
||||
DRIVER( tekken2ub ) /* Tekken 2 Ver.B (US, TES3/VER.B) */
|
||||
DRIVER( tekken2jc ) /* Tekken 2 Ver.B (Japan, TES1/VER.C) */
|
||||
DRIVER( tekken2jb ) /* Tekken 2 Ver.B (Japan, TES1/VER.B) */
|
||||
DRIVER( tekken2a ) /* Tekken 2 (World, TES2/VER.A) */
|
||||
DRIVER( tekken2ua ) /* Tekken 2 (US, TES3/VER.A) */
|
||||
DRIVER( souledge ) /* Soul Edge Ver. II (Asia, SO4/VER.C) */
|
||||
DRIVER( souledgeuc ) /* Soul Edge Ver. II (US, SO3/VER.C) */
|
||||
DRIVER( souledgea ) /* Soul Edge (World, SO2/VER.A) */
|
||||
DRIVER( souledgeua ) /* Soul Edge (US, SO3/VER.A) */
|
||||
DRIVER( souledgeja ) /* Soul Edge (Japan, SO1/VER.A) */
|
||||
DRIVER( dunkmnia ) /* Dunk Mania (World, DM2/VER.C) */
|
||||
DRIVER( dunkmniajc ) /* Dunk Mania (Japan, DM1/VER.C) */
|
||||
DRIVER( xevi3dg ) /* Xevious 3D/G (World, XV32/VER.B) */
|
||||
DRIVER( xevi3dga ) /* Xevious 3D/G (World, XV32/VER.A) */
|
||||
DRIVER( xevi3dgj ) /* Xevious 3D/G (Japan, XV31/VER.A) */
|
||||
DRIVER( primglex ) /* Prime Goal EX (Japan, PG1/VER.A) */
|
||||
DRIVER( danceyes ) /* Dancing Eyes (World, DC2/VER.B) */
|
||||
DRIVER( danceyesu ) /* Dancing Eyes (US, DC3/VER.C) */
|
||||
DRIVER( danceyesj ) /* Dancing Eyes (Japan, DC1/VER.A) */
|
||||
DRIVER( starswep ) /* Star Sweep (World, STP2/VER.A) */
|
||||
DRIVER( starswepj ) /* Star Sweep (Japan, STP1/VER.A) */
|
||||
DRIVER( myangel3 ) /* Kosodate Quiz My Angel 3 (Japan, KQT1/VER.A) */
|
||||
DRIVER( pocketrc ) /* Pocket Racer (Japan, PKR1/VER.B) */
|
||||
DRIVER( ptblank2a ) /* Point Blank 2 (World, GNB2/VER.A) */
|
||||
DRIVER( ptblank2b ) /* Point Blank 2 (World, GNB2/VER.A alt) */
|
||||
DRIVER( ptblank2c ) /* Point Blank 2 (World, unknown version) */
|
||||
DRIVER( ptblank2ua ) /* Point Blank 2 (US, GNB3/VER.A) */
|
||||
DRIVER( gunbarla ) /* Gunbarl (Japan, GNB1/VER.A) */
|
||||
|
||||
/* Namco System 12 */
|
||||
DRIVER( tekken3 ) /* Tekken 3 (TET1/VER.E) */
|
||||
DRIVER( soulclbr ) /* Soul Calibur (SOC1/VER.A) */
|
||||
DRIVER( ehrgeiz ) /* Ehrgeiz (EG3/VER.A) */
|
||||
DRIVER( mdhorse ) /* Derby Quiz My Dream Horse (MDH1/VER.A) */
|
||||
DRIVER( fgtlayer ) /* Fighting Layer (FTL1/VER.A) */
|
||||
DRIVER( pacapp ) /* Paca Paca Passion (PPP1/VERA) */
|
||||
DRIVER( sws99 ) /* Super World Stadium '99 (SS91/VER.A) */
|
||||
DRIVER( tekkentt ) /* Tekken Tag Tournament (TEG3/VER.B) */
|
||||
DRIVER( mrdrillr ) /* Mr Driller (DRI1/VER.A) */
|
||||
DRIVER( aquarush ) /* Aqua Rush (AQ1/VER.A) */
|
||||
DRIVER( golgo13 ) /* Golgo 13 (GLG1/VER.A) */
|
||||
DRIVER( tekken3 ) /* Tekken 3 (World, TET2/VER.E1) */
|
||||
DRIVER( tekken3a ) /* Tekken 3 (World, TET2/VER.A) */
|
||||
DRIVER( tekken3b ) /* Tekken 3 (World, TET2/VER.B) */
|
||||
DRIVER( tekken3c ) /* Tekken 3 (World, TET2/VER.C) */
|
||||
DRIVER( tekken3d ) /* Tekken 3 (World, TET2/VER.D) */
|
||||
DRIVER( tekken3ua ) /* Tekken 3 (US, TET3/VER.A) */
|
||||
DRIVER( tekken3ud ) /* Tekken 3 (US, TET3/VER.D) */
|
||||
DRIVER( tekken3ja ) /* Tekken 3 (Japan, TET1/VER.A) */
|
||||
DRIVER( tekken3jd ) /* Tekken 3 (Japan, TET1/VER.D) */
|
||||
DRIVER( tekken3je1 ) /* Tekken 3 (Japan, TET1/VER.E1) */
|
||||
DRIVER( lbgrande ) /* Libero Grande (World, LG2/VER.A) */
|
||||
DRIVER( toukon3 ) /* Shin Nihon Pro Wrestling Toukon Retsuden 3 Arcade Edition (Japan, TR1/VER.A) */
|
||||
DRIVER( soulclbr ) /* Soul Calibur (World, SOC12/VER.A2) */
|
||||
DRIVER( soulclbrab ) /* Soul Calibur (Asia, SOC14/VER.B) */
|
||||
DRIVER( soulclbrac ) /* Soul Calibur (Asia, SOC14/VER.C) */
|
||||
DRIVER( soulclbrub ) /* Soul Calibur (US, SOC13/VER.B) */
|
||||
DRIVER( soulclbruc ) /* Soul Calibur (US, SOC13/VER.C) */
|
||||
DRIVER( soulclbrja2 ) /* Soul Calibur (Japan, SOC11/VER.A2) */
|
||||
DRIVER( soulclbrjb ) /* Soul Calibur (Japan, SOC11/VER.B) */
|
||||
DRIVER( soulclbrjc ) /* Soul Calibur (Japan, SOC11/VER.C) */
|
||||
DRIVER( ehrgeiz ) /* Ehrgeiz (World, EG2/VER.A) */
|
||||
DRIVER( ehrgeizua ) /* Ehrgeiz (US, EG3/VER.A) */
|
||||
DRIVER( ehrgeizja ) /* Ehrgeiz (Japan, EG1/VER.A) */
|
||||
DRIVER( sws98 ) /* Super World Stadium '98 (Japan, SS81/VER.A) */
|
||||
DRIVER( mdhorse ) /* Derby Quiz My Dream Horse (Japan, MDH1/VER.A2) */
|
||||
DRIVER( tenkomor ) /* Tenkomori Shooting (World, TKM2/VER.A1) */
|
||||
DRIVER( tenkomorja1 ) /* Tenkomori Shooting (Japan, TKM1/VER.A1) */
|
||||
DRIVER( fgtlayer ) /* Fighting Layer (Asia, FTL3/VER.A) */
|
||||
DRIVER( fgtlayerja ) /* Fighting Layer (Japan, FTL0/VER.A) */
|
||||
DRIVER( pacapp ) /* Paca Paca Passion (Japan, PPP1/VER.A2) */
|
||||
DRIVER( ptblank2 ) /* Point Blank 2 (World, GNB5/VER.A) */
|
||||
DRIVER( gunbarl ) /* Gunbarl (Japan, GNB4/VER.A) */
|
||||
DRIVER( sws99 ) /* Super World Stadium '99 (Japan, SS91/VER.A3) */
|
||||
DRIVER( tektagt ) /* Tekken Tag Tournament (World, TEG2/VER.C1) */
|
||||
DRIVER( tektagtc1a ) /* Tekken Tag Tournament (World, TEG2/VER.C1, set 2) */
|
||||
DRIVER( tektagtub ) /* Tekken Tag Tournament (US, TEG3/VER.B) */
|
||||
DRIVER( tektagtuc1 ) /* Tekken Tag Tournament (US, TEG3/VER.C1) */
|
||||
DRIVER( tektagtja3 ) /* Tekken Tag Tournament (Japan, TEG1/VER.A3) */
|
||||
DRIVER( tektagtjb ) /* Tekken Tag Tournament (Japan, TEG1/VER.B) */
|
||||
DRIVER( tektagtjc1 ) /* Tekken Tag Tournament (Japan, TEG1/VER.C1) */
|
||||
DRIVER( ghlpanic ) /* Ghoul Panic (World, OB2/VER.A) */
|
||||
DRIVER( ohbakyuun ) /* Oh! Bakyuuun (Japan, OB1/VER.A) */
|
||||
DRIVER( pacapp2 ) /* Paca Paca Passion 2 (Japan, PKS1/VER.A) */
|
||||
DRIVER( mrdrillr ) /* Mr. Driller (US, DRI3/VER.A2) */
|
||||
DRIVER( mrdrillrja2 ) /* Mr. Driller (Japan, DRI1/VER.A2) */
|
||||
DRIVER( kaiunqz ) /* Kaiun Quiz (Japan, KW1/VER.A) */
|
||||
DRIVER( pacappsp ) /* Paca Paca Passion Special (Japan, PSP1/VER.A) */
|
||||
DRIVER( aquarush ) /* Aqua Rush (Japan, AQ1/VER.A1) */
|
||||
DRIVER( golgo13 ) /* Golgo 13 (Japan, GLG1/VER.A) */
|
||||
DRIVER( sws2000 ) /* Super World Stadium 2000 (Japan, SS01/VER.A) */
|
||||
DRIVER( kartduel ) /* Kart Duel (World, KTD2/VER.A) */
|
||||
DRIVER( kartduelja ) /* Kart Duel (Japan, KTD1/VER.A) */
|
||||
DRIVER( g13knd ) /* Golgo 13 Kiseki no Dandou (Japan, GLS1/VER.A) */
|
||||
|
||||
/* Namco System 10 */
|
||||
DRIVER( mrdrilr2 ) /* Mr Driller 2 */
|
||||
DRIVER( mrdrilr2 ) /* Mr. Driller 2 (World, DR22 Ver.A) */
|
||||
DRIVER( mrdrilr2j ) /* Mr. Driller 2 (Japan, DR21 Ver.A) */
|
||||
DRIVER( mrdrilr2u ) /* Mr. Driller 2 (US, DR23 Ver.A) */
|
||||
DRIVER( gjspace ) /* GekiToride-Jong Space (10011 Ver.A) */
|
||||
DRIVER( knpuzzle ) /* Kotoba no Puzzle Mojipittan (Japan, KPM1 Ver.A) */
|
||||
DRIVER( mrdrilrg ) /* Mr. Driller G (Japan, DRG1 Ver.A) */
|
||||
DRIVER( chocovdr ) /* Uchuu Daisakusen: Chocovader Contactee (Japan, CVC1 Ver.A) */
|
||||
DRIVER( gamshara ) /* Gamshara (20020912A / 10021 Ver.A) */
|
||||
DRIVER( gamsharao ) /* Gamshara (20020716A / 10021 Ver.A) */
|
||||
DRIVER( panikuru ) /* Panikuru Panekuru (Japan, PPA1 Ver.A) */
|
||||
DRIVER( startrgn ) /* Star Trigon (Japan, STT1 Ver.A) */
|
||||
DRIVER( konotako ) /* Kono e Tako (10021 Ver.A) */
|
||||
DRIVER( ptblank3 ) /* Point Blank 3 (World, GNN2 Ver.A) */
|
||||
DRIVER( gunbalina ) /* Gunbalina (Japan, GNN1 Ver.A) */
|
||||
|
||||
/* Konami GQ */
|
||||
DRIVER( cryptklr )
|
||||
@@ -2907,9 +3175,9 @@ V-V TP-027
|
||||
DRIVER( sscandal ) /* 834-5755 (c) 1985 Coreland / Sega (S1) */
|
||||
DRIVER( myherok ) /* 834-5755 (c) 1985 Coreland / Sega (S1) */
|
||||
DRIVER( shtngmst ) /* 834-5719/5720 (c) 1985 (S2) */
|
||||
DRIVER( chplft ) /* 834-5795 (c) 1985, (c) 1982 Dan Gorlin (S2) */
|
||||
DRIVER( chplftb ) /* 834-5795 (c) 1985, (c) 1982 Dan Gorlin (S2) */
|
||||
DRIVER( chplftbl ) /* bootleg (S2) */
|
||||
DRIVER( choplift ) /* 834-5795 (c) 1985, (c) 1982 Dan Gorlin (S2) */
|
||||
DRIVER( chopliftu ) /* 834-5795 (c) 1985, (c) 1982 Dan Gorlin (S2) */
|
||||
DRIVER( chopliftbl ) /* bootleg (S2) */
|
||||
DRIVER( 4dwarrio ) /* 834-5918 (c) 1985 Coreland / Sega (S1) */
|
||||
DRIVER( brain ) /* (c) 1986 Coreland / Sega (S2?) */
|
||||
DRIVER( raflesia ) /* 834-5753 (c) 1985 Coreland / Sega (S1) */
|
||||
@@ -3162,6 +3430,8 @@ Sep.1994 Quiz Ghost Hunter
|
||||
DRIVER( harddunj ) /* (c) 1994 (Japan) */
|
||||
DRIVER( titlef ) /* (c) 1992 */
|
||||
DRIVER( scross ) /* (c) 1992 (World) */
|
||||
DRIVER( scrossa ) /* (c) 1992 (World, linkable) */
|
||||
DRIVER( scrossu ) /* (c) 1992 (US) */
|
||||
|
||||
/* Sega ST-V games */
|
||||
DRIVER( astrass )
|
||||
@@ -3353,12 +3623,16 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11
|
||||
/* Sega MegaPlay */
|
||||
DRIVER( mp_sonic ) /* 01 */
|
||||
DRIVER( mp_gaxe2 ) /* 02 */
|
||||
DRIVER( mp_gslam ) /* 03 */
|
||||
DRIVER( mp_sor2 ) /* 03 */
|
||||
DRIVER( mp_twc ) /* 04 */
|
||||
DRIVER( mp_soni2 ) /* 05 */
|
||||
DRIVER( mp_bio ) /* 06 */
|
||||
DRIVER( mp_shnb3 ) /* 07 */
|
||||
DRIVER( mp_col3 ) /* 10 */
|
||||
DRIVER( mp_gunhe ) /* 10 */
|
||||
DRIVER( mp_mazin ) /* 11 */
|
||||
DRIVER( mp_col3 ) /* ?? */
|
||||
DRIVER( mp_addams )
|
||||
|
||||
/* Data East "Burger Time hardware" games */
|
||||
DRIVER( lnc ) /* (c) 1981 */
|
||||
@@ -4825,13 +5099,17 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11
|
||||
|
||||
/* Midway / Atari Voodoo based Hardware (Seattle, Flagstaff) */
|
||||
DRIVER ( wg3dh ) /* (c) 1996 Atari Games */
|
||||
DRIVER ( wg3dhfe ) /* (c) 1996 Atari Games */
|
||||
DRIVER ( mace ) /* (c) 1996 Atari Games */
|
||||
DRIVER ( macea ) /* (c) 1997 Atari Games */
|
||||
DRIVER ( sfrush ) /* (c) 1996 Atari Games */
|
||||
DRIVER ( sfrushrk ) /* (c) 1997 Atari Games */
|
||||
DRIVER ( calspeed ) /* (c) 1996 Atari Games */
|
||||
DRIVER ( carnevil ) /* (c) 1998 Midway Games */
|
||||
DRIVER ( biofreak ) /* (c) 1997 Midway Games */
|
||||
DRIVER ( blitz ) /* (c) 1997 Midway Games */
|
||||
DRIVER ( blitz99 ) /* (c) 1998 Midway Games */
|
||||
DRIVER ( blitz99a ) /* (c) 1998 Midway Games */
|
||||
DRIVER ( blitz2k ) /* (c) 1999 Midway Games */
|
||||
|
||||
/* Cinematronics raster games */
|
||||
@@ -4931,7 +5209,111 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11
|
||||
DRIVER( sengokmj ) /* (c) 1991 Sigma */
|
||||
|
||||
|
||||
DRIVER( raiden2 )
|
||||
DRIVER( raiden2 ) /* Raiden II (US, set 1) */
|
||||
DRIVER( raiden2g ) /* Raiden II (Germany) */
|
||||
DRIVER( raiden2gb ) /* Raiden II (Great Britain) */
|
||||
DRIVER( raiden2hk ) /* Raiden II (Hong Kong) */
|
||||
DRIVER( raiden2j ) /* Raiden II (Japan) */
|
||||
DRIVER( raiden2sw ) /* Raiden II (Switzerland) */
|
||||
DRIVER( raiden2u ) /* Raiden II (US, set 2) */
|
||||
DRIVER( raiden2f ) /* Raiden II (France) */
|
||||
DRIVER( raiden2nl ) /* Raiden II (Holland) */
|
||||
DRIVER( raiden2es ) /* Raiden II (Spain) */
|
||||
DRIVER( raiden2i ) /* Raiden II (Italy) */
|
||||
DRIVER( raiden2au ) /* Raiden II (Australia) */
|
||||
DRIVER( raiden2e ) /* Raiden II (easier, Korea) */
|
||||
DRIVER( raiden2eub ) /* Raiden II (easier, US set 3) */
|
||||
DRIVER( raiden2eua ) /* Raiden II (easier, US set 1) */
|
||||
DRIVER( raiden2eg ) /* Raiden II (easier, Germany) */
|
||||
DRIVER( raiden2eup ) /* Raiden II (easier, US, prototype? 11-16) */
|
||||
DRIVER( raiden2ea ) /* Raiden II (easier, Japan) */
|
||||
DRIVER( raiden2eu ) /* Raiden II (easier, US set 2) */
|
||||
DRIVER( raiden2k ) /* Raiden II (harder, Korea) */
|
||||
DRIVER( raiden2dx ) /* Raiden II (harder, Raiden DX hardware, Korea) */
|
||||
DRIVER( raidendx ) /* Raiden DX (UK) */
|
||||
DRIVER( raidendxg ) /* Raiden DX (Germany) */
|
||||
DRIVER( raidendxpt ) /* Raiden DX (Portugal) */
|
||||
DRIVER( raidendxa1 ) /* Raiden DX (Hong Kong, set 1) */
|
||||
DRIVER( raidendxa2 ) /* Raiden DX (Hong Kong, set 2) */
|
||||
DRIVER( raidendxk ) /* Raiden DX (Korea) */
|
||||
DRIVER( raidendxu ) /* Raiden DX (US) */
|
||||
DRIVER( raidendxnl ) /* Raiden DX (Holland) */
|
||||
DRIVER( raidendxj ) /* Raiden DX (Japan, set 1) */
|
||||
DRIVER( raidendxja ) /* Raiden DX (Japan, set 2) */
|
||||
DRIVER( raidendxch ) /* Raiden DX (China) */
|
||||
DRIVER( zeroteam ) /* Zero Team USA (US) */
|
||||
DRIVER( zeroteama ) /* Zero Team (Japan?, earlier?, set 1) */
|
||||
DRIVER( zeroteamb ) /* Zero Team (Japan?, later batteryless) */
|
||||
DRIVER( zeroteamc ) /* Zero Team (Taiwan) */
|
||||
DRIVER( zeroteamd ) /* Zero Team (Korea) */
|
||||
DRIVER( zeroteame ) /* Zero Team (Japan?, earlier?, set 2) */
|
||||
DRIVER( zeroteams ) /* Zero Team Selection */
|
||||
DRIVER( zeroteamsr ) /* Zero Team Suicide Revival Kit */
|
||||
DRIVER( r2dx_v33 ) /* Raiden II New / Raiden DX (newer V33 PCB) (Raiden DX EEPROM) */
|
||||
DRIVER( r2dx_v33_r2 ) /* Raiden II New / Raiden DX (newer V33 PCB) (Raiden II EEPROM) */
|
||||
DRIVER( nzeroteam ) /* New Zero Team (V33 SYSTEM TYPE_B hardware) */
|
||||
DRIVER( nzeroteama ) /* New Zero Team (V33 SYSTEM TYPE_B hardware, Zhongguo Shantou Yihuang license) */
|
||||
DRIVER( nzeroteamb ) /* New Zero Team (V33 SYSTEM TYPE_B hardware, Haoyunlai Trading Company license) */
|
||||
DRIVER( zerotm2k ) /* Zero Team 2000 */
|
||||
|
||||
/* Seibu SPI / SYS386I games */
|
||||
DRIVER( senkyu ) /* Senkyu (Japan, newer) */
|
||||
DRIVER( senkyua ) /* Senkyu (Japan, earlier) */
|
||||
DRIVER( batlball ) /* Battle Balls (Germany, newer) */
|
||||
DRIVER( batlballo ) /* Battle Balls (Germany, earlier) */
|
||||
DRIVER( batlballu ) /* Battle Balls (US) */
|
||||
DRIVER( batlballa ) /* Battle Balls (Hong Kong) */
|
||||
DRIVER( batlballe ) /* Battle Balls (Hong Kong, earlier) */
|
||||
DRIVER( batlballpt ) /* Battle Balls (Portugal) */
|
||||
DRIVER( viprp1 ) /* Viper Phase 1 (New Version, World) */
|
||||
DRIVER( viprp1k ) /* Viper Phase 1 (New Version, Korea) */
|
||||
DRIVER( viprp1u ) /* Viper Phase 1 (New Version, US set 1) */
|
||||
DRIVER( viprp1ua ) /* Viper Phase 1 (New Version, US set 2) */
|
||||
DRIVER( viprp1j ) /* Viper Phase 1 (New Version, Japan) */
|
||||
DRIVER( viprp1s ) /* Viper Phase 1 (New Version, Switzerland) */
|
||||
DRIVER( viprp1h ) /* Viper Phase 1 (New Version, Holland) */
|
||||
DRIVER( viprp1t ) /* Viper Phase 1 (New Version, Germany) */
|
||||
DRIVER( viprp1pt ) /* Viper Phase 1 (New Version, Portugal) */
|
||||
DRIVER( viprp1ot ) /* Viper Phase 1 (Germany) */
|
||||
DRIVER( viprp1oj ) /* Viper Phase 1 (Japan) */
|
||||
DRIVER( viprp1hk ) /* Viper Phase 1 (Hong Kong) */
|
||||
DRIVER( rdft ) /* Raiden Fighters (Germany) */
|
||||
DRIVER( rdftj ) /* Raiden Fighters (Japan, earlier) */
|
||||
DRIVER( rdftja ) /* Raiden Fighters (Japan, earliest) */
|
||||
DRIVER( rdftu ) /* Raiden Fighters (US, earlier) */
|
||||
DRIVER( rdftauge ) /* Raiden Fighters (Evaluation Software For Show, Germany) */
|
||||
DRIVER( rdftua ) /* Raiden Fighters (US, newer) */
|
||||
DRIVER( rdftjb ) /* Raiden Fighters (Japan, newer) */
|
||||
DRIVER( rdftau ) /* Raiden Fighters (Australia) */
|
||||
DRIVER( rdftam ) /* Raiden Fighters (Hong Kong) */
|
||||
DRIVER( rdftadi ) /* Raiden Fighters (Korea, SUB4 cart) */
|
||||
DRIVER( rdfta ) /* Raiden Fighters (Austria) */
|
||||
DRIVER( rdftgb ) /* Raiden Fighters (Great Britain) */
|
||||
DRIVER( rdftgr ) /* Raiden Fighters (Greece) */
|
||||
DRIVER( rdftit ) /* Raiden Fighters (Italy) */
|
||||
DRIVER( rdftadia ) /* Raiden Fighters (Korea, SUB2 cart) */
|
||||
DRIVER( rdft2 ) /* Raiden Fighters 2 - Operation Hell Dive (Germany) */
|
||||
DRIVER( rdft2j ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 1) */
|
||||
DRIVER( rdft2a ) /* Raiden Fighters 2 - Operation Hell Dive (Hong Kong) */
|
||||
DRIVER( rdft2s ) /* Raiden Fighters 2 - Operation Hell Dive (Switzerland) */
|
||||
DRIVER( rdft2ja ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 2) */
|
||||
DRIVER( rdft2aa ) /* Raiden Fighters 2 - Operation Hell Dive (Korea) */
|
||||
DRIVER( rdft2it ) /* Raiden Fighters 2 - Operation Hell Dive (Italy) */
|
||||
DRIVER( rdft2jb ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 3) */
|
||||
DRIVER( rdft2jc ) /* Raiden Fighters 2 - Operation Hell Dive (Japan set 4) */
|
||||
DRIVER( rdft2t ) /* Raiden Fighters 2 - Operation Hell Dive (Taiwan) */
|
||||
DRIVER( rdft2u ) /* Raiden Fighters 2 - Operation Hell Dive (US) */
|
||||
DRIVER( rfjet ) /* Raiden Fighters Jet (Germany) */
|
||||
DRIVER( rfjetu ) /* Raiden Fighters Jet (US) */
|
||||
DRIVER( rfjetj ) /* Raiden Fighters Jet (Japan) */
|
||||
DRIVER( rfjeta ) /* Raiden Fighters Jet (Korea) */
|
||||
DRIVER( rfjett ) /* Raiden Fighters Jet (Taiwan) */
|
||||
DRIVER( rdfts ) /* Raiden Fighters (Taiwan, single board) */
|
||||
DRIVER( rdft2us ) /* Raiden Fighters 2 - Operation Hell Dive (US, single board) */
|
||||
DRIVER( rfjets ) /* Raiden Fighters Jet (US, single board) */
|
||||
DRIVER( rfjetsa ) /* Raiden Fighters Jet (US, single board, test version?) */
|
||||
DRIVER( rdft22kc ) /* Raiden Fighters 2 - Operation Hell Dive 2000 (China, SYS386I) */
|
||||
DRIVER( rfjet2kc ) /* Raiden Fighters Jet 2000 (China, SYS386I) */
|
||||
|
||||
/* Seibu STI System games:
|
||||
Viper: Phase 1 (c) 1995
|
||||
@@ -5035,20 +5417,26 @@ BOMULEUL CHAJARA SEGA ST-V 1997/04/11
|
||||
DRIVER( cybattlr ) /* (c) 1993 */
|
||||
DRIVER( peekaboo ) /* (c) 1993 */
|
||||
|
||||
/* Jaleco Mega System 1 games */
|
||||
DRIVER( hayaosi1 ) /* (c) 1994 */
|
||||
/* Jaleco Mega System 32 games */
|
||||
DRIVER( hayaosi2 ) /* (c) 1994 */
|
||||
DRIVER( hayaosi3 ) /* (c) 1994 */
|
||||
DRIVER( hayaosi3a ) /* (c) 1994 */
|
||||
DRIVER( bbbxing ) /* (c) 1994 */
|
||||
DRIVER( 47pie2 ) /* (c) 1994 */
|
||||
DRIVER( 47pie2o ) /* (c) 1994 */
|
||||
DRIVER( suchie2 ) /* (c) 1994 */
|
||||
DRIVER( suchie2o ) /* (c) 1994 */
|
||||
DRIVER( desertwr ) /* (c) 1995 */
|
||||
DRIVER( gametngk ) /* (c) 1995 */
|
||||
DRIVER( tetrisp ) /* (c) 1995 Jaleco / BPS */
|
||||
DRIVER( p47aces ) /* (c) 1995 */
|
||||
DRIVER( p47acesa ) /* (c) 1995 */
|
||||
DRIVER( akiss ) /* (c) 1995 */
|
||||
DRIVER( akissa ) /* (c) 1995 */
|
||||
DRIVER( gratia ) /* (c) 1996 */
|
||||
DRIVER( gratiaa ) /* (c) 1996 */
|
||||
DRIVER( kirarast ) /* (c) 1996 */
|
||||
DRIVER( kirarasta ) /* (c) 1996 */
|
||||
DRIVER( tp2m32 ) /* (c) 1997 */
|
||||
DRIVER( wpksocv2 ) /* (c) 1996 */
|
||||
DRIVER( f1superb ) /* (c) 1994 */
|
||||
|
||||
/* Video System Co. games */
|
||||
@@ -5554,7 +5942,10 @@ Other Sun games
|
||||
|
||||
/* Fuuki FG-3 games */
|
||||
DRIVER( asurabld ) /* (c) 1998 (Japan) */
|
||||
DRIVER( asurabus ) /* (c) 2000 (Japan) */
|
||||
DRIVER( asurabus ) /* (c) 2001 (USA) */
|
||||
DRIVER( asurabusj ) /* (c) 2000 (Japan) */
|
||||
DRIVER( asurabusja ) /* (c) 2000 (Japan) */
|
||||
DRIVER( asurabusjr ) /* (c) 2000 (Japan) */
|
||||
|
||||
/* Unico games */
|
||||
DRIVER( drgnmst ) /* (c) 1994 */
|
||||
@@ -5656,13 +6047,76 @@ Other Sun games
|
||||
DRIVER( kov ) /* (c) 1999 */
|
||||
DRIVER( kovplus ) /* (c) 1999 */
|
||||
DRIVER( kov115 ) /* (c) 1999 */
|
||||
DRIVER( kovsh ) /* (c) 1999 */
|
||||
DRIVER( photoy2k ) /* (c) 1999 */
|
||||
DRIVER( puzlstar ) /* (c) 1999 */
|
||||
DRIVER( puzzli2 ) /* (c) 1999 */
|
||||
DRIVER( puzzli2s ) /* (c) 2001 */
|
||||
DRIVER( py2k2 ) /* (c) 2001 */
|
||||
DRIVER( ddp2 ) /* (c) 2001 */
|
||||
DRIVER( ddp2 ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2101 ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2100 ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2hk ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2101hk ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2100hk ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2k ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2101k ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2100k ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2j ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2101j ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2100j ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2t ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2101t ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2100t ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2c ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2101c ) /* (c) 2001 IGS */
|
||||
DRIVER( ddp2100c ) /* (c) 2001 IGS */
|
||||
DRIVER( kov2 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2106 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2104 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2103 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov21022 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2102 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2101 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2100 ) /* (c) 2000 IGS */
|
||||
DRIVER( kov2p ) /* (c) 2001 IGS */
|
||||
DRIVER( kov2p204 ) /* (c) 2001 IGS */
|
||||
DRIVER( kov2p203 ) /* (c) 2001 IGS */
|
||||
DRIVER( kov2p202 ) /* (c) 2001 IGS */
|
||||
DRIVER( kov2p200 ) /* (c) 2001 IGS */
|
||||
DRIVER( martmast ) /* (c) 2001 IGS */
|
||||
DRIVER( martmast104c ) /* (c) 2001 IGS */
|
||||
DRIVER( martmast103c ) /* (c) 2001 IGS */
|
||||
DRIVER( martmast102c ) /* (c) 2001 IGS */
|
||||
DRIVER( dw2001 ) /* (c) 2001 IGS */
|
||||
DRIVER( dwpc ) /* (c) 2001 IGS */
|
||||
DRIVER( dwpc101j ) /* (c) 2001 IGS */
|
||||
DRIVER( dmnfrnt ) /* (c) 2002 IGS */
|
||||
DRIVER( dmnfrnt103 ) /* (c) 2002 IGS */
|
||||
DRIVER( dmnfrnt102 ) /* (c) 2002 IGS */
|
||||
DRIVER( dmnfrntpcb ) /* (c) 2002 IGS */
|
||||
DRIVER( theglad ) /* (c) 2003 IGS */
|
||||
DRIVER( theglad104 ) /* (c) 2003 IGS */
|
||||
DRIVER( theglad101 ) /* (c) 2003 IGS */
|
||||
DRIVER( theglad100 ) /* (c) 2003 IGS */
|
||||
DRIVER( thegladpcb ) /* (c) 2003 IGS (Alta/AMI license) */
|
||||
DRIVER( thegladpcba ) /* (c) 2003 IGS (Alta/AMI license) */
|
||||
DRIVER( svg ) /* (c) 2005 IGS / Idea Factory */
|
||||
DRIVER( svghk ) /* (c) 2005 IGS / Idea Factory */
|
||||
DRIVER( svgtw ) /* (c) 2005 IGS / Idea Factory */
|
||||
DRIVER( svgpcb ) /* (c) 2005 IGS / Idea Factory (AMI license) */
|
||||
DRIVER( killbldp ) /* (c) 2005 IGS */
|
||||
DRIVER( happy6 ) /* (c) 2004 IGS */
|
||||
DRIVER( happy6101 ) /* (c) 2004 IGS */
|
||||
DRIVER( happy6100hk ) /* (c) 2004 IGS */
|
||||
DRIVER( happy6100cn ) /* (c) 2004 IGS */
|
||||
DRIVER( kovsh ) /* (c) 1999 IGS */
|
||||
DRIVER( kovsh103 ) /* (c) 1999 IGS */
|
||||
DRIVER( kovsh102 ) /* (c) 1999 IGS */
|
||||
DRIVER( kovsh101 ) /* (c) 1999 IGS */
|
||||
DRIVER( kovsh100 ) /* (c) 1999 IGS */
|
||||
DRIVER( photoy2k ) /* (c) 1999 IGS */
|
||||
DRIVER( photoy2k104 ) /* (c) 1999 IGS */
|
||||
DRIVER( photoy2k103j ) /* (c) 1999 IGS */
|
||||
DRIVER( photoy2k102j ) /* (c) 1999 IGS */
|
||||
|
||||
/* RamTek games */
|
||||
DRIVER( hitme ) /* [1976 Ramtek] */
|
||||
@@ -5704,7 +6158,13 @@ Other Sun games
|
||||
/* Rare games */
|
||||
DRIVER( btoads ) /* (c) 1994 Rare */
|
||||
DRIVER( kinst ) /* (c) 1994 Rare */
|
||||
DRIVER( kinst2 ) /* (c) 1994 Rare */
|
||||
DRIVER( kinst14 ) /* (c) 1994 Rare */
|
||||
DRIVER( kinst13 ) /* (c) 1994 Rare */
|
||||
DRIVER( kinstp ) /* (c) 1994 Rare */
|
||||
DRIVER( kinst2 ) /* (c) 1996 Rare */
|
||||
DRIVER( kinst213 ) /* (c) 1996 Rare */
|
||||
DRIVER( kinst211 ) /* (c) 1996 Rare */
|
||||
DRIVER( kinst210 ) /* (c) 1996 Rare */
|
||||
|
||||
/* Nihon System games */
|
||||
DRIVER( gigasb )
|
||||
@@ -6155,7 +6615,99 @@ Other Sun games
|
||||
|
||||
/* Sega Model 1 Hardware */
|
||||
DRIVER( vr ) /* (c) 1992 Sega */
|
||||
DRIVER( vformula ) /* (c) 1993 Sega */
|
||||
DRIVER( vf ) /* (c) 1993 Sega */
|
||||
DRIVER( swa ) /* (c) 1994 Sega */
|
||||
DRIVER( swaj )
|
||||
DRIVER( wingwar ) /* (c) 1994 Sega */
|
||||
DRIVER( wingwaru )
|
||||
DRIVER( wingwarj )
|
||||
DRIVER( wingwar360 )
|
||||
DRIVER( netmerc ) /* (c) 1993 Sega */
|
||||
DRIVER( vf2 ) /* (c) 1994 Sega, Model 2A */
|
||||
DRIVER( vf2b )
|
||||
DRIVER( vf2a )
|
||||
DRIVER( vf2o )
|
||||
DRIVER( vcop2 ) /* (c) 1995 Sega, Model 2A */
|
||||
DRIVER( motoraid ) /* (c) 1997 Sega, Model 2A */
|
||||
DRIVER( motoraiddx )
|
||||
DRIVER( skytargt ) /* (c) 1995 Sega, Model 2A */
|
||||
DRIVER( airwlkrs ) /* (c) 1997 Data East, Model 2A */
|
||||
DRIVER( manxtt ) /* (c) 1995 Sega, Model 2A */
|
||||
DRIVER( manxttc )
|
||||
DRIVER( manxttdx )
|
||||
DRIVER( hpyagu98 ) /* (c) 1998 Deniam, Model 2A */
|
||||
DRIVER( srallyc ) /* (c) 1995 Sega, Model 2A */
|
||||
DRIVER( srallycb )
|
||||
DRIVER( srallycc )
|
||||
DRIVER( srallycdx )
|
||||
DRIVER( srallycdxa )
|
||||
DRIVER( vcop ) /* (c) 1994 Sega, original Model 2 */
|
||||
DRIVER( vcopa )
|
||||
DRIVER( desert ) /* 1994 Sega / Martin Marietta - original Model 2 */
|
||||
DRIVER( daytona ) /* (c) 1994 Sega, original Model 2 */
|
||||
DRIVER( daytonase )
|
||||
DRIVER( daytona93 ) /* (c) 1993 Sega */
|
||||
DRIVER( daytonas )
|
||||
DRIVER( daytonat )
|
||||
DRIVER( daytonata )
|
||||
DRIVER( daytonam )
|
||||
DRIVER( daytonagtx )
|
||||
DRIVER( vstriker ) /* (c) 1994 Sega, Model 2B */
|
||||
DRIVER( vstrikero )
|
||||
DRIVER( gunblade ) /* (c) 1995 Sega, Model 2B */
|
||||
DRIVER( rchase2 ) /* (c) 1994 Sega, Model 2B */
|
||||
DRIVER( rchase2a )
|
||||
DRIVER( doa ) /* (c) 1996 Tecmo, Model 2B */
|
||||
DRIVER( doab ) /* (c) 1996 Tecmo, Model 2B */
|
||||
DRIVER( doaa ) /* (c) 1996 Tecmo, Model 2A */
|
||||
DRIVER( doaab )
|
||||
DRIVER( doaae )
|
||||
DRIVER( zerogun ) /* (c) 1997 Psikyo, Model 2B */
|
||||
DRIVER( zerogunj ) /* (c) 1997 Psikyo, Model 2B */
|
||||
DRIVER( zeroguna ) /* (c) 1997 Psikyo, Model 2A */
|
||||
DRIVER( zerogunaj )
|
||||
DRIVER( fvipers ) /* 1995 Sega - Model 2B */
|
||||
DRIVER( fvipersb )
|
||||
DRIVER( fvipersa )
|
||||
DRIVER( von ) /* 1995 Sega - Model 2B */
|
||||
DRIVER( vonu )
|
||||
DRIVER( vonj )
|
||||
DRIVER( schamp ) /* 1996 Sega - Model 2B */
|
||||
DRIVER( sfight )
|
||||
DRIVER( lastbrnx ) /* 1996 Sega - Model 2B */
|
||||
DRIVER( lastbrnxu )
|
||||
DRIVER( lastbrnxj )
|
||||
DRIVER( dynamcop ) /* 1998 Sega - Model 2A / 2B */
|
||||
DRIVER( dyndeka2 )
|
||||
DRIVER( dynamcopb )
|
||||
DRIVER( dynamcopc ) /* Model 2C */
|
||||
DRIVER( dyndeka2b )
|
||||
DRIVER( dynabb ) /* 1996 Sega - Model 2B */
|
||||
DRIVER( dynabb97 ) /* 1997 Sega - Model 2B */
|
||||
DRIVER( indy500 ) /* 1995 Sega - Model 2B */
|
||||
DRIVER( indy500d )
|
||||
DRIVER( indy500to )
|
||||
DRIVER( sgt24h ) /* 1996 Jaleco - Model 2B */
|
||||
DRIVER( stcc ) /* 1996 Sega - Model 2C */
|
||||
DRIVER( stccb )
|
||||
DRIVER( stcca )
|
||||
DRIVER( stcco )
|
||||
DRIVER( waverunr ) /* 1996 Sega - Model 2C */
|
||||
DRIVER( skisuprg ) /* 1996 Sega - Model 2C */
|
||||
DRIVER( bel ) /* 1997 Sega / EPL - Model 2C */
|
||||
DRIVER( hotd ) /* 1997 Sega - Model 2C */
|
||||
DRIVER( hotdo )
|
||||
DRIVER( segawski ) /* 1997 Sega - Model 2C */
|
||||
DRIVER( topskatr ) /* 1997 Sega - Model 2C */
|
||||
DRIVER( topskatru )
|
||||
DRIVER( topskatruo )
|
||||
DRIVER( topskatrj )
|
||||
DRIVER( overrev ) /* Model 2C */
|
||||
DRIVER( overrevb ) /* Model 2B */
|
||||
DRIVER( overrevba )
|
||||
DRIVER( pltkids ) /* (c) 1998 Psikyo, Model 2B */
|
||||
DRIVER( pltkidsa ) /* (c) 1998 Psikyo, Model 2A */
|
||||
|
||||
/* Oriental Soft */
|
||||
DRIVER( 1945kiii ) /* (c) 2000 Oriental */
|
||||
|
||||
+2
-1
@@ -70,6 +70,7 @@
|
||||
#include "palette.h"
|
||||
#include "cpuintrf.h"
|
||||
#include "cpuexec.h"
|
||||
#include "machine/random.h"
|
||||
#include "cpuint.h"
|
||||
#include "sndintrf.h"
|
||||
#include "input.h"
|
||||
@@ -440,7 +441,7 @@ struct GameDriver
|
||||
#define GAME_NO_COCKTAIL 0x0100 /* screen flip support is missing */
|
||||
#define GAME_NO_SOUND 0x0200 /* sound is missing */
|
||||
#define GAME_IMPERFECT_SOUND 0x0400 /* sound is known to be wrong */
|
||||
#define GAME_DOESNT_SERIALIZE 0x0420 /* game can not be saved through serailization */
|
||||
#define GAME_DOESNT_SERIALIZE 0x0800 /* game can not be saved through serialization */
|
||||
#define NOT_A_DRIVER 0x4000 /* set by the fake "root" driver_0 and by "containers" */
|
||||
/* e.g. driver_neogeo. */
|
||||
|
||||
|
||||
@@ -1873,7 +1873,7 @@ static READ_HANDLER( indianbt_r )
|
||||
case 0x5ffc: return 0;
|
||||
}
|
||||
logerror("unknown port 0 read @ %x\n",activecpu_get_pc());
|
||||
return rand();
|
||||
return mame_rand_int();
|
||||
}
|
||||
|
||||
static PORT_READ_START( indianbt_readport )
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ static WRITE_HANDLER( ace_characterram_w )
|
||||
|
||||
static READ_HANDLER( unk_r )
|
||||
{
|
||||
return rand()&0xff;
|
||||
return mame_rand_int()&0xff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -271,7 +271,7 @@ READ_HANDLER( devram_r )
|
||||
equal values */
|
||||
case 0xff4:
|
||||
{
|
||||
return rand();
|
||||
return mame_rand_int();
|
||||
} break;
|
||||
|
||||
default: { return devram[offset]; break;}
|
||||
|
||||
+21
-6
@@ -8,6 +8,7 @@ Preliminary driver by:
|
||||
***************************************************************************/
|
||||
|
||||
#include "driver.h"
|
||||
#include "state.h"
|
||||
#include "vidhrdw/generic.h"
|
||||
#include "cpu/konami/konami.h" /* for the callback and the firq irq definition */
|
||||
#include "vidhrdw/konamiic.h"
|
||||
@@ -434,26 +435,33 @@ ROM_END
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
static void aliens_banking( int lines )
|
||||
static int aliens_rombank = 0x10; /* CPU ROM bank lines, kept for save states */
|
||||
|
||||
static void aliens_rombank_set(void)
|
||||
{
|
||||
unsigned char *RAM = memory_region(REGION_CPU1);
|
||||
int lines = aliens_rombank;
|
||||
int offs = 0x18000;
|
||||
|
||||
|
||||
if (lines & 0x10) offs -= 0x8000;
|
||||
|
||||
offs += (lines & 0x0f)*0x2000;
|
||||
cpu_setbank( 1, &RAM[offs] );
|
||||
}
|
||||
|
||||
static void aliens_banking( int lines )
|
||||
{
|
||||
aliens_rombank = lines;
|
||||
aliens_rombank_set();
|
||||
}
|
||||
|
||||
static MACHINE_INIT( aliens )
|
||||
{
|
||||
unsigned char *RAM = memory_region(REGION_CPU1);
|
||||
|
||||
konami_cpu_setlines_callback = aliens_banking;
|
||||
|
||||
/* init the default bank */
|
||||
cpu_setbank( 1, &RAM[0x10000] );
|
||||
/* init the default bank (0x10000) */
|
||||
aliens_rombank = 0x10;
|
||||
aliens_rombank_set();
|
||||
}
|
||||
|
||||
|
||||
@@ -462,6 +470,13 @@ static DRIVER_INIT( aliens )
|
||||
{
|
||||
konami_rom_deinterleave_2(REGION_GFX1);
|
||||
konami_rom_deinterleave_2(REGION_GFX2);
|
||||
|
||||
/* Save the ROM bank and the work RAM / palette switch, and map the
|
||||
saved bank again after loading, so a loaded save state runs the
|
||||
right code */
|
||||
state_save_register_int("aliens", 0, "rombank", &aliens_rombank);
|
||||
state_save_register_int("aliens", 0, "palette_selected", &palette_selected);
|
||||
state_save_register_func_postload(aliens_rombank_set);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -650,7 +650,9 @@ INPUT_PORTS_START( llander1 )
|
||||
|
||||
/* The next one is a potentiometer */
|
||||
PORT_START /* IN3 */
|
||||
PORT_ANALOGX( 0xff, 0x00, IPT_PADDLE|IPF_REVERSE, 100, 10, 0, 255, KEYCODE_UP, KEYCODE_DOWN, JOYCODE_1_UP, JOYCODE_1_DOWN )
|
||||
//PORT_ANALOGX( 0xff, 0x00, IPT_PADDLE_V|IPF_REVERSE, 100, 10, 0, 255, KEYCODE_UP, KEYCODE_DOWN, JOYCODE_1_UP, JOYCODE_1_DOWN )
|
||||
PORT_ANALOG( 0xff, 0x00, IPT_PADDLE_V| IPF_REVERSE , 100, 10, 0, 255 )
|
||||
|
||||
INPUT_PORTS_END
|
||||
|
||||
|
||||
|
||||
@@ -1146,7 +1146,7 @@ static READ32_HANDLER( atarigx2_protection_r )
|
||||
if (lookup_table[i][0] == 0xffffffff)
|
||||
{
|
||||
if (last_write_offset*2 >= 0x700 && last_write_offset*2 < 0x720)
|
||||
result = rand() << 16;
|
||||
result = mame_rand_int() << 16;
|
||||
else
|
||||
result = 0xffff << 16;
|
||||
log_cb(RETRO_LOG_DEBUG, LOGPRE "%06X:Unhandled protection R@%04X = %04X\n", activecpu_get_previouspc(), offset, result);
|
||||
|
||||
Loaded 100 of 365 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user