2 // Thunder Graphic User Interface
5 // (c) 2004, 2014 Underground Software
7 // JLH = James Hammons <jlhamm@acm.org>
10 // --- ---------- -----------------------------------------------------------
11 // JLH 07/23/2009 Added changelog ;-)
17 #include <fstream> // Needed for tracelog
19 #include "resource.h" // Thunder graphics & sounds
25 extern SDL_Surface * screen;
27 extern uint8_t my_scr[0x14000]; // Screen buffer...
28 extern uint8_t gram1[]; // Game RAM (do here??)
29 extern uint8_t hScrollOffset; // Horizontal scroll offset
30 extern uint8_t vScrollOffset; // Vertical scroll offset
31 extern uint32_t voffsets[8];
32 extern uint8_t voice_rom[]; // PCM data pointer
33 extern fstream tr; // Tracelog
37 uint16_t text_life; // How long text is visible
38 bool show_text; // Whether or not to show text
39 uint16_t show_which_msg; // Which message to show
40 bool show_gui; // Whether or not to show GUI
41 uint16_t selection; // Which GUI item currently selected
43 uint16_t gui_debounce; // GUI key debounce value
44 uint16_t num_coins; // Number of coins dropped
45 uint16_t blink = 0; // Used to blink player 1 & 2 start buttons
46 uint16_t flash = 23; // Used to flash GUI lights
47 uint16_t iline = 0; // Used to roll line
48 uint16_t dcurcol = 179; // dipswitch cursor color
49 int dcurdir = 1; // Initially going up...
50 bool blink_on = false;
51 bool game_refresh; // Refresh rate user set
52 bool do_decrement; // Flag to handle decrement...
53 bool user_selected_something; // Flag for well, you know...
54 uint16_t dswitch; // Which dipswitch is selected...
56 // The following are global for the sound routines...
58 const float sampleBase = 22050.0/6000.0; // Btwn 5512.5 and 6000
60 bool chan1_go = false, chan2_go = false, chan3_go = false;
61 bool chan4_go = false, chan5_go = false, chan6_go = false;
62 uint8_t * sndp1, * sndp2, * sndp3, * sndp4, * sndp5, * sndp6;
63 uint32_t rom_pos, end_pos;
64 uint32_t spos1, end_pos1;
65 uint32_t spos2, end_pos2;
66 uint32_t spos3, end_pos3;
67 uint32_t spos4, end_pos4;
68 uint32_t spos5, end_pos5;
69 uint32_t spos6, end_pos6;
77 uint8_t * snd_array[3] = { sunknown, scya, scamera }; // From RESOURCE.H
78 uint32_t snd_lens[3] = { sunknownlen, scyalen, scameralen };
83 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
84 0,0,1,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,
85 0,1,0,0,0,0,1,0,0,1,0,1,0,0,1,0,1,1,1,1,0,
86 0,1,1,1,0,0,1,0,0,1,0,1,1,1,1,0,0,0,1,0,0,
87 0,1,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,
88 0,0,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,1,0,
89 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
92 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
93 0,1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,0,0,0,0,0,
94 0,0,0,0,1,0,1,0,0,1,0,1,0,0,1,0,1,1,1,1,0,
95 0,0,1,1,0,0,1,0,0,1,0,1,1,1,1,0,0,0,1,0,0,
96 0,0,0,0,1,0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,
97 0,1,1,1,0,0,0,1,1,0,0,1,0,0,1,0,1,1,1,1,0,
98 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
101 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
102 0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
103 0,1,0,0,0,0,1,1,1,0,0,0,1,1,0,0,1,1,1,0,0,
104 0,0,1,1,0,0,1,0,0,1,0,0,0,0,1,0,1,0,0,1,0,
105 0,0,0,0,1,0,1,0,0,1,0,1,1,1,1,0,1,0,0,1,0,
106 0,1,1,1,0,0,1,0,0,1,0,0,1,1,1,0,1,1,1,0,0,
107 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0
109 uint8_t boptions[] = { // 35x9
110 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
111 0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
112 0,1,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
113 0,1,0,0,1,0,1,1,1,0,0,1,1,1,1,0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,0,1,1,0,0,
114 0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,1,0,0,0,0,
115 0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,
116 0,1,0,0,1,0,1,0,0,1,0,0,1,0,0,0,0,1,0,0,1,0,0,1,0,1,0,0,1,0,0,0,0,1,0,
117 0,0,1,1,0,0,1,1,1,0,0,0,0,1,1,0,1,1,1,0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0,
118 0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
273 user_selected_something = false;
278 // Handle key debounce
280 void HandleGUIDebounce(void)
283 gui_debounce--; // Debounce GUI keys...
285 do_decrement = !do_decrement; // Called at 60Hz, so skip decrementing blink
290 blink--; // Handle blinking stuff (Should prb go in DrawGUI)
292 flash -= 2; // Handle flashing stuff (Should prb go in DrawGUI)
300 iline = 0; // 30 pixels high, going past by 1
314 // Set the refresh rate (30/60 Hz)
316 void SetRefreshRate(bool refresh)
318 game_refresh = refresh;
323 // Whether or not GUI is showing
334 void ActivateGUI(void)
343 void DeactivateGUI(void)
350 // Draw the small icons...
352 void DrawSmallIcons(uint16_t icon_not_to_draw)
356 uint8_t * sIcons[12] = { inoguis, icoinus, ipl1sts, ipl2sts, ii30hzs,
357 ii60hzs, idipsws, ichecks, ikeycns, isnapss, iresets, ibyebys };
358 uint8_t xlens[12] = { 31, 18, 32, 35, 37, 37, 29, 23, 28, 32, 19, 19 };
359 uint8_t ylens[12] = { 31, 18, 19, 19, 21, 21, 23, 20, 16, 17, 20, 23 };
360 uint8_t xpos[11] = { 33, 48, 63, 78, 104, 0, 184, 210, 225, 240, 255 };
361 uint8_t iconidx[11] = { 7, 8, 9, 10, 11, 0, 1, 2, 3, 4, 6 };
364 iconidx[9] = 5; // 60 Hz...
366 // Draw small icons 1 to 5 on left, then 11 to 7 on right.
368 for(int i=0; i<5; i++)
370 uint16_t idx = i + icon_not_to_draw; // Get correct start pos.
375 iconmem = sIcons[iconidx[idx]];
376 xl = xlens[iconidx[idx]];
377 yl = ylens[iconidx[idx]];
379 uint32_t scadr = hScrollOffset + voffsets[vScrollOffset];
380 scadr += 320 * ((224 - yl) / 2); // Center vertically
381 scadr += xpos[i] - (xl / 2); // Center around horiz. pos.
384 for(int yy=0; yy<yl; yy++)
386 for(int xx=0; xx<xl; xx++)
388 uint8_t b = iconmem[bmpptr++];
391 my_scr[scadr + xx + yy * 320] = b;
396 for(int i=10; i>5; i--)
398 uint16_t idx = i + icon_not_to_draw; // Get correct start pos.
403 iconmem = sIcons[iconidx[idx]];
404 xl = xlens[iconidx[idx]];
405 yl = ylens[iconidx[idx]];
407 uint32_t scadr = hScrollOffset + voffsets[vScrollOffset];
408 scadr += 320 * ((224 - yl) / 2); // Center vertically
409 scadr += xpos[i] - (xl / 2); // Center around horiz. pos.
412 for(int yy=0; yy<yl; yy++)
414 for(int xx=0; xx<xl; xx++)
416 uint8_t b = iconmem[bmpptr++];
419 my_scr[scadr + xx + yy * 320] = b;
427 // Draw the large (selected) icon
429 void DrawLargeIcon(uint16_t icon)
433 uint8_t * lIcons[11] = { inoguib, icoinub, ipl1stb, ipl2stb, ii30hzb,
434 ii60hzb, idipswb, ikeycnb, isnapsb, iresetb, ibyebyb };
435 uint8_t xlens[11] = { 44, 45, 50, 52, 59, 59, 42, 45, 48, 58, 42 };
436 uint8_t ylens[11] = { 44, 40, 33, 29, 52, 52, 34, 45, 37, 40, 50 };
438 uint8_t gsubs1[24] = { 21, 21, 20, 19, 168, 168, 31, 155, 68, 68, 67, 66,
439 36, 36, 35, 34, 188, 188, 183, 181, 81, 81, 85, 80 },
440 gsubs2[24] = { 20, 20, 19, 19, 31, 31, 155, 155, 67, 67, 66, 66,
441 35, 35, 34, 34, 183, 183, 181, 181, 85, 85, 80, 80 },
442 gsubs3[24] = { 35, 34, 188, 188, 183, 181, 81, 81, 85, 80, 21, 21,
443 20, 19, 168, 168, 31, 155, 68, 68, 67, 66, 36, 36 },
444 gsubs4[24] = { 34, 34, 183, 183, 181, 181, 85, 85, 80, 80, 20, 20,
445 19, 19, 31, 31, 155, 155, 67, 67, 66, 66, 35, 35 },
446 gsubs5[24] = { 20, 20, 183, 183, 31, 31, 85, 85, 67, 67, 20, 20,
447 35, 35, 31, 31, 183, 183, 67, 67, 85, 85, 35, 35 };
449 iconmem = lIcons[icon];
460 if ((icon == REFRESH) && game_refresh)
467 if (icon == DIPSWITCH)
474 uint32_t scadr = hScrollOffset + voffsets[vScrollOffset];
475 scadr += 320 * ((224 - yl) / 2); // Center vertically
476 scadr += (288 - xl) / 2; // Center horizontally
479 for(int yy=0; yy<yl; yy++)
481 for(int xx=0; xx<xl; xx++)
483 uint8_t b = iconmem[bmpptr++];
487 if ((icon == PL1START) && (b == 235) && (num_coins) && !blink_on)
488 b = 125; // Light ON color
489 /*noguib: 44x44 [Green (hi/lo): 36/235 Orange: 168/31 Neutral:12]
490 Rainbow (ROYGBP, hi/med/lo): 21,20,19; 168, 31,155; 68,67,66;
491 36,35,34; 188,183,181; 81,85,80 */
494 uint8_t fln = (23 - flash) + 1; // Want to go forward (maybe fix it?)
497 case 36: { b = gsubs1[fln]; break; }
498 case 235: { b = gsubs2[fln]; break; }
499 case 168: { b = gsubs3[fln]; break; }
500 case 31: { b = gsubs4[fln]; break; }
501 case 12: { b = gsubs5[fln]; break; }
505 if ((icon == REFRESH) && (iline == yy) && (b == 50))
508 my_scr[scadr+xx+yy*320] = b;
513 if (!blink) // Should go here???
515 blink_on = !blink_on; // Switch blink state
522 //if (flash == 1) flash = 23; // Reset flash value
527 // Draw the dipswitch portion of the GUI
529 void DrawDipswitch(void)
531 uint8_t dseloff[16] = { 0, 1, 1, 2, 3, 4, 5, 5, 6, 7, 8, 9, 10, 11, 11, 12 };
532 uint8_t * dtxt[13] = { idstext1, idstext2, idstext3, idstext4, idstext5,
533 idstext2, idstext6, idstext7, idstext8, idstext9, idstext10, idstext11,
536 uint8_t dtx[13] = { 48, 80, 96, 82, 60, 80, 76, 57, 33, 50, 62, 65, 63 },
537 dty[13] = { 7, 9, 7, 9, 7, 9, 7, 7, 7, 9, 7, 9, 7 };
538 uint32_t dtxtoff[13] = { 4*320+24, 14*320-78, 25*320+24, 32*320-80,
539 39*320+24, 49*320-78, 4*320+24, 11*320-55, 18*320+24, 25*320-48,
540 32*320+24, 42*320-63, 53*320+24 };
541 uint32_t scadr, bmpptr;
544 uint32_t dbase = hScrollOffset + voffsets[vScrollOffset];
545 dbase += (288 - 26) / 2; // Center horizontally
546 dbase += 320 * ((224 - ((65 * 2) + 8)) / 2); // Center vertically
548 scadr = dbase; // Reset screen address
551 for(int yy=0; yy<65; yy++)
553 for(int xx=0; xx<26; xx++)
555 uint8_t b = idswitch[bmpptr++];
558 my_scr[scadr + xx + yy * 320] = b;
562 scadr = dbase + (320*73); // Reset screen address
565 for(int yy=0; yy<65; yy++)
567 for(int xx=0; xx<26; xx++)
569 uint8_t b = idswitch[bmpptr++];
572 my_scr[scadr + xx + yy * 320] = b;
576 for(int i=0; i<16; i++)
578 scadr = dbase + (5 * 320 + 5) + i * 7 * 320;
581 scadr += 17*320; // Adjust for DSW #2
585 if (gram1[0x423D + (i << 1)])
586 scadr += 12; // Adjust position if ON
588 for(int yy=0; yy<5; yy++)
590 for(int xx=0; xx<5; xx++)
592 my_scr[scadr++] = idsbutton[bmpptr++];
595 scadr += 315; // Adjust position...
599 uint8_t dselected_text = dseloff[dswitch];
601 for(int i=0; i<13; i++)
603 if (dselected_text != i)
605 scadr = dbase + dtxtoff[i];
612 for(int yy=0; yy<dty[i]; yy++)
614 for(int xx=0; xx<dtx[i]; xx++)
616 uint8_t b = dtxt[i][bmpptr++];
624 scadr += (320 - dtx[i]); // Adjust position...
629 scadr = dbase + dtxtoff[dselected_text];
631 if (dselected_text>5)
636 for(int yy=0; yy<dty[dselected_text]; yy++)
638 for(int xx=0; xx<dtx[dselected_text]; xx++)
640 uint8_t b = dtxt[dselected_text][bmpptr++];
648 scadr += (320 - dtx[dselected_text]); // Adjust position...
651 if (dswitch != 16) // Draw cursor
653 scadr = dbase + (4 * 320 + 4) + dswitch * 7 * 320;
656 scadr += 17 * 320; // Adjust for DSW #2
658 for(int xx=0; xx<19; xx++)
659 my_scr[scadr++] = dcurcol;
663 for(int xx=0; xx<5; xx++)
665 my_scr[scadr] = dcurcol;
667 my_scr[scadr] = dcurcol;
671 for(int xx=0; xx<19; xx++)
672 my_scr[scadr++] = dcurcol;
678 // The actual GUI display routine
682 if (!user_selected_something) // i.e. we're not inside a selection...
684 DrawSmallIcons(selection); // 'selection' is icon *not* to draw
685 DrawLargeIcon(selection);
689 if (selection == DIPSWITCH)
696 // User pressed left arrow handler
698 void SelectLeft(void)
704 if (!user_selected_something)
713 if (gram1[0x423D + (dswitch << 1)]) // It's switchable...
714 {} //SpawnSound(USERSOUND, SCLICK);
716 {} //SpawnSound(USERSOUND, SUNGH);
718 gram1[0x423D + (dswitch << 1)] = 0; // & turn it off
725 // User pressed right arrow handler
727 void SelectRight(void)
733 if (!user_selected_something)
738 selection = 10; // Unsigned compare
742 if (!gram1[0x423D + (dswitch << 1)]) // It's switchable...
743 {} //SpawnSound(USERSOUND, SCLICK);
745 {} //SpawnSound(USERSOUND, SUNGH);
747 gram1[0x423D+(dswitch<<1)] = 1; // & turn it on
754 // User pressed Up arrow handler
762 if (user_selected_something)
764 if (selection == DIPSWITCH)
769 dswitch = 16; // Wrap non-int
770 //snd_num = dswitch; SpawnMsg(MSHOWNUMS); // Temp...
778 // User pressed down arrow handler
780 void SelectDown(void)
786 if (user_selected_something)
788 if (selection == DIPSWITCH)
794 //snd_num = dswitch; SpawnMsg(MSHOWNUMS); // Temp...
802 // User selected something! Handle it!
804 uint8_t UserSelectedSomething(void)
806 //extern uint8_t * gram1;
812 if (!user_selected_something) // Inside a selection? no...
815 if (selection == NOGUI) // Turn off GUI
820 if (selection == COINUP) // Coin up machine
822 gram1[0x41A5]++; // Add one coin... (prob. need sep. counter)
824 gram1[0x4189] = num_coins / 10; // Should be in THUNDER.CPP?
825 gram1[0x418A] = num_coins - (gram1[0x4189] * 10);
828 if (selection == PL1START) // 1 Player start
833 show_gui = false; // Shut off GUI only if coined up
836 gram1[0x418C] = 1; // Strobe start location
839 if (selection == PL2START) // 2 Player start
848 if (selection == REFRESH) // Toggle refresh rate
850 //SpawnSound(USERSOUND, SCLICK);
853 if (selection == DIPSWITCH) // Edit game settings
855 //SpawnSound(USERSOUND, SBLAH);
856 user_selected_something = true;
857 dswitch = 0; // Set at first dipswitch
860 if (selection == OPTIONS) // Edit emulator settings
864 if (selection == KEYCONFIG) // Edit game keys
868 if (selection == SNAPSHOT) // Snapshot
870 SpawnSound(USERSOUND, SCAMERA);
874 if (selection == RESET) // Reset machine
876 //SpawnSound(USERSOUND, SRESET);
879 if (selection == EXIT)
881 SpawnSound(USERSOUND, SCYA);
886 else // Selected something inside selection...
888 if (selection == DIPSWITCH)
890 if (dswitch == 16) // Selected 'back to GUI'
892 //SpawnSound(USERSOUND, SBLAH2);
893 user_selected_something = false;
897 //SpawnSound(USERSOUND, SCLICK);
898 gram1[0x423D + (dswitch << 1)] = !gram1[0x423D + (dswitch << 1)];
902 return 0xFF; // Nothing for main to do...
906 return 0xFF; // Wasn't debounced, so return invalid
911 // Show byte passed to it
913 void ShowNumbers(int number)
915 uint8_t * bnarray[16] = { bn0, bn1, bn2, bn3, bn4, bn5, bn6, bn7, bn8, bn9,
916 bnA, bnB, bnC, bnD, bnE, bnF };
917 uint32_t scadr = hScrollOffset + voffsets[vScrollOffset] + 642 + 2560;
920 uint8_t first_dig = number >> 4, second_dig = number & 0x0F;
922 for(int y=0; y<7; y++)
924 for(int x=0; x<6; x++)
926 if (bnarray[first_dig][bmpptr++] == 1)
927 my_scr[scadr + x + y * 320] = 7;
929 my_scr[scadr + x + y * 320] = 0;
936 for(int y=0; y<7; y++)
938 for(int x=0; x<6; x++)
940 if (bnarray[second_dig][bmpptr++] == 1)
941 my_scr[scadr + x + y * 320] = 7;
943 my_scr[scadr + x + y * 320] = 0;
952 void SpawnMsg(uint8_t msg)
954 text_life = 60; // 1 second...
955 show_text = true; // Show the damn thing...
956 show_which_msg = msg; // And tell it which message to show...
965 // Kill text if it's time
972 // Your life force is running out...
975 // Draw the message here...
976 uint32_t scadr = hScrollOffset + voffsets[vScrollOffset] + 642;
979 for(int y=0; y<7; y++)
981 for(int x=0; x<21; x++)
983 if (show_which_msg == M60FPS)
985 if (bmp1[bmpptr++] == 1)
986 my_scr[scadr + x + y * 320] = 7;
988 my_scr[scadr + x + y * 320] = 0;
990 else if (show_which_msg == M30FPS)
992 if (bmp2[bmpptr++] == 1)
993 my_scr[scadr + x + y * 320] = 7;
995 my_scr[scadr + x + y * 320] = 0;
997 else if (show_which_msg == MSNAPSHOT)
999 if (bmp3[bmpptr++] == 1)
1000 my_scr[scadr + x + y * 320] = 7;
1002 my_scr[scadr + x + y * 320] = 0;
1007 if (show_which_msg == MSHOWNUMS)
1008 ShowNumbers(snd_num);
1013 // Sound stuff (Will go elsewhere??? Perhaps in sound.cpp?)
1015 void SpawnSound(int type, int snd, int channel/* = 0*/)
1017 extern uint32_t psg_lens[16];
1018 extern uint8_t * psg_adrs[16];
1019 extern uint32_t voc_lens[32];
1020 extern uint8_t * voc_adrs[32];
1021 extern uint32_t fm_lens[14];
1022 extern uint8_t * fm_adrs[14];
1025 SpawnMsg(MSHOWNUMS);
1027 if (type == GAMESOUND)
1029 snd--; // Will that do it??? Yes!!!
1033 // 00 nn ss (nn # of repeats of sample ss)
1042 spos1 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
1043 spos1 += st; // Need to add start somewhere...
1058 spos2 = (voice_rom[st + (snd << 1)] << 8) | voice_rom[st + (snd << 1) + 1];
1059 spos2 += st; // Need to add start somewhere...
1065 else if (type == PSGSOUND)
1067 if (snd_num & 0x10) // Second channel?
1070 end_pos3 = psg_lens[snd_num & 0x0F];
1071 sndp3 = psg_adrs[snd_num & 0x0F];
1074 if (spos3 == end_pos3)
1075 chan3_go = false; // No sound loaded, so don't do it!
1077 else // First channel
1080 end_pos4 = psg_lens[snd_num & 0x0F];
1081 sndp4 = psg_adrs[snd_num & 0x0F];
1084 if (spos4 == end_pos4)
1085 chan4_go = false; // No sound loaded, so don't do it!
1088 else if (type == FMSOUND)
1091 end_pos5 = fm_lens[snd_num];
1092 sndp5 = fm_adrs[snd_num];
1095 if (spos5 == end_pos5)
1096 chan5_go = false; // No sound loaded, so don't do it!
1098 else if (type == USERSOUND)
1101 end_pos6 = snd_lens[snd_num]; // User sound
1102 sndp6 = snd_array[snd_num]; // Load pointer
1109 // Sound card IRQ handler
1111 void SoundFunc(void * userdata, Uint8 * buff, int num)
1113 // 0-22 different sounds...
1114 uint16_t cnt = 0, sample;
1115 uint8_t start_samp1, end_samp1, start_samp2, end_samp2;
1116 uint8_t samp1 = 128, samp2 = 128, samp3 = 128,
1117 samp4 = 128, samp5 = 128, samp6 = 128; // Zero samples...
1120 memset(buff, 128, num);
1122 if (chan1_go || chan2_go || chan3_go || chan4_go || chan5_go || chan6_go)
1130 samp1 = voice_rom[spos1++];
1132 // Kill channel 1 if done...
1138 // RLE compression...
1139 else if (samp1 == 0x00)
1142 sample1 += (float)voice_rom[spos1++] * sampleBase;
1143 // Get last good sample
1147 // Keep fractional part intact
1148 sample1 += sampleBase;
1151 prevSamp1 = samp1; // Save last sample value
1152 sample1 -= 1.0; // Decrement repeat counter
1155 // Stretching 5KHz samples to 22KHz:
1157 // 6KHz -> 22KHz: 22/6 repeats...
1162 samp2 = voice_rom[spos2++];
1167 samp2 = 128; // Kill channel 2 if done...
1169 else if (samp2 == 0x00) // RLE compression...
1171 sample2 += (float)voice_rom[spos2++] * sampleBase; // # of repeats
1175 sample2 += sampleBase;
1178 // Delta-X values were making the samples sound like crap...
1179 // start_samp2 += delta_x2;
1186 samp3 = sndp3[spos3++];
1188 if (spos3 == end_pos3)
1191 samp3 = 128; // Kill channel 3 if done...
1197 samp4 = sndp4[spos4++];
1199 if (spos4 == end_pos4)
1202 samp4 = 128; // Kill channel 4 if done...
1208 samp5 = sndp5[spos5++];
1210 if (spos5 == end_pos5)
1213 samp5 = 128; // Kill channel 5 if done...
1219 samp6 = sndp6[spos6++];
1221 if (spos6 == end_pos6)
1224 samp6 = 128; // Kill channel 6...
1229 sample = samp1 + samp2 + samp3 + samp4 + samp5 + samp6 - 640;
1231 // If it overflowed, clip it
1232 if (sample & 0xFF00)
1233 sample = (sample & 0x8000 ? 0x00 : 0xFF);
1235 buff[cnt++] = sample;