1 /* -*- Mode: C; indent-tabs-mode: t; tab-width: 4 -*-
2 // ---------------------------------------------------------------------------
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 // -------------------------------------------------------------------------*/
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"
19 #include "sjme/cleanup.h"
21 static sjme_errorCode
sjme_rom_suiteClose(
22 sjme_attrInNotNull sjme_closeable closeable
)
24 if (closeable
== NULL
)
25 return SJME_ERROR_NULL_ARGUMENTS
;
28 return sjme_error_notImplemented(0);
31 sjme_errorCode
sjme_rom_suiteDefaultLaunch(
32 sjme_attrInNotNull sjme_alloc_pool
* inPool
,
33 sjme_attrInNotNull sjme_rom_suite inSuite
,
34 sjme_attrOutNotNull sjme_lpstr
* outMainClass
,
35 sjme_attrOutNotNull sjme_list_sjme_lpstr
** outMainArgs
,
36 sjme_attrOutNotNull sjme_list_sjme_jint
** outById
,
37 sjme_attrOutNotNull sjme_list_sjme_lpstr
** outByName
)
41 if (inPool
== NULL
|| inSuite
== NULL
|| outMainClass
== NULL
||
42 outMainArgs
== NULL
|| outById
== NULL
|| outByName
== NULL
)
43 return SJME_ERROR_NULL_ARGUMENTS
;
45 /* Not supported internally? */
46 if (inSuite
->functions
->defaultLaunch
== NULL
)
47 return SJME_ERROR_UNSUPPORTED_OPERATION
;
50 if (sjme_error_is(error
= sjme_thread_spinLockGrab(
51 &inSuite
->common
.lock
)))
52 return sjme_error_default(error
);
55 error
= inSuite
->functions
->defaultLaunch(inPool
,
56 inSuite
, outMainClass
, outMainArgs
, outById
, outByName
);
59 if (sjme_error_is(sjme_thread_spinLockRelease(
60 &inSuite
->common
.lock
, NULL
)))
61 return sjme_error_default(error
);
67 sjme_errorCode
sjme_rom_suiteFromMerge(
68 sjme_attrInNotNull sjme_alloc_pool
* pool
,
69 sjme_attrOutNotNull sjme_rom_suite
* outSuite
,
70 sjme_attrInNotNull sjme_rom_suite
* inSuites
,
71 sjme_attrInPositive sjme_jint numInSuites
)
73 if (pool
== NULL
|| outSuite
== NULL
|| inSuites
== NULL
)
74 return SJME_ERROR_NULL_ARGUMENTS
;
77 return SJME_ERROR_INVALID_ARGUMENT
;
79 sjme_todo("Implement this?");
80 return SJME_ERROR_UNKNOWN
;
83 sjme_errorCode
sjme_rom_suiteFromPayload(
84 sjme_attrInNotNull sjme_alloc_pool
* pool
,
85 sjme_attrOutNotNull sjme_rom_suite
* outSuite
,
86 sjme_attrInNotNull
const sjme_payload_config
* payloadConfig
)
88 sjme_jint i
, numActive
, numLibraries
;
90 if (pool
== NULL
|| outSuite
== NULL
|| payloadConfig
== NULL
)
91 return SJME_ERROR_NULL_ARGUMENTS
;
93 /* Count the number of active ROMs. */
96 for (i
= 0; i
< SJME_NVM_PAYLOAD_MAX_ROMS
; i
++)
97 if (payloadConfig
->roms
[i
].isActive
)
102 /* Anything that is a library we need to build a container. */
103 if (payloadConfig
->roms
[i
].isLibrary
)
107 /* If there is nothing active then nothing needs to be done. */
111 return SJME_ERROR_NONE
;
114 sjme_todo("Implement this?");
115 return SJME_ERROR_UNKNOWN
;
118 sjme_errorCode
sjme_rom_suiteLibraries(
119 sjme_attrInNotNull sjme_rom_suite inSuite
,
120 sjme_attrOutNotNull sjme_list_sjme_rom_library
** outLibs
)
122 sjme_rom_suiteCache
* cache
;
123 sjme_rom_suiteListLibrariesFunc listFunc
;
124 sjme_list_sjme_rom_library
* result
;
125 sjme_errorCode error
;
128 if (inSuite
== NULL
|| outLibs
== NULL
)
129 return SJME_ERROR_NULL_ARGUMENTS
;
131 /* Must be a valid cache. */
132 cache
= &inSuite
->cache
;
133 if (cache
->common
.allocPool
== NULL
)
134 return SJME_ERROR_ILLEGAL_STATE
;
136 /* Has this been processed already? */
137 if (cache
->libraries
!= NULL
)
140 sjme_message("Using existing cache: %p", cache
->libraries
);
142 *outLibs
= cache
->libraries
;
143 return SJME_ERROR_NONE
;
146 /* Check list function. */
147 listFunc
= inSuite
->functions
->list
;
148 if (listFunc
== NULL
)
149 return SJME_ERROR_NOT_IMPLEMENTED
;
152 if (sjme_error_is(error
= sjme_thread_spinLockGrab(
153 &inSuite
->common
.lock
)))
154 return sjme_error_default(error
);
156 /* Call the list function. */
158 if (sjme_error_is(error
= listFunc(inSuite
,
159 &result
)) || result
== NULL
)
162 /* Store it within the cache. */
163 cache
->libraries
= result
;
165 /* All of these must be valid libraries. */
166 for (i
= 0, n
= result
->length
; i
< n
; i
++)
167 if (result
->elements
[i
] == NULL
)
169 error
= SJME_ERROR_LIBRARY_NOT_FOUND
;
170 goto fail_missingLib
;
174 if (sjme_error_is(error
= sjme_thread_spinLockRelease(
175 &inSuite
->common
.lock
, NULL
)))
176 return sjme_error_default(error
);
180 return SJME_ERROR_NONE
;
184 /* Release lock before failing. */
185 if (sjme_error_is(sjme_thread_spinLockRelease(
186 &inSuite
->common
.lock
, NULL
)))
187 return sjme_error_default(error
);
189 return sjme_error_default(error
);
192 sjme_errorCode
sjme_rom_suiteNew(
193 sjme_attrInNotNull sjme_alloc_pool
* pool
,
194 sjme_attrOutNotNull sjme_rom_suite
* outSuite
,
195 sjme_attrInNullable sjme_pointer data
,
196 sjme_attrInNotNull
const sjme_rom_suiteFunctions
* inFunctions
,
197 sjme_attrInNullable
const sjme_frontEnd
* copyFrontEnd
)
199 sjme_rom_suite result
;
200 sjme_errorCode error
;
202 if (pool
== NULL
|| outSuite
== NULL
|| inFunctions
== NULL
)
203 return SJME_ERROR_NULL_ARGUMENTS
;
205 /* These functions are required. */
206 if (inFunctions
->init
== NULL
||
207 inFunctions
->libraryId
== NULL
||
208 inFunctions
->list
== NULL
||
209 inFunctions
->loadLibrary
== NULL
)
210 return SJME_ERROR_NOT_IMPLEMENTED
;
212 /* Allocate resultant suite. */
214 if (sjme_error_is(error
= sjme_alloc_weakNew(pool
,
216 sjme_nvm_enqueueHandler
, SJME_NVM_ENQUEUE_IDENTITY
,
217 (void**)&result
, NULL
)) || result
== NULL
)
221 result
->common
.closeable
.closeHandler
= sjme_rom_suiteClose
;
222 result
->common
.type
= SJME_NVM_STRUCTTYPE_ROM_SUITE
;
223 result
->cache
.common
.allocPool
= pool
;
224 result
->functions
= inFunctions
;
226 /* Copy front end data? */
227 if (copyFrontEnd
!= NULL
)
228 memmove(&result
->common
.frontEnd
, copyFrontEnd
,
229 sizeof(*copyFrontEnd
));
231 /* Call initializer. */
232 if (sjme_error_is(error
= inFunctions
->init(result
, data
)))
237 return SJME_ERROR_NONE
;
243 sjme_alloc_free(result
);
245 return sjme_error_default(error
);