1 /*****************************************************************************/
5 /* Interface for the chip plugins */
9 /* (C) 2002-2003 Ullrich von Bassewitz */
10 /* Römerstrasse 52 */
11 /* D-70794 Filderstadt */
12 /* EMail: uz@cc65.org */
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. */
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: */
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 */
32 /*****************************************************************************/
54 /*****************************************************************************/
56 /*****************************************************************************/
60 static int GetCfgId (void* CfgInfo, const char* Name, char** Id);
61 /* Search CfgInfo for an attribute with the given name and type "id". If
62 * found, remove it from the configuration, pass a pointer to a dynamically
63 * allocated string containing the value to Id, and return true. If not
64 * found, return false. The memory passed in Id must be free by a call to
68 static int GetCfgStr (void* CfgInfo, const char* Name, char** S);
69 /* Search CfgInfo for an attribute with the given name and type "id". If
70 * found, remove it from the configuration, pass a pointer to a dynamically
71 * allocated string containing the value to Id, and return true. If not
72 * found, return false. The memory passed in S must be free by a call to
76 static int GetCfgNum (void* CfgInfo, const char* Name, long* Val);
77 /* Search CfgInfo for an attribute with the given name and type "number".
78 * If found, remove it from the configuration, copy it into Val and return
79 * true. If not found, return false.
84 /*****************************************************************************/
86 /*****************************************************************************/
90 /* Sorted list of all chip data structures */
91 static Collection Chips = STATIC_COLLECTION_INITIALIZER;
93 /* A collection containing all libraries */
94 static Collection ChipLibraries = STATIC_COLLECTION_INITIALIZER;
96 /* SimData instance */
97 static const SimData Sim65Data = {
113 /*****************************************************************************/
114 /* Helper functions */
115 /*****************************************************************************/
119 static int GetCfgId (void* CfgInfo, const char* Name, char** Id)
120 /* Search CfgInfo for an attribute with the given name and type "id". If
121 * found, remove it from the configuration, pass a pointer to a dynamically
122 * allocated string containing the value to Id, and return true. If not
123 * found, return false. The memory passed in Id must be free by a call to
127 return CfgDataGetId (CfgInfo, Name, Id);
132 static int GetCfgStr (void* CfgInfo, const char* Name, char** S)
133 /* Search CfgInfo for an attribute with the given name and type "id". If
134 * found, remove it from the configuration, pass a pointer to a dynamically
135 * allocated string containing the value to Id, and return true. If not
136 * found, return false. The memory passed in S must be free by a call to
140 return CfgDataGetStr (CfgInfo, Name, S);
145 static int GetCfgNum (void* CfgInfo, const char* Name, long* Val)
146 /* Search CfgInfo for an attribute with the given name and type "number".
147 * If found, remove it from the configuration, copy it into Val and return
148 * true. If not found, return false.
151 return CfgDataGetNum (CfgInfo, Name, Val);
156 static int CmpChips (void* Data attribute ((unused)),
157 const void* lhs, const void* rhs)
158 /* Compare function for CollSort */
160 /* Cast the object pointers */
161 const Chip* Left = (const Chip*) rhs;
162 const Chip* Right = (const Chip*) lhs;
165 return strcmp (Left->Data->ChipName, Right->Data->ChipName);
170 static Chip* FindChip (const char* Name)
171 /* Find a chip by name. Returns the Chip data structure or NULL if the chip
172 * could not be found.
177 /* ## We do a linear search for now */
178 for (I = 0; I < CollCount (&Chips); ++I) {
180 /* Get the chip at this position */
181 Chip* C = CollAt (&Chips, I);
183 /* Compare the name */
184 if (strcmp (Name, C->Data->ChipName) == 0) {
196 /*****************************************************************************/
198 /*****************************************************************************/
202 static ChipLibrary* NewChipLibrary (const char* PathName)
203 /* Create, initialize and return a new ChipLibrary structure */
205 /* Allocate memory */
206 ChipLibrary* L = xmalloc (sizeof (ChipLibrary));
208 /* Initialize the fields */
209 L->LibName = xstrdup (FindName (PathName));
210 L->PathName = xstrdup (PathName);
212 L->Chips = EmptyCollection;
214 /* Return the allocated structure */
220 static void FreeChipLibrary (ChipLibrary* L)
221 /* Free a ChipLibrary structure */
227 /* If the library is open, close it. Discard any errors. */
233 /* We may have to handle the Chip pointers, but currently the function
234 * is never called with a non empty Chips collection, so we don't care
242 static Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
243 /* Allocate a new chip structure, initialize and return it */
245 /* Allocate memory */
246 Chip* C = xmalloc (sizeof (Chip));
248 /* Initialize the fields */
249 C->Library = Library;
251 C->Instances = EmptyCollection;
253 /* Insert the new chip into the collection of all chips */
254 CollAppend (&Chips, C);
256 /* Return the structure */
262 ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
263 unsigned Size, Collection* Attributes)
267 /* Find the chip with the given name */
268 Chip* C = FindChip (ChipName);
270 Error ("No chip `%s' found for address $%06X", ChipName, Addr);
273 /* Allocate a new ChipInstance structure */
274 CI = xmalloc (sizeof (*CI));
276 /* Initialize the fields */
280 CI->Data = C->Data->InitInstance (Addr, Size, Attributes);
282 /* Assign the chip instance to the chip */
283 CollAppend (&C->Instances, CI);
285 /* Return the new instance struct */
291 ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
292 /* Generate a chip instance mirror and return it. */
294 /* Allocate a new ChipInstance structure */
295 ChipInstance* CI = xmalloc (sizeof (*CI));
297 /* Initialize the fields */
300 CI->Size = Orig->Size;
301 CI->Data = Orig->Data;
303 /* Assign the chip instance to the chip */
304 CollAppend (&CI->C->Instances, CI);
306 /* Return the new instance struct */
312 void SortChips (void)
313 /* Sort all chips by name. Called after loading */
315 /* Last act: Sort the chips by name */
316 CollSort (&Chips, CmpChips, 0);
321 void LoadChipLibrary (const char* LibName)
322 /* Load a chip library. This includes loading the shared libary, allocating
323 * and initializing the data structure, and loading all chip data from the
328 int (*GetChipData) (const struct ChipData**, unsigned*);
330 const ChipData* Data; /* Pointer to chip data */
331 unsigned ChipCount; /* Number of chips in this library */
335 /* Allocate a new ChipLibrary structure */
336 ChipLibrary* L = NewChipLibrary (LibName);
338 /* Open the library */
339 L->Handle = dlopen (L->PathName, RTLD_GLOBAL | RTLD_LAZY);
341 /* Check for errors */
344 Error ("Cannot open `%s': %s", L->PathName, Msg);
349 /* Locate the GetChipData function */
350 GetChipData = dlsym (L->Handle, "GetChipData");
352 /* Check the error message */
355 /* We had an error */
356 Error ("Cannot find export `GetChipData' in `%s': %s", L->LibName, Msg);
361 /* Call the function to read the chip data */
362 ErrorCode = GetChipData (&Data, &ChipCount);
363 if (ErrorCode != 0) {
364 Error ("Function `GetChipData' in `%s' returned error %d", L->LibName, ErrorCode);
369 /* Remember the library */
370 CollAppend (&ChipLibraries, L);
372 /* Print some information */
373 Print (stderr, 1, "Opened chip library `%s'\n", L->PathName);
375 /* Create the chips */
376 for (I = 0; I < ChipCount; ++I) {
380 /* Get a pointer to the chip data */
381 const ChipData* D = Data + I;
383 /* Check if the chip data has the correct version */
384 if (D->MajorVersion != CHIPDATA_VER_MAJOR) {
385 Warning ("Version mismatch for `%s' (%s), expected %u, got %u",
386 D->ChipName, L->LibName,
387 CHIPDATA_VER_MAJOR, D->MajorVersion);
388 /* Ignore this chip */
392 /* Initialize the chip passing the simulator data */
393 D->InitChip (&Sim65Data);
395 /* Generate a new chip */
398 /* Insert a reference to the chip into the library exporting it */
399 CollAppend (&L->Chips, C);
401 /* Output chip name and version to keep the user happy */
403 " Found %s `%s', version %u.%u in library `%s'\n",
404 (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu",