diff interp.c @ 0:76568becd6d6

Rhope Alpha 2a source import
author Mike Pavone <pavone@retrodev.com>
date Tue, 28 Apr 2009 23:06:07 +0000
parents
children 23dd9c766699
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/interp.c	Tue Apr 28 23:06:07 2009 +0000
@@ -0,0 +1,4102 @@
+#ifdef WIN32
+	#include <windows.h>
+	#include <winsock.h>
+	#include <crtdbg.h>
+#else
+#ifdef SYLLABLE
+	#include <unistd.h>
+	#include <atheos/threads.h>
+#else
+	#ifdef NINTENDO_DS
+		#include <nds.h>
+	#else
+		#include <unistd.h>
+		#include <pthread.h>
+	#endif
+#endif
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include "mt19937ar.h"
+#include "interp.h"
+#include "vis_threading.h"
+#include "datum.h"
+#include "parser.h"
+#include "saveload.h"
+
+#ifdef TEXT_FILE_DEBUG
+	FILE * debugfile;
+#endif
+char debugbuffer[1024];
+
+//extern HWND	hWnd;
+extern char new_name_buf[256];
+extern int buf_size;
+
+int lock_fail_counter;
+int lock_counter;
+
+VIS_CRITICAL_SECTION(data_lock)
+VIS_CRITICAL_SECTION(worker_queue_lock)
+VIS_CRITICAL_SECTION(randlock)
+VIS_Event(queue_add_event)
+
+int program_count=1;
+VIS_CRITICAL_SECTION(program_count_lock)
+
+//#define	ENABLE_PROFILING	1
+
+#ifdef	ENABLE_PROFILING
+
+__int64	vis_profile_start_times[NUM_PROFS];
+__int64 vis_profile_running_total[NUM_PROFS];
+int	vis_profile_counts[NUM_PROFS];
+
+__declspec(naked)
+unsigned __int64 __cdecl rdtsc(void)
+{
+   __asm
+   {
+      rdtsc
+      ret       ; return value at EDX:EAX
+   }
+}
+
+
+#define PROF_INIT_CUSTOM			0
+#define	PROF_WORKER_THREAD			1
+#define	PROF_PROCESS_WORKER			2
+#define	PROF_CLEANUP_CUSTOM 		3
+#define	PROF_SUB_CALLBACK			4
+#define	PROF_CLEANUP_RELEASE_REFS	5
+#define	PROF_CLEANUP_CHECK			6
+#define	PROF_CLEANUP_FREELISTS		7
+#define	PROF_PROCESS_OUTPUTS		8
+#define	PROF_OPT_PREP_INPUT			9
+#define	PROF_RUN_OPT				10
+#define	PROF_ADDQUEUE				11
+#define	PROF_ADDQUEUE_MALLOC		12
+#define	PROF_OPT_LOOP				13
+#define	PROF_EXECUTE_WORKER			14
+#define	PROF_EXECUTE_OTHER			15
+#define	PROF_PREP_MAGIC				16
+#define	PROF_CONVERT_INPUTS			17
+#define	PROF_EXECUTE_CUSTOM			18
+#define	PROF_EXECUTE_BUILTIN		19
+#define	PROF_EMPTYFUNC				20
+#define	PROF_NOCODE					21
+#define	PROF_LESSERWHOLE			22
+#define	PROF_EQUALWHOLE				23
+#define	PROF_PARTIAL_EXEC			24
+#define	PROF_ADDWHOLE				25
+#define	PROF_FULL_EXEC				26
+#define PROF_OPT_EXEC_USER			27
+#define PROF_OPT_EXEC_BUILT			28
+#define PROF_VIRTUAL_DECODE			27
+#define PROF_VIRTUAL_EXECUTE		28
+
+
+/*#define VIS_PROFILE_START(index)	vis_profile_start_times[index] = rdtsc()
+#define	VIS_PROFILE_END(index)		vis_profile_running_total[index] += (rdtsc()-vis_profile_start_times[index]); ++vis_profile_counts[index]
+
+#else
+
+#define VIS_PROFILE_START(index)
+#define	VIS_PROFILE_END(index)*/
+
+#endif
+
+queue_entry * worker_queue;
+queue_section first_section;
+queue_section * current_section;
+int queue_start;
+int queue_len;
+
+BOOL execute_active=FALSE;
+
+char text_buf[256];
+int text_buf_size;
+VIS_CRITICAL_SECTION(text_buf_lock)
+
+#ifdef WIN32
+	WSADATA wsa_data;
+	#ifdef GUI_LIB
+		char errorbuffer[1024];
+	#endif
+#endif
+
+
+worker_instance * main_instance;
+
+//company companylist[40];
+//int num_companies=0;
+
+datum * global_store_dict;
+VIS_CRITICAL_SECTION(global_store_lock);
+
+
+int empty_func(datum ** a, queue_entry * worker_entry)
+{
+	return 0;
+}
+
+worker_impl empty_test = empty_func;
+/*
+ void set_in_child(worker_def * parent, int worker_num, BOOL * in_child, BOOL value, int exclude_worker)
+{
+	int j,i = parent->workerlist[worker_num].wire_down_lookup;
+	if(exclude_worker >= 0 && exclude_worker == worker_num)
+		return;
+	in_child[worker_num] = value;
+	while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0)
+		set_in_child(parent, parent->wirelist[j].end_worker, in_child, value);
+}
+
+void build_child_worker(worker_def * parent, int worker_num, int output_num)
+{
+	int i,j, num_child_workers, num_child_wires, child_def;
+	BOOL * in_child = malloc(sizeof(BOOL)* parent->num_workers);
+	int * child_offsets = malloc(sizeof(int) * parent->num_workers);
+	for(i = 0; i < parent->num_workers; ++i)
+	{
+		in_child[i] = FALSE;
+		child_offsets[i] = -1;
+	}
+	i = parent->workerlist[worker_num].wire_down_lookup;
+	while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0)
+	{
+		if(parent->wirelist[j].output_num == output_num)
+			set_in_child(parent, parent->wirelist[j].end_worker, in_child, TRUE,-1);
+	}
+	i = parent->workerlist[worker_num].wire_down_lookup;
+	while(parent->wirelist[j=parent->workers_to_wires_down[i]].start_worker == worker_num && j >= 0)
+	{
+		if(parent->wirelist[j].output_num != output_num)
+			set_in_child(parent, parent->wirelist[j].end_worker, in_child, FALSE,-1);
+	}
+	for(i = 0; i < parent->num_workers; ++i)
+	{
+		if(i != worker_num && (parent->workerlist[i].type == 4 || (parent->workerlist[i].type == 2 && !in_child[i])))
+			set_in_child(parent, i, in_child, FALSE);
+	}
+	for(i = 0; i < parent->num_workers; ++i)
+	{
+		if(in_child[i])
+			child_offests[i] = num_child_workers++;
+	}
+	for(i = 0; i < parent->num_wires; ++i)
+	{
+		if(in_child[parent->wirelist[i].start_worker] || in_child[parent->wirelist[i].end_worker])
+			++num_child_wires;
+	}
+	child_def = num_defs++;//needs lock or atomic incrememnt
+	deflist[child_def].workerlist = malloc(sizeof(worker)*num_child_workers);
+	deflist[child_def].wirelist = malloc(sizeof(wire)*num_child_wires);
+	for(i = 0; i < parent->num_workers; ++i)
+	{
+		if(in_child[i])
+			deflist[child_def].workerlist[child_offests[i]] = parent->workerlist[i];
+	}
+} */
+
+#define MAX_TRACE_DEPTH	40
+
+void print_stack_trace(worker_instance * stack_instance)
+{
+	int i = 0;
+	ERRORPUTS("Stack trace:\n");
+	while(stack_instance && i < MAX_TRACE_DEPTH)
+	{
+		ERRORPRINTF("%s\n", stack_instance->def->name);
+		stack_instance = stack_instance->caller_instance;
+		++i;
+	}
+	if(stack_instance)
+	{
+		ERRORPUTS("Stack trace aborted after 40 entries\n");
+	}
+}
+
+void check_tail(worker_def * def)
+{
+	custom_worker * worker = def->implement_func;
+	int i,j,k,endworker;
+	BOOL can_tail, outputs_handled[32];
+	for(i = 0; i < worker->num_workers; ++i)
+	{
+		if(worker->workerlist[i].type == WORKER)
+		{
+			can_tail = TRUE;
+			for(j = 0; j < def->num_outputs; ++j)
+				outputs_handled[j] = FALSE;
+			j = worker->workerlist[i].wire_down_lookup;
+			while((k=worker->workers_to_wires_down[j]) >= 0 && worker->wirelist[k].start_worker == i)
+			{
+				endworker = worker->wirelist[k].end_worker;
+				if(worker->workerlist[endworker].type != OUTPUT || worker->workerlist[endworker].io_num != worker->wirelist[k].output_num)
+				{
+					can_tail = FALSE;
+					break;
+				}
+				else
+					outputs_handled[worker->wirelist[k].output_num] = TRUE;
+				++j;
+			}
+			if(can_tail)
+			{
+				for(j = 0; j < def->num_outputs; ++j)
+					if(!outputs_handled[j])
+					{
+						can_tail = FALSE;
+						break;
+					}
+				if(can_tail)
+					if(worker->workerlist[i].value_index == def)
+						worker->workerlist[i].type = TAIL_RECURSE;
+					else if(!def->num_stores)
+						worker->workerlist[i].type = TAIL_CALL;
+			}
+		}
+	}
+}
+
+BOOL method_match(char * name, char * method_name)
+{
+	int i = 0;
+	while(name[i] != '\0' && method_name[i] != '@' && method_name[i] != '\0')
+	{
+		if(name[i] != method_name[i])
+			return FALSE;
+		++i;
+	}
+	if(name[i] != '\0' || method_name[i] != '@')
+		return FALSE;
+	return TRUE;
+}
+
+worker_def * find_method(int type, char * name, int num_inputs, program * prog)
+{
+	int i;
+	worker_def * output = NULL;
+	company * companylist = prog->companylist;
+	VIS_EnterCriticalSection(companylist[type].lock);
+	for(i = 0; i < companylist[type].num_methods; ++i)
+	{
+		//DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs);
+		if(companylist[type].methodlist[i]->num_inputs == num_inputs && method_match(name, companylist[type].methodlist[i]->name))
+		{
+			DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name);
+			output = companylist[type].methodlist[i];
+			break;
+		}
+	}
+	VIS_LeaveCriticalSection(companylist[type].lock);
+	return output;
+}
+
+worker_def * find_method_noinputcheck(int type, char * name, program * prog)
+{
+	int i;
+	worker_def * output = NULL;
+	company * companylist = prog->companylist;
+	VIS_EnterCriticalSection(companylist[type].lock);
+	for(i = 0; i < companylist[type].num_methods; ++i)
+	{
+		//DEBUGPRINTF( "Checking method %s(%d,%d)\n", companylist[type].methodlist[i]->name, companylist[type].methodlist[i]->num_inputs, companylist[type].methodlist[i]->num_outputs);
+		if(method_match(name, companylist[type].methodlist[i]->name))
+		{
+			DEBUGPRINTF( "Found method: %s\n", companylist[type].methodlist[i]->name);
+			output = companylist[type].methodlist[i];
+			break;
+		}
+	}
+	VIS_LeaveCriticalSection(companylist[type].lock);
+	return output;
+}
+
+worker_def * find_converter_method(int totype, int fromtype, program * prog)
+{
+	int i;
+	company * companylist = prog->companylist;
+	DEBUGPRINTF( "Finding converter from %s to %s\n", companylist[fromtype].name, companylist[totype].name);
+	//DEBUGPRINTF( "Num methods %d\n", companylist[totype].num_methods);
+	for(i = 0; i < companylist[totype].num_methods; ++i)
+	{
+		//DEBUGPRINTF("methodlist[i]: %X\n", companylist[totype].methodlist[i]);
+		DEBUGPRINTF( "Checking method %s\n", companylist[totype].methodlist[i]->name);
+		
+		if(companylist[totype].methodlist[i]->name[0] == '<' && method_match(companylist[fromtype].name, companylist[totype].methodlist[i]->name+1))
+		{
+			DEBUGPRINTF( "Found Method %s\n", companylist[totype].methodlist[i]->name);
+			
+			return companylist[totype].methodlist[i];
+		}
+	}
+	return NULL;
+}
+
+worker_instance *  init_custom_worker_type(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params, int type)
+{
+	int i, workerlist_size, j, add_index_count=0;
+	int add_index[32];
+	datum * work_params[32];
+	datum * temp_params[3];
+	global_store * store;
+	worker_instance * instance;
+	BOOL release_params = TRUE;
+	def_make_lookup(def);
+	workerlist_size = sizeof(worker_instance_data)*(def->implement_func->num_workers);
+	//DEBUGPRINTF("workerlist_size: %d * %d = %d, wirelist_size: %d * %d = %d.\n", sizeof(worker_instance_data), def->implement_func->num_workers, workerlist_size, sizeof(wire_instance_data), def->implement_func->num_wires, sizeof(wire_instance_data)*(def->implement_func->num_wires));
+	//DEBUGPRINTF("Before malloc(%d)\n",sizeof(worker_instance) + workerlist_size + sizeof(wire_instance_data)*(def->implement_func->num_wires));
+	if(type == TAIL_RECURSE || type == TAIL_CALL)
+	{
+		VIS_EnterCriticalSection(caller->counter_lock);
+			if(caller->in_progress_count <= 1 && !caller->in_queue_count)
+			{
+		VIS_LeaveCriticalSection(caller->counter_lock);
+				instance = caller;
+				for(i = 0; i < instance->num_workers; ++i)
+				{
+					if(instance->def->implement_func->workerlist[i].type != WORKER && instance->def->implement_func->workerlist[i].type != TAIL_RECURSE && instance->def->implement_func->workerlist[i].type != TAIL_CALL && instance->workerlist[i].value)
+						release_ref(instance->workerlist[i].value);
+					if(instance->workerlist[i].ready_count && instance->workerlist[i].ready_count < (instance->def->implement_func->workerlist[i].num_inputs + (instance->def->implement_func->workerlist[i].null_input ? 1 : 0)))
+					{
+						DEBUGPRINTF("Freeing params for worker number %d, ready_count: %d, num_inputs: %d, null_input: %d, instance: %X\n", i, instance->workerlist[i].ready_count,instance->def->implement_func->workerlist[i].num_inputs, instance->def->implement_func->workerlist[i].null_input, instance);
+						for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j)
+						{
+							DEBUGPRINTF("Releasing param %d of worker %d\n", j, i);
+							release_ref(instance->workerlist[i].params[j]);
+						}
+					}
+				}
+				for(i = 0; i < def->num_inputs; ++i)
+					work_params[i] = params[i];
+				params = work_params;
+				if(type == TAIL_RECURSE)
+				{
+					instance->in_progress_count = 0;
+					//TODO: adjust profile counter?
+					goto init_workerlist;
+				}
+				else
+				{
+					aworker = instance->worker_in_caller;
+					callback = instance->callback;
+					callback_data = instance->callback_data;
+					caller = instance->caller_instance;
+					VIS_DeleteCriticalSection(instance->counter_lock);
+					free(instance);
+				}
+			}
+			else
+			{
+		VIS_LeaveCriticalSection(caller->counter_lock);
+			}
+	}
+				
+			
+	instance = MALLOC(sizeof(worker_instance) + workerlist_size/* + sizeof(wire_instance_data)*(def->implement_func->num_wires) */,"instance");
+
+	//DEBUGPRINTF("malloc returned %X.\n", instance);
+	VIS_PROFILE_START(PROF_INIT_CUSTOM);
+	//DEBUGPRINTF("init_custom_worker, instance: %X\n", instance);
+#ifdef USER_PROFILE
+	QueryPerformanceCounter(&(instance->start));
+#endif
+	instance->def = def;
+	instance->num_workers = def->implement_func->num_workers;
+	instance->workerlist = (worker_instance_data *)(((char *)instance) + sizeof(worker_instance));//malloc(sizeof(worker_instance_data)*(def->implement_func->num_workers));
+	//DEBUGPRINTF("workerlist at %X\n", instance->workerlist);
+	
+	/*instance->num_wires = def->implement_func->num_wires;
+	instance->wirelist = (wire_instance_data *)(((char *)(instance->workerlist)) + workerlist_size);//malloc(sizeof(wire_instance_data)*(def->implement_func->num_wires));
+	DEBUGPRINTF("wirelist at %X\n", instance->wirelist);*/
+	
+	
+	instance->callback = callback;
+	instance->worker_in_caller = aworker;
+	instance->callback_data = callback_data;
+	instance->caller_instance = caller;
+	VIS_InitializeCriticalSection(instance->counter_lock);
+	instance->in_progress_count = 0;
+	instance->in_queue_count = 0;
+	
+	if(def->num_stores)
+	{
+		instance->trans = MALLOC(sizeof(transaction) + sizeof(global_store_use) *(def->num_stores - 1),"transaction");
+		VIS_EnterCriticalSection(global_store_lock);
+			for(i = 0; i < def->num_stores; ++i)
+			{
+				temp_params[0] = add_ref(global_store_dict);
+				temp_params[1] = make_string(def->uses_stores[i], -1, def->program);
+				vis_dict_index(temp_params, NULL);
+				if(!temp_params[0])
+				{
+					printf("Error: Global store %s is not initialized\n", def->uses_stores[i]);
+					DEBUGPRINTF("Error: Global store %s is not initialized\n", def->uses_stores[i]);
+					VIS_LeaveCriticalSection(global_store_lock);
+					return NULL;
+				}
+				instance->trans->stores[i].store = temp_params[0]->c.generic.data;
+				instance->trans->stores[i].instance_data = instance->trans->stores[i].begin_data = add_ref(instance->trans->stores[i].store->data);
+				VIS_InitializeCriticalSection(instance->trans->stores[i].lock);
+				//Is this really necessary?
+				release_ref(temp_params[0]);
+			}
+		VIS_LeaveCriticalSection(global_store_lock);
+		instance->trans->num_stores = def->num_stores;
+		if((def->transaction_flags & TRANSACTION_WRITE) && (def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY)
+		{
+			release_params = FALSE;
+			for(i = 0; i < def->num_inputs; ++i)
+				instance->trans->params[i] = params[i];
+		}
+	} else {
+		instance->trans = NULL;
+	}
+	
+
+init_workerlist:	
+	//DEBUGPUTS("init worker values\n");
+	for(i = 0; i < instance->num_workers; ++i)
+	{
+//		DEBUGPRINTF("InitializeCriticalSection on workerlist[%d].worker_lock (%X)\n", i, &(instance->workerlist[i].worker_lock));
+		VIS_InitializeCriticalSection(instance->workerlist[i].worker_lock);
+		//DEBUGPUTS("ready_count = 0\n");
+		instance->workerlist[i].ready_count = 0;
+		if(def->implement_func->workerlist[i].type == INPUT && params)
+			instance->workerlist[i].value = add_ref(params[def->implement_func->workerlist[i].io_num]);
+		else //if(def->implement_func->workerlist[i].type != 2)
+			instance->workerlist[i].value = NULL;
+		//DEBUGPRINTF("instance->workerlist[%d].value = %X\n", i, instance->workerlist[i].value);
+		for(j = 0; j <= def->implement_func->workerlist[i].num_inputs; ++j)
+			instance->workerlist[i].params[j] = NULL;
+		//DEBUGPRINTF("num_inputs: %d, null_input: %d\n", def->implement_func->workerlist[i].num_inputs, def->implement_func->workerlist[i].null_input);
+
+		//There's still a potential race condition here, but it's unlikely to occur except on a system with an insane number of cores/processors
+		//and only on custom workers that have more than 32 items that will be initially ready
+		if(!def->implement_func->workerlist[i].num_inputs && !def->implement_func->workerlist[i].null_input)
+		{
+			DEBUGPRINTF("adding worker %s(%d) to queue\n", def->implement_func->workerlist[i].name, i);
+			add_index[add_index_count++] = i;
+			if(add_index_count == 32)
+			{
+				add_multiple(add_index, add_index_count, instance);
+				add_index_count = 0;
+			}
+			//add_queue(i,instance);
+		}
+	}
+
+	if(params)
+	{
+		if(release_params)
+		{
+			//DEBUGPUTS("release params\n");
+			for(i = 0; i < def->num_inputs; ++i)
+				release_ref(params[i]);
+		}
+	}
+	if(add_index_count > 0)
+		add_multiple(add_index, add_index_count, instance);
+	VIS_PROFILE_END(PROF_INIT_CUSTOM);
+
+	return instance;
+}
+
+worker_instance *  init_custom_worker(int aworker, worker_instance * caller, worker_def * def, instance_callback callback, void * callback_data, datum ** params)
+{
+	return init_custom_worker_type(aworker, caller, def, callback, callback_data, params, WORKER);
+}
+
+void cleanup_check(queue_entry aworker)
+{
+	char msg[256];
+	VIS_EnterCriticalSection(aworker.instance->counter_lock);
+		--(aworker.instance->in_progress_count);
+		DEBUGPRINTF( "Cleanup Check on %s<%d>:%X, in_progress: %d, in_queue: %d\n", aworker.instance->def->name, aworker.instance->worker_in_caller, aworker.instance, aworker.instance->in_progress_count,aworker.instance->in_queue_count);
+		
+		if(aworker.instance->in_progress_count == 0 && aworker.instance->in_queue_count == 0)
+		{
+	VIS_LeaveCriticalSection(aworker.instance->counter_lock);
+			cleanup_custom_worker(aworker.instance, aworker.worker_num);
+		}
+		else
+		{
+	VIS_LeaveCriticalSection(aworker.instance->counter_lock);
+		}
+}
+
+void cleanup_custom_worker(worker_instance * instance, int worker_num)
+{
+	BOOL do_commit = TRUE;
+	int i,j;
+	queue_entry incaller;
+	global_store * store;
+	#ifdef USER_PROFILE
+		LARGE_INTEGER end;
+		LARGE_INTEGER duration;
+	#endif
+	if(instance->trans)
+	{
+		if(instance->def->transaction_flags & TRANSACTION_WRITE)
+		{
+			VIS_EnterCriticalSection(global_store_lock);
+				if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) != TRANSACTION_FORCE)
+				{
+					for(i = 0; i < instance->trans->num_stores; ++i)
+					{
+						if(instance->trans->stores[i].begin_data != instance->trans->stores[i].store->data)
+						{
+							do_commit = FALSE;
+							break;
+						}
+					}
+				}
+				if(do_commit)
+				{
+					for(i = 0; i < instance->trans->num_stores; ++i)
+					{
+						release_ref(instance->trans->stores[i].store->data);
+						instance->trans->stores[i].store->data = instance->trans->stores[i].instance_data;
+					}
+				}
+			VIS_LeaveCriticalSection(global_store_lock);
+			if(!do_commit)//retry transaction
+			{
+				for(i = 0; i < instance->trans->num_stores; ++i)
+					release_ref(instance->trans->stores[i].instance_data);
+				puts("retrying transaction");
+				init_custom_worker(instance->worker_in_caller, instance->caller_instance, instance->def, instance->callback, instance->callback_data, instance->trans->params);
+			}
+			else if((instance->def->transaction_flags & TRANSACTION_TYPE_MASK) == TRANSACTION_RETRY)
+				for(i = 0; i < instance->def->num_inputs; ++i)
+					release_ref(instance->trans->params[i]);
+		}
+		else
+		{
+			for(i = 0; i < instance->trans->num_stores; ++i)
+				release_ref(instance->trans->stores[i].instance_data);
+		}
+		VIS_FREE(instance->trans, "transaction");
+	}
+	VIS_PROFILE_START(PROF_CLEANUP_CUSTOM);
+	DEBUGPRINTF("Cleaning up custom worker: %s:%X\n", instance->def->name, instance);
+	
+	VIS_PROFILE_START(PROF_SUB_CALLBACK);
+	if(instance->callback && do_commit)
+		instance->callback(instance->caller_instance, instance->worker_in_caller, instance, instance->callback_data);
+	//DEBUGPUTS("About to release refs\n");
+	VIS_PROFILE_END(PROF_SUB_CALLBACK);
+	VIS_PROFILE_START(PROF_CLEANUP_RELEASE_REFS);
+	/*for(i = 0; i < instance->def->implement_func->num_wires; ++i)
+	{
+		if(instance->wirelist[i].data)
+		{
+			DEBUGPRINTF("release_ref on wire %d\n", i);
+			
+			release_ref(instance->wirelist[i].data);
+		}
+	}*/
+	for(i = 0; i < instance->num_workers; ++i)
+	{
+		if(instance->def->implement_func->workerlist[i].type != WORKER && instance->def->implement_func->workerlist[i].type != TAIL_RECURSE && instance->def->implement_func->workerlist[i].type != TAIL_CALL && instance->workerlist[i].value)
+		{
+			DEBUGPRINTF( "release_ref on worker %d in instance %X\n", i, instance);
+			release_ref(instance->workerlist[i].value);
+		}
+		if(instance->workerlist[i].ready_count && instance->workerlist[i].ready_count < (instance->def->implement_func->workerlist[i].num_inputs + (instance->def->implement_func->workerlist[i].null_input ? 1 : 0)))
+		{
+			DEBUGPRINTF("Freeing params for worker number %d, ready_count: %d, num_inputs: %d, null_input: %d, instance: %X\n", i, instance->workerlist[i].ready_count,instance->def->implement_func->workerlist[i].num_inputs, instance->def->implement_func->workerlist[i].null_input, instance);
+			for(j = 0; j <= instance->def->implement_func->workerlist[i].num_inputs; ++j)
+			{
+				DEBUGPRINTF("Releasing param %d of worker %d\n", j, i);
+				release_ref(instance->workerlist[i].params[j]);
+			}
+		}
+		VIS_DeleteCriticalSection(instance->workerlist[i].worker_lock);
+	}
+	VIS_PROFILE_END(PROF_CLEANUP_RELEASE_REFS);
+	VIS_DeleteCriticalSection(instance->counter_lock);
+	//DEBUGPUTS("freeing lists\n");
+	#ifdef USER_PROFILE
+		if(do_commit)
+		{
+			QueryPerformanceCounter(&end);
+			duration.QuadPart = end.QuadPart - instance->start.QuadPart;
+			VIS_EnterCriticalSection(instance->def->lock);
+				instance->def->total.QuadPart += duration.QuadPart;
+				++instance->def->count;
+				if(duration.QuadPart > instance->def->worst.QuadPart)
+					instance->def->worst.QuadPart = duration.QuadPart;
+			VIS_LeaveCriticalSection(instance->def->lock);
+		}
+	#endif
+	/*VIS_PROFILE_START(PROF_CLEANUP_FREELISTS);
+	free(instance->workerlist);
+	free(instance->wirelist);
+	VIS_PROFILE_END(PROF_CLEANUP_FREELISTS);*/
+	VIS_PROFILE_START(PROF_CLEANUP_CHECK);
+	if(instance->caller_instance && do_commit)
+	{
+		incaller.worker_num = instance->worker_in_caller;
+		incaller.instance = instance->caller_instance;
+		DEBUGPUTS("Calling cleanup_check on parent\n");
+		cleanup_check(incaller);
+	}
+	if(do_commit && instance->callback == main_callback)
+		release_program_ref(instance->def->program);
+	VIS_PROFILE_END(PROF_CLEANUP_CHECK);
+	VIS_PROFILE_START(PROF_CLEANUP_FREELISTS);
+	VIS_FREE(instance, "worker instance");
+	VIS_PROFILE_END(PROF_CLEANUP_FREELISTS);
+	VIS_PROFILE_END(PROF_CLEANUP_CUSTOM);
+}
+/*
+void worker_complete(queue_entry aworker)
+{
+	int i,j;
+	wire * wirelist;
+	int * workers_to_wires_down;
+	VIS_PROFILE_START(PROF_WORKER_COMPLETE);
+	DEBUGPUTS("worker_complete()\n");
+	
+	
+	i = aworker.instance->def->implement_func->workerlist[aworker.worker_num].wire_down_lookup;
+	wirelist = aworker.instance->def->implement_func->wirelist;
+	workers_to_wires_down = aworker.instance->def->implement_func->workers_to_wires_down;
+	while(wirelist[j=workers_to_wires_down[i]].start_worker == aworker.worker_num && j >= 0)
+	{
+		if(aworker.instance->wirelist[j].data)
+		{
+			DEBUGPRINTF("end_worker: %d, wirelist[%d].data = %X\n", wirelist[j].end_worker, j, aworker.instance->wirelist[j].data);
+				add_if_ready(wirelist[j].end_worker, aworker.instance);
+		}
+		++i;
+	}
+	DEBUGPUTS("worker_complete done\n");
+	VIS_PROFILE_END(PROF_WORKER_COMPLETE);
+}*/
+
+void process_outputs(datum ** params, int aworker, worker_instance * instance)
+{
+	BOOL flag=FALSE;
+	int i,j;
+	worker_def * def = instance->def;
+	//custom_worker *implement_func = def->implement_func;
+	wire * def_wires = def->implement_func->wirelist;
+	worker * def_workers = def->implement_func->workerlist;
+	VIS_PROFILE_START(PROF_PROCESS_OUTPUTS);
+	DEBUGPRINTF("Process outputs for worker %d in instance %X\n", aworker, instance);
+	DEBUGPRINTF("Num_inputs: %d, num_outputs: %d\n", def_workers[aworker].num_inputs, def_workers[aworker].num_outputs);
+	if(def_workers[aworker].num_outputs && instance->workerlist)
+	{
+		//DEBUGPRINTF("num_outputs: %d\n", def_workers[aworker].num_outputs);
+		i = def_workers[aworker].wire_down_lookup;
+		while((j=def->implement_func->workers_to_wires_down[i]) >= 0 && def_wires[j].start_worker == aworker)
+		{
+			//DEBUGPRINTF("Checking output: %d\n", def_wires[j].output_num);
+			DEBUGPRINTF("output[%d] = %X\n", def_wires[j].output_num, params[def_wires[j].output_num]);
+			DEBUGPRINTF("wire leads to worker %d, instance->workerlist: %X\n", def_wires[j].end_worker, instance->workerlist);
+			VIS_EnterCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock);
+				if(params[def_wires[j].output_num] && !instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1])
+				{
+					//DEBUGPRINTF( "add_ref on output %d\n", def_wires[j].output_num);
+					instance->workerlist[def_wires[j].end_worker].params[def_wires[j].input_num+1]=add_ref(params[def_wires[j].output_num]);
+					//DEBUGPRINTF("Ready count was: %d, ", instance->workerlist[def_wires[j].end_worker].ready_count);
+					++instance->workerlist[def_wires[j].end_worker].ready_count;
+					DEBUGPRINTF("Ready count is now: %d\n", instance->workerlist[def_wires[j].end_worker].ready_count);
+					DEBUGPRINTF("num inputs: %d, null input: %d\n", instance->def->implement_func->workerlist[def_wires[j].end_worker].num_inputs, instance->def->implement_func->workerlist[def_wires[j].end_worker].null_input);
+					if(instance->workerlist[def_wires[j].end_worker].ready_count >= (instance->def->implement_func->workerlist[def_wires[j].end_worker].num_inputs + (instance->def->implement_func->workerlist[def_wires[j].end_worker].null_input ? 1 : 0)))
+					{
+						//DEBUGPUTS("flag = true\n");
+						flag = TRUE;
+						instance->workerlist[def_wires[j].end_worker].ready_count=0;
+					}
+				}
+			VIS_LeaveCriticalSection(instance->workerlist[def_wires[j].end_worker].worker_lock);
+			if(flag)
+			{
+				DEBUGPUTS("add_queue\n");
+				add_queue(def_wires[j].end_worker, instance);
+				//add_if_ready(def_wires[j].end_worker, instance);
+				flag = FALSE;
+			}
+			++i;
+		}
+		//DEBUGPUTS("releasing refs\n");
+		
+		for(i = 0; i < def_workers[aworker].num_outputs; ++i)
+			release_ref(params[i]);
+	}
+	VIS_PROFILE_END(PROF_PROCESS_OUTPUTS);
+}
+
+void main_callback(worker_instance * junkinst, int junk, worker_instance * main_instance, void * data)
+{
+	//MessageBox(NULL, "Main Callback", "Visuality Debug", MB_OK);
+	VIS_EnterCriticalSection(program_count_lock);
+		--program_count;
+		if(program_count <= 0)
+		{
+			execute_active = FALSE;
+			VIS_SetEvent(queue_add_event);
+		}
+	VIS_LeaveCriticalSection(program_count_lock);
+	if(data)
+		release_ref((datum *)data);
+}
+
+void sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data)
+{
+	int i;
+	queue_entry incaller;
+	datum * params[32];
+	worker_def * def = done_instance->def;
+	custom_worker * implement_func = def->implement_func;
+
+	incaller.worker_num = caller_workernum;
+	incaller.instance = caller_instance;
+	for(i = 0; i < def->num_outputs; ++i)
+		params[i] = NULL;
+	for(i = 0; i < implement_func->num_workers; ++i)
+	{
+		if(implement_func->workerlist[i].type == 4)
+		{
+			if(!params[implement_func->workerlist[i].io_num])
+			{
+				params[implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value;
+				DEBUGPRINTF("Output[%d] = %X\n", implement_func->workerlist[i].io_num, done_instance->workerlist[i].value);
+				done_instance->workerlist[i].value = NULL;
+			}
+		}
+	}
+	process_outputs(params, caller_workernum, caller_instance);
+	//worker_complete(incaller);
+}
+
+void pack_list_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data)
+{
+	int i;
+	queue_entry incaller;
+	datum * params[32];
+	datum * workparams[2];
+	
+	incaller.worker_num = caller_workernum;
+	incaller.instance = caller_instance;
+	for(i = 0; i < done_instance->def->num_outputs; ++i)
+		params[i] = NULL;
+	for(i = 0; i < done_instance->def->implement_func->num_workers; ++i)
+	{
+		if(done_instance->def->implement_func->workerlist[i].type == 4)
+		{
+			if(!params[done_instance->def->implement_func->workerlist[i].io_num])
+			{
+				params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value;
+				done_instance->workerlist[i].value = NULL;
+			}
+		}
+	}
+	workparams[0] = create_list(done_instance->def->program);
+	for(i = 0; i < done_instance->def->num_outputs; ++i)
+	{
+		workparams[1] = params[i];
+		vis_list_append(workparams, NULL);
+	}
+	process_outputs(workparams, caller_workernum, caller_instance);
+	//worker_complete(incaller);
+}
+
+void transaction_sub_callback(worker_instance * caller_instance, int caller_workernum, worker_instance * done_instance, void * data)
+{
+	int i;
+	
+	pack_list_sub_callback(caller_instance, caller_workernum, done_instance, NULL);
+}
+
+int global_argc;
+char ** global_argv;
+int spin_counter;
+
+void prep_program(program * prog)
+{
+	defchunk * current;
+	int i,j;
+	make_lookup_arrays(prog);
+	current = prog->defs;
+	while(current)
+	{
+		for(i = 0; i < current->num_defs; ++i)
+		{
+			#ifdef USER_PROFILE
+				current->deflist[i].count = 0;
+				current->deflist[i].total.QuadPart = 0;
+				current->deflist[i].worst.QuadPart = 0;
+				VIS_InitializeCriticalSection(current->deflist[i].lock);
+			#endif // USER_PROFILE
+			//DEBUGPRINTF("Checking worker %s with type %X\n", current->deflist[i].name, current->deflist[i].type);
+			if(current->deflist[i].type & USER_FLAG && (current->deflist[i].type & TYPE_MASK) == WORKER_TYPE)
+			{
+				//DEBUGPRINTF("Checking for constants in worker %s\n", current->deflist[i].name);
+				for(j = 0; j < current->deflist[i].implement_func->num_workers; ++j)
+					if(current->deflist[i].implement_func->workerlist[j].type == CONSTANT)
+					{
+						//current->deflist[i].implement_func->workerlist[j].value_index = (int)(get_constant(current->deflist[i].implement_func->workerlist[j].name,-1, initial_prog));
+						//DEBUGPRINTF("Set value_index for constant to %X in worker %s at index %d\n", current->deflist[i].implement_func->workerlist[j].value_index, current->deflist[i].name, j); 
+					}
+					else if(current->deflist[i].implement_func->workerlist[j].type == WORKER || current->deflist[i].implement_func->workerlist[j].type == TAIL_CALL || current->deflist[i].implement_func->workerlist[j].type == TAIL_RECURSE)
+					{
+						current->deflist[i].implement_func->workerlist[j].num_inputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_inputs;
+						current->deflist[i].implement_func->workerlist[j].num_outputs = ((worker_def *)current->deflist[i].implement_func->workerlist[j].value_index)->num_outputs;
+					}
+					else
+						current->deflist[i].implement_func->workerlist[j].value_index = 0;
+				//DEBUGPRINTF("optimize %d\n", i);
+			#ifdef ENABLE_OPT
+				optimize(current->deflist + i);
+			#endif
+			}
+		}
+		current = current->next;
+	}
+}
+
+void interp_start(int num_threads, BOOL use_this_thread, int argc, char ** argv, program * initial_prog)
+{
+	defchunk * current;
+	datum * params[2];
+	int i, junk,create_threads,j;
+	#ifdef USER_PROFILE
+		LARGE_INTEGER frequency;
+	#endif
+	lock_fail_counter = 0;
+	lock_counter = 0;
+	spin_counter = 0;
+	
+	#ifdef WIN32
+		//_CrtSetDbgFlag(_CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_CHECK_CRT_DF | _CRTDBG_ALLOC_MEM_DF);
+		WSAStartup(MAKEWORD(1, 1), &wsa_data);
+	#endif
+	VIS_InitializeCriticalSection(randlock);
+
+	DEBUGPUTS("interp_start\n");
+#ifdef ENABLE_PROFILING
+	for(i = 0; i < NUM_PROFS; ++i)
+	{
+		vis_profile_running_total[i] = 0;
+		vis_profile_counts[i] = 0;
+	}
+	VIS_PROFILE_START(PROF_EMPTYFUNC);
+	empty_test(NULL,NULL);
+	VIS_PROFILE_END(PROF_EMPTYFUNC);
+	VIS_PROFILE_START(PROF_NOCODE);
+	VIS_PROFILE_END(PROF_NOCODE);
+#endif
+	global_argc  = argc;
+	global_argv = argv;
+	init_sync_primitives();
+	init_datum_storage();
+	init_global_storage(initial_prog);
+	//init queue
+	current_section = &first_section;
+	DEBUGPRINTF("current_section = %X, &current_section = %X\n", current_section, &current_section);
+	worker_queue = current_section->entries;
+	current_section->last = NULL;
+	current_section->next = NULL;
+	queue_start = queue_len = 0;
+//	deflist[0].num_workers = num_workers;
+//	deflist[0].num_wires = num_wires;
+	prep_program(initial_prog);
+	//MessageBox(NULL, "Before fopen", "visdbg", MB_OK);
+	init_genrand(time(NULL));
+	
+	execute_active = TRUE;
+	DEBUGPUTS("Before init_custom_worker on Main\n");
+	params[0] = create_list(initial_prog);
+	for(i = 0; i < argc; ++i)
+	{
+		params[1] = make_string(argv[i], -1, initial_prog);
+		vis_list_append(params, NULL);
+	}
+	main_instance = init_custom_worker(-1, NULL, initial_prog->defs->deflist, main_callback, NULL, params);
+	
+	//num_datum = 0;
+	#if	COMPILE_THREADS > 0
+	create_threads = COMPILE_THREADS;
+	if(num_threads > 0)
+		create_threads = num_threads;
+	if(use_this_thread)
+		--create_threads;
+
+	for(i = 0; i < create_threads; ++i)
+	{
+		#ifdef WIN32
+			CreateThread(NULL, 0, worker_thread, NULL, 0, &junk);
+		#else
+		#ifdef SYLLABLE
+			resume_thread(spawn_thread("vis_worker", worker_thread, 1, 0, NULL));
+		#else
+			pthread_t pid;
+			pthread_create(&pid, NULL, worker_thread, NULL);
+		#endif
+		#endif
+	}
+	if(use_this_thread)
+		worker_thread(NULL);
+	#else
+		worker_thread(NULL);
+	#endif
+#ifdef ENABLE_PROFILING
+	for(i = 0; i < NUM_PROFS; ++i)
+		printf("%d:\t%f,\tcount: %d,\taverage: %f\n", i, (double)vis_profile_running_total[i], vis_profile_counts[i], ((double)vis_profile_running_total[i])/((double)vis_profile_counts[i]));
+#endif
+
+#ifdef USER_PROFILE
+	printf("%-33s%12s%7s%15s%12s\n\n", "Worker", "Total", "Count", "Average", "Worst");
+	current = initial_prog->defs;
+	while(current)
+	{
+		for(i = 0; i < current->num_defs; ++i)
+		{
+			if(current->deflist[i].count > 0)
+			{
+				printf("%-33s%12.0f%7d%15.2f%12.0f\n", current->deflist[i].name, (double)current->deflist[i].total.QuadPart, current->deflist[i].count, (double)current->deflist[i].total.QuadPart / (double)current->deflist[i].count, (double)current->deflist[i].worst.QuadPart);
+			}
+		}
+		current = current->next;
+	}
+	QueryPerformanceFrequency(&frequency);
+	printf("%.0f ticks per second\n", (double)frequency.QuadPart);
+#endif
+	interp_stop();
+}
+
+void interp_stop()
+{
+	int i;
+	execute_active = FALSE;
+	close_sync_primitives();
+//	Doesn't make sense in the context of multiple programs
+//	cleanup_custom_worker(main_instance);
+#ifdef WIN32
+	WSACleanup();
+#endif
+#ifdef TEXT_FILE_DEBUG
+	fclose(debugfile);
+#endif
+}
+	
+extern 
+void init_sync_primitives()
+{
+	int i;
+	DEBUGPUTS("Initializing data_lock\n");
+	VIS_InitializeCriticalSection(data_lock);
+	DEBUGPUTS("Initializing worker_queue_lock\n");
+	VIS_InitializeCriticalSection(worker_queue_lock);
+	DEBUGPUTS("Initializing text_buf_lock\n");
+	VIS_InitializeCriticalSection(text_buf_lock);
+#ifdef SYLLABLE
+	DEBUGPUTS("vis_window_init\n");
+	vis_window_init();
+#endif
+	VIS_CreateEvent(queue_add_event);//No security parameter, auto reset, starts signaled, no name
+	
+}
+
+void close_sync_primitives()
+{
+	int i;
+	VIS_DeleteCriticalSection(data_lock);
+	VIS_DeleteCriticalSection(worker_queue_lock);
+	VIS_DestroyEvent(queue_add_event);
+
+}
+
+void init_global_storage(program * prog)
+{
+	VIS_InitializeCriticalSection(global_store_lock);
+	global_store_dict = create_dict(prog);
+}
+
+void add_multiple(int * data, int num, worker_instance * instance)
+{
+	int i, index;
+	queue_section * temp;
+	DEBUGPRINTF( "Adding %d workers\n", num);
+	
+	VIS_EnterCriticalSection(instance->counter_lock);
+		instance->in_queue_count += num;
+	VIS_LeaveCriticalSection(instance->counter_lock);
+	VIS_EnterCriticalSection(worker_queue_lock);
+		for(i = 0; i < num; ++i)
+		{
+			if(queue_len >= QUEUE_SIZE)
+			{
+				if(current_section->next)
+				{
+					//DEBUGPUTS("Moving to next queue_section\n");
+					current_section = current_section->next;
+				}
+				else
+				{
+					//DEBUGPUTS("Allocating new queue_section\n");
+					VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC);
+					temp = MALLOC(sizeof(queue_section),"queue section");
+					VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC);
+					temp->last = current_section;
+					temp->next = NULL;
+					current_section->next = temp;
+					current_section = temp;
+				}
+				worker_queue = current_section->entries;
+				queue_start = queue_len = 0;
+			}
+			if(queue_start+queue_len < QUEUE_SIZE)
+				index = queue_start+queue_len;
+			else
+				index = queue_start+queue_len-QUEUE_SIZE;
+			worker_queue[index].worker_num=data[i];
+			worker_queue[index].instance = instance;
+			++queue_len;
+		}
+	VIS_LeaveCriticalSection(worker_queue_lock);
+	//DEBUGPUTS("SetEvent\n");
+	VIS_SetEvent(queue_add_event);
+}
+
+void requeue(int data, worker_instance * instance)
+{
+	add_queue(data, instance);
+	VIS_EnterCriticalSection(instance->counter_lock);
+		--(instance->in_progress_count);
+	VIS_LeaveCriticalSection(instance->counter_lock);
+}
+
+void add_queue(int data, worker_instance * instance)
+{
+	int index;
+	queue_section * temp;
+	VIS_PROFILE_START(PROF_ADDQUEUE);
+	VIS_EnterCriticalSection(instance->counter_lock);
+		++(instance->in_queue_count);
+	VIS_LeaveCriticalSection(instance->counter_lock);
+	VIS_EnterCriticalSection(worker_queue_lock);
+		if(queue_len >= QUEUE_SIZE)
+		{
+			if(current_section->next)
+			{
+				//DEBUGPUTS("Moving to next queue_section\n");
+				current_section = current_section->next;
+			}
+			else
+			{
+				//DEBUGPUTS("Allocating new queue_section\n");
+				VIS_PROFILE_START(PROF_ADDQUEUE_MALLOC);
+				temp = MALLOC(sizeof(queue_section),"queue section");
+				VIS_PROFILE_END(PROF_ADDQUEUE_MALLOC);
+				temp->last = current_section;
+				temp->next = NULL;
+				current_section->next = temp;
+				current_section = temp;
+			}
+			worker_queue = current_section->entries;
+			queue_start = queue_len = 0;
+		}
+		else if(queue_len == 0)
+		{
+			VIS_SetEvent(queue_add_event);
+			//DEBUGPUTS("SetEvent\n");
+		}
+			
+		if(queue_start+queue_len < QUEUE_SIZE)
+			index = queue_start+queue_len;
+		else
+			index = queue_start+queue_len-QUEUE_SIZE;
+		worker_queue[index].worker_num=data;
+		worker_queue[index].instance = instance;
+		++queue_len;
+		
+	VIS_LeaveCriticalSection(worker_queue_lock);
+	VIS_PROFILE_END(PROF_ADDQUEUE);
+}
+
+/**
+* Retrieves a ready worker from the queue
+*/
+queue_entry get_queue()
+{
+	queue_entry data;
+	queue_section * temp;
+	//DEBUGPUTS("Begin get_queue()\n");
+	
+	VIS_EnterCriticalSection(worker_queue_lock);
+		while(!queue_len && execute_active)
+		{
+			//DEBUGPUTS("Queue empty, resetting event\n");
+			VIS_ResetEvent(queue_add_event);
+			VIS_LeaveCriticalSection(worker_queue_lock);
+			//DEBUGPUTS("Waiting for queue_add_event\n");
+			VIS_WaitEvent(queue_add_event);
+#ifdef NINTENDO_DS
+			//TODO make the processor sleep while waiting for IRQs
+			if(irq_queue_count > 0)
+				run_queued_irqs();
+#endif
+			VIS_EnterCriticalSection(worker_queue_lock);
+		}
+		if(queue_len > 0)
+		{
+			data = worker_queue[queue_start];
+			//DEBUGPRINTF( "Next worker in queue: %d\n", data.worker_num);
+			//DEBUGPRINTF("data.instance: %X, data.instance->workerlist: %X\n", data.instance, data.instance->workerlist);
+			/*VIS_EnterCriticalSection(data.instance->workerlist[data.worker_num].worker_lock);
+				DEBUGPUTS("Adjusting ready_count");
+				data.instance->workerlist[data.worker_num].ready_count=0;
+			VIS_LeaveCriticalSection(data.instance->workerlist[data.worker_num].worker_lock);*/
+			++queue_start;
+			--queue_len;
+			//DEBUGPUTS("Adjusted ready count.\n");
+			//DEBUGPRINTF("current_section: %X\n", current_section);
+			if(queue_len == 0 && current_section->last)
+			{
+				if(current_section->next != NULL)
+				{
+					//DEBUGPUTS("Freeing current_section->next.\n");
+					VIS_FREE(current_section->next, "ready queue node");
+					current_section->next = NULL;
+				}
+				current_section = current_section->last;
+				worker_queue = current_section->entries;
+				queue_start = 0;
+				queue_len = QUEUE_SIZE;
+			}
+			else if(queue_start == QUEUE_SIZE)
+				queue_start = 0;
+		}
+		else
+		{
+			//DEBUGPUTS("Queue empty\n");
+			data.worker_num = -2;
+		}
+	VIS_LeaveCriticalSection(worker_queue_lock);
+	//DEBUGPUTS("Left worker_queue_lock\n");
+	//MessageBox(NULL,"AfterLeave","visdbg",MB_OK);
+	if(data.worker_num >= 0)
+	{
+		VIS_EnterCriticalSection(data.instance->counter_lock);
+			//DEBUGPUTS("Adjusting in_queue/in_progress counts.\n");
+			--(data.instance->in_queue_count);
+			++(data.instance->in_progress_count);
+			DEBUGPRINTF( "Counts for %s<%d> Instance:%X after get_queue: in_queue: %d in_progress: %d\n",data.instance->def->name, data.instance->worker_in_caller, data.instance, data.instance->in_queue_count, data.instance->in_progress_count);
+			
+		VIS_LeaveCriticalSection(data.instance->counter_lock);
+	}
+	//DEBUGPUTS("End get_queue()\n");
+	
+	return data;
+}
+
+void def_make_lookup(worker_def * def)
+{
+	int i, j, upoffset, offset;
+	VIS_EnterCriticalSection(def->implement_func->lock);
+		if(def->implement_func->dirty)
+		{
+			upoffset = offset = 0;
+			for(i = 0; i < def->implement_func->num_workers; ++i)
+			{
+				def->implement_func->workerlist[i].wire_down_lookup=offset;
+				def->implement_func->workerlist[i].wire_up_lookup=upoffset;
+				for(j = 0; j < def->implement_func->num_wires; ++j)
+				{
+					if(def->implement_func->wirelist[j].start_worker == i)
+						def->implement_func->workers_to_wires_down[offset++]=j;
+					if(def->implement_func->wirelist[j].end_worker == i)
+						def->implement_func->workers_to_wires_up[upoffset++]=j;
+				}
+				//Clear tail call info
+				if(def->implement_func->workerlist[i].type == TAIL_CALL || def->implement_func->workerlist[i].type == TAIL_RECURSE)
+					def->implement_func->workerlist[i].type = WORKER;
+			}
+			def->implement_func->workers_to_wires_down[offset]=-1;
+			def->implement_func->workers_to_wires_up[upoffset]=-1;
+			check_tail(def);
+			def->implement_func->dirty = FALSE;
+		}
+	VIS_LeaveCriticalSection(def->implement_func->lock);
+}
+
+/**
+* Generates lookup array to ease navigation between workers
+*/
+void make_lookup_arrays(program * prog)
+{
+	int i,j,k, offset, upoffset;
+	worker_def * deflist;
+	defchunk * current = prog->defs;
+	while(current)
+	{
+		deflist = current->deflist;
+		for(k = 0; k < current->num_defs; ++k)
+		{
+			if(deflist[k].type & USER_FLAG && (deflist[k].type & TYPE_MASK) == WORKER_TYPE)
+				def_make_lookup(deflist + k);
+		}
+		current = current->next;
+	}
+}
+extern char _end_bss[];
+void initpredefworkers(program * prog)
+{
+	int current_def = 1;
+	int current_company = 0;
+	int current_method;
+	int comp_room;
+	company * this_comp;
+	worker_def * aworker;
+	create_company(prog, "Any Type", 0, 0, FALSE);
+	create_company(prog, "Yes No", 0, 0, FALSE);
+	
+	aworker = create_worker(prog, "Print", 1, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_print;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Random", 0, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_random;
+	
+	aworker = create_worker(prog, "Build", 1, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_build;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+
+	aworker = create_worker(prog, "End", 1, 0, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_end;
+	aworker->input_types[0] = ANY_TYPE;
+	
+	create_worker(prog, "Append", 2, 1, MAGIC_TYPE);
+	create_worker(prog, "+", 2, 1, MAGIC_TYPE);
+	create_worker(prog, "-", 2, 1, MAGIC_TYPE);
+	create_worker(prog, "*", 2, 1, MAGIC_TYPE);
+	create_worker(prog, "/", 2, 1, MAGIC_TYPE);
+	create_worker(prog, ">", 2, 1, MAGIC_TYPE);
+	create_worker(prog, "<", 2, 1, MAGIC_TYPE);
+	create_worker(prog, "=", 2, 1, MAGIC_TYPE);
+
+	aworker = create_worker(prog, "Get Input", 0, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_getinput;
+	
+	aworker = create_worker(prog, "If",1, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_if;
+	aworker->input_types[0] = BUILTIN_TYPE_YESNO;
+	
+	aworker = create_worker(prog, "Type Of",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_type_of;
+	aworker->input_types[0] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Init Store",1, 0, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)init_global_store;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Wait Forever", 0, 0, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_wait_forever;
+
+#ifdef NINTENDO_DS
+	aworker = create_worker(prog, "Register Handler", 2, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_register_handler;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WORKER;
+
+	aworker = create_worker(prog, "Clear Handler", 1, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_clear_handler;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+
+	aworker = create_worker(prog, "Held Keys", 0, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_held_keys;
+
+	aworker = create_worker(prog, "Touch Position", 0, 2, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_touch_position;
+#endif
+	
+	current_method = 0;
+	//strcpy(companylist[current_company].name, "String");
+#ifdef SEGA
+	this_comp = create_company(prog, "String", 6, 0, FALSE);
+#else
+	this_comp = create_company(prog, "String", 7, 0, FALSE);
+#endif
+	aworker = create_worker(prog, "<Whole Number@String",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_inttostring;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	//add_method(this_comp, aworker);
+
+#ifndef SEGA
+	
+	aworker = create_worker(prog, "<Real Number@String",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_realtostring;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+#endif
+	
+	aworker = create_worker(prog, "=@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_stringequal;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "<Yes No@String",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_yesnotostring;
+	aworker->input_types[0] = BUILTIN_TYPE_YESNO;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, ">@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_greaterstring;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "<@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_lesserstring;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Append@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_append;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Split@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_split;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Get Raw@String",2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_get_raw;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Put Raw@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_put_raw;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = ANY_TYPE;
+
+	aworker = create_worker(prog, "Slice@String",2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_slice;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	aworker = create_worker(prog, "Reverse@String",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_reverse;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Length@String",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_length;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Put Byte@String",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_put_byte;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Get DString@String",2, 4, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_string_get_dstring;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	current_method = 0;
+	this_comp = create_company(prog, "Whole Number", 6, 0, FALSE);
+	aworker = create_worker(prog, "<String@Whole Number",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_stringtoint;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "From Hex@Whole Number",1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_fromhex;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "=@Whole Number",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_wholeequal;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, ">@Whole Number",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_greaterint;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "<@Whole Number",2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_lesserint;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "+@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_add;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "-@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_subtract;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "*@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_mult;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "/@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_div;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	aworker = create_worker(prog, "&@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_and;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	aworker = create_worker(prog, "|@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_or;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	aworker = create_worker(prog, "LShift@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_lsh;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	aworker = create_worker(prog, "RShift@Whole Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_whole_rsh;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	current_method = 0;
+	this_comp = create_company(prog, "Real Number", 6, 0, FALSE);//<string, =, >, <, +, -
+	aworker = create_worker(prog, "<String@Real Number", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_stringtoreal;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "=@Real Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_realequal;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, ">@Real Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_greaterreal;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "<@Real Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_lesserreal;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "+@Real Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_real_add;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "-@Real Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_real_subtract;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	
+	aworker = create_worker(prog, "/@Real Number", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_real_div;
+	aworker->input_types[0] = BUILTIN_TYPE_REAL;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+
+	//add_method(this_comp, aworker);
+	
+	current_method = 0;
+	this_comp = create_company(prog, "List", 7, 1, FALSE);//Index, Append, Swap, Insert, Remove, Set, Length, New
+	comp_room = add_comp_room(this_comp, "Length", 0, 0, ROOM_NO_ACCESS, ROOM_LONG);
+	
+	aworker = create_worker(prog, "Index@List", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_index;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Append@List", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_append;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = ANY_TYPE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Swap@List",3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_swap;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Insert@List",3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_insert;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = ANY_TYPE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Remove@List", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_remove;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Set@List",3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_set;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = ANY_TYPE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Length@List", 1, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_list_length;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "New@List",0, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_new;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "First@List", 1, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_first;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	
+	aworker = create_worker(prog, "Next@List", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_list_next;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	current_method = 0;
+	this_comp = create_company(prog, "Dictionary", 5, 0, FALSE);//Index, Swap, Remove, Set, Length, New
+	aworker = create_worker(prog, "Index@Dictionary", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_index;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Swap@Dictionary",3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_swap;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_STRING;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Remove@Dictionary", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_remove;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Set@Dictionary",3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_set;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Length@Dictionary", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_length;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "New@Dictionary",0, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_new;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "First@Dictionary", 1, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_first;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+	
+	aworker = create_worker(prog, "Next@Dictionary", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dict_next;
+	aworker->input_types[0] = BUILTIN_TYPE_DICT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+
+	current_method = 0;
+#ifdef SEGA
+	this_comp = create_company(prog, "File", 0, 0, FALSE);
+#else
+	
+	this_comp = create_company(prog, "File", 7, 0, FALSE);//<String, Get FString, Get DString, Get Byte, Get Word, Get Long, Put String
+	aworker = create_worker(prog, "<String@File", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_from_string;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Get FString@File", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_get_fstring;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Get DString@File", 2, 4, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_get_dstring;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+	aworker->input_types[1] = ANY_TYPE;
+
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Get Byte@File", 1, 3, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_get_byte;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Get Word@File", 1, 3, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_get_word;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Get Long@File", 1, 3, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_get_long;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Put String@File", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_put_string;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Length@File", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_file_length;
+	aworker->input_types[0] = BUILTIN_TYPE_FILE;
+
+	//add_method(this_comp, aworker);
+#endif
+	
+	current_method = 0;
+	
+	this_comp = create_company(prog, "Worker", 3, 0, FALSE);//<String, Do, Later: methods for manipulating 
+	
+	aworker = create_worker(prog, "<String@Worker", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_from_string;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Do@Worker", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_do;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_LIST;
+	
+	aworker = create_worker(prog, "Set Input@Worker", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_setinput;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = ANY_TYPE;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Add Worker Call@Worker", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_worker_call;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_WORKER;
+	
+	aworker = create_worker(prog, "Add Wire@Worker", 5, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_wire;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[3] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[4] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Add Constant@Worker", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_constant;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Add Input@Worker", 3, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_input;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Add Output@Worker", 3, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_output;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Add Object Get@Worker", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_objectget;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Add Object Set@Worker", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_objectset;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Add Global Get@Worker", 3, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_globalget;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Add Global Set@Worker", 3, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_add_globalset;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Clear@Worker", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_clear;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	
+	aworker = create_worker(prog, "Uses@Worker", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_uses;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_LIST;
+	
+	aworker = create_worker(prog, "Set IO Counts@Worker", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_setio_counts;
+	aworker->input_types[0] = BUILTIN_TYPE_WORKER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "New@Worker", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_worker_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+#ifdef GUI_LIB
+	current_method = 0;
+	
+	this_comp = create_company(prog, "Window", 3, 0, FALSE);
+	
+	aworker = create_worker(prog, "New@Window", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Add Widget@Window", 5, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_add_widget;
+	aworker->input_types[0] = BUILTIN_TYPE_WINDOW;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = ANY_TYPE;
+	aworker->input_types[3] = BUILTIN_TYPE_REAL;
+	aworker->input_types[4] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Show@Window", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_show;
+	aworker->input_types[0] = BUILTIN_TYPE_WINDOW;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	current_method = 0;
+	this_comp = create_company(prog, "Screen Window", 3, 0, FALSE);
+	
+	aworker = create_worker(prog, "Get Value@Screen Window", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_get_value;
+	aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Set Value@Screen Window", 3, 0, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_set_value;
+	aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+#ifdef SYLLABLE
+	aworker->input_types[2] = ANY_TYPE;
+#else
+	aworker->input_types[2] = BUILTIN_TYPE_STRING;
+#endif
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Wait Close@Screen Window", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_wait_close;
+	aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN;
+	//add_method(this_comp, aworker);
+
+#ifdef SYLLABLE
+	aworker = create_worker(prog, "Add Widget@Screen Window", 5, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_window_shown_addwidget;
+	aworker->input_types[0] = BUILTIN_TYPE_WINDOW_SHOWN;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = ANY_TYPE;
+	aworker->input_types[3] = BUILTIN_TYPE_REAL;
+	aworker->input_types[4] = BUILTIN_TYPE_REAL;
+#endif
+	
+	current_method = 0;
+	create_company(prog, "Button", 2, 0, FALSE);
+	
+	aworker = create_worker(prog, "New@Button", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_button_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Set Handler@Button", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_button_set_handler;
+	aworker->input_types[0] = BUILTIN_TYPE_BUTTON;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WORKER;
+	//add_method(this_comp, aworker);
+	
+	current_method = 0;
+	create_company(prog, "Input Box", 2, 0, FALSE);
+		
+	aworker = create_worker(prog, "New@Input Box", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_inputbox_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Set Type@Input Box", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_inputbox_settype;
+	aworker->input_types[0] = BUILTIN_TYPE_INPUTBOX;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	//add_method(this_comp, aworker);
+	
+#endif
+#ifndef NO_NET
+	this_comp = create_company(prog, "Net Client", 3, 0, FALSE);
+	aworker = create_worker(prog, "New@Net Client", 2, 1, WORKER_TYPE);
+	aworker->implement_func =(custom_worker *)net_client_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Put String@Net Client", 2, 2, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)net_client_put_string;
+	aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Get FString@Net Client", 2, 3, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)net_client_get_fstring;
+	aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Get DString@Net Client", 2, 4, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)net_client_get_dstring;
+	aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Put Raw@Net Client", 2, 2, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)net_client_put_raw;
+	aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Get Raw@Net Client", 2, 3, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)net_client_get_raw;
+	aworker->input_types[0] = BUILTIN_TYPE_NETCLIENT;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Listen on Port", 2, 0, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_net_listenport;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WORKER;
+#endif
+
+	create_company(prog, "Global Store", 0, 0, FALSE);
+	
+	create_company(prog, "Program", 5, 0, FALSE);
+	
+	aworker = create_worker(prog, "New@Program", 0, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_program_new;
+	
+	aworker = create_worker(prog, "New Worker@Program", 2, 2, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_program_new_worker;
+	aworker->input_types[0] = BUILTIN_TYPE_PROGRAM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Add Worker@Program", 2, 2, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_program_add_worker;
+	aworker->input_types[0] = BUILTIN_TYPE_PROGRAM;
+	aworker->input_types[1] = BUILTIN_TYPE_WORKER;
+	
+	aworker = create_worker(prog, "Add Builtins@Program", 1, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_program_add_builtins;
+	aworker->input_types[0] = BUILTIN_TYPE_PROGRAM;
+	
+	aworker = create_worker(prog, "Run@Program", 2, 1, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_program_run;
+	aworker->input_types[0] = BUILTIN_TYPE_PROGRAM;
+	aworker->input_types[1] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Find Worker@Program", 2, 2, WORKER_TYPE);
+	aworker->implement_func = (custom_worker *)vis_program_find_worker;
+	aworker->input_types[0] = BUILTIN_TYPE_PROGRAM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+
+#ifdef GUI_LIB
+#ifdef SYLLABLE
+	create_company(prog, "Custom Widget", 2, 0, FALSE);
+	
+	aworker = create_worker(prog, "New@Custom Widget", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_customwidget_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Set Handler@Custom Widget", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_button_set_handler;
+	aworker->input_types[0] = BUILTIN_TYPE_CUSTOM_WIDGET;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WORKER;
+	//add_method(this_comp, aworker);
+	
+	create_company(prog, "Screen Custom Widget", 3, 0, FALSE);
+	
+	aworker = create_worker(prog, "Default Draw@Screen Custom Widget", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_defaultpaint;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Draw Line@Screen Custom Widget", 5, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_drawline;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	aworker->input_types[3] = BUILTIN_TYPE_REAL;
+	aworker->input_types[4] = BUILTIN_TYPE_REAL;
+	//add_method(this_comp, aworker);
+	
+	aworker = create_worker(prog, "Draw String@Screen Custom Widget", 4, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_drawstring;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	aworker->input_types[3] = BUILTIN_TYPE_REAL;
+	
+	aworker = create_worker(prog, "Set Draw Color@Screen Custom Widget", 5, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_setdrawcolor;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[2] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[3] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[4] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Move By@Screen Custom Widget", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_moveby;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	
+	aworker = create_worker(prog, "Set Handler@Screen Custom Widget", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_sethandler;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WORKER;
+	
+	aworker = create_worker(prog, "Remove Handler@Screen Custom Widget", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_removehandler;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Give Focus@Screen Custom Widget", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_givefocus;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_YESNO;
+	
+	aworker = create_worker(prog, "Add Widget@Screen Custom Widget", 5, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_screen_custom_addwidget;
+	aworker->input_types[0] = BUILTIN_TYPE_SCREEN_CUSTOM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = ANY_TYPE;
+	aworker->input_types[3] = BUILTIN_TYPE_REAL;
+	aworker->input_types[4] = BUILTIN_TYPE_REAL;
+	
+#endif
+#endif
+	create_company(prog, "Buffer", 7, 0, FALSE);
+	
+	aworker = create_worker(prog, "New@Buffer", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_new;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Lock@Buffer", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_lock;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	
+	aworker = create_worker(prog, "Unlock@Buffer", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_unlock;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	
+	aworker = create_worker(prog, "Put Byte@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_putbyte;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Write Byte@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_writebyte;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Put Word@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_putshort;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Write Word@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_writeshort;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Put Long@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_putlong;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Write Long@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_writelong;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+	
+	aworker = create_worker(prog, "Reset@Buffer", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_reset;
+	aworker->input_types[0] = BUILTIN_TYPE_BUFFER;
+	
+#if defined(SEGA) || defined(NINTENDO_DS)
+
+	aworker = create_worker(prog, "From Address@Buffer", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_buffer_fromaddress;
+	aworker->input_types[0] = BUILTIN_TYPE_WHOLE;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+#endif //SEGA
+
+	create_company(prog, "Blueprint", 4, 0, FALSE);
+	
+	aworker = create_worker(prog, "New@Blueprint", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_blueprint_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Add Field@Blueprint", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_blueprint_addfield;
+	aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Name@Blueprint", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_blueprint_name;
+	aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT;
+	
+	aworker = create_worker(prog, "Get Fields@Blueprint", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_blueprint_getfields;
+	aworker->input_types[0] = BUILTIN_TYPE_BLUEPRINT;
+	
+	aworker = create_worker(prog, "Blueprint Of", 1, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_get_blueprint;
+	aworker->input_types[0] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "Get Field", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_get_field;
+	aworker->input_types[0] = ANY_TYPE;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	
+	aworker = create_worker(prog, "Set Field", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_set_field;
+	aworker->input_types[0] = ANY_TYPE;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = ANY_TYPE;
+	
+	aworker = create_worker(prog, "New Blueprint@Program", 2, 2, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_program_newblueprint;
+	aworker->input_types[0] = BUILTIN_TYPE_PROGRAM;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+
+#ifdef SYLLABLE
+	create_company(prog, "Checkbox", 2, 0, FALSE);
+
+	aworker = create_worker(prog, "New@Checkbox", 4, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_checkbox_new;
+	aworker->input_types[0] = BUILTIN_TYPE_STRING;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+	aworker->input_types[3] = BUILTIN_TYPE_YESNO;
+
+	aworker = create_worker(prog, "Set Handler@Checkbox", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_button_set_handler;
+	aworker->input_types[0] = BUILTIN_TYPE_CHECKBOX;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WORKER;
+
+	create_company(prog, "Dropdown", 4, 0, FALSE);
+
+	aworker = create_worker(prog, "New@Dropdown", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dropdown_new;
+	aworker->input_types[0] = BUILTIN_TYPE_LIST;
+	aworker->input_types[1] = BUILTIN_TYPE_REAL;
+	aworker->input_types[2] = BUILTIN_TYPE_REAL;
+
+	aworker = create_worker(prog, "Set Handler@Dropdown", 3, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_button_set_handler;
+	aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+	aworker->input_types[2] = BUILTIN_TYPE_WORKER;
+
+	aworker = create_worker(prog, "Set Text@Dropdown", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dropdown_settext;
+	aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN;
+	aworker->input_types[1] = BUILTIN_TYPE_STRING;
+
+	aworker = create_worker(prog, "Select@Dropdown", 2, 1, WORKER_TYPE);
+	aworker->implement_func=(custom_worker *)vis_dropdown_select;
+	aworker->input_types[0] = BUILTIN_TYPE_DROPDOWN;
+	aworker->input_types[1] = BUILTIN_TYPE_WHOLE;
+#endif
+
+	/*if(current_def > num_defs)
+		num_defs = current_def;
+	if(current_company > num_companies)
+		num_companies = current_company;*/
+}
+
+void initworkers(program * prog)
+{
+	//num_defs=0;
+	//num_companies=0;
+	create_worker(prog, "Main", 0, 0, USER_FLAG | WORKER_TYPE);
+
+	initpredefworkers(prog);	
+	
+}
+/*
+void add_if_ready(int workerNum, worker_instance * instance)
+{
+	//int i, j, n, old_ready_count;
+	BOOL ready=FALSE;
+	//int paramstore[32];
+	//int * params = paramstore;
+	DEBUGPUTS("add_if_ready\n");
+	if(!instance || !instance->def)
+		return;
+	VIS_PROFILE_START(PROF_ADDREADY);
+	DEBUGPRINTF( "add_if_ready on %s\n", instance->def->implement_func->workerlist[workerNum].name);
+	VIS_EnterCriticalSection(instance->workerlist[workerNum].worker_lock);
+		++instance->workerlist[workerNum].ready_count;
+		if(instance->workerlist[workerNum].ready_count >= (instance->def->implement_func->workerlist[workerNum].num_inputs + (instance->def->implement_func->workerlist[workerNum].null_input ? 1 : 0)))
+		{
+			ready = TRUE;
+			instance->workerlist[workerNum].ready_count = 0;
+		}
+	VIS_LeaveCriticalSection(instance->workerlist[workerNum].worker_lock);
+	if(ready)
+	{
+		DEBUGPRINTF("add_queue on %s\n", instance->def->implement_func->workerlist[workerNum].name);
+		add_queue(workerNum, instance);
+	}
+	VIS_PROFILE_END(PROF_ADDREADY);
+}*/
+#define RETURN_CODE_EXIT		0xABCE1234
+#define	RETURN_CODE_IDLE		0x00BADFAD
+#define	RETURN_CODE_NORMAL		0xABBAABBA
+#define RETURN_CODE_PARALLEL	0xC001D00D
+#define GET_OP1(opcode)			((opcode & 0xF0000000) >> 28)
+#define GET_OP2(opcode)			((opcode & 0x0F000000) >> 24)
+#define	GET_INST(opcode)		((opcode & 0x00FF0000) >> 16)
+
+#define MOVE_INST		0x00
+#define ADDREF_INST		0x01
+#define	RELEASE_INST	0x02
+#define LOAD_INST		0x03
+#define	CALL_INST		0x04
+#define CALLB_INST		0x05
+#define	CALLP_INST		0x06
+#define	CALLBP_INST		0x07
+#define RETURN_INST		0x08
+#define	BRANCH_INST		0x09
+#define	BRANCHT_INST	0x0A
+#define	BRANCHF_INST	0x0B
+#define WAIT_INST		0x0C
+#define ADD_INST		0x0D
+#define SUB_INST		0x0E
+#define SUBR_INST		0x0F
+#define GREATER_INST	0x10
+#define	LESSER_INST		0x11
+
+#define REGISTER_BIT	0x8
+#define NO_OPERAND		0x7
+#define OP_REG_MASK		0x7
+#define GET_REGNUM1(opcode)		((opcode & 0x0000FF00) >> 8)
+#define GET_REGNUM2(opcode)		(opcode & 0x000000FF)
+
+#define REG_DIRECT		0
+#define REG_INDIRECT	1
+#define IMMED_8			2
+#define IMMED_32		3
+#define STACK_8			4
+#define REG_REL_32		5
+#define PC_REL_8		6
+
+#define STACK_REG		31
+#define PC_REG			30
+
+#define OPC(inst, op1, reg1, op2, reg2)	((op1 << 28) | (op2 << 24) | (inst << 16) | ((reg1 & 0xff) << 8) | (reg2 & 0xFF))
+
+//unsigned long test_program[] =
+//{
+//	OPC(LOAD_INST, PC_REL_8, 8 /* Hi */, REG_DIRECT, 0),
+//	OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0),
+//	OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0),
+//	26952//Hi
+//};
+
+unsigned long test_program[] =
+{
+	//Main:
+	OPC(LOAD_INST, PC_REL_8, 20/* 10 */, REG_DIRECT, 0),
+	OPC(LOAD_INST, PC_REL_8, 20/* 2 */, PC_REL_8, 28),
+	OPC(LOAD_INST, PC_REL_8, 20/* 1 */, PC_REL_8, 28),
+	OPC(CALL_INST, PC_REL_8, 28/* Fib: */, NO_OPERAND, 0),
+	OPC(CALLB_INST, IMMED_8, 1/* Print */, NO_OPERAND, 0),
+	OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0),
+	0x3033,//'30'
+	0x32,//'2'
+	0x31,//'1'
+	0,//2 storage
+	0,//1 storage
+	//Fib:
+	OPC(ADD_INST, IMMED_8, 8, REG_DIRECT, STACK_REG),
+	OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -4),
+	OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0),
+	OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0),
+	OPC(MOVE_INST, PC_REL_8, -28/* 2 */, REG_DIRECT, 1),
+	OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0),
+	OPC(CALLB_INST, IMMED_8, 8/* < */, NO_OPERAND, 0),
+	OPC(CALLB_INST, IMMED_8, 11/* If */, NO_OPERAND, 0),
+	OPC(BRANCHT_INST, PC_REL_8, 64/* _Base */, REG_DIRECT, 0),
+	
+	OPC(RELEASE_INST, REG_INDIRECT, 1, NO_OPERAND, 0),
+	OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0),
+	OPC(MOVE_INST, PC_REL_8, -56/* 2 */, REG_DIRECT, 1),
+	OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0),
+	OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0),
+	OPC(CALL_INST, PC_REL_8, -60/* Fib */, NO_OPERAND, 0),
+	OPC(MOVE_INST, REG_DIRECT, 0, STACK_8, -8),
+	OPC(MOVE_INST, STACK_8, -4, REG_DIRECT, 0),
+	OPC(MOVE_INST, PC_REL_8, -76/* 1 */, REG_DIRECT, 1),
+	OPC(ADDREF_INST, REG_INDIRECT, 1, NO_OPERAND, 0),
+	OPC(CALLB_INST, IMMED_8, 6/* - */, NO_OPERAND, 0),
+	OPC(CALL_INST, PC_REL_8, -84/* Fib */, NO_OPERAND, 0),
+	OPC(MOVE_INST, STACK_8, -8, REG_DIRECT, 1),
+	OPC(CALLB_INST, IMMED_8, 5/* + */, NO_OPERAND, 0),
+	OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG),
+	OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0),
+	//_Base:
+	OPC(RELEASE_INST, REG_INDIRECT, 0, NO_OPERAND, 0),
+	OPC(MOVE_INST, PC_REL_8, -112/* 1 */, REG_DIRECT, 0),
+	OPC(ADDREF_INST, REG_INDIRECT, 0, NO_OPERAND, 0),
+	OPC(SUBR_INST, IMMED_8, 8, REG_DIRECT, STACK_REG),
+	OPC(RETURN_INST, NO_OPERAND, 0, NO_OPERAND, 0),
+	
+};
+
+unsigned long * get_effective_address(char op, unsigned short regnum, unsigned long ** pc, unsigned long * registers, unsigned long * immed)
+{
+	unsigned long * add = NULL;
+	unsigned long work;
+	if(op != NO_OPERAND)
+	{
+		if(op & REGISTER_BIT)
+			add = (unsigned long *)(registers[regnum] + registers[op & OP_REG_MASK]);
+		else
+		{
+			switch(op)
+			{
+				case REG_DIRECT:
+					add = registers + regnum;
+					break;
+				case REG_INDIRECT:
+					add = (unsigned long *) registers[regnum];
+					break;
+				case IMMED_8:
+					*immed = (char)regnum;
+					add = (unsigned long *)immed;
+					break;
+				case IMMED_32:
+					*immed = *((*pc)++);
+					add = (unsigned long *)immed;
+					break;
+				case STACK_8:
+					work = (char)regnum;
+					add = (unsigned long *)(registers[STACK_REG] + work);
+					break;
+				case REG_REL_32:
+					work = *((*pc)++);
+					add = (unsigned long *)(registers[regnum] + work);
+					break;
+				case PC_REL_8:
+					work = (char)regnum;
+					add = (unsigned long *)(registers[PC_REG] + work);
+					break;
+				default:
+					break;
+			}
+		}
+	}
+	return add;
+}
+
+DWORD WINAPI virtual_processor(unsigned long * program, BOOL main)
+{
+	int i;
+	unsigned long **pc;
+	unsigned long **stack;
+	unsigned long registers[32];
+	unsigned long opcode;
+	unsigned long extra, extra2;
+	queue_entry entry;
+	stack_segment initial_stack;
+	stack_segment * current = &initial_stack;
+	char slot_usage[7];
+	char op1, op2;
+	char inst;
+	unsigned long *add1, *add2;
+	long immed1, immed2;
+	initial_stack.size = MIN_STACK_SIZE;
+	initial_stack.parent = initial_stack.child = NULL;
+	initial_stack.data[0] = main ? RETURN_CODE_EXIT : RETURN_CODE_IDLE;
+	pc = (unsigned long **)(&(registers[PC_REG]));
+	stack = (unsigned long **)(&(registers[STACK_REG]));
+	*pc = program;
+	*stack = (unsigned long *)(initial_stack.data + 1);
+	entry.instance = NULL;
+	entry.worker_num = 0;
+	DEBUGPRINTF("Virtual processor, Program start: %X\n", program);
+	#ifdef ENABLE_PROFILING
+	for(i = 0; i < NUM_PROFS; ++i)
+	{
+		vis_profile_running_total[i] = 0;
+		vis_profile_counts[i] = 0;
+	}
+	VIS_PROFILE_START(PROF_EMPTYFUNC);
+	empty_test(NULL,NULL);
+	VIS_PROFILE_END(PROF_EMPTYFUNC);
+	VIS_PROFILE_START(PROF_NOCODE);
+	VIS_PROFILE_END(PROF_NOCODE);
+#endif
+	while(execute_active)
+	{
+		VIS_PROFILE_START(PROF_VIRTUAL_DECODE);
+		DEBUGPRINTF("PC: %X\n", *pc);
+		opcode = *((*pc)++);
+		op1 = GET_OP1(opcode);
+		op2 = GET_OP2(opcode);
+		add1 = get_effective_address(op1, GET_REGNUM1(opcode), pc, registers, &immed1);
+		add2 = get_effective_address(op2, GET_REGNUM2(opcode), pc, registers, &immed2);
+		DEBUGPRINTF("Opcode: %X, Instruction: %X, op1 %X, op2 %X\n", opcode, GET_INST(opcode), op1, op2);
+		inst = GET_INST(opcode);
+		VIS_PROFILE_END(PROF_VIRTUAL_DECODE);
+		VIS_PROFILE_START(PROF_VIRTUAL_EXECUTE);
+		switch(inst)
+		{
+		case MOVE_INST:
+			*add2 = *add1;
+			break;
+		case ADDREF_INST:
+			add_ref((datum *)add1);
+			break;
+		case RELEASE_INST:
+			release_ref((datum *)add1);
+			break;
+/*
+Temporarily commented out until multiple program support is finished
+		case LOAD_INST:
+			*add2 = (long)get_constant((char *)add1, -1);
+			break;
+*/
+		case CALL_INST:
+			*((*stack)++) = (unsigned long)*pc;
+			*((*stack)++) = RETURN_CODE_NORMAL;
+			*pc = add1;
+			break;
+/*
+Temporarily commented out until multiple program support is finished
+		case CALLB_INST:
+			//TODO: Needs to be made 100% correct
+			DEBUGPRINTF("Calling builtin: %s\n", deflist[*add1].name);
+			execute_def(deflist + *add1, entry, (datum **)registers, NULL);
+			break;*/
+		case CALLP_INST:
+			//TODO Implement me
+			break;
+		case CALLBP_INST:
+			//TODO Implement me
+			break;
+		case RETURN_INST:
+			switch(*(--(*stack)))
+			{
+				case RETURN_CODE_EXIT:
+					execute_active = FALSE;
+					break;
+				case RETURN_CODE_IDLE:
+					//TODO: Implement me
+					break;
+				case RETURN_CODE_NORMAL:
+					*pc = (unsigned long *)*(--(*stack));
+					break;
+				default:
+					break;
+			}
+			break;
+		case BRANCH_INST:
+			*pc = add1;
+			break;
+		case BRANCHT_INST:
+			if(*add2)
+				*pc = add1;
+			break;
+		case BRANCHF_INST:
+			if(!*add2)
+				*pc = add1;
+			break;
+		case WAIT_INST:
+			//TODO: Implement Me
+			break;
+		case ADD_INST:
+			*add2 = *add1 + *add2;
+			break;
+		case SUB_INST:
+			*add2 = *add1 - *add2;
+			break;
+		case SUBR_INST:
+			*add2 = *add2 - *add1;
+			break;
+		case GREATER_INST:
+			*add2 = *add1 > *add2;
+			break;
+		case LESSER_INST:
+			*add2 = *add1 < *add2;
+			break;
+		default:
+			break;
+		}
+		VIS_PROFILE_END(PROF_VIRTUAL_EXECUTE);
+	}
+#ifdef ENABLE_PROFILING
+	for(i = 0; i < NUM_PROFS; ++i)
+		printf("%d:\t%f,\tcount: %d,\taverage: %f\n", i, (double)vis_profile_running_total[i], vis_profile_counts[i], ((double)vis_profile_running_total[i])/((double)vis_profile_counts[i]));
+#endif
+	return 0;
+}
+
+void test_virtual()
+{
+//	int i,j,k;
+	program * prog = new_program(START_DEF_STORAGE, START_COMP_STORAGE);
+	initpredefworkers(prog);
+	init_sync_primitives();
+	init_datum_storage();
+//TODO Uncomment me
+//	init_global_storage();
+	execute_active = TRUE;
+/*	for(i = MOVE_INST; i <= LESSER_INST; ++i)
+	{
+		for(j = 0; j < 0x10; ++j)
+		{
+			for(k = 0; k < 0x10; ++k)
+			{
+				DEBUGPRINTF("i: %X, j: %X, k: %X, OPC: %X\n", i, j, k, OPC(i, j, j, k, k));
+			}
+		}
+	}*/
+	virtual_processor(test_program, TRUE);
+}
+
+DWORD WINAPI worker_thread(LPVOID param)
+{
+	queue_entry aworker;
+	int	temp_queue_len;
+	while(execute_active)
+	{
+		VIS_PROFILE_START(PROF_WORKER_THREAD);
+#ifdef NINTENDO_DS
+		if(irq_queue_count > 0)
+			run_queued_irqs();
+#endif
+		//DEBUGPUTS("Before WaitForSingleObect\n");
+		/*VIS_EnterCriticalSection(worker_queue_lock);
+			temp_queue_len = queue_len;
+		VIS_LeaveCriticalSection(worker_queue_lock);*/
+		//DEBUGPUTS("After WaitForSingleObject\n");
+		aworker = get_queue();
+		//DEBUGPUTS("After get_queue()\n");
+		//while(execute_active && aworker.worker_num < 0)//temp_queue_len == 0 && execute_active)
+		//{
+		//	VIS_WaitEvent(queue_add_event);
+		//	aworker = get_queue();
+			/*#if COMPILE_THREADS > 0
+				#ifdef WIN32
+					Sleep(0);
+				#else
+					sleep(0);
+				#endif
+			#endif
+			VIS_EnterCriticalSection(worker_queue_lock);
+				temp_queue_len = queue_len;
+			VIS_LeaveCriticalSection(worker_queue_lock);*/
+		//}
+		
+		if(aworker.worker_num >= 0)
+		{
+			//DEBUGPUTS("Before EnterCriticalSection\n");
+			
+		/*	VIS_EnterCriticalSection(worker_queue_lock);
+				if(queue_len > 0)
+				{
+					DEBUGPUTS("SetEvent\n");
+					VIS_SetEvent(queue_add_event);
+				}
+			VIS_LeaveCriticalSection(worker_queue_lock);*/
+			DEBUGPRINTF( "\nExecuting: %s<%d>, Instance: %X\n", aworker.instance->def->implement_func->workerlist[aworker.worker_num].name,aworker.worker_num,aworker.instance);
+			
+			if(process_worker(aworker) == 0)
+			{
+				//worker_complete(aworker);
+				cleanup_check(aworker);
+				//DEBUGPUTS("After cleanup_check\n");
+				
+			}
+
+		}
+		VIS_PROFILE_END(PROF_WORKER_THREAD);
+	}
+	VIS_SetEvent(queue_add_event);
+	return 0;
+}
+
+int set_comp_room(datum ** params, int room_index, queue_entry * entry, program * prog)
+{
+	int i;
+	char * data;
+	//DEBUGPRINTF("params[0]->ref_count: %d\n", params[0]->ref_count);
+	params[0] = copy_datum(params[0], 0);
+	data = ((char *)(params[0]->c.generic.data) + (int)params[0]->company->room_list[room_index].set_func);
+	DEBUGPRINTF("Set comp room: c.generic.data = %X, +get_func = %X\n", params[0]->c.generic.data, data);
+	//TODO: input conversion
+	switch(params[0]->company->room_list[room_index].get_func_type)
+	{
+	case ROOM_BYTE:
+		*data = params[1]->c.integers.num_a;
+		release_ref(params[1]);
+		break;
+	case ROOM_SHORT:
+		*((short *)data) = params[1]->c.integers.num_a;
+		release_ref(params[1]);
+		break;
+	case ROOM_LONG:
+		*((long *)data) = params[1]->c.integers.num_a;
+		release_ref(params[1]);
+		break;
+	case ROOM_SINGLE:
+		*((float *)data) = params[1]->c.real;
+		release_ref(params[1]);
+		break;
+	case ROOM_DOUBLE:
+		*((double *)data) = params[1]->c.real;
+		release_ref(params[1]);
+		break;
+	case ROOM_VIS_REF:
+		release_ref(*((datum **)data));
+		*((datum **)data) = params[1];
+		break;
+	case ROOM_CSTRING:	//not implemented
+	case ROOM_CSTRING_STRUCT:
+	case ROOM_PSTRING:
+	case ROOM_PSTRING_STRUCT:
+	case ROOM_WORKER://not implemented
+	case ROOM_VIS_OBJECT://not implemented
+	default:
+		release_ref(params[0]);
+		release_ref(params[1]);
+		params[0] = params[1] = NULL;
+		puts("unimplemented company room type\n");
+		break;
+	}
+	return 0;
+}
+
+int set_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog)
+{
+	int i;
+	for (i = 0; i < company[0]->company->num_rooms; ++i)
+		if(!strcmp(name,company[0]->company->room_list[i].name))
+		{
+			if(room_index_ret)
+				*room_index_ret = i;
+			return set_comp_room(company, i, entry, prog);
+		}
+	if(room_index_ret)
+		*room_index_ret = -1;
+	return -1;
+}
+
+int get_comp_room(datum ** company, int room_index, queue_entry * entry, program * prog)
+{
+	int i;
+	datum * out;
+	queue_entry empty;
+	char * data = ((char *)(company[0]->c.generic.data) + (int)company[0]->company->room_list[room_index].get_func);
+	company[1] = NULL;
+	DEBUGPRINTF("Get comp room: c.generic.data = %X, +get_func = %X\n", company[0]->c.generic.data, data);
+	switch(company[0]->company->room_list[room_index].get_func_type)
+	{
+	case ROOM_BYTE:
+		out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog);
+		out->c.integers.num_a = *data;
+		break;
+	case ROOM_SHORT:
+		out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog);
+		out->c.integers.num_a = *((short *)data);
+		break;
+	case ROOM_LONG:
+		out = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, prog);
+		out->c.integers.num_a = *((long *)data);
+		break;
+	case ROOM_SINGLE:
+		out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog);
+		out->c.real = *((float *)data);
+		break;
+	case ROOM_DOUBLE:
+		out = new_datum(BUILTIN_TYPE_REAL, 3, 0, prog);
+		out->c.real = *((double *)data);
+		break;
+	case ROOM_CSTRING:
+		data = *((char **)data);
+	case ROOM_CSTRING_STRUCT:
+		out = new_datum(BUILTIN_TYPE_STRING, 1, strlen(data)+1, prog);
+		strcpy(out->c.generic.data, data);
+		break;
+	case ROOM_PSTRING:
+		data = *((char **)data);
+	case ROOM_PSTRING_STRUCT:
+		out = new_datum(BUILTIN_TYPE_STRING, 1, *((unsigned char *)data), prog);
+		memcpy(out->c.generic.data, data, *((unsigned char *)data));
+		((char *)out->c.generic.data)[*((unsigned char *)data)] = '\0';
+		break;
+	case ROOM_VIS_REF:
+		out = add_ref(*((datum **)data));
+		if(!out) {
+			company[1] = company[0];
+			company[0] = NULL;
+		}
+		break;
+	case ROOM_WORKER:
+		if(entry)
+			return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), *entry, company, sub_callback);
+		else
+		{
+			empty.instance = NULL;
+			empty.worker_num = -1;
+			return execute_def((worker_def *)(company[0]->company->room_list[room_index].get_func), empty, company, sub_callback);
+		}
+	case ROOM_VIS_OBJECT://not implemented
+	default:
+		out = NULL;
+		puts("unimplemented company room type\n");
+		break;
+	}
+	release_ref(company[0]);
+	company[0] = out;
+	return 0;
+}
+
+int get_comp_room_by_name(datum ** company, char * name, int * room_index_ret, queue_entry * entry, program * prog)
+{
+	int i;
+	for (i = 0; i < company[0]->company->num_rooms; ++i)
+		if(!strcmp(name,company[0]->company->room_list[i].name))
+		{
+			if(room_index_ret)
+				*room_index_ret = i;
+			return get_comp_room(company, i, entry, prog);
+		}
+	if(room_index_ret)
+		*room_index_ret = -1;
+	return -1;
+}
+
+datum * literal_string(char * value, int len, program * prog)
+{
+	char literalchar;
+	BOOL literal;
+	int i, bufpos, lenstr;
+	datum * returnval;
+	
+	if(len < 0) {
+		len = strlen(value);
+	}
+	
+	literal = FALSE;
+	lenstr = 0;
+	for(i = 0; i < len; ++i)
+		if(literal)
+			literal = FALSE;
+		else
+		{
+			++lenstr;
+			if(value[i] == '\\')
+				literal = TRUE;
+		}
+	//DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1);
+	returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog);
+	bufpos = 0;
+	for(i = 0; i < len; ++i)
+	{
+		if(literal)
+		{
+			literal = FALSE;
+			switch(value[i])
+			{
+			case 'n':	//newline
+				literalchar = '\n';
+				break;
+			case 'r':	//carriage return
+				literalchar = '\r';
+				break;
+			case 't':	// tab
+				literalchar = '\t';
+				break;
+			case '0':	//NULL
+				literalchar = '\0';
+				break;
+			default:
+				literalchar = value[i];
+				break;
+			}
+			((char *)returnval->c.generic.data)[bufpos++] = literalchar;
+		}
+		else
+		{
+			if(value[i] == '\\')
+				literal = TRUE;
+			else
+			{
+				((char *)returnval->c.generic.data)[bufpos++] = value[i];
+			}
+		}
+	}
+	//DEBUGPRINTF("bufpos: %d\n", bufpos);
+	((char *)returnval->c.generic.data)[bufpos] = '\0';
+	DEBUGPUTS("Constant Type: String\n");
+	return returnval;
+}
+
+datum * get_constant(char * value, int len, program * prog)
+{
+	datum * params[2];
+	datum * returnval;
+	int i = 0,bufpos;
+	int start;
+	int lenstr;
+	int leftcurly;
+	int dotcount = 0;
+	char literalchar;
+	unsigned short const_type = ANY_TYPE;
+	BOOL literal;
+	if((len == 3 && memcmp(value, "Yes", len) == 0) || (len < 0 && strcmp(value, "Yes") == 0)) 
+	{
+		DEBUGPUTS("Constnat: Yes\n");
+		returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog);
+		returnval->c.integers.num_a = 1;
+		DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a);
+		return returnval;
+	} 
+	else if((len == 2 && memcmp(value, "No", len) == 0) || (len < 0 && strcmp(value, "No") == 0)) 
+	{
+		DEBUGPUTS("Constant: No\n");
+		returnval = new_datum(BUILTIN_TYPE_YESNO, 2, 0, prog);
+		returnval->c.integers.num_a = 0;
+		DEBUGPRINTF("Company: %s, integers.num_a: %d\n", returnval->company->name, returnval->c.integers.num_a);
+		return returnval;
+	}
+	if(value[0] == '{')
+	{
+		DEBUGPUTS("Constant type: List");
+		params[0] = create_list(prog);
+		i = start = 1;
+		literal = FALSE;
+		leftcurly = 0;
+		for(;value[i] != 0 && (len < 0 || i < len); ++i)
+		{
+			if(literal)
+				literal = FALSE;
+			else
+			{
+				if(value[i] == '\\')
+					literal = TRUE;
+				else if(value[i] == '}')
+					if(leftcurly)
+						--leftcurly;
+					else
+						break;
+				else if(value[i] == '{')
+					++leftcurly;
+				else if(value[i] == ',' && !leftcurly)
+				{
+					params[1] = get_constant(value+start, i-start, prog);
+					vis_list_append(params, NULL);
+					start = i+1;
+				}
+			}
+		}
+		params[1]= get_constant(value+start, i-start, prog);
+		vis_list_append(params, NULL);
+		returnval = params[0];
+	}
+	else if(value[0] == '"')
+	{
+		if(len < 0) {
+			len = strlen(value);
+		}
+		len -= 2;
+		returnval = literal_string(value+1, len, prog);
+		
+	}
+	else
+	{
+		while(value[i] != 0 && (len < 0 || i < len))
+		{
+			if(value[i] >= '0' && value[i] <= '9')
+			{
+				if(const_type == ANY_TYPE)
+					const_type = BUILTIN_TYPE_WHOLE;
+			}
+			else if(value[i] == '.')
+			{
+				if(dotcount)
+				{
+					const_type = BUILTIN_TYPE_STRING;
+				}
+				else
+				{
+					++dotcount;
+					if(const_type == BUILTIN_TYPE_WHOLE)
+						const_type = BUILTIN_TYPE_REAL;
+				}
+			}
+			else
+			{
+				//DEBUGPRINTF("Current character: %c resulted in String\n", value[i]);
+				const_type = BUILTIN_TYPE_STRING;
+				break;
+			}
+			++i;
+		}
+	
+		if(const_type == BUILTIN_TYPE_WHOLE)
+		{
+			returnval = new_datum(const_type, 2, 0, prog);
+			returnval->c.integers.num_a = atol(value);
+			DEBUGPUTS("Constant Type: Whole Number\n");
+		}
+		else if(const_type == BUILTIN_TYPE_REAL)
+		{
+			returnval = new_datum(const_type, 3, 0, prog);
+			returnval->c.real = atof(value);
+			DEBUGPUTS("Constant Type: Real Number\n");
+		}
+		else
+		{
+			/* literal = FALSE;
+			lenstr = 0;
+			for(i = 0; (i < len || len < 0) && value[i] != 0; ++i)
+				if(literal)
+					literal = FALSE;
+				else
+				{
+					++lenstr;
+					if(value[i] == '\\')
+						literal = TRUE;
+				}
+			DEBUGPRINTF("Allocating %d bytes for string constant\n", lenstr+1);
+			returnval = new_datum(BUILTIN_TYPE_STRING, 1, lenstr+1, prog);
+			bufpos = 0;
+			for(i = 0; (i < len || len < 0) && value[i] != 0; ++i)
+			{
+				DEBUGPRINTF("bufpos: %d\n", bufpos);
+				if(literal)
+				{
+					literal = FALSE;
+					switch(value[i])
+					{
+					case 'n':	//newline
+						literalchar = '\n';
+						break;
+					case 'r':	//carriage return
+						literalchar = '\r';
+						break;
+					case 't':	// tab
+						literalchar = '\t';
+						break;
+					case '0':	//NULL
+						literalchar = '\0';
+						break;
+					default:
+						literalchar = value[i];
+						break;
+					}
+					((char *)returnval->c.generic.data)[bufpos++] = literalchar;
+				}
+				else
+				{
+					if(value[i] == '\\')
+						literal = TRUE;
+					else
+					{
+						((char *)returnval->c.generic.data)[bufpos++] = value[i];
+					}
+				}
+			}
+			DEBUGPRINTF("bufpos: %d\n", bufpos);
+			((char *)returnval->c.generic.data)[bufpos] = '\0';
+			DEBUGPUTS("Constant Type: String\n"); */
+			returnval = literal_string(value, len, prog);
+		}
+	}
+	return returnval;
+}
+
+int execute_def(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback)
+{
+	return execute_def_type(process_def, worker_entry, params, callback, NULL, WORKER);
+}
+int execute_def_data(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data)
+{
+	return execute_def_type(process_def, worker_entry, params, callback, data, WORKER);
+}
+
+int execute_def_type(worker_def * process_def, queue_entry worker_entry, datum ** params, instance_callback callback, void * data, int type)
+{
+	int returnval, i;
+	worker_instance * stack_instance;
+	worker_def *temp_def, *converter;
+	worker_def *parent_def = worker_entry.instance->def;
+	unsigned short magic_cache_type;
+	#ifdef USER_PROFILE
+		LARGE_INTEGER start, end, duration;
+	#endif
+	VIS_PROFILE_START(PROF_PREP_MAGIC);
+	if((process_def->type & TYPE_MASK) == MAGIC_TYPE)
+	{
+		DEBUGPRINTF( "Magic method: %s\n", process_def->name);
+		if(!params || !params[0])
+		{
+			ERRORPRINTF("Error: null first parmeter or null parameter array for worker %s\n", process_def->name);
+			print_stack_trace(worker_entry.instance);
+			execute_active = FALSE;
+			return -1;
+		}
+		VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock);
+			temp_def = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement;
+			magic_cache_type = parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type;
+		VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock);
+		if(!temp_def || magic_cache_type != params[0]->company->type_id)
+		{
+			DEBUGPRINTF("Finding method %s with %d inputs for type %s(%d)\n", process_def->name, process_def->num_inputs, params[0]->company->name, params[0]->company->type_id);
+			temp_def = find_method(params[0]->company->type_id,process_def->name, process_def->num_inputs, process_def->program);
+			if(!temp_def) 
+			{
+				for(i = 1; i < process_def->program->num_companies; ++i)
+				{
+					temp_def = find_method(i,process_def->name, process_def->num_inputs, process_def->program);
+					if(temp_def)
+					{
+						converter = find_converter_method(temp_def->input_types[0], params[0]->company->type_id, process_def->program);
+						if(converter)
+						{
+							((worker_impl)converter->implement_func)(params, &worker_entry);
+							break;
+						}
+						else
+						{
+							//DEBUGPRINTF("Error: Needed conversion from %s to %s for input %d of %s\n", params[0]->company->name, process_def->program->companylist[temp_def->input_types[0]].name, 0, temp_def->name);
+							//printf("Warning: Needed conversion from %s to %s for input %d of %s for loose method call\n", params[0]->company->name, process_def->program->companylist[temp_def->input_types[0]].name, 0, temp_def->name);
+							temp_def = NULL;
+						}
+					}
+				}
+			}
+			if(temp_def)
+			{
+				VIS_EnterCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock);
+					parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_implement = temp_def;
+					parent_def->implement_func->workerlist[worker_entry.worker_num].magic_cache_type = temp_def->input_types[0];
+				VIS_LeaveCriticalSection(parent_def->implement_func->workerlist[worker_entry.worker_num].lock);
+			}
+			else
+			{
+				ERRORPRINTF("Error: Company %s doesn't implement worker %s. It implements the following:\n", params[0]->company->name, process_def->name);
+				for(i = 0; i < params[0]->company->num_methods; ++i)
+				{
+					ERRORPRINTF("%s\n", params[0]->company->methodlist[i]->name);
+				}
+				print_stack_trace(worker_entry.instance);
+			}
+		}
+		process_def = temp_def;
+	}
+	VIS_PROFILE_END(PROF_PREP_MAGIC);
+	if(!process_def)
+	{
+		//DEBUGPUTS("Invalid def\n");
+		VIS_PROFILE_END(PROF_EXECUTE_WORKER);
+		execute_active = FALSE;
+		return -2;
+	}
+	
+	VIS_PROFILE_START(PROF_CONVERT_INPUTS);
+	for(i = 0; i < process_def->num_inputs; ++i)
+	{
+		DEBUGPRINTF("params[%d] = %X\n", i, params[i]);
+		if(process_def->input_types[i] != ANY_TYPE && process_def->input_types[i] != params[i]->company->type_id)
+		{
+			DEBUGPRINTF("Input %d needs conversion from %d to %d\n", i, params[i]->company->type_id, process_def->input_types[i]);
+			converter = find_converter_method(process_def->input_types[i], params[i]->company->type_id, process_def->program);
+			if(!converter)
+			{
+				if(worker_entry.instance) {
+					ERRORPRINTF("Error: Needed conversion from %s to %s for input %d of %s in worker %s\n", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name, worker_entry.instance->def->name);
+				} else {
+					DEBUGPRINTF("Error: Needed conversion from %s to %s for input %d of %s\n", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name);
+					printf("Error: Needed conversion from %s to %s for input %d of %s", params[i]->company->name, process_def->program->companylist[process_def->input_types[i]].name, i, process_def->name);
+				}
+				execute_active = FALSE;
+				VIS_PROFILE_END(PROF_PROCESS_WORKER);
+				return -3;
+			}
+			((worker_impl)(converter->implement_func))(params+i, &worker_entry);
+		}
+	}
+	VIS_PROFILE_END(PROF_CONVERT_INPUTS);
+			
+	if(process_def->type & USER_FLAG)
+	{
+		VIS_PROFILE_START(PROF_EXECUTE_CUSTOM);
+		//
+		init_custom_worker_type(worker_entry.worker_num, worker_entry.instance, process_def, callback, data, params, type);
+		VIS_PROFILE_END(PROF_EXECUTE_CUSTOM);
+		VIS_PROFILE_END(PROF_PROCESS_WORKER);
+		VIS_PROFILE_END(PROF_EXECUTE_WORKER);
+		return 1;
+	}
+	else
+	{
+		VIS_PROFILE_START(PROF_EXECUTE_BUILTIN);
+		//DEBUGPRINTF("%s: before deflist[%d].implement_func: %X. vis_append: %X vis_print: %X\n",def->implement_func->workerlist[aworker].name, def->implement_func->workerlist[aworker].value_index, (int)deflist[def->implement_func->workerlist[aworker].value_index].implement_func, (int)vis_append, (int)vis_print);
+		#ifdef USER_PROFILE
+		QueryPerformanceCounter(&start);
+		#endif
+		returnval = ((worker_impl)(process_def->implement_func))(params, &worker_entry);
+		#ifdef USER_PROFILE
+		if(!returnval)
+		{
+			QueryPerformanceCounter(&end);
+			duration.QuadPart = end.QuadPart - start.QuadPart;
+			VIS_EnterCriticalSection(process_def->lock);
+				process_def->total.QuadPart += duration.QuadPart;
+				++process_def->count;
+				if(duration.QuadPart > process_def->worst.QuadPart)
+					process_def->worst.QuadPart = duration.QuadPart;
+			VIS_LeaveCriticalSection(process_def->lock);
+		}
+		#endif
+		//DEBUGPUTS("Builtin worker returned\n");
+		VIS_PROFILE_END(PROF_EXECUTE_BUILTIN);
+		return returnval;
+	}
+}
+
+void wait_callback(worker_instance * caller_instance, int caller_workerenum, worker_instance * done_instance, void * data)
+{
+	int i;
+	def_done * done = (def_done *)data;
+	//DEBUGPUTS("begin wait_callback\n");
+	for(i = 0; i < done_instance->def->num_outputs; ++i)
+		done->params[i] = NULL;
+	for(i = 0; i < done_instance->def->implement_func->num_workers; ++i)
+	{
+		if(done_instance->def->implement_func->workerlist[i].type == 4)
+		{
+			if(!(done->params[done_instance->def->implement_func->workerlist[i].io_num]))
+			{
+				done->params[done_instance->def->implement_func->workerlist[i].io_num] = done_instance->workerlist[i].value;
+				done_instance->workerlist[i].value = NULL;
+			}
+		}
+	}
+	//DEBUGPUTS("Before EnterCritical\n");
+	VIS_EnterCriticalSection(done->lock);
+		done->done_flag = TRUE;
+	VIS_LeaveCriticalSection(done->lock);
+	//DEBUGPUTS("After EnterCritical\n");
+}
+
+
+BOOL execute_def_wait(worker_def * def, datum ** params)
+{
+	int val;
+	def_done done;
+	queue_entry entry;
+	entry.worker_num = 0;
+	entry.instance = NULL;
+	VIS_InitializeCriticalSection(done.lock);
+	done.done_flag = FALSE;
+	done.params = params;
+	val = execute_def_data(def, entry, params, wait_callback, &done);
+	if(val == 0)
+		return TRUE;
+	else if (val < 0)
+		return FALSE;
+	while(1)
+	{
+		VIS_EnterCriticalSection(done.lock);
+			if(done.done_flag)
+			{
+				VIS_DeleteCriticalSection(done.lock);
+				break;
+			}
+		VIS_LeaveCriticalSection(done.lock);
+#if COMPILE_THREADS > 1
+	#ifdef WIN32
+		Sleep(0);
+	#else
+		sleep(0);
+	#endif
+#endif
+	}
+	return TRUE;
+}
+
+int process_worker(queue_entry worker_entry)
+{
+	//datum * paramstore[32];
+	datum ** params;// = paramstore;
+	int i, j, start=0;
+	global_store * store;
+	char * varname;
+	datum * varname_dat;
+	datum * tempvalindex, *todelete;
+	int got_params=0;
+	int aworker = worker_entry.worker_num;
+	worker_instance * instance = worker_entry.instance;
+	worker_def * def = instance->def;
+	worker_def * process_def;
+	worker_def * temp_def;
+	worker_def * converter;
+	int returnval = 0;
+	short const_type;
+	char * last;
+	
+	VIS_PROFILE_START(PROF_PROCESS_WORKER);
+
+	DEBUGPRINTF( "Processing worker %d with %d inputs and %d outputs\n", aworker,def->implement_func->workerlist[aworker].num_inputs, def->implement_func->workerlist[aworker].num_outputs);
+	/*VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock);
+		for(i = 0; i < def->implement_func->workerlist[aworker].num_inputs; ++i)
+		{
+			params[i] = instance->workerlist[aworker].params[i+1];
+			DEBUGPRINTF("params[%d] = %X\n", i, params[i]);
+			instance->workerlist[aworker].params[i+1] = NULL;
+		}*/
+		if(def->implement_func->workerlist[aworker].null_input)
+		{
+			//DEBUGPUTS("About to call release_ref\n");
+			release_ref(instance->workerlist[aworker].params[0]);
+			instance->workerlist[aworker].params[0] = NULL;
+		}
+	//VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock);
+	//DEBUGPRINTF("Param check complete. returnval: %d, start: %d\n", returnval, start);
+	params = instance->workerlist[aworker].params+1;
+	
+	if(def->implement_func->workerlist[aworker].type == WORKER || def->implement_func->workerlist[aworker].type == TAIL_RECURSE || def->implement_func->workerlist[aworker].type == TAIL_CALL)//Worker
+	{
+		VIS_PROFILE_START(PROF_EXECUTE_WORKER);
+		//DEBUGPUTS("Worker\n");
+		process_def = (worker_def *)(def->implement_func->workerlist[aworker].value_index);
+		//DEBUGPUTS("Got process_def\n");
+		DEBUGPRINTF("process_def->type: %X, type & TYPE_MASK: %X\n", process_def->type, (process_def->type & TYPE_MASK));
+		
+		returnval = execute_def_type(process_def, worker_entry, params, sub_callback, NULL, def->implement_func->workerlist[aworker].type);
+		DEBUGPRINTF("execute_def returned %d\n", returnval);
+		if(returnval != 0)
+		{
+			VIS_PROFILE_END(PROF_PROCESS_WORKER);
+			VIS_PROFILE_END(PROF_EXECUTE_WORKER);
+			return returnval;
+		}
+		//DEBUGPRINTF("params[0] after execute_def: %X\n", params[0]);
+		
+		//DEBUGPUTS("Before process_outputs\n");
+		
+		process_outputs(params, aworker, instance);
+		//DEBUGPUTS("After process_outputs\n");
+		
+		VIS_PROFILE_END(PROF_EXECUTE_WORKER);
+		
+	}
+	else if(def->implement_func->workerlist[aworker].type == GET_GLOBAL)
+	{
+		varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num;
+		varname_dat = make_string(varname, -1, def->program);
+		if(def->implement_func->workerlist[aworker].value_index < 0)
+		{
+			for(i = 0; i < instance->trans->num_stores; ++i)
+			{
+				VIS_EnterCriticalSection(instance->trans->stores[i].lock);
+					params[0] = add_ref(instance->trans->stores[i].instance_data);
+				VIS_LeaveCriticalSection(instance->trans->stores[i].lock);
+				params[1] = add_ref(varname_dat);
+				vis_dict_index(params, NULL);
+				
+				if(params[0])
+				{
+					def->implement_func->workerlist[aworker].value_index = i;
+					break;
+				}
+			}
+			if(def->implement_func->workerlist[aworker].value_index < 0)
+			{
+				printf("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name);
+				DEBUGPRINTF("Error: Variable %s not found in any global stores used by worker %s\n", varname, def->name);
+				execute_active = FALSE;
+				return -1;
+			}
+		}
+		else
+		{
+			VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock);
+				params[0] = add_ref(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data);
+			VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock);
+			params[1] = varname_dat;
+			vis_dict_index(params, NULL);
+			if(!params[0])
+			{
+				printf("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name);
+				DEBUGPRINTF("Error: Global variable %s not found in worker %s\n", def->implement_func->workerlist[aworker].name, def->name);
+				execute_active = FALSE;
+				return -1;
+			}
+		}
+		process_outputs(params, aworker, instance);
+		
+			
+	}
+	else if(def->implement_func->workerlist[aworker].type == SET_GLOBAL)
+	{
+		varname = def->implement_func->workerlist[aworker].name + def->implement_func->workerlist[aworker].io_num;
+		varname_dat = make_string(varname, -1, def->program);
+		params[2] = params[0];
+		params[1] = varname_dat;
+		VIS_EnterCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock);
+			//no add_ref here because we'll be replacing instance_data with the result of vis_dict set
+			params[0] = instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data;
+			vis_dict_set(params, NULL);
+			instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].instance_data = params[0];
+		VIS_LeaveCriticalSection(instance->trans->stores[(int)def->implement_func->workerlist[aworker].value_index].lock);
+		//no outputs to process
+	}
+	else if(def->implement_func->workerlist[aworker].type == GET_COMP)
+	{
+		returnval = get_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program);
+		if(returnval)
+			return returnval;
+		process_outputs(params, aworker, instance);
+	}
+	else if(def->implement_func->workerlist[aworker].type == SET_COMP)
+	{
+		returnval = set_comp_room_by_name(params, def->implement_func->workerlist[aworker].name, NULL, &worker_entry, def->program);
+		if(returnval)
+			return returnval;
+		process_outputs(params, aworker, instance);
+	}
+	else//Variable
+	{
+		VIS_PROFILE_START(PROF_EXECUTE_OTHER);
+		if(def->implement_func->workerlist[aworker].num_inputs > 0 || def->implement_func->workerlist[aworker].type == INPUT) //Is this a Room or a constant?
+		{
+			todelete = NULL;
+			VIS_EnterCriticalSection(instance->workerlist[aworker].worker_lock);
+				if(def->implement_func->workerlist[aworker].type == OUTPUT)
+				{
+					todelete = instance->workerlist[aworker].value;
+					instance->workerlist[aworker].value = params[0];
+					DEBUGPRINTF("Setting room/output at pos %d to %X in instance %X\n", aworker, params[0], instance);
+				}
+				//tempvalindex = instance->workerlist[aworker].value;
+			VIS_LeaveCriticalSection(instance->workerlist[aworker].worker_lock);
+			if(def->implement_func->workerlist[aworker].type == INPUT)
+			{
+				params[0] = instance->workerlist[aworker].value;
+				instance->workerlist[aworker].value = NULL;
+			}
+			if(todelete)
+				release_ref(todelete);
+			if(def->implement_func->workerlist[aworker].num_outputs)
+			{
+				//add_ref(tempvalindex);
+				process_outputs(params/*&tempvalindex*/, aworker, instance);
+			}
+			
+		}
+		else
+		{
+			//Hmm, do I potentially need another lock here?
+			/*if(!(instance->def->implement_func->workerlist[aworker].value_index))
+			{
+				instance->def->implement_func->workerlist[aworker].value_index = (int)(tempvalindex=get_constant(def->implement_func->workerlist[aworker].name,-1));//(int)tempvalindex;
+			}
+			else*/
+				tempvalindex = (datum *)instance->def->implement_func->workerlist[aworker].value_index;
+			add_ref(tempvalindex);
+			process_outputs(&tempvalindex, aworker, instance);
+		}
+		VIS_PROFILE_END(PROF_EXECUTE_OTHER);
+	}
+	VIS_PROFILE_END(PROF_PROCESS_WORKER);
+	return returnval;
+}
+
+#define OPT_RESULT		0
+#define OPT_CUST_RESULT	0x10000000
+#define OPT_CONST		0x20000000
+#define OPT_INPUT		0x30000000
+
+int find_input_worker(custom_worker * cust, int aworker, int input, int *ret_output)
+{
+	int o, p, wire_count;
+	int out_worker;
+	o = cust->workerlist[aworker].wire_up_lookup;
+	wire_count = 0;
+	while(cust->wirelist[p=cust->workers_to_wires_up[o]].end_worker == aworker && p >= 0)
+	{
+		if(cust->wirelist[p].input_num == input)
+		{
+			++wire_count;
+			out_worker = cust->wirelist[p].start_worker;
+			DEBUGPRINTF("Input %d attached to %s(%d)\n", input, cust->workerlist[out_worker].name, out_worker);
+			if(ret_output)
+				*ret_output = cust->wirelist[p].output_num;
+		}
+		++o;
+	}
+	DEBUGPRINTF("wire_count: %d\n", wire_count);
+	if(wire_count == 1)
+		return out_worker;
+	return -1;
+}
+
+int make_input_code(custom_worker * cust, BOOL * in_opt, int * pos_in_opt, int source_worker, int output_num, int index, opt_entry * opts, int * branch_flags, opt_entry ** branch_refs, int input_num, program * prog)
+{
+	/*if(in_opt[source_worker])
+	{
+		if(prog->deflist[cust->workerlist[source_worker].value_index].type & USER_FLAG)
+		{
+			return OPT_CUST_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF);
+		}
+		else
+		{
+			if(strcmp(prog->deflist[cust->workerlist[source_worker].value_index].name, "If") == 0)
+			{
+				if(output_num == 0)
+				{
+					branch_flags[index] = 1;
+					if(opts[pos_in_opt[source_worker]].branch1 <= index)
+						opts[pos_in_opt[source_worker]].branch1 = index+1;
+				}
+				else
+				{
+					branch_flags[index] = 2;
+					if(opts[pos_in_opt[source_worker]].branch2 <= index)
+						opts[pos_in_opt[source_worker]].branch2 = index+1;
+				}
+				branch_refs[index] = opts + pos_in_opt[source_worker];
+			}
+			else if(branch_flags[pos_in_opt[source_worker]])
+			{
+				if(branch_flags[pos_in_opt[source_worker]] == 1)
+				{
+					branch_refs[pos_in_opt[source_worker]]->branch1 = index + 1;
+					branch_flags[index] = 1;
+				}
+				else
+				{
+					branch_refs[pos_in_opt[source_worker]]->branch1 = index + 2;
+					branch_flags[index] = 2;
+				}
+				branch_refs[index] = branch_refs[pos_in_opt[source_worker]];
+			}
+			else
+				branch_flags[index] = 0;
+			if(input_num >= 0)
+				++opts[pos_in_opt[source_worker]].output_refs[output_num];
+			DEBUGPRINTF("OPT_RESULT: opt_num: %d, output_num: %d\n", pos_in_opt[source_worker], output_num);
+			return OPT_RESULT | ((pos_in_opt[source_worker] & 0xFFFF) << 8) | (output_num & 0xFF);
+		}
+	}
+	else if(cust->workerlist[source_worker].type == CONSTANT)
+	{
+		branch_flags[index] = 0;
+		DEBUGPRINTF("OPT_CONST: %d\n", source_worker);
+		return OPT_CONST | source_worker;
+	}
+	else if(cust->workerlist[source_worker].type == INPUT)
+	{
+		branch_flags[index] = 0;
+		DEBUGPRINTF("OPT_INPUT: %d\n", cust->workerlist[source_worker].io_num);
+		return OPT_INPUT | cust->workerlist[source_worker].io_num;
+	}*/
+	return -1;
+}
+
+void optimize(worker_def * def)
+{
+	/*
+	int i,j,k,m,o,p;
+	int * const_in;
+	int num_entries = 0;
+	int aworker;
+	int adjust;
+	int source_worker;
+	int source_output;
+	int source_null;
+	int null_output;
+	int wire_count;
+	int * input_data;
+	int current_null;
+	int cust_result_count;
+	int new_start;
+	custom_worker * cust = def->implement_func;
+	int start_current, end_current, new_current;
+	worker_def * deflist = def->program->deflist;
+	opt_entry * output = malloc(sizeof(opt_entry) * def->implement_func->num_workers);
+	BOOL * in_opt = malloc(sizeof(BOOL) * cust->num_workers);
+	int * branch_flags = malloc(sizeof(int) * cust->num_workers);
+	opt_entry ** branch_refs = malloc(sizeof(int) * cust->num_workers);
+	//BOOL * real_in_opt = malloc(sizeof(BOOL) * cust->num_workers);
+	int * pos_in_opt = malloc(sizeof(int) * cust->num_workers);
+	DEBUGPRINTF("deflist: %X\n", deflist);
+	for(i = 0; i < cust->num_workers; ++i)
+	{
+		branch_flags[i] = 0;
+		DEBUGPRINTF("%d: No input pass\n", i);
+		DEBUGPRINTF("Examining: %s\n", cust->workerlist[i].name);
+		if(cust->workerlist[i].num_inputs == 0 && !cust->workerlist[i].null_input && cust->workerlist[i].type == WORKER)
+		{
+			output[num_entries].def = deflist + cust->workerlist[i].value_index;
+			DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def);
+			DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[i].name);
+			output[num_entries].original_pos = i;
+			output[num_entries].input_data = NULL;
+			if(cust->workerlist[i].num_outputs)
+			{
+				output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[i].num_outputs);
+				for(j = 0; j < cust->workerlist[i].num_outputs; ++j)
+					output[num_entries].output_refs[j] = 0;
+			}
+			else
+				output[num_entries].output_refs = NULL;
+			output[num_entries].branch1 = output[num_entries].branch2 = -1;
+			//if(!(deflist[cust->workerlist[i].value_index].type & USER_FLAG))
+			//{
+				in_opt[i] = TRUE;
+				pos_in_opt[i] = num_entries;
+			//}
+			//real_in_opt[i] = TRUE;
+			++num_entries;
+		}
+		else
+		{
+			//real_in_opt[i] = FALSE;
+			in_opt[i] = FALSE;
+		}
+	}
+	start_current = num_entries;
+	for(i = 0; i < cust->num_workers; ++i)
+	{
+		DEBUGPRINTF("%d: Second pass\n", i);
+		if(cust->workerlist[i].num_inputs == 0  && !cust->workerlist[i].null_input)
+		{
+			j = cust->workerlist[i].wire_down_lookup;
+			while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == i && k >= 0)
+			{
+				aworker = cust->wirelist[k].end_worker;
+				if(!in_opt[aworker])
+				{
+					DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker);
+					if(cust->workerlist[i].null_input)
+						adjust = 1;
+					else
+						adjust = 0;
+					input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust));
+					for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m)
+					{
+						DEBUGPRINTF("Input: %d\n", m);
+						source_worker = find_input_worker(cust, aworker, m, &source_output);
+						DEBUGPRINTF("source_worker: %d\n", source_worker);
+						if(source_worker == -1)
+							break;
+						source_worker = make_input_code(cust, in_opt, pos_in_opt, source_worker, source_output, num_entries, output, branch_flags, branch_refs, m, def->program);
+						DEBUGPRINTF("input code: %X\n", source_worker);
+						if(source_worker == -1)
+							break;
+						input_data[m+adjust] = source_worker;
+						if(source_worker == -1)
+							break;
+					}
+					if(source_worker == -1)
+						free(input_data);
+					else
+					{
+						if(cust->workerlist[aworker].type == OUTPUT)
+							output[num_entries].def = NULL;
+						else
+							output[num_entries].def = deflist + cust->workerlist[aworker].value_index;
+						DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def);
+						DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name);
+						output[num_entries].original_pos = aworker;
+						output[num_entries].input_data = input_data;
+						output[num_entries].null_inputs = adjust;
+						output[num_entries].branch1 = output[num_entries].branch2 = -1;
+						if(cust->workerlist[aworker].num_outputs)
+						{
+							output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs);
+							for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m)
+								output[num_entries].output_refs[m] = 0;
+						}
+						else
+							output[num_entries].output_refs = NULL;
+						//if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG))
+						//{
+							in_opt[aworker] = TRUE;
+							pos_in_opt[aworker] = num_entries;
+						//}
+						//real_in_opt[aworker] = TRUE;
+						++num_entries;
+						
+					}
+				}
+				++j;
+			}
+		}
+	}
+	DEBUGPUTS("Before While\n");
+	end_current = num_entries;
+	while(start_current != end_current)
+	{
+		DEBUGPRINTF("start_current: %d, end_current: %d\n", start_current, end_current);
+		new_start = num_entries;
+		for(i = start_current; i < end_current; ++i)
+		{
+			DEBUGPRINTF("opt: %d, def: %X, name: %s\n", i, output[i].def, cust->workerlist[output[i].original_pos].name);
+			j = cust->workerlist[output[i].original_pos].wire_down_lookup;
+			DEBUGPRINTF("wire_down_lookup: %d\n", j);
+			while(cust->wirelist[k=cust->workers_to_wires_down[j]].start_worker == output[i].original_pos && k >= 0)
+			{
+				DEBUGPRINTF("Wire %d is attached to worker %d output %d and worker %d input %d\n", k, cust->wirelist[k].start_worker, cust->wirelist[k].output_num, cust->wirelist[k].end_worker, cust->wirelist[k].input_num);
+				aworker = cust->wirelist[k].end_worker;
+				//FIXME: Only works if constant/input attached to only one destination
+				if(cust->workerlist[aworker].type == CONSTANT || cust->workerlist[aworker].type == INPUT)
+				{
+					DEBUGPRINTF("Worker is of type %d, ", cust->workerlist[aworker].type);
+					aworker = cust->wirelist[cust->workers_to_wires_down[cust->workerlist[aworker].wire_down_lookup]].end_worker;
+					DEBUGPRINTF("reruting to worker %d\n", aworker);
+				}
+				if(!in_opt[aworker])
+				{
+					DEBUGPRINTF("Examining: %s(%d)\n", cust->workerlist[aworker].name, aworker);
+					if(cust->workerlist[i].null_input)
+						adjust = 1;
+					else
+						adjust = 0;
+					for(m = (0-adjust); m < cust->workerlist[aworker].num_inputs; ++m)
+					{	
+						source_worker = find_input_worker(cust, aworker, m, &source_output);
+						if(source_worker == -1)
+							break;
+						if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER)
+							++adjust;
+					}
+					if(source_worker != -1)
+					{
+						current_null = 0;
+						input_data = malloc(sizeof(int)* (cust->workerlist[aworker].num_inputs+adjust));
+						cust_result_count = 0;
+						for(m = (cust->workerlist[i].null_input ? -1 : 0); m < cust->workerlist[aworker].num_inputs; ++m)
+						{
+							DEBUGPRINTF("Input: %d\n", m);
+							source_worker = find_input_worker(cust, aworker, m, &source_output);
+							if(cust->workerlist[source_worker].null_input && cust->workerlist[source_worker].type != WORKER)
+							{
+								source_null = find_input_worker(cust, source_worker, -1, &null_output);
+								if(source_null == -1)
+								{
+									source_worker = -1;
+									break;
+								}
+								source_null = make_input_code(cust, in_opt, pos_in_opt, source_null, null_output, num_entries, output, branch_flags, branch_refs,-2, def->program);
+								if((source_null & 0xF0000000) == OPT_CUST_RESULT)
+									++cust_result_count;
+								if(source_null == -1)
+								{
+									source_worker = -1;
+									break;
+								}
+								input_data[current_null++] = source_null;
+							}
+							DEBUGPRINTF("source_worker: %d\n", source_worker);
+							source_worker = make_input_code(cust, in_opt, pos_in_opt, source_worker, source_output, num_entries, output, branch_flags, branch_refs, m, def->program);
+							if((source_worker & 0xF0000000) == OPT_CUST_RESULT)
+									++cust_result_count;
+							DEBUGPRINTF("input code: %d\n", source_worker);
+							if(cust_result_count >= (cust->workerlist[aworker].num_inputs + adjust))
+								source_worker = -1;
+							if(source_worker == -1)
+								break;
+							input_data[m+adjust] = source_worker;
+						}
+						if(source_worker == -1)
+							free(input_data);
+						else
+						{
+							if(cust->workerlist[aworker].type == OUTPUT)
+								output[num_entries].def = NULL;
+							else
+								output[num_entries].def = deflist + cust->workerlist[aworker].value_index;
+							DEBUGPRINTF("Set output[%d].def = %X\n", num_entries, output[num_entries].def);
+							DEBUGPRINTF("opt: %d is %s\n\n", num_entries, cust->workerlist[aworker].name);
+							output[num_entries].original_pos = aworker;
+							output[num_entries].input_data = input_data;
+							output[num_entries].null_inputs = adjust;
+							output[num_entries].branch1 = output[num_entries].branch2 = -1;
+							if(cust->workerlist[aworker].num_outputs)
+							{
+								output[num_entries].output_refs = malloc(sizeof(int)*cust->workerlist[aworker].num_outputs);
+								for(m = 0; m < cust->workerlist[aworker].num_outputs; ++m)
+									output[num_entries].output_refs[m] = 0;
+							}
+							else
+								output[num_entries].output_refs = NULL;
+							//if(cust->workerlist[aworker].type != OUTPUT && !(deflist[cust->workerlist[aworker].value_index].type & USER_FLAG))
+							//{
+								in_opt[aworker] = TRUE;
+								pos_in_opt[aworker] = num_entries;
+							//}
+							//real_in_opt[aworker] = TRUE;
+							++num_entries;
+							
+						}
+					}
+				}
+				++j;
+			}
+		}
+		start_current = new_start;
+		end_current = num_entries;
+	}
+	def->optimized = output;
+	def->opt_count = num_entries;
+	DEBUGPUTS("optimize done\n\n\n");
+	*/
+}
+
+
+void run_optimized(worker_instance * instance, datum ** params)
+{
+	int i = 0,j,k;
+	unsigned short output, opt_num;
+	datum * this_params[32];
+	queue_entry entry;
+	datum * val;
+	BOOL skip;
+	BOOL partial_flag;
+	BOOL continue_flag;
+	int count;
+	int ready;
+	int jump_from = -1;
+	int jump_to = -1;
+	int tmp, addnum;
+	opt_entry * exec_list = instance->def->optimized;
+	datum ** results = instance->opt_results;//malloc(sizeof(datum *) * instance->def->opt_count * 32);
+	VIS_PROFILE_START(PROF_RUN_OPT);
+	entry.instance = instance;
+	for(i = 0; i < instance->def->opt_count; ++i)
+	{
+		VIS_PROFILE_START(PROF_OPT_LOOP);
+		skip = FALSE;
+		partial_flag = FALSE;
+		continue_flag = FALSE;
+		DEBUGPRINTF("\nPeparing exec_list[%d]\n", i);
+		if(exec_list[i].def)
+		{
+			DEBUGPRINTF("Name: %s\n", exec_list[i].def->name);
+			count = exec_list[i].def->num_inputs;
+		}
+		else
+			count = 1;
+		count += exec_list[i].null_inputs;
+		//DEBUGPRINTF("Input count: %d\n", count);
+		if(count && !exec_list[i].input_data)
+			puts("Runtime Error: input data is NULL\n");
+		//DEBUGPRINTF("input_data: %X\n", exec_list[i].input_data);
+		VIS_PROFILE_START(PROF_OPT_PREP_INPUT);
+		for(j = 0; j < count; ++j)
+		{
+			val = NULL;
+			continue_flag = FALSE;
+			switch(exec_list[i].input_data[j] & 0xF0000000)
+			{
+				case OPT_RESULT:
+					output = exec_list[i].input_data[j] & 0xFF;
+					opt_num = (exec_list[i].input_data[j] >> 8)& 0xFFFF;
+					DEBUGPRINTF("OPT_RESULT for input %d, opt_num: %d, output: %d\n", j, opt_num, output);
+					val = results[(opt_num * 32) | output];
+					break;
+				case OPT_CUST_RESULT:
+					val = NULL;
+					partial_flag = TRUE;
+					continue_flag = TRUE;
+					break;
+				case OPT_INPUT:
+					DEBUGPRINTF("OPT_INPUT for input %d\n", j);
+					val = add_ref(params[exec_list[i].input_data[j] & 0xFF]);
+					break;
+				case OPT_CONST:
+					DEBUGPRINTF("OPT_CONST for input %d\n", j);
+					val = add_ref((datum *)(instance->def->implement_func->workerlist[exec_list[i].input_data[j] & 0xFFFFFF].value_index));
+					break;
+				default:
+					puts("Runtime Error: Invalid bytecode\n");
+					val = NULL;
+					break;
+			}
+			if(!val && !continue_flag)
+			{
+				for(k = exec_list[i].null_inputs; k < j; ++k)
+					release_ref(this_params[k]);
+				skip = TRUE;
+				break;
+			}
+			DEBUGPRINTF("this_params[%d] = %X\n", j, val);
+			if(j >= exec_list[i].null_inputs)
+				if(val)
+					this_params[j] = /*add_ref(*/val/*)*/;
+				else
+					this_params[j] = NULL;
+
+		}
+		VIS_PROFILE_END(PROF_OPT_PREP_INPUT);
+		if(!skip)
+		{
+			if(partial_flag)
+			{
+				VIS_PROFILE_START(PROF_PARTIAL_EXEC);
+				ready = 0;
+				for(j = exec_list[i].null_inputs; j < count; ++j)
+					if(this_params[j])
+					{
+						instance->workerlist[exec_list[i].original_pos].params[j-exec_list[i].null_inputs+1] = this_params[j];
+						++ready;
+					}
+				if(instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input && this_params[exec_list[i].null_inputs-1])
+					++ready;
+				DEBUGPRINTF("ready: %d\n", ready);
+				skip = TRUE;
+				VIS_EnterCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock);
+					instance->workerlist[exec_list[i].original_pos].ready_count += ready;
+					if(instance->workerlist[exec_list[i].original_pos].ready_count >= (exec_list[i].def->num_inputs + (instance->def->implement_func->workerlist[exec_list[i].original_pos].null_input ? 1 : 0)))
+					{
+						skip = FALSE;
+						instance->workerlist[exec_list[i].original_pos].ready_count = 0;
+						
+					}
+					DEBUGPRINTF("ready_count: %d\n", instance->workerlist[exec_list[i].original_pos].ready_count);
+				VIS_LeaveCriticalSection(instance->workerlist[exec_list[i].original_pos].worker_lock);
+				if(!skip)
+					add_queue(exec_list[i].original_pos, instance);
+				VIS_PROFILE_END(PROF_PARTIAL_EXEC);
+			}
+			else if(exec_list[i].def)
+			{
+				VIS_PROFILE_START(PROF_FULL_EXEC);
+				DEBUGPRINTF("opt_exec: %s(%d)\n", exec_list[i].def->name, exec_list[i].original_pos);
+				entry.worker_num = exec_list[i].original_pos;
+				if(exec_list[i].def->type & USER_FLAG)
+				{
+					VIS_PROFILE_START(PROF_OPT_EXEC_USER);
+					instance->workerlist[exec_list[i].original_pos].params[0] = NULL;
+					memcpy(instance->workerlist[exec_list[i].original_pos].params+1, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_inputs);
+					add_queue(exec_list[i].original_pos, instance);
+					VIS_PROFILE_END(PROF_OPT_EXEC_USER);
+				}
+				else
+				{
+					VIS_PROFILE_START(PROF_OPT_EXEC_BUILT);
+					if(execute_def(exec_list[i].def, entry, this_params + exec_list[i].null_inputs, sub_callback) == 0)
+					{
+						DEBUGPUTS("Exectuted with reslts\n");
+						if(exec_list[i].output_refs)
+						{
+							for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs+exec_list[i].null_inputs); ++j)
+							{
+								DEBUGPRINTF("output_refs[%d] = %d\n", j-exec_list[i].null_inputs, exec_list[i].output_refs[j-exec_list[i].null_inputs]);
+								if(!exec_list[i].output_refs[j-exec_list[i].null_inputs])
+									release_ref(this_params[j]);
+								else if(exec_list[i].output_refs[j-exec_list[i].null_inputs] > 1)
+								{
+									/*DEBUGPRINTF("multi_add_ref(%X): %d\n", this_params[j], exec_list[i].output_refs[j-exec_list[i].null_inputs]-1);
+									tmp = (int)(&(this_params[j]->ref_count));
+									addnum = exec_list[i].output_refs[j-exec_list[i].null_inputs]-1;
+									__asm
+									{
+										mov ebx, tmp
+										mov eax, addnum
+										lock xadd dword ptr [ebx], eax
+									}*/
+									VIS_EnterCriticalSection(this_params[j]->lock);
+										this_params[j]->ref_count += exec_list[i].output_refs[j-exec_list[i].null_inputs]-1;
+										
+									VIS_LeaveCriticalSection(this_params[j]->lock);
+								}
+							}
+							memcpy(results + i*32, this_params + exec_list[i].null_inputs, sizeof(datum *) * exec_list[i].def->num_outputs);
+							if(exec_list[i].branch1 >= 0)
+							{
+								if(this_params[exec_list[i].null_inputs])
+								{
+									jump_from = exec_list[i].branch1;
+									jump_to = exec_list[i].branch2;
+								}
+								else
+								{
+									i = exec_list[i].branch1-1;
+								}
+							}
+						}
+					}
+					/*else
+					{
+						for(j = exec_list[i].null_inputs; j < (exec_list[i].def->num_outputs + exec_list[i].null_inputs); ++j)
+							results[(i*32)|j] = NULL;
+					}*/
+					VIS_PROFILE_END(PROF_OPT_EXEC_BUILT);
+				}
+				VIS_PROFILE_END(PROF_FULL_EXEC);
+				DEBUGPUTS("Executed\n");
+			}
+			else
+				instance->workerlist[exec_list[i].original_pos].value = this_params[exec_list[i].null_inputs];
+		}
+		else
+		{
+			DEBUGPUTS("Skipped\n");
+			if(exec_list[i].def)
+			{
+				for(j = 0; j < exec_list[i].def->num_outputs; ++j)
+					results[(i*32)|j] = NULL;
+			}
+		}
+		if(jump_from >= 0 && (i+1) == jump_from)
+		{
+			i = jump_to-1;
+			jump_from = -1;
+		}
+		VIS_PROFILE_END(PROF_OPT_LOOP);
+	}
+	DEBUGPUTS("run_optimized calling cleanup_check\n");
+	for(i = 0; i < instance->def->num_inputs; ++i)
+		release_ref(params[i]);
+	cleanup_check(entry);
+	VIS_PROFILE_END(PROF_RUN_OPT);
+}
+
+int vis_print(datum ** inputlist, queue_entry * worker_entry)
+{
+	int result;
+#ifdef	CONSOLE
+	puts((char *)inputlist[0]->c.generic.data);
+#else
+	MessageBox(NULL, (char *)inputlist[0]->c.generic.data, "Visuality Output", MB_OK);
+#endif
+	result = 1;
+
+	release_ref(inputlist[0]);
+	inputlist[0] = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
+	//No one else knows about this new datum yet so we can skip getting a lock
+	datum_set_yesno(inputlist[0], result);
+	return 0;
+}
+
+int vis_end(datum ** inputlist, queue_entry * worker_entry)
+{
+//	fprintf(outfile, "End worker reached.\n");
+	execute_active=FALSE;
+	release_ref(inputlist[0]);
+	//interp_stop();
+	return 0;
+}
+
+#ifdef NINTENDO_DS
+const char keyLetters[15] = "ABESRLUD><XYMC";
+#define MAX_KEY_BITS	14
+#endif
+
+int vis_getinput(datum ** inputlist, queue_entry * worker_entry)
+{
+	#ifdef NINTENDO_DS
+		int held,i,pos;
+		char tempstring[14];
+		scanKeys();
+		held = keysHeld();
+		if(held)
+		{
+			pos = 0;
+			for(i = 0; i < MAX_KEY_BITS; ++i)
+				if(held & (1 << i))
+					tempstring[pos++] = keyLetters[i];
+			inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, pos+1, worker_entry->instance->def->program);
+			memcpy(inputlist[0]->c.generic.data, tempstring, pos);
+			((char *)inputlist[0]->c.generic.data)[pos]='\0';
+			return 0;
+		}
+		else
+		{
+			requeue(worker_entry->worker_num, worker_entry->instance);
+			return 1;
+		}
+	#else
+		#ifdef CONSOLE
+			gets(text_buf);
+			text_buf_size = strlen(text_buf);
+			//Nasty hack for testing until I get around to supporting command line args propery
+			//text_buf_size = strlen(global_argv[1]);
+		#else
+		
+		while(text_buf_size <= 0)
+		{
+			Sleep(30); //TODO: replace with I/O queue mechanism
+		}
+		#endif
+	//	VIS_EnterCriticalSection(text_buf_lock);
+			DEBUGPRINTF("Allocating %d bytes\n", text_buf_size+1);
+			inputlist[0] = new_datum(BUILTIN_TYPE_STRING, 1, text_buf_size+1, worker_entry->instance->def->program);
+			DEBUGPUTS("Allocated datum.\n");
+			memcpy(inputlist[0]->c.generic.data, text_buf, text_buf_size);
+			DEBUGPUTS("Copied string.\n");
+			((char *)inputlist[0]->c.generic.data)[text_buf_size]='\0';
+			DEBUGPRINTF("Input is %s\n", inputlist[0]->c.generic.data);
+			text_buf_size = 0;
+	//	VIS_LeaveCriticalSection(text_buf_lock);
+		return 0;
+	#endif
+}
+
+int vis_if(datum ** inputlist, queue_entry * worker_entry)
+{
+	if(!(inputlist[0]->c.integers.num_a))
+	{
+		inputlist[1] = inputlist[0];
+		inputlist[0] = NULL;
+	}
+	else
+		inputlist[1] = NULL;
+	return 0;
+}
+
+int vis_build(datum ** inputlist, queue_entry * worker_entry)
+{
+	int i,j;
+	company * companylist = worker_entry->instance->def->program->companylist;
+	int num_companies = worker_entry->instance->def->program->num_companies;
+	DEBUGPRINTF("Looking for company named %s\n", inputlist[0]->c.generic.data);
+	for(i = 0; i < num_companies; ++i)
+	{
+		DEBUGPRINTF("Checking company %d:%s\n", i, companylist[i].name);
+		if(!strcmp(inputlist[0]->c.generic.data, companylist[i].name))
+			break;
+	}
+	release_ref(inputlist[0]);
+	if(i < num_companies && companylist[i].build_size > 0)
+	{
+		DEBUGPRINTF("Building company with size %d\n", companylist[i].build_size);
+		inputlist[0] = new_datum(i, 1, companylist[i].build_size, worker_entry->instance->def->program);
+		for(j = 0; j < companylist[i].build_size; ++j)
+			((char*)(inputlist[0]->c.generic.data))[j] = 0;
+	}
+	else
+	{
+		DEBUGPUTS("Could not find company\n");
+		inputlist[0] = NULL;
+	}
+	return 0;
+}
+
+int vis_wait_forever(datum ** inputlist, queue_entry * worker_entry)
+{
+	return 1;
+}
+
+int init_global_store(datum ** inputlist, queue_entry * worker_entry)
+{
+	datum * params[3];
+	global_store * store;
+	datum * store_dat = new_datum(BUILTIN_TYPE_GLOBAL_STORE, 1, sizeof(global_store), worker_entry->instance->def->program);
+	store = store_dat->c.generic.data;
+	store->name = add_ref(inputlist[0]);
+	store->data = create_dict(worker_entry->instance->def->program);
+	VIS_EnterCriticalSection(global_store_lock);
+		params[0] = global_store_dict;
+		params[1] = inputlist[0];
+		params[2] = store_dat;
+		vis_dict_set(params, NULL);
+		global_store_dict = params[0];
+		DEBUGPUTS("Global store init complete\n");
+	VIS_LeaveCriticalSection(global_store_lock);
+	DEBUGPUTS("Released global_store_lock\n");
+	inputlist[0] = NULL;
+	return 0;
+}
+
+int vis_type_of(datum ** inputlist, queue_entry * worker_entry)
+{
+	datum * output = make_string(inputlist[0]->company->name, -1, worker_entry->instance->def->program);
+	release_ref(inputlist[0]);
+	inputlist[0] = output;
+	return 0;
+}
+
+int vis_random(datum ** inputlist, queue_entry * worker_entry)
+{
+	inputlist[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
+	VIS_EnterCriticalSection(randlock);
+		inputlist[0]->c.integers.num_a = genrand_int32();
+	VIS_LeaveCriticalSection(randlock);
+	return 0;
+}