32255597cdd54dc65b8cc5eb68e94b3f50be7a67
[mupen64plus-pandora.git] / source / mupen64plus-core / src / r4300 / interupt.c
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
2  *   Mupen64plus - interupt.c                                              *
3  *   Mupen64Plus homepage: http://code.google.com/p/mupen64plus/           *
4  *   Copyright (C) 2002 Hacktarux                                          *
5  *                                                                         *
6  *   This program is free software; you can redistribute it and/or modify  *
7  *   it under the terms of the GNU General Public License as published by  *
8  *   the Free Software Foundation; either version 2 of the License, or     *
9  *   (at your option) any later version.                                   *
10  *                                                                         *
11  *   This program is distributed in the hope that it will be useful,       *
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14  *   GNU General Public License for more details.                          *
15  *                                                                         *
16  *   You should have received a copy of the GNU General Public License     *
17  *   along with this program; if not, write to the                         *
18  *   Free Software Foundation, Inc.,                                       *
19  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.          *
20  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
21
22 #include <stdlib.h>
23
24 #include <SDL.h>
25
26 #define M64P_CORE_PROTOTYPES 1
27 #include "api/m64p_types.h"
28 #include "api/callbacks.h"
29 #include "api/m64p_vidext.h"
30 #include "api/vidext.h"
31 #include "memory/memory.h"
32 #include "main/rom.h"
33 #include "main/main.h"
34 #include "main/savestates.h"
35 #include "main/cheat.h"
36 #include "osd/osd.h"
37 #include "plugin/plugin.h"
38
39 #include "interupt.h"
40 #include "r4300.h"
41 #include "macros.h"
42 #include "exception.h"
43 #include "reset.h"
44 #include "new_dynarec/new_dynarec.h"
45
46 #ifdef WITH_LIRC
47 #include "main/lirc.h"
48 #endif
49
50 unsigned int next_vi;
51 int vi_field=0;
52 static int vi_counter=0;
53
54 int interupt_unsafe_state = 0;
55
56 typedef struct _interupt_queue
57 {
58    int type;
59    unsigned int count;
60    struct _interupt_queue *next;
61 } interupt_queue;
62
63 static interupt_queue *q = NULL;
64
65 static void clear_queue(void)
66 {
67     while(q != NULL)
68     {
69         interupt_queue *aux = q->next;
70         free(q);
71         q = aux;
72     }
73 }
74
75 /*static void print_queue(void)
76 {
77     interupt_queue *aux;
78     //if (Count < 0x7000000) return;
79     DebugMessage(M64MSG_INFO, "------------------ 0x%x", (unsigned int)Count);
80     aux = q;
81     while (aux != NULL)
82     {
83         DebugMessage(M64MSG_INFO, "Count:%x, %x", (unsigned int)aux->count, aux->type);
84         aux = aux->next;
85     }
86 }*/
87
88 static int SPECIAL_done = 0;
89
90 static int before_event(unsigned int evt1, unsigned int evt2, int type2)
91 {
92     if(evt1 - Count < 0x80000000)
93     {
94         if(evt2 - Count < 0x80000000)
95         {
96             if((evt1 - Count) < (evt2 - Count)) return 1;
97             else return 0;
98         }
99         else
100         {
101             if((Count - evt2) < 0x10000000)
102             {
103                 switch(type2)
104                 {
105                     case SPECIAL_INT:
106                         if(SPECIAL_done) return 1;
107                         else return 0;
108                         break;
109                     default:
110                         return 0;
111                 }
112             }
113             else return 1;
114         }
115     }
116     else return 0;
117 }
118
119 void add_interupt_event(int type, unsigned int delay)
120 {
121     unsigned int count = Count + delay/**2*/;
122     int special = 0;
123     interupt_queue *aux = q;
124    
125     if(type == SPECIAL_INT /*|| type == COMPARE_INT*/) special = 1;
126     if(Count > 0x80000000) SPECIAL_done = 0;
127    
128     if (get_event(type)) {
129         DebugMessage(M64MSG_WARNING, "two events of type 0x%x in interrupt queue", type);
130     }
131    
132     if (q == NULL)
133     {
134         q = (interupt_queue *) malloc(sizeof(interupt_queue));
135         q->next = NULL;
136         q->count = count;
137         q->type = type;
138         next_interupt = q->count;
139         //print_queue();
140         return;
141     }
142    
143     if(before_event(count, q->count, q->type) && !special)
144     {
145         q = (interupt_queue *) malloc(sizeof(interupt_queue));
146         q->next = aux;
147         q->count = count;
148         q->type = type;
149         next_interupt = q->count;
150         //print_queue();
151         return;
152     }
153    
154     while (aux->next != NULL && (!before_event(count, aux->next->count, aux->next->type) || special))
155         aux = aux->next;
156    
157     if (aux->next == NULL)
158     {
159         aux->next = (interupt_queue *) malloc(sizeof(interupt_queue));
160         aux = aux->next;
161         aux->next = NULL;
162         aux->count = count;
163         aux->type = type;
164     }
165     else
166     {
167         interupt_queue *aux2;
168         if (type != SPECIAL_INT)
169             while(aux->next != NULL && aux->next->count == count)
170                 aux = aux->next;
171         aux2 = aux->next;
172         aux->next = (interupt_queue *) malloc(sizeof(interupt_queue));
173         aux = aux->next;
174         aux->next = aux2;
175         aux->count = count;
176         aux->type = type;
177     }
178 }
179
180 void add_interupt_event_count(int type, unsigned int count)
181 {
182     add_interupt_event(type, (count - Count)/*/2*/);
183 }
184
185 static void remove_interupt_event(void)
186 {
187     interupt_queue *aux = q->next;
188     if(q->type == SPECIAL_INT) SPECIAL_done = 1;
189     free(q);
190     q = aux;
191     if (q != NULL && (q->count > Count || (Count - q->count) < 0x80000000))
192         next_interupt = q->count;
193     else
194         next_interupt = 0;
195 }
196
197 unsigned int get_event(int type)
198 {
199     interupt_queue *aux = q;
200     if (q == NULL) return 0;
201     if (q->type == type)
202         return q->count;
203     while (aux->next != NULL && aux->next->type != type)
204         aux = aux->next;
205     if (aux->next != NULL)
206         return aux->next->count;
207     return 0;
208 }
209
210 int get_next_event_type(void)
211 {
212     if (q == NULL) return 0;
213     return q->type;
214 }
215
216 void remove_event(int type)
217 {
218     interupt_queue *aux = q;
219     if (q == NULL) return;
220     if (q->type == type)
221     {
222         aux = aux->next;
223         free(q);
224         q = aux;
225         return;
226     }
227     while (aux->next != NULL && aux->next->type != type)
228         aux = aux->next;
229     if (aux->next != NULL) // it's a type int
230     {
231         interupt_queue *aux2 = aux->next->next;
232         free(aux->next);
233         aux->next = aux2;
234     }
235 }
236
237 void translate_event_queue(unsigned int base)
238 {
239     interupt_queue *aux;
240     remove_event(COMPARE_INT);
241     remove_event(SPECIAL_INT);
242     aux=q;
243     while (aux != NULL)
244     {
245         aux->count = (aux->count - Count)+base;
246         aux = aux->next;
247     }
248     add_interupt_event_count(COMPARE_INT, Compare);
249     add_interupt_event_count(SPECIAL_INT, 0);
250 }
251
252 int save_eventqueue_infos(char *buf)
253 {
254     int len = 0;
255     interupt_queue *aux = q;
256     if (q == NULL)
257     {
258         *((unsigned int*)&buf[0]) = 0xFFFFFFFF;
259         return 4;
260     }
261     while (aux != NULL)
262     {
263         memcpy(buf+len  , &aux->type , 4);
264         memcpy(buf+len+4, &aux->count, 4);
265         len += 8;
266         aux = aux->next;
267     }
268     *((unsigned int*)&buf[len]) = 0xFFFFFFFF;
269     return len+4;
270 }
271
272 void load_eventqueue_infos(char *buf)
273 {
274     int len = 0;
275     clear_queue();
276     while (*((unsigned int*)&buf[len]) != 0xFFFFFFFF)
277     {
278         int type = *((unsigned int*)&buf[len]);
279         unsigned int count = *((unsigned int*)&buf[len+4]);
280         add_interupt_event_count(type, count);
281         len += 8;
282     }
283 }
284
285 void init_interupt(void)
286 {
287     SPECIAL_done = 1;
288     next_vi = next_interupt = 5000;
289     vi_register.vi_delay = next_vi;
290     vi_field = 0;
291     clear_queue();
292     add_interupt_event_count(VI_INT, next_vi);
293     add_interupt_event_count(SPECIAL_INT, 0);
294 }
295
296 void check_interupt(void)
297 {
298     if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
299         Cause = (Cause | 0x400) & 0xFFFFFF83;
300     else
301         Cause &= ~0x400;
302     if ((Status & 7) != 1) return;
303     if (Status & Cause & 0xFF00)
304     {
305         if(q == NULL)
306         {
307             q = (interupt_queue *) malloc(sizeof(interupt_queue));
308             q->next = NULL;
309             q->count = Count;
310             q->type = CHECK_INT;
311         }
312         else
313         {
314             interupt_queue* aux = (interupt_queue *) malloc(sizeof(interupt_queue));
315             aux->next = q;
316             aux->count = Count;
317             aux->type = CHECK_INT;
318             q = aux;
319         }
320         next_interupt = Count;
321     }
322 }
323
324 void gen_interupt(void)
325 {
326     if (stop == 1)
327     {
328         vi_counter = 0; // debug
329         dyna_stop();
330     }
331
332     if (!interupt_unsafe_state)
333     {
334         if (savestates_get_job() == savestates_job_load)
335         {
336             savestates_load();
337             return;
338         }
339
340         if (reset_hard_job)
341         {
342             reset_hard();
343             reset_hard_job = 0;
344             return;
345         }
346     }
347    
348     if (skip_jump)
349     {
350         unsigned int dest = skip_jump;
351         skip_jump = 0;
352
353         if (q->count > Count || (Count - q->count) < 0x80000000)
354             next_interupt = q->count;
355         else
356             next_interupt = 0;
357         
358         last_addr = dest;
359         generic_jump_to(dest);
360         return;
361     } 
362
363     switch(q->type)
364     {
365         case SPECIAL_INT:
366             if (Count > 0x10000000) return;
367             remove_interupt_event();
368             add_interupt_event_count(SPECIAL_INT, 0);
369             return;
370             break;
371         case VI_INT:
372             if(vi_counter < 60)
373             {
374                 if (vi_counter == 0)
375                     cheat_apply_cheats(ENTRY_BOOT);
376                 vi_counter++;
377             }
378             else
379             {
380                 cheat_apply_cheats(ENTRY_VI);
381             }
382             gfx.updateScreen();
383 #ifdef WITH_LIRC
384             lircCheckInput();
385 #endif
386             SDL_PumpEvents();
387
388             refresh_stat();
389
390             // if paused, poll for input events
391             if(rompause)
392             {
393                 osd_render();  // draw Paused message in case gfx.updateScreen didn't do it
394                 VidExt_GL_SwapBuffers();
395                 while(rompause)
396                 {
397                     SDL_Delay(10);
398                     SDL_PumpEvents();
399 #ifdef WITH_LIRC
400                     lircCheckInput();
401 #endif //WITH_LIRC
402                 }
403             }
404
405             new_vi();
406             if (vi_register.vi_v_sync == 0) vi_register.vi_delay = 500000;
407             else vi_register.vi_delay = ((vi_register.vi_v_sync + 1)*1500);
408             next_vi += vi_register.vi_delay;
409             if (vi_register.vi_status&0x40) vi_field=1-vi_field;
410             else vi_field=0;
411
412             remove_interupt_event();
413             add_interupt_event_count(VI_INT, next_vi);
414     
415             MI_register.mi_intr_reg |= 0x08;
416             if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
417                 Cause = (Cause | 0x400) & 0xFFFFFF83;
418             else
419                 return;
420             if ((Status & 7) != 1) return;
421             if (!(Status & Cause & 0xFF00)) return;
422             break;
423     
424         case COMPARE_INT:
425             remove_interupt_event();
426             Count+=2;
427             add_interupt_event_count(COMPARE_INT, Compare);
428             Count-=2;
429     
430             Cause = (Cause | 0x8000) & 0xFFFFFF83;
431             if ((Status & 7) != 1) return;
432             if (!(Status & Cause & 0xFF00)) return;
433             break;
434     
435         case CHECK_INT:
436             remove_interupt_event();
437             break;
438     
439         case SI_INT:
440 #ifdef WITH_LIRC
441             lircCheckInput();
442 #endif //WITH_LIRC
443             SDL_PumpEvents();
444             PIF_RAMb[0x3F] = 0x0;
445             remove_interupt_event();
446             MI_register.mi_intr_reg |= 0x02;
447             si_register.si_stat |= 0x1000;
448             if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
449                 Cause = (Cause | 0x400) & 0xFFFFFF83;
450             else
451                 return;
452             if ((Status & 7) != 1) return;
453             if (!(Status & Cause & 0xFF00)) return;
454             break;
455     
456         case PI_INT:
457             remove_interupt_event();
458             MI_register.mi_intr_reg |= 0x10;
459             pi_register.read_pi_status_reg &= ~3;
460             if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
461                 Cause = (Cause | 0x400) & 0xFFFFFF83;
462             else
463                 return;
464             if ((Status & 7) != 1) return;
465             if (!(Status & Cause & 0xFF00)) return;
466             break;
467     
468         case AI_INT:
469             if (ai_register.ai_status & 0x80000000) // full
470             {
471                 unsigned int ai_event = get_event(AI_INT);
472                 remove_interupt_event();
473                 ai_register.ai_status &= ~0x80000000;
474                 ai_register.current_delay = ai_register.next_delay;
475                 ai_register.current_len = ai_register.next_len;
476                 add_interupt_event_count(AI_INT, ai_event+ai_register.next_delay);
477          
478                 MI_register.mi_intr_reg |= 0x04;
479                 if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
480                     Cause = (Cause | 0x400) & 0xFFFFFF83;
481                 else
482                     return;
483                 if ((Status & 7) != 1) return;
484                 if (!(Status & Cause & 0xFF00)) return;
485             }
486             else
487             {
488                 remove_interupt_event();
489                 ai_register.ai_status &= ~0x40000000;
490
491                 //-------
492                 MI_register.mi_intr_reg |= 0x04;
493                 if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
494                     Cause = (Cause | 0x400) & 0xFFFFFF83;
495                 else
496                     return;
497                 if ((Status & 7) != 1) return;
498                 if (!(Status & Cause & 0xFF00)) return;
499             }
500             break;
501
502         case SP_INT:
503             remove_interupt_event();
504             sp_register.sp_status_reg |= 0x203;
505             // sp_register.sp_status_reg |= 0x303;
506     
507             if (!(sp_register.sp_status_reg & 0x40)) return; // !intr_on_break
508             MI_register.mi_intr_reg |= 0x01;
509             if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
510                 Cause = (Cause | 0x400) & 0xFFFFFF83;
511             else
512                 return;
513             if ((Status & 7) != 1) return;
514             if (!(Status & Cause & 0xFF00)) return;
515             break;
516     
517         case DP_INT:
518             remove_interupt_event();
519             dpc_register.dpc_status &= ~2;
520             dpc_register.dpc_status |= 0x81;
521             MI_register.mi_intr_reg |= 0x20;
522             if (MI_register.mi_intr_reg & MI_register.mi_intr_mask_reg)
523                 Cause = (Cause | 0x400) & 0xFFFFFF83;
524             else
525                 return;
526             if ((Status & 7) != 1) return;
527             if (!(Status & Cause & 0xFF00)) return;
528             break;
529
530         case HW2_INT:
531             // Hardware Interrupt 2 -- remove interrupt event from queue
532             remove_interupt_event();
533             // setup r4300 Status flags: reset TS, and SR, set IM2
534             Status = (Status & ~0x00380000) | 0x1000;
535             Cause = (Cause | 0x1000) & 0xFFFFFF83;
536             /* the exception_general() call below will jump to the interrupt vector (0x80000180) and setup the
537              * interpreter or dynarec
538              */
539             break;
540
541         case NMI_INT:
542             // Non Maskable Interrupt -- remove interrupt event from queue
543             remove_interupt_event();
544             // setup r4300 Status flags: reset TS and SR, set BEV, ERL, and SR
545             Status = (Status & ~0x00380000) | 0x00500004;
546             Cause  = 0x00000000;
547             // simulate the soft reset code which would run from the PIF ROM
548             r4300_reset_soft();
549             // clear all interrupts, reset interrupt counters back to 0
550             Count = 0;
551             vi_counter = 0;
552             init_interupt();
553             // clear the audio status register so that subsequent write_ai() calls will work properly
554             ai_register.ai_status = 0;
555             // set ErrorEPC with the last instruction address
556             ErrorEPC = PC->addr;
557             // reset the r4300 internal state
558             if (r4300emu != CORE_PURE_INTERPRETER)
559             {
560                 // clear all the compiled instruction blocks and re-initialize
561                 free_blocks();
562                 init_blocks();
563             }
564             // adjust ErrorEPC if we were in a delay slot, and clear the delay_slot and dyna_interp flags
565             if(delay_slot==1 || delay_slot==3)
566             {
567                 ErrorEPC-=4;
568             }
569             delay_slot = 0;
570             dyna_interp = 0;
571             // set next instruction address to reset vector
572             last_addr = 0xa4000040;
573             generic_jump_to(0xa4000040);
574             return;
575
576         default:
577             DebugMessage(M64MSG_ERROR, "Unknown interrupt queue event type %.8X.", q->type);
578             remove_interupt_event();
579             break;
580     }
581
582 #ifdef NEW_DYNAREC
583     if (r4300emu == CORE_DYNAREC) {
584         EPC = pcaddr;
585         pcaddr = 0x80000180;
586         Status |= 2;
587         Cause &= 0x7FFFFFFF;
588         pending_exception=1;
589     } else {
590         exception_general();
591     }
592 #else
593     exception_general();
594 #endif
595
596     if (!interupt_unsafe_state)
597     {
598         if (savestates_get_job() == savestates_job_save)
599         {
600             savestates_save();
601             return;
602         }
603     }
604 }
605