2 /***************************************************************************
4 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
5 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
6 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
7 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
11 * Copyright (C) 2007-2009 Joshua Simmons <mud at majidejima dot com>
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 ****************************************************************************/
24 #include "sgf_storage.h"
28 #define ALIGNMENT_VAL (sizeof (union storage_t))
30 union storage_t
*storage_buffer
[] = { NULL
, NULL
};
31 size_t storage_buffer_size
[] = { 0, 0 };
33 uint8_t *storage_free_list
[] = { NULL
, NULL
};
34 size_t storage_free_list_size
[] = { 0, 0 };
36 bool storage_initialized
[] = { false, false };
38 size_t total_storage_size
= 0;
40 /* the next handle to check */
41 int next_free_handle_buffer
;
44 static bool setup_storage_buffer (char *temp_buffer
, size_t size
);
45 static void clear_storage_buffer (int index
);
46 static bool find_free (int *ret_buffer
, int *ret_handle
);
47 static bool is_free (int buffer_num
, int handle
);
48 static void set_free (int buffer_num
, int handle
, bool free
);
51 static void debugf_current_node (void);
54 debugf_current_node (void)
56 int temp_prop
= NO_PROP
;
59 DEBUGF ("CURRENT_NODE < 0 ON DEBUGF_CURRENT_NODE!!!!\n");
62 DEBUGF ("-----------------------------------------\n");
63 DEBUGF ("current_node: %d\n", current_node
);
64 DEBUGF ("start_node %d %d\n", start_node
, tree_head
);
65 DEBUGF ("prev/next: %d/%d\n", get_node (current_node
)->prev
,
66 get_node (current_node
)->next
);
67 DEBUGF ("num variations: %d\n", num_variations_sgf ());
69 if (!get_node (current_node
) ||
70 (temp_prop
= get_node (current_node
)->props
) < 0)
81 DEBUGF (" handle: %d\n", temp_prop
);
82 DEBUGF (" type: %d ", get_prop (temp_prop
)->type
);
83 if (get_prop (temp_prop
)->type
< PROP_NAMES_SIZE
)
85 DEBUGF ("(%s)", prop_names
[get_prop (temp_prop
)->type
]);
88 if (get_prop (temp_prop
)->type
== PROP_BLACK_MOVE
||
89 get_prop (temp_prop
)->type
== PROP_WHITE_MOVE
||
90 get_prop (temp_prop
)->type
== PROP_ADD_BLACK
||
91 get_prop (temp_prop
)->type
== PROP_ADD_WHITE
||
92 get_prop (temp_prop
)->type
== PROP_ADD_EMPTY
)
94 DEBUGF (" i: %d j: %d\n",
95 I (get_prop (temp_prop
)->data
.position
),
96 J (get_prop (temp_prop
)->data
.position
));
100 DEBUGF (" data: %d\n", get_prop (temp_prop
)->data
.number
);
102 DEBUGF (" next: %d\n", get_prop (temp_prop
)->next
);
104 temp_prop
= get_prop (temp_prop
)->next
;
111 DEBUGF ("-----------------------------------------\n");
116 clear_storage_buffer (int index
)
121 /* everything starts free */
122 rb
->memset (storage_free_list
[index
],
123 (unsigned char) 0xFF,
124 storage_free_list_size
[index
]);
126 /* if there are extra bits at the end of the free list (because
127 storage_buffer_size is not divisible by 8) then we set them not
128 free, so we won't end up using those ever by accident (shouldn't be
129 possible anyways, but makes calculation easier later) */
130 temp
= storage_free_list_size
[index
] * 8 - storage_buffer_size
[index
];
131 storage_free_list
[index
][storage_free_list_size
[index
] - 1] ^=
140 i
< sizeof (storage_initialized
) /
141 sizeof (storage_initialized
[0]); ++i
)
143 if (storage_initialized
[i
])
145 clear_storage_buffer (i
);
149 tree_head
= start_node
= current_node
= alloc_storage_sgf ();
154 "Error allocating first node! Please exit immediately.");
157 get_node (tree_head
)->props
= NO_PROP
;
158 get_node (tree_head
)->next
= NO_NODE
;
159 get_node (tree_head
)->prev
= NO_NODE
;
164 audio_stolen_sgf (void)
166 return storage_initialized
[1];
170 alloc_storage_sgf (void)
177 char *new_storage_buffer
;
180 if (!find_free (&buffer_num
, &handle
))
182 if (!storage_initialized
[1])
184 rb
->splash (2 * HZ
, "Stopping music playback to get more space");
185 DEBUGF ("stealing audio buffer: %d\n", (int) total_storage_size
);
187 new_storage_buffer
= rb
->plugin_get_audio_buffer (&size
);
188 setup_storage_buffer (new_storage_buffer
, size
);
190 DEBUGF ("after stealing: %d\n", (int) total_storage_size
);
198 if (!find_free (&buffer_num
, &handle
))
204 set_free (buffer_num
, handle
, false);
209 while (temp_buffer
!= buffer_num
)
211 if (storage_initialized
[temp_buffer
])
213 ret_val
+= storage_buffer_size
[temp_buffer
];
223 free_storage_sgf (int handle
)
227 if (handle
< 0 || (unsigned int) handle
>= total_storage_size
)
229 DEBUGF ("tried to free an out of bounds handle!!\n");
234 while ((unsigned int) handle
>= storage_buffer_size
[index
])
236 handle
-= storage_buffer_size
[index
++];
238 rb
->memset (&storage_buffer
[index
][handle
], 0xFF,
239 sizeof (union storage_t
));
240 set_free (index
, handle
, true);
245 find_free (int *ret_buffer
, int *ret_handle
)
247 unsigned int handle
= next_free_handle
;
248 unsigned int buffer_index
= next_free_handle_buffer
;
250 /* so we know where we started, to prevent infinite loop */
251 unsigned int start_handle
= handle
;
252 unsigned int start_buffer
= buffer_index
;
259 if (handle
>= storage_buffer_size
[buffer_index
])
267 if (buffer_index
>= sizeof (storage_initialized
) /
268 sizeof (storage_initialized
[0]))
273 while (!storage_initialized
[buffer_index
]);
277 if (is_free (buffer_index
, handle
))
279 next_free_handle_buffer
= buffer_index
;
280 next_free_handle
= handle
;
282 *ret_buffer
= buffer_index
;
283 *ret_handle
= handle
;
288 while (handle
!= start_handle
|| buffer_index
!= start_buffer
);
294 is_free (int buffer_num
, int handle
)
296 return storage_free_list
[buffer_num
][handle
/ 8] &
297 (1 << (7 - (handle
% 8)));
301 set_free (int buffer_num
, int handle
, bool free
)
305 /* simple, just 'or' the byte with the specific bit switched on */
306 storage_free_list
[buffer_num
][handle
/ 8] |= 1 << (7 - (handle
% 8));
310 /* start with a byte with all bits turned on and turn off the one
311 we're trying to set to zero. then take that result and 'and'
312 it with the current value */
313 storage_free_list
[buffer_num
][handle
/ 8] &=
314 0xFF ^ (1 << (7 - (handle
% 8)));
324 temp_buffer
= rb
->plugin_get_buffer (&size
);
325 setup_storage_buffer (temp_buffer
, size
);
327 if (total_storage_size
< MIN_STORAGE_BUFFER_SIZE
)
329 rb
->splash (1 * HZ
, "Stopping music playback to get more space");
330 DEBUGF ("storage_buffer_size < MIN!!: %d\n", (int) total_storage_size
);
332 temp_buffer
= rb
->plugin_get_audio_buffer (&size
);
333 setup_storage_buffer (temp_buffer
, size
);
336 if (total_storage_size
< MIN_STORAGE_BUFFER_SIZE
)
338 rb
->splash (1 * HZ
, "Low memory. Large files may not load.");
340 DEBUGF ("storage_buffer_size < MIN!!!!: %d\n",
341 (int) total_storage_size
);
344 DEBUGF ("storage_buffer_size: %d\n", (int) total_storage_size
);
347 unhandled_fd
= create_or_open_file (UNHANDLED_PROP_LIST_FILE
);
349 if (unhandled_fd
< 0)
354 rb
->lseek (unhandled_fd
, 0, SEEK_SET
);
355 rb
->ftruncate (unhandled_fd
, 0);
357 empty_stack (&parse_stack
);
364 clear_caches_sgf (void)
366 empty_stack (&parse_stack
);
368 rb
->lseek (unhandled_fd
, 0, SEEK_SET
);
369 rb
->ftruncate (unhandled_fd
, 0);
375 empty_stack (&parse_stack
);
377 rb
->lseek (unhandled_fd
, 0, SEEK_SET
);
378 rb
->ftruncate (unhandled_fd
, 0);
379 close_file (&unhandled_fd
);
381 close_file (&sgf_fd
);
385 setup_storage_buffer (char *temp_buffer
, size_t size
)
387 unsigned int index
= 0;
390 #if PLUGIN_BUFFER_SIZE < 0x10000 && !defined(SIMULATOR)
391 /* loaded as an overlay plugin, protect from overwriting ourselves */
392 if (plugin_start_addr
>= (unsigned char *) temp_buffer
&&
393 plugin_start_addr
< (unsigned char *) temp_buffer
+ size
)
395 size
= plugin_start_addr
- (unsigned char *) temp_buffer
;
401 if (index
>= sizeof (storage_initialized
) /
402 sizeof (storage_initialized
[0]))
407 if (!storage_initialized
[index
])
414 temp_buffer
= align_buffer (temp_buffer
, &size
);
415 if (!temp_buffer
|| !size
)
420 /* same as temp = size / (sizeof(union storage_t) + 1/8)
421 (we need 1 bit extra for each union storage_t, for the free list) */
423 (8 * (size
- ALIGNMENT_VAL
- 1)) / (8 * sizeof (union storage_t
) + 1);
424 /* the - ALIGNMENT_VAL - 1 is for possible wasted space in alignment
425 and possible extra byte needed in the free list */
427 storage_buffer
[index
] = (void *) temp_buffer
;
428 storage_buffer_size
[index
] = temp
;
430 storage_free_list_size
[index
] = storage_buffer_size
[index
] / 8;
431 if (storage_free_list_size
[index
] * 8 < storage_buffer_size
[index
])
433 ++(storage_free_list_size
[index
]);
436 temp_buffer
+= sizeof (union storage_t
) * temp
;
437 size
-= sizeof (union storage_t
) * temp
;
439 temp_buffer
= align_buffer (temp_buffer
, &size
);
440 if (!temp_buffer
|| !size
)
445 if (size
< storage_free_list_size
[index
])
447 DEBUGF ("Big problem on line %d in sgf.c\n", __LINE__
);
449 "Error in allocating storage buffer! Exit and report this!\n");
453 storage_free_list
[index
] = temp_buffer
;
454 total_storage_size
+= storage_buffer_size
[index
];
455 storage_initialized
[index
] = true;
457 clear_storage_buffer (index
);
463 get_node (int handle
)
469 else if ((unsigned int) handle
>= total_storage_size
)
475 while ((unsigned int) handle
>= storage_buffer_size
[index
])
477 handle
-= storage_buffer_size
[index
++];
479 return &(storage_buffer
[index
][handle
].node
);
483 get_prop (int handle
)
489 else if ((unsigned int) handle
>= total_storage_size
)
495 while ((unsigned int) handle
>= storage_buffer_size
[index
])
497 handle
-= storage_buffer_size
[index
++];
499 return &(storage_buffer
[index
][handle
].prop
);