ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/SIDPlayer/src/main.cpp
Revision: 1.2
Committed: 2000-09-19T15:34:10Z (24 years, 1 month ago) by cebix
Branch: MAIN
Changes since 1.1: +34 -649 lines
Log Message:
can now compile as a portable command-line SDL-based application

File Contents

# User Rev Content
1 cebix 1.1 /*
2 cebix 1.2 * main.cpp - SIDPlayer common routines
3 cebix 1.1 *
4     * SIDPlayer (C) Copyright 1996-2000 Christian Bauer
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 Free Software
18     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19     */
20    
21     #include "sys.h"
22    
23     #include <stdio.h>
24     #include <string.h>
25 cebix 1.2
26     #if defined(__BEOS__)
27     #include <support/UTF8.h>
28     #endif
29 cebix 1.1
30     #include "main.h"
31     #include "prefs.h"
32     #include "mem.h"
33     #include "cpu.h"
34     #include "sid.h"
35     #include "psid.h"
36    
37    
38     // Global variables
39     uint32 f_rand_seed = 1;
40 cebix 1.2 int number_of_songs, current_song;
41     char module_name[64];
42     char author_name[64];
43     char copyright_info[64];
44 cebix 1.1
45     // Flag: PSID file loaded and ready
46     static bool psid_loaded = false;
47    
48     // Data from PSID header
49     static uint16 init_adr; // C64 init routine address
50     uint16 play_adr; // C64 replay routine address
51     static uint32 speed_flags; // Speed flags (1 bit/song)
52    
53    
54    
55     /*
56     * Init everything
57     */
58    
59     void InitAll(void)
60     {
61     PrefsInit(0, NULL);
62     MemoryInit();
63     SIDInit();
64     CPUInit();
65     }
66    
67    
68     /*
69     * Exit everything
70     */
71    
72     void ExitAll(void)
73     {
74     CPUExit();
75     SIDExit();
76     MemoryExit();
77     PrefsExit();
78     }
79    
80    
81     /*
82     * Read PSID file header to buffer
83     */
84    
85     bool LoadPSIDHeader(const char *file, uint8 *p)
86     {
87     // Read header
88     memset(p, 0, PSID_MAX_HEADER_LENGTH);
89 cebix 1.2 FILE *f = fopen(file, "rb");
90     if (f == NULL)
91 cebix 1.1 return false;
92 cebix 1.2 size_t actual = fread(p, 1, PSID_MAX_HEADER_LENGTH, f);
93     fclose(f);
94 cebix 1.1 return actual >= PSID_MIN_HEADER_LENGTH;
95     }
96    
97    
98     /*
99     * Check for PSID header
100     */
101    
102     bool IsPSIDHeader(const uint8 *p)
103     {
104     // Check signature and version
105     uint32 id = read_psid_32(p, PSID_ID);
106     uint16 version = read_psid_16(p, PSID_VERSION);
107 cebix 1.2 return id == 0x50534944 && (version == 1 || version == 2);
108 cebix 1.1 }
109    
110    
111     /*
112     * Check whether file is a PSID file
113     */
114    
115     bool IsPSIDFile(const char *file)
116     {
117     // Load header
118     uint8 header[PSID_MAX_HEADER_LENGTH];
119     if (!LoadPSIDHeader(file, header))
120     return false;
121    
122     // Check header
123     return IsPSIDHeader(header);
124     }
125    
126    
127     /*
128     * Load PSID file for playing
129     */
130    
131     bool LoadPSIDFile(const char *file)
132     {
133     // Open file
134 cebix 1.2 FILE *f = fopen(file, "rb");
135     if (f == NULL)
136 cebix 1.1 return false;
137    
138     // Clear C64 RAM
139     MemoryClear();
140     psid_loaded = false;
141    
142     // Load and check header
143     uint8 header[PSID_MAX_HEADER_LENGTH];
144 cebix 1.2 memset(header, 0, PSID_MAX_HEADER_LENGTH);
145     size_t actual = fread(header, 1, PSID_MAX_HEADER_LENGTH, f);
146     if (actual < PSID_MIN_HEADER_LENGTH || !IsPSIDHeader(header)) {
147     fclose(f);
148 cebix 1.1 return false;
149     }
150    
151     // Extract data from header
152     number_of_songs = read_psid_16(header, PSID_NUMBER);
153     if (number_of_songs == 0)
154     number_of_songs = 1;
155     current_song = read_psid_16(header, PSID_DEFSONG);
156     if (current_song)
157     current_song--;
158     if (current_song >= number_of_songs)
159     current_song = 0;
160    
161     init_adr = read_psid_16(header, PSID_INIT);
162     play_adr = read_psid_16(header, PSID_MAIN);
163    
164     speed_flags = read_psid_32(header, PSID_SPEED);
165    
166 cebix 1.2 #if defined(__BEOS__)
167 cebix 1.1 int32 sl = 32, dl = 64, state = 0;
168     convert_to_utf8(B_ISO1_CONVERSION, (char *)(header + PSID_NAME), &sl, module_name, &dl, &state);
169     sl = 32, dl = 64, state = 0;
170     convert_to_utf8(B_ISO1_CONVERSION, (char *)(header + PSID_AUTHOR), &sl, author_name, &dl, &state);
171     sl = 32, dl = 64, state = 0;
172     convert_to_utf8(B_ISO1_CONVERSION, (char *)(header + PSID_COPYRIGHT), &sl, copyright_info, &dl, &state);
173     module_name[63] = 0;
174     author_name[63] = 0;
175     copyright_info[63] = 0;
176 cebix 1.2 #else
177     strncpy(module_name, (char *)(header + PSID_NAME), 32);
178     strncpy(author_name, (char *)(header + PSID_AUTHOR), 32);
179     strncpy(copyright_info, (char *)(header + PSID_COPYRIGHT), 32);
180     module_name[32] = 0;
181     author_name[32] = 0;
182     copyright_info[32] = 0;
183     #endif
184 cebix 1.1
185     // Seek to start of module data
186 cebix 1.2 fseek(f, read_psid_16(header, PSID_LENGTH), SEEK_SET);
187 cebix 1.1
188     // Find load address
189     uint16 load_adr = read_psid_16(header, PSID_START);
190     if (load_adr == 0) { // Load address is at start of module data
191 cebix 1.2 uint8 lo = fgetc(f);
192     uint8 hi = fgetc(f);
193 cebix 1.1 load_adr = (hi << 8) | lo;
194     }
195     if (init_adr == 0) // Init routine address is equal to load address
196     init_adr = load_adr;
197    
198     // Load module data to C64 RAM
199 cebix 1.2 fread(ram + load_adr, 1, RAM_SIZE - load_adr, f);
200     fclose(f);
201 cebix 1.1
202     // Select default song
203     SelectSong(current_song);
204    
205     // Set replay routine address if not given in header
206     if (play_adr == 0) { // Replay routine address is given by interrupt vector
207     if (ram[1] & 2) // Kernal ROM switched in
208     play_adr = (ram[0x0315] << 8) | ram[0x0314];
209     else // Kernal ROM switched out
210     play_adr = (ram[0xffff] << 8) | ram[0xfffe];
211     }
212    
213     // Everything OK
214     psid_loaded = true;
215     return true;
216     }
217    
218    
219     /*
220     * Select song for playing
221     */
222    
223     void SelectSong(int num)
224     {
225     if (num >= number_of_songs)
226     num = 0;
227     current_song = num;
228    
229     // Reset SID
230     SIDReset(0);
231    
232     // Set replay frequency
233     int freq = 50;
234     if (num < 32)
235     freq = speed_flags & (1 << num) ? 60 : 50;
236     SIDSetReplayFreq(freq);
237     SIDAdjustSpeed(100);
238    
239     // Execute init routine
240     CPUExecute(init_adr, current_song, 0, 0, 1000000);
241     }