sound.c (26963B)
1#include <gb/gb.h> 2#include <gbdk/console.h> 3#include <stdint.h> 4#include <stdio.h> 5 6#define ARROW_CHAR '>' 7#define SPACE_CHAR ' ' 8 9#define ARROW_X 0 10#define VAL_X 15 11#define TITLE_Y 0 12#define FIRST_X (ARROW_X+1) 13#define FIRST_Y (TITLE_Y+2) 14 15#define PLAY 0x20 16#define FREQUENCY 0x21 17 18#define MIN(x,y) ((x) > (y) ? (y) : (x)) 19#define MAX(x,y) ((x) < (y) ? (y) : (x)) 20 21#define NB_MODES 5 22 23#define UNSIGNED 0 24 25uint8_t previous_keys = 0; 26int8_t keys = 0; 27#define UPDATE_KEYS() previous_keys = keys; keys = joypad() 28#define KEY_PRESSED(K) (keys & (K)) 29#define KEY_TICKED(K) ((keys & (K)) && !(previous_keys & (K))) 30 31void show_register_channel(uint8_t mode); 32 33void clss() { 34 uint8_t i = 0; 35 for(i = 0; i < 18; ++i) { 36 gotoxy(0, i); 37 printf(" "); 38 } 39} 40 41void print(const char* str) { 42 printf("%s", str); 43} 44 45const char hex[] = "0123456789ABCDEF"; 46void printn(uint16_t n, uint8_t base, uint8_t sign) { 47 (void) sign; 48 if(base == 16u) { 49 printf("%c", hex[0x000Fu & (n >> 4u)]); 50 printf("%c", hex[0x000Fu & (n)]); 51 } else { 52 printf("%d", n); 53 } 54} 55 56 57void println(uint16_t n, uint8_t base, uint8_t sign) { 58 printn(n, base, sign); 59 printf("\n"); 60} 61 62enum notes { 63 C0, Cd0, D0, Dd0, E0, F0, Fd0, G0, Gd0, A0, Ad0, B0, 64 C1, Cd1, D1, Dd1, E1, F1, Fd1, G1, Gd1, A1, Ad1, B1, 65 C2, Cd2, D2, Dd2, E2, F2, Fd2, G2, Gd2, A2, Ad2, B2, 66 C3, Cd3, D3, Dd3, E3, F3, Fd3, G3, Gd3, A3, Ad3, B3, 67 C4, Cd4, D4, Dd4, E4, F4, Fd4, G4, Gd4, A4, Ad4, B4, 68 C5, Cd5, D5, Dd5, E5, F5, Fd5, G5, Gd5, A5, Ad5, B5, 69 SILENCE, END 70}; 71 72const uint16_t frequencies[] = { 73 44, 156, 262, 363, 457, 547, 631, 710, 786, 854, 923, 986, 74 1046, 1102, 1155, 1205, 1253, 1297, 1339, 1379, 1417, 1452, 1486, 1517, 75 1546, 1575, 1602, 1627, 1650, 1673, 1694, 1714, 1732, 1750, 1767, 1783, 76 1798, 1812, 1825, 1837, 1849, 1860, 1871, 1881, 1890, 1899, 1907, 1915, 77 1923, 1930, 1936, 1943, 1949, 1954, 1959, 1964, 1969, 1974, 1978, 1982, 78 1985, 1988, 1992, 1995, 1998, 2001, 2004, 2006, 2009, 2011, 2013, 2015 79}; 80 81const uint8_t music[] = { 82 C3, C3, G3, G3, A3, A3, G3, SILENCE, 83 F3, F3, E3, E3, D3, D3, C3, SILENCE, 84 G3, G3, F3, F3, E3, E3, D3, D3, 85 G3, G3, F3, F3, E3, E3, D3, D3, 86 C3, C3, G3, G3, A3, A3, G3, SILENCE, 87 F3, F3, E3, E3, D3, D3, C3, SILENCE, 88 END 89}; 90 91struct Params { 92 char *name; 93 uint16_t max; 94}; 95 96const struct Params params_0[] = { 97 { "Main Controls" , 0 }, 98 { "All On/Off" , 1 }, 99 { "Vin->SO1" , 1 }, 100 { "Vin->SO2" , 1 }, 101 { "SO1 Volume" , 7 }, 102 { "SO2 Volume" , 7 }, 103 { NULL , 0 } 104}; 105 106const struct Params params_1[] = { 107 { "Sound Mode #1" , 0 }, 108 { "Swp Time" , 7 }, 109 { "Swp Mode" , 1 }, 110 { "Swp Shifts" , 7 }, 111 { "Pat Duty" , 3 }, 112 { "Sound Len" , 63 }, 113 { "Env Init" , 15 }, 114 { "Env Mode" , 1 }, 115 { "Env Nb Swp" , 7 }, 116 { "Frequency" , 2047 }, 117 { "Cons Sel" , 1 }, 118 { "Out to SO1" , 1 }, 119 { "Out to SO2" , 1 }, 120 { "On/Off" , 1 }, 121 { NULL , 0 } 122}; 123 124const struct Params params_2[] = { 125 { "Sound Mode #2" , 0 }, 126 { "Pat Duty" , 3 }, 127 { "Sound Len" , 63 }, 128 { "Env Init" , 15 }, 129 { "Env Mode" , 1 }, 130 { "Env Nb Step" , 7 }, 131 { "Frequency" , 2047 }, 132 { "Cons Sel" , 1 }, 133 { "Out to SO1" , 1 }, 134 { "Out to SO2" , 1 }, 135 { "On/Off" , 1 }, 136 { NULL , 0 } 137}; 138 139const struct Params params_3[] = { 140 { "Sound Mode #3" , 0 }, 141 { "Sound On/Off" , 1 }, 142 { "Sound Len" , 255 }, 143 { "Sel Out Level" , 3 }, 144 { "Frequency" , 2047 }, 145 { "Cons Sel" , 1 }, 146 { "Out to SO1" , 1 }, 147 { "Out to SO2" , 1 }, 148 { "On/Off" , 1 }, 149 { NULL , 0 } 150}; 151 152const struct Params params_4[] = { 153 { "Sound Mode #4" , 0 }, 154 { "Sound Len" , 63 }, 155 { "Env Init" , 15 }, 156 { "Env Mode" , 1 }, 157 { "Env Nb Step" , 7 }, 158 { "Poly Cnt Freq" , 15 }, 159 { "Poly Cnt Step" , 1 }, 160 { "Poly Cnt Div" , 7 }, 161 { "Cons Sel" , 1 }, 162 { "Out to SO1" , 1 }, 163 { "Out to SO2" , 1 }, 164 { "On/Off" , 1 }, 165 { NULL , 0 } 166}; 167 168const struct Params *params_array[] = { 169 params_0, 170 params_1, 171 params_2, 172 params_3, 173 params_4, 174}; 175 176const struct Params *params; 177 178struct SoundReg { 179 struct { 180 //NR10 0xFF10 181 uint16_t sweepShifts ;//: 3; 182 uint16_t sweepMode ;//: 1; 183 uint16_t sweepTime ;//: 3; 184 uint16_t unused_1 ;//: 1; 185 186 //NR11 0xFF11 187 uint16_t soundLength ;//: 6; 188 uint16_t patternDuty ;//: 2; 189 190 //NR12 0xFF12 191 uint16_t envNbSweep ;//: 3; 192 uint16_t envMode ;//: 1; 193 uint16_t envInitialValue ;//: 4; 194 195 //NR13 0xFF13 196 uint16_t frequencyLow; 197 198 //NR14 0xFF14 199 uint16_t frequencyHigh ;//: 3; 200 uint16_t unused_2 ;//: 3; 201 uint16_t counter_ConsSel ;//: 1; 202 uint16_t restart ;//: 1; 203 } mode1; 204 struct { 205 //NR20 0xFF15 206 uint16_t unused_1; 207 208 //NR21 0xFF16 209 uint16_t soundLength ;//: 6; 210 uint16_t patternDuty ;//: 2; 211 212 //NR22 0xFF17 213 uint16_t envNbStep ;//: 3; 214 uint16_t envMode ;//: 1; 215 uint16_t envInitialValue ;//: 4; 216 217 //NR23 0xFF18 218 uint16_t frequencyLow; 219 220 //NR24 0xFF19 221 uint16_t frequencyHigh ;//: 3; 222 uint16_t unused_2 ;//: 3; 223 uint16_t counter_ConsSel ;//: 1; 224 uint16_t restart ;//: 1; 225 } mode2; 226 struct { 227 //NR30 0xFF1A 228 uint16_t unused_1 ;//: 7; 229 uint16_t on_Off ;//: 1; 230 231 //NR31 0xFF1B 232 uint16_t soundLength; 233 234 //NR32 0xFF1C 235 uint16_t unused_2 ;//: 5; 236 uint16_t selOutputLevel ;//: 2; 237 uint16_t unused_3 ;//: 1; 238 239 //NR33 0xFF1D 240 uint16_t frequencyLow; 241 242 //NR34 0xFF1E 243 uint16_t frequencyHigh ;//: 3; 244 uint16_t unused_4 ;//: 3; 245 uint16_t counter_ConsSel ;//: 1; 246 uint16_t restart ;//: 1; 247 } mode3; 248 struct { 249 //NR40 0xFF1F 250 uint16_t unused_1; 251 252 //NR41 0xFF20 253 uint16_t soundLength ;//: 6; 254 uint16_t unused_2 ;//: 2; 255 256 //NR42 0xFF21 257 uint16_t envNbStep ;//: 3; 258 uint16_t envMode ;//: 1; 259 uint16_t envInitialValue ;//: 4; 260 261 //NR43 0xFF22 262 uint16_t polyCounterDiv ;//: 3; 263 uint16_t polyCounterStep ;//: 1; 264 uint16_t polyCounterFreq ;//: 4; 265 266 //NR44 0xFF23 267 uint16_t unused_3 ;//: 6; 268 uint16_t counter_ConsSel ;//: 1; 269 uint16_t restart ;//: 1; 270 } mode4; 271 struct { 272 // NR50 0xFF24 273 uint16_t SO1_OutputLevel ;//: 3; 274 uint16_t Vin_SO1 ;//: 1; 275 uint16_t SO2_OutputLevel ;//: 3; 276 uint16_t Vin_SO2 ;//: 1; 277 278 // NR51 0xFF25 279 uint16_t Sound1_To_SO1 ;//: 1; 280 uint16_t Sound2_To_SO1 ;//: 1; 281 uint16_t Sound3_To_SO1 ;//: 1; 282 uint16_t Sound4_To_SO1 ;//: 1; 283 uint16_t Sound1_To_SO2 ;//: 1; 284 uint16_t Sound2_To_SO2 ;//: 1; 285 uint16_t Sound3_To_SO2 ;//: 1; 286 uint16_t Sound4_To_SO2 ;//: 1; 287 288 // NR52 0xFF26 289 uint16_t Sound1_On_Off ;//: 1; 290 uint16_t Sound2_On_Off ;//: 1; 291 uint16_t Sound3_On_Off ;//: 1; 292 uint16_t Sound4_On_Off ;//: 1; 293 uint16_t unused_1 ;//: 3; 294 uint16_t global_On_Off ;//: 1; 295 } control; 296}; 297 298struct SoundReg *soundReg; 299 300struct SoundReg s = { 301 { 0u, 0u, 0u, 0u, 302 1, 2, 303 3, 0, 4, 304 0x73U, 305 6, 0, 0, 0 }, 306 { 0, 307 1, 2, 308 4, 0, 8, 309 0xD7U, 310 6, 0, 0, 0 }, 311 { 0, 1, 312 0, 313 0, 3, 0, 314 0xD6U, 315 6, 0, 1, 0 }, 316 { 0, 317 58, 0, 318 1, 0, 10, 319 0, 0, 0, 320 0, 1, 0 }, 321 { 7, 0, 7, 0, 322 1, 1, 1, 1, 1, 1, 1, 1, 323 0, 0, 0, 0, 0, 1 } 324}; 325 326uint8_t NR10() { 327 return soundReg->mode1.sweepShifts | (soundReg->mode1.sweepMode << 3) | (soundReg->mode1.sweepTime << 4); 328} 329 330uint8_t NR11() { 331 return soundReg->mode1.soundLength | (soundReg->mode1.patternDuty << 6); 332} 333 334uint8_t NR12() { 335 return soundReg->mode1.envNbSweep | (soundReg->mode1.envMode << 3) | (soundReg->mode1.envInitialValue << 4); 336} 337 338uint8_t NR13() { 339 return soundReg->mode1.frequencyLow; 340} 341 342uint8_t NR14() { 343 return soundReg->mode1.frequencyHigh | (soundReg->mode1.counter_ConsSel << 6) | (soundReg->mode1.restart << 7); 344} 345 346//-------------------------- 347uint8_t NR21() { 348 return soundReg->mode2.soundLength | (soundReg->mode2.patternDuty << 6); 349} 350 351uint8_t NR22() { 352 return soundReg->mode2.envNbStep | (soundReg->mode2.envMode << 3) | (soundReg->mode2.envInitialValue << 4); 353} 354 355uint8_t NR23() { 356 return soundReg->mode2.frequencyLow; 357} 358 359uint8_t NR24() { 360 return soundReg->mode2.frequencyHigh | (soundReg->mode2.counter_ConsSel << 6) | (soundReg->mode2.restart << 7); 361} 362 363//------------------------------- 364uint8_t NR30() { 365 return soundReg->mode3.on_Off << 7; 366} 367 368uint8_t NR31() { 369 return soundReg->mode3.soundLength; 370} 371 372uint8_t NR32() { 373 return soundReg->mode3.selOutputLevel << 5; 374} 375 376uint8_t NR33() { 377 return soundReg->mode3.frequencyLow; 378} 379 380uint8_t NR34() { 381 return soundReg->mode3.frequencyHigh | (soundReg->mode3.counter_ConsSel << 6) | (soundReg->mode3.restart << 7); 382} 383 384//------------------------------- 385uint8_t NR41() { 386 return soundReg->mode4.soundLength; 387} 388 389uint8_t NR42() { 390 return soundReg->mode4.envNbStep | (soundReg->mode4.envMode << 3) | (soundReg->mode4.envInitialValue << 4); 391} 392 393uint8_t NR43() { 394 return soundReg->mode4.polyCounterDiv | (soundReg->mode4.polyCounterStep << 3) | (soundReg->mode4.polyCounterFreq << 4); 395} 396 397uint8_t NR44() { 398 return (soundReg->mode4.counter_ConsSel << 6) | (soundReg->mode4.restart << 7); 399} 400 401//------------------------------- 402uint8_t NR50() { 403 return soundReg->control.SO1_OutputLevel | (soundReg->control.Vin_SO1 << 3u) | (soundReg->control.SO2_OutputLevel << 4u) | 404 (soundReg->control.Vin_SO2 << 7u); 405} 406 407uint8_t NR51() { 408 return soundReg->control.Sound1_To_SO1 | (soundReg->control.Sound2_To_SO1 << 1) | (soundReg->control.Sound3_To_SO1 << 2) | 409 (soundReg->control.Sound4_To_SO1 << 3) | (soundReg->control.Sound1_To_SO2 << 4) | (soundReg->control.Sound2_To_SO2 << 5) | 410 (soundReg->control.Sound3_To_SO2 << 6)| (soundReg->control.Sound4_To_SO2 << 7); 411} 412 413uint8_t NR52() { 414 return soundReg->control.global_On_Off << 7; 415} 416 417//--------------------------------------------------------------------------------- 418uint16_t current_value(uint8_t mode, uint8_t line) 419{ 420 if(mode == 0) { 421 switch(line) 422 { 423 case 0: // global_On_Off 424 return soundReg->control.global_On_Off; 425 case 1: // Vin_SO1 426 return soundReg->control.Vin_SO1; 427 case 2: // Vin_SO2 428 return soundReg->control.Vin_SO2; 429 case 3: // SO1_OutputLevel 430 return soundReg->control.SO1_OutputLevel; 431 case 4: // SO2_OutputLevel 432 return soundReg->control.SO2_OutputLevel; 433 } 434 } else if(mode == 1) { 435 switch(line) 436 { 437 case 0: // sweepTime 438 return soundReg->mode1.sweepTime; 439 case 1: // sweepMode 440 return soundReg->mode1.sweepMode; 441 case 2: // sweepShifts 442 return soundReg->mode1.sweepShifts; 443 case 3: // patternDuty 444 return soundReg->mode1.patternDuty; 445 case 4: // soundLength 446 return soundReg->mode1.soundLength; 447 case 5: // envInitialValue 448 return soundReg->mode1.envInitialValue; 449 case 6: // envMode 450 return soundReg->mode1.envMode; 451 case 7: // envNbSweep 452 return soundReg->mode1.envNbSweep; 453 case 8: // frequency 454 case FREQUENCY: 455 return (soundReg->mode1.frequencyHigh << 8) | soundReg->mode1.frequencyLow; 456 case 9: // counter_ConsSel 457 return soundReg->mode1.counter_ConsSel; 458 case 10: // Sound1_To_SO1 459 return soundReg->control.Sound1_To_SO1; 460 case 11: // Sound1_To_SO2 461 return soundReg->control.Sound1_To_SO2; 462 case 12: // Sound1_On_Off 463 return soundReg->control.Sound1_On_Off; 464 } 465 } else if(mode == 2) { 466 switch(line) 467 { 468 case 0: // patternDuty 469 return soundReg->mode2.patternDuty; 470 case 1: // soundLength 471 return soundReg->mode2.soundLength; 472 case 2: // envInitialValue 473 return soundReg->mode2.envInitialValue; 474 case 3: // envMode 475 return soundReg->mode2.envMode; 476 case 4: // envNbStep 477 return soundReg->mode2.envNbStep; 478 case 5: // frequency 479 case FREQUENCY: 480 return (soundReg->mode2.frequencyHigh << 8) | soundReg->mode2.frequencyLow; 481 case 6: // counter_ConsSel 482 return soundReg->mode2.counter_ConsSel; 483 case 7: // Sound2_To_SO1 484 return soundReg->control.Sound2_To_SO1; 485 case 8: // Sound2_To_SO2 486 return soundReg->control.Sound2_To_SO2; 487 case 9: // Sound2_On_Off 488 return soundReg->control.Sound2_On_Off; 489 } 490 } else if(mode == 3) { 491 switch(line) 492 { 493 case 0: // on_Off 494 return soundReg->mode3.on_Off; 495 case 1: // soundLength 496 return soundReg->mode3.soundLength; 497 case 2: // selOutputLevel 498 return soundReg->mode3.selOutputLevel; 499 case 3: // frequency 500 case FREQUENCY: 501 return (soundReg->mode3.frequencyHigh << 8) | soundReg->mode3.frequencyLow; 502 case 4: // counter_ConsSel 503 return soundReg->mode3.counter_ConsSel; 504 case 5: // Sound3_To_SO1 505 return soundReg->control.Sound3_To_SO1; 506 case 6: // Sound3_To_SO2 507 return soundReg->control.Sound3_To_SO2; 508 case 7: // Sound3_On_Off 509 return soundReg->control.Sound3_On_Off; 510 } 511 } else if(mode == 4) { 512 switch(line) 513 { 514 case 0: // soundLength 515 return soundReg->mode4.soundLength; 516 case 1: // envInitialValue 517 return soundReg->mode4.envInitialValue; 518 case 2: // envMode 519 return soundReg->mode4.envMode; 520 case 3: // envNbStep 521 return soundReg->mode4.envNbStep; 522 case 4: // polyCounterFreq 523 return soundReg->mode4.polyCounterFreq; 524 case 5: // polyCounterStep 525 return soundReg->mode4.polyCounterStep; 526 case 6: // polyCounterDiv 527 return soundReg->mode4.polyCounterDiv; 528 case 7: // counter_ConsSel 529 return soundReg->mode4.counter_ConsSel; 530 case 8: // Sound4_To_SO1 531 return soundReg->control.Sound4_To_SO1; 532 case 9: // Sound4_To_SO2 533 return soundReg->control.Sound4_To_SO2; 534 case 10: // Sound4_On_Off 535 return soundReg->control.Sound4_On_Off; 536 } 537 } 538 return 0; 539} 540 541void update_value(uint8_t mode, uint8_t line, uint16_t value) 542{ 543 if(mode == 0) { 544 switch(line) 545 { 546 case 0: // global_On_Off 547 soundReg->control.global_On_Off = value; 548 NR52_REG = NR52(); 549 break; 550 case 1: // Vin_SO1 551 soundReg->control.Vin_SO1 = value; 552 NR50_REG = NR50(); 553 break; 554 case 2: // Vin_SO2 555 soundReg->control.Vin_SO2 = value; 556 NR50_REG = NR50(); 557 break; 558 case 3: // SO1_OutputLevel 559 soundReg->control.SO1_OutputLevel = value; 560 NR50_REG = NR50(); 561 break; 562 case 4: // SO2_OutputLevel 563 soundReg->control.SO2_OutputLevel = value; 564 NR50_REG = NR50(); 565 break; 566 case FREQUENCY: 567 update_value(1, FREQUENCY, value); 568 update_value(2, FREQUENCY, value); 569 update_value(3, FREQUENCY, value); 570 break; 571 case PLAY: // restart 572 update_value(1, FREQUENCY, current_value(1, FREQUENCY)); 573 update_value(2, FREQUENCY, current_value(2, FREQUENCY)); 574 update_value(3, FREQUENCY, current_value(3, FREQUENCY)); 575 soundReg->mode1.restart = value; 576 soundReg->mode2.restart = value; 577 soundReg->mode3.restart = value; 578 soundReg->mode4.restart = value; 579 NR14_REG = NR14(); 580 NR24_REG = NR24(); 581 NR34_REG = NR34(); 582 NR44_REG = NR44(); 583 soundReg->mode1.restart = 0; 584 soundReg->mode2.restart = 0; 585 soundReg->mode3.restart = 0; 586 soundReg->mode4.restart = 0; 587 break; 588 } 589 } else if(mode == 1) { 590 switch(line) 591 { 592 case 0: // sweepTime 593 soundReg->mode1.sweepTime = value; 594 NR10_REG = NR10(); 595 break; 596 case 1: // sweepMode 597 soundReg->mode1.sweepMode = value; 598 NR10_REG = NR10(); 599 break; 600 case 2: // sweepShifts 601 soundReg->mode1.sweepShifts = value; 602 NR10_REG = NR10(); 603 break; 604 case 3: // patternDuty 605 soundReg->mode1.patternDuty = value; 606 NR11_REG = NR11(); 607 break; 608 case 4: // soundLength 609 soundReg->mode1.soundLength = value; 610 NR11_REG = NR11(); 611 break; 612 case 5: // envInitialValue 613 soundReg->mode1.envInitialValue = value; 614 NR12_REG = NR12(); 615 break; 616 case 6: // envMode 617 soundReg->mode1.envMode = value; 618 NR12_REG = NR12(); 619 break; 620 case 7: // envNbSweep 621 soundReg->mode1.envNbSweep = value; 622 NR12_REG = NR12(); 623 break; 624 case 8: // frequency 625 case FREQUENCY: 626 soundReg->mode1.frequencyHigh = value >> 8; 627 soundReg->mode1.frequencyLow = 0xFF & value; 628 NR13_REG = NR13(); 629 NR14_REG = NR14(); 630 break; 631 case 9: // counter_ConsSel 632 soundReg->mode1.counter_ConsSel = value; 633 NR14_REG = NR14(); 634 break; 635 case 10: // Sound1_To_SO1 636 soundReg->control.Sound1_To_SO1 = value; 637 NR51_REG = NR51(); 638 break; 639 case 11: // Sound1_To_SO2 640 soundReg->control.Sound1_To_SO2 = value; 641 NR51_REG = NR51(); 642 break; 643 case 12: // Sound1_On_Off 644 soundReg->control.Sound1_On_Off = value; 645 NR52_REG = NR52(); 646 break; 647 case PLAY: // restart 648 update_value(mode, FREQUENCY, current_value(mode, FREQUENCY)); 649 soundReg->mode1.restart = value; 650 NR14_REG = NR14(); 651 soundReg->mode1.restart = 0; 652 break; 653 } 654 } else if(mode == 2) { 655 switch(line) 656 { 657 case 0: // patternDuty 658 soundReg->mode2.patternDuty = value; 659 NR21_REG = NR21(); 660 break; 661 case 1: // soundLength 662 soundReg->mode2.soundLength = value; 663 NR21_REG = NR21(); 664 break; 665 case 2: // envInitialValue 666 soundReg->mode2.envInitialValue = value; 667 NR22_REG = NR22(); 668 break; 669 case 3: // envMode 670 soundReg->mode2.envMode = value; 671 NR22_REG = NR22(); 672 break; 673 case 4: // envNbStep 674 soundReg->mode2.envNbStep = value; 675 NR22_REG = NR22(); 676 break; 677 case 5: // frequency 678 case FREQUENCY: 679 soundReg->mode2.frequencyHigh = value >> 8; 680 soundReg->mode2.frequencyLow = 0xFF & value; 681 NR23_REG = NR23(); 682 NR24_REG = NR24(); 683 break; 684 case 6: // counter_ConsSel 685 soundReg->mode2.counter_ConsSel = value; 686 NR24_REG = NR24(); 687 break; 688 case 7: // Sound2_To_SO1 689 soundReg->control.Sound2_To_SO1 = value; 690 NR51_REG = NR51(); 691 break; 692 case 8: // Sound2_To_SO2 693 soundReg->control.Sound2_To_SO2 = value; 694 NR51_REG = NR51(); 695 break; 696 case 9: // Sound2_On_Off 697 soundReg->control.Sound2_On_Off = value; 698 NR52_REG = NR52(); 699 break; 700 case PLAY: // restart 701 update_value(mode, FREQUENCY, current_value(mode, FREQUENCY)); 702 soundReg->mode2.restart = value; 703 NR24_REG = NR24(); 704 soundReg->mode2.restart = 0; 705 break; 706 } 707 } else if(mode == 3) { 708 switch(line) 709 { 710 case 0: // on_Off 711 soundReg->mode3.on_Off = value; 712 NR30_REG = NR30(); 713 break; 714 case 1: // soundLength 715 soundReg->mode3.soundLength = value; 716 NR31_REG = NR31(); 717 break; 718 case 2: // selOutputLevel 719 soundReg->mode3.selOutputLevel = value; 720 NR32_REG = NR32(); 721 break; 722 case 3: // frequency 723 case FREQUENCY: 724 soundReg->mode3.frequencyHigh = value >> 8; 725 soundReg->mode3.frequencyLow = 0xFF & value; 726 NR33_REG = NR33(); 727 NR34_REG = NR34(); 728 break; 729 case 4: // counter_ConsSel 730 soundReg->mode3.counter_ConsSel = value; 731 NR34_REG = NR34(); 732 break; 733 case 5: // Sound3_To_SO1 734 soundReg->control.Sound3_To_SO1 = value; 735 NR51_REG = NR51(); 736 break; 737 case 6: // Sound3_To_SO2 738 soundReg->control.Sound3_To_SO2 = value; 739 NR51_REG = NR51(); 740 break; 741 case 7: // Sound3_On_Off 742 soundReg->control.Sound3_On_Off = value; 743 NR52_REG = NR52(); 744 break; 745 case PLAY: // restart 746 update_value(mode, FREQUENCY, current_value(mode, FREQUENCY)); 747 soundReg->mode3.restart = value; 748 NR34_REG = NR34(); 749 soundReg->mode3.restart = 0; 750 break; 751 } 752 } else if(mode == 4) { 753 switch(line) 754 { 755 case 0: // soundLength 756 soundReg->mode4.soundLength = value; 757 NR41_REG = NR41(); 758 break; 759 case 1: // envInitialValue 760 soundReg->mode4.envInitialValue = value; 761 NR42_REG = NR42(); 762 break; 763 case 2: // envMode 764 soundReg->mode4.envMode = value; 765 NR42_REG = NR42(); 766 break; 767 case 3: // envNbStep 768 soundReg->mode4.envNbStep = value; 769 NR42_REG = NR42(); 770 break; 771 case 4: // polyCounterFreq 772 soundReg->mode4.polyCounterFreq = value; 773 NR43_REG = NR43(); 774 break; 775 case 5: // polyCounterStep 776 soundReg->mode4.polyCounterStep = value; 777 NR43_REG = NR43(); 778 break; 779 case 6: // polyCounterDiv 780 soundReg->mode4.polyCounterDiv = value; 781 NR43_REG = NR43(); 782 break; 783 case 7: // counter_ConsSel 784 soundReg->mode4.counter_ConsSel = value; 785 NR44_REG = NR44(); 786 break; 787 case 8: // Sound4_To_SO1 788 soundReg->control.Sound4_To_SO1 = value; 789 NR51_REG = NR51(); 790 break; 791 case 9: // Sound4_To_SO2 792 soundReg->control.Sound4_To_SO2 = value; 793 NR51_REG = NR51(); 794 break; 795 case 10: // Sound4_On_Off 796 soundReg->control.Sound4_On_Off = value; 797 NR52_REG = NR52(); 798 break; 799 case PLAY: // restart 800 soundReg->mode4.restart = value; 801 NR44_REG = NR44(); 802 soundReg->mode4.restart = 0; 803 break; 804 } 805 } 806} 807 808uint8_t draw_screen(uint8_t mode) 809{ 810 uint8_t i; 811 812 clss(); 813 gotoxy(FIRST_X, TITLE_Y); 814 print(params[0].name); 815 816 for(i = 0; params[i+1].name; i++) { 817 gotoxy(FIRST_X, FIRST_Y+i); 818 print(params[i+1].name); 819 gotoxy(VAL_X, FIRST_Y+i); 820 println(current_value(mode, i), 10, UNSIGNED); 821 } 822 823 return i-1; 824} 825 826 827void play_music(uint8_t mode) 828{ 829 uint8_t i = 0; 830 831 while(music[i] != END) { 832 if(music[i] != SILENCE) { 833 update_value(mode, FREQUENCY, frequencies[music[i]]); 834 update_value(mode, PLAY, 1); 835 } 836 delay(500); 837 i++; 838 } 839} 840 841 842void show_register_channel(uint8_t mode) { 843 844 switch (mode) { 845 case 1: 846 gotoxy(0, 16); 847 print("NR10-14:"); 848 849 gotoxy(1, 17); // Last line 850 printn(NR10(), 16, UNSIGNED); print(", "); 851 printn(NR11(), 16, UNSIGNED); print(", "); 852 printn(NR12(), 16, UNSIGNED); print(", "); 853 printn(NR13(), 16, UNSIGNED); print(", "); 854 printn(0x80 | NR14(), 16, UNSIGNED); 855 856 break; 857 858 case 2: 859 gotoxy(0, 16); 860 print("NR21-24:"); 861 862 gotoxy(1, 17); // Last line 863 printn(NR21(), 16, UNSIGNED); print(", "); 864 printn(NR22(), 16, UNSIGNED); print(", "); 865 printn(NR23(), 16, UNSIGNED); print(", "); 866 printn(0x80 | NR24(), 16, UNSIGNED); 867 868 break; 869 870 case 3: 871 gotoxy(0, 16); 872 print("NR30-34:"); 873 874 gotoxy(1, 17); // Last line 875 printn(NR30(), 16, UNSIGNED); print(", "); 876 printn(NR31(), 16, UNSIGNED); print(", "); 877 printn(NR32(), 16, UNSIGNED); print(", "); 878 printn(NR33(), 16, UNSIGNED); print(", "); 879 printn(0x80 | NR34(), 16, UNSIGNED); 880 881 break; 882 883 case 4: 884 gotoxy(0, 16); 885 print("NR41-44:"); 886 887 gotoxy(1, 17); // Last line 888 printn(NR41(), 16, UNSIGNED); print(", "); 889 printn(NR42(), 16, UNSIGNED); print(", "); 890 printn(NR43(), 16, UNSIGNED); print(", "); 891 printn(0x80 | NR44(), 16, UNSIGNED); 892 893 break; 894 895 case 0: 896 gotoxy(0, 16); 897 print("NR50-52:"); 898 899 gotoxy(1, 17); // Last line 900 printn(NR50(), 16, UNSIGNED); print(", "); 901 printn(NR51(), 16, UNSIGNED); print(", "); 902 printn(NR52(), 16, UNSIGNED); print(", "); 903 904 break; 905 906 } 907} 908 909 910void dump_registers() 911{ 912 clss(); 913 gotoxy(FIRST_X, TITLE_Y); 914 print("Register Dump\n\n"); 915 916 print("NR10:");println(NR10(), 16, UNSIGNED); 917 print("NR11:");printn(NR11(), 16, UNSIGNED); print(" NR21:");println(NR21(), 16, UNSIGNED); 918 print("NR12:");printn(NR12(), 16, UNSIGNED); print(" NR22:");println(NR22(), 16, UNSIGNED); 919 print("NR13:");printn(NR13(), 16, UNSIGNED); print(" NR23:");println(NR23(), 16, UNSIGNED); 920 print("NR14:");printn(0x80 | NR14(), 16, UNSIGNED); print(" NR24:");println(0x80 | NR24(), 16, UNSIGNED); 921 printf("\n"); 922 923 print("NR30:");println(NR30(), 16, UNSIGNED); 924 print("NR31:");printn(NR31(), 16, UNSIGNED); print(" NR41:");println(NR41(), 16, UNSIGNED); 925 print("NR32:");printn(NR32(), 16, UNSIGNED); print(" NR42:");println(NR42(), 16, UNSIGNED); 926 print("NR33:");printn(NR33(), 16, UNSIGNED); print(" NR43:");println(NR43(), 16, UNSIGNED); 927 print("NR34:");printn(0x80 | NR34(), 16, UNSIGNED); print(" NR44:");println(0x80 | NR44(), 16, UNSIGNED); 928 printf("\n"); 929 930 print("NR50:");println(NR50(), 16, UNSIGNED); 931 print("NR51:");println(NR51(), 16, UNSIGNED); 932 print("NR52:");println(NR52(), 16, UNSIGNED); 933} 934 935void wait_event(uint8_t mode) 936{ 937 uint8_t y, last_y; 938 uint16_t l = 0; 939 uint16_t m = 0; 940 941 while(1) { 942 params = params_array[mode]; 943 last_y = draw_screen(mode) + FIRST_Y; 944 y = FIRST_Y; 945 gotoxy(ARROW_X, y); 946 setchar(ARROW_CHAR); 947 948 show_register_channel(mode); 949 950 while(1) { 951 if(KEY_TICKED(J_UP)) { 952 gotoxy(ARROW_X, y); setchar(SPACE_CHAR); 953 if(--y < FIRST_Y) 954 y = last_y; 955 gotoxy(ARROW_X, y); setchar(ARROW_CHAR); 956 957 } else if(KEY_TICKED(J_DOWN)) { 958 gotoxy(ARROW_X, y); setchar(SPACE_CHAR); 959 if(++y > last_y) 960 y = FIRST_Y; 961 gotoxy(ARROW_X, y); setchar(ARROW_CHAR); 962 963 } else if(KEY_TICKED(J_LEFT)) { 964 l = current_value(mode, y-FIRST_Y); 965 if(l != 0) { 966 if(KEY_PRESSED(J_A) && KEY_PRESSED(J_B)) 967 l = 0; 968 else if(KEY_PRESSED(J_A)) 969 l = (l > 10) ? (l - 10) : 0; 970 else if(KEY_PRESSED(J_B)) 971 l = (l > 100) ? (l - 100) : 0; 972 else 973 l--; 974 update_value(mode, y-FIRST_Y, l); 975 } 976 gotoxy(VAL_X, y); print(" "); 977 gotoxy(VAL_X, y); println(l, 10, UNSIGNED); 978 979 show_register_channel(mode); 980 981 } else if(KEY_TICKED(J_RIGHT)) { 982 l = current_value(mode, y-FIRST_Y); 983 m = params[y-(FIRST_Y-1)].max; 984 if(l != m) { 985 if(KEY_PRESSED(J_A) && KEY_PRESSED(J_B)) { 986 l = m; 987 } 988 else if(KEY_PRESSED(J_A)) { 989 l += 10; 990 if(l > m) 991 l = m; 992 } else if(KEY_PRESSED(J_B)) { 993 l += 100; 994 if(l > m) 995 l = m; 996 } 997 else 998 l++; 999 update_value(mode, y-FIRST_Y, l); 1000 } 1001 gotoxy(VAL_X, y); print(" "); 1002 gotoxy(VAL_X, y); println(l, 10, UNSIGNED); 1003 1004 show_register_channel(mode); 1005 1006 } else if(KEY_TICKED(J_START)) { 1007 if (KEY_PRESSED(J_A)) 1008 play_music(mode); 1009 else 1010 update_value(mode, PLAY, 1); 1011 1012 } else if(KEY_PRESSED(J_SELECT)) { 1013 if(KEY_PRESSED(J_A)) 1014 dump_registers(); 1015 else { 1016 mode = (mode+1) % NB_MODES; 1017 } 1018 waitpadup(); 1019 keys = 0; 1020 break; 1021 } 1022 wait_vbl_done(); 1023 UPDATE_KEYS(); 1024 } 1025 } 1026} 1027 1028void main() 1029{ 1030 // 1031 // Before modifying any sound register, sound must be turned on! 1032 // (it is turned off by default to save batteries) 1033 // 1034 NR52_REG = 0x80; 1035 1036 soundReg = &s; 1037 NR10_REG = NR10(); 1038 NR11_REG = NR11(); 1039 NR12_REG = NR12(); 1040 NR13_REG = NR13(); 1041 NR14_REG = NR14(); 1042 1043 NR21_REG = NR21(); 1044 NR22_REG = NR22(); 1045 NR23_REG = NR23(); 1046 NR24_REG = NR24(); 1047 1048 NR30_REG = NR30(); 1049 NR31_REG = NR31(); 1050 NR32_REG = NR32(); 1051 NR33_REG = NR33(); 1052 NR34_REG = NR34(); 1053 1054 NR41_REG = NR41(); 1055 NR42_REG = NR42(); 1056 NR43_REG = NR43(); 1057 NR44_REG = NR44(); 1058 1059 NR50_REG = NR50(); 1060 NR51_REG = NR51(); 1061 NR52_REG = NR52(); 1062 1063 clss(); 1064 1065 wait_event(1); 1066} 1067