1: /*
2: * Guitar-ZyX(tm)::MasterControlProgram - portable guitar F/X controller
3: * Copyright (C) 2009 Douglas McClendon
4: *
5: * This program is free software: you can redistribute it and/or modify
6: * it under the terms of the GNU General Public License as published by
7: * the Free Software Foundation, version 3 of the License.
8: *
9: * This program is distributed in the hope that it will be useful,
10: * but WITHOUT ANY WARRANTY; without even the implied warranty of
11: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12: * GNU General Public License for more details.
13: *
14: * You should have received a copy of the GNU General Public License
15: * along with this program. If not, see <http://www.gnu.org/licenses/>.
16: */
17: /*
18: #############################################################################
19: #############################################################################
20: ##
21: ## gzmcpc::mode__tpw__jam: TouchPadWhammy Jamming Mode (i.e. the mcp's soul)
22: ##
23: #############################################################################
24: ##
25: ## Copyright 2008-2009 Douglas McClendon <dmc AT filteredperception DOT org>
26: ##
27: #############################################################################
28: #############################################################################
29: #
30: */
31:
32:
33:
34:
35: #include <nds.h>
36:
37: #include <stdio.h>
38:
39:
40: #include "debug.h"
41:
42: #include "dmc.h"
43:
44: #include "graphics.h"
45:
46: #include "input.h"
47:
48: #include "mcp.h"
49:
50: #include "metrognome.h"
51:
52: #include "modes.h"
53:
54: #include "mode__get_update.h"
55:
56: #include "mode__tpw__jam.h"
57:
58: #include "network.h"
59:
60: #include "rak.h"
61:
62: #include "sound.h"
63:
64: #include "time.h"
65:
66:
67: #include "sounds.h"
68:
69: #include "sounds_bin.h"
70:
71: #include "resources/bitmaps/dlava.h"
72:
73:
74:
75: uint8 comb_charge[COMB_WIDTH][COMB_HEIGHT];
76:
77: unsigned char x3d_intensity = 0;
78:
79: v16 model_xcenter = (MODEL_XMAX + MODEL_XMIN) / 2;
80: v16 model_ycenter = (MODEL_YMAX + MODEL_YMIN) / 2;
81: v16 model_zcenter = (MODEL_ZMAX + MODEL_ZMIN) / 2;
82: v16 model_width = MODEL_XMAX - MODEL_XMIN;
83: v16 model_height = MODEL_YMAX - MODEL_YMIN;
84: v16 model_depth = MODEL_ZMAX - MODEL_ZMIN;
85:
86:
87: int touch_whammy_enabled = 0;
88: int touch_whammy_x_midi_parm = DEFAULT_X_PARM;
89: int touch_whammy_y_midi_parm = DEFAULT_Y_PARM;
90:
91: int current_preset = 1;
92:
93: int button_x_preset_num = CM_PRESET_X_NUM;
94: int button_y_preset_num = CM_PRESET_Y_NUM;
95: int button_a_preset_num = CM_PRESET_A_NUM;
96: int button_b_preset_num = CM_PRESET_B_NUM;
97:
98: int vstrobe_bpm = VSTROBE_DEFAULT_BPM;
99: int vstrobe_enabled = 0;
100: int user_vstrobe_enabled = 0;
101:
102:
103:
104:
105:
106: void mode__tpw__jam___init(void) {
107:
108: // set main screen to be on the top lcd display
109: lcdMainOnBottom();
110:
111: videoSetMode(MODE_5_3D);
112:
113: // EXPERIMENT: 3D examples don't show this as necessary, but maybe
114: // it will fix my issue with intro mode after this
115: // not showing the texture
116: // RESULT: no difference
117: // map main screen background fourth (128k) region to vram bank A
118: vramSetBankA(VRAM_A_MAIN_BG_0x06060000);
119:
120: // initialize 3D bottom (touch) screen graphics subsystem
121: // XXX: this is now a mode specific function, probably should reside in
122: // this file.
123: gzmcpc_init_3d();
124:
125: // return to desired state
126: videoSetModeSub(MODE_5_2D);
127:
128: // use vram bank c for the secondary/sub-screen(background)
129: vramSetBankC(VRAM_C_SUB_BG);
130:
131: mcp_console_init(&top_screen,
132: MCP_SUB_SCREEN,
133: 0,
134: 1,
135: 1,
136: BgType_Text4bpp,
137: BgSize_T_256x256,
138: 31,
139: 0);
140:
141: consoleSelect(&top_screen);
142:
143: bgSetPriority(top_screen.bgId, 0);
144:
145: bgShow(top_screen.bgId);
146:
147: // default to fully faded to black (31) not the opposite (0)
148: REG_BLDY_SUB = 31;
149: // fade the subscreen background to/from black, layer 3
150: REG_BLDCNT_SUB = BLEND_FADE_BLACK | BLEND_SRC_BG3;
151:
152: // note: using offset=4, because 4 will be 64k offset, where 31 above is 62k
153: // (thus above using only 2k? seems plausible with tiles for console text chars
154: bgs3 = bgInitSub(3, BgType_Bmp8, BgSize_B8_256x256, 4, 0);
155: // its initial priority, lowest (to emphasize lack of other enabled layers)
156: // priorities 0..3, 0 highest priority
157: bgSetPriority(bgs3, 2);
158:
159: bgHide(bgs3);
160:
161: // as per libnds doc on dma
162: DC_FlushRange(dlavaBitmap, 256*256);
163: dmaCopy(dlavaBitmap, bgGetGfxPtr(bgs3), 256*256);
164: DC_FlushRange(dlavaPal, 256*2);
165: dmaCopy(dlavaPal, BG_PALETTE_SUB, 256*2);
166:
167: bgShow(bgs3);
168:
169: }
170:
171: void mode__tpw__jam___top_renderer(void) {
172:
173: long msphase, phase;
174: // long phase_prev, phase_next;
175: char stringthing[MAX_TEXT_OUTPUT_LINE_SIZE];
176: int vstrobe_period_ms;
177:
178: unsigned char t_font_int;
179: int t_blend;
180:
181: //
182: // initialize to unfaded values
183: //
184: t_blend = 0;
185: t_font_int = (unsigned char)((int)font_intensity * 1);
186:
187: //
188: // do bg fade-in
189: //
190: if (mode_ms < TPW__JAM__BOT_BG_FADE_IN_START_MS) {
191: // pre fade-in
192: t_blend = 31;
193: } else if (mode_ms < (TPW__JAM__BOT_BG_FADE_IN_START_MS +
194: TPW__JAM__BOT_BG_FADE_IN_DURATION_MS)) {
195: // main screen bg fade-in
196: t_blend = 31 - ((mode_ms - TPW__JAM__BOT_BG_FADE_IN_START_MS) * 31 /
197: TPW__JAM__BOT_BG_FADE_IN_DURATION_MS);
198:
199: }
200:
201: //
202: // do text fade-in
203: //
204: if (mode_ms < TPW__JAM__BOT_TXT_FADE_IN_START_MS) {
205: // pre fade-in
206: t_font_int = 0;
207: } else if (mode_ms < (TPW__JAM__BOT_TXT_FADE_IN_START_MS +
208: TPW__JAM__BOT_TXT_FADE_IN_DURATION_MS)) {
209: t_font_int = (unsigned char)((int)(font_intensity) *
210: (mode_ms - TPW__JAM__BOT_TXT_FADE_IN_START_MS) /
211: TPW__JAM__BOT_TXT_FADE_IN_DURATION_MS);
212: }
213:
214:
215: //
216: // do fadeout, possibly overriding above
217: //
218: if (mode != next_mode) {
219: // fade-out
220: if ((mode_ms - exit_mode_ms) < TPW__JAM__BOT_BG_FADE_OUT_DURATION_MS) {
221: t_blend = ((mode_ms - exit_mode_ms) *
222: 31 / TPW__JAM__BOT_BG_FADE_OUT_DURATION_MS);
223: } else {
224: t_blend = 31;
225: }
226: // only fadeout
227: t_blend = MAX(t_blend, mcp_get_blend(MCP_SUB_SCREEN));
228:
229: if ((mode_ms - exit_mode_ms) < TPW__JAM__BOT_TXT_FADE_OUT_DURATION_MS) {
230: t_font_int = (unsigned char)((int)(font_intensity) *
231: (TPW__JAM__BOT_TXT_FADE_OUT_DURATION_MS - (mode_ms - exit_mode_ms)) /
232: TPW__JAM__BOT_TXT_FADE_OUT_DURATION_MS);
233: } else {
234: t_font_int = 0;
235: }
236: // only fadeout
237: t_font_int = MIN(t_font_int, RGB15_TO_G5(BG_PALETTE_SUB[255]));
238: }
239:
240: mcp_set_blend(MCP_SUB_SCREEN,
241: t_blend);
242: // set the font color from the calculated intensity (greenish)
243: BG_PALETTE_SUB[255] = RGB15(t_font_int / 3,
244: t_font_int,
245: t_font_int / 3);
246:
247:
248: // XXX: moving this hear causes top screen render lockup after server connect?????
249: // (a couple other lines of the same code is below)
250: // if (time_val_compare(next_top_render, num_ticks) <= 0) {
251: // return;
252: // }
253:
254:
255: // XXX: all below might better be done once at modification time
256: textout(TLT_FX_MODE, "%s",
257: rak_preset_labels[cstate_preset - 1]);
258:
259: textout(TLT_TOUCH_VALXP, "%s",
260: get_rak_midi_label(touch_whammy_x_midi_parm));
261:
262: textout(TLT_TOUCH_VALYP, "%s",
263: get_rak_midi_label(touch_whammy_y_midi_parm));
264:
265:
266: #define VSTROBE_NUM_CHARS 22
267:
268: // XXX could do this calculation at vstrobe_bpm modification time instead
269: // of every frame
270: vstrobe_period_ms = (int)(
271: (
272: 1.0f /
273: (((float)vstrobe_bpm /
274: (float)VSTROBE_NUM_CHARS) / 60.0f)
275: ) * 1000.0f
276: );
277:
278: // XXX and these as well
279: textout(TLT_TOUCH_VAL,
280: ":X=%02d:/\\/:Y=%02d:",
281: cstate_wpx * 100 / 128,
282: cstate_wpy * 100 / 128);
283:
284: if (!vstrobe_enabled) {
285: textout(TLT_AESTHETIC, " /\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/");
286: } else {
287:
288: // age related death problem here (overflow the long)
289: msphase = ((num_ticks.s * 1000) + num_ticks.ms) % vstrobe_period_ms;
290:
291: phase = (int)(((float)msphase /
292: (float)vstrobe_period_ms)
293: * (float)VSTROBE_NUM_CHARS * 2.0f);
294:
295: if (phase >= VSTROBE_NUM_CHARS) {
296: phase = (VSTROBE_NUM_CHARS) - (phase - VSTROBE_NUM_CHARS);
297: }
298:
299: // this is the old single direction wrapping method
300: //if (phase == 0) {
301: //phase_prev = VSTROBE_NUM_CHARS - 1;
302: //} else {
303: //phase_prev = phase - 1;
304: //}
305:
306: //if (phase == (VSTROBE_NUM_CHARS - 1)) {
307: //phase_next = 0;
308: //} else {
309: //phase_next = phase + 1;
310: //}
311:
312: // dmcnote: looked it up, no -1 here, max size includes null char at end
313: snprintf(stringthing, MAX_TEXT_OUTPUT_LINE_SIZE,
314: " /\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/\\/");
315:
316: stringthing[phase + 2] = '-';
317: stringthing[phase + 3] = '<';
318: stringthing[phase + 4] = '=';
319: stringthing[phase + 5] = '>';
320: stringthing[phase + 6] = '-';
321:
322: textout(TLT_AESTHETIC, "%s", stringthing);
323:
324: } // end if/else vstrobe_enabled
325:
326: // XXX: same experiment as above
327: // next_top_render = time_val_add_ms(next_top_render, 1000 / TOP_RENDER_RATE);
328:
329: // actually render the text output
330: render_textout();
331:
332: }
333:
334: void mode__tpw__jam___bot_renderer(void) {
335:
336: int i, j;
337:
338: uint8 cursor_r;
339: uint8 cursor_g;
340: uint8 cursor_b;
341: uint8 cursor_a;
342: uint8 cursor_center_r;
343: uint8 cursor_center_g;
344: uint8 cursor_center_b;
345: uint8 cursor_center_a;
346:
347:
348: int xcomb_row_height;
349: int xcomb_col_width;
350: int xtouch_pos_y;
351: int xtouch_pos_x;
352: int xcomb_row_cursor;
353: int xcomb_col_cursor;
354:
355: int tmprate;
356: int tmpvolume;
357: int tmppanning;
358:
359: unsigned char t_3d_int;
360:
361:
362: //
363: // handle fade with intensity variable
364: //
365:
366: // initialize to unfaded value
367: t_3d_int = TPW_3D_MAX_INTENSITY;
368:
369: //
370: // do text fade-in
371: //
372: if (mode_ms < TPW__JAM__BOT_3D_FADE_IN_START_MS) {
373: // pre fade-in
374: t_3d_int = 0;
375: } else if (mode_ms < (TPW__JAM__BOT_3D_FADE_IN_START_MS +
376: TPW__JAM__BOT_3D_FADE_IN_DURATION_MS)) {
377: t_3d_int = (unsigned char)((mode_ms - TPW__JAM__BOT_3D_FADE_IN_START_MS) *
378: 255 /
379: TPW__JAM__BOT_3D_FADE_IN_DURATION_MS);
380: }
381:
382:
383: //
384: // do fadeout, possibly overriding above
385: //
386: if (mode != next_mode) {
387:
388: if ((mode_ms - exit_mode_ms) < TPW__JAM__BOT_3D_FADE_OUT_DURATION_MS) {
389: t_3d_int = (unsigned char)((TPW__JAM__BOT_3D_FADE_OUT_DURATION_MS -
390: (mode_ms - exit_mode_ms)) * 255 /
391: TPW__JAM__BOT_3D_FADE_OUT_DURATION_MS);
392: } else {
393: t_3d_int = 0;
394: }
395: // only fadeout
396: t_3d_int = MIN(t_3d_int, x3d_intensity);
397: }
398:
399: x3d_intensity = t_3d_int;
400:
401: // update comb charge matrix
402: // recharge
403:
404: // 1024 is a fixed point scaling thing
405: // take into account upper and lower half rows
406: xcomb_row_height = 192 * 1024 / (COMB_HEIGHT - 1);
407: xtouch_pos_y = (touch_pos_y * 1024) + (xcomb_row_height >> 1);
408: xcomb_row_cursor = xtouch_pos_y / xcomb_row_height;
409: // XXX error check on xcomb_row_cursor < COMB_HEIGHT
410:
411: xcomb_col_width = 256 * 1024 / COMB_WIDTH;
412: xtouch_pos_x = (touch_pos_x * 1024);
413: xtouch_pos_x += (xcomb_col_width >> 1);
414: if (xcomb_row_cursor % 2) {
415: // odd row, shift left half a col width
416: if (xtouch_pos_x > (xcomb_col_width >> 1)) {
417: xtouch_pos_x -= (xcomb_col_width >> 1);
418: } else {
419: xtouch_pos_x = 0;
420: }
421: }
422: xcomb_col_cursor = xtouch_pos_x / xcomb_col_width;
423: // XXX
424: if (xcomb_col_cursor >= COMB_WIDTH) xcomb_col_cursor--;
425:
426: // seems to be all good
427: // textout(TLT_STATUS, ":::%d:::%d:::", xcomb_row_cursor, xcomb_col_cursor);
428: // XXX: clear up inversion confusion here or elsewhere, probably all
429: // kinds of ways to make the code more readable with utility functions,
430: // and better performance being careful where values are calculated
431: // and how often.
432: if (comb_charge[(COMB_WIDTH - 1) - xcomb_col_cursor][(COMB_HEIGHT - 1) - xcomb_row_cursor] < 224) {
433: //
434: // play metrognome
435: //
436:
437: // save standard parameters for the effect
438: tmprate = sounds[SFX_METROGNOME].rate; // 1024
439: tmpvolume = sounds[SFX_METROGNOME].volume; // 255
440: tmppanning = sounds[SFX_METROGNOME].panning; // 127
441:
442: sounds[SFX_METROGNOME].volume = 255 * xcomb_row_cursor / COMB_HEIGHT; // 255
443:
444: for (i = 0 ; i < (COMB_WIDTH >> 1) ; i++) {
445: sounds[SFX_METROGNOME].rate = (int)((float)sounds[SFX_METROGNOME].rate * 1.059f);
446: }
447: for (i = 0 ; i < xcomb_col_cursor ; i++) {
448: sounds[SFX_METROGNOME].rate = (int)((float)sounds[SFX_METROGNOME].rate / 1.059f);
449: }
450:
451: // sounds[SFX_METROGNOME].panning = 255 - (255 * xcomb_col_cursor / COMB_WIDTH); // 127
452: mmEffectEx(&sounds[SFX_METROGNOME]);
453: // restore standard parameters for the effect
454: sounds[SFX_METROGNOME].rate = tmprate;
455: sounds[SFX_METROGNOME].volume = tmpvolume;
456: sounds[SFX_METROGNOME].panning = tmppanning;
457:
458: }
459: comb_charge[(COMB_WIDTH - 1) - xcomb_col_cursor][(COMB_HEIGHT - 1) - xcomb_row_cursor] = 255;
460:
461: // update comb charge matrix
462: for (i = 0; i < COMB_WIDTH ; i++) {
463: for (j = 0; j < COMB_WIDTH ; j++) {
464:
465: // decay
466: if (comb_charge[i][j] >= 2) {
467: comb_charge[i][j] = comb_charge[i][j] - 2;
468: } else {
469: comb_charge[i][j] = 0;
470: }
471: }
472: }
473:
474: // refactor to comb_row(touch_pos_x_val) and column/y
475:
476:
477: init_modelview_matrix();
478:
479: // NDS does this automagically, and current api won't allow it
480: // clear color and depth buffers
481: //glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
482: // maybe redundant, 0..31 for rgba
483: // glClearColor(0, 0, 0, 31);
484:
485:
486: // draw a cool cyber-honeycomb
487: // including trippy charge tracer and background effects
488: draw_simple_hex_grid(COMB_WIDTH,
489: COMB_HEIGHT,
490: RGB15(x3d_intensity >> 3,
491: x3d_intensity >> 3,
492: x3d_intensity >> 3));
493:
494: // define the cursor inner/outter colors based on current state
495: if (touch_whammy_enabled) {
496: cursor_r = (uint8)(0.8f * cursor_intensity * 256);
497: cursor_g = (uint8)(0.2f * cursor_intensity * 256);
498: cursor_b = (uint8)(0.2f * cursor_intensity * 256);
499: cursor_a = 0;
500: cursor_center_r = 255;
501: cursor_center_g = 255;
502: cursor_center_b = 255;
503: cursor_center_a = 255;
504: } else {
505: cursor_r = (uint8)(0.2f * cursor_intensity * 256);
506: cursor_g = (uint8)(0.2f * cursor_intensity * 256);
507: cursor_b = (uint8)(0.7f * cursor_intensity * 256);
508: cursor_a = 0;
509: cursor_center_r = 0;
510: cursor_center_g = 0;
511: cursor_center_b = 0;
512: cursor_center_a = 0;
513: }
514:
515: // draw touchwhammypad cursor
516: draw_hex(MODEL_XMAX - model_width * touch_pos_x / 256,
517: MODEL_YMAX - model_height * touch_pos_y / 192,
518: MODEL_ZMAX - model_depth / 4,
519: CURSOR_RADIUS,
520: cursor_rotation,
521: cursor_center_r,
522: cursor_center_g,
523: cursor_center_b,
524: cursor_center_a,
525: cursor_r,
526: cursor_g,
527: cursor_b,
528: cursor_a,
529: 0,
530: 0,
531: 0,
532: 255,
533: RGB15(x3d_intensity >> 3,
534: x3d_intensity >> 3,
535: x3d_intensity >> 3));
536:
537: }
538:
539: void mode__tpw__jam___input_handler(void) {
540:
541: //
542: // handle input
543: //
544:
545: // XXX refactor into classifcation/enumeration of 'interesting events
546: // watched for', and then have function to register an event
547: // handler for each. I.e. layer of abstraction between tasks and
548: // the input event they are mapped to (then expose that in configfile,
549: // and/or config menu)
550:
551: // At the outermost layer of this nest, are all combinations of modifiers
552: // I.e. heldkey combinations that are meant to do interesting things.
553: // After those cases are handled, then the normal non-modified cases are
554: // handled, and the assumption is that if we are in a modifier situation,
555: // we only want that code to be looked at.
556: // note: potential exception: touchpad held perhaps should not interfere
557: // simultaneous other inputs.
558: if ((heldkeys & KEY_L) && (heldkeys & KEY_R)) {
559: //
560: // held(L)+held(R)+something
561: //
562:
563: //: The adjustable metrognome is currently the pro only feature.
564: //: Please, do what you can to help me scrape by enough dough
565: //: so that I can add more and more features to the pro version
566: //: which will find their way into the GPL version after no more
567: //: than 7 years (and probably much MUCH sooner than that).
568: #ifdef IM_POOR_OR_LICENSED_OR_NOT
569: if (downkeys & KEY_LEFT) {
570: // XXX no limits yet
571: astrobe_bpm -= 1;
572: textout(TLT_STATUS, "metrognome bpm: %d", astrobe_bpm);
573: // XXX tired, is this really useful??
574: // heldover = IH_METROGNOME_DEC;
575: // XXX? constant: IH_METROGNOME_HELDOVER_RATE_HZ = 10?
576: heldover_sunset = time_val_add_ms(num_ticks, 224);
577: }
578: if (downkeys & KEY_RIGHT) {
579: astrobe_bpm += 1;
580: textout(TLT_STATUS, "metrognome bpm: %d", astrobe_bpm);
581: // heldover = IH_METROGNOME_INC;
582: heldover_sunset = time_val_add_ms(num_ticks, 224);
583: }
584: #endif //#ifdef IM_POOR_OR_LICENSED_OR_NOT
585:
586: if (downkeys & KEY_UP) {
587: textout(TLT_DEBUG,
588: "mf:%d:mu:%d:",
589: get_mem_free(),
590: get_mem_used());
591: textout(TLT_MODE,
592: "mf:%d:mu:%d:",
593: get_mem_free(),
594: get_mem_used());
595: }
596:
597: if (downkeys & KEY_DOWN) {
598: }
599:
600: if (downkeys & KEY_X) {
601: // experimental mode transition
602: system_xmode_new(MODE_INTRO__MAIN);
603: // XXX: perhaps imp fadeout(MODE_INTRO__MAIN), which sets mode vars,
604: // and idlefunc handles the fade
605: }
606:
607: if (downkeys & KEY_Y) {
608: // experimental mode transition
609: system_xmode_new(MODE_SSID__INPUT);
610: }
611:
612: if (downkeys & KEY_A) {
613: system_xmode_new(MODE_GET_UPDATE);
614: }
615:
616: if (downkeys & KEY_B) {
617: overwrite_self_with_update = 1;
618: system_xmode_new(MODE_GET_UPDATE);
619: }
620:
621:
622: if (downkeys & KEY_START) {
623: if (vstrobe_enabled) {
624: textout(TLT_STATUS, "strobe disabled");
625: vstrobe_enabled = 0;
626: user_vstrobe_enabled = 1;
627: } else {
628: textout(TLT_STATUS, "strobe enabled");
629: vstrobe_enabled = 1;
630: user_vstrobe_enabled = 1;
631: }
632: }
633:
634: if (downkeys & KEY_SELECT) {
635: if (astrobe_enabled) {
636: textout(TLT_STATUS, "metrognome disabled");
637: astrobe_enabled = 0;
638: } else {
639: textout(TLT_STATUS, "metrognome enabled");
640: astrobe_enabled = 1;
641: next_metrognome_play = time_val_add_ms(num_ticks, 1000 * 60 / astrobe_bpm);
642: }
643: }
644:
645: // this is temporary anyway probably...
646: // only respect held(LR)+L|R for vstrobe bpm +/- if the user has toggled it at least once
647: if (user_vstrobe_enabled) {
648:
649: if (downkeys & KEY_DOWN) {
650: // XXX no limits yet
651: vstrobe_bpm -= 1;
652: textout(TLT_STATUS, "strobe bpm: %d", vstrobe_bpm);
653: heldover_sunset = time_val_add_ms(num_ticks, 224);
654: }
655: if (downkeys & KEY_UP) {
656: vstrobe_bpm += 1;
657: textout(TLT_STATUS, "strobe bpm: %d", vstrobe_bpm);
658: heldover_sunset = time_val_add_ms(num_ticks, 224);
659: }
660:
661: } // end if (user_vstrobe_enabled)
662:
663: } else if (heldkeys & KEY_L) {
664: //
665: // held(L)+something
666: //
667:
668: // theory: held(L)+ABXY is mirrorly as nice as held(R)+LRUD
669: // (i.e. inverse of those should be rarely used UI things)
670:
671: if (downkeys & KEY_X) {
672: // XXX need to get MAX_PRESET from server
673: if (cstate_preset < MAX_PRESETS) {
674: cstate_preset += 1;
675: heldover_sunset = time_val_add_ms(num_ticks, 224);
676: }
677: }
678:
679: if (downkeys & KEY_B) {
680: if (cstate_preset > 1) {
681: cstate_preset -= 1;
682: heldover_sunset = time_val_add_ms(num_ticks, 224);
683: }
684: }
685:
686: if (downkeys & KEY_UP) {
687: debug_tweak_var++;
688: textout(TLT_STATUS, "dtv:%d:", debug_tweak_var);
689: }
690:
691: if (downkeys & KEY_DOWN) {
692: debug_tweak_var--;
693: textout(TLT_STATUS, "dtv:%d:", debug_tweak_var);
694: }
695:
696: if (downkeys & KEY_START) {
697: }
698:
699: } else if (heldkeys & KEY_R) {
700: //
701: // held(R)+something
702: //
703:
704: if (downkeys & KEY_LEFT) {
705: cursor_intensity -= 0.05f;
706: if (cursor_intensity < 0.2f) cursor_intensity = 0.2f;
707: heldover_sunset = time_val_add_ms(num_ticks, 100);
708: }
709: if (downkeys & KEY_RIGHT) {
710: cursor_intensity += 0.05f;
711: if (cursor_intensity > 0.8f) cursor_intensity = 0.8f;
712: heldover_sunset = time_val_add_ms(num_ticks, 100);
713: }
714:
715: if (downkeys & KEY_UP) {
716: if (font_intensity < FONT_INTENSITY_MAX) font_intensity++;
717: BG_PALETTE_SUB[255] = RGB15(font_intensity,
718: font_intensity,
719: font_intensity);
720: heldover_sunset = time_val_add_ms(num_ticks, 422);
721: }
722: if (downkeys & KEY_DOWN) {
723: if (font_intensity > FONT_INTENSITY_MIN) font_intensity--;
724: BG_PALETTE_SUB[255] = RGB15(font_intensity,
725: font_intensity,
726: font_intensity);
727: heldover_sunset = time_val_add_ms(num_ticks, 422);
728: }
729:
730: } else {
731: //
732: // no interesting modifer keys held
733: //
734:
735: if (downkeys & KEY_LEFT) {
736: if (touch_whammy_x_midi_parm > 0) {
737: touch_whammy_x_midi_parm--;
738: heldover_sunset = time_val_add_ms(num_ticks, 224);
739: }
740: }
741:
742: if (downkeys & KEY_RIGHT) {
743: if (touch_whammy_x_midi_parm < 127) {
744: touch_whammy_x_midi_parm++;
745: heldover_sunset = time_val_add_ms(num_ticks, 224);
746: }
747: }
748:
749: if (downkeys & KEY_DOWN) {
750: if (touch_whammy_y_midi_parm > 0) {
751: touch_whammy_y_midi_parm--;
752: heldover_sunset = time_val_add_ms(num_ticks, 224);
753: }
754: }
755:
756: if (downkeys & KEY_UP) {
757: if (touch_whammy_y_midi_parm < 127) {
758: touch_whammy_y_midi_parm++;
759: heldover_sunset = time_val_add_ms(num_ticks, 224);
760: }
761: }
762:
763:
764: if (downkeys & KEY_START) {
765: } // end if KEY_START
766:
767: if (downkeys & KEY_SELECT) {
768: if (touch_whammy_enabled) {
769: touch_whammy_enabled = 0;
770: } else {
771: touch_whammy_enabled = 1;
772: }
773: }
774:
775: // IMP TODO: need to get a name to preset hash with overridable values in defaults file...
776: if (downkeys & KEY_X) {
777: cstate_preset = button_x_preset_num;
778: }
779:
780: if (downkeys & KEY_Y) {
781: cstate_preset = button_y_preset_num;
782: }
783:
784: if (downkeys & KEY_A) {
785: cstate_preset = button_a_preset_num;
786: }
787:
788: if (downkeys & KEY_B) {
789: cstate_preset = button_b_preset_num;
790: }
791:
792: } // end button input handling
793:
794:
795: // touchpad handling is independent of modifiers (at the moment)
796: if ((downkeys & KEY_TOUCH) || (heldkeys & KEY_TOUCH)) {
797: //
798: // touchpad modifier, or slightly special, just downkey on the touchpad
799: //
800:
801: // the range seems to be x 253.0 y 189.0,
802: // which is probably really 0-255,0-191
803: // touchdata.px scans left to right on the screen
804: // but I want it inverted, as the x whammy parm gets ramped up
805: // toward the nut, or ramped down toward the bridge
806: touch_pos_x = 255 - touchdata.px;
807: // touchdata.py scans top to bottom on the screen
808: // which is what I want as that means increasing as you stroke
809: // up toward your face (which is down on the NDS)
810: touch_pos_y = touchdata.py;
811:
812: // could have some ugly non float case logic to handle spreading
813: // out the couple lost values as we really end up maybe a few values
814: // shy of the full range on upper and lower (2..253) (4..189)
815: // (that was right after I calibrated, which didn't seem to help)
816: cstate_wpx = (int)(touch_pos_x / 2);
817: cstate_wpy = (int)(touch_pos_y * 4 / 3 / 2);
818:
819: } // end touchpad input handling
820:
821: }
822:
823:
824: void mode__tpw__jam___idle(void) {
825: if (cursor_rotating) {
826: cursor_rotation -= 1.23f;
827: if (cursor_rotation < 0.0f) {
828: cursor_rotation += 360.0f;
829: }
830: }
831:
832: //
833: // handle fadeout
834: //
835: if (mode != next_mode) {
836: if (((mode_ms - exit_mode_ms) > TPW__JAM__TOP_BG_FADE_OUT_DURATION_MS) &&
837: ((mode_ms - exit_mode_ms) > TPW__JAM__BOT_BG_FADE_OUT_DURATION_MS) &&
838: ((mode_ms - exit_mode_ms) > TPW__JAM__BOT_TXT_FADE_OUT_DURATION_MS)) {
839: /*
840: // XXX: this should get moved elsewhere, and use dma
841: // XXX: not even remotely sure it is necessary or helps, just a theory
842:
843: // clear background image memory bank
844: // 256 * 256 * 2 = 128k
845: dmaFillHalfWords(0,
846: (u16*)bgGetGfxPtr(bg3),
847: 256 * 256 * 2);
848: // memptr = (u16*)bgGetGfxPtr(bg3);
849: // for (i = 0 ; i < (256 * 256) ; i++) memptr[i] = (u16)0;
850:
851: dmaFillHalfWords(0,
852: (u16*)bgGetGfxPtr(bgs1),
853: 256 * 512 / 2);
854:
855: dmaFillHalfWords(0,
856: (u16*)bgGetGfxPtr(bgs0),
857: 256 * 256 / 2);
858: */
859: system_xmode_real();
860: }
861: }
862:
863: if (mode == next_mode) {
864: }
865:
866: }
867:
868:
869: void mode__tpw__jam___exit(void) {
870:
871: }
872:
873:
874: /*
875: BCngU-0.1~
876:
877: B maj, lift bar/s1(thin). then lift s2 and go to s543, then open,
878: then c, starting with middle, and upper, then lower
879: various n, n-1, n-2 repeat4, repeat3, then n-3, -2, n-1, and mz*pp
880: */
881: