race condition fix from 2007 (gpsp09-2xb_1)
[gpsp.git] / main.h
1 /* gameplaySP
2  *
3  * Copyright (C) 2006 Exophase <exophase@gmail.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18  */
19
20 #ifndef MAIN_H
21 #define MAIN_H
22
23 typedef enum
24 {
25   TIMER_INACTIVE,
26   TIMER_PRESCALE,
27   TIMER_CASCADE
28 } timer_status_type;
29
30 typedef enum
31 {
32   TIMER_NO_IRQ,
33   TIMER_TRIGGER_IRQ
34 } timer_irq_type;
35
36
37 typedef enum
38 {
39   TIMER_DS_CHANNEL_NONE,
40   TIMER_DS_CHANNEL_A,
41   TIMER_DS_CHANNEL_B,
42   TIMER_DS_CHANNEL_BOTH
43 } timer_ds_channel_type;
44
45 typedef struct
46 {
47   s32 count;
48   u32 reload;
49   u32 prescale;
50   u32 stop_cpu_ticks;
51   fixed16_16 frequency_step;
52   timer_ds_channel_type direct_sound_channels;
53   timer_irq_type irq;
54   timer_status_type status;
55 } timer_type;
56
57 typedef enum
58 {
59   auto_frameskip,
60   manual_frameskip,
61   no_frameskip
62 } frameskip_type;
63
64 extern u32 cpu_ticks;
65 extern u32 frame_ticks;
66 extern u32 execute_cycles;
67 extern frameskip_type current_frameskip_type;
68 extern u32 frameskip_value;
69 extern u32 random_skip;
70 extern u32 global_cycles_per_instruction;
71 extern u32 synchronize_flag;
72 extern u32 skip_next_frame;
73
74 extern timer_type timer[4];
75 static u32 prescale_table[] = { 0, 6, 8, 10 };
76
77 extern u32 cycle_memory_access;
78 extern u32 cycle_pc_relative_access;
79 extern u32 cycle_sp_relative_access;
80 extern u32 cycle_block_memory_access;
81 extern u32 cycle_block_memory_sp_access;
82 extern u32 cycle_block_memory_words;
83 extern u32 cycle_dma16_words;
84 extern u32 cycle_dma32_words;
85 extern u32 flush_ram_count;
86
87 extern u64 base_timestamp;
88
89 extern u8 main_path[512];
90
91 extern u32 update_backup_flag;
92 extern u32 clock_speed;
93
94 u32 update_gba();
95 void reset_gba();
96 void synchronize();
97 void quit();
98 void delay_us(u32 us_count);
99 void get_ticks_us(u64 *tick_return);
100 void game_name_ext(u8 *src, u8 *buffer, u8 *extension);
101 void main_write_mem_savestate(file_tag_type savestate_file);
102 void main_read_savestate(file_tag_type savestate_file);
103
104
105 #ifdef PSP_BUILD
106
107 u32 file_length(u8 *filename, s32 dummy);
108
109 extern u32 real_frame_count;
110 extern u32 virtual_frame_count;
111 extern u32 max_frameskip;
112 extern u32 num_skipped_frames;
113
114 #endif
115
116
117 #ifdef GP2X_BUILD
118
119 extern u64 frame_count_initial_timestamp;
120 extern u32 real_frame_count;
121 extern u32 virtual_frame_count;
122 extern u32 max_frameskip;
123 extern u32 num_skipped_frames;
124
125 #endif
126
127
128 #ifdef PC_BUILD
129
130 u32 file_length(u8 *dummy, FILE *fp);
131
132 #endif
133
134 #define count_timer(timer_number)                                             \
135   timer[timer_number].reload = 0x10000 - value;                               \
136   if(timer_number < 2)                                                        \
137   {                                                                           \
138     u32 timer_reload =                                                        \
139      timer[timer_number].reload << timer[timer_number].prescale;              \
140     sound_update_frequency_step(timer_number);                                \
141   }                                                                           \
142
143 #define adjust_sound_buffer(timer_number, channel)                            \
144   if(timer[timer_number].direct_sound_channels & (0x01 << channel))           \
145   {                                                                           \
146     direct_sound_channel[channel].buffer_index =                              \
147      (direct_sound_channel[channel].buffer_index + buffer_adjust) %           \
148      BUFFER_SIZE;                                                             \
149   }                                                                           \
150
151 #define trigger_timer(timer_number)                                           \
152   if(value & 0x80)                                                            \
153   {                                                                           \
154     if(timer[timer_number].status == TIMER_INACTIVE)                          \
155     {                                                                         \
156       u32 prescale = prescale_table[value & 0x03];                            \
157       u32 timer_reload = timer[timer_number].reload;                          \
158                                                                               \
159       if((value >> 2) & 0x01)                                                 \
160         timer[timer_number].status = TIMER_CASCADE;                           \
161       else                                                                    \
162         timer[timer_number].status = TIMER_PRESCALE;                          \
163                                                                               \
164       timer[timer_number].prescale = prescale;                                \
165       timer[timer_number].irq = (value >> 6) & 0x01;                          \
166                                                                               \
167       address16(io_registers, 0x100 + (timer_number * 4)) =                   \
168        -timer_reload;                                                         \
169                                                                               \
170       timer_reload <<= prescale;                                              \
171       timer[timer_number].count = timer_reload;                               \
172                                                                               \
173       if(timer_reload < execute_cycles)                                       \
174         execute_cycles = timer_reload;                                        \
175                                                                               \
176       if(timer_number < 2)                                                    \
177       {                                                                       \
178         u32 buffer_adjust =                                                   \
179          (u32)(((float)(cpu_ticks - timer[timer_number].stop_cpu_ticks) *     \
180          sound_frequency) / 16777216.0) * 2;                                  \
181                                                                               \
182         sound_update_frequency_step(timer_number);                            \
183         adjust_sound_buffer(timer_number, 0);                                 \
184         adjust_sound_buffer(timer_number, 1);                                 \
185       }                                                                       \
186     }                                                                         \
187   }                                                                           \
188   else                                                                        \
189   {                                                                           \
190     if(timer[timer_number].status != TIMER_INACTIVE)                          \
191     {                                                                         \
192       timer[timer_number].status = TIMER_INACTIVE;                            \
193       timer[timer_number].stop_cpu_ticks = cpu_ticks;                         \
194     }                                                                         \
195   }                                                                           \
196   address16(io_registers, 0x102 + (timer_number * 4)) = value;                \
197
198 void change_ext(u8 *src, u8 *buffer, u8 *extension);
199
200 #endif
201
202