History

Pushed v1.07 code

- Bugfix: After deleting the very last vol/pan envelope point, the currently selected point wouldn't be properly set. This is actually a behavior/bug from real FT2, but I wanted to fix it anyway. - Bugfix: Attempting to add a vol/pan envelope point to a completely empty envelope would mess things up. Empty envelopes in an allocated instrument shouldn't happen, but it happens when loading certain non-FT2 XMs. - Bugfix: The envelope plotter could display garbage on envelopes with tick offsets above 324. Now it just cuts off at the end instead. Also yes, such envelopes can be made! OpenMPT, f.ex., has no 0..324 limit for envelope ticks in XM mode. - Bugfix: A couple of system request dialogs had the wrong button captions. (Yes/No instead of OK/Cancel). - When pressing Esc. and the song is unmodified/saved, you'll now get the classic joke quit dialogs from FT2 asking if you really want to quit. - Some minor optimizations and minor fixups. Nothing to write home about... - Windows 32-bit: This version now requires your CPU to have the SSE2 instruction set. Intel CPUs from around 2000 (AMD around 2003) and later have it. In other words, it's not worth my time trying to make the clone run on such old machines!

Olav Sørensen committed 6 years ago

Commit fe46cb41 parent 8eb89a132 files · +945 −731Browse files

Unified · Split

32 files
  1. .gitignore +2 −0
  2. src/ft2_about.c +8 −4
  3. src/ft2_audio.c +33 −25
  4. src/ft2_audio.h +1 −1
  5. src/ft2_config.c +10 −2
  6. src/ft2_diskop.c +1 −1
  7. src/ft2_edit.c +1 −1
  8. src/ft2_gui.c +16 −16
  9. src/ft2_header.h +4 −1
  10. src/ft2_inst_ed.c +89 −60
  11. src/ft2_keyboard.c +13 −7
  12. src/ft2_main.c +8 −0
  13. src/ft2_module_loader.c +50 −14
  14. src/ft2_module_loader.h +1 −0
  15. src/ft2_mouse.c +22 −12
  16. src/ft2_mouse.h +0 −1
  17. src/ft2_palette.c +5 −0
  18. src/ft2_palette.h +5 −0
  19. src/ft2_pattern_draw.c +439 −464
  20. src/ft2_pattern_draw.h +3 −2
  21. src/ft2_pattern_ed.c +26 −13
  22. src/ft2_pattern_ed.h +0 −1
  23. src/ft2_replayer.c +31 −36
  24. src/ft2_scopes.c +9 −5
  25. src/ft2_scrollbars.c +20 −1
  26. src/ft2_scrollbars.h +1 −0
  27. src/ft2_sysreqs.c +84 −27
  28. src/ft2_sysreqs.h +11 −4
  29. src/ft2_video.c +39 −25
  30. src/ft2_video.h +8 −7
  31. src/gfxdata/bmp/patternfonts.bmp +0 −0
  32. vs2019_project/ft2-clone/ft2-clone.vcxproj +6 −2
