@@ -131,30 +131,12 @@ static void clear_queue(usf_state_t * state)
131
131
132
132
static int before_event (usf_state_t * state , unsigned int evt1 , unsigned int evt2 , int type2 )
133
133
{
134
- if (evt1 - state -> g_cp0_regs [CP0_COUNT_REG ] < 0x80000000 )
135
- {
136
- if (evt2 - state -> g_cp0_regs [CP0_COUNT_REG ] < 0x80000000 )
137
- {
138
- if ((evt1 - state -> g_cp0_regs [CP0_COUNT_REG ]) < (evt2 - state -> g_cp0_regs [CP0_COUNT_REG ])) return 1 ;
139
- else return 0 ;
140
- }
141
- else
142
- {
143
- if ((state -> g_cp0_regs [CP0_COUNT_REG ] - evt2 ) < 0x10000000 )
144
- {
145
- switch (type2 )
146
- {
147
- case SPECIAL_INT :
148
- if (state -> SPECIAL_done ) return 1 ;
149
- else return 0 ;
150
- break ;
151
- default :
152
- return 0 ;
153
- }
154
- }
155
- else return 1 ;
156
- }
157
- }
134
+ int count = state -> g_cp0_regs [CP0_COUNT_REG ];
135
+
136
+ if (state -> cycle_count > 0 )
137
+ count -= state -> cycle_count ;
138
+
139
+ if ((evt1 - count ) < (evt2 - count )) return 1 ;
158
140
else return 0 ;
159
141
}
160
142
@@ -167,19 +149,9 @@ void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
167
149
{
168
150
struct node * event ;
169
151
struct node * e ;
170
- int special ;
171
-
172
- special = (type == SPECIAL_INT );
173
-
174
- if (state -> g_cp0_regs [CP0_COUNT_REG ] > 0x80000000 ) state -> SPECIAL_done = 0 ;
175
152
176
153
if (get_event (state , type )) {
177
154
DebugMessage (state , M64MSG_WARNING , "two events of type 0x%x in interrupt queue" , type );
178
- /* FIXME: hack-fix for freezing in Perfect Dark
179
- * http://code.google.com/p/mupen64plus/issues/detail?id=553
180
- * https://github.com/mupen64plus-ae/mupen64plus-ae/commit/802d8f81d46705d64694d7a34010dc5f35787c7d
181
- */
182
- return ;
183
155
}
184
156
185
157
event = alloc_node (& state -> q .pool );
@@ -197,18 +169,20 @@ void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
197
169
state -> q .first = event ;
198
170
event -> next = NULL ;
199
171
state -> next_interupt = state -> q .first -> data .count ;
172
+ state -> cycle_count = state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count ;
200
173
}
201
- else if (before_event (state , count , state -> q .first -> data .count , state -> q .first -> data .type ) && ! special )
174
+ else if (before_event (state , count , state -> q .first -> data .count , state -> q .first -> data .type ))
202
175
{
203
176
event -> next = state -> q .first ;
204
177
state -> q .first = event ;
205
178
state -> next_interupt = state -> q .first -> data .count ;
179
+ state -> cycle_count = state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count ;
206
180
}
207
181
else
208
182
{
209
183
for (e = state -> q .first ;
210
184
e -> next != NULL &&
211
- (!before_event (state , count , e -> next -> data .count , e -> next -> data .type ) || special );
185
+ (!before_event (state , count , e -> next -> data .count , e -> next -> data .type ));
212
186
e = e -> next );
213
187
214
188
if (e -> next == NULL )
@@ -218,8 +192,7 @@ void add_interupt_event_count(usf_state_t * state, int type, unsigned int count)
218
192
}
219
193
else
220
194
{
221
- if (!special )
222
- for (; e -> next != NULL && e -> next -> data .count == count ; e = e -> next );
195
+ for (; e -> next != NULL && e -> next -> data .count == count ; e = e -> next );
223
196
224
197
event -> next = e -> next ;
225
198
e -> next = event ;
@@ -235,11 +208,13 @@ static void remove_interupt_event(usf_state_t * state)
235
208
state -> q .first = e -> next ;
236
209
free_node (& state -> q .pool , e );
237
210
238
- state -> next_interupt = (state -> q .first != NULL
239
- && (state -> q .first -> data .count > state -> g_cp0_regs [CP0_COUNT_REG ]
240
- || (state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count ) < 0x80000000 ))
211
+ state -> next_interupt = (state -> q .first != NULL )
241
212
? state -> q .first -> data .count
242
213
: 0 ;
214
+
215
+ state -> cycle_count = (state -> q .first != NULL )
216
+ ? (state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count )
217
+ : 0 ;
243
218
}
244
219
245
220
unsigned int get_event (usf_state_t * state , int type )
@@ -303,8 +278,18 @@ void translate_event_queue(usf_state_t * state, unsigned int base)
303
278
{
304
279
e -> data .count = (e -> data .count - state -> g_cp0_regs [CP0_COUNT_REG ]) + base ;
305
280
}
281
+
282
+ state -> g_cp0_regs [CP0_COUNT_REG ] = base ;
283
+ add_interupt_event_count (state , SPECIAL_INT , ((state -> g_cp0_regs [CP0_COUNT_REG ] & UINT32_C (0x80000000 )) ^ UINT32_C (0x80000000 )));
284
+
285
+ /* Add count_per_op to avoid wrong event order in case CP0_COUNT_REG == CP0_COMPARE_REG */
286
+ state -> g_cp0_regs [CP0_COUNT_REG ] += state -> count_per_op ;
287
+ state -> cycle_count += state -> count_per_op ;
306
288
add_interupt_event_count (state , COMPARE_INT , state -> g_cp0_regs [CP0_COMPARE_REG ]);
307
- add_interupt_event_count (state , SPECIAL_INT , 0 );
289
+ state -> g_cp0_regs [CP0_COUNT_REG ] -= state -> count_per_op ;
290
+
291
+ /* Update next interrupt in case first event is COMPARE_INT */
292
+ state -> cycle_count = state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count ;
308
293
}
309
294
310
295
int save_eventqueue_infos (usf_state_t * state , char * buf )
@@ -336,6 +321,8 @@ void load_eventqueue_infos(usf_state_t * state, char *buf)
336
321
add_interupt_event_count (state , type , count );
337
322
len += 8 ;
338
323
}
324
+ remove_event (state , SPECIAL_INT );
325
+ add_interupt_event_count (state , SPECIAL_INT , ((state -> g_cp0_regs [CP0_COUNT_REG ] & UINT32_C (0x80000000 )) ^ UINT32_C (0x80000000 )));
339
326
}
340
327
341
328
void init_interupt (usf_state_t * state )
@@ -346,7 +333,8 @@ void init_interupt(usf_state_t * state)
346
333
347
334
clear_queue (state );
348
335
add_interupt_event_count (state , VI_INT , state -> g_vi .next_vi );
349
- add_interupt_event_count (state , SPECIAL_INT , 0 );
336
+ add_interrupt_event_count (state , SPECIAL_INT , 0x80000000 );
337
+ add_interupt_event_count (state , COMPARE_INT , 0 );
350
338
}
351
339
352
340
void check_interupt (usf_state_t * state )
@@ -389,6 +377,7 @@ void check_interupt(usf_state_t * state)
389
377
390
378
event -> data .count = state -> next_interupt = state -> g_cp0_regs [CP0_COUNT_REG ];
391
379
event -> data .type = CHECK_INT ;
380
+ state -> cycle_count = 0 ;
392
381
393
382
if (state -> q .first == NULL )
394
383
{
@@ -435,21 +424,21 @@ void raise_maskable_interrupt(usf_state_t * state, uint32_t cause)
435
424
436
425
static void special_int_handler (usf_state_t * state )
437
426
{
438
- if (state -> g_cp0_regs [CP0_COUNT_REG ] > 0x10000000 )
439
- return ;
440
-
441
- state -> SPECIAL_done = 1 ;
442
427
remove_interupt_event (state );
443
- add_interupt_event_count (state , SPECIAL_INT , 0 );
428
+ add_interupt_event_count (state , SPECIAL_INT , (( state -> g_cp0_regs [ CP0_COUNT_REG ] & UINT32_C ( 0x80000000 )) ^ UINT32_C ( 0x80000000 )) );
444
429
}
445
430
446
431
static void compare_int_handler (usf_state_t * state )
447
432
{
448
433
remove_interupt_event (state );
449
434
state -> g_cp0_regs [CP0_COUNT_REG ]+= state -> count_per_op ;
435
+ state -> cycle_count += state -> count_per_op ;
450
436
add_interupt_event_count (state , COMPARE_INT , state -> g_cp0_regs [CP0_COMPARE_REG ]);
451
437
state -> g_cp0_regs [CP0_COUNT_REG ]-= state -> count_per_op ;
452
438
439
+ /* Update next interrupt in case first event is COMPARE_INT */
440
+ state -> cycle_count = state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count ;
441
+
453
442
if (state -> enablecompare )
454
443
raise_maskable_interrupt (state , 0x8000 );
455
444
}
@@ -525,11 +514,14 @@ void osal_fastcall gen_interupt(usf_state_t * state)
525
514
unsigned int dest = state -> skip_jump ;
526
515
state -> skip_jump = 0 ;
527
516
528
- state -> next_interupt = (state -> q .first -> data .count > state -> g_cp0_regs [CP0_COUNT_REG ]
529
- || (state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count ) < 0x80000000 )
517
+ state -> next_interupt = (state -> q .first != NULL )
530
518
? state -> q .first -> data .count
531
519
: 0 ;
532
520
521
+ state -> cycle_count = (state -> q .first != NULL )
522
+ ? (state -> g_cp0_regs [CP0_COUNT_REG ] - state -> q .first -> data .count )
523
+ : 0 ;
524
+
533
525
state -> last_addr = dest ;
534
526
generic_jump_to (state , dest );
535
527
return ;
0 commit comments