psx - update to 0.9.38.1 level mednafen

This commit is contained in:
zeromus 2015-02-15 17:57:07 +00:00
parent 2afcb29e35
commit 36f9145483
28 changed files with 5325 additions and 3610 deletions

Binary file not shown.

View File

@ -93,11 +93,7 @@
<ItemGroup>
<None Include="..\psx\cpu_bigswitch.inc" />
<None Include="..\psx\cpu_computedgoto.inc" />
<None Include="..\psx\gpu_command_table.inc" />
<None Include="..\psx\gpu_common.inc" />
<None Include="..\psx\gpu_line.inc" />
<None Include="..\psx\gpu_polygon.inc" />
<None Include="..\psx\gpu_sprite.inc" />
<None Include="..\psx\spu_fir_table.inc" />
<None Include="..\psx\spu_reverb.inc" />
</ItemGroup>

View File

@ -229,21 +229,9 @@
<None Include="..\psx\spu_reverb.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\gpu_command_table.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\gpu_common.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\gpu_line.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\gpu_polygon.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\gpu_sprite.inc">
<Filter>psx</Filter>
</None>
<None Include="..\psx\cpu_computedgoto.inc">
<Filter>psx</Filter>
</None>

View File

@ -31,25 +31,29 @@
[!!] psx/psx : LoadEXE/PSF1 changes (TODO - need these)
[OK] psx/spu* : register renames and misc bugfixes
0.9.37-UNSTABLE -> 0.9.37.1
[NO] psx/cpu : fix some savestate problem with ReadAbsorbDummy, seems alarming
[NO] psx/cpu : fix some savestate problem with ReadAbsorbDummy, seems alarming but maybe was just backwards compatibility
[OK] psx/spu : clamp some sound output presumably messed up by prior reverb changes
0.9.37.1 -> 0.9.38-UNSTABLE [not integrated yet]
(major CDIF changes)
(simplefifo refactored)
[!!] psx/cdutility : substantial revisions to disc sector synthesis with respect to leadout, "UDAPP", and "TSRE" (thread-safe re-entrant) which I dont understand. Need to study for DiscSystem.
[OK] required math_ops changes
[OK] SimpleFifo changed to PSX-only FastFIFO (TOD)
[OK] psx/cdc : set SoftReset Mode to 0x20
[OK] psx/cdc : Edits to MakeStatus and BeginResults and ReadResult
[OK] psx/cdc : in HandlePlayRead, handling of leadout sector synth moved to CDIF
[OK] psx/cdc : in Update, Mode handling and reading of subcode changed
[OK] psx/cdc : in Update, reading of subcode changed. This isn't very important, it just saved reading the 2352 sector bytes when it wasn't needed.
[OK] psx/cdc : error handling in Command_Setloc
[OK] psx/cdc : PreSeekHack edits
[OK] psx/cdc : Command_GetTD improvements
[OK] psx/cdc : Command_SeekL timing changes
[OK] psx/cpu : helpful changes to case ranges and jump table
[OK] psx/cpu : helpful changes to case ranges and jump table. double check for savestate changes.
[OK] psx/dma : easy bugfixes
[??] psx/gpu : display timing changes ?? study more
[OK] psx/gpu : BlitterFifo changes, related to FBWrite/Read
[OK] psx/gpu : a bunch of bugfixes
[OK] psx/gpu : video standard mismatch warning suppressed during DisplayOff
[OK] psx/gpu : be aware of savestate changes
[OK] psx/gpu_line : easy bugfixes
[OK] psx/gte : division bugfixes

View File

@ -45,41 +45,6 @@ typedef __uint8_t uint8;
#define final
#define noexcept
#ifdef _MSC_VER
#include <intrin.h>
//http://stackoverflow.com/questions/355967/how-to-use-msvc-intrinsics-to-get-the-equivalent-of-this-gcc-code
//if needed
//uint32_t __inline ctz( uint32_t value )
//{
// DWORD trailing_zero = 0;
//
// if ( _BitScanForward( &trailing_zero, value ) )
// {
// return trailing_zero;
// }
// else
// {
// // This is undefined, I better choose 32 than 0
// return 32;
// }
//}
uint32 __inline __builtin_clz( uint32_t value )
{
unsigned long leading_zero = 0;
if ( _BitScanReverse( &leading_zero, value ) )
{
return 31 - leading_zero;
}
else
{
// Same remarks as above
return 32;
}
}
#endif
//#if MDFN_GCC_VERSION >= MDFN_MAKE_GCCV(4,7,0)
// #define MDFN_ASSUME_ALIGNED(p, align) __builtin_assume_aligned((p), (align))
//#else

View File

@ -1,6 +1,125 @@
#pragma once
#include "emuware/emuware.h"
#include <intrin.h>
//
// Result is defined for all possible inputs(including 0).
//
static INLINE unsigned MDFN_lzcount32(uint32 v)
{
#if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER)
return v ? __builtin_clz(v) : 32;
#elif defined(_MSC_VER) && defined(_WIN64)
unsigned long idx;
if(!v)
return 32;
_BitScanReverse(&idx, v);
return 31 - idx;
#else
unsigned ret = 0;
if(!v)
return(32);
if(!(v & 0xFFFF0000))
{
v <<= 16;
ret += 16;
}
if(!(v & 0xFF000000))
{
v <<= 8;
ret += 8;
}
if(!(v & 0xF0000000))
{
v <<= 4;
ret += 4;
}
if(!(v & 0xC0000000))
{
v <<= 2;
ret += 2;
}
if(!(v & 0x80000000))
{
v <<= 1;
ret += 1;
}
return(ret);
#endif
}
//
// Result is defined for all possible inputs(including 0).
//
static INLINE unsigned MDFN_lzcount64(uint64 v)
{
#if defined(__GNUC__) || defined(__clang__) || defined(__ICC) || defined(__INTEL_COMPILER)
return v ? __builtin_clzll(v) : 64;
#elif defined(_MSC_VER) && defined(_WIN64)
unsigned long idx;
if(!v)
return 64;
_BitScanReverse64(&idx, v);
return 63 - idx;
#else
unsigned ret = 0;
if(!(v & 0xFFFFFFFFFFFFFFFFULL))
return(64);
if(!(v & 0xFFFFFFFF00000000ULL))
{
v <<= 32;
ret += 32;
}
if(!(v & 0xFFFF000000000000ULL))
{
v <<= 16;
ret += 16;
}
if(!(v & 0xFF00000000000000ULL))
{
v <<= 8;
ret += 8;
}
if(!(v & 0xF000000000000000ULL))
{
v <<= 4;
ret += 4;
}
if(!(v & 0xC000000000000000ULL))
{
v <<= 2;
ret += 2;
}
if(!(v & 0x8000000000000000ULL))
{
v <<= 1;
ret += 1;
}
return(ret);
#endif
}
// Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
// Rounds up to the nearest power of 2.
@ -84,4 +203,3 @@ template<typename T, typename U, typename V> static INLINE void clamp(T *val, U
*val = maximum;
}
}

View File

@ -0,0 +1,88 @@
#ifndef __MDFN_FASTFIFO_H
#define __MDFN_FASTFIFO_H
// size should be a power of 2.
template<typename T, size_t size>
class FastFIFO
{
public:
FastFIFO()
{
memset(data, 0, sizeof(data));
read_pos = 0;
write_pos = 0;
in_count = 0;
}
INLINE ~FastFIFO()
{
}
INLINE void SaveStatePostLoad(void)
{
read_pos %= size;
write_pos %= size;
in_count %= (size + 1);
}
INLINE uint32 CanRead(void)
{
return(in_count);
}
INLINE uint32 CanWrite(void)
{
return(size - in_count);
}
INLINE T Peek(void)
{
return data[read_pos];
}
INLINE T Read(void)
{
T ret = data[read_pos];
read_pos = (read_pos + 1) & (size - 1);
in_count--;
return(ret);
}
INLINE void Write(const T& wr_data)
{
data[write_pos] = wr_data;
write_pos = (write_pos + 1) & (size - 1);
in_count++;
}
INLINE void Flush(void)
{
read_pos = 0;
write_pos = 0;
in_count = 0;
}
T data[size];
uint32 read_pos; // Read position
uint32 write_pos; // Write position
uint32 in_count; // Number of units in the FIFO
template<bool isReader> void SyncState(EW::NewState *ns)
{
//I dont like this class...
NSS(data);
NSS(read_pos);
NSS(write_pos);
NSS(in_count);
SaveStatePostLoad();
}
};
#endif

View File

