├── LICENSE ├── PT2.3F.s ├── README.md ├── bin ├── dotinfo.bin ├── exereplay.bin └── reloc32hunk.bin ├── docs ├── HOW_TO_EDIT_GFX.txt └── undocumented_pt_features.txt ├── pak ├── ptaboutbox.pak ├── ptedit1.pak ├── ptedit2.pak ├── ptedit3.pak ├── ptedit4.pak ├── ptfilereq.pak ├── ptfilereq2.pak ├── pthelpscreen.pak ├── ptmonitor.pak ├── ptplst.pak ├── ptposed.pak ├── ptpreseted.pak ├── ptsampler.pak ├── ptscope.pak ├── ptsetup.pak ├── ptsetup2.pak ├── ptspectrumana.pak └── win32 tools │ ├── ptpack.c │ ├── ptpack.exe │ ├── ptunpack.c │ ├── ptunpack.exe │ └── readme.txt ├── raw ├── ptclearbox.raw ├── ptcrunchbox.raw ├── ptfont.raw ├── ptformatbox.raw ├── ptletters.raw ├── ptmainscreen.raw ├── ptsetup2toggles.raw ├── ptsurebox.raw ├── pttoggleoff.raw ├── pttoggleon.raw ├── pttrknamebox.raw └── ptvolbox.raw ├── release ├── PT23F.info └── PT23F │ ├── PT.HELP │ ├── PT2.3F.info │ ├── ReadMe.txt │ └── ReadMe.txt.info └── replayer ├── PT2.3F_replay_cia.s └── PT2.3F_replay_vblank.s /LICENSE: -------------------------------------------------------------------------------- 1 | BSD 3-Clause License 2 | 3 | Copyright (c) 2020-2024, Olav Sørensen 4 | All rights reserved. 5 | 6 | Redistribution and use in source and binary forms, with or without 7 | modification, are permitted provided that the following conditions are met: 8 | 9 | 1. Redistributions of source code must retain the above copyright notice, this 10 | list of conditions and the following disclaimer. 11 | 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation 14 | and/or other materials provided with the distribution. 15 | 16 | 3. Neither the name of the copyright holder nor the names of its 17 | contributors may be used to endorse or promote products derived from 18 | this software without specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /PT2.3F.s: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/PT2.3F.s -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProTracker 2.3F 2 | Continuation of the ProTracker 2 series for Amiga 68k, based on a disassembly and re-source of ProTracker 2.3D. \ 3 | Download: https://16-bits.org/PT23F.LHA \ 4 | Bootable ADF: https://16-bits.org/PT23F.ADF \ 5 | \ 6 | Some new changes worthy of a mention: 7 | 1) It has been fully bugfixed to work as expected on really fast Amigas (a ton of CPU-wait-routines have been replaced with scanline-wait and other safe delay routines) 8 | 2) It has been modified to fully support 128kB samples (all the old >64kB (>$FFFE) limits/bugs are gone, both in the player and GUI) 9 | 3) A ton of other bugs have been fixed 10 | 11 | The asm syntax is AsmOne/AsmPro, and it may not be compatible with other assemblers. 12 | -------------------------------------------------------------------------------- /bin/dotinfo.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/bin/dotinfo.bin -------------------------------------------------------------------------------- /bin/exereplay.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/bin/exereplay.bin -------------------------------------------------------------------------------- /bin/reloc32hunk.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/bin/reloc32hunk.bin -------------------------------------------------------------------------------- /docs/HOW_TO_EDIT_GFX.txt: -------------------------------------------------------------------------------- 1 | All graphics are 2-bit bitplane data. RLE compressed (.pak) or raw (.raw). 2 | 3 | I recommend using IFFMaster v1.0 for Amiga to convert the files to/from .iff. 4 | This free program can be somewhat hard to find on the internet, but be patient 5 | and you will find it. 6 | 7 | I am unfortunately not aware of a simple way to edit the graphics, but I will 8 | explain the difficult process for Windows users... Other users will need to 9 | compile ptpack.c/ptunpack.c for their operating system. 10 | 11 | ---- EDITING COMPRESSED FILES (.PAK) ---- 12 | 13 | To edit f.ex. ptaboutbox.pak in Windows, do the following: 14 | 1) Go to the "pak" directory 15 | 2) Run "ptunpack.exe ptaboutbox.pak" from a command prompt 16 | (this will create ptaboutbox.raw). 17 | 3) Open IFFMaster on Amiga, go to Project->Load Picture and select the new 18 | ptaboutbox.raw. 19 | 4) Here comes the difficult part. You have to know the dimensions for the 20 | image! In this case it's 200x55. Enter 200 in the width box and 55 in the 21 | height box. Press ENTER in each edit box to confirm the inputted values. 22 | Press 2 on the keyboard to select 2 bitplanes mode. Press "Load!". 23 | 5) Go to Project->Save Picture->as IFF/ILBM 24 | 6) Open the newly saved .iff file from IFFMaster in f.ex. Photoshop, do the 25 | edits you need (do NOT introduce new colors!) then save the file 26 | (not "Save As"). Don't worry about the colors being off, they will be right 27 | in ProTracker. 28 | 7) Now open the newly saved .iff in IFFMaster. Press 2 on the keyboard after 29 | load to select 2 bitplanes mode, and save as ptaboutbox.raw 30 | (Project->Save Picture->as raw data). 31 | 8) Make sure ptaboutbox.raw is now in the "pak" folder, and that it overwrote 32 | the old file. 33 | 9) Run "ptpack.exe ptaboutbox.raw" (this will overwrite ptaboutbox.pak) 34 | 10) Some graphics have a specificed byte length in the PT source code and need 35 | updating. In this case, you need to update AboutBoxSize to have the correct 36 | filesize for the new file (f.ex. 1730). 37 | Search for ";---- Graphics Data ----" (without the quotes) with a text 38 | editor and you fill find the section. 39 | 40 | 41 | ---- EDITING RAW FILES (.RAW) ---- 42 | 43 | To edit f.ex. ptmainscreen.raw, do the following: 44 | 1) Go to the "raw" directory 45 | 2) Open IFFMaster on Amiga, go to Project->Load Picture and select 46 | ptmainscreen.raw. 47 | 4) Here comes the difficult part. You have to know the dimensions for the 48 | image! In this case it's 320x256. Enter 320 in the width box and 256 in the 49 | height box. Press ENTER in each edit box to confirm the inputted values. 50 | Press 2 on the keyboard to select 2 bitplanes mode. Press "Load!". 51 | 5) Go to Project->Save Picture->as IFF/ILBM 52 | 6) Open the newly saved .iff file from IFFMaster in f.ex. Photoshop, do the 53 | edits you need (do NOT introduce new colors!) then save the file 54 | (not "Save As"). Don't worry about the colors being off, they will be right 55 | in ProTracker. 56 | 7) Now open the newly saved .iff in IFFMaster. Press 2 on the keyboard after 57 | load to select 2 bitplanes mode, and save as ptmainscreen.raw 58 | (Project->Save Picture->as raw data). 59 | 8) Make sure ptmainscreen.raw is now in the "raw" folder, and that it 60 | overwrote the old file. 61 | 9) Some graphics have a specificed byte length in the PT source code. In this 62 | case, you don't need to change anything for ptmainscreen.raw. 63 | Read 10) above! 64 | 65 | 66 | Sorry for not writing down the graphics dimensions, I have simply forgotten 67 | most of them... 68 | -------------------------------------------------------------------------------- /docs/undocumented_pt_features.txt: -------------------------------------------------------------------------------- 1 | Undocumented features in ProTracker (up to 2.3D): 2 | 3 | 1) PT2.2A and newer: 4 | Type "lock" on the keyboard to lock PT, it asks for a password up to 8 chars 5 | (press ENTER for a password less than 8 chars), then PT is locked until you 6 | type the password again. This locks mouse/keyboard input. 7 | Removed in later versions of PT2.3F, who really uses this in 2025? 8 | 9 | 2) PT2.1A and newer (removed in PT2.3E): 10 | Type "noxious" on keyboard, it will show "not implemented". 11 | Was probably meant to show an easter egg, or some info..? 12 | 13 | 3) PT2.2A and newer: 14 | Press both left and right mouse buttons on the little dot next to the 15 | Disk Op. path gadget. This will list all available disk drives and let 16 | you select one of them. 17 | 18 | 4) PT2.1A and newer: 19 | Press CTRL + ALT + SHIFT + LEFT-AMIGA + DEL. 20 | Prepares a pattern for the infamous "backwards play" trick by inverting 21 | data. 22 | 23 | 5) PT1.0B and newer: 24 | Press the empty button next to the <> key. Stops all playing voices. 25 | -------------------------------------------------------------------------------- /pak/ptaboutbox.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptaboutbox.pak -------------------------------------------------------------------------------- /pak/ptedit1.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptedit1.pak -------------------------------------------------------------------------------- /pak/ptedit2.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptedit2.pak -------------------------------------------------------------------------------- /pak/ptedit3.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptedit3.pak -------------------------------------------------------------------------------- /pak/ptedit4.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptedit4.pak -------------------------------------------------------------------------------- /pak/ptfilereq.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptfilereq.pak -------------------------------------------------------------------------------- /pak/ptfilereq2.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptfilereq2.pak -------------------------------------------------------------------------------- /pak/pthelpscreen.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/pthelpscreen.pak -------------------------------------------------------------------------------- /pak/ptmonitor.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptmonitor.pak -------------------------------------------------------------------------------- /pak/ptplst.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptplst.pak -------------------------------------------------------------------------------- /pak/ptposed.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptposed.pak -------------------------------------------------------------------------------- /pak/ptpreseted.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptpreseted.pak -------------------------------------------------------------------------------- /pak/ptsampler.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptsampler.pak -------------------------------------------------------------------------------- /pak/ptscope.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptscope.pak -------------------------------------------------------------------------------- /pak/ptsetup.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptsetup.pak -------------------------------------------------------------------------------- /pak/ptsetup2.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptsetup2.pak -------------------------------------------------------------------------------- /pak/ptspectrumana.pak: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/ptspectrumana.pak -------------------------------------------------------------------------------- /pak/win32 tools/ptpack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define COMPACTOR_CODE 181 8 | #define RLE_BYTES_THRESHOLD 4 /* minimum equal running bytes for RLE */ 9 | 10 | #define SWAP32(value) \ 11 | ( \ 12 | (((uint32_t)((value) & 0x000000FF)) << 24) | \ 13 | (((uint32_t)((value) & 0x0000FF00)) << 8) | \ 14 | (((uint32_t)((value) & 0x00FF0000)) >> 8) | \ 15 | (((uint32_t)((value) & 0xFF000000)) >> 24) \ 16 | ) 17 | 18 | #ifdef _WIN32 19 | #define PATH_MAX MAX_PATH 20 | #endif 21 | 22 | static bool bigEndian; 23 | static char tmpFilename[PATH_MAX+4+1]; 24 | 25 | static bool pack(const char *filenameIn, const char *filenameOut); 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | // detect endianness 30 | volatile uint32_t endiantest32 = 0xFF; 31 | bigEndian = (*(uint8_t *)&endiantest32 != 0xFF); 32 | 33 | if (argc != 2) 34 | { 35 | printf("Usage: ptpack \n"); 36 | return -1; 37 | } 38 | 39 | strcpy(tmpFilename, argv[1]); 40 | 41 | uint32_t filenameLen = (uint32_t)strlen(tmpFilename); 42 | if (filenameLen >= 5) 43 | tmpFilename[filenameLen-4] = '\0'; 44 | strcat(tmpFilename, ".pak"); 45 | 46 | if (!pack(argv[1], tmpFilename)) 47 | return 1; 48 | else 49 | return 0; 50 | } 51 | 52 | static bool pack(const char *filenameIn, const char *filenameOut) 53 | { 54 | FILE *in = fopen(filenameIn, "rb"); 55 | if (in == NULL) 56 | { 57 | printf("ERROR: Could not open input file for reading!\n"); 58 | return false; 59 | } 60 | 61 | // get input file length 62 | fseek(in, 0, SEEK_END); 63 | uint32_t srcDataLen = (uint32_t)ftell(in); 64 | rewind(in); 65 | 66 | uint8_t *srcData = (uint8_t *)malloc(srcDataLen); 67 | if (srcData == NULL) 68 | { 69 | fclose(in); 70 | printf("ERROR: Out of memory!\n"); 71 | return false; 72 | } 73 | 74 | fread(srcData, 1, srcDataLen, in); 75 | fclose(in); 76 | 77 | uint8_t *dstData = (uint8_t *)malloc(srcDataLen*3); // *3 should work in all cases 78 | if (dstData == NULL) 79 | { 80 | free(srcData); 81 | printf("ERROR: Out of memory!\n"); 82 | return false; 83 | } 84 | 85 | uint8_t *src = srcData; 86 | uint8_t *dst = dstData; 87 | uint8_t *srcEnd = srcData+srcDataLen; 88 | 89 | while (src < srcEnd) 90 | { 91 | uint8_t byte = *src++; 92 | if (byte == COMPACTOR_CODE) // byte is equal to RLE ID, special case 93 | { 94 | *dst++ = COMPACTOR_CODE; // RLE identifier 95 | *dst++ = 0; // RLE count (minus one) 96 | *dst++ = COMPACTOR_CODE; // RLE data 97 | continue; 98 | } 99 | 100 | // scan amount of equal following bytes 101 | 102 | uint16_t count; 103 | for (count = 0; count < 256; count++) 104 | { 105 | if (src+count >= srcEnd || byte != src[count]) 106 | break; 107 | } 108 | 109 | src += count; 110 | count++; 111 | 112 | if (count < RLE_BYTES_THRESHOLD) 113 | { 114 | // too few equal bytes, store them instead of compressing 115 | memset(dst, byte, count); 116 | dst += count; 117 | } 118 | else 119 | { 120 | if (count > 256) // edge case 121 | { 122 | count = 256; 123 | src -= 2; 124 | } 125 | 126 | *dst++ = COMPACTOR_CODE; // RLE identifier 127 | *dst++ = (uint8_t)(count-1); // RLE count (minus one) 128 | *dst++ = byte; // RLE data 129 | } 130 | } 131 | free(srcData); 132 | 133 | FILE *out = fopen(filenameOut, "wb"); 134 | if (out == NULL) 135 | { 136 | free(dstData); 137 | printf("ERROR: Could not open output file for writing!\n"); 138 | return false; 139 | } 140 | 141 | // write unpacked length dword 142 | uint32_t dword = srcDataLen; 143 | if (!bigEndian) 144 | dword = SWAP32(dword); 145 | fwrite(&dword, 4, 1, out); 146 | 147 | // write pack data 148 | uint32_t packedLength = (uint32_t)(dst - dstData); 149 | fwrite(dstData, 1, packedLength, out); 150 | packedLength += 4; 151 | 152 | fclose(out); 153 | 154 | free(dstData); 155 | 156 | printf("RLE encoding done!\n"); 157 | printf("=============================================\n"); 158 | printf(" Original size: %d bytes\n", srcDataLen); 159 | printf(" Encoded size: %d bytes\n", packedLength); 160 | printf("Compression ratio: %.3f", srcDataLen / (double)packedLength); 161 | 162 | if (srcDataLen == packedLength) 163 | printf("\n"); 164 | else if (srcDataLen > packedLength) 165 | printf(" (bytes saved: %d)\n", srcDataLen - packedLength); 166 | else 167 | printf(" (bytes wasted: %d)\n", packedLength - srcDataLen); 168 | 169 | return true; 170 | } 171 | -------------------------------------------------------------------------------- /pak/win32 tools/ptpack.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/win32 tools/ptpack.exe -------------------------------------------------------------------------------- /pak/win32 tools/ptunpack.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #define COMPACTOR_CODE 181 8 | 9 | #define SWAP32(value) \ 10 | ( \ 11 | (((uint32_t)((value) & 0x000000FF)) << 24) | \ 12 | (((uint32_t)((value) & 0x0000FF00)) << 8) | \ 13 | (((uint32_t)((value) & 0x00FF0000)) >> 8) | \ 14 | (((uint32_t)((value) & 0xFF000000)) >> 24) \ 15 | ) 16 | 17 | #ifdef _WIN32 18 | #define PATH_MAX MAX_PATH 19 | #endif 20 | 21 | static bool bigEndian; 22 | static char tmpFilename[PATH_MAX+4+1]; 23 | 24 | static bool unpack(const char *filenameIn, const char *filenameOut); 25 | 26 | int main(int argc, char *argv[]) 27 | { 28 | // detect endianness 29 | volatile uint32_t endiantest32 = 0xFF; 30 | bigEndian = (*(uint8_t *)&endiantest32 != 0xFF); 31 | 32 | if (argc != 2) 33 | { 34 | printf("Usage: ptunpack \n"); 35 | return -1; 36 | } 37 | 38 | strcpy(tmpFilename, argv[1]); 39 | 40 | uint32_t filenameLen = (uint32_t)strlen(tmpFilename); 41 | if (filenameLen >= 5) 42 | tmpFilename[filenameLen-4] = '\0'; 43 | strcat(tmpFilename, ".raw"); 44 | 45 | if (!unpack(argv[1], tmpFilename)) 46 | return 1; 47 | else 48 | return 0; 49 | } 50 | 51 | static bool unpack(const char *filenameIn, const char *filenameOut) 52 | { 53 | FILE *f = NULL; 54 | uint8_t *srcData = NULL, *dstData = NULL; 55 | 56 | f = fopen(filenameIn, "rb"); 57 | if (f == NULL) 58 | { 59 | printf("ERROR: Could not open input file for reading!\n"); 60 | goto error; 61 | } 62 | 63 | // fetch input file length 64 | fseek(f, 0, SEEK_END); 65 | uint32_t packedLength = (uint32_t)ftell(f); 66 | rewind(f); 67 | 68 | if (packedLength <= 4) goto corruptFile; 69 | packedLength -= 4; // skip unpacked length field 70 | 71 | srcData = (uint8_t *)malloc(packedLength); 72 | if (srcData == NULL) 73 | { 74 | printf("ERROR: Out of memory!\n"); 75 | goto error; 76 | } 77 | 78 | uint32_t unpackedLength; 79 | fread(&unpackedLength, 4, 1, f); 80 | if (!bigEndian) 81 | unpackedLength = SWAP32(unpackedLength); 82 | fread(srcData, 1, packedLength, f); 83 | fclose(f); 84 | f = NULL; 85 | 86 | if (unpackedLength == 0 || unpackedLength >= 1<<20) 87 | goto corruptFile; 88 | 89 | dstData = (uint8_t *)malloc(unpackedLength); 90 | if (dstData == NULL) 91 | { 92 | printf("ERROR: Out of memory!\n"); 93 | goto error; 94 | } 95 | 96 | uint8_t *src = srcData; 97 | uint8_t *dst = dstData; 98 | uint8_t *srcEnd = srcData + packedLength; 99 | uint8_t *dstEnd = dstData + unpackedLength; 100 | 101 | // RLE decode 102 | while (src < srcEnd && dst < dstEnd) 103 | { 104 | const uint8_t byte = *src++; 105 | if (byte == COMPACTOR_CODE) 106 | { 107 | if (src >= srcEnd) goto corruptFile; 108 | uint16_t numBytes = (uint16_t)(*src++) + 1; 109 | 110 | if (src >= srcEnd) goto corruptFile; 111 | const uint8_t data = *src++; 112 | 113 | // packer is sometimes buggy, some protection is needed 114 | if (dst+numBytes > dstEnd) 115 | numBytes = dstEnd - dst; 116 | 117 | memset(dst, data, numBytes); 118 | dst += numBytes; 119 | } 120 | else 121 | { 122 | *dst++ = byte; 123 | } 124 | } 125 | free(srcData); 126 | 127 | f = fopen(filenameOut, "wb"); 128 | if (f == NULL) 129 | { 130 | printf("ERROR: Could not open output file for writing!\n"); 131 | goto error; 132 | } 133 | fwrite(dstData, 1, unpackedLength, f); 134 | fclose(f); 135 | free(dstData); 136 | 137 | printf("RLE decoding done!\n"); 138 | printf("=============================================\n"); 139 | printf("Decoded size: %d bytes\n", unpackedLength); 140 | return true; 141 | 142 | corruptFile: 143 | printf("ERROR: Corrupt input file!\n"); 144 | error: 145 | if (srcData != NULL) free(srcData); 146 | if (dstData != NULL) free(dstData); 147 | if (f != NULL) fclose(f); 148 | return false; 149 | } 150 | -------------------------------------------------------------------------------- /pak/win32 tools/ptunpack.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/pak/win32 tools/ptunpack.exe -------------------------------------------------------------------------------- /pak/win32 tools/readme.txt: -------------------------------------------------------------------------------- 1 | These Windows tools are for packing/unpacking ProTracker .raw/.pak files. 2 | The source code for these tools should be POSIX compliant and compile on 3 | other systems. -------------------------------------------------------------------------------- /raw/ptclearbox.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptclearbox.raw -------------------------------------------------------------------------------- /raw/ptcrunchbox.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptcrunchbox.raw -------------------------------------------------------------------------------- /raw/ptfont.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptfont.raw -------------------------------------------------------------------------------- /raw/ptformatbox.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptformatbox.raw -------------------------------------------------------------------------------- /raw/ptletters.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptletters.raw -------------------------------------------------------------------------------- /raw/ptmainscreen.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptmainscreen.raw -------------------------------------------------------------------------------- /raw/ptsetup2toggles.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptsetup2toggles.raw -------------------------------------------------------------------------------- /raw/ptsurebox.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptsurebox.raw -------------------------------------------------------------------------------- /raw/pttoggleoff.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/pttoggleoff.raw -------------------------------------------------------------------------------- /raw/pttoggleon.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/pttoggleon.raw -------------------------------------------------------------------------------- /raw/pttrknamebox.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/pttrknamebox.raw -------------------------------------------------------------------------------- /raw/ptvolbox.raw: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/raw/ptvolbox.raw -------------------------------------------------------------------------------- /release/PT23F.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/release/PT23F.info -------------------------------------------------------------------------------- /release/PT23F/PT.HELP: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/release/PT23F/PT.HELP -------------------------------------------------------------------------------- /release/PT23F/PT2.3F.info: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/8bitbubsy/pt23f/db45f12d9c23752df68f8e708acb01f82d0a6291/release/PT23F/PT2.3F.info -------------------------------------------------------------------------------- /release/PT23F/ReadMe.txt: -------------------------------------------------------------------------------- 1 | ProTracker v2.3F 2 | ============================== 3 | 29th of May, 2025 4 | 5 | If you find any bugs, please email me at the email/Discord found on 6 | the website 16-bits.org. 7 | 8 | NOTE: 9 | This specific version is fully 128kB sample compliant, so if you use 10 | loop points above the 64kB barrier, then the module will fail to 11 | play correctly on most ProTracker versions, except some 3.x ones. 12 | 13 | PT2.3D by: 14 | - Peter "CRAYON" Hanning 15 | - Lars "ZAP" Hamre 16 | - Detron 17 | 18 | PT2.3E/PT2.3F by: 19 | - Olav "8bitbubsy" Sorensen 20 | 21 | -- PT2.3F changelog: -- 22 | 23 | == Update 29.05.2025 =============================================== 24 | - Optimizations for song playback counter code 25 | - Song playback counter now ticks correctly on NTSC Amigas 26 | ==================================================================== 27 | 28 | == Update 24.05.2025 =============================================== 29 | - Quadrascope and Spectrum Analyzer optimizations 30 | - Very minor optimization for VU meters 31 | ==================================================================== 32 | 33 | == Update 21.05.2025 =============================================== 34 | - Safer code for when updating sample loops in realtime 35 | (e.g. when dragging the loop points while a sample is playing). 36 | - Set Sample Offset (9xx) now works on >64kB samples 37 | - Small quadrascope optimization 38 | ==================================================================== 39 | 40 | == Update 14.04.2025 =============================================== 41 | - SHIFT + ALT/CTRL + z = play sample range (hi XSM!) 42 | ==================================================================== 43 | 44 | == Update 13.04.2025 =============================================== 45 | - You can now use SHIFT + ALT/CTRL + left/right/up/down to adjust 46 | the sample data mark in the sampler screen. 47 | - Removed some unneeded stuff (PT lock & "show rasterbar" keys) 48 | ==================================================================== 49 | 50 | == Update 10.04.2025 =============================================== 51 | - Sample loops are now updated properly when dragging the loop 52 | points while the sample is playing. 53 | ==================================================================== 54 | 55 | == Update 17.11.2024 =============================================== 56 | - Small arpeggio effect optimization 57 | ==================================================================== 58 | 59 | == Update 12.09.2024 =============================================== 60 | - Bug-fix and speed-up of the volume change ("VOL") function in 61 | Edit Op. #3. 62 | ==================================================================== 63 | 64 | == Update 09.10.2023 =============================================== 65 | - The following sample editing functions have been optimized to take 66 | less time to complete: 67 | 1) Resample (Sampler screen) 68 | 2) Volume ("RAMP") (Sampler screen) 69 | 3) Volume change ("VOL") (Edit Op. #3) 70 | 4) Fade Up ("FU") (Edit Op. #3) 71 | 5) Fade Down ("FD") (Edit Op. #3) 72 | 6) Boost (Edit Op. #3, only very lightly optimized) 73 | 7) Filter (Edit Op. #3) 74 | 8) X-Fade (Edit Op. #3, only very lightly optimized) 75 | 9) Mix (Edit Op. #3) 76 | - The sample chord editor now produces better samples (16-bit mixing 77 | + normalized gain before converting to 8-bit), and takes up less 78 | RAM. It's still as slow as before, if not slightly slower. 79 | - Removed the custom length stuff from the sample chord editor. I 80 | don't really think they were all that useful. 81 | - Slightly reduced the duration of "red mouse cursor" errors 82 | - A sample's waveform no longer "wiggles" while scrolling through it 83 | in the sampler screen. It still flickers, though. 84 | - The mouse now moves slightly more smoothly (no crude acceleration) 85 | - Bugfix: Redraw sample after having mixed ("MIX") samples together 86 | - Removed the Karplus-Strong (E8x) command/effect. Not only was it 87 | not documented anywhere, but it was the most useless and annoying 88 | effect to ever exist. Probably also the least used. 89 | - Removed CTRL+V (filter all samples) and CTRL+G (boost all samples) 90 | - Edited and cleaned up the PT help file 91 | ==================================================================== 92 | 93 | == Update 14.06.2023 =============================================== 94 | - The spectrum analyzer didn't work like it should when jamming 95 | samples with the computer keyboard (if finetune wasn't zero). 96 | - Nasty out-of-bounds memory access fixed for the spectrum analyzer 97 | in some edge cases. 98 | ==================================================================== 99 | 100 | == Update 08.03.2023 =============================================== 101 | - Fixed: Another vblank+>31 speed fix, for Note Retrigger (E9x) 102 | - Removed note retrigger LUT (was used to remove DIV). Frees up 103 | around 528 bytes of RAM. This optimization was a bit pointless as 104 | a bunch of note retriggers at once is very uncommon. 105 | ==================================================================== 106 | 107 | == Update 07.03.2023 =============================================== 108 | - Fixed: Text editing delays were too short when writing/deleting 109 | characters and moving the text cursor (in comparison to PT2.3D). 110 | - Fixed: If arpeggio was used in vblank timing mode together with a 111 | speed above 31, it would not work correctly. 112 | - Fixed: Changing speed in SETUP was wrongly limited to 0..32. 113 | (I had forgotten about vblank timing mode when I made this change) 114 | - Lowered process stack from 16kB to 2kB, to free up more RAM for 115 | systems like a stock A500. 116 | - The waveform plotter in the sample editor has been given a small 117 | optimization. It's still very slow and flickery on a 7MHz 68k 118 | Amiga, though... 119 | ==================================================================== 120 | 121 | == Update 25.01.2023 =============================================== 122 | - Fixed: Weird things would happen if you were in text/number edit 123 | mode while efx F00 (stop song) got triggered (hi again Per Arne) 124 | ==================================================================== 125 | 126 | == Update 11.01.2023 =============================================== 127 | - Some specific errors (e.g. "CAN'T FIND DIR !") could cause a 128 | messed up Workbench screen on exit. 129 | - Allow CTRL+Fn (Record From) keys while the sampler screen is open 130 | (hi Per Arne). 131 | ==================================================================== 132 | 133 | == Update 27.10.2022 =============================================== 134 | - "Sample exchange" on sample 31/$1F would cause severe instability 135 | - Loading IFF samples would result in junk after the sample data 136 | - Some of the delay durations (setting edit skip, red mouse pointer 137 | etc.) were too short in comparison to previous PT versions. 138 | ==================================================================== 139 | 140 | == Update 04.08.2022 =============================================== 141 | - Don't allow 'loop toggle' (sampler screen) on empty samples. 142 | It would set replen to 0, which could make crazy things happen... 143 | ==================================================================== 144 | 145 | == Update 30.05.2022 =============================================== 146 | - Fixed EDx command causing a guru in 14.04.2022 version. 147 | Sorry again! This was a stupid mistake. 148 | ==================================================================== 149 | 150 | == Update 14.04.2022 =============================================== 151 | - Fixed severely broken E9x command from 03.03.2022 version (sorry!) 152 | ==================================================================== 153 | 154 | == Update 03.03.2022 =============================================== 155 | - Miscellaneous bug fixes ("Play Waveform", "Play Range", + more) 156 | - Fixed quadrascope period clamping bug 157 | - Fixed sample playback line not showing when using "real" VU-meters 158 | ==================================================================== 159 | 160 | == Update 20.01.2021 =============================================== 161 | - Fixed a bug where ending a parallel port sample session before 162 | filling the whole buffer, would render the tracker unstable. 163 | - The quadrascope shouldn't read out-of-bounds anymore on 164 | non-looping samples. 165 | - Another minor quadrascope fix 166 | ==================================================================== 167 | 168 | == Update 18.01.2021 =============================================== 169 | - Fix >64kB bugs in the parallel port sampling code 170 | ==================================================================== 171 | 172 | == Update 14.07.2020 =============================================== 173 | - Bugfix for 68000: Pasting to an empty sample would cause a crash 174 | ==================================================================== 175 | 176 | == Update 30.05.2020 =============================================== 177 | - Fixed: The scopes would show a blank waveform when using 9xx 178 | (set sample offset) on a non-looping sample 179 | ==================================================================== 180 | 181 | == Update 09.05.2020 =============================================== 182 | - Had to revert some of the IFF fixes because they would cause 183 | memory leaks... 184 | ==================================================================== 185 | 186 | == Update 02.03.2020 =============================================== 187 | - Fixed: RAW sample loading got broken at 20.02.2020. Sorry! 188 | ==================================================================== 189 | 190 | == Update 20.02.2020 =============================================== 191 | - Bugfix: Loading an .iff sample longer than 128kB would result in 192 | 131070-(64..256) bytes instead of 131070 bytes. 193 | - Bugfix: When loading .iff samples, the "DISP:" value in the SAMPLER 194 | screen would be too big, and thus it whould show overflowed data. 195 | - Bugfix: Moving the right loop pin (SAMPLER screen) could behave 196 | strange on samples bigger than $FFFE/65534. 197 | ==================================================================== 198 | 199 | == Update 15.02.2020 =============================================== 200 | - Fixed crashes when loading samples (accidental typo in a stealth 201 | update that was not listed here). 202 | - Also fixed memory access issue when drawing blank scopes 203 | ==================================================================== 204 | 205 | == Update 10.11.2019 =============================================== 206 | - The TUNE/FREE fields were not showing correct values at all times 207 | ==================================================================== 208 | 209 | == Update 01.11.2019 =============================================== 210 | - More quadrascope fixes, of course, what did you expect? ;) 211 | ==================================================================== 212 | 213 | == Update 28.10.2019 =============================================== 214 | - Yet again some more quadrascope bugfixes. This time the scopes will properly 215 | render on loops where start=0 and end64kB samples 31 | 32 | ; CIA Version: 33 | ; Call SetCIAInt to install the interrupt server. Then call mt_init 34 | ; to initialize the song. Playback starts when the mt_enable flag 35 | ; is set to a non-zero value. To end the song and turn off all voices, 36 | ; call mt_end. At last, call ResetCIAInt to remove the interrupt. 37 | ; 38 | ; You can use this routine to play a module. Just remove the semicolons. 39 | ; Also change the module path in mt_data at the very bottom of this file. 40 | ; Exit by pressing both mouse buttons. 41 | ; 42 | main BSR.W SetCIAInt 43 | BSR.W mt_init 44 | ST mt_Enable 45 | MOVE.L 4.W,A6 46 | LEA DOSName(PC),A1 47 | MOVEQ #0,D0 48 | JSR LVOOpenLibrary(A6) 49 | TST.L D0 50 | BEQ.B theend 51 | MOVE.L D0,A6 52 | wloop MOVEQ #10,D1 53 | JSR LVODelay(A6) 54 | BTST #6,$BFE001 55 | BNE.B wloop 56 | BTST #2,$DFF016 57 | BNE.B wloop 58 | MOVE.L A6,A1 59 | MOVE.L 4.W,A6 60 | JSR LVOCloseLibrary(A6) 61 | theend BSR.W mt_end 62 | BSR.W ResetCIAInt 63 | RTS 64 | 65 | 66 | ;---- CIA Interrupt ---- 67 | 68 | AddICRVector = -6 69 | RemICRVector = -12 70 | LVOOpenResource = -498 71 | LVOOpenLibrary = -552 72 | LVOCloseLibrary = -414 73 | LVODelay = -198 74 | 75 | ciatalo = $400 76 | ciatahi = $500 77 | ciatblo = $600 78 | ciatbhi = $700 79 | ciacra = $E00 80 | ciacrb = $F00 81 | 82 | SetCIAInt 83 | MOVEQ #2,D6 84 | LEA $BFD000,A5 85 | MOVE.B #'b',CIAAName+3 86 | SetCIALoop 87 | MOVEQ #0,D0 88 | LEA CIAAName(PC),A1 89 | MOVE.L 4.W,A6 90 | JSR LVOOpenResource(A6) 91 | MOVE.L D0,CIAAbase 92 | BEQ.W mt_Return3 93 | 94 | LEA GfxName(PC),A1 95 | MOVEQ #0,D0 96 | JSR LVOOpenLibrary(A6) 97 | TST.L D0 98 | BEQ ResetCIAInt 99 | MOVE.L D0,A1 100 | MOVE.W 206(A1),D0 ; DisplayFlags 101 | BTST #2,D0 ; PAL? 102 | BEQ.B WasNTSC 103 | MOVE.L #1773447,D7 ; PAL 104 | BRA.B sciask 105 | WasNTSC MOVE.L #1789773,D7 ; NTSC 106 | sciask MOVE.L D7,TimerValue 107 | DIVU #125,D7 ; Default to normal 50 Hz timer 108 | JSR LVOCloseLibrary(A6) 109 | 110 | MOVE.L CIAAbase(PC),A6 111 | CMP.W #2,D6 112 | BEQ.B TryTimerA 113 | TryTimerB 114 | LEA MusicIntServer(PC),A1 115 | MOVEQ #1,D0 ; Bit 1: Timer B 116 | JSR AddICRVector(A6) 117 | MOVE.L #1,TimerFlag 118 | TST.L D0 119 | BNE.B CIAError 120 | MOVE.L A5,CIAAaddr 121 | MOVE.B D7,ciatblo(A5) 122 | LSR.W #8,D7 123 | MOVE.B D7,ciatbhi(A5) 124 | BSET #0,ciacrb(A5) 125 | RTS 126 | 127 | TryTimerA 128 | LEA MusicIntServer(PC),A1 129 | MOVEQ #0,D0 ; Bit 0: Timer A 130 | JSR AddICRVector(A6) 131 | CLR.L TimerFlag 132 | TST.L D0 133 | BNE.B CIAError 134 | MOVE.L A5,CIAAaddr 135 | MOVE.B D7,ciatalo(A5) 136 | LSR.W #8,D7 137 | MOVE.B D7,ciatahi(A5) 138 | BSET #0,ciacra(A5) 139 | RTS 140 | 141 | CIAError 142 | MOVE.B #'a',CIAAName+3 143 | LEA $BFE001,A5 144 | SUBQ.W #1,D6 145 | BNE SetCIALoop 146 | CLR.L CIAAbase 147 | RTS 148 | 149 | ResetCIAInt 150 | MOVE.L CIAAbase(PC),D0 151 | BEQ.W mt_Return3 152 | CLR.L CIAAbase 153 | MOVE.L D0,A6 154 | MOVE.L CIAAaddr(PC),A5 155 | TST.L TimerFlag 156 | BEQ.B ResTimerA 157 | 158 | BCLR #0,ciacrb(A5) 159 | MOVEQ #1,D0 160 | BRA.B RemInt 161 | 162 | ResTimerA 163 | BCLR #0,ciacra(A5) 164 | MOVEQ #0,D0 165 | RemInt LEA MusicIntServer(PC),A1 166 | MOVEQ #0,d0 167 | JSR RemICRVector(A6) 168 | RTS 169 | 170 | ;---- Tempo ---- 171 | 172 | SetTempo 173 | MOVE.L CIAAbase(PC),D2 174 | BEQ.W mt_Return3 175 | CMP.W #32,D0 176 | BHS.B setemsk 177 | MOVEQ #32,D0 178 | setemsk MOVE.W D0,RealTempo 179 | MOVE.L TimerValue(PC),D2 180 | DIVU D0,D2 181 | MOVE.L CIAAaddr(PC),A4 182 | MOVE.L TimerFlag(PC),D0 183 | BEQ.B SetTemA 184 | MOVE.B D2,ciatblo(A4) 185 | LSR.W #8,D2 186 | MOVE.B D2,ciatbhi(A4) 187 | RTS 188 | 189 | SetTemA MOVE.B D2,ciatalo(A4) 190 | LSR.W #8,D2 191 | MOVE.B D2,ciatahi(A4) 192 | RTS 193 | 194 | CNOP 0,4 195 | CIAAaddr dc.l 0 196 | CIAAbase dc.l 0 197 | TimerFlag dc.l 0 198 | TimerValue dc.l 0 199 | RealTempo dc.w 125 ; copy of current BPM set in SetTempo 200 | LEDStatus dc.b 0 201 | 202 | CNOP 0,4 203 | MusicIntServer 204 | dc.l 0,0 205 | dc.b 2,5 ; type, priority 206 | dc.l MusIntName 207 | dc.l 0,mt_IntMusic 208 | 209 | DOSName dc.b "dos.library",0 210 | CIAAName dc.b "ciaa.resource",0 211 | GfxName dc.b "graphics.library",0 212 | MusIntName dc.b "ProTracker interrupt",0 213 | EVEN 214 | 215 | ;---- Playroutine ---- 216 | 217 | n_note EQU 0 ; W (MUST be first!) 218 | n_cmd EQU 2 ; W (MUST be second!) 219 | n_cmdlo EQU 3 ; B (offset in n_cmd) 220 | n_start EQU 4 ; L (aligned) 221 | n_loopstart EQU 8 ; L 222 | n_wavestart EQU 12 ; L 223 | n_peroffset EQU 16 ; L (offset to finetuned period-LUT section) 224 | n_length EQU 20 ; W (aligned) 225 | n_replen EQU 22 ; W 226 | n_period EQU 24 ; W 227 | n_dmabit EQU 26 ; W 228 | n_wantedperiod EQU 28 ; W 229 | n_finetune EQU 30 ; B 230 | n_volume EQU 31 ; B 231 | n_toneportdirec EQU 32 ; B 232 | n_toneportspeed EQU 33 ; B 233 | n_vibratocmd EQU 34 ; B 234 | n_vibratopos EQU 35 ; B 235 | n_tremolocmd EQU 36 ; B 236 | n_tremolopos EQU 37 ; B 237 | n_wavecontrol EQU 38 ; B 238 | n_glissfunk EQU 39 ; B 239 | n_sampleoffset EQU 40 ; B 240 | n_pattpos EQU 41 ; B 241 | n_loopcount EQU 42 ; B 242 | n_funkoffset EQU 43 ; B 243 | 244 | mt_init 245 | MOVEM.L D0-A6,-(SP) 246 | 247 | LEA mt_data,A0 248 | MOVE.L A0,mt_SongDataPtr 249 | MOVE.B 950(A0),mt_SongLength 250 | LEA 12(A0),A1 251 | MOVE.L A1,mt_SampleStructPtr 252 | 253 | ; count number of patterns (find highest referred pattern) 254 | LEA 952(A0),A1 ; order list address 255 | MOVEQ #128-1,D0 ; 128 order list entries 256 | MOVEQ #0,D1 257 | mtloop MOVE.L D1,D2 258 | SUBQ.W #1,D0 259 | mtloop2 MOVE.B (A1)+,D1 260 | CMP.B D2,D1 261 | BGT.B mtloop 262 | DBRA D0,mtloop2 263 | ADDQ.B #1,D2 264 | 265 | ; generate mt_SampleStarts list and fix samples 266 | 267 | LSL.L #8,D2 268 | LSL.L #2,D2 ; D2 *= 1024 269 | ADD.L #1084,D2 270 | ADD.L A0,D2 271 | MOVE.L D2,A2 ; A2 is now the address of first sample's data 272 | 273 | LEA mt_SampleStarts(PC),A1 274 | MOVEQ #31-1,D3 275 | mtloop3 MOVEQ #0,D0 276 | MOVE.W 42(A0),D0 ; get sample length 277 | BEQ.B mtskip2 ; sample is empty, don't handle 278 | MOVEQ #0,D1 279 | MOVE.W 46(A0),D1 ; get repeat 280 | MOVEQ #0,D2 281 | MOVE.W 48(A0),D2 ; get replen 282 | BNE.B mtskip 283 | MOVEQ #1,D2 284 | MOVE.W D2,48(A0) ; replen is zero, set to 1 (fixes lock-up) 285 | mtskip ADD.L D2,D1 286 | CMP.L #1,D1 ; loop enabled? (repeat+replen > 1) 287 | BHI.B mtskip2 ; yes 288 | CLR.W (A2) ; no, clear first word of sample (prevents beep) 289 | mtskip2 MOVE.L A2,(A1)+ ; move sample address into mt_SampleStarts slot 290 | ADD.L D0,D0 ; turn into real sample length 291 | ADD.L D0,A2 ; add to address 292 | LEA 30(A0),A0 ; skip to next sample list entry 293 | DBRA D3,mtloop3 294 | 295 | ; initialize stuff 296 | MOVE.B $BFE001,D0 ; copy of LED filter state 297 | AND.B #2,D0 298 | MOVE.B D0,LEDStatus 299 | BSET #1,$BFE001 ; turn off LED filter 300 | ; -------------------- 301 | MOVE.B #6,mt_Speed 302 | CLR.B mt_Counter 303 | CLR.B mt_SongPos 304 | CLR.W mt_PatternPos 305 | CLR.B mt_PattDelayTime 306 | CLR.B mt_PattDelayTime2 307 | BSR.W mt_RestoreEffects 308 | MOVEQ #125,D0 309 | BSR.W SetTempo 310 | SF mt_Enable 311 | BSR.B mt_TurnOffVoices 312 | 313 | MOVEM.L (SP)+,D0-A6 314 | RTS 315 | 316 | mt_end 317 | SF mt_Enable 318 | BCLR #1,$BFE001 ; restore previous LED filter state 319 | MOVE.L D0,-(SP) 320 | MOVE.B LEDStatus(PC),D0 321 | OR.B D0,$BFE001 322 | MOVE.L (SP)+,D0 323 | mt_TurnOffVoices 324 | MOVE.W #$F,$DFF096 ; turn off voice DMAs 325 | CLR.W $DFF0A8 ; clear voice volumes 326 | CLR.W $DFF0B8 327 | CLR.W $DFF0C8 328 | CLR.W $DFF0D8 329 | RTS 330 | 331 | mt_RestoreEffects 332 | LEA mt_audchan1temp(PC),A0 333 | BSR.B reefsub 334 | LEA mt_audchan2temp(PC),A0 335 | BSR.B reefsub 336 | LEA mt_audchan3temp(PC),A0 337 | BSR.B reefsub 338 | LEA mt_audchan4temp(PC),A0 339 | reefsub CLR.B n_wavecontrol(A0) 340 | CLR.B n_glissfunk(A0) 341 | CLR.B n_finetune(A0) 342 | CLR.B n_loopcount(A0) 343 | RTS 344 | 345 | mt_IntMusic 346 | MOVEM.L D0-A6,-(SP) 347 | TST.B mt_Enable 348 | BEQ.W mt_exit 349 | ADDQ.B #1,mt_Counter 350 | MOVE.B mt_Counter(PC),D0 351 | CMP.B mt_Speed(PC),D0 352 | BLO.B mt_NoNewNote 353 | CLR.B mt_Counter 354 | TST.B mt_PattDelayTime2 355 | BEQ.B mt_GetNewNote 356 | BSR.B mt_NoNewAllChannels 357 | BRA.W mt_dskip 358 | 359 | mt_NoNewNote 360 | BSR.B mt_NoNewAllChannels 361 | BRA.W mt_NoNewPositionYet 362 | 363 | mt_NoNewAllChannels 364 | LEA mt_audchan1temp(PC),A6 365 | LEA $DFF0A0,A5 366 | BSR.W mt_CheckEffects 367 | LEA mt_audchan2temp(PC),A6 368 | LEA $DFF0B0,A5 369 | BSR.W mt_CheckEffects 370 | LEA mt_audchan3temp(PC),A6 371 | LEA $DFF0C0,A5 372 | BSR.W mt_CheckEffects 373 | LEA mt_audchan4temp(PC),A6 374 | LEA $DFF0D0,A5 375 | BRA.W mt_CheckEffects 376 | 377 | mt_GetNewNote 378 | ; Setup pattern pointer 379 | MOVE.L mt_SongDataPtr(PC),A0 380 | LEA 952(A0),A1 ;pattpo 381 | LEA 1084(A0),A0 ;patterndata 382 | MOVEQ #0,D0 383 | MOVE.B mt_SongPos(PC),D0 384 | MOVEQ #0,D1 385 | MOVE.B (A1,D0.W),D1 386 | LSL.L #8,D1 387 | LSL.L #2,D1 388 | MOVEQ #0,D0 389 | MOVE.W mt_PatternPos(PC),D0 390 | ADD.L D0,D1 391 | ADD.L D1,A0 392 | MOVE.L A0,mt_PatternPtr 393 | 394 | CLR.W mt_DMACONtemp 395 | 396 | LEA $DFF0A0,A5 397 | LEA mt_audchan1temp(PC),A6 398 | BSR.B mt_PlayVoice 399 | MOVEQ #0,D0 400 | MOVE.B n_volume(A6),D0 401 | MOVE.W D0,8(A5) 402 | 403 | LEA $DFF0B0,A5 404 | LEA mt_audchan2temp(PC),A6 405 | BSR.B mt_PlayVoice 406 | MOVEQ #0,D0 407 | MOVE.B n_volume(A6),D0 408 | MOVE.W D0,8(A5) 409 | 410 | LEA $DFF0C0,A5 411 | LEA mt_audchan3temp(PC),A6 412 | BSR.B mt_PlayVoice 413 | MOVEQ #0,D0 414 | MOVE.B n_volume(A6),D0 415 | MOVE.W D0,8(A5) 416 | 417 | LEA $DFF0D0,A5 418 | LEA mt_audchan4temp(PC),A6 419 | BSR.B mt_PlayVoice 420 | MOVEQ #0,D0 421 | MOVE.B n_volume(A6),D0 422 | MOVE.W D0,8(A5) 423 | 424 | BRA.W mt_SetDMA 425 | 426 | mt_PlayVoice 427 | TST.L (A6) 428 | BNE.B mt_plvskip 429 | BSR.W mt_PerNop 430 | mt_plvskip 431 | MOVE.L mt_PatternPtr(PC),A0 432 | MOVE.L (A0)+,(A6) ; Read note from pattern 433 | MOVE.L A0,mt_PatternPtr 434 | 435 | MOVEQ #0,D2 436 | MOVE.B n_cmd(A6),D2 ; Get lower 4 bits of instrument 437 | AND.B #$F0,D2 438 | LSR.B #4,D2 439 | MOVE.B (A6),D0 ; Get higher 4 bits of instrument 440 | AND.B #$F0,D0 441 | OR.B D0,D2 442 | BEQ.W mt_SetRegisters ; Instrument was zero 443 | 444 | LEA mt_SampleStarts(PC),A1 445 | MOVE.L mt_SampleStructPtr(PC),A3 446 | 447 | MOVE D2,D4 448 | SUBQ.L #1,D2 449 | LSL.L #2,D2 450 | MULU.W #30,D4 451 | MOVE.L (A1,D2.L),n_start(A6) 452 | MOVE.W (A3,D4.L),n_length(A6) 453 | 454 | MOVEQ #0,D0 455 | MOVE.B 2(A3,D4.L),D0 456 | AND.B #$0F,D0 457 | MOVE.B D0,n_finetune(A6) 458 | ; ---------------------------------- 459 | LSL.B #2,D0 ; update n_peroffset 460 | LEA mt_ftunePerTab(PC),A4 461 | MOVE.L (A4,D0.W),n_peroffset(A6) 462 | ; ---------------------------------- 463 | MOVEQ #0,D3 464 | MOVE.B 3(A3,D4.L),n_volume(A6) 465 | MOVE.W 4(A3,D4.L),D3 ; Get repeat 466 | BEQ.B mt_NoLoop 467 | MOVE.L n_start(A6),D2 ; Get start 468 | ADD.L D3,D3 469 | ADD.L D3,D2 ; Add repeat 470 | MOVE.L D2,n_loopstart(A6) 471 | MOVE.L D2,n_wavestart(A6) 472 | MOVE.W 4(A3,D4.L),D0 ; Get repeat 473 | ADD.W 6(A3,D4.L),D0 ; Add replen 474 | MOVE.W D0,n_length(A6) 475 | MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen 476 | BRA.B mt_SetRegisters 477 | 478 | mt_NoLoop 479 | MOVE.L n_start(A6),D2 480 | ADD.L D3,D2 481 | MOVE.L D2,n_loopstart(A6) 482 | MOVE.L D2,n_wavestart(A6) 483 | MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen 484 | mt_SetRegisters 485 | MOVE.W (A6),D0 486 | AND.W #$0FFF,D0 487 | BEQ.W mt_CheckMoreEffects ; If no note 488 | MOVE.W 2(A6),D0 489 | AND.W #$FF0,D0 490 | CMP.W #$E50,D0 ; finetune 491 | BEQ.B mt_DoSetFineTune 492 | MOVE.B 2(A6),D0 493 | AND.B #$0F,D0 494 | CMP.B #3,D0 ; TonePortamento 495 | BEQ.B mt_ChkTonePorta 496 | CMP.B #5,D0 ; TonePortamento + VolSlide 497 | BEQ.B mt_ChkTonePorta 498 | CMP.B #9,D0 ; Sample Offset 499 | BNE.B mt_SetPeriod 500 | BSR.W mt_CheckMoreEffects 501 | BRA.B mt_SetPeriod 502 | 503 | mt_DoSetFineTune 504 | BSR.W mt_SetFineTune 505 | BRA.B mt_SetPeriod 506 | 507 | mt_ChkTonePorta 508 | BSR.W mt_SetTonePorta 509 | BRA.W mt_CheckMoreEffects 510 | 511 | mt_SetPeriod 512 | MOVE.W (A6),D1 513 | AND.W #$0FFF,D1 514 | LEA mt_PeriodTable(PC),A1 515 | MOVEQ #0,D0 516 | MOVEQ #37-1,D7 517 | mt_ftuloop 518 | CMP.W (A1,D0.W),D1 519 | BHS.B mt_ftufound 520 | ADDQ.W #2,D0 521 | DBRA D7,mt_ftuloop 522 | mt_ftufound 523 | MOVE.L n_peroffset(A6),A1 524 | MOVE.W (A1,D0.W),n_period(A6) 525 | 526 | MOVE.W 2(A6),D0 527 | AND.W #$0FF0,D0 528 | CMP.W #$0ED0,D0 ; Notedelay 529 | BEQ.W mt_CheckMoreEffects 530 | 531 | MOVE.W n_dmabit(A6),$DFF096 532 | BTST #2,n_wavecontrol(A6) 533 | BNE.B mt_vibnoc 534 | CLR.B n_vibratopos(A6) 535 | mt_vibnoc 536 | BTST #6,n_wavecontrol(A6) 537 | BNE.B mt_trenoc 538 | CLR.B n_tremolopos(A6) 539 | mt_trenoc 540 | MOVE.W n_length(A6),4(A5) ; Set length 541 | MOVE.L n_start(A6),(A5) ; Set start 542 | BNE.B mt_sdmaskp 543 | CLR.L n_loopstart(A6) 544 | MOVEQ #1,D0 545 | MOVE.W D0,4(A5) 546 | MOVE.W D0,n_replen(A6) 547 | mt_sdmaskp 548 | MOVE.W n_period(A6),D0 549 | MOVE.W D0,6(A5) ; Set period 550 | MOVE.W n_dmabit(A6),D0 551 | OR.W D0,mt_DMACONtemp 552 | BRA.W mt_CheckMoreEffects 553 | 554 | mt_SetDMA 555 | ; scanline-wait (wait before starting Paula DMA) 556 | LEA $DFF006,A0 557 | MOVEQ #7-1,D1 558 | lineloop1 559 | MOVE.B (A0),D0 560 | waiteol1 561 | CMP.B (A0),D0 562 | BEQ.B waiteol1 563 | DBRA D1,lineloop1 564 | 565 | MOVE.W mt_DMACONtemp(PC),D0 566 | OR.W #$8000,D0 ; Set bits 567 | MOVE.W D0,$DFF096 568 | 569 | ; scanline-wait (wait for Paula DMA to latch) 570 | MOVEQ #7-1,D1 571 | lineloop2 572 | MOVE.B (A0),D0 573 | waiteol2 574 | CMP.B (A0),D0 575 | BEQ.B waiteol2 576 | DBRA D1,lineloop2 577 | 578 | LEA $DFF000,A5 579 | LEA mt_audchan4temp(PC),A6 580 | MOVE.L n_loopstart(A6),$D0(A5) 581 | MOVE.W n_replen(A6),$D4(A5) 582 | LEA mt_audchan3temp(PC),A6 583 | MOVE.L n_loopstart(A6),$C0(A5) 584 | MOVE.W n_replen(A6),$C4(A5) 585 | LEA mt_audchan2temp(PC),A6 586 | MOVE.L n_loopstart(A6),$B0(A5) 587 | MOVE.W n_replen(A6),$B4(A5) 588 | LEA mt_audchan1temp(PC),A6 589 | MOVE.L n_loopstart(A6),$A0(A5) 590 | MOVE.W n_replen(A6),$A4(A5) 591 | 592 | mt_dskip 593 | ADD.W #16,mt_PatternPos 594 | MOVE.B mt_PattDelayTime(PC),D0 595 | BEQ.B mt_dskpc 596 | MOVE.B D0,mt_PattDelayTime2 597 | CLR.B mt_PattDelayTime 598 | mt_dskpc 599 | TST.B mt_PattDelayTime2 600 | BEQ.B mt_dskpa 601 | SUBQ.B #1,mt_PattDelayTime2 602 | BEQ.B mt_dskpa 603 | SUB.W #16,mt_PatternPos 604 | mt_dskpa 605 | TST.B mt_PBreakFlag 606 | BEQ.B mt_nnpysk 607 | SF mt_PBreakFlag 608 | MOVEQ #0,D0 609 | MOVE.B mt_PBreakPos(PC),D0 610 | LSL.W #4,D0 611 | MOVE.W D0,mt_PatternPos 612 | CLR.B mt_PBreakPos 613 | mt_nnpysk 614 | CMP.W #1024,mt_PatternPos 615 | BLO.B mt_NoNewPositionYet 616 | mt_NextPosition 617 | MOVEQ #0,D0 618 | MOVE.B mt_PBreakPos(PC),D0 619 | LSL.W #4,D0 620 | MOVE.W D0,mt_PatternPos 621 | CLR.B mt_PBreakPos 622 | CLR.B mt_PosJumpFlag 623 | ADDQ.B #1,mt_SongPos 624 | AND.B #127,mt_SongPos 625 | MOVE.B mt_SongPos(PC),D1 626 | CMP.B mt_SongLength(PC),D1 627 | BLO.B mt_NoNewPositionYet 628 | CLR.B mt_SongPos 629 | 630 | mt_NoNewPositionYet 631 | TST.B mt_PosJumpFlag 632 | BNE.B mt_NextPosition 633 | mt_exit MOVEM.L (SP)+,D0-A6 634 | RTS 635 | 636 | mt_CheckEffects 637 | BSR.B mt_chkefx2 638 | MOVEQ #0,D0 639 | MOVE.B n_volume(A6),D0 640 | MOVE.W D0,8(A5) 641 | RTS 642 | 643 | CNOP 0,4 644 | mt_JumpList1 645 | dc.l mt_Arpeggio ; 0xy (Arpeggio) 646 | dc.l mt_PortaUp ; 1xx (Portamento Up) 647 | dc.l mt_PortaDown ; 2xx (Portamento Down) 648 | dc.l mt_TonePortamento ; 3xx (Tone Portamento) 649 | dc.l mt_Vibrato ; 4xy (Vibrato) 650 | dc.l mt_TonePlusVolSlide ; 5xy (Tone Portamento + Volume Slide) 651 | dc.l mt_VibratoPlusVolSlide ; 6xy (Vibrato + Volume Slide) 652 | dc.l SetBack ; 7 - not used here 653 | dc.l SetBack ; 8 - unused! 654 | dc.l SetBack ; 9 - not used here 655 | dc.l SetBack ; A - not used here 656 | dc.l SetBack ; B - not used here 657 | dc.l SetBack ; C - not used here 658 | dc.l SetBack ; D - not used here 659 | dc.l mt_E_Commands ; Exy (Extended Commands) 660 | dc.l SetBack ; F - not used here 661 | 662 | mt_chkefx2 663 | BSR.W mt_UpdateFunk 664 | MOVE.W n_cmd(A6),D0 665 | AND.W #$0FFF,D0 666 | BEQ.B mt_Return3 667 | MOVEQ #0,D0 668 | MOVE.B n_cmd(A6),D0 669 | AND.B #$0F,D0 670 | MOVE.W D0,D1 671 | LSL.B #2,D1 672 | MOVE.L mt_JumpList1(PC,D1.W),A4 673 | JMP (A4) ; every efx has RTS at the end, this is safe 674 | 675 | SetBack MOVE.W n_period(A6),6(A5) 676 | CMP.B #7,D0 677 | BEQ.W mt_Tremolo 678 | CMP.B #$A,D0 679 | BEQ.W mt_VolumeSlide 680 | mt_Return3 681 | RTS 682 | 683 | mt_PerNop 684 | MOVE.W n_period(A6),6(A5) 685 | RTS 686 | 687 | ; DIV -> LUT optimization. DIVU is 140+ cycles on a 68000. 688 | mt_ArpTab 689 | dc.b 0,1,2,0,1,2,0,1 690 | dc.b 2,0,1,2,0,1,2,0 691 | dc.b 1,2,0,1,2,0,1,2 692 | dc.b 0,1,2,0,1,2,0,1 693 | 694 | mt_Arpeggio 695 | MOVEQ #0,D0 696 | MOVE.B mt_Counter(PC),D0 697 | AND.B #$1F,D0 ; just in case 698 | MOVE.B mt_ArpTab(PC,D0.W),D0 699 | CMP.B #1,D0 700 | BEQ.B mt_Arpeggio1 701 | CMP.B #2,D0 702 | BEQ.B mt_Arpeggio2 703 | mt_Arpeggio0 704 | MOVE.W n_period(A6),6(A5) 705 | RTS 706 | 707 | mt_Arpeggio1 708 | MOVEQ #0,D0 709 | MOVE.B n_cmdlo(A6),D0 710 | LSR.B #4,D0 711 | BRA.B mt_ArpeggioFind 712 | 713 | mt_Arpeggio2 714 | MOVEQ #0,D0 715 | MOVE.B n_cmdlo(A6),D0 716 | AND.B #15,D0 717 | mt_ArpeggioFind 718 | ADD.W D0,D0 719 | MOVE.L n_peroffset(A6),A0 720 | MOVEQ #0,D1 721 | MOVE.W n_period(A6),D1 722 | MOVEQ #37-1,D3 723 | mt_arploop 724 | CMP.W (A0)+,D1 725 | BHS.B mt_ArpeggioFound 726 | DBRA D3,mt_arploop 727 | RTS 728 | 729 | mt_ArpeggioFound 730 | MOVE.W -2(A0,D0.W),6(A5) 731 | RTS 732 | 733 | mt_FinePortaUp 734 | TST.B mt_Counter 735 | BNE.W mt_Return3 736 | MOVE.B #$0F,mt_LowMask 737 | mt_PortaUp 738 | MOVEQ #0,D0 739 | MOVE.B n_cmdlo(A6),D0 740 | AND.B mt_LowMask(PC),D0 741 | MOVE.B #$FF,mt_LowMask 742 | SUB.W D0,n_period(A6) 743 | MOVE.W n_period(A6),D0 744 | AND.W #$0FFF,D0 745 | CMP.W #113,D0 746 | BPL.B mt_PortaUskip 747 | AND.W #$F000,n_period(A6) 748 | OR.W #113,n_period(A6) 749 | mt_PortaUskip 750 | MOVE.W n_period(A6),D0 751 | AND.W #$0FFF,D0 752 | MOVE.W D0,6(A5) 753 | RTS 754 | 755 | mt_FinePortaDown 756 | TST.B mt_Counter 757 | BNE.W mt_Return3 758 | MOVE.B #$0F,mt_LowMask 759 | mt_PortaDown 760 | CLR.W D0 761 | MOVE.B n_cmdlo(A6),D0 762 | AND.B mt_LowMask(PC),D0 763 | MOVE.B #$FF,mt_LowMask 764 | ADD.W D0,n_period(A6) 765 | MOVE.W n_period(A6),D0 766 | AND.W #$0FFF,D0 767 | CMP.W #856,D0 768 | BMI.B mt_PortaDskip 769 | AND.W #$F000,n_period(A6) 770 | OR.W #856,n_period(A6) 771 | mt_PortaDskip 772 | MOVE.W n_period(A6),D0 773 | AND.W #$0FFF,D0 774 | MOVE.W D0,6(A5) 775 | RTS 776 | 777 | mt_SetTonePorta 778 | MOVE.W (A6),D2 779 | AND.W #$0FFF,D2 780 | MOVE.L n_peroffset(A6),A4 781 | MOVEQ #0,D0 782 | mt_StpLoop 783 | CMP.W (A4,D0.W),D2 784 | BHS.B mt_StpFound 785 | ADDQ.W #2,D0 786 | CMP.W #37*2,D0 787 | BLO.B mt_StpLoop 788 | MOVEQ #35*2,D0 789 | mt_StpFound 790 | MOVE.B n_finetune(A6),D2 791 | AND.B #8,D2 792 | BEQ.B mt_StpGoss 793 | TST.W D0 794 | BEQ.B mt_StpGoss 795 | SUBQ.W #2,D0 796 | mt_StpGoss 797 | MOVE.W (A4,D0.W),D2 798 | MOVE.W D2,n_wantedperiod(A6) 799 | MOVE.W n_period(A6),D0 800 | CLR.B n_toneportdirec(A6) 801 | CMP.W D0,D2 802 | BEQ.B mt_ClearTonePorta 803 | BGE.W mt_Return3 804 | MOVE.B #1,n_toneportdirec(A6) 805 | RTS 806 | 807 | mt_ClearTonePorta 808 | CLR.W n_wantedperiod(A6) 809 | RTS 810 | 811 | mt_TonePortamento 812 | MOVE.B n_cmdlo(A6),D0 813 | BEQ.B mt_TonePortNoChange 814 | MOVE.B D0,n_toneportspeed(A6) 815 | CLR.B n_cmdlo(A6) 816 | mt_TonePortNoChange 817 | TST.W n_wantedperiod(A6) 818 | BEQ.W mt_Return3 819 | MOVEQ #0,D0 820 | MOVE.B n_toneportspeed(A6),D0 821 | TST.B n_toneportdirec(A6) 822 | BNE.B mt_TonePortaUp 823 | mt_TonePortaDown 824 | ADD.W D0,n_period(A6) 825 | MOVE.W n_wantedperiod(A6),D0 826 | CMP.W n_period(A6),D0 827 | BGT.B mt_TonePortaSetPer 828 | MOVE.W n_wantedperiod(A6),n_period(A6) 829 | CLR.W n_wantedperiod(A6) 830 | BRA.B mt_TonePortaSetPer 831 | 832 | mt_TonePortaUp 833 | SUB.W D0,n_period(A6) 834 | MOVE.W n_wantedperiod(A6),D0 835 | CMP.W n_period(A6),D0 836 | BLT.B mt_TonePortaSetPer 837 | MOVE.W n_wantedperiod(A6),n_period(A6) 838 | CLR.W n_wantedperiod(A6) 839 | 840 | mt_TonePortaSetPer 841 | MOVE.W n_period(A6),D2 842 | MOVE.B n_glissfunk(A6),D0 843 | AND.B #$0F,D0 844 | BEQ.B mt_GlissSkip 845 | MOVE.L n_peroffset(A6),A0 846 | MOVEQ #0,D0 847 | mt_GlissLoop 848 | CMP.W (A0,D0.W),D2 849 | BHS.B mt_GlissFound 850 | ADDQ.W #2,D0 851 | CMP.W #37*2,D0 852 | BLO.B mt_GlissLoop 853 | MOVEQ #35*2,D0 854 | mt_GlissFound 855 | MOVE.W (A0,D0.W),D2 856 | mt_GlissSkip 857 | MOVE.W D2,6(A5) ; Set period 858 | RTS 859 | 860 | mt_Vibrato 861 | MOVE.B n_cmdlo(A6),D0 862 | BEQ.B mt_Vibrato2 863 | MOVE.B n_vibratocmd(A6),D2 864 | AND.B #$0F,D0 865 | BEQ.B mt_vibskip 866 | AND.B #$F0,D2 867 | OR.B D0,D2 868 | mt_vibskip 869 | MOVE.B n_cmdlo(A6),D0 870 | AND.B #$F0,D0 871 | BEQ.B mt_vibskip2 872 | AND.B #$0F,D2 873 | OR.B D0,D2 874 | mt_vibskip2 875 | MOVE.B D2,n_vibratocmd(A6) 876 | mt_Vibrato2 877 | MOVE.B n_vibratopos(A6),D0 878 | LEA mt_VibratoTable(PC),A4 879 | LSR.W #2,D0 880 | AND.W #$001F,D0 881 | MOVEQ #0,D2 882 | MOVE.B n_wavecontrol(A6),D2 883 | AND.B #3,D2 884 | BEQ.B mt_vib_sine 885 | LSL.B #3,D0 886 | CMP.B #1,D2 887 | BEQ.B mt_vib_rampdown 888 | MOVE.B #255,D2 889 | BRA.B mt_vib_set 890 | mt_vib_rampdown 891 | TST.B n_vibratopos(A6) 892 | BPL.B mt_vib_rampdown2 893 | MOVE.B #255,D2 894 | SUB.B D0,D2 895 | BRA.B mt_vib_set 896 | mt_vib_rampdown2 897 | MOVE.B D0,D2 898 | BRA.B mt_vib_set 899 | mt_vib_sine 900 | MOVE.B (A4,D0.W),D2 901 | mt_vib_set 902 | MOVE.B n_vibratocmd(A6),D0 903 | AND.W #15,D0 904 | MULU.W D0,D2 905 | LSR.W #7,D2 906 | MOVE.W n_period(A6),D0 907 | TST.B n_vibratopos(A6) 908 | BMI.B mt_VibratoNeg 909 | ADD.W D2,D0 910 | BRA.B mt_Vibrato3 911 | mt_VibratoNeg 912 | SUB.W D2,D0 913 | mt_Vibrato3 914 | MOVE.W D0,6(A5) 915 | MOVE.B n_vibratocmd(A6),D0 916 | LSR.W #2,D0 917 | AND.W #$003C,D0 918 | ADD.B D0,n_vibratopos(A6) 919 | RTS 920 | 921 | mt_TonePlusVolSlide 922 | BSR.W mt_TonePortNoChange 923 | BRA.W mt_VolumeSlide 924 | 925 | mt_VibratoPlusVolSlide 926 | BSR.B mt_Vibrato2 927 | BRA.W mt_VolumeSlide 928 | 929 | mt_Tremolo 930 | MOVE.B n_cmdlo(A6),D0 931 | BEQ.B mt_Tremolo2 932 | MOVE.B n_tremolocmd(A6),D2 933 | AND.B #$0F,D0 934 | BEQ.B mt_treskip 935 | AND.B #$F0,D2 936 | OR.B D0,D2 937 | mt_treskip 938 | MOVE.B n_cmdlo(A6),D0 939 | AND.B #$F0,D0 940 | BEQ.B mt_treskip2 941 | AND.B #$0F,D2 942 | OR.B D0,D2 943 | mt_treskip2 944 | MOVE.B D2,n_tremolocmd(A6) 945 | mt_Tremolo2 946 | MOVE.B n_tremolopos(A6),D0 947 | LEA mt_VibratoTable(PC),A4 948 | LSR.W #2,D0 949 | AND.W #$001F,D0 950 | MOVEQ #0,D2 951 | MOVE.B n_wavecontrol(A6),D2 952 | LSR.B #4,D2 953 | AND.B #3,D2 954 | BEQ.B mt_tre_sine 955 | LSL.B #3,D0 956 | CMP.B #1,D2 957 | BEQ.B mt_tre_rampdown 958 | MOVE.B #255,D2 959 | BRA.B mt_tre_set 960 | mt_tre_rampdown 961 | TST.B n_vibratopos(A6) 962 | BPL.B mt_tre_rampdown2 963 | MOVE.B #255,D2 964 | SUB.B D0,D2 965 | BRA.B mt_tre_set 966 | mt_tre_rampdown2 967 | MOVE.B D0,D2 968 | BRA.B mt_tre_set 969 | mt_tre_sine 970 | MOVE.B (A4,D0.W),D2 971 | mt_tre_set 972 | MOVE.B n_tremolocmd(A6),D0 973 | AND.W #15,D0 974 | MULU.W D0,D2 975 | LSR.W #6,D2 976 | MOVEQ #0,D0 977 | MOVE.B n_volume(A6),D0 978 | TST.B n_tremolopos(A6) 979 | BMI.B mt_TremoloNeg 980 | ADD.W D2,D0 981 | BRA.B mt_Tremolo3 982 | mt_TremoloNeg 983 | SUB.W D2,D0 984 | mt_Tremolo3 985 | BPL.B mt_TremoloSkip 986 | CLR.W D0 987 | mt_TremoloSkip 988 | CMP.W #64,D0 989 | BLS.B mt_TremoloOk 990 | MOVE.W #64,D0 991 | mt_TremoloOk 992 | MOVE.W D0,8(A5) 993 | MOVE.B n_tremolocmd(A6),D0 994 | LSR.W #2,D0 995 | AND.W #$003C,D0 996 | ADD.B D0,n_tremolopos(A6) 997 | ADDQ.L #4,SP ; hack to not set volume in mt_CheckEffects 998 | RTS 999 | 1000 | mt_SampleOffset 1001 | MOVEQ #0,D0 1002 | MOVE.B n_cmdlo(A6),D0 1003 | BEQ.B mt_sononew 1004 | MOVE.B D0,n_sampleoffset(A6) 1005 | mt_sononew 1006 | MOVE.B n_sampleoffset(A6),D0 1007 | LSL.W #7,D0 1008 | CMP.W n_length(A6),D0 1009 | BHS.B mt_sofskip 1010 | SUB.W D0,n_length(A6) 1011 | ADD.W D0,D0 1012 | ADD.L D0,n_start(A6) 1013 | RTS 1014 | mt_sofskip 1015 | MOVE.W #1,n_length(A6) 1016 | RTS 1017 | 1018 | mt_VolumeSlide 1019 | MOVEQ #0,D0 1020 | MOVE.B n_cmdlo(A6),D0 1021 | LSR.B #4,D0 1022 | BEQ.B mt_VolSlideDown 1023 | mt_VolSlideUp 1024 | ADD.B D0,n_volume(A6) 1025 | CMP.B #64,n_volume(A6) 1026 | BMI.B mt_vsuskip 1027 | MOVE.B #64,n_volume(A6) 1028 | mt_vsuskip 1029 | RTS 1030 | 1031 | mt_VolSlideDown 1032 | MOVEQ #0,D0 1033 | MOVE.B n_cmdlo(A6),D0 1034 | AND.B #$0F,D0 1035 | mt_VolSlideDown2 1036 | SUB.B D0,n_volume(A6) 1037 | BPL.B mt_vsdskip 1038 | CLR.B n_volume(A6) 1039 | mt_vsdskip 1040 | RTS 1041 | 1042 | mt_PositionJump 1043 | MOVE.B n_cmdlo(A6),D0 1044 | SUBQ.B #1,D0 1045 | MOVE.B D0,mt_SongPos 1046 | mt_pj2 CLR.B mt_PBreakPos 1047 | ST mt_PosJumpFlag 1048 | RTS 1049 | 1050 | mt_VolumeChange 1051 | MOVEQ #0,D0 1052 | MOVE.B n_cmdlo(A6),D0 1053 | CMP.B #64,D0 1054 | BLS.B mt_VolumeOk 1055 | MOVEQ #64,D0 1056 | mt_VolumeOk 1057 | MOVE.B D0,n_volume(A6) 1058 | RTS 1059 | 1060 | mt_PatternBreak 1061 | MOVEQ #0,D0 1062 | MOVE.B n_cmdlo(A6),D0 1063 | MOVE.L D0,D2 1064 | LSR.B #4,D0 1065 | MULU.W #10,D0 1066 | AND.B #$0F,D2 1067 | ADD.B D2,D0 1068 | CMP.B #63,D0 1069 | BHI.B mt_pj2 1070 | MOVE.B D0,mt_PBreakPos 1071 | ST mt_PosJumpFlag 1072 | RTS 1073 | 1074 | mt_SetSpeed 1075 | MOVEQ #0,D0 1076 | MOVE.B 3(A6),D0 1077 | BEQ.W mt_end 1078 | CMP.B #32,D0 1079 | BHS.W SetTempo 1080 | CLR.B mt_Counter 1081 | MOVE.B D0,mt_Speed 1082 | RTS 1083 | 1084 | CNOP 0,4 1085 | mt_JumpList2 1086 | dc.l mt_PerNop ; 0 - not used 1087 | dc.l mt_PerNop ; 1 - not used 1088 | dc.l mt_PerNop ; 2 - not used 1089 | dc.l mt_PerNop ; 3 - not used 1090 | dc.l mt_PerNop ; 4 - not used 1091 | dc.l mt_PerNop ; 5 - not used 1092 | dc.l mt_PerNop ; 6 - not used 1093 | dc.l mt_PerNop ; 7 - not used 1094 | dc.l mt_PerNop ; 8 - not used 1095 | dc.l mt_SampleOffset ; 9xx (Set Sample Offset) 1096 | dc.l mt_PerNop ; A - not used 1097 | dc.l mt_PositionJump ; Bxx (Position Jump) 1098 | dc.l mt_VolumeChange ; Cxx (Set Volume) 1099 | dc.l mt_PatternBreak ; Dxx (Pattern Break) 1100 | dc.l mt_E_Commands ; Exy (Extended Commands) 1101 | dc.l mt_SetSpeed ; Fxx (Set Speed) 1102 | 1103 | mt_CheckMoreEffects 1104 | MOVEQ #0,D0 1105 | MOVE.B 2(A6),D0 1106 | AND.B #$0F,D0 1107 | LSL.B #2,D0 1108 | MOVE.L mt_JumpList2(PC,D0.W),A4 1109 | JMP (A4) ; every efx has RTS at the end, this is safe 1110 | 1111 | CNOP 0,4 1112 | mt_E_JumpList 1113 | dc.l mt_FilterOnOff ; E0x (Set LED Filter) 1114 | dc.l mt_FinePortaUp ; E1x (Fine Portamento Up) 1115 | dc.l mt_FinePortaDown ; E2x (Fine Portamento Down) 1116 | dc.l mt_SetGlissControl ; E3x (Glissando/Funk Control) 1117 | dc.l mt_SetVibratoControl ; E4x (Vibrato Control) 1118 | dc.l mt_SetFineTune ; E5x (Set Finetune) 1119 | dc.l mt_JumpLoop ; E6x (Pattern Loop) 1120 | dc.l mt_SetTremoloControl ; E7x (Tremolo Control) 1121 | dc.l mt_KarplusStrong ; E8x (Karplus-Strong) 1122 | dc.l mt_RetrigNote ; E9x (Retrig Note) 1123 | dc.l mt_VolumeFineUp ; EAx (Fine Volume-Slide Up) 1124 | dc.l mt_VolumeFineDown ; EBx (Fine Volume-Slide Down) 1125 | dc.l mt_NoteCut ; ECx (Note Cut) 1126 | dc.l mt_NoteDelay ; EDx (Note Delay) 1127 | dc.l mt_PatternDelay ; EEx (Pattern Delay) 1128 | dc.l mt_FunkIt ; EFx (Invert Loop) 1129 | 1130 | mt_E_Commands 1131 | MOVEQ #0,D0 1132 | MOVE.B n_cmdlo(A6),D0 1133 | AND.B #$F0,D0 1134 | LSR.B #4-2,D0 1135 | MOVE.L mt_E_JumpList(PC,D0.W),A4 1136 | JMP (A4) ; every E-efx has RTS at the end, this is safe 1137 | 1138 | mt_FilterOnOff 1139 | TST.B mt_Counter 1140 | BNE.W mt_Return3 1141 | MOVE.B n_cmdlo(A6),D0 1142 | AND.B #1,D0 1143 | ADD.B D0,D0 1144 | AND.B #$FD,$BFE001 1145 | OR.B D0,$BFE001 1146 | RTS 1147 | 1148 | mt_SetGlissControl 1149 | MOVE.B n_cmdlo(A6),D0 1150 | AND.B #$0F,D0 1151 | AND.B #$F0,n_glissfunk(A6) 1152 | OR.B D0,n_glissfunk(A6) 1153 | RTS 1154 | 1155 | mt_SetVibratoControl 1156 | MOVE.B n_cmdlo(A6),D0 1157 | AND.B #$0F,D0 1158 | AND.B #$F0,n_wavecontrol(A6) 1159 | OR.B D0,n_wavecontrol(A6) 1160 | RTS 1161 | 1162 | mt_SetFineTune 1163 | MOVEQ #0,D0 1164 | MOVE.B n_cmdlo(A6),D0 1165 | AND.B #$0F,D0 1166 | MOVE.B D0,n_finetune(A6) 1167 | ; ---------------------------------- 1168 | LSL.B #2,D0 ; update n_peroffset 1169 | LEA mt_ftunePerTab(PC),A4 1170 | MOVE.L (A4,D0.W),n_peroffset(A6) 1171 | ; ---------------------------------- 1172 | RTS 1173 | 1174 | mt_JumpLoop 1175 | TST.B mt_Counter 1176 | BNE.W mt_Return3 1177 | MOVE.B n_cmdlo(A6),D0 1178 | AND.B #$0F,D0 1179 | BEQ.B mt_SetLoop 1180 | TST.B n_loopcount(A6) 1181 | BEQ.B mt_jumpcnt 1182 | SUBQ.B #1,n_loopcount(A6) 1183 | BEQ.W mt_Return3 1184 | mt_jmploop 1185 | MOVE.B n_pattpos(A6),mt_PBreakPos 1186 | ST mt_PBreakFlag 1187 | RTS 1188 | 1189 | mt_jumpcnt 1190 | MOVE.B D0,n_loopcount(A6) 1191 | BRA.B mt_jmploop 1192 | 1193 | mt_SetLoop 1194 | MOVE.W mt_PatternPos(PC),D0 1195 | LSR.W #4,D0 1196 | AND.B #63,D0 1197 | MOVE.B D0,n_pattpos(A6) 1198 | RTS 1199 | 1200 | mt_SetTremoloControl 1201 | MOVE.B n_cmdlo(A6),D0 1202 | AND.B #$0F,D0 1203 | LSL.B #4,D0 1204 | AND.B #$0F,n_wavecontrol(A6) 1205 | OR.B D0,n_wavecontrol(A6) 1206 | RTS 1207 | 1208 | mt_KarplusStrong 1209 | RTS 1210 | 1211 | mt_RetrigNote 1212 | MOVEQ #0,D0 1213 | MOVE.B n_cmdlo(A6),D0 1214 | AND.B #$0F,D0 1215 | BEQ.B mt_rtnend 1216 | MOVEQ #0,D1 1217 | MOVE.B mt_Counter(PC),D1 1218 | BNE.B mt_rtnskp 1219 | MOVE.W n_note(A6),D1 1220 | AND.W #$0FFF,D1 1221 | BNE.B mt_rtnend 1222 | MOVEQ #0,D1 1223 | MOVE.B mt_Counter(PC),D1 1224 | mt_rtnskp 1225 | AND.B #$1F,D1 ; just in case 1226 | LSL.W #5,D0 1227 | ADD.W D0,D1 1228 | MOVE.B mt_RetrigTab(PC,D1.W),D0 1229 | BNE.B mt_rtnend 1230 | mt_DoRetrig 1231 | MOVE.W n_dmabit(A6),$DFF096 ; Channel DMA off 1232 | MOVE.L n_start(A6),(A5) ; Set sampledata pointer 1233 | MOVE.W n_length(A6),4(A5) ; Set length 1234 | MOVE.W n_period(A6),6(A5) ; Set period 1235 | 1236 | ; scanline-wait (wait before starting Paula DMA) 1237 | LEA $DFF006,A0 1238 | MOVEQ #7-1,D1 1239 | lineloop3 1240 | MOVE.B (A0),D0 1241 | waiteol3 1242 | CMP.B (A0),D0 1243 | BEQ.B waiteol3 1244 | DBRA D1,lineloop3 1245 | 1246 | MOVE.W n_dmabit(A6),D0 1247 | BSET #15,D0 ; Set bits 1248 | MOVE.W D0,$DFF096 1249 | 1250 | ; scanline-wait (wait for Paula DMA to latch) 1251 | MOVEQ #7-1,D1 1252 | lineloop4 1253 | MOVE.B (A0),D0 1254 | waiteol4 1255 | CMP.B (A0),D0 1256 | BEQ.B waiteol4 1257 | DBRA D1,lineloop4 1258 | 1259 | MOVE.L n_loopstart(A6),(A5) 1260 | MOVE.W n_replen(A6),4(A5) 1261 | mt_rtnend 1262 | RTS 1263 | 1264 | ; DIV -> LUT optimization. Maybe a bit extreme, but DIVU is 140+ 1265 | ; cycles on a 68000. 1266 | mt_RetrigTab 1267 | dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1268 | dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1269 | dc.b 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 1270 | dc.b 0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1 1271 | dc.b 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1 1272 | dc.b 0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1 1273 | dc.b 0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1 1274 | dc.b 0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1 1275 | dc.b 0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1 1276 | dc.b 0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1 1277 | dc.b 0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1 1278 | dc.b 0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1 1279 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1 1280 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1 1281 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1 1282 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1 1283 | 1284 | mt_VolumeFineUp 1285 | TST.B mt_Counter 1286 | BNE.W mt_Return3 1287 | MOVEQ #0,D0 1288 | MOVE.B n_cmdlo(A6),D0 1289 | AND.B #$F,D0 1290 | BRA.W mt_VolSlideUp 1291 | 1292 | mt_VolumeFineDown 1293 | TST.B mt_Counter 1294 | BNE.W mt_Return3 1295 | MOVEQ #0,D0 1296 | MOVE.B n_cmdlo(A6),D0 1297 | AND.B #$0F,D0 1298 | BRA.W mt_VolSlideDown2 1299 | 1300 | mt_NoteCut 1301 | MOVEQ #0,D0 1302 | MOVE.B n_cmdlo(A6),D0 1303 | AND.B #$0F,D0 1304 | CMP.B mt_Counter(PC),D0 1305 | BNE.W mt_Return3 1306 | CLR.B n_volume(A6) 1307 | RTS 1308 | 1309 | mt_NoteDelay 1310 | MOVEQ #0,D0 1311 | MOVE.B n_cmdlo(A6),D0 1312 | AND.B #$0F,D0 1313 | CMP.B mt_Counter,D0 1314 | BNE.W mt_Return3 1315 | MOVE.W (A6),D0 1316 | AND.W #$0FFF,D0 1317 | BEQ.W mt_Return3 1318 | BRA.W mt_DoRetrig 1319 | 1320 | mt_PatternDelay 1321 | TST.B mt_Counter 1322 | BNE.W mt_Return3 1323 | MOVEQ #0,D0 1324 | MOVE.B n_cmdlo(A6),D0 1325 | AND.B #$0F,D0 1326 | TST.B mt_PattDelayTime2 1327 | BNE.W mt_Return3 1328 | ADDQ.B #1,D0 1329 | MOVE.B D0,mt_PattDelayTime 1330 | RTS 1331 | 1332 | mt_FunkIt 1333 | TST.B mt_Counter 1334 | BNE.W mt_Return3 1335 | MOVE.B n_cmdlo(A6),D0 1336 | AND.B #$0F,D0 1337 | LSL.B #4,D0 1338 | AND.B #$0F,n_glissfunk(A6) 1339 | OR.B D0,n_glissfunk(A6) 1340 | TST.B D0 1341 | BEQ.W mt_Return3 1342 | mt_UpdateFunk 1343 | MOVEQ #0,D0 1344 | MOVE.B n_glissfunk(A6),D0 1345 | LSR.B #4,D0 1346 | BEQ.B mt_funkend 1347 | LEA mt_FunkTable(PC),A0 1348 | MOVE.B (A0,D0.W),D0 1349 | ADD.B D0,n_funkoffset(A6) 1350 | BTST #7,n_funkoffset(A6) 1351 | BEQ.B mt_funkend 1352 | CLR.B n_funkoffset(A6) 1353 | MOVE.L n_wavestart(A6),A0 1354 | CMP.L #0,A0 1355 | BEQ.B mt_funkend 1356 | MOVE.L n_loopstart(A6),D0 1357 | MOVEQ #0,D1 1358 | MOVE.W n_replen(A6),D1 1359 | ADD.L D1,D0 1360 | ADD.L D1,D0 1361 | ADDQ.L #1,A0 1362 | CMP.L D0,A0 1363 | BLO.B mt_funkok 1364 | MOVE.L n_loopstart(A6),A0 1365 | mt_funkok 1366 | MOVE.L A0,n_wavestart(A6) 1367 | MOVEQ #-1,D0 1368 | SUB.B (A0),D0 1369 | MOVE.B D0,(A0) 1370 | mt_funkend 1371 | RTS 1372 | 1373 | mt_FunkTable 1374 | dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128 1375 | 1376 | mt_VibratoTable 1377 | dc.b 0, 24, 49, 74, 97,120,141,161 1378 | dc.b 180,197,212,224,235,244,250,253 1379 | dc.b 255,253,250,244,235,224,212,197 1380 | dc.b 180,161,141,120, 97, 74, 49, 24 1381 | 1382 | ; this LUT prevents MULU for getting correct period section 1383 | CNOP 0,4 1384 | mt_ftunePerTab 1385 | dc.l mt_ftune0,mt_ftune1,mt_ftune2,mt_ftune3 1386 | dc.l mt_ftune4,mt_ftune5,mt_ftune6,mt_ftune7 1387 | dc.l mt_ftune8,mt_ftune9,mt_ftuneA,mt_ftuneB 1388 | dc.l mt_ftuneC,mt_ftuneD,mt_ftuneE,mt_ftuneF 1389 | 1390 | mt_PeriodTable 1391 | ; Tuning 0, Normal 1392 | mt_ftune0 1393 | dc.w 856,808,762,720,678,640,604,570,538,508,480,453 1394 | dc.w 428,404,381,360,339,320,302,285,269,254,240,226 1395 | dc.w 214,202,190,180,170,160,151,143,135,127,120,113,0 1396 | ; Tuning 1 1397 | mt_ftune1 1398 | dc.w 850,802,757,715,674,637,601,567,535,505,477,450 1399 | dc.w 425,401,379,357,337,318,300,284,268,253,239,225 1400 | dc.w 213,201,189,179,169,159,150,142,134,126,119,113,0 1401 | ; Tuning 2 1402 | mt_ftune2 1403 | dc.w 844,796,752,709,670,632,597,563,532,502,474,447 1404 | dc.w 422,398,376,355,335,316,298,282,266,251,237,224 1405 | dc.w 211,199,188,177,167,158,149,141,133,125,118,112,0 1406 | ; Tuning 3 1407 | mt_ftune3 1408 | dc.w 838,791,746,704,665,628,592,559,528,498,470,444 1409 | dc.w 419,395,373,352,332,314,296,280,264,249,235,222 1410 | dc.w 209,198,187,176,166,157,148,140,132,125,118,111,0 1411 | ; Tuning 4 1412 | mt_ftune4 1413 | dc.w 832,785,741,699,660,623,588,555,524,495,467,441 1414 | dc.w 416,392,370,350,330,312,294,278,262,247,233,220 1415 | dc.w 208,196,185,175,165,156,147,139,131,124,117,110,0 1416 | ; Tuning 5 1417 | mt_ftune5 1418 | dc.w 826,779,736,694,655,619,584,551,520,491,463,437 1419 | dc.w 413,390,368,347,328,309,292,276,260,245,232,219 1420 | dc.w 206,195,184,174,164,155,146,138,130,123,116,109,0 1421 | ; Tuning 6 1422 | mt_ftune6 1423 | dc.w 820,774,730,689,651,614,580,547,516,487,460,434 1424 | dc.w 410,387,365,345,325,307,290,274,258,244,230,217 1425 | dc.w 205,193,183,172,163,154,145,137,129,122,115,109,0 1426 | ; Tuning 7 1427 | mt_ftune7 1428 | dc.w 814,768,725,684,646,610,575,543,513,484,457,431 1429 | dc.w 407,384,363,342,323,305,288,272,256,242,228,216 1430 | dc.w 204,192,181,171,161,152,144,136,128,121,114,108,0 1431 | ; Tuning -8 1432 | mt_ftune8 1433 | dc.w 907,856,808,762,720,678,640,604,570,538,508,480 1434 | dc.w 453,428,404,381,360,339,320,302,285,269,254,240 1435 | dc.w 226,214,202,190,180,170,160,151,143,135,127,120,0 1436 | ; Tuning -7 1437 | mt_ftune9 1438 | dc.w 900,850,802,757,715,675,636,601,567,535,505,477 1439 | dc.w 450,425,401,379,357,337,318,300,284,268,253,238 1440 | dc.w 225,212,200,189,179,169,159,150,142,134,126,119,0 1441 | ; Tuning -6 1442 | mt_ftuneA 1443 | dc.w 894,844,796,752,709,670,632,597,563,532,502,474 1444 | dc.w 447,422,398,376,355,335,316,298,282,266,251,237 1445 | dc.w 223,211,199,188,177,167,158,149,141,133,125,118,0 1446 | ; Tuning -5 1447 | mt_ftuneB 1448 | dc.w 887,838,791,746,704,665,628,592,559,528,498,470 1449 | dc.w 444,419,395,373,352,332,314,296,280,264,249,235 1450 | dc.w 222,209,198,187,176,166,157,148,140,132,125,118,0 1451 | ; Tuning -4 1452 | mt_ftuneC 1453 | dc.w 881,832,785,741,699,660,623,588,555,524,494,467 1454 | dc.w 441,416,392,370,350,330,312,294,278,262,247,233 1455 | dc.w 220,208,196,185,175,165,156,147,139,131,123,117,0 1456 | ; Tuning -3 1457 | mt_ftuneD 1458 | dc.w 875,826,779,736,694,655,619,584,551,520,491,463 1459 | dc.w 437,413,390,368,347,328,309,292,276,260,245,232 1460 | dc.w 219,206,195,184,174,164,155,146,138,130,123,116,0 1461 | ; Tuning -2 1462 | mt_ftuneE 1463 | dc.w 868,820,774,730,689,651,614,580,547,516,487,460 1464 | dc.w 434,410,387,365,345,325,307,290,274,258,244,230 1465 | dc.w 217,205,193,183,172,163,154,145,137,129,122,115,0 1466 | ; Tuning -1 1467 | mt_ftuneF 1468 | dc.w 862,814,768,725,684,646,610,575,543,513,484,457 1469 | dc.w 431,407,384,363,342,323,305,288,272,256,242,228 1470 | dc.w 216,203,192,181,171,161,152,144,136,128,121,114,0 1471 | ; ------------------------------------------------------ 1472 | ; Overflow bytes from CursorPosTable and UnshiftedKeymap 1473 | ; LUTs so that overflown arpeggio at finetune -1 sounds 1474 | ; right even if this table was to be moved. 1475 | ; ------------------------------------------------------ 1476 | dc.w 774,1800,2314,3087,4113,4627,5400,6426,6940,7713 1477 | dc.w 8739,9253,24625,12851,13365 1478 | 1479 | CNOP 0,4 1480 | mt_audchan1temp dcb.b 26 1481 | dc.w $0001 ; voice #1 DMA bit 1482 | dcb.b 16 1483 | CNOP 0,4 1484 | mt_audchan2temp dcb.b 26 1485 | dc.w $0002 ; voice #2 DMA bit 1486 | dcb.b 16 1487 | CNOP 0,4 1488 | mt_audchan3temp dcb.b 26 1489 | dc.w $0004 ; voice #3 DMA bit 1490 | dcb.b 16 1491 | CNOP 0,4 1492 | mt_audchan4temp dcb.b 26 1493 | dc.w $0008 ; voice #4 DMA bit 1494 | dcb.b 16 1495 | 1496 | CNOP 0,4 1497 | mt_SampleStarts dcb.l 31,0 1498 | mt_SongDataPtr dc.l 0 1499 | mt_SampleStructPtr dc.l 0 1500 | mt_PatternPtr dc.l 0 1501 | mt_PatternPos dc.w 0 1502 | mt_DMACONtemp dc.w 0 1503 | mt_SongLength dc.b 0 1504 | mt_Speed dc.b 6 1505 | mt_Counter dc.b 0 1506 | mt_SongPos dc.b 0 1507 | mt_PBreakPos dc.b 0 1508 | mt_PosJumpFlag dc.b 0 1509 | mt_PBreakFlag dc.b 0 1510 | mt_LowMask dc.b $FF 1511 | mt_PattDelayTime dc.b 0 1512 | mt_PattDelayTime2 dc.b 0 1513 | mt_Enable dc.b 0 1514 | 1515 | SECTION music,DATA_C 1516 | 1517 | CNOP 0,4 1518 | mt_data INCBIN "music.mod" 1519 | 1520 | ;/* End of File */ 1521 | -------------------------------------------------------------------------------- /replayer/PT2.3F_replay_vblank.s: -------------------------------------------------------------------------------- 1 | ;******************************************************* 2 | ;* ---- ProTracker V2.3F Replay Routine (VBlank) ---- * 3 | ;******************************************************* 4 | ; 5 | ; This is the vblank version of the PT2.3F replayer. If you don't know 6 | ; the difference between CIA and vblank, you probably want to use the 7 | ; CIA version instead. 8 | ; 9 | ; This replayer has been slightly optimized over the PT2.3D replayer, 10 | ; but it's still far from fully optimized. It has also been rewritten to 11 | ; behave like PT2.3F's internal replayer, for maximum accuracy. 12 | ; 13 | ; Changelog: 14 | ; - 13.03.2025: Initial version 15 | ; - 21.05.2025: Set Sample Offset (9xx) now works on >64kB samples 16 | 17 | ; Simple test code. Attempts to call mt_music() 50 times a second, but may play 18 | ; at the wrong tempo, especially in some emulator configs. 19 | main 20 | BSR.W mt_init ; setup module 21 | mloop ; --------------------------- 22 | vloop MOVE.L $DFF004,D0 ; wait for vblank 23 | AND.L #$1FF00,D0 24 | CMP.L #303<<8,D0 25 | BNE.B vloop 26 | ; --------------------------- 27 | BTST #6,$BFE001 ; test for mouse button 28 | BEQ.B exit 29 | ; --------------------------- 30 | BSR.W mt_music 31 | ; --------------------------- 32 | BRA.B mloop 33 | exit BSR.W mt_end 34 | RTS 35 | 36 | LEDStatus dc.b 0 37 | EVEN 38 | 39 | ;---- Playroutine ---- 40 | 41 | n_note EQU 0 ; W (MUST be first!) 42 | n_cmd EQU 2 ; W (MUST be second!) 43 | n_cmdlo EQU 3 ; B (offset in n_cmd) 44 | n_start EQU 4 ; L (aligned) 45 | n_loopstart EQU 8 ; L 46 | n_wavestart EQU 12 ; L 47 | n_peroffset EQU 16 ; L (offset to finetuned period-LUT section) 48 | n_length EQU 20 ; W (aligned) 49 | n_replen EQU 22 ; W 50 | n_period EQU 24 ; W 51 | n_dmabit EQU 26 ; W 52 | n_wantedperiod EQU 28 ; W 53 | n_finetune EQU 30 ; B 54 | n_volume EQU 31 ; B 55 | n_toneportdirec EQU 32 ; B 56 | n_toneportspeed EQU 33 ; B 57 | n_vibratocmd EQU 34 ; B 58 | n_vibratopos EQU 35 ; B 59 | n_tremolocmd EQU 36 ; B 60 | n_tremolopos EQU 37 ; B 61 | n_wavecontrol EQU 38 ; B 62 | n_glissfunk EQU 39 ; B 63 | n_sampleoffset EQU 40 ; B 64 | n_pattpos EQU 41 ; B 65 | n_loopcount EQU 42 ; B 66 | n_funkoffset EQU 43 ; B 67 | 68 | mt_init 69 | MOVEM.L D0-A6,-(SP) 70 | 71 | LEA mt_data,A0 72 | MOVE.L A0,mt_SongDataPtr 73 | MOVE.B 950(A0),mt_SongLength 74 | LEA 12(A0),A1 75 | MOVE.L A1,mt_SampleStructPtr 76 | 77 | ; count number of patterns (find highest referred pattern) 78 | LEA 952(A0),A1 ; order list address 79 | MOVEQ #128-1,D0 ; 128 order list entries 80 | MOVEQ #0,D1 81 | mtloop MOVE.L D1,D2 82 | SUBQ.W #1,D0 83 | mtloop2 MOVE.B (A1)+,D1 84 | CMP.B D2,D1 85 | BGT.B mtloop 86 | DBRA D0,mtloop2 87 | ADDQ.B #1,D2 88 | 89 | ; generate mt_SampleStarts list and fix samples 90 | 91 | LSL.L #8,D2 92 | LSL.L #2,D2 ; D2 *= 1024 93 | ADD.L #1084,D2 94 | ADD.L A0,D2 95 | MOVE.L D2,A2 ; A2 is now the address of first sample's data 96 | 97 | LEA mt_SampleStarts(PC),A1 98 | MOVEQ #31-1,D3 99 | mtloop3 MOVEQ #0,D0 100 | MOVE.W 42(A0),D0 ; get sample length 101 | BEQ.B mtskip2 ; sample is empty, don't handle 102 | MOVEQ #0,D1 103 | MOVE.W 46(A0),D1 ; get repeat 104 | MOVEQ #0,D2 105 | MOVE.W 48(A0),D2 ; get replen 106 | BNE.B mtskip 107 | MOVEQ #1,D2 108 | MOVE.W D2,48(A0) ; replen is zero, set to 1 (fixes lock-up) 109 | mtskip ADD.L D2,D1 110 | CMP.L #1,D1 ; loop enabled? (repeat+replen > 1) 111 | BHI.B mtskip2 ; yes 112 | CLR.W (A2) ; no, clear first word of sample (prevents beep) 113 | mtskip2 MOVE.L A2,(A1)+ ; move sample address into mt_SampleStarts slot 114 | ADD.L D0,D0 ; turn into real sample length 115 | ADD.L D0,A2 ; add to address 116 | LEA 30(A0),A0 ; skip to next sample list entry 117 | DBRA D3,mtloop3 118 | 119 | ; initialize stuff 120 | MOVE.B $BFE001,D0 ; copy of LED filter state 121 | AND.B #2,D0 122 | MOVE.B D0,LEDStatus 123 | BSET #1,$BFE001 ; turn off LED filter 124 | ; -------------------- 125 | MOVE.B #6,mt_Speed 126 | CLR.B mt_Counter 127 | CLR.B mt_SongPos 128 | CLR.W mt_PatternPos 129 | CLR.B mt_PattDelayTime 130 | CLR.B mt_PattDelayTime2 131 | BSR.W mt_RestoreEffects 132 | BSR.B mt_TurnOffVoices 133 | 134 | MOVEM.L (SP)+,D0-A6 135 | RTS 136 | 137 | mt_end 138 | BCLR #1,$BFE001 ; restore previous LED filter state 139 | MOVE.L D0,-(SP) 140 | MOVE.B LEDStatus(PC),D0 141 | OR.B D0,$BFE001 142 | MOVE.L (SP)+,D0 143 | mt_TurnOffVoices 144 | MOVE.W #$F,$DFF096 ; turn off voice DMAs 145 | CLR.W $DFF0A8 ; clear voice volumes 146 | CLR.W $DFF0B8 147 | CLR.W $DFF0C8 148 | CLR.W $DFF0D8 149 | RTS 150 | 151 | mt_RestoreEffects 152 | LEA mt_audchan1temp(PC),A0 153 | BSR.B reefsub 154 | LEA mt_audchan2temp(PC),A0 155 | BSR.B reefsub 156 | LEA mt_audchan3temp(PC),A0 157 | BSR.B reefsub 158 | LEA mt_audchan4temp(PC),A0 159 | reefsub CLR.B n_wavecontrol(A0) 160 | CLR.B n_glissfunk(A0) 161 | CLR.B n_finetune(A0) 162 | CLR.B n_loopcount(A0) 163 | RTS 164 | 165 | mt_music 166 | MOVEM.L D0-A6,-(SP) 167 | ADDQ.B #1,mt_Counter 168 | MOVE.B mt_Counter(PC),D0 169 | CMP.B mt_Speed(PC),D0 170 | BLO.B mt_NoNewNote 171 | CLR.B mt_Counter 172 | TST.B mt_PattDelayTime2 173 | BEQ.B mt_GetNewNote 174 | BSR.B mt_NoNewAllChannels 175 | BRA.W mt_dskip 176 | 177 | mt_NoNewNote 178 | BSR.B mt_NoNewAllChannels 179 | BRA.W mt_NoNewPositionYet 180 | 181 | mt_NoNewAllChannels 182 | LEA mt_audchan1temp(PC),A6 183 | LEA $DFF0A0,A5 184 | BSR.W mt_CheckEffects 185 | LEA mt_audchan2temp(PC),A6 186 | LEA $DFF0B0,A5 187 | BSR.W mt_CheckEffects 188 | LEA mt_audchan3temp(PC),A6 189 | LEA $DFF0C0,A5 190 | BSR.W mt_CheckEffects 191 | LEA mt_audchan4temp(PC),A6 192 | LEA $DFF0D0,A5 193 | BRA.W mt_CheckEffects 194 | 195 | mt_GetNewNote 196 | ; Setup pattern pointer 197 | MOVE.L mt_SongDataPtr(PC),A0 198 | LEA 952(A0),A1 ;pattpo 199 | LEA 1084(A0),A0 ;patterndata 200 | MOVEQ #0,D0 201 | MOVE.B mt_SongPos(PC),D0 202 | MOVEQ #0,D1 203 | MOVE.B (A1,D0.W),D1 204 | LSL.L #8,D1 205 | LSL.L #2,D1 206 | MOVEQ #0,D0 207 | MOVE.W mt_PatternPos(PC),D0 208 | ADD.L D0,D1 209 | ADD.L D1,A0 210 | MOVE.L A0,mt_PatternPtr 211 | 212 | CLR.W mt_DMACONtemp 213 | 214 | LEA $DFF0A0,A5 215 | LEA mt_audchan1temp(PC),A6 216 | BSR.B mt_PlayVoice 217 | MOVEQ #0,D0 218 | MOVE.B n_volume(A6),D0 219 | MOVE.W D0,8(A5) 220 | 221 | LEA $DFF0B0,A5 222 | LEA mt_audchan2temp(PC),A6 223 | BSR.B mt_PlayVoice 224 | MOVEQ #0,D0 225 | MOVE.B n_volume(A6),D0 226 | MOVE.W D0,8(A5) 227 | 228 | LEA $DFF0C0,A5 229 | LEA mt_audchan3temp(PC),A6 230 | BSR.B mt_PlayVoice 231 | MOVEQ #0,D0 232 | MOVE.B n_volume(A6),D0 233 | MOVE.W D0,8(A5) 234 | 235 | LEA $DFF0D0,A5 236 | LEA mt_audchan4temp(PC),A6 237 | BSR.B mt_PlayVoice 238 | MOVEQ #0,D0 239 | MOVE.B n_volume(A6),D0 240 | MOVE.W D0,8(A5) 241 | 242 | BRA.W mt_SetDMA 243 | 244 | mt_PlayVoice 245 | TST.L (A6) 246 | BNE.B mt_plvskip 247 | BSR.W mt_PerNop 248 | mt_plvskip 249 | MOVE.L mt_PatternPtr(PC),A0 250 | MOVE.L (A0)+,(A6) ; Read note from pattern 251 | MOVE.L A0,mt_PatternPtr 252 | 253 | MOVEQ #0,D2 254 | MOVE.B n_cmd(A6),D2 ; Get lower 4 bits of instrument 255 | AND.B #$F0,D2 256 | LSR.B #4,D2 257 | MOVE.B (A6),D0 ; Get higher 4 bits of instrument 258 | AND.B #$F0,D0 259 | OR.B D0,D2 260 | BEQ.W mt_SetRegisters ; Instrument was zero 261 | 262 | LEA mt_SampleStarts(PC),A1 263 | MOVE.L mt_SampleStructPtr(PC),A3 264 | 265 | MOVE D2,D4 266 | SUBQ.L #1,D2 267 | LSL.L #2,D2 268 | MULU.W #30,D4 269 | MOVE.L (A1,D2.L),n_start(A6) 270 | MOVE.W (A3,D4.L),n_length(A6) 271 | 272 | MOVEQ #0,D0 273 | MOVE.B 2(A3,D4.L),D0 274 | AND.B #$0F,D0 275 | MOVE.B D0,n_finetune(A6) 276 | ; ---------------------------------- 277 | LSL.B #2,D0 ; update n_peroffset 278 | LEA mt_ftunePerTab(PC),A4 279 | MOVE.L (A4,D0.W),n_peroffset(A6) 280 | ; ---------------------------------- 281 | MOVEQ #0,D3 282 | MOVE.B 3(A3,D4.L),n_volume(A6) 283 | MOVE.W 4(A3,D4.L),D3 ; Get repeat 284 | BEQ.B mt_NoLoop 285 | MOVE.L n_start(A6),D2 ; Get start 286 | ADD.L D3,D3 287 | ADD.L D3,D2 ; Add repeat 288 | MOVE.L D2,n_loopstart(A6) 289 | MOVE.L D2,n_wavestart(A6) 290 | MOVE.W 4(A3,D4.L),D0 ; Get repeat 291 | ADD.W 6(A3,D4.L),D0 ; Add replen 292 | MOVE.W D0,n_length(A6) 293 | MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen 294 | BRA.B mt_SetRegisters 295 | 296 | mt_NoLoop 297 | MOVE.L n_start(A6),D2 298 | ADD.L D3,D2 299 | MOVE.L D2,n_loopstart(A6) 300 | MOVE.L D2,n_wavestart(A6) 301 | MOVE.W 6(A3,D4.L),n_replen(A6) ; Save replen 302 | mt_SetRegisters 303 | MOVE.W (A6),D0 304 | AND.W #$0FFF,D0 305 | BEQ.W mt_CheckMoreEffects ; If no note 306 | MOVE.W 2(A6),D0 307 | AND.W #$FF0,D0 308 | CMP.W #$E50,D0 ; finetune 309 | BEQ.B mt_DoSetFineTune 310 | MOVE.B 2(A6),D0 311 | AND.B #$0F,D0 312 | CMP.B #3,D0 ; TonePortamento 313 | BEQ.B mt_ChkTonePorta 314 | CMP.B #5,D0 ; TonePortamento + VolSlide 315 | BEQ.B mt_ChkTonePorta 316 | CMP.B #9,D0 ; Sample Offset 317 | BNE.B mt_SetPeriod 318 | BSR.W mt_CheckMoreEffects 319 | BRA.B mt_SetPeriod 320 | 321 | mt_DoSetFineTune 322 | BSR.W mt_SetFineTune 323 | BRA.B mt_SetPeriod 324 | 325 | mt_ChkTonePorta 326 | BSR.W mt_SetTonePorta 327 | BRA.W mt_CheckMoreEffects 328 | 329 | mt_SetPeriod 330 | MOVE.W (A6),D1 331 | AND.W #$0FFF,D1 332 | LEA mt_PeriodTable(PC),A1 333 | MOVEQ #0,D0 334 | MOVEQ #37-1,D7 335 | mt_ftuloop 336 | CMP.W (A1,D0.W),D1 337 | BHS.B mt_ftufound 338 | ADDQ.W #2,D0 339 | DBRA D7,mt_ftuloop 340 | mt_ftufound 341 | MOVE.L n_peroffset(A6),A1 342 | MOVE.W (A1,D0.W),n_period(A6) 343 | 344 | MOVE.W 2(A6),D0 345 | AND.W #$0FF0,D0 346 | CMP.W #$0ED0,D0 ; Notedelay 347 | BEQ.W mt_CheckMoreEffects 348 | 349 | MOVE.W n_dmabit(A6),$DFF096 350 | BTST #2,n_wavecontrol(A6) 351 | BNE.B mt_vibnoc 352 | CLR.B n_vibratopos(A6) 353 | mt_vibnoc 354 | BTST #6,n_wavecontrol(A6) 355 | BNE.B mt_trenoc 356 | CLR.B n_tremolopos(A6) 357 | mt_trenoc 358 | MOVE.W n_length(A6),4(A5) ; Set length 359 | MOVE.L n_start(A6),(A5) ; Set start 360 | BNE.B mt_sdmaskp 361 | CLR.L n_loopstart(A6) 362 | MOVEQ #1,D0 363 | MOVE.W D0,4(A5) 364 | MOVE.W D0,n_replen(A6) 365 | mt_sdmaskp 366 | MOVE.W n_period(A6),D0 367 | MOVE.W D0,6(A5) ; Set period 368 | MOVE.W n_dmabit(A6),D0 369 | OR.W D0,mt_DMACONtemp 370 | BRA.W mt_CheckMoreEffects 371 | 372 | mt_SetDMA 373 | ; scanline-wait (wait before starting Paula DMA) 374 | LEA $DFF006,A0 375 | MOVEQ #7-1,D1 376 | lineloop1 377 | MOVE.B (A0),D0 378 | waiteol1 379 | CMP.B (A0),D0 380 | BEQ.B waiteol1 381 | DBRA D1,lineloop1 382 | 383 | MOVE.W mt_DMACONtemp(PC),D0 384 | OR.W #$8000,D0 ; Set bits 385 | MOVE.W D0,$DFF096 386 | 387 | ; scanline-wait (wait for Paula DMA to latch) 388 | MOVEQ #7-1,D1 389 | lineloop2 390 | MOVE.B (A0),D0 391 | waiteol2 392 | CMP.B (A0),D0 393 | BEQ.B waiteol2 394 | DBRA D1,lineloop2 395 | 396 | LEA $DFF000,A5 397 | LEA mt_audchan4temp(PC),A6 398 | MOVE.L n_loopstart(A6),$D0(A5) 399 | MOVE.W n_replen(A6),$D4(A5) 400 | LEA mt_audchan3temp(PC),A6 401 | MOVE.L n_loopstart(A6),$C0(A5) 402 | MOVE.W n_replen(A6),$C4(A5) 403 | LEA mt_audchan2temp(PC),A6 404 | MOVE.L n_loopstart(A6),$B0(A5) 405 | MOVE.W n_replen(A6),$B4(A5) 406 | LEA mt_audchan1temp(PC),A6 407 | MOVE.L n_loopstart(A6),$A0(A5) 408 | MOVE.W n_replen(A6),$A4(A5) 409 | 410 | mt_dskip 411 | ADD.W #16,mt_PatternPos 412 | MOVE.B mt_PattDelayTime(PC),D0 413 | BEQ.B mt_dskpc 414 | MOVE.B D0,mt_PattDelayTime2 415 | CLR.B mt_PattDelayTime 416 | mt_dskpc 417 | TST.B mt_PattDelayTime2 418 | BEQ.B mt_dskpa 419 | SUBQ.B #1,mt_PattDelayTime2 420 | BEQ.B mt_dskpa 421 | SUB.W #16,mt_PatternPos 422 | mt_dskpa 423 | TST.B mt_PBreakFlag 424 | BEQ.B mt_nnpysk 425 | SF mt_PBreakFlag 426 | MOVEQ #0,D0 427 | MOVE.B mt_PBreakPos(PC),D0 428 | LSL.W #4,D0 429 | MOVE.W D0,mt_PatternPos 430 | CLR.B mt_PBreakPos 431 | mt_nnpysk 432 | CMP.W #1024,mt_PatternPos 433 | BLO.B mt_NoNewPositionYet 434 | mt_NextPosition 435 | MOVEQ #0,D0 436 | MOVE.B mt_PBreakPos(PC),D0 437 | LSL.W #4,D0 438 | MOVE.W D0,mt_PatternPos 439 | CLR.B mt_PBreakPos 440 | CLR.B mt_PosJumpFlag 441 | ADDQ.B #1,mt_SongPos 442 | AND.B #127,mt_SongPos 443 | MOVE.B mt_SongPos(PC),D1 444 | CMP.B mt_SongLength(PC),D1 445 | BLO.B mt_NoNewPositionYet 446 | CLR.B mt_SongPos 447 | 448 | mt_NoNewPositionYet 449 | TST.B mt_PosJumpFlag 450 | BNE.B mt_NextPosition 451 | mt_exit MOVEM.L (SP)+,D0-A6 452 | RTS 453 | 454 | mt_CheckEffects 455 | BSR.B mt_chkefx2 456 | MOVEQ #0,D0 457 | MOVE.B n_volume(A6),D0 458 | MOVE.W D0,8(A5) 459 | RTS 460 | 461 | CNOP 0,4 462 | mt_JumpList1 463 | dc.l mt_Arpeggio ; 0xy (Arpeggio) 464 | dc.l mt_PortaUp ; 1xx (Portamento Up) 465 | dc.l mt_PortaDown ; 2xx (Portamento Down) 466 | dc.l mt_TonePortamento ; 3xx (Tone Portamento) 467 | dc.l mt_Vibrato ; 4xy (Vibrato) 468 | dc.l mt_TonePlusVolSlide ; 5xy (Tone Portamento + Volume Slide) 469 | dc.l mt_VibratoPlusVolSlide ; 6xy (Vibrato + Volume Slide) 470 | dc.l SetBack ; 7 - not used here 471 | dc.l SetBack ; 8 - unused! 472 | dc.l SetBack ; 9 - not used here 473 | dc.l SetBack ; A - not used here 474 | dc.l SetBack ; B - not used here 475 | dc.l SetBack ; C - not used here 476 | dc.l SetBack ; D - not used here 477 | dc.l mt_E_Commands ; Exy (Extended Commands) 478 | dc.l SetBack ; F - not used here 479 | 480 | mt_chkefx2 481 | BSR.W mt_UpdateFunk 482 | MOVE.W n_cmd(A6),D0 483 | AND.W #$0FFF,D0 484 | BEQ.B mt_Return3 485 | MOVEQ #0,D0 486 | MOVE.B n_cmd(A6),D0 487 | AND.B #$0F,D0 488 | MOVE.W D0,D1 489 | LSL.B #2,D1 490 | MOVE.L mt_JumpList1(PC,D1.W),A4 491 | JMP (A4) ; every efx has RTS at the end, this is safe 492 | 493 | SetBack MOVE.W n_period(A6),6(A5) 494 | CMP.B #7,D0 495 | BEQ.W mt_Tremolo 496 | CMP.B #$A,D0 497 | BEQ.W mt_VolumeSlide 498 | mt_Return3 499 | RTS 500 | 501 | mt_PerNop 502 | MOVE.W n_period(A6),6(A5) 503 | RTS 504 | 505 | mt_Arpeggio 506 | MOVEQ #0,D0 507 | MOVE.B mt_Counter(PC),D0 508 | MOVE.B mt_ArpTab(PC,D0.W),D0 509 | CMP.B #1,D0 510 | BEQ.B mt_Arpeggio1 511 | CMP.B #2,D0 512 | BEQ.B mt_Arpeggio2 513 | mt_Arpeggio0 514 | MOVE.W n_period(A6),6(A5) 515 | RTS 516 | 517 | mt_Arpeggio1 518 | MOVEQ #0,D0 519 | MOVE.B n_cmdlo(A6),D0 520 | LSR.B #4,D0 521 | BRA.B mt_ArpeggioFind 522 | 523 | mt_Arpeggio2 524 | MOVEQ #0,D0 525 | MOVE.B n_cmdlo(A6),D0 526 | AND.B #15,D0 527 | mt_ArpeggioFind 528 | ADD.W D0,D0 529 | MOVE.L n_peroffset(A6),A0 530 | MOVEQ #0,D1 531 | MOVE.W n_period(A6),D1 532 | MOVEQ #37-1,D3 533 | mt_arploop 534 | CMP.W (A0)+,D1 535 | BHS.B mt_ArpeggioFound 536 | DBRA D3,mt_arploop 537 | RTS 538 | 539 | mt_ArpeggioFound 540 | MOVE.W -2(A0,D0.W),6(A5) 541 | RTS 542 | 543 | ; DIV -> LUT optimization. DIVU is 140+ cycles on a 68000. 544 | mt_ArpTab 545 | dc.b 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1 546 | dc.b 2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0 547 | dc.b 1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 548 | dc.b 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1 549 | dc.b 2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0 550 | dc.b 1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2 551 | dc.b 0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1 552 | dc.b 2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0 553 | 554 | mt_FinePortaUp 555 | TST.B mt_Counter 556 | BNE.W mt_Return3 557 | MOVE.B #$0F,mt_LowMask 558 | mt_PortaUp 559 | MOVEQ #0,D0 560 | MOVE.B n_cmdlo(A6),D0 561 | AND.B mt_LowMask(PC),D0 562 | MOVE.B #$FF,mt_LowMask 563 | SUB.W D0,n_period(A6) 564 | MOVE.W n_period(A6),D0 565 | AND.W #$0FFF,D0 566 | CMP.W #113,D0 567 | BPL.B mt_PortaUskip 568 | AND.W #$F000,n_period(A6) 569 | OR.W #113,n_period(A6) 570 | mt_PortaUskip 571 | MOVE.W n_period(A6),D0 572 | AND.W #$0FFF,D0 573 | MOVE.W D0,6(A5) 574 | RTS 575 | 576 | mt_FinePortaDown 577 | TST.B mt_Counter 578 | BNE.W mt_Return3 579 | MOVE.B #$0F,mt_LowMask 580 | mt_PortaDown 581 | CLR.W D0 582 | MOVE.B n_cmdlo(A6),D0 583 | AND.B mt_LowMask(PC),D0 584 | MOVE.B #$FF,mt_LowMask 585 | ADD.W D0,n_period(A6) 586 | MOVE.W n_period(A6),D0 587 | AND.W #$0FFF,D0 588 | CMP.W #856,D0 589 | BMI.B mt_PortaDskip 590 | AND.W #$F000,n_period(A6) 591 | OR.W #856,n_period(A6) 592 | mt_PortaDskip 593 | MOVE.W n_period(A6),D0 594 | AND.W #$0FFF,D0 595 | MOVE.W D0,6(A5) 596 | RTS 597 | 598 | mt_SetTonePorta 599 | MOVE.W (A6),D2 600 | AND.W #$0FFF,D2 601 | MOVE.L n_peroffset(A6),A4 602 | MOVEQ #0,D0 603 | mt_StpLoop 604 | CMP.W (A4,D0.W),D2 605 | BHS.B mt_StpFound 606 | ADDQ.W #2,D0 607 | CMP.W #37*2,D0 608 | BLO.B mt_StpLoop 609 | MOVEQ #35*2,D0 610 | mt_StpFound 611 | MOVE.B n_finetune(A6),D2 612 | AND.B #8,D2 613 | BEQ.B mt_StpGoss 614 | TST.W D0 615 | BEQ.B mt_StpGoss 616 | SUBQ.W #2,D0 617 | mt_StpGoss 618 | MOVE.W (A4,D0.W),D2 619 | MOVE.W D2,n_wantedperiod(A6) 620 | MOVE.W n_period(A6),D0 621 | CLR.B n_toneportdirec(A6) 622 | CMP.W D0,D2 623 | BEQ.B mt_ClearTonePorta 624 | BGE.W mt_Return3 625 | MOVE.B #1,n_toneportdirec(A6) 626 | RTS 627 | 628 | mt_ClearTonePorta 629 | CLR.W n_wantedperiod(A6) 630 | RTS 631 | 632 | mt_TonePortamento 633 | MOVE.B n_cmdlo(A6),D0 634 | BEQ.B mt_TonePortNoChange 635 | MOVE.B D0,n_toneportspeed(A6) 636 | CLR.B n_cmdlo(A6) 637 | mt_TonePortNoChange 638 | TST.W n_wantedperiod(A6) 639 | BEQ.W mt_Return3 640 | MOVEQ #0,D0 641 | MOVE.B n_toneportspeed(A6),D0 642 | TST.B n_toneportdirec(A6) 643 | BNE.B mt_TonePortaUp 644 | mt_TonePortaDown 645 | ADD.W D0,n_period(A6) 646 | MOVE.W n_wantedperiod(A6),D0 647 | CMP.W n_period(A6),D0 648 | BGT.B mt_TonePortaSetPer 649 | MOVE.W n_wantedperiod(A6),n_period(A6) 650 | CLR.W n_wantedperiod(A6) 651 | BRA.B mt_TonePortaSetPer 652 | 653 | mt_TonePortaUp 654 | SUB.W D0,n_period(A6) 655 | MOVE.W n_wantedperiod(A6),D0 656 | CMP.W n_period(A6),D0 657 | BLT.B mt_TonePortaSetPer 658 | MOVE.W n_wantedperiod(A6),n_period(A6) 659 | CLR.W n_wantedperiod(A6) 660 | 661 | mt_TonePortaSetPer 662 | MOVE.W n_period(A6),D2 663 | MOVE.B n_glissfunk(A6),D0 664 | AND.B #$0F,D0 665 | BEQ.B mt_GlissSkip 666 | MOVE.L n_peroffset(A6),A0 667 | MOVEQ #0,D0 668 | mt_GlissLoop 669 | CMP.W (A0,D0.W),D2 670 | BHS.B mt_GlissFound 671 | ADDQ.W #2,D0 672 | CMP.W #37*2,D0 673 | BLO.B mt_GlissLoop 674 | MOVEQ #35*2,D0 675 | mt_GlissFound 676 | MOVE.W (A0,D0.W),D2 677 | mt_GlissSkip 678 | MOVE.W D2,6(A5) ; Set period 679 | RTS 680 | 681 | mt_Vibrato 682 | MOVE.B n_cmdlo(A6),D0 683 | BEQ.B mt_Vibrato2 684 | MOVE.B n_vibratocmd(A6),D2 685 | AND.B #$0F,D0 686 | BEQ.B mt_vibskip 687 | AND.B #$F0,D2 688 | OR.B D0,D2 689 | mt_vibskip 690 | MOVE.B n_cmdlo(A6),D0 691 | AND.B #$F0,D0 692 | BEQ.B mt_vibskip2 693 | AND.B #$0F,D2 694 | OR.B D0,D2 695 | mt_vibskip2 696 | MOVE.B D2,n_vibratocmd(A6) 697 | mt_Vibrato2 698 | MOVE.B n_vibratopos(A6),D0 699 | LEA mt_VibratoTable(PC),A4 700 | LSR.W #2,D0 701 | AND.W #$001F,D0 702 | MOVEQ #0,D2 703 | MOVE.B n_wavecontrol(A6),D2 704 | AND.B #3,D2 705 | BEQ.B mt_vib_sine 706 | LSL.B #3,D0 707 | CMP.B #1,D2 708 | BEQ.B mt_vib_rampdown 709 | MOVE.B #255,D2 710 | BRA.B mt_vib_set 711 | mt_vib_rampdown 712 | TST.B n_vibratopos(A6) 713 | BPL.B mt_vib_rampdown2 714 | MOVE.B #255,D2 715 | SUB.B D0,D2 716 | BRA.B mt_vib_set 717 | mt_vib_rampdown2 718 | MOVE.B D0,D2 719 | BRA.B mt_vib_set 720 | mt_vib_sine 721 | MOVE.B (A4,D0.W),D2 722 | mt_vib_set 723 | MOVE.B n_vibratocmd(A6),D0 724 | AND.W #15,D0 725 | MULU.W D0,D2 726 | LSR.W #7,D2 727 | MOVE.W n_period(A6),D0 728 | TST.B n_vibratopos(A6) 729 | BMI.B mt_VibratoNeg 730 | ADD.W D2,D0 731 | BRA.B mt_Vibrato3 732 | mt_VibratoNeg 733 | SUB.W D2,D0 734 | mt_Vibrato3 735 | MOVE.W D0,6(A5) 736 | MOVE.B n_vibratocmd(A6),D0 737 | LSR.W #2,D0 738 | AND.W #$003C,D0 739 | ADD.B D0,n_vibratopos(A6) 740 | RTS 741 | 742 | mt_TonePlusVolSlide 743 | BSR.W mt_TonePortNoChange 744 | BRA.W mt_VolumeSlide 745 | 746 | mt_VibratoPlusVolSlide 747 | BSR.B mt_Vibrato2 748 | BRA.W mt_VolumeSlide 749 | 750 | mt_Tremolo 751 | MOVE.B n_cmdlo(A6),D0 752 | BEQ.B mt_Tremolo2 753 | MOVE.B n_tremolocmd(A6),D2 754 | AND.B #$0F,D0 755 | BEQ.B mt_treskip 756 | AND.B #$F0,D2 757 | OR.B D0,D2 758 | mt_treskip 759 | MOVE.B n_cmdlo(A6),D0 760 | AND.B #$F0,D0 761 | BEQ.B mt_treskip2 762 | AND.B #$0F,D2 763 | OR.B D0,D2 764 | mt_treskip2 765 | MOVE.B D2,n_tremolocmd(A6) 766 | mt_Tremolo2 767 | MOVE.B n_tremolopos(A6),D0 768 | LEA mt_VibratoTable(PC),A4 769 | LSR.W #2,D0 770 | AND.W #$001F,D0 771 | MOVEQ #0,D2 772 | MOVE.B n_wavecontrol(A6),D2 773 | LSR.B #4,D2 774 | AND.B #3,D2 775 | BEQ.B mt_tre_sine 776 | LSL.B #3,D0 777 | CMP.B #1,D2 778 | BEQ.B mt_tre_rampdown 779 | MOVE.B #255,D2 780 | BRA.B mt_tre_set 781 | mt_tre_rampdown 782 | TST.B n_vibratopos(A6) 783 | BPL.B mt_tre_rampdown2 784 | MOVE.B #255,D2 785 | SUB.B D0,D2 786 | BRA.B mt_tre_set 787 | mt_tre_rampdown2 788 | MOVE.B D0,D2 789 | BRA.B mt_tre_set 790 | mt_tre_sine 791 | MOVE.B (A4,D0.W),D2 792 | mt_tre_set 793 | MOVE.B n_tremolocmd(A6),D0 794 | AND.W #15,D0 795 | MULU.W D0,D2 796 | LSR.W #6,D2 797 | MOVEQ #0,D0 798 | MOVE.B n_volume(A6),D0 799 | TST.B n_tremolopos(A6) 800 | BMI.B mt_TremoloNeg 801 | ADD.W D2,D0 802 | BRA.B mt_Tremolo3 803 | mt_TremoloNeg 804 | SUB.W D2,D0 805 | mt_Tremolo3 806 | BPL.B mt_TremoloSkip 807 | CLR.W D0 808 | mt_TremoloSkip 809 | CMP.W #64,D0 810 | BLS.B mt_TremoloOk 811 | MOVE.W #64,D0 812 | mt_TremoloOk 813 | MOVE.W D0,8(A5) 814 | MOVE.B n_tremolocmd(A6),D0 815 | LSR.W #2,D0 816 | AND.W #$003C,D0 817 | ADD.B D0,n_tremolopos(A6) 818 | ADDQ.L #4,SP ; hack to not set volume in mt_CheckEffects 819 | RTS 820 | 821 | mt_SampleOffset 822 | MOVEQ #0,D0 823 | MOVE.B n_cmdlo(A6),D0 824 | BEQ.B mt_sononew 825 | MOVE.B D0,n_sampleoffset(A6) 826 | mt_sononew 827 | MOVE.B n_sampleoffset(A6),D0 828 | LSL.W #7,D0 829 | CMP.W n_length(A6),D0 830 | BHS.B mt_sofskip 831 | SUB.W D0,n_length(A6) 832 | ADD.W D0,D0 833 | ADD.L D0,n_start(A6) 834 | RTS 835 | mt_sofskip 836 | MOVE.W #1,n_length(A6) 837 | RTS 838 | 839 | mt_VolumeSlide 840 | MOVEQ #0,D0 841 | MOVE.B n_cmdlo(A6),D0 842 | LSR.B #4,D0 843 | BEQ.B mt_VolSlideDown 844 | mt_VolSlideUp 845 | ADD.B D0,n_volume(A6) 846 | CMP.B #64,n_volume(A6) 847 | BMI.B mt_vsuskip 848 | MOVE.B #64,n_volume(A6) 849 | mt_vsuskip 850 | RTS 851 | 852 | mt_VolSlideDown 853 | MOVEQ #0,D0 854 | MOVE.B n_cmdlo(A6),D0 855 | AND.B #$0F,D0 856 | mt_VolSlideDown2 857 | SUB.B D0,n_volume(A6) 858 | BPL.B mt_vsdskip 859 | CLR.B n_volume(A6) 860 | mt_vsdskip 861 | RTS 862 | 863 | mt_PositionJump 864 | MOVE.B n_cmdlo(A6),D0 865 | SUBQ.B #1,D0 866 | MOVE.B D0,mt_SongPos 867 | mt_pj2 CLR.B mt_PBreakPos 868 | ST mt_PosJumpFlag 869 | RTS 870 | 871 | mt_VolumeChange 872 | MOVEQ #0,D0 873 | MOVE.B n_cmdlo(A6),D0 874 | CMP.B #64,D0 875 | BLS.B mt_VolumeOk 876 | MOVEQ #64,D0 877 | mt_VolumeOk 878 | MOVE.B D0,n_volume(A6) 879 | RTS 880 | 881 | mt_PatternBreak 882 | MOVEQ #0,D0 883 | MOVE.B n_cmdlo(A6),D0 884 | MOVE.L D0,D2 885 | LSR.B #4,D0 886 | MULU.W #10,D0 887 | AND.B #$0F,D2 888 | ADD.B D2,D0 889 | CMP.B #63,D0 890 | BHI.B mt_pj2 891 | MOVE.B D0,mt_PBreakPos 892 | ST mt_PosJumpFlag 893 | RTS 894 | 895 | mt_SetSpeed 896 | MOVE.B 3(A6),D0 897 | BEQ.W mt_end 898 | CLR.B mt_Counter 899 | MOVE.B D0,mt_Speed 900 | RTS 901 | 902 | CNOP 0,4 903 | mt_JumpList2 904 | dc.l mt_PerNop ; 0 - not used 905 | dc.l mt_PerNop ; 1 - not used 906 | dc.l mt_PerNop ; 2 - not used 907 | dc.l mt_PerNop ; 3 - not used 908 | dc.l mt_PerNop ; 4 - not used 909 | dc.l mt_PerNop ; 5 - not used 910 | dc.l mt_PerNop ; 6 - not used 911 | dc.l mt_PerNop ; 7 - not used 912 | dc.l mt_PerNop ; 8 - not used 913 | dc.l mt_SampleOffset ; 9xx (Set Sample Offset) 914 | dc.l mt_PerNop ; A - not used 915 | dc.l mt_PositionJump ; Bxx (Position Jump) 916 | dc.l mt_VolumeChange ; Cxx (Set Volume) 917 | dc.l mt_PatternBreak ; Dxx (Pattern Break) 918 | dc.l mt_E_Commands ; Exy (Extended Commands) 919 | dc.l mt_SetSpeed ; Fxx (Set Speed) 920 | 921 | mt_CheckMoreEffects 922 | MOVEQ #0,D0 923 | MOVE.B 2(A6),D0 924 | AND.B #$0F,D0 925 | LSL.B #2,D0 926 | MOVE.L mt_JumpList2(PC,D0.W),A4 927 | JMP (A4) ; every efx has RTS at the end, this is safe 928 | 929 | CNOP 0,4 930 | mt_E_JumpList 931 | dc.l mt_FilterOnOff ; E0x (Set LED Filter) 932 | dc.l mt_FinePortaUp ; E1x (Fine Portamento Up) 933 | dc.l mt_FinePortaDown ; E2x (Fine Portamento Down) 934 | dc.l mt_SetGlissControl ; E3x (Glissando/Funk Control) 935 | dc.l mt_SetVibratoControl ; E4x (Vibrato Control) 936 | dc.l mt_SetFineTune ; E5x (Set Finetune) 937 | dc.l mt_JumpLoop ; E6x (Pattern Loop) 938 | dc.l mt_SetTremoloControl ; E7x (Tremolo Control) 939 | dc.l mt_KarplusStrong ; E8x (Karplus-Strong) 940 | dc.l mt_RetrigNote ; E9x (Retrig Note) 941 | dc.l mt_VolumeFineUp ; EAx (Fine Volume-Slide Up) 942 | dc.l mt_VolumeFineDown ; EBx (Fine Volume-Slide Down) 943 | dc.l mt_NoteCut ; ECx (Note Cut) 944 | dc.l mt_NoteDelay ; EDx (Note Delay) 945 | dc.l mt_PatternDelay ; EEx (Pattern Delay) 946 | dc.l mt_FunkIt ; EFx (Invert Loop) 947 | 948 | mt_E_Commands 949 | MOVEQ #0,D0 950 | MOVE.B n_cmdlo(A6),D0 951 | AND.B #$F0,D0 952 | LSR.B #4-2,D0 953 | MOVE.L mt_E_JumpList(PC,D0.W),A4 954 | JMP (A4) ; every E-efx has RTS at the end, this is safe 955 | 956 | mt_FilterOnOff 957 | TST.B mt_Counter 958 | BNE.W mt_Return3 959 | MOVE.B n_cmdlo(A6),D0 960 | AND.B #1,D0 961 | ADD.B D0,D0 962 | AND.B #$FD,$BFE001 963 | OR.B D0,$BFE001 964 | RTS 965 | 966 | mt_SetGlissControl 967 | MOVE.B n_cmdlo(A6),D0 968 | AND.B #$0F,D0 969 | AND.B #$F0,n_glissfunk(A6) 970 | OR.B D0,n_glissfunk(A6) 971 | RTS 972 | 973 | mt_SetVibratoControl 974 | MOVE.B n_cmdlo(A6),D0 975 | AND.B #$0F,D0 976 | AND.B #$F0,n_wavecontrol(A6) 977 | OR.B D0,n_wavecontrol(A6) 978 | RTS 979 | 980 | mt_SetFineTune 981 | MOVEQ #0,D0 982 | MOVE.B n_cmdlo(A6),D0 983 | AND.B #$0F,D0 984 | MOVE.B D0,n_finetune(A6) 985 | ; ---------------------------------- 986 | LSL.B #2,D0 ; update n_peroffset 987 | LEA mt_ftunePerTab(PC),A4 988 | MOVE.L (A4,D0.W),n_peroffset(A6) 989 | ; ---------------------------------- 990 | RTS 991 | 992 | mt_JumpLoop 993 | TST.B mt_Counter 994 | BNE.W mt_Return3 995 | MOVE.B n_cmdlo(A6),D0 996 | AND.B #$0F,D0 997 | BEQ.B mt_SetLoop 998 | TST.B n_loopcount(A6) 999 | BEQ.B mt_jumpcnt 1000 | SUBQ.B #1,n_loopcount(A6) 1001 | BEQ.W mt_Return3 1002 | mt_jmploop 1003 | MOVE.B n_pattpos(A6),mt_PBreakPos 1004 | ST mt_PBreakFlag 1005 | RTS 1006 | 1007 | mt_jumpcnt 1008 | MOVE.B D0,n_loopcount(A6) 1009 | BRA.B mt_jmploop 1010 | 1011 | mt_SetLoop 1012 | MOVE.W mt_PatternPos(PC),D0 1013 | LSR.W #4,D0 1014 | AND.B #63,D0 1015 | MOVE.B D0,n_pattpos(A6) 1016 | RTS 1017 | 1018 | mt_SetTremoloControl 1019 | MOVE.B n_cmdlo(A6),D0 1020 | AND.B #$0F,D0 1021 | LSL.B #4,D0 1022 | AND.B #$0F,n_wavecontrol(A6) 1023 | OR.B D0,n_wavecontrol(A6) 1024 | RTS 1025 | 1026 | mt_KarplusStrong 1027 | RTS 1028 | 1029 | mt_RetrigNote 1030 | MOVEQ #0,D0 1031 | MOVE.B n_cmdlo(A6),D0 1032 | AND.B #$0F,D0 1033 | BEQ.B mt_rtnend 1034 | MOVEQ #0,D1 1035 | MOVE.B mt_Counter(PC),D1 1036 | BNE.B mt_rtnskp 1037 | MOVE.W n_note(A6),D1 1038 | AND.W #$0FFF,D1 1039 | BNE.B mt_rtnend 1040 | MOVEQ #0,D1 1041 | MOVE.B mt_Counter(PC),D1 1042 | mt_rtnskp 1043 | AND.B #$1F,D1 ; just in case 1044 | LSL.W #5,D0 1045 | ADD.W D0,D1 1046 | MOVE.B mt_RetrigTab(PC,D1.W),D0 1047 | BNE.B mt_rtnend 1048 | mt_DoRetrig 1049 | MOVE.W n_dmabit(A6),$DFF096 ; Channel DMA off 1050 | MOVE.L n_start(A6),(A5) ; Set sampledata pointer 1051 | MOVE.W n_length(A6),4(A5) ; Set length 1052 | MOVE.W n_period(A6),6(A5) ; Set period 1053 | 1054 | ; scanline-wait (wait before starting Paula DMA) 1055 | LEA $DFF006,A0 1056 | MOVEQ #7-1,D1 1057 | lineloop3 1058 | MOVE.B (A0),D0 1059 | waiteol3 1060 | CMP.B (A0),D0 1061 | BEQ.B waiteol3 1062 | DBRA D1,lineloop3 1063 | 1064 | MOVE.W n_dmabit(A6),D0 1065 | BSET #15,D0 ; Set bits 1066 | MOVE.W D0,$DFF096 1067 | 1068 | ; scanline-wait (wait for Paula DMA to latch) 1069 | MOVEQ #7-1,D1 1070 | lineloop4 1071 | MOVE.B (A0),D0 1072 | waiteol4 1073 | CMP.B (A0),D0 1074 | BEQ.B waiteol4 1075 | DBRA D1,lineloop4 1076 | 1077 | MOVE.L n_loopstart(A6),(A5) 1078 | MOVE.W n_replen(A6),4(A5) 1079 | mt_rtnend 1080 | RTS 1081 | 1082 | ; DIV -> LUT optimization. Maybe a bit extreme, but DIVU is 140+ 1083 | ; cycles on a 68000. 1084 | mt_RetrigTab 1085 | dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1086 | dc.b 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 1087 | dc.b 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1 1088 | dc.b 0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1,1,0,1 1089 | dc.b 0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1 1090 | dc.b 0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1,1,1,1,0,1 1091 | dc.b 0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1,1,1,1,1,0,1 1092 | dc.b 0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1,1,1,1,0,1,1,1 1093 | dc.b 0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1 1094 | dc.b 0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,0,1,1,1,1 1095 | dc.b 0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,0,1 1096 | dc.b 0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1 1097 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1 1098 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1 1099 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1 1100 | dc.b 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1 1101 | 1102 | mt_VolumeFineUp 1103 | TST.B mt_Counter 1104 | BNE.W mt_Return3 1105 | MOVEQ #0,D0 1106 | MOVE.B n_cmdlo(A6),D0 1107 | AND.B #$F,D0 1108 | BRA.W mt_VolSlideUp 1109 | 1110 | mt_VolumeFineDown 1111 | TST.B mt_Counter 1112 | BNE.W mt_Return3 1113 | MOVEQ #0,D0 1114 | MOVE.B n_cmdlo(A6),D0 1115 | AND.B #$0F,D0 1116 | BRA.W mt_VolSlideDown2 1117 | 1118 | mt_NoteCut 1119 | MOVEQ #0,D0 1120 | MOVE.B n_cmdlo(A6),D0 1121 | AND.B #$0F,D0 1122 | CMP.B mt_Counter(PC),D0 1123 | BNE.W mt_Return3 1124 | CLR.B n_volume(A6) 1125 | RTS 1126 | 1127 | mt_NoteDelay 1128 | MOVEQ #0,D0 1129 | MOVE.B n_cmdlo(A6),D0 1130 | AND.B #$0F,D0 1131 | CMP.B mt_Counter,D0 1132 | BNE.W mt_Return3 1133 | MOVE.W (A6),D0 1134 | AND.W #$0FFF,D0 1135 | BEQ.W mt_Return3 1136 | BRA.W mt_DoRetrig 1137 | 1138 | mt_PatternDelay 1139 | TST.B mt_Counter 1140 | BNE.W mt_Return3 1141 | MOVEQ #0,D0 1142 | MOVE.B n_cmdlo(A6),D0 1143 | AND.B #$0F,D0 1144 | TST.B mt_PattDelayTime2 1145 | BNE.W mt_Return3 1146 | ADDQ.B #1,D0 1147 | MOVE.B D0,mt_PattDelayTime 1148 | RTS 1149 | 1150 | mt_FunkIt 1151 | TST.B mt_Counter 1152 | BNE.W mt_Return3 1153 | MOVE.B n_cmdlo(A6),D0 1154 | AND.B #$0F,D0 1155 | LSL.B #4,D0 1156 | AND.B #$0F,n_glissfunk(A6) 1157 | OR.B D0,n_glissfunk(A6) 1158 | TST.B D0 1159 | BEQ.W mt_Return3 1160 | mt_UpdateFunk 1161 | MOVEQ #0,D0 1162 | MOVE.B n_glissfunk(A6),D0 1163 | LSR.B #4,D0 1164 | BEQ.B mt_funkend 1165 | LEA mt_FunkTable(PC),A0 1166 | MOVE.B (A0,D0.W),D0 1167 | ADD.B D0,n_funkoffset(A6) 1168 | BTST #7,n_funkoffset(A6) 1169 | BEQ.B mt_funkend 1170 | CLR.B n_funkoffset(A6) 1171 | MOVE.L n_wavestart(A6),A0 1172 | CMP.L #0,A0 1173 | BEQ.B mt_funkend 1174 | MOVE.L n_loopstart(A6),D0 1175 | MOVEQ #0,D1 1176 | MOVE.W n_replen(A6),D1 1177 | ADD.L D1,D0 1178 | ADD.L D1,D0 1179 | ADDQ.L #1,A0 1180 | CMP.L D0,A0 1181 | BLO.B mt_funkok 1182 | MOVE.L n_loopstart(A6),A0 1183 | mt_funkok 1184 | MOVE.L A0,n_wavestart(A6) 1185 | MOVEQ #-1,D0 1186 | SUB.B (A0),D0 1187 | MOVE.B D0,(A0) 1188 | mt_funkend 1189 | RTS 1190 | 1191 | mt_FunkTable 1192 | dc.b 0,5,6,7,8,10,11,13,16,19,22,26,32,43,64,128 1193 | 1194 | mt_VibratoTable 1195 | dc.b 0, 24, 49, 74, 97,120,141,161 1196 | dc.b 180,197,212,224,235,244,250,253 1197 | dc.b 255,253,250,244,235,224,212,197 1198 | dc.b 180,161,141,120, 97, 74, 49, 24 1199 | 1200 | ; this LUT prevents MULU for getting correct period section 1201 | CNOP 0,4 1202 | mt_ftunePerTab 1203 | dc.l mt_ftune0,mt_ftune1,mt_ftune2,mt_ftune3 1204 | dc.l mt_ftune4,mt_ftune5,mt_ftune6,mt_ftune7 1205 | dc.l mt_ftune8,mt_ftune9,mt_ftuneA,mt_ftuneB 1206 | dc.l mt_ftuneC,mt_ftuneD,mt_ftuneE,mt_ftuneF 1207 | 1208 | mt_PeriodTable 1209 | ; Tuning 0, Normal 1210 | mt_ftune0 1211 | dc.w 856,808,762,720,678,640,604,570,538,508,480,453 1212 | dc.w 428,404,381,360,339,320,302,285,269,254,240,226 1213 | dc.w 214,202,190,180,170,160,151,143,135,127,120,113,0 1214 | ; Tuning 1 1215 | mt_ftune1 1216 | dc.w 850,802,757,715,674,637,601,567,535,505,477,450 1217 | dc.w 425,401,379,357,337,318,300,284,268,253,239,225 1218 | dc.w 213,201,189,179,169,159,150,142,134,126,119,113,0 1219 | ; Tuning 2 1220 | mt_ftune2 1221 | dc.w 844,796,752,709,670,632,597,563,532,502,474,447 1222 | dc.w 422,398,376,355,335,316,298,282,266,251,237,224 1223 | dc.w 211,199,188,177,167,158,149,141,133,125,118,112,0 1224 | ; Tuning 3 1225 | mt_ftune3 1226 | dc.w 838,791,746,704,665,628,592,559,528,498,470,444 1227 | dc.w 419,395,373,352,332,314,296,280,264,249,235,222 1228 | dc.w 209,198,187,176,166,157,148,140,132,125,118,111,0 1229 | ; Tuning 4 1230 | mt_ftune4 1231 | dc.w 832,785,741,699,660,623,588,555,524,495,467,441 1232 | dc.w 416,392,370,350,330,312,294,278,262,247,233,220 1233 | dc.w 208,196,185,175,165,156,147,139,131,124,117,110,0 1234 | ; Tuning 5 1235 | mt_ftune5 1236 | dc.w 826,779,736,694,655,619,584,551,520,491,463,437 1237 | dc.w 413,390,368,347,328,309,292,276,260,245,232,219 1238 | dc.w 206,195,184,174,164,155,146,138,130,123,116,109,0 1239 | ; Tuning 6 1240 | mt_ftune6 1241 | dc.w 820,774,730,689,651,614,580,547,516,487,460,434 1242 | dc.w 410,387,365,345,325,307,290,274,258,244,230,217 1243 | dc.w 205,193,183,172,163,154,145,137,129,122,115,109,0 1244 | ; Tuning 7 1245 | mt_ftune7 1246 | dc.w 814,768,725,684,646,610,575,543,513,484,457,431 1247 | dc.w 407,384,363,342,323,305,288,272,256,242,228,216 1248 | dc.w 204,192,181,171,161,152,144,136,128,121,114,108,0 1249 | ; Tuning -8 1250 | mt_ftune8 1251 | dc.w 907,856,808,762,720,678,640,604,570,538,508,480 1252 | dc.w 453,428,404,381,360,339,320,302,285,269,254,240 1253 | dc.w 226,214,202,190,180,170,160,151,143,135,127,120,0 1254 | ; Tuning -7 1255 | mt_ftune9 1256 | dc.w 900,850,802,757,715,675,636,601,567,535,505,477 1257 | dc.w 450,425,401,379,357,337,318,300,284,268,253,238 1258 | dc.w 225,212,200,189,179,169,159,150,142,134,126,119,0 1259 | ; Tuning -6 1260 | mt_ftuneA 1261 | dc.w 894,844,796,752,709,670,632,597,563,532,502,474 1262 | dc.w 447,422,398,376,355,335,316,298,282,266,251,237 1263 | dc.w 223,211,199,188,177,167,158,149,141,133,125,118,0 1264 | ; Tuning -5 1265 | mt_ftuneB 1266 | dc.w 887,838,791,746,704,665,628,592,559,528,498,470 1267 | dc.w 444,419,395,373,352,332,314,296,280,264,249,235 1268 | dc.w 222,209,198,187,176,166,157,148,140,132,125,118,0 1269 | ; Tuning -4 1270 | mt_ftuneC 1271 | dc.w 881,832,785,741,699,660,623,588,555,524,494,467 1272 | dc.w 441,416,392,370,350,330,312,294,278,262,247,233 1273 | dc.w 220,208,196,185,175,165,156,147,139,131,123,117,0 1274 | ; Tuning -3 1275 | mt_ftuneD 1276 | dc.w 875,826,779,736,694,655,619,584,551,520,491,463 1277 | dc.w 437,413,390,368,347,328,309,292,276,260,245,232 1278 | dc.w 219,206,195,184,174,164,155,146,138,130,123,116,0 1279 | ; Tuning -2 1280 | mt_ftuneE 1281 | dc.w 868,820,774,730,689,651,614,580,547,516,487,460 1282 | dc.w 434,410,387,365,345,325,307,290,274,258,244,230 1283 | dc.w 217,205,193,183,172,163,154,145,137,129,122,115,0 1284 | ; Tuning -1 1285 | mt_ftuneF 1286 | dc.w 862,814,768,725,684,646,610,575,543,513,484,457 1287 | dc.w 431,407,384,363,342,323,305,288,272,256,242,228 1288 | dc.w 216,203,192,181,171,161,152,144,136,128,121,114,0 1289 | ; ------------------------------------------------------ 1290 | ; Overflow bytes from CursorPosTable and UnshiftedKeymap 1291 | ; LUTs so that overflown arpeggio at finetune -1 sounds 1292 | ; right even if this table was to be moved. 1293 | ; ------------------------------------------------------ 1294 | dc.w 774,1800,2314,3087,4113,4627,5400,6426,6940,7713 1295 | dc.w 8739,9253,24625,12851,13365 1296 | 1297 | CNOP 0,4 1298 | mt_audchan1temp dcb.b 26 1299 | dc.w $0001 ; voice #1 DMA bit 1300 | dcb.b 16 1301 | CNOP 0,4 1302 | mt_audchan2temp dcb.b 26 1303 | dc.w $0002 ; voice #2 DMA bit 1304 | dcb.b 16 1305 | CNOP 0,4 1306 | mt_audchan3temp dcb.b 26 1307 | dc.w $0004 ; voice #3 DMA bit 1308 | dcb.b 16 1309 | CNOP 0,4 1310 | mt_audchan4temp dcb.b 26 1311 | dc.w $0008 ; voice #4 DMA bit 1312 | dcb.b 16 1313 | 1314 | CNOP 0,4 1315 | mt_SampleStarts dcb.l 31,0 1316 | mt_SongDataPtr dc.l 0 1317 | mt_SampleStructPtr dc.l 0 1318 | mt_PatternPtr dc.l 0 1319 | mt_PatternPos dc.w 0 1320 | mt_DMACONtemp dc.w 0 1321 | mt_SongLength dc.b 0 1322 | mt_Speed dc.b 6 1323 | mt_Counter dc.b 0 1324 | mt_SongPos dc.b 0 1325 | mt_PBreakPos dc.b 0 1326 | mt_PosJumpFlag dc.b 0 1327 | mt_PBreakFlag dc.b 0 1328 | mt_LowMask dc.b $FF 1329 | mt_PattDelayTime dc.b 0 1330 | mt_PattDelayTime2 dc.b 0 1331 | 1332 | SECTION music,DATA_C 1333 | 1334 | CNOP 0,4 1335 | mt_data INCBIN "music.mod" 1336 | 1337 | ;/* End of File */ 1338 | --------------------------------------------------------------------------------