0
|
1 #include <nds/interrupts.h>
|
|
2 #include <nds.h>
|
|
3 #include "datum.h"
|
|
4 #include "interp.h"
|
|
5 #include "structs.h"
|
|
6 #include <string.h>
|
|
7
|
|
8 #define IRQ_STUB(num) void irq_stub_##num () { rhope_irq(num); }
|
|
9
|
|
10 datum * irq_workers[MAX_INTERRUPTS] = {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
|
|
11 program * irq_programs[MAX_INTERRUPTS];
|
|
12 worker_instance irq_instances[MAX_INTERRUPTS];
|
|
13 int irq_queue[MAX_INTERRUPTS];
|
|
14 int irq_queue_count = 0;
|
|
15
|
|
16 void rhope_irq(int num)
|
|
17 {
|
|
18 if(num < MAX_INTERRUPTS && irq_workers[num])
|
|
19 {
|
|
20 if(irq_queue_count < MAX_INTERRUPTS)
|
|
21 irq_queue[irq_queue_count++] = num;
|
|
22 //TODO Add some kind of error handling for when the IRQ_QUEUE Is full?
|
|
23 }
|
|
24 }
|
|
25
|
|
26 IRQ_STUB(0)
|
|
27 IRQ_STUB(1)
|
|
28 IRQ_STUB(2)
|
|
29 IRQ_STUB(3)
|
|
30 IRQ_STUB(4)
|
|
31 IRQ_STUB(5)
|
|
32 IRQ_STUB(6)
|
|
33 IRQ_STUB(7)
|
|
34 IRQ_STUB(8)
|
|
35 IRQ_STUB(9)
|
|
36 IRQ_STUB(10)
|
|
37 IRQ_STUB(11)
|
|
38 IRQ_STUB(12)
|
|
39 IRQ_STUB(13)
|
|
40 IRQ_STUB(14)
|
|
41 IRQ_STUB(15)
|
|
42 IRQ_STUB(16)
|
|
43 IRQ_STUB(17)
|
|
44 IRQ_STUB(18)
|
|
45 IRQ_STUB(19)
|
|
46 IRQ_STUB(20)
|
|
47 IRQ_STUB(21)
|
|
48 IRQ_STUB(22)
|
|
49 IRQ_STUB(23)
|
|
50 IRQ_STUB(24)
|
|
51
|
|
52
|
|
53
|
|
54
|
|
55 VoidFunctionPointer handlerList[MAX_INTERRUPTS] = {irq_stub_0,irq_stub_1,irq_stub_2,irq_stub_3,irq_stub_4,irq_stub_5,irq_stub_6,irq_stub_7,irq_stub_8,irq_stub_9,irq_stub_10,irq_stub_11,irq_stub_12,irq_stub_13,irq_stub_14,irq_stub_15,irq_stub_16,irq_stub_17,irq_stub_18,irq_stub_19,irq_stub_20,irq_stub_21,irq_stub_22,irq_stub_23,irq_stub_24};
|
|
56
|
|
57 int vis_register_handler(datum ** params, queue_entry * entry)
|
|
58 {
|
|
59 int num = params[0]->c.integers.num_a;
|
|
60 if(num >= MAX_INTERRUPTS)
|
|
61 {
|
|
62 release_ref(params[1]);
|
|
63 params[1] = copy_datum(params[0], 0);
|
|
64 params[0] = NULL;
|
|
65 params[1]->c.integers.num_a = MAX_INTERRUPTS-1;
|
|
66 return 0;
|
|
67 }
|
|
68 REG_IME = IME_DISABLE;
|
|
69 if(irq_workers[num])
|
|
70 release_ref(irq_workers[num]);
|
|
71 irqSet(1<<num, handlerList[num]);
|
|
72 irq_workers[num] = params[1];
|
|
73 irq_programs[num] = entry->instance->def->program; //technically the worker could be from a different program than the one doing the registering, but it's doubtful
|
|
74 irq_instances[num].def = irq_programs[num]->defs->deflist;
|
|
75 irq_instances[num].caller_instance = NULL;
|
|
76 irq_instances[num].trans = NULL;
|
|
77 irq_instances[num].num_workers = irq_instances[num].num_wires = 0;
|
|
78 VIS_InitializeCriticalSection(inst.counter_lock);
|
|
79 REG_IME = IME_ENABLE;
|
|
80 params[1] = NULL;
|
|
81 return 0;
|
|
82 }
|
|
83
|
|
84 int vis_clear_handler(datum ** params, queue_entry * entry)
|
|
85 {
|
|
86 int num = params[0]->c.integers.num_a;
|
|
87 if(num >= MAX_INTERRUPTS)
|
|
88 {
|
|
89 release_ref(params[1]);
|
|
90 params[1] = copy_datum(params[0], 0);
|
|
91 params[0] = NULL;
|
|
92 params[1]->c.integers.num_a = MAX_INTERRUPTS-1;
|
|
93 return 0;
|
|
94 }
|
|
95 REG_IME = IME_DISABLE;
|
|
96 if(irq_workers[num])
|
|
97 release_ref(irq_workers[num]);
|
|
98 irqClear(1<<num);
|
|
99 irq_workers[num] = NULL;
|
|
100 REG_IME = IME_ENABLE;
|
|
101 params[1] = NULL;
|
|
102 return 0;
|
|
103 }
|
|
104
|
|
105
|
|
106 void run_queued_irqs()
|
|
107 {
|
|
108 int irq_queue_copy[MAX_INTERRUPTS];
|
|
109 int irq_queue_count_copy;
|
|
110 int i;
|
|
111 queue_entry entry;
|
|
112 datum * params[32];
|
|
113 entry.worker_num = 0;
|
|
114 //Could this result in missed interrupts or will they just be queued in hardware until I re-enable them?
|
|
115 REG_IME = IME_DISABLE;
|
|
116 irq_queue_count_copy = irq_queue_count;
|
|
117 memcpy(irq_queue_copy, irq_queue, sizeof(int) * irq_queue_count);
|
|
118 irq_queue_count = 0;
|
|
119 REG_IME = IME_ENABLE;
|
|
120 for(i = 0; i < irq_queue_count_copy; ++i)
|
|
121 {
|
|
122 params[0] = add_ref(irq_workers[irq_queue_copy[i]]);
|
|
123 params[1] = create_list(irq_programs[irq_queue_copy[i]]);
|
|
124 params[2] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, irq_programs[irq_queue_copy[i]]);
|
|
125 params[2]->c.integers.num_a = irq_queue_copy[i];
|
|
126 vis_list_append(params + 1, &entry);
|
|
127 entry.instance = &irq_instances[irq_queue_copy[i]];
|
|
128 entry.instance->in_progress_count = entry.instance->in_queue_count = 1000;
|
|
129 vis_worker_do(params, &entry);
|
|
130 }
|
|
131
|
|
132 }
|
|
133
|
|
134 const char ndsKeyLetters[15] = "ABESRLUD><XYMC";
|
|
135 #define NDS_MAX_KEY_BITS 14
|
|
136
|
|
137 int vis_held_keys(datum ** params, queue_entry * worker_entry)
|
|
138 {
|
|
139 datum * workparams[3];
|
|
140 datum * yes;
|
|
141 char key_string[2] = " ";
|
|
142 int held,i;
|
|
143 scanKeys();
|
|
144 held = keysHeld();
|
|
145 workparams[0] = create_dict(worker_entry->instance->def->program);
|
|
146 yes = new_datum(BUILTIN_TYPE_YESNO, 2, 0, worker_entry->instance->def->program);
|
|
147 yes->c.integers.num_a = 1;
|
|
148 for(i = 0; i < NDS_MAX_KEY_BITS; ++i)
|
|
149 if(held & (1 << i))
|
|
150 {
|
|
151 key_string[0] = ndsKeyLetters[i];
|
|
152 workparams[1] = make_string(key_string, -1, worker_entry->instance->def->program);
|
|
153 workparams[2] = add_ref(yes);
|
|
154 vis_dict_set(workparams, worker_entry);
|
|
155 }
|
|
156 params[0] = workparams[0];
|
|
157 release_ref(yes);
|
|
158 return 0;
|
|
159 }
|
|
160
|
|
161 int vis_touch_position(datum ** params, queue_entry * worker_entry)
|
|
162 {
|
|
163 touchPosition touchXY;
|
|
164 touchXY=touchReadXY();
|
|
165 params[0] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
|
|
166 params[1] = new_datum(BUILTIN_TYPE_WHOLE, 2, 0, worker_entry->instance->def->program);
|
|
167 params[0]->c.integers.num_a = touchXY.px;
|
|
168 params[1]->c.integers.num_a = touchXY.py;
|
|
169 return 0;
|
|
170 }
|