A STarKos song has an SKS extension. A song is composed of Patterns, each composed of 3 Tracks, one per channel. A Pattern also posesses a Special Track. The Tracks pointed by the Pattern may be different, or the same. Thus you can have two channels playing the same notes at the same time, without requiring the space of two Tracks in memory, as only one Track is used. The Special Track is only used to change the Speed, as well as play Digidrums.
Each Pattern has its own height, from 0 to 127, regardless of the height of the Track it points to.
A SKS song is saved in ASCII on CPC. It is required because a SKS song can grow up to 55 kilobytes. The song is managed in the banks, linearly. The only possibility to save a file in these conditions with the Amsdos is to save the file byte per byte, which automatically creates an ASCII file.
SONG HEADER | ||||
---|---|---|---|---|
Offset | Field Name | Size | Value | Description |
0 | Format Tag | 10 | STK1.0SONG | ASCII string indicating the SKS format version. |
0 | Author | 10 | ASCII string, padded with spaces. | |
0 | Comments | 32 | ASCII string, padded with spaces. | |
0 | DigiChannel | 1 | 1, 2 or 3 | Indicate on which channel Digidrum should be played. |
0 | EndPattern | 1 | >=0 | Gives the number of the last Pattern. |
0 | LoopTo | 1 | >=0 | Indicate where to loop when the song is over. |
0 | Transposition | 1 | -12 to 12 | Song transpose value (add it to each note). |
0 | BegSpeed | 1 | 1 to #1F | Initial song speed. |
0 | ReplayFreq | 1 | 0 to 5 | 0=13 Hz, 1=25hz, 2=50hz, 3=100hz, 4=150hz and 5=300hz. |
PATTERNS | ||||
Offset | Field Name | Size | Value | Description |
NBPatterns 1 0 to #FF Gives the number of the last Pattern that is NON-EMPTY (see the note below). This information is non redundant to EndPattern, because the software must also save what is beyond the end of the song, the musician may have unused pattern written there. Reserved 1 0 Unused. { Chan 1 Track 2 0 to #1FF Encoded from bit 0 to 8. Transposition - -#F to #F Encoded from bit 9 to 13. Chan 2 Track 2 0 to #1FF Encoded from bit 0 to 8. Transposition - -#F to #F Encoded from bit 9 to 13. Chan 2 Track 2 0 to #1FF Encoded from bit 0 to 8. Transposition - -#F to #F Encoded from bit 9 to 13. Pattern Height 1 0 to #7F No SpecialTrack 1 0 to #FF } * (NBPatterns + 1). NOTE : a NON EMPTY Pattern here only means that the musician hasn't modified the default value in the Linker. By default, the three channels point on Track 0,1,2 respectively. The transpositions and the Special Tracks are 0, and the Pattern Height is #3F. There is always at least one line encoded, even if it has the default values (which is logical, NBPatterns giving the last Pattern. 0 means that one Pattern is in the list). Then are coded the INSTRUMENTS, the SPECIAL TRACKS, and the TRACKS. Only non-empty structures are coded, that's why all of them are identified by a 16 bits value (#FFFF marks the end of each list). If the list is empty (for example, no Special Tracks are used) then the Special Tracks list only contains a #FFFF. INSTRUMENTS ----------- Field Name Size in Bytes Value Remark ---------- ------------- ----- ------ { Instrument ID 2 1 to #FF/#FFFF #FFFF marks the end of the list. Size 2 >=2 The size includes itself. Loop Address 2 The value is RELATIVE to THIS address. Speed 1 >=0 Frames spend on each line. IsRetrig 1 0 or 1 Instrument End 1 0 to #FF Last line of the Instrument. LoopTo 1 0 to #FF <= Instrument End. IsLoop 1 0 or 1 Name 8 Instrument Name, padded with spaces (32). Instruments Data See below. } * Nb Instruments (information not given. Read data till you find an ID equal to #FFFF). NOTE : Don't forget there is ALWAYS #FFFF written at the end of the list, even if the song is empty !! Instrument Data *************** One Instrument Line Data follows this scheme : { Byte1 : Check the 7th bit. If 1, go to HARD SOUND below: NON HARD SOUND : **************** Byte1 : 76543210 0panvvvv p=Pitch ? a=Arpeggio ? n=Noise ? v=Volume If Volume=0, Noise?=0, Byte2 below is not coded (but it also means Sound?=1 and Manual Frequency=0). Other bytes may be coded, however. Byte2 : 76543210 -dsnnnnn d=Manual Frequency ? If Yes, Arpeggio and Pitch not coded. s=Sound? n=Noise, if any. If Manual Frequency? = 1 : read Manual Frequency WORD (0 to #FFF). If Arpeggio? = 1 : read Arpeggio BYTE (-#5F to #5F). If Pitch? = 1 : read Pitch WORD (-#FFF to #FFF). HARD SOUND ********** Byte1 : 76543210 1rednpas r=retrig ? e=Manual HardFrequency ? If 1, Shift and HardSync not coded. d=Manual Frequency ? If 1, Arpeggio and Pitch not coded. n=Noise ? p=Pitch ? a=Arpeggio ? s=Sound ? (0=yes 1=no) Byte2 : 76543210 hf ssscc h=Hardsync ? f=Finetune ? sss=Shift value (0-7). Inverted value. cc=Hard curve (0=R13 à 8, 1=9 2=10 3=11) If Noise? is 1 : read Noise Byte (0 to #1F). If Finetune? is 1 : read Finetune BYTE (0 to #FF). If Arpeggio? is 1 : read Arpeggio BYTE (-#5F to #5F). If Pitch? = 1 : read Pitch WORD (-#FFF to #FFF). If Manual Frequency? = 1 : read Manual Frequency WORD (0 to #FFF). If Manual HardFrequency? = 1 : read Manual HardFrequency WORD (0 to #FFFF). } * (Instrument End + 1) SPECIAL TRACKS -------------- Field Name Size in Bytes Value Remark ---------- ------------- ----- ------ { SpecialTrack ID 2 0 to #FF/#FFFF #FFFF marks the end of the list. Size 1 >=2 The biggest Special Tracks is always < 256 bytes, so a byte is enough to encode its size. The size includes the Size value. Special Track Data See below. } * Nb Special Tracks (information not given. Read data till you find an ID equal to #FFFF). Special Tracks Data ******************* Data Byte : 76543210 wddddddd If w = 1 : Wait for (b6-b0) lines. #FF marks an end of the Special Track (no test needed). If w = 0 : 76543210 0e-vvvvv e=Effect (0=Speed 1=Digidrum) v=Value (0 to #1F) TRACKS ------ Field Name Size in Bytes Value Remark ---------- ------------- ----- ------ { Track ID 2 0 to #FF/#FFFF #FFFF marks the end of the list. Size 1 >=2 The size includes the Size value. Track Data See below. } * Nb Tracks (information not given. Read data till you find an ID equal to #FFFF). Tracks Data *********** Byte1: 76543210 wddddddd If w = 1 : Wait for (b6-b0) lines. #FF marks an end of the Track (no test needed). If w = 0 : 76543210 0nnnnnnn n = Value : 0 to 95 = Note. Volume and Pitch may be present. 96=Volume only (no Note/Pitch/Instrument) 97=Pitch only (no Note/Volume/Instrument) 98=Volume+Pitch only (no Note/Instrument) 99=Reset. Nothing else to read for this line. 100=Digidrum. Read next byte to get Digidrum value. Nothing read more for this line. If no Reset and no Digidrum found : Byte2 : 76543210 -vipoooo v=Volume? 0=Yes 1=No. i=Same Instrument than before ? (0=Yes 1=No) Always 0 on a first Note found on a Track. p=Pitch? o=Inverted Volume value (0=max 15=min). Only significant if v=0. If New Instrument : read Instrument BYTE (1-#FF) If Pitch : read Pitch BYTE (-#7F to #7F)