.gitignore+2−0
@@ -15,3 +15,5 @@ vs2019_project/.vs/ft2-clone/v16/.suo · 14 unmodified lines
15vs2019_project/ft2-clone/Release/ft2-clone.vcxproj.FileListAbsolute.txt15vs2019_project/ft2-clone/Release/ft2-clone.vcxproj.FileListAbsolute.txt
16vs2019_project/ft2-clone/x64/Debug/ft2-clone.vcxproj.FileListAbsolute.txt16vs2019_project/ft2-clone/x64/Debug/ft2-clone.vcxproj.FileListAbsolute.txt
17*.cod17*.cod
18vs2019_project/ft2-clone/Debug/ft2-clone.vcxproj.FileListAbsolute.txt
19*.opendb
src/ft2_about.c+8−4
@@ -7,7 +7,7 @@ · 6 unmodified lines
7 7
8// ported from original FT2 code8// ported from original FT2 code
9 9
10#define NUM_STARS 65010#define NUM_STARS 512
11#define ABOUT_SCREEN_W 62611#define ABOUT_SCREEN_W 626
12#define ABOUT_SCREEN_H 16712#define ABOUT_SCREEN_H 167
13#define FT2_LOGO_W 44913#define FT2_LOGO_W 449
@@ -231,6 +231,8 @@ void aboutFrame(void) · 217 unmodified lines
231 231
232void showAboutScreen(void) // called once when About screen is opened232void showAboutScreen(void) // called once when About screen is opened
233{233{
234#define TEXT_BORDER_COL 0x2E2E2E
235
234 const char *infoString = "Clone by Olav \"8bitbubsy\" S\025rensen - https://16-bits.org";236 const char *infoString = "Clone by Olav \"8bitbubsy\" S\025rensen - https://16-bits.org";
235 char verText[32];237 char verText[32];
236 uint16_t x, y;238 uint16_t x, y;
@@ -246,16 +248,18 @@ void showAboutScreen(void) // called once when About screen is opened · 9 unmodified lines
246 showPushButton(PB_EXIT_ABOUT);248 showPushButton(PB_EXIT_ABOUT);
247 249
248 blit32(91, 31, ft2Logo, FT2_LOGO_W, FT2_LOGO_H);250 blit32(91, 31, ft2Logo, FT2_LOGO_W, FT2_LOGO_H);
249 blit(146, 113, aboutText, ABOUT_TEXT_W, ABOUT_TEXT_H);251 blit(146, 113, aboutText, ABOUT_TEXT_W, ABOUT_TEXT_H);
252
253 setCustomPalColor(TEXT_BORDER_COL); // sets PAL_CUSTOM
250 254
251 x = 5 + (SCREEN_W - textWidth(infoString)) / 2;255 x = 5 + (SCREEN_W - textWidth(infoString)) / 2;
252 y = 147;256 y = 147;
253 textOutBorder(x, y, PAL_FORGRND, PAL_BUTTON2, infoString);257 textOutBorder(x, y, PAL_FORGRND, PAL_CUSTOM, infoString);
254 258
255 sprintf(verText, "v%s (compiled on %s)", PROG_VER_STR, __DATE__);259 sprintf(verText, "v%s (compiled on %s)", PROG_VER_STR, __DATE__);
256 x = ((3 + ABOUT_SCREEN_W) - textWidth(verText)) / 2;260 x = ((3 + ABOUT_SCREEN_W) - textWidth(verText)) / 2;
257 y = (3 + ABOUT_SCREEN_H) - ((FONT1_CHAR_H - 2) + 3);261 y = (3 + ABOUT_SCREEN_H) - ((FONT1_CHAR_H - 2) + 3);
258 textOutBorder(x, y, PAL_FORGRND, PAL_BUTTON2, verText);262 textOutBorder(x, y, PAL_FORGRND, PAL_CUSTOM, verText);
259 263
260 aboutInit();264 aboutInit();
261 265
src/ft2_audio.c+33−25
@@ -20,7 +20,7 @@ · 19 unmodified lines
20 20
21static int8_t pmpCountDiv, pmpChannels = 2;21static int8_t pmpCountDiv, pmpChannels = 2;
22static uint16_t smpBuffSize;22static uint16_t smpBuffSize;
23static int32_t masterVol, amp, oldAudioFreq, speedVal, pmpLeft, randSeed = INITIAL_DITHER_SEED;23static int32_t masterVol, masterAmp, oldAudioFreq, speedVal, pmpLeft, randSeed = INITIAL_DITHER_SEED;
24static uint32_t tickTimeLen, tickTimeLenFrac, oldSFrq, oldSFrqRev = 0xFFFFFFFF;24static uint32_t tickTimeLen, tickTimeLenFrac, oldSFrq, oldSFrqRev = 0xFFFFFFFF;
25static float fAudioAmpMul;25static float fAudioAmpMul;
26static voice_t voice[MAX_VOICES * 2];26static voice_t voice[MAX_VOICES * 2];
@@ -124,9 +124,9 @@ void setAudioAmp(int16_t ampFactor, int16_t master, bool bitDepth32Flag) · 97 unmodified lines
124 124
125 // calculate channel amp125 // calculate channel amp
126 126
127 if (amp != ampFactor)127 if (masterAmp != ampFactor)
128 {128 {
129 amp = ampFactor;129 masterAmp = ampFactor;
130 130
131 // make all channels update volume because of amp change131 // make all channels update volume because of amp change
132 for (uint32_t i = 0; i < song.antChn; i++)132 for (uint32_t i = 0; i < song.antChn; i++)
@@ -164,10 +164,18 @@ void setSpeed(uint16_t bpm) · 31 unmodified lines
164 // number of samples per tick -> tick length for performance counter164 // number of samples per tick -> tick length for performance counter
165 dFrac = modf(speedVal * audio.dSpeedValMul, &dInt);165 dFrac = modf(speedVal * audio.dSpeedValMul, &dInt);
166 166
167 // integer part167 /* - integer part -
168 tickTimeLen = (uint32_t)dInt;168 ** Cast to int32_t so that the compiler will use fast SSE2 float->int instructions.
169 169 ** This result won't be above 2^31, so this is safe.
170 // fractional part (scaled to 0..2^32-1)170 */
171 tickTimeLen = (int32_t)dInt;
172
173 /* - fractional part (scaled to 0..2^32-1) -
174 ** We have to resort to slow float->int conversion here because the result
175 ** can be above 2^31. In 64-bit mode, this will still use a fast SSE2 instruction.
176 ** Anyhow, this function won't be called that many times a second in worst case,
177 ** so it's not a big issue at all.
178 */
171 dFrac *= UINT32_MAX;179 dFrac *= UINT32_MAX;
172 tickTimeLenFrac = (uint32_t)(dFrac + 0.5);180 tickTimeLenFrac = (uint32_t)(dFrac + 0.5);
173 }181 }
@@ -194,7 +202,7 @@ static inline void voiceUpdateVolumes(uint8_t i, uint8_t status) · 20 unmodified lines
194 202
195 v = &voice[i];203 v = &voice[i];
196 204
197 volL = v->SVol * amp; // 0..2047 * 1..32 = 0..65504205 volL = v->SVol * masterAmp; // 0..2047 * 1..32 = 0..65504
198 206
199 // (0..65504 * 0..65536) >> 4 = 0..268304384207 // (0..65504 * 0..65536) >> 4 = 0..268304384
200 volR = ((uint32_t)volL * panningTab[v->SPan]) >> 4;208 volR = ((uint32_t)volL * panningTab[v->SPan]) >> 4;
@@ -331,7 +339,6 @@ void mix_SaveIPVolumes(void) // for volume ramping · 130 unmodified lines
331void mix_UpdateChannelVolPanFrq(void)339void mix_UpdateChannelVolPanFrq(void)
332{340{
333 uint8_t status;341 uint8_t status;
334 uint16_t vol;
335 stmTyp *ch;342 stmTyp *ch;
336 voice_t *v;343 voice_t *v;
337 344
@@ -347,13 +354,7 @@ void mix_UpdateChannelVolPanFrq(void) · 9 unmodified lines
347 354
348 // volume change355 // volume change
349 if (status & IS_Vol)356 if (status & IS_Vol)
350 {357 v->SVol = ch->finalVol;
351 vol = ch->finalVol;
352 if (vol > 0) // yes, FT2 does this!
353 vol--;
354
355 v->SVol = vol;
356 }
357 358
358 // panning change359 // panning change
359 if (status & IS_Pan)360 if (status & IS_Pan)
@@ -1063,28 +1064,35 @@ static bool setupAudioBuffers(void) · 703 unmodified lines
1063{1064{
1064 const uint32_t sampleSize = sizeof (int32_t);1065 const uint32_t sampleSize = sizeof (int32_t);
1065 1066
1066 audio.mixBufferL = (int32_t *)malloc(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize);1067 audio.mixBufferLUnaligned = (int32_t *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
1067 audio.mixBufferR = (int32_t *)malloc(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize);1068 audio.mixBufferRUnaligned = (int32_t *)MALLOC_PAD(MAX_WAV_RENDER_SAMPLES_PER_TICK * sampleSize, 256);
1068 1069
1069 if (audio.mixBufferL == NULL || audio.mixBufferR == NULL)1070 if (audio.mixBufferLUnaligned == NULL || audio.mixBufferRUnaligned == NULL)
1070 return false;1071 return false;
1071 1072
1073 // make aligned main pointers
1074 audio.mixBufferL = (int32_t *)ALIGN_PTR(audio.mixBufferLUnaligned, 256);
1075 audio.mixBufferR = (int32_t *)ALIGN_PTR(audio.mixBufferRUnaligned, 256);
1076
1072 return true;1077 return true;
1073}1078}
1074 1079
1075static void freeAudioBuffers(void)1080static void freeAudioBuffers(void)
1076{1081{
1077 if (audio.mixBufferL != NULL)1082 if (audio.mixBufferLUnaligned != NULL)
1078 {1083 {
1079 free(audio.mixBufferL);1084 free(audio.mixBufferLUnaligned);
1080 audio.mixBufferL = NULL;1085 audio.mixBufferLUnaligned = NULL;
1081 }1086 }
1082 1087
1083 if (audio.mixBufferR != NULL)1088 if (audio.mixBufferRUnaligned != NULL)
1084 {1089 {
1085 free(audio.mixBufferR);1090 free(audio.mixBufferRUnaligned);
1086 audio.mixBufferR = NULL;1091 audio.mixBufferRUnaligned = NULL;
1087 }1092 }
1093
1094 audio.mixBufferL = NULL;
1095 audio.mixBufferR = NULL;
1088}1096}
1089 1097
1090void updateSendAudSamplesRoutine(bool lockMixer)1098void updateSendAudSamplesRoutine(bool lockMixer)
src/ft2_audio.h+1−1
@@ -26,7 +26,7 @@ struct audio_t · 25 unmodified lines
26 volatile bool locked, resetSyncTickTimeFlag, volumeRampingFlag, interpolationFlag;26 volatile bool locked, resetSyncTickTimeFlag, volumeRampingFlag, interpolationFlag;
27 bool linearFreqTable, rescanAudioDevicesSupported;27 bool linearFreqTable, rescanAudioDevicesSupported;
28 int32_t inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;28 int32_t inputDeviceNum, outputDeviceNum, lastWorkingAudioFreq, lastWorkingAudioBits;
29 int32_t quickVolSizeVal, *mixBufferL, *mixBufferR;29 int32_t quickVolSizeVal, *mixBufferL, *mixBufferR, *mixBufferLUnaligned, *mixBufferRUnaligned;
30 uint32_t freq;30 uint32_t freq;
31 uint32_t audLatencyPerfValInt, audLatencyPerfValFrac;31 uint32_t audLatencyPerfValInt, audLatencyPerfValFrac;
32 uint64_t tickTime64, tickTime64Frac;32 uint64_t tickTime64, tickTime64Frac;
src/ft2_config.c+10−2
@@ -29,6 +29,7 @@ · 28 unmodified lines
29#include "ft2_midi.h"29#include "ft2_midi.h"
30#include "ft2_gfxdata.h"30#include "ft2_gfxdata.h"
31#include "ft2_palette.h"31#include "ft2_palette.h"
32#include "ft2_pattern_draw.h"
32 33
33// defined at the bottom of this file34// defined at the bottom of this file
34extern const uint8_t defConfigData[CONFIG_FILE_SIZE];35extern const uint8_t defConfigData[CONFIG_FILE_SIZE];
@@ -190,6 +191,7 @@ static void loadConfigFromBuffer(uint8_t defaults) · 155 unmodified lines
190 changeBadgeType(config.id_TritonProd);191 changeBadgeType(config.id_TritonProd);
191 editor.ui.maxVisibleChannels = (uint8_t)(2 + ((config.ptnMaxChannels + 1) * 2));192 editor.ui.maxVisibleChannels = (uint8_t)(2 + ((config.ptnMaxChannels + 1) * 2));
192 setPal16(palTable[config.cfg_StdPalNr], true);193 setPal16(palTable[config.cfg_StdPalNr], true);
194 updatePattFontPtrs();
193 195
194 unlockMixerCallback();196 unlockMixerCallback();
195}197}
@@ -813,8 +815,10 @@ void setConfigIORadioButtonStates(void) // accessed by other .c files · 617 unmodified lines
813 uncheckRadioButtonGroup(RB_GROUP_CONFIG_SOUND_BUFF_SIZE);815 uncheckRadioButtonGroup(RB_GROUP_CONFIG_SOUND_BUFF_SIZE);
814 816
815 tmpID = RB_CONFIG_SBS_1024;817 tmpID = RB_CONFIG_SBS_1024;
816 if (config.specialFlags & BUFFSIZE_512) tmpID = RB_CONFIG_SBS_512;818 if (config.specialFlags & BUFFSIZE_512)
817 else if (config.specialFlags & BUFFSIZE_2048) tmpID = RB_CONFIG_SBS_2048;819 tmpID = RB_CONFIG_SBS_512;
820 else if (config.specialFlags & BUFFSIZE_2048)
821 tmpID = RB_CONFIG_SBS_2048;
818 822
819 radioButtons[tmpID].state = RADIOBUTTON_CHECKED;823 radioButtons[tmpID].state = RADIOBUTTON_CHECKED;
820 824
@@ -1873,6 +1877,7 @@ void rbConfigFontCapitals(void) · 1052 unmodified lines
1873{1877{
1874 config.ptnFont = PATT_FONT_CAPITALS;1878 config.ptnFont = PATT_FONT_CAPITALS;
1875 checkRadioButton(RB_CONFIG_FONT_CAPITALS);1879 checkRadioButton(RB_CONFIG_FONT_CAPITALS);
1880 updatePattFontPtrs();
1876 redrawPatternEditor();1881 redrawPatternEditor();
1877}1882}
1878 1883
@@ -1880,6 +1885,7 @@ void rbConfigFontLowerCase(void) · 1 unmodified line
1880{1885{
1881 config.ptnFont = PATT_FONT_LOWERCASE;1886 config.ptnFont = PATT_FONT_LOWERCASE;
1882 checkRadioButton(RB_CONFIG_FONT_LOWERCASE);1887 checkRadioButton(RB_CONFIG_FONT_LOWERCASE);
1888 updatePattFontPtrs();
1883 redrawPatternEditor();1889 redrawPatternEditor();
1884}1890}
1885 1891
@@ -1887,6 +1893,7 @@ void rbConfigFontFuture(void) · 1 unmodified line
1887{1893{
1888 config.ptnFont = PATT_FONT_FUTURE;1894 config.ptnFont = PATT_FONT_FUTURE;
1889 checkRadioButton(RB_CONFIG_FONT_FUTURE);1895 checkRadioButton(RB_CONFIG_FONT_FUTURE);
1896 updatePattFontPtrs();
1890 redrawPatternEditor();1897 redrawPatternEditor();
1891}1898}
1892 1899
@@ -1894,6 +1901,7 @@ void rbConfigFontBold(void) · 1 unmodified line
1894{1901{
1895 config.ptnFont = PATT_FONT_BOLD;1902 config.ptnFont = PATT_FONT_BOLD;
1896 checkRadioButton(RB_CONFIG_FONT_BOLD);1903 checkRadioButton(RB_CONFIG_FONT_BOLD);
1904 updatePattFontPtrs();
1897 redrawPatternEditor();1905 redrawPatternEditor();
1898}1906}
1899 1907
src/ft2_diskop.c+1−1
@@ -1089,7 +1089,7 @@ static void fileListPressed(int32_t index) · 1088 unmodified lines
1089 // in case of UTF8 -> CP437 encoding failure, there can be question marks. Remove them...1089 // in case of UTF8 -> CP437 encoding failure, there can be question marks. Remove them...
1090 removeQuestionmarksFromString(FReq_NameTemp);1090 removeQuestionmarksFromString(FReq_NameTemp);
1091 1091
1092 if (inputBox(2, dirEntry->isDir ? "Enter new directory name:" : "Enter new filename:", FReq_NameTemp, PATH_MAX - 1) == 1)1092 if (inputBox(1, dirEntry->isDir ? "Enter new directory name:" : "Enter new filename:", FReq_NameTemp, PATH_MAX - 1) == 1)
1093 {1093 {
1094 if ((FReq_NameTemp == NULL) || (FReq_NameTemp[0] == '\0'))1094 if ((FReq_NameTemp == NULL) || (FReq_NameTemp[0] == '\0'))
1095 {1095 {
src/ft2_edit.c+1−1
@@ -1858,7 +1858,7 @@ static bool askForScaleFade(char *msg) · 1857 unmodified lines
1858 uint8_t err;1858 uint8_t err;
1859 1859
1860 sprintf(volstr, "%0.2f,%0.2f", dVolScaleFK1, dVolScaleFK2);1860 sprintf(volstr, "%0.2f,%0.2f", dVolScaleFK1, dVolScaleFK2);
1861 if (inputBox(2, msg, volstr, sizeof (volstr) - 1) != 1)1861 if (inputBox(1, msg, volstr, sizeof (volstr) - 1) != 1)
1862 return false;1862 return false;
1863 1863
1864 err = false;1864 err = false;
src/ft2_gui.c+16−16
@@ -734,22 +734,22 @@ void fillRect(uint16_t xPos, uint16_t yPos, uint16_t w, uint16_t h, uint8_t pale · 733 unmodified lines
734 734
735void blit32(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, uint16_t h)735void blit32(uint16_t xPos, uint16_t yPos, const uint32_t* srcPtr, uint16_t w, uint16_t h)
736{736{
737 uint32_t* dstPtr;737 uint32_t* dstPtr;
738 738
739 assert(srcPtr != NULL && xPos < SCREEN_W && yPos < SCREEN_H && (xPos + w) <= SCREEN_W && (yPos + h) <= SCREEN_H);739 assert(srcPtr != NULL && xPos < SCREEN_W && yPos < SCREEN_H && (xPos + w) <= SCREEN_W && (yPos + h) <= SCREEN_H);
740 740
741 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];741 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
742 for (uint32_t y = 0; y < h; y++)742 for (uint32_t y = 0; y < h; y++)
743 {743 {
744 for (uint32_t x = 0; x < w; x++)744 for (uint32_t x = 0; x < w; x++)
745 {745 {
746 if (srcPtr[x] != 0x00FF00)746 if (srcPtr[x] != 0x00FF00)
747 dstPtr[x] = srcPtr[x] | 0xFF000000; // most significant 8 bits = palette number. 0xFF because no true palette747 dstPtr[x] = srcPtr[x] | 0xFF000000; // most significant 8 bits = palette number. 0xFF because no true palette
748 }748 }
749 749
750 srcPtr += w;750 srcPtr += w;
751 dstPtr += SCREEN_W;751 dstPtr += SCREEN_W;
752 }752 }
753}753}
754 754
755void blit(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h)755void blit(uint16_t xPos, uint16_t yPos, const uint8_t *srcPtr, uint16_t w, uint16_t h)
src/ft2_header.h+4−1
@@ -12,7 +12,7 @@ · 11 unmodified lines
12#endif12#endif
13#include "ft2_replayer.h"13#include "ft2_replayer.h"
14 14
15#define PROG_VER_STR "1.06"15#define PROG_VER_STR "1.07"
16 16
17// do NOT change these! It will only mess things up...17// do NOT change these! It will only mess things up...
18 18
@@ -55,6 +55,9 @@ · 36 unmodified lines
55// fast 32-bit -> 16-bit clamp55// fast 32-bit -> 16-bit clamp
56#define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31)56#define CLAMP16(i) if ((int16_t)(i) != i) i = 0x7FFF ^ (i >> 31)
57 57
58#define ALIGN_PTR(p, x) (((uintptr_t)(p) + ((x)-1)) & ~((x)-1))
59#define MALLOC_PAD(size, pad) (malloc((size) + (pad)))
60
58#define SWAP16(value) \61#define SWAP16(value) \
59( \62( \
60 (((uint16_t)((value) & 0x00FF)) << 8) | \63 (((uint16_t)((value) & 0x00FF)) << 8) | \
src/ft2_inst_ed.c+89−60
@@ -788,24 +788,28 @@ void relToneDown(void) · 787 unmodified lines
788 788
789void volEnvAdd(void)789void volEnvAdd(void)
790{790{
791 int16_t i;791 int16_t i, ant;
792 instrTyp *ins = instr[editor.curInstr];792 instrTyp *ins = instr[editor.curInstr];
793 793
794 if (ins == NULL || editor.curInstr == 0 || ins->envVPAnt >= 12)794 ant = ins->envVPAnt;
795 if (ins == NULL || editor.curInstr == 0 || ant >= 12)
795 return;796 return;
796 797
797 i = (int16_t)editor.currVolEnvPoint;798 i = (int16_t)editor.currVolEnvPoint;
799 if (i < 0 || i >= ant)
800 {
801 i = ant-1;
802 if (i < 0)
803 i = 0;
804 }
798 805
799 if (i < 0 || i >= ins->envVPAnt)806 if (i < ant-1 && ins->envVP[i+1][0]-ins->envVP[i][0] < 2)
800 i = ins->envVPAnt - 1;
801
802 if (i < ins->envVPAnt-1 && ins->envVP[i+1][0]-ins->envVP[i][0] < 2)
803 return;807 return;
804 808
805 if (ins->envVP[i][0] >= 323)809 if (ins->envVP[i][0] >= 323)
806 return;810 return;
807 811
808 for (int16_t j = ins->envVPAnt; j > i; j--)812 for (int16_t j = ant; j > i; j--)
809 {813 {
810 ins->envVP[j][0] = ins->envVP[j-1][0];814 ins->envVP[j][0] = ins->envVP[j-1][0];
811 ins->envVP[j][1] = ins->envVP[j-1][1];815 ins->envVP[j][1] = ins->envVP[j-1][1];
@@ -815,7 +819,7 @@ void volEnvAdd(void) · 3 unmodified lines
815 if (ins->envVRepS > i) { ins->envVRepS++; drawVolEnvRepS(); }819 if (ins->envVRepS > i) { ins->envVRepS++; drawVolEnvRepS(); }
816 if (ins->envVRepE > i) { ins->envVRepE++; drawVolEnvRepE(); }820 if (ins->envVRepE > i) { ins->envVRepE++; drawVolEnvRepE(); }
817 821
818 if (i < ins->envVPAnt-1)822 if (i < ant-1)
819 {823 {
820 ins->envVP[i+1][0] = (ins->envVP[i][0] + ins->envVP[i+2][0]) / 2;824 ins->envVP[i+1][0] = (ins->envVP[i][0] + ins->envVP[i+2][0]) / 2;
821 ins->envVP[i+1][1] = (ins->envVP[i][1] + ins->envVP[i+2][1]) / 2;825 ins->envVP[i+1][1] = (ins->envVP[i][1] + ins->envVP[i+2][1]) / 2;
@@ -840,7 +844,6 @@ void volEnvDel(void) · 18 unmodified lines
840 uint8_t drawSust, drawRepS, drawRepE;844 uint8_t drawSust, drawRepS, drawRepE;
841 int16_t i;845 int16_t i;
842 instrTyp *ins = instr[editor.curInstr];846 instrTyp *ins = instr[editor.curInstr];
843
844 if (ins == NULL || editor.curInstr == 0 || ins->envVPAnt <= 2)847 if (ins == NULL || editor.curInstr == 0 || ins->envVPAnt <= 2)
845 return;848 return;
846 849
@@ -873,6 +876,11 @@ void volEnvDel(void) · 26 unmodified lines
873 if (drawRepS) drawVolEnvRepS();876 if (drawRepS) drawVolEnvRepS();
874 if (drawRepE) drawVolEnvRepE();877 if (drawRepE) drawVolEnvRepE();
875 878
879 if (ins->envVPAnt == 0)
880 editor.currVolEnvPoint = 0;
881 else if (editor.currVolEnvPoint >= ins->envVPAnt)
882 editor.currVolEnvPoint = ins->envVPAnt-1;
883
876 updateVolEnv = true;884 updateVolEnv = true;
877 setSongModifiedFlag();885 setSongModifiedFlag();
878}886}
@@ -880,7 +888,6 @@ void volEnvDel(void) · 1 unmodified line
880void volEnvSusUp(void)888void volEnvSusUp(void)
881{889{
882 instrTyp *ins = instr[editor.curInstr];890 instrTyp *ins = instr[editor.curInstr];
883
884 if (ins == NULL || editor.curInstr == 0)891 if (ins == NULL || editor.curInstr == 0)
885 return;892 return;
886 893
@@ -896,7 +903,6 @@ void volEnvSusUp(void) · 9 unmodified lines
896void volEnvSusDown(void)903void volEnvSusDown(void)
897{904{
898 instrTyp *ins = instr[editor.curInstr];905 instrTyp *ins = instr[editor.curInstr];
899
900 if (ins == NULL || editor.curInstr == 0)906 if (ins == NULL || editor.curInstr == 0)
901 return;907 return;
902 908
@@ -912,7 +918,6 @@ void volEnvSusDown(void) · 9 unmodified lines
912void volEnvRepSUp(void)918void volEnvRepSUp(void)
913{919{
914 instrTyp *ins = instr[editor.curInstr];920 instrTyp *ins = instr[editor.curInstr];
915
916 if (ins == NULL || editor.curInstr == 0)921 if (ins == NULL || editor.curInstr == 0)
917 return;922 return;
918 923
@@ -928,7 +933,6 @@ void volEnvRepSUp(void) · 9 unmodified lines
928void volEnvRepSDown(void)933void volEnvRepSDown(void)
929{934{
930 instrTyp *ins = instr[editor.curInstr];935 instrTyp *ins = instr[editor.curInstr];
931
932 if (ins == NULL || editor.curInstr == 0)936 if (ins == NULL || editor.curInstr == 0)
933 return;937 return;
934 938
@@ -944,7 +948,6 @@ void volEnvRepSDown(void) · 9 unmodified lines
944void volEnvRepEUp(void)948void volEnvRepEUp(void)
945{949{
946 instrTyp *ins = instr[editor.curInstr];950 instrTyp *ins = instr[editor.curInstr];
947
948 if (ins == NULL || editor.curInstr == 0)951 if (ins == NULL || editor.curInstr == 0)
949 return;952 return;
950 953
@@ -960,7 +963,6 @@ void volEnvRepEUp(void) · 9 unmodified lines
960void volEnvRepEDown(void)963void volEnvRepEDown(void)
961{964{
962 instrTyp *ins = instr[editor.curInstr];965 instrTyp *ins = instr[editor.curInstr];
963
964 if (ins == NULL || editor.curInstr == 0)966 if (ins == NULL || editor.curInstr == 0)
965 return;967 return;
966 968
@@ -975,24 +977,28 @@ void volEnvRepEDown(void) · 8 unmodified lines
975 977
976void panEnvAdd(void)978void panEnvAdd(void)
977{979{
978 int16_t i;980 int16_t i, ant;
979 instrTyp *ins = instr[editor.curInstr];981 instrTyp *ins = instr[editor.curInstr];
980 982
981 if (ins == NULL || editor.curInstr == 0 || ins->envPPAnt >= 12)983 ant = ins->envPPAnt;
984 if (ins == NULL || editor.curInstr == 0 || ant >= 12)
982 return;985 return;
983 986
984 i = (int16_t)editor.currPanEnvPoint;987 i = (int16_t)editor.currPanEnvPoint;
988 if (i < 0 || i >= ant)
989 {
990 i = ant-1;
991 if (i < 0)
992 i = 0;
993 }
985 994
986 if (i < 0 || i >= ins->envPPAnt)995 if (i < ant-1 && ins->envPP[i+1][0]-ins->envPP[i][0] < 2)
987 i = ins->envPPAnt - 1;
988
989 if (i < ins->envPPAnt-1 && ins->envPP[i+1][0]-ins->envPP[i][0] < 2)
990 return;996 return;
991 997
992 if (ins->envPP[i][0] >= 323)998 if (ins->envPP[i][0] >= 323)
993 return;999 return;
994 1000
995 for (int16_t j = ins->envPPAnt; j > i; j--)1001 for (int16_t j = ant; j > i; j--)
996 {1002 {
997 ins->envPP[j][0] = ins->envPP[j-1][0];1003 ins->envPP[j][0] = ins->envPP[j-1][0];
998 ins->envPP[j][1] = ins->envPP[j-1][1];1004 ins->envPP[j][1] = ins->envPP[j-1][1];
@@ -1002,7 +1008,7 @@ void panEnvAdd(void) · 3 unmodified lines
1002 if (ins->envPRepS > i) { ins->envPRepS++; drawPanEnvRepS(); }1008 if (ins->envPRepS > i) { ins->envPRepS++; drawPanEnvRepS(); }
1003 if (ins->envPRepE > i) { ins->envPRepE++; drawPanEnvRepE(); }1009 if (ins->envPRepE > i) { ins->envPRepE++; drawPanEnvRepE(); }
1004 1010
1005 if (i < ins->envPPAnt-1)1011 if (i < ant-1)
1006 {1012 {
1007 ins->envPP[i+1][0] = (ins->envPP[i][0] + ins->envPP[i+2][0]) / 2;1013 ins->envPP[i+1][0] = (ins->envPP[i][0] + ins->envPP[i+2][0]) / 2;
1008 ins->envPP[i+1][1] = (ins->envPP[i][1] + ins->envPP[i+2][1]) / 2;1014 ins->envPP[i+1][1] = (ins->envPP[i][1] + ins->envPP[i+2][1]) / 2;
@@ -1027,7 +1033,6 @@ void panEnvDel(void) · 18 unmodified lines
1027 uint8_t drawSust, drawRepS, drawRepE;1033 uint8_t drawSust, drawRepS, drawRepE;
1028 int16_t i;1034 int16_t i;
1029 instrTyp *ins = instr[editor.curInstr];1035 instrTyp *ins = instr[editor.curInstr];
1030
1031 if (ins == NULL || editor.curInstr == 0 || ins->envPPAnt <= 2)1036 if (ins == NULL || editor.curInstr == 0 || ins->envPPAnt <= 2)
1032 return;1037 return;
1033 1038
@@ -1060,6 +1065,11 @@ void panEnvDel(void) · 26 unmodified lines
1060 if (drawRepS) drawPanEnvRepS();1065 if (drawRepS) drawPanEnvRepS();
1061 if (drawRepE) drawPanEnvRepE();1066 if (drawRepE) drawPanEnvRepE();
1062 1067
1068 if (ins->envPPAnt == 0)
1069 editor.currPanEnvPoint = 0;
1070 else if (editor.currPanEnvPoint >= ins->envPPAnt)
1071 editor.currPanEnvPoint = ins->envPPAnt-1;
1072
1063 updatePanEnv = true;1073 updatePanEnv = true;
1064 setSongModifiedFlag();1074 setSongModifiedFlag();
1065}1075}
@@ -1067,7 +1077,6 @@ void panEnvDel(void) · 1 unmodified line
1067void panEnvSusUp(void)1077void panEnvSusUp(void)
1068{1078{
1069 instrTyp *ins = instr[editor.curInstr];1079 instrTyp *ins = instr[editor.curInstr];
1070
1071 if (ins == NULL || editor.curInstr == 0)1080 if (ins == NULL || editor.curInstr == 0)
1072 return;1081 return;
1073 1082
@@ -1083,7 +1092,6 @@ void panEnvSusUp(void) · 9 unmodified lines
1083void panEnvSusDown(void)1092void panEnvSusDown(void)
1084{1093{
1085 instrTyp *ins = instr[editor.curInstr];1094 instrTyp *ins = instr[editor.curInstr];
1086
1087 if (ins == NULL || editor.curInstr == 0)1095 if (ins == NULL || editor.curInstr == 0)
1088 return;1096 return;
1089 1097
@@ -1099,7 +1107,6 @@ void panEnvSusDown(void) · 9 unmodified lines
1099void panEnvRepSUp(void)1107void panEnvRepSUp(void)
1100{1108{
1101 instrTyp *ins = instr[editor.curInstr];1109 instrTyp *ins = instr[editor.curInstr];
1102
1103 if (ins == NULL || editor.curInstr == 0)1110 if (ins == NULL || editor.curInstr == 0)
1104 return;1111 return;
1105 1112
@@ -1115,7 +1122,6 @@ void panEnvRepSUp(void) · 9 unmodified lines
1115void panEnvRepSDown(void)1122void panEnvRepSDown(void)
1116{1123{
1117 instrTyp *ins = instr[editor.curInstr];1124 instrTyp *ins = instr[editor.curInstr];
1118
1119 if (ins == NULL || editor.curInstr == 0)1125 if (ins == NULL || editor.curInstr == 0)
1120 return;1126 return;
1121 1127
@@ -1131,7 +1137,6 @@ void panEnvRepSDown(void) · 9 unmodified lines
1131void panEnvRepEUp(void)1137void panEnvRepEUp(void)
1132{1138{
1133 instrTyp *ins = instr[editor.curInstr];1139 instrTyp *ins = instr[editor.curInstr];
1134
1135 if (ins == NULL || editor.curInstr == 0)1140 if (ins == NULL || editor.curInstr == 0)
1136 return;1141 return;
1137 1142
@@ -1147,7 +1152,6 @@ void panEnvRepEUp(void) · 9 unmodified lines
1147void panEnvRepEDown(void)1152void panEnvRepEDown(void)
1148{1153{
1149 instrTyp *ins = instr[editor.curInstr];1154 instrTyp *ins = instr[editor.curInstr];
1150
1151 if (ins == NULL || editor.curInstr == 0)1155 if (ins == NULL || editor.curInstr == 0)
1152 return;1156 return;
1153 1157
@@ -1975,7 +1979,7 @@ static void writeEnvelope(int32_t nr) · 821 unmodified lines
1975 1979
1976 // draw center line on pan envelope1980 // draw center line on pan envelope
1977 if (nr == 1)1981 if (nr == 1)
1978 envelopeLine(nr, 8, 33, 335, 33, PAL_BLCKMRK);1982 envelopeLine(nr, 8, 33, 332, 33, PAL_BLCKMRK);
1979 1983
1980 if (ins == NULL)1984 if (ins == NULL)
1981 return;1985 return;
@@ -2035,38 +2039,48 @@ static void writeEnvelope(int32_t nr) · 53 unmodified lines
2035 // draw envelope2039 // draw envelope
2036 for (i = 0; i < nd; i++)2040 for (i = 0; i < nd; i++)
2037 {2041 {
2038 x = curEnvP[i][0]; x = CLAMP(x, 0, 340);2042 x = curEnvP[i][0];
2039 y = curEnvP[i][1]; y = CLAMP(y, 0, 64);2043 y = curEnvP[i][1];
2040 2044
2041 envelopeDot(nr, 7 + x, 64 - y);2045 x = CLAMP(x, 0, 324);
2046
2047 if (nr == 0)
2048 y = CLAMP(y, 0, 64);
2049 else
2050 y = CLAMP(y, 0, 63);
2042 2051
2043 // draw "envelope selected" data2052 if ((uint16_t)curEnvP[i][0] <= 324)
2044 if (i == selected)
2045 {2053 {
2046 envelopeLine(nr, 5 + x, 64 - y, 5 + x, 66 - y, PAL_BLCKTXT);2054 envelopeDot(nr, 7 + x, 64 - y);
2047 envelopeLine(nr, 11 + x, 64 - y, 11 + x, 66 - y, PAL_BLCKTXT);
2048 envelopePixel(nr, 5, 65 - y, PAL_BLCKTXT);
2049 envelopePixel(nr, 8 + x, 65, PAL_BLCKTXT);
2050 }
2051 2055
2052 // draw loop start marker2056 // draw "envelope selected" data
2053 if (i == ls)2057 if (i == selected)
2054 {2058 {
2055 envelopeLine(nr, x + 6, 1, x + 10, 1, PAL_PATTEXT);2059 envelopeLine(nr, 5 + x, 64 - y, 5 + x, 66 - y, PAL_BLCKTXT);
2056 envelopeLine(nr, x + 7, 2, x + 9, 2, PAL_PATTEXT);2060 envelopeLine(nr, 11 + x, 64 - y, 11 + x, 66 - y, PAL_BLCKTXT);
2057 envelopeVertLine(nr, x + 8, 1, PAL_PATTEXT);2061 envelopePixel(nr, 5, 65 - y, PAL_BLCKTXT);
2058 }2062 envelopePixel(nr, 8 + x, 65, PAL_BLCKTXT);
2063 }
2059 2064
2060 // draw sustain marker2065 // draw loop start marker
2061 if (i == sp)2066 if (i == ls)
2062 envelopeVertLine(nr, x + 8, 1, PAL_BLCKTXT);2067 {
2068 envelopeLine(nr, x + 6, 1, x + 10, 1, PAL_PATTEXT);
2069 envelopeLine(nr, x + 7, 2, x + 9, 2, PAL_PATTEXT);
2070 envelopeVertLine(nr, x + 8, 1, PAL_PATTEXT);
2071 }
2063 2072
2064 // draw loop end marker2073 // draw sustain marker
2065 if (i == le)2074 if (i == sp)
2066 {2075 envelopeVertLine(nr, x + 8, 1, PAL_BLCKTXT);
2067 envelopeLine(nr, x + 6, 65, x + 10, 65, PAL_PATTEXT);2076
2068 envelopeLine(nr, x + 7, 64, x + 9, 64, PAL_PATTEXT);2077 // draw loop end marker
2069 envelopeVertLine(nr, x + 8, 1, PAL_PATTEXT);2078 if (i == le)
2079 {
2080 envelopeLine(nr, x + 6, 65, x + 10, 65, PAL_PATTEXT);
2081 envelopeLine(nr, x + 7, 64, x + 9, 64, PAL_PATTEXT);
2082 envelopeVertLine(nr, x + 8, 1, PAL_PATTEXT);
2083 }
2070 }2084 }
2071 2085
2072 // draw envelope line2086 // draw envelope line
@@ -2465,7 +2479,7 @@ bool testInstrVolEnvMouseDown(bool mouseButtonDown) · 392 unmodified lines
2465 if (editor.currVolEnvPoint == ant-1)2479 if (editor.currVolEnvPoint == ant-1)
2466 {2480 {
2467 minX = ins->envVP[editor.currVolEnvPoint-1][0] + 1;2481 minX = ins->envVP[editor.currVolEnvPoint-1][0] + 1;
2468 maxX = 325;2482 maxX = 324;
2469 }2483 }
2470 else2484 else
2471 {2485 {
@@ -2473,6 +2487,9 @@ bool testInstrVolEnvMouseDown(bool mouseButtonDown) · 1 unmodified line
2473 maxX = ins->envVP[editor.currVolEnvPoint+1][0] - 1;2487 maxX = ins->envVP[editor.currVolEnvPoint+1][0] - 1;
2474 }2488 }
2475 2489
2490 minX = CLAMP(minX, 0, 324);
2491 maxX = CLAMP(maxX, 0, 324);
2492
2476 ins->envVP[editor.currVolEnvPoint][0] = (int16_t)(CLAMP(mx, minX, maxX));2493 ins->envVP[editor.currVolEnvPoint][0] = (int16_t)(CLAMP(mx, minX, maxX));
2477 updateVolEnv = true;2494 updateVolEnv = true;
2478 2495
@@ -2561,7 +2578,7 @@ bool testInstrPanEnvMouseDown(bool mouseButtonDown) · 82 unmodified lines
2561 if (editor.currPanEnvPoint == ant-1)2578 if (editor.currPanEnvPoint == ant-1)
2562 {2579 {
2563 minX = ins->envPP[editor.currPanEnvPoint-1][0] + 1;2580 minX = ins->envPP[editor.currPanEnvPoint-1][0] + 1;
2564 maxX = 325;2581 maxX = 324;
2565 }2582 }
2566 else2583 else
2567 {2584 {
@@ -2569,6 +2586,9 @@ bool testInstrPanEnvMouseDown(bool mouseButtonDown) · 1 unmodified line
2569 maxX = ins->envPP[editor.currPanEnvPoint+1][0] - 1;2586 maxX = ins->envPP[editor.currPanEnvPoint+1][0] - 1;
2570 }2587 }
2571 2588
2589 minX = CLAMP(minX, 0, 324);
2590 maxX = CLAMP(maxX, 0, 324);
2591
2572 ins->envPP[editor.currPanEnvPoint][0] = (int16_t)(CLAMP(mx, minX, maxX));2592 ins->envPP[editor.currPanEnvPoint][0] = (int16_t)(CLAMP(mx, minX, maxX));
2573 updatePanEnv = true;2593 updatePanEnv = true;
2574 2594
@@ -3102,7 +3122,7 @@ static int32_t SDLCALL loadInstrThread(void *ptr) · 527 unmodified lines
3102 goto loadDone;3122 goto loadDone;
3103 }3123 }
3104 3124
3105 // sanitize stuff for malicious instruments3125 // sanitize stuff for broken/unsupported instruments
3106 ih.midiProgram = CLAMP(ih.midiProgram, 0, 127);3126 ih.midiProgram = CLAMP(ih.midiProgram, 0, 127);
3107 ih.midiBend = CLAMP(ih.midiBend, 0, 36);3127 ih.midiBend = CLAMP(ih.midiBend, 0, 36);
3108 3128
@@ -3127,6 +3147,15 @@ static int32_t SDLCALL loadInstrThread(void *ptr) · 18 unmodified lines
3127 if (ih.envPRepS > 11) ih.envPRepS = 11;3147 if (ih.envPRepS > 11) ih.envPRepS = 11;
3128 if (ih.envPRepE > 11) ih.envPRepE = 11;3148 if (ih.envPRepE > 11) ih.envPRepE = 11;
3129 if (ih.envPSust > 11) ih.envPSust = 11;3149 if (ih.envPSust > 11) ih.envPSust = 11;
3150
3151 for (int16_t i = 0; i < 12; i++)
3152 {
3153 if ((uint16_t)ih.envVP[i][0] > 32767) ih.envVP[i][0] = 32767;
3154 if ((uint16_t)ih.envPP[i][0] > 32767) ih.envPP[i][0] = 32767;
3155 if ((uint16_t)ih.envVP[i][1] > 64) ih.envVP[i][1] = 64;
3156 if ((uint16_t)ih.envPP[i][1] > 63) ih.envPP[i][1] = 63;
3157 }
3158
3130 // ----------------------------------------3159 // ----------------------------------------
3131 3160
3132 memcpy(instr[editor.curInstr]->ta, ih.ta, INSTR_SIZE);3161 memcpy(instr[editor.curInstr]->ta, ih.ta, INSTR_SIZE);
src/ft2_keyboard.c+13−7
@@ -107,8 +107,10 @@ void keyDownHandler(SDL_Scancode scancode, SDL_Keycode keycode, bool keyWasRepea · 106 unmodified lines
107 107
108 if (editor.ui.sysReqShown)108 if (editor.ui.sysReqShown)
109 {109 {
110 if (keycode == SDLK_RETURN) editor.ui.sysReqEnterPressed = true;110 if (keycode == SDLK_RETURN)
111 else if (keycode == SDLK_ESCAPE) editor.ui.sysReqShown = false;111 editor.ui.sysReqEnterPressed = true;
112 else if (keycode == SDLK_ESCAPE)
113 editor.ui.sysReqShown = false;
112 114
113 return;115 return;
114 }116 }
@@ -858,7 +860,7 @@ static bool checkModifiedKeys(SDL_Keycode keycode) · 743 unmodified lines
858 video.showFPSCounter ^= 1;860 video.showFPSCounter ^= 1;
859 if (!video.showFPSCounter)861 if (!video.showFPSCounter)
860 {862 {
861 if (editor.ui.extended) // Mr. Kludge, my only friend863 if (editor.ui.extended) // yet another kludge...
862 exitPatternEditorExtended();864 exitPatternEditorExtended();
863 865
864 showTopScreen(false);866 showTopScreen(false);
@@ -1025,15 +1027,19 @@ static bool checkModifiedKeys(SDL_Keycode keycode) · 160 unmodified lines
1025 case SDLK_v:1027 case SDLK_v:
1026 if (keyb.leftAltPressed)1028 if (keyb.leftAltPressed)
1027 {1029 {
1028 if (editor.ui.sampleEditorShown) sampPaste();1030 if (editor.ui.sampleEditorShown)
1029 else if (!editor.ui.instEditorShown) scaleFadeVolumeBlock();1031 sampPaste();
1032 else if (!editor.ui.instEditorShown)
1033 scaleFadeVolumeBlock();
1030 1034
1031 return true;1035 return true;
1032 }1036 }
1033 else if (keyb.leftCtrlPressed || keyb.leftCommandPressed)1037 else if (keyb.leftCtrlPressed || keyb.leftCommandPressed)
1034 {1038 {
1035 if (editor.ui.sampleEditorShown) sampPaste();1039 if (editor.ui.sampleEditorShown)
1036 else if (!editor.ui.instEditorShown) scaleFadeVolumePattern();1040 sampPaste();
1041 else if (!editor.ui.instEditorShown)
1042 scaleFadeVolumePattern();
1037 1043
1038 return true;1044 return true;
1039 }1045 }
src/ft2_main.c+8−0
@@ -103,6 +103,13 @@ int main(int argc, char *argv[]) · 102 unmodified lines
103 return 0;103 return 0;
104 }104 }
105 105
106 if (!cpu.hasSSE2)
107 {
108 showErrorMsgBox("Your computer's processor doesn't have the SSE2 instruction set\n" \
109 "which is needed for this program to run. Sorry!");
110 return 0;
111 }
112
106 setupWin32Usleep();113 setupWin32Usleep();
107 disableWasapi(); // disable problematic WASAPI SDL2 audio driver on Windows (causes clicks/pops sometimes...)114 disableWasapi(); // disable problematic WASAPI SDL2 audio driver on Windows (causes clicks/pops sometimes...)
108#endif115#endif
@@ -192,6 +199,7 @@ int main(int argc, char *argv[]) · 83 unmodified lines
192#ifdef _WIN32 // on Windows we show the window at this point199#ifdef _WIN32 // on Windows we show the window at this point
193 SDL_ShowWindow(video.window);200 SDL_ShowWindow(video.window);
194#endif201#endif
202
195 if (config.windowFlags & START_IN_FULLSCR)203 if (config.windowFlags & START_IN_FULLSCR)
196 {204 {
197 video.fullscreen = true;205 video.fullscreen = true;
src/ft2_module_loader.c+50−14
@@ -1810,8 +1810,6 @@ xmLoadError: · 1809 unmodified lines
1810 1810
1811void loadMusic(UNICHAR *filenameU)1811void loadMusic(UNICHAR *filenameU)
1812{1812{
1813 int32_t i;
1814
1815 if (musicIsLoading)1813 if (musicIsLoading)
1816 return;1814 return;
1817 1815
@@ -1831,7 +1829,7 @@ void loadMusic(UNICHAR *filenameU) · 13 unmodified lines
1831 // prevent stuck instrument names from previous module1829 // prevent stuck instrument names from previous module
1832 memset(&songTmp, 0, sizeof (songTmp));1830 memset(&songTmp, 0, sizeof (songTmp));
1833 1831
1834 for (i = 0; i < MAX_PATTERNS; i++)1832 for (uint32_t i = 0; i < MAX_PATTERNS; i++)
1835 pattLensTmp[i] = 64;1833 pattLensTmp[i] = 64;
1836 1834
1837 thread = SDL_CreateThread(loadMusicThread, NULL, NULL);1835 thread = SDL_CreateThread(loadMusicThread, NULL, NULL);
@@ -1846,6 +1844,35 @@ void loadMusic(UNICHAR *filenameU) · 8 unmodified lines
1846 SDL_DetachThread(thread);1844 SDL_DetachThread(thread);
1847}1845}
1848 1846
1847bool loadMusicUnthreaded(UNICHAR *filenameU) // for development testing
1848{
1849 if (editor.tmpFilenameU == NULL)
1850 return false;
1851
1852 // clear deprecated pointers from possible last loading session (super important)
1853 memset(pattTmp, 0, sizeof (pattTmp));
1854 memset(instrTmp, 0, sizeof (instrTmp));
1855
1856 // prevent stuck instrument names from previous module
1857 memset(&songTmp, 0, sizeof (songTmp));
1858
1859 for (uint32_t i = 0; i < MAX_PATTERNS; i++)
1860 pattLensTmp[i] = 64;
1861
1862 UNICHAR_STRCPY(editor.tmpFilenameU, filenameU);
1863
1864 loadMusicThread(NULL);
1865 editor.loadMusicEvent = EVENT_NONE;
1866
1867 if (moduleLoaded)
1868 {
1869 setupLoadedModule();
1870 return true;
1871 }
1872
1873 return false;
1874}
1875
1849static void freeTmpModule(void)1876static void freeTmpModule(void)
1850{1877{
1851 uint16_t i;1878 uint16_t i;
@@ -1925,7 +1952,7 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 73 unmodified lines
1925 if (!allocateTmpInstr(i))1952 if (!allocateTmpInstr(i))
1926 return false;1953 return false;
1927 1954
1928 // sanitize stuff for malicious instruments1955 // sanitize stuff for broken/unsupported instruments
1929 ih.midiProgram = CLAMP(ih.midiProgram, 0, 127);1956 ih.midiProgram = CLAMP(ih.midiProgram, 0, 127);
1930 ih.midiBend = CLAMP(ih.midiBend, 0, 36);1957 ih.midiBend = CLAMP(ih.midiBend, 0, 36);
1931 1958
@@ -1941,20 +1968,29 @@ static bool loadInstrHeader(FILE *f, uint16_t i) · 9 unmodified lines
1941 if (ih.ta[j] > 15)1968 if (ih.ta[j] > 15)
1942 ih.ta[j] = 15;1969 ih.ta[j] = 15;
1943 }1970 }
1971
1972 if (ih.envVPAnt > 12) ih.envVPAnt = 12;
1973 if (ih.envVRepS > 11) ih.envVRepS = 11;
1974 if (ih.envVRepE > 11) ih.envVRepE = 11;
1975 if (ih.envVSust > 11) ih.envVSust = 11;
1976 if (ih.envPPAnt > 12) ih.envPPAnt = 12;
1977 if (ih.envPRepS > 11) ih.envPRepS = 11;
1978 if (ih.envPRepE > 11) ih.envPRepE = 11;
1979 if (ih.envPSust > 11) ih.envPSust = 11;
1980
1981 for (j = 0; j < 12; j++)
1982 {
1983 if ((uint16_t)ih.envVP[j][0] > 32767) ih.envVP[j][0] = 32767;
1984 if ((uint16_t)ih.envPP[j][0] > 32767) ih.envPP[j][0] = 32767;
1985 if ((uint16_t)ih.envVP[j][1] > 64) ih.envVP[j][1] = 64;
1986 if ((uint16_t)ih.envPP[j][1] > 63) ih.envPP[j][1] = 63;
1987
1988 }
1944 // ----------------------------------------1989 // ----------------------------------------
1945 1990
1946 // copy over final instrument data from temp buffer1991 // copy over final instrument data from temp buffer
1947 memcpy(instrTmp[i], ih.ta, INSTR_SIZE);1992 memcpy(instrTmp[i], ih.ta, INSTR_SIZE);
1948 instrTmp[i]->antSamp = ih.antSamp;1993 instrTmp[i]->antSamp = ih.antSamp;
1949
1950 if (instrTmp[i]->envVPAnt > 12) instrTmp[i]->envVPAnt = 12;
1951 if (instrTmp[i]->envVRepS > 11) instrTmp[i]->envVRepS = 11;
1952 if (instrTmp[i]->envVRepE > 11) instrTmp[i]->envVRepE = 11;
1953 if (instrTmp[i]->envVSust > 11) instrTmp[i]->envVSust = 11;
1954 if (instrTmp[i]->envPPAnt > 12) instrTmp[i]->envPPAnt = 12;
1955 if (instrTmp[i]->envPRepS > 11) instrTmp[i]->envPRepS = 11;
1956 if (instrTmp[i]->envPRepE > 11) instrTmp[i]->envPRepE = 11;
1957 if (instrTmp[i]->envPSust > 11) instrTmp[i]->envPSust = 11;
1958 }1994 }
1959 1995
1960 if (fread(ih.samp, ih.antSamp * sizeof (sampleHeaderTyp), 1, f) != 1)1996 if (fread(ih.samp, ih.antSamp * sizeof (sampleHeaderTyp), 1, f) != 1)
@@ -2501,7 +2537,7 @@ void loadDroppedFile(char *fullPathUTF8, bool songModifiedCheck) · 540 unmodified lines
2501 SDL_RestoreWindow(video.window);2537 SDL_RestoreWindow(video.window);
2502 SDL_RaiseWindow(video.window);2538 SDL_RaiseWindow(video.window);
2503 2539
2504 if (okBox(2, "System request", "You have unsaved changes in your song. Load new song and lose all changes?") != 1)2540 if (!askUnsavedChanges(ASK_TYPE_LOAD_SONG))
2505 {2541 {
2506 free(fullPathU);2542 free(fullPathU);
2507 return;2543 return;
src/ft2_module_loader.h+1−0
@@ -5,6 +5,7 @@ · 4 unmodified lines
5#include "ft2_unicode.h"5#include "ft2_unicode.h"
6 6
7void loadMusic(UNICHAR *filenameU);7void loadMusic(UNICHAR *filenameU);
8bool loadMusicUnthreaded(UNICHAR *filenameU); // for development testing
8bool handleModuleLoadFromArg(int argc, char **argv);9bool handleModuleLoadFromArg(int argc, char **argv);
9void loadDroppedFile(char *fullPathUTF8, bool songModifiedCheck);10void loadDroppedFile(char *fullPathUTF8, bool songModifiedCheck);
10void handleLoadMusicEvents(void);11void handleLoadMusicEvents(void);
src/ft2_mouse.c+22−12
@@ -667,19 +667,29 @@ void mouseButtonDownHandler(uint8_t mouseButton) · 666 unmodified lines
667 return;667 return;
668 }668 }
669 669
670 if (mouseButton == SDL_BUTTON_LEFT) mouse.leftButtonPressed = true;
671 else if (mouseButton == SDL_BUTTON_RIGHT) mouse.rightButtonPressed = true;
672
673 mouse.leftButtonReleased = false;
674 mouse.rightButtonReleased = false;
675
676 // mouse 0,0 = open exit dialog670 // mouse 0,0 = open exit dialog
677 if (mouse.x == 0 && mouse.y == 0 && quitBox(false) == 1)671 if (mouse.x == 0 && mouse.y == 0)
678 {672 {
679 editor.throwExit = true;673 if (quitBox(false) == 1)
674 editor.throwExit = true;
675
676 // release button presses from okBox()
677 mouse.leftButtonPressed = false;
678 mouse.rightButtonPressed = false;
679 mouse.leftButtonReleased = false;
680 mouse.rightButtonReleased = false;
681
680 return;682 return;
681 }683 }
682 684
685 if (mouseButton == SDL_BUTTON_LEFT)
686 mouse.leftButtonPressed = true;
687 else if (mouseButton == SDL_BUTTON_RIGHT)
688 mouse.rightButtonPressed = true;
689
690 mouse.leftButtonReleased = false;
691 mouse.rightButtonReleased = false;
692
683 // don't do mouse down testing here if we already are using an object693 // don't do mouse down testing here if we already are using an object
684 if (mouse.lastUsedObjectType != OBJECT_NONE)694 if (mouse.lastUsedObjectType != OBJECT_NONE)
685 return;695 return;
@@ -762,8 +772,8 @@ void handleLastGUIObjectDown(void) · 76 unmodified lines
762 772
763void updateMouseScaling(void)773void updateMouseScaling(void)
764{774{
765 video.dMouseXMul = (double)SCREEN_W / video.renderW;775 if (video.renderW > 0.0) video.dMouseXMul = (double)SCREEN_W / video.renderW;
766 video.dMouseYMul = (double)SCREEN_H / video.renderH;776 if (video.renderH > 0.0) video.dMouseYMul = (double)SCREEN_H / video.renderH;
767}777}
768 778
769void readMouseXY(void)779void readMouseXY(void)
@@ -818,8 +828,8 @@ void readMouseXY(void) · 48 unmodified lines
818 if (my < 0) mx = 0;828 if (my < 0) mx = 0;
819 829
820 // multiply coords by video upscaling factors (don't round)830 // multiply coords by video upscaling factors (don't round)
821 mx = (uint32_t)(mx * video.dMouseXMul);831 mx = (int32_t)(mx * video.dMouseXMul);
822 my = (uint32_t)(my * video.dMouseYMul);832 my = (int32_t)(my * video.dMouseYMul);
823 833
824 if (mx >= SCREEN_W) mx = SCREEN_W - 1;834 if (mx >= SCREEN_W) mx = SCREEN_W - 1;
825 if (my >= SCREEN_H) my = SCREEN_H - 1;835 if (my >= SCREEN_H) my = SCREEN_H - 1;
src/ft2_mouse.h+0−1
@@ -32,7 +32,6 @@ struct mouse_t · 31 unmodified lines
32 32
33void freeMouseCursors(void);33void freeMouseCursors(void);
34bool createMouseCursors(void);34bool createMouseCursors(void);
35
36void setMousePosToCenter(void);35void setMousePosToCenter(void);
37void setMouseShape(int16_t shape);36void setMouseShape(int16_t shape);
38void setMouseMode(uint8_t mode);37void setMouseMode(uint8_t mode);
src/ft2_palette.c+5−0
@@ -18,6 +18,11 @@ static uint8_t palContrast[12][2] = // palette desktop/button contrasts · 17 unmodified lines
18 {66, 62}, {68, 57}, {46, 57}, {57, 55}, {62, 57}, {52, 57}18 {66, 62}, {68, 57}, {46, 57}, {57, 55}, {62, 57}, {52, 57}
19};19};
20 20
21void setCustomPalColor(uint32_t color)
22{
23 video.palette[PAL_CUSTOM] = (PAL_CUSTOM << 24) | color;
24}
25
21void setPal16(pal16 *p, bool redrawScreen)26void setPal16(pal16 *p, bool redrawScreen)
22{27{
23#define LOOP_PIN_COL_SUB 11828#define LOOP_PIN_COL_SUB 118
src/ft2_palette.h+5−0
@@ -38,6 +38,9 @@ enum · 37 unmodified lines
38 PAL_TEXTMRK = 17,38 PAL_TEXTMRK = 17,
39 PAL_BOXSLCT = 18,39 PAL_BOXSLCT = 18,
40 40
41 // modifiable with setCustomPalColor()
42 PAL_CUSTOM = 19,
43
41 PAL_NUM44 PAL_NUM
42};45};
43 46
@@ -49,6 +52,8 @@ typedef struct pal16_t · 5 unmodified lines
49extern uint8_t cfg_ColorNr;52extern uint8_t cfg_ColorNr;
50extern pal16 palTable[12][16];53extern pal16 palTable[12][16];
51 54
55void setCustomPalColor(uint32_t color);
56
52uint8_t palMax(int32_t c);57uint8_t palMax(int32_t c);
53void setPal16(pal16 *p, bool redrawScreen);58void setPal16(pal16 *p, bool redrawScreen);
54 59
src/ft2_pattern_draw.c+439−464
@@ -12,6 +12,9 @@ · 11 unmodified lines
12#include "ft2_gui.h"12#include "ft2_gui.h"
13#include "ft2_video.h"13#include "ft2_video.h"
14 14
15static tonTyp emptyPattern[MAX_VOICES * MAX_PATT_LEN];
16
17static const uint8_t *font4Ptr, *font5Ptr;
15static const uint8_t vol2charTab1[16] = { 39, 0, 1, 2, 3, 4, 36, 52, 53, 54, 28, 31, 25, 58, 59, 22 };18static const uint8_t vol2charTab1[16] = { 39, 0, 1, 2, 3, 4, 36, 52, 53, 54, 28, 31, 25, 58, 59, 22 };
16static const uint8_t vol2charTab2[16] = { 42, 0, 1, 2, 3, 4, 36, 37, 38, 39, 28, 31, 25, 40, 41, 22 };19static const uint8_t vol2charTab2[16] = { 42, 0, 1, 2, 3, 4, 36, 37, 38, 39, 28, 31, 25, 40, 41, 22 };
17static const uint8_t columnModeTab[12] = { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 };20static const uint8_t columnModeTab[12] = { 0, 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 3 };
@@ -28,29 +31,229 @@ static const uint16_t sharpNote2Char_big[12] = { 36*16, 37*16, 36*16, 37*16, 36* · 10 unmodified lines
28static const uint16_t flatNote1Char_big[12] = { 12*16, 13*16, 13*16, 14*16, 14*16, 15*16, 16*16, 16*16, 10*16, 10*16, 11*16, 11*16 };31static const uint16_t flatNote1Char_big[12] = { 12*16, 13*16, 13*16, 14*16, 14*16, 15*16, 16*16, 16*16, 10*16, 10*16, 11*16, 11*16 };
29static const uint16_t flatNote2Char_big[12] = { 36*16, 38*16, 36*16, 38*16, 36*16, 36*16, 38*16, 36*16, 38*16, 36*16, 38*16, 36*16 };32static const uint16_t flatNote2Char_big[12] = { 36*16, 38*16, 36*16, 38*16, 36*16, 36*16, 38*16, 36*16, 38*16, 36*16, 38*16, 36*16 };
30 33
31static tonTyp emptyNote;34static const uint8_t noteTab1[96] =
35{
36 0,1,2,3,4,5,6,7,8,9,10,11,
37 0,1,2,3,4,5,6,7,8,9,10,11,
38 0,1,2,3,4,5,6,7,8,9,10,11,
39 0,1,2,3,4,5,6,7,8,9,10,11,
40 0,1,2,3,4,5,6,7,8,9,10,11,
41 0,1,2,3,4,5,6,7,8,9,10,11,
42 0,1,2,3,4,5,6,7,8,9,10,11,
43 0,1,2,3,4,5,6,7,8,9,10,11
44};
45
46static const uint8_t noteTab2[96] =
47{
48 0,0,0,0,0,0,0,0,0,0,0,0,
49 1,1,1,1,1,1,1,1,1,1,1,1,
50 2,2,2,2,2,2,2,2,2,2,2,2,
51 3,3,3,3,3,3,3,3,3,3,3,3,
52 4,4,4,4,4,4,4,4,4,4,4,4,
53 5,5,5,5,5,5,5,5,5,5,5,5,
54 6,6,6,6,6,6,6,6,6,6,6,6,
55 7,7,7,7,7,7,7,7,7,7,7,7
56};
57
58static const uint8_t hex2Dec[256] =
59{
60 0,1,2,3,4,5,6,7,8,9,
61 16,17,18,19,20,21,22,23,24,25,
62 32,33,34,35,36,37,38,39,40,41,
63 48,49,50,51,52,53,54,55,56,57,
64 64,65,66,67,68,69,70,71,72,73,
65 80,81,82,83,84,85,86,87,88,89,
66 96,97,98,99,100,101,102,103,104,105,
67 112,113,114,115,116,117,118,119,120,121,
68 128,129,130,131,132,133,134,135,136,137,
69 144,145,146,147,148,149,150,151,152,153,
70
71 0,1,2,3,4,5,6,7,8,9,
72 16,17,18,19,20,21,22,23,24,25,
73 32,33,34,35,36,37,38,39,40,41,
74 48,49,50,51,52,53,54,55,56,57,
75 64,65,66,67,68,69,70,71,72,73,
76 80,81,82,83,84,85,86,87,88,89,
77 96,97,98,99,100,101,102,103,104,105,
78 112,113,114,115,116,117,118,119,120,121,
79 128,129,130,131,132,133,134,135,136,137,
80 144,145,146,147,148,149,150,151,152,153,
81
82 0,1,2,3,4,5,6,7,8,9,
83 16,17,18,19,20,21,22,23,24,25,
84 32,33,34,35,36,37,38,39,40,41,
85 48,49,50,51,52,53,54,55,56,57,
86 64,65,66,67,68,69,70,71,72,73,
87 80,81,82,83,84,85
88};
89
90static const pattCoord_t pattCoordTable[2][2][2] =
91{
92 // no pattern stretch
93 {
94 // no pattern channel scroll
95 {
96 { 176, 292, 177, 283, 293, 13, 13 }, // normal pattern editor
97 { 56, 228, 57, 219, 229, 20, 21 }, // extended pattern editor
98 },
99
100 // pattern channel scroll
101 {
102 { 176, 285, 177, 276, 286, 12, 12 }, // normal pattern editor
103 { 56, 221, 57, 212, 222, 19, 20 }, // extended pattern editor
104 }
105 },
106
107 // pattern stretch
108 {
109 // no pattern channel scroll
110 {
111 { 177, 286, 178, 277, 288, 9, 10 }, // normal pattern editor
112 { 56, 232, 58, 223, 234, 15, 15 }, // extended pattern editor
113 },
114
115 // pattern channel scroll
116 {
117 { 176, 285, 177, 276, 286, 9, 9 }, // normal pattern editor
118 { 56, 220, 57, 211, 221, 14, 15 }, // extended pattern editor
119 },
120 }
121};
122
123static const pattCoord2_t pattCoord2Table[2][2][2] =
124{
125 // no pattern stretch
126 {
127 // no pattern channel scroll
128 {
129 { 175, 291, 107, 107 }, // normal pattern editor
130 { 55, 227, 163, 171 }, // extended pattern editor
131 },
132
133 // pattern channel scroll
134 {
135 { 175, 284, 100, 100 }, // normal pattern editor
136 { 55, 220, 156, 164 }, // extended pattern editor
137 }
138 },
139
140 // pattern stretch
141 {
142 // no pattern channel scroll
143 {
144 { 175, 285, 101, 113 }, // normal pattern editor
145 { 55, 231, 167, 167 }, // extended pattern editor
146 },
147
148 // pattern channel scroll
149 {
150 { 175, 284, 100, 100 }, // normal pattern editor
151 { 55, 219, 155, 165 }, // extended pattern editor
152 },
153 }
154};
155
156static const markCoord_t markCoordTable[2][2][2] =
157{
158 // no pattern stretch
159 {
160 // no pattern channel scroll
161 {
162 { 177, 281, 293 }, // normal pattern editor
163 { 57, 217, 229 }, // extended pattern editor
164 },
165
166 // pattern channel scroll
167 {
168 { 177, 274, 286 }, // normal pattern editor
169 { 57, 210, 222 }, // extended pattern editor
170 }
171 },
172
173 // pattern stretch
174 {
175 // no pattern channel scroll
176 {
177 { 176, 275, 286 }, // normal pattern editor
178 { 56, 221, 232 }, // extended pattern editor
179 },
180
181 // pattern channel scroll
182 {
183 { 175, 274, 284 }, // normal pattern editor
184 { 55, 209, 219 }, // extended pattern editor
185 },
186 }
187};
188
189static const uint8_t pattCursorXTab[2 * 4 * 8] =
190{
191 // no volume column shown
192 32, 88, 104, 0, 0, 120, 136, 152, // 4 columns visible
193 32, 80, 88, 0, 0, 96, 104, 112, // 6 columns visible
194 32, 56, 64, 0, 0, 72, 80, 88, // 8 columns visible
195 32, 52, 56, 0, 0, 60, 64, 68, // 12 columns visible
196
197 // volume column shown
198 32, 96, 104, 120, 128, 144, 152, 160, // 4 columns visible
199 32, 56, 64, 80, 88, 96, 104, 112, // 6 columns visible
200 32, 60, 64, 72, 76, 84, 88, 92, // 8 columns visible
201 32, 60, 64, 72, 76, 84, 88, 92, // 12 columns visible
202};
203
204static const uint8_t pattCursorWTab[2 * 4 * 8] =
205{
206 // no volume column shown
207 48, 16, 16, 0, 0, 16, 16, 16, // 4 columns visible
208 48, 8, 8, 0, 0, 8, 8, 8, // 6 columns visible
209 24, 8, 8, 0, 0, 8, 8, 8, // 8 columns visible
210 16, 4, 4, 0, 0, 4, 4, 4, // 12 columns visible
211
212 // volume column shown
213 48, 8, 8, 8, 8, 8, 8, 8, // 4 columns visible
214 24, 8, 8, 8, 8, 8, 8, 8, // 6 columns visible
215 24, 4, 4, 4, 4, 4, 4, 4, // 8 columns visible
216 24, 4, 4, 4, 4, 4, 4, 4 // 12 columns visible
217};
218
219// global tables
220
221const char chDecTab1[MAX_VOICES+1] =
222{
223 '0', '0', '0', '0', '0', '0', '0', '0', '0', '0',
224 '1', '1', '1', '1', '1', '1', '1', '1', '1', '1',
225 '2', '2', '2', '2', '2', '2', '2', '2', '2', '2',
226 '3', '3', '3'
227};
228
229const char chDecTab2[MAX_VOICES+1] =
230{
231 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
232 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
233 '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
234 '0', '1', '2'
235};
32 236
33// ft2_pattern_ed.c237// ft2_pattern_ed.c
34extern const uint16_t chanWidths[6];238extern const uint16_t chanWidths[6];
35 239
36// defined at the bottom of this file240static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontType, uint32_t color);
37extern const pattCoord_t pattCoordTable[2][2][2];241static void drawEmptyNoteSmall(uint32_t xPos, uint32_t yPos, uint32_t color);
38extern const pattCoord2_t pattCoord2Table[2][2][2];242static void drawKeyOffSmall(uint32_t xPos, uint32_t yPos, uint32_t color);
39extern const markCoord_t markCoordTable[2][2][2];243static void drawNoteSmall(uint32_t xPos, uint32_t yPos, int32_t ton, uint32_t color);
40extern const uint8_t pattCursorXTab[2 * 4 * 8];244static void drawEmptyNoteMedium(uint32_t xPos, uint32_t yPos, uint32_t color);
41extern const uint8_t pattCursorWTab[2 * 4 * 8];245static void drawKeyOffMedium(uint32_t xPos, uint32_t yPos, uint32_t color);
42 246static void drawNoteMedium(uint32_t xPos, uint32_t yPos, int32_t ton, uint32_t color);
43static void rowNumOut(uint32_t yPos, uint8_t paletteIndex, uint8_t rowChar1, uint8_t rowChar2);247static void drawEmptyNoteBig(uint32_t xPos, uint32_t yPos, uint32_t color);
44static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint8_t chr, uint8_t fontType);248static void drawKeyOffBig(uint32_t xPos, uint32_t yPos, uint32_t color);
45static void drawEmptyNoteSmall(uint16_t x, uint16_t y, uint8_t paletteIndex);249static void drawNoteBig(uint32_t xPos, uint32_t yPos, int32_t ton, uint32_t color);
46static void drawKeyOffSmall(uint16_t x, uint16_t y, uint8_t paletteIndex);250
47static void drawNoteSmall(uint16_t x, uint16_t y, uint8_t paletteIndex, int16_t ton);251void updatePattFontPtrs(void)
48static void drawEmptyNoteMedium(uint16_t x, uint16_t y, uint8_t paletteIndex);252{
49static void drawKeyOffMedium(uint16_t x, uint16_t y, uint8_t paletteIndex);253 //config.ptnFont is pre-clamped and safe
50static void drawNoteMedium(uint16_t x, uint16_t y, uint8_t paletteIndex, int16_t ton);254 font4Ptr = &font4Data[config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H)];
51static void drawEmptyNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex);255 font5Ptr = &font5Data[config.ptnFont * (FONT5_WIDTH * FONT5_CHAR_H)];
52static void drawKeyOffBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex);256}
53static void drawNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, int16_t ton);
54 257
55void drawPatternBorders(void)258void drawPatternBorders(void)
56{259{
@@ -141,11 +344,11 @@ void drawPatternBorders(void) · 84 unmodified lines
141 drawFramework(xOffs, pattCoord->upperRowsY, chanWidth, pattCoord->upperRowsH, FRAMEWORK_TYPE2); // top part344 drawFramework(xOffs, pattCoord->upperRowsY, chanWidth, pattCoord->upperRowsH, FRAMEWORK_TYPE2); // top part
142 drawFramework(xOffs, pattCoord->lowerRowsY, chanWidth, pattCoord->lowerRowsH, FRAMEWORK_TYPE2); // bottom part345 drawFramework(xOffs, pattCoord->lowerRowsY, chanWidth, pattCoord->lowerRowsH, FRAMEWORK_TYPE2); // bottom part
143 346
144 xOffs += (chanWidth + 1);347 xOffs += chanWidth+1;
145 }348 }
146 349
147 vLine(xOffs - 1, pattCoord->upperRowsY, pattCoord->upperRowsH, PAL_DESKTOP);350 vLine(xOffs-1, pattCoord->upperRowsY, pattCoord->upperRowsH, PAL_DESKTOP);
148 vLine(xOffs - 1, pattCoord->lowerRowsY, pattCoord->lowerRowsH + 1, PAL_DESKTOP);351 vLine(xOffs-1, pattCoord->lowerRowsY, pattCoord->lowerRowsH+1, PAL_DESKTOP);
149 }352 }
150 else353 else
151 {354 {
@@ -203,11 +406,9 @@ static void writeCursor(void) · 51 unmodified lines
203 }406 }
204}407}
205 408
206static void writePatternBlockMark(int16_t currRow, uint16_t rowHeight, const pattCoord_t *pattCoord)409static void writePatternBlockMark(int32_t currRow, uint32_t rowHeight, const pattCoord_t *pattCoord)
207{410{
208 uint8_t startCh, endCh;411 int32_t startCh, endCh, startRow, endRow, x1, x2, y1, y2, pattYStart, pattYEnd;
209 int16_t startRow, endRow, x1, x2, y1, y2;
210 uint16_t pattYStart, pattYEnd;
211 uint32_t w, h, *ptr32;412 uint32_t w, h, *ptr32;
212 const markCoord_t *markCoord;413 const markCoord_t *markCoord;
213 414
@@ -311,53 +512,79 @@ static void writePatternBlockMark(int16_t currRow, uint16_t rowHeight, const pat · 97 unmodified lines
311 512
312static void drawChannelNumbering(uint16_t yPos)513static void drawChannelNumbering(uint16_t yPos)
313{514{
314 uint8_t chNum;515#define CH_NUM_XPOS 29
315 uint16_t xPos;516
517 uint16_t xPos = CH_NUM_XPOS;
518 int32_t ch = editor.ui.channelOffset + 1;
316 519
317 xPos = 29;
318 for (uint8_t i = 0; i < editor.ui.numChannelsShown; i++)520 for (uint8_t i = 0; i < editor.ui.numChannelsShown; i++)
319 {521 {
320 chNum = editor.ui.channelOffset + i + 1;522 if (ch < 10)
321 if (chNum < 10)
322 {523 {
323 charOutOutlined(xPos, yPos, PAL_MOUSEPT, '0' + chNum);524 charOutOutlined(xPos, yPos, PAL_MOUSEPT, '0' + (char)ch);
324 }525 }
325 else526 else
326 {527 {
327 charOutOutlined(xPos, yPos, PAL_MOUSEPT, '0' + (chNum / 10));528 charOutOutlined(xPos, yPos, PAL_MOUSEPT, chDecTab1[ch]);
328 charOutOutlined(xPos + 9, yPos, PAL_MOUSEPT, '0' + (chNum % 10));529 charOutOutlined(xPos + (FONT1_CHAR_W + 1), yPos, PAL_MOUSEPT, chDecTab2[ch]);
329 }530 }
330 531
532 ch++;
331 xPos += editor.ui.patternChannelWidth;533 xPos += editor.ui.patternChannelWidth;
332 }534 }
333}535}
334 536
335static void drawRowNum(uint16_t yPos, uint16_t row, bool middleRowFlag)537static void drawRowNums(int32_t yPos, uint8_t row, bool selectedRowFlag)
336{538{
337 uint8_t pal;539#define LEFT_ROW_XPOS 8
540#define RIGHT_ROW_XPOS 608
541
542 const uint8_t *src1Ptr, *src2Ptr;
543 uint32_t *dst1Ptr, *dst2Ptr, pixVal;
338 544
339 // set color based on some conditions545 // set color based on some conditions
340 if (middleRowFlag)546 if (selectedRowFlag)
341 pal = PAL_FORGRND;547 pixVal = video.palette[PAL_FORGRND];
342 else if ((row & 3) == 0 && config.ptnLineLight)548 else if (config.ptnLineLight && !(row & 3))
343 pal = PAL_BLCKTXT;549 pixVal = video.palette[PAL_BLCKTXT];
344 else550 else
345 pal = PAL_PATTEXT;551 pixVal = video.palette[PAL_PATTEXT];
346 552
347 if (config.ptnHex)553 if (!config.ptnHex)
348 {554 row = hex2Dec[row];
349 rowNumOut(yPos, pal, (uint8_t)(row >> 4), row & 0x0F);555
350 }556 src1Ptr = &font4Ptr[(row >> 4) * FONT4_CHAR_W];
351 else557 src2Ptr = &font4Ptr[(row & 0x0F) * FONT4_CHAR_W];
558 dst1Ptr = &video.frameBuffer[(yPos * SCREEN_W) + LEFT_ROW_XPOS];
559 dst2Ptr = dst1Ptr + (RIGHT_ROW_XPOS - LEFT_ROW_XPOS);
560
561 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
352 {562 {
353 row %= 100;563 for (uint32_t x1 = 0; x1 < FONT4_CHAR_W; x1++)
354 rowNumOut(yPos, pal, (uint8_t)(row / 10), row % 10);564 {
565 if (src1Ptr[x1])
566 {
567 dst1Ptr[x1] = pixVal; // left side
568 dst2Ptr[x1] = pixVal; // right side
569 }
570
571 if (src2Ptr[x1])
572 {
573 dst1Ptr[FONT4_CHAR_W + x1] = pixVal; // left side
574 dst2Ptr[FONT4_CHAR_W + x1] = pixVal; // right side
575 }
576 }
577
578 src1Ptr += FONT4_WIDTH;
579 src2Ptr += FONT4_WIDTH;
580 dst1Ptr += SCREEN_W;
581 dst2Ptr += SCREEN_W;
355 }582 }
356}583}
357 584
358// DRAWING ROUTINES (WITH VOLUME COLUMN)585// DRAWING ROUTINES (WITH VOLUME COLUMN)
359 586
360static void showNoteNum(uint8_t pal, uint16_t xPos, uint16_t yPos, int16_t ton)587static void showNoteNum(uint32_t xPos, uint32_t yPos, int16_t ton, uint32_t color)
361{588{
362 xPos += 3;589 xPos += 3;
363 590
@@ -366,24 +593,24 @@ static void showNoteNum(uint8_t pal, uint16_t xPos, uint16_t yPos, int16_t ton) · 2 unmodified lines
366 if (editor.ui.numChannelsShown <= 4)593 if (editor.ui.numChannelsShown <= 4)
367 {594 {
368 if (ton <= 0 || ton > 97)595 if (ton <= 0 || ton > 97)
369 drawEmptyNoteBig(xPos, yPos, pal);596 drawEmptyNoteBig(xPos, yPos, color);
370 else if (ton == 97)597 else if (ton == 97)
371 drawKeyOffBig(xPos, yPos, pal);598 drawKeyOffBig(xPos, yPos, color);
372 else599 else
373 drawNoteBig(xPos, yPos, pal, ton);600 drawNoteBig(xPos, yPos, ton, color);
374 }601 }
375 else602 else
376 {603 {
377 if (ton <= 0 || ton > 97)604 if (ton <= 0 || ton > 97)
378 drawEmptyNoteMedium(xPos, yPos, pal);605 drawEmptyNoteMedium(xPos, yPos, color);
379 else if (ton == 97)606 else if (ton == 97)
380 drawKeyOffMedium(xPos, yPos, pal);607 drawKeyOffMedium(xPos, yPos, color);
381 else608 else
382 drawNoteMedium(xPos, yPos, pal, ton);609 drawNoteMedium(xPos, yPos, ton, color);
383 }610 }
384}611}
385 612
386static void showInstrNum(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t ins)613static void showInstrNum(uint32_t xPos, uint32_t yPos, uint8_t ins, uint32_t color)
387{614{
388 uint8_t chr1, chr2, charW, fontType;615 uint8_t chr1, chr2, charW, fontType;
389 616
@@ -408,8 +635,8 @@ static void showInstrNum(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t ins) · 18 unmodified lines
408 635
409 if (config.ptnInstrZero)636 if (config.ptnInstrZero)
410 {637 {
411 pattCharOut(xPos, yPos, pal, ins >> 4, fontType);638 pattCharOut(xPos, yPos, ins >> 4, fontType, color);
412 pattCharOut(xPos + charW, yPos, pal, ins & 0x0F, fontType);639 pattCharOut(xPos + charW, yPos, ins & 0x0F, fontType, color);
413 }640 }
414 else641 else
415 {642 {
@@ -417,14 +644,14 @@ static void showInstrNum(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t ins) · 1 unmodified line
417 chr2 = ins & 0x0F;644 chr2 = ins & 0x0F;
418 645
419 if (chr1 > 0)646 if (chr1 > 0)
420 pattCharOut(xPos, yPos, pal, chr1, fontType);647 pattCharOut(xPos, yPos, chr1, fontType, color);
421 648
422 if (chr1 > 0 || chr2 > 0)649 if (chr1 > 0 || chr2 > 0)
423 pattCharOut(xPos + charW, yPos, pal, chr2, fontType);650 pattCharOut(xPos + charW, yPos, chr2, fontType, color);
424 }651 }
425}652}
426 653
427static void showVolEfx(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t vol)654static void showVolEfx(uint32_t xPos, uint32_t yPos, uint8_t vol, uint32_t color)
428{655{
429 uint8_t char1, char2, fontType, charW;656 uint8_t char1, char2, fontType, charW;
430 657
@@ -465,11 +692,11 @@ static void showVolEfx(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t vol) · 34 unmodified lines
465 char2 = vol & 0x0F;692 char2 = vol & 0x0F;
466 }693 }
467 694
468 pattCharOut(xPos, yPos, pal, char1, fontType);695 pattCharOut(xPos, yPos, char1, fontType, color);
469 pattCharOut(xPos + charW, yPos, pal, char2, fontType);696 pattCharOut(xPos + charW, yPos, char2, fontType, color);
470}697}
471 698
472static void showEfx(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t effTyp, uint8_t eff)699static void showEfx(uint32_t xPos, uint32_t yPos, uint8_t effTyp, uint8_t eff, uint32_t color)
473{700{
474 uint8_t fontType, charW;701 uint8_t fontType, charW;
475 702
@@ -492,14 +719,14 @@ static void showEfx(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t effTyp, u · 16 unmodified lines
492 xPos += 55;719 xPos += 55;
493 }720 }
494 721
495 pattCharOut(xPos, yPos, pal, effTyp, fontType);722 pattCharOut(xPos, yPos, effTyp, fontType, color);
496 pattCharOut(xPos + charW, yPos, pal, eff >> 4, fontType);723 pattCharOut(xPos + charW, yPos, eff >> 4, fontType, color);
497 pattCharOut(xPos + (charW * 2), yPos, pal, eff & 0x0F, fontType);724 pattCharOut(xPos + (charW * 2), yPos, eff & 0x0F, fontType, color);
498}725}
499 726
500// DRAWING ROUTINES (WITHOUT VOLUME COLUMN)727// DRAWING ROUTINES (WITHOUT VOLUME COLUMN)
501 728
502static void showNoteNumNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, int16_t ton)729static void showNoteNumNoVolColumn(uint32_t xPos, uint32_t yPos, int16_t ton, uint32_t color)
503{730{
504 xPos += 3;731 xPos += 3;
505 732
@@ -508,33 +735,33 @@ static void showNoteNumNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, in · 2 unmodified lines
508 if (editor.ui.numChannelsShown <= 6)735 if (editor.ui.numChannelsShown <= 6)
509 {736 {
510 if (ton <= 0 || ton > 97)737 if (ton <= 0 || ton > 97)
511 drawEmptyNoteBig(xPos, yPos, pal);738 drawEmptyNoteBig(xPos, yPos, color);
512 else if (ton == 97)739 else if (ton == 97)
513 drawKeyOffBig(xPos, yPos, pal);740 drawKeyOffBig(xPos, yPos, color);
514 else741 else
515 drawNoteBig(xPos, yPos, pal, ton);742 drawNoteBig(xPos, yPos, ton, color);
516 }743 }
517 else if (editor.ui.numChannelsShown <= 8)744 else if (editor.ui.numChannelsShown <= 8)
518 {745 {
519 if (ton <= 0 || ton > 97)746 if (ton <= 0 || ton > 97)
520 drawEmptyNoteMedium(xPos, yPos, pal);747 drawEmptyNoteMedium(xPos, yPos, color);
521 else if (ton == 97)748 else if (ton == 97)
522 drawKeyOffMedium(xPos, yPos, pal);749 drawKeyOffMedium(xPos, yPos, color);
523 else750 else
524 drawNoteMedium(xPos, yPos, pal, ton);751 drawNoteMedium(xPos, yPos, ton, color);
525 }752 }
526 else753 else
527 {754 {
528 if (ton <= 0 || ton > 97)755 if (ton <= 0 || ton > 97)
529 drawEmptyNoteSmall(xPos, yPos, pal);756 drawEmptyNoteSmall(xPos, yPos, color);
530 else if (ton == 97)757 else if (ton == 97)
531 drawKeyOffSmall(xPos, yPos, pal);758 drawKeyOffSmall(xPos, yPos, color);
532 else759 else
533 drawNoteSmall(xPos, yPos, pal, ton);760 drawNoteSmall(xPos, yPos, ton, color);
534 }761 }
535}762}
536 763
537static void showInstrNumNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t ins)764static void showInstrNumNoVolColumn(uint32_t xPos, uint32_t yPos, uint8_t ins, uint32_t color)
538{765{
539 uint8_t chr1, chr2, charW, fontType;766 uint8_t chr1, chr2, charW, fontType;
540 767
@@ -565,8 +792,8 @@ static void showInstrNumNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, u · 24 unmodified lines
565 792
566 if (config.ptnInstrZero)793 if (config.ptnInstrZero)
567 {794 {
568 pattCharOut(xPos, yPos, pal, ins >> 4, fontType);795 pattCharOut(xPos, yPos, ins >> 4, fontType, color);
569 pattCharOut(xPos + charW, yPos, pal, ins & 0x0F, fontType);796 pattCharOut(xPos + charW, yPos, ins & 0x0F, fontType, color);
570 }797 }
571 else798 else
572 {799 {
@@ -574,23 +801,23 @@ static void showInstrNumNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, u · 1 unmodified line
574 chr2 = ins & 0x0F;801 chr2 = ins & 0x0F;
575 802
576 if (chr1 > 0)803 if (chr1 > 0)
577 pattCharOut(xPos, yPos, pal, chr1, fontType);804 pattCharOut(xPos, yPos, chr1, fontType, color);
578 805
579 if (chr1 > 0 || chr2 > 0)806 if (chr1 > 0 || chr2 > 0)
580 pattCharOut(xPos + charW, yPos, pal, chr2, fontType);807 pattCharOut(xPos + charW, yPos, chr2, fontType, color);
581 }808 }
582}809}
583 810
584static void showNoVolEfx(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t vol)811static void showNoVolEfx(uint32_t xPos, uint32_t yPos, uint8_t vol, uint32_t color)
585{812{
586 // make compiler happy813 // make compiler happy
587 (void)pal;
588 (void)xPos;814 (void)xPos;
589 (void)yPos;815 (void)yPos;
590 (void)vol;816 (void)vol;
817 (void)color;
591}818}
592 819
593static void showEfxNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_t effTyp, uint8_t eff)820static void showEfxNoVolColumn(uint32_t xPos, uint32_t yPos, uint8_t effTyp, uint8_t eff, uint32_t color)
594{821{
595 uint8_t charW, fontType;822 uint8_t charW, fontType;
596 823
@@ -619,65 +846,32 @@ static void showEfxNoVolColumn(uint8_t pal, uint16_t xPos, uint16_t yPos, uint8_ · 22 unmodified lines
619 xPos += 31;846 xPos += 31;
620 }847 }
621 848
622 pattCharOut(xPos, yPos, pal, effTyp, fontType);849 pattCharOut(xPos, yPos, effTyp, fontType, color);
623 pattCharOut(xPos + charW, yPos, pal, eff >> 4, fontType);850 pattCharOut(xPos + charW, yPos, eff >> 4, fontType, color);
624 pattCharOut(xPos + (charW * 2), yPos, pal, eff & 0x0F, fontType);851 pattCharOut(xPos + (charW * 2), yPos, eff & 0x0F, fontType, color);
625}
626
627static void drawRowNumbers(const pattCoord_t *pattCoord, int16_t currRow, uint16_t rowHeight, uint16_t upperRowsYEnd, uint16_t pattLen)
628{
629 int16_t j, rowYPos, numRows;
630
631 // upper rows
632 numRows = currRow;
633 if (numRows > 0)
634 {
635 if (numRows > pattCoord->numUpperRows)
636 numRows = pattCoord->numUpperRows;
637
638 rowYPos = upperRowsYEnd;
639 for (j = 0; j < numRows; j++)
640 {
641 drawRowNum(rowYPos, currRow - j - 1, false);
642 rowYPos -= rowHeight;
643 }
644 }
645
646 // current row
647 drawRowNum(pattCoord->midRowTextY, currRow, true);
648
649 // lower rows
650 numRows = (pattLen - 1) - currRow;
651 if (numRows > 0)
652 {
653 if (numRows > pattCoord->numLowerRows)
654 numRows = pattCoord->numLowerRows;
655
656 rowYPos = pattCoord->lowerRowsTextY;
657 for (j = 0; j < numRows; j++)
658 {
659 drawRowNum(rowYPos, currRow + j + 1, false);
660 rowYPos += rowHeight;
661 }
662 }
663}852}
664 853
665void writePattern(int16_t currRow, int16_t pattern)854void writePattern(int32_t currRow, int32_t pattern)
666{855{
667 uint8_t chans, chNum;856 int32_t row, rowsOnScreen, numRows, afterCurrRow, numChannels;
668 int16_t numRows, j;857 int32_t textY, midRowTextY, lowerRowsTextY, xPos, xWidth;
669 uint16_t pattLen, xPos, rowYPos, rowHeight, chanWidth, upperRowsYEnd;858 uint32_t rowHeight, chanWidth, chans, noteTextColors[2], color;
670 tonTyp *note, *pattPtr;859 tonTyp *note, *pattPtr;
671 const pattCoord_t *pattCoord;860 const pattCoord_t *pattCoord;
672 void (*drawNote)(uint8_t, uint16_t, uint16_t, int16_t);861 void (*drawNote)(uint32_t, uint32_t, int16_t, uint32_t);
673 void (*drawInst)(uint8_t, uint16_t, uint16_t, uint8_t);862 void (*drawInst)(uint32_t, uint32_t, uint8_t, uint32_t);
674 void (*drawVolEfx)(uint8_t, uint16_t, uint16_t, uint8_t);863 void (*drawVolEfx)(uint32_t, uint32_t, uint8_t, uint32_t);
675 void (*drawEfx)(uint8_t, uint16_t, uint16_t, uint8_t, uint8_t);864 void (*drawEfx)(uint32_t, uint32_t, uint8_t, uint8_t, uint32_t);
676 865
677 /* We're too lazy to carefully erase things as needed, just render866 /* Draw pattern framework every time (erasing existing content).
678 ** the whole pattern framework first (fast enough on modern PCs) */867 ** FT2 doesn't do this. This is quite lazy and consumes more CPU
868 ** time than needed (overlapped drawing), but it makes the pattern
869 ** mark/cursor drawing MUCH simpler to implement...
870 */
679 drawPatternBorders();871 drawPatternBorders();
680 872
873 // setup variables
874
681 chans = editor.ui.numChannelsShown;875 chans = editor.ui.numChannelsShown;
682 if (chans > editor.ui.maxVisibleChannels)876 if (chans > editor.ui.maxVisibleChannels)
683 chans = editor.ui.maxVisibleChannels;877 chans = editor.ui.maxVisibleChannels;
@@ -686,18 +880,26 @@ void writePattern(int16_t currRow, int16_t pattern) · 2 unmodified lines
686 880
687 // get channel width881 // get channel width
688 chanWidth = chanWidths[(chans / 2) - 1];882 chanWidth = chanWidths[(chans / 2) - 1];
689 editor.ui.patternChannelWidth = chanWidth + 3;883 editor.ui.patternChannelWidth = (uint16_t)(chanWidth + 3);
690 884
691 // get heights/pos/rows depending on configuration885 // get heights/pos/rows depending on configuration
692 pattCoord = &pattCoordTable[config.ptnUnpressed][editor.ui.pattChanScrollShown][editor.ui.extended];
693 rowHeight = config.ptnUnpressed ? 11 : 8;886 rowHeight = config.ptnUnpressed ? 11 : 8;
694 upperRowsYEnd = pattCoord->upperRowsTextY + ((pattCoord->numUpperRows - 1) * rowHeight);887 pattCoord = &pattCoordTable[config.ptnUnpressed][editor.ui.pattChanScrollShown][editor.ui.extended];
695 888 midRowTextY = pattCoord->midRowTextY;
889 lowerRowsTextY = pattCoord->lowerRowsTextY;
890 row = currRow - pattCoord->numUpperRows;
891 rowsOnScreen = pattCoord->numUpperRows + 1 + pattCoord->numLowerRows;
892 textY = pattCoord->upperRowsTextY;
893
894 afterCurrRow = currRow + 1;
895 numChannels = editor.ui.numChannelsShown;
696 pattPtr = patt[pattern];896 pattPtr = patt[pattern];
697 pattLen = pattLens[pattern];897 numRows = pattLens[pattern];
898 noteTextColors[0] = video.palette[PAL_PATTEXT]; // not selected
899 noteTextColors[1] = video.palette[PAL_FORGRND]; // selected
698 900
699 // draw row numbers901 if (pattPtr != NULL)
700 drawRowNumbers(pattCoord, currRow, rowHeight, upperRowsYEnd, pattLen);902 pattPtr += editor.ui.channelOffset;
701 903
702 // set up function pointers for drawing904 // set up function pointers for drawing
703 if (config.ptnS3M)905 if (config.ptnS3M)
@@ -716,148 +918,76 @@ void writePattern(int16_t currRow, int16_t pattern) · 12 unmodified lines
716 }918 }
717 919
718 // draw pattern data920 // draw pattern data
719 921 for (int32_t i = 0; i < rowsOnScreen; i++)
720 xPos = 29;
721 for (uint8_t i = 0; i < editor.ui.numChannelsShown; i++)
722 {922 {
723 chNum = editor.ui.channelOffset + i;923 if (row >= 0)
724
725 // upper rows
726 numRows = currRow;
727 if (numRows > 0)
728 {924 {
729 if (numRows > pattCoord->numUpperRows)925 bool selectedRowFlag = row == currRow;
730 numRows = pattCoord->numUpperRows;
731
732 rowYPos = upperRowsYEnd;
733 926
927 drawRowNums(textY, (uint8_t)row, selectedRowFlag);
928
734 if (pattPtr == NULL)929 if (pattPtr == NULL)
735 note = &emptyNote;930 note = emptyPattern;
736 else931 else
737 note = &pattPtr[((currRow - 1) * MAX_VOICES) + chNum];932 note = &pattPtr[(uint32_t)row * MAX_VOICES];
738 933
739 for (j = 0; j < numRows; j++)934 xPos = 29;
740 {935 xWidth = editor.ui.patternChannelWidth;
741 drawNote(PAL_PATTEXT, xPos, rowYPos, note->ton);
742 drawInst(PAL_PATTEXT, xPos, rowYPos, note->instr);
743 drawVolEfx(PAL_PATTEXT, xPos, rowYPos, note->vol);
744 drawEfx(PAL_PATTEXT, xPos, rowYPos, note->effTyp, note->eff);
745 936
746 if (pattPtr != NULL)937 color = noteTextColors[selectedRowFlag];
747 note -= MAX_VOICES;938 for (int32_t j = 0; j < numChannels; j++)
939 {
940 drawNote(xPos, textY, note->ton, color);
941 drawInst(xPos, textY, note->instr, color);
942 drawVolEfx(xPos, textY, note->vol, color);
943 drawEfx(xPos, textY, note->effTyp, note->eff, color);
748 944
749 rowYPos -= rowHeight;945 xPos += xWidth;
946 note++;
750 }947 }
751 }948 }
752 949
753 // current row950 // next row
951 if (++row >= numRows)
952 break;
754 953
755 if (pattPtr == NULL)954 // adjust textY position
756 note = &emptyNote;955 if (row == currRow)
956 textY = midRowTextY;
957 else if (row == afterCurrRow)
958 textY = lowerRowsTextY;
757 else959 else
758 note = &pattPtr[(currRow * MAX_VOICES) + chNum];960 textY += rowHeight;
759
760 rowYPos = pattCoord->midRowTextY;
761
762 drawNote(PAL_FORGRND, xPos, rowYPos, note->ton);
763 drawInst(PAL_FORGRND, xPos, rowYPos, note->instr);
764 drawVolEfx(PAL_FORGRND, xPos, rowYPos, note->vol);
765 drawEfx(PAL_FORGRND, xPos, rowYPos, note->effTyp, note->eff);
766
767 // lower rows
768 numRows = (pattLen - 1) - currRow;
769 if (numRows > 0)
770 {
771 if (numRows > pattCoord->numLowerRows)
772 numRows = pattCoord->numLowerRows;
773
774 rowYPos = pattCoord->lowerRowsTextY;
775
776 if (pattPtr == NULL)
777 note = &emptyNote;
778 else
779 note = &pattPtr[((currRow + 1) * MAX_VOICES) + chNum];
780
781 for (j = 0; j < numRows; j++)
782 {
783 drawNote(PAL_PATTEXT, xPos, rowYPos, note->ton);
784 drawInst(PAL_PATTEXT, xPos, rowYPos, note->instr);
785 drawVolEfx(PAL_PATTEXT, xPos, rowYPos, note->vol);
786 drawEfx(PAL_PATTEXT, xPos, rowYPos, note->effTyp, note->eff);
787
788 if (pattPtr != NULL)
789 note += MAX_VOICES;
790
791 rowYPos += rowHeight;
792 }
793 }
794
795 xPos += editor.ui.patternChannelWidth;
796 }961 }
797 962
798 writeCursor();963 writeCursor();
799 964
800 if (pattMark.markY1 != pattMark.markY2) // do we have a pattern mark?965 // draw pattern marking (if anything is marked)
966 if (pattMark.markY1 != pattMark.markY2)
801 writePatternBlockMark(currRow, rowHeight, pattCoord);967 writePatternBlockMark(currRow, rowHeight, pattCoord);
802 968
803 // channel numbers must be drawn in the very end969 // channel numbers must be drawn lastly
804 if (config.ptnChnNumbers)970 if (config.ptnChnNumbers)
805 drawChannelNumbering(pattCoord->upperRowsTextY);971 drawChannelNumbering(pattCoord->upperRowsTextY);
806}972}
807 973
808// ========== OPTIMIZED CHARACTER DRAWING ROUTINES FOR PATTERN EDITOR ==========974// ========== OPTIMIZED CHARACTER DRAWING ROUTINES FOR PATTERN EDITOR ==========
809 975
810void pattTwoHexOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint8_t val)976void pattTwoHexOut(uint32_t xPos, uint32_t yPos, uint8_t val, uint32_t color)
811{977{
812 const uint8_t *ch1Ptr, *ch2Ptr;978 const uint8_t *ch1Ptr, *ch2Ptr;
813 uint32_t *dstPtr, pixVal, offset;979 uint32_t *dstPtr;
814 980
815 pixVal = video.palette[paletteIndex];981 ch1Ptr = &font4Ptr[(val >> 4) * FONT4_CHAR_W];
816 offset = config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H);982 ch2Ptr = &font4Ptr[(val & 0x0F) * FONT4_CHAR_W];
817 ch1Ptr = &font4Data[((val >> 4) * FONT4_CHAR_W) + offset];
818 ch2Ptr = &font4Data[((val & 0x0F) * FONT4_CHAR_W) + offset];
819 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];983 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
820 984
821 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)985 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
822 {986 {
823 for (uint32_t x = 0; x < FONT4_CHAR_W; x++)987 for (uint32_t x = 0; x < FONT4_CHAR_W; x++)
824 {988 {
825 if (ch1Ptr[x]) dstPtr[x] = pixVal;989 if (ch1Ptr[x]) dstPtr[x] = color;
826 if (ch2Ptr[x]) dstPtr[FONT4_CHAR_W + x] = pixVal;990 if (ch2Ptr[x]) dstPtr[FONT4_CHAR_W + x] = color;
827 }
828
829 ch1Ptr += FONT4_WIDTH;
830 ch2Ptr += FONT4_WIDTH;
831 dstPtr += SCREEN_W;
832 }
833}
834
835static void rowNumOut(uint32_t yPos, uint8_t paletteIndex, uint8_t rowChar1, uint8_t rowChar2)
836{
837 const uint8_t *ch1Ptr, *ch2Ptr;
838 uint32_t *dstPtr, pixVal, offset;
839
840 pixVal = video.palette[paletteIndex];
841 offset = config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H);
842 ch1Ptr = &font4Data[(rowChar1 * FONT4_CHAR_W) + offset];
843 ch2Ptr = &font4Data[(rowChar2 * FONT4_CHAR_W) + offset];
844 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + 8];
845
846 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
847 {
848 for (uint32_t x = 0; x < FONT4_CHAR_W; x++)
849 {
850 if (ch1Ptr[x])
851 {
852 dstPtr[x] = pixVal; // left side
853 dstPtr[600 + x] = pixVal; // right side
854 }
855
856 if (ch2Ptr[x])
857 {
858 dstPtr[ FONT4_CHAR_W + x] = pixVal; // left side
859 dstPtr[(600 + FONT4_CHAR_W) + x] = pixVal; // right side
860 }
861 }991 }
862 992
863 ch1Ptr += FONT4_WIDTH;993 ch1Ptr += FONT4_WIDTH;
@@ -866,12 +996,11 @@ static void rowNumOut(uint32_t yPos, uint8_t paletteIndex, uint8_t rowChar1, uin · 2 unmodified lines
866 }996 }
867}997}
868 998
869static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint8_t chr, uint8_t fontType)999static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t chr, uint8_t fontType, uint32_t color)
870{1000{
871 const uint8_t *srcPtr;1001 const uint8_t *srcPtr;
872 uint32_t x, y, *dstPtr, pixVal;1002 uint32_t x, y, *dstPtr;
873 1003
874 pixVal = video.palette[paletteIndex];
875 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1004 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
876 1005
877 if (fontType == FONT_TYPE3)1006 if (fontType == FONT_TYPE3)
@@ -882,7 +1011,7 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint · 4 unmodified lines
882 for (x = 0; x < FONT3_CHAR_W; x++)1011 for (x = 0; x < FONT3_CHAR_W; x++)
883 {1012 {
884 if (srcPtr[x])1013 if (srcPtr[x])
885 dstPtr[x] = pixVal;1014 dstPtr[x] = color;
886 }1015 }
887 1016
888 srcPtr += FONT3_WIDTH;1017 srcPtr += FONT3_WIDTH;
@@ -891,13 +1020,13 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint · 2 unmodified lines
891 }1020 }
892 else if (fontType == FONT_TYPE4)1021 else if (fontType == FONT_TYPE4)
893 {1022 {
894 srcPtr = &font4Data[(chr * FONT4_CHAR_W) + (config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H))];1023 srcPtr = &font4Ptr[chr * FONT4_CHAR_W];
895 for (y = 0; y < FONT4_CHAR_H; y++)1024 for (y = 0; y < FONT4_CHAR_H; y++)
896 {1025 {
897 for (x = 0; x < FONT4_CHAR_W; x++)1026 for (x = 0; x < FONT4_CHAR_W; x++)
898 {1027 {
899 if (srcPtr[x])1028 if (srcPtr[x])
900 dstPtr[x] = pixVal;1029 dstPtr[x] = color;
901 }1030 }
902 1031
903 srcPtr += FONT4_WIDTH;1032 srcPtr += FONT4_WIDTH;
@@ -906,13 +1035,13 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint · 2 unmodified lines
906 }1035 }
907 else if (fontType == FONT_TYPE5)1036 else if (fontType == FONT_TYPE5)
908 {1037 {
909 srcPtr = &font5Data[(chr * FONT5_CHAR_W) + (config.ptnFont * (FONT5_WIDTH * FONT5_CHAR_H))];1038 srcPtr = &font5Ptr[chr * FONT5_CHAR_W];
910 for (y = 0; y < FONT5_CHAR_H; y++)1039 for (y = 0; y < FONT5_CHAR_H; y++)
911 {1040 {
912 for (x = 0; x < FONT5_CHAR_W; x++)1041 for (x = 0; x < FONT5_CHAR_W; x++)
913 {1042 {
914 if (srcPtr[x])1043 if (srcPtr[x])
915 dstPtr[x] = pixVal;1044 dstPtr[x] = color;
916 }1045 }
917 1046
918 srcPtr += FONT5_WIDTH;1047 srcPtr += FONT5_WIDTH;
@@ -927,7 +1056,7 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint · 8 unmodified lines
927 for (x = 0; x < FONT7_CHAR_W; x++)1056 for (x = 0; x < FONT7_CHAR_W; x++)
928 {1057 {
929 if (srcPtr[x])1058 if (srcPtr[x])
930 dstPtr[x] = pixVal;1059 dstPtr[x] = color;
931 }1060 }
932 1061
933 srcPtr += FONT7_WIDTH;1062 srcPtr += FONT7_WIDTH;
@@ -936,12 +1065,11 @@ static void pattCharOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint · 2 unmodified lines
936 }1065 }
937}1066}
938 1067
939static void drawEmptyNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex)1068static void drawEmptyNoteSmall(uint32_t xPos, uint32_t yPos, uint32_t color)
940{1069{
941 const uint8_t *srcPtr;1070 const uint8_t *srcPtr;
942 uint32_t *dstPtr, pixVal;1071 uint32_t *dstPtr;
943 1072
944 pixVal = video.palette[paletteIndex];
945 srcPtr = &font7Data[18 * FONT7_CHAR_W];1073 srcPtr = &font7Data[18 * FONT7_CHAR_W];
946 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1074 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
947 1075
@@ -950,7 +1078,7 @@ static void drawEmptyNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteInde · 2 unmodified lines
950 for (uint32_t x = 0; x < FONT7_CHAR_W*3; x++)1078 for (uint32_t x = 0; x < FONT7_CHAR_W*3; x++)
951 {1079 {
952 if (srcPtr[x])1080 if (srcPtr[x])
953 dstPtr[x] = pixVal;1081 dstPtr[x] = color;
954 }1082 }
955 1083
956 srcPtr += FONT7_WIDTH;1084 srcPtr += FONT7_WIDTH;
@@ -958,12 +1086,11 @@ static void drawEmptyNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteInde · 1 unmodified line
958 }1086 }
959}1087}
960 1088
961static void drawKeyOffSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex)1089static void drawKeyOffSmall(uint32_t xPos, uint32_t yPos, uint32_t color)
962{1090{
963 const uint8_t *srcPtr;1091 const uint8_t *srcPtr;
964 uint32_t *dstPtr, pixVal;1092 uint32_t *dstPtr;
965 1093
966 pixVal = video.palette[paletteIndex];
967 srcPtr = &font7Data[21 * FONT7_CHAR_W];1094 srcPtr = &font7Data[21 * FONT7_CHAR_W];
968 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + (xPos + 2)];1095 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + (xPos + 2)];
969 1096
@@ -972,7 +1099,7 @@ static void drawKeyOffSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 2 unmodified lines
972 for (uint32_t x = 0; x < FONT7_CHAR_W*2; x++)1099 for (uint32_t x = 0; x < FONT7_CHAR_W*2; x++)
973 {1100 {
974 if (srcPtr[x])1101 if (srcPtr[x])
975 dstPtr[x] = pixVal;1102 dstPtr[x] = color;
976 }1103 }
977 1104
978 srcPtr += FONT7_WIDTH;1105 srcPtr += FONT7_WIDTH;
@@ -980,18 +1107,18 @@ static void drawKeyOffSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
980 }1107 }
981}1108}
982 1109
983static void drawNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, int16_t ton)1110static void drawNoteSmall(uint32_t xPos, uint32_t yPos, int32_t ton, uint32_t color)
984{1111{
985 const uint8_t *ch1Ptr, *ch2Ptr, *ch3Ptr;1112 const uint8_t *ch1Ptr, *ch2Ptr, *ch3Ptr;
986 uint8_t note;1113 uint8_t note;
987 uint32_t *dstPtr, pixVal, char1, char2, char3;1114 uint32_t *dstPtr, char1, char2, char3;
988 1115
989 assert(ton >= 1 && ton <= 97);1116 assert(ton >= 1 && ton <= 97);
990 1117
991 ton--;1118 ton--;
992 1119
993 note = ton % 12;1120 note = noteTab1[ton];
994 char3 = (ton / 12) * FONT7_CHAR_W;1121 char3 = noteTab2[ton] * FONT7_CHAR_W;
995 1122
996 if (config.ptnAcc == 0)1123 if (config.ptnAcc == 0)
997 {1124 {
@@ -1004,7 +1131,6 @@ static void drawNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, in · 6 unmodified lines
1004 char2 = flatNote2Char_small[note];1131 char2 = flatNote2Char_small[note];
1005 }1132 }
1006 1133
1007 pixVal = video.palette[paletteIndex];
1008 ch1Ptr = &font7Data[char1];1134 ch1Ptr = &font7Data[char1];
1009 ch2Ptr = &font7Data[char2];1135 ch2Ptr = &font7Data[char2];
1010 ch3Ptr = &font7Data[char3];1136 ch3Ptr = &font7Data[char3];
@@ -1014,9 +1140,9 @@ static void drawNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, in · 3 unmodified lines
1014 {1140 {
1015 for (uint32_t x = 0; x < FONT7_CHAR_W; x++)1141 for (uint32_t x = 0; x < FONT7_CHAR_W; x++)
1016 {1142 {
1017 if (ch1Ptr[x]) dstPtr[ (FONT7_CHAR_W * 0) + x] = pixVal;1143 if (ch1Ptr[x]) dstPtr[ (FONT7_CHAR_W * 0) + x] = color;
1018 if (ch2Ptr[x]) dstPtr[ (FONT7_CHAR_W * 1) + x] = pixVal;1144 if (ch2Ptr[x]) dstPtr[ (FONT7_CHAR_W * 1) + x] = color;
1019 if (ch3Ptr[x]) dstPtr[((FONT7_CHAR_W * 2) - 2) + x] = pixVal;1145 if (ch3Ptr[x]) dstPtr[((FONT7_CHAR_W * 2) - 2) + x] = color;
1020 }1146 }
1021 1147
1022 ch1Ptr += FONT7_WIDTH;1148 ch1Ptr += FONT7_WIDTH;
@@ -1026,21 +1152,20 @@ static void drawNoteSmall(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, in · 3 unmodified lines
1026 }1152 }
1027}1153}
1028 1154
1029static void drawEmptyNoteMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex)1155static void drawEmptyNoteMedium(uint32_t xPos, uint32_t yPos, uint32_t color)
1030{1156{
1031 const uint8_t *srcPtr;1157 const uint8_t *srcPtr;
1032 uint32_t *dstPtr, pixVal;1158 uint32_t *dstPtr;
1033 1159
1034 pixVal = video.palette[paletteIndex];
1035 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1160 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
1036 srcPtr = &font4Data[(43 * FONT4_CHAR_W) + (config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H))];1161 srcPtr = &font4Ptr[43 * FONT4_CHAR_W];
1037 1162
1038 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)1163 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
1039 {1164 {
1040 for (uint32_t x = 0; x < FONT4_CHAR_W*3; x++)1165 for (uint32_t x = 0; x < FONT4_CHAR_W*3; x++)
1041 {1166 {
1042 if (srcPtr[x])1167 if (srcPtr[x])
1043 dstPtr[x] = pixVal;1168 dstPtr[x] = color;
1044 }1169 }
1045 1170
1046 srcPtr += FONT4_WIDTH;1171 srcPtr += FONT4_WIDTH;
@@ -1048,13 +1173,12 @@ static void drawEmptyNoteMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteInd · 1 unmodified line
1048 }1173 }
1049}1174}
1050 1175
1051static void drawKeyOffMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex)1176static void drawKeyOffMedium(uint32_t xPos, uint32_t yPos, uint32_t color)
1052{1177{
1053 const uint8_t *srcPtr;1178 const uint8_t *srcPtr;
1054 uint32_t *dstPtr, pixVal;1179 uint32_t *dstPtr;
1055 1180
1056 pixVal = video.palette[paletteIndex];1181 srcPtr = &font4Ptr[40 * FONT4_CHAR_W];
1057 srcPtr = &font4Data[(40 * FONT4_CHAR_W) + (config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H))];
1058 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1182 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
1059 1183
1060 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)1184 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
@@ -1062,7 +1186,7 @@ static void drawKeyOffMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
1062 for (uint32_t x = 0; x < FONT4_CHAR_W*3; x++)1186 for (uint32_t x = 0; x < FONT4_CHAR_W*3; x++)
1063 {1187 {
1064 if (srcPtr[x])1188 if (srcPtr[x])
1065 dstPtr[x] = pixVal;1189 dstPtr[x] = color;
1066 }1190 }
1067 1191
1068 srcPtr += FONT4_WIDTH;1192 srcPtr += FONT4_WIDTH;
@@ -1070,16 +1194,15 @@ static void drawKeyOffMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
1070 }1194 }
1071}1195}
1072 1196
1073static void drawNoteMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, int16_t ton)1197static void drawNoteMedium(uint32_t xPos, uint32_t yPos, int32_t ton, uint32_t color)
1074{1198{
1075 const uint8_t *ch1Ptr, *ch2Ptr, *ch3Ptr;1199 const uint8_t *ch1Ptr, *ch2Ptr, *ch3Ptr;
1076 uint8_t note;1200 uint32_t note, *dstPtr, char1, char2, char3;
1077 uint32_t *dstPtr, pixVal, fontOffset, char1, char2, char3;
1078 1201
1079 ton--;1202 ton--;
1080 1203
1081 note = ton % 12;1204 note = noteTab1[ton];
1082 char3 = (ton / 12) * FONT4_CHAR_W;1205 char3 = noteTab2[ton] * FONT4_CHAR_W;
1083 1206
1084 if (config.ptnAcc == 0)1207 if (config.ptnAcc == 0)
1085 {1208 {
@@ -1092,20 +1215,18 @@ static void drawNoteMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, i · 6 unmodified lines
1092 char2 = flatNote2Char_med[note];1215 char2 = flatNote2Char_med[note];
1093 }1216 }
1094 1217
1095 pixVal = video.palette[paletteIndex];1218 ch1Ptr = &font4Ptr[char1];
1096 fontOffset = config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H);1219 ch2Ptr = &font4Ptr[char2];
1097 ch1Ptr = &font4Data[char1 + fontOffset];1220 ch3Ptr = &font4Ptr[char3];
1098 ch2Ptr = &font4Data[char2 + fontOffset];
1099 ch3Ptr = &font4Data[char3 + fontOffset];
1100 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1221 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
1101 1222
1102 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)1223 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
1103 {1224 {
1104 for (uint32_t x = 0; x < FONT4_CHAR_W; x++)1225 for (uint32_t x = 0; x < FONT4_CHAR_W; x++)
1105 {1226 {
1106 if (ch1Ptr[x]) dstPtr[(FONT4_CHAR_W * 0) + x] = pixVal;1227 if (ch1Ptr[x]) dstPtr[(FONT4_CHAR_W * 0) + x] = color;
1107 if (ch2Ptr[x]) dstPtr[(FONT4_CHAR_W * 1) + x] = pixVal;1228 if (ch2Ptr[x]) dstPtr[(FONT4_CHAR_W * 1) + x] = color;
1108 if (ch3Ptr[x]) dstPtr[(FONT4_CHAR_W * 2) + x] = pixVal;1229 if (ch3Ptr[x]) dstPtr[(FONT4_CHAR_W * 2) + x] = color;
1109 }1230 }
1110 1231
1111 ch1Ptr += FONT4_WIDTH;1232 ch1Ptr += FONT4_WIDTH;
@@ -1115,13 +1236,12 @@ static void drawNoteMedium(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, i · 3 unmodified lines
1115 }1236 }
1116}1237}
1117 1238
1118static void drawEmptyNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex)1239static void drawEmptyNoteBig(uint32_t xPos, uint32_t yPos, uint32_t color)
1119{1240{
1120 const uint8_t *srcPtr;1241 const uint8_t *srcPtr;
1121 uint32_t *dstPtr, pixVal;1242 uint32_t *dstPtr;
1122 1243
1123 pixVal = video.palette[paletteIndex];1244 srcPtr = &font4Ptr[67 * FONT4_CHAR_W];
1124 srcPtr = &font4Data[(67 * FONT4_CHAR_W) + (config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H))];
1125 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1245 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
1126 1246
1127 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)1247 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
@@ -1129,7 +1249,7 @@ static void drawEmptyNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
1129 for (uint32_t x = 0; x < FONT4_CHAR_W*6; x++)1249 for (uint32_t x = 0; x < FONT4_CHAR_W*6; x++)
1130 {1250 {
1131 if (srcPtr[x])1251 if (srcPtr[x])
1132 dstPtr[x] = pixVal;1252 dstPtr[x] = color;
1133 }1253 }
1134 1254
1135 srcPtr += FONT4_WIDTH;1255 srcPtr += FONT4_WIDTH;
@@ -1137,13 +1257,12 @@ static void drawEmptyNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
1137 }1257 }
1138}1258}
1139 1259
1140static void drawKeyOffBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex)1260static void drawKeyOffBig(uint32_t xPos, uint32_t yPos, uint32_t color)
1141{1261{
1142 const uint8_t *srcPtr;1262 const uint8_t *srcPtr;
1143 uint32_t *dstPtr, pixVal;1263 uint32_t *dstPtr;
1144 1264
1145 pixVal = video.palette[paletteIndex];1265 srcPtr = &font4Data[61 * FONT4_CHAR_W];
1146 srcPtr = &font4Data[(61 * FONT4_CHAR_W) + (config.ptnFont * (FONT4_WIDTH * FONT4_CHAR_H))];
1147 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1266 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
1148 1267
1149 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)1268 for (uint32_t y = 0; y < FONT4_CHAR_H; y++)
@@ -1151,7 +1270,7 @@ static void drawKeyOffBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
1151 for (uint32_t x = 0; x < FONT4_CHAR_W*6; x++)1270 for (uint32_t x = 0; x < FONT4_CHAR_W*6; x++)
1152 {1271 {
1153 if (srcPtr[x])1272 if (srcPtr[x])
1154 dstPtr[x] = pixVal;1273 dstPtr[x] = color;
1155 }1274 }
1156 1275
1157 srcPtr += FONT4_WIDTH;1276 srcPtr += FONT4_WIDTH;
@@ -1159,16 +1278,16 @@ static void drawKeyOffBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex) · 1 unmodified line
1159 }1278 }
1160}1279}
1161 1280
1162static void drawNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, int16_t ton)1281static void drawNoteBig(uint32_t xPos, uint32_t yPos, int32_t ton, uint32_t color)
1163{1282{
1164 const uint8_t *ch1Ptr, *ch2Ptr, *ch3Ptr;1283 const uint8_t *ch1Ptr, *ch2Ptr, *ch3Ptr;
1165 uint8_t note;1284 uint8_t note;
1166 uint32_t *dstPtr, pixVal, fontOffset, char1, char2, char3;1285 uint32_t *dstPtr, char1, char2, char3;
1167 1286
1168 ton--;1287 ton--;
1169 1288
1170 note = ton % 12;1289 note = noteTab1[ton];
1171 char3 = (ton / 12) * FONT5_CHAR_W;1290 char3 = noteTab2[ton] * FONT5_CHAR_W;
1172 1291
1173 if (config.ptnAcc == 0)1292 if (config.ptnAcc == 0)
1174 {1293 {
@@ -1181,20 +1300,18 @@ static void drawNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, int1 · 6 unmodified lines
1181 char2 = flatNote2Char_big[note];1300 char2 = flatNote2Char_big[note];
1182 }1301 }
1183 1302
1184 pixVal = video.palette[paletteIndex];1303 ch1Ptr = &font5Ptr[char1];
1185 fontOffset = config.ptnFont * (FONT5_WIDTH * FONT5_CHAR_H);1304 ch2Ptr = &font5Ptr[char2];
1186 ch1Ptr = &font5Data[char1 + fontOffset];1305 ch3Ptr = &font5Ptr[char3];
1187 ch2Ptr = &font5Data[char2 + fontOffset];
1188 ch3Ptr = &font5Data[char3 + fontOffset];
1189 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];1306 dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
1190 1307
1191 for (uint32_t y = 0; y < FONT5_CHAR_H; y++)1308 for (uint32_t y = 0; y < FONT5_CHAR_H; y++)
1192 {1309 {
1193 for (uint32_t x = 0; x < FONT5_CHAR_W; x++)1310 for (uint32_t x = 0; x < FONT5_CHAR_W; x++)
1194 {1311 {
1195 if (ch1Ptr[x]) dstPtr[(FONT5_CHAR_W * 0) + x] = pixVal;1312 if (ch1Ptr[x]) dstPtr[(FONT5_CHAR_W * 0) + x] = color;
1196 if (ch2Ptr[x]) dstPtr[(FONT5_CHAR_W * 1) + x] = pixVal;1313 if (ch2Ptr[x]) dstPtr[(FONT5_CHAR_W * 1) + x] = color;
1197 if (ch3Ptr[x]) dstPtr[(FONT5_CHAR_W * 2) + x] = pixVal;1314 if (ch3Ptr[x]) dstPtr[(FONT5_CHAR_W * 2) + x] = color;
1198 }1315 }
1199 1316
1200 ch1Ptr += FONT5_WIDTH;1317 ch1Ptr += FONT5_WIDTH;
@@ -1203,145 +1320,3 @@ static void drawNoteBig(uint16_t xPos, uint16_t yPos, uint8_t paletteIndex, int1 · 2 unmodified lines
1203 dstPtr += SCREEN_W;1320 dstPtr += SCREEN_W;
1204 }1321 }
1205}1322}
1206
1207const pattCoord_t pattCoordTable[2][2][2] =
1208{
1209 /*
1210 uint16_t upperRowsY, lowerRowsY;
1211 uint16_t upperRowsTextY, midRowTextY, lowerRowsTextY;
1212 uint16_t numUpperRows, numLowerRows;
1213 */
1214
1215 // no pattern stretch
1216 {
1217 // no pattern channel scroll
1218 {
1219 { 176, 292, 177, 283, 293, 13, 13 }, // normal pattern editor
1220 { 56, 228, 57, 219, 229, 20, 21 }, // extended pattern editor
1221 },
1222
1223 // pattern channel scroll
1224 {
1225 { 176, 285, 177, 276, 286, 12, 12 }, // normal pattern editor
1226 { 56, 221, 57, 212, 222, 19, 20 }, // extended pattern editor
1227 }
1228 },
1229
1230 // pattern stretch
1231 {
1232 // no pattern channel scroll
1233 {
1234 { 177, 286, 178, 277, 288, 9, 10 }, // normal pattern editor
1235 { 56, 232, 58, 223, 234, 15, 15 }, // extended pattern editor
1236 },
1237
1238 // pattern channel scroll
1239 {
1240 { 176, 285, 177, 276, 286, 9, 9 }, // normal pattern editor
1241 { 56, 220, 57, 211, 221, 14, 15 }, // extended pattern editor
1242 },
1243 }
1244};
1245
1246const pattCoord2_t pattCoord2Table[2][2][2] =
1247{
1248 /*
1249 uint16_t upperRowsY, lowerRowsY;
1250 uint16_t upperRowsH, lowerRowsH;
1251 */
1252
1253 // no pattern stretch
1254 {
1255 // no pattern channel scroll
1256 {
1257 { 175, 291, 107, 107 }, // normal pattern editor
1258 { 55, 227, 163, 171 }, // extended pattern editor
1259 },
1260
1261 // pattern channel scroll
1262 {
1263 { 175, 284, 100, 100 }, // normal pattern editor
1264 { 55, 220, 156, 164 }, // extended pattern editor
1265 }
1266 },
1267
1268 // pattern stretch
1269 {
1270 // no pattern channel scroll
1271 {
1272 { 175, 285, 101, 113 }, // normal pattern editor
1273 { 55, 231, 167, 167 }, // extended pattern editor
1274 },
1275
1276 // pattern channel scroll
1277 {
1278 { 175, 284, 100, 100 }, // normal pattern editor
1279 { 55, 219, 155, 165 }, // extended pattern editor
1280 },
1281 }
1282};
1283
1284const markCoord_t markCoordTable[2][2][2] =
1285{
1286 // uint16_t upperRowsY, midRowY, lowerRowsY;
1287
1288 // no pattern stretch
1289 {
1290 // no pattern channel scroll
1291 {
1292 { 177, 281, 293 }, // normal pattern editor
1293 { 57, 217, 229 }, // extended pattern editor
1294 },
1295
1296 // pattern channel scroll
1297 {
1298 { 177, 274, 286 }, // normal pattern editor
1299 { 57, 210, 222 }, // extended pattern editor
1300 }
1301 },
1302
1303 // pattern stretch
1304 {
1305 // no pattern channel scroll
1306 {
1307 { 176, 275, 286 }, // normal pattern editor
1308 { 56, 221, 232 }, // extended pattern editor
1309 },
1310
1311 // pattern channel scroll
1312 {
1313 { 175, 274, 284 }, // normal pattern editor
1314 { 55, 209, 219 }, // extended pattern editor
1315 },
1316 }
1317};
1318
1319const uint8_t pattCursorXTab[2 * 4 * 8] =
1320{
1321 // no volume column shown
1322 32, 88, 104, 0, 0, 120, 136, 152, // 4 columns visible
1323 32, 80, 88, 0, 0, 96, 104, 112, // 6 columns visible
1324 32, 56, 64, 0, 0, 72, 80, 88, // 8 columns visible
1325 32, 52, 56, 0, 0, 60, 64, 68, // 12 columns visible
1326
1327 // volume column shown
1328 32, 96, 104, 120, 128, 144, 152, 160, // 4 columns visible
1329 32, 56, 64, 80, 88, 96, 104, 112, // 6 columns visible
1330 32, 60, 64, 72, 76, 84, 88, 92, // 8 columns visible
1331 32, 60, 64, 72, 76, 84, 88, 92, // 12 columns visible
1332};
1333
1334const uint8_t pattCursorWTab[2 * 4 * 8] =
1335{
1336 // no volume column shown
1337 48, 16, 16, 0, 0, 16, 16, 16, // 4 columns visible
1338 48, 8, 8, 0, 0, 8, 8, 8, // 6 columns visible
1339 24, 8, 8, 0, 0, 8, 8, 8, // 8 columns visible
1340 16, 4, 4, 0, 0, 4, 4, 4, // 12 columns visible
1341
1342 // volume column shown
1343 48, 8, 8, 8, 8, 8, 8, 8, // 4 columns visible
1344 24, 8, 8, 8, 8, 8, 8, 8, // 6 columns visible
1345 24, 4, 4, 4, 4, 4, 4, 4, // 8 columns visible
1346 24, 4, 4, 4, 4, 4, 4, 4 // 12 columns visible
1347};
src/ft2_pattern_draw.h+3−2
@@ -2,6 +2,7 @@ · 1 unmodified line
2 2
3#include <stdint.h>3#include <stdint.h>
4 4
5void updatePattFontPtrs(void);
5void drawPatternBorders(void);6void drawPatternBorders(void);
6void writePattern(int16_t currRow, int16_t pattern);7void writePattern(int32_t currRow, int32_t pattern);
7void pattTwoHexOut(uint32_t xPos, uint32_t yPos, uint8_t paletteIndex, uint8_t val);8void pattTwoHexOut(uint32_t xPos, uint32_t yPos, uint8_t val, uint32_t color);
src/ft2_pattern_ed.c+26−13
@@ -21,6 +21,8 @@ · 20 unmodified lines
21#include "ft2_mouse.h"21#include "ft2_mouse.h"
22#include "ft2_video.h"22#include "ft2_video.h"
23 23
24#include "ft2_module_loader.h"
25
24// for pattern marking w/ keyboard26// for pattern marking w/ keyboard
25static int8_t lastChMark;27static int8_t lastChMark;
26static int16_t lastRowMark;28static int16_t lastRowMark;
@@ -657,7 +659,13 @@ void patternEditorExtended(void) · 630 unmodified lines
657 drawFramework(2, 2, 51, 20, FRAMEWORK_TYPE2);659 drawFramework(2, 2, 51, 20, FRAMEWORK_TYPE2);
658 drawFramework(2, 31, 51, 20, FRAMEWORK_TYPE2);660 drawFramework(2, 31, 51, 20, FRAMEWORK_TYPE2);
659 661
662 // force updating of end/page/length when showing scrollbar
663 scrollBars[SB_POS_ED].oldEnd = 0xFFFFFFFF;
664 scrollBars[SB_POS_ED].oldPage = 0xFFFFFFFF;
665 scrollBars[SB_POS_ED].oldPos = 0xFFFFFFFF;
666
660 showScrollBar(SB_POS_ED);667 showScrollBar(SB_POS_ED);
668
661 showPushButton(PB_POSED_POS_UP);669 showPushButton(PB_POSED_POS_UP);
662 showPushButton(PB_POSED_POS_DOWN);670 showPushButton(PB_POSED_POS_DOWN);
663 showPushButton(PB_POSED_INS);671 showPushButton(PB_POSED_INS);
@@ -2063,6 +2071,10 @@ void drawPosEdNums(int16_t songPos) · 1399 unmodified lines
2063{2071{
2064 uint8_t y;2072 uint8_t y;
2065 int16_t entry;2073 int16_t entry;
2074 uint32_t color1, color2;
2075
2076 color1 = video.palette[PAL_PATTEXT];
2077 color2 = video.palette[PAL_FORGRND];
2066 2078
2067 if (songPos >= song.len)2079 if (songPos >= song.len)
2068 songPos = song.len - 1;2080 songPos = song.len - 1;
@@ -2092,13 +2104,13 @@ void drawPosEdNums(int16_t songPos) · 23 unmodified lines
2092 2104
2093 if (editor.ui.extended)2105 if (editor.ui.extended)
2094 {2106 {
2095 pattTwoHexOut(8, 4 + (y * 9), PAL_PATTEXT, (uint8_t)entry);2107 pattTwoHexOut(8, 4 + (y * 9), (uint8_t)entry, color1);
2096 pattTwoHexOut(32, 4 + (y * 9), PAL_PATTEXT, song.songTab[entry]);2108 pattTwoHexOut(32, 4 + (y * 9), song.songTab[entry], color1);
2097 }2109 }
2098 else2110 else
2099 {2111 {
2100 pattTwoHexOut(8, 4 + (y * 8), PAL_PATTEXT, (uint8_t)entry);2112 pattTwoHexOut(8, 4 + (y * 8), (uint8_t)entry, color1);
2101 pattTwoHexOut(32, 4 + (y * 8), PAL_PATTEXT, song.songTab[entry]);2113 pattTwoHexOut(32, 4 + (y * 8), song.songTab[entry], color1);
2102 }2114 }
2103 }2115 }
2104 2116
@@ -2107,13 +2119,13 @@ void drawPosEdNums(int16_t songPos) · 2 unmodified lines
2107 // middle2119 // middle
2108 if (editor.ui.extended)2120 if (editor.ui.extended)
2109 {2121 {
2110 pattTwoHexOut(8, 23, PAL_FORGRND, (uint8_t)songPos);2122 pattTwoHexOut(8, 23, (uint8_t)songPos, color2);
2111 pattTwoHexOut(32, 23, PAL_FORGRND, song.songTab[songPos]);2123 pattTwoHexOut(32, 23, song.songTab[songPos], color2);
2112 }2124 }
2113 else2125 else
2114 {2126 {
2115 pattTwoHexOut(8, 22, PAL_FORGRND, (uint8_t)songPos);2127 pattTwoHexOut(8, 22, (uint8_t)songPos, color2);
2116 pattTwoHexOut(32, 22, PAL_FORGRND, song.songTab[songPos]);2128 pattTwoHexOut(32, 22, song.songTab[songPos], color2);
2117 }2129 }
2118 2130
2119 // bottom two2131 // bottom two
@@ -2125,13 +2137,13 @@ void drawPosEdNums(int16_t songPos) · 5 unmodified lines
2125 2137
2126 if (editor.ui.extended)2138 if (editor.ui.extended)
2127 {2139 {
2128 pattTwoHexOut(8, 33 + (y * 9), PAL_PATTEXT, (uint8_t)entry);2140 pattTwoHexOut(8, 33 + (y * 9), (uint8_t)entry, color1);
2129 pattTwoHexOut(32, 33 + (y * 9), PAL_PATTEXT, song.songTab[entry]);2141 pattTwoHexOut(32, 33 + (y * 9), song.songTab[entry], color1);
2130 }2142 }
2131 else2143 else
2132 {2144 {
2133 pattTwoHexOut(8, 32 + (y * 8), PAL_PATTEXT, (uint8_t)entry);2145 pattTwoHexOut(8, 32 + (y * 8), (uint8_t)entry, color1);
2134 pattTwoHexOut(32, 32 + (y * 8), PAL_PATTEXT, song.songTab[entry]);2146 pattTwoHexOut(32, 32 + (y * 8), song.songTab[entry], color1);
2135 }2147 }
2136 }2148 }
2137}2149}
@@ -2256,7 +2268,7 @@ void drawPlaybackTime(void) · 118 unmodified lines
2256 char str[2 + 1];2268 char str[2 + 1];
2257 uint32_t a, MI_TimeH, MI_TimeM, MI_TimeS;2269 uint32_t a, MI_TimeH, MI_TimeM, MI_TimeS;
2258 2270
2259 a = ((song.musicTime / 256) * 5) / 512;2271 a = ((song.musicTime >> 8) * 5) >> 9;
2260 MI_TimeH = a / 3600;2272 MI_TimeH = a / 3600;
2261 a -= (MI_TimeH * 3600);2273 a -= (MI_TimeH * 3600);
2262 MI_TimeM = a / 60;2274 MI_TimeM = a / 60;
@@ -2803,6 +2815,7 @@ void pbToggleBadge(void) · 540 unmodified lines
2803 2815
2804void resetChannelOffset(void)2816void resetChannelOffset(void)
2805{2817{
2818 editor.ui.pattChanScrollShown = song.antChn > getMaxVisibleChannels();
2806 editor.cursor.object = CURSOR_NOTE;2819 editor.cursor.object = CURSOR_NOTE;
2807 editor.cursor.ch = 0;2820 editor.cursor.ch = 0;
2808 setScrollBarPos(SB_CHAN_SCROLL, 0, true);2821 setScrollBarPos(SB_CHAN_SCROLL, 0, true);
src/ft2_pattern_ed.h+0−1
@@ -74,7 +74,6 @@ void cursorLeft(void); · 73 unmodified lines
74void cursorRight(void);74void cursorRight(void);
75void chanLeft(void);75void chanLeft(void);
76void chanRight(void);76void chanRight(void);
77void writePattern(int16_t currRow, int16_t pattern);
78void showPatternEditor(void);77void showPatternEditor(void);
79void updateInstrumentSwitcher(void);78void updateInstrumentSwitcher(void);
80void hidePatternEditor(void);79void hidePatternEditor(void);
src/ft2_replayer.c+31−36
@@ -422,7 +422,7 @@ static void startTone(uint8_t ton, uint8_t effTyp, uint8_t eff, stmTyp *ch) · 421 unmodified lines
422 if (ton > 96) // non-FT2 security (should never happen because I clamp in the patt loaders now)422 if (ton > 96) // non-FT2 security (should never happen because I clamp in the patt loaders now)
423 ton = 96;423 ton = 96;
424 424
425 smp = ins->ta[ton-1] & 0x0F;425 smp = ins->ta[ton-1] & 0xF;
426 ch->sampleNr = smp;426 ch->sampleNr = smp;
427 427
428 s = &ins->samp[smp];428 s = &ins->samp[smp];
@@ -1208,9 +1208,9 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 779 unmodified lines
1208 uint8_t envPos;1208 uint8_t envPos;
1209 int16_t autoVibVal, panTmp;1209 int16_t autoVibVal, panTmp;
1210 uint16_t autoVibAmp, tmpPeriod, envVal;1210 uint16_t autoVibAmp, tmpPeriod, envVal;
1211 int32_t vol, tmp32;1211 int32_t tmp32;
1212 uint32_t vol;
1212 instrTyp *ins;1213 instrTyp *ins;
1213 double dVol;
1214 1214
1215 ins = ch->instrSeg;1215 ins = ch->instrSeg;
1216 1216
@@ -1257,7 +1257,7 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 40 unmodified lines
1257 {1257 {
1258 envPos = ins->envVRepS;1258 envPos = ins->envVRepS;
1259 ch->envVCnt = ins->envVP[envPos][0];1259 ch->envVCnt = ins->envVP[envPos][0];
1260 ch->envVAmp = (ins->envVP[envPos][1] & 0xFF) << 8;1260 ch->envVAmp = ins->envVP[envPos][1] << 8;
1261 }1261 }
1262 }1262 }
1263 1263
@@ -1284,7 +1284,7 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 20 unmodified lines
1284 ch->envVIPValue = 0;1284 ch->envVIPValue = 0;
1285 if (ins->envVP[envPos][0] > ins->envVP[envPos-1][0])1285 if (ins->envVP[envPos][0] > ins->envVP[envPos-1][0])
1286 {1286 {
1287 ch->envVIPValue = ((ins->envVP[envPos][1] - ins->envVP[envPos-1][1]) & 0xFF) << 8;1287 ch->envVIPValue = (ins->envVP[envPos][1] - ins->envVP[envPos-1][1]) << 8;
1288 ch->envVIPValue /= (ins->envVP[envPos][0] - ins->envVP[envPos-1][0]);1288 ch->envVIPValue /= (ins->envVP[envPos][0] - ins->envVP[envPos-1][0]);
1289 1289
1290 envVal = ch->envVAmp;1290 envVal = ch->envVAmp;
@@ -1303,10 +1303,10 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 12 unmodified lines
1303 ch->envVAmp += ch->envVIPValue;1303 ch->envVAmp += ch->envVIPValue;
1304 1304
1305 envVal = ch->envVAmp;1305 envVal = ch->envVAmp;
1306 if ((envVal >> 8) > 0x40)1306 if (envVal > 64*256)
1307 {1307 {
1308 if ((envVal >> 8) > (0x40+0xC0)/2)1308 if (envVal > 128*256)
1309 envVal = 16384;1309 envVal = 64*256;
1310 else1310 else
1311 envVal = 0;1311 envVal = 0;
1312 1312
@@ -1314,41 +1314,36 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 1 unmodified line
1314 }1314 }
1315 }1315 }
1316 1316
1317 /* old integer method with low precision (FT2 way)1317 /* original FT2 method with lower precision (finalVol = 0..256)
1318 envVal >>= 8;1318 envVal >>= 8;
1319 ch->finalVol = (song.globVol * (((envVal * ch->outVol) * ch->fadeOutAmp) >> (16 + 2))) >> 7;1319 ch->finalVol = (song.globVol * (((envVal * ch->outVol) * ch->fadeOutAmp) >> (16 + 2))) >> 7;
1320 */1320 */
1321 1321
1322 /* calculate with four times more precision (+ rounding).1322 /* calculate with four times more precision (finalVol = 0..2048)
1323 ** also, env. range is now 0..16384 instead of being shifted to 0..64. */1323 ** Also, vol envelope range is now 0..16384 instead of being shifted to 0..64
1324 */
1324 1325
1325 dVol = song.globVol * ch->outVol * ch->fadeOutAmp;1326 uint32_t vol1 = song.globVol * ch->outVol * ch->fadeOutAmp; // 0..64 * 0..64 * 0..32768 = 0..134217728
1326 dVol *= envVal; // we need a float mul because it would overflow 32-bit integer1327 uint32_t vol2 = envVal << 2; // 0..16384 * 2^2 = 0..65536
1327 dVol *= 1.0 / ((64.0 * 64.0 * 32768.0 * 16384.0) / 2048.0); // 0..2048 (real FT2 is 0..256)
1328 1328
1329 vol = (int32_t)(dVol + 0.5);1329 vol = ((uint64_t)vol1 * vol2) >> 32; // 0..2048
1330 if (vol > 2048)
1331 vol = 2048;
1332 1330
1333 ch->finalVol = (uint16_t)vol;
1334 ch->status |= IS_Vol;1331 ch->status |= IS_Vol;
1335 }1332 }
1336 else1333 else
1337 {1334 {
1338 /* old integer method with low precision (FT2 way)1335 /* original FT2 method with lower precision (finalVol = 0..256)
1339 ch->finalVol = (song.globVol * (((ch->outVol << 4) * ch->fadeOutAmp) >> 16)) >> 7;1336 ch->finalVol = (song.globVol * (((ch->outVol << 4) * ch->fadeOutAmp) >> 16)) >> 7;
1340 */1337 */
1341 1338
1342 // calculate with four times more precision (+ rounding)1339 // calculate with four times more precision (finalVol = 0..2048)
1343 dVol = song.globVol * ch->outVol * ch->fadeOutAmp;1340 vol = (song.globVol * ch->outVol * ch->fadeOutAmp) >> 16; // 0..64 * 0..64 * 0..32768 = 0..2048
1344 dVol *= 1.0 / ((64.0 * 64.0 * 32768.0) / 2048.0); // 0..2048 (real FT2 is 0..256)1341 }
1345 1342
1346 vol = (int32_t)(dVol + 0.5);1343 if (vol > 2047)
1347 if (vol > 2048)1344 vol = 2047; // range is now 0..2047 to prevent MUL overflow when voice volume is calculated
1348 vol = 2048;
1349 1345
1350 ch->finalVol = (uint16_t)vol;1346 ch->finalVol = (uint16_t)vol;
1351 }
1352 }1347 }
1353 else1348 else
1354 {1349 {
@@ -1365,7 +1360,7 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 10 unmodified lines
1365 1360
1366 if (++ch->envPCnt == ins->envPP[envPos][0])1361 if (++ch->envPCnt == ins->envPP[envPos][0])
1367 {1362 {
1368 ch->envPAmp = (ins->envPP[envPos][1] & 0xFF) << 8;1363 ch->envPAmp = ins->envPP[envPos][1] << 8;
1369 1364
1370 envPos++;1365 envPos++;
1371 if (ins->envPTyp & 4)1366 if (ins->envPTyp & 4)
@@ -1379,7 +1374,7 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 7 unmodified lines
1379 envPos = ins->envPRepS;1374 envPos = ins->envPRepS;
1380 1375
1381 ch->envPCnt = ins->envPP[envPos][0];1376 ch->envPCnt = ins->envPP[envPos][0];
1382 ch->envPAmp = (ins->envPP[envPos][1] & 0xFF) << 8;1377 ch->envPAmp = ins->envPP[envPos][1] << 8;
1383 }1378 }
1384 }1379 }
1385 1380
@@ -1406,7 +1401,7 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 20 unmodified lines
1406 ch->envPIPValue = 0;1401 ch->envPIPValue = 0;
1407 if (ins->envPP[envPos][0] > ins->envPP[envPos-1][0])1402 if (ins->envPP[envPos][0] > ins->envPP[envPos-1][0])
1408 {1403 {
1409 ch->envPIPValue = ((ins->envPP[envPos][1] - ins->envPP[envPos-1][1]) & 0xFF) << 8;1404 ch->envPIPValue = (ins->envPP[envPos][1] - ins->envPP[envPos-1][1]) << 8;
1410 ch->envPIPValue /= (ins->envPP[envPos][0] - ins->envPP[envPos-1][0]);1405 ch->envPIPValue /= (ins->envPP[envPos][0] - ins->envPP[envPos-1][0]);
1411 1406
1412 envVal = ch->envPAmp;1407 envVal = ch->envPAmp;
@@ -1425,10 +1420,10 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 12 unmodified lines
1425 ch->envPAmp += ch->envPIPValue;1420 ch->envPAmp += ch->envPIPValue;
1426 1421
1427 envVal = ch->envPAmp;1422 envVal = ch->envPAmp;
1428 if ((envVal >> 8) > 0x40)1423 if (envVal > 64*256)
1429 {1424 {
1430 if ((envVal >> 8) > (0x40+0xC0)/2)1425 if (envVal > 128*256)
1431 envVal = 16384;1426 envVal = 64*256;
1432 else1427 else
1433 envVal = 0;1428 envVal = 0;
1434 1429
@@ -1441,9 +1436,9 @@ static void fixaEnvelopeVibrato(stmTyp *ch) · 6 unmodified lines
1441 panTmp = 0 - panTmp;1436 panTmp = 0 - panTmp;
1442 panTmp += 128;1437 panTmp += 128;
1443 1438
1444 envVal -= (32 * 256);1439 envVal -= 32*256;
1445 1440
1446 ch->finalPan = ch->outPan + ((((int16_t)envVal * (panTmp << 3)) >> 16) & 0xFF);1441 ch->finalPan = ch->outPan + (uint8_t)(((int16_t)envVal * panTmp) >> 13);
1447 ch->status |= IS_Pan;1442 ch->status |= IS_Pan;
1448 }1443 }
1449 else1444 else
@@ -2589,7 +2584,7 @@ void updateChanNums(void) · 1139 unmodified lines
2589 }2584 }
2590 }2585 }
2591 2586
2592 editor.ui.pattChanScrollShown = (song.antChn > getMaxVisibleChannels());2587 editor.ui.pattChanScrollShown = song.antChn > getMaxVisibleChannels();
2593 2588
2594 if (editor.ui.patternEditorShown)2589 if (editor.ui.patternEditorShown)
2595 {2590 {
src/ft2_scopes.c+9−5
@@ -86,6 +86,10 @@ static const uint16_t scopeLenTab[16][32] = · 85 unmodified lines
86 /* 32 ch */ {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15}86 /* 32 ch */ {15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15,15}
87};87};
88 88
89// ft2_pattern_draw.c
90extern const char chDecTab1[MAX_VOICES+1];
91extern char chDecTab2[MAX_VOICES+1];
92
89void resetOldScopeRates(void)93void resetOldScopeRates(void)
90{94{
91 oldVoiceDelta = 0;95 oldVoiceDelta = 0;
@@ -175,8 +179,8 @@ static void drawScopeNumber(uint16_t scopeXOffs, uint16_t scopeYOffs, uint8_t ch · 83 unmodified lines
175 }179 }
176 else180 else
177 {181 {
178 charOutOutlined(scopeXOffs, scopeYOffs, PAL_MOUSEPT, '0' + (channel / 10));182 charOutOutlined(scopeXOffs, scopeYOffs, PAL_MOUSEPT, chDecTab1[channel]);
179 charOutOutlined(scopeXOffs + 7, scopeYOffs, PAL_MOUSEPT, '0' + (channel % 10));183 charOutOutlined(scopeXOffs + 7, scopeYOffs, PAL_MOUSEPT, chDecTab2[channel]);
180 }184 }
181 }185 }
182 else186 else
@@ -187,8 +191,8 @@ static void drawScopeNumber(uint16_t scopeXOffs, uint16_t scopeYOffs, uint8_t ch · 4 unmodified lines
187 }191 }
188 else192 else
189 {193 {
190 charOut(scopeXOffs, scopeYOffs, PAL_MOUSEPT, '0' + (channel / 10));194 charOut(scopeXOffs, scopeYOffs, PAL_MOUSEPT, chDecTab1[channel]);
191 charOut(scopeXOffs + 7, scopeYOffs, PAL_MOUSEPT, '0' + (channel % 10));195 charOut(scopeXOffs + 7, scopeYOffs, PAL_MOUSEPT, chDecTab2[channel]);
192 }196 }
193 }197 }
194}198}
@@ -597,7 +601,7 @@ void handleScopesFromChQueue(chSyncData_t *chSyncData, uint8_t *scopeUpdateStatu · 402 unmodified lines
597 if (ch->voiceDelta != oldVoiceDelta)601 if (ch->voiceDelta != oldVoiceDelta)
598 {602 {
599 oldVoiceDelta = ch->voiceDelta;603 oldVoiceDelta = ch->voiceDelta;
600 oldSFrq = (uint32_t)((oldVoiceDelta * audio.dScopeFreqMul) + 0.5); // rounded604 oldSFrq = (int32_t)((oldVoiceDelta * audio.dScopeFreqMul) + 0.5); // rounded
601 }605 }
602 606
603 sc->SFrq = oldSFrq;607 sc->SFrq = oldSFrq;
src/ft2_scrollbars.c+20−1
@@ -355,6 +355,10 @@ void setScrollBarPos(uint16_t scrollBarID, uint32_t pos, bool triggerCallBack) · 354 unmodified lines
355 assert(scrollBarID < NUM_SCROLLBARS);355 assert(scrollBarID < NUM_SCROLLBARS);
356 scrollBar = &scrollBars[scrollBarID];356 scrollBar = &scrollBars[scrollBarID];
357 357
358 if (scrollBar->oldPos == pos)
359 return;
360 scrollBar->oldPos = pos;
361
358 if (scrollBar->page == 0)362 if (scrollBar->page == 0)
359 {363 {
360 scrollBar->pos = 0;364 scrollBar->pos = 0;
@@ -405,8 +409,12 @@ void setScrollBarEnd(uint16_t scrollBarID, uint32_t end) · 44 unmodified lines
405 if (end < 1)409 if (end < 1)
406 end = 1;410 end = 1;
407 411
408 scrollBar->end = end;412 if (scrollBar->oldEnd == end)
413 return;
414 scrollBar->oldEnd = end;
409 415
416 scrollBar->end = end;
417
410 setPos = false;418 setPos = false;
411 if (scrollBar->pos >= end)419 if (scrollBar->pos >= end)
412 {420 {
@@ -439,6 +447,10 @@ void setScrollBarPageLength(uint16_t scrollBarID, uint32_t pageLength) · 26 unmodified lines
439 if (pageLength < 1)447 if (pageLength < 1)
440 pageLength = 1;448 pageLength = 1;
441 449
450 if (scrollBar->oldPage == pageLength)
451 return;
452 scrollBar->oldPage = pageLength;
453
442 scrollBar->page = pageLength;454 scrollBar->page = pageLength;
443 if (scrollBar->end > 0)455 if (scrollBar->end > 0)
444 {456 {
@@ -618,6 +630,13 @@ void handleScrollBarsWhileMouseDown(void) · 173 unmodified lines
618 630
619void initializeScrollBars(void)631void initializeScrollBars(void)
620{632{
633 for (int32_t i = 0; i < NUM_SCROLLBARS; i++)
634 {
635 scrollBars[i].oldEnd = 0xFFFFFFFF;
636 scrollBars[i].oldPage = 0xFFFFFFFF;
637 scrollBars[i].oldPos = 0xFFFFFFFF;
638 }
639
621 // pattern editor640 // pattern editor
622 setScrollBarPageLength(SB_CHAN_SCROLL, 8);641 setScrollBarPageLength(SB_CHAN_SCROLL, 8);
623 setScrollBarEnd(SB_CHAN_SCROLL, 8);642 setScrollBarEnd(SB_CHAN_SCROLL, 8);
src/ft2_scrollbars.h+1−0
@@ -75,6 +75,7 @@ typedef struct scrollBar_t // DO NOT TOUCH! · 74 unmodified lines
75 bool visible;75 bool visible;
76 uint8_t state;76 uint8_t state;
77 uint32_t pos, page, end;77 uint32_t pos, page, end;
78 uint32_t oldPos, oldPage, oldEnd;
78 uint16_t thumbX, thumbY, thumbW, thumbH; 79 uint16_t thumbX, thumbY, thumbW, thumbH;
79} scrollBar_t;80} scrollBar_t;
80 81
src/ft2_sysreqs.c+84−27
@@ -41,12 +41,41 @@ static SDL_Keycode shortCut[NUM_SYSREQ_TYPES][5] = · 40 unmodified lines
41 { SDLK_m, SDLK_s, SDLK_c, 0, 0 },41 { SDLK_m, SDLK_s, SDLK_c, 0, 0 },
42};42};
43 43
44typedef struct quitType_t
45{
46 const char *text;
47 uint8_t typ;
48} quitType_t;
49
50#define QUIT_MESSAGES 16
51
52// 8bitbubsy: Removed the MS-DOS ones...
53static quitType_t quitMessage[QUIT_MESSAGES] =
54{
55 { "Do you really want to quit?", 2 },
56 { "Musicians, press >Cancel<. Lamers, press >OK<", 1 },
57 { "Tired already?", 2 },
58 { "Dost thou wish to leave with such hasty abandon?", 2 },
59 { "So, you think you can quit this easily, huh?", 2 },
60 { "Hey, what is the matter? You are not quiting now, are you?", 2 },
61 { "Rome was not built in one day! Quit really?", 2 },
62 { "For Work and Worry, press YES. For Delectation and Demos, press NO.", 2 },
63 { "Did you really press the right key?", 2 },
64 { "You are a lamer, aren't you? Press >OK< to confirm.", 1 },
65 { "Hope ya did some good. Press >OK< to quit.", 1 },
66 { "Quit? Only for a good reason you are allowed to press >OK<.", 1 },
67 { "Are we at the end of a Fasttracker round?", 2 },
68 { "Are you just another boring user?", 2 },
69 { "Hope you're doing the compulsory \"Exit ceremony\" before pressing >OK<.", 1 },
70 { "Fasttracker...", 3 }
71};
72
44static void drawWindow(uint16_t w)73static void drawWindow(uint16_t w)
45{74{
46 const uint16_t h = SYSTEM_REQUEST_H;75 const uint16_t h = SYSTEM_REQUEST_H;
47 uint16_t x, y;76 uint16_t x, y;
48 77
49 x = (SCREEN_W / 2) - (w / 2);78 x = (SCREEN_W - w) / 2;
50 y = editor.ui.extended ? 91 : SYSTEM_REQUEST_Y;79 y = editor.ui.extended ? 91 : SYSTEM_REQUEST_Y;
51 80
52 // main fill81 // main fill
@@ -85,8 +114,10 @@ static bool mouseButtonDownLogic(uint8_t mouseButton) · 32 unmodified lines
85 return false;114 return false;
86 }115 }
87 116
88 if (mouseButton == SDL_BUTTON_LEFT) mouse.leftButtonPressed = true;117 if (mouseButton == SDL_BUTTON_LEFT)
89 else if (mouseButton == SDL_BUTTON_RIGHT) mouse.rightButtonPressed = true;118 mouse.leftButtonPressed = true;
119 else if (mouseButton == SDL_BUTTON_RIGHT)
120 mouse.rightButtonPressed = true;
90 121
91 // don't do mouse down testing here if we already are using an object122 // don't do mouse down testing here if we already are using an object
92 if (mouse.lastUsedObjectType != OBJECT_NONE)123 if (mouse.lastUsedObjectType != OBJECT_NONE)
@@ -105,8 +136,10 @@ static bool mouseButtonDownLogic(uint8_t mouseButton) · 12 unmodified lines
105 136
106static bool mouseButtonUpLogic(uint8_t mouseButton)137static bool mouseButtonUpLogic(uint8_t mouseButton)
107{138{
108 if (mouseButton == SDL_BUTTON_LEFT) mouse.leftButtonPressed = false;139 if (mouseButton == SDL_BUTTON_LEFT)
109 else if (mouseButton == SDL_BUTTON_RIGHT) mouse.rightButtonPressed = false;140 mouse.leftButtonPressed = false;
141 else if (mouseButton == SDL_BUTTON_RIGHT)
142 mouse.rightButtonPressed = false;
110 143
111 editor.textCursorBlinkCounter = 0;144 editor.textCursorBlinkCounter = 0;
112 145
@@ -118,13 +151,12 @@ static bool mouseButtonUpLogic(uint8_t mouseButton) · 5 unmodified lines
118}151}
119 152
120// WARNING: This routine must ONLY be called from the main input/video thread!153// WARNING: This routine must ONLY be called from the main input/video thread!
121int16_t okBox(int16_t typ, char *headline, char *text)154int16_t okBox(int16_t typ, const char *headline, const char *text)
122{155{
123#define PUSHBUTTON_W 80156#define PUSHBUTTON_W 80
124 157
125 int16_t returnVal, oldLastUsedObjectID, oldLastUsedObjectType;158 int16_t returnVal, oldLastUsedObjectID, oldLastUsedObjectType;
126 uint16_t x, y, i, tlen, hlen, wlen, tx, knp, headlineX, textX;159 uint16_t x, y, i, tlen, hlen, wlen, tx, knp, headlineX, textX;
127 const uint16_t mid = SCREEN_W / 2;
128 SDL_Event inputEvent;160 SDL_Event inputEvent;
129 pushButton_t *p;161 pushButton_t *p;
130 checkBox_t *c;162 checkBox_t *c;
@@ -172,9 +204,9 @@ int16_t okBox(int16_t typ, char *headline, char *text) · 41 unmodified lines
172 if (wlen > 600)204 if (wlen > 600)
173 wlen = 600;205 wlen = 600;
174 206
175 headlineX = mid - (hlen / 2);207 headlineX = (SCREEN_W - hlen) / 2;
176 textX = mid - (tlen / 2);208 textX = (SCREEN_W - tlen) / 2;
177 x = mid - (wlen / 2);209 x = (SCREEN_W - wlen) / 2;
178 210
179 // the box y position differs in extended pattern editor mode211 // the box y position differs in extended pattern editor mode
180 y = editor.ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y;212 y = editor.ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y;
@@ -184,7 +216,7 @@ int16_t okBox(int16_t typ, char *headline, char *text) · 3 unmodified lines
184 {216 {
185 p = &pushButtons[i];217 p = &pushButtons[i];
186 218
187 p->x = (mid - (tx / 2)) + (i * 100);219 p->x = ((SCREEN_W - tx) / 2) + (i * 100);
188 p->y = y + 42;220 p->y = y + 42;
189 p->w = PUSHBUTTON_W;221 p->w = PUSHBUTTON_W;
190 p->h = 16;222 p->h = 16;
@@ -231,8 +263,10 @@ int16_t okBox(int16_t typ, char *headline, char *text) · 40 unmodified lines
231 263
232 if (mouse.leftButtonPressed || mouse.rightButtonPressed)264 if (mouse.leftButtonPressed || mouse.rightButtonPressed)
233 {265 {
234 if (mouse.lastUsedObjectType == OBJECT_PUSHBUTTON) handlePushButtonsWhileMouseDown();266 if (mouse.lastUsedObjectType == OBJECT_PUSHBUTTON)
235 else if (mouse.lastUsedObjectType == OBJECT_CHECKBOX) handleCheckBoxesWhileMouseDown();267 handlePushButtonsWhileMouseDown();
268 else if (mouse.lastUsedObjectType == OBJECT_CHECKBOX)
269 handleCheckBoxesWhileMouseDown();
236 }270 }
237 271
238 while (SDL_PollEvent(&inputEvent))272 while (SDL_PollEvent(&inputEvent))
@@ -330,7 +364,7 @@ int16_t okBox(int16_t typ, char *headline, char *text) · 91 unmodified lines
330** - This routine must ONLY be called from the main input/video thread!!364** - This routine must ONLY be called from the main input/video thread!!
331** - edText must be null-terminated365** - edText must be null-terminated
332*/366*/
333int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen)367int16_t inputBox(int16_t typ, const char *headline, char *edText, uint16_t maxStrLen)
334{368{
335#define PUSHBUTTON_W 80369#define PUSHBUTTON_W 80
336#define TEXTBOX_W 250370#define TEXTBOX_W 250
@@ -338,7 +372,6 @@ int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen) · 1 unmodified line
338 char *inputText;372 char *inputText;
339 int16_t returnVal, oldLastUsedObjectID, oldLastUsedObjectType;373 int16_t returnVal, oldLastUsedObjectID, oldLastUsedObjectType;
340 uint16_t y, wlen, tx, knp, headlineX, i;374 uint16_t y, wlen, tx, knp, headlineX, i;
341 const uint16_t mid = SCREEN_W / 2;
342 SDL_Event inputEvent;375 SDL_Event inputEvent;
343 pushButton_t *p;376 pushButton_t *p;
344 textBox_t *t;377 textBox_t *t;
@@ -389,7 +422,7 @@ int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen) · 44 unmodified lines
389 mouseAnimOff();422 mouseAnimOff();
390 423
391 wlen = textWidth(headline);424 wlen = textWidth(headline);
392 headlineX = mid - (wlen / 2);425 headlineX = (SCREEN_W - wlen) / 2;
393 426
394 // count number of buttons427 // count number of buttons
395 knp = 0;428 knp = 0;
@@ -412,7 +445,7 @@ int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen) · 16 unmodified lines
412 y = editor.ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y;445 y = editor.ui.extended ? SYSTEM_REQUEST_Y_EXT : SYSTEM_REQUEST_Y;
413 446
414 // set further text box settings447 // set further text box settings
415 t->x = mid - (TEXTBOX_W / 2);448 t->x = (SCREEN_W - TEXTBOX_W) / 2;
416 t->y = y + 24;449 t->y = y + 24;
417 t->visible = true;450 t->visible = true;
418 451
@@ -423,7 +456,7 @@ int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen) · 4 unmodified lines
423 456
424 p->w = PUSHBUTTON_W;457 p->w = PUSHBUTTON_W;
425 p->h = 16;458 p->h = 16;
426 p->x = (mid - (tx / 2)) + (i * 100);459 p->x = ((SCREEN_W - tx) / 2) + (i * 100);
427 p->y = y + 42;460 p->y = y + 42;
428 p->caption = buttonText[typ][i];461 p->caption = buttonText[typ][i];
429 p->visible = true;462 p->visible = true;
@@ -452,8 +485,10 @@ int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen) · 22 unmodified lines
452 485
453 if (mouse.leftButtonPressed || mouse.rightButtonPressed)486 if (mouse.leftButtonPressed || mouse.rightButtonPressed)
454 {487 {
455 if (mouse.lastUsedObjectType == OBJECT_PUSHBUTTON) handlePushButtonsWhileMouseDown();488 if (mouse.lastUsedObjectType == OBJECT_PUSHBUTTON)
456 else if (mouse.lastUsedObjectType == OBJECT_TEXTBOX) handleTextBoxWhileMouseDown();489 handlePushButtonsWhileMouseDown();
490 else if (mouse.lastUsedObjectType == OBJECT_TEXTBOX)
491 handleTextBoxWhileMouseDown();
457 }492 }
458 493
459 while (SDL_PollEvent(&inputEvent))494 while (SDL_PollEvent(&inputEvent))
@@ -575,7 +610,7 @@ int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen) · 115 unmodified lines
575}610}
576 611
577// WARNING: This routine must NOT be called from the main input/video thread!612// WARNING: This routine must NOT be called from the main input/video thread!
578int16_t okBoxThreadSafe(int16_t typ, char *headline, char *text)613int16_t okBoxThreadSafe(int16_t typ, const char *headline, const char *text)
579{614{
580 // block multiple calls before they are completed (for safety)615 // block multiple calls before they are completed (for safety)
581 while (okBoxData.active)616 while (okBoxData.active)
@@ -592,10 +627,34 @@ int16_t okBoxThreadSafe(int16_t typ, char *headline, char *text) · 10 unmodified lines
592 return okBoxData.returnData;627 return okBoxData.returnData;
593}628}
594 629
595int16_t quitBox(bool skipQuitMsg)630static bool askQuit_RandomMsg(void)
596{631{
597 char *text;632 uint8_t msg = rand() % QUIT_MESSAGES;
633 int16_t button = okBox(quitMessage[msg].typ, "System request", quitMessage[msg].text);
598 634
635 return (button == 1) ? true : false;
636}
637
638bool askUnsavedChanges(uint8_t type)
639{
640 int16_t button;
641
642 if (type == ASK_TYPE_QUIT)
643 {
644 button = okBox(2, "System request",
645 "You have unsaved changes in your song. Do you still want to quit and lose ALL changes?");
646 }
647 else
648 {
649 button = okBox(2, "System request",
650 "You have unsaved changes in your song. Load new song and lose ALL changes?");
651 }
652
653 return (button == 1) ? true : false;
654}
655
656int16_t quitBox(bool skipQuitMsg)
657{
599 if (editor.ui.sysReqShown)658 if (editor.ui.sysReqShown)
600 return 0;659 return 0;
601 660
@@ -603,9 +662,7 @@ int16_t quitBox(bool skipQuitMsg) · 1 unmodified line
603 return 1;662 return 1;
604 663
605 if (song.isModified)664 if (song.isModified)
606 text = "You have unsaved changes in your song. Do you still want to quit and lose ALL changes?";665 return askUnsavedChanges(ASK_TYPE_QUIT);
607 else
608 text = "Do you really want to quit?";
609 666
610 return okBox(2, "System request", text);667 return askQuit_RandomMsg();
611}668}
src/ft2_sysreqs.h+11−4
@@ -3,15 +3,22 @@ · 2 unmodified lines
3#include <stdint.h>3#include <stdint.h>
4#include <stdbool.h>4#include <stdbool.h>
5 5
6int16_t okBoxThreadSafe(int16_t typ, char *headline, char *text);6int16_t okBoxThreadSafe(int16_t typ, const char *headline, const char *text);
7int16_t okBox(int16_t typ, char *headline, char *text);7int16_t okBox(int16_t typ, const char *headline, const char *text);
8int16_t quitBox(bool skipQuitMsg);8int16_t quitBox(bool skipQuitMsg);
9int16_t inputBox(int16_t typ, char *headline, char *edText, uint16_t maxStrLen);9int16_t inputBox(int16_t typ, const char *headline, char *edText, uint16_t maxStrLen);
10bool askUnsavedChanges(uint8_t type);
10 11
11// for thread-safe version of okBox()12// for thread-safe version of okBox()
12struct13struct
13{14{
14 volatile bool active;15 volatile bool active;
15 int16_t typ, returnData;16 int16_t typ, returnData;
16 char *headline, *text;17 const char *headline, *text;
17} okBoxData;18} okBoxData;
19
20enum
21{
22 ASK_TYPE_QUIT = 0,
23 ASK_TYPE_LOAD_SONG = 1,
24};
src/ft2_video.c+39−25
@@ -23,6 +23,7 @@ · 22 unmodified lines
23#include "ft2_mouse.h"23#include "ft2_mouse.h"
24#include "ft2_scopes.h"24#include "ft2_scopes.h"
25#include "ft2_pattern_ed.h"25#include "ft2_pattern_ed.h"
26#include "ft2_pattern_draw.h"
26#include "ft2_sample_ed.h"27#include "ft2_sample_ed.h"
27#include "ft2_nibbles.h"28#include "ft2_nibbles.h"
28#include "ft2_inst_ed.h"29#include "ft2_inst_ed.h"
@@ -33,13 +34,6 @@ · 4 unmodified lines
33#include "ft2_module_loader.h"34#include "ft2_module_loader.h"
34#include "ft2_midi.h"35#include "ft2_midi.h"
35 36
36// for FPS counter
37#define FPS_SCAN_FRAMES 60
38#define FPS_RENDER_W 280
39#define FPS_RENDER_H (((FONT1_CHAR_H + 1) * 8) + 1)
40#define FPS_RENDER_X 2
41#define FPS_RENDER_Y 2
42
43static const uint8_t textCursorData[12] =37static const uint8_t textCursorData[12] =
44{38{
45 PAL_FORGRND, PAL_FORGRND, PAL_FORGRND,39 PAL_FORGRND, PAL_FORGRND, PAL_FORGRND,
@@ -49,17 +43,28 @@ static const uint8_t textCursorData[12] = · 3 unmodified lines
49};43};
50 44
51static bool songIsModified;45static bool songIsModified;
52static char buf[1024], wndTitle[128 + PATH_MAX];46static char wndTitle[128 + PATH_MAX];
53static uint64_t frameStartTime, timeNext64, timeNext64Frac;47static uint64_t timeNext64, timeNext64Frac;
54static sprite_t sprites[SPRITE_NUM];48static sprite_t sprites[SPRITE_NUM];
49
50// for FPS counter
51#define FPS_SCAN_FRAMES 60
52#define FPS_RENDER_W 280
53#define FPS_RENDER_H (((FONT1_CHAR_H + 1) * 8) + 1)
54#define FPS_RENDER_X 2
55#define FPS_RENDER_Y 2
56
57static char fpsTextBuf[1024];
58static uint64_t frameStartTime;
55static double dRunningFPS, dFrameTime, dAvgFPS;59static double dRunningFPS, dFrameTime, dAvgFPS;
60// ------------------
56 61
57static void drawReplayerData(void);62static void drawReplayerData(void);
58 63
59void resetFPSCounter(void)64void resetFPSCounter(void)
60{65{
61 editor.framesPassed = 0;66 editor.framesPassed = 0;
62 buf[0] = '\0';67 fpsTextBuf[0] = '\0';
63 dRunningFPS = VBLANK_HZ;68 dRunningFPS = VBLANK_HZ;
64 dFrameTime = 1000.0 / VBLANK_HZ;69 dFrameTime = 1000.0 / VBLANK_HZ;
65}70}
@@ -106,7 +111,7 @@ static void drawFPSCounter(void) · 40 unmodified lines
106 if (dAudLatency < 0.0 || dAudLatency > 999999999.9999)111 if (dAudLatency < 0.0 || dAudLatency > 999999999.9999)
107 dAudLatency = 999999999.9999; // prevent number from overflowing text box112 dAudLatency = 999999999.9999; // prevent number from overflowing text box
108 113
109 sprintf(buf, "Frames per second: %.4f\n" \114 sprintf(fpsTextBuf, "Frames per second: %.4f\n" \
110 "Monitor refresh rate: %.1fHz (+/-)\n" \115 "Monitor refresh rate: %.1fHz (+/-)\n" \
111 "59..61Hz GPU VSync used: %s\n" \116 "59..61Hz GPU VSync used: %s\n" \
112 "Audio frequency: %.1fkHz (expected %.1fkHz)\n" \117 "Audio frequency: %.1fkHz (expected %.1fkHz)\n" \
@@ -126,7 +131,7 @@ static void drawFPSCounter(void) · 13 unmodified lines
126 xPos = FPS_RENDER_X + 3;131 xPos = FPS_RENDER_X + 3;
127 yPos = FPS_RENDER_Y + 3;132 yPos = FPS_RENDER_Y + 3;
128 133
129 textPtr = buf;134 textPtr = fpsTextBuf;
130 while (*textPtr != '\0')135 while (*textPtr != '\0')
131 {136 {
132 ch = *textPtr++;137 ch = *textPtr++;
@@ -210,7 +215,7 @@ void showErrorMsgBox(const char *fmt, ...) · 77 unmodified lines
210 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", strBuf, video.window);215 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Error", strBuf, video.window);
211}216}
212 217
213void updateRenderSizeVars(void)218static void updateRenderSizeVars(void)
214{219{
215 int32_t di;220 int32_t di;
216#ifdef __APPLE__221#ifdef __APPLE__
@@ -754,11 +759,13 @@ void closeVideo(void) · 537 unmodified lines
754 video.window = NULL;759 video.window = NULL;
755 }760 }
756 761
757 if (video.frameBuffer != NULL)762 if (video.frameBufferUnaligned != NULL)
758 {763 {
759 free(video.frameBuffer);764 free(video.frameBufferUnaligned);
760 video.frameBuffer = NULL;765 video.frameBufferUnaligned = NULL;
761 }766 }
767
768 video.frameBuffer = NULL;
762}769}
763 770
764void setWindowSizeFromConfig(bool updateRenderer)771void setWindowSizeFromConfig(bool updateRenderer)
@@ -854,7 +861,7 @@ bool recreateTexture(void) · 89 unmodified lines
854 video.texture = SDL_CreateTexture(video.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_W, SCREEN_H);861 video.texture = SDL_CreateTexture(video.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_W, SCREEN_H);
855 if (video.texture == NULL)862 if (video.texture == NULL)
856 {863 {
857 showErrorMsgBox("Couldn't create a %dx%d GPU texture:\n%s\n\nIs your GPU (+ driver) too old?", SCREEN_W, SCREEN_H, SDL_GetError());864 showErrorMsgBox("Couldn't create a %dx%d GPU texture:\n\"%s\"\n\nIs your GPU (+ driver) too old?", SCREEN_W, SCREEN_H, SDL_GetError());
858 return false;865 return false;
859 }866 }
860 867
@@ -930,7 +937,7 @@ bool setupRenderer(void) · 69 unmodified lines
930 937
931 if (video.renderer == NULL)938 if (video.renderer == NULL)
932 {939 {
933 showErrorMsgBox("Couldn't create SDL renderer:\n%s\n\nIs your GPU (+ driver) too old?",940 showErrorMsgBox("Couldn't create SDL renderer:\n\"%s\"\n\nIs your GPU (+ driver) too old?",
934 SDL_GetError());941 SDL_GetError());
935 return false;942 return false;
936 }943 }
@@ -946,19 +953,22 @@ bool setupRenderer(void) · 9 unmodified lines
946 953
947 if (!recreateTexture())954 if (!recreateTexture())
948 {955 {
949 showErrorMsgBox("Couldn't create a %dx%d GPU texture:\n%s\n\nIs your GPU (+ driver) too old?",956 showErrorMsgBox("Couldn't create a %dx%d GPU texture:\n\"%s\"\n\nIs your GPU (+ driver) too old?",
950 SCREEN_W, SCREEN_H, SDL_GetError());957 SCREEN_W, SCREEN_H, SDL_GetError());
951 return false;958 return false;
952 }959 }
953 960
954 // framebuffer used by SDL (for texture)961 // framebuffer used by SDL (for texture)
955 video.frameBuffer = (uint32_t *)malloc(SCREEN_W * SCREEN_H * sizeof (int32_t));962 video.frameBufferUnaligned = (uint32_t *)MALLOC_PAD(SCREEN_W * SCREEN_H * sizeof (int32_t), 256);
956 if (video.frameBuffer == NULL)963 if (video.frameBufferUnaligned == NULL)
957 {964 {
958 showErrorMsgBox("Not enough memory!");965 showErrorMsgBox("Not enough memory!");
959 return false;966 return false;
960 }967 }
961 968
969 // we want an aligned pointer
970 video.frameBuffer = (uint32_t *)ALIGN_PTR(video.frameBufferUnaligned, 256);
971
962 if (!setupSprites())972 if (!setupSprites())
963 return false;973 return false;
964 974
@@ -1033,16 +1043,20 @@ void handleRedrawing(void) · 68 unmodified lines
1033 if (!editor.ui.diskOpShown)1043 if (!editor.ui.diskOpShown)
1034 drawPlaybackTime();1044 drawPlaybackTime();
1035 1045
1036 if (editor.ui.sampleEditorExtShown) handleSampleEditorExtRedrawing();1046 if (editor.ui.sampleEditorExtShown)
1037 else if (editor.ui.scopesShown) drawScopes();1047 handleSampleEditorExtRedrawing();
1048 else if (editor.ui.scopesShown)
1049 drawScopes();
1038 }1050 }
1039 }1051 }
1040 }1052 }
1041 1053
1042 drawReplayerData();1054 drawReplayerData();
1043 1055
1044 if (editor.ui.instEditorShown) handleInstEditorRedrawing();1056 if (editor.ui.instEditorShown)
1045 else if (editor.ui.sampleEditorShown) handleSamplerRedrawing();1057 handleInstEditorRedrawing();
1058 else if (editor.ui.sampleEditorShown)
1059 handleSamplerRedrawing();
1046 1060
1047 // blink text edit cursor1061 // blink text edit cursor
1048 if (editor.editTextFlag && mouse.lastEditBox != -1)1062 if (editor.editTextFlag && mouse.lastEditBox != -1)
src/ft2_video.h+8−7
@@ -18,16 +18,18 @@ enum · 17 unmodified lines
18 18
19struct video_t19struct video_t
20{20{
21 uint8_t upscaleFactor;21 bool fullscreen, showFPSCounter;
22 bool fullscreen, vsync60HzPresent, showFPSCounter;
23 int32_t renderX, renderY, renderW, renderH, displayW, displayH;
24 uint32_t *frameBuffer, palette[PAL_NUM], vblankTimeLen, vblankTimeLenFrac;
25 uint32_t xScale, yScale;22 uint32_t xScale, yScale;
26 double dMonitorRefreshRate, dMouseXMul, dMouseYMul;23 uint32_t *frameBuffer, palette[PAL_NUM], vblankTimeLen, vblankTimeLenFrac;
27#ifdef _WIN3224#ifdef _WIN32
28 HWND hWnd;25 HWND hWnd;
29#endif26#endif
30 SDL_Window *window;27 SDL_Window *window;
28 double dMonitorRefreshRate, dMouseXMul, dMouseYMul;
29 uint8_t upscaleFactor;
30 bool vsync60HzPresent;
31 int32_t renderX, renderY, renderW, renderH, displayW, displayH;
32 uint32_t *frameBufferUnaligned;
31 SDL_Renderer *renderer;33 SDL_Renderer *renderer;
32 SDL_Texture *texture;34 SDL_Texture *texture;
33 SDL_Surface *iconSurface;35 SDL_Surface *iconSurface;
@@ -48,7 +50,6 @@ void endFPSCounter(void); · 14 unmodified lines
48void flipFrame(void);50void flipFrame(void);
49void showErrorMsgBox(const char *fmt, ...);51void showErrorMsgBox(const char *fmt, ...);
50void updateWindowTitle(bool forceUpdate);52void updateWindowTitle(bool forceUpdate);
51void setPalettePreset(int16_t palettePreset);
52void handleScopesFromChQueue(chSyncData_t *chSyncData, uint8_t *scopeUpdateStatus);53void handleScopesFromChQueue(chSyncData_t *chSyncData, uint8_t *scopeUpdateStatus);
53bool setupWindow(void);54bool setupWindow(void);
54bool setupRenderer(void);55bool setupRenderer(void);
@@ -67,8 +68,8 @@ void hideSprite(uint8_t sprite); · 12 unmodified lines
67void handleRedrawing(void);68void handleRedrawing(void);
68void enterFullscreen(void);69void enterFullscreen(void);
69void leaveFullScreen(void);70void leaveFullScreen(void);
70void toggleFullScreen(void);
71void setWindowSizeFromConfig(bool updateRenderer);71void setWindowSizeFromConfig(bool updateRenderer);
72bool recreateTexture(void);72bool recreateTexture(void);
73void toggleFullScreen(void);
73void setupWaitVBL(void);74void setupWaitVBL(void);
74void waitVBL(void);75void waitVBL(void);
src/gfxdata/bmp/patternfonts.bmp+0−0

Binary file not shown.

vs2019_project/ft2-clone/ft2-clone.vcxproj+6−2
@@ -116,8 +116,9 @@ · 115 unmodified lines
116 <OpenMPSupport>false</OpenMPSupport>116 <OpenMPSupport>false</OpenMPSupport>
117 <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>117 <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
118 <BufferSecurityCheck>false</BufferSecurityCheck>118 <BufferSecurityCheck>false</BufferSecurityCheck>
119 <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>119 <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
120 <DebugInformationFormat>None</DebugInformationFormat>120 <DebugInformationFormat>None</DebugInformationFormat>
121 <LanguageStandard>stdcpplatest</LanguageStandard>
121 </ClCompile>122 </ClCompile>
122 <Link>123 <Link>
123 <AdditionalLibraryDirectories>124 <AdditionalLibraryDirectories>
@@ -174,6 +175,7 @@ · 50 unmodified lines
174 <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>175 <InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
175 <BufferSecurityCheck>false</BufferSecurityCheck>176 <BufferSecurityCheck>false</BufferSecurityCheck>
176 <DebugInformationFormat>None</DebugInformationFormat>177 <DebugInformationFormat>None</DebugInformationFormat>
178 <LanguageStandard>stdcpplatest</LanguageStandard>
177 </ClCompile>179 </ClCompile>
178 <Link>180 <Link>
179 <AdditionalLibraryDirectories>181 <AdditionalLibraryDirectories>
@@ -223,12 +225,13 @@ · 43 unmodified lines
223 <PreprocessorDefinitions>__WINDOWS_MM__;_CRTDBG_MAP_ALLOC;DEBUG;_DEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;HAVE_M_PI;HAS_MIDI</PreprocessorDefinitions>225 <PreprocessorDefinitions>__WINDOWS_MM__;_CRTDBG_MAP_ALLOC;DEBUG;_DEBUG;WIN32;_CRT_SECURE_NO_WARNINGS;_USE_MATH_DEFINES;HAVE_M_PI;HAS_MIDI</PreprocessorDefinitions>
224 <ExceptionHandling>false</ExceptionHandling>226 <ExceptionHandling>false</ExceptionHandling>
225 <FloatingPointModel>Fast</FloatingPointModel>227 <FloatingPointModel>Fast</FloatingPointModel>
226 <EnableEnhancedInstructionSet>StreamingSIMDExtensions</EnableEnhancedInstructionSet>228 <EnableEnhancedInstructionSet>StreamingSIMDExtensions2</EnableEnhancedInstructionSet>
227 <ControlFlowGuard>false</ControlFlowGuard>229 <ControlFlowGuard>false</ControlFlowGuard>
228 <EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>230 <EnableParallelCodeGeneration>false</EnableParallelCodeGeneration>
229 <CreateHotpatchableImage>false</CreateHotpatchableImage>231 <CreateHotpatchableImage>false</CreateHotpatchableImage>
230 <RuntimeTypeInfo>false</RuntimeTypeInfo>232 <RuntimeTypeInfo>false</RuntimeTypeInfo>
231 <OpenMPSupport>false</OpenMPSupport>233 <OpenMPSupport>false</OpenMPSupport>
234 <LanguageStandard>stdcpplatest</LanguageStandard>
232 </ClCompile>235 </ClCompile>
233 <Link>236 <Link>
234 <AdditionalLibraryDirectories>237 <AdditionalLibraryDirectories>
@@ -276,6 +279,7 @@ · 41 unmodified lines
276 <CreateHotpatchableImage>false</CreateHotpatchableImage>279 <CreateHotpatchableImage>false</CreateHotpatchableImage>
277 <RuntimeTypeInfo>false</RuntimeTypeInfo>280 <RuntimeTypeInfo>false</RuntimeTypeInfo>
278 <OpenMPSupport>false</OpenMPSupport>281 <OpenMPSupport>false</OpenMPSupport>
282 <LanguageStandard>stdcpplatest</LanguageStandard>
279 </ClCompile>283 </ClCompile>
280 <Link>284 <Link>
281 <AdditionalLibraryDirectories>285 <AdditionalLibraryDirectories>

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t