@ -214,7 +214,7 @@ void PS_CDC::SoftReset(void)
PendingCommandPhase = 0;
PendingCommandCounter = 0;
Mode = 0;
Mode = 0x20;
HeaderBufValid = false;
DriveStatus = DS_STOPPED;
@ -375,67 +375,77 @@ void PS_CDC::WriteIRQ(uint8 V)
RecalcIRQ();
}
void PS_CDC::BeginResults(void)
{
//if(ResultsIn)
// {
// printf("Cleared %d results. IRQBuffer=0x%02x\n", ResultsIn, IRQBuffer);
//}
// TODO: test semantics on real thing.
ResultsIn = 0;
ResultsWP = 0;
ResultsRP = 0;
}
void PS_CDC::WriteResult(uint8 V)
{
ResultsBuffer[ResultsWP] = V;
ResultsWP = (ResultsWP + 1) & 0xF;
ResultsIn = (ResultsIn + 1) & 0x1F;
if(!ResultsIn)
PSX_WARNING("[CDC] Results buffer overflow!");
}
uint8 PS_CDC::ReadResult(void)
{
uint8 ret = ResultsBuffer[ResultsRP];
ResultsRP = (ResultsRP + 1) & 0xF;
ResultsIn = (ResultsIn - 1) & 0x1F;
return ret;
}
uint8 PS_CDC::MakeStatus(bool cmd_error)
{
uint8 ret = 0;
// Are these bit positions right?
if(DriveStatus == DS_PLAYING)
ret |= 0x80;
if(DriveStatus == DS_SEEKING || DriveStatus == DS_SEEKING_LOGICAL)
ret |= 0x40;
if(DriveStatus == DS_READING)
ret |= 0x20;
// TODO: shell open and seek error
if(!Cur_disc || DiscChanged)
ret |= 0x10;
if(DriveStatus != DS_STOPPED)
ret |= 0x02;
if(cmd_error)
ret |= 0x01;
DiscChanged = false;
return(ret);
void PS_CDC::BeginResults(void)
{
//if(ResultsIn)
// {
// printf("Cleared %d results. IRQBuffer=0x%02x\n", ResultsIn, IRQBuffer);
//}
ResultsIn = 0;
ResultsWP = 0;
ResultsRP = 0;
memset(ResultsBuffer, 0x00, sizeof(ResultsBuffer));
}
void PS_CDC::WriteResult(uint8 V)
{
ResultsBuffer[ResultsWP] = V;
ResultsWP = (ResultsWP + 1) & 0xF;
ResultsIn = (ResultsIn + 1) & 0x1F;
if(!ResultsIn)
PSX_WARNING("[CDC] Results buffer overflow!");
}
uint8 PS_CDC::ReadResult(void)
{
uint8 ret = ResultsBuffer[ResultsRP];
if(!ResultsIn)
PSX_WARNING("[CDC] Results buffer underflow!");
ResultsRP = (ResultsRP + 1) & 0xF;
ResultsIn = (ResultsIn - 1) & 0x1F;
return ret;
}
uint8 PS_CDC::MakeStatus(bool cmd_error)
{
uint8 ret = 0;
// Are these bit positions right?
if(DriveStatus == DS_PLAYING)
ret |= 0x80;
// Probably will want to be careful with this HeaderBufValid versus seek/read bit business in the future as it is a bit fragile;
// "Gran Turismo 1"'s music(or erroneous lack of) is a good test case.
if(DriveStatus == DS_READING)
{
if(!HeaderBufValid)
ret |= 0x40;
else
ret |= 0x20;
}
else if(DriveStatus == DS_SEEKING || DriveStatus == DS_SEEKING_LOGICAL)
ret |= 0x40;
// TODO: shell open and seek error
if(!Cur_CDIF || DiscChanged)
ret |= 0x10;
if(DriveStatus != DS_STOPPED)
ret |= 0x02;
if(cmd_error)
ret |= 0x01;
DiscChanged = false;
return(ret);
}
bool PS_CDC::DecodeSubQ(uint8 *subpw)
@ -463,13 +473,13 @@ bool PS_CDC::DecodeSubQ(uint8 *subpw)
static const int16 CDADPCMImpulse[7][25] =
{
{ 0, -5, 17, -35, 70, -23, -68, 347, -839, 2062, -4681, 15367, 21472, -5882, 2810, -1352, 635, -235, 26, 43, -35, 16, -8, 2, 0, }, /* 0 */
{ 0, -2, 10, -34, 65, -84, 52, 9, -266, 1024, -2680, 9036, 26516, -6016, 3021, -1571, 848, -365, 107, 10, -16, 17, -8, 3, -1, }, /* 1 */
{ -2, 0, 3, -19, 60, -75, 162, -227, 306, -67, -615, 3229, 29883, -4532, 2488, -1471, 882, -424, 166, -27, 5, 6, -8, 3, -1, }, /* 2 */
{ -1, 3, -2, -5, 31, -74, 179, -402, 689, -926, 1272, -1446, 31033, -1446, 1272, -926, 689, -402, 179, -74, 31, -5, -2, 3, -1, }, /* 3 */
{ -1, 3, -8, 6, 5, -27, 166, -424, 882, -1471, 2488, -4532, 29883, 3229, -615, -67, 306, -227, 162, -75, 60, -19, 3, 0, -2, }, /* 4 */
{ -1, 3, -8, 17, -16, 10, 107, -365, 848, -1571, 3021, -6016, 26516, 9036, -2680, 1024, -266, 9, 52, -84, 65, -34, 10, -2, 0, }, /* 5 */
{ 0, 2, -8, 16, -35, 43, 26, -235, 635, -1352, 2810, -5882, 21472, 15367, -4681, 2062, -839, 347, -68, -23, 70, -35, 17, -5, 0, }, /* 6 */
{ 0, -5, 17, -35, 70, -23, -68, 347, -839, 2062, -4681, 15367, 21472, -5882, 2810, -1352, 635, -235, 26, 43, -35, 16, -8, 2, 0, }, /* 0 */
{ 0, -2, 10, -34, 65, -84, 52, 9, -266, 1024, -2680, 9036, 26516, -6016, 3021, -1571, 848, -365, 107, 10, -16, 17, -8, 3, -1, }, /* 1 */
{ -2, 0, 3, -19, 60, -75, 162, -227, 306, -67, -615, 3229, 29883, -4532, 2488, -1471, 882, -424, 166, -27, 5, 6, -8, 3, -1, }, /* 2 */
{ -1, 3, -2, -5, 31, -74, 179, -402, 689, -926, 1272, -1446, 31033, -1446, 1272, -926, 689, -402, 179, -74, 31, -5, -2, 3, -1, }, /* 3 */
{ -1, 3, -8, 6, 5, -27, 166, -424, 882, -1471, 2488, -4532, 29883, 3229, -615, -67, 306, -227, 162, -75, 60, -19, 3, 0, -2, }, /* 4 */
{ -1, 3, -8, 17, -16, 10, 107, -365, 848, -1571, 3021, -6016, 26516, 9036, -2680, 1024, -266, 9, 52, -84, 65, -34, 10, -2, 0, }, /* 5 */
{ 0, 2, -8, 16, -35, 43, 26, -235, 635, -1352, 2810, -5882, 21472, 15367, -4681, 2062, -839, 347, -68, -23, 70, -35, 17, -5, 0, }, /* 6 */
};
void PS_CDC::ReadAudioBuffer(int32 samples[2])
@ -880,17 +890,11 @@ void PS_CDC::HandlePlayRead(void)
if(CurSector >= (int32)toc.tracks[100].lba)
{
PSX_WARNING("[CDC] In leadout area: %u", CurSector);
//ZERO TODO - this is the critical point for testing leadout-reading.
}
// " Synthesis is a bit of a kludge " but we've taken it out of here
//synth_leadout_sector_lba(0x02, toc, CurSector, read_buf);
Cur_disc->ReadLBA2448(CurSector,read_buf); // FIXME: error out on error.
}
else
{
Cur_disc->ReadLBA2448(CurSector,read_buf); // FIXME: error out on error.
}
DecodeSubQ(read_buf + 2352);
Cur_disc->ReadLBA2448(CurSector,read_buf); // FIXME: error out on error.
DecodeSubQ(read_buf + 2352);
if(SubQBuf_Safe[1] == 0xAA && (DriveStatus == DS_PLAYING || (!(SubQBuf_Safe[0] & 0x40) && (Mode & MODE_CDDA))))
@ -1109,7 +1113,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
if(PSRCounter > 0)
{
uint8 buf[2352 + 96];
uint8 pwbuf[96];
PSRCounter -= chunk_clocks;
@ -1126,7 +1130,7 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
SectorPipe_Pos = SectorPipe_In = 0;
SectorsRead = 0;
Mode = 0;
Mode = 0x20; // Confirmed(and see "This Is Football 2").
CurSector = 0;
CommandLoc = 0;
@ -1136,8 +1140,8 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
else if(DriveStatus == DS_SEEKING)
{
CurSector = SeekTarget;
Cur_disc->ReadLBA2448(CurSector,buf);
DecodeSubQ(buf + 2352);
Cur_disc->ReadLBA_PW(pwbuf,CurSector,false);
DecodeSubQ(pwbuf);
DriveStatus = StatusAfterSeek;
@ -1146,26 +1150,25 @@ pscpu_timestamp_t PS_CDC::Update(const pscpu_timestamp_t timestamp)
PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
}
}
else if(DriveStatus == DS_SEEKING_LOGICAL)
{
CurSector = SeekTarget;
Cur_disc->ReadLBA2448(CurSector, buf);
DecodeSubQ(buf + 2352);
memcpy(HeaderBuf, buf + 12, 12);
DriveStatus = StatusAfterSeek;
if(DriveStatus != DS_PAUSED && DriveStatus != DS_STANDBY)
{
// TODO: SetAIP(CDCIRQ_DISC_ERROR, MakeStatus() | 0x04, 0x04); when !(Mode & MODE_CDDA) and the sector isn't a data sector.
PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
}
}
else if(DriveStatus == DS_READING || DriveStatus == DS_PLAYING)
{
HandlePlayRead();
}
}
else if(DriveStatus == DS_SEEKING_LOGICAL)
{
CurSector = SeekTarget;
Cur_disc->ReadLBA_PW(pwbuf, CurSector, false);
DecodeSubQ(pwbuf);
DriveStatus = StatusAfterSeek;
if(DriveStatus != DS_PAUSED && DriveStatus != DS_STANDBY)
{
// TODO: SetAIP(CDCIRQ_DISC_ERROR, MakeStatus() | 0x04, 0x04); when !(Mode & MODE_CDDA) and the sector isn't a data sector.
PSRCounter = 33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1));
}
}
else if(DriveStatus == DS_READING || DriveStatus == DS_PLAYING)
{
HandlePlayRead();
}
}
}
if(PendingCommandCounter > 0)
@ -1552,22 +1555,32 @@ int32 PS_CDC::Command_Nop(const int arg_count, const uint8 *args)
return(0);
}
int32 PS_CDC::Command_Setloc(const int arg_count, const uint8 *args)
{
uint8 m, s, f;
m = BCD_to_U8(args[0] & 0x7F);
s = BCD_to_U8(args[1]);
f = BCD_to_U8(args[2]);
CommandLoc = f + 75 * s + 75 * 60 * m - 150;
CommandLoc_Dirty = true;
WriteResult(MakeStatus());
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
return(0);
int32 PS_CDC::Command_Setloc(const int arg_count, const uint8 *args)
{
uint8 m, s, f;
if((args[0] & 0x0F) > 0x09 || args[0] > 0x99 ||
(args[1] & 0x0F) > 0x09 || args[1] > 0x59 ||
(args[2] & 0x0F) > 0x09 || args[2] > 0x74)
{
WriteResult(MakeStatus(true));
WriteResult(ERRCODE_BAD_ARGVAL);
WriteIRQ(CDCIRQ_DISC_ERROR);
return(0);
}
m = BCD_to_U8(args[0]);
s = BCD_to_U8(args[1]);
f = BCD_to_U8(args[2]);
CommandLoc = f + 75 * s + 75 * 60 * m - 150;
CommandLoc_Dirty = true;
WriteResult(MakeStatus());
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
return(0);
}
int32 PS_CDC::CalcSeekTime(int32 initial, int32 target, bool motor_on, bool paused)
@ -1624,34 +1637,27 @@ void PS_CDC::BeginSeek(uint32 target, int after_seek)
}
#endif
// Remove this function when we have better seek emulation; it's here because the Rockman complete works games(at least 2 and 4) apparently have finicky fubared CD
// access code.
void PS_CDC::PreSeekHack(bool logical, uint32 target)
{
uint8 buf[2352 + 96];
int max_try = 32;
bool NeedHBuf = logical;
CurSector = target; // If removing/changing this, take into account how it will affect ReadN/ReadS/Play/etc command calls that interrupt a seek.
// If removing this SubQ reading bit, think about how it will interact with a Read command of data(or audio :b) sectors when Mode bit0 is 1.
if(target < toc.tracks[100].lba)
{
do
{
Cur_disc->ReadLBA2448(target++, buf);
// GetLocL related kludge, for Gran Turismo 1 music, perhaps others?
if(NeedHBuf)
{
NeedHBuf = false;
memcpy(HeaderBuf, buf + 12, 12);
HeaderBufValid = true;
}
} while(!DecodeSubQ(buf + 2352) && --max_try > 0 && target < toc.tracks[100].lba);
}
}
// Remove this function when we have better seek emulation; it's here because the Rockman complete works games(at least 2 and 4) apparently have finicky fubared CD
// access code.
void PS_CDC::PreSeekHack(int32 target)
{
uint8 pwbuf[96];
int max_try = 32;
CurSector = target; // If removing/changing this, take into account how it will affect ReadN/ReadS/Play/etc command calls that interrupt a seek.
// If removing this SubQ reading bit, think about how it will interact with a Read command of data(or audio :b) sectors when Mode bit0 is 1.
do
{
Cur_disc->ReadLBA_PW(pwbuf, target++, true);
} while(!DecodeSubQ(pwbuf) && --max_try > 0);
}
/*
Play command with a track argument that's not a valid BCD quantity causes interesting half-buggy behavior on an actual PS1(unlike some of the other commands,
an error doesn't seem to be generated for a bad BCD argument).
*/
int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
{
if(!CommandCheckDiscPresent())
@ -1675,7 +1681,7 @@ int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
}
else if(track > toc.last_track)
{
PSX_WARNING("[CDC] Attempt to play track before first track.");
PSX_WARNING("[CDC] Attempt to play track after last track.");
track = toc.last_track;
}
@ -1690,7 +1696,7 @@ int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
SeekTarget = toc.tracks[track].lba;
PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
HeaderBufValid = false;
PreSeekHack(false, SeekTarget);
PreSeekHack(SeekTarget);
ReportLastF = 0xFF;
@ -1712,7 +1718,7 @@ int32 PS_CDC::Command_Play(const int arg_count, const uint8 *args)
PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
HeaderBufValid = false;
PreSeekHack(false, SeekTarget);
PreSeekHack(SeekTarget);
ReportLastF = 0xFF;
@ -1785,7 +1791,7 @@ void PS_CDC::ReadBase(void)
PSRCounter = /*903168 * 1.5 +*/ CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
HeaderBufValid = false;
PreSeekHack(true, SeekTarget);
PreSeekHack(SeekTarget);
DriveStatus = DS_SEEKING_LOGICAL;
StatusAfterSeek = DS_READING;
@ -2062,59 +2068,60 @@ int32 PS_CDC::Command_GetTN(const int arg_count, const uint8 *args)
return(0);
}
int32 PS_CDC::Command_GetTD(const int arg_count, const uint8 *args)
{
if(!CommandCheckDiscPresent())
return(0);
int track;
uint8 m, s, f;
if(!args[0] || args[0] == 0xAA)
track = 100;
else
{
track= BCD_to_U8(args[0]);
if(track < toc.first_track || track > toc.last_track) // Error
{
WriteResult(MakeStatus(true));
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
return(0);
}
}
LBA_to_AMSF(toc.tracks[track].lba, &m, &s, &f);
WriteResult(MakeStatus());
WriteResult(U8_to_BCD(m));
WriteResult(U8_to_BCD(s));
//WriteResult(U8_to_BCD(f));
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
return(0);
int32 PS_CDC::Command_GetTD(const int arg_count, const uint8 *args)
{
if(!CommandCheckDiscPresent())
return(0);
int track;
uint8 m, s, f;
if(!args[0])
track = 100;
else
{
track = BCD_to_U8(args[0]);
if(!BCD_is_valid(args[0]) || track < toc.first_track || track > toc.last_track) // Error
{
WriteResult(MakeStatus(true));
WriteResult(ERRCODE_BAD_ARGVAL);
WriteIRQ(CDCIRQ_DISC_ERROR);
return(0);
}
}
LBA_to_AMSF(toc.tracks[track].lba, &m, &s, &f);
WriteResult(MakeStatus());
WriteResult(U8_to_BCD(m));
WriteResult(U8_to_BCD(s));
//WriteResult(U8_to_BCD(f));
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
return(0);
}
int32 PS_CDC::Command_SeekL(const int arg_count, const uint8 *args)
{
if(!CommandCheckDiscPresent())
return(0);
WriteResult(MakeStatus());
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
SeekTarget = CommandLoc;
PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
HeaderBufValid = false;
PreSeekHack(true, SeekTarget);
DriveStatus = DS_SEEKING_LOGICAL;
StatusAfterSeek = DS_STANDBY;
ClearAIP();
return(PSRCounter);
int32 PS_CDC::Command_SeekL(const int arg_count, const uint8 *args)
{
if(!CommandCheckDiscPresent())
return(0);
WriteResult(MakeStatus());
WriteIRQ(CDCIRQ_ACKNOWLEDGE);
SeekTarget = CommandLoc;
PSRCounter = (33868800 / (75 * ((Mode & MODE_SPEED) ? 2 : 1))) + CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
HeaderBufValid = false;
PreSeekHack(SeekTarget);
DriveStatus = DS_SEEKING_LOGICAL;
StatusAfterSeek = DS_STANDBY;
ClearAIP();
return(PSRCounter);
}
int32 PS_CDC::Command_SeekP(const int arg_count, const uint8 *args)
@ -2129,7 +2136,7 @@ int32 PS_CDC::Command_SeekP(const int arg_count, const uint8 *args)
PSRCounter = CalcSeekTime(CurSector, SeekTarget, DriveStatus != DS_STOPPED, DriveStatus == DS_PAUSED);
HeaderBufValid = false;
PreSeekHack(false, SeekTarget);
PreSeekHack(SeekTarget);
DriveStatus = DS_SEEKING;
StatusAfterSeek = DS_STANDBY;
ClearAIP();

View File

@ -2,6 +2,7 @@
#define __MDFN_PSX_CDC_H
#include "cdrom/CDUtility.h"
#include "cdrom/SimpleFIFO.h"
class ShockDiscRef;
@ -232,8 +233,7 @@ class PS_CDC
int32 (PS_CDC::*func2)(void);
};
void BeginSeek(uint32 target);
void PreSeekHack(bool logical, uint32 target);
void PreSeekHack(int32 target);
void ReadBase(void);
static CDC_CTEntry Commands[0x20];

File diff suppressed because it is too large Load Diff

View File

@ -1,264 +1,256 @@
#ifndef __MDFN_PSX_CPU_H
#define __MDFN_PSX_CPU_H
/*
Load delay notes:
// Takes 1 less
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"nop\n\t"
"or %0, %1, %1\n\t"
// cycle than this:
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"or %0, %1, %1\n\t"
"nop\n\t"
// Both of these
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"nop\n\t"
"or %1, %0, %0\n\t"
// take same...(which is kind of odd).
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"or %1, %0, %0\n\t"
"nop\n\t"
*/
#include "gte.h"
namespace MDFN_IEN_PSX
{
#define PS_CPU_EMULATE_ICACHE 1
class PS_CPU
{
public:
PS_CPU() MDFN_COLD;
~PS_CPU() MDFN_COLD;
template<bool isReader>void SyncState(EW::NewState *ns);
// FAST_MAP_* enums are in BYTES(8-bit), not in 32-bit units("words" in MIPS context), but the sizes
// will always be multiples of 4.
enum { FAST_MAP_SHIFT = 16 };
enum { FAST_MAP_PSIZE = 1 << FAST_MAP_SHIFT };
void SetFastMap(void *region_mem, uint32_t region_address, uint32_t region_size);
INLINE void SetEventNT(const pscpu_timestamp_t next_event_ts_arg)
{
next_event_ts = next_event_ts_arg;
}
pscpu_timestamp_t Run(pscpu_timestamp_t timestamp_in, bool BIOSPrintMode, bool ILHMode);
void Power(void) MDFN_COLD;
// which ranges 0-5, inclusive
void AssertIRQ(unsigned which, bool asserted);
void SetHalt(bool status);
// TODO eventually: factor BIU address decoding directly in the CPU core somehow without hurting speed.
void SetBIU(uint32_t val);
uint32_t GetBIU(void);
private:
struct
{
uint32_t GPR[32];
uint32_t GPR_dummy; // Used in load delay simulation(indexing past the end of GPR)
};
uint32_t LO;
uint32_t HI;
uint32_t BACKED_PC;
uint32_t BACKED_new_PC;
uint32_t BACKED_new_PC_mask;
uint32_t IPCache;
void RecalcIPCache(void);
bool Halted;
uint32_t BACKED_LDWhich;
uint32_t BACKED_LDValue;
uint32_t LDAbsorb;
pscpu_timestamp_t next_event_ts;
pscpu_timestamp_t gte_ts_done;
pscpu_timestamp_t muldiv_ts_done;
uint32_t BIU;
struct __ICache
{
uint32_t TV;
uint32_t Data;
};
union
{
__ICache ICache[1024];
uint32 ICache_Bulk[2048];
};
enum
{
CP0REG_BPC = 3, // PC breakpoint address.
CP0REG_BDA = 5, // Data load/store breakpoint address.
CP0REG_TAR = 6, // Target address(???)
CP0REG_DCIC = 7, // Cache control
CP0REG_BDAM = 9, // Data load/store address mask.
CP0REG_BPCM = 11, // PC breakpoint address mask.
CP0REG_SR = 12,
CP0REG_CAUSE = 13,
CP0REG_EPC = 14,
CP0REG_PRID = 15, // Product ID
CP0REG_ERREG = 16
};
struct
{
union
{
uint32_t Regs[32];
struct
{
uint32_t Unused00;
uint32_t Unused01;
uint32_t Unused02;
uint32_t BPC; // RW
uint32_t Unused04;
uint32_t BDA; // RW
uint32_t TAR;
uint32_t DCIC; // RW
uint32_t Unused08;
uint32_t BDAM; // R/W
uint32_t Unused0A;
uint32_t BPCM; // R/W
uint32_t SR; // R/W
uint32_t CAUSE; // R/W(partial)
uint32_t EPC; // R
uint32_t PRID; // R
uint32_t ERREG; // ?(may not exist, test)
};
};
} CP0;
#if 1
//uint32_t WrAbsorb;
//uint8_t WrAbsorbShift;
// On read:
//WrAbsorb = 0;
//WrAbsorbShift = 0;
// On write:
//WrAbsorb >>= (WrAbsorbShift >> 2) & 8;
//WrAbsorbShift -= (WrAbsorbShift >> 2) & 8;
//WrAbsorb |= (timestamp - pre_write_timestamp) << WrAbsorbShift;
//WrAbsorbShift += 8;
#endif
struct
{
uint8_t ReadAbsorb[0x20];
uint8_t ReadAbsorbDummy;
};
uint8_t ReadAbsorbWhich;
uint8_t ReadFudge;
//uint32_t WriteAbsorb;
//uint8_t WriteAbsorbCount;
//uint8_t WriteAbsorbMonkey;
uint8 MULT_Tab24[24];
MultiAccessSizeMem<1024, false> ScratchRAM;
//PS_GTE GTE;
uint8_t *FastMap[1 << (32 - FAST_MAP_SHIFT)];
uint8_t DummyPage[FAST_MAP_PSIZE];
enum
{
EXCEPTION_INT = 0,
EXCEPTION_MOD = 1,
EXCEPTION_TLBL = 2,
EXCEPTION_TLBS = 3,
EXCEPTION_ADEL = 4, // Address error on load
EXCEPTION_ADES = 5, // Address error on store
EXCEPTION_IBE = 6, // Instruction bus error
EXCEPTION_DBE = 7, // Data bus error
EXCEPTION_SYSCALL = 8, // System call
EXCEPTION_BP = 9, // Breakpoint
EXCEPTION_RI = 10, // Reserved instruction
EXCEPTION_COPU = 11, // Coprocessor unusable
EXCEPTION_OV = 12 // Arithmetic overflow
};
uint32_t Exception(uint32_t code, uint32_t PC, const uint32_t NPM) MDFN_WARN_UNUSED_RESULT;
template<bool DebugMode, bool BIOSPrintMode, bool ILHMode> pscpu_timestamp_t RunReal(pscpu_timestamp_t timestamp_in) NO_INLINE;
template<typename T> T PeekMemory(uint32_t address) MDFN_COLD;
template<typename T> T ReadMemory(pscpu_timestamp_t &timestamp, uint32_t address, bool DS24 = false, bool LWC_timing = false);
template<typename T> void WriteMemory(pscpu_timestamp_t &timestamp, uint32_t address, uint32_t value, bool DS24 = false);
//
// Mednafen debugger stuff follows:
//
public:
void SetCPUHook(void (*cpuh)(const pscpu_timestamp_t timestamp, uint32_t pc), void (*addbt)(uint32_t from, uint32_t to, bool exception));
void CheckBreakpoints(void (*callback)(bool write, uint32_t address, unsigned int len), uint32_t instr);
void* debug_GetScratchRAMPtr() { return ScratchRAM.data8; }
void* debug_GetGPRPtr() { return GPR; }
enum
{
GSREG_GPR = 0,
GSREG_PC = 32,
GSREG_PC_NEXT,
GSREG_IN_BD_SLOT,
GSREG_LO,
GSREG_HI,
GSREG_SR,
GSREG_CAUSE,
GSREG_EPC,
};
uint32_t GetRegister(unsigned int which, char *special, const uint32_t special_len);
void SetRegister(unsigned int which, uint32_t value);
bool PeekCheckICache(uint32_t PC, uint32_t *iw);
uint8_t PeekMem8(uint32_t A);
uint16_t PeekMem16(uint32_t A);
uint32_t PeekMem32(uint32_t A);
private:
void (*CPUHook)(const pscpu_timestamp_t timestamp, uint32_t pc);
void (*ADDBT)(uint32_t from, uint32_t to, bool exception);
};
}
#endif
#ifndef __MDFN_PSX_CPU_H
#define __MDFN_PSX_CPU_H
/*
Load delay notes:
// Takes 1 less
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"nop\n\t"
"or %0, %1, %1\n\t"
// cycle than this:
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"or %0, %1, %1\n\t"
"nop\n\t"
// Both of these
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"nop\n\t"
"or %1, %0, %0\n\t"
// take same...(which is kind of odd).
".set noreorder\n\t"
".set nomacro\n\t"
"lw %0, 0(%2)\n\t"
"nop\n\t"
"or %1, %0, %0\n\t"
"nop\n\t"
*/
#include "gte.h"
namespace MDFN_IEN_PSX
{
#define PS_CPU_EMULATE_ICACHE 1
class PS_CPU
{
public:
PS_CPU() MDFN_COLD;
~PS_CPU() MDFN_COLD;
template<bool isReader>void SyncState(EW::NewState *ns);
// FAST_MAP_* enums are in BYTES(8-bit), not in 32-bit units("words" in MIPS context), but the sizes
// will always be multiples of 4.
enum { FAST_MAP_SHIFT = 16 };
enum { FAST_MAP_PSIZE = 1 << FAST_MAP_SHIFT };
void SetFastMap(void *region_mem, uint32 region_address, uint32 region_size);
INLINE void SetEventNT(const pscpu_timestamp_t next_event_ts_arg)
{
next_event_ts = next_event_ts_arg;
}
pscpu_timestamp_t Run(pscpu_timestamp_t timestamp_in, bool BIOSPrintMode, bool ILHMode);
void Power(void) MDFN_COLD;
// which ranges 0-5, inclusive
void AssertIRQ(unsigned which, bool asserted);
void SetHalt(bool status);
// TODO eventually: factor BIU address decoding directly in the CPU core somehow without hurting speed.
void SetBIU(uint32 val);
uint32 GetBIU(void);
private:
uint32 GPR[32 + 1]; // GPR[32] Used as dummy in load delay simulation(indexing past the end of real GPR)
uint32 LO;
uint32 HI;
uint32 BACKED_PC;
uint32 BACKED_new_PC;
uint32 BACKED_new_PC_mask;
uint32 IPCache;
void RecalcIPCache(void);
bool Halted;
uint32 BACKED_LDWhich;
uint32 BACKED_LDValue;
uint32 LDAbsorb;
pscpu_timestamp_t next_event_ts;
pscpu_timestamp_t gte_ts_done;
pscpu_timestamp_t muldiv_ts_done;
uint32 BIU;
struct __ICache
{
uint32 TV;
uint32 Data;
};
union
{
__ICache ICache[1024];
uint32 ICache_Bulk[2048];
};
enum
{
CP0REG_BPC = 3, // PC breakpoint address.
CP0REG_BDA = 5, // Data load/store breakpoint address.
CP0REG_TAR = 6, // Target address(???)
CP0REG_DCIC = 7, // Cache control
CP0REG_BDAM = 9, // Data load/store address mask.
CP0REG_BPCM = 11, // PC breakpoint address mask.
CP0REG_SR = 12,
CP0REG_CAUSE = 13,
CP0REG_EPC = 14,
CP0REG_PRID = 15, // Product ID
CP0REG_ERREG = 16
};
struct
{
union
{
uint32 Regs[32];
struct
{
uint32 Unused00;
uint32 Unused01;
uint32 Unused02;
uint32 BPC; // RW
uint32 Unused04;
uint32 BDA; // RW
uint32 TAR;
uint32 DCIC; // RW
uint32 Unused08;
uint32 BDAM; // R/W
uint32 Unused0A;
uint32 BPCM; // R/W
uint32 SR; // R/W
uint32 CAUSE; // R/W(partial)
uint32 EPC; // R
uint32 PRID; // R
uint32 ERREG; // ?(may not exist, test)
};
};
} CP0;
#if 1
//uint32 WrAbsorb;
//uint8 WrAbsorbShift;
// On read:
//WrAbsorb = 0;
//WrAbsorbShift = 0;
// On write:
//WrAbsorb >>= (WrAbsorbShift >> 2) & 8;
//WrAbsorbShift -= (WrAbsorbShift >> 2) & 8;
//WrAbsorb |= (timestamp - pre_write_timestamp) << WrAbsorbShift;
//WrAbsorbShift += 8;
#endif
uint8 ReadAbsorb[0x20 + 1];
uint8 ReadAbsorbWhich;
uint8 ReadFudge;
//uint32 WriteAbsorb;
//uint8 WriteAbsorbCount;
//uint8 WriteAbsorbMonkey;
uint8 MULT_Tab24[24];
MultiAccessSizeMem<1024, false> ScratchRAM;
//PS_GTE GTE;
uint8 *FastMap[1 << (32 - FAST_MAP_SHIFT)];
uint8 DummyPage[FAST_MAP_PSIZE];
enum
{
EXCEPTION_INT = 0,
EXCEPTION_MOD = 1,
EXCEPTION_TLBL = 2,
EXCEPTION_TLBS = 3,
EXCEPTION_ADEL = 4, // Address error on load
EXCEPTION_ADES = 5, // Address error on store
EXCEPTION_IBE = 6, // Instruction bus error
EXCEPTION_DBE = 7, // Data bus error
EXCEPTION_SYSCALL = 8, // System call
EXCEPTION_BP = 9, // Breakpoint
EXCEPTION_RI = 10, // Reserved instruction
EXCEPTION_COPU = 11, // Coprocessor unusable
EXCEPTION_OV = 12 // Arithmetic overflow
};
uint32 Exception(uint32 code, uint32 PC, const uint32 NPM) MDFN_WARN_UNUSED_RESULT;
template<bool DebugMode, bool BIOSPrintMode, bool ILHMode> pscpu_timestamp_t RunReal(pscpu_timestamp_t timestamp_in) NO_INLINE;
template<typename T> T PeekMemory(uint32 address) MDFN_COLD;
template<typename T> T ReadMemory(pscpu_timestamp_t &timestamp, uint32 address, bool DS24 = false, bool LWC_timing = false);
template<typename T> void WriteMemory(pscpu_timestamp_t &timestamp, uint32 address, uint32 value, bool DS24 = false);
//
// Mednafen debugger stuff follows:
//
public:
void SetCPUHook(void (*cpuh)(const pscpu_timestamp_t timestamp, uint32 pc), void (*addbt)(uint32 from, uint32 to, bool exception));
void CheckBreakpoints(void (*callback)(bool write, uint32 address, unsigned int len), uint32 instr);
void* debug_GetScratchRAMPtr() { return ScratchRAM.data8; }
void* debug_GetGPRPtr() { return GPR; }
enum
{
GSREG_GPR = 0,
GSREG_PC = 32,
GSREG_PC_NEXT,
GSREG_IN_BD_SLOT,
GSREG_LO,
GSREG_HI,
GSREG_SR,
GSREG_CAUSE,
GSREG_EPC,
};
uint32 GetRegister(unsigned int which, char *special, const uint32 special_len);
void SetRegister(unsigned int which, uint32 value);
bool PeekCheckICache(uint32 PC, uint32 *iw);
uint8 PeekMem8(uint32 A);
uint16 PeekMem16(uint32 A);
uint32 PeekMem32(uint32 A);
private:
void (*CPUHook)(const pscpu_timestamp_t timestamp, uint32 pc);
void (*ADDBT)(uint32 from, uint32 to, bool exception);
};
}
#endif

View File

@ -20,10 +20,6 @@
#include "cdc.h"
#include "spu.h"
//#include <map>
// Notes: DMA tested to abort when
/* Notes:
Channel 4(SPU):
@ -84,7 +80,7 @@ static Channel DMACH[7];
static pscpu_timestamp_t lastts;
static const char *PrettyChannelNames[7] = { "MDEC IN", "MDEC OUT", "GPU", "CDC", "SPU", "PIO", "OTC" };
// static const char *PrettyChannelNames[7] = { "MDEC IN", "MDEC OUT", "GPU", "CDC", "SPU", "PIO", "OTC" };
void DMA_Init(void)
{
@ -96,17 +92,17 @@ void DMA_Kill(void)
}
static INLINE void RecalcIRQOut(void)
{
bool irqo;
irqo = (bool)DMAIntStatus;
irqo &= (DMAIntControl >> 23) & 1;
irqo |= (DMAIntControl >> 15) & 1;
IRQOut = irqo;
IRQ_Assert(IRQ_DMA, irqo);
}
static INLINE void RecalcIRQOut(void)
{
bool irqo;
irqo = (bool)DMAIntStatus;
irqo &= (DMAIntControl >> 23) & 1;
irqo |= (DMAIntControl >> 15) & 1;
IRQOut = irqo;
IRQ_Assert(IRQ_DMA, irqo);
}
void DMA_ResetTS(void)
{
@ -127,8 +123,6 @@ void DMA_Power(void)
RecalcIRQOut();
}
void PSX_SetDMASuckSuck(unsigned);
static INLINE bool ChCan(const unsigned ch, const uint32 CRModeCache)
{
switch(ch)
@ -226,19 +220,16 @@ static void RecalcHalt(void)
if(tmp > 0)
tmp--;
if(tmp > 200) // Due to 8-bit limitations in the CPU core.
tmp = 200;
PSX_SetDMASuckSuck(tmp);
PSX_SetDMACycleSteal(tmp);
}
else
PSX_SetDMASuckSuck(0);
PSX_SetDMACycleSteal(0);
CPU->SetHalt(Halt);
}
static INLINE void ChRW(const unsigned ch, const uint32 CRModeCache, uint32 *V, int32 *offset)
static INLINE void ChRW(const unsigned ch, const uint32 CRModeCache, uint32 *V, uint32 *offset)
{
unsigned extra_cyc_overhead = 0;
@ -424,7 +415,7 @@ static INLINE void RunChannelI(const unsigned ch, const uint32 CRModeCache, int3
//
{
uint32 vtmp;
int32 voffs = 0;
uint32 voffs = 0;
if(MDFN_UNLIKELY(DMACH[ch].CurAddr & 0x800000))
{
@ -626,143 +617,142 @@ static void CheckLinkedList(uint32 addr)
}
#endif
void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
{
int ch = (A & 0x7F) >> 4;
//if(ch == 2 || ch == 7)
//PSX_WARNING("[DMA] Write: %08x %08x, DMAIntStatus=%08x", A, V, DMAIntStatus);
// FIXME if we ever have "accurate" bus emulation
V <<= (A & 3) * 8;
DMA_Update(timestamp);
if(ch == 7)
{
switch(A & 0xC)
{
case 0x0: //fprintf(stderr, "Global DMA control: 0x%08x\n", V);
DMAControl = V;
RecalcHalt();
break;
case 0x4:
DMAIntControl = V & 0x00ff803f;
DMAIntStatus &= ~(V >> 24);
RecalcIRQOut();
break;
default: PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V);
break;
}
return;
}
switch(A & 0xC)
{
case 0x0: DMACH[ch].BaseAddr = V & 0xFFFFFF;
break;
case 0x4: DMACH[ch].BlockControl = V;
break;
case 0xC:
case 0x8:
{
uint32 OldCC = DMACH[ch].ChanControl;
//printf("CHCR: %u, %08x --- 0x%08x\n", ch, V, DMACH[ch].BlockControl);
//
// Kludge for DMA timing granularity and other issues. Needs to occur before setting all bits of ChanControl to the new value, to accommodate the
// case of a game cancelling DMA and changing the type of DMA(read/write, etc.) at the same time.
//
if((DMACH[ch].ChanControl & (1 << 24)) && !(V & (1 << 24)))
{
DMACH[ch].ChanControl &= ~(1 << 24); // Clear bit before RunChannel(), so it will only finish the block it's on at most.
RunChannel(timestamp, 128 * 16, ch);
DMACH[ch].WordCounter = 0;
#if 0 // TODO(maybe, need to work out worst-case performance for abnormally/brokenly large block sizes)
DMACH[ch].ClockCounter = (1 << 30);
RunChannel(timestamp, 1, ch);
DMACH[ch].ClockCounter = 0;
#endif
PSX_WARNING("[DMA] Forced stop for channel %d -- scanline=%d", ch, GPU->GetScanlineNum());
//MDFN_DispMessage("[DMA] Forced stop for channel %d", ch);
}
if(ch == 6)
DMACH[ch].ChanControl = (V & 0x51000000) | 0x2;
else
DMACH[ch].ChanControl = V & 0x71770703;
if(!(OldCC & (1 << 24)) && (V & (1 << 24)))
{
//if(ch == 0 || ch == 1)
// PSX_WARNING("[DMA] Started DMA for channel=%d --- CHCR=0x%08x --- BCR=0x%08x --- scanline=%d", ch, DMACH[ch].ChanControl, DMACH[ch].BlockControl, GPU->GetScanlineNum());
DMACH[ch].WordCounter = 0;
DMACH[ch].ClockCounter = 0;
//
// Viewpoint starts a short MEM->GPU LL DMA and apparently has race conditions that can cause a crash if it doesn't finish almost immediately(
// or at least very quickly, which the current DMA granularity has issues with, so run the channel ahead a bit to take of this issue and potentially
// games with similar issues).
//
// Though, Viewpoint isn't exactly a good game, so maybe we shouldn't bother? ;)
//
// Also, it's needed for RecalcHalt() to work with some semblance of workiness.
//
RunChannel(timestamp, 64, ch); //std::max<int>(128 - DMACycleCounter, 1)); //64); //1); //128 - DMACycleCounter);
}
RecalcHalt();
}
break;
}
PSX_SetEventNT(PSX_EVENT_DMA, timestamp + CalcNextEvent(0x10000000));
}
uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A)
{
int ch = (A & 0x7F) >> 4;
uint32 ret = 0;
if(ch == 7)
{
switch(A & 0xC)
{
default: PSX_WARNING("[DMA] Unknown read: %08x", A);
break;
case 0x0: ret = DMAControl;
break;
case 0x4: ret = DMAIntControl | (DMAIntStatus << 24) | (IRQOut << 31);
break;
}
}
else switch(A & 0xC)
{
case 0x0: ret = DMACH[ch].BaseAddr;
break;
case 0x4: ret = DMACH[ch].BlockControl;
break;
case 0xC:
case 0x8: ret = DMACH[ch].ChanControl;
break;
}
ret >>= (A & 3) * 8;
//PSX_WARNING("[DMA] Read: %08x %08x", A, ret);
return(ret);
}
void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
{
int ch = (A & 0x7F) >> 4;
//if(ch == 2 || ch == 7)
//PSX_WARNING("[DMA] Write: %08x %08x, DMAIntStatus=%08x", A, V, DMAIntStatus);
// FIXME if we ever have "accurate" bus emulation
V <<= (A & 3) * 8;
DMA_Update(timestamp);
if(ch == 7)
{
switch(A & 0xC)
{
case 0x0: //fprintf(stderr, "Global DMA control: 0x%08x\n", V);
DMAControl = V;
RecalcHalt();
break;
case 0x4:
DMAIntControl = V & 0x00ff803f;
DMAIntStatus &= ~(V >> 24);
RecalcIRQOut();
break;
default: PSX_WARNING("[DMA] Unknown write: %08x %08x", A, V);
break;
}
return;
}
switch(A & 0xC)
{
case 0x0: DMACH[ch].BaseAddr = V & 0xFFFFFF;
break;
case 0x4: DMACH[ch].BlockControl = V;
break;
case 0xC:
case 0x8:
{
uint32 OldCC = DMACH[ch].ChanControl;
//printf("CHCR: %u, %08x --- 0x%08x\n", ch, V, DMACH[ch].BlockControl);
//
// Kludge for DMA timing granularity and other issues. Needs to occur before setting all bits of ChanControl to the new value, to accommodate the
// case of a game cancelling DMA and changing the type of DMA(read/write, etc.) at the same time.
//
if((DMACH[ch].ChanControl & (1 << 24)) && !(V & (1 << 24)))
{
DMACH[ch].ChanControl &= ~(1 << 24); // Clear bit before RunChannel(), so it will only finish the block it's on at most.
RunChannel(timestamp, 128 * 16, ch);
DMACH[ch].WordCounter = 0;
#if 0 // TODO(maybe, need to work out worst-case performance for abnormally/brokenly large block sizes)
DMACH[ch].ClockCounter = (1 << 30);
RunChannel(timestamp, 1, ch);
DMACH[ch].ClockCounter = 0;
#endif
PSX_WARNING("[DMA] Forced stop for channel %d -- scanline=%d", ch, GPU->GetScanlineNum());
//MDFN_DispMessage("[DMA] Forced stop for channel %d", ch);
}
if(ch == 6)
DMACH[ch].ChanControl = (V & 0x51000000) | 0x2;
else
DMACH[ch].ChanControl = V & 0x71770703;
if(!(OldCC & (1 << 24)) && (V & (1 << 24)))
{
//if(ch == 0 || ch == 1)
// PSX_WARNING("[DMA] Started DMA for channel=%d --- CHCR=0x%08x --- BCR=0x%08x --- scanline=%d", ch, DMACH[ch].ChanControl, DMACH[ch].BlockControl, GPU->GetScanlineNum());
DMACH[ch].WordCounter = 0;
DMACH[ch].ClockCounter = 0;
//
// Viewpoint starts a short MEM->GPU LL DMA and apparently has race conditions that can cause a crash if it doesn't finish almost immediately(
// or at least very quickly, which the current DMA granularity has issues with, so run the channel ahead a bit to take of this issue and potentially
// games with similar issues).
//
// Though, Viewpoint isn't exactly a good game, so maybe we shouldn't bother? ;)
//
// Also, it's needed for RecalcHalt() to work with some semblance of workiness.
//
RunChannel(timestamp, 64, ch); //std::max<int>(128 - DMACycleCounter, 1)); //64); //1); //128 - DMACycleCounter);
}
RecalcHalt();
}
break;
}
PSX_SetEventNT(PSX_EVENT_DMA, timestamp + CalcNextEvent(0x10000000));
}
uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A)
{
int ch = (A & 0x7F) >> 4;
uint32 ret = 0;
if(ch == 7)
{
switch(A & 0xC)
{
default: PSX_WARNING("[DMA] Unknown read: %08x", A);
break;
case 0x0: ret = DMAControl;
break;
case 0x4: ret = DMAIntControl | (DMAIntStatus << 24) | (IRQOut << 31);
break;
}
}
else switch(A & 0xC)
{
case 0x0: ret = DMACH[ch].BaseAddr;
break;
case 0x4: ret = DMACH[ch].BlockControl;
break;
case 0xC:
case 0x8: ret = DMACH[ch].ChanControl;
break;
}
ret >>= (A & 3) * 8;
//PSX_WARNING("[DMA] Read: %08x %08x", A, ret);
return(ret);
}
void DMA_SyncState(bool isReader, EW::NewState *ns)

View File

@ -4,18 +4,16 @@
namespace MDFN_IEN_PSX
{
bool DMA_GPUWriteActive(void);
pscpu_timestamp_t DMA_Update(const pscpu_timestamp_t timestamp);
void DMA_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
uint32 DMA_Read(const pscpu_timestamp_t timestamp, uint32 A);
void DMA_ResetTS(void);
void DMA_Power(void) MDFN_COLD;
void DMA_Init(void) MDFN_COLD;
void DMA_Kill(void) MDFN_COLD;
void DMA_Power(void) MDFN_COLD;
void DMA_Init(void) MDFN_COLD;
void DMA_Kill(void) MDFN_COLD;

View File

@ -15,6 +15,8 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include "psx.h"
#include "frontio.h"

File diff suppressed because it is too large Load Diff

View File

@ -3,7 +3,7 @@
#pragma once
#include "cdrom/SimpleFIFO.h"
#include "FastFIFO.h"
#include "git.h"
struct ShockRenderOptions;
@ -72,7 +72,7 @@ class PS_GPU
if(InCmd & (INCMD_FBREAD | INCMD_FBWRITE))
return(false);
if(BlitterFIFO.CanRead() >= Commands[BlitterFIFO.ReadUnit(true) >> 24].fifo_fb_len)
if(BlitterFIFO.CanRead() >= Commands[BlitterFIFO.Peek() >> 24].fifo_fb_len)
return(false);
return(true);
@ -155,18 +155,21 @@ class PS_GPU
int32 OffsX;
int32 OffsY;
bool dtd;
bool dfe;
uint32 MaskSetOR;
uint32 MaskEvalAND;
uint8 tww, twh, twx, twy;
int32 TexPageX;
int32 TexPageY;
bool dtd;
bool dfe;
uint32 MaskSetOR;
uint32 MaskEvalAND;
bool TexDisable;
bool TexDisableAllowChange;
uint8 tww, twh, twx, twy;
uint32 TexPageX;
uint32 TexPageY;
uint32 SpriteFlip;
uint32 abr;
@ -230,9 +233,9 @@ class PS_GPU
static const CTEntry Commands_60_7F[0x20];
static const CTEntry Commands_80_FF[0x80];
SimpleFIFO<uint32> BlitterFIFO;
uint32 DataReadBuffer;
FastFIFO<uint32, 0x20> BlitterFIFO; // 0x10 on actual PS1 GPU, 0x20 here(see comment at top of gpu.h)
uint32 DataReadBuffer;
uint32 DataReadBufferEx;
bool IRQPending;
//

View File

@ -17,6 +17,7 @@
#include "psx.h"
#include "gpu.h"
#include "math_ops.h"
namespace MDFN_IEN_PSX
{
@ -24,8 +25,8 @@ namespace MDFN_IEN_PSX
struct line_fxp_coord
{
int64 x, y;
int32 r, g, b;
uint64 x, y;
uint32 r, g, b;
};
struct line_fxp_step
@ -40,8 +41,8 @@ enum { Line_RGB_FractBits = 12 };
template<bool goraud>
static INLINE void LinePointToFXPCoord(const line_point &point, const line_fxp_step &step, line_fxp_coord &coord)
{
coord.x = ((int64)point.x << Line_XY_FractBits) | (1LL << (Line_XY_FractBits - 1));
coord.y = ((int64)point.y << Line_XY_FractBits) | (1LL << (Line_XY_FractBits - 1));
coord.x = ((uint64)point.x << Line_XY_FractBits) | (1ULL << (Line_XY_FractBits - 1));
coord.y = ((uint64)point.y << Line_XY_FractBits) | (1ULL << (Line_XY_FractBits - 1));
coord.x -= 1024;
@ -56,10 +57,9 @@ static INLINE void LinePointToFXPCoord(const line_point &point, const line_fxp_s
}
}
template<typename T, unsigned bits>
static INLINE T LineDivide(T delta, int32 dk)
static INLINE int64 LineDivide(int64 delta, int32 dk)
{
delta <<= bits;
delta = (uint64)delta << Line_XY_FractBits;
if(delta < 0)
delta -= dk - 1;
@ -86,28 +86,28 @@ static INLINE void LinePointsToFXPStep(const line_point &point0, const line_poin
return;
}
step.dx_dk = LineDivide<int64, Line_XY_FractBits>(point1.x - point0.x, dk);
step.dy_dk = LineDivide<int64, Line_XY_FractBits>(point1.y - point0.y, dk);
step.dx_dk = LineDivide(point1.x - point0.x, dk);
step.dy_dk = LineDivide(point1.y - point0.y, dk);
if(goraud)
{
step.dr_dk = ((point1.r - point0.r) << Line_RGB_FractBits) / dk;
step.dg_dk = ((point1.g - point0.g) << Line_RGB_FractBits) / dk;
step.db_dk = ((point1.b - point0.b) << Line_RGB_FractBits) / dk;
step.dr_dk = (int32)((uint32)(point1.r - point0.r) << Line_RGB_FractBits) / dk;
step.dg_dk = (int32)((uint32)(point1.g - point0.g) << Line_RGB_FractBits) / dk;
step.db_dk = (int32)((uint32)(point1.b - point0.b) << Line_RGB_FractBits) / dk;
}
}
template<bool goraud>
static INLINE void AddLineStep(line_fxp_coord &point, const line_fxp_step &step, int32 count = 1)
static INLINE void AddLineStep(line_fxp_coord &point, const line_fxp_step &step)
{
point.x += step.dx_dk * count;
point.y += step.dy_dk * count;
point.x += step.dx_dk;
point.y += step.dy_dk;
if(goraud)
{
point.r += step.dr_dk * count;
point.g += step.dg_dk * count;
point.b += step.db_dk * count;
point.r += step.dr_dk;
point.g += step.dg_dk;
point.b += step.db_dk;
}
}
@ -125,19 +125,12 @@ void PS_GPU::DrawLine(line_point *points)
k = (i_dx > i_dy) ? i_dx : i_dy;
if(i_dx >= 1024)
{
PSX_DBG(PSX_DBG_WARNING, "[GPU] Line too long: i_dx=%d\n", i_dx);
return;
}
if(i_dy >= 512)
{
PSX_DBG(PSX_DBG_WARNING, "[GPU] Line too long: i_dy=%d\n", i_dy);
return;
}
// May not be correct(do tests for the case of k == i_dy on real thing.
if(points[0].x > points[1].x)
if(points[0].x >= points[1].x && k)
{
line_point tmp = points[1];
@ -145,7 +138,7 @@ void PS_GPU::DrawLine(line_point *points)
points[0] = tmp;
}
DrawTimeAvail -= k * ((BlendMode >= 0) ? 2 : 1);
DrawTimeAvail -= k * 2;
//
//
@ -181,7 +174,7 @@ void PS_GPU::DrawLine(line_point *points)
b = points[0].b;
}
if(goraud && dtd)
if(dtd)
{
pix |= DitherLUT[y & 3][x & 3][r] << 0;
pix |= DitherLUT[y & 3][x & 3][g] << 5;

View File

@ -19,6 +19,7 @@
#include "psx.h"
#include "gpu.h"
#include "math_ops.h"
namespace MDFN_IEN_PSX
{
@ -406,7 +407,7 @@ INLINE void PS_GPU::DrawTriangle(tri_vertex *vertices)
tp->x_step[right_facing] = bound_coord_us;
tp->x_coord[!right_facing] = base_coord + ((vertices[vo].y - vertices[0].y) * base_step);
tp->x_step[!right_facing] = base_step;
tp->dec_mode = !!vo;
tp->dec_mode = vo;
}
{
@ -418,7 +419,7 @@ INLINE void PS_GPU::DrawTriangle(tri_vertex *vertices)
tp->x_step[right_facing] = bound_coord_ls;
tp->x_coord[!right_facing] = base_coord + ((vertices[1 ^ vp].y - vertices[0].y) * base_step); //base_coord + ((vertices[1].y - vertices[0].y) * base_step);
tp->x_step[!right_facing] = base_step;
tp->dec_mode = !!vp;
tp->dec_mode = vp;
}
for(unsigned i = 0; i < 2; i++) //2; i++)

View File

@ -17,6 +17,7 @@
#include "psx.h"
#include "gpu.h"
#include "math_ops.h"
namespace MDFN_IEN_PSX
{

View File

@ -17,6 +17,7 @@
// I could find no other commands than 'R', 'W', and 'S' (not sure what 'S' is for, however)
#include <assert.h>
#include "../psx.h"
#include "../frontio.h"
#include "memcard.h"
@ -309,220 +310,215 @@ bool InputDevice_Memcard::Clock(bool TxD, int32 &dsr_pulse_delay)
}
switch(command_phase)
{
case 0:
if(receive_buffer != 0x81)
command_phase = -1;
else
{
//printf("[MCR] Device selected\n");
transmit_buffer = presence_new ? 0x08 : 0x00;
transmit_count = 1;
command_phase++;
}
break;
case 1:
command = receive_buffer;
//printf("[MCR] Command received: %c\n", command);
if(command == 'R' || command == 'W')
{
command_phase++;
transmit_buffer = 0x5A;
transmit_count = 1;
}
else
{
if(command == 'S')
{
PSX_WARNING("[MCR] Memcard S command unsupported.");
}
command_phase = -1;
transmit_buffer = 0;
transmit_count = 0;
}
break;
case 2:
transmit_buffer = 0x5D;
transmit_count = 1;
command_phase++;
break;
case 3:
transmit_buffer = 0x00;
transmit_count = 1;
if(command == 'R')
command_phase = 1000;
else if(command == 'W')
command_phase = 2000;
break;
//
// Read
//
case 1000:
addr = receive_buffer << 8;
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase++;
break;
case 1001:
addr |= receive_buffer & 0xFF;
transmit_buffer = '\\';
transmit_count = 1;
command_phase++;
break;
case 1002:
//printf("[MCR] READ ADDR=0x%04x\n", addr);
if(addr >= (sizeof(card_data) >> 7))
addr = 0xFFFF;
calced_xor = 0;
transmit_buffer = ']';
transmit_count = 1;
command_phase++;
// TODO: enable this code(or something like it) when CPU instruction timing is a bit better.
//
//dsr_pulse_delay = 32000;
//goto SkipDPD;
//
break;
case 1003:
transmit_buffer = addr >> 8;
calced_xor ^= transmit_buffer;
transmit_count = 1;
command_phase++;
break;
case 1004:
transmit_buffer = addr & 0xFF;
calced_xor ^= transmit_buffer;
if(addr == 0xFFFF)
{
transmit_count = 1;
command_phase = -1;
}
else
{
transmit_count = 1;
command_phase = 1024;
}
break;
// Transmit actual 128 bytes data
//case (1024 + 0) ... (1024 + 128 - 1):
BIGCASE128(1024)
transmit_buffer = card_data[(addr << 7) + (command_phase - 1024)];
calced_xor ^= transmit_buffer;
transmit_count = 1;
command_phase++;
break;
// XOR
case (1024 + 128):
transmit_buffer = calced_xor;
transmit_count = 1;
command_phase++;
break;
// End flag
case (1024 + 129):
transmit_buffer = 'G';
transmit_count = 1;
command_phase = -1;
break;
//
// Write
//
case 2000:
calced_xor = receive_buffer;
addr = receive_buffer << 8;
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase++;
break;
case 2001:
calced_xor ^= receive_buffer;
addr |= receive_buffer & 0xFF;
//printf("[MCR] WRITE ADDR=0x%04x\n", addr);
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase = 2048;
break;
//case (2048 + 0) ... (2048 + 128 - 1):
BIGCASE128(2048)
calced_xor ^= receive_buffer;
rw_buffer[command_phase - 2048] = receive_buffer;
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase++;
break;
case (2048 + 128): // XOR
write_xor = receive_buffer;
transmit_buffer = '\\';
transmit_count = 1;
command_phase++;
break;
case (2048 + 129):
transmit_buffer = ']';
transmit_count = 1;
command_phase++;
break;
case (2048 + 130): // End flag
//MDFN_DispMessage("%02x %02x", calced_xor, write_xor);
//printf("[MCR] Write End. Actual_XOR=0x%02x, CW_XOR=0x%02x\n", calced_xor, write_xor);
if(calced_xor != write_xor)
transmit_buffer = 'N';
else if(addr >= (sizeof(card_data) >> 7))
transmit_buffer = 0xFF;
else
{
transmit_buffer = 'G';
presence_new = false;
// If the current data is different from the data to be written, increment the dirty count.
// memcpy()'ing over to card_data is also conditionalized here for a slight optimization.
if(memcmp(&card_data[addr << 7], rw_buffer, 128))
{
memcpy(&card_data[addr << 7], rw_buffer, 128);
dirty_count++;
data_used = true;
}
}
transmit_count = 1;
command_phase = -1;
break;
}
//if(command_phase != -1 || transmit_count)
// printf("[MCR] Receive: 0x%02x, Send: 0x%02x -- %d\n", receive_buffer, transmit_buffer, command_phase);
}
if(!bitpos && transmit_count)
dsr_pulse_delay = 0x100;
//SkipDPD: ;
return(ret);
if(command_phase == 0)
{
if(receive_buffer != 0x81)
command_phase = -1;
else
{
//printf("[MCR] Device selected\n");
transmit_buffer = presence_new ? 0x08 : 0x00;
transmit_count = 1;
command_phase++;
}
}
else if(command_phase == 1)
{
command = receive_buffer;
//printf("[MCR] Command received: %c\n", command);
if(command == 'R' || command == 'W')
{
command_phase++;
transmit_buffer = 0x5A;
transmit_count = 1;
}
else
{
if(command == 'S')
{
PSX_WARNING("[MCR] Memcard S command unsupported.");
}
command_phase = -1;
transmit_buffer = 0;
transmit_count = 0;
}
}
else if(command_phase == 2)
{
transmit_buffer = 0x5D;
transmit_count = 1;
command_phase++;
}
else if(command_phase == 3)
{
transmit_buffer = 0x00;
transmit_count = 1;
if(command == 'R')
command_phase = 1000;
else if(command == 'W')
command_phase = 2000;
}
//
// Read
//
else if(command_phase == 1000)
{
addr = receive_buffer << 8;
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase++;
}
else if(command_phase == 1001)
{
addr |= receive_buffer & 0xFF;
transmit_buffer = '\\';
transmit_count = 1;
command_phase++;
}
else if(command_phase == 1002)
{
//printf("[MCR] READ ADDR=0x%04x\n", addr);
if(addr >= (sizeof(card_data) >> 7))
addr = 0xFFFF;
calced_xor = 0;
transmit_buffer = ']';
transmit_count = 1;
command_phase++;
// TODO: enable this code(or something like it) when CPU instruction timing is a bit better.
//
//dsr_pulse_delay = 32000;
//goto SkipDPD;
//
}
else if(command_phase == 1003)
{
transmit_buffer = addr >> 8;
calced_xor ^= transmit_buffer;
transmit_count = 1;
command_phase++;
}
else if(command_phase == 1004)
{
transmit_buffer = addr & 0xFF;
calced_xor ^= transmit_buffer;
if(addr == 0xFFFF)
{
transmit_count = 1;
command_phase = -1;
}
else
{
transmit_count = 1;
command_phase = 1024;
}
}
// Transmit actual 128 bytes data
else if(command_phase >= (1024 + 0) && command_phase <= (1024 + 128 - 1))
{
transmit_buffer = card_data[(addr << 7) + (command_phase - 1024)];
calced_xor ^= transmit_buffer;
transmit_count = 1;
command_phase++;
}
// XOR
else if(command_phase == (1024 + 128))
{
transmit_buffer = calced_xor;
transmit_count = 1;
command_phase++;
}
// End flag
else if(command_phase == (1024 + 129))
{
transmit_buffer = 'G';
transmit_count = 1;
command_phase = -1;
}
//
// Write
//
else if(command_phase == 2000)
{
calced_xor = receive_buffer;
addr = receive_buffer << 8;
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase++;
}
else if(command_phase == 2001)
{
calced_xor ^= receive_buffer;
addr |= receive_buffer & 0xFF;
//printf("[MCR] WRITE ADDR=0x%04x\n", addr);
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase = 2048;
}
else if(command_phase >= (2048 + 0) && command_phase <= (2048 + 128 - 1))
{
calced_xor ^= receive_buffer;
rw_buffer[command_phase - 2048] = receive_buffer;
transmit_buffer = receive_buffer;
transmit_count = 1;
command_phase++;
}
else if(command_phase == (2048 + 128)) // XOR
{
write_xor = receive_buffer;
transmit_buffer = '\\';
transmit_count = 1;
command_phase++;
}
else if(command_phase == (2048 + 129))
{
transmit_buffer = ']';
transmit_count = 1;
command_phase++;
}
else if(command_phase == (2048 + 130)) // End flag
{
//MDFN_DispMessage("%02x %02x", calced_xor, write_xor);
//printf("[MCR] Write End. Actual_XOR=0x%02x, CW_XOR=0x%02x\n", calced_xor, write_xor);
if(calced_xor != write_xor)
transmit_buffer = 'N';
else if(addr >= (sizeof(card_data) >> 7))
transmit_buffer = 0xFF;
else
{
transmit_buffer = 'G';
presence_new = false;
// If the current data is different from the data to be written, increment the dirty count.
// memcpy()'ing over to card_data is also conditionalized here for a slight optimization.
if(memcmp(&card_data[addr << 7], rw_buffer, 128))
{
memcpy(&card_data[addr << 7], rw_buffer, 128);
dirty_count++;
data_used = true;
}
}
transmit_count = 1;
command_phase = -1;
}
//if(command_phase != -1 || transmit_count)
// printf("[MCR] Receive: 0x%02x, Send: 0x%02x -- %d\n", receive_buffer, transmit_buffer, command_phase);
}
if(!bitpos && transmit_count)
dsr_pulse_delay = 0x100;
//SkipDPD: ;
return(ret);
}
uint32 InputDevice_Memcard::GetNVSize(void)

View File

@ -15,6 +15,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include "../psx.h"
#include "../frontio.h"
#include "multitap.h"
@ -128,11 +129,12 @@ void InputDevice_Multitap::Power(void)
full_mode = false;
full_mode_setting = false;
prev_fm_success = false;
memset(sb, 0, sizeof(sb));
fm_dp = 0;
memset(fm_buffer, 0, sizeof(fm_buffer));
fm_deferred_error_temp = false;
fm_deferred_error = false;
fm_command_error = false;
for(int i = 0; i < 4; i++)
{
@ -241,40 +243,50 @@ pscpu_timestamp_t InputDevice_Multitap::GPULineHook(const pscpu_timestamp_t line
return(ret);
}
void InputDevice_Multitap::SetDTR(bool new_dtr)
{
bool old_dtr = dtr;
dtr = new_dtr;
if(!dtr)
{
if(old_dtr)
{
//printf("Multitap stop.\n");
}
bit_counter = 0;
receive_buffer = 0;
selected_device = -1;
mc_mode = false;
full_mode = false;
}
if(!old_dtr && dtr)
{
full_mode = full_mode_setting;
byte_counter = 0;
//if(full_mode)
// printf("Multitap start: %d\n", full_mode);
}
for(int i = 0; i < 4; i++)
{
pad_devices[i]->SetDTR(dtr);
mc_devices[i]->SetDTR(dtr);
}
void InputDevice_Multitap::SetDTR(bool new_dtr)
{
bool old_dtr = dtr;
dtr = new_dtr;
if(!dtr)
{
if(old_dtr)
{
//printf("Multitap stop.\n");
}
bit_counter = 0;
receive_buffer = 0;
selected_device = -1;
mc_mode = false;
full_mode = false;
}
if(!old_dtr && dtr)
{
full_mode = full_mode_setting;
if(!prev_fm_success)
{
memset(sb, 0, sizeof(sb));
for(unsigned i = 0; i < 4; i++)
sb[i][0] = 0x42;
}
prev_fm_success = false;
byte_counter = 0;
//if(full_mode)
// printf("Multitap start: %d\n", full_mode);
}
for(int i = 0; i < 4; i++)
{
pad_devices[i]->SetDTR(dtr);
mc_devices[i]->SetDTR(dtr);
}
}
bool InputDevice_Multitap::GetDSR(void)
@ -282,213 +294,209 @@ bool InputDevice_Multitap::GetDSR(void)
return(0);
}
bool InputDevice_Multitap::Clock(bool TxD, int32 &dsr_pulse_delay)
{
if(!dtr)
return(1);
bool ret = 1;
int32 tmp_pulse_delay[2][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
//printf("Receive bit: %d\n", TxD);
//printf("TxD %d\n", TxD);
receive_buffer &= ~ (1 << bit_counter);
receive_buffer |= TxD << bit_counter;
if(1)
{
if(byte_counter == 0)
{
bool mangled_txd = TxD;
if(bit_counter < 4)
mangled_txd = (0x01 >> bit_counter) & 1;
for(unsigned i = 0; i < 4; i++)
{
pad_devices[i]->Clock(mangled_txd, tmp_pulse_delay[0][i]);
mc_devices[i]->Clock(mangled_txd, tmp_pulse_delay[1][i]);
}
}
else
{
if(full_mode)
{
if(byte_counter == 1)
{
ret = (0x80 >> bit_counter) & 1;
for(unsigned i = 0; i < 4; i++)
{
fm_buffer[i][0] &= (pad_devices[i]->Clock(TxD, tmp_pulse_delay[0][i]) << bit_counter) | (~(1U << bit_counter));
}
}
else if(byte_counter == 2)
{
ret = (0x5A >> bit_counter) & 1;
}
// || byte_counter == (0x03 + 0x08 * 1) || byte_counter == (0x03 + 0x08 * 2) || byte_counter == (0x03 + 0x08 * 3))
else if(byte_counter >= 0x03 && byte_counter < 0x03 + 0x08 * 4)
{
if(!fm_command_error && byte_counter >= (0x03 + 1) && byte_counter < (0x03 + 0x08))
{
for(unsigned i = 0; i < 4; i++)
{
fm_buffer[i][byte_counter - 0x03] &= (pad_devices[i]->Clock(0, tmp_pulse_delay[0][i]) << bit_counter) | (~(1U << bit_counter));
}
}
ret &= ((&fm_buffer[0][0])[byte_counter - 0x03] >> bit_counter) & 1;
}
}
else // to if(full_mode)
{
if((unsigned)selected_device < 4)
{
ret &= pad_devices[selected_device]->Clock(TxD, tmp_pulse_delay[0][selected_device]);
ret &= mc_devices[selected_device]->Clock(TxD, tmp_pulse_delay[1][selected_device]);
}
}
} // end else to if(byte_counter == 0)
}
//
//
//
bit_counter = (bit_counter + 1) & 0x7;
if(bit_counter == 0)
{
//printf("Receive: 0x%02x\n", receive_buffer);
if(byte_counter == 0)
{
mc_mode = (bool)(receive_buffer & 0xF0);
if(mc_mode)
full_mode = false;
//printf("Zoomba: 0x%02x\n", receive_buffer);
//printf("Full mode: %d %d %d\n", full_mode, bit_counter, byte_counter);
if(full_mode)
{
memset(fm_buffer, 0xFF, sizeof(fm_buffer));
selected_device = 0;
}
else
{
//printf("Device select: %02x\n", receive_buffer);
fm_deferred_error = false;
selected_device = ((receive_buffer & 0xF) - 1) & 0xFF;
}
}
if(byte_counter == 1)
{
command = receive_buffer;
//printf("Multitap sub-command: %02x\n", command);
if(full_mode)
{
if(command != 0x42)
fm_command_error = true;
else
fm_command_error = fm_deferred_error;
}
else
{
fm_command_error = false;
}
fm_deferred_error = false;
}
if((!mc_mode || full_mode) && byte_counter == 2)
{
//printf("Full mode setting: %02x\n", receive_buffer);
full_mode_setting = receive_buffer & 0x01;
}
if(full_mode)
{
if(byte_counter == (3 + 8 * 0) || byte_counter == (3 + 8 * 1) || byte_counter == (3 + 8 * 2) || byte_counter == (3 + 8 * 3))
{
unsigned index = (byte_counter - 3) >> 3;
assert(index < 4);
if(index == 0)
fm_deferred_error_temp = false;
if((fm_dp & (1U << index)) && receive_buffer != 0x42)
{
//printf("Multitap command check failed: %u, 0x%02x\n", byte_counter, receive_buffer);
fm_deferred_error_temp = true;
}
}
if(byte_counter == 33)
fm_deferred_error = fm_deferred_error_temp;
}
// Handle DSR stuff
if(full_mode)
{
if(byte_counter == 0) // Next byte: 0x80
{
dsr_pulse_delay = 1000;
fm_dp = 0;
for(unsigned i = 0; i < 4; i++)
fm_dp |= (((bool)(tmp_pulse_delay[0][i])) << i);
}
else if(byte_counter == 1) // Next byte: 0x5A
dsr_pulse_delay = 0x40;
else if(byte_counter == 2) // Next byte(typically, controller-dependent): 0x41
{
if(fm_dp)
dsr_pulse_delay = 0x40;
else
dsr_pulse_delay = 0;
}
else if(byte_counter >= 3 && byte_counter < 34) // Next byte when byte_counter==3 (typically, controller-dependent): 0x5A
{
if(byte_counter < 10)
{
int d = 0x40;
for(unsigned i = 0; i < 4; i++)
if(tmp_pulse_delay[0][i] > d)
d = tmp_pulse_delay[0][i];
dsr_pulse_delay = d;
}
else
dsr_pulse_delay = 0x20;
if(byte_counter == 3 && fm_command_error)
dsr_pulse_delay = 0;
}
} // end if(full_mode)
else
{
if((unsigned)selected_device < 4)
{
dsr_pulse_delay = std::max<int32>(tmp_pulse_delay[0][selected_device], tmp_pulse_delay[1][selected_device]);
}
}
//
//
//
//printf("Byte Counter Increment\n");
if(byte_counter < 255)
byte_counter++;
}
return(ret);
}
}
bool InputDevice_Multitap::Clock(bool TxD, int32 &dsr_pulse_delay)
{
if(!dtr)
return(1);
bool ret = 1;
int32 tmp_pulse_delay[2][4] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
//printf("Receive bit: %d\n", TxD);
//printf("TxD %d\n", TxD);
receive_buffer &= ~ (1 << bit_counter);
receive_buffer |= TxD << bit_counter;
if(1)
{
if(byte_counter == 0)
{
bool mangled_txd = TxD;
if(bit_counter < 4)
mangled_txd = (0x01 >> bit_counter) & 1;
for(unsigned i = 0; i < 4; i++)
{
pad_devices[i]->Clock(mangled_txd, tmp_pulse_delay[0][i]);
mc_devices[i]->Clock(mangled_txd, tmp_pulse_delay[1][i]);
}
}
else
{
if(full_mode)
{
if(byte_counter == 1)
ret = (0x80 >> bit_counter) & 1;
else if(byte_counter == 2)
ret = (0x5A >> bit_counter) & 1;
else if(byte_counter >= 0x03 && byte_counter < 0x03 + 0x08 * 4)
{
if(!fm_command_error && byte_counter < (0x03 + 0x08))
{
for(unsigned i = 0; i < 4; i++)
{
fm_buffer[i][byte_counter - 0x03] &= (pad_devices[i]->Clock((sb[i][byte_counter - 0x03] >> bit_counter) & 1, tmp_pulse_delay[0][i]) << bit_counter) | (~(1U << bit_counter));
}
}
ret &= ((&fm_buffer[0][0])[byte_counter - 0x03] >> bit_counter) & 1;
}
}
else // to if(full_mode)
{
if((unsigned)selected_device < 4)
{
ret &= pad_devices[selected_device]->Clock(TxD, tmp_pulse_delay[0][selected_device]);
ret &= mc_devices[selected_device]->Clock(TxD, tmp_pulse_delay[1][selected_device]);
}
}
} // end else to if(byte_counter == 0)
}
//
//
//
bit_counter = (bit_counter + 1) & 0x7;
if(bit_counter == 0)
{
//printf("MT Receive: 0x%02x\n", receive_buffer);
if(byte_counter == 0)
{
mc_mode = (bool)(receive_buffer & 0xF0);
if(mc_mode)
full_mode = false;
//printf("Zoomba: 0x%02x\n", receive_buffer);
//printf("Full mode: %d %d %d\n", full_mode, bit_counter, byte_counter);
if(full_mode)
{
memset(fm_buffer, 0xFF, sizeof(fm_buffer));
selected_device = 0;
}
else
{
//printf("Device select: %02x\n", receive_buffer);
selected_device = ((receive_buffer & 0xF) - 1) & 0xFF;
}
}
if(byte_counter == 1)
{
command = receive_buffer;
//printf("Multitap sub-command: %02x\n", command);
if(full_mode)
{
if(command != 0x42)
fm_command_error = true;
else
fm_command_error = false;
}
else
{
fm_command_error = false;
}
}
if((!mc_mode || full_mode) && byte_counter == 2)
{
//printf("Full mode setting: %02x\n", receive_buffer);
full_mode_setting = receive_buffer & 0x01;
}
if(full_mode)
{
if(byte_counter >= 3 + 8 * 0 && byte_counter < (3 + 8 * 4))
{
const unsigned adjbi = byte_counter - 3;
sb[adjbi >> 3][adjbi & 0x7] = receive_buffer;
}
if(byte_counter == 33)
prev_fm_success = true;
}
// Handle DSR stuff
if(full_mode)
{
if(byte_counter == 0) // Next byte: 0x80
{
dsr_pulse_delay = 1000;
fm_dp = 0;
for(unsigned i = 0; i < 4; i++)
fm_dp |= (((bool)(tmp_pulse_delay[0][i])) << i);
}
else if(byte_counter == 1) // Next byte: 0x5A
dsr_pulse_delay = 0x40;
else if(byte_counter == 2) // Next byte(typically, controller-dependent): 0x41
{
if(fm_dp)
dsr_pulse_delay = 0x40;
else
{
byte_counter = 255;
dsr_pulse_delay = 0;
}
}
else if(byte_counter >= 3 && byte_counter < 34) // Next byte when byte_counter==3 (typically, controller-dependent): 0x5A
{
if(byte_counter < 10)
{
int d = 0x40;
for(unsigned i = 0; i < 4; i++)
{
int32 tpd = tmp_pulse_delay[0][i];
if(byte_counter == 3 && (fm_dp & (1U << i)) && tpd == 0)
{
//printf("SNORG: %u %02x\n", i, sb[i][0]);
fm_command_error = true;
}
if(tpd > d)
d = tpd;
}
dsr_pulse_delay = d;
}
else
dsr_pulse_delay = 0x20;
if(byte_counter == 3 && fm_command_error)
{
byte_counter = 255;
dsr_pulse_delay = 0;
}
}
} // end if(full_mode)
else
{
if((unsigned)selected_device < 4)
{
dsr_pulse_delay = std::max<int32>(tmp_pulse_delay[0][selected_device], tmp_pulse_delay[1][selected_device]);
}
}
//
//
//
//printf("Byte Counter Increment\n");
if(byte_counter < 255)
byte_counter++;
}
return(ret);
}
}

View File

@ -39,10 +39,13 @@ class InputDevice_Multitap final : public InputDevice
bool full_mode;
bool mc_mode;
bool prev_fm_success;
uint8 fm_dp; // Device-present.
uint8 fm_buffer[4][8];
uint8 sb[4][8];
bool fm_deferred_error_temp;
bool fm_deferred_error;
bool fm_command_error;

View File

@ -26,7 +26,7 @@
if(InFIFO.CanWrite())
{
InFIFO.WriteUnit(V);
InFIFO.Write(V);
if(InCommand)
{
@ -57,9 +57,10 @@
#include "psx.h"
#include "mdec.h"
#include "FastFIFO.h"
#include "math_ops.h"
#include "masmem.h"
#include "cdrom/SimpleFIFO.h"
#if defined(__SSE2__)
#include <xmmintrin.h>
@ -79,8 +80,8 @@ namespace MDFN_IEN_PSX
static int32 ClockCounter;
static unsigned MDRPhase;
static SimpleFIFO<uint32> InFIFO(0x20);
static SimpleFIFO<uint32> OutFIFO(0x20);
static FastFIFO<uint32, 0x20> InFIFO;
static FastFIFO<uint32, 0x20> OutFIFO;
static int8 block_y[8][8];
static int8 block_cb[8][8]; // [y >> 1][x >> 1]
@ -443,10 +444,10 @@ static INLINE void WriteImageData(uint16 V, int32* eat_cycles)
int ci = sign_10_to_s16(V & 0x3FF);
int tmp;
if(q != 0)
tmp = ((ci * q) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0);
else
tmp = (ci * 2) << 4;
if(q != 0)
tmp = (int32)((uint32)(ci * q) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0);
else
tmp = (uint32)(ci * 2) << 4;
// Not sure if it should be 0x3FFF or 0x3FF0 or maybe 0x3FF8?
Coeff[ZigZag[0]] = std::min<int>(0x3FFF, std::max<int>(-0x4000, tmp));
@ -476,10 +477,10 @@ static INLINE void WriteImageData(uint16 V, int32* eat_cycles)
int ci = sign_10_to_s16(V & 0x3FF);
int tmp;
if(q != 0)
tmp = (((ci * q) >> 3) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0);
else
tmp = (ci * 2) << 4;
if(q != 0)
tmp = (int32)((uint32)((ci * q) >> 3) << 4) + (ci ? ((ci < 0) ? 8 : -8) : 0);
else
tmp = (uint32)(ci * 2) << 4;
// Not sure if it should be 0x3FFF or 0x3FF0 or maybe 0x3FF8?
Coeff[ZigZag[CoeffIndex]] = std::min<int>(0x3FFF, std::max<int>(-0x4000, tmp));
@ -504,10 +505,12 @@ static INLINE void WriteImageData(uint16 V, int32* eat_cycles)
case 5: IDCT(Coeff, &block_y[0][0]); break;
}
//
// Approximate, actual timing seems to be a bit complex.
//
*eat_cycles += 341;
//
// Timing in the actual PS1 MDEC is complex due to (apparent) pipelining, but the average when decoding a large number of blocks is
// about 512. We'll go with a lower value here to be conservative due to timing granularity and other timing deficiencies in Mednafen. BUT, don't
// go lower than 460, or Parasite Eve 2's 3D models will stutter like crazy during FMV-background sequences.
//
*eat_cycles += 474;
if(DecodeWB >= 2)
{
@ -529,8 +532,8 @@ static INLINE void WriteImageData(uint16 V, int32* eat_cycles)
//
#define MDEC_WAIT_COND(n) { case __COUNTER__: if(!(n)) { MDRPhase = __COUNTER__ - MDRPhaseBias - 1; return; } }
#define MDEC_WRITE_FIFO(n) { MDEC_WAIT_COND(OutFIFO.CanWrite()); OutFIFO.WriteUnit(n); }
#define MDEC_READ_FIFO(n) { MDEC_WAIT_COND(InFIFO.CanRead()); n = InFIFO.ReadUnit(); }
#define MDEC_WRITE_FIFO(n) { MDEC_WAIT_COND(OutFIFO.CanWrite()); OutFIFO.Write(n); }
#define MDEC_READ_FIFO(n) { MDEC_WAIT_COND(InFIFO.CanRead()); n = InFIFO.Read(); }
#define MDEC_EAT_CLOCKS(n) { ClockCounter -= (n); MDEC_WAIT_COND(ClockCounter > 0); }
void MDEC_Run(int32 clocks)
@ -671,50 +674,52 @@ void MDEC_Run(int32 clocks)
}
#endif
void MDEC_DMAWrite(uint32 V)
{
if(InFIFO.CanWrite())
{
InFIFO.WriteUnit(V);
MDEC_Run(0);
}
else
{
PSX_DBG(PSX_DBG_WARNING, "Input FIFO DMA write overflow?!\n");
}
}
uint32 MDEC_DMARead(int32* offs)
{
uint32 V = 0;
*offs = 0;
if(MDFN_LIKELY(OutFIFO.CanRead()))
{
V = OutFIFO.ReadUnit();
*offs = (RAMOffsetY & 0x7) * RAMOffsetWWS;
if(RAMOffsetY & 0x08)
{
*offs = (*offs - RAMOffsetWWS*7);
}
RAMOffsetCounter--;
if(!RAMOffsetCounter)
{
RAMOffsetCounter = RAMOffsetWWS;
RAMOffsetY++;
}
}
else
{
PSX_DBG(PSX_DBG_WARNING, "[MDEC] BONUS GNOMES\n");
V = rand();
}
return(V);
void MDEC_DMAWrite(uint32 V)
{
if(InFIFO.CanWrite())
{
InFIFO.Write(V);
MDEC_Run(0);
}
else
{
PSX_DBG(PSX_DBG_WARNING, "[MDEC] DMA write when input FIFO is full!!\n");
}
}
uint32 MDEC_DMARead(uint32* offs)
{
uint32 V = 0;
*offs = 0;
if(MDFN_LIKELY(OutFIFO.CanRead()))
{
V = OutFIFO.Read();
*offs = (RAMOffsetY & 0x7) * RAMOffsetWWS;
if(RAMOffsetY & 0x08)
{
*offs = (*offs - RAMOffsetWWS*7);
}
RAMOffsetCounter--;
if(!RAMOffsetCounter)
{
RAMOffsetCounter = RAMOffsetWWS;
RAMOffsetY++;
}
MDEC_Run(0);
}
else
{
PSX_DBG(PSX_DBG_WARNING, "[MDEC] DMA read when output FIFO is empty!\n");
}
return(V);
}
bool MDEC_DMACanWrite(void)
@ -759,7 +764,7 @@ void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V)
{
if(InFIFO.CanWrite())
{
InFIFO.WriteUnit(V);
InFIFO.Write(V);
if(!InCommand)
{
@ -799,7 +804,7 @@ uint32 MDEC_Read(const pscpu_timestamp_t timestamp, uint32 A)
else
{
if(OutFIFO.CanRead())
ret = OutFIFO.ReadUnit();
ret = OutFIFO.Read();
}
//PSX_WARNING("[MDEC] Read: 0x%08x 0x%08x -- %d %d", A, ret, InputBuffer.CanRead(), InCounter);

View File

@ -6,7 +6,7 @@ namespace MDFN_IEN_PSX
void MDEC_DMAWrite(uint32 V);
uint32 MDEC_DMARead(int32* offs);
uint32 MDEC_DMARead(uint32* offs);
void MDEC_Write(const pscpu_timestamp_t timestamp, uint32 A, uint32 V);
uint32 MDEC_Read(const pscpu_timestamp_t timestamp, uint32 A);

View File

@ -47,8 +47,8 @@ namespace MDFN_IEN_PSX
{
static unsigned psx_dbg_level = 0;
#if PSX_DBGPRINT_ENABLE
static unsigned psx_dbg_level = 0;
void PSX_DBG_BIOS_PUTC(uint8 c) noexcept
{
@ -81,9 +81,10 @@ void PSX_DBG(unsigned level, const char *format, ...) noexcept
va_end(ap);
}
}
#else
static unsigned const psx_dbg_level = 0;
#endif
struct MDFN_PseudoRNG // Based off(but not the same as) public-domain "JKISS" PRNG.
{
MDFN_PseudoRNG()
@ -212,7 +213,16 @@ static struct
};
} SysControl;
static unsigned DMACycleSteal = 0; // Doesn't need to be saved in save states, since it's recalculated in the ForceEventUpdates() call chain.
void PSX_SetDMACycleSteal(unsigned stealage)
{
if(stealage > 200) // Due to 8-bit limitations in the CPU core.
stealage = 200;
DMACycleSteal = stealage;
}
//
// Event stuff
//
@ -337,43 +347,12 @@ void ForceEventUpdates(const pscpu_timestamp_t timestamp)
bool PSX_EventHandler(const pscpu_timestamp_t timestamp)
{
event_list_entry *e = events[PSX_EVENT__SYNFIRST].next;
#if PSX_EVENT_SYSTEM_CHECKS
pscpu_timestamp_t prev_event_time = 0;
#endif
#if 0
{
printf("EventHandler - timestamp=%8d\n", timestamp);
event_list_entry *moo = &events[PSX_EVENT__SYNFIRST];
while(moo)
{
printf("%u: %8d\n", moo->which, moo->event_time);
moo = moo->next;
}
}
#endif
#if PSX_EVENT_SYSTEM_CHECKS
assert(Running == 0 || timestamp >= e->event_time); // If Running == 0, our EventHandler
#endif
while(timestamp >= e->event_time) // If Running = 0, PSX_EventHandler() may be called even if there isn't an event per-se, so while() instead of do { ... } while
{
event_list_entry *prev = e->prev;
pscpu_timestamp_t nt;
#if PSX_EVENT_SYSTEM_CHECKS
// Sanity test to make sure events are being evaluated in temporal order.
if(e->event_time < prev_event_time)
abort();
prev_event_time = e->event_time;
#endif
//printf("Event: %u %8d\n", e->which, e->event_time);
#if PSX_EVENT_SYSTEM_CHECKS
if((timestamp - e->event_time) > 50)
printf("Late: %u %d --- %8d\n", e->which, timestamp - e->event_time, timestamp);
#endif
switch(e->which)
{
default: abort();
@ -408,26 +387,6 @@ bool PSX_EventHandler(const pscpu_timestamp_t timestamp)
e = prev->next;
}
#if PSX_EVENT_SYSTEM_CHECKS
for(int i = PSX_EVENT__SYNFIRST + 1; i < PSX_EVENT__SYNLAST; i++)
{
if(timestamp >= events[i].event_time)
{
printf("BUG: %u\n", i);
event_list_entry *moo = &events[PSX_EVENT__SYNFIRST];
while(moo)
{
printf("%u: %8d\n", moo->which, moo->event_time);
moo = moo->next;
}
abort();
}
}
#endif
return(Running);
}
@ -443,14 +402,6 @@ void PSX_RequestMLExit(void)
// End event stuff
//
void DMA_CheckReadDebug(uint32 A);
static unsigned sucksuck = 0;
void PSX_SetDMASuckSuck(unsigned suckage)
{
sucksuck = suckage;
}
// Remember to update MemPeek<>() when we change address decoding in MemRW()
template<typename T, bool IsWrite, bool Access24> static INLINE void MemRW(pscpu_timestamp_t &timestamp, uint32 A, uint32 &V)
@ -462,14 +413,10 @@ template<typename T, bool IsWrite, bool Access24> static INLINE void MemRW(pscpu
printf("Read%d: %08x(orig=%08x)\n", (int)(sizeof(T) * 8), A & mask[A >> 29], A);
#endif
if(!IsWrite)
timestamp += sucksuck;
//if(A == 0xa0 && IsWrite)
// DBG_Break();
if(!IsWrite)
timestamp += DMACycleSteal;
if(A < 0x00800000)
//if(A <= 0x1FFFFF)
{
if(IsWrite)
{
@ -480,8 +427,6 @@ template<typename T, bool IsWrite, bool Access24> static INLINE void MemRW(pscpu
timestamp += 3;
}
//DMA_CheckReadDebug(A);
//assert(A <= 0x1FFFFF);
if(Access24)
{
if(IsWrite)
@ -797,7 +742,6 @@ void PSX_MemWrite16(pscpu_timestamp_t timestamp, uint32 A, uint32 V)
void PSX_MemWrite24(pscpu_timestamp_t timestamp, uint32 A, uint32 V)
{
//assert(0);
MemRW<uint32, true, true>(timestamp, A, V);
}
@ -2357,6 +2301,18 @@ Breakout:
return SHOCK_OK;
}
bool ShockDiscRef::ReadLBA_PW(uint8* pwbuf96, int32 lba, bool hint_fullread)
{
//TODO - whats that hint mean
//TODO - should return false if out of range totally
//reference: static const int32 LBA_Read_Minimum = -150;
//reference: static const int32 LBA_Read_Maximum = 449849; // 100 * 75 * 60 - 150 - 1
u8 tmp[2448];
ReadLBA2448(lba,tmp);
memcpy(pwbuf96,tmp+2352,96);
return true;
}
s32 ShockDiscRef::ReadLBA2448(s32 lba, void* dst2448)
{
return InternalReadLBA2448(lba, dst2448, true);

View File

@ -89,6 +89,8 @@ namespace MDFN_IEN_PSX
#define PSX_EVENT_MAXTS 0x20000000
void PSX_SetEventNT(const int type, const pscpu_timestamp_t next_timestamp);
void PSX_SetDMACycleSteal(unsigned stealage);
void PSX_GPULineHook(const pscpu_timestamp_t timestamp, const pscpu_timestamp_t line_timestamp, bool vsync, uint32 *pixels, const MDFN_PixelFormat* const format, const unsigned width, const unsigned pix_clock_offset, const unsigned pix_clock, const unsigned pix_clock_divider);
uint32 PSX_GetRandU32(uint32 mina, uint32 maxa);
@ -237,8 +239,18 @@ public:
return mcbReadTOC(mOpaque, read_target, tracks);
}
//formerly ReadRawSector
//Reads 2352 + 96
s32 ReadLBA2448(s32 lba, void* dst2448);
s32 ReadLBA2048(s32 lba, void* dst2048);
//formerly ReadRawSectorPWOnly
//Reads 96 bytes (of raw subchannel PW data) into pwbuf.
//Probably the same format as what's at the end of ReadLBA2448
//TODO - reorder args
bool ReadLBA_PW(uint8* pwbuf96, int32 lba, bool hint_fullread);
//only used by disc analysis stuff which should be refactored anyway. should eventually be removed
s32 ReadLBA2048(s32 lba, void* dst2048);
private:
s32 InternalReadLBA2448(s32 lba, void* dst2448, bool needSubcode);

View File

@ -846,6 +846,7 @@ while(sample_clocks > 0)
accum[lr] += ((reverb[lr] * ReverbVol[lr]) >> 15);
clamp(&accum[lr], -32768, 32767);
output[lr] = (accum[lr] * GlobalSweep[lr].ReadVolume()) >> 15;
clamp(&output[lr], -32768, 32767);
}
if(IntermediateBufferPos < 4096) // Overflow might occur in some debugger use cases.
@ -1304,6 +1305,10 @@ uint32 PS_SPU::GetRegister(unsigned int which, char *special, const uint32 speci
break;
}
}
else if(which >= GSREG_FB_SRC_A && which <= GSREG_IN_COEF_R)
{
ret = ReverbRegs[which - GSREG_FB_SRC_A];
}
else switch(which)
{
case GSREG_SPUCONTROL:
@ -1377,43 +1382,6 @@ uint32 PS_SPU::GetRegister(unsigned int which, char *special, const uint32 speci
case GSREG_BLOCKEND:
ret = BlockEnd;
break;
//case GSREG_FB_SRC_A ... GSREG_IN_COEF_R:
case GSREG_FB_SRC_A:
case GSREG_FB_SRC_B:
case GSREG_IIR_ALPHA:
case GSREG_ACC_COEF_A:
case GSREG_ACC_COEF_B:
case GSREG_ACC_COEF_C:
case GSREG_ACC_COEF_D:
case GSREG_IIR_COEF:
case GSREG_FB_ALPHA:
case GSREG_FB_X:
case GSREG_IIR_DEST_A0:
case GSREG_IIR_DEST_A1:
case GSREG_ACC_SRC_A0:
case GSREG_ACC_SRC_A1:
case GSREG_ACC_SRC_B0:
case GSREG_ACC_SRC_B1:
case GSREG_IIR_SRC_A0:
case GSREG_IIR_SRC_A1:
case GSREG_IIR_DEST_B0:
case GSREG_IIR_DEST_B1:
case GSREG_ACC_SRC_C0:
case GSREG_ACC_SRC_C1:
case GSREG_ACC_SRC_D0:
case GSREG_ACC_SRC_D1:
case GSREG_IIR_SRC_B1:
case GSREG_IIR_SRC_B0:
case GSREG_MIX_DEST_A0:
case GSREG_MIX_DEST_A1:
case GSREG_MIX_DEST_B0:
case GSREG_MIX_DEST_B1:
case GSREG_IN_COEF_L:
case GSREG_IN_COEF_R:
ret = ReverbRegs[which - GSREG_FB_SRC_A];
break;
}
return(ret);
@ -1421,8 +1389,11 @@ uint32 PS_SPU::GetRegister(unsigned int which, char *special, const uint32 speci
void PS_SPU::SetRegister(unsigned int which, uint32 value)
{
switch(which)
if(which >= GSREG_FB_SRC_A && which <= GSREG_IN_COEF_R)
{
ReverbRegs[which - GSREG_FB_SRC_A] = value;
}
else switch(which)
{
case GSREG_SPUCONTROL:
SPUControl = value;
@ -1499,44 +1470,6 @@ void PS_SPU::SetRegister(unsigned int which, uint32 value)
case GSREG_BLOCKEND:
BlockEnd = value & 0xFFFFFF;
break;
//case GSREG_FB_SRC_A ... GSREG_IN_COEF_R:
case GSREG_FB_SRC_A:
case GSREG_FB_SRC_B:
case GSREG_IIR_ALPHA:
case GSREG_ACC_COEF_A:
case GSREG_ACC_COEF_B:
case GSREG_ACC_COEF_C:
case GSREG_ACC_COEF_D:
case GSREG_IIR_COEF:
case GSREG_FB_ALPHA:
case GSREG_FB_X:
case GSREG_IIR_DEST_A0:
case GSREG_IIR_DEST_A1:
case GSREG_ACC_SRC_A0:
case GSREG_ACC_SRC_A1:
case GSREG_ACC_SRC_B0:
case GSREG_ACC_SRC_B1:
case GSREG_IIR_SRC_A0:
case GSREG_IIR_SRC_A1:
case GSREG_IIR_DEST_B0:
case GSREG_IIR_DEST_B1:
case GSREG_ACC_SRC_C0:
case GSREG_ACC_SRC_C1:
case GSREG_ACC_SRC_D0:
case GSREG_ACC_SRC_D1:
case GSREG_IIR_SRC_B1:
case GSREG_IIR_SRC_B0:
case GSREG_MIX_DEST_A0:
case GSREG_MIX_DEST_A1:
case GSREG_MIX_DEST_B0:
case GSREG_MIX_DEST_B1:
case GSREG_IN_COEF_L:
case GSREG_IN_COEF_R:
ReverbRegs[which - GSREG_FB_SRC_A] = value;
break;
}
}

View File

@ -15,6 +15,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <assert.h>
#include "psx.h"
#include "timer.h"