initial pandora port, with hardware scaling and stuff
[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 #else
110
111 u32 file_length(u8 *dummy, FILE *fp);
112
113 #endif
114
115 extern u32 real_frame_count;
116 extern u32 virtual_frame_count;
117 extern u32 max_frameskip;
118 extern u32 num_skipped_frames;
119
120 #define count_timer(timer_number)                                             \
121   timer[timer_number].reload = 0x10000 - value;                               \
122   if(timer_number < 2)                                                        \
123   {                                                                           \
124     u32 timer_reload =                                                        \
125      timer[timer_number].reload << timer[timer_number].prescale;              \
126     sound_update_frequency_step(timer_number);                                \
127   }                                                                           \
128
129 #define adjust_sound_buffer(timer_number, channel)                            \
130   if(timer[timer_number].direct_sound_channels & (0x01 << channel))           \
131   {                                                                           \
132     direct_sound_channel[channel].buffer_index =                              \
133      (direct_sound_channel[channel].buffer_index + buffer_adjust) %           \
134      BUFFER_SIZE;                                                             \
135   }                                                                           \
136
137 #define trigger_timer(timer_number)                                           \
138   if(value & 0x80)                                                            \
139   {                                                                           \
140     if(timer[timer_number].status == TIMER_INACTIVE)                          \
141     {                                                                         \
142       u32 prescale = prescale_table[value & 0x03];                            \
143       u32 timer_reload = timer[timer_number].reload;                          \
144                                                                               \
145       if((value >> 2) & 0x01)                                                 \
146         timer[timer_number].status = TIMER_CASCADE;                           \
147       else                                                                    \
148         timer[timer_number].status = TIMER_PRESCALE;                          \
149                                                                               \
150       timer[timer_number].prescale = prescale;                                \
151       timer[timer_number].irq = (value >> 6) & 0x01;                          \
152                                                                               \
153       address16(io_registers, 0x100 + (timer_number * 4)) =                   \
154        -timer_reload;                                                         \
155                                                                               \
156       timer_reload <<= prescale;                                              \
157       timer[timer_number].count = timer_reload;                               \
158                                                                               \
159       if(timer_reload < execute_cycles)                                       \
160         execute_cycles = timer_reload;                                        \
161                                                                               \
162       if(timer_number < 2)                                                    \
163       {                                                                       \
164         u32 buffer_adjust =                                                   \
165          (u32)(((float)(cpu_ticks - timer[timer_number].stop_cpu_ticks) *     \
166          sound_frequency) / 16777216.0) * 2;                                  \
167                                                                               \
168         sound_update_frequency_step(timer_number);                            \
169         adjust_sound_buffer(timer_number, 0);                                 \
170         adjust_sound_buffer(timer_number, 1);                                 \
171       }                                                                       \
172     }                                                                         \
173   }                                                                           \
174   else                                                                        \
175   {                                                                           \
176     if(timer[timer_number].status != TIMER_INACTIVE)                          \
177     {                                                                         \
178       timer[timer_number].status = TIMER_INACTIVE;                            \
179       timer[timer_number].stop_cpu_ticks = cpu_ticks;                         \
180     }                                                                         \
181   }                                                                           \
182   address16(io_registers, 0x102 + (timer_number * 4)) = value;                \
183
184 void change_ext(u8 *src, u8 *buffer, u8 *extension);
185
186 void set_clock_speed();
187
188 #endif
189
190