Skip to content

Commit e9b8ff7

Browse files
authored
Merge pull request #3 from proskd/fix-emulation
Fix Jaguar Emulation in Provenance
2 parents c0f37f9 + ce16412 commit e9b8ff7

17 files changed

Lines changed: 485 additions & 636 deletions

File tree

src/blitter.c

Lines changed: 148 additions & 150 deletions
Large diffs are not rendered by default.

src/dac.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -164,12 +164,12 @@ void SoundCallback(void * userdata, uint16_t * buffer, int length)
164164
{
165165
double timeToNextEvent = GetTimeToNextEvent(EVENT_JERRY);
166166

167-
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
167+
DSPExec(USEC_TO_RISC_CYCLES(timeToNextEvent));
168168

169-
HandleNextEvent(EVENT_JERRY);
170-
}
171-
while (!bufferDone);
172-
audio_batch_cb((int16_t*)sampleBuffer, length / 2);
169+
HandleNextEvent(EVENT_JERRY);
170+
}
171+
while (!bufferDone);
172+
audio_batch_cb((int16_t*)sampleBuffer, length / 2);
173173
}
174174

175175
// LTXD/RTXD/SCLK/SMODE ($F1A148/4C/50/54)

src/dsp.c

Lines changed: 92 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,29 @@ void (* dsp_opcode[64])() =
233233
dsp_opcode_store_r14_ri, dsp_opcode_store_r15_ri, dsp_opcode_illegal, dsp_opcode_addqmod,
234234
};
235235

236+
uint32_t dsp_opcode_use[65];
237+
238+
const char * dsp_opcode_str[65]=
239+
{
240+
"add", "addc", "addq", "addqt",
241+
"sub", "subc", "subq", "subqt",
242+
"neg", "and", "or", "xor",
243+
"not", "btst", "bset", "bclr",
244+
"mult", "imult", "imultn", "resmac",
245+
"imacn", "div", "abs", "sh",
246+
"shlq", "shrq", "sha", "sharq",
247+
"ror", "rorq", "cmp", "cmpq",
248+
"subqmod", "sat16s", "move", "moveq",
249+
"moveta", "movefa", "movei", "loadb",
250+
"loadw", "load", "sat32s", "load_r14_indexed",
251+
"load_r15_indexed", "storeb", "storew", "store",
252+
"mirror", "store_r14_indexed","store_r15_indexed","move_pc",
253+
"jump", "jr", "mmult", "mtoi",
254+
"normi", "nop", "load_r14_ri", "load_r15_ri",
255+
"store_r14_ri", "store_r15_ri", "illegal", "addqmod",
256+
"STALL"
257+
};
258+
236259
uint32_t dsp_pc;
237260
static uint64_t dsp_acc; // 40 bit register, NOT 32!
238261
static uint32_t dsp_remain;
@@ -241,17 +264,16 @@ static uint32_t dsp_flags;
241264
static uint32_t dsp_matrix_control;
242265
static uint32_t dsp_pointer_to_matrix;
243266
static uint32_t dsp_data_organization;
244-
245-
Bits32 dsp_control;
267+
uint32_t dsp_control;
246268
static uint32_t dsp_div_control;
247269
static uint8_t dsp_flag_z, dsp_flag_n, dsp_flag_c;
248270
static uint32_t * dsp_reg = NULL, * dsp_alternate_reg = NULL;
249271
uint32_t dsp_reg_bank_0[32], dsp_reg_bank_1[32];
250272

251-
static uint8_t dsp_opcode_first_parameter;
252-
static uint8_t dsp_opcode_second_parameter;
273+
static uint32_t dsp_opcode_first_parameter;
274+
static uint32_t dsp_opcode_second_parameter;
253275

254-
#define DSP_RUNNING (dsp_control.bits.b0)
276+
#define DSP_RUNNING (dsp_control & 0x01)
255277

256278
#define RM dsp_reg[dsp_opcode_first_parameter]
257279
#define RN dsp_reg[dsp_opcode_second_parameter]
@@ -282,10 +304,26 @@ static uint8_t dsp_ram_8[0x2000];
282304

283305
#define BRANCH_CONDITION(x) dsp_branch_condition_table[(x) + ((jaguar_flags & 7) << 5)]
284306

307+
static uint32_t dsp_in_exec = 0;
308+
static uint32_t dsp_releaseTimeSlice_flag = 0;
309+
285310
// Private function prototypes
286311

287312
void FlushDSPPipeline(void);
288313

314+
315+
void dsp_reset_stats(void)
316+
{
317+
unsigned i;
318+
for(i=0; i<65; i++)
319+
dsp_opcode_use[i] = 0;
320+
}
321+
322+
void DSPReleaseTimeslice(void)
323+
{
324+
dsp_releaseTimeSlice_flag = 1;
325+
}
326+
289327
void dsp_build_branch_condition_table(void)
290328
{
291329
unsigned i, j;
@@ -355,24 +393,20 @@ uint8_t DSPReadByte(uint32_t offset, uint32_t who/*=UNKNOWN*/)
355393

356394
uint16_t DSPReadWord(uint32_t offset, uint32_t who/*=UNKNOWN*/)
357395
{
358-
Offset offsett;
359-
offsett.LONG = offset;
360-
offset = offsett.Members.offset;
396+
offset &= 0xFFFFFFFE;
397+
361398
if (offset >= DSP_WORK_RAM_BASE && offset <= DSP_WORK_RAM_BASE+0x1FFF)
362399
{
363400
offset -= DSP_WORK_RAM_BASE;
364-
return GET16(dsp_ram_8, offset);
365-
}
401+
return GET16(dsp_ram_8, offset);
402+
}
366403
else if ((offset>=DSP_CONTROL_RAM_BASE)&&(offset<DSP_CONTROL_RAM_BASE+0x20))
367404
{
368-
DSPLong data;
369-
data.LONG = DSPReadLong(offset & 0xFFFFFFFC, who);
370-
371-
if (offset & 0x03) {
372-
return data.Data.LWORD;
373-
} else {
374-
return data.Data.UWORD;
375-
}
405+
uint32_t data = DSPReadLong(offset & 0xFFFFFFFC, who);
406+
407+
if (offset & 0x03)
408+
return data & 0xFFFF;
409+
return data >> 16;
376410
}
377411

378412
return JaguarReadWord(offset, who);
@@ -404,7 +438,7 @@ uint32_t DSPReadLong(uint32_t offset, uint32_t who/*=UNKNOWN*/)
404438
case 0x10:
405439
return dsp_pc;
406440
case 0x14:
407-
return dsp_control.WORD;
441+
return dsp_control;
408442
case 0x18:
409443
return dsp_modulo;
410444
case 0x1C:
@@ -513,8 +547,8 @@ void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
513547
dsp_flag_c = (dsp_flags >> 1) & 0x01;
514548
dsp_flag_n = (dsp_flags >> 2) & 0x01;
515549
DSPUpdateRegisterBanks();
516-
dsp_control.WORD &= ~((dsp_flags & CINT04FLAGS) >> 3);
517-
dsp_control.WORD &= ~((dsp_flags & CINT5FLAG) >> 1);
550+
dsp_control &= ~((dsp_flags & CINT04FLAGS) >> 3);
551+
dsp_control &= ~((dsp_flags & CINT5FLAG) >> 1);
518552
break;
519553
}
520554
case 0x04:
@@ -543,6 +577,7 @@ void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
543577
if (JERRYIRQEnabled(IRQ2_DSP))
544578
{
545579
JERRYSetPendingIRQ(IRQ2_DSP);
580+
DSPReleaseTimeslice();
546581
m68k_set_irq(2); // Set 68000 IPL 2...
547582
}
548583
data &= ~CPUINT;
@@ -551,12 +586,13 @@ void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
551586
if (data & DSPINT0)
552587
{
553588
m68k_end_timeslice();
589+
DSPReleaseTimeslice();
554590
DSPSetIRQLine(DSPIRQ_CPU, ASSERT_LINE);
555591
data &= ~DSPINT0;
556592
}
557593
// Protect writes to VERSION and the interrupt latches...
558594
mask = VERSION | INT_LAT0 | INT_LAT1 | INT_LAT2 | INT_LAT3 | INT_LAT4 | INT_LAT5;
559-
dsp_control.WORD = (dsp_control.WORD & mask) | (data & ~mask);
595+
dsp_control = (dsp_control & mask) | (data & ~mask);
560596
//CC only!
561597
//!!!!!!!!
562598

