Sections

2024-04-08

Music Tracker Effects Rosetta Stone

This is a part of a treatise on a system to handle music modules in CSV, or maybe pipe-separated values. It is advisable to store the effect type as a single ASCII character instead of a 2-hexit number. There is an unfinished university project of mine called ReTeMuS (Renderer/Redactor of Text Musical Sequences) that was supposed to support multiple effect letter semantics, as per song configuration, but JavaFX with its Observers just sucks. Most music module formats are binary, which is very unUNIXy. Renoise uses XML, which is not much more readable for humans. OpenMPT and Furnace clipboard is text-based, but COBOLesquely fixed-width. It's possible to make ChatGPT generate some patterns in such format, but it's very uncreative. The main reason for ReTeMuS has been to have native xenharmonic and microtonal support, because 12EDO is full of copyright lawsuits. See also a Czech article about note names and accidentals for microtonal tunings.


There are 4 main families of effect letter nomenclature:

MOD -> MTM -> XM -> MT2   Protracker -> Multitracker -> FastTracker -> MadTracker

STM -> S3M -> IT -> MPTM  ScreamTracker 1/2/3 -> Impulse Tracker -> Modplug Tracker

RNS -> XRNS               NoiseTrekker -> Renoise

669 ~> FAR                Composer 669 -> UNIS 669 ~> Farandole Composer

Scroll way below for FM synthesis. Radium doesn't really use effect letters. There're synthesizing trackers like AHX, HivelyTracker, Klystrack, StarTrekker, Buzz, and Psycle, but they are out of scope. Art of Noise has crept in because it's Protracker compatible and OctaMED also has wavetables. SunVox has crept in because of effect column similarities to MadTracker.

The pace of tracker development was very rapid. Once people figured out software mixing on Amiga, the channel limit went to the moon, while on PC we got NNAs:

Year  Chn  Smp  Platform   Tracker
1986    3    0  C64        Soundmonitor
1987    4   15  Amiga      The Ultimate Soundtracker
1989    4   31  PC:LPTDAC  Scream Tracker 1
1989    8   36  Amiga      Oktalyzer
1991    8   63  Amiga      OctaMED
1992    8   64  PC:GUS     Composer 669
1993   32   31  PC:GUS     Multitracker (MTM allows 63 smp)
1994   25   99  PC:AL+GUS  Scream Tracker 3 (S3M allows 32 chn & 255 smp)
1994   32  127  PC:GUS     FastTracker 2 (XM allows 65534 chn & 255 ins)
1994  256  128  Amiga      Symphonie Pro 1
1995   64   99  PC         Impulse Tracker 1 (256 virtual ch, format 128ch 255ins)
1997  127  255  Win32      ModPlug Tracker (256 virtual ch)
1997  inf  inf  Win32      Jeskola Buzz
1998  254  255  Amiga      DigiBooster Pro 2
2002  inf  inf  WinLinMac  Renoise
2005   28  255  Win32      Famitracker (multichip emulation)


SAMPLE-BASED

I've decided to sort the table according to XM effects, since the Protracker subset is generally agreeable, even though the letters G..Z or hex 10..FF are wild west. I mostly follow OpenMPT's extensions as they backport the IT effects, MT2's are a whole different can of worms. Some effects could be described in Italian like in classical music, but EDM, DAWs, Computers, and the Internet all use English.

Keep in mind that each implementation behaves slightly differently in certain edge cases. Some effects may be per note, others per channel, coarse slides may also update mixer on 1st tick of row too, fine slides may slide on the 2nd tick, the FT2 E60 has a bug that mandates use of D00, F00 may either stop, hang, or crash, PT2 could do wavetables with on-the-fly sample swapping and offsetting, the small volume column effect parameter mapping to the big effect column effects differs between IT and XM, speed in LFO type effects may be interpreted differently, effect memory is shared differently, Furnace has persistent effects that are stopped instead of continued with zeroes, and so on and so on. *sniff*

