Taking a short break.
[SquirrelJME.git] / nanocoat / src / romSuite.c
blobe3972390031b10d49cf330513583d6865d7ab4bf
1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
3 // SquirrelJME
4 // Copyright (C) Stephanie Gawroriski <xer@multiphasicapps.net>
5 // ---------------------------------------------------------------------------
6 // SquirrelJME is under the Mozilla Public License Version 2.0.
7 // See license.mkd for licensing and copyright information.
8 // -------------------------------------------------------------------------*/
10 #include <string.h>
12 #include "sjme/nvm/rom.h"
13 #include "sjme/alloc.h"
14 #include "sjme/debug.h"
15 #include "sjme/nvm/payload.h"
16 #include "sjme/nvm/romInternal.h"
17 #include "sjme/util.h"
18 #include "sjme/zip.h"
19 #include "sjme/cleanup.h"
21 sjme_errorCode sjme_rom_suiteDefaultLaunch(
22 sjme_attrInNotNull sjme_alloc_pool* inPool,
23 sjme_attrInNotNull sjme_rom_suite inSuite,
24 sjme_attrOutNotNull sjme_lpstr* outMainClass,
25 sjme_attrOutNotNull sjme_list_sjme_lpstr** outMainArgs,
26 sjme_attrOutNotNull sjme_list_sjme_jint** outById,
27 sjme_attrOutNotNull sjme_list_sjme_lpstr** outByName)
29 sjme_errorCode error;
31 if (inPool == NULL || inSuite == NULL || outMainClass == NULL ||
32 outMainArgs == NULL || outById == NULL || outByName == NULL)
33 return SJME_ERROR_NULL_ARGUMENTS;
35 /* Not supported internally? */
36 if (inSuite->functions->defaultLaunch == NULL)
37 return SJME_ERROR_UNSUPPORTED_OPERATION;
39 /* Lock suite. */
40 if (sjme_error_is(error = sjme_thread_spinLockGrab(
41 &inSuite->common.lock)))
42 return sjme_error_default(error);
44 /* Forward call. */
45 error = inSuite->functions->defaultLaunch(inPool,
46 inSuite, outMainClass, outMainArgs, outById, outByName);
48 /* Unlock suite. */
49 if (sjme_error_is(sjme_thread_spinLockRelease(
50 &inSuite->common.lock, NULL)))
51 return sjme_error_default(error);
53 /* Success? */
54 return error;
57 sjme_errorCode sjme_rom_suiteFromMerge(
58 sjme_attrInNotNull sjme_alloc_pool* pool,
59 sjme_attrOutNotNull sjme_rom_suite* outSuite,
60 sjme_attrInNotNull sjme_rom_suite* inSuites,
61 sjme_attrInPositive sjme_jint numInSuites)
63 if (pool == NULL || outSuite == NULL || inSuites == NULL)
64 return SJME_ERROR_NULL_ARGUMENTS;
66 if (numInSuites < 0)
67 return SJME_ERROR_INVALID_ARGUMENT;
69 sjme_todo("Implement this?");
70 return SJME_ERROR_UNKNOWN;
73 sjme_errorCode sjme_rom_suiteFromPayload(
74 sjme_attrInNotNull sjme_alloc_pool* pool,
75 sjme_attrOutNotNull sjme_rom_suite* outSuite,
76 sjme_attrInNotNull const sjme_payload_config* payloadConfig)
78 sjme_jint i, numActive, numLibraries;
80 if (pool == NULL || outSuite == NULL || payloadConfig == NULL)
81 return SJME_ERROR_NULL_ARGUMENTS;
83 /* Count the number of active ROMs. */
84 numActive = 0;
85 numLibraries = 0;
86 for (i = 0; i < SJME_NVM_PAYLOAD_MAX_ROMS; i++)
87 if (payloadConfig->roms[i].isActive)
89 /* Count up! */
90 numActive++;
92 /* Anything that is a library we need to build a container. */
93 if (payloadConfig->roms[i].isLibrary)
94 numLibraries++;
97 /* If there is nothing active then nothing needs to be done. */
98 if (numActive == 0)
100 *outSuite = NULL;
101 return SJME_ERROR_NONE;
104 sjme_todo("Implement this?");
105 return SJME_ERROR_UNKNOWN;
108 sjme_errorCode sjme_rom_suiteLibraries(
109 sjme_attrInNotNull sjme_rom_suite inSuite,
110 sjme_attrOutNotNull sjme_list_sjme_rom_library** outLibs)
112 sjme_rom_suiteCache* cache;
113 sjme_rom_suiteListLibrariesFunc listFunc;
114 sjme_list_sjme_rom_library* result;
115 sjme_errorCode error;
116 sjme_jint i, n;
118 if (inSuite == NULL || outLibs == NULL)
119 return SJME_ERROR_NULL_ARGUMENTS;
121 /* Must be a valid cache. */
122 cache = &inSuite->cache;
123 if (cache->common.allocPool == NULL)
124 return SJME_ERROR_ILLEGAL_STATE;
126 /* Has this been processed already? */
127 if (cache->libraries != NULL)
129 /* Debug. */
130 sjme_message("Using existing cache: %p", cache->libraries);
132 *outLibs = cache->libraries;
133 return SJME_ERROR_NONE;
136 /* Check list function. */
137 listFunc = inSuite->functions->list;
138 if (listFunc == NULL)
139 return SJME_ERROR_NOT_IMPLEMENTED;
141 /* Lock suite. */
142 if (sjme_error_is(error = sjme_thread_spinLockGrab(
143 &inSuite->common.lock)))
144 return sjme_error_default(error);
146 /* Call the list function. */
147 result = NULL;
148 if (sjme_error_is(error = listFunc(inSuite,
149 &result)) || result == NULL)
150 goto fail_list;
152 /* Store it within the cache. */
153 cache->libraries = result;
155 /* All of these must be valid libraries. */
156 for (i = 0, n = result->length; i < n; i++)
157 if (result->elements[i] == NULL)
159 error = SJME_ERROR_LIBRARY_NOT_FOUND;
160 goto fail_missingLib;
163 /* Unlock suite. */
164 if (sjme_error_is(error = sjme_thread_spinLockRelease(
165 &inSuite->common.lock, NULL)))
166 return sjme_error_default(error);
168 /* Success! */
169 *outLibs = result;
170 return SJME_ERROR_NONE;
172 fail_missingLib:
173 fail_list:
174 /* Release lock before failing. */
175 if (sjme_error_is(sjme_thread_spinLockRelease(
176 &inSuite->common.lock, NULL)))
177 return sjme_error_default(error);
179 return sjme_error_default(error);
182 sjme_errorCode sjme_rom_suiteNew(
183 sjme_attrInNotNull sjme_alloc_pool* pool,
184 sjme_attrOutNotNull sjme_rom_suite* outSuite,
185 sjme_attrInNullable sjme_pointer data,
186 sjme_attrInNotNull const sjme_rom_suiteFunctions* inFunctions,
187 sjme_attrInNullable const sjme_frontEnd* copyFrontEnd)
189 sjme_rom_suite result;
190 sjme_errorCode error;
192 if (pool == NULL || outSuite == NULL || inFunctions == NULL)
193 return SJME_ERROR_NULL_ARGUMENTS;
195 /* These functions are required. */
196 if (inFunctions->init == NULL ||
197 inFunctions->libraryId == NULL ||
198 inFunctions->list == NULL ||
199 inFunctions->loadLibrary == NULL)
200 return SJME_ERROR_NOT_IMPLEMENTED;
202 /* Allocate resultant suite. */
203 result = NULL;
204 if (sjme_error_is(error = sjme_nvm_alloc(pool,
205 sizeof(*result), SJME_NVM_STRUCT_ROM_SUITE,
206 SJME_AS_NVM_COMMONP(&result))) || result == NULL)
207 goto fail_alloc;
209 /* Setup result. */
210 result->cache.common.allocPool = pool;
211 result->functions = inFunctions;
213 /* Copy front end data? */
214 if (copyFrontEnd != NULL)
215 memmove(&result->common.frontEnd, copyFrontEnd,
216 sizeof(*copyFrontEnd));
218 /* Call initializer. */
219 if (sjme_error_is(error = inFunctions->init(result, data)))
220 goto fail_init;
222 /* Success! */
223 *outSuite = result;
224 return SJME_ERROR_NONE;
226 fail_init:
227 fail_alloc:
228 if (result != NULL)
229 sjme_closeable_close(SJME_AS_CLOSEABLE(result));
231 return sjme_error_default(error);