@@ -566,6 +602,8 @@ void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who/*=UNKNOWN*/)
566602
{
567603
if (who == M68K)
568604
m68k_end_timeslice();
605+
else if (who == DSP)
606+
DSPReleaseTimeslice();
569607

570608
if (!wasRunning)
571609
FlushDSPPipeline();
@@ -608,7 +646,7 @@ void DSPHandleIRQs(void)
608646
return;
609647

610648
// Get the active interrupt bits (latches) & interrupt mask (enables)
611-
bits = ((dsp_control.WORD >> 10) & 0x20) | ((dsp_control.WORD >> 6) & 0x1F);
649+
bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
612650
mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
613651

614652
bits &= mask;
@@ -695,7 +733,7 @@ void DSPHandleIRQsNP(void)
695733
return;
696734

697735
// Get the active interrupt bits (latches) & interrupt mask (enables)
698-
bits = ((dsp_control.WORD >> 10) & 0x20) | ((dsp_control.WORD >> 6) & 0x1F);
736+
bits = ((dsp_control >> 10) & 0x20) | ((dsp_control >> 6) & 0x1F);
699737
mask = ((dsp_flags >> 11) & 0x20) | ((dsp_flags >> 4) & 0x1F);
700738

701739
bits &= mask;
@@ -735,11 +773,11 @@ void DSPSetIRQLine(int irqline, int state)
735773
{
736774
//NOTE: This doesn't take INT_LAT5 into account. !!! FIX !!!
737775
uint32_t mask = INT_LAT0 << irqline;
738-
dsp_control.WORD &= ~mask; // Clear the latch bit
776+
dsp_control &= ~mask; // Clear the latch bit
739777

740778
if (state)
741779
{
742-
dsp_control.WORD |= mask; // Set the latch bit
780+
dsp_control |= mask; // Set the latch bit
743781
DSPHandleIRQsNP();
744782
}
745783
}
@@ -767,8 +805,9 @@ void DSPReset(void)
767805
dsp_matrix_control = 0x00000000;
768806
dsp_pointer_to_matrix = 0x00000000;
769807
dsp_data_organization = 0xFFFFFFFF;
770-
dsp_control.WORD = 0x00002000; // Report DSP version 2
808+
dsp_control = 0x00002000; // Report DSP version 2
771809
dsp_div_control = 0x00000000;
810+
dsp_in_exec = 0;
772811

773812
dsp_reg = dsp_reg_bank_0;
774813
dsp_alternate_reg = dsp_reg_bank_1;
@@ -779,6 +818,7 @@ void DSPReset(void)
779818
CLR_ZNC;
780819
IMASKCleared = false;
781820
FlushDSPPipeline();
821+
dsp_reset_stats();
782822

783823
// Contents of local RAM are quasi-stable; we simulate this by randomizing RAM contents
784824
for(i=0; i<8192; i+=4)
@@ -800,27 +840,31 @@ INLINE void DSPExec(int32_t cycles)
800840
dsp_control &= ~0x10;
801841
}
802842
#endif
843+
dsp_releaseTimeSlice_flag = 0;
844+
dsp_in_exec++;
803845

804846
while (cycles > 0 && DSP_RUNNING)
805847
{
848+
uint16_t opcode;
849+
uint32_t index;
850+
806851
if (IMASKCleared) // If IMASK was cleared,
807852
{
808853
DSPHandleIRQsNP(); // See if any other interrupts are pending!
809854
IMASKCleared = false;
810855
}
811856

812-
OpCode opcode;
813-
opcode.WORD = DSPReadWord(dsp_pc, DSP);
814-
uint8_t index = opcode.Codes.index;
815-
uint8_t fp = opcode.Codes.first;
816-
uint8_t sp = opcode.Codes.second;
817-
dsp_opcode_first_parameter = fp;
818-
dsp_opcode_second_parameter = sp;
819-
dsp_pc += 2;
820-
dsp_opcode[index]();
821-
822-
cycles -= dsp_opcode_cycles[index];
857+
opcode = DSPReadWord(dsp_pc, DSP);
858+
index = opcode >> 10;
859+
dsp_opcode_first_parameter = (opcode >> 5) & 0x1F;
860+
dsp_opcode_second_parameter = opcode & 0x1F;
861+
dsp_pc += 2;
862+
dsp_opcode[index]();
863+
dsp_opcode_use[index]++;
864+
cycles -= dsp_opcode_cycles[index];
823865
}
866+
867+
dsp_in_exec--;
824868
}
825869

