Skip to content

Instantly share code, notes, and snippets.

@0b5vr
Created August 26, 2023 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save 0b5vr/8af3d6df8c62779e29261ba5a7a6c413 to your computer and use it in GitHub Desktop.
Save 0b5vr/8af3d6df8c62779e29261ba5a7a6c413 to your computer and use it in GitHub Desktop.
rough prototype of protracker module pattern for imhex
#include <std/io.pat>
#include <std/math.pat>
fn charString(str value) {
return value;
};
fn u16LengthInWords(u16 value) {
return 2 * value;
};
fn u8Finetune(u8 value) {
if (value & 0xf0 != 0x0) {
return "invalid";
}
if (value >= 8) {
return s8(value) - 16;
} else {
return s8(value);
}
};
fn u8Volume(u8 value) {
if (value > 0x40) {
return "invalid";
}
return value;
};
fn u16PeriodToNote(u16 period) {
match (period) {
(0): return "---";
(57): return "B-4";
(60): return "A#4";
(64): return "A-4";
(67): return "G#4";
(71): return "G-4";
(76): return "F#4";
(80): return "F-4";
(85): return "E-4";
(90): return "D#4";
(95): return "D-4";
(101): return "C#4";
(107): return "C-4";
(113): return "B-3";
(120): return "A#3";
(127): return "A-3";
(135): return "G#3";
(143): return "G-3";
(151): return "F#3";
(160): return "F-3";
(170): return "E-3";
(180): return "D#3";
(190): return "D-3";
(202): return "C#3";
(214): return "C-3";
(226): return "B-2";
(240): return "A#2";
(254): return "A-2";
(269): return "G#2";
(285): return "G-2";
(302): return "F#2";
(320): return "F-2";
(339): return "E-2";
(360): return "D#2";
(381): return "D-2";
(404): return "C#2";
(428): return "C-2";
(453): return "B-1";
(480): return "A#1";
(508): return "A-1";
(538): return "G#1";
(570): return "G-1";
(604): return "F#1";
(640): return "F-1";
(678): return "E-1";
(720): return "D#1";
(762): return "D-1";
(808): return "C#1";
(856): return "C-1";
(907): return "B-0";
(961): return "A#0";
(1017): return "A-0";
(1077): return "G#0";
(1141): return "G-0";
(1209): return "F#0";
(1281): return "F-0";
(1357): return "E-0";
(1440): return "D#0";
(1525): return "D-0";
(1616): return "C#0";
(1712): return "C-0";
}
return "???";
};
fn u32Cell(u32 cell) {
u16 period = (cell & 0x0fff0000) >> 16;
u8 sample = ((cell & 0xf0000000) >> 24) | ((cell & 0x0000f000) >> 12);
u16 effect = cell & 0x00000fff;
str note = u16PeriodToNote(period);
return std::format("{} {:02X} {:03X}", note, sample, effect);
};
fn findMax(auto orders, u32 length) {
u8 max;
for (u8 i = 0, i < length, i = i + 1) {
max = std::math::max(max, orders[i]);
}
return max;
};
struct SampleInfo {
char name[22] [[format("charString"), color("888800")]];
be u16 length [[format("u16LengthInWords")]];
u8 finetune [[format("u8Finetune")]];
u8 volume [[format("u8Volume")]];
be u16 loopStart [[format("u16LengthInWords")]];
be u16 loopLength [[format("u16LengthInWords")]];
};
struct PatternCell {
be u32 cell [[format("u32Cell")]];
};
struct PatternRow {
be PatternCell cells[4];
};
struct Pattern {
PatternRow rows[64];
};
struct ModuleFile {
char name[20] [[format("charString")]];
SampleInfo sampleInfos[31] [[color("ffff00")]];
u8 songLength;
u8 magic;
u8 songOrder[128];
char sampleTag[4];
u8 nPatterns = findMax(songOrder, 128) + 1;
Pattern patterns[nPatterns] [[color("0000ff")]];
};
ModuleFile mod @ 0x00;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment