@@ -32,7 +32,7 @@ uint64_t ps2_ee_timers_read32(struct ps2_ee_timers* timers, uint32_t addr) {
3232 // printf("ee: timer %d read %08x\n", t, addr & 0xff);
3333
3434 switch (addr & 0xff ) {
35- case 0x00 : return timers -> timer [t ].counter ;
35+ case 0x00 : return timers -> timer [t ].counter & 0xffff ;
3636 case 0x10 : return timers -> timer [t ].mode ;
3737 case 0x20 : return timers -> timer [t ].compare ;
3838 case 0x30 : return timers -> timer [t ].hold ;
@@ -42,11 +42,61 @@ uint64_t ps2_ee_timers_read32(struct ps2_ee_timers* timers, uint32_t addr) {
4242}
4343
4444static inline void ee_timers_write_mode (struct ps2_ee_timers * timers , uint32_t data , int t ) {
45- timers -> timer [t ].mode &= 0xc00 ;
46- timers -> timer [t ].mode |= data & (~0xc00 );
47- timers -> timer [t ].mode &= ~(data & 0xc00 );
45+ struct ee_timer * timer = & timers -> timer [t ];
46+
47+ timer -> mode &= 0xc00 ;
48+ timer -> mode |= data & (~0xc00 );
49+ timer -> mode &= ~(data & 0xc00 );
50+
51+ timer -> clks = data & 3 ;
52+ timer -> gate = (data >> 2 ) & 1 ;
53+ timer -> gats = (data >> 3 ) & 1 ;
54+ timer -> gatm = (data >> 4 ) & 3 ;
55+ timer -> zret = (data >> 6 ) & 1 ;
56+ timer -> cue = (data >> 7 ) & 1 ;
57+ timer -> cmpe = (data >> 8 ) & 1 ;
58+ timer -> ovfe = (data >> 9 ) & 1 ;
59+
60+ if (timer -> gate ) {
61+ printf ("timers: Timer %d gate write %08x\n" , t , data );
62+
63+ exit (1 );
64+ }
65+
66+ // printf("timers: Timer %d mode write %08x mode=%08x counter=%04x compare=%04x clks=%d gate=%d gats=%d gatm=%d zret=%d cue=%d cmpe=%d ovfe=%d\n",
67+ // t, data,
68+ // timer->mode,
69+ // timer->counter,
70+ // timer->compare,
71+ // timer->clks, timer->gate, timer->gats, timer->gatm,
72+ // timer->zret, timer->cue, timer->cmpe, timer->ovfe
73+ // );
74+
75+ switch (timer -> clks ) {
76+ case 0 : timer -> delta = 1 ; break ;
77+ case 1 : timer -> delta = 16 ; break ;
78+ case 2 : timer -> delta = 256 ; break ;
79+ case 3 : timer -> delta = 9370 ; break ;
80+ }
81+
82+ timer -> delta_reload = timer -> delta ;
4883
49- // printf("timers: timer %d write %08x -> %08x\n", t, data, timers->timer[t].mode);
84+ if (timer -> cmpe || timer -> ovfe ) {
85+ timer -> check_enabled = 1 ;
86+
87+ if (timer -> counter < timer -> compare ) {
88+ timer -> cycles_until_check = timer -> compare - timer -> counter ;
89+ } else {
90+ timer -> cycles_until_check = 0 ;
91+ }
92+
93+ timer -> check_reload = timer -> cycles_until_check ;
94+
95+ printf ("timer %d: compare/overflow IRQ enabled counter=%04x target=%04x\n" , t , timer -> counter , timer -> compare );
96+
97+ if (timer -> ovfe )
98+ exit (1 );
99+ }
50100}
51101
52102void ps2_ee_timers_write32 (struct ps2_ee_timers * timers , uint32_t addr , uint64_t data ) {
@@ -62,77 +112,47 @@ void ps2_ee_timers_write32(struct ps2_ee_timers* timers, uint32_t addr, uint64_t
62112 }
63113}
64114
65- void ee_timer_tick (struct ps2_ee_timers * timers , int timer ) {
66- struct ee_timer * t = & timers -> timer [timer ];
115+ int loop2 = 1 ;
67116
68- if (!(t -> mode & 0x80 ))
69- return ;
117+ void ps2_ee_timers_tick (struct ps2_ee_timers * timers ) {
118+ for (int i = 0 ; i < 4 ; i ++ ) {
119+ struct ee_timer * t = & timers -> timer [i ];
70120
71- uint32_t prev = t -> counter ;
121+ if (!t -> cue )
122+ continue ;
72123
73- switch (t -> mode & 3 ) {
74- case 0 : {
75- ++ t -> counter ;
76- } break ;
77- case 1 : {
78- if (t -> internal >= 16 ) {
79- ++ t -> counter ;
80- t -> internal = 0 ;
81- } else {
82- ++ t -> internal ;
83- }
84- } break ;
85- case 2 : {
86- if (t -> internal >= 256 ) {
87- ++ t -> counter ;
88- t -> internal = 0 ;
89- } else {
90- ++ t -> internal ;
91- }
92- } break ;
93- case 3 : {
94- if (t -> internal >= 9370 ) {
95- ++ t -> counter ;
96- t -> internal = 0 ;
97- } else {
98- ++ t -> internal ;
99- }
100- } break ;
101- }
124+ t -> delta -- ;
102125
103- // printf("ee: timer %d counter=%08x\n", timer, t->counter);
126+ if (t -> delta )
127+ continue ;
104128
105- if ((t -> counter >= t -> compare ) && (prev < t -> compare )) {
106- t -> mode |= 0x400 ;
129+ t -> delta = t -> delta_reload ;
130+ t -> counter ++ ;
131+ t -> counter &= 0xffff ;
107132
108- if (t -> mode & 0x100 ) {
109- // printf("ee: timer %d compare IRQ\n", timer) ;
133+ if (t -> check_enabled ) {
134+ t -> cycles_until_check -- ;
110135
111- ps2_intc_irq ( timers -> intc , EE_INTC_TIMER0 + timer );
112- }
136+ if ( t -> cycles_until_check )
137+ continue ;
113138
114- if (t -> mode & 0x40 ) {
115- t -> counter = 0 ;
116- }
117- }
139+ // printf("timer %d: counter=%04x target=%04x cycles_until_check=%04x\n", i, t->counter, t->compare, t->cycles_until_check);
118140
119- if (t -> counter > 0xffff ) {
120- t -> mode |= 0x800 ;
121- t -> counter -= 0xffff ;
141+ // if (!loop2--)
142+ // exit(1);
122143
123- if (t -> mode & 0x200 ) {
124- // printf("ee: timer %d overflow IRQ\n", timer);
144+ if (t -> cmpe && t -> counter == t -> compare ) {
145+ ps2_intc_irq (timers -> intc , EE_INTC_TIMER0 + i );
146+ }
125147
126- ps2_intc_irq (timers -> intc , EE_INTC_TIMER0 + timer );
148+ if (t -> zret ) {
149+ t -> counter = 0 ;
150+ t -> cycles_until_check = t -> compare ;
151+ } else {
152+ t -> cycles_until_check = 0x10000 ;
153+ }
127154 }
128155 }
129-
130- t -> counter &= 0xffff ;
131- }
132-
133- void ps2_ee_timers_tick (struct ps2_ee_timers * timers ) {
134- for (int i = 0 ; i < 4 ; i ++ )
135- ee_timer_tick (timers , i );
136156}
137157
138158void ps2_ee_timers_write16 (struct ps2_ee_timers * timers , uint32_t addr , uint64_t data ) {
0 commit comments