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 = {
115 /*****************************************************************************/
116 /* Helper functions */
117 /*****************************************************************************/
121 static int GetCfgId (void* CfgInfo, const char* Name, char** Id)
122 /* Search CfgInfo for an attribute with the given name and type "id". If
123 * found, remove it from the configuration, pass a pointer to a dynamically
124 * allocated string containing the value to Id, and return true. If not
125 * found, return false. The memory passed in Id must be free by a call to
129 return CfgDataGetId (CfgInfo, Name, Id);
134 static int GetCfgStr (void* CfgInfo, const char* Name, char** S)
135 /* Search CfgInfo for an attribute with the given name and type "id". If
136 * found, remove it from the configuration, pass a pointer to a dynamically
137 * allocated string containing the value to Id, and return true. If not
138 * found, return false. The memory passed in S must be free by a call to
142 return CfgDataGetStr (CfgInfo, Name, S);
147 static int GetCfgNum (void* CfgInfo, const char* Name, long* Val)
148 /* Search CfgInfo for an attribute with the given name and type "number".
149 * If found, remove it from the configuration, copy it into Val and return
150 * true. If not found, return false.
153 return CfgDataGetNum (CfgInfo, Name, Val);
158 static int CmpChips (void* Data attribute ((unused)),
159 const void* lhs, const void* rhs)
160 /* Compare function for CollSort */
162 /* Cast the object pointers */
163 const Chip* Left = (const Chip*) rhs;
164 const Chip* Right = (const Chip*) lhs;
167 return strcmp (Left->Data->ChipName, Right->Data->ChipName);
172 static Chip* FindChip (const char* Name)
173 /* Find a chip by name. Returns the Chip data structure or NULL if the chip
174 * could not be found.
179 /* ## We do a linear search for now */
180 for (I = 0; I < CollCount (&Chips); ++I) {
182 /* Get the chip at this position */
183 Chip* C = CollAt (&Chips, I);
185 /* Compare the name */
186 if (strcmp (Name, C->Data->ChipName) == 0) {
198 /*****************************************************************************/
200 /*****************************************************************************/
204 static ChipLibrary* NewChipLibrary (const char* PathName)
205 /* Create, initialize and return a new ChipLibrary structure */
207 /* Allocate memory */
208 ChipLibrary* L = xmalloc (sizeof (ChipLibrary));
210 /* Initialize the fields */
211 L->LibName = xstrdup (FindName (PathName));
212 L->PathName = xstrdup (PathName);
214 L->Chips = EmptyCollection;
216 /* Return the allocated structure */
222 static void FreeChipLibrary (ChipLibrary* L)
223 /* Free a ChipLibrary structure */
229 /* If the library is open, close it. Discard any errors. */
235 /* We may have to handle the Chip pointers, but currently the function
236 * is never called with a non empty Chips collection, so we don't care
244 static Chip* NewChip (ChipLibrary* Library, const ChipData* Data)
245 /* Allocate a new chip structure, initialize and return it */
247 /* Allocate memory */
248 Chip* C = xmalloc (sizeof (Chip));
250 /* Initialize the fields */
253 C->Instances = EmptyCollection;
255 /* Insert the new chip into the collection of all chips */
256 CollAppend (&Chips, C);
258 /* Return the structure */
264 ChipInstance* NewChipInstance (const char* ChipName, unsigned Addr,
265 unsigned Size, Collection* Attributes)
269 /* Find the chip with the given name */
270 Chip* C = FindChip (ChipName);
272 Error ("No chip `%s' found for address $%06X", ChipName, Addr);
275 /* Allocate a new ChipInstance structure */
276 CI = xmalloc (sizeof (*CI));
278 /* Initialize the fields */
283 CI->Data = C->Data->CreateInstance (Addr, Size, Attributes);
285 /* Assign the chip instance to the chip */
286 CollAppend (&C->Instances, CI);
288 /* Return the new instance struct */
294 ChipInstance* MirrorChipInstance (const ChipInstance* Orig, unsigned Addr)
295 /* Generate a chip instance mirror and return it. */
297 /* Allocate a new ChipInstance structure */
298 ChipInstance* CI = xmalloc (sizeof (*CI));
300 /* Initialize the fields */
303 CI->Size = Orig->Size;
304 CI->Data = Orig->Data;
306 /* Assign the chip instance to the chip */
307 CollAppend (&CI->C->Instances, CI);
309 /* Return the new instance struct */
315 void SortChips (void)
316 /* Sort all chips by name. Called after loading */
318 /* Last act: Sort the chips by name */
319 CollSort (&Chips, CmpChips, 0);
324 void LoadChipLibrary (const char* LibName)
325 /* Load a chip library. This includes loading the shared libary, allocating
326 * and initializing the data structure, and loading all chip data from the
331 int (*GetChipData) (const struct ChipData**, unsigned*);
333 const ChipData* Data; /* Pointer to chip data */
334 unsigned ChipCount; /* Number of chips in this library */
338 /* Allocate a new ChipLibrary structure */
339 ChipLibrary* L = NewChipLibrary (LibName);
341 /* Open the library */
342 L->Handle = dlopen (L->PathName, RTLD_GLOBAL | RTLD_LAZY);
344 /* Check for errors */
347 Error ("Cannot open `%s': %s", L->PathName, Msg);
352 /* Locate the GetChipData function */
353 GetChipData = dlsym (L->Handle, "GetChipData");
355 /* Check the error message */
358 /* We had an error */
359 Error ("Cannot find export `GetChipData' in `%s': %s", L->LibName, Msg);
364 /* Call the function to read the chip data */
365 ErrorCode = GetChipData (&Data, &ChipCount);
366 if (ErrorCode != 0) {
367 Error ("Function `GetChipData' in `%s' returned error %d", L->LibName, ErrorCode);
372 /* Remember the library */
373 CollAppend (&ChipLibraries, L);
375 /* Print some information */
376 Print (stderr, 1, "Opened chip library `%s'\n", L->PathName);
378 /* Create the chips */
379 for (I = 0; I < ChipCount; ++I) {
383 /* Get a pointer to the chip data */
384 const ChipData* D = Data + I;
386 /* Check if the chip data has the correct version */
387 if (D->MajorVersion != CHIPDATA_VER_MAJOR) {
388 Warning ("Version mismatch for `%s' (%s), expected %u, got %u",
389 D->ChipName, L->LibName,
390 CHIPDATA_VER_MAJOR, D->MajorVersion);
391 /* Ignore this chip */
395 /* Initialize the chip passing the simulator data */
396 D->InitChip (&Sim65Data);
398 /* Generate a new chip */
401 /* Insert a reference to the chip into the library exporting it */
402 CollAppend (&L->Chips, C);
404 /* Output chip name and version to keep the user happy */
406 " Found %s `%s', version %u.%u in library `%s'\n",
407 (D->Type == CHIPDATA_TYPE_CHIP)? "chip" : "cpu",