]> git.sur5r.net Git - cc65/blob - src/sim65/chip.c
57e920616bc5c00460412ea2bc92caa83608495e
[cc65] / src / sim65 / chip.c
1 /*****************************************************************************/
2 /*                                                                           */
3 /*                                    chip.c                                 */
4 /*                                                                           */
5 /*                        Interface for the chip plugins                     */
6 /*                                                                           */
7 /*                                                                           */
8 /*                                                                           */
9 /* (C) 2002-2003 Ullrich von Bassewitz                                       */
10 /*               Römerstrasse 52                                             */
11 /*               D-70794 Filderstadt                                         */
12 /* EMail:        uz@cc65.org                                                 */
13 /*                                                                           */
14 /*                                                                           */
15 /* This software is provided 'as-is', without any expressed or implied       */
16 /* warranty.  In no event will the authors be held liable for any damages    */
17 /* arising from the use of this software.                                    */
18 /*                                                                           */
19 /* Permission is granted to anyone to use this software for any purpose,     */
20 /* including commercial applications, and to alter it and redistribute it    */
21 /* freely, subject to the following restrictions:                            */
22 /*                                                                           */
23 /* 1. The origin of this software must not be misrepresented; you must not   */
24 /*    claim that you wrote the original software. If you use this software   */
25 /*    in a product, an acknowledgment in the product documentation would be  */
26 /*    appreciated but is not required.                                       */
27 /* 2. Altered source versions must be plainly marked as such, and must not   */
28 /*    be misrepresented as being the original software.                      */
29 /* 3. This notice may not be removed or altered from any source              */
30 /*    distribution.                                                          */
31 /*                                                                           */
32 /*****************************************************************************/
33
34
35
36 #include <string.h>
37 #include <dlfcn.h>
38
39 /* common */
40 #include "coll.h"
41 #include "fname.h"
42 #include "print.h"
43 #include "xmalloc.h"
44
45 /* sim65 */
46 #include "cfgdata.h"
47 #include "chipdata.h"
48 #include "error.h"
49 #include "chip.h"
50
51
52
53 /*****************************************************************************/
54 /*                                     Data                                  */
55 /*****************************************************************************/
56
57
58
59 /* Sorted list of all chip data structures */
60 static Collection Chips = STATIC_COLLECTION_INITIALIZER;
61
62 /* A collection containing all libraries */
63 static Collection ChipLibraries = STATIC_COLLECTION_INITIALIZER;
64
65 /* SimData instance */
66 static const SimData Sim65Data = {
67     1,                  /* MajorVersion */
68     1,                  /* MinorVersion */
69     xmalloc,
70     xfree,
71     Warning,
72     Error,
73     Internal,
74     CfgDataGetId,
75     CfgDataGetStr,
76     CfgDataGetNum
77 };
78
79
80
81 /*****************************************************************************/
82 /*                               Helper functions                            */
83 /*****************************************************************************/
84
85
86
87 static int CmpChips (void* Data attribute ((unused)),
88                      const void* lhs, const void* rhs)
89 /* Compare function for CollSort */
90 {
91     /* Cast the object pointers */
92     const Chip* Left  = (const Chip*) rhs;
93     const Chip* Right = (const Chip*) lhs;
94
95     /* Do the compare */
96     return strcmp (Left->Data->ChipName, Right->Data->ChipName);
97 }
98
99
100
101 static Chip* FindChip (const char* Name)
102 /* Find a chip by name. Returns the Chip data structure or NULL if the chip
103  * could not be found.
104  */
105 {
106     unsigned I;
107
108     /* ## We do a linear search for now */
109     for (I = 0; I < CollCount (&Chips); ++I) {
110
111         /* Get the chip at this position */
112         Chip* C = CollAt (&Chips, I);
113
114         /* Compare the name */
115         if (strcmp (Name, C->Data->ChipName) == 0) {
116             /* Found */
117             return C;
118         }
119     }
120
121     /* Not found */
122     return 0;
123 }
124
125
126
127 /*****************************************************************************/
128 /*                                   Code                                    */
129 /*****************************************************************************/
130
131
132
133 static ChipLibrary* NewChipLibrary (const char* PathName)
134 /* Create, initialize and return a new ChipLibrary structure */
135 {
136     /* Allocate memory */
137     ChipLibrary* L = xmalloc (sizeof (ChipLibrary));
138
139     /* Initialize the fields */
140     L->LibName   = xstrdup (FindName (PathName));
141     L->PathName  = xstrdup (PathName);
142     L->Handle    = 0;
143     L->Chips     = EmptyCollection;
144
145     /* Return the allocated structure */
146     return L;
147 }
148
149
150
151 static void FreeChipLibrary (ChipLibrary* L)
152 /* Free a ChipLibrary structure */
153 {
154     /* Free the names */
155     xfree (L->LibName);
156     xfree (L->PathName);
157
158     /* If the library is open, close it. Discard any errors. */
159     if (L->Handle) {
160         dlclose (L->Handle);
161         (void) dlerror ();
162     }
163
164     /* We may have to handle the Chip pointers, but currently the function
165      * is never called with a non empty Chips collection, so we don't care
166      * for now.
167      */
168     xfree (L);
169 }
170
171
172
173 static Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
174 /* Allocate a new chip structure, initialize and return it */
175 {
176     /* Allocate memory */
177     Chip* C = xmalloc (sizeof (Chip));
178
179     /* Initialize the fields */
180     C->Library   = Library;
181     C->Data      = Data;
182     C->Instances = EmptyCollection;
183
184     /* Insert the new chip into the collection of all chips */
185     CollAppend (&Chips, C);
186
187     /* Return the structure */
188     return C;
189 }
190
191
192
193 ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
194                                unsigned Size, Collection* Attributes)
195 {
196     ChipInstance* CI;
197
198     /* Find the chip with the given name */
199     Chip* C = FindChip (ChipName);
200     if (C == 0) {
201         Error ("No chip `%s' found for address $%06X", ChipName, Addr);
202     }
203
204     /* Allocate a new ChipInstance structure */
205     CI = xmalloc (sizeof (*CI));
206
207     /* Initialize the fields */
208     CI->C    = C;
209     CI->Addr = Addr;
210     CI->Size = Size;
211     CI->Data = C->Data->InitInstance (Addr, Size, Attributes);
212
213     /* Assign the chip instance to the chip */
214     CollAppend (&C->Instances, CI);
215
216     /* Return the new instance struct */
217     return CI;
218 }
219
220
221
222 ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
223 /* Generate a chip instance mirror and return it. */
224 {
225     /* Allocate a new ChipInstance structure */
226     ChipInstance* CI = xmalloc (sizeof (*CI));
227
228     /* Initialize the fields */
229     CI->C    = Orig->C;
230     CI->Addr = Addr;
231     CI->Size = Orig->Size;
232     CI->Data = Orig->Data;
233
234     /* Assign the chip instance to the chip */
235     CollAppend (&CI->C->Instances, CI);
236
237     /* Return the new instance struct */
238     return CI;
239 }
240
241
242
243 void SortChips (void)
244 /* Sort all chips by name. Called after loading */
245 {
246     /* Last act: Sort the chips by name */
247     CollSort (&Chips, CmpChips, 0);
248 }
249
250
251
252 void LoadChipLibrary (const char* LibName)
253 /* Load a chip library. This includes loading the shared libary, allocating
254  * and initializing the data structure, and loading all chip data from the
255  * library.
256  */
257 {
258     const char* Msg;
259     int (*GetChipData) (const struct ChipData**, unsigned*);
260     int ErrorCode;
261     const ChipData* Data;       /* Pointer to chip data */
262     unsigned ChipCount;         /* Number of chips in this library */
263     unsigned I;
264
265
266     /* Allocate a new ChipLibrary structure */
267     ChipLibrary* L = NewChipLibrary (LibName);
268
269     /* Open the library */
270     L->Handle = dlopen (L->PathName, RTLD_GLOBAL | RTLD_LAZY);
271
272     /* Check for errors */
273     Msg = dlerror ();
274     if (Msg) {
275         Error ("Cannot open `%s': %s", L->PathName, Msg);
276         FreeChipLibrary (L);
277         return;
278     }
279
280     /* Locate the GetChipData function */
281     GetChipData = dlsym (L->Handle, "GetChipData");
282
283     /* Check the error message */
284     Msg = dlerror ();
285     if (Msg) {
286         /* We had an error */
287         Error ("Cannot find export `GetChipData' in `%s': %s", L->LibName, Msg);
288         FreeChipLibrary (L);
289         return;
290     }
291
292     /* Call the function to read the chip data */
293     ErrorCode = GetChipData (&Data, &ChipCount);
294     if (ErrorCode != 0) {
295         Error ("Function `GetChipData' in `%s' returned error %d", L->LibName, ErrorCode);
296         FreeChipLibrary (L);
297         return;
298     }
299
300     /* Remember the library */
301     CollAppend (&ChipLibraries, L);
302
303     /* Print some information */
304     Print (stderr, 1, "Opened chip library `%s'\n", L->PathName);
305
306     /* Create the chips */
307     for (I = 0; I < ChipCount; ++I) {
308
309         Chip* C;
310
311         /* Get a pointer to the chip data */
312         const ChipData* D = Data + I;
313
314         /* Check if the chip data has the correct version */
315         if (Data->MajorVersion != CHIPDATA_VER_MAJOR) {
316             Warning ("Version mismatch for `%s' (%s), expected %u, got %u",
317                      D->ChipName, L->LibName,
318                      CHIPDATA_VER_MAJOR, D->MajorVersion);
319             /* Ignore this chip */
320             continue;
321         }
322
323         /* Generate a new chip */
324         C = NewChip (L, D);
325
326         /* Insert a reference to the chip into the library exporting it */
327         CollAppend (&L->Chips, C);
328
329         /* Output chip name and version to keep the user happy */
330         Print (stdout, 1,
331                "  Found `%s', version %u.%u in library `%s'\n",
332                Data->ChipName,
333                Data->MajorVersion,
334                Data->MinorVersion,
335                L->LibName);
336     }
337 }
338
339
340