ref: 1e8cf25675af7c7d6bab838e3c005447871b4b8f
dir: /src/pt2_pattern_viewer.c/
#include <stdint.h>
#include <stdbool.h>
#include "pt2_header.h"
#include "pt2_palette.h"
#include "pt2_tables.h"
#include "pt2_textout.h"
#include "pt2_structs.h"
#include "pt2_config.h"
#include "pt2_visuals.h"
#define MIDDLE_ROW 7
#define VISIBLE_ROWS 15
static const char emptyDottedEffect[4] = { 0x02, 0x02, 0x02, 0x00 };
static const char emptyDottedSample[3] = { 0x02, 0x02, 0x00 };
static int32_t periodToNote(int32_t period) // 0 = no note, 1 = illegal note, 2..37 = note
{
int32_t beg, end, tableVal;
if (period == 0)
return 0;
beg = 0;
end = 36 - 1;
// do binary search
while (beg <= end)
{
const int32_t mid = (beg + end) >> 1;
tableVal = periodTable[mid];
if (period == tableVal)
return 2+mid;
if (period < tableVal)
beg = mid+1;
else
end = mid-1;
}
return 1; // illegal note
}
static void drawPatternNormal(void)
{
const char **noteNames;
char smpChar;
int32_t row, j, x, y;
note_t *patt, *note;
if (config.accidental)
noteNames = (const char **)noteNames2;
else
noteNames = (const char **)noteNames1;
patt = song->patterns[song->currPattern];
row = song->currRow - MIDDLE_ROW;
y = 140;
for (int32_t i = 0; i < VISIBLE_ROWS; i++, y += 7, row++)
{
if (row < 0 || row >= MOD_ROWS)
{
// clear empty rows outside of pattern data
fillRect(8, y, FONT_CHAR_W*2, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(0*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(1*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(2*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(3*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
}
else
{
if (i == MIDDLE_ROW) // middle row has twice as tall glyphs
{
y++;
printTwoDecimalsBigBg(8, y, row, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
note = patt + (row << 2);
x = 32;
for (j = 0; j < AMIGA_VOICES; j++, note++)
{
textOutBigBg(x, y, noteNames[periodToNote(note->period)], video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8*3;
smpChar = (config.blankZeroFlag && !(note->sample & 0xF0)) ? ' ' : hexTable[note->sample >> 4];
charOutBigBg(x, y, smpChar, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8;
printOneHexBigBg(x, y, note->sample & 0x0F, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8;
printOneHexBigBg(x, y, note->command, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8;
printTwoHexBigBg(x, y, note->param, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += (8*2)+8;
}
y += 6;
}
else // non-middle rows
{
printTwoDecimalsBg(8, y, row, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
note = patt + (row << 2);
x = 32;
for (j = 0; j < AMIGA_VOICES; j++, note++)
{
textOutBg(x, y, noteNames[periodToNote(note->period)], video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8*3;
smpChar = (config.blankZeroFlag && !(note->sample & 0xF0)) ? ' ' : hexTable[note->sample >> 4];
charOutBg(x, y, smpChar, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8;
printOneHexBg(x , y, note->sample & 0x0F, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8;
printOneHexBg(x, y, note->command, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8;
printTwoHexBg(x, y, note->param, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += (8*2)+8;
}
}
}
}
}
static void drawPatternDotted(void)
{
char smpChar;
const char **noteNames;
int32_t row, j, x, y;
note_t *patt, *note;
if (config.accidental)
noteNames = (const char **)noteNames4;
else
noteNames = (const char **)noteNames3;
patt = song->patterns[song->currPattern];
row = song->currRow - MIDDLE_ROW;
y = 140;
for (int32_t i = 0; i < VISIBLE_ROWS; i++, y += 7, row++)
{
if (row < 0 || row >= MOD_ROWS)
{
// clear empty rows outside of pattern data
fillRect(8, y, FONT_CHAR_W*2, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(0*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(1*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(2*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
fillRect(32+(3*72), y, FONT_CHAR_W*8, FONT_CHAR_H, video.palette[PAL_BACKGRD]);
}
else
{
if (i == MIDDLE_ROW) // middle row has twice as tall glyphs
{
y++;
printTwoDecimalsBigBg(8, y, row, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
note = patt + (row << 2);
x = 32;
for (j = 0; j < AMIGA_VOICES; j++, note++)
{
textOutBigBg(x, y, noteNames[periodToNote(note->period)], video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8*3;
if (note->sample == 0)
{
textOutBigBg(x, y, emptyDottedSample, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8*2;
}
else
{
smpChar = (note->sample & 0xF0) ? hexTable[note->sample >> 4] : 0x02;
charOutBigBg(x, y, smpChar, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8;
printOneHexBigBg(x, y, note->sample & 0x0F, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8;
}
if (note->command == 0 && note->param == 0)
{
textOutBigBg(x, y, emptyDottedEffect, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += (8*3)+8;
}
else
{
printOneHexBigBg(x, y, note->command, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += 8;
printTwoHexBigBg(x, y, note->param, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
x += (8*2)+8;
}
}
y += 6;
}
else // non-middle rows
{
printTwoDecimalsBg(8, y, row, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
// pattern data
note = patt + (row << 2);
x = 32;
for (j = 0; j < AMIGA_VOICES; j++, note++)
{
textOutBg(x, y, noteNames[periodToNote(note->period)], video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8*3;
if (note->sample == 0)
{
textOutBg(x, y, emptyDottedSample, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8*2;
}
else
{
smpChar = (note->sample & 0xF0) ? hexTable[note->sample >> 4] : 0x02;
charOutBg(x, y, smpChar, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8;
printOneHexBg(x, y, note->sample & 0x0F, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8;
}
if (note->command == 0 && note->param == 0)
{
textOutBg(x, y, emptyDottedEffect, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += (8*3)+8;
}
else
{
printOneHexBg(x, y, note->command, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += 8;
printTwoHexBg(x, y, note->param, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
x += (8*2)+8;
}
}
}
}
}
}
void redrawPattern(void)
{
if (config.pattDots)
drawPatternDotted();
else
drawPatternNormal();
}