Merge branch 'master' of https://github.com/tildearrow/furnace into esfm
| 
						 | 
				
			
			@ -16,7 +16,7 @@ set(CMAKE_CXX_EXTENSIONS OFF)
 | 
			
		|||
 | 
			
		||||
set(CMAKE_PROJECT_VERSION_MAJOR 0)
 | 
			
		||||
set(CMAKE_PROJECT_VERSION_MINOR 6)
 | 
			
		||||
set(CMAKE_PROJECT_VERSION_PATCH 0)
 | 
			
		||||
set(CMAKE_PROJECT_VERSION_PATCH 1)
 | 
			
		||||
 | 
			
		||||
set(BUILD_GUI_DEFAULT ON)
 | 
			
		||||
set(USE_SDL2_DEFAULT ON)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ for other operating systems, you may [build the source](#developer-info).
 | 
			
		|||
    - YM3812 (OPL2)
 | 
			
		||||
    - YMF262 (OPL3) with full 4-op support!
 | 
			
		||||
    - Y8950 (OPL with ADPCM)
 | 
			
		||||
  - ESS ESFM (like OPL3 but with more features)
 | 
			
		||||
  - square wave chips:
 | 
			
		||||
    - AY-3-8910/YM2149(F) used in several computers and game consoles
 | 
			
		||||
    - Commodore VIC used in the VIC-20
 | 
			
		||||
| 
						 | 
				
			
			@ -86,6 +87,7 @@ for other operating systems, you may [build the source](#developer-info).
 | 
			
		|||
  - modern/fantasy:
 | 
			
		||||
    - Commander X16 VERA
 | 
			
		||||
    - tildearrow Sound Unit
 | 
			
		||||
    - PowerNoise
 | 
			
		||||
    - Generic PCM DAC
 | 
			
		||||
- mix and match sound chips!
 | 
			
		||||
  - over 200 ready to use presets from computers, game consoles and arcade boards...
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										8
									
								
								TODO.md
									
									
									
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -1,13 +1,5 @@
 | 
			
		|||
# to-do
 | 
			
		||||
 | 
			
		||||
- finish color import improvements (settings refactor)
 | 
			
		||||
- new undo stuff
 | 
			
		||||
- fix some bugs
 | 
			
		||||
- finish auto-clone
 | 
			
		||||
 | 
			
		||||
once you have done all of this (maybe not the first one), release 0.6.1
 | 
			
		||||
 | 
			
		||||
# and then
 | 
			
		||||
 | 
			
		||||
- new oscilloscope renderer - custom code that uses texture and fixes two issues: too many vertices, and broken anti-aliasing
 | 
			
		||||
- new pattern renderer - performance improvements
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,8 +15,8 @@ android {
 | 
			
		|||
        }
 | 
			
		||||
        minSdkVersion 21
 | 
			
		||||
        targetSdkVersion 26
 | 
			
		||||
        versionCode 181
 | 
			
		||||
        versionName "0.6"
 | 
			
		||||
        versionCode 192
 | 
			
		||||
        versionName "0.6.1"
 | 
			
		||||
        externalNativeBuild {
 | 
			
		||||
            cmake {
 | 
			
		||||
                arguments "-DANDROID_APP_PLATFORM=android-21", "-DANDROID_STL=c++_static", "-DWARNINGS_ARE_ERRORS=ON"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
 | 
			
		||||
    package="org.tildearrow.furnace"
 | 
			
		||||
    android:versionCode="181"
 | 
			
		||||
    android:versionName="0.6"
 | 
			
		||||
    android:versionCode="192"
 | 
			
		||||
    android:versionName="0.6.1"
 | 
			
		||||
    android:installLocation="auto">
 | 
			
		||||
 | 
			
		||||
    <!-- OpenGL ES 2.0 -->
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								demos/amiga/trance_dream.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/ay8930/One_Minute_Waltz.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/ay8930/Playing_On_The_Stairs.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/AAAA.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/ALCATRAZ_ALWAYS.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/CampingJourney.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Deadline.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Devil_Detective.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Drinkin_Coffee_Way_Too_Much.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/EdgeRunning_2078.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Fighting_the_Dimensions_Big_Bad_Because_its_Fun.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/I_Cant_Escape_Your_Memory.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Just_me_and_my_Brain.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Ken_Stage.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Magician_Lake_Cover.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Napalm-Loader.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Perilous059.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Poets_I.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Redial.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/SearchPrincess.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Second_Start.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Strange_Sunset.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Tangent_to_a_Segue.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/TheOneWayFuture.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Unconscious_Unravelling.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/Unknown_Location.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/WalkInThePark.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/act_of_fighter.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/cielos_esfumados.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/esfm_ins.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/experiment.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/flashback.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/frosty_dusk.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/haunted_castle.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/her_wishes.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/ledstorm.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/loneguitarist.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/moon_closedspace.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/sticker1.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/synthy.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/wack.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/esfm/x_evil_soul.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/misc/Playground_2xT6W28.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/misc/Someting_I_can_feel_MSM5232.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/misc/T_Six_T6W28.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/msx/Morning_Alarm.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/multichip/Chip_Duel_AY-3-8910+SN76489.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/nes/Fur_Nes.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/specs2/back_into_adventure.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						
							
								
								
									
										
											BIN
										
									
								
								demos/specs2/spa.fur
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -9,10 +9,8 @@ alternatively, window > instrument editor displays it.
 | 
			
		|||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
**TODO: add descriptions to buttons in the image. it really needs them.**
 | 
			
		||||
 | 
			
		||||
- **Instrument Selector**: displays a list of instruments in the song.
 | 
			
		||||
- **Open**: open an instrument file.
 | 
			
		||||
- **Select**: displays a list of instruments in the song.
 | 
			
		||||
- **Load**: open an instrument file.
 | 
			
		||||
- **Save**: save current instrument to a file.
 | 
			
		||||
  - right-click to see additional options, such as saving in DefleMask preset format (.dmp).
 | 
			
		||||
- **Name**: changes the instrument name.
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +74,7 @@ the following instrument types are available:
 | 
			
		|||
- [TED](ted.md) - for use with Commodore Plus/4 and Commodore 16's TED chip.
 | 
			
		||||
- [C140](c140.md) - for use with C140 sample chip.
 | 
			
		||||
- [C219](c219.md) - for use with C219 sample chip.
 | 
			
		||||
- [PowerNoise](powernoise.md) - for use with PowerNoise chip.
 | 
			
		||||
 | 
			
		||||
## macros
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -93,9 +92,6 @@ each macro has the following parameters:
 | 
			
		|||
  - **Step Length (ticks)**: determines the number of ticks between macro steps. default is 1.
 | 
			
		||||
  - **Delay**: delays the macro until this many ticks have elapsed. default is 0.
 | 
			
		||||
  - the button is highlighted if either of these parameters is set to non-default values.
 | 
			
		||||
- release mode: determines how macro release (`===` or `REL` in the pattern) is handled:
 | 
			
		||||
  - **Active**: jumps to release position on release.
 | 
			
		||||
  - **Passive**: does not jump to release position. this will result in delay if release position has not been reached yet.
 | 
			
		||||
 | 
			
		||||
## macro types
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,8 +111,6 @@ this is the most basic macro type. when the instrument is played, every value in
 | 
			
		|||
 | 
			
		||||

 | 
			
		||||
 | 
			
		||||
**TODO: once again, text in the image. this sucks.**
 | 
			
		||||
 | 
			
		||||
the Length field allows you to set the number of steps in the sequence.
 | 
			
		||||
 | 
			
		||||
the sequence view allows you to edit the macro.
 | 
			
		||||
| 
						 | 
				
			
			@ -171,6 +165,10 @@ the sequence can be edited in the text input field at the very bottom. the follo
 | 
			
		|||
 | 
			
		||||
in bitmask-style macros, the values are added up in binary and converted to decimal.
 | 
			
		||||
 | 
			
		||||
the release mode parameter determines how macro release (`===` or `REL` in the pattern) is handled:
 | 
			
		||||
- **Active**: jumps to release position on release.
 | 
			
		||||
- **Passive**: does not jump to release position. this will result in delay if release position has not been reached yet.
 | 
			
		||||
 | 
			
		||||
### ADSR
 | 
			
		||||
 | 
			
		||||

 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		 Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 39 KiB  | 
| 
						 | 
				
			
			@ -24,6 +24,20 @@ note that using samples on Lynx is CPU expensive!
 | 
			
		|||
 | 
			
		||||
Atari Lynx generates sound using a 12-bit linear feedback shift register with configurable tap. nine separate bits can be enabled to be the source of feedback: 0, 1, 2, 3, 4, 5, 7, 10 and 11. to generate _any_ sound at least one bit _must_ be enabled.
 | 
			
		||||
 | 
			
		||||
### LFSR-based synthesis
 | 
			
		||||
 | 
			
		||||
a linear-feedback shift register is one method used for random number generation.
 | 
			
		||||
it works by shifting a sequence of binary numbers (bits), taking the last bit into the output. then some of the bits are combined with others, doing a XOR (exclusive or) operation and then being pushed back.
 | 
			
		||||
 | 
			
		||||
think of it as a conveyor carrying glass bottles. each bottle may be empty or carrying water.
 | 
			
		||||
the bottle at the end is taken. if there's water, then the output is 1. if it's empty, the output is 0.
 | 
			
		||||
depending on the LFSR configuration, many bottles at specific positions ("taps") are looked at. these are combined from left to right, two by two:
 | 
			
		||||
- if two bottles are identical, an empty bottle is pushed.
 | 
			
		||||
- if one bottle has water but the other is empty, a water bottle is pushed.
 | 
			
		||||
the process is repeated indefinitely.
 | 
			
		||||
 | 
			
		||||
unlike PowerNoise, Lynx's taps are in fixed positions, but it has many of them.
 | 
			
		||||
 | 
			
		||||
### square wave
 | 
			
		||||
 | 
			
		||||
the LFSR is shifted at the rate define by sound pitch and generates square wave by setting channel output value to +volume or -volume, depending on the bit shifted in.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
		 Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 38 KiB  | 
| 
		 Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 50 KiB  | 
| 
		 Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 78 KiB  | 
| 
		 Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 78 KiB  | 
| 
						 | 
				
			
			@ -15,7 +15,7 @@ depending on the LFSR configuration:
 | 
			
		|||
- a bottle is pushed into the conveyor. it is either empty or filled with water depending on the bottle at a specific position in the conveyor (this is called a "tap"), or
 | 
			
		||||
- two bottles at specific positions ("taps") are looked at and combined as follows:
 | 
			
		||||
  - if the bottles are identical, an empty bottle is pushed.
 | 
			
		||||
  - if one bottle has water but the other is empty, a watee bottle is pushed.
 | 
			
		||||
  - if one bottle has water but the other is empty, a water bottle is pushed.
 | 
			
		||||
the process is repeated indefinitely.
 | 
			
		||||
 | 
			
		||||
PowerNoise uses either one or two taps for the LFSR, configurable via the Control macro.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -90,6 +90,7 @@ this is the full list of chips that Furnace supports.
 | 
			
		|||
- [PET](pet.md)
 | 
			
		||||
- [Pokémon Mini](pokemini.md)
 | 
			
		||||
- [POKEY](pokey.md)
 | 
			
		||||
- [PowerNoise](powernoise.md)
 | 
			
		||||
- [PV-1000](pv1000.md)
 | 
			
		||||
- [QSound](qsound.md)
 | 
			
		||||
- [RF5C68/RF5C164](ricoh.md)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										2
									
								
								extern/YMF262-LLE/fmopl3.c
									
									
									
									
										vendored
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -1442,6 +1442,8 @@ void FMOPL3_Clock(fmopl3_t *chip)
 | 
			
		|||
 | 
			
		||||
            int sign;
 | 
			
		||||
 | 
			
		||||
            chip->op_value_debug = chip->op_value;
 | 
			
		||||
 | 
			
		||||
            int accm_a = chip->fsm_out[6] ? 0 : chip->accm_a[1];
 | 
			
		||||
            accm_a += (chip->pan_l[1][1] & 1) != 0 ? value : 0;
 | 
			
		||||
            chip->accm_a[0] = accm_a;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										1
									
								
								extern/YMF262-LLE/fmopl3.h
									
									
									
									
										vendored
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -297,6 +297,7 @@ typedef struct
 | 
			
		|||
    int op_mod[2];
 | 
			
		||||
 | 
			
		||||
    int op_value;
 | 
			
		||||
    int op_value_debug;
 | 
			
		||||
 | 
			
		||||
    int accm_a[2];
 | 
			
		||||
    int accm_b[2];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										4
									
								
								extern/backward/backward.hpp
									
									
									
									
										vendored
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -4253,7 +4253,7 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    MessageBox(NULL,"Error","Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.",MB_OK|MB_ICONERROR);
 | 
			
		||||
    MessageBox(NULL,"Error","Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.\r\n\r\nif Furnace keeps crashing and you believe it is caused by a configuration problem, you may start Furnace with the -safemode parameter.",MB_OK|MB_ICONERROR);
 | 
			
		||||
    std::string crashLocation;
 | 
			
		||||
    char* userProfile=getenv("USERPROFILE");
 | 
			
		||||
    if (userProfile==NULL) {
 | 
			
		||||
| 
						 | 
				
			
			@ -4492,7 +4492,7 @@ private:
 | 
			
		|||
    printer.print(st, std::cerr);
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
    MessageBox(NULL,"Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.","Error",MB_OK|MB_ICONERROR);
 | 
			
		||||
    MessageBox(NULL,"Furnace has crashed! please report this to the issue tracker immediately:\r\nhttps://github.com/tildearrow/furnace/issues/new\r\n\r\na file called furnace_crash.txt will be created in your user directory.\r\nthis will be important for locating the origin of the crash.\r\n\r\nif Furnace keeps crashing and you believe it is caused by a configuration problem, you may start Furnace with the -safemode parameter.","Error",MB_OK|MB_ICONERROR);
 | 
			
		||||
    std::string crashLocation;
 | 
			
		||||
    char* userProfile=getenv("USERPROFILE");
 | 
			
		||||
    if (userProfile==NULL) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -6,7 +6,7 @@ when copying pattern data from Furnace, it's stored in the clipboard as plain te
 | 
			
		|||
org.tildearrow.furnace - Pattern Data (144)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
this top line of text is always the same except for the number in parentheses, which is the internal build number. for example, 0.6 is `181`.
 | 
			
		||||
this top line of text is always the same except for the number in parentheses, which is the internal build number. for example, 0.6.1 is `192`.
 | 
			
		||||
 | 
			
		||||
the second line is a number between 0 and 18 (decimal) which indicates which column the clip starts from.
 | 
			
		||||
- `0`: note.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@ these fields are 0 in format versions prior to 100 (0.6pre1).
 | 
			
		|||
 | 
			
		||||
the format versions are:
 | 
			
		||||
 | 
			
		||||
- 192: Furnace 0.6.1
 | 
			
		||||
- 181: Furnace 0.6
 | 
			
		||||
- 180: Furnace 0.6pre18
 | 
			
		||||
- 179: Furnace 0.6pre17
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,17 +15,17 @@
 | 
			
		|||
	<key>CFBundleInfoDictionaryVersion</key>
 | 
			
		||||
	<string>6.0</string>
 | 
			
		||||
	<key>CFBundleLongVersionString</key>
 | 
			
		||||
	<string>0.6</string>
 | 
			
		||||
	<string>0.6.1</string>
 | 
			
		||||
	<key>CFBundleName</key>
 | 
			
		||||
	<string>Furnace</string>
 | 
			
		||||
	<key>CFBundlePackageType</key>
 | 
			
		||||
	<string>APPL</string>
 | 
			
		||||
	<key>CFBundleShortVersionString</key>
 | 
			
		||||
	<string>0.6</string>
 | 
			
		||||
	<string>0.6.1</string>
 | 
			
		||||
	<key>CFBundleSignature</key>
 | 
			
		||||
	<string>????</string>
 | 
			
		||||
	<key>CFBundleVersion</key>
 | 
			
		||||
	<string>0.6</string>
 | 
			
		||||
	<string>0.6.1</string>
 | 
			
		||||
	<key>NSHumanReadableCopyright</key>
 | 
			
		||||
	<string></string>
 | 
			
		||||
	<key>NSHighResolutionCapable</key>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -325,7 +325,7 @@ if __name__ == "__main__":
 | 
			
		|||
            <h1>Furnace<br/>User Manual</h1>
 | 
			
		||||
          </div>
 | 
			
		||||
          <div>
 | 
			
		||||
            <i>for version 0.6</i>
 | 
			
		||||
            <i>for version 0.6.1</i>
 | 
			
		||||
          </div>
 | 
			
		||||
        </section>
 | 
			
		||||
        <section id="authors">
 | 
			
		||||
| 
						 | 
				
			
			@ -348,7 +348,7 @@ if __name__ == "__main__":
 | 
			
		|||
            <p>this documentation is under the <a href="https://creativecommons.org/licenses/by/3.0/">Creative Commons Attribution 3.0 Unported</a> license.</p>
 | 
			
		||||
            <p>you may reproduce, modify and/or distribute this documentation provided this copyright notice (including license and attribution) is present and any necessary disclaimers whether modifications have been made.</p>
 | 
			
		||||
            <p>this documentation is provided as-is and without warranty of any kind.</p>
 | 
			
		||||
            <p>this manual is written for version 0.6 of Furnace.<br/>it may not necessarily apply to previous or future versions.</p>
 | 
			
		||||
            <p>this manual is written for version 0.6.1 of Furnace.<br/>it may not necessarily apply to previous or future versions.</p>
 | 
			
		||||
        </section>
 | 
			
		||||
        <section id="index">
 | 
			
		||||
          %s
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,10 @@
 | 
			
		|||
  
 | 
			
		||||
  <name>Furnace</name>
 | 
			
		||||
  <summary>Open-source chiptune tracker</summary>
 | 
			
		||||
  <developer id="tildearrow.org">
 | 
			
		||||
    <name>tildearrow and contributors</name>
 | 
			
		||||
  </developer>
 | 
			
		||||
  <developer_name>tildearrow and contributors</developer_name>
 | 
			
		||||
  <url type="homepage">https://github.com/tildearrow/furnace</url>
 | 
			
		||||
  
 | 
			
		||||
  <metadata_license>CC0-1.0</metadata_license>
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +36,8 @@
 | 
			
		|||
  <launchable type="desktop-id">furnace.desktop</launchable>
 | 
			
		||||
  <screenshots>
 | 
			
		||||
    <screenshot type="default">
 | 
			
		||||
      <image>https://tildearrow.org/storage/images/furnace.png</image>
 | 
			
		||||
      <caption>Furnace during playback</caption>
 | 
			
		||||
      <image>https://raw.githubusercontent.com/tildearrow/furnace/94cce861800c0473bdddb8270e462ebcdd18202a/papers/screenshot3.png</image>
 | 
			
		||||
    </screenshot>
 | 
			
		||||
  </screenshots>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										479
									
								
								res/icons.sfd
									
									
									
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -21,7 +21,7 @@ OS2Version: 0
 | 
			
		|||
OS2_WeightWidthSlopeOnly: 0
 | 
			
		||||
OS2_UseTypoMetrics: 0
 | 
			
		||||
CreationTime: 1691897631
 | 
			
		||||
ModificationTime: 1701817435
 | 
			
		||||
ModificationTime: 1706927377
 | 
			
		||||
PfmFamily: 81
 | 
			
		||||
TTFWeight: 400
 | 
			
		||||
TTFWidth: 5
 | 
			
		||||
| 
						 | 
				
			
			@ -47,13 +47,13 @@ LangName: 1033
 | 
			
		|||
Encoding: UnicodeBmp
 | 
			
		||||
UnicodeInterp: none
 | 
			
		||||
NameList: AGL For New Fonts
 | 
			
		||||
DisplaySize: -96
 | 
			
		||||
DisplaySize: -24
 | 
			
		||||
AntiAlias: 1
 | 
			
		||||
FitToEm: 0
 | 
			
		||||
WinInfo: 57672 8 5
 | 
			
		||||
WinInfo: 57540 21 12
 | 
			
		||||
BeginPrivate: 0
 | 
			
		||||
EndPrivate
 | 
			
		||||
BeginChars: 65536 96
 | 
			
		||||
BeginChars: 65536 98
 | 
			
		||||
 | 
			
		||||
StartChar: space
 | 
			
		||||
Encoding: 32 32 0
 | 
			
		||||
| 
						 | 
				
			
			@ -2270,15 +2270,15 @@ SplineSet
 | 
			
		|||
 1653.60449219 798.544921875 1681.75488281 781.904296875 1709.90625 765.263671875 c 1
 | 
			
		||||
 1688.8125 716.044921875 1660.609375 678.232421875 1625.453125 651.982421875 c 0
 | 
			
		||||
 1590.21875 625.732421875 1544.125 612.685546875 1487.171875 612.685546875 c 0xcbcd
 | 
			
		||||
1289.23339844 435.383789062 m 1
 | 
			
		||||
 1289.23339844 -25.1181640625 l 1
 | 
			
		||||
 1585.29882812 247.456054688 l 1
 | 
			
		||||
 1585.29882812 117.280273438 l 1
 | 
			
		||||
 1187.45410156 -248.998046875 l 1xd3ce
 | 
			
		||||
 1187.45410156 211.504882812 l 1
 | 
			
		||||
 891.388671875 -61.0693359375 l 1
 | 
			
		||||
 891.388671875 69.1064453125 l 1
 | 
			
		||||
 1289.23339844 435.383789062 l 1
 | 
			
		||||
1289.23339844 435.383789062 m 5
 | 
			
		||||
 1289.23339844 -25.1181640625 l 5
 | 
			
		||||
 1585.29882812 247.456054688 l 5
 | 
			
		||||
 1585.29882812 117.280273438 l 5
 | 
			
		||||
 1187.45410156 -248.998046875 l 5xd3ce
 | 
			
		||||
 1187.45410156 211.504882812 l 5
 | 
			
		||||
 891.388671875 -61.0693359375 l 5
 | 
			
		||||
 891.388671875 69.1064453125 l 5
 | 
			
		||||
 1289.23339844 435.383789062 l 5
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndChar
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -6736,54 +6736,8 @@ EndChar
 | 
			
		|||
StartChar: uniE159
 | 
			
		||||
Encoding: 57689 57689 95
 | 
			
		||||
Width: 1792
 | 
			
		||||
Flags: HWO
 | 
			
		||||
Flags: HW
 | 
			
		||||
LayerCount: 2
 | 
			
		||||
UndoRedoHistory
 | 
			
		||||
Layer: 0
 | 
			
		||||
Undoes
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 0
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 0
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 1
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
1632 70 m 1
 | 
			
		||||
 1632 -50 l 1025
 | 
			
		||||
160 1210 m 1
 | 
			
		||||
 160 1330 l 1025
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 1
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 0
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
160 1270 m 25
 | 
			
		||||
 160 1270 560 1270 896 640 c 0
 | 
			
		||||
 1232 10 1632 10 1632 10 c 1025
 | 
			
		||||
1632 70 m 5
 | 
			
		||||
 1632 -50 l 1029
 | 
			
		||||
160 1210 m 5
 | 
			
		||||
 160 1330 l 1029
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
EndUndoes
 | 
			
		||||
Redoes
 | 
			
		||||
EndRedoes
 | 
			
		||||
EndUndoRedoHistory
 | 
			
		||||
Back
 | 
			
		||||
SplineSet
 | 
			
		||||
160 1270 m 25
 | 
			
		||||
| 
						 | 
				
			
			@ -6794,314 +6748,6 @@ SplineSet
 | 
			
		|||
160 1210 m 1
 | 
			
		||||
 160 1330 l 1025
 | 
			
		||||
EndSplineSet
 | 
			
		||||
UndoRedoHistory
 | 
			
		||||
Layer: 1
 | 
			
		||||
Undoes
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 0
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
1632 1210.01171875 m 1
 | 
			
		||||
 1632 1329.98828125 l 1
 | 
			
		||||
 1619.75878906 1329.98828125 1193.45019531 1325.24316406 843.048828125 668.2421875 c 0
 | 
			
		||||
 755.229492188 503.581054688 663.75 384.705078125 577.82421875 298.780273438 c 0
 | 
			
		||||
 473.91796875 194.873046875 377.610351562 138.502929688 303.73046875 107.581054688 c 0
 | 
			
		||||
 262.674804688 90.396484375 228.48828125 81.078125 203.702148438 76.0087890625 c 0
 | 
			
		||||
 176.166992188 70.3779296875 160.23046875 70 159.536132812 69.986328125 c 1
 | 
			
		||||
 159.698242188 69.9873046875 160 69.98828125 160 69.98828125 c 1
 | 
			
		||||
 160 -49.98828125 l 1
 | 
			
		||||
 172.241210938 -49.98828125 598.549804688 -45.2431640625 948.951171875 611.7578125 c 0
 | 
			
		||||
 1036.77050781 776.418945312 1128.25 895.294921875 1214.17578125 981.219726562 c 0
 | 
			
		||||
 1318.08203125 1085.12695312 1414.38964844 1141.49707031 1488.26953125 1172.41894531 c 0
 | 
			
		||||
 1529.32519531 1189.60351562 1563.51171875 1198.921875 1588.29785156 1203.99121094 c 0
 | 
			
		||||
 1615.83300781 1209.62207031 1631.76953125 1210 1632.46386719 1210.01367188 c 1
 | 
			
		||||
 1632.30175781 1210.01269531 1632 1210.01171875 1632 1210.01171875 c 1
 | 
			
		||||
159.999999952 1210.01176537 m 1
 | 
			
		||||
 159.999999952 1329.98823463 l 1
 | 
			
		||||
 170.809951102 1329.98823463 504.536374276 1326.28810718 823.734604363 872.948478072 c 1
 | 
			
		||||
 800.889124326 837.280193024 778.251310121 799.419416229 755.928040313 759.232259114 c 1
 | 
			
		||||
 695.916689064 850.735795855 635.614260663 923.430234862 577.824293264 981.220202232 c 0
 | 
			
		||||
 473.917602143 1085.12689335 377.61065751 1141.49706263 303.730893464 1172.41936621 c 0
 | 
			
		||||
 262.674555191 1189.60345677 228.488523437 1198.92230209 203.702403502 1203.99126863 c 0
 | 
			
		||||
 176.167181121 1209.62244935 160.230079948 1210.00005891 159.536222574 1210.01396385 c 1
 | 
			
		||||
 159.698263781 1210.01275358 159.999999952 1210.01176537 159.999999952 1210.01176537 c 1
 | 
			
		||||
1632 1090.03515625 m 5
 | 
			
		||||
 1632 1449.96484375 l 5
 | 
			
		||||
 1558.47725996 1449.96484375 1167.58409474 1409.79522486 823.734604363 872.948478072 c 5
 | 
			
		||||
 865.988935134 812.936984165 907.988680731 745.046220598 948.951069976 668.241740764 c 4
 | 
			
		||||
 977.706682766 614.324966782 1006.85482384 565.317167145 1036.07195969 520.767740886 c 5
 | 
			
		||||
 1042.35821703 532.084488601 1048.61953126 543.58571637 1054.85351562 555.274414062 c 4
 | 
			
		||||
 1093.06152344 626.915039062 1265.13574219 948.919921875 1534.69042969 1061.74121094 c 4
 | 
			
		||||
 1536.87304688 1062.65429688 1591.23828125 1085.29492188 1632 1090.03515625 c 5
 | 
			
		||||
1036.07195969 520.767740886 m 1
 | 
			
		||||
 1096.08331094 429.264204145 1156.38573934 356.569765138 1214.17570674 298.779797768 c 0
 | 
			
		||||
 1318.08239786 194.873106647 1414.38934249 138.502937368 1488.26910654 107.580633787 c 0
 | 
			
		||||
 1529.32544481 90.3965432265 1563.51147656 81.0776979108 1588.2975965 76.0087313726 c 0
 | 
			
		||||
 1615.83281888 70.3775506458 1631.76992005 69.9999410877 1632.46377743 69.986036148 c 1
 | 
			
		||||
 1632.30173622 69.9872464204 1632.00000005 69.9882346324 1632.00000005 69.9882346324 c 1
 | 
			
		||||
 1632.00000005 -49.9882346324 l 1
 | 
			
		||||
 1621.1900489 -49.9882346324 1287.46362572 -46.2881071791 968.265395637 407.051521928 c 1
 | 
			
		||||
 991.110875674 442.719806976 1013.74868988 480.580583771 1036.07195969 520.767740886 c 1
 | 
			
		||||
968.265395637 407.051521928 m 5
 | 
			
		||||
 926.011064866 467.063015835 884.011319269 534.953779402 843.048930024 611.758259236 c 4
 | 
			
		||||
 814.293317234 665.675033218 785.145176159 714.682832855 755.928040313 759.232259114 c 5
 | 
			
		||||
 749.641782968 747.9155114 743.380468741 736.41428363 737.146484375 724.725585938 c 4
 | 
			
		||||
 698.938476562 653.084960938 526.864257812 331.080078125 257.309570312 218.258789062 c 4
 | 
			
		||||
 255.126953125 217.345703125 200.76171875 194.705078125 160 189.96484375 c 5
 | 
			
		||||
 160 -169.96484375 l 5
 | 
			
		||||
 233.522740042 -169.96484375 624.415905262 -129.795224857 968.265395637 407.051521928 c 5
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 1
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 0
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
1632 1090.03515625 m 5
 | 
			
		||||
 1632 1449.96484375 l 5
 | 
			
		||||
 1552.21679688 1449.96484375 1098.71386719 1402.66308594 737.146484375 724.725585938 c 4
 | 
			
		||||
 698.938476562 653.084960938 526.864257812 331.080078125 257.309570312 218.258789062 c 4
 | 
			
		||||
 255.126953125 217.345703125 200.76171875 194.705078125 160 189.96484375 c 5
 | 
			
		||||
 160 -169.96484375 l 5
 | 
			
		||||
 239.783203125 -169.96484375 693.286132812 -122.663085938 1054.85351562 555.274414062 c 4
 | 
			
		||||
 1093.06152344 626.915039062 1265.13574219 948.919921875 1534.69042969 1061.74121094 c 4
 | 
			
		||||
 1536.87304688 1062.65429688 1591.23828125 1085.29492188 1632 1090.03515625 c 5
 | 
			
		||||
1632 1210.01171875 m 1
 | 
			
		||||
 1632 1329.98828125 l 1
 | 
			
		||||
 1619.75878906 1329.98828125 1193.45019531 1325.24316406 843.048828125 668.2421875 c 0
 | 
			
		||||
 755.229492188 503.581054688 663.75 384.705078125 577.82421875 298.780273438 c 0
 | 
			
		||||
 473.91796875 194.873046875 377.610351562 138.502929688 303.73046875 107.581054688 c 0
 | 
			
		||||
 262.674804688 90.396484375 228.48828125 81.078125 203.702148438 76.0087890625 c 0
 | 
			
		||||
 176.166992188 70.3779296875 160.23046875 70 159.536132812 69.986328125 c 1
 | 
			
		||||
 159.698242188 69.9873046875 160 69.98828125 160 69.98828125 c 1
 | 
			
		||||
 160 -49.98828125 l 1
 | 
			
		||||
 172.241210938 -49.98828125 598.549804688 -45.2431640625 948.951171875 611.7578125 c 0
 | 
			
		||||
 1036.77050781 776.418945312 1128.25 895.294921875 1214.17578125 981.219726562 c 0
 | 
			
		||||
 1318.08203125 1085.12695312 1414.38964844 1141.49707031 1488.26953125 1172.41894531 c 0
 | 
			
		||||
 1529.32519531 1189.60351562 1563.51171875 1198.921875 1588.29785156 1203.99121094 c 0
 | 
			
		||||
 1615.83300781 1209.62207031 1631.76953125 1210 1632.46386719 1210.01367188 c 1
 | 
			
		||||
 1632.30175781 1210.01269531 1632 1210.01171875 1632 1210.01171875 c 1
 | 
			
		||||
159.999999952 1210.01176537 m 5
 | 
			
		||||
 159.999999952 1329.98823463 l 5
 | 
			
		||||
 172.240934135 1329.98823462 598.550052583 1325.24364837 948.951069976 668.241740764 c 4
 | 
			
		||||
 1036.77007573 503.581104976 1128.25010681 384.70539769 1214.17570674 298.779797768 c 4
 | 
			
		||||
 1318.08239786 194.873106647 1414.38934249 138.502937368 1488.26910654 107.580633787 c 4
 | 
			
		||||
 1529.32544481 90.3965432265 1563.51147656 81.0776979108 1588.2975965 76.0087313726 c 4
 | 
			
		||||
 1615.83281888 70.3775506458 1631.76992005 69.9999410877 1632.46377743 69.986036148 c 5
 | 
			
		||||
 1632.30173622 69.9872464204 1632.00000005 69.9882346324 1632.00000005 69.9882346324 c 5
 | 
			
		||||
 1632.00000005 -49.9882346324 l 5
 | 
			
		||||
 1619.75906587 -49.9882346228 1193.44994742 -45.2436483754 843.048930024 611.758259236 c 4
 | 
			
		||||
 755.229924271 776.418895024 663.749893187 895.29460231 577.824293264 981.220202232 c 4
 | 
			
		||||
 473.917602143 1085.12689335 377.61065751 1141.49706263 303.730893464 1172.41936621 c 4
 | 
			
		||||
 262.674555191 1189.60345677 228.488523437 1198.92230209 203.702403502 1203.99126863 c 4
 | 
			
		||||
 176.167181121 1209.62244935 160.230079948 1210.00005891 159.536222574 1210.01396385 c 5
 | 
			
		||||
 159.698263781 1210.01275358 159.999999952 1210.01176537 159.999999952 1210.01176537 c 5
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 2
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
160 1270 m 29
 | 
			
		||||
 160 1270 560 1270 896 640 c 4
 | 
			
		||||
 1232 10 1632 10 1632 10 c 1029
 | 
			
		||||
1632 1210.01171875 m 1
 | 
			
		||||
 1632 1329.98828125 l 1
 | 
			
		||||
 1619.75878906 1329.98828125 1193.45019531 1325.24316406 843.048828125 668.2421875 c 0
 | 
			
		||||
 755.229492188 503.581054688 663.75 384.705078125 577.82421875 298.780273438 c 0
 | 
			
		||||
 473.91796875 194.873046875 377.610351562 138.502929688 303.73046875 107.581054688 c 0
 | 
			
		||||
 262.674804688 90.396484375 228.48828125 81.078125 203.702148438 76.0087890625 c 0
 | 
			
		||||
 176.166992188 70.3779296875 160.23046875 70 159.536132812 69.986328125 c 1
 | 
			
		||||
 159.698242188 69.9873046875 160 69.98828125 160 69.98828125 c 1
 | 
			
		||||
 160 -49.98828125 l 1
 | 
			
		||||
 172.241210938 -49.98828125 598.549804688 -45.2431640625 948.951171875 611.7578125 c 0
 | 
			
		||||
 1036.77050781 776.418945312 1128.25 895.294921875 1214.17578125 981.219726562 c 0
 | 
			
		||||
 1318.08203125 1085.12695312 1414.38964844 1141.49707031 1488.26953125 1172.41894531 c 0
 | 
			
		||||
 1529.32519531 1189.60351562 1563.51171875 1198.921875 1588.29785156 1203.99121094 c 0
 | 
			
		||||
 1615.83300781 1209.62207031 1631.76953125 1210 1632.46386719 1210.01367188 c 1
 | 
			
		||||
 1632.30175781 1210.01269531 1632 1210.01171875 1632 1210.01171875 c 1
 | 
			
		||||
1632 1090.03515625 m 1
 | 
			
		||||
 1632 1449.96484375 l 1
 | 
			
		||||
 1552.21679688 1449.96484375 1098.71386719 1402.66308594 737.146484375 724.725585938 c 0
 | 
			
		||||
 698.938476562 653.084960938 526.864257812 331.080078125 257.309570312 218.258789062 c 0
 | 
			
		||||
 255.126953125 217.345703125 200.76171875 194.705078125 160 189.96484375 c 1
 | 
			
		||||
 160 -169.96484375 l 1
 | 
			
		||||
 239.783203125 -169.96484375 693.286132812 -122.663085938 1054.85351562 555.274414062 c 0
 | 
			
		||||
 1093.06152344 626.915039062 1265.13574219 948.919921875 1534.69042969 1061.74121094 c 0
 | 
			
		||||
 1536.87304688 1062.65429688 1591.23828125 1085.29492188 1632 1090.03515625 c 1
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 3
 | 
			
		||||
Type: 3
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 4
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
159.999999952 1210.01176537 m 5
 | 
			
		||||
 159.999999952 1329.98823463 l 5
 | 
			
		||||
 172.240934135 1329.98823462 598.550052583 1325.24364837 948.951069976 668.241740764 c 4
 | 
			
		||||
 1036.77007573 503.581104976 1128.25010681 384.70539769 1214.17570674 298.779797768 c 4
 | 
			
		||||
 1318.08239786 194.873106647 1414.38934249 138.502937368 1488.26910654 107.580633787 c 4
 | 
			
		||||
 1529.32544481 90.3965432265 1563.51147656 81.0776979108 1588.2975965 76.0087313726 c 4
 | 
			
		||||
 1615.83281888 70.3775506458 1631.76992005 69.9999410877 1632.46377743 69.986036148 c 5
 | 
			
		||||
 1632.30173622 69.9872464204 1632.00000005 69.9882346324 1632.00000005 69.9882346324 c 5
 | 
			
		||||
 1632.00000005 -49.9882346324 l 5
 | 
			
		||||
 1619.75906587 -49.9882346228 1193.44994742 -45.2436483754 843.048930024 611.758259236 c 4
 | 
			
		||||
 755.229924271 776.418895024 663.749893187 895.29460231 577.824293264 981.220202232 c 4
 | 
			
		||||
 473.917602143 1085.12689335 377.61065751 1141.49706263 303.730893464 1172.41936621 c 4
 | 
			
		||||
 262.674555191 1189.60345677 228.488523437 1198.92230209 203.702403502 1203.99126863 c 4
 | 
			
		||||
 176.167181121 1209.62244935 160.230079948 1210.00005891 159.536222574 1210.01396385 c 5
 | 
			
		||||
 159.698263781 1210.01275358 159.999999952 1210.01176537 159.999999952 1210.01176537 c 5
 | 
			
		||||
159.999999857 1090.0352961 m 5
 | 
			
		||||
 159.999999857 1449.9647039 l 5
 | 
			
		||||
 239.782893731 1449.96470383 693.286263441 1402.66324695 1054.85320993 724.725222292 c 4
 | 
			
		||||
 1093.06152816 653.084625607 1265.13598183 331.080480771 1534.69080463 218.25857115 c 4
 | 
			
		||||
 1536.87267214 217.345352617 1591.23876559 194.705394151 1632.00000014 189.964703897 c 5
 | 
			
		||||
 1632.00000014 -169.964703897 l 5
 | 
			
		||||
 1552.21710627 -169.964703835 1098.71373656 -122.663246954 737.146790073 555.274777708 c 4
 | 
			
		||||
 698.938471842 626.915374393 526.864018169 948.919519229 257.309195374 1061.74142885 c 4
 | 
			
		||||
 255.127327856 1062.65464738 200.761234414 1085.29460585 159.999999857 1090.0352961 c 5
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 5
 | 
			
		||||
Type: 3
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 6
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
160 1270 m 29
 | 
			
		||||
 160 1270 560 1270 896 640 c 4
 | 
			
		||||
 1232 10 1632 10 1632 10 c 1029
 | 
			
		||||
159.999999952 1210.01176537 m 1
 | 
			
		||||
 159.999999952 1329.98823463 l 1
 | 
			
		||||
 172.240934135 1329.98823462 598.550052583 1325.24364837 948.951069976 668.241740764 c 0
 | 
			
		||||
 1036.77007573 503.581104976 1128.25010681 384.70539769 1214.17570674 298.779797768 c 0
 | 
			
		||||
 1318.08239786 194.873106647 1414.38934249 138.502937368 1488.26910654 107.580633787 c 0
 | 
			
		||||
 1529.32544481 90.3965432265 1563.51147656 81.0776979108 1588.2975965 76.0087313726 c 0
 | 
			
		||||
 1615.83281888 70.3775506458 1631.76992005 69.9999410877 1632.46377743 69.986036148 c 1
 | 
			
		||||
 1632.30173622 69.9872464204 1632.00000005 69.9882346324 1632.00000005 69.9882346324 c 1
 | 
			
		||||
 1632.00000005 -49.9882346324 l 1
 | 
			
		||||
 1619.75906587 -49.9882346228 1193.44994742 -45.2436483754 843.048930024 611.758259236 c 0
 | 
			
		||||
 755.229924271 776.418895024 663.749893187 895.29460231 577.824293264 981.220202232 c 0
 | 
			
		||||
 473.917602143 1085.12689335 377.61065751 1141.49706263 303.730893464 1172.41936621 c 0
 | 
			
		||||
 262.674555191 1189.60345677 228.488523437 1198.92230209 203.702403502 1203.99126863 c 0
 | 
			
		||||
 176.167181121 1209.62244935 160.230079948 1210.00005891 159.536222574 1210.01396385 c 1
 | 
			
		||||
 159.698263781 1210.01275358 159.999999952 1210.01176537 159.999999952 1210.01176537 c 1
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 7
 | 
			
		||||
Type: 3
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 8
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
160 1270 m 29
 | 
			
		||||
 160 1270 560 1270 896 640 c 4
 | 
			
		||||
 1232 10 1632 10 1632 10 c 1029
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 9
 | 
			
		||||
Type: 3
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 10
 | 
			
		||||
Type: 2
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 2
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
SplineSet
 | 
			
		||||
160 1270 m 29
 | 
			
		||||
 160 1270 560 1270 896 640 c 4
 | 
			
		||||
 1232 10 1632 10 1632 10 c 1029
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
UndoOperation
 | 
			
		||||
Index: 11
 | 
			
		||||
Type: 1
 | 
			
		||||
WasModified: 1
 | 
			
		||||
WasOrder2: 0
 | 
			
		||||
Layer: 1
 | 
			
		||||
Width: 1792
 | 
			
		||||
VWidth: 1792
 | 
			
		||||
LBearingChange: 0
 | 
			
		||||
UnicodeEnc: 0
 | 
			
		||||
InstructionsLength: 0
 | 
			
		||||
EndUndoOperation
 | 
			
		||||
EndUndoes
 | 
			
		||||
Redoes
 | 
			
		||||
EndRedoes
 | 
			
		||||
EndUndoRedoHistory
 | 
			
		||||
Fore
 | 
			
		||||
SplineSet
 | 
			
		||||
1632 1210.01171875 m 1
 | 
			
		||||
| 
						 | 
				
			
			@ -7139,5 +6785,102 @@ SplineSet
 | 
			
		|||
 991.110875674 442.719806976 1013.74868988 480.580583771 1036.07195969 520.767740886 c 1
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndChar
 | 
			
		||||
 | 
			
		||||
StartChar: uniE15A
 | 
			
		||||
Encoding: 57690 57690 96
 | 
			
		||||
Width: 1792
 | 
			
		||||
Flags: HW
 | 
			
		||||
LayerCount: 2
 | 
			
		||||
Fore
 | 
			
		||||
SplineSet
 | 
			
		||||
170.8046875 72.1796875 m 1
 | 
			
		||||
 170.8046875 351.37890625 170.8046875 630.578125 170.8046875 909.77734375 c 1
 | 
			
		||||
 290.791992188 909.77734375 410.778320312 909.77734375 530.765625 909.77734375 c 1
 | 
			
		||||
 608.40234375 909.77734375 668.36328125 887.0234375 710.74609375 841.41796875 c 128
 | 
			
		||||
 753.2265625 795.8125 774.41796875 734.58203125 774.41796875 657.82421875 c 256
 | 
			
		||||
 774.41796875 580.96875 753.2265625 519.73828125 710.74609375 474.1328125 c 128
 | 
			
		||||
 668.36328125 428.625 608.40234375 405.7734375 530.765625 405.7734375 c 1
 | 
			
		||||
 455.9609375 405.7734375 381.15625 405.7734375 306.3515625 405.7734375 c 1
 | 
			
		||||
 306.3515625 294.576171875 306.3515625 183.377929688 306.3515625 72.1796875 c 1
 | 
			
		||||
 261.168945312 72.1796875 215.987304688 72.1796875 170.8046875 72.1796875 c 1
 | 
			
		||||
306.3515625 524.62109375 m 1
 | 
			
		||||
 378.356445312 524.62109375 450.362304688 524.62109375 522.3671875 524.62109375 c 1
 | 
			
		||||
 556.7421875 524.62109375 583.59765625 533.60546875 602.73828125 551.57421875 c 128
 | 
			
		||||
 621.9765625 569.54296875 631.546875 595.421875 631.546875 629.015625 c 1
 | 
			
		||||
 631.546875 648.189453125 631.546875 667.362304688 631.546875 686.53515625 c 1
 | 
			
		||||
 631.546875 720.2265625 621.9765625 746.0078125 602.73828125 763.9765625 c 128
 | 
			
		||||
 583.59765625 781.9453125 556.7421875 791.02734375 522.3671875 791.02734375 c 1
 | 
			
		||||
 450.362304688 791.02734375 378.356445312 791.02734375 306.3515625 791.02734375 c 1
 | 
			
		||||
 306.3515625 702.225585938 306.3515625 613.423828125 306.3515625 524.62109375 c 1
 | 
			
		||||
1196.390625 535.36328125 m 1
 | 
			
		||||
 1165.59667969 594.576171875 1134.80175781 653.788085938 1104.0078125 713 c 1
 | 
			
		||||
 1102.80371094 713 1101.59863281 713 1100.39453125 713 c 1
 | 
			
		||||
 1100.39453125 499.393554688 1100.39453125 285.787109375 1100.39453125 72.1796875 c 1
 | 
			
		||||
 1057.19824219 72.1796875 1014.00097656 72.1796875 970.8046875 72.1796875 c 1
 | 
			
		||||
 970.8046875 351.37890625 970.8046875 630.578125 970.8046875 909.77734375 c 1
 | 
			
		||||
 1021.1953125 909.77734375 1071.5859375 909.77734375 1121.9765625 909.77734375 c 1
 | 
			
		||||
 1213.1875 755.3828125 1304.3984375 600.98828125 1395.609375 446.59375 c 1
 | 
			
		||||
 1426.40332031 387.381835938 1457.19824219 328.169921875 1487.9921875 268.95703125 c 1
 | 
			
		||||
 1489.19628906 268.95703125 1490.40136719 268.95703125 1491.60546875 268.95703125 c 1
 | 
			
		||||
 1491.60546875 482.564453125 1491.60546875 696.170898438 1491.60546875 909.77734375 c 1
 | 
			
		||||
 1534.80175781 909.77734375 1577.99902344 909.77734375 1621.1953125 909.77734375 c 1
 | 
			
		||||
 1621.1953125 630.578125 1621.1953125 351.37890625 1621.1953125 72.1796875 c 1
 | 
			
		||||
 1570.8046875 72.1796875 1520.4140625 72.1796875 1470.0234375 72.1796875 c 1
 | 
			
		||||
 1378.8125 226.57421875 1287.6015625 380.96875 1196.390625 535.36328125 c 1
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndChar
 | 
			
		||||
 | 
			
		||||
StartChar: uniE15B
 | 
			
		||||
Encoding: 57691 57691 97
 | 
			
		||||
Width: 1792
 | 
			
		||||
Flags: HWO
 | 
			
		||||
LayerCount: 2
 | 
			
		||||
Fore
 | 
			
		||||
SplineSet
 | 
			
		||||
938.209960938 435.383789062 m 1
 | 
			
		||||
 938.209960938 -25.1181640625 l 1
 | 
			
		||||
 1234.27539062 247.456054688 l 1
 | 
			
		||||
 1234.27539062 117.280273438 l 1
 | 
			
		||||
 836.430664062 -248.998046875 l 1xd3ce
 | 
			
		||||
 836.430664062 211.504882812 l 1
 | 
			
		||||
 540.365234375 -61.0693359375 l 1
 | 
			
		||||
 540.365234375 69.1064453125 l 1
 | 
			
		||||
 938.209960938 435.383789062 l 1
 | 
			
		||||
315.962890625 621 m 1
 | 
			
		||||
 315.962890625 844.359375 315.962890625 1067.71875 315.962890625 1291.078125 c 1
 | 
			
		||||
 411.952148438 1291.078125 507.942382812 1291.078125 603.931640625 1291.078125 c 1
 | 
			
		||||
 666.041015625 1291.078125 714.009765625 1272.875 747.916015625 1236.390625 c 128
 | 
			
		||||
 781.900390625 1199.90625 798.853515625 1150.921875 798.853515625 1089.515625 c 256
 | 
			
		||||
 798.853515625 1028.03125 781.900390625 979.046875 747.916015625 942.5625 c 128
 | 
			
		||||
 714.009765625 906.15625 666.041015625 887.875 603.931640625 887.875 c 1
 | 
			
		||||
 544.087890625 887.875 484.244140625 887.875 424.400390625 887.875 c 1
 | 
			
		||||
 424.400390625 798.916992188 424.400390625 709.958984375 424.400390625 621 c 1
 | 
			
		||||
 388.254882812 621 352.108398438 621 315.962890625 621 c 1
 | 
			
		||||
424.400390625 982.953125 m 1
 | 
			
		||||
 482.004882812 982.953125 539.608398438 982.953125 597.212890625 982.953125 c 1
 | 
			
		||||
 624.712890625 982.953125 646.197265625 990.140625 661.509765625 1004.515625 c 128
 | 
			
		||||
 676.900390625 1018.890625 684.556640625 1039.59375 684.556640625 1066.46875 c 1
 | 
			
		||||
 684.556640625 1081.80761719 684.556640625 1097.14648438 684.556640625 1112.484375 c 1
 | 
			
		||||
 684.556640625 1139.4375 676.900390625 1160.0625 661.509765625 1174.4375 c 128
 | 
			
		||||
 646.197265625 1188.8125 624.712890625 1196.078125 597.212890625 1196.078125 c 1
 | 
			
		||||
 539.608398438 1196.078125 482.004882812 1196.078125 424.400390625 1196.078125 c 1
 | 
			
		||||
 424.400390625 1125.03710938 424.400390625 1053.99511719 424.400390625 982.953125 c 1
 | 
			
		||||
1136.43164062 991.546875 m 1
 | 
			
		||||
 1111.79589844 1038.91699219 1087.16113281 1086.28710938 1062.52539062 1133.65625 c 1
 | 
			
		||||
 1061.56152344 1133.65625 1060.59863281 1133.65625 1059.63476562 1133.65625 c 1
 | 
			
		||||
 1059.63476562 962.771484375 1059.63476562 791.885742188 1059.63476562 621 c 1
 | 
			
		||||
 1025.07714844 621 990.520507812 621 955.962890625 621 c 1
 | 
			
		||||
 955.962890625 844.359375 955.962890625 1067.71875 955.962890625 1291.078125 c 1
 | 
			
		||||
 996.275390625 1291.078125 1036.58789062 1291.078125 1076.90039062 1291.078125 c 1
 | 
			
		||||
 1149.86914062 1167.5625 1222.83789062 1044.046875 1295.80664062 920.53125 c 1
 | 
			
		||||
 1320.44238281 873.162109375 1345.07714844 825.791992188 1369.71289062 778.421875 c 1
 | 
			
		||||
 1370.67675781 778.421875 1371.63964844 778.421875 1372.60351562 778.421875 c 1
 | 
			
		||||
 1372.60351562 949.307617188 1372.60351562 1120.19335938 1372.60351562 1291.078125 c 1
 | 
			
		||||
 1407.16113281 1291.078125 1441.71777344 1291.078125 1476.27539062 1291.078125 c 1
 | 
			
		||||
 1476.27539062 1067.71875 1476.27539062 844.359375 1476.27539062 621 c 1
 | 
			
		||||
 1435.96289062 621 1395.65039062 621 1355.33789062 621 c 1
 | 
			
		||||
 1282.36914062 744.515625 1209.40039062 868.03125 1136.43164062 991.546875 c 1
 | 
			
		||||
EndSplineSet
 | 
			
		||||
EndChar
 | 
			
		||||
EndChars
 | 
			
		||||
EndSplineFont
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										
											BIN
										
									
								
								res/icons.ttf
									
									
									
									
									
								
							
							
						
						| 
						 | 
				
			
			@ -16,9 +16,9 @@ if you find issues (e.g. bugs or annoyances), report them. links below.
 | 
			
		|||
- Furnace on GitHub (project page and issue tracker): https://github.com/tildearrow/furnace
 | 
			
		||||
  - issues: https://github.com/tildearrow/furnace/issues
 | 
			
		||||
  - discussion: https://github.com/tildearrow/furnace/discussions
 | 
			
		||||
- Furnace on Revolt: https://rvlt.gg/GRPS6tmc
 | 
			
		||||
- Furnace on Discord: https://discord.gg/EfrwT2wq7z
 | 
			
		||||
- online manual: https://tildearrow.org/furnace/doc/v0.6/
 | 
			
		||||
- Furnace on Revolt: https://rvlt.gg/GRPS6tmc
 | 
			
		||||
- online manual: https://tildearrow.org/furnace/doc/v0.6.1/
 | 
			
		||||
 | 
			
		||||
# notes
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,9 +26,9 @@ if you find issues (e.g. bugs or annoyances), report them. links below.
 | 
			
		|||
- Furnace on GitHub (project page and issue tracker): https://github.com/tildearrow/furnace
 | 
			
		||||
  - issues: https://github.com/tildearrow/furnace/issues
 | 
			
		||||
  - discussion: https://github.com/tildearrow/furnace/discussions
 | 
			
		||||
- Furnace on Revolt: https://rvlt.gg/GRPS6tmc
 | 
			
		||||
- Furnace on Discord: https://discord.gg/EfrwT2wq7z
 | 
			
		||||
- online manual: https://tildearrow.org/furnace/doc/v0.6/
 | 
			
		||||
- Furnace on Revolt: https://rvlt.gg/GRPS6tmc
 | 
			
		||||
- online manual: https://tildearrow.org/furnace/doc/v0.6.1/
 | 
			
		||||
 | 
			
		||||
# notes
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -16,9 +16,9 @@ if you find issues (e.g. bugs or annoyances), report them. links below.
 | 
			
		|||
- Furnace on GitHub (project page and issue tracker): https://github.com/tildearrow/furnace
 | 
			
		||||
  - issues: https://github.com/tildearrow/furnace/issues
 | 
			
		||||
  - discussion: https://github.com/tildearrow/furnace/discussions
 | 
			
		||||
- Furnace on Revolt: https://rvlt.gg/GRPS6tmc
 | 
			
		||||
- Furnace on Discord: https://discord.gg/EfrwT2wq7z
 | 
			
		||||
- online manual: https://tildearrow.org/furnace/doc/v0.6/
 | 
			
		||||
- Furnace on Revolt: https://rvlt.gg/GRPS6tmc
 | 
			
		||||
- online manual: https://tildearrow.org/furnace/doc/v0.6.1/
 | 
			
		||||
 | 
			
		||||
# notes
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,11 +8,11 @@ fi
 | 
			
		|||
 | 
			
		||||
cd /tmp/furnace
 | 
			
		||||
 | 
			
		||||
if [ ! -e linuxbuild ]; then
 | 
			
		||||
  mkdir linuxbuild || exit 1
 | 
			
		||||
if [ ! -e aibuild ]; then
 | 
			
		||||
  mkdir aibuild || exit 1
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
cd linuxbuild
 | 
			
		||||
cd aibuild
 | 
			
		||||
 | 
			
		||||
cmake -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_FLAGS="-O2" -DCMAKE_CXX_FLAGS="-O2 -Wall -Wextra -Wno-unused-parameter -Werror" -DWITH_DEMOS=OFF -DWITH_INSTRUMENTS=OFF -DWITH_WAVETABLES=OFF .. || exit 1
 | 
			
		||||
make -j4 || exit 1
 | 
			
		||||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ make -j4 || exit 1
 | 
			
		|||
cd ..
 | 
			
		||||
 | 
			
		||||
mkdir -p release/linux/furnace.AppDir || exit 1
 | 
			
		||||
cd linuxbuild
 | 
			
		||||
cd aibuild
 | 
			
		||||
 | 
			
		||||
make DESTDIR=/tmp/furnace/release/linux/furnace.AppDir install || exit 1
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										22
									
								
								src/divasm/divasm.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Furnace Tracker - multi-system chiptune tracker
 | 
			
		||||
 * Copyright (C) 2021-2024 tildearrow and contributors
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License along
 | 
			
		||||
 * with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
 #include "divasm.h"
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
| 
						 | 
				
			
			@ -1,3 +1,27 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Furnace Tracker - multi-system chiptune tracker
 | 
			
		||||
 * Copyright (C) 2021-2024 tildearrow and contributors
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License along
 | 
			
		||||
 * with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// this is a mini-assembler written for Furnace.
 | 
			
		||||
// it will be used in future ROM export (yes, that's right, ROM is baked at export time).
 | 
			
		||||
 | 
			
		||||
#include "../engine/safeWriter.h"
 | 
			
		||||
 | 
			
		||||
struct DivASMResult {
 | 
			
		||||
  int line, err;
 | 
			
		||||
  DivASMResult():
 | 
			
		||||
| 
						 | 
				
			
			@ -5,26 +29,34 @@ struct DivASMResult {
 | 
			
		|||
    err(0) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct DivASMFile {
 | 
			
		||||
  String name;
 | 
			
		||||
  SafeReader* data;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum DivASMTarget {
 | 
			
		||||
  DIV_ASM_TARGET_DUMMY=0,
 | 
			
		||||
  DIV_ASM_TARGET_6502,
 | 
			
		||||
  DIV_ASM_TARGET_SPC700
 | 
			
		||||
  DIV_ASM_TARGET_SPC700,
 | 
			
		||||
  DIV_ASM_TARGET_Z80
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct DivLabel {
 | 
			
		||||
  String name;
 | 
			
		||||
  unsigned int location;
 | 
			
		||||
  bool direct;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct DivOper {
 | 
			
		||||
  String operation;
 | 
			
		||||
  int line;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class DivASM {
 | 
			
		||||
  std::vector<DivASMFile> files;
 | 
			
		||||
  SafeWriter* result;
 | 
			
		||||
 | 
			
		||||
  std::vector<DivLabel> labels;
 | 
			
		||||
  std::vector<DivOper> ops;
 | 
			
		||||
 | 
			
		||||
  public:
 | 
			
		||||
    DivASMResult getError();
 | 
			
		||||
    SafeWriter* assemble(String name);
 | 
			
		||||
    void addFile(String name, SafeReader* data);
 | 
			
		||||
    SafeWriter* assemble(SafeReader* data);
 | 
			
		||||
 | 
			
		||||
    DivASM(DivASMTarget target);
 | 
			
		||||
    DivASM();
 | 
			
		||||
    ~DivASM();
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										30
									
								
								src/divasm/standalone.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
/**
 | 
			
		||||
 * Furnace Tracker - multi-system chiptune tracker
 | 
			
		||||
 * Copyright (C) 2021-2024 tildearrow and contributors
 | 
			
		||||
 *
 | 
			
		||||
 * This program is free software; you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU General Public License as published by
 | 
			
		||||
 * the Free Software Foundation; either version 2 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * This program is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU General Public License along
 | 
			
		||||
 * with this program; if not, write to the Free Software Foundation, Inc.,
 | 
			
		||||
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include "divasm.h"
 | 
			
		||||
 | 
			
		||||
int main(int argc, char** argv) {
 | 
			
		||||
  if (argc<2) {
 | 
			
		||||
    printf("usage: %s file\n",argv[0]);
 | 
			
		||||
    return 1;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,7 @@
 | 
			
		|||
#ifndef _CHIP_UTILS_H
 | 
			
		||||
#define _CHIP_UTILS_H
 | 
			
		||||
 | 
			
		||||
#include "defines.h"
 | 
			
		||||
#include "macroInt.h"
 | 
			
		||||
 | 
			
		||||
// custom clock limits
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +30,7 @@
 | 
			
		|||
// common shared channel struct
 | 
			
		||||
template<typename T> struct SharedChannel {
 | 
			
		||||
  int freq, baseFreq, baseNoteOverride, pitch, pitch2, arpOff;
 | 
			
		||||
  int ins, note;
 | 
			
		||||
  int ins, note, sampleNote, sampleNoteDelta;
 | 
			
		||||
  bool active, insChanged, freqChanged, fixedArp, keyOn, keyOff, portaPause, inPorta;
 | 
			
		||||
  T vol, outVol;
 | 
			
		||||
  DivMacroInt std;
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +72,8 @@ template<typename T> struct SharedChannel {
 | 
			
		|||
    arpOff(0),
 | 
			
		||||
    ins(-1),
 | 
			
		||||
    note(0),
 | 
			
		||||
    sampleNote(DIV_NOTE_NULL),
 | 
			
		||||
    sampleNoteDelta(0),
 | 
			
		||||
    active(false),
 | 
			
		||||
    insChanged(true),
 | 
			
		||||
    freqChanged(false),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -36,5 +36,6 @@
 | 
			
		|||
 | 
			
		||||
// dispatch
 | 
			
		||||
#define DIV_MAX_OUTPUTS 16
 | 
			
		||||
#define DIV_NOTE_NULL 0x7fffffff
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,11 +25,10 @@
 | 
			
		|||
#include "../pch.h"
 | 
			
		||||
#include "config.h"
 | 
			
		||||
#include "chipUtils.h"
 | 
			
		||||
#include "defines.h"
 | 
			
		||||
 | 
			
		||||
#define ONE_SEMITONE 2200
 | 
			
		||||
 | 
			
		||||
#define DIV_NOTE_NULL 0x7fffffff
 | 
			
		||||
 | 
			
		||||
#define addWrite(a,v) regWrites.push_back(DivRegWrite(a,v));
 | 
			
		||||
 | 
			
		||||
// HOW TO ADD A NEW COMMAND:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,10 +52,10 @@ class DivWorkPool;
 | 
			
		|||
#define EXTERN_BUSY_BEGIN_SOFT e->softLocked=true; e->isBusy.lock();
 | 
			
		||||
#define EXTERN_BUSY_END e->isBusy.unlock(); e->softLocked=false;
 | 
			
		||||
 | 
			
		||||
#define DIV_UNSTABLE
 | 
			
		||||
//#define DIV_UNSTABLE
 | 
			
		||||
 | 
			
		||||
#define DIV_VERSION "dev191"
 | 
			
		||||
#define DIV_ENGINE_VERSION 191
 | 
			
		||||
#define DIV_VERSION "0.6.1"
 | 
			
		||||
#define DIV_ENGINE_VERSION 192
 | 
			
		||||
// for imports
 | 
			
		||||
#define DIV_VERSION_MOD 0xff01
 | 
			
		||||
#define DIV_VERSION_FC 0xff02
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -370,20 +370,10 @@ void DivPlatformAmiga::tick(bool sysTick) {
 | 
			
		|||
      chan[i].outVol=((chan[i].vol%65)*MIN(64,chan[i].std.vol.val))>>6;
 | 
			
		||||
      chan[i].writeVol=true;
 | 
			
		||||
    }
 | 
			
		||||
    double off=1.0;
 | 
			
		||||
    if (!chan[i].useWave && chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
 | 
			
		||||
      DivSample* s=parent->getSample(chan[i].sample);
 | 
			
		||||
      if (s->centerRate<1) {
 | 
			
		||||
        off=1.0;
 | 
			
		||||
      } else {
 | 
			
		||||
        off=8363.0/(double)s->centerRate;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (NEW_ARP_STRAT) {
 | 
			
		||||
      chan[i].handleArp();
 | 
			
		||||
    } else if (chan[i].std.arp.had) {
 | 
			
		||||
      // TODO: why the off mult? this may be a bug!
 | 
			
		||||
      chan[i].baseFreq=round(off*NOTE_PERIODIC_NOROUND(parent->calcArp(chan[i].note,chan[i].std.arp.val)));
 | 
			
		||||
      chan[i].baseFreq=round(NOTE_PERIODIC_NOROUND(parent->calcArp(chan[i].note,chan[i].std.arp.val)));
 | 
			
		||||
      chan[i].freqChanged=true;
 | 
			
		||||
    }
 | 
			
		||||
    if (chan[i].useWave && chan[i].std.wave.had) {
 | 
			
		||||
| 
						 | 
				
			
			@ -577,10 +567,14 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
 | 
			
		|||
            chan[c.chan].updateWave=true;
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
      } else {
 | 
			
		||||
        if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
          chan[c.chan].sample=ins->amiga.getSample(c.value);
 | 
			
		||||
          chan[c.chan].sampleNote=c.value;
 | 
			
		||||
          c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
        }
 | 
			
		||||
        chan[c.chan].useWave=false;
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -657,9 +651,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].updateWave=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AMIGA);
 | 
			
		||||
      chan[c.chan].sample=ins->amiga.getSample(c.value2);
 | 
			
		||||
      int destFreq=round(NOTE_PERIODIC_NOROUND(c.value2));
 | 
			
		||||
      int destFreq=round(NOTE_PERIODIC_NOROUND(c.value2+chan[c.chan].sampleNoteDelta));
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -682,7 +674,7 @@ int DivPlatformAmiga::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=round(NOTE_PERIODIC_NOROUND(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0))));
 | 
			
		||||
      chan[c.chan].baseFreq=round(NOTE_PERIODIC_NOROUND(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0))));
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      chan[c.chan].note=c.value;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -405,7 +405,12 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
 | 
			
		|||
        if (!parent->song.disableSampleMacro && (ins->type==DIV_INS_AMIGA || ins->amiga.useSample)) {
 | 
			
		||||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].dac.sample=ins->amiga.getSample(c.value);
 | 
			
		||||
            chan[c.chan].sampleNote=c.value;
 | 
			
		||||
            c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
            chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
          } else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].dac.sample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
            c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
          }
 | 
			
		||||
          if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) {
 | 
			
		||||
            chan[c.chan].dac.sample=-1;
 | 
			
		||||
| 
						 | 
				
			
			@ -457,6 +462,8 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
 | 
			
		|||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
        chan[c.chan].freqChanged=true;
 | 
			
		||||
        chan[c.chan].note=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -526,7 +533,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2);
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -549,7 +556,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -406,7 +406,12 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
 | 
			
		|||
        if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
 | 
			
		||||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].dac.sample=ins->amiga.getSample(c.value);
 | 
			
		||||
            chan[c.chan].sampleNote=c.value;
 | 
			
		||||
            c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
            chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
          } else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].dac.sample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
            c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
          }
 | 
			
		||||
          if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) {
 | 
			
		||||
            chan[c.chan].dac.sample=-1;
 | 
			
		||||
| 
						 | 
				
			
			@ -458,6 +463,8 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
 | 
			
		|||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
        chan[c.chan].freqChanged=true;
 | 
			
		||||
        chan[c.chan].note=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -520,7 +527,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2);
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -543,7 +550,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -320,7 +320,9 @@ int DivPlatformC140::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].macroPanMul=ins->type==DIV_INS_AMIGA?127:255;
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].sample=ins->amiga.getSample(c.value);
 | 
			
		||||
        chan[c.chan].sampleNote=c.value;
 | 
			
		||||
        c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
 | 
			
		||||
| 
						 | 
				
			
			@ -393,7 +395,7 @@ int DivPlatformC140::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=NOTE_FREQUENCY(c.value2);
 | 
			
		||||
      int destFreq=NOTE_FREQUENCY(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -416,7 +418,7 @@ int DivPlatformC140::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      chan[c.chan].note=c.value;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -719,27 +719,51 @@ void DivPlatformES5506::tick(bool sysTick) {
 | 
			
		|||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// man this code
 | 
			
		||||
// part of the reason why it's so messy is because the chip is
 | 
			
		||||
// overly complex and because when this pull request was made,
 | 
			
		||||
// Furnace still was in an early state with no support for sample
 | 
			
		||||
// maps or whatever...
 | 
			
		||||
// one day I'll come back and clean this up
 | 
			
		||||
int DivPlatformES5506::dispatch(DivCommand c) {
 | 
			
		||||
  switch (c.cmd) {
 | 
			
		||||
    case DIV_CMD_NOTE_ON: {
 | 
			
		||||
      DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_ES5506);
 | 
			
		||||
      bool sampleValid=false;
 | 
			
		||||
      if (((ins->amiga.useNoteMap) && (c.value>=0 && c.value<120)) ||
 | 
			
		||||
          ((!ins->amiga.useNoteMap) && (ins->amiga.initSample>=0 && ins->amiga.initSample<parent->song.sampleLen))) {
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        int sample=ins->amiga.getSample(c.value);
 | 
			
		||||
        chan[c.chan].sampleNote=c.value;
 | 
			
		||||
        if (sample>=0 && sample<parent->song.sampleLen) {
 | 
			
		||||
          sampleValid=true;
 | 
			
		||||
          chan[c.chan].volMacroMax=ins->type==DIV_INS_AMIGA?64:0xfff;
 | 
			
		||||
          chan[c.chan].panMacroMax=ins->type==DIV_INS_AMIGA?127:0xfff;
 | 
			
		||||
          chan[c.chan].pcm.next=ins->amiga.useNoteMap?c.value:sample;
 | 
			
		||||
          c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
          chan[c.chan].pcm.note=c.value;
 | 
			
		||||
          chan[c.chan].filter=ins->es5506.filter;
 | 
			
		||||
          chan[c.chan].envelope=ins->es5506.envelope;
 | 
			
		||||
        } else {
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        }
 | 
			
		||||
      } else {
 | 
			
		||||
        int sample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
        if (sample>=0 && sample<parent->song.sampleLen) {
 | 
			
		||||
          sampleValid=true;
 | 
			
		||||
          chan[c.chan].volMacroMax=ins->type==DIV_INS_AMIGA?64:0xfff;
 | 
			
		||||
          chan[c.chan].panMacroMax=ins->type==DIV_INS_AMIGA?127:0xfff;
 | 
			
		||||
          chan[c.chan].pcm.next=ins->amiga.useNoteMap?chan[c.chan].sampleNote:sample;
 | 
			
		||||
          c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
          chan[c.chan].pcm.note=c.value;
 | 
			
		||||
          chan[c.chan].filter=ins->es5506.filter;
 | 
			
		||||
          chan[c.chan].envelope=ins->es5506.envelope;
 | 
			
		||||
        } else {
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (!sampleValid) {
 | 
			
		||||
        chan[c.chan].pcm.index=chan[c.chan].pcm.next=-1;
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        chan[c.chan].filter=DivInstrumentES5506::Filter();
 | 
			
		||||
        chan[c.chan].envelope=DivInstrumentES5506::Envelope();
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			@ -962,7 +986,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int nextFreq=chan[c.chan].baseFreq;
 | 
			
		||||
      const int destFreq=NOTE_ES5506(c.chan,c.value2);
 | 
			
		||||
      const int destFreq=NOTE_ES5506(c.chan,c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>nextFreq) {
 | 
			
		||||
        nextFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -987,7 +1011,7 @@ int DivPlatformES5506::dispatch(DivCommand c) {
 | 
			
		|||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].note=c.value;
 | 
			
		||||
      chan[c.chan].nextNote=chan[c.chan].note+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0));
 | 
			
		||||
      chan[c.chan].nextNote=chan[c.chan].note+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0));
 | 
			
		||||
      chan[c.chan].noteChanged.note=1;
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -207,7 +207,9 @@ int DivPlatformGA20::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:255;
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].sample=ins->amiga.getSample(c.value);
 | 
			
		||||
        chan[c.chan].sampleNote=c.value;
 | 
			
		||||
        c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
| 
						 | 
				
			
			@ -263,7 +265,7 @@ int DivPlatformGA20::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      const int destFreq=NOTE_PERIODIC(c.value2);
 | 
			
		||||
      const int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -286,7 +288,7 @@ int DivPlatformGA20::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      chan[c.chan].note=c.value;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -704,8 +704,12 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
 | 
			
		|||
        } else if (chan[c.chan].furnaceDac) {
 | 
			
		||||
          chan[c.chan].dacMode=0;
 | 
			
		||||
          rWrite(0x2b,0<<7);
 | 
			
		||||
          chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        } else if (!chan[c.chan].dacMode) {
 | 
			
		||||
          rWrite(0x2b,0<<7);
 | 
			
		||||
          chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (c.chan>=5 && chan[c.chan].dacMode) {
 | 
			
		||||
| 
						 | 
				
			
			@ -713,7 +717,12 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
 | 
			
		|||
        if (ins->type==DIV_INS_AMIGA) { // Furnace mode
 | 
			
		||||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].dacSample=ins->amiga.getSample(c.value);
 | 
			
		||||
            chan[c.chan].sampleNote=c.value;
 | 
			
		||||
            c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
            chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
          } else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
            c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
          }
 | 
			
		||||
          if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
 | 
			
		||||
            chan[c.chan].dacSample=-1;
 | 
			
		||||
| 
						 | 
				
			
			@ -752,6 +761,8 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
 | 
			
		|||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].note=c.value;
 | 
			
		||||
          }
 | 
			
		||||
          chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
          chan[c.chan].dacSample=12*chan[c.chan].sampleBank+chan[c.chan].note%12;
 | 
			
		||||
          if (chan[c.chan].dacSample>=parent->song.sampleLen) {
 | 
			
		||||
            chan[c.chan].dacSample=-1;
 | 
			
		||||
| 
						 | 
				
			
			@ -863,7 +874,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
 | 
			
		|||
    }
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      if (parent->song.linearPitch==2) {
 | 
			
		||||
        int destFreq=NOTE_FREQUENCY(c.value2);
 | 
			
		||||
        int destFreq=NOTE_FREQUENCY(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
        bool return2=false;
 | 
			
		||||
        if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
          chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -909,7 +920,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
 | 
			
		|||
        break;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.chan>=5 && chan[c.chan].furnaceDac && chan[c.chan].dacMode) {
 | 
			
		||||
        int destFreq=parent->calcBaseFreq(1,1,c.value2,false);
 | 
			
		||||
        int destFreq=parent->calcBaseFreq(1,1,c.value2+chan[c.chan].sampleNoteDelta,false);
 | 
			
		||||
        bool return2=false;
 | 
			
		||||
        if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
          chan[c.chan].baseFreq+=c.value*16;
 | 
			
		||||
| 
						 | 
				
			
			@ -963,7 +974,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
 | 
			
		|||
      if (c.chan==csmChan) {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
      } else if (c.chan>=5 && chan[c.chan].furnaceDac && chan[c.chan].dacMode) {
 | 
			
		||||
        chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
 | 
			
		||||
        chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+chan[c.chan].sampleNoteDelta,false);
 | 
			
		||||
      } else {
 | 
			
		||||
        if (chan[c.chan].insChanged) {
 | 
			
		||||
          DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -281,7 +281,9 @@ int DivPlatformK007232::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:15;
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].sample=ins->amiga.getSample(c.value);
 | 
			
		||||
        chan[c.chan].sampleNote=c.value;
 | 
			
		||||
        c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
| 
						 | 
				
			
			@ -347,7 +349,7 @@ int DivPlatformK007232::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      const int destFreq=NOTE_PERIODIC(c.value2);
 | 
			
		||||
      const int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -370,7 +372,7 @@ int DivPlatformK007232::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val-12):(0)));
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      chan[c.chan].note=c.value;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -230,7 +230,9 @@ int DivPlatformK053260::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:127;
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].sample=ins->amiga.getSample(c.value);
 | 
			
		||||
        chan[c.chan].sampleNote=c.value;
 | 
			
		||||
        c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
        chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +293,7 @@ int DivPlatformK053260::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2);
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -314,7 +316,7 @@ int DivPlatformK053260::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
 | 
			
		||||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      chan[c.chan].note=c.value;
 | 
			
		||||
      break;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -228,19 +228,28 @@ int DivPlatformLynx::dispatch(DivCommand c) {
 | 
			
		|||
          WRITE_CONTROL(c.chan,0x18);
 | 
			
		||||
          WRITE_BACKUP(c.chan,0);
 | 
			
		||||
        } else {
 | 
			
		||||
          chan[c.chan].sampleNote=DIV_NOTE_NULL;
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=0;
 | 
			
		||||
          WRITE_FEEDBACK(c.chan,chan[c.chan].duty.feedback);
 | 
			
		||||
          WRITE_CONTROL(c.chan,(chan[c.chan].fd.clockDivider|0x18|chan[c.chan].duty.int_feedback7));
 | 
			
		||||
          WRITE_BACKUP(c.chan,chan[c.chan].fd.backup);
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        if (chan[c.chan].pcm) {
 | 
			
		||||
      if (chan[c.chan].pcm) {
 | 
			
		||||
        if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
          chan[c.chan].sample=ins->amiga.getSample(c.value);
 | 
			
		||||
          chan[c.chan].sampleNote=c.value;
 | 
			
		||||
          c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
          chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
          chan[c.chan].sampleBaseFreq=NOTE_FREQUENCY(c.value);
 | 
			
		||||
          chan[c.chan].sampleAccum=0;
 | 
			
		||||
          chan[c.chan].samplePos=0;
 | 
			
		||||
        } else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
 | 
			
		||||
          chan[c.chan].sample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
          c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
        }
 | 
			
		||||
        chan[c.chan].sampleAccum=0;
 | 
			
		||||
        chan[c.chan].samplePos=0;
 | 
			
		||||
      }
 | 
			
		||||
      if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
 | 
			
		||||
        chan[c.chan].freqChanged=true;
 | 
			
		||||
        chan[c.chan].note=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -301,7 +310,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2);
 | 
			
		||||
      int destFreq=NOTE_PERIODIC(c.value2+chan[c.chan].sampleNoteDelta);
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -327,7 +336,7 @@ int DivPlatformLynx::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    case DIV_CMD_LEGATO: {
 | 
			
		||||
      int whatAMess=c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0));
 | 
			
		||||
      int whatAMess=c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0));
 | 
			
		||||
      chan[c.chan].baseFreq=NOTE_PERIODIC(whatAMess);
 | 
			
		||||
      if (chan[c.chan].pcm) {
 | 
			
		||||
        chan[c.chan].sampleBaseFreq=NOTE_FREQUENCY(whatAMess);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -178,7 +178,12 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
 | 
			
		|||
        if (ins->type==DIV_INS_AMIGA) {
 | 
			
		||||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            dacSample=ins->amiga.getSample(c.value);
 | 
			
		||||
            chan[c.chan].sampleNote=c.value;
 | 
			
		||||
            c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
            chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
          } else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
 | 
			
		||||
            dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
            c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
          }
 | 
			
		||||
          if (dacSample<0 || dacSample>=parent->song.sampleLen) {
 | 
			
		||||
            dacSample=-1;
 | 
			
		||||
| 
						 | 
				
			
			@ -189,8 +194,8 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
 | 
			
		|||
          }
 | 
			
		||||
          dacPos=0;
 | 
			
		||||
          dacPeriod=0;
 | 
			
		||||
          chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
 | 
			
		||||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
 | 
			
		||||
            chan[c.chan].freqChanged=true;
 | 
			
		||||
            chan[c.chan].note=c.value;
 | 
			
		||||
          }
 | 
			
		||||
| 
						 | 
				
			
			@ -270,7 +275,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=(c.chan==2)?(parent->calcBaseFreq(1,1,c.value2,false)):(NOTE_PERIODIC(c.value2));
 | 
			
		||||
      int destFreq=(c.chan==2)?(parent->calcBaseFreq(1,1,c.value2+chan[c.chan].sampleNoteDelta,false)):(NOTE_PERIODIC(c.value2));
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -304,7 +309,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
 | 
			
		|||
      break;
 | 
			
		||||
    case DIV_CMD_LEGATO:
 | 
			
		||||
      if (c.chan==2) {
 | 
			
		||||
        chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)),false);
 | 
			
		||||
        chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)),false);
 | 
			
		||||
      } else {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -407,7 +407,14 @@ int DivPlatformNES::dispatch(DivCommand c) {
 | 
			
		|||
          if (c.value!=DIV_NOTE_NULL) {
 | 
			
		||||
            dacSample=ins->amiga.getSample(c.value);
 | 
			
		||||
            if (ins->type==DIV_INS_AMIGA) {
 | 
			
		||||
              chan[c.chan].sampleNote=c.value;
 | 
			
		||||
              c.value=ins->amiga.getFreq(c.value);
 | 
			
		||||
              chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
 | 
			
		||||
            }
 | 
			
		||||
          } else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
 | 
			
		||||
            dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
 | 
			
		||||
            if (ins->type==DIV_INS_AMIGA) {
 | 
			
		||||
              c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          if (dacSample<0 || dacSample>=parent->song.sampleLen) {
 | 
			
		||||
| 
						 | 
				
			
			@ -535,7 +542,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
 | 
			
		|||
      chan[c.chan].freqChanged=true;
 | 
			
		||||
      break;
 | 
			
		||||
    case DIV_CMD_NOTE_PORTA: {
 | 
			
		||||
      int destFreq=(c.chan==4)?(parent->calcBaseFreq(1,1,c.value2,false)):(NOTE_PERIODIC(c.value2));
 | 
			
		||||
      int destFreq=(c.chan==4)?(parent->calcBaseFreq(1,1,c.value2+chan[c.chan].sampleNoteDelta,false)):(NOTE_PERIODIC(c.value2));
 | 
			
		||||
      bool return2=false;
 | 
			
		||||
      if (destFreq>chan[c.chan].baseFreq) {
 | 
			
		||||
        chan[c.chan].baseFreq+=c.value;
 | 
			
		||||
| 
						 | 
				
			
			@ -636,7 +643,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
 | 
			
		|||
    case DIV_CMD_LEGATO:
 | 
			
		||||
      if (c.chan==3) break;
 | 
			
		||||
      if (c.chan==4) {
 | 
			
		||||
        chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)),false);
 | 
			
		||||
        chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)),false);
 | 
			
		||||
      } else {
 | 
			
		||||
        chan[c.chan].baseFreq=NOTE_PERIODIC(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
 | 
			
		||||
      }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||