826870
// DSP opcode handlers
@@ -1640,10 +1684,8 @@ void FlushDSPPipeline(void)
16401684

16411685
plPtrFetch = 3, plPtrRead = 2, plPtrExec = 1, plPtrWrite = 0;
16421686

1643-
pipeline[0].opcode = PIPELINE_STALL;
1644-
pipeline[1].opcode = PIPELINE_STALL;
1645-
pipeline[2].opcode = PIPELINE_STALL;
1646-
pipeline[3].opcode = PIPELINE_STALL;
1687+
for(i=0; i<4; i++)
1688+
pipeline[i].opcode = PIPELINE_STALL;
16471689

16481690
for(i=0; i<32; i++)
16491691
scoreboard[i] = 0;
@@ -1883,6 +1925,7 @@ INLINE static void DSP_jr(void)
18831925
}//*/
18841926
dsp_pc += 2; // For DSP_DIS_* accuracy
18851927
DSPOpcode[pipeline[plPtrExec].opcode]();
1928+
dsp_opcode_use[pipeline[plPtrExec].opcode]++;
18861929
pipeline[plPtrWrite] = pipeline[plPtrExec];
18871930

18881931
// Step 3: Flush pipeline & set new PC
@@ -1956,8 +1999,9 @@ INLINE static void DSP_jump(void)
19561999
pipeline[plPtrExec].reg2 = dsp_reg[pipeline[plPtrExec].operand2];
19572000
pipeline[plPtrExec].writebackRegister = pipeline[plPtrExec].operand2; // Set it to RN
19582001
}
1959-
dsp_pc += 2; // For DSP_DIS_* accuracy
2002+
dsp_pc += 2; // For DSP_DIS_* accuracy
19602003
DSPOpcode[pipeline[plPtrExec].opcode]();
2004+
dsp_opcode_use[pipeline[plPtrExec].opcode]++;
19612005
pipeline[plPtrWrite] = pipeline[plPtrExec];
19622006

19632007
// Step 3: Flush pipeline & set new PC
@@ -2056,7 +2100,7 @@ INLINE static void DSP_mmult(void)
20562100
for (i = 0; i < count; i++)
20572101
{
20582102
int16_t a;
2059-
int16_t b;
2103+
int16_t b;
20602104

20612105
if (i&0x01)
20622106
a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
@@ -2072,7 +2116,7 @@ INLINE static void DSP_mmult(void)
20722116
for (i = 0; i < count; i++)
20732117
{
20742118
int16_t a;
2075-
int16_t b;
2119+
int16_t b;
20762120

20772121
if (i&0x01)
20782122
a=(int16_t)((dsp_alternate_reg[dsp_opcode_first_parameter + (i>>1)]>>16)&0xffff);
@@ -2086,7 +2130,7 @@ INLINE static void DSP_mmult(void)
20862130

20872131
PRES = res = (int32_t)accum;
20882132
// carry flag to do
2089-
//NOTE: The flags are set based upon the last add/multiply done...
2133+
//NOTE: The flags are set based upon the last add/multiply done...
20902134
SET_ZN(PRES);
20912135
}
20922136

@@ -2107,8 +2151,8 @@ INLINE static void DSP_movei(void)
21072151

21082152
INLINE static void DSP_movepc(void)
21092153
{
2110-
//Need to fix this to take into account pipelining effects... !!! FIX !!! [DONE]
2111-
//Account for pipeline effects...
2154+
//Need to fix this to take into account pipelining effects... !!! FIX !!! [DONE]
2155+
//Account for pipeline effects...
21122156
PRES = dsp_pc - 2 - (pipeline[plPtrRead].opcode == 38 ? 6 : (pipeline[plPtrRead].opcode == PIPELINE_STALL ? 0 : 2));
21132157
}
21142158

src/dsp.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ uint32_t DSPReadLong(uint32_t offset, uint32_t who);
2929
void DSPWriteByte(uint32_t offset, uint8_t data, uint32_t who);
3030
void DSPWriteWord(uint32_t offset, uint16_t data, uint32_t who);
3131
void DSPWriteLong(uint32_t offset, uint32_t data, uint32_t who);
32+
void DSPReleaseTimeslice(void);
3233
bool DSPIsRunning(void);
3334

3435
void DSPExecP(int32_t cycles);

0 commit comments

Comments
 (0)