Pipe (|) and comma (,) are reserved for separators. IT column also disregards double quote (") for string escaping, dot (.) for denoting empty space, and equals (=) for denoting Excel formulae, because I ran out of ASCII. The upper half of the codepage is used for semigraphics tiles. We have Unicode terminals now, but entering Unicode letters and symbols with arcane compose sequences, by switching around multiple keyboard layouts, or having to hex-dial with Ctrl+Shift+U is UX from hell.


Effect column (pitch, volume, panning, tempo, fake letter):

XM   IT   RNS   FUR   FNK  8MED  Description
0xy  Jxy   Axy  00xy  Lxy  00xy  Arpeggio (x & y semitones from note, x=y 2 cycle)
1xx  Exx        01xx  Axx  01xx  Portamento down (IT only 00..DF)
2xx  Fxx        02xx  Bxx  02xx  Portamento up (IT only 00..DF)
3xx  Gxx   Gxx  03xx  Cxx  03xx  Portamento to note
3FF  GFF   GFF             0FFD  Instant note portamento
4xy  Hxy   Vxy  04xx  Dxy  14xy  Vibrato (x speed, y depth)
                           04xy  Vibrato (x speed, y depth*2)
                      Exy        Vibrato "fanin" (x speed slide down, stabilize)
                      Fxy        Vibrato "fanout" (x speed slide up, destabilize)
5xy  Kxy        05xx       05xx  Volume slide (see Axy/Dxy), continue portamento
6xy  Lxy        06xx       06xx  Volume slide (see Axy/Dxy), continue vibrato
7xy  Rxy   Txy  07xx  Kxy  07xx  Tremolo (x speed, y depth)
8xx  Xxx   Pxx  80xx             Panning (RNS pre-mixer, ST3 00..7F)
                08xy             Set balance (x left, y right)
                81xx             Set left panning
                82xx             Set right panning
                88xy             Set rear balance (x left, y right)
                89xx             Set rear left panning
                8Axx             Set rear right panning
9xx  Oxx   Sxx  9xxx  Mxx  19xx  Sample offset (times 256, RNS cue default)
Axy  Dxy        0Axy       0Dxy  Volume slide (x ↑, y ↓, IT no F, see DxF & DFx)
                FAxy             Fast volume slide (x ↑, y ↓, 4x faster than 0Axy)
                      O8x        Volume crest (attack to max, decay to note volume)
                      Jxy        "Fake reverb" volume decay (x ticks/step, y speed)
Bxx  Bxx        0Bxx       0Bxx  Jump to order no. x
Cxx  vxx   lxx   xx    xx  0Cxx  Note volume (IT/RNS/FUR/FNK see volume column)
                      Ixy        Target volume slide (vol col, x tickstep, y step)
                D3xx  I1x        Target volume slide (vol col)
                D4xx  I6x        Fine target volume slide (vol col, assume speed 6)
Dxx  Cxx  ZBxx  0Dxx       1Dxx  Pattern break to row xx of next pattern (S3M BCD)
D00  C00  ZB00  0D00       0F00  Pattern break
E00  S00        1000       0FF8  Disable Amiga "LED" Filter
E01  S01        1001       0FF9  Enable Amiga "LED" Filter
E02  S02        1200             Amiga: period mod with next ch off; GUS: Pause off
E03  S03        1201             Amiga: period mod with next ch on; GUS: Pause on
E04  S04        1100             Amiga: AM with next ch off; GUS: Filter mode 0
E05  S05        1101             Amiga: AM with next ch on; GUS: Filter mode 1
E06  S06        1102             GUS: Filter mode 2 (Amiga: AM with 2nd next ch)
E07  S07        1103             GUS: Filter mode 3 (Amiga: AM with 3rd next ch)
E08  S08                         AON keep wave off
E09  S09                         AON keep wave on
E0A  S0A                         AON keep envelope off
E0B  S0B                         AON keep envelope on
E0C  S0C                         AON wavetable freeze off
E0D  S0D                         AON wavetable freeze on
E0E  S0E                         AON wavetable never reset off
E0F  S0F                         AON wavetable never reset on
E1x  FFx        F1xx  O4x  11xx  Fine portamento slide up (1/16 semitone, 192EDO)
E2x  EFx        F2xx  O5x  12xx  Fine portamento slide down (1/16 semitone, 192EDO)
E3x  S1x                         Glissando (snap porta to note) (0 off, 1 on)
E4x  S3x                         Vibrato waveform (0 ~, 1 N, 2 LП, 3 ░, +4 cont)
                E30x             Vibrato shape (0..B: ~ m w ^v И N LП ░ П_ Ц¯ ∩_ ∪¯)
E40  S30        E300  O00                         sine
                E303  O01                         triangle
E41  S31        E306  O02                         square
E42  S32        E305  O03                         sawtooth
E43  S33        E307  O04                         random
E5x  S2x                   15xx  Set Amiga finetune (4bit signed, MED 8bit signed)
E6x  SBx                   16xx  Pattern loop here x times (E60/SB0: loop start)
E7x  S4x                         Tremolo waveform (0 ~, 1 N, 2 LП, 3 ░, +4 cont)
E70  S40              O05                         sine
                      O06                         triangle
E71  S41              O07                         square
E72  S42              O08                         sawtooth
E73  S43              O09                         random
E8x  S8x        80xx  OEx        Coarse Panning (0 left, F right; FUR dup x)
E9x  Q8x        0Cxx  ODx  1F0x  Retrigger note each x ticks (no volume change)
E96  Q86        0C06       0FF1  Play note also on next row (XM/IT assume F06/A06)
E92  Q82        0C02       0FF3  Play note thrice per row (XM/IT assume F06/A06)
EAx  DxF        F8xx  O6x  1Axx  Fine volume slide up
EBx  DFx        F9xx  O7x  1Bxx  Fine volume slide down
ECx  SCx   CFx  ECxx  O1x  18xx  Note cut after x ticks (volume FX in FNK)
EDx  SDx   Qxx  EDxx  O2x  1Fx0  Note delay by x ticks
ED6  SD6   Q06  ED06       0FF2  Delay note to the next row (assume F06/A06/ZK06)
EEx  SEx                   1Exx  Pattern row prolong ("speed"*ticks, same row sum)
EFx  SFx                         Funkrepeat / Invert loop / Select Z "MIDI" macro
                F5xx             Disable macro
                F6xx             Enable macro
Fxx  Axx  ZKxx  0Fxx  OFx  09xx  "Speed" (row ticks, XM <20, FUR no grooves odd rows)
Fxx  Txx  ZTxx  F0xx             Set tempo in BPM (XM >=20, not when VBlankSync)
F00  A00  ZT00  FFxx       0FFE  Halt, hang, next song, or tick warp
Gxx  Vxx                         Global volume (00..80)
Hxy  Wxy                         Global volume slide (x up, y down, IT F=fine)
HFx  WFx              OAx        Fine global volume slide down (FNK 0..7 -> 0..1C)
HxF  WxF              OAx        Fine global volume slide up (FNK 8..F -> 0..1C)
Ixx  +xx        E5xx             Finetune (00..80..FF, range ± 1 semitone)
Jxx  *xx                         Smooth finetune (00..80..FF, range ± 1 semitone)
Kxx  $xx        FCxx             Key off after x ticks (XM more like fast fade)
                E7xx             Macro release
Lxx  &xx   Exx             0Exx  Envelope position (8MED "synth" program jump)
Mxx  ?xx   Yxx                   Play row with probability (Y00: random note)
Nxx  %xx   Jxx                   Route track (J00: master, JFF: parent group)
Oxx  'xx   Zxx  F7xx             Trigger a phrase (Z7F: keymap) / restart macro
Pxy  Pxy        83xy             Panning slide (x left, y right)
PxF  PxF        85x0  O0F            - Fine panning slide right (FNK 1/256)
PFx  PFx        850x  O0E            - Fine panning slide left (FNK 1/256)
Qxy  ;xy                   1Fxy  Delay for x ticks and retrigger every y ticks
Rxy  Qxy   Rxy                   Retrigger note each y ticks with volume change x
Sxx  -xx   Xxx                   Stop effect device no. x (X00 panic)
                      O0A        Stop pitch/note effects
                      O0B        Stop volume/pan effects
                      O0C        Stop all effects
Txy  Ixy                         Tremor (x on ticks, y off ticks)
Uxx  Uxy                         Fine vibrato (4x more precise than 4xy/Hxy)
Vxx  Mxx   Mxx        Nxx        Channel volume (XM/IT ..40, RNS/FNK ..FF -60~+3db)
Wxx  Nxy                         Channel volume slide
X0x  /xx        E0xx  O3x        Set arpeggio speed (X00: HMNT mega arpeggio)
X1x  FEx                         Extra fine portamento up (4x E1x/FFx precission)
X2x  EEx                         Extra fine portamento down (4x E2x/EFx precission)
X3x             EA0x             Legato control (auto insta porta) (0 off, 1 on)
X4x             E4xx             Set vibrato range
X5x  S5x                         Panbrello shape (0 ~, 1 N, 2 LП, 3 ░, +4 cont) 
X6x  S6x  ZDxx                   Fine pattern row prolong (ticks, same row sum)
X7x  S7x                         New Note Action and envelope control (hack in XM)
X70  S70                             - Playing notes cut
X71  S71                   0FFB      - Playing notes off/release (MED except last)
X72  S72                             - Playing notes fade
X73  S73                             - Set NNA to cut
X74  S74                   0FFA      - Set NNA to continue (sustain pedal)
X75  S75                   0FFB      - Set NNA to off/release (pedal off)
X76  S76                             - Set NNA to fade
X77  S77                             - Volume envelope off
X78  S78                             - Volume envelope on
X79  S79                             - Panning envelope off
X7A  S7A                             - Panning envelope on
X7B  S7B                             - Pitch envelope off
X7C  S7C                             - Pitch envelope on
X7D  S7D                             - Pitch envelope acts as pitch envelope
X7E  S7E                             - Pitch envelope acts as filter envelope
X7F  S7F                             - (unused, Toggle envelope reset?)
X8x  @xx   Wxx                   Track pre-mixer surround width
X9x  S9x                         Sound control (hack in XM)
X90  S90                             - Surround off
X91  S91                             - Surround on (invert right channel, ST3 XA4)
X92  S92                             - (unused, improved 2D surround (Xxx, S8y)?)
X93  S93                             - (unused, 3D surround (Xxy, S8z)?)
X94  S94                             - (unused, side 2D surround (Xyy, S8x)?)
X95  S95                             - (unused, polar coord surround (Xθφ S8r)?)
X96  S96                             - (unused, echo off?)
X97  S97                             - (unused, echo on?)
X98  S98                             - Reverb off
X99  S99                             - Reverb on
X9A  S9A                             - Center surround (S91 RC, Xxx to front)
X9B  S9B                             - Quad surround (S91 to rear, Xxx stays rear)
X9C  S9C                             - Global (per-channel) filters
X9D  S9D                             - Local (per-note) filters
X9E  S9E   B01  DF00                 - Play sample forwards
X9F  S9F   B00  DF01                 - Play sample backwards
                      O9x        Channel echo feedback gain
                      OBx        Channel echo delay
                      OCx        Channel echo decay
XAx  SAx        92xx             Set high sample offset (times 65536)
XBx  =F0  ZLxx                   Set lines per beat (ZL00 Stop, XB0/=F0 Disable)
XCx  =00  ZG0x                   Toggle song groove/swing (0 off, 1 on)
XDx  =xx        09xx             Groove/swing pattern (IT<F0, even speed if none)
XEx  T0x                         Tempo slide down (ritardando)
XFx  T1x                         Tempo slide up (accelerando)
Yxy  Yxy   Nxy  84xx             Panbrello (x speed, y depth)
Zxx  Zxx                   10xx  MIDI macro (default 00..7F cutoff, 80..8F/FF reso)
[xx  [xx   Oxx  F4xx             "Finer" volume slide down (64x slower than Axy)
                      Hxy        Variably fine volslide down (x ticks/step, y step)
\xx  \xx                         Smooth Zxx MIDI Macro
]xx  ]xx   Ixx  F3xx             "Finer" volume slide up (64x slower than Axy)
                      Gxy        Varibably fine volslide up (x ticks/step, y step)
^xx  ^xx        EFxx             Global pitch bend (cumulative, legacy)
_xx  _xx                   0Axx  MIDI polyphonic aftertouch (also Zxx macro)
`xy  `xy   Cxy             08xy  Cut volume by x/15 after y ticks / Decay & hold
`Fy  `Fy   CFy  DCyy       08Fy  Mute after x ticks
{xy  }xy        E2xy             Note slide down (x speed, y semitones)
}xy  {xy        E1xy             Note slide up (x speed, y semitones)
~xx  ~xx        13xx             Set waveform / Wavetable jump / Move loop like EFx
!xx  !xx   Lxx                   Track pre-mixer volume (00 -inf, FF +3 db)
#xx  #xx                         Parameter extension (LSB, original effect MSB)
$xx                              Wavetable speed / Funkrepeat (see AON)
%xx  "xx        Cxxx       0Fxx  Set tick rate in Hz (MED 0F33 = 50 Hz)
&xx             EExx       2Dxx  Send external command (sync) / Run (ARexx) script
'xx             FDxx             Set virtual tempo numerator (tick skip/dup)
(xx  (xx   Dxx                   "Extra finer" portamento down (each tick)
)xx  )xx   Uxx                   "Extra finer" portamento up (each tick)
*xx  .xx                   1Cxx  MIDI program change (*xx #xx #xx bankM bankL prog)
                EBxx             Set legacy sample mode bank (maybe for SF2)
/xx             FExx             Set virtual tempo denominator (tick skip/dup)
:xy  :xy                         Note delay for x ticks and cut after y ticks
;xy                              AON play samples >128k (x), avoid noise <512 (y) 
<xy  <xy        E9xy             Quick legato down (y semitones, after x ticks)
=xx                              (Excel formulae - echos, delays, dubs, layers)
>xy  >xy        E8xy             Quick legato up (y semitones, after x ticks)
                E6xy             Legacy quick legato (x < 8 up, x > 7 down)
?xy                              Oktalyzer arpeggio 3
@xy                              Oktalyzer arpeggio 4
     xyy                   3xyy  Set custom MIDI controller x to y (IT x 0..9)
          xyzz                   Set chain effect x's param y to z (MPT PC note)
           Fxx                   (unused, filter?)
           Hxx                   (unused, Hertz?)
           Kxx                   (unused, key off?)
                0Exx             (unused)
                14xx             Set GUS filter coefficient K1 low byte
                15xx                                           high
                16xx                                        K2 low
                17xx                                           high
                18xx                                        K1 slide up
                19xx                                                 down
                1Axx                                        K2       up
                1Bxx                                                 down
                2xxx             Set GUS envelope count (000..1FF)
                22xx                              left volume ramp (signed 8bit)
                23xx                              right
                24xx                              filter coefficient K1 ramp
                25xx                                                         (slow)
                26xx                                                 K2
                27xx                                                         (slow)
                3xxx             Set GUS filter coefficient K1
                4xxx             Set GUS filter coefficient K2
                5xxx             Other chip specific commands
                6xxx             Other chip specific commands
                7xxx             Other chip specific commands
                Axxx             (unused)
                Bxxx             (unused)
                D0xx             (unused)
                D1xx             (unused)
                D2xx             (unused)
                D5xx             (unused)
                D6xx             (unused)
                D7xx             (unused)
                D8xx             (unused)
                D9xx             (unused)
                DAxx             (unused)
                DBxx             (unused)
                DDxx             (unused)
                DExx             (unused)
                FBxx             (unused)
                      O0D        (unused, was toggle sample looping)
                           0FF4  (unused)
                           0FF5  (unused)
                           0FF6  (unused)
                           0FF7  (unused)
                           0FFC  (unused)
                           13xx  (unused)
                           17xx  (unused)
                           1Bxx  (unused)
                           4xyy  (unused, disambiguate MIDI effects?)

Retrigger volume alteration:
0 last, 1 -1, 2 -2, 3 -4, 4 -8, 5 -16, 6 *2/3, 7 /2,
8 none, 9 +1, A +2, B +4, C +8, D +16, E *3/2, F *2

Volume column (unless noted otherwise, XM/RNS 0..F, IT 0..9):

  XM  IT   RNS  FUR  Description
  xx  vxx  lxx  xx   Note Volume (XM+IT 00..40, RNS 0..80)
p/↔x  pxx  pxx       Note panning (XM 0..F, IT 00..20..40, RNS 00..40..80)
  +x  ax   ix        Volume slide up (RNS 16x more coarse than Ixx)
  -x  bx   ox        Volume slide down (RNS 16x more coarse than Oxx)
u/↑x  cx   hx        Fine volume slide up
d/↓x  dx   nx        Fine volume slide down
  ix  ex   dx        Portamento down (IT 4x more coarse than Exx, RNS semitones)
  zx  fx   ux        Portamento up (IT 4x more coarse than Fxx, RNS semitones)
m/♩x  gx   gx        Portamento to note (XM 4x coarser, IT mapping, RNS semitones)
v/≈x  hx   vx        Vibrato depth
  ox  ox   sx        Sample cue (times 2048 by default, with Oxx per256age)
l/←x  lx   jx        Panning slide left (0..F)
r/→x  rx   kx        Panning slide right (0..F)
  sx  ux   fx        Vibrato speed (frequency) (0..F)
  b0  w0   b0        Play backwards
  b1  w1   b1        Play forwards
  cx  kx   cx        Note cut after x ticks
  nx  mx   mx        MIDI Command (provide instrument no. and effect data xxyy)
  n0  m0   m0            - Controller change (xx controller no., yy value)
  n1  m1   m1            - Pitch bend (xx main, yy fine tune)
  n2  m2   m2            - Program change (xx bank?, yy preset)
  n3  m3   m3            - Channel pressure (yy amount)
  qx  qx   qx        Note delay by x ticks
  gx  ix   rx        Retrigger envelope and effects (not sample)
  yx  yx   yx        Trigger note with probability
  ex  nxx  exx       Fractional note delay to next row (XM ⅟16, IT ⅟64, RNS ⅟256)

Small to big IT effect mapping:
e0=E00, e1=E04, e2=E08, e3=E0C, e4=E10, e5=E14, e6=E18, e7=E1C, e8=E20, e9=E24
f0=F00, f1=G04, f2=F08, f3=F0C, f4=F10, f5=F14, f6=F18, f7=F1C, f8=F20, f9=F24
g0=G00, g1=G01, g2=G04, g3=G08, g4=G10, g5=G20, g6=G40, g7=G60, g8=G80, g9=GFF

Note: Renoise has a separate volume, panning and delay column. Delay column only accepts effect exx, effects ix and ox are exclusive to volume column, and jx and kx are exclusive to panning column. ReTeMuS is all-forgiving, for it doesn't care.

Note: HivelyTracker, DigiBooster 3, and AdLibTracker 2 have another full effect column instead of a volume column. Famitracker and DefleMask let you have 4 full effect columns in addition to a volume column, and Furnace even 8. Once the volume column stopped to be only for volume in FT2, it's to be expected that users will try to put an effect into the wrong column. Also someone will definitely mix hexadecimal XM/RNS volume column effects with IT decimal ones, so better define interpretation for values A..F or 41..FF for the IT ones. For example v255 or vFF would be ~4x amplification and p65 to p255 would continue running quadraphonically along the square, which would make for "8D" effect. Or gA..gF would be fine note portamento 1..6 16ths of a semitone.

Note: Some effects internally exist in libOpenMPT for backwards compatibility, but they are inaccessible from OpenMPT UI, so my letters are pure invention. These are: {xy, }xy, {xy+Rzt, }xy+Rzt, X9F+9xx, X96/X97, o0+9xx, .xx (dummy), X9E/X9F, AON Gxx (8bit Cxx), X00+0xx (HMN 7xx), Lxx (8MED Exx)

Note: Furnace briefly changed the sample offset effect to allow for selecting offset byte. Only 3 bytes were supported up to 92xx, meaning you couldn't jump past sample 16777215 (6m20s of CD audio or 87s of 192 kHz hi-res master). Recently it was changed to take full range of the 9xxx space at regular 256 sample increments, which means it's only possible to jump to sample 1048320 (23.77s of CD audio or 5.46s of 192 kHz), just like with SAx+Oxx in Impulse Tracker.

Note: FunkTrackerGOLD is heavily volume-centered, probably due to lack of volume envelopes. The echo is a true DSP. Was the 1st tracker for *NIX, discontinued way before Soundtracker (XM effects) and Cheesetracker (IT effects) came out, will only work with OSS (modprobe snd-pcm-oss). The code uses nested functions which aren't standard C90, and sys/stat.h defines are broken. After getting it to compile without any -Wextra warnings in -std=c90, it segfaults when trying to play, and valgrind constantly breaks on Manjaro due to missing debuginfo, so can't fix.


MadTracker 2 wide effects

In MadTracker 2, any XM effect can be specified with 00xxyy, and any IT effect can be specified with 10xxyy, xx being displayed alphanumerically for XM (Z=35=23h) and alphabetically for IT (Z=26=1Ah). Extensions beyond that range (like \xx #xx :xy &xx $xx) are not supported. The proprietary effects have very long words. There's also separate panning column supporting only Lx and Rx, and volume column supports only Ux and Dx.

Also MT2's antipiracy model of not opening modules made with old cracked versions was flawed because it punished those who had repented, and new cracked versions made sure to patch it, besides it's basically abandonware anyway. With a little bit of extra office work, all the limitations of unregistered version can be gotten around, just like with the mono-only file output driver of Impulse Tracker 2. But pirates gotta pirate, just like with The Ultimate Soundtracker. Remember where the demoscene came from, and these people can crack Denuvo. Also you can't put any DRM in a plain text format.


00xxyy - FT2 effect (xx is displayed alphanumerically as 0..9A..Z)
01xxxx - Portamento up (1/256ths of a semitone)
02xxxx - Portamento down (1/256ths of a semitone)
03xxxx - Glissando (1/256ths of a semitone per tick)
04xxyy - Vibrato (x speed, y depth)
07xxyy - Tremolo (x speed, y depth)
080xyy - Set polarity (x) and panning (yy, 01..80..FF, 00 is no change)
0800yy      - no inversion
0801yy      - invert left channel
0802yy      - invert right channel
0803yy      - invert both channels
09xxxx - Sample offset (times 256)
0Cxxxx - Volume (0000..8000..FFFF, 2x amplification)
0Fxxyz - Set tempo, rows per beat, and ticks per row
10xxyy - Impulse Tracker effect (xx is displayed alphabetically as -A..Z)
1D00xy - Tremor (x off ticks, y on ticks, inverse of 10-Ixy or 00-Txy)
20xxyy - Set cutoff (xx>0) and/or resonance (yy>0)
21xxyy - Set attack (xx-1 if xx>0) and/or decay (yy-1 if yy>0)
22xyzt - Set cutoff, resonance, attack, and/or decay (= 20x0y0 + 21z0t0)
240000 - Reverse
80xxxx - Channel volume (0000..8000..FFFF, 2x amplification)
90xxyy - Sample cue (xx) with 1/256ths to next cue (yy), if no cue then fractional sample position (xx denominator, yy numerator)
9Dxxyy - Set offset (256*xx) and note delay (yy ticks)
CCxxyy - Send MIDI CC (xx controller code, yy value)
F0xxxx - Set channel effect
F00000       - No effect
F00001       - Delay [value, depth, feedback]
F00002       - Stereo delay [value, depth, feedback, waveform, period, amplitude]
F00003       - Filter [type{LP,HP,BP,notch,2no,peak,2pk,phaser},cutoff,reso,width]
F00004       - Flanger [waveform, period, amplitude]
F00005       - Analog wah filter [cutoff, resonance, waveform, period, amplitude]
F00006       - Distortion/Compressor [level, threshold, curvature]
F00102       - mpReverb [gain, pre-delay, low-cut, time]
F00103       - mpReverb2 [{mpReverb}, width, pan, lowgain, color]
Fxyyyy - Set channel effect parameter [x] to value y (see above, 1 based)
F900xx - Mix this channel into a channel on the right (xx > this channel no.)
FF0x0y - Visual slideshow effect (karaoke?)
FF010y       - Logo change (0 white bg, 1 black bg, 2 master osc, 3 tracks osc)
FF020y       - Fade toggle (0 off, 1 on)
FF030y       - User logo y (0 cover, 1..F slides, dimensions 256x96)

I like effect namespacing, now you only have to choose between MT2 and SuxVox letters:

xxyyzz - Renoise effect chain thing (xx is A1..C3 for RNS 1..Y, yy is 0..Z)
E2xxyy - Renoise effect (ZA..ZZ is E1..FB internally)
E60xyy - FunkTrackerGOLD effect (display x as -A..O)
E90x0y - UNIS 669 effect (display x as -A..H)
E8xxyy - Oktalyzer effect (display xx as 0..Z)
EAxxyy - Art Of Noise effect (display xx as 0..Z)
EDxxyy - OctaMED effect
EExxyy - PolyEnd Tracker effect (display xx as ASCII)
EFxyzw - Furnace effect
EF10xy - Farandole Composer effect (when emulating GUS)


SunVox effects

SunVox has similarly wide effects like MT2, but the parameter supposedly goes only to 8000h. 00xxyy and 10xxyy is conveniently free. There are also some destructive effects:

01xxxx - portamento up
02xxxx - portamento down
03xxxx - note portamento
04xxyy - vibrato with xx speed and yy depth
05xxxx - pitch bend up (1/256 semitones)
06xxxx - pitch bend down (1/256 semitones)
07xxxx - set phase or sample offset (0000..8000 beginning..end)
08xxyy - arpeggio (xx 2nd note step, yy 3rd note step) [MT2 conflict]
09xxxx - set phase or sample offset (times 256 samples)
0Axxyy - volume slide xx up or yy down
0F00yy - set speed (yy 01..1F), BPM (yy 20..FF)
0FFxyy - set time grids (x 0 or 1, yy 00..20)
11xxxx - fine slide up
12xxxx - fine slide down
130xyz - set Bypass/Solo/Mute flags (1st 16 channels)
140xyz - reset Bypass/Solo/Mute flags (1st 16 channels)
15xxyy - global pitch bend (note xx, 1/128 semitones yy) (7F..01,80..FF)
19xxxx - retrigger note after xxxx ticks
1Axxyy - fine volume slide up/down (xx up, yy down)
1C00xx - cut note after xx ticks
1D00xx - note delay yy ticks [MT2 conflict]
1Fxxxx - set BPM [different semnatics than MT2]
20xxxx - note probability [MT2 conflict]
21xxxx - note probability with random velocity [MT2 conflict]
22xxxx - set controller value to random number from 0000 to xxxx [MT2 conflict]
23xxyy - set controller value to random number between xx and yy
24xxxx - take a note from line xxxx on the same track [MT2 conflict]
25xxyy - take a random note from the range of lines xx..yy on the same track
26xxxx - take a note from track xxx on the same line
27xxyy - take a random note from the range of tracks xx..yy on the same line
28xxxx - take a note from line xxxx on track 0
29xxyy - take a random note from the range of lines xx..yy on track 0
300000 - stop playing the song
31xxxx - jump to address xxxx after row (see 32000x)
32000x - set jump address mode:
320000       - absolute address
320001       - pattern beginning + address
320002       - pattern beginning - address
320003       - next line + address
320004       - next line - address
33xxxx - slot sync for sv_sync_resume() in SunVox library
34xxyy - set (xx) or reset (yy) project options: 1 - no porta on 1st tick, 2 - no volslide on 1st tick, 4 - Round-robin track alloc algo instead of tight packing
350xyy - bind MIDI out msg x (0 PC, 1 Pr, 2 PB) to ctrl y (0 off; 80..FF ctrl0..7F)
38xxyy - delete event on track xx with a probability of yy (00..FF)
39xxyy - cyclic shift of track xx down by yy lines
3Axxyy - generate a new iteration of yy-line polyrhythm on track xx
3Bxxyy - copy track xx to the pattern yy (replacing track xx there)
3Cxxyy - copy track xx from from the pattern yy (replacing track xx here)
3Dxxyy - write random values to track yy from line xx (min, max, column in track 0)
40xxxx..5Fxxxx - delay an event for fraction of the line (40..5F 0..96.875%)


OctaMED MIDI reminder

In OctaMED, cetain effects take on different meaning with MIDI instruments (probably an implementation detail, but maybe add $4000 to avoid conflicts):

00xx - MIDI controler value (select with 05xx) [Zxx]
01xx - MIDI pitch bend up
02xx - MIDI pitch bend down
03xx - Set MIDI pitch bend [Ixx]
04xx - MIDI modulation
05xx - Select MIDI controller [EFx select macro]
0Cxx - MIDI velocity (0C40 is MIDI 7F)
0Dxx - MIDI channel pressure [Vxx]
0Exx - MIDI panning (00..3F..7F) [8xx]

See http://cd.textfiles.com/zoom2/info/guides/octamed4manual/102-114.guide and http://cd.textfiles.com/amigaformat/aformat-26-199804/-Websites-/OctaMED/amdetails.html .


Amiga history

You can sometimes see remnants of old Soundtracker pirate editions effects, before everyone agreed on Protracker ones. Taken from https://web.archive.org/web/20230316093224/http://helllabs.org/tracker-history/trackers.svg , which misses Symphonie Pro and MultiTracker.

1xy - arpeggio
2xx - portamento up (<80) or down (>80) (split by DOC ST IX, moving arp to 0)
3xx..Bxx - "modulation" (removed by DOC ST IX)
3xx - note portamento (NST 1.0, ST 2.5, MED 2.10)
4xx - vibrato (NST 1.0, ST 2.5, MED 2.10)
5xx - finetune (His Master's NoiseTracker, modern in PT, PT E5x, 8MED 15xx)
6xx - sync? (modern in PT)
7xy - mega arpeggio (His Master's NoiseTracker, modern in PT)
8xy - decay and hold (MED 3.00, modern in FT2), supposedly string synthesis in PT
9xx - ticks per row (MED 3.00, grooves in DefleMask, modern in PT)
Axy - nibble volume slide (ST 2.5)
Bxx - position jump (DOC ST 2.0, MED 2.10)
Cxx - volume (TJC ST II)
Dxx - volume slide (TJC ST II, removed by DOC ST IX, modern in DOC ST 2.0)
Exx - fine volume slide (TJC ST II, removed by DOC ST IX, PT 1.0 EAx EBx)
Fxx - tick rate (ST III and DOC ST IV, FFx was reserved by OctaMED)


Oktalyzer has few somewhat intuitive effects (actually base36, format description was unaware of presentation), with bespoke arpeggios:

1xx  Portamento down [E30+1xx]
2xx  Portamento up [E30+2xx]
Axy  Arpeggio 3: -x,0,+y [3FF @ F01 or ?xy]
Bxy  Arpeggio 4: 0,+y,0,-x [3FF @ F01 or @xy]
C0y  Arpeggio 5: +y,+y,0 [0yy]
Dxx  Glissando down (semitones per tick = linear) [E31+1(40*x) or {1x]
F0x  Set Amiga LED filter [E0x]
Hxx  Glissando up (semitones per tick = linear) [E31+2(40*x) or }1x]
Lxx  Chromatic walkdown (semitones per line) [3FF or {yx @ F0y]
Pxx  Position jump [Bxx]
R00  Release sample [X71]
Sxx  Set "speed" (ticks between advancing lines) [Fxx 01..1F]
Uxx  Chromatic walkup (semitones per line) [3FF or }yx @ F0y]
Vxx  Volume control (xx <= 0x40) [Cxx]
V4x  Fast volume slide down (V50 counts as by 10h etc.) [A0x]
V5x  Fast volume slide up [Ax0]
V6x  Fine volume slide down [EAx]
V7x  Fine volume slide up [EBx]


There's quite interesting Art of Noise, which has letters like FastTracker, but different, mainly for wavetable synthesis. Protracker 1 and 2 solved it by simply allowing to swap the sample on the fly and version 1.1 had the Funkrepeat (EFx, moving loop points) and plucking string synth (8xx) effects. Later Protracker versions had Invert Loop effect in place of Funkrepeat. Invert Loop trashed the sample data by randomly sign inverting samples. Other Art of Noise effects try to get around having only 1 effect column, and unlike 5xy and 6xy the parameter is not just volume (letter marked orange):

E5x - set loop point [E60]
Gxy - set volume to 4*x+y+4 vblanks (dunno what vblanks have to do with volume)
Hxy - synth control (x keep wave bool, y keep envelope bool) [E08/E09+E0A/E0B]
Ixx - wavetable speed [EFx funkrepeat or $xx]
Jxx - set arpspeed [X0x]
Kxx - set volume & continue vibrato [Cxx+400]
Lxy - fine volume slide & portamento up (volslide x, porta y) [EAx+20y]
Mxy - fine volume slide & portamento down (volslide x, porta y) [EBx+10y]
N0x - avoid noise (wave < 512 B, bool) [;0x]
O0x - play samples > 128 kB (bool) [;x0]
Pxy - fine volume slide & continue vibrato (x up, y down) [EAx+EBy+400]
Qxy - volume slide & portamento down (syndrums) (x porta, y volslide) [10x+A0y]
Rxx - set volume & continue tone portamento [Cxx+300]
Sxy - fine volume slide & continue tone portamento (x up, y down) [EAx+EBy+300]
Txx - set track-volume [Vxx]
Uxy - set wavetable mode (x freeze, y never reset) [E0C/E0D+E0E/E0F]
Vxx..Zxx - unused, unused, extenal event 1,2,3 (sync) [&xx]


DigiBooster 1.6 effects (only those different to ProTracker):

8xx - Robot ("metallic" effect, "I am Iron Man"?) [Txy]
E3x - Play sample backward, x=1 "next from front loops" (sic) [X9F]
E40 - Stop playing sample (performance reasons) [EC0]
E5x - (unused)
E7x - (unused)
E8x - High sample offset (times 0x10000) [XAx]
E9x - Retrace (retrigger?) [E9x]
EFx - (unused)


669 -> UNIS -> Farandole 

Composer/UNIS 669 has only 6 or 8 effect letters and the effects take only 1 nibble as the parameter. Also the tick rate is slightly less than 32 Hz, which amounts to 78 BPM at "speed" 6 and 4 rows per beat, which is why the default "speed" was 4, so 117 BPM. Panning has only 4-bit precision, which makes panbrello impractical. Volume being 4-bit is fine, tremolo is just more like gate.

Ax - Portamento up [10x]
Bx - Portamento down [20x]
Cx - Portamento to note [30x]
Dx - Set finetune (5/8 semitones up in XMP, nonlinear FFx in OMPT) [E1x]
Ex - Persistent vibrato depth (actually more like 2-note arpeggio) [40x/0xx]
Fx - Set "speed" (F0: Super Fast Tempo™) [F0x]
G0 - Fine panning slide left [P4F]
G1 - Fine panning slide right [PF4]
Gx - (unused; Fvol, Fporta, gliss, filter, Ftempo, offset mul, patt break?)
Hx - Retrigger note with speed x [E9x]
Ix..Ox - (unused; note cut, note delay, patt delay, loop, tremolo, pan, offset?)
x - volume (separate column, 4bit)

The successor to UNIS is FunkTracker(GOLD), which has had the letters considerably rearranged and the effect width was expanded over the volume column.

Farandole Composer looks like Composer 669 with 16 channels, but has 16 completely different effect letters vaguely closer to ProTracker, and a very outlandish tempo system centered around GUS. Could be a nice complement to FUR set in GUS mode (10xy - Farandole Composer effect, FC10xy in MT2):

03 - Fulfill sample loop (cuts note due to bugs) [EC1]
04 - Old tempo mode (allow slow tempos due to underflow, process at 4 Hz)
05 - New tempo mode (default 32 Hz)
1x - Pitch offset up (4*x GUS frequency steps @ 16 channels) [E1x]
2x - Pitch offset down (4*x GUS frequency steps @ 16 channels) [E2x]
3x - Persistent note portamento (rows to complete in, but scales with tempo)
4x - Retrigger note x times in the row (subdivide, 0 is crash)
5x - Set vibrato depth (global, default 4) [X4x]
6x - Vibrato speed [4x0]
7x - Fine volume slide up [EAx]
8x - Fine volume slide down [EBx]
9x - Sustained persistent vibrato speed
ax - Persistent slide to volume (2* faster than 3x)
bx - Set panning [E8x]
cx - Retrigger once on tick x (supposed delay with timing like 4F, c0=4F)
dx - "Fine" tempo slide down (cursed) [XEx]
ex - "Fine" tempo slide up (cursed, up to 100) [XFx]
fx - Set "coarse" tempo (cursed, higher->slower, [256, (128/i)]) [F0x]
x - volume (separate column, 4bit)

This was very obscure. Thanks to AliceLR AKA Lachesis for write up and libxmp implementation, and complaining about inaccurate import: https://bugs.openmpt.org/view.php?id=1541 . Nobody seems to have really used Farandole, as when it was released in 1993, there was already Multitracker with full 32 GUS channels and familiar Protracker effect syntax and semantics, although no volume column, and on the horizon was ScreamTracker 3 with 16 digital/GUS channels and 9 AdLib channels, richer effect repertoire, and no scary evaluation period language.


There's also format specification archive at ModLand: https://ftp.modland.com/pub/documents/format_documentation/ . If you know some Finnish, this paper discusses the history of trackers: https://musiikki.journal.fi/article/view/87867/47085 .


WaveTracker

A wavetable-oriented tracker with vertical pianoroll visualization, in addition to per-channel oscilloscopes. The 6px proportional font is very small, so no Hi-DPI screens. Also only 24 channels, but maybe that will eventually increase. Effect letters resemble Famitracker a bit, but it's another tracker that had to make their own. Effect parameters that are not nibble-split are decimal, sort of like ST3's pattern break. There's a separate decimal volume column, and I guess the instrument column is also decimal. As is typical for chiptune trackers, instead of effect memory, the effects are continuous and x00 turns them off.


0xy - Arpeggio
1xx - Portamento up
2xx - Portamento down
3xx - Portamento to note (Glide)
4xy - Vibrato (speed x, depth y)
5xx - (unused)
6xx - (unused)
7xy - Tremolo (speed x, depth y)
8xx - Pan (00..50..99)
9xx - Stereo width (Right channel phase offset) [X8x]
Axx - Volume slide down [A0x]
Bxx - Position jump
C00 - Halt [F00]
Dxx - Pattern break to row x
Exx - (unused)
Fxx - Speed (ticks per row)
Gxx - Row delay for x ticks (per-channel, so more like note delay) [EDx]
Hxy - Channel Filter (cutoff x, resonance y) [Zxx]
Ixx - Wave blend (00 original wave, 99 next wave)
Jxx - Wave stretch (a bit like PWM)
Kxx - Wave Sync
Lxx - (unused)
Mxx - Wave FM (original wave carrier, next wave modulator)
Nxx - (unused)
Oxx - (unused)
Pxx - Channel pitch bend (50 center) [Ixx]
Qxy - Note bend up (speed x, y semitones) [}xy]
Rxy - Note bend down (speed x, y semitones) [{xy]
Sxx - Note cut after x ticks [ECx]
Txx - (unused)
Uxx - (unused)
Vxx - Set wave [~xx]
Wxx - Volume fade up [Ax0]
Xxx - Channel downsample factor
Yxx - Sample percentage offset {o0+Oxx}
Zxx - (unused)


PolyEnd Tracker+

A hardware tracker for DAW-less musicians. Has an FM, wavetable, and granular synth, and many keys that resemble a PC keyboard. But has only 16 tracks (channels) after an upgrade from 8, and sample RAM in the order of MB, which is too little for $799 (non-Plus was $599), which is the cost of a new PC with Renoise. Of course PolyEnd had to make their own effect alphabet, as if there wasn't already enough of them. There are 2 effect columns, commands are alphabetical, parameters have 3 digits and are decimal, some have a sign. I had to objdump the firmware and look for strings in it to get the full documentation, RTFM wasn't enough.

!xxx - Effect off
A+xx - Arpeggiator (needs MIDI Chord, +: / up, \ down, R rnd, x: speed) [X0x] {/xx}
Bxxx - Band Pass Filter Cutoff (0..100%) {Zxx}
Cxxx - Chance of a note playing (0..100%) [Mxx] {?xx}
Dxxx - Overdrive amount (0..100%) {Mxx}
Exxx - Bitcrusher (4..16 bits)
Fxxx - Portamento up in 1/16th semitone increments (0..255) [2xx] {Fxx}
Gxxx - Note portamento (glide time: 0..49 = 0s..1s, 50..100 1s..15s) [3xx] {Gxx}
Hxxx - High Pass Filter Cutoff (0..100%) {Zxx}
Ixxx - Swing (25..75%) [XDx] {=xx}
Jxxx - Portamento down in 1/16th semitone increments (0..255) [1xx] {Exx}
Kxxx - (unused, key off?)
Lxxx - Low Pass Filter Cutoff (0..100%) {Zxx}
M+xx - Micro Tune (-99..+99) {+xx}
Nxxx - (unused, pattern delay?)
Oxyz - MIDI Chord (used also with A+xx, 0 actually?, base16) [0xy] {Jxy}
P+xx - Pan (-50..+50) [8xx] {Xxx}
Qxxx - (unused, resonance?)
Rxyy - Retrigger (x: nN note↓↑, vV vol↓↑, R rnd, _ normal; y: 0..16) [Rxy] {Qxy}
Sxxx - Sample slice/cue (1..48) {ox}
Txxx - Tempo (10..400 BPM or STP for stop (excluded from random)) [Fxx >= 20] {Txx}
U+xx - Tuning (-24..+24 semitones) [<0x or >0x]
Vxxx - Volume or Velocity for MIDI (0..100% or 0..127) [Cxx] {vxx}
Wxxx - (unused, volume slide up)
Xxxx - Pattern break (seems to conflict with xxxx) [Dxx] {Cxx}
axxx - Custom MIDI CC A (0..127, needs a channel in the instrument slot (M1..M16))
bxxx - Custom MIDI CC B
cxxx - Custom MIDI CC C
dxxx - Custom MIDI CC D
exxx - Custom MIDI CC E
fxxx - Custom MIDI CC F / MIDI program change [*xx] {.xx}
gxxx - Volume LFO Rate (tremolo or tremor) [7xy] {Rxy}
hxxx - Panning LFO Rate (panbrello) {Yxy}
ixxx - Random instrument range (-48..+48)
jxxx - Filter LFO Rate ("filtrolo")
kxxx - Position LFO Rate ("wavolo") [$xx or EFx funkrepeat]
lxyy - Finetune LFO Rate (vibrato) [4xy] {Hxy}
mxxx - Micro move (note delay, 0..100%) [EDx] {SDx}
n+xx - Random note range (-100..+100)
oxxx - (unused, pattern loop?)
pxxx - Sample, wavetable, or granular position (0..100%) [9xx or ~xx] {Oxx or ~xx}
qxxx - Gate length (note cut, 0..100%) [ECx] {SCx}
rxxx - Reverse sample (<<< or >>>) {S9F}
sxxx - Delay send (0..100%, reverb in old firmware) 
txxx - Reverb send (0..100%, not in old firmware)
uxxx - (unused, orderlist jump?)
v+xx - Random volume range (-100..+100)
wxxx - (unused, volume slide down?)
x+xx - Random FX value range (-255..+255)

Volume LFO rate values (LFOs are synced to tempo):
24 16 12 8 6 4 3 2 3/2 1 3/4 1/2 3/8 1/3 1/4 3/16 1/6 1/8 1/12 1/16 1/24 1/32 1/48 1/64

Panning, filter, position, and finetune LFO rate values:
128 96 64 48 32 24 16 12 8 6 4 3 2 3/2 1 3/4 1/2 3/8 1/3 1/4 3/16 1/6 1/8 1/12 1/16 1/24 1/32 1/48 1/64

Some instrument properties numeric IDs:
Tune = 5
Finetune = 3
Volume = 7
Panning = 10
Filter type = 9
Cutoff = 1
Resonance = 11
Overdrive = 12
Bit Depth = 13
Reverb Send = 14
Delay Send =  15
Volume Automation Type = 20
Volume Attack - Shape LFO = 21
Volume Decay - Speed LFO = 22
Volume Sustain = 23
Volume Release = 24
Volume Amount = 25
Panning Automation Type = 26
Panning Attack - Shape LFO = 27
Panning Decay - Speed LFO = 28
Panning Sustain = 29
Panning Release = 30
Panning Amount = 31
Cutoff Automation Type = 83
Cutoff Attack - Shape LFO = 84
Cutoff Decay - Speed LFO = 85
Cutoff Sustain = 86
Cutoff Release = 87
Cutoff Amount = 88
Wavetable Position Automation Type = 102
Wavetable Position Attack - Shape LFO = 103
Wavetable Position Decay - Speed LFO = 104
Wavetable Position Sustain = 105
Wavetable Position Release = 106
Wavetable Position Amount = 107
Granular Position Automation Type = 108
Granular Position Attack - Shape LFO = 109
Granular Position Decay - Speed LFO = 110
Granular Position Sustain = 111
Granular Position Release = 112
Granular Position Amount = 113
Finetune Automation Type = 114
Finetune Attack - Shape LFO  = 115
Finetune Decay - Speed LFO = 116
Finetune Sustain = 117
Finetune Release = 118
Finetune Amount = 119

There's also a word list for the built-in name generator with 1000 adjectives and 1000 nouns, which includes the word "kurwa".


FM SYNTHESIS

Due to my procrastination, below is an FM effect list (actually phase modulation), sorted by AdlibTracker 2. MPT column is a superset of Scream Tracker 3, as Impulse Tracker supported FM only as a MIDI device, and ST3 didn't support OPL3. Famitracker column considers only VRC7, which is a cut down OPLL. BambooTracker supports only OPNA. Furnace column also considers OPZ, an expanded OPM, and ESFM, an expanded OPL3. DreamTracker for Commander X16, namely its OPM or OPP chip (differs only in test registers and timer resolution), recently got full 2 bytes for effects, but VERA PSG is omitted to reduce clutter, as has already happened with OPZ and ESFM.


L3   L3   LL   NA    Z     M/P
AT2  MPT  FAM  BAM   FUR   DRTR  Description
0xy  Jxy  0xy  00xy  00xy  0Axy  Arpeggio (x & y semitones from note, x=y 2 cycle)
1xx  Exx  1xx  01xx  01xx  00xx  Portamento down (MPT only 00..DF)
                           02xx  Pitch sweep down (persistent)
2xx  Fxx  2xx  02xx  02xx  01xx  Portamento up (MPT only 00..DF)
                           03xx  Pitch sweep up (persistent)
3xx  Gxx  3xx  03xx  03xx  06xx  Portamento to note (FUR/DRTR persistent)
4xy  Hxy  4xy  04xy  04xy  08xy  Vibrato (x speed, y depth)
5xy  Kxy             05xx        Volume slide (see Axy), continue the portamento
6xy  Lxy             06xx        Volume slide (see Axy), continue the vibrato
7xy  FFx             F1xx        Fine portamento up
8xx  EFx             F2xx        Fine portamento down
9xx  Oxx       T1xx  12xx  44xx  Set modulator1/OP1 level (OPL 3F, OPM 7F)
               B0xx              Brightness (direct modulators TL+=xx-80h)
Axy  Dxy  Axy  0Axy  0Axy  04yy  Volume slide (x ↑, y ↓, DRTR <40 ↓, 40..7F ↑)
               EAxy              Extended volslide (step=x-y, new note no reset)
                     FAxy        Fast volume slide (4x faster than 0Axy)
                           05xx  Volume sweep (persistent, <40 ↓, 40..7F ↑)
Bxx  Bxx  Bxx  0Bxx  0Bxx  C3xx  Jump to order no. x (can use with Dxx)
Cxx  vxx   x    xx    xx   0Dxx  Note volume (MPT/FAM/BAM/FUR volume column)
     Wxx       T0xx              Set attenuation/level of all operators
Dxx  Cxx  Dxx  0Dxx  0Dxx  C2xx  Pattern break to row xx (default next)
                           C4xx  Jump to row x (primarily for "tables")
Exx                  Cxxx  C7xx  Set tick rate in Hz ("tempo")
Fxx  Axx  Fxx  0Fxx  0Fxx  C1xx  Set "speed" (ticks per row) (FAM xx<20)
     Txx  Fxx  0Fxx  F0xx  C6xx  Set tempo in BPM (MPT xx>=20, see T0x and T1x)
                     FDxx        Set virtual tempo numerator
                     FExx        Set virtual tempo denominator
F00  A00  Cxx  0Cxx  FFxx  C000  Halt, hang, next song, or tick warp
Gxy                              Fine volume slide, continuing the note portamento
Hxy                              Fine volume slide, continuing the vibrato
Ixx            T2xx  13xx  46xx  OPL3 Set carrier1/OP2 level (OPL 3F, OPM 7F)
Jxy                              Set waveform (x carrier, y modulator)
                     2Axy        OPL2/L3/Z Set OPx to waveform y (x=0 all)
K0x  DFx             F8xx        Fine volume slide down
Kx0  DxF             F9xx        Fine volume slide up
Lxx  Q0x  Xxx        0Cxx        Retrigger note in x ticks
Mxy  Rxy  7xy  07xy  07xy  09xy  Tremolo (x speed, y depth)
Nxy  Ixy                         Tremor (x ticks on, y ticks off)
Oxy                              Volume slide, continuing the arpeggio
Pxy                              Fine volume slide, continuting the arpeggio
Qxy  Qxy       0Kxy        40xx  Retrigger note each y ticks with volume change x
Rxy                              Volume slide, continuing portamento up
Sxy                              Volume slide, continuing portamento down
Txy                              Volume slide, continuing fine portamento up
Uxy                              Volume slide, continuing fine portamento down
Vxy                              Fine volume slide, continuing portamento up
Wxy                              Fine volume slide, continuing portamento down
Xxy                              Fine volume slide, continuing fine portamento up
Yxy                              Fine volume slide, continuing fine portamento down
Z0x                  10xx        OPL3 Set global tremolo/AM depth (0=1db, 1=4.8db)
                     1Exx  5Cxx  OPM/Z global AM LFO depth (..7F) (OPM reg $19)
Z1x                  1Fxx        OPL3 Set global vibrato/PM depth (0=7%, 1=14%)
                     1Fxx  5Cxx  OPM/Z global PM LFO depth (..7F) (+$#80, reg $19)
                     62xx  59x_  PM Sensitivity (reg $38+chn)
                     63xx  59_x  AM Sensitivity (reg $38+chn)
                     17xx  5Bxx  Set LFO frequency (00 8 mHz, FF 33 Hz) (reg $18)
                     10xy        OPN setup LFO (x off/on, y speed)
Z2x            A1xx  1Axx  48_x  Set OP1 (modulator) attack
Z3x            D1xx  57xx  4C_x                      decay (OPZ 00..1F)
Z4x                  511x  54x_                      sustain
Z5x            RR1x  521x  54_x                      release
Z6x            A2xx  1Bxx  4A_x  Set OP2 (carrier) attack
Z7x            D2xx  58xx  4E_x                    decay (OPZ 00..1F)
Z8x                  512x  56x_                    sustain
Z9x            RR2x  522x  56_x                    release
               A3xx  1Cxx  49_x  Set OP3 (modulator 2) attack
               D3xx  59xx  4D_x                        decay (OPZ 00..1F)
                     513x  55x_                        sustain
               RR3x  523x  55_x                        release
               A4xx  1Dxx  4B_x  Set OP4 (carrier 2) attack
               D4xx  5Axx  4F_x                      decay (OPZ 00..1F)
                     514x  57x_                      sustain
               RR4x  524x  57_x                      release
                     51xy        Set OPx sustain to y (x=0 all operators)
               RRxy  52xy        Set OPx release to y (x=0 all operators)
               A0xx  19xx        Set attack of all operators
               D0xx  56xx        Set decay of all operators (OPZ 00..1F)
ZAx            FB0x  110x  58x_  Set feedback strength (0..7)
                           58xx  Pan, M1 Feedback, Algo (2-3-3 bit, OPM reg $20+ch)
ZBx            080x  08xy  0Exy  Panning (AT2 1-0-2, BAM 2-3-1, FUR/DRTR 10-11-01)
     S8x                         Coarse linear panning (0-8-F)
     Xxx             80xx        Linear panning (FUR/MPT 00-80-FF, ST3 00-40-7F)
ZB1  S80             81xx        Left panning
ZB2  S8F             82xx        Right panning
     S91             88xy        Rear panning (FUR 10-11-01, MPT S9B+S91+Xxx)
                     89xx        Rear left panning
                     8Axx        Rear right panning
ZCx  SBx                         Pattern loop x times (ZC0: loop start, same track)
ZDx                              Recursive pattern loop x times (ZD0: loop start)
ZE0                              Macro key off loop off
ZE1                                                 on
                     E7xx        Macro release
ZE2                              Restarting envelope with note portamento off
ZE3                                                                       on
ZE4  &00                         Restart envelope
ZE5                              4OP track volume lock off
ZE6                                                    on
ZE7                              (unused)
ZE8                              (unused)
ZE9                              (unused)
ZEA                              (unused)
ZEB                              (unused)
ZEC                              (unused)
ZED                              (unused)
ZEE                              (unused)
ZEF                              (unused)
ZF0  $00  Lxx  0Sxx  FCxx        Release sustaining sound (AT2 ignore ADSR)
ZF1                              Reset instrument volume
ZF2                              Track volume lock on (volume is per channel)
ZF3                                                off (volume is per note)
ZF4                              Volume peak lock on
ZF5                                               off
ZF6                              Toggle modulator volume slides (usable with ZF7)
ZF7                              Toggle carrier volume slides (usable with ZF6)
ZF8                              Toggle default volume slides
ZF9                              Track panning lock on (only ZBx to change)
ZFA                                                 off
ZFB                              End vibrato, restore frequency
ZFC                              End tremolo, restore volume
ZFD                              This vibrato fine (with 4xx, 6xx, Hxx, <xx, >xx)
ZFE                              This tremolo fine (with Mxx, >xx, <xx)
ZFF                              Don't restart macro/arp/vibr position (!xx, @xx)
#0x                  61xx  58_x  Set connection type (FM algorithm) (reg $20+ch)
#1x            ML1x  161x  40_x  Set OP1 (modulator) multiplier
#2x                  541x  48x_                      key scaling level (0..3)
#3x                  501x  4Cx_                      tremolo/AM (0 off, 1 on)
#4x                  531x  4Cx_                      vibrato/PM (0 off, 1 on)
#5x                  5B1x                            KSR (0 off, 1 on) (KES)
#6x                  551x                            env sustain (0 off, 1 on)
#7x            ML2x  162x  42_x  Set OP2 (carrier) multiplier
#8x                  542x  4Ax_                    key scaling level (0..3)
#9x                  502x  4Dx_                    tremolo/AM (0 off, 1 on)
#Ax                  532x  4Ex_                    vibrato/PM (0 off, 1 on)
#Bx                  5B2x                          KSR (0 off, 1 on) (KES)
#Cx                  552x                          env sustain (0 off, 1 on)
               ML3x  163x  41_x  Set OP3 (modulator 2) multiplier
                     543x  49x_                        key scaling level (0..3)
                     503x  4Ex_                        tremolo/AM (0 off, 1 on)
                     533x  4Dx_                        vibrato/PM (0 off, 1 on)
                     5B3x                              KSR (0 off, 1 on) (KES)
                     553x                              env sustain (0 off, 1 on)
               ML4x  164x  43_x  Set OP4 (carrier 2) multiplier
                     544x  4Bx_                      key scaling level (0..3)
                     504x  4Fx_                      tremolo/AM (0 off, 1 on)
                     534x  4Fx_                      vibrato/PM (0 off, 1 on)
                     5B4x                            KSR (0 off, 1 on) (KES)
                     554x                            env sustain (0 off, 1 on)
               MLxy  16xy        Set OPx multiplier (x=0 all operators)
                     54xy        Set OPx envelope scale (KSL) (y 0..3)
                     50xy        Set OPx tremolo/AM (x=0 all operators)
                     53xy        OPL3 Set OPx vibrato/PM (y=0 off, y=1 on, x=0 all)
                     5Bxy        Set OPx key envelope scale (y=0 off, y=1 on)
                     55xy        Set OPx envelope sustain (y=0 off, y=1 on)
#Dx                              (unused)
#Ex                              (unused)
#Fx                              (unused)
&0x  S6x                         Fine pattern delay (ticks)
&1x  SEx                         Pattern delay (rows)
&2x  SDx  Gxx  0Gxx  EDxx  10xx  Note delay (ticks)
&3x  SCx  Sxx  ESxx  ECxx  0Fxx  Note cut (ticks)
&4x  S2x                         Fine tune up
&5x  S2x                         Fine tune down
&6x  Wx0                         Global volume slide up
&7x  W0x                         Global volume slide down
&8x  WxF                         Fine global volume slide up
&9x  WFx                         Fine global volume slide down
&Ax                              Extra fine global volume slide up (4 ticks)
&Bx                              Extra fine global volume slide down (4 ticks)
&Cx                  F3xx        Extra fine volume slide up (AT2 4, FUR 64 ticks)
&Dx                  F4xx        Extra fine volume slide down (AT2 4, FUR 64 ticks)
&Ex                              Extra fine portamento up (4 ticks, not MPT FEx)
&Fx                              Extra fine portamento down (4 ticks, not MPT EEx)
$xy                              Extra fine arpeggio
~xy                              Extra fine vibrato (every 4 ticks, not MPT Uxy)
^xy                              Extra fine tremolo
!xx                              Swap arpeggio table
@xx                        12xx  Swap vibrato table
=xx                              Force instrument volume
%xx  Vxx                         Set global volume
<xx                              Global portamento down (fine ZFD, x-fine ZFE)
>xx                              Global portamento up (fine ZFD, x-fine ZFE)
                     EFxx        Global pitch bend (80 center, cumulative, legacy)
                           C5xx  Global transpose (semitones?)
`xx                              Calculate vibrato&tremolo speed table (`00 reset)
     Mxx                   11xx  MPT Channel volume / DRTR Channel attenuation
     Nxy                   14xy  Channel volume slide (DRTR attenuation)
     Pxy             83xy        Panning slide (not really useful)
     S0x       T4xx  15xx  47xx  OP4 attenuation/level (C2) (OPL 3F, OPM 7F)
     S1x                         Glissando control
     S3x                         Vibrato waveform
     S4x                         Tremolo waveform
     S5x                         Panbrello waveform (impacts rounding off-center)
     S7x                         NNA things (unusable, toggle hard envelope reset?)
     S9x                         Sound control (unusable rest)
     S9F                   42xx  PCM Reverse sample / OPL envelopes?
     SAx       T3xx  14xx  45xx  OP3 attenuation/level (M2) (OPL 3F, OPM 7F)
     SFx                         Select MIDI macro (OP level to control with Zxx)
     T0x                         Tempo slide down (ritardando)
     T1x                         Tempo slide up (accelerando)
     Uxy                         Fine vibrato
     Yxy             84xy  0Cxy  Panbrello (alternate between channels)
     Zxx                   45xx  MIDI macro (filter may control OPx level)
     \xx                         Smooth MIDI macro
                           400x  MIDI set channel
                           41xx  MIDI select CC
                           42xx  MIDI send selected CC with value x
                           43xx  MIDI set coarse NRPN
                           44xx  MIDI set fine NRPN
                           46xx  MIDI set resonance
     :xy                         Note delay (x) and cut (y)
     #xx                         Parameter extension
     +xx  Pxx  0Pxx  E5xx        Finetune / Fine pitch (00 b, 80 L7, FF #)
     *xx       FPxx              Smooth finetune (00 b, 80 L7, FF #)
          =xx              1200  Phase reset / Reset channel
          5xy  05xy              (unused, volslide with ongoing portamento)
          6xy  06xy              (unused, volslide with ongoing vibrato)
          8xx                    (unused, no stereo on OPLL)
          9xx  09xx              (unused)
          Exx  0Exx              (unused)
          Hxx                    OPLL/VRC7 custom patch byte port
          Ixx                    OPLL/VRC7 custom patch byte write
          Jxx                    (unused)
          Kxx                    Note frequency multiplier
          Mxy  Mxyy              Set note volume to y after x ticks
          Mx0  Mx00  DCxx        Mute note after x ticks
          Nxy                    Target volume slide (x speed, y value (4bit))
                     D3xx        Target volume slide (vol col)
                     D4xx        Fine target volume slide (vol col)
          Oxx  0Oxx  09xx        Select groove / Groove index / Groove pattern
          Qxy  0Qxy  E1xy        Note slide up (x speed, y semitones)
          Rxy  0Rxy  E2xy        Note slide down (x speed, y semitones)
          Txy  0Txy  E6xy  13cy  Legacy legato (x ticks, y semitones (signed))
          Uxx  0Uxx              (unused)
          Vxx        10xx        OPLL/VRC7 patch index
          Wxx                    ((A)D)PCM pitch
          Yxx                    ((A)D)PCM sample offset x64
          Zxx                    (A)DPCM delta counter
               0Hxy              OPNA/NB AY auto envelope (x shift, y shape)
                     29xy        OPN AY auto envelope (x numerator, y denominator)
                     22xy        OPN AY set envelope mode (x shape, y enable)
                     25xx        OPN AY envelope slide up
                     26xx        OPN AY envelope slide down
               0Ixx  24xx        OPN AY HW envelope period MSB
               0Jxx  23xx        OPN AY HW envelope period LSB
               0Lxx              (unused)
               0Mxx              (unused)
               0Nxx              (unused)
               0V0x  200x        OPN AY tone mix (bits: 0 envelope noise square)
               0Vxx  1Fxx        OPNA/NB Rhythm/ADPCM-A master volume (00..3F)
               0Wxx  21xx        OPN AY noise frequency/color (00..1F)
               0Xxx  2Exx        Register address bank 0 / Write to I/O port A
               0Yxx  2Fxx        Register address bank 1 / Write to I/O port B
               0Zxx              Register value set
                     0Exx        (unused)
                     10xx  5D_x  OPM/Z set Chn7 C2 noise freq (00..1F, OPM reg $0F)
                     1000  5D0_  OPM/Z Chn7 Car2 noise disable
                     10xx  5D8_  OPM/Z Chn7 Car2 noise enable (FUR also set freq)
                     170x        OPN2 toggle legacy sample mode (keymap, see EBxx)
                     18xx        OPL3/OPLL toggle drums mode (x=0 off, x=1 on)
                     18xx        OPN toggle extended channel 3 mode (0 off, 1 on)
                     180x  5A_x  OPM/Z LFO waveform (0 saw, 1 sq, 2 tri, 3 noi)
                           5Ax_  OPM CT ouput pins control (high crumb) (reg $1B)
                     20xy        ESFM set panning of OP1 (x left, y right)
                     21xy                              2
                     22xy                              3
                     23xy                              4
                     24xy        ESFM set OPx output level register (y 0..7)
                     24xx        OPZ set LFO2 speed
                     25xy        ESFM set OPx modulation input level (y 0..7)
                     25xx        OPZ set LFO2 waveform (0 saw, 1 sq, 2 tri, 3 noi)
                     26xy        ESFM set OPx envelope decay (y 0..7)
                     26xx        OPZ set AM2 depth (00..7F)
                     27xx        ESFM set OP4 noise mode (0..3)
                     27xx        OPZ set PM2 depth (00..7F)
                     28xy        OPZ set OPx reverb (0..7, x=0 all)
                     29xy        (unused)
                     2Bxy        OPZ OPx envelope generator shift (0..3, x=0 all)
                     2Cxy        OPZ set OPx fine multiplier to y
                     2Dxy        (unused)
                     2Exx        ESFM Toggle hard envelope reset on new notes
                     2Fxy        ESFM set OPx fixed frequency block (y octave 0..7)
                     2Fxx        OPZ Toggle hard envelope reset on new notes
                     300x        OPL/M/N Toggle hard envelope reset on new notes
                     3xyy        ESFM set OP(x>>2) fixed frequency f-num x%4 to y
                     3xyy        OPZ OP1,2 fixed freq (x oct OP1 0..7, OP2 8..F)
                     4xyy        OPZ OP3,4 fixed freq (x oct OP3 0..7, OP4 8..F)
                     4xyy        ESFM set OPx detune (80 center, x=0 all)
                     53xy        OPN/Z set OPx detune (fine) (3 center)
                     55xy        OPN OPx SSG envelope (y<8 on, y=8 off, x=0 all)
                     551x              1 (M1)
                     552x              2 (C1)
                     553x              3 (M2)
                     554x              4 (C2)
                     55xy        OPM/Z OPx detune 2 (0..3, x=0 all) (reg $C0+ch)
                     551x  50x_        OP1 (M1)
                     552x  52x_          2 (C1)
                     553x  51x_          3 (M2)
                     554x  53x_          4 (C2)
                     5Bxx        OPM/Z set decay 2 of all OPs (00..1F) (reg $C0+ch)
                     5Cxx  50_x                       OP1 (M1)
                     5Dxx  52_x                         2 (C1)
                     5Exx  51_x                         3 (M2)
                     5Fxx  53_x                         4 (C2)
                     60xy        OPM/N Set OPx mask to y (x=0 all)
                     6xxx        (unused 64..6F)
                     7xxx        (unused)
                     91xx  41xx  PCM sample offset (x256, not applicable)
                     9xyy        PCM variable precission offset (y*2^(8*x))
                     Axxx        (unused)
                     Bxxx        (unused)
                     Dxxx        (unused D0, D1, D2, D5..DB, DD, DE)
                     DF00        PCM play sample forwards (invert envelopes?)
                     DF01        PCM play sample backwards (invert envelopes?)
                     E0xx  0Bxx  Set arpeggio speed
                     E3xx        Set vibrato shape (0 up&down, 1 up, 2 down)
                     E4xx        Set vibrato range
                     E8xy        Quick legato up
                     E9xy        Quick legato down
                     EAxx  0700  Legato control / auto insta porta
                     EBxx        Set legacy sample mode bank (OPLL user patch?)
                     EExx        Send external command
                     F5xx        Disable macro
                     F6xx  3Exx  Enable macro / DRTR set table
                     F7xx  3Fxx  Restart macro / "table"
                           3Dxx  Set table speed
                           3Cxx  Set table loop mode
                     FBxx        (unused)
                           15xx  (unused, up to 3Bxx)
                           43xx  PCM Sample loop
                           44xx  PCM Sample FIFO loop
                           5Exx  Global To Operator Volume
                           5Fxx  (unused)
                           6xxx  (unused, up to Bxxx)
                           C80x  Set background red component (visual)
                           C9xy  Set background green (x) & blue (y) component
                           CAxx  (unused, up to FFxx)


Waveforms for Jxy effect:
0 sine, 1 dromedars, 2 absolute sine, 3 pulse sine,
4 even period sine, 5 camels, 6 square, 7 saw


Parameters for 'xx effect:

Param  Size  Max     Factor
01..EF   32  01..EF  x1
F0..F3   32  FF      x1..x4
F4..F7   64  FF      x1..x4
F8..FB  128  FF      x1..x4
FC..FF  256  FF      x1..x4


Furnace macro (external envelope) IDs:

00 volume, 01 arpeggio, 02 duty/noise, 03 waveform, 04 pitch, 05..07 extra 1..3, 08 extra A (ALG), 09 extra B (FM), 0A extra C (FMS), 0B extra D (AMS), 0C panning left, 0D panning right, 0E phase reset, 0F..13 extra 4..8

20 AM, 21 AR, 22 DR, 23 MULT, 24 RR, 25 SL, 26 TL, 27 DT2, 28 RS, 29 DT, 2A D2R, 2B SSG-EG, 2C DAM, 2D DVB, 2E EGT, 2F KSL, 30 SUS, 31 VIB, 32 WS, 33 KSR

40.. OP2, 60.. OP3, 80.. OP4, A0.. unassigned


Note: In AT2 parlance, "extra fine" means executed every 4 frames (ticks), even for pitch effects. The effect parameter range is not altered.

Note: In MPT, Oxx is reused for modulator volume and Zxx usually for carrier volume, I've also reused SAx for OP3/M2 and S0x for OP4/C2 volume.

Note: Furnace's effect letters are not necessarily compatible between different FM chips. This is apparent with OPZ and ESFM.

Note: DreamTracker uses Modulator 1,2 and Carrier 1,2, which is confusing given Furnace's OP1..4 and Adlib Tracker modulator 1, carrier 1, and then on 2nd 4OP channel halves modulator 2, carrier 2. OP2 and OP3 is thus probably swapped between on OPM compared to OPL3.

Note: DreamTracker uses direct register mapping, which sometimes contain more values, not always at nibble boundaries. The position is hinted by using _x for lower bits and x_ for upper bits.

Note: Basically everywhere except OpenMPT the volume column is only for volume. AdlibTracker 2 has 2 full effect columns instead, and some effects have pair synergy.


Reality AdLib Tracker has few effects:

1xx - Slide note down (pitch bend)
2xx - Slide note up (pitch bend)
3xx - Slide to note
5xx - Volume slide while continuing note slide (01..49 down, 51..99 up)
Axx - Volume slide (01..49 down, 51..99 up)
Cxx - Set volume
Dxx - Pattern break
Fxx - Set "speed" (ticks per row)
Ixx - Ignore note transposing (only in Riffs)
Mxx - Set Multiplier (only in Riffs, Channels 2..5 and 6..9 affect OP1..4)
Rxy - Play Riff (x which, y channel, y=0 stop)
Txy - Play Riff transposed (provide a note)
Uxy - Feedback (only in Riffs, x which 0/1, y value 0..7)
Vxx - Operator Volume (only in Riffs, Channels 2..5 and 6..9 affect OP1..4)


SoundFX, not having quite many FX:

1xy - Arpeggio
2xy - Pitch bend (x down, y up)
300 - LED on (set bit 0 at address 0xbfe001)
400 - LED off (clear bit 0 at address 0xbfe001)
5xx - Fine volume slide up (add xx to current volume)
6xx - Set volume
7xx - Set step up
8xx - Set step down


EdLib (incomplete):

6000 - Cut
7xyy - Vibrato
90xx - Levels
Bxxx - SpFX sound
Cxxx - Instrument
Dxxx - Slide up
Exxx - Slide down


Surprise AdLib Tracker likely mostly follows the ProTracker nomenclature. MasterTracker (or MasterPlayer) and Composer 667 don't seem to have per-channel effect columns or they have some event editor on other screen or in another window like Symphonie Pro. Internet in the 2020s seems really quite barren compared to 2000s when I 1st found out about trackers.

There were other Famitracker extensions and modifications which added more chips or targeted different chips, but Furnace made them all obsolete by supporting all of them at the same time, even if it didn't make historical sense. Therefore these chips are approached more like modular machines in Buzz, yet they provide for nostalgic attachment and allow leveraging of existing know-how. There's still a possibility of making a cartridge with such unlikely combination of expansion sound chips, just like it was done on NES, which inspired the original Famitracker.


SID

The filters are what makes SID sound trippy, VIC-20 "squares" are close, but Atari square is Metal. Ordered according to GoatTracker Ultra, even though it has fewer effects, because it runs in SDL on other computers and supports microtonality and quad SID, and Furnace is what to transition to, with way more SIDs supported. This means there is way more grouping of effects. CT is Cybertracker, OT is Odin Tracker, SIDW is SID Wizard. Compared to OPL3, SID is quite simple.


GT   CT   OT   SIDW  FUR   Description
     0xx  Axy        00xy  Arpeggio
               0Cxx  E0xx  Chord speed adjustment (or arpeggio, also Cx)
               07xx        Select chord (also 7x)
               09xx        Go to waveform/arpeggio table position
1xx  1xx       01xx  01xx  Portamento up
                     E1xy  Note slide up (x speed, y semitones)
          FBx        F1xx  Fine porta up
2xx  2xx       02xx  02xx  Portamento down
                     E2xy  Note slide down (x speed, y semitones)
          FAx        F2xx  Fine porta down
               0Dxx        Detune note (also Dx)
                     E5xx  Finetune (0 flat, 80 center, FF sharp)
                     EFxx  Global pitch bend (0 b, 80 L7, FF #)
          1xx              Combined portamento (<80 down, >80 up)
                     06xy  Volslide, continuing portamento
3xx  3xx  3xx  03xx  03xx  Note porta
300  3FF       03FF        Note legato (insta porta, auto direction)
                     EA0x  Legato control (auto insta porta)
     EEx             1A0x  Skip note hard restart (disable envelope reset)
          FFx        15xx  Set envelope reset time (silence before new note)
                     E6xy  Legacy legato (x<8 up, x>7 down, x&7 time, y semitones)
                     E8xy  Quick legato up (x time, y semitones)
                     E9xy  Quick legato down (x time, y semitones)
4xy  4xy  4xy  08xy  04xy  Vibrato (x speed, y depth) (SIDW also 8y and 9x)
                     05xy  Volslide, continuing vibrato
               16x0        Select vibrato type (0..3)
                     E30x  Set vibrato shape (0 up&down, 1 up, 2 down)
                     E4xx  Set vibrato range/depth
5xy  E1x  7xy  05xy  20xy  Attack x, decay y (also SIDW 2x)
5xy  E2y  7xy  05xy  20xy  Attack x, decay y (split due to CT, SIDW also 3x)
6xy  E3y  8xy  06xy  21xy  Sustain x, release y (also SIDW 5x)
6xy  Cxx  8xy  06xy  21xy  Sustain x, release y (split due to CT, SIDW also 6x)
70x  E4x  90x  040x  100x  Set waveform (SIDW also 4x)
8xx                        Set wavetable (0 stop exe)
9xx                        Set pulsetable
          5xx              Set pulse speed
          6xx              Set pulse limits
               0Axx        Adjust pulsewidth program table index (PW envelope)
          2xx  0Exx  12xx  Set pulsewidth (8 MSB, FUR 0..64 (100 dec))
                     3xxx  Set full precission pulse width (0..FFF)
                     1Cxy  Reset pulse width on new note (x) and/or now (y)
     Axx                   Pulse width slide up
     Bxx                   Pulse width slide down
Axx                        Set filtertable
               0Bxx        Branch to filter program table index (filter envelope)
Bxy  E7x  Exy  1Fxy        Set Resonance(x)/FilterSwitch(y) register (incl ext in)
                Fx   130x  Set resonance
     E0x                   Send channel to filter (0 no, 1 yes, or lower reg bits?)
     E9x  F9x   Bx   140x  Set filter mode bitmask (3OFF/HP/BP/LP)
Cxx       Cxx  1Cxx  11xx  Set cutoff MSB (SIDW persistent, FUR 0..64 (100 dec))
               0Fxx        Cutoff high byte shift, add to filter envelope
                     4xxx  Set full precision cutoff (0..7FF)
                     1Bxy  Reset cutoff on new note (x) and/or now (y)
          FEx              Select instrument to control the cutoff
     7xx                   Set cutoff direction (<80 down, 80 keep, >80 up)
     5xx                   Cutoff slide up
     6xx                   Cutoff slide down
D0x  ECx  F8x   Ax         Global volume (SIDW small effect)
Dxx                        Timing mark (10..FF) (maybe for 4bit volume hack sample)
                     0Axy  Volume slide (only global volume on SID, maybe sustain)
                     F3xx  Finer volume slide up
                     F4xx  Finer volume slide down
                     F8xx  Fine volume slide up
                     F9xx  Fine volume slide down
                     FAxy  Fast volume slide (FA0F is basically a note cut)
                     D3xx  Target volume slide (vol col)
                     D4xx  Fine target volume slide (vol col)
                     DCxx  Mute after x ticks
Exx            12xx  09xx  Groove/Swing program/table index
               11xy        Old funktempo/swing, alternate between x and y speeds
               15xx        Track/Channel groove index
               14xy        Track/Channel old funktempo/swing
F00                        Recall even row tempo (zero-based)
F01                        Recall row row tempo (zero-based)
Fxx            10xx        Tempo (GT 03..7F global, 83..FF local, SIDW global)
          Fxx        0Fxx  Set speed (ticks per row, OT <80) 
                     Cxxx  Set tick rate in Hz
                     F0xx  Set BPM
                     FDxx  Set virtual tempo numerator
                     FExx  Set virtual tempo denominator
                     FFxx  Halt
               13xx        Track/Channel local tempo
     8xx                   (unused)
     9xx                   (unused)
     Dxx             F7xx  Multi-effect / Macro
                     F5xx  Disable macro
                     F6xx  Enable macro
     E5x                   (unused)
     E6x                   (unused)
     E8x        Ex         TestRingSyncGate bitmask (SIDW small effect)
                     1Exy  x: [A,D,S,R,ring,sync,3off]; max y: [F,F,F,F,1,1,1]
     EAx                   (unused)
     EBx                   (unused)
     EDx  Dxx        0Dxx  Pattern break
     EFx                   (unused)
          Bxx        0Bxx  Position jump to order x
          FCx        ECxx  Note cut
          FDx              (unused)
               17xx        (unused)
               18xx        (unused)
               19xx        (unused)
               1Axx        (unused)
               1Bxx        (unused)
               1Dxx        Track/Channel delay for ticks
               1Exx  EDxx  Note delay for ticks
                     0Cxx  Retrigger
                     0Exx  (unused)
                     9xyy  Sample offsets (for hacks)
                     DF00  Play sample forwards
                     DF01  Play sample backwards
                     EBxx  Set legacy sample mode bank (for hacks)
                     EExx  Send external command (sync)
                     FBxx  (unused)
                     FCxx  Note release


SID Wizard note column effects:

Sync off/on, Ringmod off/on, Noteporta off/on, vibrato depth (0..F)


SID Wizard instrument column effects:

xx  Select instrument (persistent)
3F  Legato (instant portamento)
4x  Waveform
5x  Sustain
6x  Release
7x  Select Chord (call chord table with 7F from arp table)


SID Wizard orderlist effects (GoatTracker apparently has something like this too):

xx  Pattern number (00..7F)
8x  Transpose -x+16 semitones down (F..0, somehow)
90  Switch off transposing (set original key)
9x  Transpose x semitones up (1..F)
Ax  Set main volume
Bx..FD  Set track tempo (00..5D)
FE  Song/sequence end, stop playback
FF  Loop to the position specified after (<$80) or go to subsong minus $80 (>=$80)


Note: GoatTracker makes heavy use of tables, most parameters are indices to them.

Note: Defmon and Soundmonitor don't really use effect letters. There's a note delay column and 2 "sound program" columns in Defmon. Soundmonitor uses toggles for transpose, portamento, and arpeggio, in a somewhat cryptic way.

Note: Furnace offers "fixed" SID2 with slightly less effects and heavily expanded 6-channel SID3 using almost entire chip-specific effect byte range of 0x10 to 0x7F and 0xA0 to 0xBF, ending at 0xB2. It also offers Commander X16 VERA, which has 16 channels and stereo PCM out, but no ADSR, filter, oscillator sync, and ring modulation, so the META is actually additive synthesis.


I'm not familiar with AY (see OPN SSG), SAA1099, POKEY, and software used to sequence music for them, so I won't be providing any effect table here, it would have just a Furnace column. Nintendo is boycotted due to no-life lawyers, for 2A03 see leftovers in Famitracker column. TI SN76489, VIC-20, TED and TIA are too simple for a dedicated effect list, it's mostly about spamming their registers to achieve something even remotely musically entraining. ZX Beeper and PC Speaker use CPU-intensive modulations (rapid spamming) with software mixing.

An interesting endeavor would be to compile an effect letter азбука for use with Soviet computers. However it would probably end up like Impulse Tracker, with actual letters left for \xx, #xx, :xy, +xx, *xx, $xy and &xx. When trackers were becoming a thing in 1989, the Eastern Bloc and Soviet Union were collapsing, and everybody wanted western stuff like Amigas and PCs, even if it meant that they had to learn English and Latin. And the effect letters were originally hexadecimal digits, only some developers decided to use alphabet instead. Maybe there already is a fully cyrillic music tracker.


2024-02-23

GISA - Getman Instruction Set Architecture

NOT FINAL

Why another ISA?

To have one that can be written like Protrackter MODs, that is the opcode, registers, and immediates are clearly apparent from the machine code without the need for a disassembler, and also the machine code can be written directly without the need for assembler, meaning it can be easily cross-checked. Back in 2018 I had to use all 3 attempts at the exam from MIPS assembler with pipelining, branch prediction, hazard detection and stalling, so I'll make my own ISA where I don't have to deal with this, making the scheduler by my own later.

Also I don't like RISC-V being primarily little endian and missing an official 16-bit variant. Little endian is confusingly notated in hexadecimal in mixed endian actually, so it's like reading Kharoshthi or Tamil. Network byte order is big endian, therefore a big endian ISA is better suited for devices connected to the Internet, or so called IoT. Microcontrollers don't need to be 32-bit, and while the 8 bit segment is served by the well-known 6502 and Z80 alredy, the 16 bit segment is somewhat lacking in widely famous architectures, mostly PIC, AVR, some TI chips, expanded 8-bit designs like 65816 and Z180, and proprietary console chips.

On the other side of the bit count, RISC-V is reluctant to fully specify its 128-bit variant, and is entertaining the idea of having near and far pointers again, after all that 80286 segment nonsense. In GISA, everything is the same amount of bits, so the floats would also be 128 bit, which is useful.

Furthermore, you need to pay membership fees to the RISC-V foundation to be able to have your products boast about using RISC-V, just like with Khronos Group and Vulkan. It might be cheaper to just copy LoongArch like Loongson did with MIPS. I prefer to call things what they really are, be it someone's trademark or not.

There are no privilege levels, there is no MMU, everything runs with full access to everything, just like YHWH/Gospodin/Allah intended, and just like it was on the Amiga and DOS. This is a better approach for real-time embedded systems than having to deal with some address translation and prolonged context switching. Remember the connection to music making. Note that as per hadith, only "vain entertainment" music is haram, and MODs are nerdy music.

Eventually I plan to write a B compiler for word-address variants, tentatively called HornyB or HoneyB, and write my own TempleOS or Oberon, tentatively called MosqueTOS, but it may end up more like SerenityOS because POSIX. The byte-address variants get a C compiler and a port of Plan9/Inferno, MINIX 1/2 or uClinux, and may thus run something actually useful. All BSDs ever since 386BSD require MMU. Porting HelenOS, MINIX 3, Mach/Hurd or other microkernel OSs to this noMMU architecture could probably net me a honorary PhD from MatFyz, VU or MIT, but RTOSes would be more fun and demoscene-y, and Selbstgesamtkunstwerke yield more to monolithic kernels. Should the compilers be too difficult, an assembly port of Workbench/AmigaOS or BASIC may be a possiblity.

Lest I be accused of creating a bytecode instead of an ISA, most bytecodes are stack-based and intended to be emitted by high-level object-oriented language compilers, whereas GISA has full access to entire memory and is made to be written directly, just like the olden days.


Different variants

Variants with different bit widths aren't binary compatible. Everything in them is that bit size, registers, instructions, and address space. There can be some jumpers for emulation of smaller sizes, but that's a sillicone wastage.

The B variants differ from the regular variants by having byte-addresible registers and memory with a byte select mask appended to every register number. This dramatically reduces the number of registers and the byte size of address space, however permits better string manipulation and struct packing, and allows more data types than just int, uint, and float. It would make sense to make these variants little endian, but that would be confusing.


GISA-8 - 4 opcodes, 3 registers, 256 B address space (W/B is redundant)

GISA-16W - 16 opcodes, 16/31 registers, 64k 16-bit words address space (128 kB)

GISA-16B - 16 opcodes, 3 registers, 64 kB address space

GISA-32W - 256 opcodes, 255 registers, 4G 32-bit words address space (16 GB)

GISA-32B - 256 opcodes, 16/31 registers, 4 GB address space

GISA-64W - 65536 opcodes, 65535 registers, 16E 64-bit word address space (128 EB)

GISA-64B - 65536 opcodes, 256/511 registers, 16 EB address space

GISA-128W - 4G opcodes, 4G-1 regs, 268435456Q 128-bit w addr space (4294967296 QB)

GISA-128B - 4G opcodes, 65536/131071 regs, 268435456 QB address space


I prefer 16W over 16B and 64B over 64W, but I am quite split on 32W and 32B. RISC-V has both RV32E and RV32I defined. Some may question the presence of 8 and 16 bit variants, but their paedagocial value is greater than the possibly too large 32 and 64 bit variants.

Each architecture can be harvardized, that is the program counter points to a completely different XOM, maybe on an EEPROM. This seems secure, like W^X, and also doubles the total memory size, but smells of console DRM, and gets rid of the fun self-modifying code provides. There is still a way to extract the contents from within using instruction recovery attack: https://arxiv.org/pdf/1909.05771.pdf . The bootstrap process of the von Neumann version is blit the code into RAM and set the program counter to the entry point.

Once I come up with a way to generate 4 milliards of instructions, I'll specify 128W and 128B, but I don't think there will be ever need to have more than 16 EB or address space at home, and datacenters won't be using some weird guy's embedded ISA.



GISA-8

This one is extremely simple, and could be fun for curious elementary school kids to implement in Minecraft, assuming they are being taught proper discrete mathematics instead of how to be walking calculators. It's not very much capable for a load-store architectiure, possibly try OISC, which means dump the registers. However if I can write a brainfuck interpreter, it means it's linearly bound Turing complete. Good luck fitting the program into 256 B and not overwriting it. Self-modifying code is needed.

Each instruction word is 8 bits and has 4 fields, each of 2 bits. The 1st field is always the opcode. The instruction types are RRI only. There are only 4 opcodes, so this is a FISC. Exceptionally, binary notation is preferred.

Opcodes:

00: AI  dest  src  imm   Add Immediate (signed)  dest = src + imm
01: LA  dest  src  imm   Load from Address       dest = mem[src+imm]
10: SA  dest  src  imm   Store to Address        mem[dest] = src + imm
11: BN  dest  src  imm   Branch if not Zero      pc += (!src) ? dest+imm : 0

Due to there only being 2 bits for the immediate, only values -2, -1, 0, and 1 are possible. After executing BZ, program counter still gets incremented, so you can skip over a instruction with 1.

Registers:

00: r0, zero
01: r1, sp
10: r2, s1
11: r3, s2

There is also a separate program counter, which physically occupies the space where the zero register would be, but isn't connected to the usual read and write circuitry.

There is no interrupt, you have to poll the I/O.

GISA-8 is much more of a Zachtronics puzzle than an actually usable architecture, and is provided mainly for completeness and paedagogy, illustrating the principles of larger GISAs.


Brainfuck interpreter for GISA-8

This is to prove that GISA-8 is linearly bound Turing complete. P" would be enough, but we can do some I/O at least. This is assuming a Harvardized version where the interpreter code itself is in a separate 256 B XOM addressed by the program counter.

Memory map:

00000000 ~ 01111111: Brainfuck Memory (128 B)
10000000 ~ 11110111: Brainfuck Program (120 B)
11111000: Program length; Counter; Code pointer; Data pointer 
11111100: Keyboard Input Data
11111101: Keyboard Input Advance Signal 
11111110: Terminal Output Data
11111111: Terminal Output Advance Signal

Register map:

00: ze      zero
01: mp      brainfuck memory pointer
10: ac      accumulator
11: pp      brainfuck program pointer
--: pc      machine program counter

The Brainfuck program can be self-modifying. Due to extreme space constraints, the syntax may have to be extended to allow numbers to be used for long runs of symbols, so insted of 50 pluses which would take 50 B, you would write "50+", which takes just 3 B. Most sample programs tend to fit within 120 B, though.

Brainfuck command interpretation in assembly:

+   LA ac mp 0 ; SA mp ac 1
-   LA ac mp 0 ; SA mp ac -1
>   AI mp mp 1
<   AI mp mp -1
[   LA ac mp 0 ; BN ze ac 7 ; (ascertain next ] location, put in ac) ; AI pp ac 0
]   LA ac mp 0 ; BZ ze ac 7 ; (ascertain prev [ location, put in ac) ; AI pp ac 0
,   AI ac ze -2 ; AI ac ac -2 ; SA mp ac 0 ; AI ac ac 1 ; SA ac ze 1 ; SA ac ze 0 
.   AI ac ze -2 ; SA ac mp 0 ; AI ac ac 1 ; SA ac ze 1 ; SA ac ze 0

(init)   LA mp ze 0 ; LA pp ...  (obtain value 128 somehow)
(next)   AI pp pp 1 ; LA ac pp 0 ; BN ze ac 1; BZ ze ze -1; (loop upon reaching \0)

The [ and ] would be much easier when implementing a compiler instead of an interpreter, which would have figured out the jump addresses at compile time. It's also annoying that there's no space for logic, and I haven't decided upon which condition to branch.



GISA-16W

This width conveniently comes out as exactly 1 hexadecimal digit for opcode and registers. This makes it highly resemble a Protracker channel, just missing the note column.

There's some VLIW potential of programming 4 cores independently. A possible nickname for GISA-16W-VLIW4 is PTISA, a pun on Interslavic "ptica", GISA-16W-VLIW8 could be OCTISA after Octalyzer, GISA-16W-VLIW16 could be STISA after Scream Tracker 3, and GISA-16-VLIW32 could be MTISA after Multitracker, for cores sitting on many I/O devices, as there would be only 8 kB per core. This is intended for controlling stage hardware without MIDI.

I'm indecissive of how to indicate hexadecimal - $AB like 6502, ABh like Intel, 0xAB like AT&T, or xAB like laziness.

Effects Opcodes:

0: ADD      dest src1 src2     Add
1: AND      dest src1 src2     And
2: OR       dest src1 src2     Or
3: SUB      dest src1 src2     Subtract (compare)
4: ADDI     dest src  imm      Add immediate
5: SLAI     dest src  imm      Shift left arithmetical immediate
6: SLLI     dest src  imm      Shift left logical immediate
7: SRI      dest src  imm      Shift right immediate
8: XOR      dest src1 src2     Exclusive or
9: XAND     dest src1 src2     Exclusive and (if and only if, exclusive not or)
A: LA       dest imm           Load address
B: SA       src  imm           Store address
C: BEZ      dest imm           Branch on equals zero
D: BNZ      dest imm           Branch on not zero
E: J        dest imm           Jump reg+imm
F: JAL      dest imm           Jump and link

The operations are inspired by school MIPS lessons. I'm not sure how much of a Turing tarpit is this selection. May need to fit interrupts somewhere, but they are basically a jump to a table offset, that says jump to a handler.

Note to self: TIS-100 has MOV, ADD, SUB, NEG, JMP, JEZ, JNZ, JGZ, JLZ, JRO.


Registers:

0: r0, zero
1: r1, sp
2: r2
3: r3
4: r4
5: r5
6: r6
7: r7
8: r8
9: r9
A: r10
B: r11
C: r12
D: r13
E: r14
F: r15

Because there is no byte addressibility, the address space spans 128 kB instead of usual 64 kB. This yields to UTF-16 instead of UTF-8, and the bit wastage isn't that high because 42069 (A3F3h) is a perfect 16-bit number.

The regular von Neumann version may be a good place for porting Wozmon, as those 256 B of dense 6502 code wouldn't fit in the address space of even Harvardized GISA-8 while having to express that with just 4 different types of instructions.



GISA-16B

There is no byte addressible VLIW version. 64 kB of RAM would only fit 8k VLIWs for 4core, or 1k VLIWs for 32core.

The register fileld is broken up into 2 evenly sized parts. The higher crumb determines the register, and the lower crumb represents a byte select mask. This leaves us with 4 registers.

There are 2 bytes in 16 bits, and so the bytemask is 2 bits.

00: no byte selected / the other register file (O)

01: low byte selected (L)

10: high byte selected (H)

11: all bytes selected (X)

Being able to select no bytes alleviates the need for a hardwired zero register, however there are now number of registers way to specify zero, so optionally there can be another set of registers minus one that will now be the only zero, this time without byte subdivisions, like for addresses, integers, UTF-16 and stuff. This will increase the number of registers to 8, at the expense of unnecessary complexity for a 16-bit processor, unlike the plain simple 16 16-bit only registers.

Intel's 4 general purpose registers come to mind here, so I'll use their letters.

Registers:

0: AO, r0, zero
1: AL, r4l
2: AH, r4h
3: AX, r4
4: BO, SI, r5 *
5: BL, r1l
6: BH, r1h
7: BX, r1, sp
8: CO, DI, r6 *
9: CL, r2l
A: CH, r2h
B: CX, r2
C: DO, BP, r7 *
D: DL, r3l
E: DH, r3h
F: DX, r3

* optional register, act as r0 if not implemented, or maybe halt and catch fire


Wozmon for GISA-16B

Wozmon is a memory editor and assembler for 6502, that Wozniak of Apple has managed to cram in zeropage, that is in 256 B. We only have 256 B of memory address space on GISA-8, and also none of that instruction compactness, so it would't fit there.

Porting of this needs to find a way around the lack of interrupts. It will finally use von Neumann memory architecture. The 6502 had 3 8-bit registers, here we have at least 4 16-bit ones.



GISA-32W

This is the smallest GISA to have float support, as the number of opcodes started to allow it. The float registers are separate from integer registers. There is now a full byte for each opcode and register. I would consider this to be the base ISA, other widths are mostly derivations.

Following the tracker inspiration, GISA-32W-VLIW32 could be called FTISA (ptica with a lisp, after FastTracker 2), GISA-32-VLIW64 ITISA after Impulse Tracker, and GISA-32W-VLIW128 MPTISA after (Open)ModPlug Tracker. Having 128 cores with just 16 GB of memory would still be quite silly (512M per core), but at least you can race condition the entire memory.

There was this unreadable opcode diagram I made in 2019:


May need some adjusting and rethinking, mainly regarding unsigned.


Opcodes, column is the 1st nibble, row is the 2nd nibble:

     0    1   2   3    4   5   6   7   8   9   A   B    C    D    E    F

0

1

2

3

4

5

6

7

8

9

A

B

C

D

E

F


The instruction format is in the least significant bits of the opcode, as we the people don't see ADD as too different from ADDI, and unlike RISC-V, which is for machines, GISA is for people, at least those like me.


Registers:

00: r0, zero
01: r1, sp
02: r2
etc.
FF: r255


Floating point registers are a separate file. They can be combined to make vectors, but that's more of a compiler, scheduler and thermals thing. Naturally only IEEE single precisstion is supported.

The main programming language for GISA-32W is B. The sinuglar word type can get interpreted either as an uint32, int32, float32, char32, or pointers to such. Most importatntly, pointers in B are in words, so *(0xFFFFFFFF) points to the last word, which would be *(0x3FFFFFFF0) read size 4, on a byte addressible architecture. If somehow wanting to use C, you get only int, unsigned, float, wchar. Software packing of 16-bit and 8-bit types is possible, but then the pointers would have to be in bytes, so quarter of memory would be unreachable.


There it may make sense to have some control and status registers, which could even switch between GISA-W and GISA-B, as well as emulate GISA-16 and GISA-8.


GISA-32B

The byte for specifying register is split into 2 nibbles, therefore there are 16 registers with 16 possible modes of access using an agruably INTERCAL inspired select mask:

0: 0000: zero or alternate register file
1: 0001: the lowermost byte -> 8b
2: 0010: lower middle byte -> 8b
3: 0011: lower half or lower word -> 16b
4: 0100: upper middle byte -> 8 b
5: 0101: upper middle and lowermost byte -> 16 b
6: 0110: upper middle and lower middle byte -> 16 b
7: 0111: all but the uppermost byte -> 24 b
8: 1000: the uppermost byte -> 8 b
9: 1001: the uppermost and lowermost byte -> 16 b
A: 1010: the uppermost and lower middle byte -> 16 b
B: 1011: all but upper middle byte -> 24 b
C: 1100: upper half or upper word -> 16 b
D: 1101: all but lower middle byte -> 24 b
E: 1110: all but the lowermost byte -> 24 b
F: 1111: all bytes -> 32 b

The discontinuous selects can be slid together or continuous selects can be pulled apart using a different select mask on the destination register. If the number of selected bytes in the destination mismatches with number of bytes selected in the source, the result depends on endianess, but GISA should be big-endian. There are too many little endian ISAs already. This is basically connecting part of registers to the parts of the bus to make lesser sized reads.

This allows for some intersting string manipulation:

DB 400h "AZOV"
DB 404h "KRYM"
LI r2mf, *400h
LI r3mf, *404h
ADD r3mf, r3mc, r2m3  ; "KROV"
SA r3mf, 408h

Whereas on 32W you would need to make 2 ANDs and 1 OR instead of 1 ADD, and consume 1 more register.

It also makes it possible to implement 3 byte or 24 bit integers directly in hardware, and use the leftover byte for some char or bool, or to implement some rudimentary vectors.

Byte selector works also on floating point registers too, but casting is not so straightforward. 8-bit and 24-bits float are handled as truncations of 16-bit and 32-bit floats, until I come up with a useful format or control registers to change bit allocations to your liking.

The C types would be:

char - 8 bits

short short float - 8 bits (compiler hack)

short short - 16 bits (compiler hack)

short float - 16 bits (an old C++ proposal)

short - 24 bits

int - 32 bits

float - 32 bits

wchar - 32 bits

long - 64 bits (paired registers)

double - 64 bits (float-float or software)

long long - 128 bits (4 registers)


GISA-64W

This is in fact more of a CISC architecture, because there are 65536 opcodes, which is around the number on x86 with all those extensions. Some of the 16 bits in the opcode could correspond directly to ALU controls, and other could clearly encode the instruction format. Collecting all the instructions on all the CISC CPUs and adapting their format to RISC would be just like collecting roots for GeSeL.

For the intents of vector instructions, the register file is all zero registers beyond FFFF.

The memory addressed is 128 EiB or 2^67 B. This is about the maximum I expect consumer devices to ever reach. Such amount of sillicon atoms for the perfectly miniaturized memory cells would fill an entire room.

There is no VLIW because no tracker implements more than 256 effects. But if I finally finish ReTeMuS (Renderer/Redactor of Text Music Sequences, also called vitracker, MT637, GSS etc.), then there may be a 256core version, that is only 256T VLIWs in RAM.


GISA-64B

Much more preferable, since no one is willing to devote the sillicon space to 65536 64-bit registers (8 Mb). 256 of them is much more acceptable, with 256 different byte masks.

This makes it possible to directly implement also 5 byte (40 bit), 6 byte (48 bit), and 7 byte (56 bit) integers and floats, in addition to 3 byte (24 bit) intergers and floats from GISA-32B. For floats, default behavior is to truncate the mantissa of the next higher IEEE standard, however there are many bespoke extended precision float formats, notably the 40-bit one used by BASIC.

As usual, there can be another set of non byte-addressable registers for when accessing them with a zero mask, bringing the total to 512. To reiterate, float registers have their separate file, that too can have alternate file for zero select mask, so there can be 1024 total registers.

There is still no MMU, so porting TempleOS is made easier. This is not meant to run regular operating systems, where the kernel controls hardware-assisted memory management. User is considered smart enough to know where they are writing to or where they are reading from, like some MMIO device, and also when to not cause a race condition.

The C types would be:

char - 8 bits

short short float - 8 bits (compiler hack)

short short - 16 bits (compiler hack)

short float - 16 bits (an old C++ proposal)

short - 24 bits

int - 32 bits

float - 32 bits

wchar - 32 bits

short short short long - 40 bits (compiler hack)

short short short double - 40 bits (compiler hack)

short short long - 48 bits (compiler hack)

short short double - 48 bits (compiler hack)

short long - 56 bits (compiler hack)

short double - 56 bits (compiler hack)

long - 64 bits

double - 64 bits

long long - 128 bits (paired registers)

long double - 128 bits (double-double or software)

long long long - 256 bits (4 registers, compiler hack)


GISA-128W

There are 32 bits for the opcode, so each of them can be directly assigned to a control somewhere down the instruction decoder and ALU config. This can create many "undocumented" instructions, like with the 6502. I'll just need to decide on the topology. Also you won't need any cache with 4 milliard registers.

The address space without byte addressability is humongous. 2^132 B, with Harvardized program counter even 2^133 B. There are no SI prefixes for that, not yet approved QiB is only 2^100, 3 more prefixes are needed. Don't you ever come at me with this not being enough. There's barely enough sillicon atoms in the entire Earth for a milliard of such memory kits, less than 1 per 8 people.


GISA-128B

4G registers is so many it could be construed as a direct 32-bit addressing of the memory. Therefore it's highly advisable to reduce it to 65536 with 16 individually addressible bytes or their combinations. And yes, there is the option to have another 65536 non-byte addressible registers if that's too little now.

In addition to GISA-64B, there can be 9 to 15 byte (72 to 120 step 8 bits) integer and float types alike. A specific consideration should be made for 80-bit extended precission most notably known from Intel 8087, 72 bit float being truncation thereof.

The C types are the same as GISA-64B, but there are additionally these hacks:

short short short short short short short long long - 72 bits

short short short short short short short long double - 72 bits

short short short short short short long long - 80 bits

short short short short short short long double - 80 bits

short short short short short long long - 88 bits

short short short short short long double - 88 bits

short short short short long long - 96 bits

short short short short long double - 96 bits

short short short long long - 104 bits

short short short long double - 104 bits

short short long long - 112 bits

short short long double - 112 bits

short long long - 120 bits

short long double - 120 bits

long long double - 256 bits (quadruple-quadruple or software)

long long long long - 512 bits (4 registers)

But using int###_t and float###_t is probably better. The compiler is to manage the register splits and masks, but it may be a good idea to hint it with proper declaration order.


There is unlikely to ever be a need for an address space bigger than 128-bit, since there is not enough sillicon atoms in the Earth to make this much memory. Or would you like to mmap all the Internet? If you have read everything up to here, you could very well extrapolate GISA-256W and GISA-256B, but there would be nothing new, everything just would be wider with more dead space. You would get octuple precission floating point, though.




2024-02-18

OpenStreetMap Tile Layers for KDE Marble

I've started to disagree with the featured tile layers on openstreetmap.org. First, whoever makes the decisions decided to feature Tracestrack Topo, which is broken when HTTP Referer header is disabled, therefore it doesn't work in Librewolf by default, and neither does in KDE Marble. There's already OpenTopoMap, which handles depressions way better (Z0 to Z10). Way odd for a company from the Netherlands to make their home country look so ugly, but it's even more apparent at the Caspian sea. The Z9 to Z11 of Tracestrack Topo are quite nice, though. The Z12 to Z19 are however too similar to the default Carto, and buildings are gone until Z15 inclusive, which makes it less usable.

Secondly, they removed my favorite ÖPNVKarte, which was miles better than Thunderforest's Transport. Supposedly it was months out of date, but the only out of date thing important for me were some missing tram line extensions, which started to pop up quite frequently considering how long it takes to legally build anything in Czechia, to the point it's easier to do it illegally and bulldoze it years later when you finally actually have to. Prague Metro has been the same since 2015, and bus routes are volatile by design. I have paper maps 20 or even 100 years out of date, a few months is nothing.

In August 2025, 2 vector tile layers have been featured, Shortbread (MVT) and OpenMapTiler (PBF). However I now have an 5120x1440 ultrawide monitor, which is wider than the HTML canvas can handle, so it's blurry. Shortbread was like F4map and tried to respond to dark mode with a simple luminance inversion, now it has a different always light design. Transport has an actual dark variant and is now also vectorized. OpenMapTiler is basically a vector version of Carto. The zoom is still discrete.

I've been collecting other tile layer URLs, as far as they were working, also stealing some API keys with them from the F12 devtools, originally intending to make a beefed up version of montage.sh from OpenTopoMap to scrape all tiles at all zooms to stitch together and print various territories to avoid relying on my phone's rapidly depleting battery, given the need to increase brightness. But I've discovered that KDE Marble can import those tile layer URLs and project them onto the globe, so there goes the silly Mercator Greenland and Siberia exaggeration. Printing the view is supported too, and just like with web maps, 4K display is recommended for A4, as 2160 px * 2.54 cm/in / 17.3 cm = 317 DPI. Do not confuse KDE Marble with Marble Maps, which is a differnet app with buggy UI (you can't exit settings, you have to restart), that doesn't support importing custom tile URLs.

I have intentionally omitted US-focused layers, yet kept European focused ones. As a European, I don't really care about the USA, for I am not likely to set foot in there unless public transit gets decent (see ÖPVNKarte and OpenRailwayMap), and American OSM data is not quite up to the European levels of quality. There will always be better data for the US on proprietary American maps, like Bing Maps, Google Maps, Yahoo Maps etc., just as there is better data for China on Baidu and for Russia+CIS on Yandex. OSM is mainly a European project with some activity in the 3rd world as per humanitarian efforts.

While Google Earth Pro can be made to display tile overlays too, the 3D terrain and buildings interfere heavily, and besides being proprietary, it requires perfectly functioning 3D graphics, which wasn't the case with Intel GMA on Linux, and may not be necessarily the case with nVidia. It occasionally crashes, and instead of fixing it, Google has decided to nix it in lieu of the web version, killing the old 3D buildings for good. For viewing flat 2D tiles on a globe, KDE Marble consumes much less resources, and with a hybrid tile layer looks quite close to Google Earth. Also there are multiple projections to choose from, even Azimuthal to appease Discworld LARPers, but Gnomonic is the best for determining Qibla.

There are however some limitations. Non-Mercator projections aren't that smart with regards to reading the file header and assume the dimensions from the config file, which defaults to 256x256, which needs to be edited manually. Non-power-of-2 sizes do seem to work, but are omitted to reduce clutter except Yandex Labels 10x, that is 2560x2560, which was the largest offered size. The tiles are somewhat blurry at the standard density, however the font size of some of those tiles is now at least properly readable on 8K Big Brother telescreens. Also, the projections maintain the same pixel density for a given zoom, so when actually specifying their correct resolution, they look actually less detailed, except HERE, which corrects for this by providing a zoom level 1 deeper for 512x512 tiles. If the size is kept declared as 256x256, the Mercator projection detail increases as intended, but other projections display patchwork. Possibly on Hi-DPI monitors the base size looks unreadably tiny or Marble respects DPI settings and adjusts the target pixel density. Furthermore, Bing uses some sort of quadtree index, which is way above the capabilites of {x} {y} {zoomLevel} placeholders and reminds me of INTERCAL mingle operator. Some tile providers may also use the correct ellipsoidal Mercator projection formulas instead of spherical misinterpretation of WGS84 data (namely Yandex), shifting things alongside a merididian by up to 40 km. Webcator is in fact so shitty that the US DoD NGA said it sucks and the popularity of it is dangerous, and EPSG long refused to assign a SRID to it, therefore it works better than China's offical coordinate scrambling algorithm GCJ-02 and its bespoke Baidu BD-09 variation (which also seems to use some weird tile indexing). Also, the default zoom range only suffices up to zoom 19. Some tilesets, namely the ESRI World Imagery, go up to zoom 23 (not everywhere), Voyager/DarkMatter/Positron go up to 20 with 8x making it effectively 23, and Yandex Labels go up to 21 with 10x making it effectively 24.25. However expanding the zoom range causes the view to glitch to a different position when zooming too quickly too deep.

Editing of the imported tile layers properties is very clumsy. There is no GUI for it. You have to manually edit XML in $XDG_DATA_HOME/marble/maps/earth/${mapname}/${mapname}.dgml , $XDG_DATA_HOME being usually ~/.local/share , ~ being usually /home/$(whoami) , therefore full path is most likely /home/$(whoami)/.local/share/marble/maps/earth/${mapname}/${mapname}.dgml . If you somehow still use that spyware proprietary software bootloader, then %LOCALAPPDATA%\.marble\data\maps\earth\%mapname%\%mapname%.dgml , %LOCALAPPDATA% being usually %HOMEPATH%\AppData\Local , %HOMEPATH% being usually %HOMEDRIVE%\Users\%username%, and %HOMEDRIVE% being usually C:, therefore the full path is most likely C:\Users\%username%\AppData\Local\.marble\data\maps\earth\%mapname%\%mapname%.dgml. Note that ancient versions of Windows NT use "Application Data" for AppData and "Documents and Settings" for Users, as to make sure the MAX_PATH limit of 260 is hit more often.

Deleting hard disk cache from the GUI doesn't work properly on these custom indexed tile layers, you have to delete all numbered directories manually. This can be achieved by a bash one-liner:

for Z in {1..24}; do find "$1" -type d -name "$Z" -exec rm -rf {} + ; done

Don't delete the ${mapname}/0/0/0. files. They are somehow load-bearing. The default cache validity is a year, which seems quite long, but there is also a size limit configurable from the GUI, which is to be reached instead. The providers shouldn't be spammed with tile requests repeatedly, and new motorway stretches usually open in December or around election time.

Since then, most of the work went into upstreaming the Qt6 port for KDE 6 instead of making it behave better.


Here is the link to the tile layers, finally:

https://drive.google.com/file/d/1mKJGLWdU5LI7Eh-YENAM_DV0R3_RTB1C/view?usp=drive_link

Extract this archive into ~/.local/share/marble/maps/ or %LOCALAPPDATA%\.marble\data\maps\ , so that the earth directory in the archive merges with the earth directory already present there. Depending on your distribution, actual path may differ. Preferrably, restart KDE Marble. Some tile layers don't work on the outdated Windows version from 2015, mainly the high DPI and non PNG8 or JPG ones. Possibly it has to do something with missing filename extension, as the tiles end with a mere dot due to URL rewrites containing none, but for the love of Allah, please stop using such shitty operating systems where a file name ending in a dot is a problem.

Licensing note: There are some proprietary tile layer URLs included with some low zoom pre-cache tiles. These are provided for evaluation, comparison, personal, or private use. Don't use them in any situation where you wouldn't use the Webcator projection. Especially don't abuse those with API keys included in them. I was too lazy to fill in attribution text, for what is essentially a sophisticated URL collection. Usually the provider is included in the name.

There is no warranty, tile providers may start Referer and Origin checking or even stop providing the tiles altogether, KDE Marble may freeze, SSD may lock to read-only mode due to cache thrashing exhausting write cycles (there are a lot of small files being downloaded), Internet bill may force you to declare bankruptcy, tyrannical government may prosecute you for using foreign maps with wrong borders (see Yandex which removed them), you may simply dislike the appearance of some tiles or presence of some tile layers, and so on and so on.

Last updated on 2026-05-10 (ISO), 10.05.2026 (Central-East Europe), 05/10/2026 (USA), 2026\10\05 (US-occupied Middle East).


Tile layers available from the "store" or shipped by default:

OpenTopoMap
OpenStreetMap Carto
OpenSeaMap //overlay on top of OpenStreetMap Carto
OpenFireMap //overlay on top of OpenStreetMap Carto, DACH only
Hike and Bike Map //RIP
Thunderforest OpenCycleMap //API key watermark
ÖPVNKarte (Public Transport) //aka OpenBusMap


Included tile layers (bold works on the old 2015 ₩i₦₫o₩$ version):

BVG //mixed 512x512 and 256x256; config 512 crashes, 256 non-Mercator patchwork 
Bergfex OSM //1x, 2x
Carto Dark (Dark Matter) //1x, 2x, 4x, 8x
Carto Light (Positron) //1x, 2x, 4x, 8x
Clockwork Micro Aspect //512x512 only
Clockwork Micro Hillshade //512x512 only
Clockwork Micro Raw //512x512 only
Clockwork Micro Slopes //512x512 only
Clockwork Micro Streets
CyclOSM
DeepStateMap //1x, 2x; only NE semihemisphere; also .webp, but not supported
DeepStateMap Dark //1x, 2x
DeepStateMap Satellite //512x512 only; only Ukraine, Moldova, and Romania
ESRI World Boundaries & Places //ESRI tiles have highly variable available zooms
ESRI NatGeo World Map
ESRI Ocean Basemap
ESRI World Imagery
ESRI Light Gray Base
ESRI World Physical Map
ESRI World Shaded Relief
ESRI World Street Map
ESRI World Terrain Base
ESRI World Topo Map
ESRI World Transportation
F4map
Facebook Dark
Facebook Light
Freemap //A, C, K, T; Slovakia and boderlands only
Freemap Ortofotomozaika //Slovakia only
Freemap Outdoors //only Central-South Europe
GBIF Classic //1x, 2x, 4x; GBIF tiles have double² resolution, 1x is 512x512 etc.
GBIF Dark //1x, 2x, 4x
GBIF Light //1x, 2x, 4x
GBIF Middle //1x, 2x, 4x
GBIF Geyser //1x, 2x, 4x
GBIF Tuatra //1x, 2x, 4x
GBIF Violet //1x, 2x, 4x
GBIF Natural //1x, 2x, 4x
GBIF OSM Bright //1x, 2x, 4x
Geofabrik Basic Color
Geofabrik Basic Greys
Geofabrik Basic Pastel
Geofabrik German //now 512x512
Geofabrik Topo //now 512x512
Kartogiraffe //RTL scripts are rendered LTR with glyphs unmirrored
LiveUAMap //indispensable for illiterates in non-Latin scripts
MTBmap //only Europe
Mappy //only Europe and Russia at high zooms
Maptoolkit Topo
Michelin Labels (hybrid)
Michelin Light (viamichelin)
Michelin Simplified (light)
OSM Basque (euskara)
OSM Breton
OSM Occitan
OSM DE //Böhmische Dörfer endlich auf Deutsch
OSM DE Truck //only Europe, Georgia and Turkey, only past Stalingrad
OSM FR
OSM GPS Trails
OSM Humanitarian
OpenGeoFiction Carto
OpenGeoFiction CyclOGF
OpenGeoFiction Topo
OpenRailwayMap Maximum Speed
OpenRailwayMap Signalling
OpenRailwayMap Standard
OpenRiverBoatMap
OpenStreetMap PL (osmapa.pl) //RIP domain (August 2026)
Outdooractive Summer
Outdooractive Winter
Prahou na kole (Městem na kole) //Czechia only
SafeCast
Serbiamap Cyrillic
Serbiamap Latin
Sherpa Map //no hillshade backgroud, .webp not supported
Sherpa MapBox //512x512 only
Sigma Cycle
Sigma Topo
Skobbler Day //1x, 2x
Skobbler Light //1x, 2x
Skobbler Night //1x, 2x
Skobbler Outdoors //1x, 2x
Spinal Map //1x, 2x
Thunderforest Atlas //1x, 2x
Thunderforest Landscape //1x, 2x
Thunderforest Mobile Atlas //1x, 2x
Thunderforest Neighbourhood //1x, 2x
Thunderforest OpenCycleMap //1x, 2x
Thunderforest Outdoors //1x, 2x
Thunderforest Pioneer //1x, 2x
Thunderforest Transport //1x, 2x
Thunderforest Transport Dark //1x, 2x
TopPlusOpen Color
TopPlusOpen Grau
UMP-pcPL //only Europe, mainly Poland; retro style, old data outside Poland
Voyager //1x, 2x, 4x, 8x
Wanderreitkarte
WayMarkedTrails Cycling
WayMarkedTrails Hiking
WayMarkedTrails MTB
WayMarkedTrails Riding
WayMarkedTrails Skating
WayMarkedTrails Slopes
Waze //now 512x512
WhereGroup Lyrk
Yandex Labels //1x, 2x, 4x, 8x, 10x; true Mercator
Yandex Satellite //true Mercator


Excluded tile providers due to too nosy HTTP header checking:

Mapy.cz
OpenSnowMap
Stadia (including Stamen)
Tracestrack


Appendix - Size table:

Useful for determining processing and render limitations. For DimPixels and Pixels, standard density is assumed. For RawBytes, a 4-Byte (32-bit) color format like ARGB8 or A2RGB10 or R11G11B10 is assumed. Ocean tile ranges (70 % of Earth) can be optimized by hardlinking to a single ocean tile. NTFS, ZFS and XFS seem to be better than ext4 and FATs, but ReFS, btrfs and bchachefs are even better.


SI PREFIXES IN THE TABLE BELOW ARE BINARY!

z     2^z      2^(2z)  2^(z+8)  2^(2z+16)  2^(2z+20)
Zoom  DimTiles  Tiles  DimPixels  Pixels  RawBytes  Comment
  0         1      1        256      64K      256K  single tile
  1         2      4        512     256K        1M  quarterglobes/čtvrtkoule
  2         4     16          1K      1M        4M  like Blue Marble 2005
  3         8     64          2K      4M       16M  chessboard
  4        16    256          4K     16M       64M
  5        32      1K         8K     64M      256M
  6        64      4K        16K    256M        1G  may work as wallpaper
  7       128     16K        32K      1G        4G  32b viewers limit
  8       256     64K        64K      4G       16G  Tiles = DimPx; FAT32 sg
  9       512    256K       128K     16G       64G  expensive GPU VRAM
 10         1K     1M       256K     64G      256G  exFAT single dir limit
 11         2K     4M       512K    256G        1T  ext4 sg dir (no largedir)
 12         4K    16M         1M      1T        4T
 13         8K    64M         2M      4T       16T  8.3 name single dir limit
 14        16K   256M         4M     16T       64T  FAT32 total files
 15        32K     1G         8M     64T      256T 
 16        64K     4G        16M    256T        1P  NTFS sg,FAT32 per,ext4 Σ
 17       128K    16G        32M      1P        4P  OpenTopoMap
 18       256K    64G        64M      4P       16P  ÖPNVKarte & OSM DE
 19       512K   256G       128M     16P       64P  OSM Carto
 20         1M     1T       256M     64P      256P  CycloOSM & HOT & OSM FR
 21         2M     4T       512M    256P        1E  exFAT per, ThunderForest
 22         4M    16T         1G      1E        4E
 23         8M    64T         2G      4E       16E  ESRI World Imagery
 24        16M   256T         4G     16E       64E  ZFS per dir, 64b viewers
 25        32M     1P         8G     64E      256E
 26        64M     4P        16G    256E        1Z  8.3 name limit
 27       128M    16P        32G      1Z        4Z
 28       256M    64P        64G      4Z       16Z
 29       512M   256P       128G     16Z       64Z
 30         1G     1E       256G     64Z      256Z
 31         2G     4E       512G    256Z        1Y
 32         4G    16E         1T      1Y        4Y  NTFS per dir & total, XFS


Appendix - Scale table:

Actual scale depends on the latitude. Formula for the denominator in "1:m":

m=eqcircum*COS((deg+min/60+sec/(60^2))*pi/180)/(2^(zoom+8)/(100*dpi/2,54))

where:

* eqcircum      is the equatorial circumference of 40075017 m,
* deg, min, sec is the latitude in sexagesimal degrees (decimal sucks),
    + The Tropics            being at 23°26' in 2045 and 27' in 1927,
    + The (Ant)Arctic Circle being at 66°34' in 2045 and 33' in 1927,
* pi            is 3.14159265358979323846264338327950288419750...,
* zoom          is the zoom level or base 2 log of number of tiles per side,
* dpi           are dots per inch, the display or print density, assumed 96.

Meaning, 1 unit of your silly length measure on the map corresponds to m units of your silly length measure in the real world.


SI PREFIXES IN THE TABLE BELOW ARE DECIMAL!

                 1:...    23°26'    66°34'      π/12       π/6       π/4       π/3    5*π/12
 z  Dim96DPI   Equator    Tropic   ArcticC    15°lat    30°lat    45°lat    60°lat    75°lat
 0   67.733m  591.659M  542.861M  235.292M  571.498M  512.391M  418.366M  295.829M  153.133M
 1  135.467m  295.829M  271.430M  117.646M  285.749M  256.196M  209.183M  147.915M   76.566M
 2  270.933m  147.915M  135.715M   58.823M  142.875M  128.098M  104.591M   73.957M   38.283M
 3  541.867m   73.957M   67.858M   29.411M   71.437M   64.049M   52.296M   36.979M   19.142M
 4    1.084    36.979M   33.929M   14.706M   35.719M   32.024M   26.148M   18.489M    9.571M
 5    2.167    18.489M   16.964M    7.353M   17.859M   16.012M   13.074M    9.245M    4.785M
 6    4.335     9.245M    8.482M    3.676M    8.930M    8.006M    6.537M    4.622M    2.393M
 7    8.670     4.622M    4.241M    1.838M    4.465M    4.003M    3.268M    2.311M    1.196M
 8   17.340     2.311M    2.121M  919.109k    2.232M    2.002M    1.634M    1.156M  598.174k
 9   34.679     1.156M    1.060M  459.554k    1.116M    1.001M  817.121k  577.792k  299.087k
10   69.359   577.792k  530.137k  229.777k  558.104k  500.382k  408.560k  288.896k  149.543k
11  138.718   288.896k  265.069k  114.889k  279.052k  250.191k  204.280k  144.448k   74.772k
12  277.436   144.448k  132.534k   57.444k  139.523k  125.096k  102.140k   72.224k   37.386k
13  554.872    72.224k   66.267k   28.722k   69.763k   62.548k   51.070k   36.112k   18.693k
14    1.110k   36.112k   33.134k   14.361k   34.881k   31.274k   25.535k   18.056k    9.346k
15    2.219k   18.056k   16.567k    7.181k   17.441k   15.637k   12.768k    9.028k    4.673k
16    4.439k    9.028k    8.283k    3.590k    8.720k    7.818k    6.384k    4.514k    2.337k
17    8.878k    4.514k    4.143k    1.795k    4.360k    3.909k    3.192k    2.257k    1.168k
18   17.756k    2.257k    2.071k  897.567     2.180k    1.955k    1.596k    1.128k  584.154
19   35.512k    1.128k    1.035k  448.784     1.090k  977.309   797.970   564.250   292.077
20   71.024k  564.250   517.712   224.392   545.023   488.655   398.985   282.125   146.039
21  142.047k  282.125   258.856   112.196   272.512   244.327   199.492   141.062    73.019
22  284.094k  141.062   129.428    56.098   136.256   122.164    99.746    70.531    36.510
23  568.188k   70.531    64.714    28.049    68.128    61.082    49.873    35.266    18.255
24    1.136M   35.266    32.357    14.024    34.064    30.541    24.937    17.633     9.127
25    2.273M   17.633    16.179     7.012    17.032    15.270    12.468     8.816     4.564
26    4.546M    8.816     8.089     3.506     8.516     7.635     6.234     4.408     2.282
27    9.091M    4.408     4.045     1.753     4.258     3.818     3.117     2.204     1.141
28   18.182M    2.204     2.022   876.531m    2.129     1.909     1.559     1.102   570.463m
29   36.364M    1.102     1.011   438.265m    1.064   954.404m  779.267m  551.025m  285.232m
30   72.728M  551.025m  505.578m  219.133m  532.249m  477.202m  389.634m  275.513m  142.616m
31  145.456M  275.513m  252.789m  109.566m  266.125m  238.601m  194.817m  137.756m   71.308m
32  290.912M  137.756m  126.395m   54.783m  133.062m  119.300m   97.408m   68.878m   35.654m


You could print all zoom 5 tiles on a B0 paper at roughly 200 DPI as a world map poster. Given it's a crappy version of Mercator, it's only useful as a decoration.

I don't think there's a formatting option in LibreOffice Calc to display these decimal humanized values. Maybe 591M659 would be more intuitive than 591.659M, which is equivalent to 591659k, but I want to leave some decimals. Zoom 30 is deeper than 1:1 even at equator. Obviously, the axial tilt and equatorial circumference of other celestial bodies is different. Since Earth is the largest rocky planet, 16 zoom levels will generally suffice for the other 3, Galilean moons may not need more than 12, and dwarf planets may be content with 8. May not work with odd-shaped asteroids.


2024-02-12

Gudhót'n - if a Slavic language was spoken in Mordor


⚞Ⰳ⃝⚟

(lazy Unifont pixelart)


Foreword

This is an English grammar for a dialect of a mostly aposteriori semi-constructed semi-planned language Budhót'n, which was inspired by Palaeogetmanic, adapted so that it fits with Neogetmanic and OSloJ. It was supposed to be an auxlang, given an undue emphasis on foreign words, however the phonology and orthography got out of hand for that to ever function as such, and Slavic grammar isn't exactly condusive for auxlangs. This dialect of mine I call Gudhót'n, which is a reference to git gud in conlanging, and also G follows V which follows B in Glagolitic.

Furthermore, all existing documentation of Budhót'n was in Czech, which itself is a Slavic language. You couldn't learn a foreign word heavy Slavic auxlang unless you knew a Slavic natlang, at which point you will be learning Old Church Slavonic instead of this. Conlang reviwers cannot be expected to learn Czech, an undescribable gobbledygook, just to make a review, which is also a reason for this grammar in English. Also, Neogetmanic grammar is in Czech still, however that isn't an auxlang, so this grammar doubles as a English version of that too.

Given the similarity of Slavic languages, this might not be a natlang ripoff per se, there's a lot of Polish, Russian, and BCMS words. Still, in conlanging it's better to keep off your natlang's language family as much as possible, and that's why I invented the word modlanging. Were it not for prescriptivism, there would be no Palaeogetmanic, it would just be a Czech idiolect.

There is to be a website, but yuck Wordpress: https://www.budhotn.cz/

Linked open data for this abomination may or may be not subject of my thesis.

This is canonical content and pronunciation: https://www.youtube.com/watch?v=RVKbzEPLnNY


Phonology and orthography

The original Budhót'n alphabet consists of 91 letters arranged linearly with some inconsistent assignments made because of Windows Czech keyboard driver being limited to CP1250 with dead keys. This grammar is made on Linux, where this restriction doesn't hold, therefore Gudhót'n is free to use accents consistently. Windows Character Map can't even Unicode properly. Custom .XCompose may be needed.

Legacy WinLatin2 alphabet:

'  A  Á  À    Ă  Å  Ą  B  C  Ć  Ç  Cz Č  D  Ď  Đ Dth Dz Dž E  Ë  É  È  Ê  F  G  Ğ  H  Ch  İ  I  Ï  Í  Ì  Π J  K  Kh L  Ĺ  Ľ  Ł  Lh M  N  Ń  Ņ  Ň  O  Ö  Ó  Ò  Ô  Ő  P  Q  R  Ŕ  Rh Rz  Ŗ  Ř  S  Ś  Sz Ş  Š  T  Ť  Ţ  Th U  Ü  Ú  Ù  Û  Ů  Ų  Ű  V  W  X  Y  Ÿ  Ý  Z  Ż  Ź  Ž  Zh

Neogetmanic mapping (different collation order):

'  A  Á  Ǝ̇  Ȧ  Ą    Ǫ  B  C  Ć  Ċ  Č  Č̇  D  Ď  Ʒ̇  Đ  Ʒ  Ǯ  E  Ä  É  Ë  Ė  F  G  Ġ  H  Ȟ  I̋  I  Ï  Í  Į  Ẏ  J  K  Ɣ  L  Ĺ  Ľ  W  Ꝇ  M  N  Ŋ  Ṅ  Ň  O  Ǝ  Ó  Ö  Ȯ  Ǝ́  P  Q  R  Ŕ  R̂  Ṙ  Ř̇  Ř  S  Ś  Š  Ṡ  Ṧ  T  Ť  Ṫ  Ŧ  U  Ü  Ú  Ų  U̇  Ô  U̇́  Ű  V  V́  X  Y  Ÿ  Ý  Z  Ž  Ź  Ž̇  Ż

IPA:

ʔ  a  aː ɐ  ɑ  ã  oa ɔ̃  b  t͡s t͡sː t͡ʂ t͡ʃ t͡ɕ d  ɟ  d͡ʐ ð  d͡z d͡ʒ ɛ  æ  ɛː e  ɜ  f  g  ɢ  ɦ  x  iː ɪ  i  ɪː ĩ  ɥ  j  k  ɣ  l  lː ʎ  w  ɬ  m  n  ŋ  ɴ  ɲ  o  ə  oː ø  ɔ  əː p  q  r  rː ɹ  ʐ̝  ʀ̝  r̝  s  sː ʃ  ʂ  ɕ  t  c  ʈ  θ  ʊ  y  uː ũ  ɵ  uo ɵː yː v  vː ks ɨ  ʏ  ɨː z  ʒ  zː ʑ  ʐ

BuSloJ flattening:

'  A  Á  A  A  A  OA A  B  C  Č  Č  Č  Č  D  Ď  Ǯ  Ʒ  Ʒ  Ǯ  E  E  É  E  E  F  G  G  H  H  Í  I  I  Í  I  I  J  K  H  L  Ĺ  Ľ  V  L  M  N  N  N  Ň  O  Y  Ó  Y  O  Ý  P  K  R  Ŕ  R  Ř  Ř  Ř  S  S  Š  Š  Š  T  Ť  Ť  C  U  Y  Ú  U  U  UO Ú  Y  V  V  KS I  Y  Í  Z  Ž  Z  Ž  Ž

GeSeL correspondence:

'  A  A  A  A  A  A  A  B  C  J  J  J  J  D  D  J  C  C  J  A  A  A  I  E  F  G  G  H  H  I  I  I  I  I  I  Y  K  G  L  L  L  W  L  M  N  N  N  N  O  E  O  E  O  E  P  Q  R  R  R  J  J  J  S  S  X  X  X  T  T  T  C  U  I  U  U  U  U  U  I  V  V  KS I  I  I  Z  X  Z  X  X

Neogetmanic table by accent:

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z Ʒ Ǝ 
Á   Ć   É       Í     Ĺ     Ó     Ŕ Ś   Ú V́     Ý Ź   Ǝ́ 
    Č Ď       Ȟ       Ľ   Ň       Ř Š Ť           Ž Ǯ   
    Č̇                             Ṙ́ Ṧ   U̇́         Ž̇     
Ȧ   Ċ   Ė   Ġ             Ṅ Ȯ     Ṙ Ṡ Ṫ U̇       Ẏ Ż Ʒ̇   
                           Ô     R̂                     
Ä       Ë       Ï           Ö           Ü       Ÿ       
                I̋           Ő           Ű               
Ą     Đ     Ɣ   Į     Ꝇ   Ŋ Ǫ         Ŧ Ų               


Accents work as follows:

Sign  Description  Effect                 Letters                    Decomposition
´  Acute          Lengthtening            Á Ć É Í Ĺ Ó Ŕ Ś Ú V́ Ý Ź Ǝ́  doubling
 ̇́  Acute and dot  Alternate lenghtening   U̇́                          doubling
ˇ  Caron          Middle palatalization   Č Ď Ȟ Ľ Ň Ř Š Ť Ž Ǯ        cz dj ch lj nj
 ̌̇  Caron and dot  Soft* palatalization    Č̇ Ř̇ Ṧ Ž̇ 
˙  Dot (vowel)     Alternate               Ȧ Ė Ȯ U̇ Ẏ
˙  Dot (consonant) Hard palatalization     Ċ Ġ Ṅ Ṙ Ṡ Ṫ Ż Ʒ̇
^  Circumflex     Velarization            Â Ô R̂
¨  Umlaut         Vowel offset            Ä Ë Ï Ö Ü Ÿ
˝  Acute umlaut   Offset vowel length     I̋ Ő Ű    
˛  Tail           Short nasalization      Ą Į Ŋ Ǫ Ų
-  Strikethru     Eth and Thorn           Đ Ŧ
   Variation      Ghain and Llan          Ɣ Ꝇ

* except Ř̇, see below

This system is modular, in fact it's a 2D orthography, just like Brahmic abugidas or vocalized Arabic, but due to the sheer amount of legacy data, upwards modularity is restricted to Neogetmanic. It seems to work better than IPA for me. All script conversions as described in Neogetmanic hold here too. There's an original mapping to cyrillic, but mine better fits the Neogetmanic <-> DOSloJ span.

There had to be made sereval letters which were not originally in Neogetmanic. This is how crazy the phonology is. Namely the angled candabindu series and the exclamation point letters. As it turns out, Polish Ć Ś Ź is not the same as Czech Č Š Ž, despite them sounding way too soft to other Slavs. Both dot, caron, and acute were taken, so I came up with combining caron and dot. There is precomposed Ṧ in Unicode, good luck with generalizing that to the rest of the letters, and even better luck typing this with Windows' ancient keyboard driver. The other oddities are Ř̇ and U̇́. Ř̇ is logically a long Polish Rz, however it can also be long Czech Ř, which I write Ř́, or Getmanian Ř, which I write Ř̇ or Ř̇́ when long. In fact, Polish Rz is actually Ż in place where there was a sort of R sound, yet the orthography claims to be fully phonetic. U̇́ is supposed to be the Black Speech long Û, the short Û being written U̇, which is Czech Ů in Neogetmanic. This comes to the subtitle of a Slavic language spoken in Mordor.

There are some "long consonants", in the old wrong IPA, Ř̇ is transcribed the same as ̇´R and Ṫ is transcribed the same as Ť´ :

CC = Ć (Ć), RR = Ŕ (Ŕ), RzRz ~ Ř̇ (Ŗ), SS = Ś (Ś), ŤŤ ~ Ṫ (Ţ), VV = V́ (W)

For actual auxlang application purposes, a flattening into OSloJ called BuSLoJ is available. BuSloJ can further be decomposed into mainline OSLoJ and DOSloJ. BuSloJ isn't directly compatible with Visual OSloJ, as it puts the palatalization on the consonant instead of the vowel. There is a "simplified" original Budhót'n orthography, but not nearly enough. You can't have an auxlang with more than 60 letter long alphabet, unless it was made for increasing the entertaining value of the Phonology section of Conlang Critic. Whilst Palaeogetmanic had an undue amount of letters, they were all inverse contraptions.

Phonology in Gudhót'n remains generally unchanged from Budhót'n aside from me pronouncing Rs and Řs like [ʀ] instead of [r] and Ls like [ʟ] instead of [l]. Nonetheless, the official "IPA" is completely wrong because of a crappy keyboard layout, so I provide a more accurate one, though not completely stable as I still figure out what was meant. There are no specific orthography rules, everything is written phonetically, however some supposed phonemes are indistinguishible to me. This allows automatic generation of IPA with sed scripts, however because Google Sheets still can't λ, 128 nested SUBSTITUTEs have to be used, which doesn't work in LibreOffice. Just use AWK, sed, tr, and cut on TSVs.

There are some funny names for punctuation characters, inspired by INTERCAL and my attempt at translation, but let's not worry about them now.


Morphology

Standard Slavic parts of speech are followed.


Nouns

There are all the typical 3 genders, masculine, feminine, and neuter. Based on the nominative, genitive and accusative singular, each of them can also be animate (acc=gen), inanimate (acc=nom), ADHD (all distinct) or zombie (all same). There is no gender inclusivity in Budhót'n and Gudhót'n, only a nonbinary indication particle, see Neogetmanic for true "naplěvať" gender.

There is no dual number, fortunately.

Ending determines the declination paradigma, however it seems random. Furthermore, the endings change depending on the suffix. Prefixes have no impact on declination. Both prefixes and suffixes are ripped off from Czech and Slovak.


Masculine

   god   lock   guest  castle  youngman  forest  people   mate

1
2
3
4
5
6
7

1
2
3
4
5
6
7


Feminine

  goddess   power  girl  pain  woman  machine  kingdom

1
2
3
4
5
6
7

1
2
3
4
5
6
7


Neuter

  army   beer   chicken   sea

1
2
3
4
5
6
7

1
2
3
4
5
6
7


Adjectives

In addition to grading, adjectives also have gender. Luckily, there aren't gazillions of declinations.

There are 2 types of gradation. The older one from way less Slavic times of Budhót'n consists of prepending prefixes (oddly reminiscent of Icelandic), the new one consists of a suffix and a prefix, with the same irregularities.

  masculine       feminine   -ness        neuter

1
2
3
4
5
6
7

1
2
3
4
5
6
7



Pronouns

Slavic pronouns are more complex than it seems. There's about 200 of them belonging to different classes, and just like nouns, they have genders and declinations, in addition to the usual person.

A gender neutral pronoun for genders not known at the compile time is missing, just like in Czech. There is however a particle for nonbinarity. Neogetmanic has onǝ and ěǒ.

To complicate matters further, all 4 politeness levels have distinct pronouns, a feauture of Japanese and Korean no one should ever copy. Politeness is for subs anyway.

Personal

Since regular English is insufficient to differentiate plural and genders, some cringe slang terms were used.

   I   U   he   she   it   we  y'all   dem boiz  dem grlz  dem thangz

1
2
3
4
5
6
7

1
2
3
4
5
6
7

1
2
3
4
5
6
7

1
2
3
4
5
6
7


Possesive

   mine  ur  his  hers  its   our   yer  boiz'  grlz'  thangz'

1
2
3
4
5
6
7

1
2
3
4
5
6
7

1
2
3
4
5
6
7

1
2
3
4
5
6
7


Query

There is no table of corellatives like in Esperanto. There are prefixes ňe- for some-, ňi- for no-, gde- for -ever, -koꝇiv for any-. 

   who   what     which  which  whose

1
2
3
4
5
6
7

1
2
3
4
5
6
7


Non-declining adverbial pronouns:

where  when  how  whence  whither



Pointing

   dat boi   dat grl   dat thang    that

1
2
3
4
5
6
7

1
2
3
4
5
6
7



Quantificatiors

   each   every  all   some   one   alone   same

1
2
3
4
5
6
7

1
2
3
4
5
6
7



Numbers


There is a special modification of the long system, in that it uses it's own numbers instead of Latin. So instead of billion you have dvaljon, and so on and so on.


Suffixes for fraction, multiple, grouping.

SI prefixes are adapted, including the latest ronna and quetta.



Verbs


There are 5 tenses: legendary, past, present, future, and apocalyptical. Legandary and apocalyptical tenses are used for events that didn't or won't happen, just like in many religious scriptures. For more Atheist applications, they can be used for very remote past and future, like the Big Bang or the Heath Death of the Universe.

The endings are strictly concatenative, there is no stem change like in Czech. The only exception is the verb to be. Determinig a stem from dictionary is however not as straightforward.

   legendary   past   present    future   apocalyptical

1
2
3

1
2
3


Informal conjugation is available, which is a feature imported from Finnish.


   legendary   past   present    future   apocalyptical

1
2
3

1
2
3


There are verbal prefixes, but they seem to work same as in Czech.


Adverbs

These were undocumented until I mined the painstakingly hand-input data. As per author's comments, there seems to be a class that is indistinguishible from znamenje type nouns, and another class that is indistinguishible from neuter adjectives. Also many preposition and noun sequences are written without the space, in Czech syntax classes this is called adverbial determination (příslovečné určení).



Prepositions

There are some apriori prepositions.


Conjunctions

These parts of speech are actually apriori, or stolen from languages I don't know.


Particles

This category is considered the "other" or "miscelaneous". There are multiple special syntax elements.


Interjections

They can be appended with an ending to form a noun, adjective, verb, or adverb. Bare interjections are generally undocumented and made on the spot with the broad phoneme repertoire.

Some phrasal greetings are considered interjections. 


Syntax

Except for particles, the syntax in Budhót'n and Gudhót'n is a complete ripoff of Czech, because it wasn't documented, so the natlang stepped in.


There are many phrasal sentences written as a single long word.


Lexicon

There are 4 levels of politeness: literary, colloquial, unliterary, and expressive. In addition to that, there are some 3k archaisms I personally collected from the old website. These names are taken from Czech vocabulary layers, but should be thought of as being nondescript steps. The literary level consists of early words, as it's the original level.

There are multiple packages mostly copied from other dictionaries, each having its own global politeness level. Altogether this language is supposed to have around 500k words. Quite a lot for a conlang made by 2 people. There is no point in shoving words if your application doesn't use them. Google Sheets just get laggy.

Punctuation and letters - literary, 200

Basic words - all 4 levels, 4*10k

Phrases - literary, 1k

Foreign words - literary, 20k of projected 100k

Unforeign words - impromptu literary additions, 5k

Getmanisms - unliterary, also some impromptu, 3k

Czech 2.0 - colloquial, 10k of projected 30k

Conversation mini-dictionaries - archaic, 3k * 12 = 36k

Vulgarisms - expressive, 500

GeSeLisms - unliterary, projected 4*4k

Autosteal transcription - unliterary, projected 50k