goattracker-2.72/0000755000000000000000000000000011617743364012464 5ustar rootrootgoattracker-2.72/readme.txt0000644000000000000000000023572711604145320014462 0ustar rootrootGoatTracker v2.72 ----------------- Editor by Lasse rni (loorni@gmail.com) HardSID 4U support by Tli Sndor. Uses reSID engine by Dag Lem. Uses reSID distortion / nonlinearity by Antti Lankila. Uses 6510 crossassembler from Exomizer2 beta by Magnus Lind. Uses the SDL library. GoatTracker icon by Antonio Vera. Command quick reference by Simon Bennett. Patches by Stefan A. Haubenthal, Valerio Cannone and Raine M. Ekman. Distributed under GNU General Public License (see the file COPYING for details) Covert BitOps homepage: http://covertbitops.c64.org GoatTracker 2 SourceForge.net page: http://sourceforge.net/projects/goattracker2 Table of contents ----------------- 1. General information 1.1 Warnings 1.2 Compatibility with v1.xx 2. Using GoatTracker 2.1 Command line options 2.2 Hardware support 2.3 Keyboard commands 2.3.1 General keys 2.3.2 Pattern edit mode 2.3.2.1 Protracker note-entry mode 2.3.2.2 DMC note-entry mode 2.3.3 Song edit mode 2.3.4 Instrument edit mode 2.3.5 Table edit mode 2.3.6 Songname edit mode 2.4 Mouse control 3. Song data 3.1 Orderlist data 3.2 Pattern data 3.3 Instrument data 3.4 Table data 3.4.1 Wavetable 3.4.2 Pulsetable 3.4.3 Filtertable 3.4.4 Speedtable 3.5 Playback details 3.6 Miscellaneous tips 3.6.1 Limit-based modulation steps 3.6.2 Precalculated note-independent "hifi player" portamento/vibrato 3.7 Multispeed tips 4. Using the included utilities 4.1 INS2SND2.EXE 4.2 SNGSPLI2.EXE 4.3 MOD2SNG.EXE 4.4 BETACONV.EXE 5. Using the songs outside the editor 5.1 Playroutine options 6. File/data formats description 6.1 GoatTracker v2 song (.SNG) format 6.1.1 Song header 6.1.2 Song orderlists 6.1.3 Instruments 6.1.4 Tables 6.1.5 Patterns header 6.1.6 Patterns 6.2 GoatTracker v2 instrument (.INS) format 6.3 Sound effect data format 7. Recompiling 8. Version history 1. General information ---------------------- This program is a tracker-like C64 music editor running on Win32 or Linux platforms (using the SDL library, see http://www.libsdl.org) GoatTracker v2 adds more commands and uniform step programming tables for waveform/arpeggio, pulse effects, and filter effects. It is likely much more complex to learn & master than v1.xx. Familiarity with tracker programs in general, hexadecimal notation, and the C64's SID chip are required. Consult the C64 Programmer's Reference Guide (http://project64.c64.org) or AAY64 (http://www.the-dreams.de/aay.html) for SID chip reference. For filesize & library compatibility reasons, precompiled binaries exist only for Win32 platform. 1.1 Warnings ------------ 1. Always look at the end of this file for changes! Sometimes keyboard commands change etc. 2. Always save your songs in the .SNG-format with F11 key if you plan to continue editing! Packed & relocated songs (PRG/BIN/SID) can not be loaded back into the editor. 3. Even the reSID emulation is in some cases quite far from the output of a real SID. Especially if filters are in use, consider strongly testing your tune on a C64 or on a HardSID card. (Using filters has always been complicated because every SID tends to sound different.) 4. The editor will stop playing if: - The song restart position is illegal (beyond end of song) - The sequence of orderlist commands is incorrect * In a sequence of both TRANSPOSE & REPEAT, TRANSPOSE must come first * The last thing before a RST-endmark should be a pattern number - Gateoff timer value is too high compared to song tempo. - The song tries to jump directly onto a table row containing a jump (FF xx), either with instrument pointers or 8XY, 9XY, AXY commands. - The song tries to execute pattern commands 0XY, 8XY or EXY from the wavetable. These all are error conditions, and trying to pack/relocate such song should give an error message. 5. Using delayed wavetable or no wavechange (0x 00, where x is 0-F) in the first step of instrument wavetable is unsupported and may result in missing notes. 6. When using a playroutine with unbuffered SID-writes (Standard /w unbuffered or Minimal) and encountering ADSR-bugs after packing/relocating, you can try either: 1) Set pulse-startpos to nonzero value in the troublesome instruments and change the 1stFrame Wave parameter of some instrument slightly, for example from $09 to $0B, to disable a playroutine optimization. The idea in this is to make the noteinit routine take more CPU cycles. 2) Use a playroutine with buffered writes to pack/relocate. 3) Try hardrestart attack parameter $F for alternative SID register write order. 7. From v2.18 onwards, wavetable left side values have changed. Delay can now be maximum 16 frames (values $00-$0F), and waveform register values $00-$0F (inaudible) have been mapped to table values $E0-$EF. For example, testbit + gate would be $E9. You need to manually convert values $08-$0F from your old songs! 8. From v2.2 onwards, a new table (speedtable) has been added. The portamento, vibrato and funktempo commands use it. Old songs will be converted upon loading to use the speedtable. Note the keyboard command SHIFT+RETURN to convert the old style parameters. 9. From v2.4 onwards, pulse modulation speed has 1 bit added accuracy, so you need to double pulsespeeds when composing new songs. Old songs will be converted automatically. 10. From v2.59 onwards, gateoff timer parameter high bit disables hardrestart and bit $40 disables gateoff. Old songs & instruments will be converted automatically. 11. From v2.62 onwards, realtime calculated portamento/vibrato speeds are supported. This is activated by having the high bit ($80) set in the speed- table left side. Naturally, this means that very high portamento speeds (>= $8000) or vibrato speeds (>= $80) become unavailable, but these should not be very useful anyway. 12. From v2.68 onwards, SID write order has been tweaked for better stability regarding badlines. This has the consequence, however, that notes with attack 0 & release 1 may ADSR-bug. In this case, try hardrestart attack parameter $F for alternative SID register write order. 1.2 Compatibility with v1.xx ---------------------------- GoatTracker v2 can load v1.xx songs and instruments, but it saves only in v2 format. Some subtleties (like tricks involving instrument changes) will not play back exactly like in v1.xx. The only major feature removal is that of the arpeggio command in v2. Everything that this command does can also be done with wavetables, and the import feature converts all arpeggio commands to corresponding wavetable programs. 2. Using GoatTracker -------------------- 2.1 Command line options ------------------------ Start Goattracker V2 by typing GOATTRK2 in the command prompt, followed by the songname to be loaded at startup (optional) and any command line options you may want. For example "goattrk2 dojo.sng -s1 -e1" to set 1x-speed mode and SID model 8580 and to load "dojo.sng" on startup. -Axx Set hard restart ADSR parameter in hex. DEFAULT=0F00 -Bxx Set sound buffer length in milliseconds DEFAULT=100 -Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on) -Dxx Pattern row display (0 = decimal, 1 = hexadecimal) -Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=6581 -Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default) -Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz) -Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.) -Ixx Set reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) DEFAULT=off -Kxx Note-entry mode (0 = PROTRACKER 1 = DMC) DEFAULT=PROTRK. -Lxx SID memory location in hex. DEFAULT=D400 -Mxx Set sound mixing rate DEFAULT=44100 -Oxx Set pulse optimization/skipping (0 = off, 1 = on) DEFAULT=on -Rxx Set realtime command optimization/skipping (0 = off, 1 = on) DEFAULT=on -Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.) -Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0 -Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0 -Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on -Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window -Zxx Set random reSID write delay in cycles (0 = off) DEFAULT=off -N Use NTSC timing -P Use PAL timing (DEFAULT) -W Write emulated sound output to a file SIDAUDIO.RAW -? Show command line options -?? Standalone online help window Try the command line options if there are any problems. For example, if you experience choppy audio you can increase audio buffering with -B option. SDL seems to have trouble with some soundcards under Windows; you might want to try even a 500ms buffer, or tweak the hardware acceleration level of the soundcard (from Control Panel). Also, reSID interpolation will take remarkably more CPU time and could cause the sound and/or editing to get choppy. Finevibrato mode is on by default. You can change this behaviour with -V option. Note that finevibrato mode only affects the conversion of old style vibrato parameters to speedtable format. Pulse optimization -O determines if pulsetable execution will be skipped when getting new notes or a new pattern. By default it is on. Be warned that turning it off will increase the rastertime requirements of packed/relocated songs greatly! Realtime command optimization -R determines if portamento, vibrato & instrument vibrato will be skipped on tick 0 of each pattern row. By default it is on, as this is how tracker programs have operated traditionally. Turning it off makes the commands sound same regardless of tempo but will increase rastertime use. The hard restart ADSR parameter will especially affect how rapid passages of notes will sound like. 0000 is probably too hard to be useful, except perhaps with gateoff timer value 1. 0F00 (default) is a lot softer, and 0F01 adds also a little bit of release to the gateoff phase for even softer sound. 000F makes the note start very pronounced. Hard restart parameter with attack at maximum (F) enables the use of an alternative playroutine, where waveform is written before ADSR. This can give more reliable note triggering, especially for very fast releases 0 & 1, but may change the characteristics of the note's decay & release. 2.2 Hardware support -------------------- HardSID support is available with the /H option (use first HardSID = -H1, second = -H2 etc., return to emulated output = -H0). You must have the HardSID drivers installed to use this feature. CatWeasel MK3 PCI SID support is available with -C option (-C1 to turn on). To use the PC64 cable, you need Daniel Illgen's HardSID-DLL-Clone. Available at http://dawork.synchronus.de/ To enable better support of multispeeds and cycle-exact timing on HardSID (currently Win32 only), download an enhanced HardSID.dll: For HardSID ISA/PCI cards - http://sourceforge.net/project/showfiles.php?group_id=9266&release_id=61843 For HardSID 4U - http://www.hardsid.com Cycle-exact HardSID buffer length is separately configurable for interactive mode (-T option) & playback mode (-U option). HardSID interactive mode: Low latency mode for jamming and accurate GUI display. Interactive mode can be activated during song/pattern playback by enabling jamming (space key). HardSID playback mode: High stability mode to avoid interruptions caused by other applications/poor drivers/weaker CPU. GUI display is less accurate in this mode. Set the -U parameter to zero to achieve the maximum stability (less accurate GUI). 2.3 Keyboard commands --------------------- This program is mainly operated on keyboard. For a list of keyboard commands press F12 (online help) in the tracker or see the table below: NOTE: SHIFT & CTRL are interchangeable in the commands. You can also use [ ] or ( ) instead of < >. 2.3.1 General keys ------------------ F1 Play from beginning F2 Play from current pos. F3 Play one pattern from current pos. F4 Stop playing & silence all sounds F5 Go to pattern editor F6 Go to song editor F7 Go to instrument/table editor F8 Go to songname editor F9 Pack, relocate & save PRG,SID etc. F10 Load song (Pattern/Song/Songname mode) or instrument (Instrument mode) F11 Save song (Pattern/Song/Songname mode) or instrument (Instrument mode) F12 Online help screen. Press F12 again to toggle context mode SHIFT+F1 Play from beginning /w follow play SHIFT+F2 Play from current pos. /w follow play SHIFT+F3 Play one pattern from current pos. /w follow play SHIFT+F4 Mute current channel SHIFT+F5 Decrease speed multiplier SHIFT+F6 Increase speed multiplier SHIFT+F7 Edit hardrestart ADSR parameter SHIFT+F8 Switch between 6581 and 8580 SID models SHIFT+,. Move song startposition on all channels and restart last playmode TAB Cycle between editing modes (forwards) SHIFT+TAB Cycle between editing modes (backwards) INS Insert row (Press INS/DEL on endmark to change pattern/song length) DEL Delete row SHIFT+ESC Optimize musicdata, or clear musicdata & set default pattern length ESC Exit program 2.3.2 Pattern edit mode ----------------------- - + Select instrument / * Select octave < > Select pattern BACKQUOTE Select channel 0-9 & A-F Enter parameters SPACE Switch between jam/editmode RETURN (also CAPSLOCK) Insert keyoff Enter table (when cursor is over a table-utilizing command) Enter instrument (when cursor is over a nonzero instrument number) SHIFT+RET. Insert keyon Convert portamento/vibrato/funktempo old style parameter to a speedtable entry (when cursor is over the command) Go into an empty table entry (when parameter is zero on a table-utilizing command) BACKSPACE Insert rest SHIFT+BKSP. Insert rest and clear commands SHIFT+SPACE Play from cursor position SHIFT+Q Transpose halfstep up SHIFT+A Transpose halfstep down SHIFT+W Transpose octave up SHIFT+S Transpose octave down SHIFT+O Shrink pattern (divide size by 2) SHIFT+P Expand pattern (multiply size by 2) SHIFT+J Join pattern with next pattern in orderlist SHIFT+K Split pattern from edit position SHIFT+H Calculate "hifi" left/right shifted speedtable entry for portamento or vibrato SHIFT+I Invert selection / whole pattern if no selection SHIFT+CRSR UP,DOWN Mark pattern SHIFT+CRSR LEFT,RIGHT Select pattern SHIFT+L Mark/unmark entire pattern SHIFT+M,N Choose highlighting step size SHIFT+X,C,V Cut,copy,paste pattern SHIFT+E,R Copy,paste commands SHIFT+Z Cycle autoadvance-mode For pattern joining to work properly, select the pattern you want to join with the next from the orderlist first (by pressing RETURN on it). Both joining and splitting will rearrange pattern numbers (for example if you split pattern 00, pattern 01 will be created and old patterns 01-xx will be shifted forward in the pattern order) SHIFT+SPACE will play from the pattern onwards if playback was previously stopped, but if it is pressed while in pattern play mode, it will stay in the current pattern. There are 2 modes for note entering: 2.3.2.1 Protracker note-entry mode ---------------------------------- This is the default or activated with command line option /K0. There are two rows of a piano keyboard: Lower octave Higher octave S D G H K L 2 3 5 6 7 9 0 Z X CV B NM , . Q W ER T Y UI O P Octave (0-7) is selected with / and * keys on the numeric keypad. In this mode there are 2 different autoadvance-modes (the mode can be seen from the color of the jam/editmode indicator) GREEN - Advance when entering notes & command-databytes RED - Do not advance automatically 2.3.2.2 DMC note-entry mode --------------------------- Activated with command line option /K1, there is one row of piano keyboard W E T Y U O P A S DF G H JK L and octave of a note (sets default octave at the same time) is changed with number keys 0-7. In this mode there are 3 different autoadvance-modes: GREEN - Advance when entering notes, octaves or command-databytes YELLOW - Advance when entering notes or command-databytes, not octaves RED - Do not advance automatically 2.3.3 Song edit mode -------------------- < > Select subtune - + Insert Transpose down/up command (shown as -/+ in the orderlist) 0-9 & A-F Enter pattern numbers SPACE Set start position for F2 key BACKSPACE Set end position for F2 key RETURN Go to pattern SHIFT+R Insert Repeat command (shown as "R" in the order-list) SHIFT+CRSR LEFT/RIGHT Mark orderlist SHIFT+1,2,3 Swap current channel orderlist with channel 1,2,3 SHIFT+X,C,V Cut,copy,paste channel orderlist SHIFT+L Mark/unmark entire orderlist SHIFT+SPACE Set start position on all channels SHIFT+RET. Go to pattern on all channels SHIFT+SPACE or SHIFT+BACKSPACE set the start/end mark on all channels to the same position. To clear the endmark, press BACKSPACE again on it or at/before the startmark. 2.3.4 Instrument edit mode -------------------------- < > Select instrument - + Select instrument / * Select octave F7 Go to table editor 0-9 & A-F Enter parameters SPACE Play test note SHIFT+SPACE Silence test note RETURN Go to table position indicated by wave/pulse/filter/vibratopos. SHIFT+N Edit instrument name SHIFT+S Smart paste an instrument SHIFT+U Unlock/lock table scrolling SHIFT+X,C,V Cut,copy,paste instrument SHIFT+DEL (also SHIFT+BACKSPACE) Delete instrument & tabledata SHIFT+RET. Set tablepointer to empty position or convert old style vibrato parameter The test note will be played on the channel you last were on in the pattern editor. To hear filtering as intended, be sure to play it on a channel that has been selected for filtering in the filter parameters. Note that cut,copy,paste instrument do not touch the tabledata, just for the case you need it in another instrument. If you want to completely get rid of an instrument + its associated tabledata, press SHIFT+DEL. If wave/pulse/filter/vibrato param. is zero and you press RETURN over it, you will move to the first free location in the corresponding table. If you press SHIFT+RETURN, also the instrument parameter will be set accordingly. If vibrato parameter is nonzero and you press SHIFT+RETURN over it, it will be interpreted as an old style vibrato parameter (left nybble speed, right nybble depth) and converted to a speedtable entry. "Smart paste" will convert instrument numbers in all patterns if you "move" an instrument by cut/pasting it. 2.3.5 Table edit mode --------------------- < > Select instrument - + Select instrument / * Select octave BACKQUOTE Select table F7 Go to instrument editor 0-9 & A-F Enter parameters SPACE Play test note SHIFT+SPACE Silence test note RETURN Go back to wave/pulse/filterpos. parameter SHIFT+Q,A Transpose speedtable portamento speed halfstep up/down SHIFT+W,S Transpose speedtable portamento speed octave up/down, or multiply/divide pulse/filterspeed by 2 SHIFT+L Convert modulation step to SHIFT+N Negate speed parameter (pulse/filtertable) or relative note (wavetable) SHIFT+O Optimize current table (remove unused entries) SHIFT+R Convert note between absolute/relative in wavetable SHIFT+U Unlock/lock table scrolling If you need to insert rows in the beginning of an instrument's wave/pulse/ filtertable, press SHIFT+INS instead of just INS: this way table pointers pointing to the table first row will not move. For easier programming of negative modulation speeds in pulse/filtertables, you can first enter a positive speed positive value ($00-$7F) and then press SHIFT+N to negate it. Conversion between relative and absolute notes will use the basenote C-0 if octave is 0, C-1 if octave is 1 and so on. When table scrolling is unlocked, each table maintains its separate view position. To indicate this mode, a "U" letter is visible in the bottom right part of the screen. By default table scrolling is locked. 2.3.6 Songname edit mode ------------------------ Use cursor UP/DOWN to move between song, author & copyright strings, and other keys to edit them. 2.4 Mouse control ----------------- By clicking with the left mouse button, you can select the data to edit. By dragging with middle or right mouse button, you can mark orderlist/pattern/ tabledata. Some values like octave or subtune/pattern numbers can be incremented with the left mouse button and decremented with the right. By holding the middle/right mouse button in the status bar, a menu becomes active. Continue to hold and click with left button to select options. In the fileselector, confirm loading or entering a directory by double- clicking. Doubleclick outside the selector to cancel. 3. Song data ------------ 3.1 Orderlist data ------------------ A song can consist of up to 32 subtunes. For each subtune's each channel, there is an orderlist which determines in what order patterns are to be played. In addition to pattern numbers, there can be TRANSPOSE & REPEAT commands and finally there is a RST (RESTART) endmark followed by restart position. The maximum length of an orderlist is 254 pattern numbers/commands + the endmark. TRANSPOSE is measured in halftones. Transpose up (shown as +X) can be 0-14 halftones and transpose down (shown as -X) can be 1-15. Transpose is automatically reset only when starting the song, not when looping. A REPEAT command (shown as RX) will repeat the pattern following it 1-16 times. "Repeat 16 times" is displayed as R0. There are some rules for orderlist command order: - If there are both TRANSPOSE and REPEAT commands before a pattern number, TRANSPOSE must come first. - The last thing before the RST-endmark must be a pattern number. If you need to reset transpose on song repeat, do it in the beginning of the repeat loop. In case of wrong order, the editor will halt playback. This tells that the resulting packed/relocated song would play incorrectly. 3.2 Pattern data ---------------- Patterns are single-channel only for flexibility & low memory use. They contain the actual notes, instrument changes & sound commands. A pattern can have variable length, up to 128 rows. There can be 208 different patterns in a song. The explanation of a pattern row: Note name | | Octave | | | | Instrument number ($01 - $3F, or $00 for no change) | | | | | | Command ($0 - $F) | | | | | | | | Databyte | | | | | C-1 00 0 00 The highest note available in a pattern is G#7. To reach the top three notes (A-7 to B-7), you can use transpose. In place of a normal note, there can also be one of these special "notes": ... Rest --- Key off (clear gatebit mask) +++ Key on (set gatebit mask) The actual state of the gatebit will be the gatebit mask ANDed with data from the wavetable. A key on cannot set the gatebit if it was explicitly cleared at the wavetable. Commands 1XY-4XY and FXY bear some resemblance to Soundtracker/Protracker/ Fasttracker effect commands. However, they are different in some ways, so read their descriptions! Note that there is no "databyte $00 uses the last databyte"-action in the commands. Command 0XY: Do nothing. Databyte will always be $00. Command 1XY: Portamento up. XY is an index to a 16-bit speed value in the speedtable. Command 2XY: Portamento down. XY is an index to a 16-bit speed value in the speedtable. Command 3XY: Toneportamento. Raise or lower pitch until target note has been reached. XY is an index to a 16-bit speed value in the speedtable, or $00 for "tie-note" effect (move pitch instantly to target note) Command 4XY: Vibrato. XY is an index to the speed table, where left side determines how long until the direction changes (speed) and right side determines the amount of pitch change on each tick (depth). Command 5XY: Set attack/decay register to value XY. Command 6XY: Set sustain/release register to value XY. Command 7XY: Set waveform register to value XY. If a wavetable is actively changing the channel's waveform at the same time, will be ineffective. Command 8XY: Set wavetable pointer. $00 stops wavetable execution. Command 9XY: Set pulsetable pointer. $00 stops pulsetable execution. Command AXY: Set filtertable pointer. $00 stops filtertable execution. Command BXY: Set filter control. X is resonance and Y is channel bitmask. $00 turns filter off and also stops filtertable execution. Command CXY: Set filter cutoff to XY. Can be ineffective if the filtertable is active and also changing the cutoff. Command DXY: Set mastervolume to Y, if X is $0. If X is not $0, value XY is copied to the timing mark location, which is playeraddress+$3F. Command EXY: Funktempo. XY is an index to the speedtable, tempo will alternate between left side value and right side value on subsequent pattern steps. Sets the funktempo active on all channels, but you can use the next command to override this per-channel. Command FXY: Set tempo. Values $03-$7F set tempo on all channels, values $83- $FF only on current channel (subtract $80 to get actual tempo). Tempos $00-$01 recall the funktempo values set by EXY command. Master volume is by default the maximum ($F), but it is only reset when loading a new song or clearing songdata in the editor, not every time playback starts. If you change mastervolume, you have to reset it manually in the beginning of your song. If the command is not 1XY-4XY, instrument vibrato will be active. Note that the one-shot commands 5XY-FXY allow the previous 1XY-4XY command or instrument vibrato to continue "underneath" them. In section 3.6 (hints & tips) there is an example of this. 3.3 Instrument data ------------------- You can use up to 63 different instruments in a song. Each instrument is defined by 9 parameters: Attack/Decay $0 is fastest attack or decay, $F is slowest Sustain/Release Sustain level $0 is silent and $F is the loudest. Release behaves like Attack & Decay (F slowest). Wavetable Pos Wavetable startposition. Value $00 stops the wavetable execution and is not very useful. Pulsetable Pos Pulsetable startposition. Value $00 will leave pulse execution untouched. Filtertable Pos Filtertable startposition. Value $00 will leave filter execution untouched. In most cases it makes sense to have a filter-controlling instrument only on one channel at a time. Vibrato Param Instrument vibrato parameter. An index to the speedtable, see command 4XY. Vibrato Delay How many ticks until instrument vibrato starts. Value $00 turns instrument vibrato off. HR/Gate Timer How many ticks before note start note fetch, gateoff and hard restart happen. Can be at most tempo-1. So on tempo 4 highest acceptable value is 3. Bitvalue $80 disables hard restart and bitvalue $40 disables gateoff. 1stFrame Wave Waveform used on init frame of the note, usually $09 (gate + testbit). Values $00, $FE and $FF have special meaning: leave waveform unchanged and additionally set gate off ($FE), gate on ($FF), or gate unchanged ($00). In case of illegal (too high) gateoff timer values, the song playback is stopped. ADSR settings are crucial to getting any sound at all. If all of them are zero just a very short "click" will be heard. Here is a diagram to help you visualize the Attack, Decay, Sustain & Release phases: V /\ |<- gatebit reset (key-off) at this point O / \ | L / \__________| U / |\ M / | \ E / | \ TIME ----------------------------> A D S R Some ADSR examples: A/D 09 Will produce a sound that starts from full volume right away and fades S/R 00 to silence automatically. By increasing the Decay value, the fade will last longer. A/D 00 A sound that goes very fast from full volume to sustain level 8. S/R 8A If you increase the Decay value, it will go to the sustain level slower. After key-off, starts fading out with speed A. A/D CC A sound that rises slowly to maximum volume, then decays slowly to the S/R AF sustain level A and after key-off, fades out to silence very slowly. Instrument legato works as following: When HR/Gate Timer parameter has bit $40 set, no hard restart or gateoff will be performed. When 1st Frame Wave is also $00, no 1st frame waveform will be set and gate flag is untouched. However wave/ pulse/filterpointers and ADSR are initialized normally. You can also use this in conjunction with command 8XY to set another wavetable pointer for the note. 3.4 Table data -------------- Tables control the execution of instruments' waveform/arpeggio changes, pulse modulation, and filter modulation. All the tables are controlled by the left side bytes, while the right side byte specifies additional parameters. Note that you should never jump directly onto a table jump command (FF) either with instrument parameters or pattern commands 8XY, 9XY, AXY. Otherwise, results are undefined. 3.4.1 Wavetable --------------- Wavetable left side: 00 Leave waveform unchanged 01-0F Delay this step by 1-15 frames 10-DF Waveform values E0-EF Inaudible waveform values $00-$0F F0-FE Execute command 0XY-EXY. Right side is parameter. FF Jump. Right side tells position ($00 = stop) Wavetable right side: 00-5F Relative notes 60-7F Negative relative notes (lower pitch) 80 Keep frequency unchanged 81-DF Absolute notes C#0 - B-7 Short explanation of waveform bitvalues: 01 = Gatebit. When on, initiates attack/decay/sustain phase. When off, initiates the release phase. 02 = Synchronize. Creates weird effects using output of another channel 04 = Ring modulation. Creates weird effects using output of another channel. Most effective with the triangle waveform. 08 = Testbit. Silences sound and resets the oscillator. 10 = Triangle waveform. 20 = Sawtooth waveform. 40 = Pulse waveform. 80 = Noise waveform. All waveforms except noise can be combined (for example triangle+pulse), but the effect will be different on 6581 and 8580 SID chips, so use caution. The way how the channels work with synchronize/ringmod: - When used on channel 1, channel 3's output modulates the sound. - When used on channel 2, channel 1's output modulates the sound. - When used on channel 3, channel 2's output modulates the sound. Wavetable delay or no wavechange should not be used in the first step of instrument wavetable. Otherwise, missing notes may be caused. On the other hand, if you use 8XY command to jump into a wavetable program, those are allowed. Using wavetable delay or a wavetable step with no frequency change allows realtime commands & instrument vibrato to be executed together with wave- table. Be warned that this has the potential for large rastertime usage! You can execute pattern commands from the wavetable. Right side is the command parameter. Note that commands 0XY (do nothing), 8XY (set wavetable pointer) and EXY (funktempo) are illegal and should not be used. When executing a command, no wave/note will be changed on the same frame. Some examples of wave tables (all examples start on table step 1) 01: 21 00 Sawtooth waveform on note's original pitch. 02: FF 00 01: 41 00 A flute sound with pulse on the first tick and triangle on all 02: 11 00 the rest. 03: FF 00 01: 41 01 A "koto" sound that is one halfstep higher on the first tick and 02: 40 00 on original pitch the next. Gatebit is also cleared on the second 03: FF 00 tick. 01: 81 D0 A snaredrum sound, using all absolute notes so it does not depend 02: 41 AA on which note it's played. Use pulsewidth 800 for best result. 03: 41 A4 04: 80 D4 05: 80 D1 06: FF 00 01: 81 DF A pulse sound on original pitch, preceded with a short noise (like 02: 41 00 a hi-hat or something) that has always an absolute pitch of B-7. 03: FF 00 01: 41 00 A 4-note looping arpeggio sound with pulse waveform. Note that 02: 00 04 waveform does not change in the looping part. 03: 00 07 04: 00 0C 05: 00 00 06: FF 02 01: 21 00 A delayed minor chord arpeggio with sawtooth waveform. Each step 02: 02 03 takes 3 ticks. 03: 02 07 04: 02 00 05: FF 02 01: 41 00 Use pulse first, but then switch between pulse & triangle every 5 02: 03 80 ticks while frequency remains unchanged (allowing for vibrato & 03: 11 80 slides). 04: 03 80 05: 41 80 06: FF 02 01: 81 CF Short noise in the beginning, sawtooth, after a short delay change 02: 21 00 sustain/release (via pattern command 6XY) to $2A. 03: 08 00 04: F6 2A 05: FF 00 3.4.2 Pulsetable ---------------- Pulsetable left side: 01-7F Pulse modulation step. Left side indicates time and right side the speed (signed 8-bit value). 8X-FX Set pulse width. X is the high 4 bits, right side tells the 8 low bits. FF Jump. Right side tells position ($00 = stop) Some examples of pulse tables (all examples start on table step 1) 01: 88 00 Set pulse value $800 (middle) 02: FF 00 Stop pulse execution 01: 80 10 Set pulse value $010 (very thin) 02: 20 40 For 32 ticks, increase pulse with speed $0040 (64) 03: 40 E0 For 64 ticks, decrease pulse with speed $FFE0 (-32) 04: 40 20 For 64 ticks, increase pulse with speed $0020 (32) 05: FF 03 Jump back to step 03 for a nice loop 3.4.3 Filtertable ----------------- Filtertable left side: 00 Set cutoff, indicated by right side 01-7F Filter modulation step. Left side indicates time and right side the speed (signed 8-bit value) 80-F0 Set filter parameters. Left side high nybble tells the passband ($90 = lowpass, $A0 = bandpass etc.) and right side tells resonance/channel bitmask, as in command BXY. FF Jump. Right side tells position ($00 = stop) If "Set filter parameters" is followed by "Set cutoff" directly below, both will be executed on the same frame. Some examples of filter tables (all examples start on table step 1) 01: 90 F1 Set lowpass, resonance F, channel bitmask 1 (filter channel 1 only) 02: 00 40 Set cutoff to $40 03: FF 00 Stop filter execution 01: 80 00 No passband selected, resonance 0, bitmask 0 (no filtered channels) 02: FF 00 Stop filter execution 01: A0 87 Set bandpass, resonance 8, channel bitmask 7 (filter all channels) 02: 00 00 Set cutoff to $00 03: 7F 01 Increase cutoff with speed $01 for 127 ticks 04: 7F 01 Continue cutoff increase 05: 7F FF Then decrease back to starting position (speed $FF = -1)... 06: 7F FF 07: FF 03 ...and loop back to step 03 01: C0 F2 Set highpass, resonance F, channel bitmask 2 (filter channel 2) 02: 00 F0 Set cutoff to $F0 03: 90 F2 On the next frame, change to lowpass... 04: 00 50 ...and set cutoff $50 05: FF 00 Stop filter execution Note that the second example could also be achieved simply with pattern command B00 (set filter control, and stop filter execution, because parameter was $00) 3.4.4 Speedtable ---------------- The speedtable is shared by vibrato, portamento and funktempo. No jump commands exist. For vibrato: XX YY Left side tells how long until vibrato direction changes (speed), right side is the value added to pitch each tick (depth). For portamento: XX YY A 16-bit value added to pitch each tick. Left side is the MSB and the right side the LSB. For funktempo: XX YY Two 8-bit tempo values that are alternated on each pattern row, starting from the left side. For both vibrato and portamento, if XX has the high bit ($80) set, note independent vibrato depth / portamento speed calculation is enabled, and YY specifies the divisor (higher value -> lower result and more rastertime taken). Vibrato examples: 01: 03 40 Vibrato with speed $03 and depth $40. Corresponds to old vibrato parameter $34 01: 05 04 Speed $05 and depth $04. Slow shallow vibrato, suitable for bass notes. Not possible to achieve with old parameters. 01: 83 04 Speed $03, note-independent depth enabled, depth divisor 4 right- shifts (division by 16). Portamento examples: 01: 00 20 Portamento with speed $0020, corresponds to old parameter $08 (4 * $08 = $0020). 01: 01 00 Portamento with speed $0100, corresponds to old parameter $40 (4 * $40 = $0100). 01: 4F FF Portamento with speed $4fff, loops the pitch highbyte very fast so that a SEUCK-like "space" effect is heard. Not possible to achieve with old parameters. 01: 80 01 Note-independent speed enabled, speed divisor 1 rightshift (division by 2). Funktempo examples: 01: 09 06 Play tempo $09 on even pattern steps and $06 on odd steps, corresponds to old parameter $96. 01: 24 18 The same funktempo adjusted for 4x-multispeed. Not possible to achieve with old parameters. Note that you can enter old style vibrato parameters, portamento speeds and funktempo to patterns & instruments, and when cursor is over the parameter, press SHIFT+RETURN to create a new speedtable entry corresponding to that parameter. The parameter will now be overwritten by a speedtable pointer. 3.5 Playback details -------------------- Each pattern row is divided into as many 50Hz/60Hz "ticks" as the tempo indicates. Some ticks are reserved for special actions, and to conserve raster- time, certain realtime effects/commands (pulse, vibrato, portamento) are skipped at the same time. Let's assume a tempo of 6 and gateoff timer value 2 and look at what happens on each tick: Tick Actions 0 - Initialization of new notes (no audible sound yet) - Orderlist advance if necessary - Pulsetable execution only if no orderlist advance - Wavetable execution - "One-shot" commands 5XY-FXY 1 - New notes become audible - Pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY 2,3 - Pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY 4 - New notes fetched from the pattern - Gateoff and hard restart for new notes (2 ticks before first frame, as gateoff timer indicates) - No pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY 5 - Pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY Filtertable is executed on each tick regardless of what the channels are doing. Wavetable is never skipped, so arpeggios/drumsounds should always play OK. With the commandline parameter /O0 (or by clicking the "PO" text on the status bar) you can disable pulse skipping. This leads to increased rastertime use but can be good for example with tempo 3 tunes. Likewise, with the commandline parameter /R0 (or by clicking the "RO" text on the status bar) you can disable realtime pattern command skipping on tick 0. 3.6 Miscellaneous tips ---------------------- - Patterns will take less memory the less there are command changes. When the song is packed/relocated, for example a long vibrato or portamento command needs to be stored only once as long as the parameter stays the same on subsequent pattern rows. - Using instrument vibrato can make 4XY commands unnecessary and save even more memory. Use realtime calculated note-independent speed (see speedtable section) if you want the vibrato to have the same magnitude regardless of the note. - In the instrument parameters, there is no option to stop pulse execution directly. So if you have for example a sawtooth instrument, there might be an "unnecessary" pulsemodulation going on underneath and wasting rastertime. There are two ways you can stop this: 1) Make a short pulseprogram like this and use it in the instrument: 01: 80 00 Set pulse $000 02: FF 00 Stop pulse execution 2) Use pattern command 900 to stop pulse execution - If you have a realtime command (vibrato/portamento), you can put "one-shot" commands 5XY-FXY inbetween and the realtime command will be unaffected. An example: C-4 01000 --- 00401 Begin vibrato with speedtable index $01 --- 00401 --- 00401 --- 0065A Set sustain/release to $5A. Vibrato executes also on this step! --- 00401 Continue vibrato normally --- 00401 However, the vibrato would stop immediately if command 0 was encountered. - Normally tempo 3 is the fastest you can use. However, by using the funktempo command you can get tempo 2. To do this, create a following speedtable entry: 02 02, and point your funktempo command to it. You also need to use gateoff timer 1 in all instruments and disable the pulse-optimization skipping. - For very optimized songdata & player you can refrain from using any pattern commands and rely on the instruments' step-programming. Even in this case, you can set song startup default tempo with the Attack/Decay parameter of the last instrument (63), if you otherwise leave this instrument unused. 3.6.1 Limit-based modulation steps ---------------------------------- You can enter pulse/filter modulation steps in limit-based format, and convert them to time-based with SHIFT+L. For example, you could enter the following in the pulsetable: 01: 84 00 Set initial pulse to $400 02: C0 10 Modulate pulse to $C00 with speed $0010 03: 40 10 Modulate pulse back to $400 with speed $0010 Now position the cursor on step 02 and press SHIFT+L twice, to convert both of the modulation steps to usual time-based steps. If necessary, the steps will be expanded to several (if the resulting time parameter is over $7F.) Remember that the player only understands time-based steps and you always have to convert limit-based steps before they play correctly! 3.6.2 Precalculated note-independent "hifi player" portamento/vibrato --------------------------------------------------------------------- From v2.62 onwards, GoatTracker actually supports realtime calculated note independent portamento and vibrato speeds, see speedtable section for this. However, this makes the player bigger and much slower. You can still also use the old method of manually precalculating needed note-independent speeds with the SHIFT+H function, which this section is about. The idea is to take the frequency difference between 2 adjacent notes in the frequency table and manipulate it by bit shifting left (multiply) or right (divide). To use, you need a portamento or vibrato command in the pattern, and the note you wish to base the calculation on on the current pattern step or before it (before it only for toneportamento) The amount of shift is determined by the command parameter. A number in the left nybble means shift left and right nybble right shift. When you press Shift+H while the cursor is on the command, a speedtable entry is created, and the parameter is replaced with a speedtable index. Some examples: C-3 00110 Take the frequency difference between C-3 & C#3 and shift it left 1 times (multiply by 2.) E-4 00000 ... 00000 G-4 00302 Take the frequency difference between E-4 & F-4 and shift it right 2 times (divide by 4.) 3.7 Multispeed tips ------------------- - When making multispeed songs, remember to multiply your tempos and also the gateoff timer values! For example, gateoff timer is normally 2, but in a 2X- speed tune the same gateoff length would be achieved with value 4. - If you want to keep vibrato the same compared to 1X-speed, you must multiply vibrato speed by the speed multiplier, and divide vibrato depth by the multiplier. Remember also to divide portamento and pulse/filter modulation speeds as necessary. - When importing a v1.xx multispeed song, you also need to multiply the gateoff timers. - In the instruments, using Attack 0 might result in a very silent first row of the wavetable. You could try increasing the attack, or adding one or more rows of E9 00 (testbit+gate) to the beginning of the wavetable. 4. Using the included utilities ------------------------------- 4.1 INS2SND2.EXE ---------------- INS2SND2.EXE converts GoatTracker v1.xx or v2 instruments (.INS-files) into sound effects, outputting the data as source code or binary. Usage: INS2SND Options: -b output in binary -c output in CovertScript format (deprecated) Default output is C64 assembler (DASM) style source code Look at section 6.3 or run the program without parameters to see the limitations of the sound effect system. 4.2 SNGSPLI2.EXE ---------------- SNGSPLI2.EXE splits the patterns of a GoatTracker v2 song into smaller pieces for memory use optimization. It is comfortable to compose with large patterns but usually more efficient memory-wise to use small patterns. Remember! Always keep the original song because a pattern-splitted song is much harder to edit further. Usage: SNGSPLI2 [target len] For example, if a pattern is 64 rows long and the target length is 16, it will be split into 4 pieces. A pattern that falls below 2 x target length, will not be split at all. 4.3 MOD2SNG.EXE --------------- Dedicated exclusively to T.M.R, this program converts the pattern & orderlist data of 4-channel, 31-instrument MOD-files into GoatTracker .SNG files. You must choose one channel to leave out, and obviously instruments are not converted, except for their names. You can also specify a transpose in halfsteps. Usage: MOD2SNG [channel] [transpose] [channel] is the channel to leave out (1-4), default 4 [transpose] is the halfstep transpose added to notes, default 0 4.4 BETACONV.EXE ---------------- Converts GT v2 beta songs to new format used by GT v2 RC1 onwards. Old format had 47 instruments max. and new has 63 max. Additionally, depending on what beta version you used, you can choose to halve vibrato depths and pulse speeds to make them play correct in the current version. Warning: the conversion is irreversible, so have backups if you overwrite the old versions. Usage: BETACONV [vibdepth] [pulse] [vibdepth] decides whether to halve vibdepth (1=yes 0=no), default 0 [pulse] decides whether to halve pulse speed (1=yes 0=no), default 0 5. Using the songs outside the editor ------------------------------------- Press F9 in the editor to enter the packer/relocator. Choose playroutine options, startaddress, zeropage address (need 2 consecutive locations) and file format (PRG/BIN/SID), then type the filename. If you use patterns longer than 64 rows, there is the possibility that relocation fails because of too complex patterns. Each pattern row can be 0-4 bytes packed, and the total amount of bytes per one pattern may not exceed 256. If wave/pulse/filtertables overflow past row 255 without a jump command or there are other serious errors, you get a warning screen and have to fix the error. The relocator optimizes & removes when saving: - Unused patterns - Unused instruments - Unused table-entries - Selfcontained (ie. no jumps to/from outside) duplicate parts of tables - Player code not needed in the playback of the song Look at /examples/example1.prg - example4.prg to get an idea how much these playroutines take rastertime. No promises! The basic functions independent of playroutine options are: Init music: LDA #subtunenumber ;Starting from 0 JSR startaddress Play one frame of music: JSR startaddress+3 5.1 Playroutine options ----------------------- BUFFERED SID-WRITES - Instead of writing each SID value as soon as possible, waits for the end of the channel's execution on each frame and then writes the registers in one go. Improves sound stability but takes more memory & raster- time. SOUND EFFECT SUPPORT - Adds a sound effect engine for use in games. Implies buffered writes. To use, call in the following way: LDA #effect LDX #channel ;0, 7 or 14 for channels 1-3 JSR startaddress+6 The sound effects have a hardcoded priority system based on their start addresses. A sound higher up in memory (bigger address) will never be interrupted with a sound lower in memory. VOLUME CHANGE SUPPORT - Adds a routine in the player's jumptable to change the master volume level. To use, call in the following way: LDA #volume ;0-15 JSR startaddress+6 ;(startaddress+9 with sound effect support) Note that the master volume command (DXY) also modifies this same location, so it will clash if you also change the volume manually. STORE AUTHOR-INFO - Writes the "AUTHOR" string from songname editor to the location range (startaddress+$20 - startaddress+$3F). Also enables timing mark support. A timing mark is a mastervolume command (DXY) with parameter $10-$FF. This parameter will be copied into startaddress+$3F when the command is encountered in playback. USE ZEROPAGE GHOSTREGS - Instead of writing to the SID, a memory range in the zeropage is used for holding the SID register data. This can then be copied in the main program to the SID, for example to enable the playroutine & music data to reside under the I/O area. Implies buffered writes. A reverse copy loop should be used after each call to the playroutine: LDX #$18 copy: LDA ghostregs,x STA $D400,x DEX BPL copy The copy loop can also be unrolled for more speed. Note that when you use the alternative hardrestart method & playroutine (hard- restart attack parameter F) the copy loop should not be in reverse order but should be for each channel: wave, frequency, pulsewidth, and ADSR last. If you are using both sound effect support and ghostregisters, there exists a possibility of sound errors in the case that a sound effect has finished, and the same channel starts a new pulse-waveform note without setting an initial pulsewidth value (for example, like in the beginning of Sanxion loader tune). This is because the ghostregisters are shared between music & sound effect playback, and the sound effect has already overwritten the previous pulse width. DISABLE OPTIMIZATIONS - The relocator removes saved playroutine code based on what effects & commands the song uses, resulting in a smaller playroutine accordingly. If you encounter anomalies in the sound (such as ADSR bugs caused by unpredictable timing variation) you can try disabling the optimizations. Normally this is not necessary, but is included just in case. 6. File/data formats description -------------------------------- The sections in the files appear in the sequential order in which they are described. 6.1 GoatTracker v2 song (.SNG) format ------------------------------------- 6.1.1 Song header ----------------- Offset Size Description +0 4 Identification string GTS5 +4 32 Song name, padded with zeros +36 32 Author name, padded with zeros +68 32 Copyright string, padded with zeros +100 byte Number of subtunes 6.1.2 Song orderlists --------------------- The orderlist structure repeats first for channels 1,2,3 of first subtune, then for channels 1,2,3 of second subtune etc., until all subtunes have been gone thru. Offset Size Description +0 byte Length of this channel's orderlist n, not counting restart pos. +1 n+1 The orderlist data: Values $00-$CF are pattern numbers Values $D0-$DF are repeat commands Values $E0-$FE are transpose commands Value $FF is the RST endmark, followed by a byte that indicates the restart position 6.1.3 Instruments ----------------- Offset Size Description +0 byte Amount of instruments n Then, this structure repeats n times for each instrument. Instrument 0 (the empty instrument) is not stored. Offset Size Description +0 byte Attack/Decay +1 byte Sustain/Release +2 byte Wavepointer +3 byte Pulsepointer +4 byte Filterpointer +5 byte Vibrato param. (speedtable pointer) +6 byte Vibraro delay +7 byte Gateoff timer +8 byte Hard restart/1st frame waveform +9 16 Instrument name 6.1.4 Tables ------------ This structure repeats for each of the 4 tables (wavetable, pulsetable, filtertable, speedtable). Offset Size Description +0 byte Amount n of rows in the table +1 n Left side of the table +1+n n Right side of the table 6.1.5 Patterns header --------------------- Offset Size Description +0 byte Number of patterns n 6.1.6 Patterns -------------- Repeat n times, starting from pattern number 0. Offset Size Description +0 byte Length of pattern in rows m +1 m*4 Groups of 4 bytes for each row of the pattern: 1st byte: Notenumber Values $60-$BC are the notes C-0 - G#7 Value $BD is rest Value $BE is keyoff Value $BF is keyon Value $FF is pattern end 2nd byte: Instrument number ($00-$3F) 3rd byte: Command ($00-$0F) 4th byte: Command databyte 6.2 GoatTracker v2 instrument (.INS) format ------------------------------------------- Offset Size Description +0 4 Identification string GTI5 +4 byte Attack/Decay +5 byte Sustain/Release +6 byte Wavepointer +7 byte Pulsepointer +8 byte Filterpointer +9 byte Vibrato param. (speedtable pointer) +10 byte Vibrato delay +11 byte Gateoff timer +12 byte Hard restart/1st frame waveform +13 16 Instrument name After the instrument data, this structure repeats for each of the 4 tables (wavetable, pulsetable, filtertable, speedtable). Offset Size Description +0 byte Amount n of rows in the table +1 n Left side of the table +1+n n Right side of the table Note that the tables are a partial snapshot of the current song the instrument was saved from, so upon loading they have to be relocated to the current free table locations. 6.3 Sound effect data format ---------------------------- Offset Size Description +0 byte Attack/Decay +1 byte Sustain/Release +2 byte Pulse width. This value has nybbles reversed from what it looks like in the editor so a middle pulse $800 will be stored as $08, and the sound effect routine will put this value to both $D402 and $D403 registers. +3 ? Wavetable. Contains note/waveform pairs (different order than in instrument wavetable), from which the waveform can be omitted if unchanged, as the value ranges do not overlap: Value $00 ends the sound effect Values $01-$81 are waveforms Values $82-$DF are absolute notes D-0 - B-7 Note that a note cannot be omitted to store only waveform changes! As you can see, the sound effect format is very simplistic. When converting an instrument to a sound effect with INS2SND2, following things cause an error message: - If the resulting sound effect is more than 128 bytes - If the instrument's wavetable contains relative notes, absolute notes C-0 or C#0, or waveforms > 129 ($81) The instrument's pulsewidth modulation & filter settings will be completely discarded. 7. Recompiling -------------- To recompile for Win32, you need the MinGW development environment, use the file src/makefile.win as makefile. To recompile for Linux, use src/makefile. In both cases you need the SDL development libraries in addition to the SDL runtime, see http://www.libsdl.org. Compile first the utilities (datafile & dat2inc) from the src/bme directory, and place them to your path. 8. Version history ------------------ v2.0Beta - Original public release v2.0 - Fixed crash in DMC-note entry mode. - Fixed v1.xx import pulse conversion, a case where pulse startpos was lower than the pulse low limit was not converted right. - Fixed instrument gatetimer becoming zero (can lead to tempo bugs) when cutting an instrument (SHIFT+X) - Fixed order of SID writes to make editor & C64 playroutine behave as similarly as possible. - Fixed removal of table-entries (when loading an instrument) in case another instrument uses them too. - Fixed toneportamento (3XY) with wavetable delays. - Fixed funktempo in packed/relocated songs. - Fixed behaviour of + & - keys while editing instrument name. - Fixed pattern editor transpose functions. - Added SHIFT+DEL to delete an instrument + its tabledata. - Added SHIFT+INS to insert rows on table first row without having to adjust tablepointers afterwards. - Added SHIFT+W,S for octave transpose. - Added SHIFT+1,2,3 to swap orderlists between channels. - Added SHIFT+BACKSPACE to clear a whole pattern row. - Added optimized playroutines, that will be used if all instruments have the same gateoff timer & 1st wave parameters. - Added duplicate check for v1.xx pulse conversion. - Added BETACONV-utility for conversion from beta format. - Added reSID interpolation option /I. - Added hexadecimal pattern row display option /D. - Added SID memory location parameter /L. - reSID interpolation is on by default. - Changed appearance of pattern special notes (rest, keyoff/on) - Increased amount of instruments to 63 and changed song dataformat. - v1.xx import converts arpeggios to instruments as long as there is room. - Vibrato depth changed back to same as in v1.xx. - Pulse modulation speeds are doubled. - Upon startup, songdata erase, or importing v1.xx data, gatetimer will be set to 2 * multiplier as opposed to just 2. - Optimized size & speed of all playroutines (initialization, checking for new note fetch, pulsetable execution). - Wavetable delay or no-wavechange on first step of instrument is definitely unsupported now! Protection to allow this conflicted with 3XY command. v2.01 - Added under-IO gamemusic playroutine. v2.02 - Added RETURN when instrument tableparameter (wave/pulse/filter) is 0 to get you to the first free table location. SHIFT+RETURN will additionally also set the instrument tableparameter. - Added "set mastervolume"-jump to gamemusic routines. - Improved sound effect handling, when an effect is interrupted by another (less silence between sounds). v2.03 - Added execution of realtime commands & instrument vibrato during wavetable delay. - Added wavetable right side value $80 to keep frequency unchanged (as a consequence, the note C-0 will cause the same effect). - Added relocator optimizations: all unnecessary data is stripped when packing/relocating. - Playroutines size-optimized. - Explanation of how different gatetimer values can lead to playback going out of sync (section 3.3). - reSID interpolation is no longer on by default :) v2.04 - Added a questionable 25Hz mode (/S0) - Execution of commands on wavetable delay is completely reworked and more consistent now. - Note C-0 is usable again. v2.05 - Added instrument legato feature (Hardres/1stwave parameter $00). - ADSR writes moved farther away from wave writes in the standard playroutine noteinit, lessening possibility of ADSR bugs. - Song initialization and pulsetable execution speed/sizeoptimized. v2.06 - Packer/relocator tolerates up to 256 bytes long patterns now. - Optimized playroutine sizes. v2.07 - Fixed transpose reset with F2/F3 song start (should not happen). - Fixed varying tempo on channels with F2/F3 song start. - Added warning screen to packer/relocator if table execution overflows. - Added writing of PAL/NTSC and 6581/8580 flags according to PSID V2 NG specification. - -mwindows added to linker options for no displaying of DOS prompt window (in win32 version). v2.08 - Added finevibrato mode (/V command line option). - Optimized playroutine sizes & speed. v2.09 - Fixed max.pattern length in Clear Musicdata operation. - Added Minimal playroutine. - First wave value $80 also acts as a proper legato instrument now. - Optimized playroutine sizes & speed. - SID chip type & timing (PAL/NTSC) displayed on top row. v2.1 - Added SHIFT+N for negating pulse/filter modulation speeds. - Added no-funktempo & no-octave0 optimizations to playroutines (a total of 8 sub-types for each playroutine). - Maximum speed is 16X now. - Separate song/instrument/packed song directories are remembered during session. - Pathname is displayed in the fileselector. - Filters ** and *.* display all files in the fileselector. - Song entered on commandline will be loaded at startup. - Song filename currently being edited is shown in the titlebar. - Currently edited song filename will be used as default in the "SAVE SONG" and "SAVE MUSIC+PLAYROUTINE" dialogs. - Instrument name will also be used as instrument filename as default in the "SAVE INSTRUMENT" dialog. - UPX used for compression of win32 executables. - Included a short reference of waveform bits (manual only). - Configuration file has clearer structure. v2.11 - Added SHIFT+S for smart instrument paste (converts instrument numbers in all patterns, after cut/pasting an instrument). - Added SHIFT+L which allows to write pulse/filter modulation steps and then convert them to the proper format. v2.12 - Playroutine 1 has buffered SID-writes. - Octave 0 is not disabled in routines with sound FX (no matter what the relocator says...) v2.13 - Standard playroutine now both in unbuffered and buffered flavors. v2.15 - Added SHIFT+I for inverting current pattern selection / whole pattern. v2.16 - Fixed octave selection with / * for laptop keyboards. - Empty patterns referenced in the orderlist will be saved when saving a song. - Save dialog will reappear if writing the song/instrument/executable music failed. - Optimized handling of "packed rests" in the playroutines. - Added < > for instrument selection in instrument/table edit modes. v2.17 - Fixed initialization of instrument vibrato. - Playroutines size-optimized. v2.18 - Wavetable left side values changed. Delay is now $01-$0F and inaudible waveforms (register values $00-$0F) have been mapped to table values $E0-$EF. Old songs using values $08-$0F have to be manually converted! v2.2 - Added the speedtable for more precise control of vibrato, portamento and funktempo. - Added SHIFT+O to optimize the speedtable (remove unused entries). - Added SHIFT+R to convert between absolute/relative notes in the wavetable. - Added SHIFT+RETURN in pattern/instrument editor to convert old style portamento, vibrato and funktempo parameters to speedtable entries. - SHIFT+R will paste several effect rows if there is data in pattern copybuffer. - Editing during Follow Play is possible. - Song and instrument format modified for 4 tables. Old 3-table data will be loaded but not saved anymore. v2.21 - Fixed NTSC CIA timer value for SID files. - Shift+E will copy several effect rows if pattern has been marked. v2.22 - Shift+N will also negate relative wavetable notes. - When converting oldstyle parameters to speedtable entries with SHIFT+RETURN, the speedtable view will shift to the new entry if one was created. v2.23 - Fixed SHIFT+INS in wavetable (inserts $E9 $00 now as it should). - Added SHIFT+U to unlock table scrolling. - Added SHIFT+F5/F6 to change speed multiplier. v2.24 - Added SHIFT+F7 to edit the hardrestart ADSR parameter. - Added SHIFT+F8 to switch between 6581 and 8580 SID models. v2.25 - Added detail to table overflow error message in relocator. - Added stop of playback if a tablepointer gets pointed directly to a jump (would bug in packed/relocated tune). - Added relocator error message for the above case. - Added relocator error message for illegal song restart position. - Not possible to save erroneous packed/relocated songs anymore (now that there is adequate error location). - Added SHIFT+,. to move song startposition on all channels and restart last playmode. v2.26 - Fixed relocator complaining of FF parameter in speedtable. - To increase stability, in multispeed mode relocator does not use the "same gatetimer/1st wave" optimization. - Changed Shift+O to optimize the currently edited table, not just speedtable. - Added an option to optimize everything with the SHIFT+ESC clear function. This clears unused patterns, instruments and table-entries. v2.27 - Fixed optimize function with different pattern lengths. - Added marking & copy/pasting orderlist data like patterns & tables. v2.28 - Added sort of mouse control. - Sound reinitialization when changing multiplier or other parameters is now faster. v2.29Beta - Internal reorganization. - New assembler-based relocator that leaves out unused portions of player code. - Instead of choosing a player version, one can choose combinations of player features. - Relocator does not save selfcontained duplicate parts of tables. - Added keys 0-9 & A-Z in the fileselector to move to the corresponding part of the filelist (if found). - Added SHIFT+H to calculate left/right shifted "hifi" speedtable values, according to the frequency of a note. v2.3 - Fixed songdata optimize function. - Fixed relocator with no-hardrestart instrument in slot 1. - Fixed relocator handling of effect C (Set cutoff). v2.31 - Fixed effect copy/paste. - Added possibility to disable pulseskipping with /O command line option. Warning: causes huge rastertime increase. - Tempo 2 is allowed. See the tips section (3.6) for details. v2.32 - Maximum pattern length increased to 128. Do not complain of "pattern too complex" errors :) - Optimized playroutine init in case of only 1 subtune. v2.33 - Fixed a bug where relocator was checking pattern 208 (illegal). - Optimized playroutine in case there is no keyoff/keyon used. - Optimized playroutine in case there are no pattern effects used. - Optimized playroutine channel variables in case there is no transpose, repeat, wavedelay and pattern effects. - If not using the last instrument (63), you can control song startup default tempo by using its Attack/Decay parameter. v2.34 - Added relocator optimization for using 1 or 2 channels only. To enable, you must use only channels 1 or 1,2 and not be using sound effect support or zeropage ghostregs. - Turning off buffered writes in relocator options works now even if sound effects or zeropage ghostregs are selected (they will be turned off too). v2.35 - Auto-creation of speedtable entries will always generate a new entry (except for song loading), duplicate values will be optimized by the relocator. - Pressing SHIFT+RETURN over a speedtable-using pattern command while the parameter is zero, goes to the next empty speedtable entry and sets the command parameter to point to that entry. v2.4 - Added one bit of accuracy to pulse modulation speed. A new song- format (identifier GTS4) reflects this, old songs will be converted upon loading. - Added possibility to execute pattern commands from the wavetable. v2.41 - Fixed player code assembly errors when using some pattern commands only from the wavetable. - Fixed player code bug with command B when command A is not used. - Fixed SHIFT+O removing table entries pointed to from wavetable pattern commands. v2.42 - Fixed frequency table size determination. - Changed behaviour of keyoff in pattern editing changed to use releasenote() like the instrument editor. - Added SHIFT+RETURN when parameter is zero to get you into an empty table entry for 8, 9 and A pattern commands as well. - Added adjustment of table views when changing instrument number in unlocked table scrolling mode. - Added RETURN over nonzero instrument number (in patterns) to go editing that instrument. v2.43 - Added duplicate pattern detection/removal to song optimize. - Added pattern shrink/expand (SHIFT+O,P). - Added pattern join/split (SHIFT+J,K). v2.44 - Fixed editor playroutine to not execute tick n commands, when a command has already been executed through the wavetable. v2.45 - Added possibility to disable realtime pattern command optimization at tick 0 (/Rxx command line option or click the "RO" text on the statusbar) for tempo-independent portamento & vibrato. - To make room on the status bar for the realtime optimization status indicator, finevibrato & pulse optimization indicators have been shortened to "FV" and "PO". v2.46 - Added transpose of speedtable portamento speeds (SHIFT+Q,A,W,S) SHIFT+W,S (octave transpose, multiply/divide by 2) also work in pulse & filtertable. - When editing the wavetable, RETURN & SHIFT+RETURN work for wave- table executed commands as in patterns (go to table position pointed by command, create new speedtable entries) v2.47 - Added experimental random delay to write of reSID registers, in order to make potential ADSR-bugging on C64 audible. The amount of delay in cycles can be adjusted with /Z command line option. - SHIFT+L in pulsetable creates repeated "set tempo" commands if speed is greater than 127. v2.48 - Fixed playroutine to use configurable baseaddress again. v2.49 - Added /G command line option, guard 1stwave/gatetimer parameters. When this is on (default), only silent waveforms can be entered as firstwave (only thing that makes sense) and editing gatetimer of one instrument affects all of them, as otherwise bugs in playback result easily. Use /G0 to turn off. v2.5 - Fixed "optimize everything" removing the tempo setting in instrument 63. - Fixed default tempo of multispeed tunes in packer/relocator. v2.51 - Fixed packing of empty patterns when not using any effects. - Fixed differing gatetimer value in instruments causing playback going out of sync. - /G command line option no longer has to keep gatetimer values the same. - Added high bit of gatetimer value to control whether wavetable execution starts right on the note init frame. If used, will cause significant rastertime increase. v2.52 - SHIFT+ENTER in orderlist view takes the next available pattern if pressed on a repeat or transpose command. - Added SHIFT+SPACE in pattern editor to start playback on a specific pattern row. v2.53 - Fixed F3 to always play the currently visible patterns. - Added BACKSPACE in the orderlist editor to set playback end position. Only effective when starting playback from position, not beginning. v2.54 - Fixed SHIFT+F3. - Changed SHIFT+, . to update the pattern view. - Changed SHIFT+SPACE to remain in pattern playback mode, if it was active. v2.55 - Added BACKSPACE in the fileselector to go to the parent dir. v2.56 - Song filename cleared on songdata erase. - Added /F to set custom SID clock frequency. - Graphics output routines no longer compare text screen buffer to previous to find out if it should be updated. v2.57 - Added alternative hardrestart method & playroutine that is used when HR attack parameter is at maximum (FF00 or F800 for example) - this can in theory give better reliability. v2.58 - Cleanup, removal of a few questionable features: * Gatetimer high bit to start wavetable immediately * Guard 1stwave parameter v2.59 - Songformat version update (GTS5/GTI5) - Gateoff timer parameter bits control now hardrestart disable ($80) & gateoff disable ($40). - 1stFrame Wave can be any from $01-$8F, $00 to leave both waveform & gateflag unchanged, or $FE / $FF to control gateflag but leave waveform unchanged. v2.6 - Fixed pattern default length selection display when decrementing from a length of 100 or higher. - Fixed mouse selection of pattern when adjusting an adjacent channel. - Fixed help screen instructions. - Changed resolution to 800x600. - Changed all songname rows to be displayed at the same time. - Changed mouse control to allow pattern column selection even when left mouse button is held down. - Changed speed of PageUp/PageDown scrolling to be faster. - Optimized graphics output. - BME library is no longer needed. v2.61 - Added the backquote key (top-left on keyboard) to select channel in pattern edit mode, and to select table in table edit mode. Use with SHIFT to go backwards. - Added SHIFT+channel number to mute channels in pattern edit mode. v2.62 - Added possibility for realtime calculated note independent (hifi) portamento & vibrato. Warning: has potential for huge rastertime increase. v2.63 - Fixed note independent portamento & vibrato to use the last note set in wavetable for calculations, instead of the last note in patterndata. v2.64 - Fixed paste in table (SHIFT+V) working also without SHIFT pressed. v2.65 - Fixed raw keycodes over 511 interpreted as some other keys in the 0-511 range. v2.66Beta - Initial cycle-exact HardSID support (Win32 only) - Permit running without sound. v2.67 - Configurable cycle-exact HardSID buffer length (separate for inter- active and playback mode, see /T and /U command line options) v2.68 - Fixed set tempo -command overwriting frequencytable in 1 or 2 channel modes. - Fixed sound uninit crash with multicore processors (?) - SID register write order tweaked to resemble JCH NewPlayer 21. - Unbuffered playroutine optimized & modified to resemble buffered mode timing more. - New reSID-fp engine (with distortion & nonlinearity) from Antti Lankila integrated. Activated with /I command line option parameters 2 & 3. - Command quick reference by Simon Bennett included. v2.69 - Fixed click bug in reSID audio output. - Newest reSID-fp code integrated. - reSID-fp filter parameters adjustable from the configuration file. v2.70 - Hotfix for the new HardSID UPlay/Uno devices from Tli Sndor. - Fixed possible crash on some versions of the HardSID dll. v2.71 - Added keycode fix patch from Valerio Cannone. - Added fullscreen switch patch from Raine M. Ekman (see /X option) - Added context mode to online help patch from Raine M. Ekman. - Added /G command line option for setting A-4 pitch. v2.72 - Fixed incorrect transpose range determination in the relocator. - Fixed crash in jam mode whan an illegal pattern command was executed from the wavetable. goattracker-2.72/copying0000644000000000000000000004311010774364076014060 0ustar rootroot GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. goattracker-2.72/src/0000755000000000000000000000000011604145110013230 5ustar rootrootgoattracker-2.72/src/gpattern.c0000644000000000000000000010201311460110256015220 0ustar rootroot// // GOATTRACKER v2 pattern editor // #define GPATTERN_C #include "goattrk2.h" unsigned char notekeytbl1[] = {KEY_Z, KEY_S, KEY_X, KEY_D, KEY_C, KEY_V, KEY_G, KEY_B, KEY_H, KEY_N, KEY_J, KEY_M, KEY_COMMA, KEY_L, KEY_COLON}; unsigned char notekeytbl2[] = {KEY_Q, KEY_2, KEY_W, KEY_3, KEY_E, KEY_R, KEY_5, KEY_T, KEY_6, KEY_Y, KEY_7, KEY_U, KEY_I, KEY_9, KEY_O, KEY_0, KEY_P}; unsigned char dmckeytbl[] = {KEY_A, KEY_W, KEY_S, KEY_E, KEY_D, KEY_F, KEY_T, KEY_G, KEY_Y, KEY_H, KEY_U, KEY_J, KEY_K, KEY_O, KEY_L, KEY_P}; unsigned char patterncopybuffer[MAX_PATTROWS*4+4]; unsigned char cmdcopybuffer[MAX_PATTROWS*4+4]; int patterncopyrows = 0; int cmdcopyrows = 0; int epnum[MAX_CHN]; int eppos; int epview; int epcolumn; int epchn; int epoctave = 2; int epmarkchn = -1; int epmarkstart; int epmarkend; void patterncommands(void) { int c, scrrep; switch(key) { case '<': case '(': case '[': prevpattern(); break; case '>': case ')': case ']': nextpattern(); break; } { int newnote = -1; if (key) { switch (keypreset) { case KEY_TRACKER: for (c = 0; c < sizeof(notekeytbl1); c++) { if ((rawkey == notekeytbl1[c]) && (!epcolumn) && (!shiftpressed)) { newnote = FIRSTNOTE+c+epoctave*12; } } for (c = 0; c < sizeof(notekeytbl2); c++) { if ((rawkey == notekeytbl2[c]) && (!epcolumn) && (!shiftpressed)) { newnote = FIRSTNOTE+c+(epoctave+1)*12; } } break; case KEY_DMC: for (c = 0; c < sizeof(dmckeytbl); c++) { if ((rawkey == dmckeytbl[c]) && (!epcolumn) && (!shiftpressed)) { newnote = FIRSTNOTE+c+epoctave*12; } } break; } } if (newnote > LASTNOTE) newnote = -1; if ((rawkey == 0x08) && (!epcolumn)) newnote = REST; if ((rawkey == 0x14) && (!epcolumn)) newnote = KEYOFF; if (rawkey == KEY_ENTER) { switch(epcolumn) { case 0: if (shiftpressed) newnote = KEYON; else newnote = KEYOFF; break; case 1: case 2: if (pattern[epnum[epchn]][eppos*4+1]) { gotoinstr(pattern[epnum[epchn]][eppos*4+1]); return; } break; default: switch (pattern[epnum[epchn]][eppos*4+2]) { case CMD_SETWAVEPTR: if (pattern[epnum[epchn]][eppos*4+3]) { gototable(WTBL, pattern[epnum[epchn]][eppos*4+3] - 1); return; } else { if (shiftpressed) { int pos = gettablelen(WTBL); if (pos >= MAX_TABLELEN-1) pos = MAX_TABLELEN - 1; pattern[epnum[epchn]][eppos*4+3] = pos + 1; gototable(WTBL, pos); return; } } break; case CMD_SETPULSEPTR: if (pattern[epnum[epchn]][eppos*4+3]) { gototable(PTBL, pattern[epnum[epchn]][eppos*4+3] - 1); return; } else { if (shiftpressed) { int pos = gettablelen(PTBL); if (pos >= MAX_TABLELEN-1) pos = MAX_TABLELEN - 1; pattern[epnum[epchn]][eppos*4+3] = pos + 1; gototable(PTBL, pos); return; } } break; case CMD_SETFILTERPTR: if (pattern[epnum[epchn]][eppos*4+3]) { gototable(FTBL, pattern[epnum[epchn]][eppos*4+3] - 1); return; } else { if (shiftpressed) { int pos = gettablelen(FTBL); if (pos >= MAX_TABLELEN-1) pos = MAX_TABLELEN - 1; pattern[epnum[epchn]][eppos*4+3] = pos + 1; gototable(FTBL, pos); return; } } break; case CMD_FUNKTEMPO: if (pattern[epnum[epchn]][eppos*4+3]) { if (!shiftpressed) { gototable(STBL, pattern[epnum[epchn]][eppos*4+3] - 1); return; } else { int pos = makespeedtable(pattern[epnum[epchn]][eppos*4+3], MST_FUNKTEMPO, 1); pattern[epnum[epchn]][eppos*4+3] = pos + 1; } } else { if (shiftpressed) { int pos = findfreespeedtable(); if (pos >= 0) { pattern[epnum[epchn]][eppos*4+3] = pos + 1; gototable(STBL, pos); return; } } } break; case CMD_PORTAUP: case CMD_PORTADOWN: case CMD_TONEPORTA: if (pattern[epnum[epchn]][eppos*4+3]) { if (!shiftpressed) { gototable(STBL, pattern[epnum[epchn]][eppos*4+3] - 1); return; } else { int pos = makespeedtable(pattern[epnum[epchn]][eppos*4+3], MST_PORTAMENTO, 1); pattern[epnum[epchn]][eppos*4+3] = pos + 1; } } else { if (shiftpressed) { int pos = findfreespeedtable(); if (pos >= 0) { pattern[epnum[epchn]][eppos*4+3] = pos + 1; gototable(STBL, pos); return; } } } break; case CMD_VIBRATO: if (pattern[epnum[epchn]][eppos*4+3]) { if (!shiftpressed) { gototable(STBL, pattern[epnum[epchn]][eppos*4+3] - 1); return; } else { int pos = makespeedtable(pattern[epnum[epchn]][eppos*4+3], finevibrato, 1); pattern[epnum[epchn]][eppos*4+3] = pos + 1; } } else { if (shiftpressed) { int pos = findfreespeedtable(); if (pos >= 0) { pattern[epnum[epchn]][eppos*4+3] = pos + 1; gototable(STBL, pos); return; } } } break; } break; } if ((autoadvance < 2) && (epcolumn)) { eppos++; if (eppos > pattlen[epnum[epchn]]) { eppos = 0; } } } if (newnote >= 0) { if ((recordmode) && (eppos < pattlen[epnum[epchn]])) { pattern[epnum[epchn]][eppos*4] = newnote; if (newnote < REST) { pattern[epnum[epchn]][eppos*4+1] = einum; } else { pattern[epnum[epchn]][eppos*4+1] = 0; } if ((shiftpressed) && (newnote == REST)) { pattern[epnum[epchn]][eppos*4+2] = 0; pattern[epnum[epchn]][eppos*4+3] = 0; } } if (recordmode) { if (autoadvance < 2) { eppos++; if (eppos > pattlen[epnum[epchn]]) { eppos = 0; } } } playtestnote(newnote, einum, epchn); } } switch(rawkey) { case KEY_O: if (shiftpressed) shrinkpattern(); break; case KEY_P: if (shiftpressed) expandpattern(); break; case KEY_J: if (shiftpressed) joinpattern(); break; case KEY_K: if (shiftpressed) splitpattern(); break; case KEY_Z: if (shiftpressed) { autoadvance++; if (autoadvance > 2) autoadvance = 0; if (keypreset == KEY_TRACKER) { if (autoadvance == 1) autoadvance = 2; } } break; case KEY_E: if (shiftpressed) { if (epmarkchn != -1) { if (epmarkstart < epmarkend) { int d = 0; for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; cmdcopybuffer[d*4+2] = pattern[epnum[epmarkchn]][c*4+2]; cmdcopybuffer[d*4+3] = pattern[epnum[epmarkchn]][c*4+3]; d++; } cmdcopyrows = d; } else { int d = 0; for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; cmdcopybuffer[d*4+2] = pattern[epnum[epmarkchn]][c*4+2]; cmdcopybuffer[d*4+3] = pattern[epnum[epmarkchn]][c*4+3]; d++; } cmdcopyrows = d; } epmarkchn = -1; } else { if (eppos < pattlen[epnum[epchn]]) { cmdcopybuffer[2] = pattern[epnum[epchn]][eppos*4+2]; cmdcopybuffer[3] = pattern[epnum[epchn]][eppos*4+3]; cmdcopyrows = 1; } } } break; case KEY_R: if (shiftpressed) { for (c = 0; c < cmdcopyrows; c++) { if (eppos >= pattlen[epnum[epchn]]) break; pattern[epnum[epchn]][eppos*4+2] = cmdcopybuffer[c*4+2]; pattern[epnum[epchn]][eppos*4+3] = cmdcopybuffer[c*4+3]; eppos++; } } break; case KEY_I: if (shiftpressed) { int d, e; char temp; if (epmarkchn != -1) { if (epmarkstart <= epmarkend) { e = epmarkend; for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; for (d = 0; d < 4; d++) { temp = pattern[epnum[epmarkchn]][c*4+d]; pattern[epnum[epmarkchn]][c*4+d] = pattern[epnum[epmarkchn]][e*4+d]; pattern[epnum[epmarkchn]][e*4+d] = temp; } e--; if (e < c) break; } } else { e = epmarkstart; for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; for (d = 0; d < 4; d++) { temp = pattern[epnum[epmarkchn]][c*4+d]; pattern[epnum[epmarkchn]][c*4+d] = pattern[epnum[epmarkchn]][e*4+d]; pattern[epnum[epmarkchn]][e*4+d] = temp; } e--; if (e < c) break; } } } else { e = pattlen[epnum[epchn]] - 1; for (c = 0; c < pattlen[epnum[epchn]]; c++) { for (d = 0; d < 4; d++) { temp = pattern[epnum[epchn]][c*4+d]; pattern[epnum[epchn]][c*4+d] = pattern[epnum[epchn]][e*4+d]; pattern[epnum[epchn]][e*4+d] = temp; } e--; if (e < c) break; } } } break; case KEY_Q: if (shiftpressed) { if (epmarkchn != -1) { if (epmarkstart <= epmarkend) { for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] < LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] >= FIRSTNOTE)) pattern[epnum[epmarkchn]][c*4]++; } } else { for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] < LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] >= FIRSTNOTE)) pattern[epnum[epmarkchn]][c*4]++; } } } else { for (c = 0; c < pattlen[epnum[epchn]]; c++) { if ((pattern[epnum[epchn]][c*4] < LASTNOTE) && (pattern[epnum[epchn]][c*4] >= FIRSTNOTE)) pattern[epnum[epchn]][c*4]++; } } } break; case KEY_A: if (shiftpressed) { if (epmarkchn != -1) { if (epmarkstart <= epmarkend) { for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] <= LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] > FIRSTNOTE)) pattern[epnum[epmarkchn]][c*4]--; } } else { for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] <= LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] > FIRSTNOTE)) pattern[epnum[epmarkchn]][c*4]--; } } } else { for (c = 0; c < pattlen[epnum[epchn]]; c++) { if ((pattern[epnum[epchn]][c*4] <= LASTNOTE) && (pattern[epnum[epchn]][c*4] > FIRSTNOTE)) pattern[epnum[epchn]][c*4]--; } } } break; case KEY_W: if (shiftpressed) { if (epmarkchn != -1) { if (epmarkstart <= epmarkend) { for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] <= LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] >= FIRSTNOTE)) { pattern[epnum[epmarkchn]][c*4] += 12; if (pattern[epnum[epmarkchn]][c*4] > LASTNOTE) pattern[epnum[epmarkchn]][c*4] = LASTNOTE; } } } else { for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] <= LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] >= FIRSTNOTE)) { pattern[epnum[epmarkchn]][c*4] += 12; if (pattern[epnum[epmarkchn]][c*4] > LASTNOTE) pattern[epnum[epmarkchn]][c*4] = LASTNOTE; } } } } else { for (c = 0; c < pattlen[epnum[epchn]]; c++) { if ((pattern[epnum[epchn]][c*4] <= LASTNOTE) && (pattern[epnum[epchn]][c*4] >= FIRSTNOTE)) { pattern[epnum[epchn]][c*4] += 12; if (pattern[epnum[epchn]][c*4] > LASTNOTE) pattern[epnum[epchn]][c*4] = LASTNOTE; } } } } break; case KEY_S: if (shiftpressed) { if (epmarkchn != -1) { if (epmarkstart <= epmarkend) { for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] <= LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] >= FIRSTNOTE)) { pattern[epnum[epmarkchn]][c*4] -= 12; if (pattern[epnum[epmarkchn]][c*4] < FIRSTNOTE) pattern[epnum[epmarkchn]][c*4] = FIRSTNOTE; } } } else { for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; if ((pattern[epnum[epmarkchn]][c*4] <= LASTNOTE) && (pattern[epnum[epmarkchn]][c*4] >= FIRSTNOTE)) { pattern[epnum[epmarkchn]][c*4] -= 12; if (pattern[epnum[epmarkchn]][c*4] < FIRSTNOTE) pattern[epnum[epmarkchn]][c*4] = FIRSTNOTE; } } } } else { for (c = 0; c < pattlen[epnum[epchn]]; c++) { if ((pattern[epnum[epchn]][c*4] <= LASTNOTE) && (pattern[epnum[epchn]][c*4] >= FIRSTNOTE)) { pattern[epnum[epchn]][c*4] -= 12; if (pattern[epnum[epchn]][c*4] < FIRSTNOTE) pattern[epnum[epchn]][c*4] = FIRSTNOTE; } } } } break; case KEY_M: if (shiftpressed) { stepsize++; if (stepsize > MAX_PATTROWS) stepsize = MAX_PATTROWS; } break; case KEY_N: if (shiftpressed) { stepsize--; if (stepsize < 2) stepsize = 2; } break; case KEY_H: if (shiftpressed) { switch (pattern[epnum[epchn]][eppos*4+2]) { case CMD_PORTAUP: case CMD_PORTADOWN: case CMD_VIBRATO: case CMD_TONEPORTA: if (pattern[epnum[epchn]][eppos*4+2] == CMD_TONEPORTA) c = eppos-1; else c = eppos; for (; c >= 0; c--) { if ((pattern[epnum[epchn]][c*4] >= FIRSTNOTE) && (pattern[epnum[epchn]][c*4] <= LASTNOTE)) { int delta; int pitch1; int pitch2; int pos; int note = pattern[epnum[epchn]][c*4] - FIRSTNOTE; int right = pattern[epnum[epchn]][eppos*4+3] & 0xf; int left = pattern[epnum[epchn]][eppos*4+3] >> 4; if (note > MAX_NOTES-1) note--; pitch1 = freqtbllo[note] | (freqtblhi[note] << 8); pitch2 = freqtbllo[note+1] | (freqtblhi[note+1] << 8); delta = pitch2 - pitch1; while (left--) delta <<= 1; while (right--) delta >>= 1; if (pattern[epnum[epchn]][eppos*4+2] == CMD_VIBRATO) { if (delta > 0xff) delta = 0xff; } pos = makespeedtable(delta, MST_RAW, 1); pattern[epnum[epchn]][eppos*4+3] = pos + 1; break; } } break; } } break; case KEY_L: if (shiftpressed) { if (epmarkchn == -1) { epmarkchn = epchn; epmarkstart = 0; epmarkend = pattlen[epnum[epchn]]-1; } else epmarkchn = -1; } break; case KEY_C: case KEY_X: if (shiftpressed) { if (epmarkchn != -1) { if (epmarkstart <= epmarkend) { int d = 0; for (c = epmarkstart; c <= epmarkend; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; patterncopybuffer[d*4] = pattern[epnum[epmarkchn]][c*4]; patterncopybuffer[d*4+1] = pattern[epnum[epmarkchn]][c*4+1]; patterncopybuffer[d*4+2] = pattern[epnum[epmarkchn]][c*4+2]; patterncopybuffer[d*4+3] = pattern[epnum[epmarkchn]][c*4+3]; if (rawkey == KEY_X) { pattern[epnum[epmarkchn]][c*4] = REST; pattern[epnum[epmarkchn]][c*4+1] = 0; pattern[epnum[epmarkchn]][c*4+2] = 0; pattern[epnum[epmarkchn]][c*4+3] = 0; } d++; } patterncopyrows = d; } else { int d = 0; for (c = epmarkend; c <= epmarkstart; c++) { if (c >= pattlen[epnum[epmarkchn]]) break; patterncopybuffer[d*4] = pattern[epnum[epmarkchn]][c*4]; patterncopybuffer[d*4+1] = pattern[epnum[epmarkchn]][c*4+1]; patterncopybuffer[d*4+2] = pattern[epnum[epmarkchn]][c*4+2]; patterncopybuffer[d*4+3] = pattern[epnum[epmarkchn]][c*4+3]; if (rawkey == KEY_X) { pattern[epnum[epmarkchn]][c*4] = REST; pattern[epnum[epmarkchn]][c*4+1] = 0; pattern[epnum[epmarkchn]][c*4+2] = 0; pattern[epnum[epmarkchn]][c*4+3] = 0; } d++; } patterncopyrows = d; } epmarkchn = -1; } else { int d = 0; for (c = 0; c < pattlen[epnum[epchn]]; c++) { patterncopybuffer[d*4] = pattern[epnum[epchn]][c*4]; patterncopybuffer[d*4+1] = pattern[epnum[epchn]][c*4+1]; patterncopybuffer[d*4+2] = pattern[epnum[epchn]][c*4+2]; patterncopybuffer[d*4+3] = pattern[epnum[epchn]][c*4+3]; if (rawkey == KEY_X) { pattern[epnum[epchn]][c*4] = REST; pattern[epnum[epchn]][c*4+1] = 0; pattern[epnum[epchn]][c*4+2] = 0; pattern[epnum[epchn]][c*4+3] = 0; } d++; } patterncopyrows = d; } } break; case KEY_V: if ((shiftpressed) && (patterncopyrows)) { for (c = 0; c < patterncopyrows; c++) { if (eppos >= pattlen[epnum[epchn]]) break; pattern[epnum[epchn]][eppos*4] = patterncopybuffer[c*4]; pattern[epnum[epchn]][eppos*4+1] = patterncopybuffer[c*4+1]; pattern[epnum[epchn]][eppos*4+2] = patterncopybuffer[c*4+2]; pattern[epnum[epchn]][eppos*4+3] = patterncopybuffer[c*4+3]; eppos++; } } break; case KEY_DEL: if (epmarkchn == epchn) epmarkchn = -1; if ((pattlen[epnum[epchn]]-eppos)*4-4 >= 0) { memmove(&pattern[epnum[epchn]][eppos*4], &pattern[epnum[epchn]][eppos*4+4], (pattlen[epnum[epchn]]-eppos)*4-4); pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-4] = REST; pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-3] = 0x00; pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-2] = 0x00; pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-1] = 0x00; } else { if (eppos == pattlen[epnum[epchn]]) { if (pattlen[epnum[epchn]] > 1) { pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-4] = ENDPATT; pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-3] = 0x00; pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-2] = 0x00; pattern[epnum[epchn]][pattlen[epnum[epchn]]*4-1] = 0x00; countthispattern(); eppos = pattlen[epnum[epchn]]; } } } break; case KEY_INS: if (epmarkchn == epchn) epmarkchn = -1; if ((pattlen[epnum[epchn]]-eppos)*4-4 >= 0) { memmove(&pattern[epnum[epchn]][eppos*4+4], &pattern[epnum[epchn]][eppos*4], (pattlen[epnum[epchn]]-eppos)*4-4); pattern[epnum[epchn]][eppos*4] = REST; pattern[epnum[epchn]][eppos*4+1] = 0x00; pattern[epnum[epchn]][eppos*4+2] = 0x00; pattern[epnum[epchn]][eppos*4+3] = 0x00; } else { if (eppos == pattlen[epnum[epchn]]) { if (pattlen[epnum[epchn]] < MAX_PATTROWS) { pattern[epnum[epchn]][eppos*4] = REST; pattern[epnum[epchn]][eppos*4+1] = 0x00; pattern[epnum[epchn]][eppos*4+2] = 0x00; pattern[epnum[epchn]][eppos*4+3] = 0x00; pattern[epnum[epchn]][eppos*4+4] = ENDPATT; pattern[epnum[epchn]][eppos*4+5] = 0x00; pattern[epnum[epchn]][eppos*4+6] = 0x00; pattern[epnum[epchn]][eppos*4+7] = 0x00; countthispattern(); eppos = pattlen[epnum[epchn]]; } } } break; case KEY_SPACE: if (!shiftpressed) recordmode ^= 1; else { if (lastsonginit != PLAY_PATTERN) { if (eseditpos != espos[eschn]) { int c; for (c = 0; c < MAX_CHN; c++) { if (eseditpos < songlen[esnum][c]) espos[c] = eseditpos; if (esend[c] <= espos[c]) esend[c] = 0; } } initsongpos(esnum, PLAY_POS, eppos); } else initsongpos(esnum, PLAY_PATTERN, eppos); followplay = 0; } break; case KEY_RIGHT: if (!shiftpressed) { epcolumn++; if (epcolumn >= 6) { epcolumn = 0; epchn++; if (epchn >= MAX_CHN) epchn = 0; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } } else { if (epnum[epchn] < MAX_PATT-1) { epnum[epchn]++; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } if (epchn == epmarkchn) epmarkchn = -1; } break; case KEY_LEFT: if (!shiftpressed) { epcolumn--; if (epcolumn < 0) { epcolumn = 5; epchn--; if (epchn < 0) epchn = MAX_CHN-1; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } } else { if (epnum[epchn] > 0) { epnum[epchn]--; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } if (epchn == epmarkchn) epmarkchn = -1; } break; case KEY_HOME: while (eppos != 0) patternup(); break; case KEY_END: while (eppos != pattlen[epnum[epchn]]) patterndown(); break; case KEY_PGUP: for (scrrep = PGUPDNREPEAT; scrrep; scrrep--) patternup(); break; case KEY_PGDN: for (scrrep = PGUPDNREPEAT; scrrep; scrrep--) patterndown(); break; case KEY_UP: patternup(); break; case KEY_DOWN: patterndown(); break; case KEY_APOST2: if (!shiftpressed) { epchn++; if (epchn >= MAX_CHN) epchn = 0; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } else { epchn--; if (epchn < 0) epchn = MAX_CHN-1; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } break; case KEY_1: case KEY_2: case KEY_3: if (shiftpressed) mutechannel(rawkey - KEY_1); break; } if ((keypreset != KEY_TRACKER) && (hexnybble >= 0) && (hexnybble <= 7) && (!epcolumn)) { int oldbyte = pattern[epnum[epchn]][eppos*4]; epoctave = hexnybble; if ((oldbyte >= FIRSTNOTE) && (oldbyte <= LASTNOTE)) { int newbyte; int oldnote = (oldbyte - FIRSTNOTE) %12; if (recordmode) { newbyte = oldnote+epoctave*12 + FIRSTNOTE; if (newbyte <= LASTNOTE) { pattern[epnum[epchn]][eppos*4] = newbyte; } } if ((recordmode) && (autoadvance < 1)) { eppos++; if (eppos > pattlen[epnum[epchn]]) { eppos = 0; } } } } if ((hexnybble >= 0) && (epcolumn) && (recordmode)) { if (eppos < pattlen[epnum[epchn]]) { switch(epcolumn) { case 1: pattern[epnum[epchn]][eppos*4+1] &= 0x0f; pattern[epnum[epchn]][eppos*4+1] |= hexnybble << 4; pattern[epnum[epchn]][eppos*4+1] &= (MAX_INSTR - 1); break; case 2: pattern[epnum[epchn]][eppos*4+1] &= 0xf0; pattern[epnum[epchn]][eppos*4+1] |= hexnybble; pattern[epnum[epchn]][eppos*4+1] &= (MAX_INSTR - 1); break; case 3: pattern[epnum[epchn]][eppos*4+2] = hexnybble; if (!pattern[epnum[epchn]][eppos*4+2]) pattern[epnum[epchn]][eppos*4+3] = 0; break; case 4: pattern[epnum[epchn]][eppos*4+3] &= 0x0f; pattern[epnum[epchn]][eppos*4+3] |= hexnybble << 4; if (!pattern[epnum[epchn]][eppos*4+2]) pattern[epnum[epchn]][eppos*4+3] = 0; break; case 5: pattern[epnum[epchn]][eppos*4+3] &= 0xf0; pattern[epnum[epchn]][eppos*4+3] |= hexnybble; if (!pattern[epnum[epchn]][eppos*4+2]) pattern[epnum[epchn]][eppos*4+3] = 0; break; } } if (autoadvance < 2) { eppos++; if (eppos > pattlen[epnum[epchn]]) { eppos = 0; } } } epview = eppos-VISIBLEPATTROWS/2; } void patterndown(void) { if (shiftpressed) { if ((epmarkchn != epchn) || (eppos != epmarkend)) { epmarkchn = epchn; epmarkstart = epmarkend = eppos; } } eppos++; if (eppos > pattlen[epnum[epchn]]) { eppos = 0; } if (shiftpressed) epmarkend = eppos; } void patternup(void) { if (shiftpressed) { if ((epmarkchn != epchn) || (eppos != epmarkend)) { epmarkchn = epchn; epmarkstart = epmarkend = eppos; } } eppos--; if (eppos < 0) { eppos = pattlen[epnum[epchn]]; } if (shiftpressed) epmarkend = eppos; } void prevpattern(void) { if (epnum[epchn] > 0) { epnum[epchn]--; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } if (epchn == epmarkchn) epmarkchn = -1; } void nextpattern(void) { if (epnum[epchn] < MAX_PATT-1) { epnum[epchn]++; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; } if (epchn == epmarkchn) epmarkchn = -1; } void shrinkpattern(void) { int c = epnum[epchn]; int l = pattlen[c]; int nl = l/2; int d; if (pattlen[c] < 2) return; stopsong(); for (d = 0; d < nl; d++) { pattern[c][d*4] = pattern[c][d*2*4]; pattern[c][d*4+1] = pattern[c][d*2*4+1]; pattern[c][d*4+2] = pattern[c][d*2*4+2]; pattern[c][d*4+3] = pattern[c][d*2*4+3]; } pattern[c][nl*4] = ENDPATT; pattern[c][nl*4+1] = 0; pattern[c][nl*4+2] = 0; pattern[c][nl*4+3] = 0; eppos /= 2; countthispattern(); } void expandpattern(void) { int c = epnum[epchn]; int l = pattlen[c]; int nl = l*2; int d; unsigned char temp[MAX_PATTROWS*4+4]; if (nl > MAX_PATTROWS) return; memset(temp, 0, sizeof temp); stopsong(); for (d = 0; d <= nl; d++) { if (d & 1) { temp[d*4] = REST; temp[d*4+1] = 0; temp[d*4+2] = 0; temp[d*4+3] = 0; } else { temp[d*4] = pattern[c][d*2]; temp[d*4+1] = pattern[c][d*2+1]; temp[d*4+2] = pattern[c][d*2+2]; temp[d*4+3] = pattern[c][d*2+3]; } } memcpy(pattern[c], temp, (nl+1)*4); eppos *= 2; countthispattern(); } void splitpattern(void) { int c = epnum[epchn]; int l = pattlen[c]; int d; if (eppos == 0) return; if (eppos == l) return; stopsong(); if (insertpattern(c)) { int oldesnum = esnum; int oldeschn = eschn; int oldeseditpos = eseditpos; for (d = eppos; d <= l; d++) { pattern[c+1][(d-eppos)*4] = pattern[c][d*4]; pattern[c+1][(d-eppos)*4+1] = pattern[c][d*4+1]; pattern[c+1][(d-eppos)*4+2] = pattern[c][d*4+2]; pattern[c+1][(d-eppos)*4+3] = pattern[c][d*4+3]; } pattern[c][eppos*4] = ENDPATT; pattern[c][eppos*4+1] = 0; pattern[c][eppos*4+2] = 0; pattern[c][eppos*4+3] = 0; countpatternlengths(); for (esnum = 0; esnum < MAX_SONGS; esnum++) { for (eschn = 0; eschn < MAX_CHN; eschn++) { for (eseditpos = 0; eseditpos < songlen[esnum][eschn]; eseditpos++) { if (songorder[esnum][eschn][eseditpos] == c) { songorder[esnum][eschn][eseditpos] = c+1; insertorder(c); } } } } eschn = oldeschn; eseditpos = oldeseditpos; esnum = oldesnum; } } void joinpattern(void) { int c = epnum[epchn]; int d; if (eschn != epchn) return; if (songorder[esnum][epchn][eseditpos] != c) return; d = songorder[esnum][epchn][eseditpos + 1]; if (d >= MAX_PATT) return; if (pattlen[c] + pattlen[d] > MAX_PATTROWS) return; stopsong(); if (insertpattern(c)) { int oldesnum = esnum; int oldeschn = eschn; int oldeseditpos = eseditpos; int e, f; d++; for (e = 0; e < pattlen[c]; e++) { pattern[c+1][e*4] = pattern[c][e*4]; pattern[c+1][e*4+1] = pattern[c][e*4+1]; pattern[c+1][e*4+2] = pattern[c][e*4+2]; pattern[c+1][e*4+3] = pattern[c][e*4+3]; } for (f = 0; f < pattlen[d]; f++) { pattern[c+1][e*4] = pattern[d][f*4]; pattern[c+1][e*4+1] = pattern[d][f*4+1]; pattern[c+1][e*4+2] = pattern[d][f*4+2]; pattern[c+1][e*4+3] = pattern[d][f*4+3]; e++; } pattern[c+1][e*4] = ENDPATT; pattern[c+1][e*4+1] = 0; pattern[c+1][e*4+2] = 0; pattern[c+1][e*4+3] = 0; countpatternlengths(); for (esnum = 0; esnum < MAX_SONGS; esnum++) { for (eschn = 0; eschn < MAX_CHN; eschn++) { for (eseditpos = 0; eseditpos < songlen[esnum][eschn]; eseditpos++) { if ((songorder[esnum][eschn][eseditpos] == c) && (songorder[esnum][eschn][eseditpos+1] == d)) { deleteorder(); songorder[esnum][eschn][eseditpos] = c+1; } } } } eschn = oldeschn; eseditpos = oldeseditpos; esnum = oldesnum; findusedpatterns(); { int del1 = pattused[c]; int del2 = pattused[d]; if (!del1) { deletepattern(c); if (d > c) d--; } if (!del2) deletepattern(d); } } } goattracker-2.72/src/gorder.h0000644000000000000000000000111610774364076014707 0ustar rootroot#ifndef GORDER_H #define GORDER_H #ifndef GORDER_C extern int espos[MAX_CHN]; extern int esend[MAX_CHN]; extern int eseditpos; extern int esview; extern int escolumn; extern int eschn; extern int esnum; extern int esmarkchn; extern int esmarkstart; extern int esmarkend; extern int enpos; #endif void updateviewtopos(void); void orderlistcommands(void); void namecommands(void); void nextsong(void); void prevsong(void); void songchange(void); void orderleft(void); void orderright(void); void deleteorder(void); void insertorder(unsigned char byte); #endif goattracker-2.72/src/greloc.c0000644000000000000000000015400711604134052014661 0ustar rootroot// // GOATTRACKER v2 packer/relocator // #define GRELOC_C #include "goattrk2.h" #include "membuf.h" #include "parse.h" char *playeroptname[] = { "Buffered SID-writes", "Sound effect support", "Volume change support", "Store author-info", "Use zeropage ghostregs", "Disable optimization" }; char *tableleftname[] = { "mt_wavetbl", "mt_pulsetimetbl", "mt_filttimetbl", "mt_speedlefttbl"}; char *tablerightname[] = { "mt_notetbl", "mt_pulsespdtbl", "mt_filtspdtbl", "mt_speedrighttbl"}; unsigned char chnused[MAX_CHN]; unsigned char pattused[MAX_PATT]; unsigned char pattmap[MAX_PATT]; unsigned char instrused[MAX_INSTR]; unsigned char instrmap[MAX_INSTR]; unsigned char tableused[MAX_TABLES][MAX_TABLELEN+1]; unsigned char tablemap[MAX_TABLES][MAX_TABLELEN+1]; int pattoffset[MAX_PATT]; int pattsize[MAX_PATT]; int songoffset[MAX_SONGS][MAX_CHN]; int songsize[MAX_SONGS][MAX_CHN]; int tableerror; int channels; int fixedparams; int simplepulse; int firstnote; int lastnote; int patternlastnote; int nofilter; int nofiltermod; int nopulse; int nopulsemod; int nowavedelay; int norepeat; int notrans; int noportamento; int notoneporta; int novib; int noinsvib; int nosetad; int nosetsr; int nosetwave; int nosetwaveptr; int nosetpulseptr; int nosetfiltptr; int nosetfiltcutoff; int nosetfiltctrl; int nosetmastervol; int nofunktempo; int noglobaltempo; int nochanneltempo; int nogate; int noeffects; int nowavecmd; int nofirstwavecmd; int nocalculatedspeed; int nonormalspeed; int nozerospeed; struct membuf src = STATIC_MEMBUF_INIT; struct membuf dest = STATIC_MEMBUF_INIT; void relocator(void) { char packedsongname[MAX_FILENAME]; char packedfilter[MAX_FILENAME]; unsigned char *packeddata = NULL; char *playername = "player.s"; int tableerrortype = TYPE_NONE; int tableerrorcause = CAUSE_NONE; int tableerrorsource1 = 0; int tableerrorsource2 = 0; int patterns = 0; int songs = 0; int instruments = 0; int numlegato = 0; int numnohr = 0; int numnormal = 0; int freenormal; int freenohr; int freelegato; int transuprange = 0; int transdownrange = 0; int pattdatasize = 0; int patttblsize = 0; int songdatasize = 0; int songtblsize = 0; int instrsize = 0; int wavetblsize = 0; int pulsetblsize = 0; int filttblsize = 0; int speedtblsize = 0; int playersize = 0; int packedsize = 0; FILE *songhandle = NULL; int selectdone; int opt = 0; unsigned char speedcode[] = {0xa2,0x00,0x8e,0x04,0xdc,0xa2,0x00,0x8e,0x05,0xdc}; int c,d,e; unsigned char patttemp[512]; unsigned char *songwork = NULL; unsigned char *pattwork = NULL; unsigned char *instrwork = NULL; channels = 3; fixedparams = 1; simplepulse = 1; firstnote = MAX_NOTES-1; lastnote = 0; patternlastnote = 0; noeffects = 1; nogate = 1; nofilter = 1; nofiltermod = 1; nopulse = 1; nopulsemod = 1; nowavedelay = 1; nowavecmd = 1; norepeat = 1; notrans = 1; noportamento = 1; notoneporta = 1; novib = 1; noinsvib = 1; nosetad = 1; nosetsr = 1; nosetwave = 1; nosetwaveptr = 1; nosetpulseptr = 1; nosetfiltptr = 1; nosetfiltcutoff = 1; nosetfiltctrl = 1; nosetmastervol = 1; nofunktempo = 1; noglobaltempo = 1; nochanneltempo = 1; nofirstwavecmd = 1; nocalculatedspeed = 1; nonormalspeed = 1; nozerospeed = 1; stopsong(); memset(pattused, 0, sizeof pattused); memset(instrused, 0, sizeof instrused); memset(chnused, 0, sizeof chnused); memset(tableused, 0, sizeof tableused); memset(tablemap, 0, sizeof tablemap); tableerror = 0; membuf_free(&src); membuf_free(&dest); // Process song-orderlists countpatternlengths(); // Calculate amount of songs with nonzero length for (c = 0; c < MAX_SONGS; c++) { if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2])) { // See which patterns are used in this song for (d = 0; d < MAX_CHN; d++) { songdatasize += songlen[c][d]+2; for (e = 0; e < songlen[c][d]; e++) { if (songorder[c][d][e] < REPEAT) { int f; int num = songorder[c][d][e]; pattused[num] = 1; for (f = 0; f < pattlen[num]; f++) { if ((pattern[num][f*4] != REST) || (pattern[num][f*4+1]) || (pattern[num][f*4+2])) chnused[d] = 1; } } else { if (songorder[c][d][e] >= TRANSDOWN) { notrans = 0; if (songorder[c][d][e] < TRANSUP) { int newtransdownrange = -(songorder[c][d][e] - TRANSUP); if (newtransdownrange > transdownrange) transdownrange = newtransdownrange; } else { int newtransuprange = songorder[c][d][e] - TRANSUP; if (newtransuprange > transuprange) transuprange = newtransuprange; } } else norepeat = 0; } } if (songorder[c][d][songlen[c][d]+1] >= songlen[c][d]) { sprintf(textbuffer, "ILLEGAL SONG RESTART POSITION! (SUBTUNE %02X, CHANNEL %d)", c, d+1); clearscreen(); printtextc(MAX_ROWS/2, 15, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } } songs++; } } // Optimize amount of used channels if (!chnused[2]) channels = 2; if ((!chnused[1]) && (!chnused[2])) channels = 1; if (!songs) { clearscreen(); printtextc(MAX_ROWS/2, CTITLE, "NO SONGS, NO DATA TO SAVE!"); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } // Build the pattern-mapping // Instrument 1 is always used instrused[1] = 1; for (c = 0; c < MAX_PATT; c++) { if (pattused[c]) { pattmap[c] = patterns; patterns++; // See which instruments/tablecommands are used for (d = 0; d < pattlen[c]; d++) { tableerror = 0; if ((pattern[c][d*4] == KEYOFF) || (pattern[c][d*4] == KEYON)) nogate = 0; if (pattern[c][d*4+1]) instrused[pattern[c][d*4+1]] = 1; if (pattern[c][d*4+2]) noeffects = 0; if ((pattern[c][d*4+2] >= CMD_SETWAVEPTR) && (pattern[c][d*4+2] <= CMD_SETFILTERPTR)) exectable(pattern[c][d*4+2] - CMD_SETWAVEPTR, pattern[c][d*4+3]); if ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO)) { exectable(STBL, pattern[c][d*4+3]); calcspeedtest(pattern[c][d*4+3]); } if (pattern[c][d*4+2] == CMD_FUNKTEMPO) exectable(STBL, pattern[c][d*4+3]); if (pattern[c][d*4+2] == CMD_FUNKTEMPO) { nofunktempo = 0; noglobaltempo = 0; } if ((pattern[c][d*4+2] == CMD_SETTEMPO) && ((pattern[c][d*4+3] & 0x7f) < 3)) nofunktempo = 0; // See, which are the highest/lowest notes used if ((pattern[c][d*4] >= FIRSTNOTE) && (pattern[c][d*4] <= LASTNOTE)) { int newfirstnote = pattern[c][d*4] - FIRSTNOTE - transdownrange; int newlastnote = pattern[c][d*4] - FIRSTNOTE + transuprange; if (newfirstnote < 0) newfirstnote = 0; if (newlastnote > MAX_NOTES-1) newlastnote = MAX_NOTES-1; if (newfirstnote < firstnote) firstnote = newfirstnote; if (newlastnote > lastnote) { patternlastnote = newlastnote; lastnote = newlastnote; } if (newfirstnote > lastnote) { patternlastnote = newfirstnote; lastnote = newfirstnote; } } if ((tableerror) && (!tableerrortype)) { tableerrortype = tableerror; tableerrorcause = CAUSE_PATTERN; tableerrorsource1 = c; tableerrorsource2 = d; } } } } // Count amount of normal, nohr, and legato instruments // Also see if special first wave parameters are used for (c = 0; c < MAX_INSTR; c++) { if (instrused[c]) { if (instr[c].gatetimer & 0x40) numlegato++; else { if (instr[c].gatetimer & 0x80) numnohr++; else numnormal++; } if ((!instr[c].firstwave) || (instr[c].firstwave >= 0xfe)) nofirstwavecmd = 0; } } freenormal = 1; freenohr = freenormal + numnormal; freelegato = freenohr + numnohr; // Build the instrument-mapping for (c = 0; c < MAX_INSTR; c++) { if (instrused[c]) { if (instr[c].gatetimer & 0x40) instrmap[c] = freelegato++; else { if (instr[c].gatetimer & 0x80) instrmap[c] = freenohr++; else instrmap[c] = freenormal++; } instruments++; for (d = 0; d < MAX_TABLES; d++) { tableerror = 0; exectable(d, instr[c].ptr[d]); if (d == STBL) calcspeedtest(instr[c].ptr[d]); if ((tableerror) && (!tableerrortype)) { tableerrortype = tableerror; tableerrorcause = CAUSE_INSTRUMENT; tableerrorsource1 = c; tableerrorsource2 = d; } } } } // Execute tableprograms invoked from wavetable commands for (c = 0; c < MAX_TABLELEN; c++) { if (tableused[WTBL][c+1]) { if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) { d = -1; tableerror = 0; switch(ltable[WTBL][c] - WAVECMD) { case CMD_PORTAUP: case CMD_PORTADOWN: case CMD_TONEPORTA: case CMD_VIBRATO: d = STBL; calcspeedtest(rtable[WTBL][c]); break; case CMD_SETPULSEPTR: d = PTBL; nopulse = 0; break; case CMD_SETFILTERPTR: d = FTBL; nofilter = 0; break; case CMD_DONOTHING: case CMD_SETWAVEPTR: case CMD_FUNKTEMPO: sprintf(textbuffer, "ILLEGAL WAVETABLE COMMAND (ROW %02X, COMMAND %X)", c+1, ltable[WTBL][c] - WAVECMD); clearscreen(); printtextc(MAX_ROWS/2, 15, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } if (d != -1) exectable(d, rtable[WTBL][c]); if ((tableerror) && (!tableerrortype)) { tableerrortype = tableerror; tableerrorcause = CAUSE_WAVECMD; tableerrorsource1 = c+1; tableerrorsource2 = d; } } } } // Build the table-mapping for (c = 0; c < MAX_TABLES; c++) { int e = 1; for (d = 0; d < MAX_TABLELEN; d++) { if (tableused[c][d+1]) { tablemap[c][d+1] = e; e++; } } } // Check for table errors if (tableerrorcause) { clearscreen(); switch(tableerrortype) { case TYPE_JUMP: sprintf(textbuffer, "TABLE POINTER POINTS TO A JUMP! "); break; case TYPE_OVERFLOW: sprintf(textbuffer, "TABLE EXECUTION OVERFLOWS! "); break; } switch (tableerrorcause) { case CAUSE_PATTERN: sprintf(textbuffer + strlen(textbuffer), "(PATTERN %02X, ROW %02d)", tableerrorsource1, tableerrorsource2); break; case CAUSE_WAVECMD: sprintf(textbuffer + strlen(textbuffer), "WAVETABLE CMD (ROW %02X, ", tableerrorsource1); goto TABLETYPE; case CAUSE_INSTRUMENT: sprintf(textbuffer + strlen(textbuffer), "(INSTRUMENT %02X, ", tableerrorsource1); TABLETYPE: switch (tableerrorsource2) { case WTBL: strcat(textbuffer, "WAVE"); break; case PTBL: strcat(textbuffer, "PULSE"); break; case FTBL: strcat(textbuffer, "FILTER"); break; } strcat(textbuffer, ")"); break; } printtextc(MAX_ROWS/2, 15, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } // Find duplicate ranges in tables for (c = 0; c < MAX_TABLES; c++) findtableduplicates(c); // Select playroutine options clearscreen(); printblankc(0, 0, 15+16, MAX_COLUMNS); if (!strlen(loadedsongfilename)) sprintf(textbuffer, "%s Packer/Relocator", programname); else sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename); textbuffer[MAX_COLUMNS] = 0; printtext(0, 0, 15+16, textbuffer); printtext(1, 2, CTITLE, "SELECT PLAYROUTINE OPTIONS: (CURSORS=MOVE/CHANGE, ENTER=ACCEPT, ESC=CANCEL)"); selectdone = 0; while (!selectdone) { for (c = 0; c < MAX_OPTIONS; c++) { int color = CNORMAL; if (opt == c) color = CEDIT; printtext(1, 3+c, color, playeroptname[c]); if (playerversion & (PLAYER_BUFFERED << c)) printtext(24, 3+c, color, "Yes"); else printtext(24, 3+c, color, "No "); } fliptoscreen(); waitkeynoupdate(); if (win_quitted) { exitprogram = 1; goto PRCLEANUP; } switch(rawkey) { case KEY_LEFT: case KEY_RIGHT: case KEY_SPACE: playerversion ^= (PLAYER_BUFFERED << opt); if (opt) { if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS)) playerversion |= PLAYER_BUFFERED; } else { if (!(playerversion & PLAYER_BUFFERED)) { playerversion &= ~PLAYER_SOUNDEFFECTS; playerversion &= ~PLAYER_ZPGHOSTREGS; } } break; case KEY_UP: opt--; if (opt < 0) opt = MAX_OPTIONS-1; break; case KEY_DOWN: opt++; if (opt >= MAX_OPTIONS) opt = 0; break; case KEY_ESC: selectdone = -1; break; case KEY_ENTER: selectdone = 1; break; } } if (selectdone == -1) goto PRCLEANUP; // Disable optimizations if necessary if (playerversion & PLAYER_NOOPTIMIZATION) { fixedparams = 0; if (!numlegato) numlegato++; simplepulse = 0; firstnote = 0; lastnote = MAX_NOTES-1; nogate = 0; noeffects = 0; nofilter = 0; nofiltermod = 0; nopulse = 0; nopulsemod = 0; nowavedelay = 0; nowavecmd = 0; norepeat = 0; notrans = 0; noportamento = 0; notoneporta = 0; novib = 0; noinsvib = 0; nosetad = 0; nosetsr = 0; nosetwave = 0; nosetwaveptr = 0; nosetpulseptr = 0; nosetfiltptr = 0; nosetfiltcutoff = 0; nosetfiltctrl = 0; nosetmastervol = 0; nofunktempo = 0; noglobaltempo = 0; nochanneltempo = 0; nofirstwavecmd = 0; nocalculatedspeed = 0; nonormalspeed = 0; nozerospeed = 0; } // Make sure buffering is used if it is needed if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS)) playerversion |= PLAYER_BUFFERED; // Sound effect or ghostreg players always use full 3 channels if ((playerversion & PLAYER_SOUNDEFFECTS) || (playerversion & PLAYER_ZPGHOSTREGS)) channels = 3; // Allocate memory for song-orderlists songtblsize = songs*6; songwork = malloc(songdatasize); if (!songwork) { clearscreen(); printtextc(MAX_ROWS/2, CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!"); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } // Generate songorderlists & songtable songdatasize = 0; for (c = 0; c < songs; c++) { if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2])) { for (d = 0; d < MAX_CHN; d++) { songoffset[c][d] = songdatasize; songsize[c][d] = songlen[c][d] + 2; for (e = 0; e < songlen[c][d]; e++) { // Pattern if (songorder[c][d][e] < REPEAT) songwork[songdatasize++] = pattmap[songorder[c][d][e]]; else { // Transpose if (songorder[c][d][e] >= TRANSDOWN) { songwork[songdatasize++] = songorder[c][d][e]; } // Repeat sequence: must be swapped else { // See that repeat amount is more than 1 if (songorder[c][d][e] > REPEAT) { // Insanity check that a pattern indeed follows if (songorder[c][d][e+1] < REPEAT) { songwork[songdatasize++] = pattmap[songorder[c][d][e+1]]; songwork[songdatasize++] = songorder[c][d][e]; e++; } else songwork[songdatasize++] = songorder[c][d][e]; } } } } // Endmark & repeat position songwork[songdatasize++] = songorder[c][d][e++]; songwork[songdatasize++] = songorder[c][d][e++]; } } else { for (d = 0; d < MAX_CHN; d++) { songoffset[c][d] = songdatasize; songsize[c][d] = 0; } } } // Calculate total size of patterns for (c = 0; c < MAX_PATT; c++) { if (pattused[c]) { int result = packpattern(patttemp, pattern[c], pattlen[c]); if (result < 0) { clearscreen(); sprintf(textbuffer, "PATTERN %02X IS TOO COMPLEX (OVER 256 BYTES PACKED)!", c); printtextc(MAX_ROWS/2, 15, textbuffer); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } pattdatasize += result; } } patttblsize = patterns*2; pattwork = malloc(pattdatasize); if (!pattwork) { clearscreen(); printtextc(MAX_ROWS/2, CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!"); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } // This time pack the patterns for real pattdatasize = 0; d = 0; for (c = 0; c < MAX_PATT; c++) { if (pattused[c]) { pattoffset[d] = pattdatasize; pattsize[d] = packpattern(&pattwork[pattdatasize], pattern[c], pattlen[c]); pattdatasize += pattsize[d]; d++; } } // Then process instruments instrsize = instruments*9; instrwork = malloc(instrsize); if (!instrwork) { clearscreen(); printtextc(MAX_ROWS/2, CTITLE, "OUT OF MEMORY IN PACKER/RELOCATOR!"); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } for (c = 1; c < MAX_INSTR; c++) { if (instrused[c]) { d = instrmap[c] - 1; instrwork[d] = instr[c].ad; instrwork[d+instruments] = instr[c].sr; instrwork[d+instruments*2] = tablemap[WTBL][instr[c].ptr[WTBL]]; instrwork[d+instruments*3] = tablemap[PTBL][instr[c].ptr[PTBL]]; instrwork[d+instruments*4] = tablemap[FTBL][instr[c].ptr[FTBL]]; if (instr[c].vibdelay) { instrwork[d+instruments*5] = tablemap[STBL][instr[c].ptr[STBL]]; instrwork[d+instruments*6] = instr[c].vibdelay - 1; } else { instrwork[d+instruments*5] = 0; instrwork[d+instruments*6] = 0; } instrwork[d+instruments*7] = instr[c].gatetimer & 0x3f; instrwork[d+instruments*8] = instr[c].firstwave; if (instr[c].ptr[STBL]) { novib = 0; noinsvib = 0; } if (instr[c].ptr[PTBL]) nopulse = 0; if (instr[c].ptr[FTBL]) nofilter = 0; // See if all instruments use same gatetimer & firstwave parameters if ((instr[c].gatetimer != instr[1].gatetimer) || (instr[c].firstwave != instr[1].firstwave)) fixedparams = 0; // or if special firstwave commands are in use if ((!instr[c].firstwave) || (instr[c].firstwave >= 0xfe)) fixedparams = 0; } } // Disable sameparam optimization for multispeed stability if (multiplier > 1) { fixedparams = 0; numlegato++; numnohr++; } if (fixedparams) instrsize -= instruments*2; if (noinsvib) instrsize -= instruments*2; if (nopulse) instrsize -= instruments; if (nofilter) instrsize -= instruments; // Process tables for (c = 0; c < MAX_TABLELEN; c++) { if (tableused[WTBL][c+1]) { wavetblsize += 2; if ((ltable[WTBL][c] >= WAVEDELAY) && (ltable[WTBL][c] <= WAVELASTDELAY)) nowavedelay = 0; if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) { nowavecmd = 0; noeffects = 0; switch (ltable[WTBL][c] - WAVECMD) { case CMD_PORTAUP: case CMD_PORTADOWN: noportamento = 0; break; case CMD_TONEPORTA: notoneporta = 0; break; case CMD_VIBRATO: novib = 0; break; case CMD_SETAD: nosetad = 0; break; case CMD_SETSR: nosetsr = 0; break; case CMD_SETWAVE: nosetwave = 0; break; case CMD_SETPULSEPTR: nosetpulseptr = 0; break; case CMD_SETFILTERPTR: nosetfiltptr = 0; break; case CMD_SETFILTERCUTOFF: nosetfiltcutoff = 0; break; case CMD_SETFILTERCTRL: nosetfiltctrl = 0; break; case CMD_SETMASTERVOL: nosetmastervol = 0; break; } } if (ltable[WTBL][c] < WAVECMD) { if (rtable[WTBL][c] <= 0x80) { int newlastnote = rtable[WTBL][c] + patternlastnote; if (newlastnote > MAX_NOTES - 1) newlastnote = MAX_NOTES - 1; if (rtable[WTBL][c] >= 0x20) firstnote = 0; if (newlastnote > lastnote) lastnote = newlastnote; } else { int newfirstnote = rtable[WTBL][c] & 0x7f; int newlastnote = rtable[WTBL][c] & 0x7f; if (newlastnote > MAX_NOTES - 1) newlastnote = MAX_NOTES - 1; if (newfirstnote < firstnote) firstnote = newfirstnote; if (newlastnote > lastnote) lastnote = newlastnote; } } } } for (c = 0; c < MAX_TABLELEN; c++) { if (tableused[PTBL][c+1]) { pulsetblsize += 2; if ((ltable[PTBL][c] >= 0x80) && (ltable[PTBL][c] != 0xff)) { if (rtable[PTBL][c] & 0xf) simplepulse = 0; } if (ltable[PTBL][c] < 0x80) { nopulsemod = 0; if (rtable[PTBL][c] & 0xf) simplepulse = 0; } } } for (c = 0; c < MAX_TABLELEN; c++) { if (tableused[FTBL][c+1]) { filttblsize += 2; if (ltable[FTBL][c] < 0x80) nofiltermod = 0; } } for (c = 0; c < MAX_TABLELEN; c++) { if (tableused[STBL][c+1]) speedtblsize += 2; } // Zero entry of speedtable if ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta)) speedtblsize += 2; if (nopulse) pulsetblsize = 0; if (nofilter) filttblsize = 0; sprintf(textbuffer, "SELECT START ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); printtext(1, 10, 15, textbuffer); selectdone = 0; while (!selectdone) { sprintf(textbuffer, "$%04X", playeradr); printtext(1, 11, 10, textbuffer); fliptoscreen(); waitkeynoupdate(); if (win_quitted) { exitprogram = 1; goto PRCLEANUP; } switch(rawkey) { case KEY_LEFT: playeradr -= 0x0400; playeradr &= 0xff00; break; case KEY_UP: playeradr += 0x0100; playeradr &= 0xff00; break; case KEY_RIGHT: playeradr += 0x0400; playeradr &= 0xff00; break; case KEY_DOWN: playeradr -= 0x0100; playeradr &= 0xff00; break; case KEY_ESC: selectdone = -1; break; case KEY_ENTER: selectdone = 1; break; } } if (selectdone == -1) goto PRCLEANUP; sprintf(textbuffer, "SELECT ZEROPAGE ADDRESS: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); printtext(1, 13, 15, textbuffer); selectdone = 0; while (!selectdone) { if (playerversion & PLAYER_ZPGHOSTREGS) { if (zeropageadr < 0x02) zeropageadr = 0xe5; if (zeropageadr > 0xe5) zeropageadr = 0x02; } else { if (zeropageadr < 0x02) zeropageadr = 0xfe; if (zeropageadr > 0xfe) zeropageadr = 0x02; } if (!(playerversion & PLAYER_ZPGHOSTREGS)) { if (zeropageadr < 0x90) sprintf(textbuffer, "$%02X-$%02X (Used by BASIC interpreter) ", zeropageadr, zeropageadr+1); if ((zeropageadr >= 0x90) && (zeropageadr < 0xfb)) sprintf(textbuffer, "$%02X-$%02X (Used by KERNAL routines) ", zeropageadr, zeropageadr+1); if ((zeropageadr >= 0xfb) && (zeropageadr < 0xfe)) sprintf(textbuffer, "$%02X-$%02X (Unused) ", zeropageadr, zeropageadr+1); if (zeropageadr >= 0xfe) sprintf(textbuffer, "$%02X-$%02X ($FF used by BASIC interpreter)", zeropageadr, zeropageadr+1); } else { sprintf(textbuffer, "$%02X-$%02X (ghostregs start at %02X)", zeropageadr, zeropageadr+26, zeropageadr); } printtext(1, 14, 10, textbuffer); fliptoscreen(); waitkeynoupdate(); if (win_quitted) { exitprogram = 1; goto PRCLEANUP; } switch(rawkey) { case KEY_LEFT: zeropageadr -= 0x10; break; case KEY_UP: zeropageadr++; break; case KEY_RIGHT: zeropageadr += 0x10; break; case KEY_DOWN: zeropageadr--; break; case KEY_ESC: selectdone = -1; break; case KEY_ENTER: selectdone = 1; break; } } if (selectdone == -1) goto PRCLEANUP; // Validate frequencytable parameters if (lastnote < firstnote) lastnote = firstnote; if (firstnote < 0) firstnote = 0; if (!nocalculatedspeed) lastnote++; // Calculated speeds need the next frequency value if (lastnote > MAX_NOTES-1) lastnote = MAX_NOTES-1; // For sound effect support, always use the full table if (playerversion & PLAYER_SOUNDEFFECTS) { firstnote = 0; lastnote = MAX_NOTES-1; } // Insert baseaddresses insertdefine("base", playeradr); insertdefine("zpbase", zeropageadr); insertdefine("SIDBASE", sidaddress); // Insert conditionals insertdefine("SOUNDSUPPORT", (playerversion & PLAYER_SOUNDEFFECTS) ? 1 : 0); insertdefine("VOLSUPPORT", (playerversion & PLAYER_VOLUME) ? 1 : 0); insertdefine("BUFFEREDWRITES", (playerversion & PLAYER_BUFFERED) ? 1 : 0); insertdefine("ZPGHOSTREGS", (playerversion & PLAYER_ZPGHOSTREGS) ? 1 : 0); insertdefine("FIXEDPARAMS", fixedparams); insertdefine("SIMPLEPULSE", simplepulse); insertdefine("PULSEOPTIMIZATION", optimizepulse); insertdefine("REALTIMEOPTIMIZATION", optimizerealtime); insertdefine("NOAUTHORINFO", (playerversion & PLAYER_AUTHORINFO) ? 0 : 1); insertdefine("NOEFFECTS", noeffects); insertdefine("NOGATE", nogate); insertdefine("NOFILTER", nofilter); insertdefine("NOFILTERMOD", nofiltermod); insertdefine("NOPULSE", nopulse); insertdefine("NOPULSEMOD", nopulsemod); insertdefine("NOWAVEDELAY", nowavedelay); insertdefine("NOWAVECMD", nowavecmd); insertdefine("NOREPEAT", norepeat); insertdefine("NOTRANS", notrans); insertdefine("NOPORTAMENTO", noportamento); insertdefine("NOTONEPORTA", notoneporta); insertdefine("NOVIB", novib); insertdefine("NOINSTRVIB", noinsvib); insertdefine("NOSETAD", nosetad); insertdefine("NOSETSR", nosetsr); insertdefine("NOSETWAVE", nosetwave); insertdefine("NOSETWAVEPTR", nosetwaveptr); insertdefine("NOSETPULSEPTR", nosetpulseptr); insertdefine("NOSETFILTPTR", nosetfiltptr); insertdefine("NOSETFILTCTRL", nosetfiltctrl); insertdefine("NOSETFILTCUTOFF", nosetfiltcutoff); insertdefine("NOSETMASTERVOL", nosetmastervol); insertdefine("NOFUNKTEMPO", nofunktempo); insertdefine("NOGLOBALTEMPO", noglobaltempo); insertdefine("NOCHANNELTEMPO", nochanneltempo); insertdefine("NOFIRSTWAVECMD", nofirstwavecmd); insertdefine("NOCALCULATEDSPEED", nocalculatedspeed); insertdefine("NONORMALSPEED", nonormalspeed); insertdefine("NOZEROSPEED", nozerospeed); // Insert parameters insertdefine("NUMCHANNELS", channels); insertdefine("NUMSONGS", songs); insertdefine("FIRSTNOTE", firstnote); insertdefine("FIRSTNOHRINSTR", numnormal + 1); insertdefine("FIRSTLEGATOINSTR", numnormal + numnohr + 1); insertdefine("NUMHRINSTR", numnormal); insertdefine("NUMNOHRINSTR", numnohr); insertdefine("NUMLEGATOINSTR", numlegato); insertdefine("ADPARAM", adparam >> 8); insertdefine("SRPARAM", adparam & 0xff); if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL]))) insertdefine("DEFAULTTEMPO", instr[MAX_INSTR-1].ad - 1); else insertdefine("DEFAULTTEMPO", multiplier ? (multiplier*6-1) : 5); // Fixed firstwave & gatetimer if (fixedparams) { insertdefine("FIRSTWAVEPARAM", instr[1].firstwave); insertdefine("GATETIMERPARAM", instr[1].gatetimer & 0x3f); } // Insert source code of player if (adparam >= 0xf000) playername = "altplayer.s"; if (!insertfile(playername)) { clearscreen(); printtextc(MAX_ROWS/2, CTITLE, "COULD NOT OPEN PLAYROUTINE!"); fliptoscreen(); waitkeynoupdate(); goto PRCLEANUP; } // Insert frequencytable insertlabel("mt_freqtbllo"); insertbytes(&freqtbllo[firstnote], lastnote-firstnote+1); insertlabel("mt_freqtblhi"); insertbytes(&freqtblhi[firstnote], lastnote-firstnote+1); // Insert songtable insertlabel("mt_songtbllo"); for (c = 0; c < songs*3; c++) { sprintf(textbuffer, "mt_song%d", c); insertaddrlo(textbuffer); } insertlabel("mt_songtblhi"); for (c = 0; c < songs*3; c++) { sprintf(textbuffer, "mt_song%d", c); insertaddrhi(textbuffer); } // Insert patterntable insertlabel("mt_patttbllo"); for (c = 0; c < patterns; c++) { sprintf(textbuffer, "mt_patt%d", c); insertaddrlo(textbuffer); } insertlabel("mt_patttblhi"); for (c = 0; c < patterns; c++) { sprintf(textbuffer, "mt_patt%d", c); insertaddrhi(textbuffer); } // Insert instruments insertlabel("mt_insad"); insertbytes(&instrwork[0], instruments); insertlabel("mt_inssr"); insertbytes(&instrwork[instruments], instruments); insertlabel("mt_inswaveptr"); insertbytes(&instrwork[instruments*2], instruments); if (!nopulse) { insertlabel("mt_inspulseptr"); insertbytes(&instrwork[instruments*3], instruments); } if (!nofilter) { insertlabel("mt_insfiltptr"); insertbytes(&instrwork[instruments*4], instruments); } if (!noinsvib) { insertlabel("mt_insvibparam"); insertbytes(&instrwork[instruments*5], instruments); insertlabel("mt_insvibdelay"); insertbytes(&instrwork[instruments*6], instruments); } if (!fixedparams) { insertlabel("mt_insgatetimer"); insertbytes(&instrwork[instruments*7], instruments); insertlabel("mt_insfirstwave"); insertbytes(&instrwork[instruments*8], instruments); } // Insert tables for (c = 0; c < MAX_TABLES; c++) { if ((c == PTBL) && (nopulse)) goto SKIPTABLE; if ((c == FTBL) && (nofilter)) goto SKIPTABLE; // Write table left side // Extra zero for speedtable if ((c == STBL) && ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))) insertbyte(0); // Table label insertlabel(tableleftname[c]); // Table data for (d = 0; d < MAX_TABLELEN; d++) { if (tableused[c][d+1]) { switch (c) { // In wavetable, convert waveform values for the playroutine case WTBL: { unsigned char wave = ltable[c][d]; if ((ltable[c][d] >= WAVESILENT) && (ltable[c][d] <= WAVELASTSILENT)) wave &= 0xf; if ((ltable[c][d] > WAVELASTDELAY) && (ltable[c][d] <= WAVELASTSILENT) && (!nowavedelay)) wave += 0x10; insertbyte(wave); } break; case PTBL: if ((simplepulse) && (ltable[c][d] != 0xff) && (ltable[c][d] > 0x80)) insertbyte(0x80); else insertbyte(ltable[c][d]); break; // In filtertable, modify passband bits case FTBL: if ((ltable[c][d] != 0xff) && (ltable[c][d] > 0x80)) insertbyte(((ltable[c][d] & 0x70) >> 1) | 0x80); else insertbyte(ltable[c][d]); break; default: insertbyte(ltable[c][d]); break; } } } // Write table right side, remapping jumps as necessary // Extra zero for speedtable if ((c == STBL) && ((!novib) || (!nofunktempo) || (!noportamento) || (!notoneporta))) insertbyte(0); // Table label insertlabel(tablerightname[c]); for (d = 0; d < MAX_TABLELEN; d++) { if (tableused[c][d+1]) { if ((ltable[c][d] != 0xff) || (c == STBL)) { switch(c) { case WTBL: if ((ltable[c][d] >= WAVECMD) && (ltable[c][d] <= WAVELASTCMD)) { // Remap table-referencing commands switch (ltable[c][d] - WAVECMD) { case CMD_PORTAUP: case CMD_PORTADOWN: case CMD_TONEPORTA: case CMD_VIBRATO: insertbyte(tablemap[STBL][rtable[c][d]]); break; case CMD_SETPULSEPTR: insertbyte(tablemap[PTBL][rtable[c][d]]); break; case CMD_SETFILTERPTR: insertbyte(tablemap[FTBL][rtable[c][d]]); break; default: insertbyte(rtable[c][d]); break; } } else { // For normal notes, reverse all right side high bits insertbyte(rtable[c][d] ^ 0x80); } break; case PTBL: if (simplepulse) { if (ltable[c][d] >= 0x80) insertbyte((ltable[c][d] & 0x0f) | (rtable[c][d] & 0xf0)); else { int pulsespeed = rtable[c][d] >> 4; if (rtable[c][d] & 0x80) { pulsespeed |= 0xf0; pulsespeed--; } pulsespeed = swapnybbles(pulsespeed); insertbyte(pulsespeed); } } else insertbyte(rtable[c][d]); break; default: insertbyte(rtable[c][d]); break; } } else insertbyte(tablemap[c][rtable[c][d]]); } } SKIPTABLE: ; } // Insert orderlists for (c = 0; c < songs; c++) { for (d = 0; d < MAX_CHN; d++) { sprintf(textbuffer, "mt_song%d", c*3+d); insertlabel(textbuffer); insertbytes(&songwork[songoffset[c][d]], songsize[c][d]); } } // Insert patterns for (c = 0; c < patterns; c++) { sprintf(textbuffer, "mt_patt%d", c); insertlabel(textbuffer); insertbytes(&pattwork[pattoffset[c]], pattsize[c]); } /* { FILE *handle = fopen("debug.s", "wb"); fwrite(membuf_get(&src), membuf_memlen(&src), 1, handle); fclose(handle); } */ // Assemble; on error fail in a rude way (the parser does so too) if (assemble(&src, &dest)) exit(1); packeddata = membuf_get(&dest); packedsize = membuf_memlen(&dest); playersize = packedsize - songtblsize - songdatasize - patttblsize - pattdatasize - instrsize - wavetblsize - pulsetblsize - filttblsize - speedtblsize; // Copy author info if (playerversion & PLAYER_AUTHORINFO) { for (c = 0; c < 32; c++) { packeddata[32+c] = authorname[c]; // Convert 0 to space if (packeddata[32+c] == 0) packeddata[32+c] = 0x20; } } // Print results clearscreen(); printblankc(0, 0, 15+16, MAX_COLUMNS); if (!strlen(loadedsongfilename)) sprintf(textbuffer, "%s Packer/Relocator", programname); else sprintf(textbuffer, "%s Packer/Relocator - %s", programname, loadedsongfilename); textbuffer[80] = 0; printtext(0, 0, 15+16, textbuffer); sprintf(textbuffer, "PACKING RESULTS:"); printtext(1, 2, 15, textbuffer); sprintf(textbuffer, "Playroutine: %d bytes", playersize); printtext(1, 3, 7, textbuffer); sprintf(textbuffer, "Songtable: %d bytes", songtblsize); printtext(1, 4, 7, textbuffer); sprintf(textbuffer, "Song-orderlists: %d bytes", songdatasize); printtext(1, 5, 7, textbuffer); sprintf(textbuffer, "Patterntable: %d bytes", patttblsize); printtext(1, 6, 7, textbuffer); sprintf(textbuffer, "Patterns: %d bytes", pattdatasize); printtext(1, 7, 7, textbuffer); sprintf(textbuffer, "Instruments: %d bytes", instrsize); printtext(1, 8, 7, textbuffer); sprintf(textbuffer, "Tables: %d bytes", wavetblsize+pulsetblsize+filttblsize+speedtblsize); printtext(1, 9, 7, textbuffer); sprintf(textbuffer, "Total size: %d bytes", packedsize); printtext(1, 11, 7, textbuffer); fliptoscreen(); // Now ask for fileformat printtext(1, 13, CTITLE, "SELECT FORMAT TO SAVE IN: (CURSORS=MOVE, ENTER=ACCEPT, ESC=CANCEL)"); selectdone = 0; while (!selectdone) { switch(fileformat) { case FORMAT_SID: printtext(1, 14, CEDIT, "SID - SIDPlay music file format "); strcpy(packedfilter, "*.sid"); break; case FORMAT_PRG: printtext(1, 14, CEDIT, "PRG - C64 native format "); strcpy(packedfilter, "*.prg"); break; case FORMAT_BIN: printtext(1, 14, CEDIT, "BIN - Raw binary format (no startaddress)"); strcpy(packedfilter, "*.bin"); break; } fliptoscreen(); waitkeynoupdate(); if (win_quitted) { exitprogram = 1; goto PRCLEANUP; } switch(rawkey) { case KEY_LEFT: case KEY_DOWN: fileformat--; if (fileformat < FORMAT_SID) fileformat = FORMAT_BIN; break; case KEY_RIGHT: case KEY_UP: fileformat++; if (fileformat > FORMAT_BIN) fileformat = FORMAT_SID; break; case KEY_ESC: selectdone = -1; break; case KEY_ENTER: selectdone = 1; break; } } if (selectdone == -1) goto PRCLEANUP; // By default, copy loaded song name up to the extension memset(packedsongname, 0, sizeof packedsongname); for (c = 0; c < strlen(loadedsongfilename); c++) { if (loadedsongfilename[c] == '.') break; packedsongname[c] = loadedsongfilename[c]; } switch (fileformat) { case FORMAT_PRG: strcat(packedsongname, ".prg"); break; case FORMAT_BIN: strcat(packedsongname, ".bin"); break; case FORMAT_SID: strcat(packedsongname, ".sid"); break; } // Now ask for filename, retry if unsuccessful while (!songhandle) { if (!fileselector(packedsongname, packedpath, packedfilter, "Save Music+Playroutine", 3)) goto PRCLEANUP; if (strlen(packedsongname) < MAX_FILENAME-4) { int extfound = 0; for (c = strlen(packedsongname)-1; c >= 0; c--) { if (packedsongname[c] == '.') extfound = 1; } if (!extfound) { switch (fileformat) { case FORMAT_PRG: strcat(packedsongname, ".prg"); break; case FORMAT_BIN: strcat(packedsongname, ".bin"); break; case FORMAT_SID: strcat(packedsongname, ".sid"); break; } } } songhandle = fopen(packedsongname, "wb"); } if (fileformat == FORMAT_PRG) { fwritele16(songhandle, playeradr); } if (fileformat == FORMAT_SID) { unsigned char ident[] = {'P', 'S', 'I', 'D', 0x00, 0x02, 0x00, 0x7c}; unsigned char byte; // Identification fwrite(ident, sizeof ident, 1, songhandle); // Load address byte = 0x00; fwrite8(songhandle, byte); fwrite8(songhandle, byte); // Init address if ((multiplier > 1) || (!multiplier)) { unsigned speedvalue; byte = (playeradr-10) >> 8; fwrite8(songhandle, byte); byte = (playeradr-10) & 0xff; fwrite8(songhandle, byte); if (multiplier) { if (ntsc) speedvalue = 0x42c6/multiplier; else speedvalue = 0x4cc7/multiplier; } else { if (ntsc) speedvalue = 0x42c6*2; else speedvalue = 0x4cc7*2; } speedcode[1] = speedvalue & 0xff; speedcode[6] = speedvalue >> 8; } else { byte = (playeradr) >> 8; fwrite8(songhandle, byte); byte = (playeradr) & 0xff; fwrite8(songhandle, byte); } // Play address byte = (playeradr+3) >> 8; fwrite8(songhandle, byte); byte = (playeradr+3) & 0xff; fwrite8(songhandle, byte); // Number of subtunes byte = 0x00; fwrite8(songhandle, byte); byte = songs; fwrite8(songhandle, byte); // Default subtune byte = 0x00; fwrite8(songhandle, byte); byte = 0x01; fwrite8(songhandle, byte); // Song speed bits byte = 0x00; if ((ntsc) || (multiplier > 1) || (!multiplier)) byte = 0xff; fwrite8(songhandle, byte); fwrite8(songhandle, byte); fwrite8(songhandle, byte); fwrite8(songhandle, byte); // Songname etc. fwrite(songname, sizeof songname, 1, songhandle); fwrite(authorname, sizeof authorname, 1, songhandle); fwrite(copyrightname, sizeof copyrightname, 1, songhandle); // Flags byte = 0x00; fwrite8(songhandle, byte); if (ntsc) byte = 8; else byte = 4; if (sidmodel) byte |= 32; else byte |= 16; fwrite8(songhandle, byte); // Reserved longword byte = 0x00; fwrite8(songhandle, byte); fwrite8(songhandle, byte); fwrite8(songhandle, byte); fwrite8(songhandle, byte); // Load address if ((multiplier > 1) || (!multiplier)) { byte = (playeradr-10) & 0xff; fwrite8(songhandle, byte); byte = (playeradr-10) >> 8; fwrite8(songhandle, byte); } else { byte = (playeradr) & 0xff; fwrite8(songhandle, byte); byte = (playeradr) >> 8; fwrite8(songhandle, byte); } if ((multiplier > 1) || (!multiplier)) fwrite(speedcode, 10, 1, songhandle); } fwrite(packeddata, packedsize, 1, songhandle); fclose(songhandle); PRCLEANUP: membuf_free(&src); membuf_free(&dest); if (pattwork) free(pattwork); if (songwork) free(songwork); if (instrwork) free(instrwork); printmainscreen(); key = 0; rawkey = 0; } int packpattern(unsigned char *dest, unsigned char *src, int rows) { unsigned char temp1[MAX_PATTROWS*4]; unsigned char temp2[512]; unsigned char instr = 0; int command = -1; int databyte = -1; int destsizeim = 0; int destsize = 0; int c, d; // First optimize instrument changes for (c = 0; c < rows; c++) { if ((c) && (src[c*4+1]) && (src[c*4+1] == instr)) { temp1[c*4] = src[c*4]; temp1[c*4+1] = 0; temp1[c*4+2] = src[c*4+2]; temp1[c*4+3] = src[c*4+3]; } else { temp1[c*4] = src[c*4]; temp1[c*4+1] = src[c*4+1]; temp1[c*4+2] = src[c*4+2]; temp1[c*4+3] = src[c*4+3]; if (src[c*4+1]) instr = src[c*4+1]; } switch(temp1[c*4+2]) { // Remap speedtable commands case CMD_PORTAUP: case CMD_PORTADOWN: noportamento = 0; temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]]; break; case CMD_TONEPORTA: notoneporta = 0; temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]]; break; case CMD_VIBRATO: novib = 0; temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]]; break; case CMD_SETAD: nosetad = 0; break; case CMD_SETSR: nosetsr = 0; break; case CMD_SETWAVE: nosetwave = 0; break; // Remap table commands case CMD_SETWAVEPTR: nosetwaveptr = 0; temp1[c*4+3] = tablemap[WTBL][temp1[c*4+3]]; break; case CMD_SETPULSEPTR: nosetpulseptr = 0; nopulse = 0; temp1[c*4+3] = tablemap[PTBL][temp1[c*4+3]]; break; case CMD_SETFILTERPTR: nosetfiltptr = 0; nofilter = 0; temp1[c*4+3] = tablemap[FTBL][temp1[c*4+3]]; break; case CMD_SETFILTERCTRL: nosetfiltctrl = 0; nofilter = 0; break; case CMD_SETFILTERCUTOFF: nosetfiltcutoff = 0; nofilter = 0; break; case CMD_SETMASTERVOL: nosetmastervol = 0; // If no authorinfo being saved, erase timingmarks (not supported) if (!(playerversion & PLAYER_AUTHORINFO)) { if (temp1[c*4+3] > 0x0f) { temp1[c*4+2] = 0; temp1[c*4+3] = 0; } } break; case CMD_FUNKTEMPO: nofunktempo = 0; temp1[c*4+3] = tablemap[STBL][temp1[c*4+3]]; break; case CMD_SETTEMPO: if (temp1[c*4+3] >= 0x80) nochanneltempo = 0; else noglobaltempo = 0; // Decrease databyte of all tempo commands for the playroutine // Do not touch funktempo if ((temp1[c*4+3] & 0x7f) >= 3) temp1[c*4+3]--; break; } } if (noeffects) { command = 0; databyte = 0; } // Write in playroutine format for (c = 0; c < rows; c++) { // Instrument change with mapping if (temp1[c*4+1]) { temp2[destsizeim++] = instrmap[INSTRCHG+temp1[c*4+1]]; } // Rest+FX if (temp1[c*4] == REST) { if ((temp1[c*4+2] != command) || (temp1[c*4+3] != databyte)) { command = temp1[c*4+2]; databyte = temp1[c*4+3]; temp2[destsizeim++] = FXONLY+command; if (command) temp2[destsizeim++] = databyte; } else temp2[destsizeim++] = REST; } else { // Normal note if ((temp1[c*4+2] != command) || (temp1[c*4+3] != databyte)) { command = temp1[c*4+2]; databyte = temp1[c*4+3]; temp2[destsizeim++] = FX+command; if (command) temp2[destsizeim++] = databyte; } temp2[destsizeim++] = temp1[c*4]; } } // Final step: optimize long singlebyte rests with "packed rest" for (c = 0; c < destsizeim;) { int packok = 1; // Never pack first row or sequencer goes crazy if (!c) packok = 0; // There must be no instrument or command changes on the row to be packed if (temp2[c] < FX) { dest[destsize++] = temp2[c++]; packok = 0; } if ((temp2[c] >= FXONLY) && (temp2[c] < FIRSTNOTE)) { int fxnum = temp2[c] - FXONLY; dest[destsize++] = temp2[c++]; if (fxnum) dest[destsize++] = temp2[c++]; packok = 0; goto NEXTROW; } if (temp2[c] < FXONLY) { int fxnum = temp2[c] - FX; dest[destsize++] = temp2[c++]; if (fxnum) dest[destsize++] = temp2[c++]; packok = 0; } if (temp2[c] != REST) packok = 0; if (!packok) dest[destsize++] = temp2[c++]; else { for (d = c; d < destsizeim; ) { if (temp2[d] == REST) { d++; if (d-c == 64) break; } else break; } d -= c; if (d > 1) { dest[destsize++] = -d; c += d; } else dest[destsize++] = temp2[c++]; } NEXTROW: {} } // See if pattern too big if (destsize > 256) return -1; // If less than 256 bytes, insert endmark if (destsize < 256) dest[destsize++] = 0x00; return destsize; } int testoverlap(int area1start, int area1size, int area2start, int area2size) { int area1last = area1start+area1size-1; int area2last = area2start+area2size-1; if (area1start == area2start) return 1; if (area1start < area2start) { if (area1last < area2start) return 0; else return 1; } else { if (area2last < area1start) return 0; else return 1; } } unsigned char swapnybbles(unsigned char n) { unsigned char highnybble = n >> 4; unsigned char lownybble = n & 0xf; return (lownybble << 4) | highnybble; } int insertfile(char *name) { int size; int handle = io_open(name); if (handle == -1) return 0; size = io_lseek(handle, 0, SEEK_END); io_lseek(handle, 0, SEEK_SET); while (size--) { membuf_append_char(&src, io_read8(handle)); } io_close(handle); return 1; } void inserttext(const char *text) { membuf_append(&src, text, strlen(text)); } void insertdefine(const char *name, int value) { char insertbuffer[80]; sprintf(insertbuffer, "%-16s = %d\n", name, value); inserttext(insertbuffer); } void insertlabel(const char *name) { char insertbuffer[80]; sprintf(insertbuffer, "%s:\n", name); inserttext(insertbuffer); } void insertbytes(const unsigned char *bytes, int size) { char insertbuffer[80]; int row = 0; while (size--) { if (!row) { inserttext(" .BYTE ("); sprintf(insertbuffer, "$%02x", *bytes); inserttext(insertbuffer); bytes++; row++; } else { sprintf(insertbuffer, ",$%02x", *bytes); inserttext(insertbuffer); bytes++; row++; if (row == MAX_BYTES_PER_ROW) { inserttext(")\n"); row = 0; } } } if (row) inserttext(")\n"); } void insertbyte(unsigned char byte) { char insertbuffer[80]; sprintf(insertbuffer, " .BYTE ($%02x)\n", byte); inserttext(insertbuffer); } void insertaddrlo(const char *name) { char insertbuffer[80]; sprintf(insertbuffer, " .BYTE (%s %% 256)\n", name); inserttext(insertbuffer); } void insertaddrhi(const char *name) { char insertbuffer[80]; sprintf(insertbuffer, " .BYTE (%s / 256)\n", name); inserttext(insertbuffer); } void findtableduplicates(int num) { int c,d,e; if (num == STBL) { for (c = 1; c <= MAX_TABLELEN; c++) { if (tableused[num][c]) { for (d = c+1; d <= MAX_TABLELEN; d++) { if (tableused[num][d]) { if ((ltable[num][d-1] == ltable[num][c-1]) && (rtable[num][d-1] == rtable[num][c-1])) { // Duplicate found, remove and map to the original tableused[num][d] = 0; for (e = d; e <= MAX_TABLELEN; e++) if (tableused[num][e]) tablemap[num][e]--; tablemap[num][d] = tablemap[num][c]; } } } } } } else { for (c = 1; c <= MAX_TABLELEN; c++) { if (isusedandselfcontained(num, c)) { for (d = c + gettablepartlen(num, c - 1); d <= MAX_TABLELEN; ) { int len = gettablepartlen(num, d - 1); if (isusedandselfcontained(num, d)) { for (e = 0; e < len; e++) { if (e < len-1) { // Is table data the same? if ((ltable[num][d+e-1] != ltable[num][c+e-1]) || (rtable[num][d+e-1] != rtable[num][c+e-1])) break; } else { // Do both parts have a jump in the end? if (ltable[num][d+e-1] != ltable[num][c+e-1]) break; // Do both parts end? if (rtable[num][d+e-1] == 0) { if (rtable[num][c+e-1] != 0) break; } else { // Do both parts loop in the same way? if ((rtable[num][d+e-1] - d) != (rtable[num][c+e-1] - c)) break; } } } if (e == len) { // Duplicate found, remove and map to the original for (e = 0; e < len; e++) tableused[num][d+e] = 0; for (e = d; e < MAX_TABLELEN; e++) if (tableused[num][e]) tablemap[num][e] -= len; for (e = 0; e < len; e++) tablemap[num][d+e] = tablemap[num][c+e]; } } d += len; } } } } } int isusedandselfcontained(int num, int start) { int len = gettablepartlen(num, start - 1); int end = start + len - 1; int c; // Don't use jumps only if (len == 1) return 0; // Check that whole table is used for (c = start; c <= end; c++) { if (tableused[num][c] == 0) return 0; } // Check for jump to outside if (rtable[num][end-1] != 0) { if ((rtable[num][end-1] < start) || (rtable[num][end-1] > end)) return 0; } // Check for jump from outside for (c = 1; c < start; c++) if ((tableused[num][c]) && (ltable[num][c-1] == 0xff) && (rtable[num][c-1] >= start) && (rtable[num][c-1] <= end)) return 0; for (c = end+1; c <= MAX_TABLELEN; c++) if ((tableused[num][c]) && (ltable[num][c-1] == 0xff) && (rtable[num][c-1] >= start) && (rtable[num][c-1] <= end)) return 0; // OK! return 1; } void calcspeedtest(unsigned char pos) { if (!pos) { nozerospeed = 0; return; } if (ltable[STBL][pos-1] >= 0x80) nocalculatedspeed = 0; else nonormalspeed = 0; } goattracker-2.72/src/gtable.c0000644000000000000000000005546311460107730014655 0ustar rootroot// // GOATTRACKER v2 table editor // #define GTABLE_C #include "goattrk2.h" unsigned char ltablecopybuffer[MAX_TABLELEN]; unsigned char rtablecopybuffer[MAX_TABLELEN]; int tablecopyrows = 0; int etview[MAX_TABLES]; int etnum; int etpos; int etcolumn; int etlock = 1; int etmarknum = -1; int etmarkstart; int etmarkend; void tablecommands(void) { int c; switch(rawkey) { case KEY_Q: if ((shiftpressed) && (etnum == STBL)) { int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos]; speed *= 34716; speed /= 32768; if (speed > 65535) speed = 65535; ltable[etnum][etpos] = speed >> 8; rtable[etnum][etpos] = speed & 0xff; } break; case KEY_A: if ((shiftpressed) && (etnum == STBL)) { int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos]; speed *= 30929; speed /= 32768; ltable[etnum][etpos] = speed >> 8; rtable[etnum][etpos] = speed & 0xff; } break; case KEY_W: if ((shiftpressed) && (etnum == STBL)) { int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos]; speed *= 2; if (speed > 65535) speed = 65535; ltable[etnum][etpos] = speed >> 8; rtable[etnum][etpos] = speed & 0xff; } if ((shiftpressed) && ((etnum == PTBL) || (etnum == FTBL)) && (ltable[etnum][etpos] < 0x80)) { int speed = (signed char)(rtable[etnum][etpos]); speed *= 2; if (speed > 127) speed = 127; if (speed < -128) speed = -128; rtable[etnum][etpos] = speed; } break; case KEY_S: if ((shiftpressed) && (etnum == STBL)) { int speed = (ltable[etnum][etpos] << 8) | rtable[etnum][etpos]; speed /= 2; ltable[etnum][etpos] = speed >> 8; rtable[etnum][etpos] = speed & 0xff; } if ((shiftpressed) && ((etnum == PTBL) || (etnum == FTBL)) && (ltable[etnum][etpos] < 0x80)) { int speed = (signed char)(rtable[etnum][etpos]); speed /= 2; rtable[etnum][etpos] = speed; } break; case KEY_SPACE: if (!shiftpressed) playtestnote(FIRSTNOTE + epoctave * 12, einum, epchn); else releasenote(epchn); break; case KEY_RIGHT: etcolumn++; if (etcolumn > 3) { etpos -= etview[etnum]; etcolumn = 0; etnum++; if (etnum >= MAX_TABLES) etnum = 0; etpos += etview[etnum]; } if (shiftpressed) etmarknum = -1; break; case KEY_LEFT: etcolumn--; if (etcolumn < 0) { etpos -= etview[etnum]; etcolumn = 3; etnum--; if (etnum < 0) etnum = MAX_TABLES - 1; etpos += etview[etnum]; } if (shiftpressed) etmarknum = -1; break; case KEY_HOME: while (etpos != 0) tableup(); break; case KEY_END: while (etpos != MAX_TABLELEN-1) tabledown(); break; case KEY_PGUP: for (c = 0; c < PGUPDNREPEAT; c++) tableup(); break; case KEY_PGDN: for (c = 0; c < PGUPDNREPEAT; c++) tabledown(); break; case KEY_UP: tableup(); break; case KEY_DOWN: tabledown(); break; case KEY_X: case KEY_C: if (shiftpressed) { if (etmarknum != -1) { int d = 0; if (etmarkstart <= etmarkend) { for (c = etmarkstart; c <= etmarkend; c++) { ltablecopybuffer[d] = ltable[etmarknum][c]; rtablecopybuffer[d] = rtable[etmarknum][c]; if (rawkey == KEY_X) { ltable[etmarknum][c] = 0; rtable[etmarknum][c] = 0; } d++; } } else { for (c = etmarkend; c <= etmarkstart; c++) { ltablecopybuffer[d] = ltable[etmarknum][c]; rtablecopybuffer[d] = rtable[etmarknum][c]; if (rawkey == KEY_X) { ltable[etmarknum][c] = 0; rtable[etmarknum][c] = 0; } d++; } } tablecopyrows = d; } etmarknum = -1; } break; case KEY_V: if (shiftpressed) { if (tablecopyrows) { for (c = 0; c < tablecopyrows; c++) { ltable[etnum][etpos] = ltablecopybuffer[c]; rtable[etnum][etpos] = rtablecopybuffer[c]; etpos++; if (etpos >= MAX_TABLELEN) etpos = MAX_TABLELEN-1; } } } break; case KEY_O: if (shiftpressed) optimizetable(etnum); break; case KEY_U: if (shiftpressed) { etlock ^= 1; validatetableview(); } break; case KEY_R: if (etnum == WTBL) { if (ltable[etnum][etpos] != 0xff) { // Convert absolute pitch to relative pitch or vice versa int basenote = epoctave * 12; int note = rtable[etnum][etpos]; if (note >= 0x80) { note -= basenote; note &= 0x7f; } else { note += basenote; note |= 0x80; } rtable[etnum][etpos] = note; } } case KEY_L: if (etnum == PTBL) { int c; int currentpulse = -1; int targetpulse = ltable[etnum][etpos] << 4; int speed = rtable[etnum][etpos]; int time; int steps; if (!speed) break; // Follow the chain of pulse commands backwards to the nearest set command so we know what current pulse is for (c = etpos-1; c >= 0; c--) { if (ltable[etnum][c] == 0xff) break; if (ltable[etnum][c] >= 0x80) { currentpulse = (ltable[etnum][c] << 8) | rtable[etnum][c]; currentpulse &= 0xfff; break; } } if (currentpulse == -1) break; // Then follow the chain of modulation steps for (; c < etpos; c++) { if (ltable[etnum][c] < 0x80) { currentpulse += ltable[etnum][c] * (rtable[etnum][c] & 0xff); if (rtable[etnum][c] >= 0x80) currentpulse -= 256 * ltable[etnum][c]; currentpulse &= 0xfff; } } time = abs(targetpulse - currentpulse) / speed; if (speed < 128) steps = (time + 126) / 127; else steps = time; if (!steps) break; if (etpos + steps > MAX_TABLELEN) break; if (targetpulse < currentpulse) speed = -speed; // Make room in the table for (c = steps; c > 1; c--) inserttable(etnum, etpos, 1); while (time) { if (abs(speed) < 128) { if (time < 127) ltable[etnum][etpos] = time; else ltable[etnum][etpos] = 127; rtable[etnum][etpos] = speed; time -= ltable[etnum][etpos]; etpos++; } else { currentpulse += speed; ltable[etnum][etpos] = 0x80 | ((currentpulse >> 8) & 0xf); rtable[etnum][etpos] = currentpulse & 0xff; time--; etpos++; } } } if (etnum == FTBL) { int c; int currentfilter = -1; int targetfilter = ltable[etnum][etpos]; int speed = rtable[etnum][etpos] & 0x7f; int time; int steps; if (!speed) break; // Follow the chain of filter commands backwards to the nearest set command so we know what current pulse is for (c = etpos-1; c >= 0; c--) { if (ltable[etnum][c] == 0xff) break; if (ltable[etnum][c] == 0x00) { currentfilter = rtable[etnum][c]; break; } } if (currentfilter == -1) break; // Then follow the chain of modulation steps for (; c < etpos; c++) { if (ltable[etnum][c] < 0x80) { currentfilter += ltable[etnum][c] * rtable[etnum][c]; currentfilter &= 0xff; } } time = abs(targetfilter - currentfilter) / speed; steps = (time + 126) / 127; if (!steps) break; if (etpos + steps > MAX_TABLELEN) break; if (targetfilter < currentfilter) speed = -speed; // Make room in the table for (c = steps; c > 1; c--) inserttable(etnum, etpos, 1); while (time) { if (time < 127) ltable[etnum][etpos] = time; else ltable[etnum][etpos] = 127; rtable[etnum][etpos] = speed; time -= ltable[etnum][etpos]; etpos++; } } break; case KEY_N: if (shiftpressed) { switch (etnum) { // Negate pulse or filter speed case FTBL: if (!ltable[etnum][etpos]) break; case PTBL: if (ltable[etnum][etpos] < 0x80) rtable[etnum][etpos] = (rtable[etnum][etpos] ^ 0xff) + 1; break; // Negate relative note case WTBL: if ((ltable[etnum][etpos] != 0xff) && (rtable[etnum][etpos] < 0x80)) rtable[etnum][etpos] = (0x80 - rtable[etnum][etpos]) & 0x7f; break; } } break; case KEY_DEL: deletetable(etnum, etpos); break; case KEY_INS: inserttable(etnum, etpos, shiftpressed); break; case KEY_ENTER: if (etnum == WTBL) { int table = -1; int mstmode = MST_PORTAMENTO; switch (ltable[etnum][etpos]) { case WAVECMD + CMD_PORTAUP: case WAVECMD + CMD_PORTADOWN: case WAVECMD + CMD_TONEPORTA: table = STBL; break; case WAVECMD + CMD_VIBRATO: table = STBL; mstmode = finevibrato; break; case WAVECMD + CMD_FUNKTEMPO: table = STBL; mstmode = MST_FUNKTEMPO; break; case WAVECMD + CMD_SETPULSEPTR: table = PTBL; break; case WAVECMD + CMD_SETFILTERPTR: table = FTBL; break; } switch (table) { default: editmode = EDIT_INSTRUMENT; eipos = etnum + 2; return; case STBL: if (rtable[etnum][etpos]) { if (!shiftpressed) { gototable(STBL, rtable[etnum][etpos] - 1); return; } else { int oldeditpos = etpos; int oldeditcolumn = etcolumn; int pos = makespeedtable(rtable[etnum][etpos], mstmode, 1); gototable(WTBL, oldeditpos); etcolumn = oldeditcolumn; rtable[etnum][etpos] = pos + 1; return; } } else { int pos = findfreespeedtable(); if (pos >= 0) { rtable[etnum][etpos] = pos + 1; gototable(STBL, pos); return; } } break; case PTBL: case FTBL: if (rtable[etnum][etpos]) { gototable(table, rtable[etnum][etpos] - 1); return; } else { if (shiftpressed) { int pos = gettablelen(table); if (pos >= MAX_TABLELEN-1) pos = MAX_TABLELEN - 1; rtable[etnum][etpos] = pos + 1; gototable(table, pos); return; } } } } else { editmode = EDIT_INSTRUMENT; eipos = etnum + 2; return; } break; case KEY_APOST2: if (shiftpressed) { etpos -= etview[etnum]; etnum--; if (etnum < 0) etnum = MAX_TABLES-1; etpos += etview[etnum]; } else { etpos -= etview[etnum]; etnum++; if (etnum >= MAX_TABLES) etnum = 0; etpos += etview[etnum]; } } if (hexnybble >= 0) { switch(etcolumn) { case 0: ltable[etnum][etpos] &= 0x0f; ltable[etnum][etpos] |= hexnybble << 4; break; case 1: ltable[etnum][etpos] &= 0xf0; ltable[etnum][etpos] |= hexnybble; break; case 2: rtable[etnum][etpos] &= 0x0f; rtable[etnum][etpos] |= hexnybble << 4; break; case 3: rtable[etnum][etpos] &= 0xf0; rtable[etnum][etpos] |= hexnybble; break; } etcolumn++; if (etcolumn > 3) { etcolumn = 0; etpos++; if (etpos >= MAX_TABLELEN) etpos = MAX_TABLELEN-1; } } validatetableview(); } void deletetable(int num, int pos) { int c, d; // Shift tablepointers in instruments for (c = 1; c < MAX_INSTR; c++) { if ((instr[c].ptr[num]-1) > pos) instr[c].ptr[num]--; } // Shift tablepointers in wavetable commands for (c = 0; c < MAX_TABLELEN; c++) { if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) { int cmd = ltable[WTBL][c] & 0xf; if (num < STBL) { if (cmd == CMD_SETWAVEPTR+num) { if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]--; } } else { if ((cmd == CMD_FUNKTEMPO) || ((cmd >= CMD_PORTAUP) && (cmd <= CMD_VIBRATO))) { if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]--; } } } } // Shift tablepointers in patterns for (c = 0; c < MAX_PATT; c++) { for (d = 0; d <= MAX_PATTROWS; d++) { if (num < STBL) { if (pattern[c][d*4+2] == CMD_SETWAVEPTR+num) { if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]--; } } else { if ((pattern[c][d*4+2] == CMD_FUNKTEMPO) || ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO))) { if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]--; } } } } // Shift jumppointers in the table itself for (c = 0; c < MAX_TABLELEN; c++) { if (num != STBL) { if (ltable[num][c] == 0xff) if ((rtable[num][c]-1) > pos) rtable[num][c]--; } } for (c = pos; c < MAX_TABLELEN; c++) { if (c+1 < MAX_TABLELEN) { ltable[num][c] = ltable[num][c+1]; rtable[num][c] = rtable[num][c+1]; } else { ltable[num][c] = 0; rtable[num][c] = 0; } } } void inserttable(int num, int pos, int mode) { int c, d; // Shift tablepointers in instruments for (c = 1; c < MAX_INSTR; c++) { if (!mode) { if ((instr[c].ptr[num]-1) >= pos) instr[c].ptr[num]++; } else { if ((instr[c].ptr[num]-1) > pos) instr[c].ptr[num]++; } } // Shift tablepointers in wavetable commands for (c = 0; c < MAX_TABLELEN; c++) { if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) { int cmd = ltable[WTBL][c] & 0xf; if (num < STBL) { if (cmd == CMD_SETWAVEPTR+num) { if (!mode) { if ((rtable[WTBL][c]-1) >= pos) rtable[WTBL][c]++; } else { if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]++; } } } else { if ((cmd == CMD_FUNKTEMPO) || ((cmd >= CMD_PORTAUP) && (cmd <= CMD_VIBRATO))) { if (!mode) { if ((rtable[WTBL][c]-1) >= pos) rtable[WTBL][c]++; } else { if ((rtable[WTBL][c]-1) > pos) rtable[WTBL][c]++; } } } } } // Shift tablepointers in patterns for (c = 0; c < MAX_PATT; c++) { for (d = 0; d <= MAX_PATTROWS; d++) { if (num < STBL) { if (pattern[c][d*4+2] == CMD_SETWAVEPTR+num) { if (!mode) { if ((pattern[c][d*4+3]-1) >= pos) pattern[c][d*4+3]++; } else { if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]++; } } } else { if ((pattern[c][d*4+2] == CMD_FUNKTEMPO) || ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO))) { if (!mode) { if ((pattern[c][d*4+3]-1) >= pos) pattern[c][d*4+3]++; } else { if ((pattern[c][d*4+3]-1) > pos) pattern[c][d*4+3]++; } } } } } // Shift jumppointers in the table itself if (num != STBL) { for (c = 0; c < MAX_TABLELEN; c++) { if (ltable[num][c] == 0xff) { if (!mode) { if ((rtable[num][c]-1) >= pos) rtable[num][c]++; } else { if ((rtable[num][c]-1) > pos) rtable[num][c]++; } } } } for (c = MAX_TABLELEN-1; c >= pos; c--) { if (c > pos) { ltable[num][c] = ltable[num][c-1]; rtable[num][c] = rtable[num][c-1]; } else { if ((num == WTBL) && (mode == 1)) { ltable[num][c] = 0xe9; rtable[num][c] = 0; } else { ltable[num][c] = 0; rtable[num][c] = 0; } } } } int gettablelen(int num) { int c; for (c = MAX_TABLELEN-1; c >= 0; c--) { if (ltable[num][c] | rtable[num][c]) break; } return c+1; } int gettablepartlen(int num, int pos) { int c; if (pos < 0) return 0; if (num == STBL) return 1; for (c = pos; c < MAX_TABLELEN; c++) { if (ltable[num][c] == 0xff) { c++; break; } } return c-pos; } void optimizetable(int num) { int c,d; memset(tableused, 0, sizeof tableused); for (c = 0; c < MAX_PATT; c++) { for (d = 0; d < pattlen[c]; d++) { if ((pattern[c][d*4+2] >= CMD_SETWAVEPTR) && (pattern[c][d*4+2] <= CMD_SETFILTERPTR)) exectable(pattern[c][d*4+2] - CMD_SETWAVEPTR, pattern[c][d*4+3]); if ((pattern[c][d*4+2] >= CMD_PORTAUP) && (pattern[c][d*4+2] <= CMD_VIBRATO)) exectable(STBL, pattern[c][d*4+3]); if (pattern[c][d*4+2] == CMD_FUNKTEMPO) exectable(STBL, pattern[c][d*4+3]); } } for (c = 0; c < MAX_INSTR; c++) { for (d = 0; d < MAX_TABLES; d++) { exectable(d, instr[c].ptr[d]); } } for (c = 0; c < MAX_TABLELEN; c++) { if (tableused[WTBL][c+1]) { if ((ltable[WTBL][c] >= WAVECMD) && (ltable[WTBL][c] <= WAVELASTCMD)) { d = -1; switch(ltable[WTBL][c] - WAVECMD) { case CMD_PORTAUP: case CMD_PORTADOWN: case CMD_TONEPORTA: case CMD_VIBRATO: d = STBL; break; case CMD_SETPULSEPTR: d = PTBL; break; case CMD_SETFILTERPTR: d = FTBL; break; } if (d != -1) exectable(d, rtable[WTBL][c]); } } } for (c = MAX_TABLELEN-1; c >= 0; c--) { if ((ltable[num][c]) || (rtable[num][c])) break; } for (; c >= 0; c--) { if (!tableused[num][c+1]) deletetable(num, c); } } int makespeedtable(unsigned data, int mode, int makenew) { int c; unsigned char l = 0, r = 0; if (!data) return -1; switch (mode) { case MST_NOFINEVIB: l = (data & 0xf0) >> 4; r = (data & 0x0f) << 4; break; case MST_FINEVIB: l = (data & 0x70) >> 4; r = ((data & 0x0f) << 4) | ((data & 0x80) >> 4); break; case MST_FUNKTEMPO: l = (data & 0xf0) >> 4; r = data & 0x0f; break; case MST_PORTAMENTO: l = (data << 2) >> 8; r = (data << 2) & 0xff; break; case MST_RAW: r = data & 0xff; l = data >> 8; break; } if (makenew == 0) { for (c = 0; c < MAX_TABLELEN; c++) { if ((ltable[STBL][c] == l) && (rtable[STBL][c] == r)) return c; } } for (c = 0; c < MAX_TABLELEN; c++) { if ((!ltable[STBL][c]) && (!rtable[STBL][c])) { ltable[STBL][c] = l; rtable[STBL][c] = r; settableview(STBL, c); return c; } } return -1; } void deleteinstrtable(int i) { int c,d; int eraseok = 1; for (c = 0; c < MAX_TABLES; c++) { if (instr[i].ptr[c]) { int pos = instr[i].ptr[c]-1; int len = gettablepartlen(c, pos); // Check that this table area isn't used by another instrument for (d = 1; d < MAX_INSTR; d++) { if ((d != i) && (instr[d].ptr[c])) { int cmppos = instr[d].ptr[c]-1; if ((cmppos >= pos) && (cmppos < pos+len)) eraseok = 0; } } if (eraseok) while (len--) deletetable(c, pos); } } } void gototable(int num, int pos) { editmode = EDIT_TABLES; settableview(num, pos); } void settableview(int num, int pos) { etnum = num; etcolumn = 0; etpos = pos; validatetableview(); } void settableviewfirst(int num, int pos) { etview[num] = pos; settableview(num, pos); } void validatetableview(void) { if (etpos - etview[etnum] < 0) etview[etnum] = etpos; if (etpos - etview[etnum] >= VISIBLETABLEROWS) etview[etnum] = etpos - VISIBLETABLEROWS + 1; // Table view lock? if (etlock) { int c; for (c = 0; c < MAX_TABLES; c++) etview[c] = etview[etnum]; } } void tableup(void) { if (shiftpressed) { if ((etmarknum != etnum) || (etpos != etmarkend)) { etmarknum = etnum; etmarkstart = etmarkend = etpos; } } etpos--; if (etpos < 0) etpos = 0; if (shiftpressed) etmarkend = etpos; } void tabledown(void) { if (shiftpressed) { if ((etmarknum != etnum) || (etpos != etmarkend)) { etmarknum = etnum; etmarkstart = etmarkend = etpos; } } etpos++; if (etpos >= MAX_TABLELEN) etpos = MAX_TABLELEN-1; if (shiftpressed) etmarkend = etpos; } void exectable(int num, int ptr) { // Jump error check if ((num != STBL) && (ptr) && (ptr <= MAX_TABLELEN)) { if (ltable[num][ptr-1] == 0xff) { tableerror = TYPE_JUMP; return; } } for (;;) { // Exit when table stopped if (!ptr) break; // Overflow check if ((num != STBL) && (ptr > MAX_TABLELEN)) { tableerror = TYPE_OVERFLOW; break; } // If were already here, exit if (tableused[num][ptr]) break; // Mark current position used tableused[num][ptr] = 1; // Go to next ptr. if (num != STBL) { if (ltable[num][ptr-1] == 0xff) { ptr = rtable[num][ptr-1]; } else ptr++; } else break; } } int findfreespeedtable(void) { int c; for (c = 0; c < MAX_TABLELEN; c++) { if ((!ltable[STBL][c]) && (!rtable[STBL][c])) { return c; } } return -1; } goattracker-2.72/src/betaconv.c0000644000000000000000000002241410774364076015225 0ustar rootroot/* * GoatTracker V2.0 beta songconvertor */ #include #include #include #include #include "bme_end.h" #include "gcommon.h" #define MAX_SPLITS 16 INSTR instr[MAX_INSTR]; unsigned char ltable[3][MAX_TABLELEN*2]; unsigned char rtable[3][MAX_TABLELEN*2]; unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4]; unsigned char songname[MAX_STR]; unsigned char authorname[MAX_STR]; unsigned char copyrightname[MAX_STR]; int pattlen[MAX_PATT]; int songlen[MAX_SONGS][MAX_CHN]; int highestusedpattern = 0; int highestusedinstr = 0; int wavelen = 0, pulselen = 0, filtlen = 0; int vibdepth = 0, pulse = 0; int main(int argc, char **argv); int loadsong(char *name); int savesong(char *name); void countpatternlengths(void); void clearsong(void); int gettablelen(int num); int main(int argc, char **argv) { if (argc < 3) { printf("Usage: BETACONV [vibdepth] [pulse]\n" "[vibdepth] decides whether to halve vibdepth (1=yes 0=no), default 0\n" "[pulse] decides whether to halve pulse speed (1=yes 0=no), default 0\n\n" "Converts GT2 early beta (47 instr.) song to GT2 current format (63 instr.)\n" "Optionally, halves vibrato depths and pulse speeds.\n"); return 1; } if (argc >= 4) { sscanf(argv[3], "%u", &vibdepth); } if (argc >= 5) { sscanf(argv[4], "%u", &pulse); } if (!loadsong(argv[1])) { printf("ERROR: Couldn't load source song."); return 1; } if (!savesong(argv[2])) { printf("ERROR: Couldn't save destination song."); return 1; } return 0; } int loadsong(char *name) { char ident[4]; int c; FILE *srchandle = fopen(name, "rb"); if (srchandle) { fread(ident, 4, 1, srchandle); if (!memcmp(ident, "GTS2", 4)) { int d; unsigned char length; unsigned char amount; int loadbytes; clearsong(); // Read infotexts fread(songname, sizeof songname, 1, srchandle); fread(authorname, sizeof authorname, 1, srchandle); fread(copyrightname, sizeof copyrightname, 1, srchandle); // Read songorderlists amount = fread8(srchandle); for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = fread8(srchandle); loadbytes = length; loadbytes++; fread(songorder[d][c], loadbytes, 1, srchandle); } } // Read instruments for (c = 1; c <= 47; c++) { instr[c].ad = fread8(srchandle); instr[c].sr = fread8(srchandle); instr[c].ptr[WTBL] = fread8(srchandle); instr[c].ptr[PTBL] = fread8(srchandle); instr[c].ptr[FTBL] = fread8(srchandle); instr[c].vibdelay = fread8(srchandle); instr[c].ptr[STBL] = fread8(srchandle); if (vibdepth) instr[c].ptr[STBL] = (instr[c].ptr[STBL] & 0xf0) | ((instr[c].ptr[STBL] & 0x0f) >> 1); instr[c].gatetimer = fread8(srchandle); instr[c].firstwave = fread8(srchandle); fread(&instr[c].name, MAX_INSTRNAMELEN, 1, srchandle); } // Read tables for (c = 0; c < 3; c++) { loadbytes = fread8(srchandle); fread(ltable[c], loadbytes, 1, srchandle); fread(rtable[c], loadbytes, 1, srchandle); if ((c == PTBL) && (pulse)) { for (d = 0; d < loadbytes; d++) { if ((ltable[PTBL][d]) && (ltable[PTBL][d] < 0x80)) { // Halve positive pulsespeed if (rtable[PTBL][d] < 0x80) { rtable[PTBL][d] >>= 1; } else { rtable[PTBL][d] >>= 1; rtable[PTBL][d] |= 0x80; } } } } } // Read patterns amount = fread8(srchandle); for (c = 0; c < amount; c++) { length = fread8(srchandle); fread(pattern[c], length*4, 1, srchandle); for (d = 0; d < length; d++) { // Convert notes in patterns to new format if (pattern[c][d*4] == 0xb0) pattern[c][d*4] = REST; if ((pattern[c][d*4] >= 0x50) && (pattern[c][d*4] <= 0xaf)) { pattern[c][d*4] += 0x10; if (pattern[c][d*4] > REST) pattern[c][d*4] = REST; } // Halve vibrato depth if ((vibdepth) && (pattern[c][d*4+2] == 0x4)) pattern[c][d*4+3] = (pattern[c][d*4+3] & 0xf0) | ((pattern[c][d*4+3] & 0x0f) >> 1); } } countpatternlengths(); for (c = 1; c < MAX_INSTR; c++) { if ((instr[c].ad) || (instr[c].sr) || (instr[c].ptr[0]) || (instr[c].ptr[1]) || (instr[c].ptr[2]) || (instr[c].vibdelay) || (instr[c].ptr[STBL])) { if (c > highestusedinstr) highestusedinstr = c; } } fclose(srchandle); return 1; } fclose(srchandle); } return 0; } int savesong(char *name) { char ident[] = {'G', 'T', 'S', '2'}; FILE *handle; int c; handle = fopen(name, "wb"); if (handle) { int d; unsigned char length; unsigned char amount; int writebytes; fwrite(ident, 4, 1, handle); // Write infotexts fwrite(songname, sizeof songname, 1, handle); fwrite(authorname, sizeof authorname, 1, handle); fwrite(copyrightname, sizeof copyrightname, 1, handle); // Determine amount of songs to be saved c = 0; for (;;) { if (c == MAX_SONGS) break; if ((!songlen[c][0])|| (!songlen[c][1])|| (!songlen[c][2])) break; c++; } amount = c; fwrite8(handle, amount); // Write songorderlists for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = songlen[d][c]+1; fwrite8(handle, length); writebytes = length; writebytes++; fwrite(songorder[d][c], writebytes, 1, handle); } } // Write instruments fwrite8(handle, highestusedinstr); for (c = 1; c <= highestusedinstr; c++) { fwrite8(handle, instr[c].ad); fwrite8(handle, instr[c].sr); fwrite8(handle, instr[c].ptr[WTBL]); fwrite8(handle, instr[c].ptr[PTBL]); fwrite8(handle, instr[c].ptr[FTBL]); fwrite8(handle, instr[c].vibdelay); fwrite8(handle, instr[c].ptr[STBL]); fwrite8(handle, instr[c].gatetimer); fwrite8(handle, instr[c].firstwave); fwrite(&instr[c].name, MAX_INSTRNAMELEN, 1, handle); } // Write tables for (c = 0; c < 3; c++) { writebytes = gettablelen(c); fwrite8(handle, writebytes); fwrite(ltable[c], writebytes, 1, handle); fwrite(rtable[c], writebytes, 1, handle); } // Write patterns amount = highestusedpattern + 1; fwrite8(handle, amount); for (c = 0; c < amount; c++) { length = pattlen[c]+1; fwrite8(handle, length); fwrite(pattern[c], length*4, 1, handle); } fclose(handle); return 1; } return 0; } void countpatternlengths(void) { int c, d, e; highestusedpattern = 0; highestusedinstr = 0; for (c = 0; c < MAX_PATT; c++) { for (d = 0; d <= MAX_PATTROWS; d++) { if (pattern[c][d*4] == ENDPATT) break; if ((pattern[c][d*4] != REST) || (pattern[c][d*4+1]) || (pattern[c][d*4+2]) || (pattern[c][d*4+3])) highestusedpattern = c; if (pattern[c][d*4+1] > highestusedinstr) highestusedinstr = pattern[c][d*4+1]; } pattlen[c] = d; } for (e = 0; e < MAX_SONGS; e++) { for (c = 0; c < MAX_CHN; c++) { for (d = 0; d < MAX_SONGLEN; d++) { if (songorder[e][c][d] >= LOOPSONG) break; if (songorder[e][c][d] < MAX_PATT) { if (songorder[e][c][d] > highestusedpattern) highestusedpattern = songorder[e][c][d]; } } songlen[e][c] = d; } } } void clearsong(void) { int c; for (c = 0; c < MAX_CHN; c++) { int d; for (d = 0; d < MAX_SONGS; d++) { memset(&songorder[d][c][0], 0, MAX_SONGLEN); if (!d) { songorder[d][c][0] = c; songorder[d][c][1] = LOOPSONG; songorder[d][c][2] = 0; } else { songorder[d][c][0] = LOOPSONG; songorder[d][c][1] = 0; } } } memset(songname, 0, sizeof songname); memset(authorname, 0, sizeof authorname); memset(copyrightname, 0, sizeof copyrightname); for (c = 0; c < MAX_PATT; c++) { int d; memset(&pattern[c][0], 0, MAX_PATTROWS*4); for (d = 0; d < MAX_PATTROWS; d++) pattern[c][d*4] = REST; for (d = MAX_PATTROWS; d <= MAX_PATTROWS; d++) pattern[c][d*4] = ENDPATT; } for (c = 0; c < MAX_INSTR; c++) { memset(&instr[c], 0, sizeof(INSTR)); } memset(ltable, 0, sizeof ltable); memset(rtable, 0, sizeof rtable); countpatternlengths(); } int gettablelen(int num) { int c; for (c = MAX_TABLELEN-1; c >= 0; c--) { if (ltable[num][c] | rtable[num][c]) break; } return c+1; } goattracker-2.72/src/gsid.h0000644000000000000000000000145111313456432014341 0ustar rootroot#ifndef GSID_H #define GSID_H #define NUMSIDREGS 0x19 #define SIDWRITEDELAY 9 // lda $xxxx,x 4 cycles, sta $d400,x 5 cycles #define SIDWAVEDELAY 4 // and $xxxx,x 4 cycles extra typedef struct { float distortionrate; float distortionpoint; float distortioncfthreshold; float type3baseresistance; float type3offset; float type3steepness; float type3minimumfetresistance; float type4k; float type4b; float voicenonlinearity; } FILTERPARAMS; void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsigned customclockrate, unsigned usefp); int sid_fillbuffer(short *ptr, int samples); unsigned char sid_getorder(unsigned char index); #ifndef GSID_C extern unsigned char sidreg[NUMSIDREGS]; extern FILTERPARAMS filterparams; #endif #endif goattracker-2.72/src/mod2sng.c0000644000000000000000000002073510774364076015001 0ustar rootroot/* * MOD (4chn) -> GoatTracker SNG converter. * Dedicated to T.M.R! */ #include #include #include #include "bme_end.h" typedef struct { unsigned char note; unsigned char instr; unsigned char command; unsigned char data; } NOTE; typedef struct { unsigned char note; unsigned char command; unsigned char data; } GOATNOTE; unsigned short periodtable[16][12] = { {6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4064, 3840, 3624}, {6800, 6416, 6056, 5720, 5392, 5096, 4808, 4536, 4280, 4040, 3816, 3600}, {6752, 6368, 6016, 5672, 5360, 5056, 4776, 4504, 4256, 4016, 3792, 3576}, {6704, 6328, 5968, 5632, 5320, 5024, 4736, 4472, 4224, 3984, 3760, 3552}, {6656, 6280, 5928, 5592, 5280, 4984, 4704, 4440, 4192, 3960, 3736, 3528}, {6608, 6232, 5888, 5552, 5240, 4952, 4672, 4408, 4160, 3928, 3704, 3496}, {6560, 6192, 5840, 5512, 5208, 4912, 4640, 4376, 4128, 3896, 3680, 3472}, {6512, 6144, 5800, 5472, 5168, 4880, 4600, 4344, 4104, 3872, 3656, 3448}, {7256, 6848, 6464, 6096, 5760, 5424, 5120, 4832, 4560, 4304, 4032, 3840}, {7200, 6800, 6416, 6056, 5720, 5400, 5088, 4808, 4536, 4280, 4040, 3816}, {7152, 6752, 6368, 6016, 5672, 5360, 5056, 4776, 4504, 4256, 4016, 3792}, {7096, 6704, 6328, 5968, 5632, 5320, 5024, 4736, 4472, 4224, 3984, 3760}, {7048, 6656, 6280, 5928, 5592, 5280, 4984, 4704, 4440, 4192, 3952, 3736}, {7000, 6608, 6232, 5888, 5552, 5240, 4952, 4672, 4408, 4160, 3928, 3704}, {6944, 6560, 6192, 5840, 5512, 5208, 4912, 4640, 4376, 4128, 3896, 3680}, {6896, 6512, 6144, 5800, 5472, 5168, 4880, 4600, 4344, 4104, 3872, 3656} }; unsigned char modheader[1084]; unsigned char modpatterns[64*64*4*4]; NOTE modnotes[64*64*4]; GOATNOTE goatnotes[208][65]; unsigned char orderlist[3][256]; GOATNOTE tempnotes[65]; char ident[] = {'G', 'T', 'S', '!'}; char zeroarray[32] = {0}; int maxpatt = 0; int orderlen; int leaveout = 3; int transpose = 0; int goatchan = 0; int goatpatt = 0; int main(int argc, char **argv) { FILE *in, *out; int c, d; unsigned char *srcptr; NOTE *destptr; if (argc < 3) { printf("Usage: mod2sng [channel] [transpose]\n" "[channel] is the channel to leave out (1-4), default 4\n" "[transpose] is the halfstep transpose added to notes, default 0\n"); return 1; } in = fopen(argv[1], "rb"); if (!in) { printf("Source open error.\n"); return 1; } out = fopen(argv[2], "wb"); if (!out) { printf("Destination open error.\n"); return 1; } if (argc > 3) { sscanf(argv[3], "%d", &leaveout); leaveout--; if ((leaveout < 0) || (leaveout > 3)) { printf("Illegal channel number.\n"); return 1; } } if (argc > 4) { sscanf(argv[4], "%d", &transpose); } for (c = 0; c < 1084; c++) { modheader[c] = fread8(in); } orderlen = modheader[950]; for (c = 0; c < 128; c++) { if (modheader[952+c] > maxpatt) maxpatt = modheader[952+c]; } maxpatt++; for (c = 0; c < maxpatt * 1024; c++) { modpatterns[c] = fread8(in); } fclose(in); // Convert patterns into easier-to-read format destptr = modnotes; srcptr = modpatterns; for (c = 0; c < maxpatt * 256; c++) { // Note: FT2 saves the 13th bit of period into 5th bit of // samplenumber, and when loading it ofcourse cannot read // the period back correctly! We don't use the 13th bit! unsigned short period = ((srcptr[0] & 0x0f) << 8) | srcptr[1]; unsigned char note = 0, instrument, command; if (period) { int findnote; int offset = 0x7fffffff; for (findnote = 0; findnote < 96; findnote++) { if (abs(period - (periodtable[0][findnote % 12] >> (findnote / 12))) < offset) { note = findnote + 1; offset = abs(period - (periodtable[0][findnote % 12] >> (findnote / 12))); } } } instrument = (srcptr[0] & 0xf0) | ((srcptr[2] & 0xf0) >> 4); command = srcptr[2] & 0x0f; destptr->note = note; destptr->instr = instrument; destptr->command = command; destptr->data = srcptr[3]; srcptr += 4; destptr++; } // Convert patterns into goatpatterns, and create orderlists for (c = 0; c < 4; c++) { if (c != leaveout) { for (d = 0; d < orderlen; d++) { int patt = modheader[952+d]; int e = 0; int o = patt*256+c; int breakflag = 0; unsigned char prevgoatdata = 0; memset(tempnotes, 0, sizeof tempnotes); for (;;) { unsigned char goatcommand = 0; unsigned char goatdata = 0; if (modnotes[o+e*4].note) { tempnotes[e].note = modnotes[o+e*4].note - 1 + transpose; if (tempnotes[e].note > 0x5d) tempnotes[e].note = 0x5d; } else tempnotes[e].note = 0x5f; switch(modnotes[o+e*4].command) { case 0: goatcommand = modnotes[o+e*4].command; goatdata = modnotes[o+e*4].data; break; case 1: case 2: case 3: case 4: goatcommand = modnotes[o+e*4].command; if (modnotes[o+e*4].data) goatdata = modnotes[o+e*4].data; else goatdata = prevgoatdata; prevgoatdata = goatdata; break; case 0xf: if (modnotes[o+e*4].data < 0x20) // Ticktempo { goatcommand = 7; goatdata = modnotes[o+e*4].data; } break; case 0xc: // Convert zero volume to keyoff if ((!modnotes[o+e*4].data) && (tempnotes[e].note == 0x5f)) tempnotes[e].note = 0x5e; break; case 0xb: case 0xd: breakflag = 1; break; default: break; } tempnotes[e].command = (modnotes[o+e*4].instr << 3) | goatcommand; tempnotes[e].data = goatdata; e++; if (e == 64) break; if (breakflag) break; } tempnotes[e].note = 0xff; for (e = 0; e < goatpatt; e++) { int f; for (f = 0; f < 65; f++) { if ((goatnotes[e][f].note != tempnotes[f].note) || (goatnotes[e][f].command != tempnotes[f].command) || (goatnotes[e][f].data != tempnotes[f].data)) break; } // Same pattern if (f == 65) { orderlist[goatchan][d] = e; break; } } // No same pattern pattern if (e == goatpatt) { int f; if (goatpatt >= 208) { printf("208 patterns exceeded!\n"); return 1; } for (f = 0; f < 65; f++) { goatnotes[goatpatt][f].note = tempnotes[f].note; goatnotes[goatpatt][f].command = tempnotes[f].command; goatnotes[goatpatt][f].data = tempnotes[f].data; } orderlist[goatchan][d] = goatpatt; goatpatt++; } } goatchan++; } } fwrite(ident, 4, 1, out); // Ident fwrite(&modheader[0], 20, 1, out); // Infotexts fwrite(zeroarray, 12, 1, out); fwrite(zeroarray, 32, 1, out); fwrite(zeroarray, 32, 1, out); fwrite8(out, 1); // Number of songs // Orderlist for (c = 0; c < 3; c++) { fwrite8(out, orderlen+1); for (d = 0; d < orderlen; d++) { fwrite8(out, orderlist[c][d]); } fwrite8(out, 0xff); // Loop song fwrite8(out, 0x0); // From beginning } // Instruments for (c = 1; c < 32; c++) { fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 2); fwrite(&modheader[20+30*(c-1)], 15, 1, out); fwrite8(out, 0); fwrite8(out, 0); fwrite8(out, 0); } // Patterns fwrite8(out, goatpatt); for (c = 0; c < goatpatt; c++) { fwrite8(out, 65*3); for (d = 0; d < 65; d++) { fwrite8(out, goatnotes[c][d].note); fwrite8(out, goatnotes[c][d].command); fwrite8(out, goatnotes[c][d].data); } } fclose(out); printf("Converted successfully.\n"); return 0; } goattracker-2.72/src/palette.lbm0000644000000000000000000000471610774364076015417 0ustar rootrootFORM PBM BMHD@@CMAP33??ggg??So˗?oo?gDPPSnh@CRNGCRNG /CRNG`oCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGTINYhP2BODYgoattracker-2.72/src/cursor.bin0000644000000000000000000000027510774364074015266 0ustar rootroot  goattracker-2.72/src/gsid.cpp0000644000000000000000000001160211314436034014670 0ustar rootroot/* * GOATTRACKER reSID interface */ #define GSID_C #include #include #include "resid/sid.h" #include "resid-fp/sidfp.h" extern "C" { #include "gsid.h" #include "gsound.h" int clockrate; int samplerate; unsigned char sidreg[NUMSIDREGS]; unsigned char sidorder[] = {0x15,0x16,0x18,0x17, 0x02,0x03,0x06,0x05,0x00,0x01,0x04, 0x09,0x0a,0x0d,0x0c,0x07,0x08,0x0b, 0x10,0x11,0x14,0x13,0x0e,0x0f,0x12}; unsigned char altsidorder[] = {0x15,0x16,0x18,0x17, 0x04,0x00,0x01,0x02,0x03,0x05,0x06, 0x0b,0x07,0x08,0x09,0x0a,0x0c,0x0d, 0x12,0x0e,0x0f,0x10,0x11,0x13,0x14}; SID *sid = 0; SIDFP *sidfp = 0; FILTERPARAMS filterparams = {0.50f, 3.3e6f, 1.0e-4f, 1147036.4394268463f, 274228796.97550374f, 1.0066634233403395f, 16125.154840564108f, 5.5f, 20.f, 0.9613160610660189f}; extern unsigned residdelay; extern unsigned adparam; void sid_init(int speed, unsigned m, unsigned ntsc, unsigned interpolate, unsigned customclockrate, unsigned usefp) { int c; if (ntsc) clockrate = NTSCCLOCKRATE; else clockrate = PALCLOCKRATE; if (customclockrate) clockrate = customclockrate; samplerate = speed; if (!usefp) { if (sidfp) { delete sidfp; sidfp = NULL; } if (!sid) sid = new SID; } else { if (sid) { delete sid; sid = NULL; } if (!sidfp) sidfp = new SIDFP; } switch(interpolate) { case 0: if (sid) sid->set_sampling_parameters(clockrate, SAMPLE_FAST, speed); if (sidfp) sidfp->set_sampling_parameters(clockrate, SAMPLE_INTERPOLATE, speed); break; default: if (sid) sid->set_sampling_parameters(clockrate, SAMPLE_INTERPOLATE, speed); if (sidfp) sidfp->set_sampling_parameters(clockrate, SAMPLE_RESAMPLE_INTERPOLATE, speed); break; } if (sid) sid->reset(); if (sidfp) sidfp->reset(); for (c = 0; c < NUMSIDREGS; c++) { sidreg[c] = 0x00; } if (m == 1) { if (sid) sid->set_chip_model(MOS8580); if (sidfp) sidfp->set_chip_model(MOS8580); } else { if (sid) sid->set_chip_model(MOS6581); if (sidfp) sidfp->set_chip_model(MOS6581); } if (sidfp) { sidfp->get_filter().set_distortion_properties( filterparams.distortionrate, filterparams.distortionpoint, filterparams.distortioncfthreshold); sidfp->get_filter().set_type3_properties( filterparams.type3baseresistance, filterparams.type3offset, filterparams.type3steepness, filterparams.type3minimumfetresistance); sidfp->get_filter().set_type4_properties( filterparams.type4k, filterparams.type4b); sidfp->set_voice_nonlinearity( filterparams.voicenonlinearity); } } unsigned char sid_getorder(unsigned char index) { if (adparam >= 0xf000) return altsidorder[index]; else return sidorder[index]; } int sid_fillbuffer(short *ptr, int samples) { int tdelta; int tdelta2; int result = 0; int total = 0; int c; int badline = rand() % NUMSIDREGS; tdelta = clockrate * samples / samplerate; if (tdelta <= 0) return total; for (c = 0; c < NUMSIDREGS; c++) { unsigned char o = sid_getorder(c); // Extra delay for loading the waveform (and mt_chngate,x) if ((o == 4) || (o == 11) || (o == 18)) { tdelta2 = SIDWAVEDELAY; if (sid) result = sid->clock(tdelta2, ptr, samples); if (sidfp) result = sidfp->clock(tdelta2, ptr, samples); total += result; ptr += result; samples -= result; tdelta -= SIDWAVEDELAY; } // Possible random badline delay once per writing if ((badline == c) && (residdelay)) { tdelta2 = residdelay; if (sid) result = sid->clock(tdelta2, ptr, samples); if (sidfp) result = sidfp->clock(tdelta2, ptr, samples); total += result; ptr += result; samples -= result; tdelta -= residdelay; } if (sid) sid->write(o, sidreg[o]); if (sidfp) sidfp->write(o, sidreg[o]); tdelta2 = SIDWRITEDELAY; if (sid) result = sid->clock(tdelta2, ptr, samples); if (sidfp) result = sidfp->clock(tdelta2, ptr, samples); total += result; ptr += result; samples -= result; tdelta -= SIDWRITEDELAY; if (tdelta <= 0) return total; } if (sid) result = sid->clock(tdelta, ptr, samples); if (sidfp) result = sidfp->clock(tdelta, ptr, samples); total += result; ptr += result; samples -= result; // Loop extra cycles until all samples produced while (samples) { tdelta = clockrate * samples / samplerate; if (tdelta <= 0) return total; if (sid) result = sid->clock(tdelta, ptr, samples); if (sidfp) result = sidfp->clock(tdelta, ptr, samples); total += result; ptr += result; samples -= result; } return total; } } goattracker-2.72/src/gsong.c0000644000000000000000000012727511460110342014526 0ustar rootroot// // GOATTRACKER v2 song data model, loading/saving/conversion // #define GSONG_C #include "goattrk2.h" INSTR instr[MAX_INSTR]; unsigned char ltable[MAX_TABLES][MAX_TABLELEN]; unsigned char rtable[MAX_TABLES][MAX_TABLELEN]; unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4]; char songname[MAX_STR]; char authorname[MAX_STR]; char copyrightname[MAX_STR]; int pattlen[MAX_PATT]; int songlen[MAX_SONGS][MAX_CHN]; int highestusedpattern; int highestusedinstr; int savesong(void) { int c; char ident[] = {'G', 'T', 'S', '5'}; FILE *handle; if (strlen(songfilename) < MAX_FILENAME-4) { int extfound = 0; for (c = strlen(songfilename)-1; c >= 0; c--) { if (songfilename[c] == '.') extfound = 1; } if (!extfound) strcat(songfilename, ".sng"); } handle = fopen(songfilename, "wb"); if (handle) { int d; int length; int amount; int writebytes; fwrite(ident, 4, 1, handle); // Determine amount of patterns & instruments countpatternlengths(); for (c = 1; c < MAX_INSTR; c++) { if ((instr[c].ad) || (instr[c].sr) || (instr[c].ptr[0]) || (instr[c].ptr[1]) || (instr[c].ptr[2]) || (instr[c].vibdelay) || (instr[c].ptr[3])) { if (c > highestusedinstr) highestusedinstr = c; } } // Write infotexts fwrite(songname, sizeof songname, 1, handle); fwrite(authorname, sizeof authorname, 1, handle); fwrite(copyrightname, sizeof copyrightname, 1, handle); // Determine amount of songs to be saved c = MAX_SONGS - 1; for (;;) { if ((songlen[c][0])&& (songlen[c][1])&& (songlen[c][2])) break; if (c == 0) break; c--; } amount = c + 1; fwrite8(handle, amount); // Write songorderlists for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = songlen[d][c]+1; fwrite8(handle, length); writebytes = length; writebytes++; fwrite(songorder[d][c], writebytes, 1, handle); } } // Write amount of instruments fwrite8(handle, highestusedinstr); // Write instruments for (c = 1; c <= highestusedinstr; c++) { fwrite8(handle, instr[c].ad); fwrite8(handle, instr[c].sr); fwrite8(handle, instr[c].ptr[WTBL]); fwrite8(handle, instr[c].ptr[PTBL]); fwrite8(handle, instr[c].ptr[FTBL]); fwrite8(handle, instr[c].ptr[STBL]); fwrite8(handle, instr[c].vibdelay); fwrite8(handle, instr[c].gatetimer); fwrite8(handle, instr[c].firstwave); fwrite(&instr[c].name, MAX_INSTRNAMELEN, 1, handle); } // Write tables for (c = 0; c < MAX_TABLES; c++) { writebytes = gettablelen(c); fwrite8(handle, writebytes); fwrite(ltable[c], writebytes, 1, handle); fwrite(rtable[c], writebytes, 1, handle); } // Write patterns amount = highestusedpattern + 1; fwrite8(handle, amount); for (c = 0; c < amount; c++) { length = pattlen[c]+1; fwrite8(handle, length); fwrite(pattern[c], length * 4, 1, handle); } fclose(handle); strcpy(loadedsongfilename, songfilename); return 1; } return 0; } int saveinstrument(void) { int c; char ident[] = {'G', 'T', 'I', '5'}; FILE *handle; if (strlen(instrfilename) < MAX_FILENAME-4) { int extfound = 0; for (c = strlen(instrfilename)-1; c >= 0; c--) { if (instrfilename[c] == '.') extfound = 1; } if (!extfound) strcat(instrfilename, ".ins"); } handle = fopen(instrfilename, "wb"); if (handle) { fwrite(ident, 4, 1, handle); // Write instrument fwrite8(handle, instr[einum].ad); fwrite8(handle, instr[einum].sr); fwrite8(handle, instr[einum].ptr[WTBL]); fwrite8(handle, instr[einum].ptr[PTBL]); fwrite8(handle, instr[einum].ptr[FTBL]); fwrite8(handle, instr[einum].ptr[STBL]); fwrite8(handle, instr[einum].vibdelay); fwrite8(handle, instr[einum].gatetimer); fwrite8(handle, instr[einum].firstwave); fwrite(&instr[einum].name, MAX_INSTRNAMELEN, 1, handle); for (c = 0; c < MAX_TABLES; c++) { if (instr[einum].ptr[c]) { int pos = instr[einum].ptr[c] - 1; int len = gettablepartlen(c, pos); fwrite8(handle, len); fwrite(<able[c][pos], len, 1, handle); fwrite(&rtable[c][pos], len, 1, handle); } else fwrite8(handle, 0); } fclose(handle); return 1; } return 0; } void loadsong(void) { int c; int ok = 0; char ident[4]; FILE *handle; handle = fopen(songfilename, "rb"); if (handle) { fread(ident, 4, 1, handle); if ((!memcmp(ident, "GTS3", 4)) || (!memcmp(ident, "GTS4", 4)) || (!memcmp(ident, "GTS5", 4))) { int d; int length; int amount; int loadsize; clearsong(1,1,1,1,1); ok = 1; // Read infotexts fread(songname, sizeof songname, 1, handle); fread(authorname, sizeof authorname, 1, handle); fread(copyrightname, sizeof copyrightname, 1, handle); // Read songorderlists amount = fread8(handle); for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = fread8(handle); loadsize = length; loadsize++; fread(songorder[d][c], loadsize, 1, handle); } } // Read instruments amount = fread8(handle); for (c = 1; c <= amount; c++) { instr[c].ad = fread8(handle); instr[c].sr = fread8(handle); instr[c].ptr[WTBL] = fread8(handle); instr[c].ptr[PTBL] = fread8(handle); instr[c].ptr[FTBL] = fread8(handle); instr[c].ptr[STBL] = fread8(handle); instr[c].vibdelay = fread8(handle); instr[c].gatetimer = fread8(handle); instr[c].firstwave = fread8(handle); fread(&instr[c].name, MAX_INSTRNAMELEN, 1, handle); } // Read tables for (c = 0; c < MAX_TABLES; c++) { loadsize = fread8(handle); fread(ltable[c], loadsize, 1, handle); fread(rtable[c], loadsize, 1, handle); } // Read patterns amount = fread8(handle); for (c = 0; c < amount; c++) { length = fread8(handle) * 4; fread(pattern[c], length, 1, handle); } countpatternlengths(); songchange(); } // Goattracker v2.xx (3-table) import if (!memcmp(ident, "GTS2", 4)) { int d; int length; int amount; int loadsize; clearsong(1,1,1,1,1); ok = 1; // Read infotexts fread(songname, sizeof songname, 1, handle); fread(authorname, sizeof authorname, 1, handle); fread(copyrightname, sizeof copyrightname, 1, handle); // Read songorderlists amount = fread8(handle); for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = fread8(handle); loadsize = length; loadsize++; fread(songorder[d][c], loadsize, 1, handle); } } // Read instruments amount = fread8(handle); for (c = 1; c <= amount; c++) { instr[c].ad = fread8(handle); instr[c].sr = fread8(handle); instr[c].ptr[WTBL] = fread8(handle); instr[c].ptr[PTBL] = fread8(handle); instr[c].ptr[FTBL] = fread8(handle); instr[c].vibdelay = fread8(handle); instr[c].ptr[STBL] = makespeedtable(fread8(handle), finevibrato, 0) + 1; instr[c].gatetimer = fread8(handle); instr[c].firstwave = fread8(handle); fread(&instr[c].name, MAX_INSTRNAMELEN, 1, handle); } // Read tables for (c = 0; c < MAX_TABLES-1; c++) { loadsize = fread8(handle); fread(ltable[c], loadsize, 1, handle); fread(rtable[c], loadsize, 1, handle); } // Read patterns amount = fread8(handle); for (c = 0; c < amount; c++) { int d; length = fread8(handle) * 4; fread(pattern[c], length, 1, handle); // Convert speedtable-requiring commands for (d = 0; d < length; d++) { switch (pattern[c][d*4+2]) { case CMD_FUNKTEMPO: pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], MST_FUNKTEMPO, 0) + 1; break; case CMD_PORTAUP: case CMD_PORTADOWN: case CMD_TONEPORTA: pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], MST_PORTAMENTO, 0) + 1; break; case CMD_VIBRATO: pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], finevibrato, 0) + 1; break; } } } countpatternlengths(); songchange(); } // Goattracker 1.xx import if (!memcmp(ident, "GTS!", 4)) { int d; int length; int amount; int loadsize; int fw = 0; int fp = 0; int ff = 0; int fi = 0; int numfilter = 0; unsigned char filtertable[256]; unsigned char filtermap[64]; int arpmap[32][256]; unsigned char pulse[32], pulseadd[32], pulselimitlow[32], pulselimithigh[32]; int filterjumppos[64]; clearsong(1,1,1,1,1); ok = 1; // Read infotexts fread(songname, sizeof songname, 1, handle); fread(authorname, sizeof authorname, 1, handle); fread(copyrightname, sizeof copyrightname, 1, handle); // Read songorderlists amount = fread8(handle); for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = fread8(handle); loadsize = length; loadsize++; fread(songorder[d][c], loadsize, 1, handle); } } // Convert instruments for (c = 1; c < 32; c++) { unsigned char wavelen; instr[c].ad = fread8(handle); instr[c].sr = fread8(handle); pulse[c] = fread8(handle); pulseadd[c] = fread8(handle); pulselimitlow[c] = fread8(handle); pulselimithigh[c] = fread8(handle); instr[c].ptr[FTBL] = fread8(handle); // Will be converted later if (instr[c].ptr[FTBL] > numfilter) numfilter = instr[c].ptr[FTBL]; if (pulse[c] & 1) instr[c].gatetimer |= 0x80; // "No hardrestart" flag pulse[c] &= 0xfe; wavelen = fread8(handle)/2; fread(&instr[c].name, MAX_INSTRNAMELEN, 1, handle); instr[c].ptr[WTBL] = fw+1; // Convert wavetable for (d = 0; d < wavelen; d++) { if (fw < MAX_TABLELEN) { ltable[WTBL][fw] = fread8(handle); rtable[WTBL][fw] = fread8(handle); if (ltable[WTBL][fw] == 0xff) if (rtable[WTBL][fw]) rtable[WTBL][fw] += instr[c].ptr[WTBL]-1; if ((ltable[WTBL][fw] >= 0x8) && (ltable[WTBL][fw] <= 0xf)) ltable[WTBL][fw] |= 0xe0; fw++; } else { fread8(handle); fread8(handle); } } // Remove empty wavetable afterwards if ((wavelen == 2) && (!ltable[WTBL][fw-2]) && (!rtable[WTBL][fw-2])) { instr[c].ptr[WTBL] = 0; fw -= 2; ltable[WTBL][fw] = 0; rtable[WTBL][fw] = 0; ltable[WTBL][fw+1] = 0; rtable[WTBL][fw+1] = 0; } // Convert pulsetable if (pulse[c]) { int pulsetime, pulsedist, hlpos; // Check for duplicate pulse settings for (d = 1; d < c; d++) { if ((pulse[d] == pulse[c]) && (pulseadd[d] == pulseadd[c]) && (pulselimitlow[d] == pulselimitlow[c]) && (pulselimithigh[d] == pulselimithigh[c])) { instr[c].ptr[PTBL] = instr[d].ptr[PTBL]; goto PULSEDONE; } } // Initial pulse setting if (fp >= MAX_TABLELEN) goto PULSEDONE; instr[c].ptr[PTBL] = fp+1; ltable[PTBL][fp] = 0x80 | (pulse[c] >> 4); rtable[PTBL][fp] = pulse[c] << 4; fp++; // Pulse modulation if (pulseadd[c]) { int startpulse = pulse[c]*16; int currentpulse = pulse[c]*16; // Phase 1: From startpos to high limit pulsedist = pulselimithigh[c]*16 - currentpulse; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd[c]; currentpulse += pulsetime*pulseadd[c]; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = pulseadd[c] / 2; fp++; pulsetime -= acttime; } } hlpos = fp; // Phase 2: from high limit to low limit pulsedist = currentpulse - pulselimitlow[c]*16; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd[c]; currentpulse -= pulsetime*pulseadd[c]; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = -(pulseadd[c] / 2); fp++; pulsetime -= acttime; } } // Phase 3: from low limit back to startpos/high limit if ((startpulse < pulselimithigh[c]*16) && (startpulse > currentpulse)) { pulsedist = startpulse - currentpulse; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd[c]; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = pulseadd[c] / 2; fp++; pulsetime -= acttime; } } // Pulse jump back to beginning if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = 0xff; rtable[PTBL][fp] = instr[c].ptr[PTBL] + 1; fp++; } else { pulsedist = pulselimithigh[c]*16 - currentpulse; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd[c]; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = pulseadd[c] / 2; fp++; pulsetime -= acttime; } } // Pulse jump back to beginning if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = 0xff; rtable[PTBL][fp] = hlpos + 1; fp++; } } else { // Pulse stopped if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = 0xff; rtable[PTBL][fp] = 0; fp++; } PULSEDONE: {} } } // Convert patterns amount = fread8(handle); for (c = 0; c < amount; c++) { length = fread8(handle); for (d = 0; d < length/3; d++) { unsigned char note, cmd, data, instr; note = fread8(handle); cmd = fread8(handle); data = fread8(handle); instr = cmd >> 3; cmd &= 7; switch(note) { default: note += FIRSTNOTE; if (note > LASTNOTE) note = REST; break; case OLDKEYOFF: note = KEYOFF; break; case OLDREST: note = REST; break; case ENDPATT: break; } switch(cmd) { case 5: cmd = CMD_SETFILTERPTR; if (data > numfilter) numfilter = data; break; case 7: if (data < 0xf0) cmd = CMD_SETTEMPO; else { cmd = CMD_SETMASTERVOL; data &= 0x0f; } break; } pattern[c][d*4] = note; pattern[c][d*4+1] = instr; pattern[c][d*4+2] = cmd; pattern[c][d*4+3] = data; } } countpatternlengths(); fi = highestusedinstr + 1; songchange(); // Read filtertable fread(filtertable, 256, 1, handle); // Convert filtertable for (c = 0; c < 64; c++) { filterjumppos[c] = -1; filtermap[c] = 0; if (filtertable[c*4+3] > numfilter) numfilter = filtertable[c*4+3]; } if (numfilter > 63) numfilter = 63; for (c = 1; c <= numfilter; c++) { filtermap[c] = ff+1; if (filtertable[c*4]|filtertable[c*4+1]|filtertable[c*4+2]|filtertable[c*4+3]) { // Filter set if (filtertable[c*4]) { ltable[FTBL][ff] = 0x80 + (filtertable[c*4+1] & 0x70); rtable[FTBL][ff] = filtertable[c*4]; ff++; if (filtertable[c*4+2]) { ltable[FTBL][ff] = 0x00; rtable[FTBL][ff] = filtertable[c*4+2]; ff++; } } else { // Filter modulation int time = filtertable[c*4+1]; while (time) { int acttime = time; if (acttime > 127) acttime = 127; ltable[FTBL][ff] = acttime; rtable[FTBL][ff] = filtertable[c*4+2]; ff++; time -= acttime; } } // Jump to next step: unnecessary if follows directly if (filtertable[c*4+3] != c+1) { filterjumppos[c] = ff; ltable[FTBL][ff] = 0xff; rtable[FTBL][ff] = filtertable[c*4+3]; // Fix the jump later ff++; } } } // Now fix jumps as the filterstep mapping is known for (c = 1; c <= numfilter; c++) { if (filterjumppos[c] != -1) rtable[FTBL][filterjumppos[c]] = filtermap[rtable[FTBL][filterjumppos[c]]]; } // Fix filterpointers in instruments for (c = 1; c < 32; c++) instr[c].ptr[FTBL] = filtermap[instr[c].ptr[FTBL]]; // Now fix pattern commands memset(arpmap, 0, sizeof arpmap); for (c = 0; c < MAX_PATT; c++) { unsigned char i = 0; for (d = 0; d <= MAX_PATTROWS; d++) { if (pattern[c][d*4+1]) i = pattern[c][d*4+1]; // Convert portamento & vibrato if (pattern[c][d*4+2] == CMD_PORTAUP) pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], MST_PORTAMENTO, 0) + 1; if (pattern[c][d*4+2] == CMD_PORTADOWN) pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], MST_PORTAMENTO, 0) + 1; if (pattern[c][d*4+2] == CMD_TONEPORTA) pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], MST_PORTAMENTO, 0) + 1; if (pattern[c][d*4+2] == CMD_VIBRATO) pattern[c][d*4+3] = makespeedtable(pattern[c][d*4+3], MST_NOFINEVIB, 0) + 1; // Convert filterjump if (pattern[c][d*4+2] == CMD_SETFILTERPTR) pattern[c][d*4+3] = filtermap[pattern[c][d*4+3]]; // Convert funktempo if ((pattern[c][d*4+2] == CMD_SETTEMPO) && (!pattern[c][d*4+3])) { pattern[c][d*4+2] = CMD_FUNKTEMPO; pattern[c][d*4+3] = makespeedtable((filtertable[2] << 4) | (filtertable[3] & 0x0f), MST_FUNKTEMPO, 0) + 1; } // Convert arpeggio if ((pattern[c][d*4+2] == CMD_DONOTHING) && (pattern[c][d*4+3])) { // Must be in conjunction with a note if ((pattern[c][d*4] >= FIRSTNOTE) && (pattern[c][d*4] <= LASTNOTE)) { unsigned char param = pattern[c][d*4+3]; if (i) { // Old arpeggio if (arpmap[i][param]) { // As command, or as instrument? if (arpmap[i][param] < 256) { pattern[c][d*4+2] = CMD_SETWAVEPTR; pattern[c][d*4+3] = arpmap[i][param]; } else { pattern[c][d*4+1] = arpmap[i][param] - 256; pattern[c][d*4+3] = 0; } } else { int e; unsigned char arpstart; unsigned char arploop; // New arpeggio // Copy first the instrument's wavetable up to loop/end point arpstart = fw + 1; if (instr[i].ptr[WTBL]) { for (e = instr[i].ptr[WTBL]-1;; e++) { if (ltable[WTBL][e] == 0xff) break; if (fw < MAX_TABLELEN) { ltable[WTBL][fw] = ltable[WTBL][e]; fw++; } } } // Then make the arpeggio arploop = fw + 1; if (fw < MAX_TABLELEN-3) { ltable[WTBL][fw] = (param & 0x80) >> 7; rtable[WTBL][fw] = (param & 0x70) >> 4; fw++; ltable[WTBL][fw] = (param & 0x80) >> 7; rtable[WTBL][fw] = (param & 0xf); fw++; ltable[WTBL][fw] = (param & 0x80) >> 7; rtable[WTBL][fw] = 0; fw++; ltable[WTBL][fw] = 0xff; rtable[WTBL][fw] = arploop; fw++; // Create new instrument if possible if (fi < MAX_INSTR) { arpmap[i][param] = fi + 256; instr[fi] = instr[i]; instr[fi].ptr[WTBL] = arpstart; // Add arpeggio parameter to new instrument name if (strlen(instr[fi].name) < MAX_INSTRNAMELEN-3) { char arpname[8]; sprintf(arpname, "0%02X", param&0x7f); strcat(instr[fi].name, arpname); } fi++; } else { arpmap[i][param] = arpstart; } } if (arpmap[i][param]) { // As command, or as instrument? if (arpmap[i][param] < 256) { pattern[c][d*4+2] = CMD_SETWAVEPTR; pattern[c][d*4+3] = arpmap[i][param]; } else { pattern[c][d*4+1] = arpmap[i][param] - 256; pattern[c][d*4+3] = 0; } } } } } // If arpeggio could not be converted, databyte zero if (!pattern[c][d*4+2]) pattern[c][d*4+3] = 0; } } } } fclose(handle); } if (ok) { strcpy(loadedsongfilename, songfilename); // Reset table views for (c = 0; c < MAX_TABLES; c++) settableview(c, 0); // Convert pulsemodulation speed of < v2.4 songs if (ident[3] < '4') { for (c = 0; c < MAX_TABLELEN; c++) { if ((ltable[PTBL][c] < 0x80) && (rtable[PTBL][c])) { int speed = ((signed char)rtable[PTBL][c]); speed <<= 1; if (speed > 127) speed = 127; if (speed < -128) speed = -128; rtable[PTBL][c] = speed; } } } // Convert old legato/nohr parameters if (ident[3] < '5') { for (c = 1; c < MAX_INSTR; c++) { if (instr[c].firstwave >= 0x80) { instr[c].gatetimer |= 0x80; instr[c].firstwave &= 0x7f; } if (!instr[c].firstwave) instr[c].gatetimer |= 0x40; } } } } void loadinstrument(void) { char ident[4]; FILE *handle; int c,d; int pulsestart = -1; int pulseend = -1; handle = fopen(instrfilename, "rb"); if (handle) { stopsong(); fread(ident, 4, 1, handle); if ((!memcmp(ident, "GTI3", 4)) || (!memcmp(ident, "GTI4", 4)) || (!memcmp(ident, "GTI5", 4))) { unsigned char optr[4]; instr[einum].ad = fread8(handle); instr[einum].sr = fread8(handle); optr[0] = fread8(handle); optr[1] = fread8(handle); optr[2] = fread8(handle); optr[3] = fread8(handle); instr[einum].vibdelay = fread8(handle); instr[einum].gatetimer = fread8(handle); instr[einum].firstwave = fread8(handle); fread(&instr[einum].name, MAX_INSTRNAMELEN, 1, handle); // Erase old tabledata deleteinstrtable(einum); // Load new tabledata for (c = 0; c < MAX_TABLES; c++) { int start = gettablelen(c); int len = fread8(handle); if (len) { for (d = start; (d < start+len) && (d < MAX_TABLELEN); d++) ltable[c][d] = fread8(handle); while (d < start+len) { fread8(handle); d++; } for (d = start; (d < start+len) && (d < MAX_TABLELEN); d++) rtable[c][d] = fread8(handle); while (d < start+len) { fread8(handle); d++; } if (c != STBL) { for (d = start; (d < start+len) && (d < MAX_TABLELEN); d++) { if (ltable[c][d] == 0xff) { if (rtable[c][d]) rtable[c][d] = rtable[c][d] - optr[c] + start + 1; } } } if (c == PTBL) { pulsestart = start; pulseend = start + len; } instr[einum].ptr[c] = start + 1; } else instr[einum].ptr[c] = 0; } } // Goattracker v2.xx (3-table) import if (!memcmp(ident, "GTI2", 4)) { unsigned char optr[3]; instr[einum].ad = fread8(handle); instr[einum].sr = fread8(handle); optr[0] = fread8(handle); optr[1] = fread8(handle); optr[2] = fread8(handle); instr[einum].vibdelay = fread8(handle); instr[einum].ptr[STBL] = makespeedtable(fread8(handle), finevibrato, 0) + 1; instr[einum].gatetimer = fread8(handle); instr[einum].firstwave = fread8(handle); fread(&instr[einum].name, MAX_INSTRNAMELEN, 1, handle); // Erase old tabledata deleteinstrtable(einum); // Load new tabledata for (c = 0; c < MAX_TABLES-1; c++) { int start = gettablelen(c); int len = fread8(handle); if (len) { for (d = start; (d < start+len) && (d < MAX_TABLELEN); d++) ltable[c][d] = fread8(handle); while (d < start+len) { fread8(handle); d++; } for (d = start; (d < start+len) && (d < MAX_TABLELEN); d++) rtable[c][d] = fread8(handle); while (d < start+len) { fread8(handle); d++; } for (d = start; (d < start+len) && (d < MAX_TABLELEN); d++) { if (ltable[c][d] == 0xff) { if (rtable[c][d]) rtable[c][d] = rtable[c][d] - optr[c] + start + 1; } } if (c == PTBL) { pulsestart = start; pulseend = start + len; } instr[einum].ptr[c] = start + 1; } else instr[einum].ptr[c] = 0; } } // Goattracker 1.xx import if (!memcmp(ident, "GTI!", 4)) { unsigned char pulse, pulseadd, pulselimitlow, pulselimithigh, wavelen; unsigned char filtertemp[4]; int fw, fp, ff; // Erase old tabledata deleteinstrtable(einum); fw = gettablelen(WTBL); fp = gettablelen(PTBL); ff = gettablelen(FTBL); instr[einum].ad = fread8(handle); instr[einum].sr = fread8(handle); if (multiplier) instr[einum].gatetimer = 2 * multiplier; else instr[einum].gatetimer = 1; instr[einum].firstwave = 0x9; pulse = fread8(handle); pulseadd = fread8(handle); pulselimitlow = fread8(handle); pulselimithigh = fread8(handle); instr[einum].ptr[FTBL] = fread8(handle) ? ff+1 : 0; if (pulse & 1) instr[einum].gatetimer |= 0x80; // "No hardrestart" flag wavelen = fread8(handle)/2; fread(&instr[einum].name, MAX_INSTRNAMELEN, 1, handle); instr[einum].ptr[WTBL] = fw+1; // Convert wavetable for (d = 0; d < wavelen; d++) { if (fw < MAX_TABLELEN) { ltable[WTBL][fw] = fread8(handle); rtable[WTBL][fw] = fread8(handle); if (ltable[WTBL][fw] == 0xff) if (rtable[WTBL][fw]) rtable[WTBL][fw] += instr[einum].ptr[WTBL]-1; fw++; } else { fread8(handle); fread8(handle); } } // Remove empty wavetable afterwards if ((wavelen == 2) && (!ltable[WTBL][fw-2]) && (!rtable[WTBL][fw-2])) { instr[einum].ptr[WTBL] = 0; fw -= 2; ltable[WTBL][fw] = 0; rtable[WTBL][fw] = 0; ltable[WTBL][fw+1] = 0; rtable[WTBL][fw+1] = 0; } // Convert pulsetable pulse &= 0xfe; if (pulse) { int pulsetime, pulsedist, hlpos; // Initial pulse setting if (fp >= MAX_TABLELEN) goto PULSEDONE; pulsestart = fp; instr[einum].ptr[PTBL] = fp+1; ltable[PTBL][fp] = 0x80 | (pulse >> 4); rtable[PTBL][fp] = pulse << 4; fp++; // Pulse modulation if (pulseadd) { int startpulse = pulse*16; int currentpulse = pulse*16; // Phase 1: From startpos to high limit pulsedist = pulselimithigh*16 - currentpulse; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd; currentpulse += pulsetime*pulseadd; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = pulseadd / 2; fp++; pulsetime -= acttime; } } hlpos = fp; // Phase 2: from high limit to low limit pulsedist = currentpulse - pulselimitlow*16; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd; currentpulse -= pulsetime*pulseadd; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = -(pulseadd / 2); fp++; pulsetime -= acttime; } } // Phase 3: from low limit back to startpos/high limit if ((startpulse < pulselimithigh*16) && (startpulse > currentpulse)) { pulsedist = startpulse - currentpulse; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = pulseadd / 2; fp++; pulsetime -= acttime; } } // Pulse jump back to beginning if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = 0xff; rtable[PTBL][fp] = instr[einum].ptr[PTBL] + 1; fp++; } else { pulsedist = pulselimithigh*16 - currentpulse; if (pulsedist > 0) { pulsetime = pulsedist/pulseadd; while (pulsetime) { int acttime = pulsetime; if (acttime > 127) acttime = 127; if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = acttime; rtable[PTBL][fp] = pulseadd / 2; fp++; pulsetime -= acttime; } } // Pulse jump back to beginning if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = 0xff; rtable[PTBL][fp] = hlpos + 1; fp++; } } else { // Pulse stopped if (fp >= MAX_TABLELEN) goto PULSEDONE; ltable[PTBL][fp] = 0xff; rtable[PTBL][fp] = 0; fp++; } PULSEDONE: pulseend = fp; } // Convert filter (if any) if ((instr[einum].ptr[FTBL]) && (ff < MAX_TABLELEN-2)) { fread(filtertemp, sizeof filtertemp, 1, handle); // Filter set if (filtertemp[0]) { ltable[FTBL][ff] = 0x80 + (filtertemp[1] & 0x70); rtable[FTBL][ff] = filtertemp[0]; ff++; if (filtertemp[2]) { ltable[FTBL][ff] = 0x00; rtable[FTBL][ff] = filtertemp[2]; ff++; } } else { // Filter modulation int time = filtertemp[1]; while (time) { int acttime = time; if (acttime > 127) acttime = 127; ltable[FTBL][ff] = acttime; rtable[FTBL][ff] = filtertemp[2]; ff++; time -= acttime; } } // Jump to next step: always end the filter ltable[FTBL][ff] = 0xff; rtable[FTBL][ff] = 0; ff++; } } fclose(handle); // Convert pulsemodulation speed of < v2.4 instruments if ((ident[3] < '4') && (pulsestart != -1)) { for (c = pulsestart; (c < pulseend) && (c < MAX_TABLELEN); c++) { if ((ltable[PTBL][c] < 0x80) && (rtable[PTBL][c])) { int speed = ((signed char)rtable[PTBL][c]); speed <<= 1; if (speed > 127) speed = 127; if (speed < -128) speed = -128; rtable[PTBL][c] = speed; } } } // Convert old legato/nohr parameters if (ident[3] < '5') { if (instr[einum].firstwave >= 0x80) { instr[einum].firstwave &= 0x7f; instr[einum].gatetimer |= 0x80; } if (!instr[einum].firstwave) instr[einum].gatetimer |= 0x40; } } } void clearsong(int cs, int cp, int ci, int ct, int cn) { int c; if (!(cs | cp | ci | ct | cn)) return; stopsong(); masterfader = 0x0f; epmarkchn = -1; etmarknum = -1; esmarkchn = -1; followplay = 0; for (c = 0; c < MAX_CHN; c++) { int d; chn[c].mute = 0; if (multiplier) chn[c].tempo = multiplier*6-1; else chn[c].tempo = 6-1; chn[c].pattptr = 0; if (cs) { memset(loadedsongfilename, 0, sizeof loadedsongfilename); for (d = 0; d < MAX_SONGS; d++) { memset(&songorder[d][c][0], 0, MAX_SONGLEN+2); if (!d) { songorder[d][c][0] = c; songorder[d][c][1] = LOOPSONG; } else { songorder[d][c][0] = LOOPSONG; } } epnum[c] = songorder[0][c][0]; espos[c] = 0; esend[c] = 0; } } if (cs) { esview = 0; eseditpos = 0; escolumn = 0; eschn = 0; esnum = 0; eppos = 0; epview =-VISIBLEPATTROWS/2; epcolumn = 0; epchn = 0; } if (cn) { memset(songname, 0, sizeof songname); memset(authorname, 0, sizeof authorname); memset(copyrightname, 0, sizeof copyrightname); enpos = 0; } if (cp) { memset(loadedsongfilename, 0, sizeof loadedsongfilename); for (c = 0; c < MAX_PATT; c++) clearpattern(c); } if (ci) { for (c = 0; c < MAX_INSTR; c++) clearinstr(c); memset(&instrcopybuffer, 0, sizeof(INSTR)); eipos = 0; eicolumn = 0; einum = 1; } if (ct == 1) { for (c = MAX_TABLES-1; c >= 0; c--) { memset(ltable[c], 0, MAX_TABLELEN); memset(rtable[c], 0, MAX_TABLELEN); settableview(c, 0); } } countpatternlengths(); } void countpatternlengths(void) { int c, d, e; highestusedpattern = 0; highestusedinstr = 0; for (c = 0; c < MAX_PATT; c++) { for (d = 0; d <= MAX_PATTROWS; d++) { if (pattern[c][d*4] == ENDPATT) break; if ((pattern[c][d*4] != REST) || (pattern[c][d*4+1]) || (pattern[c][d*4+2]) || (pattern[c][d*4+3])) highestusedpattern = c; if (pattern[c][d*4+1] > highestusedinstr) highestusedinstr = pattern[c][d*4+1]; } pattlen[c] = d; } for (e = 0; e < MAX_SONGS; e++) { for (c = 0; c < MAX_CHN; c++) { for (d = 0; d < MAX_SONGLEN; d++) { if (songorder[e][c][d] >= LOOPSONG) break; if ((songorder[e][c][d] < REPEAT) && (songorder[e][c][d] > highestusedpattern)) highestusedpattern = songorder[e][c][d]; } songlen[e][c] = d; } } } void countthispattern(void) { int c, d, e; c = epnum[epchn]; for (d = 0; d <= MAX_PATTROWS; d++) { if (pattern[c][d*4] == ENDPATT) break; } pattlen[c] = d; e = esnum; c = eschn; for (d = 0; d < MAX_SONGLEN; d++) { if (songorder[e][c][d] >= LOOPSONG) break; if (songorder[e][c][d] > highestusedpattern) highestusedpattern = songorder[e][c][d]; } songlen[e][c] = d; } int insertpattern(int p) { int c, d, e; findusedpatterns(); if (p >= MAX_PATT-2) return 0; if (pattused[MAX_PATT-1]) return 0; memmove(pattern[p+2], pattern[p+1], (MAX_PATT-p-2)*(MAX_PATTROWS*4+4)); countpatternlengths(); for (c = 0; c < MAX_SONGS; c++) { if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2])) { for (d = 0; d < MAX_CHN; d++) { for (e = 0; e < songlen[c][d]; e++) { if ((songorder[c][d][e] < REPEAT) && (songorder[c][d][e] > p) && (songorder[c][d][e] != MAX_PATT-1)) songorder[c][d][e]++; } } } } for (c = 0; c < MAX_CHN; c++) { if ((epnum[c] > p) && (epnum[c] != MAX_PATT-1)) epnum[c]++; } return 1; } void deletepattern(int p) { int c, d, e; if (p == MAX_PATT-1) return; memmove(pattern[p], pattern[p+1], (MAX_PATT-p-1)*(MAX_PATTROWS*4+4)); clearpattern(MAX_PATT-1); countpatternlengths(); for (c = 0; c < MAX_SONGS; c++) { if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2])) { for (d = 0; d < MAX_CHN; d++) { for (e = 0; e < songlen[c][d]; e++) { if ((songorder[c][d][e] < REPEAT) && (songorder[c][d][e] > p)) songorder[c][d][e]--; } } } } for (c = 0; c < MAX_CHN; c++) { if (epnum[c] > p) epnum[c]--; } } void clearpattern(int p) { int c; memset(pattern[p], 0, MAX_PATTROWS*4); for (c = 0; c < defaultpatternlength; c++) pattern[p][c*4] = REST; for (c = defaultpatternlength; c <= MAX_PATTROWS; c++) pattern[p][c*4] = ENDPATT; } void findusedpatterns(void) { int c, d, e; countpatternlengths(); memset(pattused, 0, sizeof pattused); for (c = 0; c < MAX_SONGS; c++) { if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2])) { for (d = 0; d < MAX_CHN; d++) { for (e = 0; e < songlen[c][d]; e++) { if (songorder[c][d][e] < REPEAT) pattused[songorder[c][d][e]] = 1; } } } } } void findduplicatepatterns(void) { int c, d; findusedpatterns(); for (c = 0; c < MAX_PATT; c++) { if (pattused[c]) { for (d = c+1; d < MAX_PATT; d++) { if (pattlen[d] == pattlen[c]) { if (!memcmp(pattern[c], pattern[d], pattlen[c]*4)) { int f, g, h; for (f = 0; f < MAX_SONGS; f++) { if ((songlen[f][0]) && (songlen[f][1]) && (songlen[f][2])) { for (g = 0; g < MAX_CHN; g++) { for (h = 0; h < songlen[f][g]; h++) { if (songorder[f][g][h] == d) songorder[f][g][h] = c; } } } } for (f = 0; f < MAX_CHN; f++) if (epnum[f] == d) epnum[f] = c; } } } } } findusedpatterns(); } void optimizeeverything(int oi, int ot) { int c, d, e; stopsong(); findduplicatepatterns(); memset(instrused, 0, sizeof instrused); for (c = MAX_PATT-1; c >= 0; c--) { if (pattused[c]) { for (d = 0; d < MAX_PATTROWS; d++) { if (pattern[c][d*4] == ENDPATT) break; if (pattern[c][d*4+1]) instrused[pattern[c][d*4+1]] = 1; } } else deletepattern(c); } countpatternlengths(); if (oi) { for (c = MAX_INSTR-2; c >= 1; c--) { if (!instrused[c]) { clearinstr(c); if (c < MAX_INSTR-2) { memmove(&instr[c], &instr[c+1], (MAX_INSTR-2-c) * sizeof(INSTR)); clearinstr(MAX_INSTR-2); for (d = 0; d < MAX_PATT; d++) { for (e = 0; e < pattlen[d]; e++) { if ((pattern[d][e*4+1] > c) && (pattern[d][e*4+1] != MAX_INSTR-1)) pattern[d][e*4+1]--; } } } } } } if (ot) { for (c = 0; c < MAX_TABLES; c++) optimizetable(c); } } goattracker-2.72/src/cwsid.h0000644000000000000000000000203110774364076014533 0ustar rootroot#ifndef DEVSID__H #define DEVSID__H /* The ioctl numbers are modelled after the hardsid linux device driver, so a software may autodetect which device is present behind a /dev/sid. http://hardsid.sourceforge.net/ */ #define CWSID_IOCTL_TYPE ('S') #define CWSID_IOCTL_RESET _IO (CWSID_IOCTL_TYPE, 0) #define CWSID_IOCTL_SIDTYPE _IOR(CWSID_IOCTL_TYPE, 3, int) #define CWSID_IOCTL_CARDTYPE _IOR(CWSID_IOCTL_TYPE, 4, int) #define CWSID_IOCTL_WAITIRQ _IO(CWSID_IOCTL_TYPE, 0x10) #define CWSID_IOCTL_PAL _IO(CWSID_IOCTL_TYPE, 0x11) #define CWSID_IOCTL_NTSC _IO(CWSID_IOCTL_TYPE, 0x12) #define CWSID_IOCTL_SETHZ _IOW(CWSID_IOCTL_TYPE, 0x20,int) #define CWSID_IOCTL_DOUBLEBUFFER _IOW(CWSID_IOCTL_TYPE, 0x21,int) #define CWSID_IOCTL_DELAY _IOW(CWSID_IOCTL_TYPE, 0x22,int) #define CWSID_IOCTL_REALREAD _IOW(CWSID_IOCTL_TYPE, 0x23,int) /* a magic number used by the CWSID_IOCTL_SIDTYPE and CWSID_IOCTL_CARDTYPE ioctls to identify a CatWeasel SID */ #define CWSID_MAGIC 0x100 #endif goattracker-2.72/src/goattrk2.c0000644000000000000000000010654611604134140015146 0ustar rootroot// // GOATTRACKER v2.72 // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // #define GOATTRK2_C #ifdef __WIN32__ #include #endif #include "goattrk2.h" #include "bme.h" int menu = 0; int editmode = EDIT_PATTERN; int recordmode = 1; int followplay = 0; int hexnybble = -1; int stepsize = 4; int autoadvance = 0; int defaultpatternlength = 64; int cursorflash = 0; int cursorcolortable[] = {1,2,7,2}; int exitprogram = 0; int eacolumn = 0; int eamode = 0; unsigned keypreset = KEY_TRACKER; unsigned playerversion = 0; int fileformat = FORMAT_PRG; int zeropageadr = 0xfc; int playeradr = 0x1000; unsigned sidmodel = 0; unsigned multiplier = 1; unsigned adparam = 0x0f00; unsigned ntsc = 0; unsigned patternhex = 0; unsigned sidaddress = 0xd400; unsigned finevibrato = 1; unsigned optimizepulse = 1; unsigned optimizerealtime = 1; unsigned customclockrate = 0; unsigned usefinevib = 0; unsigned b = DEFAULTBUF; unsigned mr = DEFAULTMIXRATE; unsigned writer = 0; unsigned hardsid = 0; unsigned catweasel = 0; unsigned interpolate = 0; unsigned residdelay = 0; unsigned hardsidbufinteractive = 20; unsigned hardsidbufplayback = 400; float basepitch = 0.0f; char configbuf[MAX_PATHNAME]; char loadedsongfilename[MAX_FILENAME]; char songfilename[MAX_FILENAME]; char songfilter[MAX_FILENAME]; char songpath[MAX_PATHNAME]; char instrfilename[MAX_FILENAME]; char instrfilter[MAX_FILENAME]; char instrpath[MAX_PATHNAME]; char packedpath[MAX_PATHNAME]; char *programname = "$VER: GoatTracker v2.72"; char textbuffer[MAX_PATHNAME]; unsigned char hexkeytbl[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; extern unsigned char datafile[]; int main(int argc, char **argv) { char filename[MAX_PATHNAME]; FILE *configfile; int c,d; programname += sizeof "$VER:"; // Open datafile io_openlinkeddatafile(datafile); // Load configuration #ifdef __WIN32__ GetModuleFileName(NULL, filename, MAX_PATHNAME); filename[strlen(filename)-3] = 'c'; filename[strlen(filename)-2] = 'f'; filename[strlen(filename)-1] = 'g'; #elif __amigaos__ strcpy(filename, "PROGDIR:goattrk2.cfg"); #else strcpy(filename, getenv("HOME")); strcat(filename, "/.goattrk/goattrk2.cfg"); #endif configfile = fopen(filename, "rt"); if (configfile) { getparam(configfile, &b); getparam(configfile, &mr); getparam(configfile, &hardsid); getparam(configfile, &sidmodel); getparam(configfile, &ntsc); getparam(configfile, (unsigned *)&fileformat); getparam(configfile, (unsigned *)&playeradr); getparam(configfile, (unsigned *)&zeropageadr); getparam(configfile, &playerversion); getparam(configfile, &keypreset); getparam(configfile, (unsigned *)&stepsize); getparam(configfile, &multiplier); getparam(configfile, &catweasel); getparam(configfile, &adparam); getparam(configfile, &interpolate); getparam(configfile, &patternhex); getparam(configfile, &sidaddress); getparam(configfile, &finevibrato); getparam(configfile, &optimizepulse); getparam(configfile, &optimizerealtime); getparam(configfile, &residdelay); getparam(configfile, &customclockrate); getparam(configfile, &hardsidbufinteractive); getparam(configfile, &hardsidbufplayback); getfloatparam(configfile, &filterparams.distortionrate); getfloatparam(configfile, &filterparams.distortionpoint); getfloatparam(configfile, &filterparams.distortioncfthreshold); getfloatparam(configfile, &filterparams.type3baseresistance); getfloatparam(configfile, &filterparams.type3offset); getfloatparam(configfile, &filterparams.type3steepness); getfloatparam(configfile, &filterparams.type3minimumfetresistance); getfloatparam(configfile, &filterparams.type4k); getfloatparam(configfile, &filterparams.type4b); getfloatparam(configfile, &filterparams.voicenonlinearity); getparam(configfile, &win_fullscreen); getfloatparam(configfile, &basepitch); fclose(configfile); } // Init pathnames initpaths(); // Scan command line for (c = 1; c < argc; c++) { #ifdef __WIN32__ if ((argv[c][0] == '-') || (argv[c][0] == '/')) #else if (argv[c][0] == '-') #endif { int y = 0; switch(toupper(argv[c][1])) { case '?': if (!initscreen()) return 1; if(argv[c][2]=='?') { onlinehelp(1,0); return 0; } printtext(0,y++,15,"Usage: GOATTRK2 [songname] [options]"); printtext(0,y++,15,"Options:"); printtext(0,y++,15,"-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00"); printtext(0,y++,15,"-Bxx Set sound buffer length in milliseconds DEFAULT=100"); printtext(0,y++,15,"-Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on)"); printtext(0,y++,15,"-Dxx Pattern row display (0 = decimal, 1 = hexadecimal)"); printtext(0,y++,15,"-Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=6581"); printtext(0,y++,15,"-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)"); printtext(0,y++,15,"-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)"); printtext(0,y++,15,"-Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.)"); printtext(0,y++,15,"-Ixx Set reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) DEFAULT=off"); printtext(0,y++,15,"-Kxx Note-entry mode (0 = PROTRACKER 1 = DMC) DEFAULT=PROTRK."); printtext(0,y++,15,"-Lxx SID memory location in hex. DEFAULT=D400"); printtext(0,y++,15,"-Mxx Set sound mixing rate DEFAULT=44100"); printtext(0,y++,15,"-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on"); printtext(0,y++,15,"-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on"); printtext(0,y++,15,"-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.)"); printtext(0,y++,15,"-Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0"); printtext(0,y++,15,"-Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0"); printtext(0,y++,15,"-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on"); printtext(0,y++,15,"-Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window"); printtext(0,y++,15,"-Zxx Set random reSID write delay in cycles (0 = off) DEFAULT=off"); printtext(0,y++,15,"-N Use NTSC timing"); printtext(0,y++,15,"-P Use PAL timing (DEFAULT)"); printtext(0,y++,15,"-W Write sound output to a file SIDAUDIO.RAW"); printtext(0,y++,15,"-? Show this info again"); printtext(0,y++,15,"-?? Standalone online help window"); waitkeynoupdate(); return 0; case 'Z': sscanf(&argv[c][2], "%u", &residdelay); break; case 'A': sscanf(&argv[c][2], "%x", &adparam); break; case 'S': sscanf(&argv[c][2], "%u", &multiplier); break; case 'B': sscanf(&argv[c][2], "%u", &b); break; case 'D': sscanf(&argv[c][2], "%u", &patternhex); break; case 'E': sscanf(&argv[c][2], "%u", &sidmodel); break; case 'I': sscanf(&argv[c][2], "%u", &interpolate); break; case 'K': sscanf(&argv[c][2], "%u", &keypreset); break; case 'L': sscanf(&argv[c][2], "%x", &sidaddress); break; case 'N': ntsc = 1; customclockrate = 0; break; case 'P': ntsc = 0; customclockrate = 0; break; case 'F': sscanf(&argv[c][2], "%u", &customclockrate); break; case 'M': sscanf(&argv[c][2], "%u", &mr); break; case 'O': sscanf(&argv[c][2], "%u", &optimizepulse); break; case 'R': sscanf(&argv[c][2], "%u", &optimizerealtime); break; case 'H': sscanf(&argv[c][2], "%u", &hardsid); break; case 'V': sscanf(&argv[c][2], "%u", &finevibrato); break; case 'T': sscanf(&argv[c][2], "%u", &hardsidbufinteractive); break; case 'U': sscanf(&argv[c][2], "%u", &hardsidbufplayback); break; case 'W': writer = 1; break; case 'X': sscanf(&argv[c][2], "%u", &win_fullscreen); break; case 'C': sscanf(&argv[c][2], "%u", &catweasel); break; case 'G': sscanf(&argv[c][2], "%f", &basepitch); break; } } else { char startpath[MAX_PATHNAME]; strcpy(songfilename, argv[c]); for (d = strlen(argv[c])-1; d >= 0; d--) { if ((argv[c][d] == '/') || (argv[c][d] == '\\')) { strcpy(startpath, argv[c]); startpath[d+1] = 0; chdir(startpath); initpaths(); strcpy(songfilename, &argv[c][d+1]); break; } } } } // Validate parameters sidmodel &= 1; adparam &= 0xffff; zeropageadr &= 0xff; playeradr &= 0xff00; sidaddress &= 0xffff; if (!stepsize) stepsize = 4; if (multiplier > 16) multiplier = 16; if (keypreset > 2) keypreset = 0; if ((finevibrato == 1) && (multiplier < 2)) usefinevib = 1; if (finevibrato > 1) usefinevib = 1; if (optimizepulse > 1) optimizepulse = 1; if (optimizerealtime > 1) optimizerealtime = 1; if (residdelay > 63) residdelay = 63; if (customclockrate < 100) customclockrate = 0; // Calculate frequencytable if necessary if (basepitch < 0.0f) basepitch = 0.0f; if (basepitch > 0.0f) calculatefreqtable(); // Set screenmode if (!initscreen()) return 1; // Reset channels/song initchannels(); clearsong(1,1,1,1,1); // Init sound if (!sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate)) { printtextc(MAX_ROWS/2-1,15,"Sound init failed. Press any key to run without sound (notice that song timer won't start)"); waitkeynoupdate(); } // Load song if applicable if (strlen(songfilename)) loadsong(); // Start editor mainloop printmainscreen(); while (!exitprogram) { waitkeymouse(); docommand(); } // Shutdown sound output now sound_uninit(); // Save configuration #ifndef __WIN32__ #ifdef __amigaos__ strcpy(filename, "PROGDIR:goattrk2.cfg"); #else strcpy(filename, getenv("HOME")); strcat(filename, "/.goattrk"); mkdir(filename, S_IRUSR | S_IWUSR | S_IXUSR); strcat(filename, "/goattrk2.cfg"); #endif #endif configfile = fopen(filename, "wt"); if (configfile) { fprintf(configfile, ";------------------------------------------------------------------------------\n" ";GT2 config file. Rows starting with ; are comments. Hexadecimal parameters are\n" ";to be preceded with $ and decimal parameters with nothing. \n" ";------------------------------------------------------------------------------\n" "\n" ";reSID buffer length (in milliseconds)\n%d\n\n" ";reSID mixing rate (in Hz)\n%d\n\n" ";Hardsid device number (0 = off)\n%d\n\n" ";reSID model (0 = 6581, 1 = 8580)\n%d\n\n" ";Timing mode (0 = PAL, 1 = NTSC)\n%d\n\n" ";Packer/relocator fileformat (0 = SID, 1 = PRG, 2 = BIN)\n%d\n\n" ";Packer/relocator player address\n$%04x\n\n" ";Packer/relocator zeropage baseaddress\n$%02x\n\n" ";Packer/relocator player type (0 = standard ... 3 = minimal)\n%d\n\n" ";Key entry mode (0 = Protracker, 1 = DMC)\n%d\n\n" ";Pattern highlight step size\n%d\n\n" ";Speed multiplier (0 = 25Hz, 1 = 1X, 2 = 2X etc.)\n%d\n\n" ";Use CatWeasel SID (0 = off, 1 = on)\n%d\n\n" ";Hardrestart ADSR parameter\n$%04x\n\n" ";reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on)\n%d\n\n" ";Hexadecimal pattern display (0 = off, 1 = on)\n%d\n\n" ";SID baseaddress\n$%04x\n\n" ";Finevibrato mode (0 = off, 1 = on)\n%d\n\n" ";Pulseskipping (0 = off, 1 = on)\n%d\n\n" ";Realtime effect skipping (0 = off, 1 = on)\n%d\n\n" ";Random reSID write delay in cycles (0 = off)\n%d\n\n" ";Custom SID clock cycles per second (0 = use PAL/NTSC default)\n%d\n\n" ";HardSID interactive mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n" ";HardSID playback mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n" ";reSID-fp distortion rate\n%f\n\n" ";reSID-fp distortion point\n%f\n\n" ";reSID-fp distortion CF threshold\n%f\n\n" ";reSID-fp type 3 base resistance\n%f\n\n" ";reSID-fp type 3 base offset\n%f\n\n" ";reSID-fp type 3 base steepness\n%f\n\n" ";reSID-fp type 3 minimum FET resistance\n%f\n\n" ";reSID-fp type 4 k\n%f\n\n" ";reSID-fp type 4 b\n%f\n\n" ";reSID-fp voice nonlinearity\n%f\n\n" ";Window type (0 = window, 1 = fullscreen)\n%d\n\n" ";Base pitch of A-4 in Hz (0 = use default frequencytable)\n%f\n\n", b, mr, hardsid, sidmodel, ntsc, fileformat, playeradr, zeropageadr, playerversion, keypreset, stepsize, multiplier, catweasel, adparam, interpolate, patternhex, sidaddress, finevibrato, optimizepulse, optimizerealtime, residdelay, customclockrate, hardsidbufinteractive, hardsidbufplayback, filterparams.distortionrate, filterparams.distortionpoint, filterparams.distortioncfthreshold, filterparams.type3baseresistance, filterparams.type3offset, filterparams.type3steepness, filterparams.type3minimumfetresistance, filterparams.type4k, filterparams.type4b, filterparams.voicenonlinearity, win_fullscreen, basepitch); fclose(configfile); } // Exit return 0; } void waitkey(void) { for (;;) { displayupdate(); getkey(); if ((rawkey) || (key)) break; if (win_quitted) break; } converthex(); } void waitkeymouse(void) { for (;;) { displayupdate(); getkey(); if ((rawkey) || (key)) break; if (win_quitted) break; if (mouseb) break; } converthex(); } void waitkeymousenoupdate(void) { for (;;) { fliptoscreen(); getkey(); if ((rawkey) || (key)) break; if (win_quitted) break; if (mouseb) break; } converthex(); } void waitkeynoupdate(void) { for (;;) { fliptoscreen(); getkey(); if ((rawkey) || (key)) break; if ((mouseb) && (!prevmouseb)) break; if (win_quitted) break; } } void converthex() { int c; hexnybble = -1; for (c = 0; c < 16; c++) { if (tolower(key) == hexkeytbl[c]) { if (c >= 10) { if (!shiftpressed) hexnybble = c; } else { hexnybble = c; } } } } void docommand(void) { // "GUI" operation :) mousecommands(); // Mode-specific commands switch(editmode) { case EDIT_ORDERLIST: orderlistcommands(); break; case EDIT_INSTRUMENT: instrumentcommands(); break; case EDIT_TABLES: tablecommands(); break; case EDIT_PATTERN: patterncommands(); break; case EDIT_NAMES: namecommands(); break; } // General commands generalcommands(); } void mousecommands(void) { int c; if (!mouseb) return; // Pattern editpos & pattern number selection for (c = 0; c < MAX_CHN; c++) { if ((mousey == 2) && (mousex >= 13 + c*15) && (mousex <= 14 + c*15)) { if ((!prevmouseb) || (mouseheld > HOLDDELAY)) { if (mouseb & MOUSEB_LEFT) { epchn = c; nextpattern(); } if (mouseb & MOUSEB_RIGHT) { epchn = c; prevpattern(); } } } else { if ((mousey >= 2) && (mousey <= 34) && (mousex >= 6 + c*15) && (mousex <= 14 + c*15)) { int x = mousex-6-c*15; int newpos = mousey-3+epview; if (newpos < 0) newpos = 0; if (newpos > pattlen[epnum[epchn]]) newpos = pattlen[epnum[epchn]]; editmode = EDIT_PATTERN; if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb)) { if ((epmarkchn != c) || (newpos != epmarkend)) { epmarkchn = c; epmarkstart = epmarkend = newpos; } } if (mouseb & MOUSEB_LEFT) { epchn = c; if (x < 4) epcolumn = 0; if (x >= 4) epcolumn = x-3; } if (!prevmouseb) { if (mouseb & MOUSEB_LEFT) eppos = newpos; } else { if (mouseb & MOUSEB_LEFT) { if (mousey == 2) eppos--; if (mousey == 34) eppos++; } } if (eppos < 0) eppos = 0; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; if (mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) epmarkend = newpos; } } } // Song editpos & songnumber selection if ((mousey >= 3) && (mousey <= 8) && (mousex >= 40+10)) { int newpos = esview + (mousex-44-10) / 3; int newcolumn = (mousex-44-10) % 3; int newchn = mousey - 3; if (newcolumn < 0) newcolumn = 0; if (newcolumn > 1) newcolumn = 1; if (newpos < 0) { newpos = 0; newcolumn = 0; } if (newpos == songlen[esnum][eschn]) { newpos++; newcolumn = 0; } if (newpos > songlen[esnum][eschn]+1) { newpos = songlen[esnum][eschn] + 1; newcolumn = 1; } editmode = EDIT_ORDERLIST; if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb) && (newpos < songlen[esnum][eschn])) { if ((esmarkchn != newchn) || (newpos != esmarkend)) { esmarkchn = newchn; esmarkstart = esmarkend = newpos; } } if (mouseb & MOUSEB_LEFT) { eschn = newchn; eseditpos = newpos; escolumn = newcolumn; } if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (newpos < songlen[esnum][eschn])) esmarkend = newpos; } if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 2) && (mousex >= 63+10) && (mousex <= 64+10)) { if (mouseb & MOUSEB_LEFT) nextsong(); if (mouseb & MOUSEB_RIGHT) prevsong(); } // Instrument editpos & instrument number selection if ((mousey >= 8) && (mousey <= 12) && (mousex >= 56+10) && (mousex <= 57+10)) { editmode = EDIT_INSTRUMENT; eipos = mousey-8; eicolumn = mousex-56-10; } if ((mousey >= 8) && (mousey <= 11) && (mousex >= 76+10) && (mousex <= 77+10)) { editmode = EDIT_INSTRUMENT; eipos = mousey-8+5; eicolumn = mousex-76-10; } if ((mousey == 7) && (mousex >= 60+10)) { editmode = EDIT_INSTRUMENT; eipos = 9; } if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 7) && (mousex >= 56+10) && (mousex <= 57+10)) { if (mouseb & MOUSEB_LEFT) nextinstr(); if (mouseb & MOUSEB_RIGHT) previnstr(); } // Table editpos for (c = 0; c < MAX_TABLES; c++) { if ((mousey >= 14) && (mousey <= 30) && (mousex >= 43+10+c*10) && (mousex <= 47+10+c*10)) { int newpos = mousey-15+etview[etnum]; if (newpos < 0) newpos = 0; if (newpos >= MAX_TABLELEN) newpos = MAX_TABLELEN-1; editmode = EDIT_TABLES; if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb)) { if ((etmarknum != etnum) || (newpos != etmarkend)) { etmarknum = c; etmarkstart = etmarkend = newpos; } } if (mouseb & MOUSEB_LEFT) { etnum = c; etpos = mousey-15+etview[etnum]; etcolumn = mousex-43-10-c*10; } if (etcolumn >= 2) etcolumn--; if (etpos < 0) etpos = 0; if (etpos > MAX_TABLELEN-1) etpos = MAX_TABLELEN-1; if (mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) etmarkend = newpos; } } // Name editpos if ((mousey >= 31) && (mousey <= 33) && (mousex >= 47+10)) { editmode = EDIT_NAMES; enpos = mousey - 31; } // Status panel if ((!prevmouseb) && (mousex == 7) && (mousey == 23+3+9)) { if (mouseb & (MOUSEB_LEFT)) if (epoctave < 7) epoctave++; if (mouseb & (MOUSEB_RIGHT)) if (epoctave > 0) epoctave--; } if ((!prevmouseb) && (mousex <= 7) && (mousey == 24+3+9)) { recordmode ^= 1; } for (c = 0; c < MAX_CHN; c++) { if ((!prevmouseb) && (mousey >= 23+3+9) && (mousex >= 80 + 7*c) && (mousex <= 85 + 7*c)) mutechannel(c); } // Titlebar actions if (!menu) { if ((mousey == 0) && (!prevmouseb) && (mouseb == MOUSEB_LEFT)) { if ((mousex >= 40+10) && (mousex <= 41+10)) { usefinevib ^= 1; } if ((mousex >= 43+10) && (mousex <= 44+10)) { optimizepulse ^= 1; } if ((mousex >= 46+10) && (mousex <= 47+10)) { optimizerealtime ^= 1; } if ((mousex >= 49+10) && (mousex <= 52+10)) { ntsc ^= 1; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } if ((mousex >= 54+10) && (mousex <= 57+10)) { sidmodel ^= 1; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } if ((mousex >= 62+10) && (mousex <= 65+10)) editadsr(); if ((mousex >= 67+10) && (mousex <= 68+10)) prevmultiplier(); if ((mousex >= 69+10) && (mousex <= 70+10)) nextmultiplier(); } } else { if ((!mousey) && (mouseb & MOUSEB_LEFT) && (!(prevmouseb & MOUSEB_LEFT))) { if ((mousex >= 0) && (mousex <= 5)) { initsong(esnum, PLAY_BEGINNING); followplay = shiftpressed; } if ((mousex >= 7) && (mousex <= 15)) { initsong(esnum, PLAY_POS); followplay = shiftpressed; } if ((mousex >= 17) && (mousex <= 26)) { initsong(esnum, PLAY_PATTERN); followplay = shiftpressed; } if ((mousex >= 28) && (mousex <= 33)) stopsong(); if ((mousex >= 35) && (mousex <= 40)) load(); if ((mousex >= 42) && (mousex <= 47)) save(); if ((mousex >= 49) && (mousex <= 57)) relocator(); if ((mousex >= 59) && (mousex <= 64)) onlinehelp(0,0); if ((mousex >= 66) && (mousex <= 72)) clear(); if ((mousex >= 74) && (mousex <= 79)) quit(); } } } void generalcommands(void) { int c; switch(key) { case '?': case '-': if ((editmode != EDIT_NAMES) && (editmode != EDIT_ORDERLIST)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos == 9))) previnstr(); } break; case '+': case '_': if ((editmode != EDIT_NAMES) && (editmode != EDIT_ORDERLIST)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) nextinstr(); } break; case '*': if (editmode != EDIT_NAMES) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave < 7) epoctave++; } } break; case '/': case '\'': if (editmode != EDIT_NAMES) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave > 0) epoctave--; } } break; case '<': if (((editmode == EDIT_INSTRUMENT) && (eipos != 9)) || (editmode == EDIT_TABLES)) previnstr(); break; case '>': if (((editmode == EDIT_INSTRUMENT) && (eipos != 9)) || (editmode == EDIT_TABLES)) nextinstr(); break; case ';': for (c = 0; c < MAX_CHN; c++) { if (espos[c]) espos[c]--; if (espos[c] < esview) { esview = espos[c]; eseditpos = espos[c]; } } updateviewtopos(); rewindsong(); break; case ':': for (c = 0; c < MAX_CHN; c++) { if (espos[c] < songlen[esnum][c]-1) espos[c]++; if (espos[c] - esview >= VISIBLEORDERLIST) { esview = espos[c] - VISIBLEORDERLIST + 1; eseditpos = espos[c]; } } updateviewtopos(); rewindsong(); break; } if (win_quitted) exitprogram = 1; switch(rawkey) { case KEY_ESC: if (!shiftpressed) quit(); else clear(); break; case KEY_KPMULTIPLY: if ((editmode != EDIT_NAMES) && (!key)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave < 7) epoctave++; } } break; case KEY_KPDIVIDE: if ((editmode != EDIT_NAMES) && (!key)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave > 0) epoctave--; } } break; case KEY_F12: onlinehelp(0, shiftpressed); break; case KEY_TAB: if (!shiftpressed) editmode++; else editmode--; if (editmode > EDIT_NAMES) editmode = EDIT_PATTERN; if (editmode < EDIT_PATTERN) editmode = EDIT_NAMES; break; case KEY_F1: initsong(esnum, PLAY_BEGINNING); followplay = shiftpressed; break; case KEY_F2: initsong(esnum, PLAY_POS); followplay = shiftpressed; break; case KEY_F3: initsong(esnum, PLAY_PATTERN); followplay = shiftpressed; break; case KEY_F4: if (shiftpressed) mutechannel(epchn); else stopsong(); break; case KEY_F5: if (!shiftpressed) editmode = EDIT_PATTERN; else prevmultiplier(); break; case KEY_F6: if (!shiftpressed) editmode = EDIT_ORDERLIST; else nextmultiplier(); break; case KEY_F7: if (!shiftpressed) { if (editmode == EDIT_INSTRUMENT) editmode = EDIT_TABLES; else editmode = EDIT_INSTRUMENT; } else editadsr(); break; case KEY_F8: if (!shiftpressed) editmode = EDIT_NAMES; else { sidmodel ^= 1; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } break; case KEY_F9: relocator(); break; case KEY_F10: load(); break; case KEY_F11: save(); break; } } void load(void) { if ((editmode != EDIT_INSTRUMENT) && (editmode != EDIT_TABLES)) { if (fileselector(songfilename, songpath, songfilter, "LOAD SONG", 0)) loadsong(); } else { if (einum) { if (fileselector(instrfilename, instrpath, instrfilter, "LOAD INSTRUMENT", 0)) loadinstrument(); } } key = 0; rawkey = 0; } void save(void) { if ((editmode != EDIT_INSTRUMENT) && (editmode != EDIT_TABLES)) { int done = 0; // Repeat until quit or save successful while (!done) { if (strlen(loadedsongfilename)) strcpy(songfilename, loadedsongfilename); if (fileselector(songfilename, songpath, songfilter, "SAVE SONG", 3)) done = savesong(); else done = 1; } } else { if (einum) { int done = 0; int useinstrname = 0; char tempfilename[MAX_FILENAME]; // Repeat until quit or save successful while (!done) { if ((!strlen(instrfilename)) && (strlen(instr[einum].name))) { useinstrname = 1; strcpy(instrfilename, instr[einum].name); strcat(instrfilename, ".ins"); strcpy(tempfilename, instrfilename); } if (fileselector(instrfilename, instrpath, instrfilter, "SAVE INSTRUMENT", 3)) done = saveinstrument(); else done = 1; if (useinstrname) { if (!strcmp(tempfilename, instrfilename)) memset(instrfilename, 0, sizeof instrfilename); } } } } key = 0; rawkey = 0; } void quit(void) { if ((!shiftpressed) || (mouseb)) { printtextcp(49, 36, 15, "Really Quit (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) exitprogram = 1; } key = 0; rawkey = 0; } void clear(void) { int cs = 0; int cp = 0; int ci = 0; int ct = 0; int cn = 0; printtextcp(49, 36, 15, "Optimize everything (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) { optimizeeverything(1, 1); key = 0; rawkey = 0; return; } printtextcp(49, 36, 15, "Clear orderlists (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) cs = 1; printtextcp(49, 36, 15, "Clear patterns (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) cp = 1; printtextcp(49, 36, 15, "Clear instruments (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) ci = 1; printtextcp(49, 36, 15, "Clear tables (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) ct = 1; printtextcp(49, 36, 15, "Clear songname (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) cn = 1; if (cp == 1) { int selectdone = 0; int olddpl = defaultpatternlength; printtext(40, 36, 15,"Pattern length:"); while (!selectdone) { sprintf(textbuffer, "%02d ", defaultpatternlength); printtext(55, 36, 15, textbuffer); waitkey(); switch(rawkey) { case KEY_LEFT: defaultpatternlength -= 7; case KEY_DOWN: defaultpatternlength--; if (defaultpatternlength < 1) defaultpatternlength = 1; break; case KEY_RIGHT: defaultpatternlength += 7; case KEY_UP: defaultpatternlength++; if (defaultpatternlength > MAX_PATTROWS) defaultpatternlength = MAX_PATTROWS; break; case KEY_ESC: defaultpatternlength = olddpl; selectdone = 1; break; case KEY_ENTER: selectdone = 1; break; } } printblank(20, 36, 58); } if (cs | cp | ci | ct | cn) memset(songfilename, 0, sizeof songfilename); clearsong(cs, cp, ci, ct, cn); key = 0; rawkey = 0; } void editadsr(void) { eamode = 1; eacolumn = 0; for (;;) { waitkeymouse(); if (win_quitted) { exitprogram = 1; key = 0; rawkey = 0; return; } if (hexnybble >= 0) { switch(eacolumn) { case 0: adparam &= 0x0fff; adparam |= hexnybble << 12; break; case 1: adparam &= 0xf0ff; adparam |= hexnybble << 8; break; case 2: adparam &= 0xff0f; adparam |= hexnybble << 4; break; case 3: adparam &= 0xfff0; adparam |= hexnybble; break; } eacolumn++; } switch(rawkey) { case KEY_F7: if (!shiftpressed) break; case KEY_ESC: case KEY_ENTER: case KEY_TAB: eamode = 0; key = 0; rawkey = 0; return; case KEY_BACKSPACE: if (!eacolumn) break; case KEY_LEFT: eacolumn--; break; case KEY_RIGHT: eacolumn++; } eacolumn &= 3; if ((mouseb) && (!prevmouseb)) { eamode = 0; return; } } } void getparam(FILE *handle, unsigned *value) { char *configptr; for (;;) { if (feof(handle)) return; fgets(configbuf, MAX_PATHNAME, handle); if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break; } configptr = configbuf; if (*configptr == '$') { *value = 0; configptr++; for (;;) { char c = tolower(*configptr++); int h = -1; if ((c >= 'a') && (c <= 'f')) h = c - 'a' + 10; if ((c >= '0') && (c <= '9')) h = c - '0'; if (h >= 0) { *value *= 16; *value += h; } else break; } } else { *value = 0; for (;;) { char c = tolower(*configptr++); int d = -1; if ((c >= '0') && (c <= '9')) d = c - '0'; if (d >= 0) { *value *= 10; *value += d; } else break; } } } void getfloatparam(FILE *handle, float *value) { char *configptr; for (;;) { if (feof(handle)) return; fgets(configbuf, MAX_PATHNAME, handle); if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break; } configptr = configbuf; *value = 0.0f; sscanf(configptr, "%f", value); } void prevmultiplier(void) { if (multiplier > 0) { multiplier--; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } } void nextmultiplier(void) { if (multiplier < 16) { multiplier++; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } } void calculatefreqtable() { double basefreq = (double)basepitch * (16777216.0 / 985248.0) * pow(2.0, 0.25) / 32.0; int c; for (c = 0; c < 8*12 ; c++) { double note = c; double freq = basefreq * pow(2.0, note/12.0); int intfreq = freq + 0.5; if (intfreq > 0xffff) intfreq = 0xffff; freqtbllo[c] = intfreq & 0xff; freqtblhi[c] = intfreq >> 8; } } goattracker-2.72/src/gsound.c0000644000000000000000000003100611460110362014674 0ustar rootroot// // GOATTRACKER sound routines // #define GSOUND_C #ifdef __WIN32__ #include #endif #include "goattrk2.h" // General / reSID output int playspeed; int usehardsid = 0; int usecatweasel = 0; int initted = 0; int firsttimeinit = 1; unsigned framerate = PALFRAMERATE; Sint16 *buffer = NULL; FILE *writehandle = NULL; void sound_playrout(void); void sound_mixer(Sint32 *dest, unsigned samples); Uint32 sound_timer(Uint32 interval); #ifdef __WIN32__ // Win32 HardSID output typedef void (CALLBACK* lpWriteToHardSID)(Uint8 DeviceID, Uint8 SID_reg, Uint8 Data); typedef Uint8 (CALLBACK* lpReadFromHardSID)(Uint8 DeviceID, Uint8 SID_reg); typedef void (CALLBACK* lpInitHardSID_Mapper)(void); typedef void (CALLBACK* lpMuteHardSID_Line)(int Mute); typedef void (CALLBACK* lpHardSID_Delay)(Uint8 DeviceID, Uint16 Cycles); typedef void (CALLBACK* lpHardSID_Write)(Uint8 DeviceID, Uint16 Cycles, Uint8 SID_reg, Uint8 Data); typedef void (CALLBACK* lpHardSID_Flush)(Uint8 DeviceID); typedef void (CALLBACK* lpHardSID_SoftFlush)(Uint8 DeviceID); typedef boolean (CALLBACK* lpHardSID_Lock)(Uint8 DeviceID); lpWriteToHardSID WriteToHardSID = NULL; lpReadFromHardSID ReadFromHardSID = NULL; lpInitHardSID_Mapper InitHardSID_Mapper = NULL; lpMuteHardSID_Line MuteHardSID_Line = NULL; lpHardSID_Delay HardSID_Delay = NULL; lpHardSID_Write HardSID_Write = NULL; lpHardSID_Flush HardSID_Flush = NULL; lpHardSID_SoftFlush HardSID_SoftFlush = NULL; lpHardSID_Lock HardSID_Lock = NULL; HINSTANCE hardsiddll = 0; int dll_initialized = FALSE; // Cycle-exact HardSID support int cycleexacthardsid = FALSE; SDL_Thread* playerthread = NULL; SDL_mutex* flushmutex = NULL; volatile int runplayerthread = FALSE; volatile int flushplayerthread = FALSE; volatile int suspendplayroutine = FALSE; int sound_thread(void *userdata); void InitHardDLL(void); // Win32 CatWeasel MK3 PCI output #define SID_SID_PEEK_POKE CTL_CODE(FILE_DEVICE_SOUND,0x0800UL + 1,METHOD_BUFFERED,FILE_ANY_ACCESS) HANDLE catweaselhandle; #else // Unix HardSID & CatWeasel output int hardsidfd = -1; int catweaselfd = -1; #endif int sound_init(unsigned b, unsigned mr, unsigned writer, unsigned hardsid, unsigned m, unsigned ntsc, unsigned multiplier, unsigned catweasel, unsigned interpolate, unsigned customclockrate) { int c; #ifdef __WIN32__ if (!flushmutex) flushmutex = SDL_CreateMutex(); #endif sound_uninit(); if (multiplier) { if (ntsc) { framerate = NTSCFRAMERATE * multiplier; snd_bpmtempo = 150 * multiplier; } else { framerate = PALFRAMERATE * multiplier; snd_bpmtempo = 125 * multiplier; } } else { if (ntsc) { framerate = NTSCFRAMERATE / 2; snd_bpmtempo = 150 / 2; } else { framerate = PALFRAMERATE / 2; snd_bpmtempo = 125 / 2; } } if (hardsid) { #ifdef __WIN32__ InitHardDLL(); if (dll_initialized) { usehardsid = hardsid; if (cycleexacthardsid) { HardSID_Lock(usehardsid-1); HardSID_Flush(usehardsid-1); HardSID_Write(usehardsid-1, SIDWRITEDELAY, 0, 0x00); Sleep(300); } for (c = 0; c < NUMSIDREGS; c++) { sidreg[c] = 0; if (cycleexacthardsid) { HardSID_Write(usehardsid-1, SIDWRITEDELAY, c, 0x00); } else { WriteToHardSID(usehardsid-1, c, 0x00); } } if (cycleexacthardsid) { HardSID_SoftFlush(usehardsid-1); } else { MuteHardSID_Line(FALSE); } } else return 0; if (!cycleexacthardsid) { SDL_SetTimer(1000 / framerate, sound_timer); } else { runplayerthread = TRUE; playerthread = SDL_CreateThread(sound_thread, NULL); if (!playerthread) return 0; } #else char filename[80]; sprintf(filename, "/dev/sid%d", hardsid-1); hardsidfd = open(filename, O_WRONLY, S_IREAD|S_IWRITE); if (hardsidfd >= 0) { usehardsid = hardsid; for (c = 0; c < NUMSIDREGS; c++) { Uint32 dataword = c << 8; write(hardsidfd, &dataword, 4); } } else return 0; SDL_SetTimer(1000 / framerate, sound_timer); #endif goto SOUNDOK; } if (catweasel) { #ifdef __WIN32__ catweaselhandle = CreateFile("\\\\.\\SID6581_1", GENERIC_READ, FILE_SHARE_WRITE|FILE_SHARE_READ, 0L, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0L); if (catweaselhandle == INVALID_HANDLE_VALUE) return 0; #else catweaselfd = open("/dev/sid", O_WRONLY); if (catweaselfd < 0) catweaselfd = open("/dev/misc/sid", O_WRONLY); if (catweaselfd < 0) return 0; #ifndef __amigaos__ if (ntsc) ioctl(catweaselfd, CWSID_IOCTL_NTSC); else ioctl(catweaselfd, CWSID_IOCTL_PAL); #endif #endif usecatweasel = 1; SDL_SetTimer(1000 / framerate, sound_timer); goto SOUNDOK; } if (!buffer) buffer = malloc(MIXBUFFERSIZE * sizeof(Sint16)); if (!buffer) return 0; if (writer) writehandle = fopen("sidaudio.raw", "wb"); playspeed = mr; if (playspeed < MINMIXRATE) playspeed = MINMIXRATE; if (playspeed > MAXMIXRATE) playspeed = MAXMIXRATE; if (b < MINBUF) b = MINBUF; if (b > MAXBUF) b = MAXBUF; if (firsttimeinit) { if (!snd_init(mr, SIXTEENBIT|MONO, b, 1, 0)) return 0; firsttimeinit = 0; } playspeed = snd_mixrate; sid_init(playspeed, m, ntsc, interpolate & 1, customclockrate, interpolate >> 1); snd_player = &sound_playrout; snd_setcustommixer(sound_mixer); SOUNDOK: initted = 1; return 1; } void sound_uninit(void) { int c; if (!initted) return; initted = 0; // Apparently a delay is needed to make sure the sound timer thread is // not mixing stuff anymore, and we can safely delete related structures SDL_Delay(50); if (usehardsid || usecatweasel) { #ifdef __WIN32__ if (!playerthread) { SDL_SetTimer(0, NULL); } else { runplayerthread = FALSE; SDL_WaitThread(playerthread, NULL); playerthread = NULL; } #else SDL_SetTimer(0, NULL); #endif } else { snd_setcustommixer(NULL); snd_player = NULL; } if (writehandle) { fclose(writehandle); writehandle = NULL; } if (buffer) { free(buffer); buffer = NULL; } if (usehardsid) { #ifdef __WIN32__ for (c = 0; c < NUMSIDREGS; c++) { if (cycleexacthardsid) { HardSID_Write(usehardsid-1, SIDWRITEDELAY, c, 0x00); } else { WriteToHardSID(usehardsid-1, c, 0x00); } } MuteHardSID_Line(TRUE); #else if (hardsidfd >= 0) { for (c = 0; c < NUMSIDREGS; c++) { Uint32 dataword = c << 8; write(hardsidfd, &dataword, 4); } close(hardsidfd); hardsidfd = -1; } #endif } if (usecatweasel) { #ifdef __WIN32__ DWORD w; unsigned char buf[NUMSIDREGS * 2]; for (w = 0; w < NUMSIDREGS; w++) { buf[w*2] = 0x18 - w; buf[w*2+1] = 0; } DeviceIoControl(catweaselhandle, SID_SID_PEEK_POKE, buf, sizeof(buf), 0L, 0UL, &w, 0L); CloseHandle(catweaselhandle); catweaselhandle = INVALID_HANDLE_VALUE; #else if (catweaselfd >= 0) { unsigned char buf[NUMSIDREGS]; memset(buf, 0, sizeof(buf)); lseek(catweaselfd, 0, SEEK_SET); write(catweaselfd, buf, sizeof(buf)); close(catweaselfd); catweaselfd = -1; } #endif } } void sound_suspend(void) { #ifdef __WIN32__ SDL_LockMutex(flushmutex); suspendplayroutine = TRUE; SDL_UnlockMutex(flushmutex); #endif } void sound_flush(void) { #ifdef __WIN32__ SDL_LockMutex(flushmutex); flushplayerthread = TRUE; SDL_UnlockMutex(flushmutex); #endif } Uint32 sound_timer(Uint32 interval) { if (!initted) return interval; sound_playrout(); return interval; } #ifdef __WIN32__ int sound_thread(void *userdata) { unsigned long flush_cycles_interactive = hardsidbufinteractive * 1000; /* 0 = flush off for interactive mode*/ unsigned long flush_cycles_playback = hardsidbufplayback * 1000; /* 0 = flush off for playback mode*/ unsigned long cycles_after_flush = 0; boolean interactive; while (runplayerthread) { unsigned cycles = 1000000 / framerate; // HardSID should be clocked at 1MHz int c; if (flush_cycles_interactive > 0 || flush_cycles_playback > 0) { cycles_after_flush += cycles; } // Do flush if starting playback, stopping playback, starting an interactive note etc. if (flushplayerthread) { SDL_LockMutex(flushmutex); if (HardSID_Flush) { HardSID_Flush(usehardsid-1); } // Can clear player suspend now (if set) suspendplayroutine = FALSE; flushplayerthread = FALSE; SDL_UnlockMutex(flushmutex); SDL_Delay(0); } if (!suspendplayroutine) playroutine(); interactive = !(boolean)recordmode /* jam mode */ || !(boolean)isplaying(); for (c = 0; c < NUMSIDREGS; c++) { unsigned o = sid_getorder(c); // Extra delay before loading the waveform (and mt_chngate,x) if ((o == 4) || (o == 11) || (o == 18)) { HardSID_Write(usehardsid-1, SIDWRITEDELAY+SIDWAVEDELAY, o, sidreg[o]); cycles -= SIDWRITEDELAY+SIDWAVEDELAY; } else { HardSID_Write(usehardsid-1, SIDWRITEDELAY, o, sidreg[o]); cycles -= SIDWRITEDELAY; } } // Now wait the rest of frame while (cycles) { unsigned runnow = cycles; if (runnow > 65535) runnow = 65535; HardSID_Delay(usehardsid-1, runnow); cycles -= runnow; } if ((flush_cycles_interactive>0 && interactive && cycles_after_flush>=flush_cycles_interactive) || (flush_cycles_playback>0 && !interactive && cycles_after_flush>=flush_cycles_playback)) { if (HardSID_SoftFlush) HardSID_SoftFlush(usehardsid-1); cycles_after_flush = 0; } } unsigned r; for (r = 0; r < NUMSIDREGS; r++) { HardSID_Write(usehardsid-1, SIDWRITEDELAY, r, 0); } if (HardSID_SoftFlush) HardSID_SoftFlush(usehardsid-1); return 0; } #endif void sound_playrout(void) { int c; playroutine(); if (usehardsid) { #ifdef __WIN32__ for (c = 0; c < NUMSIDREGS; c++) { unsigned o = sid_getorder(c); if (cycleexacthardsid) { HardSID_Write(usehardsid-1, SIDWRITEDELAY, o, sidreg[o]); } else { WriteToHardSID(usehardsid-1, o, sidreg[o]); } } #else for (c = 0; c < NUMSIDREGS; c++) { unsigned o = sid_getorder(c); Uint32 dataword = (o << 8) | sidreg[o]; write(hardsidfd, &dataword, 4); } #endif } else if (usecatweasel) { #ifdef __WIN32__ DWORD w; unsigned char buf[NUMSIDREGS * 2]; for(w = 0; w < NUMSIDREGS; w++) { unsigned o = sid_getorder(w); buf[w*2] = o; buf[w*2+1] = sidreg[o]; } DeviceIoControl(catweaselhandle, SID_SID_PEEK_POKE, buf, sizeof(buf), 0L, 0UL, &w, 0L); #else for (c = 0; c < NUMSIDREGS; c++) { unsigned o = sid_getorder(c); lseek(catweaselfd, o, SEEK_SET); write(catweaselfd, &sidreg[o], 1); } #endif } } void sound_mixer(Sint32 *dest, unsigned samples) { int c; if (!initted) return; if (samples > MIXBUFFERSIZE) return; if (!buffer) return; sid_fillbuffer(buffer, samples); if (writehandle) fwrite(buffer, samples * sizeof(Uint16), 1, writehandle); for (c = 0; c < samples; c++) dest[c] = buffer[c]; } #ifdef __WIN32__ void InitHardDLL() { if (!(hardsiddll=LoadLibrary("HARDSID.DLL"))) return; WriteToHardSID = (lpWriteToHardSID) GetProcAddress(hardsiddll, "WriteToHardSID"); ReadFromHardSID = (lpReadFromHardSID) GetProcAddress(hardsiddll, "ReadFromHardSID"); InitHardSID_Mapper = (lpInitHardSID_Mapper) GetProcAddress(hardsiddll, "InitHardSID_Mapper"); MuteHardSID_Line = (lpMuteHardSID_Line) GetProcAddress(hardsiddll, "MuteHardSID_Line"); if (!WriteToHardSID) return; // Try to get cycle-exact interface HardSID_Delay = (lpHardSID_Delay) GetProcAddress(hardsiddll, "HardSID_Delay"); HardSID_Write = (lpHardSID_Write) GetProcAddress(hardsiddll, "HardSID_Write"); HardSID_Flush = (lpHardSID_Flush) GetProcAddress(hardsiddll, "HardSID_Flush"); HardSID_SoftFlush = (lpHardSID_SoftFlush) GetProcAddress(hardsiddll, "HardSID_SoftFlush"); HardSID_Lock = (lpHardSID_Lock) GetProcAddress(hardsiddll, "HardSID_Lock"); if ((HardSID_Delay) && (HardSID_Write) && (HardSID_Flush) && (HardSID_SoftFlush) && (HardSID_Lock)) cycleexacthardsid = TRUE; InitHardSID_Mapper(); dll_initialized = TRUE; } #endif goattracker-2.72/src/gconsole.h0000644000000000000000000000154710774364076015246 0ustar rootroot#ifndef GCONSOLE_H #define GCONSOLE_H #define MAX_COLUMNS 100 #define MAX_ROWS 37 #define HOLDDELAY 24 #define DOUBLECLICKDELAY 15 #define MOUSESIZEX 11 #define MOUSESIZEY 20 int initscreen(void); void closescreen(void); void clearscreen(void); void fliptoscreen(void); void printtext(int x, int y, int color, const char *text); void printtextc(int y, int color, const char *text); void printtextcp(int cp, int y, int color, const char *text); void printblank(int x, int y, int length); void printblankc(int x, int y, int color, int length); void drawbox(int x, int y, int color, int sx, int sy); void printbg(int x, int y, int color, int length); void getkey(void); #ifndef GCONSOLE_C extern int key, rawkey, shiftpressed, cursorflashdelay; extern int mouseb, prevmouseb; extern int mouseheld; extern int mousex, mousey; #endif #endif goattracker-2.72/src/makefile.win0000644000000000000000000000210211460133166015527 0ustar rootroot# # Win32 makefile # PREFIX=../win32/ SUFFIX=.exe LIBS=-lmingw32 -lSDLmain -lSDL -mwindows -static-libstdc++ -static-libgcc RM= -del include makefile.common $(PREFIX)goattrk2$(SUFFIX): goatdata.o goattrk2.o gsong.o gorder.o gpattern.o ginstr.o gtable.o gplay.o gdisplay.o \ gfile.o greloc.o ghelp.o gsound.o gconsole.o gsid.o \ resid/envelope.o resid/extfilt.o resid/filter.o resid/pot.o resid/sid.o resid/wave.o resid/wave6581__ST.o \ resid/wave6581_P_T.o resid/wave6581_PS_.o resid/wave6581_PST.o resid/wave8580__ST.o resid/wave8580_P_T.o \ resid/wave8580_PS_.o resid/wave8580_PST.o resid/voice.o \ resid-fp/envelopefp.o resid-fp/extfiltfp.o resid-fp/filterfp.o resid-fp/potfp.o resid-fp/sidfp.o \ resid-fp/wavefp.o resid-fp/voicefp.o \ asm/asmtab.o asm/chnkpool.o asm/expr.o asm/lexyy.o asm/log.o asm/membuf.o asm/membufio.o asm/namedbuf.o asm/parse.o \ asm/pc.o asm/vec.o \ bme/bme_gfx.o bme/bme_snd.o bme/bme_win.o bme/bme_mou.o bme/bme_kbd.o bme/bme_io.o bme/bme_end.o bme/bme.o windres goattrk2.rc goaticon.o $(CXX) -o $@ $^ goaticon.o $(LIBS) strip $@ goattracker-2.72/src/sngspli2.c0000644000000000000000000003330110774364076015162 0ustar rootroot/* * GoatTracker V2.xx pattern splitter */ #include #include #include #include #include "bme_end.h" #include "gcommon.h" #define MAX_SPLITS 16 INSTR instr[MAX_INSTR]; char ident[4]; unsigned char ltable[4][MAX_TABLELEN*2]; unsigned char rtable[4][MAX_TABLELEN*2]; unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; unsigned char destsongorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; unsigned char ordermaptbl[MAX_SONGLEN+2]; unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4]; unsigned char destpattern[MAX_PATT+1][MAX_PATTROWS*4+4]; unsigned char songname[MAX_STR]; unsigned char authorname[MAX_STR]; unsigned char copyrightname[MAX_STR]; int pattlen[MAX_PATT]; int songlen[MAX_SONGS][MAX_CHN]; int destpattlen[MAX_PATT+1]; int destsonglen[MAX_SONGS][MAX_CHN]; int destpattsplits[MAX_PATT+1]; int patternmaptable[MAX_PATT][MAX_SPLITS]; int tables = 0; int dp; int highestusedpattern = 0; int highestusedinstr = 0; int targetlen = 16; int wavelen = 0, pulselen = 0, filtlen = 0; int main(int argc, char **argv); int loadsong(char *name); int savesong(char *name); int processsong(void); void countpatternlengths(void); void countdestpatternlengths(void); void clearsong(void); int gettablelen(int num); int main(int argc, char **argv) { if (argc < 3) { printf("Usage: SNGSPLI2 [length]\n\n" "Splits patterns of the song into smaller patterns with [length] rows,\n" "searching for possible duplicates and probably making the song take less\n" "memory. For safety reasons source & destination cannot be same, because\n" "a splitted song is harder to edit. Always keep the original!\n\n" "Default length is 16.\n"); return 1; } if (!strcmp(argv[1], argv[2])) { printf("ERROR: Source and destination are not allowed to be the same."); return 1; } if (argc >= 4) { sscanf(argv[3], "%u", &targetlen); if (targetlen < 1) targetlen = 1; if (targetlen > MAX_PATTROWS) targetlen = MAX_PATTROWS; } if (!loadsong(argv[1])) { printf("ERROR: Couldn't load source song."); return 1; } if (!processsong()) { return 1; } if (!savesong(argv[2])) { printf("ERROR: Couldn't save destination song."); return 1; } return 0; } int processsong(void) { int c,d,e; int splitsize; int songs; int dsl; dp = 0; // Destination patterns for (c = 0; c <= highestusedpattern; c++) { destpattsplits[c] = 0; splitsize = targetlen; while (pattlen[c] / splitsize > MAX_SPLITS) splitsize *= 2; if (pattlen[c] <= splitsize) splitsize = pattlen[c]; d = 0; while (d < pattlen[c]) { int remain = pattlen[c] - d; int splitfound = 0; // Check existing patterns for matches for (e = 0; e < dp; e++) { if ((destpattlen[e] <= remain) && (destpattlen[e] >= splitsize) && (!memcmp(&pattern[c][d*4], destpattern[e], destpattlen[e]*4))) { patternmaptable[c][destpattsplits[c]] = e; destpattsplits[c]++; d += destpattlen[e]; splitfound = 1; break; } } if (!splitfound) { // If less than 2 splits left, do in one part if (remain < splitsize * 2) { memcpy(destpattern[dp], &pattern[c][d*4], remain*4); destpattern[dp][remain*4] = ENDPATT; destpattern[dp][remain*4+1] = 0; destpattern[dp][remain*4+2] = 0; destpattern[dp][remain*4+3] = 0; destpattlen[dp] = remain; patternmaptable[c][destpattsplits[c]] = dp; destpattsplits[c]++; d += remain; dp++; } else { memcpy(destpattern[dp], &pattern[c][d*4], splitsize*4); destpattern[dp][splitsize*4] = ENDPATT; destpattern[dp][splitsize*4+1] = 0; destpattern[dp][splitsize*4+2] = 0; destpattern[dp][splitsize*4+3] = 0; destpattlen[dp] = splitsize; patternmaptable[c][destpattsplits[c]] = dp; destpattsplits[c]++; d += splitsize; dp++; } } // This should never happen if (destpattsplits[c] >= MAX_SPLITS) { printf("ERROR: Internal error, too many splits!"); return 0; } // This might happen :-) if (dp > MAX_PATT) { printf("ERROR: 255 patterns exceeded!"); return 0; } } } // Now convert all songs // Determine amount of songs to be processed c = 0; for (;;) { if (c == MAX_SONGS) break; if ((!songlen[c][0])|| (!songlen[c][1])|| (!songlen[c][2])) break; c++; } songs = c; for (c = 0; c < songs; c++) { for (d = 0; d < MAX_CHN; d++) { dsl = 0; for (e = 0; e <= songlen[c][d]+1; e++) { int pattnum = songorder[c][d][e]; ordermaptbl[e] = dsl; if (e < songlen[c][d]) { if (pattnum < MAX_PATT) { int f; for (f = 0; f < destpattsplits[pattnum]; f++) { destsongorder[c][d][dsl] = patternmaptable[pattnum][f]; dsl++; if (dsl > MAX_SONGLEN) { printf("ERROR: Orderlist-length of 254 exceeded!"); return 0; } } } else { destsongorder[c][d][dsl] = pattnum; dsl++; if (dsl > MAX_SONGLEN) { printf("ERROR: Orderlist-length of 254 exceeded!"); return 0; } } } else { if (pattnum == LOOPSONG) { destsongorder[c][d][dsl] = pattnum; } else { // Map old orderlist position to new destsongorder[c][d][dsl] = ordermaptbl[pattnum]; } dsl++; } } } } // Everything ok! countdestpatternlengths(); { int destpatttbl = 0, destpatt = 0, destsong = 0; int srcpatttbl = 0, srcpatt = 0, srcsong = 0; for (c = 0; c < MAX_SONGS; c++) { if ((songlen[c][0]) && (songlen[c][1]) && (songlen[c][2])) { for (d = 0; d < MAX_CHN; d++) { srcsong += songlen[c][d]+1; destsong += destsonglen[c][d]+1; } } } for (c = 0; c < highestusedpattern; c++) { srcpatt += pattlen[c]*4 + 4; srcpatttbl += 2; } for (c = 0; c < dp; c++) { destpatt += destpattlen[c]*4 + 4; destpatttbl += 2; } printf("Processing complete. Results:\n\n" " Songdata Patterns Patt.Tbl Total\n" "Before %-8d %-8d %-8d %-8d\n" "After %-8d %-8d %-8d %-8d\n", srcsong,srcpatt,srcpatttbl,srcsong+srcpatt+srcpatttbl, destsong,destpatt,destpatttbl,destsong+destpatt+destpatttbl); } return 1; } int loadsong(char *name) { int c; FILE *srchandle = fopen(name, "rb"); if (srchandle) { fread(ident, 4, 1, srchandle); if (!memcmp(ident, "GTS2", 4)) tables = 3; if (!memcmp(ident, "GTS3", 4)) tables = 4; if (!memcmp(ident, "GTS4", 4)) tables = 4; if (!memcmp(ident, "GTS5", 4)) tables = 4; if (tables) { int d; unsigned char length; unsigned char amount; int loadbytes; clearsong(); // Read infotexts fread(songname, sizeof songname, 1, srchandle); fread(authorname, sizeof authorname, 1, srchandle); fread(copyrightname, sizeof copyrightname, 1, srchandle); // Read songorderlists amount = fread8(srchandle); for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = fread8(srchandle); loadbytes = length; loadbytes++; fread(songorder[d][c], loadbytes, 1, srchandle); } } // Read instruments highestusedinstr = fread8(srchandle); for (c = 1; c <= highestusedinstr; c++) { instr[c].ad = fread8(srchandle); instr[c].sr = fread8(srchandle); instr[c].ptr[WTBL] = fread8(srchandle); instr[c].ptr[PTBL] = fread8(srchandle); instr[c].ptr[FTBL] = fread8(srchandle); instr[c].ptr[STBL] = fread8(srchandle); instr[c].vibdelay = fread8(srchandle); instr[c].gatetimer = fread8(srchandle); instr[c].firstwave = fread8(srchandle); fread(&instr[c].name, MAX_INSTRNAMELEN, 1, srchandle); } // Read tables for (c = 0; c < tables; c++) { loadbytes = fread8(srchandle); fread(ltable[c], loadbytes, 1, srchandle); fread(rtable[c], loadbytes, 1, srchandle); } // Read patterns amount = fread8(srchandle); for (c = 0; c < amount; c++) { length = fread8(srchandle); fread(pattern[c], length*4, 1, srchandle); } countpatternlengths(); fclose(srchandle); return 1; } fclose(srchandle); } return 0; } int savesong(char *name) { FILE *handle; int c; handle = fopen(name, "wb"); if (handle) { int d; unsigned char length; unsigned char amount; int writebytes; fwrite(ident, 4, 1, handle); countdestpatternlengths(); // Write infotexts fwrite(songname, sizeof songname, 1, handle); fwrite(authorname, sizeof authorname, 1, handle); fwrite(copyrightname, sizeof copyrightname, 1, handle); // Determine amount of songs to be saved c = 0; for (;;) { if (c == MAX_SONGS) break; if ((!destsonglen[c][0])|| (!destsonglen[c][1])|| (!destsonglen[c][2])) break; c++; } amount = c; fwrite8(handle, amount); // Write songorderlists for (d = 0; d < amount; d++) { for (c = 0; c < MAX_CHN; c++) { length = destsonglen[d][c]+1; fwrite8(handle, length); writebytes = length; writebytes++; fwrite(destsongorder[d][c], writebytes, 1, handle); } } // Write instruments fwrite8(handle, highestusedinstr); for (c = 1; c <= highestusedinstr; c++) { fwrite8(handle, instr[c].ad); fwrite8(handle, instr[c].sr); fwrite8(handle, instr[c].ptr[WTBL]); fwrite8(handle, instr[c].ptr[PTBL]); fwrite8(handle, instr[c].ptr[FTBL]); fwrite8(handle, instr[c].ptr[STBL]); fwrite8(handle, instr[c].vibdelay); fwrite8(handle, instr[c].gatetimer); fwrite8(handle, instr[c].firstwave); fwrite(&instr[c].name, MAX_INSTRNAMELEN, 1, handle); } // Write tables for (c = 0; c < tables; c++) { writebytes = gettablelen(c); fwrite8(handle, writebytes); fwrite(ltable[c], writebytes, 1, handle); fwrite(rtable[c], writebytes, 1, handle); } // Write patterns amount = dp; fwrite8(handle, amount); for (c = 0; c < amount; c++) { length = destpattlen[c]+1; fwrite8(handle, length); fwrite(destpattern[c], length*4, 1, handle); } fclose(handle); return 1; } return 0; } void countpatternlengths(void) { int c, d, e; highestusedpattern = 0; for (c = 0; c < MAX_PATT; c++) { for (d = 0; d <= MAX_PATTROWS; d++) { if (pattern[c][d*4] == ENDPATT) break; } pattlen[c] = d; } for (e = 0; e < MAX_SONGS; e++) { for (c = 0; c < MAX_CHN; c++) { for (d = 0; d < MAX_SONGLEN; d++) { if (songorder[e][c][d] >= LOOPSONG) break; if (songorder[e][c][d] < MAX_PATT) { if (songorder[e][c][d] > highestusedpattern) highestusedpattern = songorder[e][c][d]; } } songlen[e][c] = d; } } } void countdestpatternlengths(void) { int c, d, e; for (c = 0; c < MAX_PATT; c++) { for (d = 0; d <= MAX_PATTROWS; d++) { if (destpattern[c][d*4] == ENDPATT) break; } destpattlen[c] = d; } for (e = 0; e < MAX_SONGS; e++) { for (c = 0; c < MAX_CHN; c++) { for (d = 0; d < MAX_SONGLEN; d++) { if (destsongorder[e][c][d] >= LOOPSONG) break; } destsonglen[e][c] = d; } } } void clearsong(void) { int c; for (c = 0; c < MAX_CHN; c++) { int d; for (d = 0; d < MAX_SONGS; d++) { destsonglen[d][c] = 0; destsongorder[d][c][0] = LOOPSONG; memset(&songorder[d][c][0], 0, MAX_SONGLEN); if (!d) { songorder[d][c][0] = c; songorder[d][c][1] = LOOPSONG; songorder[d][c][2] = 0; } else { songorder[d][c][0] = LOOPSONG; songorder[d][c][1] = 0; } } } memset(songname, 0, sizeof songname); memset(authorname, 0, sizeof authorname); memset(copyrightname, 0, sizeof copyrightname); for (c = 0; c < MAX_PATT; c++) { int d; memset(&pattern[c][0], 0, MAX_PATTROWS*4); for (d = 0; d < MAX_PATTROWS; d++) pattern[c][d*4] = REST; for (d = MAX_PATTROWS; d <= MAX_PATTROWS; d++) pattern[c][d*4] = ENDPATT; } for (c = 0; c < MAX_INSTR; c++) { memset(&instr[c], 0, sizeof(INSTR)); } memset(ltable, 0, sizeof ltable); memset(rtable, 0, sizeof rtable); countpatternlengths(); } int gettablelen(int num) { int c; for (c = MAX_TABLELEN-1; c >= 0; c--) { if (ltable[num][c] | rtable[num][c]) break; } return c+1; } goattracker-2.72/src/goattrk2.rc0000644000000000000000000000004610774364076015340 0ustar rootroot6581 ICON DISCARDABLE "goattrk2.ico" goattracker-2.72/src/goattrk2.h0000644000000000000000000000547611460120144015152 0ustar rootroot#ifndef GOATTRK2_H #define GOATTRK2_H #include #include #include #include #include #include #include #include #include "bme.h" #include "gcommon.h" #include "gconsole.h" #include "gsound.h" #include "gsid.h" #include "gsong.h" #include "gplay.h" #include "gdisplay.h" #include "greloc.h" #include "gfile.h" #include "gpattern.h" #include "gorder.h" #include "ginstr.h" #include "gtable.h" #define EDIT_PATTERN 0 #define EDIT_ORDERLIST 1 #define EDIT_INSTRUMENT 2 #define EDIT_TABLES 3 #define EDIT_NAMES 4 #define KEY_TRACKER 0 #define KEY_DMC 1 #define VISIBLEPATTROWS 31 #define VISIBLEORDERLIST 15 #define VISIBLETABLEROWS 15 #define VISIBLEFILES 24 #define PGUPDNREPEAT 8 #ifndef GOATTRK2_C extern int menu; extern int editmode; extern int recordmode; extern int followplay; extern int hexnybble; extern int stepsize; extern int autoadvance; extern int defaultpatternlength; extern int cursorflash; extern int cursorcolortable[]; extern int exitprogram; extern int eacolumn; extern int eamode; extern unsigned keypreset; extern unsigned playerversion; extern int fileformat; extern int zeropageadr; extern int playeradr; extern unsigned sidmodel; extern unsigned multiplier; extern unsigned adparam; extern unsigned ntsc; extern unsigned patternhex; extern unsigned sidaddress; extern unsigned finevibrato; extern unsigned optimizepulse; extern unsigned optimizerealtime; extern unsigned usefinevib; extern unsigned b; extern unsigned mr; extern unsigned writer; extern unsigned hardsid; extern unsigned catweasel; extern unsigned interpolate; extern unsigned hardsidbufinteractive; extern unsigned hardsidbufplayback; extern float basepitch; extern char configbuf[MAX_PATHNAME]; extern char loadedsongfilename[MAX_FILENAME]; extern char songfilename[MAX_FILENAME]; extern char songfilter[MAX_FILENAME]; extern char songpath[MAX_PATHNAME]; extern char instrfilename[MAX_FILENAME]; extern char instrfilter[MAX_FILENAME]; extern char instrpath[MAX_PATHNAME]; extern char packedpath[MAX_PATHNAME]; extern char *programname; extern char textbuffer[MAX_PATHNAME]; extern unsigned char hexkeytbl[16]; extern unsigned char datafile[]; #endif void getparam(FILE *handle, unsigned *value); void getfloatparam(FILE *handle, float *value); void waitkey(void); void waitkeymouse(void); void waitkeynoupdate(void); void waitkeymousenoupdate(void); void converthex(void); void docommand(void); void onlinehelp(int standalone, int context); void mousecommands(void); void generalcommands(void); void load(void); void save(void); void quit(void); void clear(void); void prevmultiplier(void); void nextmultiplier(void); void editadsr(void); void calculatefreqtable(void); #endif goattracker-2.72/src/gdisplay.h0000644000000000000000000000045310774364076015244 0ustar rootroot#ifndef GDISPLAY_H #define GDISPLAY_H #define CNORMAL 8 #define CMUTE 3 #define CEDIT 10 #define CPLAYING 12 #define CCOMMAND 7 #define CTITLE 15 void printmainscreen(void); void displayupdate(void); void printstatus(void); void resettime(void); void incrementtime(void); #endif goattracker-2.72/src/gsong.h0000644000000000000000000000173411036462276014541 0ustar rootroot#ifndef GSONG_H #define GSONG_H #ifndef GSONG_C extern INSTR instr[MAX_INSTR]; extern unsigned char ltable[MAX_TABLES][MAX_TABLELEN]; extern unsigned char rtable[MAX_TABLES][MAX_TABLELEN]; extern unsigned char songorder[MAX_SONGS][MAX_CHN][MAX_SONGLEN+2]; extern unsigned char pattern[MAX_PATT][MAX_PATTROWS*4+4]; extern char songname[MAX_STR]; extern char authorname[MAX_STR]; extern char copyrightname[MAX_STR]; extern int pattlen[MAX_PATT]; extern int songlen[MAX_SONGS][MAX_CHN]; extern int highestusedpattern; extern int highestusedinstr; #endif void loadsong(void); void loadinstrument(void); int savesong(void); int saveinstrument(void); void clearsong(int cs, int cp, int ci, int cf, int cn); void countpatternlengths(void); void countthispattern(void); void clearpattern(int p); int insertpattern(int p); void deletepattern(int p); void findusedpatterns(void); void findduplicatepatterns(void); void optimizeeverything(int oi, int ot); #endif goattracker-2.72/src/gconsole.c0000644000000000000000000002313111460107764015222 0ustar rootroot/* * GOATTRACKER "console" output routines */ #define GCONSOLE_C #include #include #include #include "goattrk2.h" int gfxinitted = 0; unsigned *scrbuffer = NULL; unsigned *prevscrbuffer = NULL; unsigned char *chardata = NULL; int key = 0; int rawkey = 0; int shiftpressed = 0; int cursorflashdelay = 0; int mouseb = 0; int prevmouseb = 0; unsigned mousex = 0; unsigned mousey = 0; unsigned mousepixelx = 0; unsigned mousepixely = 0; unsigned oldmousepixelx = 0xffffffff; unsigned oldmousepixely = 0xffffffff; int mouseheld = 0; int region[MAX_ROWS]; void initicon(void); inline void setcharcolor(unsigned *dptr, short ch, short color) { *dptr = (ch & 0xff) | (color << 16); } inline void setcolor(unsigned *dptr, short color) { *dptr = (*dptr & 0xffff) | (color << 16); } int initscreen(void) { int handle; if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER) < 0) return 0; win_openwindow("GoatTracker", NULL); win_setmousemode(MOUSE_ALWAYS_HIDDEN); initicon(); if (!gfx_init(MAX_COLUMNS * 8, MAX_ROWS * 16, 60, 0)) { win_fullscreen = 0; if (!gfx_init(MAX_COLUMNS * 8, MAX_ROWS * 16, 60, 0)) return 0; } scrbuffer = malloc(MAX_COLUMNS * MAX_ROWS * sizeof(unsigned)); prevscrbuffer = malloc(MAX_COLUMNS * MAX_ROWS * sizeof(unsigned)); if ((!scrbuffer) || (!prevscrbuffer)) return 0; memset(region, 0, sizeof region); chardata = malloc(4096); if (!chardata) return 0; handle = io_open("chargen.bin"); if (handle == -1) return 0; io_read(handle, &chardata[0], 4096); io_close(handle); gfx_loadpalette("palette.bin"); gfx_setpalette(); gfx_loadsprites(0, "cursor.bin"); gfxinitted = 1; clearscreen(); atexit(closescreen); return 1; } void initicon(void) { int handle = io_open("goattrk2.bmp"); if (handle != -1) { SDL_RWops *rw; SDL_Surface *icon; char *iconbuffer; int size; size = io_lseek(handle, 0, SEEK_END); io_lseek(handle, 0, SEEK_SET); iconbuffer = malloc(size); if (iconbuffer) { io_read(handle, iconbuffer, size); io_close(handle); rw = SDL_RWFromMem(iconbuffer, size); icon = SDL_LoadBMP_RW(rw, 0); SDL_WM_SetIcon(icon, 0); free(iconbuffer); } } } void closescreen(void) { if (scrbuffer) { free(scrbuffer); scrbuffer = NULL; } if (prevscrbuffer) { free(prevscrbuffer); prevscrbuffer = NULL; } if (chardata) { free(chardata); chardata = NULL; } gfxinitted = 0; } void clearscreen(void) { int c; unsigned *dptr = scrbuffer; if (!gfxinitted) return; for (c = 0; c < MAX_ROWS * MAX_COLUMNS; c++) { setcharcolor(dptr, 0x20, 0x7); dptr++; } } void printtext(int x, int y, int color, const char *text) { unsigned *dptr = scrbuffer + (x + y * MAX_COLUMNS); if (!gfxinitted) return; if (y < 0) return; if (y >= MAX_ROWS) return; while (*text) { setcharcolor(dptr, *text, color); dptr++; text++; } } void printtextc(int y, int color, const char *text) { int x = (MAX_COLUMNS - strlen(text)) / 2; printtext(x, y, color, text); } void printtextcp(int cp, int y, int color, const char *text) { int x = cp - (strlen(text) / 2); printtext(x, y, color, text); } void printblank(int x, int y, int length) { unsigned *dptr = scrbuffer + (x + y * MAX_COLUMNS); if (!gfxinitted) return; if (y < 0) return; if (y >= MAX_ROWS) return; while (length--) { setcharcolor(dptr, 0x20, 0x7); dptr++; } } void printblankc(int x, int y, int color, int length) { unsigned *dptr = scrbuffer + (x + y * MAX_COLUMNS); if (!gfxinitted) return; if (y < 0) return; if (y >= MAX_ROWS) return; while (length--) { setcharcolor(dptr, 0x20, color); dptr++; } } void drawbox(int x, int y, int color, int sx, int sy) { unsigned *dptr; unsigned *dptr2; int counter; if (!gfxinitted) return; if (y < 0) return; if (y >= MAX_ROWS) return; if (y+sy > MAX_ROWS) return; if ((!sx) || (!sy)) return; dptr = scrbuffer + (x + y * MAX_COLUMNS); dptr2 = scrbuffer + ((x+sx-1) + y * MAX_COLUMNS); counter = sy; while (counter--) { setcharcolor(dptr, '|', color); setcharcolor(dptr2, '|', color); dptr += MAX_COLUMNS; dptr2 += MAX_COLUMNS; } dptr = scrbuffer + (x + y * MAX_COLUMNS); dptr2 = scrbuffer + (x + (y+sy-1) * MAX_COLUMNS); counter = sx; while (counter--) { setcharcolor(dptr, '-', color); setcharcolor(dptr2, '-', color); dptr++; dptr2++; } dptr = scrbuffer + (x + y * MAX_COLUMNS); setcharcolor(dptr, '+', color); dptr = scrbuffer + ((x+sx-1) + y * MAX_COLUMNS); setcharcolor(dptr, '+', color); dptr = scrbuffer + (x + (y+sy-1) * MAX_COLUMNS); setcharcolor(dptr, '+', color); dptr = scrbuffer + ((x+sx-1) + (y+sy-1) * MAX_COLUMNS); setcharcolor(dptr, '+', color); } void printbg(int x, int y, int color, int length) { unsigned *dptr = scrbuffer + (x + y * MAX_COLUMNS); if (!gfxinitted) return; if (y < 0) return; if (y >= MAX_ROWS) return; while (length--) { setcolor(dptr, 15 | (color << 4)); dptr++; } } void fliptoscreen(void) { unsigned *sptr = scrbuffer; unsigned *cmpptr = prevscrbuffer; int x,y; int regionschanged = 0; if (!gfxinitted) return; // Mark previous mousecursor area changed if mouse moved if ((mousepixelx != oldmousepixelx) || (mousepixely != oldmousepixely)) { if ((oldmousepixelx >= 0) && (oldmousepixely >= 0)) { int sy = oldmousepixely >> 4; int ey = (oldmousepixely + MOUSESIZEY - 1) >> 4; int sx = oldmousepixelx >> 3; int ex = (oldmousepixelx + MOUSESIZEX - 1) >> 3; if (ey >= MAX_ROWS) ey = MAX_ROWS - 1; if (ex >= MAX_COLUMNS) ex = MAX_COLUMNS - 1; for (y = sy; y <= ey; y++) { for (x = sx; x <= ex; x++) prevscrbuffer[y*MAX_COLUMNS+x] = 0xffffffff; } } } // If redraw requested, mark whole screen changed if (gfx_redraw) { gfx_redraw = 0; memset(prevscrbuffer, 0xff, MAX_COLUMNS*MAX_ROWS*sizeof(unsigned)); } if (!gfx_lock()) return; // Now redraw text on changed areas for (y = 0; y < MAX_ROWS; y++) { for (x = 0; x < MAX_COLUMNS; x++) { // Check if char changed if (*sptr != *cmpptr) { *cmpptr = *sptr; region[y] = 1; regionschanged = 1; { unsigned char *chptr = &chardata[(*sptr & 0xffff)*16]; unsigned char *dptr = gfx_screen->pixels + y*16 * gfx_screen->pitch + x*8; unsigned char bgcolor = (*sptr) >> 20; unsigned char fgcolor = ((*sptr) >> 16) & 0xf; int c; for (c = 0; c < 16; c++) { unsigned char e = *chptr++; if (e & 128) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 64) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 32) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 16) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 8) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 4) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 2) *dptr++ = fgcolor; else *dptr++ = bgcolor; if (e & 1) *dptr++ = fgcolor; else *dptr++ = bgcolor; dptr += gfx_screen->pitch - 8; } } } sptr++; cmpptr++; } } // Redraw mouse if text was redrawn if (regionschanged) { int sy = mousepixely >> 4; int ey = (mousepixely + MOUSESIZEY - 1) >> 4; if (ey >= MAX_ROWS) ey = MAX_ROWS - 1; gfx_drawsprite(mousepixelx, mousepixely, 0x1); for (y = sy; y <= ey; y++) region[y] = 1; } // Store current mouse position as old oldmousepixelx = mousepixelx; oldmousepixely = mousepixely; // Redraw changed screen regions gfx_unlock(); for (y = 0; y < MAX_ROWS; y++) { if (region[y]) { SDL_UpdateRect(gfx_screen, 0, y*16, MAX_COLUMNS*8, 16); region[y] = 0; } } } void getkey(void) { int c; win_asciikey = 0; cursorflashdelay += win_getspeed(50); prevmouseb = mouseb; mou_getpos(&mousepixelx, &mousepixely); mouseb = mou_getbuttons(); mousex = mousepixelx / 8; mousey = mousepixely / 16; if (mouseb) mouseheld++; else mouseheld = 0; key = win_asciikey; rawkey = 0; for (c = 0; c < MAX_KEYS; c++) { if (win_keytable[c]) { if ((c != KEY_LEFTSHIFT) && (c != KEY_RIGHTSHIFT) && (c != KEY_CTRL) && (c != KEY_RIGHTCTRL)) { rawkey = c; win_keytable[c] = 0; break; } } } shiftpressed = 0; if ((win_keystate[KEY_LEFTSHIFT])||(win_keystate[KEY_RIGHTSHIFT])|| (win_keystate[KEY_CTRL])||(win_keystate[KEY_RIGHTCTRL])) shiftpressed = 1; if (rawkey == SDLK_KP_ENTER) { key = KEY_ENTER; rawkey = SDLK_RETURN; } if (rawkey == SDLK_KP0) key = '0'; if (rawkey == SDLK_KP1) key = '1'; if (rawkey == SDLK_KP2) key = '2'; if (rawkey == SDLK_KP3) key = '3'; if (rawkey == SDLK_KP4) key = '4'; if (rawkey == SDLK_KP5) key = '5'; if (rawkey == SDLK_KP6) key = '6'; if (rawkey == SDLK_KP7) key = '7'; if (rawkey == SDLK_KP8) key = '8'; if (rawkey == SDLK_KP9) key = '9'; } goattracker-2.72/src/gplay.h0000644000000000000000000000262410774364076014546 0ustar rootroot#ifndef GPLAY_H #define GPLAY_H #define PLAY_PLAYING 0x00 #define PLAY_BEGINNING 0x01 #define PLAY_POS 0x02 #define PLAY_PATTERN 0x03 #define PLAY_STOP 0x04 #define PLAY_STOPPED 0x80 typedef struct { unsigned char trans; unsigned char instr; unsigned char note; unsigned char lastnote; unsigned char newnote; unsigned pattptr; unsigned char pattnum; unsigned char songptr; unsigned char repeat; unsigned short freq; unsigned char gate; unsigned char wave; unsigned short pulse; unsigned char ptr[2]; unsigned char pulsetime; unsigned char wavetime; unsigned char vibtime; unsigned char vibdelay; unsigned char command; unsigned char cmddata; unsigned char newcommand; unsigned char newcmddata; unsigned char tick; unsigned char tempo; unsigned char mute; unsigned char advance; unsigned char gatetimer; } CHN; #ifndef GPLAY_C extern CHN chn[MAX_CHN]; extern unsigned char masterfader; extern unsigned char freqtbllo[]; extern unsigned char freqtblhi[]; extern int lastsonginit; #endif void initchannels(void); void initsong(int num, int playmode); void initsongpos(int num, int playmode, int pattpos); void stopsong(void); void rewindsong(void); void playtestnote(int note, int ins, int chnnum); void releasenote(int chnnum); void mutechannel(int chnnum); int isplaying(void); void playroutine(void); #endif goattracker-2.72/src/altplayer.s0000644000000000000000000015255611051325226015433 0ustar rootroot;------------------------------------------------------------------------------- ; GoatTracker V2.68 alternative SID write order playroutine ; ; NOTE: This playroutine source code does not fall under the GPL license! ; Use it, or song binaries created from it freely for any purpose, commercial ; or noncommercial. ; ; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer. ; Does not directly compile on DASM etc. ;------------------------------------------------------------------------------- ;Defines will be inserted by the relocator here .IF (ZPGHOSTREGS == 0) mt_temp1 = zpbase+0 mt_temp2 = zpbase+1 .ELSE ghostfreqlo = zpbase+0 ghostfreqhi = zpbase+1 ghostpulselo = zpbase+2 ghostpulsehi = zpbase+3 ghostwave = zpbase+4 ghostad = zpbase+5 ghostsr = zpbase+6 ghostfiltcutlow = zpbase+21 ghostfiltcutoff = zpbase+22 ghostfiltctrl = zpbase+23 ghostfilttype = zpbase+24 mt_temp1 = zpbase+25 mt_temp2 = zpbase+26 .ENDIF ;Defines for the music data ;Patterndata notes ENDPATT = $00 INS = $00 FX = $40 FXONLY = $50 NOTE = $60 REST = $bd KEYOFF = $be KEYON = $bf FIRSTPACKEDREST = $c0 PACKEDREST = $00 ;Effects DONOTHING = $00 PORTAUP = $01 PORTADOWN = $02 TONEPORTA = $03 VIBRATO = $04 SETAD = $05 SETSR = $06 SETWAVE = $07 SETWAVEPTR = $08 SETPULSEPTR = $09 SETFILTPTR = $0a SETFILTCTRL = $0b SETFILTCUTOFF = $0c SETMASTERVOL = $0d SETFUNKTEMPO = $0e SETTEMPO = $0f ;Orderlist commands REPEAT = $d0 TRANSDOWN = $e0 TRANS = $f0 TRANSUP = $f0 LOOPSONG = $ff ;Wave,pulse,filttable comands LOOPWAVE = $ff LOOPPULSE = $ff LOOPFILT = $ff SETPULSE = $80 SETFILTER = $80 SETCUTOFF = $00 .ORG (base) ;Jump table jmp mt_init jmp mt_play .IF (SOUNDSUPPORT != 0) jmp mt_playsfx .ENDIF .IF (VOLSUPPORT != 0) jmp mt_setmastervol .ENDIF ;Author info .IF (NOAUTHORINFO == 0) authorinfopos = base + $20 checkpos1: .IF ((authorinfopos - checkpos1) > 15) mt_tick0jumptbl: .BYTE (mt_tick0_0 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_5 % 256) .BYTE (mt_tick0_6 % 256) .BYTE (mt_tick0_7 % 256) .BYTE (mt_tick0_8 % 256) .BYTE (mt_tick0_9 % 256) .BYTE (mt_tick0_a % 256) .BYTE (mt_tick0_b % 256) .BYTE (mt_tick0_c % 256) .BYTE (mt_tick0_d % 256) .BYTE (mt_tick0_e % 256) .BYTE (mt_tick0_f % 256) .ENDIF checkpos2: .IF ((authorinfopos - checkpos2) > 4) mt_effectjumptbl: .BYTE (mt_effect_0 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_3 % 256) .BYTE (mt_effect_4 % 256) .ENDIF checkpos3: .IF ((authorinfopos - checkpos3) > 1) mt_funktempotbl: .BYTE (8,5) .ENDIF ;This is pretty stupid way of filling left-out space, but .ORG ;seemed to bug checkpos4: .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF checkpos5: .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF checkpos6: .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF mt_author: .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .ENDIF ;0 Instrument vibrato mt_tick0_0: .IF (NOEFFECTS == 0) .IF (NOINSTRVIB == 0) lda mt_insvibparam-1,y jmp mt_tick0_34 .ELSE .IF (NOVIB == 0) jmp mt_tick0_34 .ENDIF .ENDIF .ENDIF ;1,2 Portamentos mt_tick0_12: .IF (NOVIB == 0) tay lda #$00 sta mt_chnvibtime,x tya .ENDIF ;3,4 Toneportamento, Vibrato mt_tick0_34: .IF (NOEFFECTS == 0) .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) sta mt_chnparam,x lda mt_chnnewfx,x sta mt_chnfx,x .ENDIF rts .ENDIF ;5 Set AD mt_tick0_5: .IF (NOSETAD == 0) .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 1) sta mt_chntempo+7 .ENDIF .IF (NUMCHANNELS > 2) sta mt_chntempo+14 .ENDIF rts .ENDIF mt_tick0_f_setchantempo: .IF (NOCHANNELTEMPO == 0) and #$7f sta mt_chntempo,x rts .ENDIF ;Continuous effect code ;0 Instrument vibrato .IF (NOINSTRVIB == 0) mt_effect_0_delay: dec mt_chnvibdelay,x mt_effect_0_donothing: jmp mt_done mt_effect_0: beq mt_effect_0_donothing ;Speed 0 = no vibrato at all lda mt_chnvibdelay,x bne mt_effect_0_delay .ELSE mt_effect_0: mt_effect_0_donothing: jmp mt_done .ENDIF ;4 Vibrato mt_effect_4: .IF (NOVIB == 0) .IF (NOCALCULATEDSPEED == 0) lda mt_speedlefttbl-1,y .IF (NONORMALSPEED == 0) bmi mt_effect_4_nohibyteclear ldy #$00 ;Clear speed highbyte sty 1) sta mt_init+5 asl adc #$00 .ENDIF sta mt_initsongnum+1 rts ;Play soundeffect -routine .IF (SOUNDSUPPORT != 0) ;Sound FX init routine mt_playsfx: sta mt_playsfxlo+1 sty mt_playsfxhi+1 lda mt_chnsfx,x ;Need a priority check? beq mt_playsfxok tya ;Check address highbyte cmp mt_chnsfxhi,x bcc mt_playsfxskip ;Lower than current -> skip bne mt_playsfxok ;Higher than current -> OK lda mt_playsfxlo+1 ;Check address lowbyte cmp mt_chnsfxlo,x bcc mt_playsfxskip ;Lower than current -> skip mt_playsfxok: lda #$01 sta mt_chnsfx,x mt_playsfxlo: lda #$00 sta mt_chnsfxlo,x mt_playsfxhi: lda #$00 sta mt_chnsfxhi,x mt_playsfxskip: rts .ENDIF ;Set mastervolume -routine .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0)) mt_setmastervol: sta mt_masterfader+1 rts .ENDIF ;Playroutine mt_play: ldx #$00 ;Channel index ;Song initialization mt_initsongnum: ldy #$00 bmi mt_filtstep txa ldx #NUMCHANNELS * 14 - 1 mt_resetloop: sta mt_chnsongptr,x ;Reset sequencer + voice dex ;variables on all channels bpl mt_resetloop .IF (ZPGHOSTREGS == 0) .IF (NUMCHANNELS == 2) sta SIDBASE+$12 .ENDIF .IF (NUMCHANNELS == 1) sta SIDBASE+$0b sta SIDBASE+$12 .ENDIF sta SIDBASE+$15 ;Reset filter cutoff lowbyte .ELSE sta 1) tya iny sta mt_chnsongnum,x ;Store index to songtable .ENDIF mt_defaulttempo: lda #DEFAULTTEMPO ;Set default tempo sta mt_chntempo,x lda #$01 sta mt_chncounter,x ;Reset counter sta mt_chninstr,x ;Reset instrument jmp mt_loadregswave ;Load waveform ;Filter execution mt_filtstep: .IF (NOFILTER == 0) ldy #$00 ;See if filter stopped beq mt_filtdone .IF (NOFILTERMOD == 0) mt_filttime: lda #$00 ;See if time left for mod. bne mt_filtmod ;step .ENDIF mt_newfiltstep: lda mt_filttimetbl-1,y ;$80-> = set filt parameters beq mt_setcutoff ;$00 = set cutoff .IF (NOFILTERMOD == 0) bpl mt_newfiltmod .ENDIF mt_setfilt: asl ;Set passband sta mt_filttype+1 lda mt_filtspdtbl-1,y ;Set resonance/channel sta mt_filtctrl+1 lda mt_filttimetbl,y ;Check for cutoff setting bne mt_nextfiltstep2 ;following immediately mt_setcutoff2: iny mt_setcutoff: lda mt_filtspdtbl-1,y ;Take cutoff value sta mt_filtcutoff+1 .IF (NOFILTERMOD == 0) jmp mt_nextfiltstep mt_newfiltmod: sta mt_filttime+1 ;$01-$7f = new modulation step mt_filtmod: lda mt_filtspdtbl-1,y ;Take filt speed clc adc mt_filtcutoff+1 sta mt_filtcutoff+1 dec mt_filttime+1 bne mt_storecutoff .ENDIF mt_nextfiltstep: lda mt_filttimetbl,y ;Jump in filttable? mt_nextfiltstep2: cmp #LOOPFILT iny tya bcc mt_nofiltjump lda mt_filtspdtbl-1,y ;Take jump point mt_nofiltjump: sta mt_filtstep+1 mt_filtdone: mt_filtcutoff: lda #$00 mt_storecutoff: .IF (ZPGHOSTREGS == 0) sta SIDBASE+$16 .ELSE sta 0) || (NOFIRSTWAVECMD == 0)) lda #$ff mt_skipwave2: sta mt_chngate,x ;Reset gateflag .ELSE inc mt_chngate,x .ENDIF mt_skipwave: .IF ((BUFFEREDWRITES == 0) && (NOFIRSTWAVECMD == 0)) lda mt_chnwave,x and mt_chngate,x sta SIDBASE+$04,x .ENDIF lda mt_inswaveptr-1,y ;Load waveptr sta mt_chnwaveptr,x .IF (NOPULSE == 0) lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) beq mt_skippulse sta mt_chnpulseptr,x .IF (NOPULSEMOD == 0) lda #$00 ;Reset pulse step duration sta mt_chnpulsetime,x .ENDIF .ENDIF mt_skippulse: .IF (NOFILTER == 0) lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) beq mt_skipfilt sta mt_filtstep+1 .IF (NOFILTERMOD == 0) lda #$00 sta mt_filttime+1 .ENDIF .ENDIF mt_skipfilt: lda mt_insad-1,y ;Load Attack/Decay .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) lda mt_chninstr,x cmp #FIRSTNOHRINSTR ;Instrument order: .IF (NUMLEGATOINSTR > 0) bcs mt_nohr_legato ;With HR - no HR - legato .ELSE bcs mt_skiphr .ENDIF .ENDIF .IF (NUMHRINSTR > 0) lda #ADPARAM ;Hard restart .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 0) mt_nohr_legato: cmp #FIRSTLEGATOINSTR bcc mt_skiphr bcs mt_rest .ENDIF ;Sound FX code .IF (SOUNDSUPPORT != 0) .IF (ZPGHOSTREGS == 0) ;Sound FX code without ghostregs mt_sfxexec: lda mt_chnsfxlo,x sta 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnfx: .BYTE (0) mt_chnparam: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) mt_chnpulsetime: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .IF ((ZPGHOSTREGS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF ((BUFFEREDWRITES != 0) || (FIXEDPARAMS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnad: .BYTE (0) mt_chnsr: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) mt_chnlastnote: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE ;Optimized channel variables mt_chnsongptr: .BYTE (0) mt_chnpattptr: .BYTE (0) mt_chnpackedrest: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnpulsetime: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .ENDIF ;Songdata & frequencytable will be inserted by the relocator here goattracker-2.72/src/makefile.common0000644000000000000000000000336711313456432016241 0ustar rootroot# common makefile directives for linux and win32 build CC=gcc CXX=g++ CFLAGS+=-O3 -Wall -Ibme -Iasm CXXFLAGS=$(CFLAGS) EXE= $(PREFIX)goattrk2$(SUFFIX) \ $(PREFIX)ins2snd2$(SUFFIX) \ $(PREFIX)sngspli2$(SUFFIX) \ $(PREFIX)betaconv$(SUFFIX) \ $(PREFIX)mod2sng$(SUFFIX) all: $(EXE) $(PREFIX)goattrk2$(SUFFIX): goatdata.o goattrk2.o gsong.o gorder.o gpattern.o ginstr.o gtable.o gplay.o gdisplay.o \ gfile.o greloc.o ghelp.o gsound.o gconsole.o gsid.o \ resid/envelope.o resid/extfilt.o resid/filter.o resid/pot.o resid/sid.o resid/wave.o resid/wave6581__ST.o \ resid/wave6581_P_T.o resid/wave6581_PS_.o resid/wave6581_PST.o resid/wave8580__ST.o resid/wave8580_P_T.o \ resid/wave8580_PS_.o resid/wave8580_PST.o resid/voice.o \ resid-fp/envelopefp.o resid-fp/extfiltfp.o resid-fp/filterfp.o resid-fp/potfp.o resid-fp/sidfp.o \ resid-fp/wavefp.o resid-fp/voicefp.o \ asm/asmtab.o asm/chnkpool.o asm/expr.o asm/lexyy.o asm/log.o asm/membuf.o asm/membufio.o asm/namedbuf.o asm/parse.o \ asm/pc.o asm/vec.o \ bme/bme_gfx.o bme/bme_snd.o bme/bme_win.o bme/bme_mou.o bme/bme_kbd.o bme/bme_io.o bme/bme_end.o bme/bme.o $(CXX) -o $@ $^ $(LIBS) strip $@ $(PREFIX)mod2sng$(SUFFIX): mod2sng.o bme/bme_end.o gcc -o $@ $^ strip $@ $(PREFIX)ins2snd2$(SUFFIX): ins2snd2.o bme/bme_end.o gcc -o $@ $^ strip $@ $(PREFIX)sngspli2$(SUFFIX): sngspli2.o bme/bme_end.o gcc -o $@ $^ strip $@ $(PREFIX)betaconv$(SUFFIX): betaconv.o bme/bme_end.o gcc -o $@ $^ strip $@ goattrk2.dat: player.s altplayer.s chargen.bin palette.bin cursor.bin goattrk2.bmp goattrk2.seq datafile $@ goattrk2.seq goatdata.c: goattrk2.dat dat2inc $< $@ clean: $(RM) *.o *~ $(RM) asm/*.o $(RM) bme/*.o $(RM) resid/*.o $(RM) resid-fp/*.o $(RM) $(EXE) goattracker-2.72/src/makefile0000644000000000000000000000021011033643770014734 0ustar rootroot# # Linux makefile # CFLAGS=`sdl-config --cflags` PREFIX=../linux/ SUFFIX= LIBS=`sdl-config --libs` include makefile.common goattracker-2.72/src/goattrk2.ico0000644000000000000000000000627610774364076015521 0ustar rootroot  ( @HH{{{{{{{??{{?{{{{?{??{7{?{{{{?{?{{?{{?{{{{{?{?{{{???{????{{?{?{{{{{{{{{{{{{{Žŀ{{{{{{{ŀ{{{{ŽŽŽŽŽŽ{{{{{ŽŽŽ{{@@@{{Ž@@@@@@{Ž{{{{{ŽŽŽŽŽ{@@@{{{{@@@{ŽŽ{{555=5=5=5=ŽŽŽŽŽŽŽ555={Y]UUY]UUUUŽŽY]Y]UU{@@@{u}u}uuŽŽŽŽŽu}u}u}{@@@@@@{``ŽŽŽŽ``{{{{{}ŽŽŽŽŽŽŽŽ}@@@@@@{KŀŽC{{@ŽŀŽ@@{{{{{{ww{Žowww{@@@@@@{ŽŽ@@@@@@{{{{{{Žŀ{@@@{{{@@@ЬŽЬдЬЬдЬŽŀЬЬд{{{@@@{ààààà{@@@{{{ŽŽ{@@@@@@{{{{{{goattracker-2.72/src/ginstr.h0000644000000000000000000000045010774364076014733 0ustar rootroot#ifndef GINSTR_H #define GINSTR_H #ifndef GINSTR_C int einum; int eipos; int eicolumn; INSTR instrcopybuffer; #endif void instrumentcommands(void); void nextinstr(void); void previnstr(void); void clearinstr(int num); void gotoinstr(int i); void showinstrtable(void); #endif goattracker-2.72/src/chargen.bin0000644000000000000000000001000010774364074015343 0ustar rootroot<<<fff$lllllll||| 0`Ɔ8ll8vv000` 000000 0 0f<~6ll60``|```08ll8~p0`lllll|fffff|``vv ll<8ll8|l6l0fΞ>0`܆ > 0`0 ~0000`|6666666666666666666666666666667666666668l8l88l>lffff<8ll88lllll|~~`~ // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __POTFP_H__ #define __POTFP_H__ #include "siddefsfp.h" class PotentiometerFP { public: reg8 readPOT(); }; #endif goattracker-2.72/src/resid-fp/voicefp.cpp0000644000000000000000000000636611313456432017124 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "voicefp.h" // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- VoiceFP::VoiceFP() { set_chip_model(MOS6581); } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void VoiceFP::set_chip_model(chip_model model) { wave.set_chip_model(model); if (model == MOS6581) { /* there is some level from each voice even if the env is down and osc * is stopped. You can hear this by routing a voice into filter (filter * should be kept disabled for this) as the master level changes. This * tunable affects the volume of digis. */ voice_DC = static_cast(0x800 * 0xff); /* In 8580 the waveforms seem well centered, but on the 6581 there is some * offset change as envelope grows, indicating that the waveforms are not * perfectly centered. The likely cause for this is the follows: * * The waveform DAC generates a voltage between 5 and 12 V corresponding * to oscillator state 0 .. 4095. * * The envelope DAC generates a voltage between waveform gen output and * the 5V level. * * The outputs are amplified against the 12V voltage and sent to the * mixer. * * The SID virtual ground is around 6.5 V. */ } else { voice_DC = 0.f; } } // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void VoiceFP::writeCONTROL_REG(WaveformGeneratorFP& source, reg8 control) { wave.writeCONTROL_REG(source, control); envelope.writeCONTROL_REG(control); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void VoiceFP::reset() { wave.reset(); envelope.reset(); } // ---------------------------------------------------------------------------- // VoiceFP mute. // ---------------------------------------------------------------------------- void VoiceFP::mute(bool enable) { envelope.mute(enable); } goattracker-2.72/src/resid-fp/sidfp.h0000644000000000000000000000570111313457456016242 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __SIDFP_H__ #define __SIDFP_H__ #include "siddefsfp.h" #include "voicefp.h" #include "filterfp.h" #include "extfiltfp.h" #include "potfp.h" class SIDFP { public: SIDFP(); ~SIDFP(); static float kinked_dac(const int x, const float nonlinearity, const int bits); void set_chip_model(chip_model model); FilterFP& get_filter() { return filter; } void enable_filter(bool enable); bool set_sampling_parameters(double clock_freq, sampling_method method, double sample_freq, double pass_freq = 20000); void set_voice_nonlinearity(float nl); void clock(); int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1); int clock_fast(cycle_count& delta_t, short* buf, int n, int interleave = 1); void reset(); // Read/write registers. reg8 read(reg8 offset); void write(reg8 offset, reg8 value); void mute(reg8 channel, bool enable); // 16-bit input (EXT IN). void input(int sample); // 16-bit output (AUDIO OUT). float output(); private: static double I0(double x); inline int clock_interpolate(cycle_count& delta_t, short* buf, int n, int interleave); inline int clock_resample_interpolate(cycle_count& delta_t, short* buf, int n, int interleave); inline void age_bus_value(cycle_count); VoiceFP voice[3]; FilterFP filter; ExternalFilterFP extfilt; PotentiometerFP potx; PotentiometerFP poty; reg8 bus_value; cycle_count bus_value_ttl; // External audio input. float ext_in; // Sampling variables. sampling_method sampling; float cycles_per_sample; float sample_offset; int sample_index; int fir_N; int fir_RES; /* for linear interpolation mode */ float sample_prev; // Ring buffer with overflow for contiguous storage of RINGSIZE samples. float* sample; // FIR_RES filter tables (FIR_N*FIR_RES). float* fir; /* analog parts are run at half the rate of digital ones. */ float lastsample[3]; unsigned char filtercyclegate; }; #endif // not __SIDFP_H__ goattracker-2.72/src/resid-fp/potfp.cpp0000644000000000000000000000210611313456432016605 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "potfp.h" reg8 PotentiometerFP::readPOT() { // NB! Not modeled. return 0xff; } goattracker-2.72/src/resid-fp/wavefp.h0000644000000000000000000001330511313456432016415 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __WAVEFP_H__ #define __WAVEFP_H__ #include "siddefsfp.h" extern float dac[12]; extern float wftable[11][4096]; // ---------------------------------------------------------------------------- // A 24 bit accumulator is the basis for waveform generation. FREQ is added to // the lower 16 bits of the accumulator each cycle. // The accumulator is set to zero when TEST is set, and starts counting // when TEST is cleared. // The noise waveform is taken from intermediate bits of a 23 bit shift // register. This register is clocked by bit 19 of the accumulator. // ---------------------------------------------------------------------------- class WaveformGeneratorFP { public: WaveformGeneratorFP(); void set_chip_model(chip_model model); inline void clock(); inline void synchronize(WaveformGeneratorFP& dest, WaveformGeneratorFP& source); void reset(); void writeFREQ_LO(reg8 value); void writeFREQ_HI(reg8 value); void writePW_LO(reg8 value); void writePW_HI(reg8 value); void writeCONTROL_REG(WaveformGeneratorFP& source, reg8 value); reg8 readOSC(WaveformGeneratorFP& source); inline float output(WaveformGeneratorFP& source); protected: void clock_noise(const bool clock); reg12 outputN___(); void set_nonlinearity(float nl); void rebuild_wftable(); void calculate_waveform_sample(float o[12]); chip_model model; // Tell whether the accumulator MSB was set high on this cycle. bool msb_rising; reg24 accumulator; reg24 shift_register; reg8 previous; int noise_overwrite_delay; // Fout = (Fn*Fclk/16777216)Hz reg16 freq; // PWout = (PWn/40.95)% reg12 pw; // The control register right-shifted 4 bits; used for output function // table lookup. reg8 waveform; // The remaining control register bits. bool test, ring_mod, sync; // The gate bit is handled by the EnvelopeGenerator. // zero level offset of waveform (< 0) float wave_zero; float previous_dac; friend class VoiceFP; friend class SIDFP; }; // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- inline void WaveformGeneratorFP::clock() { /* no digital operation if test bit is set. Only emulate analog fade. */ if (test) { if (noise_overwrite_delay != 0) { if (-- noise_overwrite_delay == 0) { shift_register |= 0x7ffffc; clock_noise(false); } } return; } reg24 accumulator_prev = accumulator; // Calculate new accumulator value; accumulator += freq; accumulator &= 0xffffff; // Check whether the MSB became set high. This is used for synchronization. msb_rising = !(accumulator_prev & 0x800000) && (accumulator & 0x800000); // Shift noise register once for each time accumulator bit 19 is set high. if (!(accumulator_prev & 0x080000) && (accumulator & 0x080000)) { clock_noise(true); } } // ---------------------------------------------------------------------------- // Synchronize oscillators. // This must be done after all the oscillators have been clock()'ed since the // oscillators operate in parallel. // Note that the oscillators must be clocked exactly on the cycle when the // MSB is set high for hard sync to operate correctly. See SID::clock(). // ---------------------------------------------------------------------------- inline void WaveformGeneratorFP::synchronize(WaveformGeneratorFP& sync_dest, WaveformGeneratorFP &sync_source) { // A special case occurs when a sync source is synced itself on the same // cycle as when its MSB is set high. In this case the destination will // not be synced. This has been verified by sampling OSC3. if (msb_rising && sync_dest.sync && !(sync && sync_source.msb_rising)) { sync_dest.accumulator = 0; } } // ---------------------------------------------------------------------------- // Select one of 16 possible combinations of waveforms. // ---------------------------------------------------------------------------- inline float WaveformGeneratorFP::output(WaveformGeneratorFP& sync_source) { if (waveform == 0 || waveform > 7) { return previous_dac; } /* waveforms 1 .. 7 left */ /* Phase for all waveforms */ reg12 phase = accumulator >> 12; /* pulse on/off generates 4 more variants after the main pulse types */ int variant = waveform >= 4 && (test || phase >= pw) ? 3 : -1; /* triangle waveform XOR circuit. Since the table already makes a triangle * wave internally, we only need to account for the sync source here. * Flipping the top bit suffices to reproduce the original SID ringmod */ phase ^= ((waveform & 3) == 1 && ring_mod && (sync_source.accumulator & 0x800000)) ? 0x800 : 0x00; return wftable[waveform + variant][phase]; } #endif // not __WAVEFP_H__ goattracker-2.72/src/resid-fp/voicefp.h0000644000000000000000000000366311313456432016566 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __VOICEFP_H__ #define __VOICEFP_H__ #include "siddefsfp.h" #include "wavefp.h" #include "envelopefp.h" class VoiceFP { public: VoiceFP(); void set_chip_model(chip_model model); void reset(); void mute(bool enable); void writeCONTROL_REG(WaveformGeneratorFP& source, reg8 value); // Amplitude modulated waveform output. // Range [-2048*255, 2047*255]. inline float output(WaveformGeneratorFP& source); protected: WaveformGeneratorFP wave; EnvelopeGeneratorFP envelope; // Multiplying D/A DC offset. float voice_DC; friend class SIDFP; }; // ---------------------------------------------------------------------------- // Amplitude modulated waveform output. // Ideal range [-2048*255, 2047*255]. // ---------------------------------------------------------------------------- inline float VoiceFP::output(WaveformGeneratorFP& source) { return wave.output(source) * envelope.output() + voice_DC; } #endif // not __VOICEFP_H__ goattracker-2.72/src/resid-fp/extfiltfp.h0000644000000000000000000000611711313456432017135 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __EXTFILTFP_H__ #define __EXTFILTFP_H__ #include #include "siddefsfp.h" // ---------------------------------------------------------------------------- // The audio output stage in a Commodore 64 consists of two STC networks, // a low-pass filter with 3-dB frequency 16kHz followed by a high-pass // filter with 3-dB frequency 16Hz (the latter provided an audio equipment // input impedance of 1kOhm). // The STC networks are connected with a BJT supposedly meant to act as // a unity gain buffer, which is not really how it works. A more elaborate // model would include the BJT, however DC circuit analysis yields BJT // base-emitter and emitter-base impedances sufficiently low to produce // additional low-pass and high-pass 3dB-frequencies in the order of hundreds // of kHz. This calls for a sampling frequency of several MHz, which is far // too high for practical use. // ---------------------------------------------------------------------------- class ExternalFilterFP { public: ExternalFilterFP(); void set_clock_frequency(float); inline void clock(float Vi); void reset(); // Audio output (20 bits). inline float output(); private: inline void nuke_denormals(); // State of filters. float Vlp; // lowpass float Vhp; // highpass // Cutoff frequencies. float w0lp; float w0hp; friend class SIDFP; }; // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- inline void ExternalFilterFP::clock(float Vi) { float dVlp = w0lp * (Vi - Vlp); float dVhp = w0hp * (Vlp - Vhp); Vlp += dVlp; Vhp += dVhp; } // ---------------------------------------------------------------------------- // Audio output (19.5 bits). // ---------------------------------------------------------------------------- inline float ExternalFilterFP::output() { return Vlp - Vhp; } inline void ExternalFilterFP::nuke_denormals() { if (Vhp > -1e-12f && Vhp < 1e-12f) Vhp = 0; if (Vlp > -1e-12f && Vlp < 1e-12f) Vlp = 0; } #endif // not __EXTFILTFP_H__ goattracker-2.72/src/resid-fp/envelopefp.cpp0000644000000000000000000002267111313456432017631 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "envelopefp.h" #include "sidfp.h" void EnvelopeGeneratorFP::set_nonlinearity(float nl) { for (int i = 0; i < 256; i ++) env_dac[i] = SIDFP::kinked_dac(i, nl, 8); } // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- EnvelopeGeneratorFP::EnvelopeGeneratorFP() { reset(); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void EnvelopeGeneratorFP::reset() { muted = false; envelope_counter = 0; envelope_counter_dac = 0; attack = 0; decay = 0; sustain = 0; release = 0; gate = 0; rate_counter = 0; exponential_counter = 0; exponential_counter_period = 1; state = RELEASE; rate_period = rate_counter_period[release]; hold_zero = true; } void EnvelopeGeneratorFP::mute(bool enable) { muted = enable; } // Rate counter periods are calculated from the Envelope Rates table in // the Programmer's Reference Guide. The rate counter period is the number of // cycles between each increment of the envelope counter. // The rates have been verified by sampling ENV3. // // The rate counter is a 16 bit register which is incremented each cycle. // When the counter reaches a specific comparison value, the envelope counter // is incremented (attack) or decremented (decay/release) and the // counter is zeroed. // // NB! Sampling ENV3 shows that the calculated values are not exact. // It may seem like most calculated values have been rounded (.5 is rounded // down) and 1 has beed added to the result. A possible explanation for this // is that the SID designers have used the calculated values directly // as rate counter comparison values, not considering a one cycle delay to // zero the counter. This would yield an actual period of comparison value + 1. // // The time of the first envelope count can not be exactly controlled, except // possibly by resetting the chip. Because of this we cannot do cycle exact // sampling and must devise another method to calculate the rate counter // periods. // // The exact rate counter periods can be determined e.g. by counting the number // of cycles from envelope level 1 to envelope level 129, and dividing the // number of cycles by 128. CIA1 timer A and B in linked mode can perform // the cycle count. This is the method used to find the rates below. // // To avoid the ADSR delay bug, sampling of ENV3 should be done using // sustain = release = 0. This ensures that the attack state will not lower // the current rate counter period. // // The ENV3 sampling code below yields a maximum timing error of 14 cycles. // lda #$01 // l1: cmp $d41c // bne l1 // ... // lda #$ff // l2: cmp $d41c // bne l2 // // This yields a maximum error for the calculated rate period of 14/128 cycles. // The described method is thus sufficient for exact calculation of the rate // periods. // reg16 EnvelopeGeneratorFP::rate_counter_period[] = { 9, // 2ms*1.0MHz/256 = 7.81 32, // 8ms*1.0MHz/256 = 31.25 63, // 16ms*1.0MHz/256 = 62.50 95, // 24ms*1.0MHz/256 = 93.75 149, // 38ms*1.0MHz/256 = 148.44 220, // 56ms*1.0MHz/256 = 218.75 267, // 68ms*1.0MHz/256 = 265.63 313, // 80ms*1.0MHz/256 = 312.50 392, // 100ms*1.0MHz/256 = 390.63 977, // 250ms*1.0MHz/256 = 976.56 1954, // 500ms*1.0MHz/256 = 1953.13 3126, // 800ms*1.0MHz/256 = 3125.00 3907, // 1 s*1.0MHz/256 = 3906.25 11720, // 3 s*1.0MHz/256 = 11718.75 19532, // 5 s*1.0MHz/256 = 19531.25 31251 // 8 s*1.0MHz/256 = 31250.00 }; // For decay and release, the clock to the envelope counter is sequentially // divided by 1, 2, 4, 8, 16, 30, 1 to create a piece-wise linear approximation // of an exponential. The exponential counter period is loaded at the envelope // counter values 255, 93, 54, 26, 14, 6, 0. The period can be different for the // same envelope counter value, depending on whether the envelope has been // rising (attack -> release) or sinking (decay/release). // // Since it is not possible to reset the rate counter (the test bit has no // influence on the envelope generator whatsoever) a method must be devised to // do cycle exact sampling of ENV3 to do the investigation. This is possible // with knowledge of the rate period for A=0, found above. // // The CPU can be synchronized with ENV3 by first synchronizing with the rate // counter by setting A=0 and wait in a carefully timed loop for the envelope // counter _not_ to change for 9 cycles. We can then wait for a specific value // of ENV3 with another timed loop to fully synchronize with ENV3. // // At the first period when an exponential counter period larger than one // is used (decay or relase), one extra cycle is spent before the envelope is // decremented. The envelope output is then delayed one cycle until the state // is changed to attack. Now one cycle less will be spent before the envelope // is incremented, and the situation is normalized. // The delay is probably caused by the comparison with the exponential counter, // and does not seem to affect the rate counter. This has been verified by // timing 256 consecutive complete envelopes with A = D = R = 1, S = 0, using // CIA1 timer A and B in linked mode. If the rate counter is not affected the // period of each complete envelope is // (255 + 162*1 + 39*2 + 28*4 + 12*8 + 8*16 + 6*30)*32 = 756*32 = 32352 // which corresponds exactly to the timed value divided by the number of // complete envelopes. // NB! This one cycle delay is not modeled. // From the sustain levels it follows that both the low and high 4 bits of the // envelope counter are compared to the 4-bit sustain value. // This has been verified by sampling ENV3. // reg8 EnvelopeGeneratorFP::sustain_level[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }; // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void EnvelopeGeneratorFP::writeCONTROL_REG(reg8 control) { reg8 gate_next = control & 0x01; // The rate counter is never reset, thus there will be a delay before the // envelope counter starts counting up (attack) or down (release). // Gate bit on: Start attack, decay, sustain. if (!gate && gate_next) { state = ATTACK; update_rate_period(rate_counter_period[attack]); // Switching to attack state unlocks the zero freeze. hold_zero = false; } // Gate bit off: Start release. else if (gate && !gate_next) { state = RELEASE; update_rate_period(rate_counter_period[release]); } gate = gate_next; } void EnvelopeGeneratorFP::writeATTACK_DECAY(reg8 attack_decay) { attack = (attack_decay >> 4) & 0x0f; decay = attack_decay & 0x0f; if (state == ATTACK) { update_rate_period(rate_counter_period[attack]); } else if (state == DECAY_SUSTAIN) { update_rate_period(rate_counter_period[decay]); } } void EnvelopeGeneratorFP::writeSUSTAIN_RELEASE(reg8 sustain_release) { sustain = (sustain_release >> 4) & 0x0f; release = sustain_release & 0x0f; if (state == RELEASE) { update_rate_period(rate_counter_period[release]); } } void EnvelopeGeneratorFP::update_rate_period(reg16 newperiod) { rate_period = newperiod; /* The ADSR counter is XOR shift register with 0x7fff unique values. * If the rate_period is adjusted to a value already seen in this cycle, * the register will wrap around. This is known as the ADSR delay bug. * * To simplify the hot path calculation, we simulate this through observing * that we add the 0x7fff cycle delay by changing the rate_counter variable * directly. This takes care of the 99 % common case. However, playroutine * could make multiple consequtive rate_period adjustments, in which case we * need to cancel the previous adjustment. */ /* if the new period exeecds 0x7fff, we need to wrap */ if (rate_period - rate_counter > 0x7fff) rate_counter += 0x7fff; /* simulate 0x7fff wraparound, if the period-to-be-written * is less than the current value. */ if (rate_period <= rate_counter) rate_counter -= 0x7fff; /* at this point it should be impossible for * rate_counter >= rate_period. If it is, there is a bug... */ } reg8 EnvelopeGeneratorFP::readENV() { return envelope_counter; } goattracker-2.72/src/resid-fp/sidfp.cpp0000644000000000000000000006047211313457454016601 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "sidfp.h" #include #define RINGSIZE 2048 #ifdef __SSE__ #include #endif /* tables used by voice/wavegen/envgen */ float dac[12]; float env_dac[256]; float wftable[11][4096]; void SIDFP::set_voice_nonlinearity(float nl) { /* all voices, waves, etc. share the same tables */ voice[0].envelope.set_nonlinearity(nl); voice[0].wave.set_nonlinearity(nl); voice[0].wave.rebuild_wftable(); filter.set_nonlinearity(nl); } float SIDFP::kinked_dac(const int x, const float nonlinearity, const int max) { float value = 0.f; int bit = 1; float weight = 1.f; const float dir = 2.0f * nonlinearity; for (int i = 0; i < max; i ++) { if (x & bit) value += weight; bit <<= 1; weight *= dir; } return value / (weight / nonlinearity / nonlinearity) * (1 << max); } // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- SIDFP::SIDFP() { // Initialize pointers. sample = 0; fir = 0; lastsample[0] = lastsample[1] = lastsample[2] = 0; filtercyclegate = 0; set_sampling_parameters(985248, SAMPLE_INTERPOLATE, 44100); bus_value = 0; bus_value_ttl = 0; input(0); } // ---------------------------------------------------------------------------- // Destructor. // ---------------------------------------------------------------------------- SIDFP::~SIDFP() { delete[] sample; delete[] fir; } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void SIDFP::set_chip_model(chip_model model) { for (int i = 0; i < 3; i++) { voice[i].set_chip_model(model); } voice[0].wave.rebuild_wftable(); filter.set_chip_model(model); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void SIDFP::reset() { for (int i = 0; i < 3; i++) { voice[i].reset(); } filter.reset(); extfilt.reset(); bus_value = 0; bus_value_ttl = 0; } // ---------------------------------------------------------------------------- // Write 16-bit sample to audio input. // NB! The caller is responsible for keeping the value within 16 bits. // Note that to mix in an external audio signal, the signal should be // resampled to 1MHz first to avoid sampling noise. // ---------------------------------------------------------------------------- void SIDFP::input(int sample) { // Voice outputs are 20 bits. Scale up to match three voices in order // to facilitate simulation of the MOS8580 "digi boost" hardware hack. ext_in = static_cast((sample << 4) * 3); } // ---------------------------------------------------------------------------- // Read sample from audio output, 16-bit result. // Do not use this directly, rather use the high-quality resampling outputs. // ---------------------------------------------------------------------------- float SIDFP::output() { /* Scale to roughly -1 .. 1 range. Voices go from -2048 to 2048 or so, * envelope from 0 to 255, there are 3 voices, and there's factor of 2 * for resonance. */ return extfilt.output() * (1.f / (2047.f * 255.f * 3.0f * 2.0f)); } // ---------------------------------------------------------------------------- // Read registers. // // Reading a write only register returns the last byte written to any SID // register. The individual bits in this value start to fade down towards // zero after a few cycles. All bits reach zero within approximately // $2000 - $4000 cycles. // It has been claimed that this fading happens in an orderly fashion, however // sampling of write only registers reveals that this is not the case. // NB! This is not correctly modeled. // The actual use of write only registers has largely been made in the belief // that all SID registers are readable. To support this belief the read // would have to be done immediately after a write to the same register // (remember that an intermediate write to another register would yield that // value instead). With this in mind we return the last value written to // any SID register for $2000 cycles without modeling the bit fading. // ---------------------------------------------------------------------------- reg8 SIDFP::read(reg8 offset) { switch (offset) { case 0x19: return potx.readPOT(); case 0x1a: return poty.readPOT(); case 0x1b: return voice[2].wave.readOSC(voice[0].wave); case 0x1c: return voice[2].envelope.readENV(); default: return bus_value; } } // ---------------------------------------------------------------------------- // Write registers. // ---------------------------------------------------------------------------- void SIDFP::write(reg8 offset, reg8 value) { bus_value = value; bus_value_ttl = 34000; switch (offset) { case 0x00: voice[0].wave.writeFREQ_LO(value); break; case 0x01: voice[0].wave.writeFREQ_HI(value); break; case 0x02: voice[0].wave.writePW_LO(value); break; case 0x03: voice[0].wave.writePW_HI(value); break; case 0x04: voice[0].writeCONTROL_REG(voice[1].wave, value); break; case 0x05: voice[0].envelope.writeATTACK_DECAY(value); break; case 0x06: voice[0].envelope.writeSUSTAIN_RELEASE(value); break; case 0x07: voice[1].wave.writeFREQ_LO(value); break; case 0x08: voice[1].wave.writeFREQ_HI(value); break; case 0x09: voice[1].wave.writePW_LO(value); break; case 0x0a: voice[1].wave.writePW_HI(value); break; case 0x0b: voice[1].writeCONTROL_REG(voice[2].wave, value); break; case 0x0c: voice[1].envelope.writeATTACK_DECAY(value); break; case 0x0d: voice[1].envelope.writeSUSTAIN_RELEASE(value); break; case 0x0e: voice[2].wave.writeFREQ_LO(value); break; case 0x0f: voice[2].wave.writeFREQ_HI(value); break; case 0x10: voice[2].wave.writePW_LO(value); break; case 0x11: voice[2].wave.writePW_HI(value); break; case 0x12: voice[2].writeCONTROL_REG(voice[0].wave, value); break; case 0x13: voice[2].envelope.writeATTACK_DECAY(value); break; case 0x14: voice[2].envelope.writeSUSTAIN_RELEASE(value); break; case 0x15: filter.writeFC_LO(value); break; case 0x16: filter.writeFC_HI(value); break; case 0x17: filter.writeRES_FILT(value); break; case 0x18: filter.writeMODE_VOL(value); break; default: break; } } // ---------------------------------------------------------------------------- // SID voice muting. // ---------------------------------------------------------------------------- void SIDFP::mute(reg8 channel, bool enable) { // Only have 3 voices! if (channel >= 3) return; voice[channel].mute (enable); } // ---------------------------------------------------------------------------- // Enable filter. // ---------------------------------------------------------------------------- void SIDFP::enable_filter(bool enable) { filter.enable_filter(enable); } // ---------------------------------------------------------------------------- // I0() computes the 0th order modified Bessel function of the first kind. // This function is originally from resample-1.5/filterkit.c by J. O. Smith. // ---------------------------------------------------------------------------- double SIDFP::I0(double x) { // Max error acceptable in I0 could be 1e-6, which gives that 96 dB already. // I'm overspecify these errors to get a beautiful FFT dump of the FIR. const double I0e = 1e-10; double sum, u, halfx, temp; int n; sum = u = n = 1; halfx = x/2.0; do { temp = halfx/n++; u *= temp*temp; sum += u; } while (u >= I0e*sum); return sum; } // ---------------------------------------------------------------------------- // Setting of SID sampling parameters. // // Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64. // The default end of passband frequency is pass_freq = 0.9*sample_freq/2 // for sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample // frequencies. // // For resampling, the ratio between the clock frequency and the sample // frequency is limited as follows: // 125*clock_freq/sample_freq < 16384 // E.g. provided a clock frequency of ~ 1MHz, the sample frequency can not // be set lower than ~ 8kHz. A lower sample frequency would make the // resampling code overfill its 16k sample ring buffer. // // The end of passband frequency is also limited: // pass_freq <= 0.9*sample_freq/2 // E.g. for a 44.1kHz sampling rate the end of passband frequency is limited // to slightly below 20kHz. This constraint ensures that the FIR table is // not overfilled. // ---------------------------------------------------------------------------- bool SIDFP::set_sampling_parameters(double clock_freq, sampling_method method, double sample_freq, double pass_freq) { filter.set_clock_frequency(static_cast(clock_freq * 0.5)); extfilt.set_clock_frequency(static_cast(clock_freq * 0.5)); cycles_per_sample = static_cast(clock_freq / sample_freq); // FIR initialization is only necessary for resampling. if (method != SAMPLE_RESAMPLE_INTERPOLATE) { sampling = method; delete[] sample; delete[] fir; sample = 0; fir = 0; sample_prev = 0; return true; } sample_offset = 0; // Allocate sample buffer. if (!sample) sample = new float[RINGSIZE*2]; // Clear sample buffer. for (int j = 0; j < RINGSIZE*2; j++) sample[j] = 0; sample_index = 0; /* Up to 20 kHz or at most 90 % of passband if it's lower than 20 kHz. */ if (pass_freq > 20000) pass_freq = 20000; if (2*pass_freq/sample_freq > 0.9) pass_freq = 0.9*sample_freq/2; // 16 bits -> -96dB stopband attenuation. const double A = -20*log10(1.0/(1 << 16)); // For calculation of beta and N see the reference for the kaiserord // function in the MATLAB Signal Processing Toolbox: // http://www.mathworks.com/access/helpdesk/help/toolbox/signal/kaiserord.html const double beta = 0.1102*(A - 8.7); const double I0beta = I0(beta); // Since we clock the filter at half the rate, we need to design the FIR // with the reduced rate in mind. double f_cycles_per_sample = (clock_freq * 0.5)/sample_freq; double f_samples_per_cycle = sample_freq/(clock_freq * 0.5); double aliasing_allowance = sample_freq / 2 - 20000; // no allowance to 20 kHz if (aliasing_allowance < 0) aliasing_allowance = 0; double transition_bandwidth = sample_freq/2 - pass_freq + aliasing_allowance; { // The filter order will maximally be 124 with the current constraints. // N >= (96.33 - 7.95)/(2 * pi * 2.285 * (maxfreq - passbandfreq) >= 123 // The filter order is equal to the number of zero crossings, i.e. // it should be an even number (sinc is symmetric about x = 0). // // XXX: analysis indicates that the filter is slighly overspecified by // there constraints. Need to check why. One possibility is the // level of audio being in truth closer to 15-bit than 16-bit. int N = static_cast((A - 7.95)/(2 * M_PI * 2.285 * transition_bandwidth/sample_freq) + 0.5); N += N & 1; // The filter length is equal to the filter order + 1. // The filter length must be an odd number (sinc is symmetric about x = 0). fir_N = static_cast(N*f_cycles_per_sample) + 1; fir_N |= 1; // Check whether the sample ring buffer would overfill. if (fir_N > RINGSIZE - 1) return false; /* Error is bound by 1.234 / L^2, so for 16-bit: sqrt(1.234 * (1 << 16)) */ fir_RES = static_cast(sqrt(1.234 * (1 << 16)) / f_cycles_per_sample + 0.5); } sampling = method; // Allocate memory for FIR tables. delete[] fir; fir = new float[fir_N*fir_RES]; // The cutoff frequency is midway through the transition band double wc = (pass_freq + transition_bandwidth/2) / sample_freq * M_PI * 2; // Calculate fir_RES FIR tables for linear interpolation. for (int i = 0; i < fir_RES; i++) { double j_offset = double(i)/fir_RES; // Calculate FIR table. This is the sinc function, weighted by the // Kaiser window. for (int j = 0; j < fir_N; j ++) { double jx = double(j) - fir_N/2.f - j_offset; double wt = wc*jx/f_cycles_per_sample; double temp = jx/(fir_N/2); double Kaiser = fabs(temp) <= 1 ? I0(beta*sqrt(1 - temp*temp))/I0beta : 0; // between 1e-7 and 1e-8 the FP result approximates to 1 due to FP limits double sincwt = fabs(wt) >= 1e-8 ? sin(wt)/wt : 1; fir[i * fir_N + j] = static_cast(f_samples_per_cycle*wc/M_PI*sincwt*Kaiser); } } return true; } inline void SIDFP::age_bus_value(cycle_count n) { // Age bus value. This is not supposed to be cycle exact, // so it should be safe to approximate. if (bus_value_ttl != 0) { bus_value_ttl -= n; if (bus_value_ttl <= 0) { bus_value = 0; bus_value_ttl = 0; } } } // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- void SIDFP::clock() { // Clock amplitude modulators. for (int i = 0; i < 3; i++) { voice[i].envelope.clock(); voice[i].wave.clock(); } voice[0].wave.synchronize(voice[1].wave, voice[2].wave); voice[1].wave.synchronize(voice[2].wave, voice[0].wave); voice[2].wave.synchronize(voice[0].wave, voice[1].wave); /* because the analog parts are relatively expensive and do not really need * the precision of 1 MHz calculations, I average successive samples here to * reduce the cpu drain for filter calculations and output resampling. */ float voicestate[3]; voicestate[0] = voice[0].output(voice[2].wave); voicestate[1] = voice[1].output(voice[0].wave); voicestate[2] = voice[2].output(voice[1].wave); /* for every second sample in sequence, clock filter */ if (filtercyclegate ++ & 1) { extfilt.clock(filter.clock( (lastsample[0] + voicestate[0]) * 0.5f, (lastsample[1] + voicestate[1]) * 0.5f, (lastsample[2] + voicestate[2]) * 0.5f, ext_in )); } lastsample[0] = voicestate[0]; lastsample[1] = voicestate[1]; lastsample[2] = voicestate[2]; } // ---------------------------------------------------------------------------- // SID clocking with audio sampling. // // The example below shows how to clock the SID a specified amount of cycles // while producing audio output: // // while (delta_t) { // bufindex += sid.clock(delta_t, buf + bufindex, buflength - bufindex); // write(dsp, buf, bufindex*2); // bufindex = 0; // } // // ---------------------------------------------------------------------------- int SIDFP::clock(cycle_count& delta_t, short* buf, int n, int interleave) { /* XXX I assume n is generally large enough for delta_t here... */ age_bus_value(delta_t); /* We can only control that SSE is really used for GCC */ #if defined(__SSE__) && defined(__GNUC__) int old = _mm_getcsr(); _mm_setcsr(old | _MM_FLUSH_ZERO_ON); #endif int res; switch (sampling) { default: case SAMPLE_INTERPOLATE: res = clock_interpolate(delta_t, buf, n, interleave); break; case SAMPLE_RESAMPLE_INTERPOLATE: res = clock_resample_interpolate(delta_t, buf, n, interleave); break; } #if defined(__SSE__) && defined(__GNUC__) _mm_setcsr(old); #else filter.nuke_denormals(); extfilt.nuke_denormals(); #endif return res; } int SIDFP::clock_fast(cycle_count& delta_t, short* buf, int n, int interleave) { age_bus_value(delta_t); #if defined(__SSE__) && defined(__GNUC__) int old = _mm_getcsr(); _mm_setcsr(old | _MM_FLUSH_ZERO_ON); #endif int res = clock_interpolate(delta_t, buf, n, interleave); #if defined(__SSE__) && defined(__GNUC__) _mm_setcsr(old); #else filter.nuke_denormals(); extfilt.nuke_denormals(); #endif return res; } // ---------------------------------------------------------------------------- // SID clocking with audio sampling - cycle based with linear sample // interpolation. // // Here the chip is clocked every cycle. This yields higher quality // sound since the samples are linearly interpolated, and since the // external filter attenuates frequencies above 16kHz, thus reducing // sampling noise. // ---------------------------------------------------------------------------- inline int SIDFP::clock_interpolate(cycle_count& delta_t, short* buf, int n, int interleave) { int s = 0; int i; for (;;) { float next_sample_offset = sample_offset + cycles_per_sample; int delta_t_sample = static_cast(next_sample_offset); if (delta_t_sample > delta_t) { break; } if (s >= n) { return s; } for (i = 0; i < delta_t_sample - 1; i++) { clock(); } if (i < delta_t_sample) { sample_prev = output(); clock(); } delta_t -= delta_t_sample; sample_offset = next_sample_offset - delta_t_sample; float sample_now = output(); int sample_int = (int)((sample_prev + (sample_offset * (sample_now - sample_prev))) * 32768.0f); if (sample_int < -32768) sample_int = -32768; if (sample_int > 32767) sample_int = 32767; buf[s++ * interleave] = sample_int; sample_prev = sample_now; } for (i = 0; i < delta_t - 1; i++) { clock(); } if (i < delta_t) { sample_prev = output(); clock(); } sample_offset -= delta_t; delta_t = 0; return s; } static float convolve(const float *a, const float *b, int n) { float out = 0.f; #ifdef __SSE__ __m128 out4 = { 0, 0, 0, 0 }; /* examine if we can use aligned loads on both pointers -- some x86-32/64 * hackery here ... should use uintptr_t, but that needs --std=C99... */ int diff = static_cast(a - b) & 0xf; int a_align = static_cast(reinterpret_cast(a)) & 0xf; /* advance if necessary. We can't let n fall < 0, so no while (n --). */ while (n > 0 && a_align != 0 && a_align != 16) { out += (*(a ++)) * (*(b ++)); n --; a_align += 4; } if (diff == 0) { while (n >= 4) { out4 = _mm_add_ps(out4, _mm_mul_ps(_mm_load_ps(a), _mm_load_ps(b))); a += 4; b += 4; n -= 4; } } else { /* loadu is difficult to optimize: * * - using load and movhl tricks to sync the halves was not noticeably * faster, less than 1 % and that might have been measurement error. * - preparing copies of b for syncing with any alignment increased * memory pressure to the point that cache misses made it slower! */ while (n >= 4) { out4 = _mm_add_ps(out4, _mm_mul_ps(_mm_load_ps(a), _mm_loadu_ps(b))); a += 4; b += 4; n -= 4; } } /* sum the upper half of values with the lower half, pairwise */ out4 = _mm_add_ps(_mm_movehl_ps(out4, out4), out4); /* sum the value at slot 1 with the value at slot 0 */ out4 = _mm_add_ss(_mm_shuffle_ps(out4, out4, 1), out4); float out_tmp; /* save slot 0 to out_tmp, which is now 0+1+2+3 */ _mm_store_ss(&out_tmp, out4); out += out_tmp; #endif while (n --) out += (*(a ++)) * (*(b ++)); return out; } // ---------------------------------------------------------------------------- // SID clocking with audio sampling - cycle based with audio resampling. // // This is the theoretically correct (and computationally intensive) audio // sample generation. The samples are generated by resampling to the specified // sampling frequency. The work rate is inversely proportional to the // percentage of the bandwidth allocated to the filter transition band. // // This implementation is based on the paper "A Flexible Sampling-Rate // Conversion Method", by J. O. Smith and P. Gosset, or rather on the // expanded tutorial on the "Digital Audio Resampling Home Page": // http://www-ccrma.stanford.edu/~jos/resample/ // // By building shifted FIR tables with samples according to the // sampling frequency, this implementation dramatically reduces the // computational effort in the filter convolutions, without any loss // of accuracy. The filter convolutions are also vectorizable on // current hardware. // // Further possible optimizations are: // * An equiripple filter design could yield a lower filter order, see // http://www.mwrf.com/Articles/ArticleID/7229/7229.html // * The Convolution Theorem could be used to bring the complexity of // convolution down from O(n*n) to O(n*log(n)) using the Fast Fourier // Transform, see http://en.wikipedia.org/wiki/Convolution_theorem // * Simply resampling in two steps can also yield computational // savings, since the transition band will be wider in the first step // and the required filter order is thus lower in this step. // Laurent Ganier has found the optimal intermediate sampling frequency // to be (via derivation of sum of two steps): // 2 * pass_freq + sqrt [ 2 * pass_freq * orig_sample_freq // * (dest_sample_freq - 2 * pass_freq) / dest_sample_freq ] // // NB! the result of right shifting negative numbers is really // implementation dependent in the C++ standard. // ---------------------------------------------------------------------------- inline int SIDFP::clock_resample_interpolate(cycle_count& delta_t, short* buf, int n, int interleave) { int s = 0; for (;;) { float next_sample_offset = sample_offset + cycles_per_sample; /* full clocks left to next sample */ int delta_t_sample = static_cast(next_sample_offset); if (delta_t_sample > delta_t || s >= n) break; /* clock forward delta_t_sample samples */ for (int i = 0; i < delta_t_sample; i++) { clock(); if (filtercyclegate & 1) { sample[sample_index] = sample[sample_index + RINGSIZE] = output(); ++ sample_index; sample_index &= RINGSIZE - 1; } } delta_t -= delta_t_sample; /* Phase of the sample in terms of clock, [0 .. 1[. */ sample_offset = next_sample_offset - static_cast(delta_t_sample); /* find the first of the nearest fir tables close to the phase */ float fir_offset_rmd = sample_offset * fir_RES; int fir_offset = static_cast(fir_offset_rmd); /* [0 .. 1[ */ fir_offset_rmd -= static_cast(fir_offset); /* find fir_N most recent samples, plus one extra in case the FIR wraps. */ float* sample_start = sample + sample_index - fir_N + RINGSIZE - 1; float v1 = convolve(sample_start, fir + fir_offset * fir_N, fir_N); // Use next FIR table, wrap around to first FIR table using // the next sample. if (++ fir_offset == fir_RES) { fir_offset = 0; ++ sample_start; } float v2 = convolve(sample_start, fir + fir_offset * fir_N, fir_N); // Linear interpolation between the sinc tables yields good approximation // for the exact value. int sample_int = (int)((v1 + fir_offset_rmd * (v2 - v1)) * 32768.0f); if (sample_int < -32768) sample_int = -32768; if (sample_int > 32767) sample_int = 32767; buf[s++ * interleave] = sample_int; } /* clock forward delta_t samples */ for (int i = 0; i < delta_t; i++) { clock(); if (filtercyclegate & 1) { sample[sample_index] = sample[sample_index + RINGSIZE] = output(); ++ sample_index; sample_index &= RINGSIZE - 1; } } sample_offset -= static_cast(delta_t); delta_t = 0; return s; } goattracker-2.72/src/resid-fp/siddefsfp.h0000644000000000000000000000212711313456432017074 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 1999 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __SIDDEFSFP_H__ #define __SIDDEFSFP_H__ #include "../resid/siddefs.h" #endif // not __SIDDEFSFP_H__ goattracker-2.72/src/resid-fp/extfiltfp.cpp0000644000000000000000000000411011313456432017457 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "extfiltfp.h" const float pass_frequency = 15915.6f; // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- ExternalFilterFP::ExternalFilterFP() { reset(); set_clock_frequency(1e6f); } // ---------------------------------------------------------------------------- // Setup of the external filter sampling parameters. // ---------------------------------------------------------------------------- void ExternalFilterFP::set_clock_frequency(float clock_frequency) { // Low-pass: R = 10kOhm, C = 1000pF; w0l = 1/RC = 1/(1e4*1e-9) = 100000 // High-pass: R = 1kOhm, C = 10uF; w0h = 1/RC = 1/(1e3*1e-5) = 100 w0hp = 100.f / clock_frequency; w0lp = pass_frequency * 2.f * static_cast(M_PI) / clock_frequency; } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void ExternalFilterFP::reset() { // State of filter. Vlp = 0; Vhp = 0; } goattracker-2.72/src/resid-fp/filterfp.cpp0000644000000000000000000001135311313456432017274 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- // Filter distortion code written by Antti S. Lankila 2007 - 2009. #include "filterfp.h" #include "sidfp.h" // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- FilterFP::FilterFP() { model = (chip_model) 0; // neither 6581/8580; init time only enable_filter(true); /* approximate; sid.cc calls us when set_sampling_parameters() occurs. */ set_clock_frequency(1e6f); /* these parameters are a work-in-progress. */ set_distortion_properties(0.5f, 3.3e6f, 3.0e-4f); /* sound similar to alankila6581r4ar3789 */ set_type3_properties(1299501.5675945764f, 284015710.29875594f, 1.0065089724604026f, 18741.324073610594f); /* sound similar to trurl8580r5_3691 */ set_type4_properties(6.55f, 20.f); reset(); set_chip_model(MOS6581); } // ---------------------------------------------------------------------------- // Enable filter. // ---------------------------------------------------------------------------- void FilterFP::enable_filter(bool enable) { enabled = enable; if (! enabled) filt = 0; // XXX should also restore this... } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void FilterFP::set_chip_model(chip_model model) { this->model = model; set_Q(); set_w0(); } void FilterFP::set_nonlinearity(float nl) { nonlinearity = nl; set_w0(); } /* dist_CT eliminates 1/x at hot spot */ void FilterFP::set_clock_frequency(float clock) { clock_frequency = clock; distortion_CT = 1.f / (sidcaps_6581 * clock_frequency); set_w0(); } void FilterFP::set_distortion_properties(float a, float nl, float il) { attenuation = a; distortion_nonlinearity = nl; intermixing_leaks = il; set_w0(); } void FilterFP::set_type4_properties(float k, float b) { type4_k = k; type4_b = b; set_w0(); } void FilterFP::set_type3_properties(float br, float o, float s, float mfr) { type3_baseresistance = br; type3_offset = o; type3_steepness = -logf(s) / FC_TO_OSC; /* s^x to e^(x*ln(s)), 1/e^x == e^-x. */ type3_minimumfetresistance = mfr; set_w0(); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void FilterFP::reset() { fc = 0; res = filt = voice3off = hp_bp_lp = 0; vol = 0; volf = Vhp = Vbp = Vlp = 0; type3_fc_kink_exp = 0; type4_w0_cache = 0; set_w0(); set_Q(); } // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void FilterFP::writeFC_LO(reg8 fc_lo) { fc = (fc & 0x7f8) | (fc_lo & 0x007); set_w0(); } void FilterFP::writeFC_HI(reg8 fc_hi) { fc = ((fc_hi << 3) & 0x7f8) | (fc & 0x007); set_w0(); } void FilterFP::writeRES_FILT(reg8 res_filt) { res = (res_filt >> 4) & 0x0f; set_Q(); filt = enabled ? res_filt & 0x0f : 0; } void FilterFP::writeMODE_VOL(reg8 mode_vol) { voice3off = mode_vol & 0x80; hp_bp_lp = mode_vol >> 4; vol = mode_vol & 0x0f; volf = static_cast(vol) / 15.f; } // Set filter cutoff frequency. void FilterFP::set_w0() { if (model == MOS6581) { float type3_fc_kink = SIDFP::kinked_dac(fc, nonlinearity, 11); type3_fc_kink_exp = type3_offset * expf(type3_fc_kink * type3_steepness * FC_TO_OSC); } if (model == MOS8580) { type4_w0_cache = type4_w0(); } } // Set filter resonance. void FilterFP::set_Q() { if (model == MOS6581) { _1_div_Q = 1.f / (0.5f + res / 20.f); } else { _1_div_Q = 1.f / (0.707f + res / 15.f); } } goattracker-2.72/src/resid-fp/filterfp.h0000644000000000000000000002535511313456432016750 0ustar rootroot// This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- // Filter distortion code written by Antti S. Lankila 2007 - 2009. #ifndef __FILTERFP_H__ #define __FILTERFP_H__ #include #include "siddefsfp.h" // ---------------------------------------------------------------------------- // The SID filter is modeled with a two-integrator-loop biquadratic filter, // which has been confirmed by Bob Yannes to be the actual circuit used in // the SID chip. // // Measurements show that excellent emulation of the SID filter is achieved, // except when high resonance is combined with high sustain levels. // In this case the SID op-amps are performing less than ideally and are // causing some peculiar behavior of the SID filter. This however seems to // have more effect on the overall amplitude than on the color of the sound. // // The theory for the filter circuit can be found in "Microelectric Circuits" // by Adel S. Sedra and Kenneth C. Smith. // The circuit is modeled based on the explanation found there except that // an additional inverter is used in the feedback from the bandpass output, // allowing the summer op-amp to operate in single-ended mode. This yields // inverted filter outputs with levels independent of Q, which corresponds with // the results obtained from a real SID. // // We have been able to model the summer and the two integrators of the circuit // to form components of an IIR filter. // Vhp is the output of the summer, Vbp is the output of the first integrator, // and Vlp is the output of the second integrator in the filter circuit. // // According to Bob Yannes, the active stages of the SID filter are not really // op-amps. Rather, simple NMOS inverters are used. By biasing an inverter // into its region of quasi-linear operation using a feedback resistor from // input to output, a MOS inverter can be made to act like an op-amp for // small signals centered around the switching threshold. // // Qualified guesses at SID filter schematics are depicted below. // // SID filter // ---------- // // ----------------------------------------------- // | | // | ---Rq-- | // | | | | // | --------------|--R-----[A>--|--R-----[A>--| // | | | | // vi -----R1-- | | | // // vhp vbp vlp // // // vi - input voltage // vhp - highpass output // vbp - bandpass output // vlp - lowpass output // [A> - op-amp // R1 - summer resistor // Rq - resistor array controlling resonance (4 resistors) // R - NMOS FET voltage controlled resistor controlling cutoff frequency // Rs - shunt resitor // C - capacitor // // // // SID integrator // -------------- // // V+ // // | // | // -----| // | | // | ||-- // -|| // ---C--- ||-> // | | | // |---Rs-----------|---- vo // | | // | ||-- // vi ---- -----|------------|| // | ^ | ||-> // |___| | | // ----- | | // | | | // |---R2-- | // | // R1 V- // | // | // // Vw // // ---------------------------------------------------------------------------- class FilterFP { public: FilterFP(); void enable_filter(bool enable); void set_chip_model(chip_model model); void set_distortion_properties(float, float, float); void set_type3_properties(float, float, float, float); void set_type4_properties(float, float); void set_clock_frequency(float); void set_nonlinearity(float); inline float clock(float voice1, float voice2, float voice3, float ext_in); void reset(); // Write registers. void writeFC_LO(reg8); void writeFC_HI(reg8); void writeRES_FILT(reg8); void writeMODE_VOL(reg8); private: void set_Q(); void set_w0(); float type3_w0(const float dist); float type4_w0(); void calculate_helpers(); void nuke_denormals(); float waveshaper1(float value); float waveshaper2(float value); // Filter enabled. bool enabled; // 6581/8580 filter model (XXX: we should specialize in separate classes) chip_model model; // Filter cutoff frequency. reg12 fc; // Filter resonance. reg8 res; // Selects which inputs to route through filter. reg8 filt; // Switch voice 3 off. reg8 voice3off; // Highpass, bandpass, and lowpass filter modes. reg8 hp_bp_lp; // Output master volume. reg4 vol; float volf; /* avoid integer-to-float conversion at output */ // clock float clock_frequency; /* Distortion params for Type3 */ float attenuation, distortion_nonlinearity, intermixing_leaks; /* Type3 params. */ float type3_baseresistance, type3_offset, type3_steepness, type3_minimumfetresistance; /* Type4 params */ float type4_k, type4_b; // State of filter. float Vhp, Vbp, Vlp; /* Resonance/Distortion/Type3/Type4 helpers. */ float type4_w0_cache, _1_div_Q, type3_fc_kink_exp, distortion_CT; float nonlinearity; friend class SIDFP; }; // ---------------------------------------------------------------------------- // Inline functions. // The following functions are defined inline because they are called every // time a sample is calculated. // ---------------------------------------------------------------------------- const float sidcaps_6581 = 470e-12f; const float FC_TO_OSC = 512.f; inline static float fastexp(float val) { typedef union { int i; float f; } conv; conv tmp; /* single precision fp has 1 + 8 + 23 bits, exponent bias is 127. * It therefore follows that we need to shift left by 23 bits, and to * calculate exp(x) instead of pow(2, x) we divide the power by ln(2). */ const float a = static_cast((1 << 23) / M_LN2); /* The other factor corrects for the exponent bias so that 2^0 = 1. */ const float b = static_cast((1 << 23) * 127); /* According to "A Fast, Compact Approximation of the Exponential Function" * by Nicol N. Schraudolph, 60801.48 yields the minimum RMS error for the * piecewise-linear approximation when using doubles (20 bits residual). * We have 23 bits, so we scale this value by 8. */ const float c = 60801.48f * 8.f; /* Parenthesis are important: C standard disallows folding subtraction. * Unfortunately GCC appears to generate a write to memory rather than * handle this conversion entirely in registers. */ tmp.i = static_cast(a * val + (b - c + 0.5f)); return tmp.f; } inline float FilterFP::type3_w0(const float dist) { float fetresistance = type3_fc_kink_exp; if (dist > 0) { fetresistance *= fastexp(dist * type3_steepness); } const float dynamic_resistance = type3_minimumfetresistance + fetresistance; /* 2 parallel resistors */ const float _1_div_resistance = (type3_baseresistance + dynamic_resistance) / (type3_baseresistance * dynamic_resistance); /* 1.f / (clock * caps * resistance) */ return distortion_CT * _1_div_resistance; } inline float FilterFP::type4_w0() { const float freq = type4_k * fc + type4_b; return 2.f * static_cast(M_PI) * freq / clock_frequency; } inline float FilterFP::waveshaper1(float value) { if (value > distortion_nonlinearity) { value -= (value - distortion_nonlinearity) * 0.5f; } return value; } // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- inline float FilterFP::clock(float voice1, float voice2, float voice3, float ext_in) { float Vi = 0.f, Vf = 0.f; // Route voices into or around filter. ((filt & 1) ? Vi : Vf) += voice1; ((filt & 2) ? Vi : Vf) += voice2; // NB! Voice 3 is not silenced by voice3off if it is routed through // the filter. if (filt & 4) { Vi += voice3; } else if (! voice3off) { Vf += voice3; } ((filt & 8) ? Vi : Vf) += ext_in; if (hp_bp_lp & 1) { Vf += Vlp; } if (hp_bp_lp & 2) { Vf += Vbp; } if (hp_bp_lp & 4) { Vf += Vhp; } if (model == MOS6581) { Vlp -= Vbp * type3_w0(Vbp); Vbp -= Vhp * type3_w0(Vhp); Vhp = (Vbp * _1_div_Q - Vlp - Vi * 0.85f) * attenuation; /* output strip mixing to filter state */ if (hp_bp_lp & 1) { Vlp += Vf * intermixing_leaks; } if (hp_bp_lp & 2) { Vbp += Vf * intermixing_leaks; } if (hp_bp_lp & 4) { Vhp += Vf * intermixing_leaks; } /* saturate. This is likely the output inverter saturation. */ Vf *= volf; Vf = waveshaper1(Vf); } else { /* On the 8580, BP appears mixed in phase with the rest. */ Vlp += Vbp * type4_w0_cache; Vbp += Vhp * type4_w0_cache; Vhp = -Vbp * _1_div_Q - Vlp - Vi; Vf *= volf; } return Vf; } inline void FilterFP::nuke_denormals() { /* We only need this for systems that don't do -msse and -mfpmath=sse */ if (Vbp > -1e-12f && Vbp < 1e-12f) Vbp = 0; if (Vlp > -1e-12f && Vlp < 1e-12f) Vlp = 0; } #endif // not __FILTER_H__ goattracker-2.72/src/resid-fp/versionfp.cpp0000644000000000000000000000203111313456432017465 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __VERSIONFP_CC__ #include "siddefsfp.h" goattracker-2.72/src/resid-fp/envelopefp.h0000644000000000000000000001243011313456432017266 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __ENVELOPEFP_H__ #define __ENVELOPEFP_H__ #include "siddefsfp.h" extern float env_dac[256]; // ---------------------------------------------------------------------------- // A 15 bit counter is used to implement the envelope rates, in effect // dividing the clock to the envelope counter by the currently selected rate // period. // In addition, another counter is used to implement the exponential envelope // decay, in effect further dividing the clock to the envelope counter. // The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope // counter values 255, 93, 54, 26, 14, 6, respectively. // ---------------------------------------------------------------------------- class EnvelopeGeneratorFP { public: EnvelopeGeneratorFP(); enum State { ATTACK, DECAY_SUSTAIN, RELEASE }; inline void clock(); void reset(); void mute(bool enable); void writeCONTROL_REG(reg8); void writeATTACK_DECAY(reg8); void writeSUSTAIN_RELEASE(reg8); reg8 readENV(); inline float output(); protected: void set_nonlinearity(float nl); void update_rate_period(reg16 period); int rate_counter; int rate_period; reg8 exponential_counter; reg8 exponential_counter_period; reg8 envelope_counter; float envelope_counter_dac; bool hold_zero; bool muted; reg4 attack; reg4 decay; reg4 sustain; reg4 release; reg8 gate; State state; // Lookup table to convert from attack, decay, or release value to rate // counter period. static reg16 rate_counter_period[]; // The 16 selectable sustain levels. static reg8 sustain_level[]; friend class SIDFP; }; // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- inline void EnvelopeGeneratorFP::clock() { if (++ rate_counter != rate_period) return; rate_counter = 0; // The first envelope step in the attack state also resets the exponential // counter. This has been verified by sampling ENV3. // if (state == ATTACK || ++exponential_counter == exponential_counter_period) { exponential_counter = 0; // Check whether the envelope counter is frozen at zero. if (hold_zero) { return; } switch (state) { case ATTACK: // The envelope counter can flip from 0xff to 0x00 by changing state to // release, then to attack. The envelope counter is then frozen at // zero; to unlock this situation the state must be changed to release, // then to attack. This has been verified by sampling ENV3. // ++envelope_counter &= 0xff; if (envelope_counter == 0xff) { state = DECAY_SUSTAIN; update_rate_period(rate_counter_period[decay]); } break; case DECAY_SUSTAIN: if (envelope_counter != sustain_level[sustain]) { --envelope_counter; } break; case RELEASE: // The envelope counter can flip from 0x00 to 0xff by changing state to // attack, then to release. The envelope counter will then continue // counting down in the release state. // This has been verified by sampling ENV3. // NB! The operation below requires two's complement integer. // --envelope_counter &= 0xff; break; } // Check for change of exponential counter period. switch (envelope_counter) { case 0xff: exponential_counter_period = 1; break; case 0x5d: exponential_counter_period = 2; break; case 0x36: exponential_counter_period = 4; break; case 0x1a: exponential_counter_period = 8; break; case 0x0e: exponential_counter_period = 16; break; case 0x06: exponential_counter_period = 30; break; case 0x00: exponential_counter_period = 1; // When the envelope counter is changed to zero, it is frozen at zero. // This has been verified by sampling ENV3. hold_zero = true; break; } envelope_counter_dac = muted ? 0.f : env_dac[envelope_counter]; } } // ---------------------------------------------------------------------------- // Read the envelope generator output. // ---------------------------------------------------------------------------- inline float EnvelopeGeneratorFP::output() { return envelope_counter_dac; } #endif // not __ENVELOPE_H__ goattracker-2.72/src/resid-fp/wavefp.cpp0000644000000000000000000002344111313456432016752 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wavefp.h" #include "sidfp.h" typedef struct { float bias; float pulsestrength; float topbit; float distance; float stmix; } waveformconfig_t; const float sharpness = 512.f; const waveformconfig_t wfconfig[2][5] = { { /* kevtris chip G (6581) */ { 0.880815f, 0.f, 0.f, 0.3279614f, 0.5999545f }, // error 1795 { 0.8924618f, 2.014781f, 1.003332f, 0.02992322f, 0.0f }, // error 11610 { 0.8646501f, 1.712586f, 1.137704f, 0.02845423f, 0.f }, // error 21307 { 0.9527834f, 1.794777f, 0.f, 0.09806272f, 0.7752482f }, // error 196 { 0.5f, 0.0f, 1.0f, 0.0f, 0.0f, }, }, { /* kevtris chip V (8580) */ { 0.9781665f, 0.f, 0.9899469f, 8.087667f, 0.8226412f }, // error 5546 { 0.9097769f, 2.039997f, 0.9584096f, 0.1765447f, 0.f }, // error 18763 { 0.9231212f, 2.084788f, 0.9493895f, 0.1712518f, 0.f }, // error 17103 { 0.9845552f, 1.415612f, 0.9703883f, 3.68829f, 0.8265008f }, // error 3319 { 0.5f, 0.0f, 1.0f, 0.0f, 0.0f }, } }; /* render output from bitstate */ static float make_sample(float *o) { float out = 0; for (int i = 0; i < 12; i ++) { out += o[i] * dac[i]; } return out; } /* generate tables for waveforms 1 .. 7 */ void WaveformGeneratorFP::rebuild_wftable() { float o[12]; reg8 oldwf = waveform; reg32 oldacc = accumulator; reg12 oldpw = pw; for (waveform = 1; waveform < 8; waveform ++) { for (accumulator = 0; accumulator < (1<<24); accumulator += (1<<12)) { /* generate pulse-low variants. Also, * when waveform < 4, pw doesn't matter. */ pw = 0x1000; /* pulse always low */ calculate_waveform_sample(o); wftable[waveform - 1][accumulator >> 12] = make_sample(o) + wave_zero; /* Add pulse-high variants after pulse-low state variants */ if (waveform >= 4) { pw = 0x000; /* pulse always high */ calculate_waveform_sample(o); wftable[waveform + 3][accumulator >> 12] = make_sample(o) + wave_zero; } } } waveform = oldwf; accumulator = oldacc; pw = oldpw; } /* explode reg12 to a floating point bit array */ static void populate(reg12 v, float o[12]) { int j = 1; for (int i = 0; i < 12; i ++) { o[i] = v & j ? 1.f : 0.f; j <<= 1; } } /* waveform values valid are 1 .. 7 */ void WaveformGeneratorFP::calculate_waveform_sample(float o[12]) { int i; /* P */ if (waveform == 4) { populate((accumulator >> 12) >= pw ? 0xfff : 0x000, o); return; } const waveformconfig_t config = wfconfig[ model == MOS6581 ? 0 : 1 ][ waveform == 3 ? 0 : waveform == 5 ? 1 : waveform == 6 ? 2 : waveform == 7 ? 3 : 4 ]; /* S with strong top bit for 6581 */ populate(accumulator >> 12, o); /* convert to T */ if ((waveform & 3) == 1) { bool top = (accumulator & 0x800000) != 0; for (i = 11; i > 0; i --) { if (top) { o[i] = 1.0f - o[i-1]; } else { o[i] = o[i-1]; } } o[0] = 0; } /* convert to ST */ if ((waveform & 3) == 3) { /* bottom bit is grounded via T waveform selector */ o[0] *= config.stmix; for (i = 1; i < 12; i ++) { o[i] = o[i - 1] * (1.f - config.stmix) + o[i] * config.stmix; } } o[11] *= config.topbit; /* ST, P* waveform? */ if (waveform == 3 || waveform > 4) { float distancetable[12 * 2 + 1]; for (i = 0; i <= 12; i ++) { distancetable[12+i] = distancetable[12-i] = 1.f / (1.f + i * i * config.distance); } float pulse = (accumulator >> 12) >= pw ? 1.f : -1.f; pulse *= config.pulsestrength; float tmp[12]; for (i = 0; i < 12; i ++) { float avg = 0; float n = 0; for (int j = 0; j < 12; j ++) { float weight = distancetable[i - j + 12]; avg += o[j] * weight; n += weight; } /* pulse control bit */ if (waveform > 4) { float weight = distancetable[i - 12 + 12]; avg += pulse * weight; n += weight; } tmp[i] = (o[i] + avg / n) * 0.5f; } for (i = 0; i < 12; i ++) { o[i] = tmp[i]; } } /* use the environment around bias value to set/clear dac bit. The * relationship is nonlinear because that seems to sound a bit better. */ for (i = 0; i < 12; i ++) { o[i] = (o[i] - config.bias) * sharpness; o[i] += 0.5f; if (o[i] > 1.f) { o[i] = 1.f; } if (o[i] < 0.f) { o[i] = 0.; } } } void WaveformGeneratorFP::set_nonlinearity(float nl) { for (int i = 0; i < 12; i ++) { dac[i] = SIDFP::kinked_dac((1 << i), nl, 12); } } // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- WaveformGeneratorFP::WaveformGeneratorFP() { set_chip_model(MOS6581); reset(); } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void WaveformGeneratorFP::set_chip_model(chip_model model) { this->model = model; wave_zero = static_cast(model == MOS6581 ? -0x380 : -0x800); } // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void WaveformGeneratorFP::writeFREQ_LO(reg8 freq_lo) { freq = (freq & 0xff00) | (freq_lo & 0xff); } void WaveformGeneratorFP::writeFREQ_HI(reg8 freq_hi) { freq = ((freq_hi << 8) & 0xff00) | (freq & 0xff); } void WaveformGeneratorFP::writePW_LO(reg8 pw_lo) { pw = (pw & 0xf00) | (pw_lo & 0x0ff); } void WaveformGeneratorFP::writePW_HI(reg8 pw_hi) { pw = ((pw_hi << 8) & 0xf00) | (pw & 0x0ff); } void WaveformGeneratorFP::writeCONTROL_REG(WaveformGeneratorFP& source, reg8 control) { /* when selecting the 0 waveform, the previous output is held for * a time in the DAC MOSFET gates. We keep on holding forever, though... */ reg4 waveform_next = (control >> 4) & 0x0f; if (waveform_next == 0 && waveform >= 1 && waveform <= 7) { previous = readOSC(source); previous_dac = output(source); } waveform = waveform_next; ring_mod = (control & 0x04) != 0; sync = (control & 0x02) != 0; bool test_next = (control & 0x08) != 0; // Test bit rising? Invert bit 19 and write it to bit 1. if (test_next && !test) { accumulator = 0; reg24 bit19 = (shift_register >> 18) & 2; shift_register = (shift_register & 0x7ffffd) | (bit19^2); noise_overwrite_delay = 200000; /* 200 ms, probably too generous? */ } else { if (! test_next) { // Test bit falling? clock noise once, // otherwise just emulate noise's combined waveforms. clock_noise(test); } } test = test_next; } reg8 WaveformGeneratorFP::readOSC(WaveformGeneratorFP& source) { float o[12]; if (waveform == 0 || waveform > 7) { return previous; } /* Include effects of the test bit & ring mod */ reg12 oldpw = pw; if (test) { pw = 0; } reg24 oldaccumulator = accumulator; accumulator ^= (waveform & 3) == 1 && ring_mod && (source.accumulator & 0x800000) ? 0x800000 : 0; calculate_waveform_sample(o); pw = oldpw; accumulator = oldaccumulator; reg8 out = 0; reg8 bit = 1; for (int i = 4; i < 12; i ++) { if (o[i] > 0.5f) { out |= bit; } bit <<= 1; } return out; } void WaveformGeneratorFP::clock_noise(const bool clock) { if (clock) { reg24 bit0 = ((shift_register >> 22) ^ (shift_register >> 17)) & 0x1; shift_register <<= 1; shift_register |= bit0; } // clear output bits of shift register if noise and other waveforms // are selected simultaneously if (waveform > 8) { shift_register &= 0x7fffff^(1<<22)^(1<<20)^(1<<16)^(1<<13)^(1<<11)^(1<<7)^(1<<4)^(1<<2); } if (waveform >= 8) { previous = outputN___() >> 4; previous_dac = wave_zero; for (int i = 0; i < 8; i ++) { if (previous & (1 << i)) { previous_dac += dac[i+4]; } } } } reg12 WaveformGeneratorFP::outputN___() { return ((shift_register & 0x400000) >> 11) | ((shift_register & 0x100000) >> 10) | ((shift_register & 0x010000) >> 7) | ((shift_register & 0x002000) >> 5) | ((shift_register & 0x000800) >> 4) | ((shift_register & 0x000080) >> 1) | ((shift_register & 0x000010) << 1) | ((shift_register & 0x000004) << 2); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void WaveformGeneratorFP::reset() { accumulator = 0; previous = 0; previous_dac = 0; shift_register = 0x7ffffc; freq = 0; pw = 0; test = 0; waveform = 0; writeCONTROL_REG(*this, 0); msb_rising = false; } goattracker-2.72/src/gorder.c0000644000000000000000000003421511460110232014660 0ustar rootroot// // GOATTRACKER v2 orderlist & songname editor // #define GORDER_C #include "goattrk2.h" unsigned char trackcopybuffer[MAX_SONGLEN+2]; int trackcopyrows = 0; int trackcopywhole; int trackcopyrpos; int espos[MAX_CHN]; int esend[MAX_CHN]; int eseditpos; int esview; int escolumn; int eschn; int esnum; int esmarkchn = -1; int esmarkstart; int esmarkend; int enpos; void orderlistcommands(void); void namecommands(void); void orderlistcommands(void) { int c, scrrep; if (hexnybble >= 0) { if (eseditpos != songlen[esnum][eschn]) { switch(escolumn) { case 0: songorder[esnum][eschn][eseditpos] &= 0x0f; songorder[esnum][eschn][eseditpos] |= hexnybble << 4; if (eseditpos < songlen[esnum][eschn]) { if (songorder[esnum][eschn][eseditpos] >= MAX_PATT) songorder[esnum][eschn][eseditpos] = MAX_PATT - 1; } else { if (songorder[esnum][eschn][eseditpos] >= MAX_SONGLEN) songorder[esnum][eschn][eseditpos] = MAX_SONGLEN - 1; } break; case 1: songorder[esnum][eschn][eseditpos] &= 0xf0; if ((songorder[esnum][eschn][eseditpos] & 0xf0) == 0xd0) { hexnybble--; if (hexnybble < 0) hexnybble = 0xf; } if ((songorder[esnum][eschn][eseditpos] & 0xf0) == 0xe0) { hexnybble = 16 - hexnybble; hexnybble &= 0xf; } songorder[esnum][eschn][eseditpos] |= hexnybble; if (eseditpos < songlen[esnum][eschn]) { if (songorder[esnum][eschn][eseditpos] == LOOPSONG) songorder[esnum][eschn][eseditpos] = LOOPSONG-1; if (songorder[esnum][eschn][eseditpos] == TRANSDOWN) songorder[esnum][eschn][eseditpos] = TRANSDOWN+0x0f; } else { if (songorder[esnum][eschn][eseditpos] >= MAX_SONGLEN) songorder[esnum][eschn][eseditpos] = MAX_SONGLEN - 1; } break; } escolumn++; if (escolumn > 1) { escolumn = 0; if (eseditpos < (songlen[esnum][eschn]+1)) { eseditpos++; if (eseditpos == songlen[esnum][eschn]) eseditpos++; } } } } switch(key) { case 'R': if (eseditpos < songlen[esnum][eschn]) { songorder[esnum][eschn][eseditpos] = REPEAT + 0x01; escolumn = 1; } break; case '+': if (eseditpos < songlen[esnum][eschn]) { songorder[esnum][eschn][eseditpos] = TRANSUP; escolumn = 1; } break; case '-': if (eseditpos < songlen[esnum][eschn]) { songorder[esnum][eschn][eseditpos] = TRANSDOWN + 0x0F; escolumn = 1; } break; case '>': case ')': case ']': nextsong(); break; case '<': case '(': case '[': prevsong(); break; } switch(rawkey) { case KEY_1: case KEY_2: case KEY_3: if (shiftpressed) { int schn = eschn; int tchn = 0; esmarkchn = -1; if (rawkey == KEY_1) tchn = 0; if (rawkey == KEY_2) tchn = 1; if (rawkey == KEY_3) tchn = 2; if (schn != tchn) { for (c = 0; c < MAX_SONGLEN+2; c++) { unsigned char temp = songorder[esnum][schn][c]; songorder[esnum][schn][c] = songorder[esnum][tchn][c]; songorder[esnum][tchn][c] = temp; } } } break; case KEY_X: if (shiftpressed) { if (esmarkchn != -1) { int d = 0; eschn = esmarkchn; if (esmarkstart <= esmarkend) { eseditpos = esmarkstart; for (c = esmarkstart; c <= esmarkend; c++) trackcopybuffer[d++] = songorder[esnum][eschn][c]; trackcopyrows = d; } else { eseditpos = esmarkend; for (c = esmarkend; c <= esmarkstart; c++) trackcopybuffer[d++] = songorder[esnum][eschn][c]; trackcopyrows = d; } if (trackcopyrows == songlen[esnum][eschn]) { trackcopywhole = 1; trackcopyrpos = songorder[esnum][eschn][songlen[esnum][eschn]+1]; } else trackcopywhole = 0; for (c = 0; c < trackcopyrows; c++) deleteorder(); esmarkchn = -1; } } break; case KEY_C: if (shiftpressed) { if (esmarkchn != -1) { int d = 0; if (esmarkstart <= esmarkend) { for (c = esmarkstart; c <= esmarkend; c++) trackcopybuffer[d++] = songorder[esnum][eschn][c]; trackcopyrows = d; } else { for (c = esmarkend; c <= esmarkstart; c++) trackcopybuffer[d++] = songorder[esnum][eschn][c]; trackcopyrows = d; } if (trackcopyrows == songlen[esnum][eschn]) { trackcopywhole = 1; trackcopyrpos = songorder[esnum][eschn][songlen[esnum][eschn]+1]; } else trackcopywhole = 0; esmarkchn = -1; } } break; case KEY_V: if (shiftpressed) { int oldlen = songlen[esnum][eschn]; if (eseditpos < songlen[esnum][eschn]) { for (c = trackcopyrows-1; c >= 0; c--) insertorder(trackcopybuffer[c]); } else { for (c = 0; c < trackcopyrows; c++) insertorder(trackcopybuffer[c]); } if ((trackcopywhole) && (!oldlen)) songorder[esnum][eschn][songlen[esnum][eschn]+1] = trackcopyrpos; } break; case KEY_L: if (shiftpressed) { if (esmarkchn == -1) { esmarkchn = eschn; esmarkstart = 0; esmarkend = songlen[esnum][eschn]-1; } else esmarkchn = -1; } break; case KEY_SPACE: if (!shiftpressed) { if (eseditpos < songlen[esnum][eschn]) espos[eschn] = eseditpos; if (esend[eschn] < espos[eschn]) esend[eschn] = 0; } else { for (c = 0; c < MAX_CHN; c++) { if (eseditpos < songlen[esnum][c]) espos[c] = eseditpos; if (esend[c] < espos[c]) esend[c] = 0; } } break; case KEY_BACKSPACE: if (!shiftpressed) { if ((esend[eschn] != eseditpos) && (eseditpos > espos[eschn])) { if (eseditpos < songlen[esnum][eschn]) esend[eschn] = eseditpos; } else esend[eschn] = 0; } else { if ((esend[eschn] != eseditpos) && (eseditpos > espos[eschn])) { for (c = 0; c < MAX_CHN; c++) { if (eseditpos < songlen[esnum][c]) esend[c] = eseditpos; } } else { for (c = 0; c < MAX_CHN; c++) esend[c] = 0; } } break; case KEY_ENTER: if (eseditpos < songlen[esnum][eschn]) { if (!shiftpressed) { if (songorder[esnum][eschn][eseditpos] < MAX_PATT) epnum[eschn] = songorder[esnum][eschn][eseditpos]; } else { int c, d; for (c = 0; c < MAX_CHN; c++) { int start; if (eseditpos != espos[eschn]) start = eseditpos; else start = espos[c]; for (d = start; d < songlen[esnum][c]; d++) { if (songorder[esnum][c][d] < MAX_PATT) { epnum[c] = songorder[esnum][c][d]; break; } } } } epmarkchn = -1; } epchn = eschn; epcolumn = 0; eppos = 0; epview = - VISIBLEPATTROWS/2; editmode = EDIT_PATTERN; if (epchn == epmarkchn) epmarkchn = -1; break; case KEY_DEL: esmarkchn = -1; deleteorder(); break; case KEY_INS: esmarkchn = -1; insertorder(0); break; case KEY_HOME: if (songlen[esnum][eschn]) { while ((eseditpos != 0) || (escolumn != 0)) orderleft(); } break; case KEY_END: while (eseditpos != songlen[esnum][eschn]+1) orderright(); break; case KEY_PGUP: for (scrrep = PGUPDNREPEAT * 2; scrrep; scrrep--) orderleft(); break; case KEY_PGDN: for (scrrep = PGUPDNREPEAT * 2; scrrep; scrrep--) orderright(); break; case KEY_LEFT: orderleft(); break; case KEY_RIGHT: orderright(); break; case KEY_UP: eschn--; if (eschn < 0) eschn = MAX_CHN - 1; if ((eseditpos == songlen[esnum][eschn]) || (eseditpos > songlen[esnum][eschn]+1)) { eseditpos = songlen[esnum][eschn]+1; escolumn = 0; } if (shiftpressed) esmarkchn = -1; break; case KEY_DOWN: eschn++; if (eschn >= MAX_CHN) eschn = 0; if ((eseditpos == songlen[esnum][eschn]) || (eseditpos > songlen[esnum][eschn]+1)) { eseditpos = songlen[esnum][eschn]+1; escolumn = 0; } if (shiftpressed) esmarkchn = -1; break; } if (eseditpos - esview < 0) { esview = eseditpos; } if (eseditpos - esview >= VISIBLEORDERLIST) { esview = eseditpos - VISIBLEORDERLIST + 1; } } void namecommands(void) { switch(rawkey) { case KEY_DOWN: case KEY_ENTER: enpos++; if (enpos > 2) enpos = 0; break; case KEY_UP: enpos--; if (enpos < 0) enpos = 2; break; } switch(enpos) { case 0: editstring(songname, MAX_STR); break; case 1: editstring(authorname, MAX_STR); break; case 2: editstring(copyrightname, MAX_STR); break; } } void insertorder(unsigned char byte) { if ((songlen[esnum][eschn] - eseditpos)-1 >= 0) { int len; if (songlen[esnum][eschn] < MAX_SONGLEN) { len = songlen[esnum][eschn]+1; songorder[esnum][eschn][len+1] = songorder[esnum][eschn][len]; songorder[esnum][eschn][len] = LOOPSONG; if (len) songorder[esnum][eschn][len-1] = byte; countthispattern(); } memmove(&songorder[esnum][eschn][eseditpos+1], &songorder[esnum][eschn][eseditpos], (songlen[esnum][eschn] - eseditpos)-1); songorder[esnum][eschn][eseditpos] = byte; len = songlen[esnum][eschn]+1; if ((songorder[esnum][eschn][len] > eseditpos) && (songorder[esnum][eschn][len] < (len-2))) songorder[esnum][eschn][len]++; } else { if (eseditpos > songlen[esnum][eschn]) { if (songlen[esnum][eschn] < MAX_SONGLEN) { songorder[esnum][eschn][eseditpos+1] = songorder[esnum][eschn][eseditpos]; songorder[esnum][eschn][eseditpos] = LOOPSONG; if (eseditpos) songorder[esnum][eschn][eseditpos-1] = byte; countthispattern(); eseditpos = songlen[esnum][eschn]+1; } } } } void deleteorder(void) { if ((songlen[esnum][eschn] - eseditpos)-1 >= 0) { int len; memmove(&songorder[esnum][eschn][eseditpos], &songorder[esnum][eschn][eseditpos+1], (songlen[esnum][eschn] - eseditpos)-1); songorder[esnum][eschn][songlen[esnum][eschn]-1] = 0x00; if (songlen[esnum][eschn] > 0) { songorder[esnum][eschn][songlen[esnum][eschn]-1] = songorder[esnum][eschn][songlen[esnum][eschn]]; songorder[esnum][eschn][songlen[esnum][eschn]] = songorder[esnum][eschn][songlen[esnum][eschn]+1]; countthispattern(); } if (eseditpos == songlen[esnum][eschn]) eseditpos++; len = songlen[esnum][eschn]+1; if ((songorder[esnum][eschn][len] > eseditpos) && (songorder[esnum][eschn][len] > 0)) songorder[esnum][eschn][len]--; } else { if (eseditpos > songlen[esnum][eschn]) { if (songlen[esnum][eschn] > 0) { songorder[esnum][eschn][songlen[esnum][eschn]-1] = songorder[esnum][eschn][songlen[esnum][eschn]]; songorder[esnum][eschn][songlen[esnum][eschn]] = songorder[esnum][eschn][songlen[esnum][eschn]+1]; countthispattern(); eseditpos = songlen[esnum][eschn]+1; } } } } void orderleft(void) { if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) { if ((esmarkchn != eschn) || (eseditpos != esmarkend)) { esmarkchn = eschn; esmarkstart = esmarkend = eseditpos; } } escolumn--; if (escolumn < 0) { if (eseditpos > 0) { eseditpos--; if (eseditpos == songlen[esnum][eschn]) eseditpos--; escolumn = 1; if (eseditpos < 0) { eseditpos = 1; escolumn = 0; } } else escolumn = 0; } if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) esmarkend = eseditpos; } void orderright(void) { if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) { if ((esmarkchn != eschn) || (eseditpos != esmarkend)) { esmarkchn = eschn; esmarkstart = esmarkend = eseditpos; } } escolumn++; if (escolumn > 1) { escolumn = 0; if (eseditpos < (songlen[esnum][eschn]+1)) { eseditpos++; if (eseditpos == songlen[esnum][eschn]) eseditpos++; } else escolumn = 1; } if ((shiftpressed) && (eseditpos < songlen[esnum][eschn])) esmarkend = eseditpos; } void nextsong(void) { esnum++; if (esnum >= MAX_SONGS) esnum = MAX_SONGS - 1; songchange(); } void prevsong(void) { esnum--; if (esnum < 0) esnum = 0; songchange(); } void songchange(void) { int c; for (c = 0; c < MAX_CHN; c++) { espos[c] = 0; esend[c] = 0; epnum[c] = c; } updateviewtopos(); eppos = 0; epview = - VISIBLEPATTROWS/2; eseditpos = 0; if (eseditpos == songlen[esnum][eschn]) eseditpos++; esview = 0; epmarkchn = -1; esmarkchn = -1; stopsong(); } void updateviewtopos(void) { int c, d; for (c = 0; c < MAX_CHN; c++) { for (d = espos[c]; d < songlen[esnum][c]; d++) { if (songorder[esnum][c][d] < MAX_PATT) { epnum[c] = songorder[esnum][c][d]; break; } } } } goattracker-2.72/src/goattrk2.res0000644000000000000000000000643410774364076015534 0ustar rootroot  ( @ HH{{{{{{{??{{?{{{{?{??{7{?{{{{?{?{{?{{?{{{{{?{?{{{???{????{{?{?{{{{{{{{{{{{{{Žŀ{{{{{{{ŀ{{{{ŽŽŽŽŽŽ{{{{{ŽŽŽ{{@@@{{Ž@@@@@@{Ž{{{{{ŽŽŽŽŽ{@@@{{{{@@@{ŽŽ{{555=5=5=5=ŽŽŽŽŽŽŽ555={Y]UUY]UUUUŽŽY]Y]UU{@@@{u}u}uuŽŽŽŽŽu}u}u}{@@@@@@{``ŽŽŽŽ``{{{{{}ŽŽŽŽŽŽŽŽ}@@@@@@{KŀŽC{{@ŽŀŽ@@{{{{{{ww{Žowww{@@@@@@{ŽŽ@@@@@@{{{{{{Žŀ{@@@{{{@@@ЬŽЬдЬЬдЬŽŀЬЬд{{{@@@{ààààà{@@@{{{ŽŽ{@@@@@@{{{{{{ 0   goattracker-2.72/src/gcommon.h0000644000000000000000000000275011036462276015062 0ustar rootroot#ifndef GCOMMON_H #define GCOMMON_H #define CMD_DONOTHING 0 #define CMD_PORTAUP 1 #define CMD_PORTADOWN 2 #define CMD_TONEPORTA 3 #define CMD_VIBRATO 4 #define CMD_SETAD 5 #define CMD_SETSR 6 #define CMD_SETWAVE 7 #define CMD_SETWAVEPTR 8 #define CMD_SETPULSEPTR 9 #define CMD_SETFILTERPTR 10 #define CMD_SETFILTERCTRL 11 #define CMD_SETFILTERCUTOFF 12 #define CMD_SETMASTERVOL 13 #define CMD_FUNKTEMPO 14 #define CMD_SETTEMPO 15 #define WTBL 0 #define PTBL 1 #define FTBL 2 #define STBL 3 #define MAX_FILT 64 #define MAX_STR 32 #define MAX_INSTR 64 #define MAX_CHN 3 #define MAX_PATT 208 #define MAX_TABLES 4 #define MAX_TABLELEN 255 #define MAX_INSTRNAMELEN 16 #define MAX_PATTROWS 128 #define MAX_SONGLEN 254 #define MAX_SONGS 32 #define MAX_NOTES 96 #define REPEAT 0xd0 #define TRANSDOWN 0xe0 #define TRANSUP 0xf0 #define LOOPSONG 0xff #define ENDPATT 0xff #define INSTRCHG 0x00 #define FX 0x40 #define FXONLY 0x50 #define FIRSTNOTE 0x60 #define LASTNOTE 0xbc #define REST 0xbd #define KEYOFF 0xbe #define KEYON 0xbf #define OLDKEYOFF 0x5e #define OLDREST 0x5f #define WAVEDELAY 0x1 #define WAVELASTDELAY 0xf #define WAVESILENT 0xe0 #define WAVELASTSILENT 0xef #define WAVECMD 0xf0 #define WAVELASTCMD 0xfe typedef struct { unsigned char ad; unsigned char sr; unsigned char ptr[MAX_TABLES]; unsigned char vibdelay; unsigned char gatetimer; unsigned char firstwave; char name[MAX_INSTRNAMELEN]; } INSTR; #endif goattracker-2.72/src/goattrk2.bmp0000644000000000000000000000606610774364074015520 0ustar rootrootBM6 6(  # # {{{{{{{{{77{{7{{{{{{{{7{7{7{{7{{{{7{{{{{{7{{7{{7{{{7{{{{{{{{{{7{{7{{{{{{{777{7777{{7{7{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{{@@@{{{{{@@@@@@{{{{{{{{{{{{@@@{{{{@@@{{{{{{{55555555555555{{UUUUUUUUUUUUUUUU{@@@{{{{{uuuuuuuuuuuu{@@@@@@{````{{{{{{{{{{}}{@@@@@@{CC{{{{{{@@@{{{{{{oo{oooo{@@@@@@{{{{{{@@@@@@{{{{{{{{{{{{@@@{{{{{{@@@{ЬЬЬЬЬЬЬЬЬЬ{{{{{@@@{{@@@{{{{{{{{@@@@@@{{{{{{{{{{{goattracker-2.72/src/goattrk2.c.bak0000644000000000000000000010655111460120656015705 0ustar rootroot// // GOATTRACKER v2.71 // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // #define GOATTRK2_C #ifdef __WIN32__ #include #endif #include "goattrk2.h" #include "bme.h" int menu = 0; int editmode = EDIT_PATTERN; int recordmode = 1; int followplay = 0; int hexnybble = -1; int stepsize = 4; int autoadvance = 0; int defaultpatternlength = 64; int cursorflash = 0; int cursorcolortable[] = {1,2,7,2}; int exitprogram = 0; int eacolumn = 0; int eamode = 0; unsigned keypreset = KEY_TRACKER; unsigned playerversion = 0; int fileformat = FORMAT_PRG; int zeropageadr = 0xfc; int playeradr = 0x1000; unsigned sidmodel = 0; unsigned multiplier = 1; unsigned adparam = 0x0f00; unsigned ntsc = 0; unsigned patternhex = 0; unsigned sidaddress = 0xd400; unsigned finevibrato = 1; unsigned optimizepulse = 1; unsigned optimizerealtime = 1; unsigned customclockrate = 0; unsigned usefinevib = 0; unsigned b = DEFAULTBUF; unsigned mr = DEFAULTMIXRATE; unsigned writer = 0; unsigned hardsid = 0; unsigned catweasel = 0; unsigned interpolate = 0; unsigned residdelay = 0; unsigned hardsidbufinteractive = 20; unsigned hardsidbufplayback = 400; float basepitch = 0.0f; char configbuf[MAX_PATHNAME]; char loadedsongfilename[MAX_FILENAME]; char songfilename[MAX_FILENAME]; char songfilter[MAX_FILENAME]; char songpath[MAX_PATHNAME]; char instrfilename[MAX_FILENAME]; char instrfilter[MAX_FILENAME]; char instrpath[MAX_PATHNAME]; char packedpath[MAX_PATHNAME]; char *programname = "$VER: GoatTracker v2.71"; char textbuffer[MAX_PATHNAME]; unsigned char hexkeytbl[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; extern unsigned char datafile[]; int main(int argc, char **argv) { char filename[MAX_PATHNAME]; FILE *configfile; int c,d; programname += sizeof "$VER:"; // Open datafile io_openlinkeddatafile(datafile); // Load configuration #ifdef __WIN32__ GetModuleFileName(NULL, filename, MAX_PATHNAME); filename[strlen(filename)-3] = 'c'; filename[strlen(filename)-2] = 'f'; filename[strlen(filename)-1] = 'g'; #elif __amigaos__ strcpy(filename, "PROGDIR:goattrk2.cfg"); #else strcpy(filename, getenv("HOME")); strcat(filename, "/.goattrk/goattrk2.cfg"); #endif configfile = fopen(filename, "rt"); if (configfile) { getparam(configfile, &b); getparam(configfile, &mr); getparam(configfile, &hardsid); getparam(configfile, &sidmodel); getparam(configfile, &ntsc); getparam(configfile, (unsigned *)&fileformat); getparam(configfile, (unsigned *)&playeradr); getparam(configfile, (unsigned *)&zeropageadr); getparam(configfile, &playerversion); getparam(configfile, &keypreset); getparam(configfile, (unsigned *)&stepsize); getparam(configfile, &multiplier); getparam(configfile, &catweasel); getparam(configfile, &adparam); getparam(configfile, &interpolate); getparam(configfile, &patternhex); getparam(configfile, &sidaddress); getparam(configfile, &finevibrato); getparam(configfile, &optimizepulse); getparam(configfile, &optimizerealtime); getparam(configfile, &residdelay); getparam(configfile, &customclockrate); getparam(configfile, &hardsidbufinteractive); getparam(configfile, &hardsidbufplayback); getfloatparam(configfile, &filterparams.distortionrate); getfloatparam(configfile, &filterparams.distortionpoint); getfloatparam(configfile, &filterparams.distortioncfthreshold); getfloatparam(configfile, &filterparams.type3baseresistance); getfloatparam(configfile, &filterparams.type3offset); getfloatparam(configfile, &filterparams.type3steepness); getfloatparam(configfile, &filterparams.type3minimumfetresistance); getfloatparam(configfile, &filterparams.type4k); getfloatparam(configfile, &filterparams.type4b); getfloatparam(configfile, &filterparams.voicenonlinearity); getparam(configfile, &win_fullscreen); getfloatparam(configfile, &basepitch); fclose(configfile); } // Init pathnames initpaths(); // Scan command line for (c = 1; c < argc; c++) { #ifdef __WIN32__ if ((argv[c][0] == '-') || (argv[c][0] == '/')) #else if (argv[c][0] == '-') #endif { int y = 0; switch(toupper(argv[c][1])) { case '?': if (!initscreen()) return 1; if(argv[c][2]=='?') { onlinehelp(1,0); return 0; } printtext(0,y++,15,"Usage: GOATTRK2 [songname] [options]"); printtext(0,y++,15,"Options:"); printtext(0,y++,15,"-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00"); printtext(0,y++,15,"-Bxx Set sound buffer length in milliseconds DEFAULT=100"); printtext(0,y++,15,"-Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on)"); printtext(0,y++,15,"-Dxx Pattern row display (0 = decimal, 1 = hexadecimal)"); printtext(0,y++,15,"-Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=6581"); printtext(0,y++,15,"-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)"); printtext(0,y++,15,"-Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.)"); printtext(0,y++,15,"-Ixx Set reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) DEFAULT=off"); printtext(0,y++,15,"-Kxx Note-entry mode (0 = PROTRACKER 1 = DMC) DEFAULT=PROTRK."); printtext(0,y++,15,"-Lxx SID memory location in hex. DEFAULT=D400"); printtext(0,y++,15,"-Mxx Set sound mixing rate DEFAULT=44100"); printtext(0,y++,15,"-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on"); printtext(0,y++,15,"-Pxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)"); printtext(0,y++,15,"-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on"); printtext(0,y++,15,"-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.)"); printtext(0,y++,15,"-Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0"); printtext(0,y++,15,"-Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0"); printtext(0,y++,15,"-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on"); printtext(0,y++,15,"-Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window"); printtext(0,y++,15,"-Zxx Set random reSID write delay in cycles (0 = off) DEFAULT=off"); printtext(0,y++,15,"-N Use NTSC timing"); printtext(0,y++,15,"-P Use PAL timing (DEFAULT)"); printtext(0,y++,15,"-W Write sound output to a file SIDAUDIO.RAW"); printtext(0,y++,15,"-? Show this info again"); printtext(0,y++,15,"-?? Standalone online help window"); waitkeynoupdate(); return 0; case 'Z': sscanf(&argv[c][2], "%u", &residdelay); break; case 'A': sscanf(&argv[c][2], "%x", &adparam); break; case 'S': sscanf(&argv[c][2], "%u", &multiplier); break; case 'B': sscanf(&argv[c][2], "%u", &b); break; case 'D': sscanf(&argv[c][2], "%u", &patternhex); break; case 'E': sscanf(&argv[c][2], "%u", &sidmodel); break; case 'I': sscanf(&argv[c][2], "%u", &interpolate); break; case 'K': sscanf(&argv[c][2], "%u", &keypreset); break; case 'L': sscanf(&argv[c][2], "%x", &sidaddress); break; case 'N': ntsc = 1; customclockrate = 0; break; case 'P': ntsc = 0; customclockrate = 0; break; case 'F': sscanf(&argv[c][2], "%u", &customclockrate); break; case 'M': sscanf(&argv[c][2], "%u", &mr); break; case 'O': sscanf(&argv[c][2], "%u", &optimizepulse); break; case 'R': sscanf(&argv[c][2], "%u", &optimizerealtime); break; case 'H': sscanf(&argv[c][2], "%u", &hardsid); break; case 'V': sscanf(&argv[c][2], "%u", &finevibrato); break; case 'T': sscanf(&argv[c][2], "%u", &hardsidbufinteractive); break; case 'U': sscanf(&argv[c][2], "%u", &hardsidbufplayback); break; case 'W': writer = 1; break; case 'X': sscanf(&argv[c][2], "%u", &win_fullscreen); break; case 'C': sscanf(&argv[c][2], "%u", &catweasel); break; case 'G': sscanf(&argv[c][2], "%f", &basepitch); break; } } else { char startpath[MAX_PATHNAME]; strcpy(songfilename, argv[c]); for (d = strlen(argv[c])-1; d >= 0; d--) { if ((argv[c][d] == '/') || (argv[c][d] == '\\')) { strcpy(startpath, argv[c]); startpath[d+1] = 0; chdir(startpath); initpaths(); strcpy(songfilename, &argv[c][d+1]); break; } } } } // Validate parameters sidmodel &= 1; adparam &= 0xffff; zeropageadr &= 0xff; playeradr &= 0xff00; sidaddress &= 0xffff; if (!stepsize) stepsize = 4; if (multiplier > 16) multiplier = 16; if (keypreset > 2) keypreset = 0; if ((finevibrato == 1) && (multiplier < 2)) usefinevib = 1; if (finevibrato > 1) usefinevib = 1; if (optimizepulse > 1) optimizepulse = 1; if (optimizerealtime > 1) optimizerealtime = 1; if (residdelay > 63) residdelay = 63; if (customclockrate < 100) customclockrate = 0; // Calculate frequencytable if necessary if (basepitch < 0.0f) basepitch = 0.0f; if (basepitch > 0.0f) calculatefreqtable(); // Set screenmode if (!initscreen()) return 1; // Reset channels/song initchannels(); clearsong(1,1,1,1,1); // Init sound if (!sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate)) { printtextc(MAX_ROWS/2-1,15,"Sound init failed. Press any key to run without sound (notice that song timer won't start)"); waitkeynoupdate(); } // Load song if applicable if (strlen(songfilename)) loadsong(); // Start editor mainloop printmainscreen(); while (!exitprogram) { waitkeymouse(); docommand(); } // Shutdown sound output now sound_uninit(); // Save configuration #ifndef __WIN32__ #ifdef __amigaos__ strcpy(filename, "PROGDIR:goattrk2.cfg"); #else strcpy(filename, getenv("HOME")); strcat(filename, "/.goattrk"); mkdir(filename, S_IRUSR | S_IWUSR | S_IXUSR); strcat(filename, "/goattrk2.cfg"); #endif #endif configfile = fopen(filename, "wt"); if (configfile) { fprintf(configfile, ";------------------------------------------------------------------------------\n" ";GT2 config file. Rows starting with ; are comments. Hexadecimal parameters are\n" ";to be preceded with $ and decimal parameters with nothing. \n" ";------------------------------------------------------------------------------\n" "\n" ";reSID buffer length (in milliseconds)\n%d\n\n" ";reSID mixing rate (in Hz)\n%d\n\n" ";Hardsid device number (0 = off)\n%d\n\n" ";reSID model (0 = 6581, 1 = 8580)\n%d\n\n" ";Timing mode (0 = PAL, 1 = NTSC)\n%d\n\n" ";Packer/relocator fileformat (0 = SID, 1 = PRG, 2 = BIN)\n%d\n\n" ";Packer/relocator player address\n$%04x\n\n" ";Packer/relocator zeropage baseaddress\n$%02x\n\n" ";Packer/relocator player type (0 = standard ... 3 = minimal)\n%d\n\n" ";Key entry mode (0 = Protracker, 1 = DMC)\n%d\n\n" ";Pattern highlight step size\n%d\n\n" ";Speed multiplier (0 = 25Hz, 1 = 1X, 2 = 2X etc.)\n%d\n\n" ";Use CatWeasel SID (0 = off, 1 = on)\n%d\n\n" ";Hardrestart ADSR parameter\n$%04x\n\n" ";reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on)\n%d\n\n" ";Hexadecimal pattern display (0 = off, 1 = on)\n%d\n\n" ";SID baseaddress\n$%04x\n\n" ";Finevibrato mode (0 = off, 1 = on)\n%d\n\n" ";Pulseskipping (0 = off, 1 = on)\n%d\n\n" ";Realtime effect skipping (0 = off, 1 = on)\n%d\n\n" ";Random reSID write delay in cycles (0 = off)\n%d\n\n" ";Custom SID clock cycles per second (0 = use PAL/NTSC default)\n%d\n\n" ";HardSID interactive mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n" ";HardSID playback mode buffer size (in milliseconds, 0 = maximum/no flush)\n%d\n\n" ";reSID-fp distortion rate\n%f\n\n" ";reSID-fp distortion point\n%f\n\n" ";reSID-fp distortion CF threshold\n%f\n\n" ";reSID-fp type 3 base resistance\n%f\n\n" ";reSID-fp type 3 base offset\n%f\n\n" ";reSID-fp type 3 base steepness\n%f\n\n" ";reSID-fp type 3 minimum FET resistance\n%f\n\n" ";reSID-fp type 4 k\n%f\n\n" ";reSID-fp type 4 b\n%f\n\n" ";reSID-fp voice nonlinearity\n%f\n\n" ";Window type (0 = window, 1 = fullscreen)\n%d\n\n" ";Base pitch of A-4 in Hz (0 = use default frequencytable)\n%f\n\n", b, mr, hardsid, sidmodel, ntsc, fileformat, playeradr, zeropageadr, playerversion, keypreset, stepsize, multiplier, catweasel, adparam, interpolate, patternhex, sidaddress, finevibrato, optimizepulse, optimizerealtime, residdelay, customclockrate, hardsidbufinteractive, hardsidbufplayback, filterparams.distortionrate, filterparams.distortionpoint, filterparams.distortioncfthreshold, filterparams.type3baseresistance, filterparams.type3offset, filterparams.type3steepness, filterparams.type3minimumfetresistance, filterparams.type4k, filterparams.type4b, filterparams.voicenonlinearity, win_fullscreen, basepitch); fclose(configfile); } // Exit return 0; } void waitkey(void) { for (;;) { displayupdate(); getkey(); if ((rawkey) || (key)) break; if (win_quitted) break; } converthex(); } void waitkeymouse(void) { for (;;) { displayupdate(); getkey(); if ((rawkey) || (key)) break; if (win_quitted) break; if (mouseb) break; } converthex(); } void waitkeymousenoupdate(void) { for (;;) { fliptoscreen(); getkey(); if ((rawkey) || (key)) break; if (win_quitted) break; if (mouseb) break; } converthex(); } void waitkeynoupdate(void) { for (;;) { fliptoscreen(); getkey(); if ((rawkey) || (key)) break; if ((mouseb) && (!prevmouseb)) break; if (win_quitted) break; } } void converthex() { int c; hexnybble = -1; for (c = 0; c < 16; c++) { if (tolower(key) == hexkeytbl[c]) { if (c >= 10) { if (!shiftpressed) hexnybble = c; } else { hexnybble = c; } } } } void docommand(void) { // "GUI" operation :) mousecommands(); // Mode-specific commands switch(editmode) { case EDIT_ORDERLIST: orderlistcommands(); break; case EDIT_INSTRUMENT: instrumentcommands(); break; case EDIT_TABLES: tablecommands(); break; case EDIT_PATTERN: patterncommands(); break; case EDIT_NAMES: namecommands(); break; } // General commands generalcommands(); } void mousecommands(void) { int c; if (!mouseb) return; // Pattern editpos & pattern number selection for (c = 0; c < MAX_CHN; c++) { if ((mousey == 2) && (mousex >= 13 + c*15) && (mousex <= 14 + c*15)) { if ((!prevmouseb) || (mouseheld > HOLDDELAY)) { if (mouseb & MOUSEB_LEFT) { epchn = c; nextpattern(); } if (mouseb & MOUSEB_RIGHT) { epchn = c; prevpattern(); } } } else { if ((mousey >= 2) && (mousey <= 34) && (mousex >= 6 + c*15) && (mousex <= 14 + c*15)) { int x = mousex-6-c*15; int newpos = mousey-3+epview; if (newpos < 0) newpos = 0; if (newpos > pattlen[epnum[epchn]]) newpos = pattlen[epnum[epchn]]; editmode = EDIT_PATTERN; if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb)) { if ((epmarkchn != c) || (newpos != epmarkend)) { epmarkchn = c; epmarkstart = epmarkend = newpos; } } if (mouseb & MOUSEB_LEFT) { epchn = c; if (x < 4) epcolumn = 0; if (x >= 4) epcolumn = x-3; } if (!prevmouseb) { if (mouseb & MOUSEB_LEFT) eppos = newpos; } else { if (mouseb & MOUSEB_LEFT) { if (mousey == 2) eppos--; if (mousey == 34) eppos++; } } if (eppos < 0) eppos = 0; if (eppos > pattlen[epnum[epchn]]) eppos = pattlen[epnum[epchn]]; if (mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) epmarkend = newpos; } } } // Song editpos & songnumber selection if ((mousey >= 3) && (mousey <= 8) && (mousex >= 40+10)) { int newpos = esview + (mousex-44-10) / 3; int newcolumn = (mousex-44-10) % 3; int newchn = mousey - 3; if (newcolumn < 0) newcolumn = 0; if (newcolumn > 1) newcolumn = 1; if (newpos < 0) { newpos = 0; newcolumn = 0; } if (newpos == songlen[esnum][eschn]) { newpos++; newcolumn = 0; } if (newpos > songlen[esnum][eschn]+1) { newpos = songlen[esnum][eschn] + 1; newcolumn = 1; } editmode = EDIT_ORDERLIST; if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb) && (newpos < songlen[esnum][eschn])) { if ((esmarkchn != newchn) || (newpos != esmarkend)) { esmarkchn = newchn; esmarkstart = esmarkend = newpos; } } if (mouseb & MOUSEB_LEFT) { eschn = newchn; eseditpos = newpos; escolumn = newcolumn; } if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (newpos < songlen[esnum][eschn])) esmarkend = newpos; } if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 2) && (mousex >= 63+10) && (mousex <= 64+10)) { if (mouseb & MOUSEB_LEFT) nextsong(); if (mouseb & MOUSEB_RIGHT) prevsong(); } // Instrument editpos & instrument number selection if ((mousey >= 8) && (mousey <= 12) && (mousex >= 56+10) && (mousex <= 57+10)) { editmode = EDIT_INSTRUMENT; eipos = mousey-8; eicolumn = mousex-56-10; } if ((mousey >= 8) && (mousey <= 11) && (mousex >= 76+10) && (mousex <= 77+10)) { editmode = EDIT_INSTRUMENT; eipos = mousey-8+5; eicolumn = mousex-76-10; } if ((mousey == 7) && (mousex >= 60+10)) { editmode = EDIT_INSTRUMENT; eipos = 9; } if (((!prevmouseb) || (mouseheld > HOLDDELAY)) && (mousey == 7) && (mousex >= 56+10) && (mousex <= 57+10)) { if (mouseb & MOUSEB_LEFT) nextinstr(); if (mouseb & MOUSEB_RIGHT) previnstr(); } // Table editpos for (c = 0; c < MAX_TABLES; c++) { if ((mousey >= 14) && (mousey <= 30) && (mousex >= 43+10+c*10) && (mousex <= 47+10+c*10)) { int newpos = mousey-15+etview[etnum]; if (newpos < 0) newpos = 0; if (newpos >= MAX_TABLELEN) newpos = MAX_TABLELEN-1; editmode = EDIT_TABLES; if ((mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) && (!prevmouseb)) { if ((etmarknum != etnum) || (newpos != etmarkend)) { etmarknum = c; etmarkstart = etmarkend = newpos; } } if (mouseb & MOUSEB_LEFT) { etnum = c; etpos = mousey-15+etview[etnum]; etcolumn = mousex-43-10-c*10; } if (etcolumn >= 2) etcolumn--; if (etpos < 0) etpos = 0; if (etpos > MAX_TABLELEN-1) etpos = MAX_TABLELEN-1; if (mouseb & (MOUSEB_RIGHT|MOUSEB_MIDDLE)) etmarkend = newpos; } } // Name editpos if ((mousey >= 31) && (mousey <= 33) && (mousex >= 47+10)) { editmode = EDIT_NAMES; enpos = mousey - 31; } // Status panel if ((!prevmouseb) && (mousex == 7) && (mousey == 23+3+9)) { if (mouseb & (MOUSEB_LEFT)) if (epoctave < 7) epoctave++; if (mouseb & (MOUSEB_RIGHT)) if (epoctave > 0) epoctave--; } if ((!prevmouseb) && (mousex <= 7) && (mousey == 24+3+9)) { recordmode ^= 1; } for (c = 0; c < MAX_CHN; c++) { if ((!prevmouseb) && (mousey >= 23+3+9) && (mousex >= 80 + 7*c) && (mousex <= 85 + 7*c)) mutechannel(c); } // Titlebar actions if (!menu) { if ((mousey == 0) && (!prevmouseb) && (mouseb == MOUSEB_LEFT)) { if ((mousex >= 40+10) && (mousex <= 41+10)) { usefinevib ^= 1; } if ((mousex >= 43+10) && (mousex <= 44+10)) { optimizepulse ^= 1; } if ((mousex >= 46+10) && (mousex <= 47+10)) { optimizerealtime ^= 1; } if ((mousex >= 49+10) && (mousex <= 52+10)) { ntsc ^= 1; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } if ((mousex >= 54+10) && (mousex <= 57+10)) { sidmodel ^= 1; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } if ((mousex >= 62+10) && (mousex <= 65+10)) editadsr(); if ((mousex >= 67+10) && (mousex <= 68+10)) prevmultiplier(); if ((mousex >= 69+10) && (mousex <= 70+10)) nextmultiplier(); } } else { if ((!mousey) && (mouseb & MOUSEB_LEFT) && (!(prevmouseb & MOUSEB_LEFT))) { if ((mousex >= 0) && (mousex <= 5)) { initsong(esnum, PLAY_BEGINNING); followplay = shiftpressed; } if ((mousex >= 7) && (mousex <= 15)) { initsong(esnum, PLAY_POS); followplay = shiftpressed; } if ((mousex >= 17) && (mousex <= 26)) { initsong(esnum, PLAY_PATTERN); followplay = shiftpressed; } if ((mousex >= 28) && (mousex <= 33)) stopsong(); if ((mousex >= 35) && (mousex <= 40)) load(); if ((mousex >= 42) && (mousex <= 47)) save(); if ((mousex >= 49) && (mousex <= 57)) relocator(); if ((mousex >= 59) && (mousex <= 64)) onlinehelp(0,0); if ((mousex >= 66) && (mousex <= 72)) clear(); if ((mousex >= 74) && (mousex <= 79)) quit(); } } } void generalcommands(void) { int c; switch(key) { case '?': case '-': if ((editmode != EDIT_NAMES) && (editmode != EDIT_ORDERLIST)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos == 9))) previnstr(); } break; case '+': case '_': if ((editmode != EDIT_NAMES) && (editmode != EDIT_ORDERLIST)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) nextinstr(); } break; case '*': if (editmode != EDIT_NAMES) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave < 7) epoctave++; } } break; case '/': case '\'': if (editmode != EDIT_NAMES) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave > 0) epoctave--; } } break; case '<': if (((editmode == EDIT_INSTRUMENT) && (eipos != 9)) || (editmode == EDIT_TABLES)) previnstr(); break; case '>': if (((editmode == EDIT_INSTRUMENT) && (eipos != 9)) || (editmode == EDIT_TABLES)) nextinstr(); break; case ';': for (c = 0; c < MAX_CHN; c++) { if (espos[c]) espos[c]--; if (espos[c] < esview) { esview = espos[c]; eseditpos = espos[c]; } } updateviewtopos(); rewindsong(); break; case ':': for (c = 0; c < MAX_CHN; c++) { if (espos[c] < songlen[esnum][c]-1) espos[c]++; if (espos[c] - esview >= VISIBLEORDERLIST) { esview = espos[c] - VISIBLEORDERLIST + 1; eseditpos = espos[c]; } } updateviewtopos(); rewindsong(); break; } if (win_quitted) exitprogram = 1; switch(rawkey) { case KEY_ESC: if (!shiftpressed) quit(); else clear(); break; case KEY_KPMULTIPLY: if ((editmode != EDIT_NAMES) && (!key)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave < 7) epoctave++; } } break; case KEY_KPDIVIDE: if ((editmode != EDIT_NAMES) && (!key)) { if (!((editmode == EDIT_INSTRUMENT) && (eipos >= 9))) { if (epoctave > 0) epoctave--; } } break; case KEY_F12: onlinehelp(0, shiftpressed); break; case KEY_TAB: if (!shiftpressed) editmode++; else editmode--; if (editmode > EDIT_NAMES) editmode = EDIT_PATTERN; if (editmode < EDIT_PATTERN) editmode = EDIT_NAMES; break; case KEY_F1: initsong(esnum, PLAY_BEGINNING); followplay = shiftpressed; break; case KEY_F2: initsong(esnum, PLAY_POS); followplay = shiftpressed; break; case KEY_F3: initsong(esnum, PLAY_PATTERN); followplay = shiftpressed; break; case KEY_F4: if (shiftpressed) mutechannel(epchn); else stopsong(); break; case KEY_F5: if (!shiftpressed) editmode = EDIT_PATTERN; else prevmultiplier(); break; case KEY_F6: if (!shiftpressed) editmode = EDIT_ORDERLIST; else nextmultiplier(); break; case KEY_F7: if (!shiftpressed) { if (editmode == EDIT_INSTRUMENT) editmode = EDIT_TABLES; else editmode = EDIT_INSTRUMENT; } else editadsr(); break; case KEY_F8: if (!shiftpressed) editmode = EDIT_NAMES; else { sidmodel ^= 1; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } break; case KEY_F9: relocator(); break; case KEY_F10: load(); break; case KEY_F11: save(); break; } } void load(void) { if ((editmode != EDIT_INSTRUMENT) && (editmode != EDIT_TABLES)) { if (fileselector(songfilename, songpath, songfilter, "LOAD SONG", 0)) loadsong(); } else { if (einum) { if (fileselector(instrfilename, instrpath, instrfilter, "LOAD INSTRUMENT", 0)) loadinstrument(); } } key = 0; rawkey = 0; } void save(void) { if ((editmode != EDIT_INSTRUMENT) && (editmode != EDIT_TABLES)) { int done = 0; // Repeat until quit or save successful while (!done) { if (strlen(loadedsongfilename)) strcpy(songfilename, loadedsongfilename); if (fileselector(songfilename, songpath, songfilter, "SAVE SONG", 3)) done = savesong(); else done = 1; } } else { if (einum) { int done = 0; int useinstrname = 0; char tempfilename[MAX_FILENAME]; // Repeat until quit or save successful while (!done) { if ((!strlen(instrfilename)) && (strlen(instr[einum].name))) { useinstrname = 1; strcpy(instrfilename, instr[einum].name); strcat(instrfilename, ".ins"); strcpy(tempfilename, instrfilename); } if (fileselector(instrfilename, instrpath, instrfilter, "SAVE INSTRUMENT", 3)) done = saveinstrument(); else done = 1; if (useinstrname) { if (!strcmp(tempfilename, instrfilename)) memset(instrfilename, 0, sizeof instrfilename); } } } } key = 0; rawkey = 0; } void quit(void) { if ((!shiftpressed) || (mouseb)) { printtextcp(49, 36, 15, "Really Quit (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) exitprogram = 1; } key = 0; rawkey = 0; } void clear(void) { int cs = 0; int cp = 0; int ci = 0; int ct = 0; int cn = 0; printtextcp(49, 36, 15, "Optimize everything (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) { optimizeeverything(1, 1); key = 0; rawkey = 0; return; } printtextcp(49, 36, 15, "Clear orderlists (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) cs = 1; printtextcp(49, 36, 15, "Clear patterns (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) cp = 1; printtextcp(49, 36, 15, "Clear instruments (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) ci = 1; printtextcp(49, 36, 15, "Clear tables (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) ct = 1; printtextcp(49, 36, 15, "Clear songname (y/n)?"); waitkey(); printblank(20, 36, 58); if ((key == 'y') || (key == 'Y')) cn = 1; if (cp == 1) { int selectdone = 0; int olddpl = defaultpatternlength; printtext(40, 36, 15,"Pattern length:"); while (!selectdone) { sprintf(textbuffer, "%02d ", defaultpatternlength); printtext(55, 36, 15, textbuffer); waitkey(); switch(rawkey) { case KEY_LEFT: defaultpatternlength -= 7; case KEY_DOWN: defaultpatternlength--; if (defaultpatternlength < 1) defaultpatternlength = 1; break; case KEY_RIGHT: defaultpatternlength += 7; case KEY_UP: defaultpatternlength++; if (defaultpatternlength > MAX_PATTROWS) defaultpatternlength = MAX_PATTROWS; break; case KEY_ESC: defaultpatternlength = olddpl; selectdone = 1; break; case KEY_ENTER: selectdone = 1; break; } } printblank(20, 36, 58); } if (cs | cp | ci | ct | cn) memset(songfilename, 0, sizeof songfilename); clearsong(cs, cp, ci, ct, cn); key = 0; rawkey = 0; } void editadsr(void) { eamode = 1; eacolumn = 0; for (;;) { waitkeymouse(); if (win_quitted) { exitprogram = 1; key = 0; rawkey = 0; return; } if (hexnybble >= 0) { switch(eacolumn) { case 0: adparam &= 0x0fff; adparam |= hexnybble << 12; break; case 1: adparam &= 0xf0ff; adparam |= hexnybble << 8; break; case 2: adparam &= 0xff0f; adparam |= hexnybble << 4; break; case 3: adparam &= 0xfff0; adparam |= hexnybble; break; } eacolumn++; } switch(rawkey) { case KEY_F7: if (!shiftpressed) break; case KEY_ESC: case KEY_ENTER: case KEY_TAB: eamode = 0; key = 0; rawkey = 0; return; case KEY_BACKSPACE: if (!eacolumn) break; case KEY_LEFT: eacolumn--; break; case KEY_RIGHT: eacolumn++; } eacolumn &= 3; if ((mouseb) && (!prevmouseb)) { eamode = 0; return; } } } void getparam(FILE *handle, unsigned *value) { char *configptr; for (;;) { if (feof(handle)) return; fgets(configbuf, MAX_PATHNAME, handle); if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break; } configptr = configbuf; if (*configptr == '$') { *value = 0; configptr++; for (;;) { char c = tolower(*configptr++); int h = -1; if ((c >= 'a') && (c <= 'f')) h = c - 'a' + 10; if ((c >= '0') && (c <= '9')) h = c - '0'; if (h >= 0) { *value *= 16; *value += h; } else break; } } else { *value = 0; for (;;) { char c = tolower(*configptr++); int d = -1; if ((c >= '0') && (c <= '9')) d = c - '0'; if (d >= 0) { *value *= 10; *value += d; } else break; } } } void getfloatparam(FILE *handle, float *value) { char *configptr; for (;;) { if (feof(handle)) return; fgets(configbuf, MAX_PATHNAME, handle); if ((configbuf[0]) && (configbuf[0] != ';') && (configbuf[0] != ' ') && (configbuf[0] != 13) && (configbuf[0] != 10)) break; } configptr = configbuf; *value = 0.0f; sscanf(configptr, "%f", value); } void prevmultiplier(void) { if (multiplier > 0) { multiplier--; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } } void nextmultiplier(void) { if (multiplier < 16) { multiplier++; sound_init(b, mr, writer, hardsid, sidmodel, ntsc, multiplier, catweasel, interpolate, customclockrate); } } void calculatefreqtable() { double basefreq = (double)basepitch * (16777216.0 / 985248.0) * pow(2.0, 0.25) / 32.0; int c; for (c = 0; c < 8*12 ; c++) { double note = c; double freq = basefreq * pow(2.0, note/12.0); int intfreq = freq + 0.5; if (intfreq > 0xffff) intfreq = 0xffff; freqtbllo[c] = intfreq & 0xff; freqtblhi[c] = intfreq >> 8; } } goattracker-2.72/src/gplay.c0000644000000000000000000006753011604143762014536 0ustar rootroot// // GOATTRACKER v2 playroutine // #define GPLAY_C #include "goattrk2.h" unsigned char freqtbllo[] = { 0x17,0x27,0x39,0x4b,0x5f,0x74,0x8a,0xa1,0xba,0xd4,0xf0,0x0e, 0x2d,0x4e,0x71,0x96,0xbe,0xe8,0x14,0x43,0x74,0xa9,0xe1,0x1c, 0x5a,0x9c,0xe2,0x2d,0x7c,0xcf,0x28,0x85,0xe8,0x52,0xc1,0x37, 0xb4,0x39,0xc5,0x5a,0xf7,0x9e,0x4f,0x0a,0xd1,0xa3,0x82,0x6e, 0x68,0x71,0x8a,0xb3,0xee,0x3c,0x9e,0x15,0xa2,0x46,0x04,0xdc, 0xd0,0xe2,0x14,0x67,0xdd,0x79,0x3c,0x29,0x44,0x8d,0x08,0xb8, 0xa1,0xc5,0x28,0xcd,0xba,0xf1,0x78,0x53,0x87,0x1a,0x10,0x71, 0x42,0x89,0x4f,0x9b,0x74,0xe2,0xf0,0xa6,0x0e,0x33,0x20,0xff, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; unsigned char freqtblhi[] = { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x02, 0x02,0x02,0x02,0x02,0x02,0x02,0x03,0x03,0x03,0x03,0x03,0x04, 0x04,0x04,0x04,0x05,0x05,0x05,0x06,0x06,0x06,0x07,0x07,0x08, 0x08,0x09,0x09,0x0a,0x0a,0x0b,0x0c,0x0d,0x0d,0x0e,0x0f,0x10, 0x11,0x12,0x13,0x14,0x15,0x17,0x18,0x1a,0x1b,0x1d,0x1f,0x20, 0x22,0x24,0x27,0x29,0x2b,0x2e,0x31,0x34,0x37,0x3a,0x3e,0x41, 0x45,0x49,0x4e,0x52,0x57,0x5c,0x62,0x68,0x6e,0x75,0x7c,0x83, 0x8b,0x93,0x9c,0xa5,0xaf,0xb9,0xc4,0xd0,0xdd,0xea,0xf8,0xff, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; CHN chn[MAX_CHN]; unsigned char filterctrl = 0; unsigned char filtertype = 0; unsigned char filtercutoff = 0; unsigned char filtertime = 0; unsigned char filterptr = 0; unsigned char funktable[2]; unsigned char masterfader = 0x0f; int psnum = 0; int songinit = 0; int lastsonginit = 0; int startpattpos = 0; void sequencer(int c, CHN *cptr); void initchannels(void) { int c; CHN *cptr = &chn[0]; memset(chn, 0, sizeof chn); for (c = 0; c < MAX_CHN; c++) { chn[c].trans = 0; chn[c].instr = 1; if (multiplier) cptr->tempo = 6*multiplier-1; else cptr->tempo = 6-1; cptr++; } if (multiplier) { funktable[0] = 9*multiplier-1; funktable[1] = 6*multiplier-1; } else { funktable[0] = 9-1; funktable[1] = 6-1; } } void initsong(int num, int mode) { sound_suspend(); songinit = PLAY_STOPPED; psnum = num; songinit = mode; startpattpos = 0; sound_flush(); } void initsongpos(int num, int mode, int pattpos) { sound_suspend(); songinit = PLAY_STOPPED; psnum = num; songinit = mode; startpattpos = pattpos; sound_flush(); } void stopsong(void) { if (songinit != PLAY_STOPPED) { sound_suspend(); songinit = PLAY_STOP; sound_flush(); } } void rewindsong(void) { if (lastsonginit == PLAY_BEGINNING) lastsonginit = PLAY_POS; initsong(psnum, lastsonginit); } void playtestnote(int note, int ins, int chnnum) { if (note == KEYON) return; if ((note == REST) || (note == KEYOFF)) { releasenote(chnnum); return; } if (!(instr[ins].gatetimer & 0x40)) { chn[chnnum].gate = 0xfe; // Keyoff if (!(instr[ins].gatetimer & 0x80)) { sidreg[0x5+chnnum*7] = adparam>>8; // Hardrestart sidreg[0x6+chnnum*7] = adparam&0xff; } } chn[chnnum].instr = ins; chn[chnnum].newnote = note; if (songinit == PLAY_STOPPED) { chn[chnnum].tick = (instr[ins].gatetimer & 0x3f)+1; chn[chnnum].gatetimer = instr[ins].gatetimer & 0x3f; } } void releasenote(int chnnum) { chn[chnnum].gate = 0xfe; } void mutechannel(int chnnum) { chn[chnnum].mute ^= 1; } int isplaying(void) { return (songinit != PLAY_STOPPED); } void playroutine(void) { INSTR *iptr; CHN *cptr = &chn[0]; int c; if (songinit == PLAY_STOP) followplay = 0; if ((songinit > 0) && (songinit < PLAY_STOPPED)) { lastsonginit = songinit; filterctrl = 0; filterptr = 0; resettime(); if ((songinit == 0x02) || (songinit == 0x03)) { if ((espos[0] >= songlen[psnum][0]) || (espos[1] >= songlen[psnum][1]) || (espos[2] >= songlen[psnum][2])) songinit = 0x01; } for (c = 0; c < MAX_CHN; c++) { cptr->songptr = 0; cptr->command = 0; cptr->cmddata = 0; cptr->newcommand = 0; cptr->newcmddata = 0; cptr->advance = 1; cptr->wave = 0; cptr->ptr[WTBL] = 0; cptr->newnote = 0; cptr->repeat = 0; if (multiplier) cptr->tick = 6*multiplier-1; else cptr->tick = 6-1; cptr->gatetimer = instr[1].gatetimer & 0x3f; cptr->pattptr = 0x7fffffff; if (cptr->tempo < 2) cptr->tempo = 0; switch (songinit) { case PLAY_BEGINNING: if (multiplier) { funktable[0] = 9*multiplier-1; funktable[1] = 6*multiplier-1; cptr->tempo = 6*multiplier-1; } else { funktable[0] = 9-1; funktable[1] = 6-1; cptr->tempo = 6-1; } if ((instr[MAX_INSTR-1].ad >= 2) && (!(instr[MAX_INSTR-1].ptr[WTBL]))) cptr->tempo = instr[MAX_INSTR-1].ad - 1; cptr->trans = 0; cptr->instr = 1; sequencer(c, cptr); break; case PLAY_PATTERN: cptr->advance = 0; cptr->pattptr = startpattpos * 4; cptr->pattnum = epnum[c]; if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4)) cptr->pattptr = 0; break; case PLAY_POS: cptr->songptr = espos[c]; sequencer(c, cptr); break; } cptr++; } if (songinit != PLAY_STOP) songinit = 0; else songinit = PLAY_STOPPED; if ((!songlen[psnum][0]) || (!songlen[psnum][1]) || (!songlen[psnum][2])) songinit = PLAY_STOPPED; // Zero length song startpattpos = 0; } else { if (filterptr) { // Filter jump if (ltable[FTBL][filterptr-1] == 0xff) { filterptr = rtable[FTBL][filterptr-1]; if (!filterptr) goto FILTERSTOP; } if (!filtertime) { // Filter set if (ltable[FTBL][filterptr-1] >= 0x80) { filtertype = ltable[FTBL][filterptr-1] & 0x70; filterctrl = rtable[FTBL][filterptr-1]; filterptr++; // Can be combined with cutoff set if (ltable[FTBL][filterptr-1] == 0x00) { filtercutoff = rtable[FTBL][filterptr-1]; filterptr++; } } else { // New modulation step if (ltable[FTBL][filterptr-1]) filtertime = ltable[FTBL][filterptr-1]; else { // Cutoff set filtercutoff = rtable[FTBL][filterptr-1]; filterptr++; } } } // Filter modulation if (filtertime) { filtercutoff += rtable[FTBL][filterptr-1]; filtertime--; if (!filtertime) filterptr++; } } FILTERSTOP: sidreg[0x15] = 0x00; sidreg[0x16] = filtercutoff; sidreg[0x17] = filterctrl; sidreg[0x18] = filtertype | masterfader; for (c = 0; c < MAX_CHN; c++) { iptr = &instr[cptr->instr]; // Reset tempo in jammode if ((songinit == PLAY_STOPPED) && (cptr->tempo < 2)) { if (multiplier) cptr->tempo = 6*multiplier-1; else cptr->tempo = 6-1; } // Decrease tick cptr->tick--; if (!cptr->tick) goto TICK0; // Tick N // Reload counter if (cptr->tick >= 0x80) { if (cptr->tempo >= 2) cptr->tick = cptr->tempo; else { // Set funktempo, switch between 2 values cptr->tick = funktable[cptr->tempo]; cptr->tempo ^= 1; } // Check for illegally high gatetimer and stop the song in this case if (chn->gatetimer > cptr->tick) stopsong(); } goto WAVEEXEC; // Tick 0 TICK0: // Advance in sequencer sequencer(c, cptr); // Get gatetimer compare-value cptr->gatetimer = iptr->gatetimer & 0x3f; // New note init if (cptr->newnote) { cptr->note = cptr->newnote-FIRSTNOTE; cptr->command = 0; cptr->vibdelay = iptr->vibdelay; cptr->cmddata = iptr->ptr[STBL]; if (cptr->newcommand != CMD_TONEPORTA) { if (iptr->firstwave) { if (iptr->firstwave >= 0xfe) cptr->gate = iptr->firstwave; else { cptr->wave = iptr->firstwave; cptr->gate = 0xff; } } cptr->ptr[WTBL] = iptr->ptr[WTBL]; if (cptr->ptr[WTBL]) { // Stop the song in case of jumping into a jump if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff) stopsong(); } if (iptr->ptr[PTBL]) { cptr->ptr[PTBL] = iptr->ptr[PTBL]; cptr->pulsetime = 0; if (cptr->ptr[PTBL]) { // Stop the song in case of jumping into a jump if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) stopsong(); } } if (iptr->ptr[FTBL]) { filterptr = iptr->ptr[FTBL]; filtertime = 0; if (filterptr) { // Stop the song in case of jumping into a jump if (ltable[FTBL][filterptr-1] == 0xff) stopsong(); } } sidreg[0x5+7*c] = iptr->ad; sidreg[0x6+7*c] = iptr->sr; } } // Tick 0 effects switch (cptr->newcommand) { case CMD_DONOTHING: cptr->command = 0; cptr->cmddata = iptr->ptr[STBL]; break; case CMD_PORTAUP: case CMD_PORTADOWN: cptr->vibtime = 0; cptr->command = cptr->newcommand; cptr->cmddata = cptr->newcmddata; break; case CMD_TONEPORTA: case CMD_VIBRATO: cptr->command = cptr->newcommand; cptr->cmddata = cptr->newcmddata; break; case CMD_SETAD: sidreg[0x5+7*c] = cptr->newcmddata; break; case CMD_SETSR: sidreg[0x6+7*c] = cptr->newcmddata; break; case CMD_SETWAVE: cptr->wave = cptr->newcmddata; break; case CMD_SETWAVEPTR: cptr->ptr[WTBL] = cptr->newcmddata; cptr->wavetime = 0; if (cptr->ptr[WTBL]) { // Stop the song in case of jumping into a jump if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff) stopsong(); } break; case CMD_SETPULSEPTR: cptr->ptr[PTBL] = cptr->newcmddata; cptr->pulsetime = 0; if (cptr->ptr[PTBL]) { // Stop the song in case of jumping into a jump if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) stopsong(); } break; case CMD_SETFILTERPTR: filterptr = cptr->newcmddata; filtertime = 0; if (filterptr) { // Stop the song in case of jumping into a jump if (ltable[FTBL][filterptr-1] == 0xff) stopsong(); } break; case CMD_SETFILTERCTRL: filterctrl = cptr->newcmddata; if (!filterctrl) filterptr = 0; break; case CMD_SETFILTERCUTOFF: filtercutoff = cptr->newcmddata; break; case CMD_SETMASTERVOL: if (cptr->newcmddata < 0x10) masterfader = cptr->newcmddata; break; case CMD_FUNKTEMPO: if (cptr->newcmddata) { funktable[0] = ltable[STBL][cptr->newcmddata-1]-1; funktable[1] = rtable[STBL][cptr->newcmddata-1]-1; } chn[0].tempo = 0; chn[1].tempo = 0; chn[2].tempo = 0; break; case CMD_SETTEMPO: { unsigned char newtempo = cptr->newcmddata & 0x7f; if (newtempo >= 3) newtempo--; if (cptr->newcmddata >= 0x80) cptr->tempo = newtempo; else { chn[0].tempo = newtempo; chn[1].tempo = newtempo; chn[2].tempo = newtempo; } } break; } if (cptr->newnote) { cptr->newnote = 0; if (cptr->newcommand != CMD_TONEPORTA) goto NEXTCHN; } WAVEEXEC: if (cptr->ptr[WTBL]) { unsigned char wave = ltable[WTBL][cptr->ptr[WTBL]-1]; unsigned char note = rtable[WTBL][cptr->ptr[WTBL]-1]; if (wave > WAVELASTDELAY) { // Normal waveform values if (wave < WAVESILENT) cptr->wave = wave; // Values without waveform selected if ((wave >= WAVESILENT) && (wave <= WAVELASTSILENT)) cptr->wave = wave & 0xf; // Command execution from wavetable if ((wave >= WAVECMD) && (wave <= WAVELASTCMD)) { unsigned char param = rtable[WTBL][cptr->ptr[WTBL]-1]; switch (wave & 0xf) { case CMD_DONOTHING: case CMD_SETWAVEPTR: case CMD_FUNKTEMPO: stopsong(); break; case CMD_PORTAUP: { unsigned short speed = 0; if (param) { speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1]; } if (speed >= 0x8000) { speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][param-1]; } cptr->freq += speed; } break; case CMD_PORTADOWN: { unsigned short speed = 0; if (param) { speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1]; } if (speed >= 0x8000) { speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][param-1]; } cptr->freq -= speed; } break; case CMD_TONEPORTA: { unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8); unsigned short speed = 0; if (!param) { cptr->freq = targetfreq; cptr->vibtime = 0; } else { speed = (ltable[STBL][param-1] << 8) | rtable[STBL][param-1]; if (speed >= 0x8000) { speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][param-1]; } if (cptr->freq < targetfreq) { cptr->freq += speed; if (cptr->freq > targetfreq) { cptr->freq = targetfreq; cptr->vibtime = 0; } } if (cptr->freq > targetfreq) { cptr->freq -= speed; if (cptr->freq < targetfreq) { cptr->freq = targetfreq; cptr->vibtime = 0; } } } } break; case CMD_VIBRATO: { unsigned short speed = 0; unsigned char cmpvalue = 0; if (param) { cmpvalue = ltable[STBL][param-1]; speed = rtable[STBL][param-1]; } if (cmpvalue >= 0x80) { cmpvalue &= 0x7f; speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][param-1]; } if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue)) cptr->vibtime ^= 0xff; cptr->vibtime += 0x02; if (cptr->vibtime & 0x01) cptr->freq -= speed; else cptr->freq += speed; } break; case CMD_SETAD: sidreg[0x5+7*c] = param; break; case CMD_SETSR: sidreg[0x6+7*c] = param;; break; case CMD_SETWAVE: cptr->wave = param; break; case CMD_SETPULSEPTR: cptr->ptr[PTBL] = param; cptr->pulsetime = 0; if (cptr->ptr[PTBL]) { // Stop the song in case of jumping into a jump if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) stopsong(); } break; case CMD_SETFILTERPTR: filterptr = param; filtertime = 0; if (filterptr) { // Stop the song in case of jumping into a jump if (ltable[FTBL][filterptr-1] == 0xff) stopsong(); } break; case CMD_SETFILTERCTRL: filterctrl = param; if (!filterctrl) filterptr = 0; break; case CMD_SETFILTERCUTOFF: filtercutoff = param; break; case CMD_SETMASTERVOL: if (cptr->newcmddata < 0x10) masterfader = param; break; } } } else { // Wavetable delay if (cptr->wavetime != wave) { cptr->wavetime++; goto TICKNEFFECTS; } } cptr->wavetime = 0; cptr->ptr[WTBL]++; // Wavetable jump if (ltable[WTBL][cptr->ptr[WTBL]-1] == 0xff) { cptr->ptr[WTBL] = rtable[WTBL][cptr->ptr[WTBL]-1]; } if ((wave >= WAVECMD) && (wave <= WAVELASTCMD)) goto PULSEEXEC; if (note != 0x80) { if (note < 0x80) note += cptr->note; note &= 0x7f; cptr->freq = freqtbllo[note] | (freqtblhi[note]<<8); cptr->vibtime = 0; cptr->lastnote = note; goto PULSEEXEC; } } // Tick N command TICKNEFFECTS: if ((!optimizerealtime) || (cptr->tick)) { switch(cptr->command) { case CMD_PORTAUP: { unsigned short speed = 0; if (cptr->cmddata) { speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1]; } if (speed >= 0x8000) { speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][cptr->cmddata-1]; } cptr->freq += speed; } break; case CMD_PORTADOWN: { unsigned short speed = 0; if (cptr->cmddata) { speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1]; } if (speed >= 0x8000) { speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][cptr->cmddata-1]; } cptr->freq -= speed; } break; case CMD_DONOTHING: if ((!cptr->cmddata) || (!cptr->vibdelay)) break; if (cptr->vibdelay > 1) { cptr->vibdelay--; break; } case CMD_VIBRATO: { unsigned short speed = 0; unsigned char cmpvalue = 0; if (cptr->cmddata) { cmpvalue = ltable[STBL][cptr->cmddata-1]; speed = rtable[STBL][cptr->cmddata-1]; } if (cmpvalue >= 0x80) { cmpvalue &= 0x7f; speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][cptr->cmddata-1]; } if ((cptr->vibtime < 0x80) && (cptr->vibtime > cmpvalue)) cptr->vibtime ^= 0xff; cptr->vibtime += 0x02; if (cptr->vibtime & 0x01) cptr->freq -= speed; else cptr->freq += speed; } break; case CMD_TONEPORTA: { unsigned short targetfreq = freqtbllo[cptr->note] | (freqtblhi[cptr->note] << 8); unsigned short speed = 0; if (!cptr->cmddata) { cptr->freq = targetfreq; cptr->vibtime = 0; } else { speed = (ltable[STBL][cptr->cmddata-1] << 8) | rtable[STBL][cptr->cmddata-1]; if (speed >= 0x8000) { speed = freqtbllo[cptr->lastnote + 1] | (freqtblhi[cptr->lastnote + 1] << 8); speed -= freqtbllo[cptr->lastnote] | (freqtblhi[cptr->lastnote] << 8); speed >>= rtable[STBL][cptr->cmddata-1]; } if (cptr->freq < targetfreq) { cptr->freq += speed; if (cptr->freq > targetfreq) { cptr->freq = targetfreq; cptr->vibtime = 0; } } if (cptr->freq > targetfreq) { cptr->freq -= speed; if (cptr->freq < targetfreq) { cptr->freq = targetfreq; cptr->vibtime = 0; } } } } break; } } PULSEEXEC: if (optimizepulse) { if ((songinit != PLAY_STOPPED) && (cptr->tick == cptr->gatetimer)) goto GETNEWNOTES; } if (cptr->ptr[PTBL]) { // Skip pulse when sequencer has been executed if (optimizepulse) { if ((!cptr->tick) && (!cptr->pattptr)) goto NEXTCHN; } // Pulsetable jump if (ltable[PTBL][cptr->ptr[PTBL]-1] == 0xff) { cptr->ptr[PTBL] = rtable[PTBL][cptr->ptr[PTBL]-1]; if (!cptr->ptr[PTBL]) goto PULSEEXEC; } if (!cptr->pulsetime) { // Set pulse if (ltable[PTBL][cptr->ptr[PTBL]-1] >= 0x80) { cptr->pulse = (ltable[PTBL][cptr->ptr[PTBL]-1] & 0xf) << 8; cptr->pulse |= rtable[PTBL][cptr->ptr[PTBL]-1]; cptr->ptr[PTBL]++; } else { cptr->pulsetime = ltable[PTBL][cptr->ptr[PTBL]-1]; } } // Pulse modulation if (cptr->pulsetime) { unsigned char speed = rtable[PTBL][cptr->ptr[PTBL]-1]; if (speed < 0x80) { cptr->pulse += speed; cptr->pulse &= 0xfff; } else { cptr->pulse += speed; cptr->pulse -= 0x100; cptr->pulse &= 0xfff; } cptr->pulsetime--; if (!cptr->pulsetime) cptr->ptr[PTBL]++; } } if ((songinit == PLAY_STOPPED) || (cptr->tick != cptr->gatetimer)) goto NEXTCHN; // New notes processing GETNEWNOTES: { unsigned char newnote; newnote = pattern[cptr->pattnum][cptr->pattptr]; if (pattern[cptr->pattnum][cptr->pattptr+1]) cptr->instr = pattern[cptr->pattnum][cptr->pattptr+1]; cptr->newcommand = pattern[cptr->pattnum][cptr->pattptr+2]; cptr->newcmddata = pattern[cptr->pattnum][cptr->pattptr+3]; cptr->pattptr += 4; if (pattern[cptr->pattnum][cptr->pattptr] == ENDPATT) cptr->pattptr = 0x7fffffff; if (newnote == KEYOFF) cptr->gate = 0xfe; if (newnote == KEYON) cptr->gate = 0xff; if (newnote <= LASTNOTE) { cptr->newnote = newnote+cptr->trans; if ((cptr->newcommand) != CMD_TONEPORTA) { if (!(instr[cptr->instr].gatetimer & 0x40)) { cptr->gate = 0xfe; if (!(instr[cptr->instr].gatetimer & 0x80)) { sidreg[0x5+7*c] = adparam>>8; sidreg[0x6+7*c] = adparam&0xff; } } } } } NEXTCHN: if (cptr->mute) sidreg[0x4+7*c] = cptr->wave = 0x08; else { sidreg[0x0+7*c] = cptr->freq & 0xff; sidreg[0x1+7*c] = cptr->freq >> 8; sidreg[0x2+7*c] = cptr->pulse & 0xfe; sidreg[0x3+7*c] = cptr->pulse >> 8; sidreg[0x4+7*c] = cptr->wave & cptr->gate; } cptr++; } } if (songinit != PLAY_STOPPED) incrementtime(); } void sequencer(int c, CHN *cptr) { if ((songinit != PLAY_STOPPED) && (cptr->pattptr == 0x7fffffff)) { cptr->pattptr = startpattpos * 4; if (!cptr->advance) goto SEQDONE; // Song loop if (songorder[psnum][c][cptr->songptr] == LOOPSONG) { cptr->songptr = songorder[psnum][c][cptr->songptr+1]; if (cptr->songptr >= songlen[psnum][c]) { stopsong(); cptr->songptr = 0; goto SEQDONE; } } // Transpose if ((songorder[psnum][c][cptr->songptr] >= TRANSDOWN) && (songorder[psnum][c][cptr->songptr] < LOOPSONG)) { cptr->trans = songorder[psnum][c][cptr->songptr]-TRANSUP; cptr->songptr++; } // Repeat if ((songorder[psnum][c][cptr->songptr] >= REPEAT) && (songorder[psnum][c][cptr->songptr] < TRANSDOWN)) { cptr->repeat = songorder[psnum][c][cptr->songptr]-REPEAT; cptr->songptr++; } // Pattern number cptr->pattnum = songorder[psnum][c][cptr->songptr]; if (cptr->repeat) cptr->repeat--; else cptr->songptr++; // Check for illegal pattern now if (cptr->pattnum >= MAX_PATT) { stopsong(); cptr->pattnum = 0; } if (cptr->pattptr >= (pattlen[cptr->pattnum] * 4)) cptr->pattptr = 0; // Check for playback endpos if ((lastsonginit != PLAY_BEGINNING) && (esend[c] > 0) && (esend[c] > espos[c]) && (cptr->songptr > esend[c]) && (espos[c] < songlen[psnum][c])) cptr->songptr = espos[c]; } SEQDONE: {} } goattracker-2.72/src/resid/0000755000000000000000000000000011604145110014336 5ustar rootrootgoattracker-2.72/src/resid/wave8580_PST.cpp0000644000000000000000000010110211313456166017067 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave8580_PST[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x70, /* 0x7f0: */ 0x60, 0x20, 0x70, 0x70, 0x70, 0x70, 0x70, 0x78, /* 0x7f8: */ 0x78, 0x78, 0x7c, 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, /* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x1e, 0x3f, /* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xdf8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8c, 0x9f, /* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 0xe68: */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe78: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe80: */ 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, 0x80, /* 0xe88: */ 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xea0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xea8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xeb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xeb8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xec0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xec8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xed0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xed8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xee0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xee8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, /* 0xef0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xef8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf, /* 0xf00: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf08: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf10: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf18: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf20: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf28: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf30: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf38: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf40: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf48: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf50: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf58: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf60: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf68: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, /* 0xf70: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf78: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe3, /* 0xf80: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf88: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf90: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf98: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xfa0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xfa8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xfb0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, /* 0xfb8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfc0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfc8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfd0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfd8: */ 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfe0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfe8: */ 0xf8, 0xf8, 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, /* 0xff0: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, /* 0xff8: */ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; goattracker-2.72/src/resid/wave6581__ST.cpp0000644000000000000000000010110211313456166017105 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave6581__ST[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3f0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, /* 0x3f8: */ 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x3f, 0x3f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7e0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, /* 0x7e8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, /* 0x7f0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, /* 0x7f8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, /* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, /* 0xbf8: */ 0x1e, 0x1e, 0x1e, 0x1e, 0x1f, 0x1f, 0x3f, 0x3f, /* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f, /* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, /* 0xfe8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, /* 0xff0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, /* 0xff8: */ 0x3e, 0x3e, 0x3f, 0x3f, 0x7f, 0x7f, 0x7f, 0x7f, }; goattracker-2.72/src/resid/wave6581_PS_.cpp0000644000000000000000000010110211313456166017101 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave6581_PS_[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, /* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3f, /* 0x3f8: */ 0x00, 0x30, 0x38, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, /* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5f, /* 0x5f8: */ 0x00, 0x40, 0x40, 0x5f, 0x5c, 0x5f, 0x5f, 0x5f, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6b, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x6d, /* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x6e8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x6e, /* 0x6f0: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x6f, /* 0x6f8: */ 0x00, 0x60, 0x60, 0x6f, 0x60, 0x6f, 0x6f, 0x6f, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x738: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x60, 0x73, /* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x758: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x75, /* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x768: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x76, /* 0x770: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x77, /* 0x778: */ 0x00, 0x70, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, /* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x798: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x79, /* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x7a8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x70, 0x7a, /* 0x7b0: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7b, /* 0x7b8: */ 0x40, 0x70, 0x70, 0x7b, 0x78, 0x7b, 0x7b, 0x7b, /* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, /* 0x7c8: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7c, /* 0x7d0: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7d, /* 0x7d8: */ 0x40, 0x70, 0x78, 0x7d, 0x78, 0x7d, 0x7d, 0x7d, /* 0x7e0: */ 0x00, 0x40, 0x40, 0x78, 0x60, 0x78, 0x78, 0x7e, /* 0x7e8: */ 0x60, 0x78, 0x78, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e, /* 0x7f0: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, /* 0x7f8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, /* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1f, /* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2f, /* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, /* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, /* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3f, /* 0xbf8: */ 0x00, 0x30, 0x38, 0x3f, 0x3e, 0x3f, 0x3f, 0x3f, /* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4f, /* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x57, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5d, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x5f, /* 0xdf8: */ 0x00, 0x40, 0x40, 0x5f, 0x5c, 0x5f, 0x5f, 0x5f, /* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, /* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6b, /* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x6d, /* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0xee8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x6e, /* 0xef0: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x6f, /* 0xef8: */ 0x00, 0x60, 0x60, 0x6f, 0x60, 0x6f, 0x6f, 0x6f, /* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0xf38: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x60, 0x73, /* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0xf58: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x60, 0x60, 0x75, /* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0xf68: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x76, /* 0xf70: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x77, /* 0xf78: */ 0x00, 0x70, 0x70, 0x77, 0x70, 0x77, 0x77, 0x77, /* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0xf98: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x79, /* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0xfa8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x70, 0x70, 0x7a, /* 0xfb0: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7b, /* 0xfb8: */ 0x40, 0x70, 0x70, 0x7b, 0x78, 0x7b, 0x7b, 0x7b, /* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, /* 0xfc8: */ 0x00, 0x00, 0x00, 0x70, 0x00, 0x70, 0x70, 0x7c, /* 0xfd0: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7d, /* 0xfd8: */ 0x40, 0x70, 0x78, 0x7d, 0x78, 0x7d, 0x7d, 0x7d, /* 0xfe0: */ 0x00, 0x40, 0x40, 0x78, 0x60, 0x78, 0x78, 0x7e, /* 0xfe8: */ 0x60, 0x78, 0x78, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e, /* 0xff0: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7c, 0x7f, 0x7f, 0x7f, /* 0xff8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, }; goattracker-2.72/src/resid/wave8580_PS_.cpp0000644000000000000000000010110211313456166017102 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave8580_PS_[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x1f, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0f, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x17, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3d, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, /* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, /* 0x3f8: */ 0x00, 0x0c, 0x1c, 0x3f, 0x1e, 0x3f, 0x3f, 0x3f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5e, /* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5f, /* 0x5f8: */ 0x00, 0x00, 0x00, 0x5f, 0x0c, 0x5f, 0x5f, 0x5f, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x65, /* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, /* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6f, /* 0x6f8: */ 0x00, 0x40, 0x40, 0x6f, 0x40, 0x6f, 0x6f, 0x6f, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, /* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x61, /* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x768: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x70, /* 0x770: */ 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x70, /* 0x778: */ 0x40, 0x60, 0x60, 0x77, 0x60, 0x77, 0x77, 0x77, /* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, /* 0x798: */ 0x00, 0x40, 0x40, 0x60, 0x40, 0x60, 0x60, 0x79, /* 0x7a0: */ 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x60, /* 0x7a8: */ 0x40, 0x40, 0x40, 0x60, 0x60, 0x60, 0x60, 0x78, /* 0x7b0: */ 0x40, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, /* 0x7b8: */ 0x60, 0x70, 0x70, 0x78, 0x70, 0x79, 0x7b, 0x7b, /* 0x7c0: */ 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, /* 0x7c8: */ 0x60, 0x60, 0x60, 0x70, 0x60, 0x70, 0x70, 0x7c, /* 0x7d0: */ 0x60, 0x70, 0x70, 0x70, 0x70, 0x70, 0x70, 0x7c, /* 0x7d8: */ 0x70, 0x78, 0x78, 0x7c, 0x78, 0x7c, 0x7c, 0x7d, /* 0x7e0: */ 0x70, 0x78, 0x78, 0x78, 0x78, 0x78, 0x78, 0x7c, /* 0x7e8: */ 0x78, 0x7c, 0x7c, 0x7e, 0x7c, 0x7e, 0x7e, 0x7e, /* 0x7f0: */ 0x7c, 0x7c, 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, /* 0x7f8: */ 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0xff, /* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, /* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8f, /* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, /* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, /* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x8d, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x8e, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x8f, /* 0x9f8: */ 0x80, 0x80, 0x80, 0x9f, 0x80, 0x9f, 0x9f, 0x9f, /* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xa78: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x87, /* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xab8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x83, /* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, /* 0xad8: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, /* 0xae0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xae8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x84, /* 0xaf0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x87, /* 0xaf8: */ 0x80, 0x80, 0x80, 0x87, 0x80, 0x8f, 0xaf, 0xaf, /* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0xb18: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb20: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80, 0x80, /* 0xb28: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb30: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb38: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x83, /* 0xb40: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb48: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb50: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb58: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, /* 0xb60: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb68: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, /* 0xb70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, /* 0xb78: */ 0x80, 0x80, 0x80, 0xa0, 0x80, 0xa3, 0xb7, 0xb7, /* 0xb80: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xb1, /* 0xba0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xba8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xb0, /* 0xbb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xb0, /* 0xbb8: */ 0x80, 0xa0, 0xa0, 0xb0, 0xa0, 0xb8, 0xb9, 0xbb, /* 0xbc0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, /* 0xbc8: */ 0x80, 0x80, 0x80, 0xa0, 0x80, 0xa0, 0xa0, 0xb8, /* 0xbd0: */ 0x80, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xb8, /* 0xbd8: */ 0xa0, 0xb0, 0xb0, 0xb8, 0xb0, 0xbc, 0xbc, 0xbd, /* 0xbe0: */ 0xa0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb8, 0xb8, 0xbc, /* 0xbe8: */ 0xb0, 0xb8, 0xb8, 0xbc, 0xb8, 0xbc, 0xbe, 0xbe, /* 0xbf0: */ 0xb8, 0xbc, 0xbc, 0xbe, 0xbc, 0xbe, 0xbe, 0xbf, /* 0xbf8: */ 0xbe, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, /* 0xc00: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, /* 0xc08: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, /* 0xc10: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc18: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc20: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc28: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc30: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc38: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x81, /* 0xc40: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc48: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc50: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc58: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc60: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc68: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc78: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc7, /* 0xc80: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xc98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xca0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xca8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xcb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xcb8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc3, /* 0xcc0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xcc8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0xcd0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0xcd8: */ 0x80, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc1, /* 0xce0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0xce8: */ 0x80, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xcf0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc7, /* 0xcf8: */ 0xc0, 0xc0, 0xc0, 0xc7, 0xc0, 0xcf, 0xcf, 0xcf, /* 0xd00: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xd08: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xd10: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xd18: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0xd20: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xd28: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0xd30: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, /* 0xd38: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc3, /* 0xd40: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0xd48: */ 0x80, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, /* 0xd50: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd58: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, /* 0xd60: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd68: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd70: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd78: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc1, 0xc7, 0xd7, /* 0xd80: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd88: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd90: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xd98: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xda0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xda8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, /* 0xdb0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, /* 0xdb8: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd8, 0xdb, /* 0xdc0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xdc8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, /* 0xdd0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd8, /* 0xdd8: */ 0xc0, 0xc0, 0xc0, 0xd8, 0xd0, 0xd8, 0xd8, 0xdd, /* 0xde0: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd0, 0xdc, /* 0xde8: */ 0xd0, 0xd8, 0xd8, 0xdc, 0xd8, 0xdc, 0xdc, 0xde, /* 0xdf0: */ 0xd8, 0xdc, 0xdc, 0xde, 0xdc, 0xde, 0xde, 0xdf, /* 0xdf8: */ 0xde, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, 0xdf, /* 0xe00: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe08: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe10: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe18: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe20: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe28: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe30: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe38: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe3, /* 0xe40: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe48: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xe50: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, /* 0xe58: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe1, /* 0xe60: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, /* 0xe68: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xe70: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xe78: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe1, 0xe3, 0xe7, /* 0xe80: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, /* 0xe88: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, /* 0xe90: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, /* 0xe98: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xea0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xea8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xeb0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xeb8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xeb, /* 0xec0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xec8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xed0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xed8: */ 0xe0, 0xe0, 0xe0, 0xe8, 0xe0, 0xe8, 0xe8, 0xed, /* 0xee0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xec, /* 0xee8: */ 0xe0, 0xe0, 0xe0, 0xec, 0xe8, 0xec, 0xec, 0xee, /* 0xef0: */ 0xe8, 0xe8, 0xe8, 0xec, 0xec, 0xee, 0xee, 0xef, /* 0xef8: */ 0xec, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, /* 0xf00: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf08: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf10: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf18: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, /* 0xf20: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, /* 0xf28: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf0, /* 0xf30: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf38: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf3, /* 0xf40: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf48: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf50: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf58: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf5, /* 0xf60: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf68: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, 0xf4, 0xf6, /* 0xf70: */ 0xf0, 0xf0, 0xf0, 0xf4, 0xf0, 0xf4, 0xf6, 0xf7, /* 0xf78: */ 0xf4, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, 0xf7, 0xf7, /* 0xf80: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, /* 0xf88: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf8, 0xf8, 0xf8, /* 0xf90: */ 0xf0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf8, /* 0xf98: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf9, /* 0xfa0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfa8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfa, /* 0xfb0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xfb, /* 0xfb8: */ 0xf8, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, 0xfb, 0xfb, /* 0xfc0: */ 0xf8, 0xf8, 0xf8, 0xfc, 0xf8, 0xfc, 0xfc, 0xfc, /* 0xfc8: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, /* 0xfd0: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, /* 0xfd8: */ 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, 0xfd, 0xfd, /* 0xfe0: */ 0xfc, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xfe8: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xff0: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xff8: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; goattracker-2.72/src/resid/sid.h0000644000000000000000000000720611313457374015312 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __SID_H__ #define __SID_H__ #include "siddefs.h" #include "voice.h" #include "filter.h" #include "extfilt.h" #include "pot.h" class SID { public: SID(); ~SID(); void set_chip_model(chip_model model); void enable_filter(bool enable); void enable_external_filter(bool enable); bool set_sampling_parameters(double clock_freq, sampling_method method, double sample_freq, double pass_freq = -1, double filter_scale = 0.97); void adjust_sampling_frequency(double sample_freq); void fc_default(const fc_point*& points, int& count); PointPlotter fc_plotter(); void clock(); void clock(cycle_count delta_t); int clock(cycle_count& delta_t, short* buf, int n, int interleave = 1); void reset(); // Read/write registers. reg8 read(reg8 offset); void write(reg8 offset, reg8 value); // Read/write state. class State { public: State(); char sid_register[0x20]; reg8 bus_value; cycle_count bus_value_ttl; reg24 accumulator[3]; reg24 shift_register[3]; reg16 rate_counter[3]; reg16 rate_counter_period[3]; reg16 exponential_counter[3]; reg16 exponential_counter_period[3]; reg8 envelope_counter[3]; EnvelopeGenerator::State envelope_state[3]; bool hold_zero[3]; }; State read_state(); void write_state(const State& state); // 16-bit input (EXT IN). void input(int sample); // 16-bit output (AUDIO OUT). int output(); // n-bit output. int output(int bits); protected: static double I0(double x); RESID_INLINE int clock_fast(cycle_count& delta_t, short* buf, int n, int interleave); RESID_INLINE int clock_interpolate(cycle_count& delta_t, short* buf, int n, int interleave); RESID_INLINE int clock_resample_interpolate(cycle_count& delta_t, short* buf, int n, int interleave); RESID_INLINE int clock_resample_fast(cycle_count& delta_t, short* buf, int n, int interleave); Voice voice[3]; Filter filter; ExternalFilter extfilt; Potentiometer potx; Potentiometer poty; reg8 bus_value; cycle_count bus_value_ttl; double clock_frequency; // External audio input. int ext_in; // Sampling variables. sampling_method sampling; cycle_count cycles_per_sample; cycle_count sample_offset; int sample_index; short sample_prev; int fir_N; int fir_RES; // Ring buffer with overflow for contiguous storage of RINGSIZE samples. short* sample; // FIR_RES filter tables (FIR_N*FIR_RES). short* fir; }; #endif // not __SID_H__ goattracker-2.72/src/resid/wave.h0000644000000000000000000003712611313456166015477 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __WAVE_H__ #define __WAVE_H__ #include "siddefs.h" // ---------------------------------------------------------------------------- // A 24 bit accumulator is the basis for waveform generation. FREQ is added to // the lower 16 bits of the accumulator each cycle. // The accumulator is set to zero when TEST is set, and starts counting // when TEST is cleared. // The noise waveform is taken from intermediate bits of a 23 bit shift // register. This register is clocked by bit 19 of the accumulator. // ---------------------------------------------------------------------------- class WaveformGenerator { public: WaveformGenerator(); void set_sync_source(WaveformGenerator*); void set_chip_model(chip_model model); RESID_INLINE void clock(); RESID_INLINE void clock(cycle_count delta_t); RESID_INLINE void synchronize(); void reset(); void writeFREQ_LO(reg8); void writeFREQ_HI(reg8); void writePW_LO(reg8); void writePW_HI(reg8); void writeCONTROL_REG(reg8); reg8 readOSC(); // 12-bit waveform output. RESID_INLINE reg12 output(); protected: const WaveformGenerator* sync_source; WaveformGenerator* sync_dest; // Tell whether the accumulator MSB was set high on this cycle. bool msb_rising; reg24 accumulator; reg24 shift_register; // Fout = (Fn*Fclk/16777216)Hz reg16 freq; // PWout = (PWn/40.95)% reg12 pw; // The control register right-shifted 4 bits; used for output function // table lookup. reg8 waveform; // The remaining control register bits. reg8 test; reg8 ring_mod; reg8 sync; // The gate bit is handled by the EnvelopeGenerator. // 16 possible combinations of waveforms. RESID_INLINE reg12 output____(); RESID_INLINE reg12 output___T(); RESID_INLINE reg12 output__S_(); RESID_INLINE reg12 output__ST(); RESID_INLINE reg12 output_P__(); RESID_INLINE reg12 output_P_T(); RESID_INLINE reg12 output_PS_(); RESID_INLINE reg12 output_PST(); RESID_INLINE reg12 outputN___(); RESID_INLINE reg12 outputN__T(); RESID_INLINE reg12 outputN_S_(); RESID_INLINE reg12 outputN_ST(); RESID_INLINE reg12 outputNP__(); RESID_INLINE reg12 outputNP_T(); RESID_INLINE reg12 outputNPS_(); RESID_INLINE reg12 outputNPST(); // Sample data for combinations of waveforms. static reg8 wave6581__ST[]; static reg8 wave6581_P_T[]; static reg8 wave6581_PS_[]; static reg8 wave6581_PST[]; static reg8 wave8580__ST[]; static reg8 wave8580_P_T[]; static reg8 wave8580_PS_[]; static reg8 wave8580_PST[]; reg8* wave__ST; reg8* wave_P_T; reg8* wave_PS_; reg8* wave_PST; friend class Voice; friend class SID; }; // ---------------------------------------------------------------------------- // Inline functions. // The following functions are defined inline because they are called every // time a sample is calculated. // ---------------------------------------------------------------------------- #if RESID_INLINING || defined(__WAVE_CC__) // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- RESID_INLINE void WaveformGenerator::clock() { // No operation if test bit is set. if (test) { return; } reg24 accumulator_prev = accumulator; // Calculate new accumulator value; accumulator += freq; accumulator &= 0xffffff; // Check whether the MSB is set high. This is used for synchronization. msb_rising = !(accumulator_prev & 0x800000) && (accumulator & 0x800000); // Shift noise register once for each time accumulator bit 19 is set high. if (!(accumulator_prev & 0x080000) && (accumulator & 0x080000)) { reg24 bit0 = ((shift_register >> 22) ^ (shift_register >> 17)) & 0x1; shift_register <<= 1; shift_register &= 0x7fffff; shift_register |= bit0; } } // ---------------------------------------------------------------------------- // SID clocking - delta_t cycles. // ---------------------------------------------------------------------------- RESID_INLINE void WaveformGenerator::clock(cycle_count delta_t) { // No operation if test bit is set. if (test) { return; } reg24 accumulator_prev = accumulator; // Calculate new accumulator value; reg24 delta_accumulator = delta_t*freq; accumulator += delta_accumulator; accumulator &= 0xffffff; // Check whether the MSB is set high. This is used for synchronization. msb_rising = !(accumulator_prev & 0x800000) && (accumulator & 0x800000); // Shift noise register once for each time accumulator bit 19 is set high. // Bit 19 is set high each time 2^20 (0x100000) is added to the accumulator. reg24 shift_period = 0x100000; while (delta_accumulator) { if (delta_accumulator < shift_period) { shift_period = delta_accumulator; // Determine whether bit 19 is set on the last period. // NB! Requires two's complement integer. if (shift_period <= 0x080000) { // Check for flip from 0 to 1. if (((accumulator - shift_period) & 0x080000) || !(accumulator & 0x080000)) { break; } } else { // Check for flip from 0 (to 1 or via 1 to 0) or from 1 via 0 to 1. if (((accumulator - shift_period) & 0x080000) && !(accumulator & 0x080000)) { break; } } } // Shift the noise/random register. // NB! The shift is actually delayed 2 cycles, this is not modeled. reg24 bit0 = ((shift_register >> 22) ^ (shift_register >> 17)) & 0x1; shift_register <<= 1; shift_register &= 0x7fffff; shift_register |= bit0; delta_accumulator -= shift_period; } } // ---------------------------------------------------------------------------- // Synchronize oscillators. // This must be done after all the oscillators have been clock()'ed since the // oscillators operate in parallel. // Note that the oscillators must be clocked exactly on the cycle when the // MSB is set high for hard sync to operate correctly. See SID::clock(). // ---------------------------------------------------------------------------- RESID_INLINE void WaveformGenerator::synchronize() { // A special case occurs when a sync source is synced itself on the same // cycle as when its MSB is set high. In this case the destination will // not be synced. This has been verified by sampling OSC3. if (msb_rising && sync_dest->sync && !(sync && sync_source->msb_rising)) { sync_dest->accumulator = 0; } } // ---------------------------------------------------------------------------- // Output functions. // NB! The output from SID 8580 is delayed one cycle compared to SID 6581, // this is not modeled. // ---------------------------------------------------------------------------- // No waveform: // Zero output. // RESID_INLINE reg12 WaveformGenerator::output____() { return 0x000; } // Triangle: // The upper 12 bits of the accumulator are used. // The MSB is used to create the falling edge of the triangle by inverting // the lower 11 bits. The MSB is thrown away and the lower 11 bits are // left-shifted (half the resolution, full amplitude). // Ring modulation substitutes the MSB with MSB EOR sync_source MSB. // RESID_INLINE reg12 WaveformGenerator::output___T() { reg24 msb = (ring_mod ? accumulator ^ sync_source->accumulator : accumulator) & 0x800000; return ((msb ? ~accumulator : accumulator) >> 11) & 0xfff; } // Sawtooth: // The output is identical to the upper 12 bits of the accumulator. // RESID_INLINE reg12 WaveformGenerator::output__S_() { return accumulator >> 12; } // Pulse: // The upper 12 bits of the accumulator are used. // These bits are compared to the pulse width register by a 12 bit digital // comparator; output is either all one or all zero bits. // NB! The output is actually delayed one cycle after the compare. // This is not modeled. // // The test bit, when set to one, holds the pulse waveform output at 0xfff // regardless of the pulse width setting. // RESID_INLINE reg12 WaveformGenerator::output_P__() { return (test || (accumulator >> 12) >= pw) ? 0xfff : 0x000; } // Noise: // The noise output is taken from intermediate bits of a 23-bit shift register // which is clocked by bit 19 of the accumulator. // NB! The output is actually delayed 2 cycles after bit 19 is set high. // This is not modeled. // // Operation: Calculate EOR result, shift register, set bit 0 = result. // // ----------------------->--------------------- // | | // ----EOR---- | // | | | // 2 2 2 1 1 1 1 1 1 1 1 1 1 | // Register bits: 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 <--- // | | | | | | | | // OSC3 bits : 7 6 5 4 3 2 1 0 // // Since waveform output is 12 bits the output is left-shifted 4 times. // RESID_INLINE reg12 WaveformGenerator::outputN___() { return ((shift_register & 0x400000) >> 11) | ((shift_register & 0x100000) >> 10) | ((shift_register & 0x010000) >> 7) | ((shift_register & 0x002000) >> 5) | ((shift_register & 0x000800) >> 4) | ((shift_register & 0x000080) >> 1) | ((shift_register & 0x000010) << 1) | ((shift_register & 0x000004) << 2); } // Combined waveforms: // By combining waveforms, the bits of each waveform are effectively short // circuited. A zero bit in one waveform will result in a zero output bit // (thus the infamous claim that the waveforms are AND'ed). // However, a zero bit in one waveform will also affect the neighboring bits // in the output. The reason for this has not been determined. // // Example: // // 1 1 // Bit # 1 0 9 8 7 6 5 4 3 2 1 0 // ----------------------- // Sawtooth 0 0 0 1 1 1 1 1 1 0 0 0 // // Triangle 0 0 1 1 1 1 1 1 0 0 0 0 // // AND 0 0 0 1 1 1 1 1 0 0 0 0 // // Output 0 0 0 0 1 1 1 0 0 0 0 0 // // // This behavior would be quite difficult to model exactly, since the SID // in this case does not act as a digital state machine. Tests show that minor // (1 bit) differences can actually occur in the output from otherwise // identical samples from OSC3 when waveforms are combined. To further // complicate the situation the output changes slightly with time (more // neighboring bits are successively set) when the 12-bit waveform // registers are kept unchanged. // // It is probably possible to come up with a valid model for the // behavior, however this would be far too slow for practical use since it // would have to be based on the mutual influence of individual bits. // // The output is instead approximated by using the upper bits of the // accumulator as an index to look up the combined output in a table // containing actual combined waveform samples from OSC3. // These samples are 8 bit, so 4 bits of waveform resolution is lost. // All OSC3 samples are taken with FREQ=0x1000, adding a 1 to the upper 12 // bits of the accumulator each cycle for a sample period of 4096 cycles. // // Sawtooth+Triangle: // The sawtooth output is used to look up an OSC3 sample. // // Pulse+Triangle: // The triangle output is right-shifted and used to look up an OSC3 sample. // The sample is output if the pulse output is on. // The reason for using the triangle output as the index is to handle ring // modulation. Only the first half of the sample is used, which should be OK // since the triangle waveform has half the resolution of the accumulator. // // Pulse+Sawtooth: // The sawtooth output is used to look up an OSC3 sample. // The sample is output if the pulse output is on. // // Pulse+Sawtooth+Triangle: // The sawtooth output is used to look up an OSC3 sample. // The sample is output if the pulse output is on. // RESID_INLINE reg12 WaveformGenerator::output__ST() { return wave__ST[output__S_()] << 4; } RESID_INLINE reg12 WaveformGenerator::output_P_T() { return (wave_P_T[output___T() >> 1] << 4) & output_P__(); } RESID_INLINE reg12 WaveformGenerator::output_PS_() { return (wave_PS_[output__S_()] << 4) & output_P__(); } RESID_INLINE reg12 WaveformGenerator::output_PST() { return (wave_PST[output__S_()] << 4) & output_P__(); } // Combined waveforms including noise: // All waveform combinations including noise output zero after a few cycles. // NB! The effects of such combinations are not fully explored. It is claimed // that the shift register may be filled with zeroes and locked up, which // seems to be true. // We have not attempted to model this behavior, suffice to say that // there is very little audible output from waveform combinations including // noise. We hope that nobody is actually using it. // RESID_INLINE reg12 WaveformGenerator::outputN__T() { return 0; } RESID_INLINE reg12 WaveformGenerator::outputN_S_() { return 0; } RESID_INLINE reg12 WaveformGenerator::outputN_ST() { return 0; } RESID_INLINE reg12 WaveformGenerator::outputNP__() { return 0; } RESID_INLINE reg12 WaveformGenerator::outputNP_T() { return 0; } RESID_INLINE reg12 WaveformGenerator::outputNPS_() { return 0; } RESID_INLINE reg12 WaveformGenerator::outputNPST() { return 0; } // ---------------------------------------------------------------------------- // Select one of 16 possible combinations of waveforms. // ---------------------------------------------------------------------------- RESID_INLINE reg12 WaveformGenerator::output() { // It may seem cleaner to use an array of member functions to return // waveform output; however a switch with inline functions is faster. switch (waveform) { default: case 0x0: return output____(); case 0x1: return output___T(); case 0x2: return output__S_(); case 0x3: return output__ST(); case 0x4: return output_P__(); case 0x5: return output_P_T(); case 0x6: return output_PS_(); case 0x7: return output_PST(); case 0x8: return outputN___(); case 0x9: return outputN__T(); case 0xa: return outputN_S_(); case 0xb: return outputN_ST(); case 0xc: return outputNP__(); case 0xd: return outputNP_T(); case 0xe: return outputNPS_(); case 0xf: return outputNPST(); } } #endif // RESID_INLINING || defined(__WAVE_CC__) #endif // not __WAVE_H__ goattracker-2.72/src/resid/extfilt.h0000644000000000000000000001235211313456166016206 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __EXTFILT_H__ #define __EXTFILT_H__ #include "siddefs.h" // ---------------------------------------------------------------------------- // The audio output stage in a Commodore 64 consists of two STC networks, // a low-pass filter with 3-dB frequency 16kHz followed by a high-pass // filter with 3-dB frequency 16Hz (the latter provided an audio equipment // input impedance of 1kOhm). // The STC networks are connected with a BJT supposedly meant to act as // a unity gain buffer, which is not really how it works. A more elaborate // model would include the BJT, however DC circuit analysis yields BJT // base-emitter and emitter-base impedances sufficiently low to produce // additional low-pass and high-pass 3dB-frequencies in the order of hundreds // of kHz. This calls for a sampling frequency of several MHz, which is far // too high for practical use. // ---------------------------------------------------------------------------- class ExternalFilter { public: ExternalFilter(); void enable_filter(bool enable); void set_chip_model(chip_model model); RESID_INLINE void clock(sound_sample Vi); RESID_INLINE void clock(cycle_count delta_t, sound_sample Vi); void reset(); // Audio output (20 bits). RESID_INLINE sound_sample output(); protected: // Filter enabled. bool enabled; // Maximum mixer DC offset. sound_sample mixer_DC; // State of filters. sound_sample Vlp; // lowpass sound_sample Vhp; // highpass sound_sample Vo; // Cutoff frequencies. sound_sample w0lp; sound_sample w0hp; friend class SID; }; // ---------------------------------------------------------------------------- // Inline functions. // The following functions are defined inline because they are called every // time a sample is calculated. // ---------------------------------------------------------------------------- #if RESID_INLINING || defined(__EXTFILT_CC__) // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- RESID_INLINE void ExternalFilter::clock(sound_sample Vi) { // This is handy for testing. if (!enabled) { // Remove maximum DC level since there is no filter to do it. Vlp = Vhp = 0; Vo = Vi - mixer_DC; return; } // delta_t is converted to seconds given a 1MHz clock by dividing // with 1 000 000. // Calculate filter outputs. // Vo = Vlp - Vhp; // Vlp = Vlp + w0lp*(Vi - Vlp)*delta_t; // Vhp = Vhp + w0hp*(Vlp - Vhp)*delta_t; sound_sample dVlp = (w0lp >> 8)*(Vi - Vlp) >> 12; sound_sample dVhp = w0hp*(Vlp - Vhp) >> 20; Vo = Vlp - Vhp; Vlp += dVlp; Vhp += dVhp; } // ---------------------------------------------------------------------------- // SID clocking - delta_t cycles. // ---------------------------------------------------------------------------- RESID_INLINE void ExternalFilter::clock(cycle_count delta_t, sound_sample Vi) { // This is handy for testing. if (!enabled) { // Remove maximum DC level since there is no filter to do it. Vlp = Vhp = 0; Vo = Vi - mixer_DC; return; } // Maximum delta cycles for the external filter to work satisfactorily // is approximately 8. cycle_count delta_t_flt = 8; while (delta_t) { if (delta_t < delta_t_flt) { delta_t_flt = delta_t; } // delta_t is converted to seconds given a 1MHz clock by dividing // with 1 000 000. // Calculate filter outputs. // Vo = Vlp - Vhp; // Vlp = Vlp + w0lp*(Vi - Vlp)*delta_t; // Vhp = Vhp + w0hp*(Vlp - Vhp)*delta_t; sound_sample dVlp = (w0lp*delta_t_flt >> 8)*(Vi - Vlp) >> 12; sound_sample dVhp = w0hp*delta_t_flt*(Vlp - Vhp) >> 20; Vo = Vlp - Vhp; Vlp += dVlp; Vhp += dVhp; delta_t -= delta_t_flt; } } // ---------------------------------------------------------------------------- // Audio output (19.5 bits). // ---------------------------------------------------------------------------- RESID_INLINE sound_sample ExternalFilter::output() { return Vo; } #endif // RESID_INLINING || defined(__EXTFILT_CC__) #endif // not __EXTFILT_H__ goattracker-2.72/src/resid/wave.cpp0000644000000000000000000001043011313456166016017 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __WAVE_CC__ #include "wave.h" // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- WaveformGenerator::WaveformGenerator() { sync_source = this; set_chip_model(MOS6581); reset(); } // ---------------------------------------------------------------------------- // Set sync source. // ---------------------------------------------------------------------------- void WaveformGenerator::set_sync_source(WaveformGenerator* source) { sync_source = source; source->sync_dest = this; } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void WaveformGenerator::set_chip_model(chip_model model) { if (model == MOS6581) { wave__ST = wave6581__ST; wave_P_T = wave6581_P_T; wave_PS_ = wave6581_PS_; wave_PST = wave6581_PST; } else { wave__ST = wave8580__ST; wave_P_T = wave8580_P_T; wave_PS_ = wave8580_PS_; wave_PST = wave8580_PST; } } // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void WaveformGenerator::writeFREQ_LO(reg8 freq_lo) { freq = freq & 0xff00 | freq_lo & 0x00ff; } void WaveformGenerator::writeFREQ_HI(reg8 freq_hi) { freq = (freq_hi << 8) & 0xff00 | freq & 0x00ff; } void WaveformGenerator::writePW_LO(reg8 pw_lo) { pw = pw & 0xf00 | pw_lo & 0x0ff; } void WaveformGenerator::writePW_HI(reg8 pw_hi) { pw = (pw_hi << 8) & 0xf00 | pw & 0x0ff; } void WaveformGenerator::writeCONTROL_REG(reg8 control) { waveform = (control >> 4) & 0x0f; ring_mod = control & 0x04; sync = control & 0x02; reg8 test_next = control & 0x08; // Test bit set. // The accumulator and the shift register are both cleared. // NB! The shift register is not really cleared immediately. It seems like // the individual bits in the shift register start to fade down towards // zero when test is set. All bits reach zero within approximately // $2000 - $4000 cycles. // This is not modeled. There should fortunately be little audible output // from this peculiar behavior. if (test_next) { accumulator = 0; shift_register = 0; } // Test bit cleared. // The accumulator starts counting, and the shift register is reset to // the value 0x7ffff8. // NB! The shift register will not actually be set to this exact value if the // shift register bits have not had time to fade to zero. // This is not modeled. else if (test) { shift_register = 0x7ffff8; } test = test_next; // The gate bit is handled by the EnvelopeGenerator. } reg8 WaveformGenerator::readOSC() { return output() >> 4; } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void WaveformGenerator::reset() { accumulator = 0; shift_register = 0x7ffff8; freq = 0; pw = 0; test = 0; ring_mod = 0; sync = 0; msb_rising = false; } goattracker-2.72/src/resid/wave8580__ST.cpp0000644000000000000000000010110211313456166017106 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave8580__ST[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3f0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, /* 0x3f8: */ 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, 0x1f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x1f, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7e0: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, /* 0x7e8: */ 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, 0x38, /* 0x7f0: */ 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3c, 0x3e, /* 0x7f8: */ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x0f, 0x0f, /* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf0: */ 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, 0x1c, /* 0xbf8: */ 0x1e, 0x1e, 0x1f, 0x1f, 0x1f, 0x1f, 0x3f, 0x3f, /* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, /* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf8: */ 0x0e, 0x0e, 0x0e, 0x0e, 0x0f, 0x0f, 0x1f, 0x1f, /* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x83, 0x83, /* 0xe80: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xe98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xea0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xea8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xeb0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xeb8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xec0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xec8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xed0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xed8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xee0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xee8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xef0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xef8: */ 0x80, 0x80, 0x80, 0x80, 0x87, 0x87, 0x87, 0x8f, /* 0xf00: */ 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, /* 0xf08: */ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf10: */ 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf18: */ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0xf20: */ 0xc0, 0xe0, 0xe0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, /* 0xf28: */ 0xe0, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, /* 0xf30: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf38: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf40: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf48: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf50: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf58: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf60: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf68: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf70: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0xf78: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe3, 0xe3, /* 0xf80: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf88: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf90: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xf98: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfa0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfa8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfb0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0xfb8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf1, /* 0xfc0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfc8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfd0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfd8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0xfe0: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, /* 0xfe8: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, /* 0xff0: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0xff8: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; goattracker-2.72/src/resid/pot.h0000644000000000000000000000217610774364076015344 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __POT_H__ #define __POT_H__ #include "siddefs.h" class Potentiometer { public: reg8 readPOT(); }; #endif goattracker-2.72/src/resid/siddefs.h0000644000000000000000000000446711313456706016160 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 1999 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __SIDDEFS_H__ #define __SIDDEFS_H__ // Define bool, true, and false for C++ compilers that lack these keywords. #define RESID_HAVE_BOOL 1 #if !RESID_HAVE_BOOL typedef int bool; const bool true = 1; const bool false = 0; #endif // We could have used the smallest possible data type for each SID register, // however this would give a slower engine because of data type conversions. // An int is assumed to be at least 32 bits (necessary in the types reg24, // cycle_count, and sound_sample). GNU does not support 16-bit machines // (GNU Coding Standards: Portability between CPUs), so this should be // a valid assumption. typedef unsigned int reg4; typedef unsigned int reg8; typedef unsigned int reg12; typedef unsigned int reg16; typedef unsigned int reg24; typedef unsigned int reg32; typedef int cycle_count; typedef int sound_sample; typedef sound_sample fc_point[2]; enum chip_model { MOS6581 = 1, MOS8580 }; enum sampling_method { SAMPLE_FAST, SAMPLE_INTERPOLATE, SAMPLE_RESAMPLE_INTERPOLATE, SAMPLE_RESAMPLE_FAST }; extern "C" { #ifndef __VERSION_CC__ extern const char* resid_version_string; #else const char* resid_version_string = VERSION; #endif } // Inlining on/off. #define RESID_INLINING 1 #define RESID_INLINE inline #endif // not __SIDDEFS_H__ goattracker-2.72/src/resid/wave6581_P_T.cpp0000644000000000000000000010110211313456166017102 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave6581_P_T[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x38, 0x3f, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x40, 0x5f, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x378: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x60, 0x6f, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x60, 0x00, 0x60, 0x70, 0x77, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x70, 0x40, 0x70, 0x70, 0x7b, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x70, /* 0x3e8: */ 0x00, 0x40, 0x40, 0x70, 0x60, 0x70, 0x78, 0x7d, /* 0x3f0: */ 0x00, 0x40, 0x60, 0x78, 0x60, 0x78, 0x78, 0x7e, /* 0x3f8: */ 0x70, 0x7c, 0x7c, 0x7f, 0x7e, 0x7f, 0x7f, 0x7f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x9f, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x578: */ 0x00, 0x80, 0x80, 0x80, 0x80, 0xa0, 0xa0, 0xaf, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0, /* 0x5b8: */ 0x00, 0x80, 0x80, 0xa0, 0x80, 0xa0, 0xb0, 0xb7, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xa0, /* 0x5d8: */ 0x00, 0x80, 0x80, 0xa0, 0x80, 0xb0, 0xb0, 0xbb, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xb0, /* 0x5e8: */ 0x80, 0x80, 0x80, 0xb0, 0x80, 0xb0, 0xb8, 0xbd, /* 0x5f0: */ 0x80, 0x80, 0x80, 0xb8, 0xa0, 0xb8, 0xb8, 0xbe, /* 0x5f8: */ 0xa0, 0xb8, 0xbc, 0xbf, 0xbe, 0xbf, 0xbf, 0xbf, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, /* 0x670: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, /* 0x678: */ 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x698: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0xc0, 0xc0, /* 0x6b8: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd7, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0, /* 0x6d0: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, /* 0x6d8: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd0, 0xdb, /* 0x6e0: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xd0, /* 0x6e8: */ 0x80, 0xc0, 0xc0, 0xd0, 0xc0, 0xd0, 0xd8, 0xdd, /* 0x6f0: */ 0xc0, 0xc0, 0xc0, 0xd0, 0xc0, 0xd8, 0xd8, 0xde, /* 0x6f8: */ 0xc0, 0xd8, 0xdc, 0xdf, 0xdc, 0xdf, 0xdf, 0xdf, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x718: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0xc0, 0xc0, 0xe0, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x728: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, /* 0x730: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, /* 0x738: */ 0x80, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe7, /* 0x740: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0xc0, /* 0x748: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, /* 0x750: */ 0x00, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xe0, /* 0x758: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xeb, /* 0x760: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, /* 0x768: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xed, /* 0x770: */ 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, 0xe8, 0xee, /* 0x778: */ 0xe0, 0xe8, 0xec, 0xef, 0xec, 0xef, 0xef, 0xef, /* 0x780: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0x788: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xf0, /* 0x790: */ 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xf0, /* 0x798: */ 0xc0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf3, /* 0x7a0: */ 0x80, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xf0, /* 0x7a8: */ 0xc0, 0xe0, 0xe0, 0xf0, 0xe0, 0xf0, 0xf0, 0xf5, /* 0x7b0: */ 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf6, /* 0x7b8: */ 0xf0, 0xf0, 0xf4, 0xf7, 0xf4, 0xf7, 0xf7, 0xf7, /* 0x7c0: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, /* 0x7c8: */ 0xe0, 0xe0, 0xe0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf9, /* 0x7d0: */ 0xe0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xfa, /* 0x7d8: */ 0xf0, 0xf8, 0xf8, 0xfb, 0xf8, 0xfb, 0xfb, 0xfb, /* 0x7e0: */ 0xe0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xfc, 0xfc, /* 0x7e8: */ 0xf8, 0xfc, 0xfc, 0xfd, 0xfc, 0xfd, 0xfd, 0xfd, /* 0x7f0: */ 0xf8, 0xfc, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0x7f8: */ 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x800: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, /* 0x808: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, 0xf8, /* 0x810: */ 0xfd, 0xfd, 0xfd, 0xfc, 0xfd, 0xfc, 0xfc, 0xf8, /* 0x818: */ 0xfc, 0xfc, 0xfc, 0xf0, 0xf8, 0xf0, 0xf0, 0xe0, /* 0x820: */ 0xfb, 0xfb, 0xfb, 0xf8, 0xfb, 0xf8, 0xf8, 0xf0, /* 0x828: */ 0xfa, 0xf8, 0xf8, 0xf0, 0xf8, 0xf0, 0xf0, 0xe0, /* 0x830: */ 0xf9, 0xf8, 0xf8, 0xf0, 0xf8, 0xf0, 0xe0, 0xe0, /* 0x838: */ 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, /* 0x840: */ 0xf7, 0xf7, 0xf7, 0xf4, 0xf7, 0xf4, 0xf0, 0xf0, /* 0x848: */ 0xf6, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, /* 0x850: */ 0xf5, 0xf0, 0xf0, 0xe0, 0xf0, 0xe0, 0xe0, 0xc0, /* 0x858: */ 0xf0, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xc0, 0x80, /* 0x860: */ 0xf3, 0xf0, 0xf0, 0xe0, 0xf0, 0xe0, 0xe0, 0xc0, /* 0x868: */ 0xf0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, /* 0x870: */ 0xf0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, /* 0x878: */ 0xc0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0x880: */ 0xef, 0xef, 0xef, 0xec, 0xef, 0xec, 0xe8, 0xe0, /* 0x888: */ 0xee, 0xe8, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, /* 0x890: */ 0xed, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, /* 0x898: */ 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, /* 0x8a0: */ 0xeb, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, /* 0x8a8: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, /* 0x8b0: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, /* 0x8b8: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0x8c0: */ 0xe7, 0xe0, 0xe0, 0xc0, 0xe0, 0xc0, 0xc0, 0x80, /* 0x8c8: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, /* 0x8d0: */ 0xe0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, /* 0x8d8: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0xe0, 0xc0, 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x900: */ 0xdf, 0xdf, 0xdf, 0xdc, 0xdf, 0xdc, 0xd8, 0xc0, /* 0x908: */ 0xde, 0xd8, 0xd8, 0xc0, 0xd8, 0xc0, 0xc0, 0xc0, /* 0x910: */ 0xdd, 0xd8, 0xd0, 0xc0, 0xd0, 0xc0, 0xc0, 0x80, /* 0x918: */ 0xd0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, /* 0x920: */ 0xdb, 0xd0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, /* 0x928: */ 0xc0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x00, /* 0x930: */ 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0x938: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x940: */ 0xd7, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, /* 0x948: */ 0xc0, 0xc0, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0x950: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0x958: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0x968: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x980: */ 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x00, /* 0x988: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0x990: */ 0xc0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0xc0, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c0: */ 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa00: */ 0xbf, 0xbf, 0xbf, 0xbe, 0xbf, 0xbc, 0xbc, 0xa0, /* 0xa08: */ 0xbe, 0xbc, 0xb8, 0xa0, 0xb8, 0xa0, 0x80, 0x80, /* 0xa10: */ 0xbd, 0xb8, 0xb0, 0x80, 0xb0, 0x80, 0x80, 0x80, /* 0xa18: */ 0xb0, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0xa20: */ 0xbb, 0xb0, 0xb0, 0x80, 0xa0, 0x80, 0x80, 0x00, /* 0xa28: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa30: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa38: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa40: */ 0xb7, 0xb0, 0xa0, 0x80, 0xa0, 0x80, 0x80, 0x00, /* 0xa48: */ 0xa0, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xa50: */ 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa80: */ 0xaf, 0xa0, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x00, /* 0xa88: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac0: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb00: */ 0x9f, 0x90, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0xb08: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb10: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb20: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb40: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb80: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc00: */ 0x7f, 0x7f, 0x7f, 0x7e, 0x7f, 0x7c, 0x7c, 0x70, /* 0xc08: */ 0x7e, 0x7c, 0x78, 0x60, 0x78, 0x60, 0x60, 0x00, /* 0xc10: */ 0x7d, 0x78, 0x78, 0x60, 0x70, 0x40, 0x40, 0x00, /* 0xc18: */ 0x70, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc20: */ 0x7b, 0x78, 0x70, 0x40, 0x70, 0x40, 0x00, 0x00, /* 0xc28: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc30: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc40: */ 0x77, 0x70, 0x70, 0x00, 0x60, 0x00, 0x00, 0x00, /* 0xc48: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc50: */ 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc80: */ 0x6f, 0x60, 0x60, 0x00, 0x60, 0x00, 0x00, 0x00, /* 0xc88: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd00: */ 0x5f, 0x58, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* 0xd08: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe00: */ 0x3f, 0x3c, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; goattracker-2.72/src/resid/filter.h0000644000000000000000000003446611313456166016026 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __FILTER_H__ #define __FILTER_H__ #include "siddefs.h" #include "spline.h" // ---------------------------------------------------------------------------- // The SID filter is modeled with a two-integrator-loop biquadratic filter, // which has been confirmed by Bob Yannes to be the actual circuit used in // the SID chip. // // Measurements show that excellent emulation of the SID filter is achieved, // except when high resonance is combined with high sustain levels. // In this case the SID op-amps are performing less than ideally and are // causing some peculiar behavior of the SID filter. This however seems to // have more effect on the overall amplitude than on the color of the sound. // // The theory for the filter circuit can be found in "Microelectric Circuits" // by Adel S. Sedra and Kenneth C. Smith. // The circuit is modeled based on the explanation found there except that // an additional inverter is used in the feedback from the bandpass output, // allowing the summer op-amp to operate in single-ended mode. This yields // inverted filter outputs with levels independent of Q, which corresponds with // the results obtained from a real SID. // // We have been able to model the summer and the two integrators of the circuit // to form components of an IIR filter. // Vhp is the output of the summer, Vbp is the output of the first integrator, // and Vlp is the output of the second integrator in the filter circuit. // // According to Bob Yannes, the active stages of the SID filter are not really // op-amps. Rather, simple NMOS inverters are used. By biasing an inverter // into its region of quasi-linear operation using a feedback resistor from // input to output, a MOS inverter can be made to act like an op-amp for // small signals centered around the switching threshold. // // Qualified guesses at SID filter schematics are depicted below. // // SID filter // ---------- // // ----------------------------------------------- // | | // | ---Rq-- | // | | | | // | --------------|--R-----[A>--|--R-----[A>--| // | | | | // vi -----R1-- | | | // // vhp vbp vlp // // // vi - input voltage // vhp - highpass output // vbp - bandpass output // vlp - lowpass output // [A> - op-amp // R1 - summer resistor // Rq - resistor array controlling resonance (4 resistors) // R - NMOS FET voltage controlled resistor controlling cutoff frequency // Rs - shunt resitor // C - capacitor // // // // SID integrator // -------------- // // V+ // // | // | // -----| // | | // | ||-- // -|| // ---C--- ||-> // | | | // |---Rs-----------|---- vo // | | // | ||-- // vi ---- -----|------------|| // | ^ | ||-> // |___| | | // ----- | | // | | | // |---R2-- | // | // R1 V- // | // | // // Vw // // ---------------------------------------------------------------------------- class Filter { public: Filter(); void enable_filter(bool enable); void set_chip_model(chip_model model); RESID_INLINE void clock(sound_sample voice1, sound_sample voice2, sound_sample voice3, sound_sample ext_in); RESID_INLINE void clock(cycle_count delta_t, sound_sample voice1, sound_sample voice2, sound_sample voice3, sound_sample ext_in); void reset(); // Write registers. void writeFC_LO(reg8); void writeFC_HI(reg8); void writeRES_FILT(reg8); void writeMODE_VOL(reg8); // SID audio output (16 bits). sound_sample output(); // Spline functions. void fc_default(const fc_point*& points, int& count); PointPlotter fc_plotter(); protected: void set_w0(); void set_Q(); // Filter enabled. bool enabled; // Filter cutoff frequency. reg12 fc; // Filter resonance. reg8 res; // Selects which inputs to route through filter. reg8 filt; // Switch voice 3 off. reg8 voice3off; // Highpass, bandpass, and lowpass filter modes. reg8 hp_bp_lp; // Output master volume. reg4 vol; // Mixer DC offset. sound_sample mixer_DC; // State of filter. sound_sample Vhp; // highpass sound_sample Vbp; // bandpass sound_sample Vlp; // lowpass sound_sample Vnf; // not filtered // Cutoff frequency, resonance. sound_sample w0, w0_ceil_1, w0_ceil_dt; sound_sample _1024_div_Q; // Cutoff frequency tables. // FC is an 11 bit register. sound_sample f0_6581[2048]; sound_sample f0_8580[2048]; sound_sample* f0; static fc_point f0_points_6581[]; static fc_point f0_points_8580[]; fc_point* f0_points; int f0_count; friend class SID; }; // ---------------------------------------------------------------------------- // Inline functions. // The following functions are defined inline because they are called every // time a sample is calculated. // ---------------------------------------------------------------------------- #if RESID_INLINING || defined(__FILTER_CC__) // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- RESID_INLINE void Filter::clock(sound_sample voice1, sound_sample voice2, sound_sample voice3, sound_sample ext_in) { // Scale each voice down from 20 to 13 bits. voice1 >>= 7; voice2 >>= 7; // NB! Voice 3 is not silenced by voice3off if it is routed through // the filter. if (voice3off && !(filt & 0x04)) { voice3 = 0; } else { voice3 >>= 7; } ext_in >>= 7; // This is handy for testing. if (!enabled) { Vnf = voice1 + voice2 + voice3 + ext_in; Vhp = Vbp = Vlp = 0; return; } // Route voices into or around filter. // The code below is expanded to a switch for faster execution. // (filt1 ? Vi : Vnf) += voice1; // (filt2 ? Vi : Vnf) += voice2; // (filt3 ? Vi : Vnf) += voice3; sound_sample Vi; switch (filt) { default: case 0x0: Vi = 0; Vnf = voice1 + voice2 + voice3 + ext_in; break; case 0x1: Vi = voice1; Vnf = voice2 + voice3 + ext_in; break; case 0x2: Vi = voice2; Vnf = voice1 + voice3 + ext_in; break; case 0x3: Vi = voice1 + voice2; Vnf = voice3 + ext_in; break; case 0x4: Vi = voice3; Vnf = voice1 + voice2 + ext_in; break; case 0x5: Vi = voice1 + voice3; Vnf = voice2 + ext_in; break; case 0x6: Vi = voice2 + voice3; Vnf = voice1 + ext_in; break; case 0x7: Vi = voice1 + voice2 + voice3; Vnf = ext_in; break; case 0x8: Vi = ext_in; Vnf = voice1 + voice2 + voice3; break; case 0x9: Vi = voice1 + ext_in; Vnf = voice2 + voice3; break; case 0xa: Vi = voice2 + ext_in; Vnf = voice1 + voice3; break; case 0xb: Vi = voice1 + voice2 + ext_in; Vnf = voice3; break; case 0xc: Vi = voice3 + ext_in; Vnf = voice1 + voice2; break; case 0xd: Vi = voice1 + voice3 + ext_in; Vnf = voice2; break; case 0xe: Vi = voice2 + voice3 + ext_in; Vnf = voice1; break; case 0xf: Vi = voice1 + voice2 + voice3 + ext_in; Vnf = 0; break; } // delta_t = 1 is converted to seconds given a 1MHz clock by dividing // with 1 000 000. // Calculate filter outputs. // Vhp = Vbp/Q - Vlp - Vi; // dVbp = -w0*Vhp*dt; // dVlp = -w0*Vbp*dt; sound_sample dVbp = (w0_ceil_1*Vhp >> 20); sound_sample dVlp = (w0_ceil_1*Vbp >> 20); Vbp -= dVbp; Vlp -= dVlp; Vhp = (Vbp*_1024_div_Q >> 10) - Vlp - Vi; } // ---------------------------------------------------------------------------- // SID clocking - delta_t cycles. // ---------------------------------------------------------------------------- RESID_INLINE void Filter::clock(cycle_count delta_t, sound_sample voice1, sound_sample voice2, sound_sample voice3, sound_sample ext_in) { // Scale each voice down from 20 to 13 bits. voice1 >>= 7; voice2 >>= 7; // NB! Voice 3 is not silenced by voice3off if it is routed through // the filter. if (voice3off && !(filt & 0x04)) { voice3 = 0; } else { voice3 >>= 7; } ext_in >>= 7; // Enable filter on/off. // This is not really part of SID, but is useful for testing. // On slow CPUs it may be necessary to bypass the filter to lower the CPU // load. if (!enabled) { Vnf = voice1 + voice2 + voice3 + ext_in; Vhp = Vbp = Vlp = 0; return; } // Route voices into or around filter. // The code below is expanded to a switch for faster execution. // (filt1 ? Vi : Vnf) += voice1; // (filt2 ? Vi : Vnf) += voice2; // (filt3 ? Vi : Vnf) += voice3; sound_sample Vi; switch (filt) { default: case 0x0: Vi = 0; Vnf = voice1 + voice2 + voice3 + ext_in; break; case 0x1: Vi = voice1; Vnf = voice2 + voice3 + ext_in; break; case 0x2: Vi = voice2; Vnf = voice1 + voice3 + ext_in; break; case 0x3: Vi = voice1 + voice2; Vnf = voice3 + ext_in; break; case 0x4: Vi = voice3; Vnf = voice1 + voice2 + ext_in; break; case 0x5: Vi = voice1 + voice3; Vnf = voice2 + ext_in; break; case 0x6: Vi = voice2 + voice3; Vnf = voice1 + ext_in; break; case 0x7: Vi = voice1 + voice2 + voice3; Vnf = ext_in; break; case 0x8: Vi = ext_in; Vnf = voice1 + voice2 + voice3; break; case 0x9: Vi = voice1 + ext_in; Vnf = voice2 + voice3; break; case 0xa: Vi = voice2 + ext_in; Vnf = voice1 + voice3; break; case 0xb: Vi = voice1 + voice2 + ext_in; Vnf = voice3; break; case 0xc: Vi = voice3 + ext_in; Vnf = voice1 + voice2; break; case 0xd: Vi = voice1 + voice3 + ext_in; Vnf = voice2; break; case 0xe: Vi = voice2 + voice3 + ext_in; Vnf = voice1; break; case 0xf: Vi = voice1 + voice2 + voice3 + ext_in; Vnf = 0; break; } // Maximum delta cycles for the filter to work satisfactorily under current // cutoff frequency and resonance constraints is approximately 8. cycle_count delta_t_flt = 8; while (delta_t) { if (delta_t < delta_t_flt) { delta_t_flt = delta_t; } // delta_t is converted to seconds given a 1MHz clock by dividing // with 1 000 000. This is done in two operations to avoid integer // multiplication overflow. // Calculate filter outputs. // Vhp = Vbp/Q - Vlp - Vi; // dVbp = -w0*Vhp*dt; // dVlp = -w0*Vbp*dt; sound_sample w0_delta_t = w0_ceil_dt*delta_t_flt >> 6; sound_sample dVbp = (w0_delta_t*Vhp >> 14); sound_sample dVlp = (w0_delta_t*Vbp >> 14); Vbp -= dVbp; Vlp -= dVlp; Vhp = (Vbp*_1024_div_Q >> 10) - Vlp - Vi; delta_t -= delta_t_flt; } } // ---------------------------------------------------------------------------- // SID audio output (20 bits). // ---------------------------------------------------------------------------- RESID_INLINE sound_sample Filter::output() { // This is handy for testing. if (!enabled) { return (Vnf + mixer_DC)*static_cast(vol); } // Mix highpass, bandpass, and lowpass outputs. The sum is not // weighted, this can be confirmed by sampling sound output for // e.g. bandpass, lowpass, and bandpass+lowpass from a SID chip. // The code below is expanded to a switch for faster execution. // if (hp) Vf += Vhp; // if (bp) Vf += Vbp; // if (lp) Vf += Vlp; sound_sample Vf; switch (hp_bp_lp) { default: case 0x0: Vf = 0; break; case 0x1: Vf = Vlp; break; case 0x2: Vf = Vbp; break; case 0x3: Vf = Vlp + Vbp; break; case 0x4: Vf = Vhp; break; case 0x5: Vf = Vlp + Vhp; break; case 0x6: Vf = Vbp + Vhp; break; case 0x7: Vf = Vlp + Vbp + Vhp; break; } // Sum non-filtered and filtered output. // Multiply the sum with volume. return (Vnf + Vf + mixer_DC)*static_cast(vol); } #endif // RESID_INLINING || defined(__FILTER_CC__) #endif // not __FILTER_H__ goattracker-2.72/src/resid/spline.h0000644000000000000000000002152111313456166016017 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __SPLINE_H__ #define __SPLINE_H__ // Our objective is to construct a smooth interpolating single-valued function // y = f(x). // // Catmull-Rom splines are widely used for interpolation, however these are // parametric curves [x(t) y(t) ...] and can not be used to directly calculate // y = f(x). // For a discussion of Catmull-Rom splines see Catmull, E., and R. Rom, // "A Class of Local Interpolating Splines", Computer Aided Geometric Design. // // Natural cubic splines are single-valued functions, and have been used in // several applications e.g. to specify gamma curves for image display. // These splines do not afford local control, and a set of linear equations // including all interpolation points must be solved before any point on the // curve can be calculated. The lack of local control makes the splines // more difficult to handle than e.g. Catmull-Rom splines, and real-time // interpolation of a stream of data points is not possible. // For a discussion of natural cubic splines, see e.g. Kreyszig, E., "Advanced // Engineering Mathematics". // // Our approach is to approximate the properties of Catmull-Rom splines for // piecewice cubic polynomials f(x) = ax^3 + bx^2 + cx + d as follows: // Each curve segment is specified by four interpolation points, // p0, p1, p2, p3. // The curve between p1 and p2 must interpolate both p1 and p2, and in addition // f'(p1.x) = k1 = (p2.y - p0.y)/(p2.x - p0.x) and // f'(p2.x) = k2 = (p3.y - p1.y)/(p3.x - p1.x). // // The constraints are expressed by the following system of linear equations // // [ 1 xi xi^2 xi^3 ] [ d ] [ yi ] // [ 1 2*xi 3*xi^2 ] * [ c ] = [ ki ] // [ 1 xj xj^2 xj^3 ] [ b ] [ yj ] // [ 1 2*xj 3*xj^2 ] [ a ] [ kj ] // // Solving using Gaussian elimination and back substitution, setting // dy = yj - yi, dx = xj - xi, we get // // a = ((ki + kj) - 2*dy/dx)/(dx*dx); // b = ((kj - ki)/dx - 3*(xi + xj)*a)/2; // c = ki - (3*xi*a + 2*b)*xi; // d = yi - ((xi*a + b)*xi + c)*xi; // // Having calculated the coefficients of the cubic polynomial we have the // choice of evaluation by brute force // // for (x = x1; x <= x2; x += res) { // y = ((a*x + b)*x + c)*x + d; // plot(x, y); // } // // or by forward differencing // // y = ((a*x1 + b)*x1 + c)*x1 + d; // dy = (3*a*(x1 + res) + 2*b)*x1*res + ((a*res + b)*res + c)*res; // d2y = (6*a*(x1 + res) + 2*b)*res*res; // d3y = 6*a*res*res*res; // // for (x = x1; x <= x2; x += res) { // plot(x, y); // y += dy; dy += d2y; d2y += d3y; // } // // See Foley, Van Dam, Feiner, Hughes, "Computer Graphics, Principles and // Practice" for a discussion of forward differencing. // // If we have a set of interpolation points p0, ..., pn, we may specify // curve segments between p0 and p1, and between pn-1 and pn by using the // following constraints: // f''(p0.x) = 0 and // f''(pn.x) = 0. // // Substituting the results for a and b in // // 2*b + 6*a*xi = 0 // // we get // // ki = (3*dy/dx - kj)/2; // // or by substituting the results for a and b in // // 2*b + 6*a*xj = 0 // // we get // // kj = (3*dy/dx - ki)/2; // // Finally, if we have only two interpolation points, the cubic polynomial // will degenerate to a straight line if we set // // ki = kj = dy/dx; // #if SPLINE_BRUTE_FORCE #define interpolate_segment interpolate_brute_force #else #define interpolate_segment interpolate_forward_difference #endif // ---------------------------------------------------------------------------- // Calculation of coefficients. // ---------------------------------------------------------------------------- inline void cubic_coefficients(double x1, double y1, double x2, double y2, double k1, double k2, double& a, double& b, double& c, double& d) { double dx = x2 - x1, dy = y2 - y1; a = ((k1 + k2) - 2*dy/dx)/(dx*dx); b = ((k2 - k1)/dx - 3*(x1 + x2)*a)/2; c = k1 - (3*x1*a + 2*b)*x1; d = y1 - ((x1*a + b)*x1 + c)*x1; } // ---------------------------------------------------------------------------- // Evaluation of cubic polynomial by brute force. // ---------------------------------------------------------------------------- template inline void interpolate_brute_force(double x1, double y1, double x2, double y2, double k1, double k2, PointPlotter plot, double res) { double a, b, c, d; cubic_coefficients(x1, y1, x2, y2, k1, k2, a, b, c, d); // Calculate each point. for (double x = x1; x <= x2; x += res) { double y = ((a*x + b)*x + c)*x + d; plot(x, y); } } // ---------------------------------------------------------------------------- // Evaluation of cubic polynomial by forward differencing. // ---------------------------------------------------------------------------- template inline void interpolate_forward_difference(double x1, double y1, double x2, double y2, double k1, double k2, PointPlotter plot, double res) { double a, b, c, d; cubic_coefficients(x1, y1, x2, y2, k1, k2, a, b, c, d); double y = ((a*x1 + b)*x1 + c)*x1 + d; double dy = (3*a*(x1 + res) + 2*b)*x1*res + ((a*res + b)*res + c)*res; double d2y = (6*a*(x1 + res) + 2*b)*res*res; double d3y = 6*a*res*res*res; // Calculate each point. for (double x = x1; x <= x2; x += res) { plot(x, y); y += dy; dy += d2y; d2y += d3y; } } template inline double x(PointIter p) { return (*p)[0]; } template inline double y(PointIter p) { return (*p)[1]; } // ---------------------------------------------------------------------------- // Evaluation of complete interpolating function. // Note that since each curve segment is controlled by four points, the // end points will not be interpolated. If extra control points are not // desirable, the end points can simply be repeated to ensure interpolation. // Note also that points of non-differentiability and discontinuity can be // introduced by repeating points. // ---------------------------------------------------------------------------- template inline void interpolate(PointIter p0, PointIter pn, PointPlotter plot, double res) { double k1, k2; // Set up points for first curve segment. PointIter p1 = p0; ++p1; PointIter p2 = p1; ++p2; PointIter p3 = p2; ++p3; // Draw each curve segment. for (; p2 != pn; ++p0, ++p1, ++p2, ++p3) { // p1 and p2 equal; single point. if (x(p1) == x(p2)) { continue; } // Both end points repeated; straight line. if (x(p0) == x(p1) && x(p2) == x(p3)) { k1 = k2 = (y(p2) - y(p1))/(x(p2) - x(p1)); } // p0 and p1 equal; use f''(x1) = 0. else if (x(p0) == x(p1)) { k2 = (y(p3) - y(p1))/(x(p3) - x(p1)); k1 = (3*(y(p2) - y(p1))/(x(p2) - x(p1)) - k2)/2; } // p2 and p3 equal; use f''(x2) = 0. else if (x(p2) == x(p3)) { k1 = (y(p2) - y(p0))/(x(p2) - x(p0)); k2 = (3*(y(p2) - y(p1))/(x(p2) - x(p1)) - k1)/2; } // Normal curve. else { k1 = (y(p2) - y(p0))/(x(p2) - x(p0)); k2 = (y(p3) - y(p1))/(x(p3) - x(p1)); } interpolate_segment(x(p1), y(p1), x(p2), y(p2), k1, k2, plot, res); } } // ---------------------------------------------------------------------------- // Class for plotting integers into an array. // ---------------------------------------------------------------------------- template class PointPlotter { protected: F* f; public: PointPlotter(F* arr) : f(arr) { } void operator ()(double x, double y) { // Clamp negative values to zero. if (y < 0) { y = 0; } f[F(x)] = F(y); } }; #endif // not __SPLINE_H__ goattracker-2.72/src/resid/version.cpp0000644000000000000000000000205210774364076016553 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __VERSION_CC__ #include "siddefs.h" goattracker-2.72/src/resid/filter.cpp0000644000000000000000000002233511313456166016351 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __FILTER_CC__ #include "filter.h" // Maximum cutoff frequency is specified as // FCmax = 2.6e-5/C = 2.6e-5/2200e-12 = 11818. // // Measurements indicate a cutoff frequency range of approximately // 220Hz - 18kHz on a MOS6581 fitted with 470pF capacitors. The function // mapping FC to cutoff frequency has the shape of the tanh function, with // a discontinuity at FCHI = 0x80. // In contrast, the MOS8580 almost perfectly corresponds with the // specification of a linear mapping from 30Hz to 12kHz. // // The mappings have been measured by feeding the SID with an external // signal since the chip itself is incapable of generating waveforms of // higher fundamental frequency than 4kHz. It is best to use the bandpass // output at full resonance to pick out the cutoff frequency at any given // FC setting. // // The mapping function is specified with spline interpolation points and // the function values are retrieved via table lookup. // // NB! Cutoff frequency characteristics may vary, we have modeled two // particular Commodore 64s. fc_point Filter::f0_points_6581[] = { // FC f FCHI FCLO // ---------------------------- { 0, 220 }, // 0x00 - repeated end point { 0, 220 }, // 0x00 { 128, 230 }, // 0x10 { 256, 250 }, // 0x20 { 384, 300 }, // 0x30 { 512, 420 }, // 0x40 { 640, 780 }, // 0x50 { 768, 1600 }, // 0x60 { 832, 2300 }, // 0x68 { 896, 3200 }, // 0x70 { 960, 4300 }, // 0x78 { 992, 5000 }, // 0x7c { 1008, 5400 }, // 0x7e { 1016, 5700 }, // 0x7f { 1023, 6000 }, // 0x7f 0x07 { 1023, 6000 }, // 0x7f 0x07 - discontinuity { 1024, 4600 }, // 0x80 - { 1024, 4600 }, // 0x80 { 1032, 4800 }, // 0x81 { 1056, 5300 }, // 0x84 { 1088, 6000 }, // 0x88 { 1120, 6600 }, // 0x8c { 1152, 7200 }, // 0x90 { 1280, 9500 }, // 0xa0 { 1408, 12000 }, // 0xb0 { 1536, 14500 }, // 0xc0 { 1664, 16000 }, // 0xd0 { 1792, 17100 }, // 0xe0 { 1920, 17700 }, // 0xf0 { 2047, 18000 }, // 0xff 0x07 { 2047, 18000 } // 0xff 0x07 - repeated end point }; fc_point Filter::f0_points_8580[] = { // FC f FCHI FCLO // ---------------------------- { 0, 0 }, // 0x00 - repeated end point { 0, 0 }, // 0x00 { 128, 800 }, // 0x10 { 256, 1600 }, // 0x20 { 384, 2500 }, // 0x30 { 512, 3300 }, // 0x40 { 640, 4100 }, // 0x50 { 768, 4800 }, // 0x60 { 896, 5600 }, // 0x70 { 1024, 6500 }, // 0x80 { 1152, 7500 }, // 0x90 { 1280, 8400 }, // 0xa0 { 1408, 9200 }, // 0xb0 { 1536, 9800 }, // 0xc0 { 1664, 10500 }, // 0xd0 { 1792, 11000 }, // 0xe0 { 1920, 11700 }, // 0xf0 { 2047, 12500 }, // 0xff 0x07 { 2047, 12500 } // 0xff 0x07 - repeated end point }; // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- Filter::Filter() { fc = 0; res = 0; filt = 0; voice3off = 0; hp_bp_lp = 0; vol = 0; // State of filter. Vhp = 0; Vbp = 0; Vlp = 0; Vnf = 0; enable_filter(true); // Create mappings from FC to cutoff frequency. interpolate(f0_points_6581, f0_points_6581 + sizeof(f0_points_6581)/sizeof(*f0_points_6581) - 1, PointPlotter(f0_6581), 1.0); interpolate(f0_points_8580, f0_points_8580 + sizeof(f0_points_8580)/sizeof(*f0_points_8580) - 1, PointPlotter(f0_8580), 1.0); set_chip_model(MOS6581); } // ---------------------------------------------------------------------------- // Enable filter. // ---------------------------------------------------------------------------- void Filter::enable_filter(bool enable) { enabled = enable; } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void Filter::set_chip_model(chip_model model) { if (model == MOS6581) { // The mixer has a small input DC offset. This is found as follows: // // The "zero" output level of the mixer measured on the SID audio // output pin is 5.50V at zero volume, and 5.44 at full // volume. This yields a DC offset of (5.44V - 5.50V) = -0.06V. // // The DC offset is thus -0.06V/1.05V ~ -1/18 of the dynamic range // of one voice. See voice.cc for measurement of the dynamic // range. mixer_DC = -0xfff*0xff/18 >> 7; f0 = f0_6581; f0_points = f0_points_6581; f0_count = sizeof(f0_points_6581)/sizeof(*f0_points_6581); } else { // No DC offsets in the MOS8580. mixer_DC = 0; f0 = f0_8580; f0_points = f0_points_8580; f0_count = sizeof(f0_points_8580)/sizeof(*f0_points_8580); } set_w0(); set_Q(); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void Filter::reset() { fc = 0; res = 0; filt = 0; voice3off = 0; hp_bp_lp = 0; vol = 0; // State of filter. Vhp = 0; Vbp = 0; Vlp = 0; Vnf = 0; set_w0(); set_Q(); } // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void Filter::writeFC_LO(reg8 fc_lo) { fc = fc & 0x7f8 | fc_lo & 0x007; set_w0(); } void Filter::writeFC_HI(reg8 fc_hi) { fc = (fc_hi << 3) & 0x7f8 | fc & 0x007; set_w0(); } void Filter::writeRES_FILT(reg8 res_filt) { res = (res_filt >> 4) & 0x0f; set_Q(); filt = res_filt & 0x0f; } void Filter::writeMODE_VOL(reg8 mode_vol) { voice3off = mode_vol & 0x80; hp_bp_lp = (mode_vol >> 4) & 0x07; vol = mode_vol & 0x0f; } // Set filter cutoff frequency. void Filter::set_w0() { const double pi = 3.1415926535897932385; // Multiply with 1.048576 to facilitate division by 1 000 000 by right- // shifting 20 times (2 ^ 20 = 1048576). w0 = static_cast(2*pi*f0[fc]*1.048576); // Limit f0 to 16kHz to keep 1 cycle filter stable. const sound_sample w0_max_1 = static_cast(2*pi*16000*1.048576); w0_ceil_1 = w0 <= w0_max_1 ? w0 : w0_max_1; // Limit f0 to 4kHz to keep delta_t cycle filter stable. const sound_sample w0_max_dt = static_cast(2*pi*4000*1.048576); w0_ceil_dt = w0 <= w0_max_dt ? w0 : w0_max_dt; } // Set filter resonance. void Filter::set_Q() { // Q is controlled linearly by res. Q has approximate range [0.707, 1.7]. // As resonance is increased, the filter must be clocked more often to keep // stable. // The coefficient 1024 is dispensed of later by right-shifting 10 times // (2 ^ 10 = 1024). _1024_div_Q = static_cast(1024.0/(0.707 + 1.0*res/0x0f)); } // ---------------------------------------------------------------------------- // Spline functions. // ---------------------------------------------------------------------------- // ---------------------------------------------------------------------------- // Return the array of spline interpolation points used to map the FC register // to filter cutoff frequency. // ---------------------------------------------------------------------------- void Filter::fc_default(const fc_point*& points, int& count) { points = f0_points; count = f0_count; } // ---------------------------------------------------------------------------- // Given an array of interpolation points p with n points, the following // statement will specify a new FC mapping: // interpolate(p, p + n - 1, filter.fc_plotter(), 1.0); // Note that the x range of the interpolation points *must* be [0, 2047], // and that additional end points *must* be present since the end points // are not interpolated. // ---------------------------------------------------------------------------- PointPlotter Filter::fc_plotter() { return PointPlotter(f0); } goattracker-2.72/src/resid/pot.cpp0000644000000000000000000000213410774364076015671 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "pot.h" reg8 Potentiometer::readPOT() { // NB! Not modeled. return 0xff; } goattracker-2.72/src/resid/wave8580_P_T.cpp0000644000000000000000000010110211313456166017103 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave8580_P_T[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x00, 0x00, 0x00, 0x1c, 0x00, 0x3c, 0x3f, 0x3f, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x5e, 0x5f, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x378: */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x60, 0x60, 0x6f, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x60, /* 0x3b8: */ 0x40, 0x40, 0x60, 0x60, 0x60, 0x60, 0x70, 0x77, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, /* 0x3c8: */ 0x40, 0x40, 0x40, 0x40, 0x40, 0x60, 0x60, 0x60, /* 0x3d0: */ 0x40, 0x40, 0x40, 0x60, 0x60, 0x60, 0x60, 0x70, /* 0x3d8: */ 0x60, 0x60, 0x60, 0x70, 0x70, 0x70, 0x78, 0x7b, /* 0x3e0: */ 0x60, 0x60, 0x60, 0x70, 0x60, 0x70, 0x70, 0x70, /* 0x3e8: */ 0x70, 0x70, 0x70, 0x78, 0x78, 0x78, 0x78, 0x7c, /* 0x3f0: */ 0x78, 0x78, 0x78, 0x7c, 0x78, 0x7c, 0x7c, 0x7e, /* 0x3f8: */ 0x7c, 0x7e, 0x7e, 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x4d8: */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x4e8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x4f0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x4f8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x8e, 0x9f, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, /* 0x530: */ 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x538: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x540: */ 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x80, 0x80, /* 0x548: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x550: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x558: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x560: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x568: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x570: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x578: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xaf, /* 0x580: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x588: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x590: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x598: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x5a0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x5a8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x5b0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x5b8: */ 0x80, 0x80, 0x80, 0xa0, 0xa0, 0xa0, 0xa0, 0xb7, /* 0x5c0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x5c8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, /* 0x5d0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xa0, 0xa0, /* 0x5d8: */ 0xa0, 0xa0, 0xa0, 0xb0, 0xa0, 0xb0, 0xb0, 0xbb, /* 0x5e0: */ 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xb0, 0xb0, /* 0x5e8: */ 0xa0, 0xb0, 0xb0, 0xb8, 0xb0, 0xb8, 0xb8, 0xbc, /* 0x5f0: */ 0xb0, 0xb8, 0xb8, 0xb8, 0xb8, 0xbc, 0xbc, 0xbe, /* 0x5f8: */ 0xbc, 0xbc, 0xbe, 0xbf, 0xbe, 0xbf, 0xbf, 0xbf, /* 0x600: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x608: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x610: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x618: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x620: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x628: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x630: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x638: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, /* 0x640: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x648: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x650: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, /* 0x658: */ 0x80, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x660: */ 0x80, 0x80, 0x80, 0xc0, 0x80, 0xc0, 0xc0, 0xc0, /* 0x668: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x670: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x678: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xcf, /* 0x680: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xc0, 0xc0, /* 0x688: */ 0xc0, 0x80, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x690: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x698: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6a0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6a8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6b0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6b8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd7, /* 0x6c0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6c8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6d0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x6d8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, 0xd0, 0xd9, /* 0x6e0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xd0, /* 0x6e8: */ 0xc0, 0xd0, 0xd0, 0xd0, 0xd0, 0xd8, 0xd8, 0xdc, /* 0x6f0: */ 0xd0, 0xd0, 0xd8, 0xd8, 0xd8, 0xdc, 0xdc, 0xde, /* 0x6f8: */ 0xdc, 0xdc, 0xde, 0xdf, 0xde, 0xdf, 0xdf, 0xdf, /* 0x700: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x708: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x710: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x718: */ 0xc0, 0xc0, 0xc0, 0xe0, 0xc0, 0xe0, 0xe0, 0xe0, /* 0x720: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xe0, /* 0x728: */ 0xc0, 0xc0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x730: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x738: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe7, /* 0x740: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x748: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x750: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x758: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, /* 0x760: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x768: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe8, 0xec, /* 0x770: */ 0xe0, 0xe0, 0xe0, 0xe8, 0xe8, 0xe8, 0xec, 0xee, /* 0x778: */ 0xec, 0xec, 0xec, 0xee, 0xee, 0xef, 0xef, 0xef, /* 0x780: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x788: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, /* 0x790: */ 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x798: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x7a0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x7a8: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, /* 0x7b0: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf4, /* 0x7b8: */ 0xf0, 0xf4, 0xf4, 0xf6, 0xf6, 0xf7, 0xf7, 0xf7, /* 0x7c0: */ 0xf0, 0xf0, 0xf0, 0xf8, 0xf0, 0xf8, 0xf8, 0xf8, /* 0x7c8: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0x7d0: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0x7d8: */ 0xf8, 0xf8, 0xf8, 0xfa, 0xfa, 0xfb, 0xfb, 0xfb, /* 0x7e0: */ 0xf8, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, /* 0x7e8: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfd, 0xfd, 0xfd, /* 0x7f0: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, /* 0x7f8: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x800: */ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0x808: */ 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfe, 0xfc, /* 0x810: */ 0xfd, 0xfd, 0xfd, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, /* 0x818: */ 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xfc, 0xf8, /* 0x820: */ 0xfb, 0xfb, 0xfb, 0xfa, 0xfa, 0xf8, 0xf8, 0xf8, /* 0x828: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0x830: */ 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, 0xf8, /* 0x838: */ 0xf8, 0xf8, 0xf8, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x840: */ 0xf7, 0xf7, 0xf7, 0xf6, 0xf6, 0xf4, 0xf4, 0xf0, /* 0x848: */ 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x850: */ 0xf4, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x858: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x860: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, /* 0x868: */ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, /* 0x870: */ 0xf0, 0xf0, 0xf0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x878: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x880: */ 0xef, 0xef, 0xef, 0xee, 0xee, 0xec, 0xec, 0xe8, /* 0x888: */ 0xee, 0xec, 0xe8, 0xe8, 0xe8, 0xe0, 0xe0, 0xe0, /* 0x890: */ 0xec, 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x898: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8a0: */ 0xe8, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8a8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8b0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8b8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8c0: */ 0xe7, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8c8: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, /* 0x8d0: */ 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, /* 0x8d8: */ 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x8e0: */ 0xe0, 0xe0, 0xe0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x8e8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x8f0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x8f8: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x900: */ 0xdf, 0xdf, 0xdf, 0xde, 0xdf, 0xde, 0xdc, 0xdc, /* 0x908: */ 0xde, 0xdc, 0xdc, 0xd8, 0xd8, 0xd8, 0xd0, 0xd0, /* 0x910: */ 0xdc, 0xd8, 0xd8, 0xd0, 0xd0, 0xd0, 0xd0, 0xc0, /* 0x918: */ 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x920: */ 0xd9, 0xd0, 0xd0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x928: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x930: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x938: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x940: */ 0xd7, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x948: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x950: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x958: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x960: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x968: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x970: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, /* 0x978: */ 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x980: */ 0xcf, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x988: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x990: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, /* 0x998: */ 0xc0, 0xc0, 0xc0, 0x80, 0xc0, 0x80, 0x80, 0x80, /* 0x9a0: */ 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x80, 0x80, /* 0x9a8: */ 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9b0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9b8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9c0: */ 0xc0, 0xc0, 0xc0, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9c8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9d0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9d8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9e0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9e8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9f0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0x9f8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa00: */ 0xbf, 0xbf, 0xbf, 0xbe, 0xbf, 0xbe, 0xbc, 0xbc, /* 0xa08: */ 0xbe, 0xbc, 0xbc, 0xb8, 0xb8, 0xb8, 0xb8, 0xb0, /* 0xa10: */ 0xbc, 0xb8, 0xb8, 0xb0, 0xb8, 0xb0, 0xb0, 0xb0, /* 0xa18: */ 0xb0, 0xb0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, /* 0xa20: */ 0xbb, 0xb0, 0xb0, 0xa0, 0xb0, 0xa0, 0xa0, 0xa0, /* 0xa28: */ 0xa0, 0xa0, 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa30: */ 0xa0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa38: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa40: */ 0xb7, 0xb0, 0xa0, 0xa0, 0xa0, 0x80, 0x80, 0x80, /* 0xa48: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa50: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa58: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa60: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa68: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa70: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa78: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa80: */ 0xaf, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa88: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa90: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xa98: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xaa0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xaa8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xab0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xab8: */ 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xac0: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xac8: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, /* 0xad0: */ 0x80, 0x80, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb00: */ 0x9f, 0x9e, 0x88, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb08: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb10: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, /* 0xb18: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0xb20: */ 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, /* 0xb28: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb40: */ 0x80, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb80: */ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc00: */ 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, 0x7e, 0x7e, 0x7c, /* 0xc08: */ 0x7e, 0x7c, 0x7c, 0x78, 0x7c, 0x78, 0x78, 0x78, /* 0xc10: */ 0x7c, 0x78, 0x78, 0x78, 0x78, 0x70, 0x70, 0x70, /* 0xc18: */ 0x78, 0x70, 0x70, 0x60, 0x70, 0x60, 0x60, 0x60, /* 0xc20: */ 0x7b, 0x78, 0x70, 0x70, 0x70, 0x60, 0x60, 0x60, /* 0xc28: */ 0x70, 0x60, 0x60, 0x60, 0x60, 0x40, 0x40, 0x40, /* 0xc30: */ 0x60, 0x60, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, /* 0xc38: */ 0x40, 0x40, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* 0xc40: */ 0x77, 0x70, 0x60, 0x60, 0x60, 0x60, 0x40, 0x40, /* 0xc48: */ 0x60, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, /* 0xc50: */ 0x40, 0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc80: */ 0x6f, 0x64, 0x60, 0x40, 0x40, 0x00, 0x00, 0x00, /* 0xc88: */ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd00: */ 0x5f, 0x5e, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe00: */ 0x3f, 0x3f, 0x3e, 0x00, 0x1c, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf00: */ 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xff8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; goattracker-2.72/src/resid/voice.cpp0000644000000000000000000001160011313456166016162 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __VOICE_CC__ #include "voice.h" // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- Voice::Voice() { set_chip_model(MOS6581); } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void Voice::set_chip_model(chip_model model) { wave.set_chip_model(model); if (model == MOS6581) { // The waveform D/A converter introduces a DC offset in the signal // to the envelope multiplying D/A converter. The "zero" level of // the waveform D/A converter can be found as follows: // // Measure the "zero" voltage of voice 3 on the SID audio output // pin, routing only voice 3 to the mixer ($d417 = $0b, $d418 = // $0f, all other registers zeroed). // // Then set the sustain level for voice 3 to maximum and search for // the waveform output value yielding the same voltage as found // above. This is done by trying out different waveform output // values until the correct value is found, e.g. with the following // program: // // lda #$08 // sta $d412 // lda #$0b // sta $d417 // lda #$0f // sta $d418 // lda #$f0 // sta $d414 // lda #$21 // sta $d412 // lda #$01 // sta $d40e // // ldx #$00 // lda #$38 ; Tweak this to find the "zero" level //l cmp $d41b // bne l // stx $d40e ; Stop frequency counter - freeze waveform output // brk // // The waveform output range is 0x000 to 0xfff, so the "zero" // level should ideally have been 0x800. In the measured chip, the // waveform output "zero" level was found to be 0x380 (i.e. $d41b // = 0x38) at 5.94V. wave_zero = 0x380; // The envelope multiplying D/A converter introduces another DC // offset. This is isolated by the following measurements: // // * The "zero" output level of the mixer at full volume is 5.44V. // * Routing one voice to the mixer at full volume yields // 6.75V at maximum voice output (wave = 0xfff, sustain = 0xf) // 5.94V at "zero" voice output (wave = any, sustain = 0x0) // 5.70V at minimum voice output (wave = 0x000, sustain = 0xf) // * The DC offset of one voice is (5.94V - 5.44V) = 0.50V // * The dynamic range of one voice is |6.75V - 5.70V| = 1.05V // * The DC offset is thus 0.50V/1.05V ~ 1/2 of the dynamic range. // // Note that by removing the DC offset, we get the following ranges for // one voice: // y > 0: (6.75V - 5.44V) - 0.50V = 0.81V // y < 0: (5.70V - 5.44V) - 0.50V = -0.24V // The scaling of the voice amplitude is not symmetric about y = 0; // this follows from the DC level in the waveform output. voice_DC = 0x800*0xff; } else { // No DC offsets in the MOS8580. wave_zero = 0x800; voice_DC = 0; } } // ---------------------------------------------------------------------------- // Set sync source. // ---------------------------------------------------------------------------- void Voice::set_sync_source(Voice* source) { wave.set_sync_source(&source->wave); } // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void Voice::writeCONTROL_REG(reg8 control) { wave.writeCONTROL_REG(control); envelope.writeCONTROL_REG(control); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void Voice::reset() { wave.reset(); envelope.reset(); } goattracker-2.72/src/resid/envelope.h0000644000000000000000000002227111313456166016345 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __ENVELOPE_H__ #define __ENVELOPE_H__ #include "siddefs.h" // ---------------------------------------------------------------------------- // A 15 bit counter is used to implement the envelope rates, in effect // dividing the clock to the envelope counter by the currently selected rate // period. // In addition, another counter is used to implement the exponential envelope // decay, in effect further dividing the clock to the envelope counter. // The period of this counter is set to 1, 2, 4, 8, 16, 30 at the envelope // counter values 255, 93, 54, 26, 14, 6, respectively. // ---------------------------------------------------------------------------- class EnvelopeGenerator { public: EnvelopeGenerator(); enum State { ATTACK, DECAY_SUSTAIN, RELEASE }; RESID_INLINE void clock(); RESID_INLINE void clock(cycle_count delta_t); void reset(); void writeCONTROL_REG(reg8); void writeATTACK_DECAY(reg8); void writeSUSTAIN_RELEASE(reg8); reg8 readENV(); // 8-bit envelope output. RESID_INLINE reg8 output(); protected: reg16 rate_counter; reg16 rate_period; reg8 exponential_counter; reg8 exponential_counter_period; reg8 envelope_counter; bool hold_zero; reg4 attack; reg4 decay; reg4 sustain; reg4 release; reg8 gate; State state; // Lookup table to convert from attack, decay, or release value to rate // counter period. static reg16 rate_counter_period[]; // The 16 selectable sustain levels. static reg8 sustain_level[]; friend class SID; }; // ---------------------------------------------------------------------------- // Inline functions. // The following functions are defined inline because they are called every // time a sample is calculated. // ---------------------------------------------------------------------------- #if RESID_INLINING || defined(__ENVELOPE_CC__) // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- RESID_INLINE void EnvelopeGenerator::clock() { // Check for ADSR delay bug. // If the rate counter comparison value is set below the current value of the // rate counter, the counter will continue counting up until it wraps around // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the // envelope can finally be stepped. // This has been verified by sampling ENV3. // if (++rate_counter & 0x8000) { ++rate_counter &= 0x7fff; } if (rate_counter != rate_period) { return; } rate_counter = 0; // The first envelope step in the attack state also resets the exponential // counter. This has been verified by sampling ENV3. // if (state == ATTACK || ++exponential_counter == exponential_counter_period) { exponential_counter = 0; // Check whether the envelope counter is frozen at zero. if (hold_zero) { return; } switch (state) { case ATTACK: // The envelope counter can flip from 0xff to 0x00 by changing state to // release, then to attack. The envelope counter is then frozen at // zero; to unlock this situation the state must be changed to release, // then to attack. This has been verified by sampling ENV3. // ++envelope_counter &= 0xff; if (envelope_counter == 0xff) { state = DECAY_SUSTAIN; rate_period = rate_counter_period[decay]; } break; case DECAY_SUSTAIN: if (envelope_counter != sustain_level[sustain]) { --envelope_counter; } break; case RELEASE: // The envelope counter can flip from 0x00 to 0xff by changing state to // attack, then to release. The envelope counter will then continue // counting down in the release state. // This has been verified by sampling ENV3. // NB! The operation below requires two's complement integer. // --envelope_counter &= 0xff; break; } // Check for change of exponential counter period. switch (envelope_counter) { case 0xff: exponential_counter_period = 1; break; case 0x5d: exponential_counter_period = 2; break; case 0x36: exponential_counter_period = 4; break; case 0x1a: exponential_counter_period = 8; break; case 0x0e: exponential_counter_period = 16; break; case 0x06: exponential_counter_period = 30; break; case 0x00: exponential_counter_period = 1; // When the envelope counter is changed to zero, it is frozen at zero. // This has been verified by sampling ENV3. hold_zero = true; break; } } } // ---------------------------------------------------------------------------- // SID clocking - delta_t cycles. // ---------------------------------------------------------------------------- RESID_INLINE void EnvelopeGenerator::clock(cycle_count delta_t) { // Check for ADSR delay bug. // If the rate counter comparison value is set below the current value of the // rate counter, the counter will continue counting up until it wraps around // to zero at 2^15 = 0x8000, and then count rate_period - 1 before the // envelope can finally be stepped. // This has been verified by sampling ENV3. // // NB! This requires two's complement integer. int rate_step = rate_period - rate_counter; if (rate_step <= 0) { rate_step += 0x7fff; } while (delta_t) { if (delta_t < rate_step) { rate_counter += delta_t; if (rate_counter & 0x8000) { ++rate_counter &= 0x7fff; } return; } rate_counter = 0; delta_t -= rate_step; // The first envelope step in the attack state also resets the exponential // counter. This has been verified by sampling ENV3. // if (state == ATTACK || ++exponential_counter == exponential_counter_period) { exponential_counter = 0; // Check whether the envelope counter is frozen at zero. if (hold_zero) { rate_step = rate_period; continue; } switch (state) { case ATTACK: // The envelope counter can flip from 0xff to 0x00 by changing state to // release, then to attack. The envelope counter is then frozen at // zero; to unlock this situation the state must be changed to release, // then to attack. This has been verified by sampling ENV3. // ++envelope_counter &= 0xff; if (envelope_counter == 0xff) { state = DECAY_SUSTAIN; rate_period = rate_counter_period[decay]; } break; case DECAY_SUSTAIN: if (envelope_counter != sustain_level[sustain]) { --envelope_counter; } break; case RELEASE: // The envelope counter can flip from 0x00 to 0xff by changing state to // attack, then to release. The envelope counter will then continue // counting down in the release state. // This has been verified by sampling ENV3. // NB! The operation below requires two's complement integer. // --envelope_counter &= 0xff; break; } // Check for change of exponential counter period. switch (envelope_counter) { case 0xff: exponential_counter_period = 1; break; case 0x5d: exponential_counter_period = 2; break; case 0x36: exponential_counter_period = 4; break; case 0x1a: exponential_counter_period = 8; break; case 0x0e: exponential_counter_period = 16; break; case 0x06: exponential_counter_period = 30; break; case 0x00: exponential_counter_period = 1; // When the envelope counter is changed to zero, it is frozen at zero. // This has been verified by sampling ENV3. hold_zero = true; break; } } rate_step = rate_period; } } // ---------------------------------------------------------------------------- // Read the envelope generator output. // ---------------------------------------------------------------------------- RESID_INLINE reg8 EnvelopeGenerator::output() { return envelope_counter; } #endif // RESID_INLINING || defined(__ENVELOPE_CC__) #endif // not __ENVELOPE_H__ goattracker-2.72/src/resid/wave6581_PST.cpp0000644000000000000000000010110211313456166017066 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "wave.h" reg8 WaveformGenerator::wave6581_PST[] = { /* 0x000: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x008: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x010: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x018: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x020: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x080: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x088: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x090: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x098: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x0f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x100: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x108: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x110: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x118: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x120: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x128: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x130: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x138: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x140: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x148: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x150: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x158: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x160: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x168: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x170: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x178: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x180: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x188: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x190: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x198: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x1f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x200: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x208: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x210: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x218: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x220: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x228: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x230: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x238: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x240: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x248: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x250: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x258: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x260: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x268: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x270: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x278: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x280: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x288: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x290: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x298: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x2f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x300: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x308: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x310: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x318: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x320: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x328: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x330: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x338: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x340: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x348: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x350: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x358: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x360: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x368: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x370: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x378: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x380: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x388: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x390: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x398: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x3f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, /* 0x400: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x408: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x410: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x418: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x420: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x428: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x430: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x438: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x440: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x448: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x450: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x458: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x460: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x468: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x470: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x478: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x480: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x488: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x490: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x498: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x4f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x500: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x508: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x510: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x518: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x520: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x528: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x530: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x538: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x540: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x548: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x550: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x558: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x560: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x568: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x570: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x578: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x580: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x588: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x590: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x598: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x600: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x608: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x610: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x618: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x620: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x628: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x630: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x638: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x640: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x648: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x650: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x658: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x660: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x668: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x670: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x678: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x680: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x688: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x690: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x698: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x6f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x700: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x708: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x710: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x718: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x720: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x728: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x730: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x738: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x740: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x748: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x750: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x758: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x760: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x768: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x770: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x778: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x780: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x788: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x790: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x798: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* 0x7f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, /* 0x7f8: */ 0x00, 0x00, 0x00, 0x78, 0x78, 0x7e, 0x7f, 0x7f, /* 0x800: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x808: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x810: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x818: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x820: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x828: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x830: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x838: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x840: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x848: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x850: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x858: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x860: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x868: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x870: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x878: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x880: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x888: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x890: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x898: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x8f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x900: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x908: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x910: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x918: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x920: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x928: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x930: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x938: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x940: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x948: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x950: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x958: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x960: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x968: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x970: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x978: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x980: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x988: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x990: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x998: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9a8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9b8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9c8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9d8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9e8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x9f8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xa98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xab8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xac8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xad8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xae8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xaf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xb98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xba8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xbf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, /* 0xc00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xca8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xce8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xcf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xda8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xde8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xe98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xea8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xeb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xec8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xed8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xee8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xef8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf00: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf08: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf10: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf18: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf28: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf30: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf38: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf40: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf48: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf50: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf58: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf60: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf68: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf70: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf78: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf80: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf88: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf90: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xf98: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfa8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfb8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfc8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfd8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xfe8: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, /* 0xff0: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, /* 0xff8: */ 0x00, 0x00, 0x00, 0x78, 0x78, 0x7e, 0x7f, 0x7f, }; goattracker-2.72/src/resid/extfilt.cpp0000644000000000000000000000543411313456166016544 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __EXTFILT_CC__ #include "extfilt.h" // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- ExternalFilter::ExternalFilter() { reset(); enable_filter(true); set_chip_model(MOS6581); // Low-pass: R = 10kOhm, C = 1000pF; w0l = 1/RC = 1/(1e4*1e-9) = 100000 // High-pass: R = 1kOhm, C = 10uF; w0h = 1/RC = 1/(1e3*1e-5) = 100 // Multiply with 1.048576 to facilitate division by 1 000 000 by right- // shifting 20 times (2 ^ 20 = 1048576). w0lp = 104858; w0hp = 105; } // ---------------------------------------------------------------------------- // Enable filter. // ---------------------------------------------------------------------------- void ExternalFilter::enable_filter(bool enable) { enabled = enable; } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void ExternalFilter::set_chip_model(chip_model model) { if (model == MOS6581) { // Maximum mixer DC output level; to be removed if the external // filter is turned off: ((wave DC + voice DC)*voices + mixer DC)*volume // See voice.cc and filter.cc for an explanation of the values. mixer_DC = ((((0x800 - 0x380) + 0x800)*0xff*3 - 0xfff*0xff/18) >> 7)*0x0f; } else { // No DC offsets in the MOS8580. mixer_DC = 0; } } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void ExternalFilter::reset() { // State of filter. Vlp = 0; Vhp = 0; Vo = 0; } goattracker-2.72/src/resid/envelope.cpp0000644000000000000000000002042611313456166016700 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #define __ENVELOPE_CC__ #include "envelope.h" // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- EnvelopeGenerator::EnvelopeGenerator() { reset(); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void EnvelopeGenerator::reset() { envelope_counter = 0; attack = 0; decay = 0; sustain = 0; release = 0; gate = 0; rate_counter = 0; exponential_counter = 0; exponential_counter_period = 1; state = RELEASE; rate_period = rate_counter_period[release]; hold_zero = true; } // Rate counter periods are calculated from the Envelope Rates table in // the Programmer's Reference Guide. The rate counter period is the number of // cycles between each increment of the envelope counter. // The rates have been verified by sampling ENV3. // // The rate counter is a 16 bit register which is incremented each cycle. // When the counter reaches a specific comparison value, the envelope counter // is incremented (attack) or decremented (decay/release) and the // counter is zeroed. // // NB! Sampling ENV3 shows that the calculated values are not exact. // It may seem like most calculated values have been rounded (.5 is rounded // down) and 1 has beed added to the result. A possible explanation for this // is that the SID designers have used the calculated values directly // as rate counter comparison values, not considering a one cycle delay to // zero the counter. This would yield an actual period of comparison value + 1. // // The time of the first envelope count can not be exactly controlled, except // possibly by resetting the chip. Because of this we cannot do cycle exact // sampling and must devise another method to calculate the rate counter // periods. // // The exact rate counter periods can be determined e.g. by counting the number // of cycles from envelope level 1 to envelope level 129, and dividing the // number of cycles by 128. CIA1 timer A and B in linked mode can perform // the cycle count. This is the method used to find the rates below. // // To avoid the ADSR delay bug, sampling of ENV3 should be done using // sustain = release = 0. This ensures that the attack state will not lower // the current rate counter period. // // The ENV3 sampling code below yields a maximum timing error of 14 cycles. // lda #$01 // l1: cmp $d41c // bne l1 // ... // lda #$ff // l2: cmp $d41c // bne l2 // // This yields a maximum error for the calculated rate period of 14/128 cycles. // The described method is thus sufficient for exact calculation of the rate // periods. // reg16 EnvelopeGenerator::rate_counter_period[] = { 9, // 2ms*1.0MHz/256 = 7.81 32, // 8ms*1.0MHz/256 = 31.25 63, // 16ms*1.0MHz/256 = 62.50 95, // 24ms*1.0MHz/256 = 93.75 149, // 38ms*1.0MHz/256 = 148.44 220, // 56ms*1.0MHz/256 = 218.75 267, // 68ms*1.0MHz/256 = 265.63 313, // 80ms*1.0MHz/256 = 312.50 392, // 100ms*1.0MHz/256 = 390.63 977, // 250ms*1.0MHz/256 = 976.56 1954, // 500ms*1.0MHz/256 = 1953.13 3126, // 800ms*1.0MHz/256 = 3125.00 3907, // 1 s*1.0MHz/256 = 3906.25 11720, // 3 s*1.0MHz/256 = 11718.75 19532, // 5 s*1.0MHz/256 = 19531.25 31251 // 8 s*1.0MHz/256 = 31250.00 }; // For decay and release, the clock to the envelope counter is sequentially // divided by 1, 2, 4, 8, 16, 30, 1 to create a piece-wise linear approximation // of an exponential. The exponential counter period is loaded at the envelope // counter values 255, 93, 54, 26, 14, 6, 0. The period can be different for the // same envelope counter value, depending on whether the envelope has been // rising (attack -> release) or sinking (decay/release). // // Since it is not possible to reset the rate counter (the test bit has no // influence on the envelope generator whatsoever) a method must be devised to // do cycle exact sampling of ENV3 to do the investigation. This is possible // with knowledge of the rate period for A=0, found above. // // The CPU can be synchronized with ENV3 by first synchronizing with the rate // counter by setting A=0 and wait in a carefully timed loop for the envelope // counter _not_ to change for 9 cycles. We can then wait for a specific value // of ENV3 with another timed loop to fully synchronize with ENV3. // // At the first period when an exponential counter period larger than one // is used (decay or relase), one extra cycle is spent before the envelope is // decremented. The envelope output is then delayed one cycle until the state // is changed to attack. Now one cycle less will be spent before the envelope // is incremented, and the situation is normalized. // The delay is probably caused by the comparison with the exponential counter, // and does not seem to affect the rate counter. This has been verified by // timing 256 consecutive complete envelopes with A = D = R = 1, S = 0, using // CIA1 timer A and B in linked mode. If the rate counter is not affected the // period of each complete envelope is // (255 + 162*1 + 39*2 + 28*4 + 12*8 + 8*16 + 6*30)*32 = 756*32 = 32352 // which corresponds exactly to the timed value divided by the number of // complete envelopes. // NB! This one cycle delay is not modeled. // From the sustain levels it follows that both the low and high 4 bits of the // envelope counter are compared to the 4-bit sustain value. // This has been verified by sampling ENV3. // reg8 EnvelopeGenerator::sustain_level[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, }; // ---------------------------------------------------------------------------- // Register functions. // ---------------------------------------------------------------------------- void EnvelopeGenerator::writeCONTROL_REG(reg8 control) { reg8 gate_next = control & 0x01; // The rate counter is never reset, thus there will be a delay before the // envelope counter starts counting up (attack) or down (release). // Gate bit on: Start attack, decay, sustain. if (!gate && gate_next) { state = ATTACK; rate_period = rate_counter_period[attack]; // Switching to attack state unlocks the zero freeze. hold_zero = false; } // Gate bit off: Start release. else if (gate && !gate_next) { state = RELEASE; rate_period = rate_counter_period[release]; } gate = gate_next; } void EnvelopeGenerator::writeATTACK_DECAY(reg8 attack_decay) { attack = (attack_decay >> 4) & 0x0f; decay = attack_decay & 0x0f; if (state == ATTACK) { rate_period = rate_counter_period[attack]; } else if (state == DECAY_SUSTAIN) { rate_period = rate_counter_period[decay]; } } void EnvelopeGenerator::writeSUSTAIN_RELEASE(reg8 sustain_release) { sustain = (sustain_release >> 4) & 0x0f; release = sustain_release & 0x0f; if (state == RELEASE) { rate_period = rate_counter_period[release]; } } reg8 EnvelopeGenerator::readENV() { return output(); } goattracker-2.72/src/resid/voice.h0000644000000000000000000000464710774364076015654 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #ifndef __VOICE_H__ #define __VOICE_H__ #include "siddefs.h" #include "wave.h" #include "envelope.h" class Voice { public: Voice(); void set_chip_model(chip_model model); void set_sync_source(Voice*); void reset(); void writeCONTROL_REG(reg8); // Amplitude modulated waveform output. // Range [-2048*255, 2047*255]. RESID_INLINE sound_sample output(); protected: WaveformGenerator wave; EnvelopeGenerator envelope; // Waveform D/A zero level. sound_sample wave_zero; // Multiplying D/A DC offset. sound_sample voice_DC; friend class SID; }; // ---------------------------------------------------------------------------- // Inline functions. // The following function is defined inline because it is called every // time a sample is calculated. // ---------------------------------------------------------------------------- #if RESID_INLINING || defined(__VOICE_CC__) // ---------------------------------------------------------------------------- // Amplitude modulated waveform output. // Ideal range [-2048*255, 2047*255]. // ---------------------------------------------------------------------------- RESID_INLINE sound_sample Voice::output() { // Multiply oscillator output with envelope output. return (wave.output() - wave_zero)*envelope.output() + voice_DC; } #endif // RESID_INLINING || defined(__VOICE_CC__) #endif // not __VOICE_H__ goattracker-2.72/src/resid/sid.cpp0000644000000000000000000007626111313457372015652 0ustar rootroot// --------------------------------------------------------------------------- // This file is part of reSID, a MOS6581 SID emulator engine. // Copyright (C) 2004 Dag Lem // // 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // --------------------------------------------------------------------------- #include "sid.h" #include // Resampling constants. // The error in interpolated lookup is bounded by 1.234/L^2, // while the error in non-interpolated lookup is bounded by // 0.7854/L + 0.4113/L^2, see // http://www-ccrma.stanford.edu/~jos/resample/Choice_Table_Size.html // For a resolution of 16 bits this yields L >= 285 and L >= 51473, // respectively. #define FIR_N 125 #define FIR_RES_INTERPOLATE 285 #define FIR_RES_FAST 51473 #define FIR_SHIFT 15 #define RINGSIZE 16384 // Fixpoint constants (16.16 bits). #define FIXP_SHIFT 16 #define FIXP_MASK 0xffff // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- SID::SID() { // Initialize pointers. sample = 0; fir = 0; voice[0].set_sync_source(&voice[2]); voice[1].set_sync_source(&voice[0]); voice[2].set_sync_source(&voice[1]); set_sampling_parameters(985248, SAMPLE_FAST, 44100); bus_value = 0; bus_value_ttl = 0; ext_in = 0; } // ---------------------------------------------------------------------------- // Destructor. // ---------------------------------------------------------------------------- SID::~SID() { delete[] sample; delete[] fir; } // ---------------------------------------------------------------------------- // Set chip model. // ---------------------------------------------------------------------------- void SID::set_chip_model(chip_model model) { for (int i = 0; i < 3; i++) { voice[i].set_chip_model(model); } filter.set_chip_model(model); extfilt.set_chip_model(model); } // ---------------------------------------------------------------------------- // SID reset. // ---------------------------------------------------------------------------- void SID::reset() { for (int i = 0; i < 3; i++) { voice[i].reset(); } filter.reset(); extfilt.reset(); bus_value = 0; bus_value_ttl = 0; } // ---------------------------------------------------------------------------- // Write 16-bit sample to audio input. // NB! The caller is responsible for keeping the value within 16 bits. // Note that to mix in an external audio signal, the signal should be // resampled to 1MHz first to avoid sampling noise. // ---------------------------------------------------------------------------- void SID::input(int sample) { // Voice outputs are 20 bits. Scale up to match three voices in order // to facilitate simulation of the MOS8580 "digi boost" hardware hack. ext_in = (sample << 4)*3; } // ---------------------------------------------------------------------------- // Read sample from audio output. // Both 16-bit and n-bit output is provided. // ---------------------------------------------------------------------------- int SID::output() { const int range = 1 << 16; const int half = range >> 1; int sample = extfilt.output()/((4095*255 >> 7)*3*15*2/range); if (sample >= half) { return half - 1; } if (sample < -half) { return -half; } return sample; } int SID::output(int bits) { const int range = 1 << bits; const int half = range >> 1; int sample = extfilt.output()/((4095*255 >> 7)*3*15*2/range); if (sample >= half) { return half - 1; } if (sample < -half) { return -half; } return sample; } // ---------------------------------------------------------------------------- // Read registers. // // Reading a write only register returns the last byte written to any SID // register. The individual bits in this value start to fade down towards // zero after a few cycles. All bits reach zero within approximately // $2000 - $4000 cycles. // It has been claimed that this fading happens in an orderly fashion, however // sampling of write only registers reveals that this is not the case. // NB! This is not correctly modeled. // The actual use of write only registers has largely been made in the belief // that all SID registers are readable. To support this belief the read // would have to be done immediately after a write to the same register // (remember that an intermediate write to another register would yield that // value instead). With this in mind we return the last value written to // any SID register for $2000 cycles without modeling the bit fading. // ---------------------------------------------------------------------------- reg8 SID::read(reg8 offset) { switch (offset) { case 0x19: return potx.readPOT(); case 0x1a: return poty.readPOT(); case 0x1b: return voice[2].wave.readOSC(); case 0x1c: return voice[2].envelope.readENV(); default: return bus_value; } } // ---------------------------------------------------------------------------- // Write registers. // ---------------------------------------------------------------------------- void SID::write(reg8 offset, reg8 value) { bus_value = value; bus_value_ttl = 0x2000; switch (offset) { case 0x00: voice[0].wave.writeFREQ_LO(value); break; case 0x01: voice[0].wave.writeFREQ_HI(value); break; case 0x02: voice[0].wave.writePW_LO(value); break; case 0x03: voice[0].wave.writePW_HI(value); break; case 0x04: voice[0].writeCONTROL_REG(value); break; case 0x05: voice[0].envelope.writeATTACK_DECAY(value); break; case 0x06: voice[0].envelope.writeSUSTAIN_RELEASE(value); break; case 0x07: voice[1].wave.writeFREQ_LO(value); break; case 0x08: voice[1].wave.writeFREQ_HI(value); break; case 0x09: voice[1].wave.writePW_LO(value); break; case 0x0a: voice[1].wave.writePW_HI(value); break; case 0x0b: voice[1].writeCONTROL_REG(value); break; case 0x0c: voice[1].envelope.writeATTACK_DECAY(value); break; case 0x0d: voice[1].envelope.writeSUSTAIN_RELEASE(value); break; case 0x0e: voice[2].wave.writeFREQ_LO(value); break; case 0x0f: voice[2].wave.writeFREQ_HI(value); break; case 0x10: voice[2].wave.writePW_LO(value); break; case 0x11: voice[2].wave.writePW_HI(value); break; case 0x12: voice[2].writeCONTROL_REG(value); break; case 0x13: voice[2].envelope.writeATTACK_DECAY(value); break; case 0x14: voice[2].envelope.writeSUSTAIN_RELEASE(value); break; case 0x15: filter.writeFC_LO(value); break; case 0x16: filter.writeFC_HI(value); break; case 0x17: filter.writeRES_FILT(value); break; case 0x18: filter.writeMODE_VOL(value); break; default: break; } } // ---------------------------------------------------------------------------- // Constructor. // ---------------------------------------------------------------------------- SID::State::State() { int i; for (i = 0; i < 0x20; i++) { sid_register[i] = 0; } bus_value = 0; bus_value_ttl = 0; for (i = 0; i < 3; i++) { accumulator[i] = 0; shift_register[i] = 0x7ffff8; rate_counter[i] = 0; rate_counter_period[i] = 9; exponential_counter[i] = 0; exponential_counter_period[i] = 1; envelope_counter[i] = 0; envelope_state[i] = EnvelopeGenerator::RELEASE; hold_zero[i] = true; } } // ---------------------------------------------------------------------------- // Read state. // ---------------------------------------------------------------------------- SID::State SID::read_state() { State state; int i, j; for (i = 0, j = 0; i < 3; i++, j += 7) { WaveformGenerator& wave = voice[i].wave; EnvelopeGenerator& envelope = voice[i].envelope; state.sid_register[j + 0] = wave.freq & 0xff; state.sid_register[j + 1] = wave.freq >> 8; state.sid_register[j + 2] = wave.pw & 0xff; state.sid_register[j + 3] = wave.pw >> 8; state.sid_register[j + 4] = (wave.waveform << 4) | (wave.test ? 0x08 : 0) | (wave.ring_mod ? 0x04 : 0) | (wave.sync ? 0x02 : 0) | (envelope.gate ? 0x01 : 0); state.sid_register[j + 5] = (envelope.attack << 4) | envelope.decay; state.sid_register[j + 6] = (envelope.sustain << 4) | envelope.release; } state.sid_register[j++] = filter.fc & 0x007; state.sid_register[j++] = filter.fc >> 3; state.sid_register[j++] = (filter.res << 4) | filter.filt; state.sid_register[j++] = (filter.voice3off ? 0x80 : 0) | (filter.hp_bp_lp << 4) | filter.vol; // These registers are superfluous, but included for completeness. for (; j < 0x1d; j++) { state.sid_register[j] = read(j); } for (; j < 0x20; j++) { state.sid_register[j] = 0; } state.bus_value = bus_value; state.bus_value_ttl = bus_value_ttl; for (i = 0; i < 3; i++) { state.accumulator[i] = voice[i].wave.accumulator; state.shift_register[i] = voice[i].wave.shift_register; state.rate_counter[i] = voice[i].envelope.rate_counter; state.rate_counter_period[i] = voice[i].envelope.rate_period; state.exponential_counter[i] = voice[i].envelope.exponential_counter; state.exponential_counter_period[i] = voice[i].envelope.exponential_counter_period; state.envelope_counter[i] = voice[i].envelope.envelope_counter; state.envelope_state[i] = voice[i].envelope.state; state.hold_zero[i] = voice[i].envelope.hold_zero; } return state; } // ---------------------------------------------------------------------------- // Write state. // ---------------------------------------------------------------------------- void SID::write_state(const State& state) { int i; for (i = 0; i <= 0x18; i++) { write(i, state.sid_register[i]); } bus_value = state.bus_value; bus_value_ttl = state.bus_value_ttl; for (i = 0; i < 3; i++) { voice[i].wave.accumulator = state.accumulator[i]; voice[i].wave.shift_register = state.shift_register[i]; voice[i].envelope.rate_counter = state.rate_counter[i]; voice[i].envelope.rate_period = state.rate_counter_period[i]; voice[i].envelope.exponential_counter = state.exponential_counter[i]; voice[i].envelope.exponential_counter_period = state.exponential_counter_period[i]; voice[i].envelope.envelope_counter = state.envelope_counter[i]; voice[i].envelope.state = state.envelope_state[i]; voice[i].envelope.hold_zero = state.hold_zero[i]; } } // ---------------------------------------------------------------------------- // Enable filter. // ---------------------------------------------------------------------------- void SID::enable_filter(bool enable) { filter.enable_filter(enable); } // ---------------------------------------------------------------------------- // Enable external filter. // ---------------------------------------------------------------------------- void SID::enable_external_filter(bool enable) { extfilt.enable_filter(enable); } // ---------------------------------------------------------------------------- // I0() computes the 0th order modified Bessel function of the first kind. // This function is originally from resample-1.5/filterkit.c by J. O. Smith. // ---------------------------------------------------------------------------- double SID::I0(double x) { // Max error acceptable in I0. const double I0e = 1e-6; double sum, u, halfx, temp; int n; sum = u = n = 1; halfx = x/2.0; do { temp = halfx/n++; u *= temp*temp; sum += u; } while (u >= I0e*sum); return sum; } // ---------------------------------------------------------------------------- // Setting of SID sampling parameters. // // Use a clock freqency of 985248Hz for PAL C64, 1022730Hz for NTSC C64. // The default end of passband frequency is pass_freq = 0.9*sample_freq/2 // for sample frequencies up to ~ 44.1kHz, and 20kHz for higher sample // frequencies. // // For resampling, the ratio between the clock frequency and the sample // frequency is limited as follows: // 125*clock_freq/sample_freq < 16384 // E.g. provided a clock frequency of ~ 1MHz, the sample frequency can not // be set lower than ~ 8kHz. A lower sample frequency would make the // resampling code overfill its 16k sample ring buffer. // // The end of passband frequency is also limited: // pass_freq <= 0.9*sample_freq/2 // E.g. for a 44.1kHz sampling rate the end of passband frequency is limited // to slightly below 20kHz. This constraint ensures that the FIR table is // not overfilled. // ---------------------------------------------------------------------------- bool SID::set_sampling_parameters(double clock_freq, sampling_method method, double sample_freq, double pass_freq, double filter_scale) { // Check resampling constraints. if (method == SAMPLE_RESAMPLE_INTERPOLATE || method == SAMPLE_RESAMPLE_FAST) { // Check whether the sample ring buffer would overfill. if (FIR_N*clock_freq/sample_freq >= RINGSIZE) { return false; } // The default passband limit is 0.9*sample_freq/2 for sample // frequencies below ~ 44.1kHz, and 20kHz for higher sample frequencies. if (pass_freq < 0) { pass_freq = 20000; if (2*pass_freq/sample_freq >= 0.9) { pass_freq = 0.9*sample_freq/2; } } // Check whether the FIR table would overfill. else if (pass_freq > 0.9*sample_freq/2) { return false; } // The filter scaling is only included to avoid clipping, so keep // it sane. if (filter_scale < 0.9 || filter_scale > 1.0) { return false; } } clock_frequency = clock_freq; sampling = method; cycles_per_sample = cycle_count(clock_freq/sample_freq*(1 << FIXP_SHIFT) + 0.5); sample_offset = 0; sample_prev = 0; // FIR initialization is only necessary for resampling. if (method != SAMPLE_RESAMPLE_INTERPOLATE && method != SAMPLE_RESAMPLE_FAST) { delete[] sample; delete[] fir; sample = 0; fir = 0; return true; } const double pi = 3.1415926535897932385; // 16 bits -> -96dB stopband attenuation. const double A = -20*log10(1.0/(1 << 16)); // A fraction of the bandwidth is allocated to the transition band, double dw = (1 - 2*pass_freq/sample_freq)*pi; // The cutoff frequency is midway through the transition band. double wc = (2*pass_freq/sample_freq + 1)*pi/2; // For calculation of beta and N see the reference for the kaiserord // function in the MATLAB Signal Processing Toolbox: // http://www.mathworks.com/access/helpdesk/help/toolbox/signal/kaiserord.html const double beta = 0.1102*(A - 8.7); const double I0beta = I0(beta); // The filter order will maximally be 124 with the current constraints. // N >= (96.33 - 7.95)/(2.285*0.1*pi) -> N >= 123 // The filter order is equal to the number of zero crossings, i.e. // it should be an even number (sinc is symmetric about x = 0). int N = int((A - 7.95)/(2.285*dw) + 0.5); N += N & 1; double f_samples_per_cycle = sample_freq/clock_freq; double f_cycles_per_sample = clock_freq/sample_freq; // The filter length is equal to the filter order + 1. // The filter length must be an odd number (sinc is symmetric about x = 0). fir_N = int(N*f_cycles_per_sample) + 1; fir_N |= 1; // We clamp the filter table resolution to 2^n, making the fixpoint // sample_offset a whole multiple of the filter table resolution. int res = method == SAMPLE_RESAMPLE_INTERPOLATE ? FIR_RES_INTERPOLATE : FIR_RES_FAST; int n = (int)ceil(log(res/f_cycles_per_sample)/log(2)); fir_RES = 1 << n; // Allocate memory for FIR tables. delete[] fir; fir = new short[fir_N*fir_RES]; // Calculate fir_RES FIR tables for linear interpolation. for (int i = 0; i < fir_RES; i++) { int fir_offset = i*fir_N + fir_N/2; double j_offset = double(i)/fir_RES; // Calculate FIR table. This is the sinc function, weighted by the // Kaiser window. for (int j = -fir_N/2; j <= fir_N/2; j++) { double jx = j - j_offset; double wt = wc*jx/f_cycles_per_sample; double temp = jx/(fir_N/2); double Kaiser = fabs(temp) <= 1 ? I0(beta*sqrt(1 - temp*temp))/I0beta : 0; double sincwt = fabs(wt) >= 1e-6 ? sin(wt)/wt : 1; double val = (1 << FIR_SHIFT)*filter_scale*f_samples_per_cycle*wc/pi*sincwt*Kaiser; fir[fir_offset + j] = short(val + 0.5); } } // Allocate sample buffer. if (!sample) { sample = new short[RINGSIZE*2]; } // Clear sample buffer. for (int j = 0; j < RINGSIZE*2; j++) { sample[j] = 0; } sample_index = 0; return true; } // ---------------------------------------------------------------------------- // Adjustment of SID sampling frequency. // // In some applications, e.g. a C64 emulator, it can be desirable to // synchronize sound with a timer source. This is supported by adjustment of // the SID sampling frequency. // // NB! Adjustment of the sampling frequency may lead to noticeable shifts in // frequency, and should only be used for interactive applications. Note also // that any adjustment of the sampling frequency will change the // characteristics of the resampling filter, since the filter is not rebuilt. // ---------------------------------------------------------------------------- void SID::adjust_sampling_frequency(double sample_freq) { cycles_per_sample = cycle_count(clock_frequency/sample_freq*(1 << FIXP_SHIFT) + 0.5); } // ---------------------------------------------------------------------------- // Return array of default spline interpolation points to map FC to // filter cutoff frequency. // ---------------------------------------------------------------------------- void SID::fc_default(const fc_point*& points, int& count) { filter.fc_default(points, count); } // ---------------------------------------------------------------------------- // Return FC spline plotter object. // ---------------------------------------------------------------------------- PointPlotter SID::fc_plotter() { return filter.fc_plotter(); } // ---------------------------------------------------------------------------- // SID clocking - 1 cycle. // ---------------------------------------------------------------------------- void SID::clock() { int i; // Age bus value. if (--bus_value_ttl <= 0) { bus_value = 0; bus_value_ttl = 0; } // Clock amplitude modulators. for (i = 0; i < 3; i++) { voice[i].envelope.clock(); } // Clock oscillators. for (i = 0; i < 3; i++) { voice[i].wave.clock(); } // Synchronize oscillators. for (i = 0; i < 3; i++) { voice[i].wave.synchronize(); } // Clock filter. filter.clock(voice[0].output(), voice[1].output(), voice[2].output(), ext_in); // Clock external filter. extfilt.clock(filter.output()); } // ---------------------------------------------------------------------------- // SID clocking - delta_t cycles. // ---------------------------------------------------------------------------- void SID::clock(cycle_count delta_t) { int i; if (delta_t <= 0) { return; } // Age bus value. bus_value_ttl -= delta_t; if (bus_value_ttl <= 0) { bus_value = 0; bus_value_ttl = 0; } // Clock amplitude modulators. for (i = 0; i < 3; i++) { voice[i].envelope.clock(delta_t); } // Clock and synchronize oscillators. // Loop until we reach the current cycle. cycle_count delta_t_osc = delta_t; while (delta_t_osc) { cycle_count delta_t_min = delta_t_osc; // Find minimum number of cycles to an oscillator accumulator MSB toggle. // We have to clock on each MSB on / MSB off for hard sync to operate // correctly. for (i = 0; i < 3; i++) { WaveformGenerator& wave = voice[i].wave; // It is only necessary to clock on the MSB of an oscillator that is // a sync source and has freq != 0. if (!(wave.sync_dest->sync && wave.freq)) { continue; } reg16 freq = wave.freq; reg24 accumulator = wave.accumulator; // Clock on MSB off if MSB is on, clock on MSB on if MSB is off. reg24 delta_accumulator = (accumulator & 0x800000 ? 0x1000000 : 0x800000) - accumulator; cycle_count delta_t_next = delta_accumulator/freq; if (delta_accumulator%freq) { ++delta_t_next; } if (delta_t_next < delta_t_min) { delta_t_min = delta_t_next; } } // Clock oscillators. for (i = 0; i < 3; i++) { voice[i].wave.clock(delta_t_min); } // Synchronize oscillators. for (i = 0; i < 3; i++) { voice[i].wave.synchronize(); } delta_t_osc -= delta_t_min; } // Clock filter. filter.clock(delta_t, voice[0].output(), voice[1].output(), voice[2].output(), ext_in); // Clock external filter. extfilt.clock(delta_t, filter.output()); } // ---------------------------------------------------------------------------- // SID clocking with audio sampling. // Fixpoint arithmetics is used. // // The example below shows how to clock the SID a specified amount of cycles // while producing audio output: // // while (delta_t) { // bufindex += sid.clock(delta_t, buf + bufindex, buflength - bufindex); // write(dsp, buf, bufindex*2); // bufindex = 0; // } // // ---------------------------------------------------------------------------- int SID::clock(cycle_count& delta_t, short* buf, int n, int interleave) { switch (sampling) { default: case SAMPLE_FAST: return clock_fast(delta_t, buf, n, interleave); case SAMPLE_INTERPOLATE: return clock_interpolate(delta_t, buf, n, interleave); case SAMPLE_RESAMPLE_INTERPOLATE: return clock_resample_interpolate(delta_t, buf, n, interleave); case SAMPLE_RESAMPLE_FAST: return clock_resample_fast(delta_t, buf, n, interleave); } } // ---------------------------------------------------------------------------- // SID clocking with audio sampling - delta clocking picking nearest sample. // ---------------------------------------------------------------------------- RESID_INLINE int SID::clock_fast(cycle_count& delta_t, short* buf, int n, int interleave) { int s = 0; for (;;) { cycle_count next_sample_offset = sample_offset + cycles_per_sample + (1 << (FIXP_SHIFT - 1)); cycle_count delta_t_sample = next_sample_offset >> FIXP_SHIFT; if (delta_t_sample > delta_t) { break; } if (s >= n) { return s; } clock(delta_t_sample); delta_t -= delta_t_sample; sample_offset = (next_sample_offset & FIXP_MASK) - (1 << (FIXP_SHIFT - 1)); buf[s++*interleave] = output(); } clock(delta_t); sample_offset -= delta_t << FIXP_SHIFT; delta_t = 0; return s; } // ---------------------------------------------------------------------------- // SID clocking with audio sampling - cycle based with linear sample // interpolation. // // Here the chip is clocked every cycle. This yields higher quality // sound since the samples are linearly interpolated, and since the // external filter attenuates frequencies above 16kHz, thus reducing // sampling noise. // ---------------------------------------------------------------------------- RESID_INLINE int SID::clock_interpolate(cycle_count& delta_t, short* buf, int n, int interleave) { int s = 0; int i; for (;;) { cycle_count next_sample_offset = sample_offset + cycles_per_sample; cycle_count delta_t_sample = next_sample_offset >> FIXP_SHIFT; if (delta_t_sample > delta_t) { break; } if (s >= n) { return s; } for (i = 0; i < delta_t_sample - 1; i++) { clock(); } if (i < delta_t_sample) { sample_prev = output(); clock(); } delta_t -= delta_t_sample; sample_offset = next_sample_offset & FIXP_MASK; short sample_now = output(); buf[s++*interleave] = sample_prev + (sample_offset*(sample_now - sample_prev) >> FIXP_SHIFT); sample_prev = sample_now; } for (i = 0; i < delta_t - 1; i++) { clock(); } if (i < delta_t) { sample_prev = output(); clock(); } sample_offset -= delta_t << FIXP_SHIFT; delta_t = 0; return s; } // ---------------------------------------------------------------------------- // SID clocking with audio sampling - cycle based with audio resampling. // // This is the theoretically correct (and computationally intensive) audio // sample generation. The samples are generated by resampling to the specified // sampling frequency. The work rate is inversely proportional to the // percentage of the bandwidth allocated to the filter transition band. // // This implementation is based on the paper "A Flexible Sampling-Rate // Conversion Method", by J. O. Smith and P. Gosset, or rather on the // expanded tutorial on the "Digital Audio Resampling Home Page": // http://www-ccrma.stanford.edu/~jos/resample/ // // By building shifted FIR tables with samples according to the // sampling frequency, this implementation dramatically reduces the // computational effort in the filter convolutions, without any loss // of accuracy. The filter convolutions are also vectorizable on // current hardware. // // Further possible optimizations are: // * An equiripple filter design could yield a lower filter order, see // http://www.mwrf.com/Articles/ArticleID/7229/7229.html // * The Convolution Theorem could be used to bring the complexity of // convolution down from O(n*n) to O(n*log(n)) using the Fast Fourier // Transform, see http://en.wikipedia.org/wiki/Convolution_theorem // * Simply resampling in two steps can also yield computational // savings, since the transition band will be wider in the first step // and the required filter order is thus lower in this step. // Laurent Ganier has found the optimal intermediate sampling frequency // to be (via derivation of sum of two steps): // 2 * pass_freq + sqrt [ 2 * pass_freq * orig_sample_freq // * (dest_sample_freq - 2 * pass_freq) / dest_sample_freq ] // // NB! the result of right shifting negative numbers is really // implementation dependent in the C++ standard. // ---------------------------------------------------------------------------- RESID_INLINE int SID::clock_resample_interpolate(cycle_count& delta_t, short* buf, int n, int interleave) { int s = 0; for (;;) { cycle_count next_sample_offset = sample_offset + cycles_per_sample; cycle_count delta_t_sample = next_sample_offset >> FIXP_SHIFT; if (delta_t_sample > delta_t) { break; } if (s >= n) { return s; } for (int i = 0; i < delta_t_sample; i++) { clock(); sample[sample_index] = sample[sample_index + RINGSIZE] = output(); ++sample_index; sample_index &= 0x3fff; } delta_t -= delta_t_sample; sample_offset = next_sample_offset & FIXP_MASK; int fir_offset = sample_offset*fir_RES >> FIXP_SHIFT; int fir_offset_rmd = sample_offset*fir_RES & FIXP_MASK; short* fir_start = fir + fir_offset*fir_N; short* sample_start = sample + sample_index - fir_N + RINGSIZE; // Convolution with filter impulse response. int v1 = 0; for (int j = 0; j < fir_N; j++) { v1 += sample_start[j]*fir_start[j]; } // Use next FIR table, wrap around to first FIR table using // previous sample. if (++fir_offset == fir_RES) { fir_offset = 0; --sample_start; } fir_start = fir + fir_offset*fir_N; // Convolution with filter impulse response. int v2 = 0; for (int j = 0; j < fir_N; j++) { v2 += sample_start[j]*fir_start[j]; } // Linear interpolation. // fir_offset_rmd is equal for all samples, it can thus be factorized out: // sum(v1 + rmd*(v2 - v1)) = sum(v1) + rmd*(sum(v2) - sum(v1)) int v = v1 + (fir_offset_rmd*(v2 - v1) >> FIXP_SHIFT); v >>= FIR_SHIFT; // Saturated arithmetics to guard against 16 bit sample overflow. const int half = 1 << 15; if (v >= half) { v = half - 1; } else if (v < -half) { v = -half; } buf[s++*interleave] = v; } for (int i = 0; i < delta_t; i++) { clock(); sample[sample_index] = sample[sample_index + RINGSIZE] = output(); ++sample_index; sample_index &= 0x3fff; } sample_offset -= delta_t << FIXP_SHIFT; delta_t = 0; return s; } // ---------------------------------------------------------------------------- // SID clocking with audio sampling - cycle based with audio resampling. // ---------------------------------------------------------------------------- RESID_INLINE int SID::clock_resample_fast(cycle_count& delta_t, short* buf, int n, int interleave) { int s = 0; for (;;) { cycle_count next_sample_offset = sample_offset + cycles_per_sample; cycle_count delta_t_sample = next_sample_offset >> FIXP_SHIFT; if (delta_t_sample > delta_t) { break; } if (s >= n) { return s; } for (int i = 0; i < delta_t_sample; i++) { clock(); sample[sample_index] = sample[sample_index + RINGSIZE] = output(); ++sample_index; sample_index &= 0x3fff; } delta_t -= delta_t_sample; sample_offset = next_sample_offset & FIXP_MASK; int fir_offset = sample_offset*fir_RES >> FIXP_SHIFT; short* fir_start = fir + fir_offset*fir_N; short* sample_start = sample + sample_index - fir_N + RINGSIZE; // Convolution with filter impulse response. int v = 0; for (int j = 0; j < fir_N; j++) { v += sample_start[j]*fir_start[j]; } v >>= FIR_SHIFT; // Saturated arithmetics to guard against 16 bit sample overflow. const int half = 1 << 15; if (v >= half) { v = half - 1; } else if (v < -half) { v = -half; } buf[s++*interleave] = v; } for (int i = 0; i < delta_t; i++) { clock(); sample[sample_index] = sample[sample_index + RINGSIZE] = output(); ++sample_index; sample_index &= 0x3fff; } sample_offset -= delta_t << FIXP_SHIFT; delta_t = 0; return s; } goattracker-2.72/src/gfile.c0000644000000000000000000003144611460122606014477 0ustar rootroot// // GOATTRACKER v2 file selector // #define GFILE_C #ifdef __WIN32__ #include #endif #include "goattrk2.h" DIRENTRY direntry[MAX_DIRFILES]; void initpaths(void) { int c; for (c = 0; c < MAX_DIRFILES; c++) direntry[c].name = NULL; memset(loadedsongfilename, 0, sizeof loadedsongfilename); memset(songfilename, 0, sizeof songfilename); memset(instrfilename, 0, sizeof instrfilename); memset(songpath, 0, sizeof songpath); memset(instrpath, 0, sizeof instrpath); memset(packedpath, 0, sizeof packedpath); strcpy(songfilter, "*.sng"); strcpy(instrfilter, "*.ins"); getcwd(songpath, MAX_PATHNAME); strcpy(instrpath, songpath); strcpy(packedpath, songpath); } int fileselector(char *name, char *path, char *filter, char *title, int filemode) { int c, d, scrrep; int color; int files; int filepos = 0; int fileview = 0; int lastclick = 0; int lastfile = 0; int lowest; int exitfilesel; DIR *dir; struct dirent *de; struct stat st; #ifdef __WIN32__ char drivestr[] = "A:\\"; char driveexists[26]; #endif char cmpbuf[MAX_PATHNAME]; char tempname[MAX_PATHNAME]; // Set initial path (if any) if (strlen(path)) chdir(path); // Scan for all existing drives #ifdef __WIN32__ for (c = 0; c < 26; c++) { drivestr[0] = 'A'+c; if (GetDriveType(drivestr) > 1) driveexists[c] = 1; else driveexists[c] = 0; } #endif // Read new directory NEWPATH: getcwd(path, MAX_PATHNAME); files = 0; // Deallocate old names for (c = 0; c < MAX_DIRFILES; c++) { if (direntry[c].name) { free(direntry[c].name); direntry[c].name = NULL; } } #ifdef __WIN32__ // Create drive letters for (c = 0; c < 26; c++) { if (driveexists[c]) { drivestr[0] = 'A'+c; direntry[files].name = strdup(drivestr); direntry[files].attribute = 2; files++; } } #endif // Process directory #ifdef __amigaos__ dir = opendir(""); #else dir = opendir("."); #endif if (dir) { char *filtptr = strstr(filter, "*"); if (!filtptr) filtptr = filter; else filtptr++; for (c = 0; c < strlen(filter); c++) filter[c] = tolower(filter[c]); while ((de = readdir(dir))) { if ((files < MAX_DIRFILES) && (strlen(de->d_name) < MAX_FILENAME)) { direntry[files].name = strdup(de->d_name); direntry[files].attribute = 0; stat(de->d_name, &st); if (st.st_mode & S_IFDIR) { direntry[files].attribute = 1; files++; } else { int c; // If a file, must match filter strcpy(cmpbuf, de->d_name); if ((!strcmp(filtptr, "*")) || (!strcmp(filtptr, ".*"))) files++; else { for (c = 0; c < strlen(cmpbuf); c++) cmpbuf[c] = tolower(cmpbuf[c]); if (strstr(cmpbuf, filtptr)) files++; else { free(direntry[files].name); direntry[files].name = NULL; } } } } } closedir(dir); } // Sort the filelist in a most horrible fashion for (c = 0; c < files; c++) { lowest = c; for (d = c+1; d < files; d++) { if (direntry[d].attribute < direntry[lowest].attribute) { lowest = d; } else { if (direntry[d].attribute == direntry[lowest].attribute) { if (cmpname(direntry[d].name, direntry[lowest].name) < 0) { lowest = d; } } } } if (lowest != c) { DIRENTRY swaptemp = direntry[c]; direntry[c] = direntry[lowest]; direntry[lowest] = swaptemp; } } // Search for the current filename fileview = 0; filepos = 0; for (c = 0; c < files; c++) { if ((!direntry[c].attribute) && (!cmpname(name, direntry[c].name))) { filepos = c; } } exitfilesel = -1; while (exitfilesel < 0) { int cc = cursorcolortable[cursorflash]; if (cursorflashdelay >= 6) { cursorflashdelay %= 6; cursorflash++; cursorflash &= 3; } fliptoscreen(); getkey(); if (lastclick) lastclick--; if (win_quitted) { exitprogram = 1; for (c = 0; c < MAX_DIRFILES; c++) { if (direntry[c].name) { free(direntry[c].name); direntry[c].name = NULL; } } return 0; } if (mouseb) { // Cancel (click outside) if ((mousey < 3) || (mousey > 3+VISIBLEFILES+6) || (mousex <= 4+10) || (mousex >= 75+10)) { if ((!prevmouseb) && (lastclick)) exitfilesel = 0; } // Select dir,name,filter if ((mousey >= 3+VISIBLEFILES+3) && (mousey <= 3+VISIBLEFILES+5) && (mousex >= 14+10) && (mousex <= 73+10)) { filemode = mousey - (3+VISIBLEFILES+3) + 1; if ((filemode == 3) && (!prevmouseb) && (lastclick)) goto ENTERFILE; } // Select file from list if ((mousey >= 3) && (mousey <= 3+VISIBLEFILES+2) && (mousex >= 6+10) && (mousex <= 73+10)) { filemode = 0; filepos = mousey - 4 - 1 + fileview; if (filepos < 0) filepos = 0; if (filepos > files-1) filepos = files - 1; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); if ((!prevmouseb) && (lastclick) && (lastfile == filepos)) goto ENTERFILE; } } if (!filemode) { if (((key >= '0') && (key <= '0')) || ((key >= 'a') && (key <= 'z')) || ((key >= 'A') && (key <= 'Z'))) { char k = tolower(key); int oldfilepos = filepos; for (filepos = oldfilepos + 1; filepos < files; filepos++) if (tolower(direntry[filepos].name[0]) == k) break; if (filepos >= files) { for (filepos = 0; filepos < oldfilepos; filepos++) if (tolower(direntry[filepos].name[0]) == k) break; } if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } } switch(rawkey) { case KEY_ESC: exitfilesel = 0; break; case KEY_BACKSPACE: if (!filemode) { #ifdef __amigaos__ chdir("/"); #else chdir(".."); #endif goto NEWPATH; } break; case KEY_HOME: if (!filemode) { filepos = 0; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } break; case KEY_END: if (!filemode) { filepos = files-1; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } break; case KEY_PGUP: for (scrrep = PGUPDNREPEAT; scrrep; scrrep--) { if ((!filemode) && (filepos > 0)) { filepos--; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } } break; case KEY_UP: if ((!filemode) && (filepos > 0)) { filepos--; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } break; case KEY_PGDN: for (scrrep = PGUPDNREPEAT; scrrep; scrrep--) { if ((!filemode) && (filepos < files-1)) { filepos++; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } } break; case KEY_DOWN: if ((!filemode) && (filepos < files-1)) { filepos++; if (!direntry[filepos].attribute) strcpy(name, direntry[filepos].name); } break; case KEY_TAB: if (!shiftpressed) { filemode++; if (filemode > 3) filemode = 0; } else { filemode--; if (filemode < 0) filemode = 3; } break; case KEY_ENTER: ENTERFILE: switch(filemode) { case 0: switch (direntry[filepos].attribute) { case 0: strcpy(name, direntry[filepos].name); exitfilesel = 1; break; case 1: chdir(direntry[filepos].name); goto NEWPATH; case 2: strcpy(tempname, direntry[filepos].name); if (strlen(tempname)) { if (tempname[strlen(tempname)-1] != '\\') strcat(tempname, "\\"); } chdir(tempname); goto NEWPATH; } break; case 1: chdir(path); case 2: filemode = 0; goto NEWPATH; case 3: exitfilesel = 1; break; } break; } switch(filemode) { case 1: editstring(path, MAX_PATHNAME); break; case 2: editstring(filter, MAX_FILENAME); break; case 3: editstring(name, MAX_FILENAME); break; } // Validate filelist view if (filepos < fileview) fileview = filepos; if (filepos - fileview >= VISIBLEFILES) fileview = filepos - VISIBLEFILES + 1; // Refresh fileselector display if (isplaying()) printstatus(); for (c = 0; c < VISIBLEFILES+7; c++) { printblank(50-(MAX_FILENAME+10)/2, 3+c, MAX_FILENAME+10); } drawbox(50-(MAX_FILENAME+10)/2, 3, 15, MAX_FILENAME+10, VISIBLEFILES+7); printblankc(50-(MAX_FILENAME+10)/2+1, 4, 15+16,MAX_FILENAME+8); printtext(50-(MAX_FILENAME+10)/2+1, 4, 15+16, title); for (c = 0; c < VISIBLEFILES; c++) { if ((fileview+c >= 0) && (fileview+c < files)) { switch (direntry[fileview+c].attribute) { case 0: sprintf(textbuffer, "%-60s ", direntry[fileview+c].name); break; case 1: sprintf(textbuffer, "%-60s ", direntry[fileview+c].name); break; case 2: sprintf(textbuffer, "%-60s ", direntry[fileview+c].name); break; } } else { sprintf(textbuffer, " "); } color = CNORMAL; if ((fileview+c) == filepos) color = CEDIT; textbuffer[68] = 0; printtext(50-(MAX_FILENAME+10)/2+1, 5+c, color, textbuffer); if ((!filemode) && ((fileview+c) == filepos)) printbg(50-(MAX_FILENAME+10)/2+1, 5+c, cc, 68); } printtext(50-(MAX_FILENAME+10)/2+1, 6+VISIBLEFILES, 15, "PATH: "); sprintf(textbuffer, "%-60s", path); textbuffer[MAX_FILENAME] = 0; color = CNORMAL; if (filemode == 1) color = CEDIT; printtext(50-(MAX_FILENAME+10)/2+9, 6+VISIBLEFILES, color, textbuffer); if ((filemode == 1) && (strlen(path) < MAX_FILENAME)) printbg(50-(MAX_FILENAME+10)/2+9+strlen(path), 6+VISIBLEFILES, cc, 1); printtext(50-(MAX_FILENAME+10)/2+1, 7+VISIBLEFILES, 15, "FILTER: "); sprintf(textbuffer, "%-60s", filter); textbuffer[MAX_FILENAME] = 0; color = CNORMAL; if (filemode == 2) color = CEDIT; printtext(50-(MAX_FILENAME+10)/2+9, 7+VISIBLEFILES, color, textbuffer); if (filemode == 2) printbg(50-(MAX_FILENAME+10)/2+9+strlen(filter), 7+VISIBLEFILES, cc, 1); printtext(50-(MAX_FILENAME+10)/2+1, 8+VISIBLEFILES, 15, "NAME: "); sprintf(textbuffer, "%-60s", name); textbuffer[MAX_FILENAME] = 0; color = CNORMAL; if (filemode == 3) color = CEDIT; printtext(50-(MAX_FILENAME+10)/2+9, 8+VISIBLEFILES, color, textbuffer); if (filemode == 3) printbg(50-(MAX_FILENAME+10)/2+9+strlen(name), 8+VISIBLEFILES, cc, 1); if (win_quitted) exitfilesel = 0; if ((mouseb) && (!prevmouseb)) { lastclick = DOUBLECLICKDELAY; lastfile = filepos; } } // Deallocate all used names for (c = 0; c < MAX_DIRFILES; c++) { if (direntry[c].name) { free(direntry[c].name); direntry[c].name = NULL; } } // Restore screen & exit printmainscreen(); return exitfilesel; } void editstring(char *buffer, int maxlength) { int len = strlen(buffer); if (key) { if ((key >= 32) && (key < 256)) { if (len < maxlength-1) { buffer[len] = key; buffer[len+1] = 0; } } if ((key == 8) && (len > 0)) { buffer[len-1] = 0; } } } int cmpname(char *string1, char *string2) { for (;;) { unsigned char char1 = tolower(*string1++); unsigned char char2 = tolower(*string2++); if (char1 < char2) return -1; if (char1 > char2) return 1; if ((!char1) || (!char2)) return 0; } } goattracker-2.72/src/player.s0000644000000000000000000015147211355652152014736 0ustar rootroot;------------------------------------------------------------------------------- ; GoatTracker V2.68 playroutine ; ; NOTE: This playroutine source code does not fall under the GPL license! ; Use it, or song binaries created from it freely for any purpose, commercial ; or noncommercial. ; ; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer. ; Does not directly compile on DASM etc. ;------------------------------------------------------------------------------- ;Defines will be inserted by the relocator here .IF (ZPGHOSTREGS == 0) mt_temp1 = zpbase+0 mt_temp2 = zpbase+1 .ELSE ghostfreqlo = zpbase+0 ghostfreqhi = zpbase+1 ghostpulselo = zpbase+2 ghostpulsehi = zpbase+3 ghostwave = zpbase+4 ghostad = zpbase+5 ghostsr = zpbase+6 ghostfiltcutlow = zpbase+21 ghostfiltcutoff = zpbase+22 ghostfiltctrl = zpbase+23 ghostfilttype = zpbase+24 mt_temp1 = zpbase+25 mt_temp2 = zpbase+26 .ENDIF ;Defines for the music data ;Patterndata notes ENDPATT = $00 INS = $00 FX = $40 FXONLY = $50 NOTE = $60 REST = $bd KEYOFF = $be KEYON = $bf FIRSTPACKEDREST = $c0 PACKEDREST = $00 ;Effects DONOTHING = $00 PORTAUP = $01 PORTADOWN = $02 TONEPORTA = $03 VIBRATO = $04 SETAD = $05 SETSR = $06 SETWAVE = $07 SETWAVEPTR = $08 SETPULSEPTR = $09 SETFILTPTR = $0a SETFILTCTRL = $0b SETFILTCUTOFF = $0c SETMASTERVOL = $0d SETFUNKTEMPO = $0e SETTEMPO = $0f ;Orderlist commands REPEAT = $d0 TRANSDOWN = $e0 TRANS = $f0 TRANSUP = $f0 LOOPSONG = $ff ;Wave,pulse,filttable comands LOOPWAVE = $ff LOOPPULSE = $ff LOOPFILT = $ff SETPULSE = $80 SETFILTER = $80 SETCUTOFF = $00 .ORG (base) ;Jump table jmp mt_init jmp mt_play .IF (SOUNDSUPPORT != 0) jmp mt_playsfx .ENDIF .IF (VOLSUPPORT != 0) jmp mt_setmastervol .ENDIF ;Author info .IF (NOAUTHORINFO == 0) authorinfopos = base + $20 checkpos1: .IF ((authorinfopos - checkpos1) > 15) mt_tick0jumptbl: .BYTE (mt_tick0_0 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_5 % 256) .BYTE (mt_tick0_6 % 256) .BYTE (mt_tick0_7 % 256) .BYTE (mt_tick0_8 % 256) .BYTE (mt_tick0_9 % 256) .BYTE (mt_tick0_a % 256) .BYTE (mt_tick0_b % 256) .BYTE (mt_tick0_c % 256) .BYTE (mt_tick0_d % 256) .BYTE (mt_tick0_e % 256) .BYTE (mt_tick0_f % 256) .ENDIF checkpos2: .IF ((authorinfopos - checkpos2) > 4) mt_effectjumptbl: .BYTE (mt_effect_0 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_3 % 256) .BYTE (mt_effect_4 % 256) .ENDIF checkpos3: .IF ((authorinfopos - checkpos3) > 1) mt_funktempotbl: .BYTE (8,5) .ENDIF ;This is pretty stupid way of filling left-out space, but .ORG ;seemed to bug checkpos4: .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF checkpos5: .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF checkpos6: .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF mt_author: .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .ENDIF ;0 Instrument vibrato mt_tick0_0: .IF (NOEFFECTS == 0) .IF (NOINSTRVIB == 0) lda mt_insvibparam-1,y jmp mt_tick0_34 .ELSE .IF (NOVIB == 0) jmp mt_tick0_34 .ENDIF .ENDIF .ENDIF ;1,2 Portamentos mt_tick0_12: .IF (NOVIB == 0) tay lda #$00 sta mt_chnvibtime,x tya .ENDIF ;3,4 Toneportamento, Vibrato mt_tick0_34: .IF (NOEFFECTS == 0) .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) sta mt_chnparam,x lda mt_chnnewfx,x sta mt_chnfx,x .ENDIF rts .ENDIF ;5 Set AD mt_tick0_5: .IF (NOSETAD == 0) .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 1) sta mt_chntempo+7 .ENDIF .IF (NUMCHANNELS > 2) sta mt_chntempo+14 .ENDIF rts .ENDIF mt_tick0_f_setchantempo: .IF (NOCHANNELTEMPO == 0) and #$7f sta mt_chntempo,x rts .ENDIF ;Continuous effect code ;0 Instrument vibrato .IF (NOINSTRVIB == 0) mt_effect_0_delay: dec mt_chnvibdelay,x mt_effect_0_donothing: jmp mt_done mt_effect_0: beq mt_effect_0_donothing ;Speed 0 = no vibrato at all lda mt_chnvibdelay,x bne mt_effect_0_delay .ELSE mt_effect_0: mt_effect_0_donothing: jmp mt_done .ENDIF ;4 Vibrato mt_effect_4: .IF (NOVIB == 0) .IF (NOCALCULATEDSPEED == 0) lda mt_speedlefttbl-1,y .IF (NONORMALSPEED == 0) bmi mt_effect_4_nohibyteclear ldy #$00 ;Clear speed highbyte sty 1) sta mt_init+5 asl adc #$00 .ENDIF sta mt_initsongnum+1 rts ;Play soundeffect -routine .IF (SOUNDSUPPORT != 0) ;Sound FX init routine mt_playsfx: sta mt_playsfxlo+1 sty mt_playsfxhi+1 lda mt_chnsfx,x ;Need a priority check? beq mt_playsfxok tya ;Check address highbyte cmp mt_chnsfxhi,x bcc mt_playsfxskip ;Lower than current -> skip bne mt_playsfxok ;Higher than current -> OK lda mt_playsfxlo+1 ;Check address lowbyte cmp mt_chnsfxlo,x bcc mt_playsfxskip ;Lower than current -> skip mt_playsfxok: lda #$01 sta mt_chnsfx,x mt_playsfxlo: lda #$00 sta mt_chnsfxlo,x mt_playsfxhi: lda #$00 sta mt_chnsfxhi,x mt_playsfxskip: rts .ENDIF ;Set mastervolume -routine .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0)) mt_setmastervol: sta mt_masterfader+1 rts .ENDIF ;Playroutine mt_play: ldx #$00 ;Channel index ;Song initialization mt_initsongnum: ldy #$00 bmi mt_filtstep txa ldx #NUMCHANNELS * 14 - 1 mt_resetloop: sta mt_chnsongptr,x ;Reset sequencer + voice dex ;variables on all channels bpl mt_resetloop .IF (ZPGHOSTREGS == 0) .IF (NUMCHANNELS == 2) sta SIDBASE+$12 .ENDIF .IF (NUMCHANNELS == 1) sta SIDBASE+$0b sta SIDBASE+$12 .ENDIF sta SIDBASE+$15 ;Reset filter cutoff lowbyte .ELSE sta 1) tya iny sta mt_chnsongnum,x ;Store index to songtable .ENDIF mt_defaulttempo: lda #DEFAULTTEMPO ;Set default tempo sta mt_chntempo,x lda #$01 sta mt_chncounter,x ;Reset counter sta mt_chninstr,x ;Reset instrument jmp mt_loadregswaveonly ;Load waveform ;Filter execution mt_filtstep: .IF (NOFILTER == 0) ldy #$00 ;See if filter stopped beq mt_filtdone .IF (NOFILTERMOD == 0) mt_filttime: lda #$00 ;See if time left for mod. bne mt_filtmod ;step .ENDIF mt_newfiltstep: lda mt_filttimetbl-1,y ;$80-> = set filt parameters beq mt_setcutoff ;$00 = set cutoff .IF (NOFILTERMOD == 0) bpl mt_newfiltmod .ENDIF mt_setfilt: asl ;Set passband sta mt_filttype+1 lda mt_filtspdtbl-1,y ;Set resonance/channel sta mt_filtctrl+1 lda mt_filttimetbl,y ;Check for cutoff setting bne mt_nextfiltstep2 ;following immediately mt_setcutoff2: iny mt_setcutoff: lda mt_filtspdtbl-1,y ;Take cutoff value sta mt_filtcutoff+1 .IF (NOFILTERMOD == 0) jmp mt_nextfiltstep mt_newfiltmod: sta mt_filttime+1 ;$01-$7f = new modulation step mt_filtmod: lda mt_filtspdtbl-1,y ;Take filt speed clc adc mt_filtcutoff+1 sta mt_filtcutoff+1 dec mt_filttime+1 bne mt_storecutoff .ENDIF mt_nextfiltstep: lda mt_filttimetbl,y ;Jump in filttable? mt_nextfiltstep2: cmp #LOOPFILT iny tya bcc mt_nofiltjump lda mt_filtspdtbl-1,y ;Take jump point mt_nofiltjump: sta mt_filtstep+1 mt_filtdone: mt_filtcutoff: lda #$00 mt_storecutoff: .IF (ZPGHOSTREGS == 0) sta SIDBASE+$16 .ELSE sta 0) || (NOFIRSTWAVECMD == 0)) lda #$ff mt_skipwave2: sta mt_chngate,x ;Reset gateflag .ELSE inc mt_chngate,x .ENDIF mt_skipwave: .IF (NOPULSE == 0) lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) beq mt_skippulse sta mt_chnpulseptr,x .IF (NOPULSEMOD == 0) lda #$00 ;Reset pulse step duration sta mt_chnpulsetime,x .ENDIF .ENDIF mt_skippulse: .IF (NOFILTER == 0) lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) beq mt_skipfilt sta mt_filtstep+1 .IF (NOFILTERMOD == 0) lda #$00 sta mt_filttime+1 .ENDIF .ENDIF mt_skipfilt: lda mt_inswaveptr-1,y ;Load waveptr sta mt_chnwaveptr,x lda mt_inssr-1,y ;Load Sustain/Release .IF (BUFFEREDWRITES == 0) sta SIDBASE+$06,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnsr,x .ELSE sta 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) lda mt_chninstr,x cmp #FIRSTNOHRINSTR ;Instrument order: .IF (NUMLEGATOINSTR > 0) bcs mt_nohr_legato ;With HR - no HR - legato .ELSE bcs mt_skiphr .ENDIF .ENDIF .IF (NUMHRINSTR > 0) lda #SRPARAM ;Hard restart .IF (BUFFEREDWRITES == 0) sta SIDBASE+$06,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnsr,x .ELSE sta 0) mt_nohr_legato: cmp #FIRSTLEGATOINSTR bcc mt_skiphr bcs mt_rest .ENDIF ;Sound FX code .IF (SOUNDSUPPORT != 0) .IF (ZPGHOSTREGS == 0) ;Sound FX code without ghostregs mt_sfxexec: lda mt_chnsfxlo,x sta 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnfx: .BYTE (0) mt_chnparam: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) mt_chnpulsetime: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .IF ((ZPGHOSTREGS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF ((BUFFEREDWRITES != 0) || (FIXEDPARAMS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnad: .BYTE (0) mt_chnsr: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) mt_chnlastnote: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE ;Optimized channel variables mt_chnsongptr: .BYTE (0) mt_chnpattptr: .BYTE (0) mt_chnpackedrest: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnpulsetime: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .ENDIF ;Songdata & frequencytable will be inserted by the relocator here goattracker-2.72/src/ins2snd2.c0000644000000000000000000001543610774364076015074 0ustar rootroot/* * GoatTracker V2.0 Instrument -> Sound effect convertor */ #include #include #include #include #include "bme_end.h" #include "gcommon.h" int main(int argc, char **argv); unsigned char swapnybbles(unsigned char n); void outputbyte(unsigned char c); int covert = 0; int binary = 0; int bytecount = 0; FILE *handle; FILE *out; int main(int argc, char **argv) { int c,d; int prevwave = 0xff; int currwave = 0; int fileok = 0; INSTR instr; int wavelen,pulselen,filtlen; unsigned char ident[4] = {0}; unsigned char wavetable[MAX_TABLELEN*2]; unsigned char pulsetable[MAX_TABLELEN*2]; unsigned char filttable[MAX_TABLELEN*2]; unsigned char pulse = 0; if (argc < 3) { printf("Usage: INS2SND2 \n" "-b Produce binary output\n" "-c Produce output in CovertScript format (deprecated)\n\n" "Takes a GoatTracker V1.xx or V2 instrument and outputs the corresponding sound\n" "effect data as source code (default) or binary. Things that can't be converted\n" "and will result in an error:\n" "- Waveforms greater than $81\n" "- Relative notes\n" "- Wavetable longer than 128 bytes\n" "- Absolute notes C-0 & C#0\n" "Things that will be lost in conversion:\n" "- Wavetable loops\n" "- Pulsewidth modulation\n" "- Filter settings\n"); return 1; } if (argc > 3) { for (c = 3; c < argc; c++) { if (((argv[c][0] == '-') || (argv[c][0] == '/')) && (strlen(argv[c]) > 1)) { int ch = tolower(argv[c][1]); switch(ch) { case 'b': binary = 1; break; case 'c': covert = 1; break; } } } } handle = fopen(argv[1], "rb"); if (!handle) { printf("ERROR: Can't open instrumentfile\n"); return 1; } memset(wavetable, 0, MAX_TABLELEN*2); memset(pulsetable, 0, MAX_TABLELEN*2); memset(filttable, 0, MAX_TABLELEN*2); fread(ident, 4, 1, handle); if (!memcmp(ident, "GTI!", 4)) { fileok = 1; instr.ad = fread8(handle); instr.sr = fread8(handle); pulse = fread8(handle) & 0xfe; fread8(handle); // Throw away pulse speed fread8(handle); // Throw away pulse limit low fread8(handle); // Throw away pulse limit high fread8(handle); // Throw away filtersetting wavelen = fread8(handle); fread(&instr.name, MAX_INSTRNAMELEN, 1, handle); fread(wavetable, wavelen, 1, handle); } if (!memcmp(ident, "GTI2", 4)) { fileok = 1; instr.ad = fread8(handle); instr.sr = fread8(handle); instr.ptr[0] = fread8(handle); instr.ptr[1] = fread8(handle); instr.ptr[2] = fread8(handle); instr.vibdelay = fread8(handle); instr.ptr[3] = fread8(handle); instr.gatetimer = fread8(handle); instr.firstwave = fread8(handle); fread(&instr.name, MAX_INSTRNAMELEN, 1, handle); wavelen = fread8(handle); for (c = 0; c < wavelen; c++) wavetable[c*2] = fread8(handle); for (c = 0; c < wavelen; c++) wavetable[c*2+1] = fread8(handle); pulselen = fread8(handle); for (c = 0; c < pulselen; c++) pulsetable[c*2] = fread8(handle); for (c = 0; c < pulselen; c++) pulsetable[c*2+1] = fread8(handle); filtlen = fread8(handle); for (c = 0; c < filtlen; c++) filttable[c*2] = fread8(handle); for (c = 0; c < filtlen; c++) filttable[c*2+1] = fread8(handle); pulse = (pulsetable[0] << 4) | (pulsetable[1] >> 4); } if ((!memcmp(ident, "GTI3", 4)) || (!memcmp(ident, "GTI4", 4) || (!memcmp(ident, "GTI5", 4)))) { fileok = 1; instr.ad = fread8(handle); instr.sr = fread8(handle); instr.ptr[0] = fread8(handle); instr.ptr[1] = fread8(handle); instr.ptr[2] = fread8(handle); instr.ptr[3] = fread8(handle); instr.vibdelay = fread8(handle); instr.gatetimer = fread8(handle); instr.firstwave = fread8(handle); fread(&instr.name, MAX_INSTRNAMELEN, 1, handle); wavelen = fread8(handle); for (c = 0; c < wavelen; c++) wavetable[c*2] = fread8(handle); for (c = 0; c < wavelen; c++) wavetable[c*2+1] = fread8(handle); pulselen = fread8(handle); for (c = 0; c < pulselen; c++) pulsetable[c*2] = fread8(handle); for (c = 0; c < pulselen; c++) pulsetable[c*2+1] = fread8(handle); filtlen = fread8(handle); for (c = 0; c < filtlen; c++) filttable[c*2] = fread8(handle); for (c = 0; c < filtlen; c++) filttable[c*2+1] = fread8(handle); pulse = (pulsetable[0] << 4) | (pulsetable[1] >> 4); } fclose(handle); if (!fileok) { printf("ERROR: File is not a GoatTracker instrument!\n"); return 1; } if (!binary) out = fopen(argv[2], "wt"); else out = fopen(argv[2], "wb"); if (!out) { printf("ERROR: Can't write to output file.\n"); return 1; } d = 0; outputbyte(instr.ad); d++; outputbyte(instr.sr); d++; outputbyte(swapnybbles(pulse)); d++; for (c = 0; c < MAX_TABLELEN; c++) { if (wavetable[c*2] == 0xff) { outputbyte(0); d++; break; } if (wavetable[c*2+1] < 0x82) { printf("ERROR: Relative note or absolute C-0, C#0 found\n"); fclose(out); return 1; } if (wavetable[c*2] > 0x81) { printf("ERROR: Waveform greater than $81 found\n"); fclose(out); return 1; } if (wavetable[c*2]) { currwave = wavetable[c*2]; } outputbyte(wavetable[c*2+1]); d++; if (currwave != prevwave) { outputbyte(currwave); prevwave = currwave; d++; } } if (d > 255) { fclose(out); printf("ERROR: Sound effect exceeds 255 bytes\n"); return 1; } fclose(out); return 0; } void outputbyte(unsigned char c) { if (binary) fwrite8(out, c); else { if (!covert) { if (!bytecount) { fprintf(out, " dc.b "); } else fprintf(out, ","); fprintf(out, "$%02X", c); bytecount++; if (bytecount == 16) { bytecount = 0; fprintf(out, "\n"); } } else { if (bytecount) { fprintf(out,","); } if (bytecount == 16) { fprintf(out,"\n"); bytecount = 0; } bytecount++; fprintf(out, "0x%02x", c); } } } unsigned char swapnybbles(unsigned char n) { unsigned char highnybble = n >> 4; unsigned char lownybble = n & 0xf; return (lownybble << 4) | highnybble; } goattracker-2.72/src/ginstr.c0000644000000000000000000001134711460110112014702 0ustar rootroot// // GOATTRACKER v2 instrument editor // #define GINSTR_C #include "goattrk2.h" INSTR instrcopybuffer; int cutinstr = -1; int einum; int eipos; int eicolumn; void instrumentcommands(void) { switch(rawkey) { case 0x8: case KEY_DEL: if ((einum) && (shiftpressed) && (eipos < 9)) { deleteinstrtable(einum); clearinstr(einum); } break; case KEY_X: if ((einum) && (shiftpressed) && (eipos < 9)) { cutinstr = einum; memcpy(&instrcopybuffer, &instr[einum], sizeof(INSTR)); clearinstr(einum); } break; case KEY_C: if ((einum) && (shiftpressed) && (eipos < 9)) { cutinstr = -1; memcpy(&instrcopybuffer, &instr[einum], sizeof(INSTR)); } break; case KEY_S: if ((einum) && (shiftpressed) && (eipos < 9)) { memcpy(&instr[einum], &instrcopybuffer, sizeof(INSTR)); if (cutinstr != -1) { int c, d; for (c = 0; c < MAX_PATT; c++) { for (d = 0; d < pattlen[c]; d++) if (pattern[c][d*4+1] == cutinstr) pattern[c][d*4+1] = einum; } } } break; case KEY_V: if ((einum) && (shiftpressed) && (eipos < 9)) { memcpy(&instr[einum], &instrcopybuffer, sizeof(INSTR)); } break; case KEY_RIGHT: if (eipos < 9) { eicolumn++; if (eicolumn > 1) { eicolumn = 0; eipos += 5; if (eipos >= 9) eipos -= 10; if (eipos < 0) eipos = 8; } } break; case KEY_LEFT: if (eipos < 9) { eicolumn--; if (eicolumn < 0) { eicolumn = 1; eipos -= 5; if (eipos < 0) eipos += 10; if (eipos >= 9) eipos = 8; } } break; case KEY_DOWN: if (eipos < 9) { eipos++; if (eipos > 8) eipos = 0; } break; case KEY_UP: if (eipos < 9) { eipos--; if (eipos < 0) eipos = 8; } break; case KEY_N: if ((eipos != 9) && (shiftpressed)) { eipos = 9; return; } break; case KEY_U: if (shiftpressed) { etlock ^= 1; validatetableview(); } break; case KEY_SPACE: if (eipos != 9) { if (!shiftpressed) playtestnote(FIRSTNOTE + epoctave * 12, einum, epchn); else releasenote(epchn); } break; case KEY_ENTER: if (!einum) break; switch(eipos) { case 2: case 3: case 4: case 5: { int pos; if (instr[einum].ptr[eipos-2]) { if ((eipos == 5) && (shiftpressed)) { instr[einum].ptr[STBL] = makespeedtable(instr[einum].ptr[STBL], finevibrato, 1) + 1; break; } pos = instr[einum].ptr[eipos-2] - 1; } else { pos = gettablelen(eipos-2); if (pos >= MAX_TABLELEN-1) pos = MAX_TABLELEN - 1; if (shiftpressed) instr[einum].ptr[eipos-2] = pos + 1; } gototable(eipos-2, pos); } return; case 9: eipos = 0; break; } break; } if ((eipos == 9) && (einum)) editstring(instr[einum].name, MAX_INSTRNAMELEN); if ((hexnybble >= 0) && (eipos < 9) && (einum)) { unsigned char *ptr = &instr[einum].ad; ptr += eipos; switch(eicolumn) { case 0: *ptr &= 0x0f; *ptr |= hexnybble << 4; eicolumn++; break; case 1: *ptr &= 0xf0; *ptr |= hexnybble; eicolumn++; if (eicolumn > 1) { eicolumn = 0; eipos++; if (eipos >= 9) eipos = 0; } break; } } // Validate instrument parameters if (einum) { if (!(instr[einum].gatetimer & 0x3f)) instr[einum].gatetimer |= 1; } } void clearinstr(int num) { memset(&instr[num], 0, sizeof(INSTR)); if (num) { if (multiplier) instr[num].gatetimer = 2 * multiplier; else instr[num].gatetimer = 1; instr[num].firstwave = 0x9; } } void gotoinstr(int i) { if (i < 0) return; if (i >= MAX_INSTR) return; einum = i; showinstrtable(); editmode = EDIT_INSTRUMENT; } void nextinstr(void) { einum++; if (einum >= MAX_INSTR) einum = MAX_INSTR - 1; showinstrtable(); } void previnstr(void) { einum--; if (einum < 0) einum = 0; showinstrtable(); } void showinstrtable(void) { if (!etlock) { int c; for (c = MAX_TABLES-1; c >= 0; c--) { if (instr[einum].ptr[c]) settableviewfirst(c, instr[einum].ptr[c] - 1); } } } goattracker-2.72/src/cursor.lbm0000644000000000000000000000527410774364076015276 0ustar rootrootFORM PBM BMHD@@CMAP˫cc?[?Os#7O#o3;?K燇__;;## o[G'W'7k7KKccǧ'''KKKoooG_kDPPSnh@00CRNGCRNG /CRNG`oCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGCRNGTINY}P2BODY goattracker-2.72/src/gfile.h0000644000000000000000000000061210774364076014513 0ustar rootroot#ifndef GFILE_H #define GFILE_H #define MAX_DIRFILES 16384 #define MAX_FILENAME 60 #define MAX_PATHNAME 256 typedef struct { char *name; int attribute; } DIRENTRY; void initpaths(void); int fileselector(char *name, char *path, char *filter, char *title, int filemode); void editstring(char *buffer, int maxlength); int cmpname(char *string1, char *string2); #endif goattracker-2.72/src/ghelp.c0000644000000000000000000004332211460110062014475 0ustar rootroot// // GOATTRACKER v2 online help // #define GHELP_C #include "goattrk2.h" #define HELP_HEADER 15 #define HELP_NORMAL 7 int printrows(int column, int row, int color, char *strings[] ) { int n = 0; while(strings[n]) { printtext(column, row++, color, strings[n++]); } return row; } void onlinehelp(int standalone,int context) { char *genkeys[] = { "F1 Play from beginning", "F2 Play from current position", "F3 Play current pattern", "F4 Stop playing", "F5 Go to pattern editor", "F6 Go to orderlist editor", "F7 Go to instrument/table editor", "F8 Go to songname editor", "F9 Pack, relocate & save PRG,SID etc.", "F10 Load song/instrument", "F11 Save song/instrument", "F12 This screen", "SHIFT+F1-F3 Follow play begin/pos/patt.", "SHIFT+F4 Mute current channel", "SHIFT+F5-F6 Change speed multiplier", "SHIFT+F7 Change hardrestart ADSR", "SHIFT+F8 Switch between 6581/8580 SID", "SHIFT+, . Move song startpos & restart", "TAB Cycle between editing modes", "INS Insert row (Press on endmark to", "DEL Delete row change patt. length)", "SHIFT+ESC Clear/optimize all musicdata", "ESC Exit program", NULL }; char *patternkeys[] = { "Enter notes like on piano (PT or DMC)", "0-9 & A-F to enter commands", "SPC Switch between jam/editmode", "BACKSPC Insert rest", "RET Keyoff (/w SHIFT = Keyon)", "- + Select instrument", "/ * Select octave", "< > Select pattern", "BACKQUOTE Select channel", "SHIFT+SPC Play from cursor pos", "SHIFT+CRSR Mark pattern", "SHIFT+Q,W Transpose half/octave up", "SHIFT+A,S Transpose half/octave down", "SHIFT+E,R Copy,paste effects", "SHIFT+H Make hifi vib/portaspeed", "SHIFT+I Invert selection/pattern", "SHIFT+J,K Join/split pattern", "SHIFT+L Mark/unmark whole pattern", "SHIFT+M,N Choose highlighting step", "SHIFT+O,P Shrink/expand pattern", "SHIFT+X,C,V Cut,copy,paste pattern", "SHIFT+Z Cycle autoadvance-mode", "SHIFT+1,2,3 Mute channel", NULL }; char *songkeys[] = { "0-9 & A-F to enter pattern numbers", "SPC Set start position for F2 key", "BACKSPC Set end position for F2 key", "RET Go to pattern (/w SHIFT=all chns.)", "< > Select subtune", "- + Insert transpose down/up command", "SHIFT+CRSR LEFT/RIGHT Mark orderlist", "SHIFT+L Mark/unmark whole orderlist", "SHIFT+R Insert repeat command", "SHIFT+X,C,V Cut,copy,paste orderlist", "SHIFT+1,2,3 Swap orderlist with chn.", NULL }; char *instkeys[] = { "0-9 & A-F to enter parameters", "SPC Play test note", "SHIFT+SPC Silence test note", "RET Go to table", "- + Select instrument", "/ * Select octave", "BACKQUOTE Select table", "SHIFT+CRSR Mark table", "SHIFT+Q,W Trans. speed half/octave up", "SHIFT+A,S Trans. speed half/octave down", "SHIFT+L Convert pulse/filter limit", "SHIFT+N Edit name/negate value or note", "SHIFT+O Optimize table (remove unused)", "SHIFT+R Convert absolute/relative note", "SHIFT+S ""Smart"" instrument paste", "SHIFT+U Unlock/lock table view", "SHIFT+X,C,V Cut,copy,paste instr./table", "SHIFT+DEL Delete instrument+tabledata", "SHIFT+RET Convert vibrato parameter", NULL }; char *pattcmds[] = { " ", "Command 0XY: Do nothing. Databyte will always be 00. ", " ", "Command 1XY: Portamento up. XY is index to a 16-bit speed in speedtable. ", " ", "Command 2XY: Portamento down. XY is index to a 16-bit speed in speedtable. ", " ", "Command 3XY: Toneportamento. Raise or lower pitch until target note has been ", " reached. XY is index to a 16-bit speed or 00 for ""tie note"". ", " ", "Command 4XY: Vibrato. XY is index to speedtable. Left side value determines how", " long until the direction changes (speed) and right side value is ", " the amount of pitch change each tick (depth). ", " ", "Command 5XY: Set attack/decay register to value XY. ", " ", "Command 6XY: Set sustain/release register to value XY. ", " ", "Command 7XY: Set waveform register to value XY. If a wavetable is actively ", " changing the channel's waveform at the same time, will be ", " ineffective. ", " ", "Command 8XY: Set wavetable pointer. 00 stops wavetable execution. ", " ", "Command 9XY: Set pulsetable pointer. 00 stops pulsetable execution. ", " ", "Command AXY: Set filtertable pointer. 00 stops filtertable execution. ", " ", "Command BXY: Set filter control. X is resonance and Y is channel bitmask. ", " 00 turns filter off and also stops filtertable execution. ", " ", "Command CXY: Set filter cutoff to XY. Can be ineffective if the filtertable is ", " active and also changing the cutoff. ", " ", "Command DXY: Set mastervolume to Y, if X is 0. If X is not 0, value XY is ", " copied to the timing mark location, which is playeraddress+$3F. ", " ", "Command EXY: Funktempo. XY is an index to speedtable. Will alternate left side ", " and right side tempo values on each pattern step. ", " ", "Command FXY: Set tempo. Values 03-7F set tempo on all channels, values 83-FF ", " only on current channel (subtract 80 to get actual tempo). Tempos ", " 00 and 01 recall the funktempos set by EXY command. ", NULL }; char *instparm[] = { " ", "Attack/Decay 0 is fastest attack or decay, F is slowest ", " ", "Sustain/Release Sustain level 0 is silent and F is the loudest. Release ", " behaves like Attack & Decay (F slowest). ", " ", "Wavetable Pos Wavetable startposition. Value 00 stops the wavetable ", " execution and is not very useful. ", " ", "Pulsetable Pos Pulsetable startposition. Value 00 will leave pulse ", " execution untouched. ", " ", "Filtertable Pos Filtertable startposition. Value 00 will leave filter ", " execution untouched. In most cases it makes sense to have", " a filter-controlling instrument only on one channel at a ", " time. ", " ", "Vibrato Param Instrument vibrato parameters. An index to the speed- ", " table, see command 4XY. ", " ", "Vibrato Delay How many ticks until instrument vibrato starts. Value 00 ", " turns instrument vibrato off. ", " ", "HR/Gate Timer How many ticks before note start note fetch, gateoff and ", " hard restart happen. Can be at most tempo-1. So on tempo ", " 4 highest acceptable value is 3. Bitvalue 80 disables ", " hard restart and bitvalue 40 disables gateoff. ", " ", "1stFrame Wave Waveform used on init frame of the note, usually 09 (gate", " + testbit). Values 00, FE and FF have special meaning: ", " leave waveform unchanged and additionally set gate off ", " (FE), gate on (FF), or gate unchanged (00). ", NULL }; char *tables[] = { " ", "Wavetable left side: 00 Leave waveform unchanged ", " 01-0F Delay this step by 1-15 frames ", " 10-DF Waveform values ", " E0-EF Inaudible waveform values 00-0F ", " F0-FE Execute command 0XY-EXY. Right side is parameter ", " FF Jump. Right side tells jump position (00 = stop) ", " ", "Wavetable right side: 00-5F Relative notes ", " 60-7F Negative relative notes (lower pitch) ", " 80 Keep frequency unchanged ", " 81-DF Absolute notes C#0 - B-7 ", " ", "Pulsetable left side: 01-7F Pulse modulation step. Left side indicates time and", " right side the speed (8bit signed value). ", " 8X-FX Set pulse width. X is the high 4 bits, right side ", " tells the 8 low bits. ", " FF Jump. Right side tells jump position (00 = stop) ", " ", "Filt.table left side: 00 Set cutoff, indicated by right side ", " 01-7F Filter modulation step. Left side indicates time ", " and right side the speed (signed 8bit value) ", " 80-F0 Set filter parameters. Left side high nybble tells ", " the passband (90 = lowpass, A0 = bandpass etc.) and", " right side tells resonance/channel bitmask, as in ", " command BXY. ", " FF Jump. Right side tells jump position (00 = stop) ", " ", "Speedtbl. vibrato: XX YY Left side tells how long until vibrato direction ", " changes (speed), right side is the value added to ", " pitch each tick (depth). ", " ", "Speedtbl. portamento: XX YY A 16-bit value added to pitch each tick. Left side ", " is the MSB and the right side the LSB. ", " ", "Speedtbl. funktempo: XX YY Two 8-bit tempo values that are alternated on each ", " pattern row, starting from the left side. ", " ", "For both vibrato and portamento, if XX has the high bit ($80) set, note ", "independent vibrato depth / portamento speed calculation is enabled, and YY ", "specifies the divisor (higher value -> lower result and more rastertime taken).", NULL }; int hview = -1; int lastrow=0; for (;;) { int left = hview + 2; int right = hview + 2; clearscreen(); if(!context) { printtext(0, left++, HELP_HEADER, "GENERAL KEYS"); left = printrows(0,left,HELP_NORMAL, genkeys); left++; printtext(40,right++, HELP_HEADER, "PATTERN EDIT MODE"); right = printrows(40,right,HELP_NORMAL, patternkeys); right++; printtext(0, left++, HELP_HEADER, "SONG EDIT MODE"); left = printrows(0,left,HELP_NORMAL, songkeys); left++; printtext(0, left++, HELP_HEADER, "SONGNAME EDIT MODE"); printtext(0, left++, HELP_NORMAL, "Use cursor UP/DOWN to change rows"); left++; printtext(40,right++, HELP_HEADER, "INSTRUMENT/TABLE EDIT MODE"); right = printrows(40,right,HELP_NORMAL, instkeys); right++; left = (left -1) hview = -1; if (hview < -(lastrow-MAX_ROWS+1)) hview = -(lastrow-MAX_ROWS+1); if ((mouseb) && (!prevmouseb) && (!mousey)) break; } EXITHELP: ; if(!standalone) { printmainscreen(); key = 0; rawkey = 0; } } goattracker-2.72/src/gdisplay.c0000644000000000000000000003472511313471200015222 0ustar rootroot// // GOATTRACKER v2 screen display routines // #define GDISPLAY_C #include "goattrk2.h" char *notename[] = {"C-0", "C#0", "D-0", "D#0", "E-0", "F-0", "F#0", "G-0", "G#0", "A-0", "A#0", "B-0", "C-1", "C#1", "D-1", "D#1", "E-1", "F-1", "F#1", "G-1", "G#1", "A-1", "A#1", "B-1", "C-2", "C#2", "D-2", "D#2", "E-2", "F-2", "F#2", "G-2", "G#2", "A-2", "A#2", "B-2", "C-3", "C#3", "D-3", "D#3", "E-3", "F-3", "F#3", "G-3", "G#3", "A-3", "A#3", "B-3", "C-4", "C#4", "D-4", "D#4", "E-4", "F-4", "F#4", "G-4", "G#4", "A-4", "A#4", "B-4", "C-5", "C#5", "D-5", "D#5", "E-5", "F-5", "F#5", "G-5", "G#5", "A-5", "A#5", "B-5", "C-6", "C#6", "D-6", "D#6", "E-6", "F-6", "F#6", "G-6", "G#6", "A-6", "A#6", "B-6", "C-7", "C#7", "D-7", "D#7", "E-7", "F-7", "F#7", "G-7", "G#7", "...", "---", "+++"}; char timechar[] = {':', ' '}; int timemin = 0; int timesec = 0; int timeframe = 0; void printmainscreen(void) { clearscreen(); printstatus(); fliptoscreen(); } void displayupdate(void) { if (cursorflashdelay >= 6) { cursorflashdelay %= 6; cursorflash++; cursorflash &= 3; } printstatus(); fliptoscreen(); } void printstatus(void) { int c, d, color; int cc = cursorcolortable[cursorflash]; menu = 0; if ((mouseb > MOUSEB_LEFT) && (mousey <= 1) && (!eamode)) menu = 1; printblankc(0, 0, 15+16, MAX_COLUMNS); if (!menu) { if (!strlen(loadedsongfilename)) sprintf(textbuffer, "%s", programname); else sprintf(textbuffer, "%s - %s", programname, loadedsongfilename); textbuffer[49] = 0; printtext(0, 0, 15+16, textbuffer); if (usefinevib) printtext(40+10, 0, 15+16, "FV"); if (optimizepulse) printtext(43+10, 0, 15+16, "PO"); if (optimizerealtime) printtext(46+10, 0, 15+16, "RO"); if (ntsc) printtext(49+10, 0, 15+16, "NTSC"); else printtext(49+10, 0, 15+16, " PAL"); if (!sidmodel) printtext(54+10, 0, 15+16, "6581"); else printtext(54+10, 0, 15+16, "8580"); sprintf(textbuffer, "HR:%04X", adparam); printtext(59+10, 0, 15+16, textbuffer); if (eamode) printbg(62+10+eacolumn, 0, cc, 1); if (multiplier) { sprintf(textbuffer, "%2dX", multiplier); printtext(67+10, 0, 15+16, textbuffer); } else printtext(67+10, 0, 15+16, "25Hz"); printtext(72+20, 0, 15+16, "F12=HELP"); } else { printtext(0, 0, 15+16, " PLAY | PLAYPOS | PLAYPATT | STOP | LOAD | SAVE | PACK/RL | HELP | CLEAR | QUIT |"); } if ((followplay) && (isplaying())) { for (c = 0; c < MAX_CHN; c++) { int newpos = chn[c].pattptr / 4; if (chn[c].advance) epnum[c] = chn[c].pattnum; if (newpos > pattlen[epnum[c]]) newpos = pattlen[epnum[c]]; if (c == epchn) { eppos = newpos; epview = newpos-VISIBLEPATTROWS/2; } newpos = chn[c].songptr; newpos--; if (newpos < 0) newpos = 0; if (newpos > songlen[esnum][c]) newpos = songlen[esnum][c]; if ((c == eschn) && (chn[c].advance)) { eseditpos = newpos; if (newpos - esview < 0) { esview = newpos; } if (newpos - esview >= VISIBLEORDERLIST) { esview = newpos - VISIBLEORDERLIST + 1; } } } } for (c = 0; c < MAX_CHN; c++) { sprintf(textbuffer, "CHN %d PATT.%02X", c+1, epnum[c]); printtext(2+c*15, 2, CTITLE, textbuffer); for (d = 0; d < VISIBLEPATTROWS; d++) { int p = epview+d; color = CNORMAL; if ((epnum[c] == chn[c].pattnum) && (isplaying())) { int chnrow = chn[c].pattptr / 4; if (chnrow > pattlen[chn[c].pattnum]) chnrow = pattlen[chn[c].pattnum]; if (chnrow == p) color = CPLAYING; } if (chn[c].mute) color = CMUTE; if (p == eppos) color = CEDIT; if ((p < 0) || (p > pattlen[epnum[c]])) { sprintf(textbuffer, " "); } else { if (!patternhex) { if (p < 100) sprintf(textbuffer, " %02d", p); else sprintf(textbuffer, "%03d", p); } else sprintf(textbuffer, " %02X", p); if (pattern[epnum[c]][p*4] == ENDPATT) { sprintf(&textbuffer[3], " PATT. END"); if (color == CNORMAL) color = CCOMMAND; } else { sprintf(&textbuffer[3], " %s %02X%01X%02X", notename[pattern[epnum[c]][p*4]-FIRSTNOTE], pattern[epnum[c]][p*4+1], pattern[epnum[c]][p*4+2], pattern[epnum[c]][p*4+3]); } } textbuffer[3] = 0; if (p%stepsize) { printtext(2+c*15, 3+d, CNORMAL, textbuffer); } else { printtext(2+c*15, 3+d, CCOMMAND, textbuffer); } printtext(6+c*15, 3+d, color, &textbuffer[4]); if (c == epmarkchn) { if (epmarkstart <= epmarkend) { if ((p >= epmarkstart) && (p <= epmarkend)) printbg(2+c*15+4, 3+d, 1, 9); } else { if ((p <= epmarkstart) && (p >= epmarkend)) printbg(2+c*15+4, 3+d, 1, 9); } } if ((color == CEDIT) && (editmode == EDIT_PATTERN) && (epchn == c)) { switch(epcolumn) { case 0: if (!eamode) printbg(2+c*15+4, 3+d, cc, 3); break; default: if (!eamode) printbg(2+c*15+7+epcolumn, 3+d, cc, 1); break; } } } } sprintf(textbuffer, "CHN ORDERLIST (SUBTUNE %02X, POS %02X)", esnum, eseditpos); printtext(40+10, 2, CTITLE, textbuffer); for (c = 0; c < MAX_CHN; c++) { sprintf(textbuffer, " %d ", c+1); printtext(40+10, 3+c, 15, textbuffer); for (d = 0; d < VISIBLEORDERLIST; d++) { int p = esview+d; color = CNORMAL; if (isplaying()) { int chnpos = chn[c].songptr; chnpos--; if (chnpos < 0) chnpos = 0; if ((p == chnpos) && (chn[c].advance)) color = CPLAYING; } if (p == espos[c]) color = CEDIT; if ((esend[c]) && (p == esend[c])) color = CEDIT; if ((p < 0) || (p > (songlen[esnum][c]+1)) || (p > MAX_SONGLEN+1)) { sprintf(textbuffer, " "); } else { if (songorder[esnum][c][p] < LOOPSONG) { if ((songorder[esnum][c][p] < REPEAT) || (p >= songlen[esnum][c])) { sprintf(textbuffer, "%02X ", songorder[esnum][c][p]); if ((p >= songlen[esnum][c]) && (color == CNORMAL)) color = CCOMMAND; } else { if (songorder[esnum][c][p] >= TRANSUP) { sprintf(textbuffer, "+%01X ", songorder[esnum][c][p]&0xf); if (color == CNORMAL) color = CCOMMAND; } else { if (songorder[esnum][c][p] >= TRANSDOWN) { sprintf(textbuffer, "-%01X ", 16-(songorder[esnum][c][p] & 0x0f)); if (color == CNORMAL) color = CCOMMAND; } else { sprintf(textbuffer, "R%01X ", (songorder[esnum][c][p]+1) & 0x0f); if (color == CNORMAL) color = CCOMMAND; } } } } if (songorder[esnum][c][p] == LOOPSONG) { sprintf(textbuffer, "RST"); if (color == CNORMAL) color = CCOMMAND; } } printtext(44+10+d*3, 3+c, color, textbuffer); if (c == esmarkchn) { if (esmarkstart <= esmarkend) { if ((p >= esmarkstart) && (p <= esmarkend)) { if (p != esmarkend) printbg(44+10+d*3, 3+c, 1, 3); else printbg(44+10+d*3, 3+c, 1, 2); } } else { if ((p <= esmarkstart) && (p >= esmarkend)) { if (p != esmarkstart) printbg(44+10+d*3, 3+c, 1, 3); else printbg(44+10+d*3, 3+c, 1, 2); } } } if ((p == eseditpos) && (editmode == EDIT_ORDERLIST) && (eschn == c)) { if (!eamode) printbg(44+10+d*3+escolumn, 3+c, cc, 1); } } } sprintf(textbuffer, "INSTRUMENT NUM. %02X %-16s", einum, instr[einum].name); printtext(40+10, 7, CTITLE, textbuffer); sprintf(textbuffer, "Attack/Decay %02X", instr[einum].ad); if (eipos == 0) color = CEDIT; else color = CNORMAL; printtext(40+10, 8, color, textbuffer); sprintf(textbuffer, "Sustain/Release %02X", instr[einum].sr); if (eipos == 1) color = CEDIT; else color = CNORMAL; printtext(40+10, 9, color, textbuffer); sprintf(textbuffer, "Wavetable Pos %02X", instr[einum].ptr[WTBL]); if (eipos == 2) color = CEDIT; else color = CNORMAL; printtext(40+10, 10, color, textbuffer); sprintf(textbuffer, "Pulsetable Pos %02X", instr[einum].ptr[PTBL]); if (eipos == 3) color = CEDIT; else color = CNORMAL; printtext(40+10, 11, color, textbuffer); sprintf(textbuffer, "Filtertable Pos %02X", instr[einum].ptr[FTBL]); if (eipos == 4) color = CEDIT; else color = CNORMAL; printtext(40+10, 12, color, textbuffer); sprintf(textbuffer, "Vibrato Param %02X", instr[einum].ptr[STBL]); if (eipos == 5) color = CEDIT; else color = CNORMAL; printtext(60+10, 8, color, textbuffer); sprintf(textbuffer, "Vibrato Delay %02X", instr[einum].vibdelay); if (eipos == 6) color = CEDIT; else color = CNORMAL; printtext(60+10, 9, color, textbuffer); sprintf(textbuffer, "HR/Gate Timer %02X", instr[einum].gatetimer); if (eipos == 7) color = CEDIT; else color = CNORMAL; printtext(60+10, 10, color, textbuffer); sprintf(textbuffer, "1stFrame Wave %02X", instr[einum].firstwave); if (eipos == 8) color = CEDIT; else color = CNORMAL; printtext(60+10, 11, color, textbuffer); if (editmode == EDIT_INSTRUMENT) { if (eipos < 9) { if (!eamode) printbg(56+10+eicolumn+20*(eipos/5), 8+(eipos%5), cc, 1); } else { if (!eamode) printbg(60+10+strlen(instr[einum].name), 7, cc, 1); } } sprintf(textbuffer, "WAVE TBL PULSETBL FILT.TBL SPEEDTBL"); printtext(40+10, 14, CTITLE, textbuffer); for (c = 0; c < MAX_TABLES; c++) { for (d = 0; d < VISIBLETABLEROWS; d++) { int p = etview[c]+d; color = CNORMAL; switch (c) { case WTBL: if (ltable[c][p] >= WAVECMD) color = CCOMMAND; break; case PTBL: if (ltable[c][p] >= 0x80) color = CCOMMAND; break; case FTBL: if ((ltable[c][p] >= 0x80) || ((!ltable[c][p]) && (rtable[c][p]))) color = CCOMMAND; break; } if ((p == etpos) && (etnum == c)) color = CEDIT; sprintf(textbuffer, "%02X:%02X %02X", p+1, ltable[c][p], rtable[c][p]); printtext(40+10+10*c, 15+d, color, textbuffer); if (etmarknum == c) { if (etmarkstart <= etmarkend) { if ((p >= etmarkstart) && (p <= etmarkend)) printbg(40+10+10*c+3, 15+d, 1, 5); } else { if ((p <= etmarkstart) && (p >= etmarkend)) printbg(40+10+10*c+3, 15+d, 1, 5); } } } } if (editmode == EDIT_TABLES) { if (!eamode) printbg(43+10+etnum*10+(etcolumn & 1)+(etcolumn/2)*3, 15+etpos-etview[etnum], cc, 1); } printtext(40+10, 31, CTITLE, "NAME "); sprintf(textbuffer, "%-32s", songname); printtext(47+10, 31, CEDIT, textbuffer); printtext(40+10, 32, CTITLE, "AUTHOR "); sprintf(textbuffer, "%-32s", authorname); printtext(47+10, 32, CEDIT, textbuffer); printtext(40+10, 33, CTITLE, "COPYR. "); sprintf(textbuffer, "%-32s", copyrightname); printtext(47+10, 33, CEDIT, textbuffer); if ((editmode == EDIT_NAMES) && (!eamode)) { switch(enpos) { case 0: printbg(47+10+strlen(songname), 31, cc, 1); break; case 1: printbg(47+10+strlen(authorname), 32, cc, 1); break; case 2: printbg(47+10+strlen(copyrightname), 33, cc, 1); break; } } sprintf(textbuffer, "OCTAVE %d", epoctave); printtext(0, 35, CTITLE, textbuffer); switch(autoadvance) { case 0: color = 10; break; case 1: color = 14; break; case 2: color = 12; break; } if (recordmode) printtext(0, 36, color, "EDITMODE"); else printtext(0, 36, color, "JAM MODE"); if (isplaying()) printtext(10, 35, CTITLE, "PLAYING"); else printtext(10, 35, CTITLE, "STOPPED"); if (multiplier) { if (!ntsc) sprintf(textbuffer, " %02d%c%02d ", timemin, timechar[timeframe/(25*multiplier) & 1], timesec); else sprintf(textbuffer, " %02d%c%02d ", timemin, timechar[timeframe/(30*multiplier) & 1], timesec); } else { if (!ntsc) sprintf(textbuffer, " %02d%c%02d ", timemin, timechar[(timeframe/13) & 1], timesec); else sprintf(textbuffer, " %02d%c%02d ", timemin, timechar[(timeframe/15) & 1], timesec); } printtext(10, 36, CEDIT, textbuffer); printtext(80, 35, CTITLE, " CHN1 CHN2 CHN3 "); for (c = 0; c < MAX_CHN; c++) { int chnpos = chn[c].songptr; int chnrow = chn[c].pattptr/4; chnpos--; if (chnpos < 0) chnpos = 0; if (chnrow > pattlen[chn[c].pattnum]) chnrow = pattlen[chn[c].pattnum]; if (chnrow >= 100) chnrow -= 100; sprintf(textbuffer, "%03d/%02d", chnpos,chnrow); printtext(80+7*c, 36, CEDIT, textbuffer); } if (etlock) printtext(78, 36, CTITLE, " "); else printtext(78, 36, CTITLE, "U"); } void resettime(void) { timemin = 0; timesec = 0; timeframe = 0; } void incrementtime(void) { { timeframe++; if (!ntsc) { if (((multiplier) && (timeframe >= PALFRAMERATE*multiplier)) || ((!multiplier) && (timeframe >= PALFRAMERATE/2))) { timeframe = 0; timesec++; } } else { if (((multiplier) && (timeframe >= NTSCFRAMERATE*multiplier)) || ((!multiplier) && (timeframe >= NTSCFRAMERATE/2))) { timeframe = 0; timesec++; } } if (timesec == 60) { timesec = 0; timemin++; timemin %= 60; } } } goattracker-2.72/src/greloc.h0000644000000000000000000000300110774364076014673 0ustar rootroot#ifndef GRELOC_H #define GRELOC_H #define FORMAT_SID 0 #define FORMAT_PRG 1 #define FORMAT_BIN 2 #define PLAYER_BUFFERED 8 #define PLAYER_SOUNDEFFECTS 16 #define PLAYER_VOLUME 32 #define PLAYER_AUTHORINFO 64 #define PLAYER_ZPGHOSTREGS 128 #define PLAYER_NOOPTIMIZATION 256 #define MAX_OPTIONS 6 #define TYPE_NONE 0 #define TYPE_OVERFLOW 1 #define TYPE_JUMP 2 #define CAUSE_NONE 0 #define CAUSE_PATTERN 1 #define CAUSE_INSTRUMENT 2 #define CAUSE_WAVECMD 3 #define MAX_BYTES_PER_ROW 16 #ifndef GRELOC_C extern unsigned char pattused[MAX_PATT]; extern unsigned char instrused[MAX_INSTR]; extern unsigned char tableused[MAX_TABLES][MAX_TABLELEN+1]; extern unsigned char pattmap[MAX_PATT]; extern unsigned char instrmap[MAX_INSTR]; extern unsigned char tablemap[MAX_TABLES][MAX_TABLELEN+1]; extern int tableerror; #endif void relocator(void); int testoverlap(int area1start, int area1size, int area2start, int area2size); int packpattern(unsigned char *dest, unsigned char *src, int rows); unsigned char swapnybbles(unsigned char n); void findtableduplicates(int num); int isusedandselfcontained(int num, int start); void calcspeedtest(unsigned char pos); int insertfile(char *name); void inserttext(const char *text); void insertdefine(const char *name, int value); void insertlabel(const char *name); void insertbyte(unsigned char byte); void insertbytes(const unsigned char *bytes, int size); void insertaddrlo(const char *name); void insertaddrhi(const char *name); #endif goattracker-2.72/src/bme/0000755000000000000000000000000011604145110013773 5ustar rootrootgoattracker-2.72/src/bme/datafile.c0000644000000000000000000001062110774364076015735 0ustar rootroot// // Datafile creator // #include #include #include #include #include #include "bme_end.h" #define MAXFILES 16384 #define MAXFILENAME 64 typedef struct { Uint32 offset; Uint32 length; char name[13]; } HEADER; static HEADER header[MAXFILES]; static char fullname[MAXFILES][MAXFILENAME]; static int files; int main(int argc, char **argv); int addfile(HEADER *header, FILE *dest, char *name); void fwrite8(FILE *file, unsigned data); void fwritele16(FILE *file, unsigned data); void fwritele32(FILE *file, unsigned data); int main(int argc, char **argv) { FILE *datafile, *listfile; int c; if (argc < 3) { printf("Usage: DATAFILE \n\n" "The purpose of this program is to gather many files into one datafile, like\n" "usually seen in games. The files can be read by BME's IO functions after\n" "opening the datafile first with io_opendatafile(). The filelistfile must\n" "contain name (use only 8+3 chars) of each file on its own row, for example:\n\n" "editor.spr\n" "fonts.spr\n"); return 0; } listfile = fopen(argv[2], "rt"); if (!listfile) { printf("ERROR: Couldn't open filelist.\n"); return 1; } datafile = fopen(argv[1], "wb"); if (!datafile) { printf("ERROR: Couldn't create datafile.\n"); fclose(listfile); return 1; } memset(&header[0], 0, MAXFILES * sizeof(HEADER)); // Get names from list for (;;) { char searchname[64]; int d; FILE *test; if (fscanf(listfile, "%63s", searchname) == EOF) break; test = fopen(searchname, "rb"); if (test) { fclose(test); strcpy(fullname[files], searchname); for (c = strlen(fullname[files]) - 1; c >= 0; c--) { if (fullname[files][c] == '\\') { c++; break; } } if (c < 0) c = 0; memset(header[files].name, 0, 13); d = 0; while (fullname[files][c]) { header[files].name[d] = toupper(fullname[files][c]); c++; d++; } files++; if (files == MAXFILES) break; } if (files == MAXFILES) break; } fclose(listfile); // Write datafile header fwrite("DAT!", 4, 1, datafile); fwritele32(datafile, files); // Write incomplete fileheaders for (c = 0; c < files; c++) { fwritele32(datafile, header[c].offset); fwritele32(datafile, header[c].length); fwrite(header[c].name, 13, 1, datafile); } // Process each file for (c = 0; c < files; c++) { printf("Adding %s...\n", header[c].name); if (!addfile(&header[c], datafile, fullname[c])) { printf("Terminating & deleting datafile...\n"); fclose(datafile); remove(argv[1]); return 1; } } // Seek back to start & write correct headers fseek(datafile, sizeof files + 4, SEEK_SET); for (c = 0; c < files; c++) { fwritele32(datafile, header[c].offset); fwritele32(datafile, header[c].length); fwrite(header[c].name, 13, 1, datafile); } fclose(datafile); printf("Everything OK!\n"); return 0; } int addfile(HEADER *header, FILE *dest, char *name) { FILE *src; unsigned char *originalbuf; src = fopen(name, "rb"); if (!src) { printf("ERROR: Couldn't open file %s\n", name); return 0; } header->offset = ftell(dest); fseek(src, 0, SEEK_END); header->length = ftell(src); fseek(src, 0, SEEK_SET); originalbuf = malloc(header->length); if (!originalbuf) { printf("ERROR: No memory to load file!\n"); fclose(src); return 0; } printf("* Loading file\n"); fread(originalbuf, header->length, 1, src); fclose(src); printf("* Writing file (size was %d)\n", header->length); fwrite(originalbuf, header->length, 1, dest); free(originalbuf); return 1; } goattracker-2.72/src/bme/bme_cfg.h0000644000000000000000000000066510774364076015562 0ustar rootroot// BME configuration (some static things) #define MAX_JOYSTICKS 16 // Maximum joysticks #define MAX_HANDLES 16 // Up to 16 simultaneus files open from the // datafile #define MAX_COLORS 256 // 8bit oldskool mode #define DEFAULT_MAX_SPRFILES 256 // Default maximum of 256 spritefiles, though // this can be set during running of program #define MAX_KEYS 512 goattracker-2.72/src/bme/bme_kbd.h0000644000000000000000000000040510774364076015553 0ustar rootroot// BME keyboard functions header file int kbd_init(void); void kbd_uninit(void); int kbd_waitkey(void); int kbd_getkey(void); int kbd_checkkey(int rawcode); int kbd_getascii(void); unsigned kbd_getvirtualkey(void); char *kbd_getkeyname(int rawcode); goattracker-2.72/src/bme/bme.c0000644000000000000000000000020510774364076014724 0ustar rootroot// // BME (Blasphemous Multimedia Engine) main module // #include "bme_err.h" #include "bme_cfg.h" int bme_error = BME_OK; goattracker-2.72/src/bme/bme_end.c0000644000000000000000000000237710774364076015566 0ustar rootroot#include #include void fwrite8(FILE *file, unsigned data) { Uint8 bytes[1]; bytes[0] = data; fwrite(bytes, 1, 1, file); } void fwritele16(FILE *file, unsigned data) { Uint8 bytes[2]; bytes[0] = data; bytes[1] = data >> 8; fwrite(bytes, 2, 1, file); } void fwritele32(FILE *file, unsigned data) { Uint8 bytes[4]; bytes[0] = data; bytes[1] = data >> 8; bytes[2] = data >> 16; bytes[3] = data >> 24; fwrite(bytes, 4, 1, file); } unsigned fread8(FILE *file) { Uint8 bytes[1]; fread(bytes, 1, 1, file); return bytes[0]; } unsigned freadle16(FILE *file) { Uint8 bytes[2]; fread(bytes, 2, 1, file); return (bytes[0]) | (bytes[1] << 8); } unsigned freadle32(FILE *file) { Uint8 bytes[4]; fread(bytes, 4, 1, file); return (bytes[0]) | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24); } unsigned freadhe16(FILE *file) { Uint8 bytes[2]; fread(bytes, 2, 1, file); return (bytes[1]) | (bytes[0] << 8); } unsigned freadhe32(FILE *file) { Uint8 bytes[4]; fread(bytes, 4, 1, file); return (bytes[3]) | (bytes[2] << 8) | (bytes[1] << 16) | (bytes[0] << 24); } goattracker-2.72/src/bme/dat2inc.c0000644000000000000000000000167710774364076015523 0ustar rootroot// // Datafile -> C include file // #include int main(int argc, char *argv[]) { FILE *in; FILE *out; int length; int c; if (argc < 3) { printf("Usage: dat2inc \n\n"); return 1; } in = fopen(argv[1], "rb"); if (!in) { printf("Datafile open error!\n"); return 1; } out = fopen(argv[2], "wt"); if (!out) { printf("Includefile open error!\n"); return 1; } fseek(in, 0, SEEK_END); length = ftell(in); fseek(in, 0, SEEK_SET); fprintf(out, "unsigned char datafile[] = {\n"); for (c = 0; c < length; c++) { if (c) { fprintf(out, ", "); if (!(c % 10)) fprintf(out, "\n"); } fprintf(out, "0x%02x", fgetc(in)); } fprintf(out, "};\n"); fclose(in); fclose(out); return 0; } goattracker-2.72/src/bme/bme_mou.c0000644000000000000000000000203010774364076015602 0ustar rootroot// // BME (Blasphemous Multimedia Engine) mouse module // #include #include #include #include #include "bme_main.h" #include "bme_cfg.h" #include "bme_win.h" #include "bme_gfx.h" #include "bme_io.h" #include "bme_err.h" void mou_init(void); void mou_uninit(void); void mou_getpos(unsigned *x, unsigned *y); void mou_getmove(int *dx, int *dy); unsigned mou_getbuttons(void); void mou_init(void) { win_mousebuttons = 0; } void mou_uninit(void) { } void mou_getpos(unsigned *x, unsigned *y) { if (!gfx_initted) { *x = win_mousexpos; *y = win_mouseypos; } else { *x = win_mousexpos * gfx_virtualxsize / gfx_windowxsize; *y = win_mouseypos * gfx_virtualysize / gfx_windowysize; } } void mou_getmove(int *dx, int *dy) { *dx = win_mousexrel; *dy = win_mouseyrel; win_mousexrel = 0; win_mouseyrel = 0; } unsigned mou_getbuttons(void) { return win_mousebuttons; } goattracker-2.72/src/bme/bme_mou.h0000644000000000000000000000027610774364076015621 0ustar rootroot// BME mouse functions header file void mou_init(void); void mou_uninit(void); void mou_getpos(unsigned *x, unsigned *y); void mou_getmove(int *dx, int *dy); unsigned mou_getbuttons(void); goattracker-2.72/src/bme/bme_gfx.c0000644000000000000000000003334411313456422015565 0ustar rootroot// // BME (Blasphemous Multimedia Engine) graphics main module // #include #include #include #include #include "bme_main.h" #include "bme_cfg.h" #include "bme_win.h" #include "bme_io.h" #include "bme_err.h" // Prototypes int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags); int gfx_reinit(void); void gfx_uninit(void); int gfx_lock(void); void gfx_unlock(void); void gfx_flip(void); void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom); void gfx_setmaxspritefiles(int num); void gfx_setmaxcolors(int num); int gfx_loadpalette(char *name); void gfx_calcpalette(int fade, int radd, int gadd, int badd); void gfx_setpalette(void); int gfx_loadblocks(char *name); int gfx_loadsprites(int num, char *name); void gfx_freesprites(int num); void gfx_drawsprite(int x, int y, unsigned num); void gfx_getspriteinfo(unsigned num); int gfx_initted = 0; int gfx_redraw = 0; int gfx_fullscreen = 0; int gfx_scanlinemode = 0; int gfx_preventswitch = 0; int gfx_virtualxsize; int gfx_virtualysize; int gfx_windowxsize; int gfx_windowysize; int gfx_blockxsize = 16; int gfx_blockysize = 16; int spr_xsize = 0; int spr_ysize = 0; int spr_xhotspot = 0; int spr_yhotspot = 0; unsigned gfx_nblocks = 0; Uint8 gfx_palette[MAX_COLORS * 3] = {0}; SDL_Surface *gfx_screen = NULL; // Static variables static int gfx_initexec = 0; static unsigned gfx_last_xsize; static unsigned gfx_last_ysize; static unsigned gfx_last_framerate; static unsigned gfx_last_flags; static int gfx_cliptop; static int gfx_clipbottom; static int gfx_clipleft; static int gfx_clipright; static int gfx_maxcolors = MAX_COLORS; static int gfx_maxspritefiles = 0; static SPRITEHEADER **gfx_spriteheaders = NULL; static Uint8 **gfx_spritedata = NULL; static unsigned *gfx_spriteamount = NULL; static SDL_Color gfx_sdlpalette[MAX_COLORS]; static int gfx_locked = 0; int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags) { int sdlflags = SDL_HWSURFACE; // Prevent re-entry (by window procedure) if (gfx_initexec) return BME_OK; gfx_initexec = 1; gfx_last_xsize = xsize; gfx_last_ysize = ysize; gfx_last_framerate = framerate; gfx_last_flags = flags & ~(GFX_FULLSCREEN | GFX_WINDOW); // Store the options contained in the flags gfx_scanlinemode = flags & (GFX_SCANLINES | GFX_DOUBLESIZE); if (flags & GFX_NOSWITCHING) gfx_preventswitch = 1; else gfx_preventswitch = 0; if (win_fullscreen) sdlflags |= SDL_FULLSCREEN; if (flags & GFX_FULLSCREEN) sdlflags |= SDL_FULLSCREEN; if (flags & GFX_WINDOW) sdlflags &= ~SDL_FULLSCREEN; if (sdlflags & SDL_FULLSCREEN) gfx_fullscreen = 1; else gfx_fullscreen = 0; // Calculate virtual window size gfx_virtualxsize = xsize; gfx_virtualxsize /= 16; gfx_virtualxsize *= 16; gfx_virtualysize = ysize; if ((!gfx_virtualxsize) || (!gfx_virtualysize)) { gfx_initexec = 0; gfx_uninit(); bme_error = BME_ILLEGAL_CONFIG; return BME_ERROR; } // Calculate actual window size (for scanline mode & doublesize mode // this is double the virtual) gfx_windowxsize = gfx_virtualxsize; gfx_windowysize = gfx_virtualysize; if (gfx_scanlinemode) { gfx_windowxsize <<= 1; gfx_windowysize <<= 1; } gfx_setclipregion(0, 0, gfx_virtualxsize, gfx_virtualysize); // Colors 0 & 255 are always black & white gfx_sdlpalette[0].r = 0; gfx_sdlpalette[0].g = 0; gfx_sdlpalette[0].b = 0; gfx_sdlpalette[255].r = 255; gfx_sdlpalette[255].g = 255; gfx_sdlpalette[255].b = 255; gfx_screen = SDL_SetVideoMode(gfx_windowxsize, gfx_windowysize, 8, sdlflags); gfx_initexec = 0; if (gfx_screen) { gfx_initted = 1; gfx_redraw = 1; gfx_setpalette(); win_setmousemode(win_mousemode); return BME_OK; } else return BME_ERROR; } int gfx_reinit(void) { return gfx_init(gfx_last_xsize, gfx_last_ysize, gfx_last_framerate, gfx_last_flags); } void gfx_uninit(void) { gfx_initted = 0; return; } int gfx_lock(void) { if (gfx_locked) return 1; if (!gfx_initted) return 0; if (!SDL_LockSurface(gfx_screen)) { gfx_locked = 1; return 1; } else return 0; } void gfx_unlock(void) { if (gfx_locked) { SDL_UnlockSurface(gfx_screen); gfx_locked = 0; } } void gfx_flip() { SDL_Flip(gfx_screen); gfx_redraw = 0; } void gfx_setmaxcolors(int num) { gfx_maxcolors = num; } int gfx_loadpalette(char *name) { int handle; handle = io_open(name); if (handle == -1) { bme_error = BME_OPEN_ERROR; return BME_ERROR; } if (io_read(handle, gfx_palette, sizeof gfx_palette) != sizeof gfx_palette) { bme_error = BME_READ_ERROR; io_close(handle); return BME_ERROR; } io_close(handle); gfx_calcpalette(64, 0, 0, 0); bme_error = BME_OK; return BME_OK; } void gfx_calcpalette(int fade, int radd, int gadd, int badd) { Uint8 *sptr = &gfx_palette[3]; int c, cl; if (radd < 0) radd = 0; if (gadd < 0) gadd = 0; if (badd < 0) badd = 0; for (c = 1; c < 255; c++) { cl = *sptr; cl *= fade; cl >>= 6; cl += radd; if (cl > 63) cl = 63; if (cl < 0) cl = 0; gfx_sdlpalette[c].r = (cl << 2) | (cl & 3); sptr++; cl = *sptr; cl *= fade; cl >>= 6; cl += gadd; if (cl > 63) cl = 63; if (cl < 0) cl = 0; gfx_sdlpalette[c].g = (cl << 2) | (cl & 3); sptr++; cl = *sptr; cl *= fade; cl >>= 6; cl += badd; if (cl > 63) cl = 63; if (cl < 0) cl = 0; gfx_sdlpalette[c].b = (cl << 2) | (cl & 3); sptr++; } } void gfx_setpalette(void) { if (!gfx_initted) return; SDL_SetColors(gfx_screen, &gfx_sdlpalette[0], 0, gfx_maxcolors); } void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom) { if (left >= right) return; if (top >= bottom) return; if (left >= gfx_virtualxsize) return; if (top >= gfx_virtualysize) return; if (right > gfx_virtualxsize) return; if (bottom > gfx_virtualysize) return; gfx_clipleft = left; gfx_clipright = right; gfx_cliptop = top; gfx_clipbottom = bottom; } void gfx_setmaxspritefiles(int num) { if (num <= 0) return; if (gfx_spriteheaders) return; gfx_spriteheaders = malloc(num * sizeof(Uint8 *)); gfx_spritedata = malloc(num * sizeof(Uint8 *)); gfx_spriteamount = malloc(num * sizeof(unsigned)); if ((gfx_spriteheaders) && (gfx_spritedata) && (gfx_spriteamount)) { int c; gfx_maxspritefiles = num; for (c = 0; c < num; c++) { gfx_spriteamount[c] = 0; gfx_spritedata[c] = NULL; gfx_spriteheaders[c] = NULL; } } else gfx_maxspritefiles = 0; } int gfx_loadsprites(int num, char *name) { int handle, size, c; int datastart; if (!gfx_spriteheaders) { gfx_setmaxspritefiles(DEFAULT_MAX_SPRFILES); } bme_error = BME_OPEN_ERROR; if (num >= gfx_maxspritefiles) return BME_ERROR; gfx_freesprites(num); handle = io_open(name); if (handle == -1) return BME_ERROR; size = io_lseek(handle, 0, SEEK_END); io_lseek(handle, 0, SEEK_SET); gfx_spriteamount[num] = io_readle32(handle); gfx_spriteheaders[num] = malloc(gfx_spriteamount[num] * sizeof(SPRITEHEADER)); if (!gfx_spriteheaders[num]) { bme_error = BME_OUT_OF_MEMORY; io_close(handle); return BME_ERROR; } for (c = 0; c < gfx_spriteamount[num]; c++) { SPRITEHEADER *hptr = gfx_spriteheaders[num] + c; hptr->xsize = io_readle16(handle); hptr->ysize = io_readle16(handle); hptr->xhot = io_readle16(handle); hptr->yhot = io_readle16(handle); hptr->offset = io_readle32(handle); } datastart = io_lseek(handle, 0, SEEK_CUR); gfx_spritedata[num] = malloc(size - datastart); if (!gfx_spritedata[num]) { bme_error = BME_OUT_OF_MEMORY; io_close(handle); return BME_ERROR; } io_read(handle, gfx_spritedata[num], size - datastart); io_close(handle); bme_error = BME_OK; return BME_OK; } void gfx_freesprites(int num) { if (num >= gfx_maxspritefiles) return; if (gfx_spritedata[num]) { free(gfx_spritedata[num]); gfx_spritedata[num] = NULL; } if (gfx_spriteheaders[num]) { free(gfx_spriteheaders[num]); gfx_spriteheaders[num] = NULL; } } void gfx_copyscreen8(Uint8 *destaddress, Uint8 *srcaddress, unsigned pitch) { int c, d; switch(gfx_scanlinemode) { default: for (c = 0; c < gfx_virtualysize; c++) { memcpy(destaddress, srcaddress, gfx_virtualxsize); destaddress += pitch; srcaddress += gfx_virtualxsize; } break; case GFX_SCANLINES: for (c = 0; c < gfx_virtualysize; c++) { d = gfx_virtualxsize; while (d--) { *destaddress = *srcaddress; destaddress++; *destaddress = *srcaddress; destaddress++; srcaddress++; } destaddress += pitch*2 - (gfx_virtualxsize << 1); } break; case GFX_DOUBLESIZE: for (c = 0; c < gfx_virtualysize; c++) { d = gfx_virtualxsize; while (d--) { *destaddress = *srcaddress; destaddress++; *destaddress = *srcaddress; destaddress++; srcaddress++; } destaddress += pitch - (gfx_virtualxsize << 1); srcaddress -= gfx_virtualxsize; d = gfx_virtualxsize; while (d--) { *destaddress = *srcaddress; destaddress++; *destaddress = *srcaddress; destaddress++; srcaddress++; } destaddress += pitch - (gfx_virtualxsize << 1); } break; } } void gfx_getspriteinfo(unsigned num) { unsigned sprf = num >> 16; unsigned spr = (num & 0xffff) - 1; SPRITEHEADER *hptr; if ((sprf >= gfx_maxspritefiles) || (!gfx_spriteheaders[sprf]) || (spr >= gfx_spriteamount[sprf])) hptr = NULL; else hptr = gfx_spriteheaders[sprf] + spr; if (!hptr) { spr_xsize = 0; spr_ysize = 0; spr_xhotspot = 0; spr_yhotspot = 0; return; } spr_xsize = hptr->xsize; spr_ysize = hptr->ysize; spr_xhotspot = hptr->xhot; spr_yhotspot = hptr->yhot; } void gfx_drawsprite(int x, int y, unsigned num) { unsigned sprf = num >> 16; unsigned spr = (num & 0xffff) - 1; SPRITEHEADER *hptr; Uint8 *sptr; Uint8 *dptr; int cx; if (!gfx_initted) return; if (!gfx_locked) return; if ((sprf >= gfx_maxspritefiles) || (!gfx_spriteheaders[sprf]) || (spr >= gfx_spriteamount[sprf])) { spr_xsize = 0; spr_ysize = 0; spr_xhotspot = 0; spr_yhotspot = 0; return; } else hptr = gfx_spriteheaders[sprf] + spr; sptr = gfx_spritedata[sprf] + hptr->offset; spr_xsize = hptr->xsize; spr_ysize = hptr->ysize; spr_xhotspot = hptr->xhot; spr_yhotspot = hptr->yhot; x -= spr_xhotspot; y -= spr_yhotspot; if (x >= gfx_clipright) return; if (y >= gfx_clipbottom) return; if (x + spr_xsize <= gfx_clipleft) return; if (y + spr_ysize <= gfx_cliptop) return; while (y < gfx_cliptop) { int dec = *sptr++; if (dec == 255) { if (!(*sptr)) return; y++; } else { if (dec < 128) { sptr += dec; } } } while (y < gfx_clipbottom) { int dec; cx = x; dptr = gfx_screen->pixels + y * gfx_screen->pitch + x; for (;;) { dec = *sptr++; if (dec == 255) { if (!(*sptr)) return; y++; break; } if (dec < 128) { if ((cx + dec <= gfx_clipleft) || (cx >= gfx_clipright)) { goto SKIP; } if (cx < gfx_clipleft) { dec -= (gfx_clipleft - cx); sptr += (gfx_clipleft - cx); dptr += (gfx_clipleft - cx); cx = gfx_clipleft; } while ((cx < gfx_clipright) && (dec)) { *dptr = *sptr; cx++; sptr++; dptr++; dec--; } SKIP: cx += dec; sptr += dec; dptr += dec; } else { cx += (dec & 0x7f); dptr += (dec & 0x7f); } } } } goattracker-2.72/src/bme/makefile.win0000644000000000000000000000032411313456422016276 0ustar rootrootall: dat2inc.exe datafile.exe datafile.exe: datafile.c bme_end.c gcc -o datafile.exe datafile.c bme_end.c strip datafile.exe dat2inc.exe: dat2inc.c gcc -o dat2inc.exe dat2inc.c strip dat2inc.exe goattracker-2.72/src/bme/bme_snd.c0000644000000000000000000004150710774364076015602 0ustar rootroot// // BME (Blasphemous Multimedia Engine) sound main module // #include #include #include #include #include "bme_main.h" #include "bme_cfg.h" #include "bme_win.h" #include "bme_io.h" #include "bme_err.h" // Prototypes int snd_init(unsigned mixrate, unsigned mixmode, unsigned bufferlength, unsigned channels, int usedirectsound); void snd_uninit(void); void snd_setcustommixer(void (*custommixer)(Sint32 *dest, unsigned samples)); static int snd_initmixer(void); static void snd_uninitmixer(void); static void snd_mixdata(Uint8 *dest, unsigned bytes); static void snd_mixchannels(Sint32 *dest, unsigned samples); static void snd_mixer(void *userdata, Uint8 *stream, int len); // Lowlevel mixing functions static void snd_clearclipbuffer(Sint32 *clipbuffer, unsigned clipsamples); static void snd_mixchannel(CHANNEL *chptr, Sint32 *dest, unsigned samples); static void snd_16bit_postprocess(Sint32 *src, Sint16 *dest, unsigned samples); static void snd_8bit_postprocess(Sint32 *src, Uint8 *dest, unsigned samples); void (*snd_player)(void) = NULL; CHANNEL *snd_channel = NULL; int snd_channels = 0; int snd_sndinitted = 0; int snd_bpmcount; int snd_bpmtempo = 125; unsigned snd_mixmode; unsigned snd_mixrate; static void (*snd_custommixer)(Sint32 *dest, unsigned samples) = NULL; static unsigned snd_buffersize; static unsigned snd_samplesize; static unsigned snd_previouschannels = 0xffffffff; static int snd_atexit_registered = 0; static Sint32 *snd_clipbuffer = NULL; static SDL_AudioSpec desired; static SDL_AudioSpec obtained; int snd_init(unsigned mixrate, unsigned mixmode, unsigned bufferlength, unsigned channels, int usedirectsound) { int c; // Register snd_uninit as an atexit function if (!snd_atexit_registered) { atexit(snd_uninit); snd_atexit_registered = 1; } // If user wants to re-initialize, shutdown first snd_uninit(); // Check for illegal config if ((channels < 1) || (!mixrate) || (!bufferlength)) { bme_error = BME_ILLEGAL_CONFIG; snd_uninit(); return BME_ERROR; } desired.freq = mixrate; desired.format = AUDIO_U8; if (mixmode & SIXTEENBIT) { desired.format = AUDIO_S16SYS; } desired.channels = 1; if (mixmode & STEREO) desired.channels = 2; desired.samples = bufferlength * mixrate / 1000; { int bits = 0; for (;;) { desired.samples >>= 1; if (!desired.samples) break; bits++; } desired.samples = 1 << bits; } desired.callback = snd_mixer; desired.userdata = NULL; // Init tempo count snd_bpmcount = 0; // (Re)allocate channels if necessary if (snd_previouschannels != channels) { CHANNEL *chptr; if (snd_channel) { free(snd_channel); snd_channel = NULL; snd_channels = 0; } snd_channel = malloc(channels * sizeof(CHANNEL)); if (!snd_channel) { bme_error = BME_OUT_OF_MEMORY; snd_uninit(); return BME_ERROR; } chptr = &snd_channel[0]; snd_channels = channels; snd_previouschannels = channels; // Init all channels (no sound played, no sample, mastervolume 64) for (c = snd_channels; c > 0; c--) { chptr->voicemode = VM_OFF; chptr->smp = NULL; chptr->mastervol = 64; chptr++; } } SDL_PauseAudio(1); if (SDL_OpenAudio(&desired, &obtained)) { bme_error = BME_OPEN_ERROR; snd_uninit(); return BME_ERROR; } snd_sndinitted = 1; snd_mixmode = 0; snd_samplesize = 1; if (obtained.channels == 2) { snd_mixmode |= STEREO; snd_samplesize <<= 1; } if ((obtained.format == AUDIO_S16SYS) || (obtained.format == AUDIO_S16LSB) || (obtained.format == AUDIO_S16MSB)) { snd_mixmode |= SIXTEENBIT; snd_samplesize <<= 1; } snd_buffersize = obtained.size; snd_mixrate = obtained.freq; // Allocate mixer tables if (!snd_initmixer()) { bme_error = BME_OUT_OF_MEMORY; snd_uninit(); return BME_ERROR; } SDL_PauseAudio(0); bme_error = BME_OK; return BME_OK; } void snd_uninit(void) { if (snd_sndinitted) { SDL_CloseAudio(); snd_sndinitted = 0; } snd_uninitmixer(); } void snd_setcustommixer(void (*custommixer)(Sint32 *dest, unsigned samples)) { snd_custommixer = custommixer; } static int snd_initmixer(void) { snd_uninitmixer(); if (snd_mixmode & STEREO) { snd_clipbuffer = malloc((snd_buffersize / snd_samplesize) * sizeof(int) * 2); } else { snd_clipbuffer = malloc((snd_buffersize / snd_samplesize) * sizeof(int)); } if (!snd_clipbuffer) return 0; return 1; } static void snd_uninitmixer(void) { if (snd_clipbuffer) { free(snd_clipbuffer); snd_clipbuffer = NULL; } } static void snd_mixer(void *userdata, Uint8 *stream, int len) { snd_mixdata(stream, len); } static void snd_mixdata(Uint8 *dest, unsigned bytes) { unsigned mixsamples = bytes; unsigned clipsamples = bytes; Sint32 *clipptr = (Sint32 *)snd_clipbuffer; if (snd_mixmode & STEREO) mixsamples >>= 1; if (snd_mixmode & SIXTEENBIT) { clipsamples >>= 1; mixsamples >>= 1; } snd_clearclipbuffer(snd_clipbuffer, clipsamples); if (snd_player) // Must the player be called? { int musicsamples; while(mixsamples) { if ((!snd_bpmcount) && (snd_player)) // Player still active? { // Call player snd_player(); // Reset tempocounter snd_bpmcount = ((snd_mixrate * 5) >> 1) / snd_bpmtempo; } musicsamples = mixsamples; if (musicsamples > snd_bpmcount) musicsamples = snd_bpmcount; snd_bpmcount -= musicsamples; if (!snd_custommixer) { snd_mixchannels(clipptr, musicsamples); } else { snd_custommixer(clipptr, musicsamples); } if (snd_mixmode & STEREO) clipptr += musicsamples * 2; else clipptr += musicsamples; mixsamples -= musicsamples; } } else { if (!snd_custommixer) { snd_mixchannels(clipptr, mixsamples); } else { snd_custommixer(clipptr, mixsamples); } } clipptr = (Sint32 *)snd_clipbuffer; if (snd_mixmode & SIXTEENBIT) { snd_16bit_postprocess(clipptr, (Sint16 *)dest, clipsamples); } else { snd_8bit_postprocess(clipptr, dest, clipsamples); } } static void snd_mixchannels(Sint32 *dest, unsigned samples) { CHANNEL *chptr = &snd_channel[0]; int c; for (c = snd_channels; c; c--) { snd_mixchannel(chptr, dest, samples); chptr++; } } static void snd_clearclipbuffer(Sint32 *clipbuffer, unsigned clipsamples) { memset(clipbuffer, 0, clipsamples*sizeof(int)); } static void snd_16bit_postprocess(Sint32 *src, Sint16 *dest, unsigned samples) { while (samples--) { int sample = *src++; if (sample > 32767) sample = 32767; if (sample < -32768) sample = -32768; *dest++ = sample; } } static void snd_8bit_postprocess(Sint32 *src, Uint8 *dest, unsigned samples) { while (samples--) { int sample = *src++; if (sample > 32767) sample = 32767; if (sample < -32768) sample = -32768; *dest++ = (sample >> 8) + 128; } } static void snd_mixchannel(CHANNEL *chptr, Sint32 *dest, unsigned samples) { if (chptr->voicemode & VM_ON) { unsigned freq, intadd, fractadd; freq = chptr->freq; if (freq > 535232) freq = 535232; intadd = freq / snd_mixrate; fractadd = (((freq % snd_mixrate) << 16) / snd_mixrate) & 65535; if (snd_mixmode & STEREO) { int leftvol = (((chptr->vol * chptr->mastervol) >> 6) * (255-chptr->panning)) >> 7; int rightvol = (((chptr->vol * chptr->mastervol) >> 6) * (chptr->panning)) >> 7; if (leftvol > 255) leftvol = 255; if (rightvol > 255) rightvol = 255; if (leftvol < 0) leftvol = 0; if (rightvol < 0) rightvol = 0; if (chptr->voicemode & VM_16BIT) { Sint16 *pos = (Sint16 *)chptr->pos; Sint16 *end = (Sint16 *)chptr->end; Sint16 *repeat = (Sint16 *)chptr->repeat; if (chptr->voicemode & VM_LOOP) { while (samples--) { *dest = *dest + ((*pos * leftvol) >> 8); dest++; *dest = *dest + ((*pos * rightvol) >> 8); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; while (pos >= end) pos -= (end - repeat); } } else { while (samples--) { *dest = *dest + ((*pos * leftvol) >> 8); dest++; *dest = *dest + ((*pos * rightvol) >> 8); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; if (pos >= end) { chptr->voicemode &= ~VM_ON; break; } } } chptr->pos = (Sint8 *)pos; } else { Sint8 *pos = (Sint8 *)chptr->pos; Sint8 *end = chptr->end; Sint8 *repeat = chptr->repeat; if (chptr->voicemode & VM_LOOP) { while (samples--) { *dest = *dest + (*pos * leftvol); dest++; *dest = *dest + (*pos * rightvol); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; while (pos >= end) pos -= (end - repeat); } } else { while (samples--) { *dest = *dest + (*pos * leftvol); dest++; *dest = *dest + (*pos * rightvol); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; if (pos >= end) { chptr->voicemode &= ~VM_ON; break; } } } chptr->pos = (Sint8 *)pos; } } else { int vol = ((chptr->vol * chptr->mastervol) >> 6); if (vol > 255) vol = 255; if (vol < 0) vol = 0; if (chptr->voicemode & VM_16BIT) { Sint16 *pos = (Sint16 *)chptr->pos; Sint16 *end = (Sint16 *)chptr->end; Sint16 *repeat = (Sint16 *)chptr->repeat; if (chptr->voicemode & VM_LOOP) { while (samples--) { *dest = *dest + ((*pos * vol) >> 8); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; while (pos >= end) pos -= (end - repeat); } } else { while (samples--) { *dest = *dest + ((*pos * vol) >> 8); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; if (pos >= end) { chptr->voicemode &= ~VM_ON; break; } } } chptr->pos = (Sint8 *)pos; } else { Sint8 *pos = (Sint8 *)chptr->pos; Sint8 *end = chptr->end; Sint8 *repeat = chptr->repeat; if (chptr->voicemode & VM_LOOP) { while (samples--) { *dest = *dest + (*pos * vol); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; while (pos >= end) pos -= (end - repeat); } } else { while (samples--) { *dest = *dest + (*pos * vol); dest++; chptr->fractpos += fractadd; if (chptr->fractpos > 65535) { chptr->fractpos &= 65535; pos++; } pos += intadd; if (pos >= end) { chptr->voicemode &= ~VM_ON; break; } } } chptr->pos = (Sint8 *)pos; } } } } goattracker-2.72/src/bme/bme_gfx.h0000644000000000000000000000230110774364076015574 0ustar rootroot// BME graphics module header file int gfx_init(unsigned xsize, unsigned ysize, unsigned framerate, unsigned flags); int gfx_reinit(void); void gfx_uninit(void); int gfx_lock(void); void gfx_unlock(void); void gfx_flip(void); void gfx_setclipregion(unsigned left, unsigned top, unsigned right, unsigned bottom); void gfx_setmaxspritefiles(int num); void gfx_setmaxcolors(int num); int gfx_loadpalette(char *name); void gfx_calcpalette(int fade, int radd, int gadd, int badd); void gfx_setpalette(void); int gfx_loadblocks(char *name); int gfx_loadsprites(int num, char *name); void gfx_freesprites(int num); void gfx_drawsprite(int x, int y, unsigned num); extern int gfx_initted; extern int gfx_scanlinemode; extern int gfx_preventswitch; extern int gfx_fullscreen; extern int gfx_redraw; extern unsigned gfx_windowxsize; extern unsigned gfx_windowysize; extern unsigned gfx_virtualxsize; extern unsigned gfx_virtualysize; extern unsigned gfx_nblocks; extern int gfx_blockxsize; extern int gfx_blockysize; extern int spr_xsize; extern int spr_ysize; extern int spr_xhotspot; extern int spr_yhotspot; extern Uint8 *gfx_vscreen; extern Uint8 *gfx_blocks; extern Uint8 gfx_palette[]; extern SDL_Surface *gfx_screen; goattracker-2.72/src/bme/bme_io.c0000644000000000000000000002021311036462276015405 0ustar rootroot// // BME (Blasphemous Multimedia Engine) datafile IO main module // #include #include #include #include #include #include "bme_main.h" #include "bme_err.h" #include "bme_cfg.h" typedef struct { Uint32 offset; Sint32 length; char name[13]; } HEADER; typedef struct { HEADER *currentheader; int filepos; int open; } HANDLE; static int io_usedatafile = 0; static HEADER *fileheaders; static unsigned files; static char ident[4]; static char *idstring = "DAT!"; static HANDLE handle[MAX_HANDLES]; static FILE *fileptr[MAX_HANDLES] = {NULL}; static FILE *datafilehandle = NULL; static unsigned char *datafileptr; static unsigned char *datafilestart; static unsigned freadle32(FILE *index); static void linkedseek(unsigned pos); static void linkedread(void *buffer, int length); static unsigned linkedreadle32(void); void io_setfilemode(int usedf) { io_usedatafile = usedf; } int io_openlinkeddatafile(unsigned char *ptr) { int index; if (datafilehandle) fclose(datafilehandle); datafilehandle = NULL; datafilestart = ptr; linkedseek(0); linkedread(ident, 4); if (memcmp(ident, idstring, 4)) { bme_error = BME_WRONG_FORMAT; return BME_ERROR; } files = linkedreadle32(); fileheaders = malloc(files * sizeof(HEADER)); if (!fileheaders) { bme_error = BME_OUT_OF_MEMORY; return BME_ERROR; } for (index = 0; index < files; index++) { fileheaders[index].offset = linkedreadle32(); fileheaders[index].length = linkedreadle32(); linkedread(&fileheaders[index].name, 13); } for (index = 0; index < MAX_HANDLES; index++) handle[index].open = 0; io_usedatafile = 1; bme_error = BME_OK; return BME_OK; } int io_opendatafile(char *name) { int index; if (name) { datafilehandle = fopen(name, "rb"); if (!datafilehandle) { bme_error = BME_OPEN_ERROR; return BME_ERROR; } } fread(ident, 4, 1, datafilehandle); if (memcmp(ident, idstring, 4)) { bme_error = BME_WRONG_FORMAT; return BME_ERROR; } files = freadle32(datafilehandle); fileheaders = malloc(files * sizeof(HEADER)); if (!fileheaders) { bme_error = BME_OUT_OF_MEMORY; return BME_ERROR; } for (index = 0; index < files; index++) { fileheaders[index].offset = freadle32(datafilehandle); fileheaders[index].length = freadle32(datafilehandle); fread(&fileheaders[index].name, 13, 1, datafilehandle); } for (index = 0; index < MAX_HANDLES; index++) handle[index].open = 0; io_usedatafile = 1; bme_error = BME_OK; return BME_OK; } // Returns nonnegative file handle if successful, -1 on error int io_open(char *name) { if (!name) return -1; if (!io_usedatafile) { int index; for (index = 0; index < MAX_HANDLES; index++) { if (!fileptr[index]) break; } if (index == MAX_HANDLES) return -1; else { FILE *file = fopen(name, "rb"); if (!file) { return -1; } else { fileptr[index] = file; return index; } } } else { int index; int namelength; char namecopy[13]; namelength = strlen(name); if (namelength > 12) namelength = 12; memcpy(namecopy, name, namelength + 1); for (index = 0; index < strlen(namecopy); index++) { namecopy[index] = toupper(namecopy[index]); } for (index = 0; index < MAX_HANDLES; index++) { if (!handle[index].open) { int count = files; handle[index].currentheader = fileheaders; while (count) { if (!strcmp(namecopy, handle[index].currentheader->name)) { handle[index].open = 1; handle[index].filepos = 0; return index; } count--; handle[index].currentheader++; } return -1; } } return -1; } } // Returns file position after seek or -1 on error int io_lseek(int index, int offset, int whence) { if (!io_usedatafile) { fseek(fileptr[index], offset, whence); return ftell(fileptr[index]); } else { int newpos; if ((index < 0) || (index >= MAX_HANDLES)) return -1; if (!handle[index].open) return -1; switch(whence) { default: case SEEK_SET: newpos = offset; break; case SEEK_CUR: newpos = offset + handle[index].filepos; break; case SEEK_END: newpos = offset + handle[index].currentheader->length; break; } if (newpos < 0) newpos = 0; if (newpos > handle[index].currentheader->length) newpos = handle[index].currentheader->length; handle[index].filepos = newpos; return newpos; } } // Returns number of bytes actually read, -1 on error int io_read(int index, void *buffer, int length) { if (!io_usedatafile) { return fread(buffer, 1, length, fileptr[index]); } else { int readbytes; if ((index < 0) || (index >= MAX_HANDLES)) return -1; if (!handle[index].open) return -1; if (length + handle[index].filepos > handle[index].currentheader->length) length = handle[index].currentheader->length - handle[index].filepos; if (datafilehandle) { fseek(datafilehandle, handle[index].currentheader->offset + handle[index].filepos, SEEK_SET); readbytes = fread(buffer, 1, length, datafilehandle); } else { linkedseek(handle[index].currentheader->offset + handle[index].filepos); linkedread(buffer, length); readbytes = length; } handle[index].filepos += readbytes; return readbytes; } } // Returns nothing void io_close(int index) { if (!io_usedatafile) { fclose(fileptr[index]); fileptr[index] = NULL; } else { if ((index < 0) || (index >= MAX_HANDLES)) return; handle[index].open = 0; } } unsigned io_read8(int index) { unsigned char byte; io_read(index, &byte, 1); return byte; } unsigned io_readle16(int index) { unsigned char bytes[2]; io_read(index, bytes, 2); return (bytes[1] << 8) | bytes[0]; } unsigned io_readhe16(int index) { unsigned char bytes[2]; io_read(index, bytes, 2); return (bytes[0] << 8) | bytes[1]; } unsigned io_readle32(int index) { unsigned char bytes[4]; io_read(index, bytes, 4); return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; } unsigned io_readhe32(int index) { unsigned char bytes[4]; io_read(index, bytes, 4); return (bytes[0] << 24) | (bytes[1] << 16) | (bytes[2] << 8) | bytes[3]; } static unsigned freadle32(FILE *file) { unsigned char bytes[4]; fread(&bytes, 4, 1, file); return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; } static void linkedseek(unsigned pos) { datafileptr = &datafilestart[pos]; } static void linkedread(void *buffer, int length) { unsigned char *dest = (unsigned char *)buffer; while (length--) { *dest++ = *datafileptr++; } } static unsigned linkedreadle32(void) { unsigned char bytes[4]; linkedread(&bytes, 4); return (bytes[3] << 24) | (bytes[2] << 16) | (bytes[1] << 8) | bytes[0]; } goattracker-2.72/src/bme/bme_joy.h0000644000000000000000000000017010774364076015613 0ustar rootroot// Joystick functions header file int joy_detect(unsigned id); unsigned joy_getstatus(unsigned id, int threshold); goattracker-2.72/src/bme/makefile0000644000000000000000000000026411313456422015505 0ustar rootrootall: dat2inc datafile datafile: datafile.c bme_end.c gcc -o datafile datafile.c bme_end.c strip datafile dat2inc: dat2inc.c gcc -o dat2inc dat2inc.c strip dat2inc goattracker-2.72/src/bme/bme_win.h0000644000000000000000000000147210774364076015615 0ustar rootroot// BME windows, input & timing module header file int win_openwindow(char *appname, char *icon); void win_closewindow(void); void win_messagebox(char *string); void win_checkmessages(void); int win_getspeed(int framerate); void win_setmousemode(int mode); extern int win_windowinitted; extern int win_quitted; extern int win_fullscreen; extern unsigned char win_keytable[MAX_KEYS]; extern unsigned char win_keystate[MAX_KEYS]; extern unsigned char win_asciikey; extern unsigned win_virtualkey; extern unsigned win_mousexpos; extern unsigned win_mouseypos; extern unsigned win_mousexrel; extern unsigned win_mouseyrel; extern unsigned win_mousebuttons; extern int win_mousemode; SDL_Joystick *joy[MAX_JOYSTICKS]; extern Sint16 joyx[MAX_JOYSTICKS]; extern Sint16 joyy[MAX_JOYSTICKS]; extern Uint32 joybuttons[MAX_JOYSTICKS]; goattracker-2.72/src/bme/bme_win.c0000644000000000000000000001434410774364074015610 0ustar rootroot// // BME (Blasphemous Multimedia Engine) windows & timing module // #include #include #include #include #include "bme_main.h" #include "bme_gfx.h" #include "bme_mou.h" #include "bme_io.h" #include "bme_err.h" #include "bme_cfg.h" SDL_Joystick *joy[MAX_JOYSTICKS] = {NULL}; Sint16 joyx[MAX_JOYSTICKS]; Sint16 joyy[MAX_JOYSTICKS]; Uint32 joybuttons[MAX_JOYSTICKS]; // Prototypes int win_openwindow(char *appname, char *icon); void win_closewindow(void); void win_messagebox(char *string); void win_checkmessages(void); int win_getspeed(int framerate); void win_setmousemode(int mode); // Global variables int win_fullscreen = 0; // By default windowed int win_windowinitted = 0; int win_quitted = 0; unsigned char win_keytable[MAX_KEYS] = {0}; unsigned char win_asciikey = 0; unsigned win_virtualkey = 0; unsigned win_mousexpos = 0; unsigned win_mouseypos = 0; unsigned win_mousexrel = 0; unsigned win_mouseyrel = 0; unsigned win_mousebuttons = 0; int win_mousemode = MOUSE_FULLSCREEN_HIDDEN; unsigned char win_keystate[MAX_KEYS] = {0}; // Static variables static int win_lasttime = 0; static int win_currenttime = 0; static int win_framecounter = 0; static int win_activateclick = 0; int win_openwindow(char *appname, char *icon) { if (!win_windowinitted) { if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK) < 0) { return BME_ERROR; } atexit(SDL_Quit); win_windowinitted = 1; } SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); SDL_EnableUNICODE(1); SDL_WM_SetCaption(appname, icon); return BME_OK; } void win_closewindow(void) { } void win_messagebox(char *string) { return; } int win_getspeed(int framerate) { // Note: here 1/10000th of a second accuracy is used (although // timer resolution is only millisecond) for minimizing // inaccuracy in frame duration calculation -> smoother screen // update int frametime = 10000 / framerate; int frames = 0; while (!frames) { win_checkmessages(); win_lasttime = win_currenttime; win_currenttime = SDL_GetTicks(); win_framecounter += (win_currenttime - win_lasttime)*10; frames = win_framecounter / frametime; win_framecounter -= frames * frametime; if (!frames) SDL_Delay((frametime - win_framecounter)/10); } return frames; } // This is the "message pump". Called by following functions: // win_getspeed(); // kbd_waitkey(); // // It is recommended to be called in any long loop where those two functions // are not called. void win_checkmessages(void) { SDL_Event event; unsigned keynum; win_activateclick = 0; SDL_PumpEvents(); while (SDL_PollEvent(&event)) { switch (event.type) { case SDL_JOYBUTTONDOWN: joybuttons[event.jbutton.which] |= 1 << event.jbutton.button; break; case SDL_JOYBUTTONUP: joybuttons[event.jbutton.which] &= ~(1 << event.jbutton.button); break; case SDL_JOYAXISMOTION: switch (event.jaxis.axis) { case 0: joyx[event.jaxis.which] = event.jaxis.value; break; case 1: joyy[event.jaxis.which] = event.jaxis.value; break; } break; case SDL_MOUSEMOTION: win_mousexpos = event.motion.x; win_mouseypos = event.motion.y; win_mousexrel += event.motion.xrel; win_mouseyrel += event.motion.yrel; break; case SDL_MOUSEBUTTONDOWN: switch(event.button.button) { case SDL_BUTTON_LEFT: win_mousebuttons |= MOUSEB_LEFT; break; case SDL_BUTTON_MIDDLE: win_mousebuttons |= MOUSEB_MIDDLE; break; case SDL_BUTTON_RIGHT: win_mousebuttons |= MOUSEB_RIGHT; break; } break; case SDL_MOUSEBUTTONUP: switch(event.button.button) { case SDL_BUTTON_LEFT: win_mousebuttons &= ~MOUSEB_LEFT; break; case SDL_BUTTON_MIDDLE: win_mousebuttons &= ~MOUSEB_MIDDLE; break; case SDL_BUTTON_RIGHT: win_mousebuttons &= ~MOUSEB_RIGHT; break; } break; case SDL_QUIT: win_quitted = 1; break; case SDL_KEYDOWN: win_virtualkey = event.key.keysym.sym; win_asciikey = event.key.keysym.unicode; keynum = event.key.keysym.sym; if (keynum < MAX_KEYS) { win_keytable[keynum] = 1; win_keystate[keynum] = 1; if ((keynum == KEY_ENTER) && ((win_keystate[KEY_ALT]) || (win_keystate[KEY_RIGHTALT]))) { win_fullscreen ^= 1; gfx_reinit(); } } break; case SDL_KEYUP: keynum = event.key.keysym.sym; if (keynum < MAX_KEYS) { win_keytable[keynum] = 0; win_keystate[keynum] = 0; } break; case SDL_VIDEORESIZE: case SDL_VIDEOEXPOSE: gfx_redraw = 1; break; } } } void win_setmousemode(int mode) { win_mousemode = mode; switch(mode) { case MOUSE_ALWAYS_VISIBLE: SDL_ShowCursor(SDL_ENABLE); break; case MOUSE_FULLSCREEN_HIDDEN: if (gfx_fullscreen) { SDL_ShowCursor(SDL_DISABLE); } else { SDL_ShowCursor(SDL_ENABLE); } break; case MOUSE_ALWAYS_HIDDEN: SDL_ShowCursor(SDL_DISABLE); break; } } goattracker-2.72/src/bme/bme.h0000644000000000000000000000046610774364076014742 0ustar rootroot// BME header file for user applications #ifndef BME_H #define BME_H #include #include "bme_main.h" #include "bme_cfg.h" #include "bme_err.h" #include "bme_snd.h" #include "bme_gfx.h" #include "bme_win.h" #include "bme_kbd.h" #include "bme_mou.h" #include "bme_io.h" #include "bme_end.h" #endif goattracker-2.72/src/bme/bme_kbd.c0000644000000000000000000000763110774364076015556 0ustar rootroot// // BME (Blasphemous Multimedia Engine) keyboard module // #include #include #include #include #include "bme_main.h" #include "bme_cfg.h" #include "bme_win.h" #include "bme_io.h" #include "bme_err.h" int kbd_init(void); void kbd_uninit(void); int kbd_waitkey(void); int kbd_getkey(void); int kbd_checkkey(int rawcode); int kbd_getascii(void); unsigned kbd_getvirtualkey(void); char *kbd_getkeyname(int rawcode); static KEY keyname[] = {{KEY_BACKSPACE, "BACKSPACE"}, {KEY_CAPSLOCK, "CAPSLOCK"}, {KEY_ENTER, "ENTER"}, {KEY_ESC, "ESC"}, {KEY_NUMLOCK, "NUMLOCK"}, {KEY_LEFTSHIFT, "SHIFT"}, {KEY_RIGHTSHIFT, "SHIFT"}, {KEY_SCROLLLOCK, "SCR. LOCK"}, {KEY_SPACE, "SPACE"}, {KEY_TAB, "TAB"}, {KEY_F1, "F1"}, {KEY_F2, "F2"}, {KEY_F3, "F3"}, {KEY_F4, "F4"}, {KEY_F5, "F5"}, {KEY_F6, "F6"}, {KEY_F7, "F7"}, {KEY_F8, "F8"}, {KEY_F9, "F9"}, {KEY_F10, "F10"}, {KEY_F11, "F11"}, {KEY_F12, "F12"}, {KEY_A, "A"}, {KEY_N, "N"}, {KEY_B, "B"}, {KEY_O, "O"}, {KEY_C, "C"}, {KEY_P, "P"}, {KEY_D, "D"}, {KEY_Q, "Q"}, {KEY_E, "E"}, {KEY_R, "R"}, {KEY_F, "F"}, {KEY_S, "S"}, {KEY_G, "G"}, {KEY_T, "T"}, {KEY_H, "H"}, {KEY_U, "U"}, {KEY_I, "I"}, {KEY_V, "V"}, {KEY_J, "J"}, {KEY_W, "W"}, {KEY_K, "K"}, {KEY_X, "X"}, {KEY_L, "L"}, {KEY_Y, "Y"}, {KEY_M, "M"}, {KEY_Z, "Z"}, {KEY_1, "1"}, {KEY_2, "2"}, {KEY_3, "3"}, {KEY_4, "4"}, {KEY_5, "5"}, {KEY_6, "6"}, {KEY_7, "7"}, {KEY_8, "8"}, {KEY_9, "9"}, {KEY_0, "0"}, {KEY_MINUS, "-"}, {KEY_EQUAL, "="}, {KEY_BRACKETL, "["}, {KEY_BRACKETR, "]"}, {KEY_SEMICOLON, ";"}, {KEY_APOST1, "'"}, {KEY_APOST2, "`"}, {KEY_COMMA, ","}, {KEY_COLON, "."}, {KEY_SLASH, "/"}, {KEY_BACKSLASH, "\\"}, {KEY_ALT, "ALT"}, {KEY_CTRL, "CTRL"}, {KEY_DEL, "DELETE"}, {KEY_DOWN, "CRS. DOWN"}, {KEY_END, "END"}, {KEY_HOME, "HOME"}, {KEY_INS, "INSERT"}, {KEY_LEFT, "CRS. LEFT"}, {KEY_PGDN, "PAGE DOWN"}, {KEY_PGUP, "PAGE UP"}, {KEY_RIGHT, "CRS. RIGHT"}, {KEY_UP, "CRS. UP"}, {KEY_WINDOWSL, "WINDOWS KEY"}, {KEY_WINDOWSR, "WINDOWS KEY"}, {KEY_MENU, "MENU KEY"}, {0xff, "?"}}; int kbd_init(void) { return BME_OK; } void kbd_uninit(void) { } int kbd_waitkey(void) { int index; win_asciikey = 0; for (;;) { win_checkmessages(); for (index = 0; index < MAX_KEYS; index++) { if (win_keytable[index]) { win_keytable[index] = 0; return index; } } SDL_Delay(15); } } int kbd_getkey(void) { int index; for (index = 0; index < MAX_KEYS; index++) { if (win_keytable[index]) { win_keytable[index] = 0; return index; } } return 0; } int kbd_checkkey(int rawcode) { if (rawcode >= MAX_KEYS) return 0; if (win_keytable[rawcode]) { win_keytable[rawcode] = 0; return 1; } return 0; } int kbd_getascii(void) { int key; if (win_asciikey) { key = win_asciikey; win_asciikey = 0; return key; } else return 0; } unsigned kbd_getvirtualkey(void) { unsigned key; if (win_virtualkey) { key = win_virtualkey; win_virtualkey = 0; return key; } else return 0; } char *kbd_getkeyname(int rawcode) { KEY *ptr = &keyname[0]; while (ptr->rawcode != 255) { if (ptr->rawcode == rawcode) { return ptr->name; } ptr++; } return ptr->name; } goattracker-2.72/src/bme/bme_snd.h0000644000000000000000000000141710774364076015603 0ustar rootroot// Sound functions header file int snd_init(unsigned mixrate, unsigned mixmode, unsigned bufferlength, unsigned channels, int usedirectsound); void snd_uninit(void); void snd_setcustommixer(void (*custommixer)(Sint32 *dest, unsigned samples)); void snd_preventdistortion(unsigned channels); void snd_setmastervolume(unsigned chnum, unsigned char mastervol); void snd_setmusicmastervolume(unsigned musicchannels, unsigned char mastervol); void snd_setsfxmastervolume(unsigned musicchannels, unsigned char mastervol); extern void (*snd_player)(void); extern CHANNEL *snd_channel; extern int snd_sndinitted; extern int snd_bpmtempo; extern int snd_bpmcount; extern int snd_channels; extern int snd_buffers; extern unsigned snd_mixmode; extern unsigned snd_mixrate; goattracker-2.72/src/bme/bme_err.h0000644000000000000000000000064210774364076015606 0ustar rootroot// BME error code header file // BME function return codes #define BME_OK 1 #define BME_ERROR 0 // BME detailed error types (in bme_error) #define BME_OPEN_ERROR -1 #define BME_READ_ERROR -2 #define BME_WRONG_FORMAT -3 #define BME_OUT_OF_MEMORY -4 #define BME_THREAD_ERROR -5 #define BME_ILLEGAL_CONFIG -6 #define BME_OUT_OF_CHANNELS -7 #define BME_GRAPHICS_ERROR -8 #define BME_SOUND_ERROR -9 goattracker-2.72/src/bme/bme_main.h0000644000000000000000000001312510774364076015742 0ustar rootroot// BME main definitions header file #define GFX_SCANLINES 1 #define GFX_DOUBLESIZE 2 #define GFX_USE1PAGE 0 #define GFX_USE2PAGES 4 #define GFX_USE3PAGES 8 #define GFX_WAITVBLANK 16 #define GFX_FULLSCREEN 32 #define GFX_WINDOW 64 #define GFX_NOSWITCHING 128 #define GFX_USEDIBSECTION 256 #define MOUSE_ALWAYS_VISIBLE 0 #define MOUSE_FULLSCREEN_HIDDEN 1 #define MOUSE_ALWAYS_HIDDEN 2 #define MOUSEB_LEFT 1 #define MOUSEB_RIGHT 2 #define MOUSEB_MIDDLE 4 #define JOY_LEFT 1 #define JOY_RIGHT 2 #define JOY_UP 4 #define JOY_DOWN 8 #define JOY_FIRE1 16 #define JOY_FIRE2 32 #define JOY_FIRE3 64 #define JOY_FIRE4 128 #define LEFT 0 #define MIDDLE 128 #define RIGHT 255 #define B_OFF 0 #define B_SOLID 1 #define B_NOTSOLID 2 #define MONO 0 #define STEREO 1 #define EIGHTBIT 0 #define SIXTEENBIT 2 #define VM_OFF 0 #define VM_ON 1 #define VM_ONESHOT 0 #define VM_LOOP 2 #define VM_16BIT 4 #define KEY_BACKSPACE SDLK_BACKSPACE #define KEY_CAPSLOCK SDLK_CAPSLOCK #define KEY_ENTER SDLK_RETURN #define KEY_ESC SDLK_ESCAPE #define KEY_ALT SDLK_LALT #define KEY_CTRL SDLK_LCTRL #define KEY_LEFTCTRL SDLK_LCTRL #define KEY_RIGHTALT SDLK_RALT #define KEY_RIGHTCTRL SDLK_RCTRL #define KEY_LEFTSHIFT SDLK_LSHIFT #define KEY_RIGHTSHIFT SDLK_RSHIFT #define KEY_NUMLOCK SDLK_NUMLOCK #define KEY_SCROLLLOCK SDLK_SCROLLOCK #define KEY_SPACE SDLK_SPACE #define KEY_TAB SDLK_TAB #define KEY_F1 SDLK_F1 #define KEY_F2 SDLK_F2 #define KEY_F3 SDLK_F3 #define KEY_F4 SDLK_F4 #define KEY_F5 SDLK_F5 #define KEY_F6 SDLK_F6 #define KEY_F7 SDLK_F7 #define KEY_F8 SDLK_F8 #define KEY_F9 SDLK_F9 #define KEY_F10 SDLK_F10 #define KEY_F11 SDLK_F11 #define KEY_F12 SDLK_F12 #define KEY_A SDLK_a #define KEY_N SDLK_n #define KEY_B SDLK_b #define KEY_O SDLK_o #define KEY_C SDLK_c #define KEY_P SDLK_p #define KEY_D SDLK_d #define KEY_Q SDLK_q #define KEY_E SDLK_e #define KEY_R SDLK_r #define KEY_F SDLK_f #define KEY_S SDLK_s #define KEY_G SDLK_g #define KEY_T SDLK_t #define KEY_H SDLK_h #define KEY_U SDLK_u #define KEY_I SDLK_i #define KEY_V SDLK_v #define KEY_J SDLK_j #define KEY_W SDLK_w #define KEY_K SDLK_k #define KEY_X SDLK_x #define KEY_L SDLK_l #define KEY_Y SDLK_y #define KEY_M SDLK_m #define KEY_Z SDLK_z #define KEY_1 SDLK_1 #define KEY_2 SDLK_2 #define KEY_3 SDLK_3 #define KEY_4 SDLK_4 #define KEY_5 SDLK_5 #define KEY_6 SDLK_6 #define KEY_7 SDLK_7 #define KEY_8 SDLK_8 #define KEY_9 SDLK_9 #define KEY_0 SDLK_0 #define KEY_MINUS SDLK_MINUS #define KEY_EQUAL SDLK_EQUALS #define KEY_BRACKETL SDLK_LEFTBRACKET #define KEY_BRACKETR SDLK_RIGHTBRACKET #define KEY_SEMICOLON SDLK_SEMICOLON #define KEY_APOST1 SDLK_QUOTE #define KEY_APOST2 SDLK_BACKQUOTE #define KEY_COMMA SDLK_COMMA #define KEY_COLON SDLK_PERIOD #define KEY_PERIOD SDLK_PERIOD #define KEY_SLASH SDLK_SLASH #define KEY_BACKSLASH SDLK_BACKSLASH #define KEY_DEL SDLK_DELETE #define KEY_DOWN SDLK_DOWN #define KEY_END SDLK_END #define KEY_HOME SDLK_HOME #define KEY_INS SDLK_INSERT #define KEY_LEFT SDLK_LEFT #define KEY_PGDN SDLK_PAGEDOWN #define KEY_PGUP SDLK_PAGEUP #define KEY_RIGHT SDLK_RIGHT #define KEY_UP SDLK_UP #define KEY_WINDOWSL SDLK_LSUPER #define KEY_WINDOWSR SDLK_RSUPER #define KEY_MENU SDLK_MENU #define KEY_PAUSE SDLK_PAUSE #define KEY_KPDIVIDE SDLK_KP_DIVIDE #define KEY_KPMULTIPLY SDLK_KP_MULTIPLY #define KEY_KPPLUS SDLK_KP_PLUS #define KEY_KPMINUS SDLK_KP_MINUS #define KEY_KP0 SDLK_KP0 #define KEY_KP1 SDLK_KP1 #define KEY_KP2 SDLK_KP2 #define KEY_KP3 SDLK_KP3 #define KEY_KP4 SDLK_KP4 #define KEY_KP5 SDLK_KP5 #define KEY_KP6 SDLK_KP6 #define KEY_KP7 SDLK_KP7 #define KEY_KP8 SDLK_KP8 #define KEY_KP9 SDLK_KP9 #define KEY_KPUP SDLK_KP8 #define KEY_KPDOWN SDLK_KP2 #define KEY_KPLEFT SDLK_KP4 #define KEY_KPRIGHT SDLK_KP6 #define KEY_KPENTER SDLK_KP_ENTER #define KEY_KPEQUALS SDLK_KP_EQUALS #define KEY_KPPERIOD SDLK_KP_PERIOD typedef struct { Sint8 *start; Sint8 *repeat; Sint8 *end; unsigned char voicemode; } SAMPLE; typedef struct { volatile Sint8 *pos; Sint8 *repeat; Sint8 *end; SAMPLE *smp; unsigned freq; volatile unsigned fractpos; int vol; int mastervol; unsigned panning; volatile unsigned voicemode; } CHANNEL; typedef struct { unsigned rawcode; char *name; } KEY; typedef struct { Sint16 xsize; Sint16 ysize; Sint16 xhot; Sint16 yhot; Uint32 offset; } SPRITEHEADER; typedef struct { Uint32 type; Uint32 offset; } BLOCKHEADER; typedef struct { Uint8 blocksname[13]; Uint8 palettename[13]; } MAPHEADER; typedef struct { Sint32 xsize; Sint32 ysize; Uint8 xdivisor; Uint8 ydivisor; Uint8 xwrap; Uint8 ywrap; } LAYERHEADER; extern int bme_error; goattracker-2.72/src/bme/bme_end.h0000644000000000000000000000044610774364076015566 0ustar rootrootvoid fwrite8(FILE *file, unsigned data); void fwritele16(FILE *file, unsigned data); void fwritele32(FILE *file, unsigned data); unsigned fread8(FILE *file); unsigned freadle16(FILE *file); unsigned freadle32(FILE *file); unsigned freadhe16(FILE *file); unsigned freadhe32(FILE *file); goattracker-2.72/src/bme/bme_io.h0000644000000000000000000000071310774364076015424 0ustar rootroot// BME IO module header file int io_open(char *name); int io_lseek(int handle, int bytes, int whence); int io_read(int handle, void *buffer, int size); void io_close(int handle); int io_opendatafile(char *name); int io_openlinkeddatafile(unsigned char *ptr); void io_setfilemode(int usedf); unsigned io_read8(int handle); unsigned io_readle16(int handle); unsigned io_readle32(int handle); unsigned io_readhe16(int handle); unsigned io_readhe32(int handle); goattracker-2.72/src/bme/makefile.mos0000644000000000000000000000027711604130742016303 0ustar rootrootall: dat2inc datafile datafile: datafile.c bme_end.c gcc `sdl-config --cflags` -o datafile datafile.c bme_end.c strip datafile dat2inc: dat2inc.c gcc -o dat2inc dat2inc.c strip dat2inc goattracker-2.72/src/gtable.h0000644000000000000000000000164610774364076014673 0ustar rootroot#ifndef GTABLE_H #define GTABLE_H #define MST_NOFINEVIB 0 #define MST_FINEVIB 1 #define MST_FUNKTEMPO 2 #define MST_PORTAMENTO 3 #define MST_RAW 4 #ifndef GTABLE_C extern int etview[MAX_TABLES]; extern int etnum; extern int etpos; extern int etcolumn; extern int etlock; extern int etmarknum; extern int etmarkstart; extern int etmarkend; #endif void tablecommands(void); void tableup(void); void tabledown(void); void inserttable(int num, int pos, int mode); void deletetable(int num, int pos); int makespeedtable(unsigned data, int mode, int makenew); void optimizetable(int num); void deleteinstrtable(int i); int gettablelen(int num); int gettablepartlen(int num, int pos); void gototable(int num, int pos); void settableview(int num, int pos); void settableviewfirst(int num, int pos); void validatetableview(void); void exectable(int num, int ptr); int findfreespeedtable(void); #endif goattracker-2.72/src/gpattern.h0000644000000000000000000000100310774364076015244 0ustar rootroot#ifndef GPATTERN_H #define GPATTERN_H #ifndef GPATTERN_C extern int epnum[MAX_CHN]; extern int eppos; extern int epview; extern int epcolumn; extern int epchn; extern int epoctave; extern int epmarkchn; extern int epmarkstart; extern int epmarkend; #endif void patterncommands(void); void nextpattern(void); void prevpattern(void); void patternup(void); void patterndown(void); void shrinkpattern(void); void expandpattern(void); void splitpattern(void); void joinpattern(void); #endif goattracker-2.72/src/gsound.h0000644000000000000000000000142111012666210014700 0ustar rootroot#ifndef GSOUND_H #define GSOUND_H #ifdef GSOUND_C #ifdef __WIN32__ #include #else #include #include #include #include "cwsid.h" #endif #endif #define MINMIXRATE 11025 #define MAXMIXRATE 48000 #define MINBUF 20 #define MAXBUF 2000 #define DEFAULTBUF 100 #define DEFAULTMIXRATE 44100 #define PALFRAMERATE 50 #define PALCLOCKRATE 985248 #define NTSCFRAMERATE 60 #define NTSCCLOCKRATE 1022727 #define MIXBUFFERSIZE 65536 int sound_init(unsigned b, unsigned mr, unsigned writer, unsigned hardsid, unsigned m, unsigned ntsc, unsigned multiplier, unsigned catweasel, unsigned interpolate, unsigned customclockrate); void sound_uninit(void); void sound_suspend(void); void sound_flush(void); #endif goattracker-2.72/src/palette.bin0000644000000000000000000000140010774364074015376 0ustar rootroot *22"2222%%%""?(?(22?22?<??????goattracker-2.72/src/goattrk2.seq0000644000000000000000000000011310774364076015517 0ustar rootrootplayer.s altplayer.s chargen.bin palette.bin cursor.bin goattrk2.bmp goattracker-2.72/src/makefile.mos0000644000000000000000000000020211313456432015530 0ustar rootroot# # MorphOS makefile # CFLAGS=`sdl-config --cflags` PREFIX=../morphos/ SUFFIX= LIBS=`sdl-config --libs` include makefile.common goattracker-2.72/src/asm/0000755000000000000000000000000011604145110014010 5ustar rootrootgoattracker-2.72/src/asm/lexyy.c0000644000000000000000000016051110774364074015355 0ustar rootroot/* A lexical scanner generated by flex */ /* Scanner skeleton version: * $Header: /home/daffy/u0/vern/flex/RCS/flex.skl,v 2.91 96/09/10 16:58:48 vern Exp $ */ #define FLEX_SCANNER #define YY_FLEX_MAJOR_VERSION 2 #define YY_FLEX_MINOR_VERSION 5 #include #include /* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ #ifdef c_plusplus #ifndef __cplusplus #define __cplusplus #endif #endif #ifdef __cplusplus #include /* Use prototypes in function declarations. */ #define YY_USE_PROTOS /* The "const" storage-class-modifier is valid. */ #define YY_USE_CONST #else /* ! __cplusplus */ #if __STDC__ #define YY_USE_PROTOS #define YY_USE_CONST #endif /* __STDC__ */ #endif /* ! __cplusplus */ #ifdef __TURBOC__ #pragma warn -rch #pragma warn -use #include #include #define YY_USE_CONST #define YY_USE_PROTOS #endif #ifdef YY_USE_CONST #define yyconst const #else #define yyconst #endif #ifdef YY_USE_PROTOS #define YY_PROTO(proto) proto #else #define YY_PROTO(proto) () #endif /* Returned upon end-of-file. */ #define YY_NULL 0 /* Promotes a possibly negative, possibly signed char to an unsigned * integer for use as an array index. If the signed char is negative, * we want to instead treat it as an 8-bit unsigned char, hence the * double cast. */ #define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) /* Enter a start condition. This macro really ought to take a parameter, * but we do it the disgusting crufty way forced on us by the ()-less * definition of BEGIN. */ #define BEGIN yy_start = 1 + 2 * /* Translate the current start state into a value that can be later handed * to BEGIN to return to the state. The YYSTATE alias is for lex * compatibility. */ #define YY_START ((yy_start - 1) / 2) #define YYSTATE YY_START /* Action number for EOF rule of a given start state. */ #define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) /* Special action meaning "start processing a new file". */ #define YY_NEW_FILE yyrestart( yyin ) #define YY_END_OF_BUFFER_CHAR 0 /* Size of default input buffer. */ #define YY_BUF_SIZE 16384 typedef struct yy_buffer_state *YY_BUFFER_STATE; extern int yyleng; extern FILE *yyin, *yyout; #define EOB_ACT_CONTINUE_SCAN 0 #define EOB_ACT_END_OF_FILE 1 #define EOB_ACT_LAST_MATCH 2 /* The funky do-while in the following #define is used to turn the definition * int a single C statement (which needs a semi-colon terminator). This * avoids problems with code like: * * if ( condition_holds ) * yyless( 5 ); * else * do_something_else(); * * Prior to using the do-while the compiler would get upset at the * "else" because it interpreted the "if" statement as being all * done when it reached the ';' after the yyless() call. */ /* Return all but the first 'n' matched characters back to the input stream. */ #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ *yy_cp = yy_hold_char; \ YY_RESTORE_YY_MORE_OFFSET \ yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ YY_DO_BEFORE_ACTION; /* set up yytext again */ \ } \ while ( 0 ) #define unput(c) yyunput( c, yytext_ptr ) /* The following is because we cannot portably get our hands on size_t * (without autoconf's help, which isn't available because we want * flex-generated scanners to compile on their own). */ typedef unsigned int yy_size_t; struct yy_buffer_state { FILE *yy_input_file; char *yy_ch_buf; /* input buffer */ char *yy_buf_pos; /* current position in input buffer */ /* Size of input buffer in bytes, not including room for EOB * characters. */ yy_size_t yy_buf_size; /* Number of characters read into yy_ch_buf, not including EOB * characters. */ int yy_n_chars; /* Whether we "own" the buffer - i.e., we know we created it, * and can realloc() it to grow it, and should free() it to * delete it. */ int yy_is_our_buffer; /* Whether this is an "interactive" input source; if so, and * if we're using stdio for input, then we want to use getc() * instead of fread(), to make sure we stop fetching input after * each newline. */ int yy_is_interactive; /* Whether we're considered to be at the beginning of a line. * If so, '^' rules will be active on the next match, otherwise * not. */ int yy_at_bol; /* Whether to try to fill the input buffer when we reach the * end of it. */ int yy_fill_buffer; int yy_buffer_status; #define YY_BUFFER_NEW 0 #define YY_BUFFER_NORMAL 1 /* When an EOF's been seen but there's still some text to process * then we mark the buffer as YY_EOF_PENDING, to indicate that we * shouldn't try reading from the input source any more. We might * still have a bunch of tokens to match, though, because of * possible backing-up. * * When we actually see the EOF, we change the status to "new" * (via yyrestart()), so that the user can continue scanning by * just pointing yyin at a new input file. */ #define YY_BUFFER_EOF_PENDING 2 }; static YY_BUFFER_STATE yy_current_buffer = 0; /* We provide macros for accessing buffer states in case in the * future we want to put the buffer states in a more general * "scanner state". */ #define YY_CURRENT_BUFFER yy_current_buffer /* yy_hold_char holds the character lost when yytext is formed. */ static char yy_hold_char; static int yy_n_chars; /* number of characters read into yy_ch_buf */ int yyleng; /* Points to current character in buffer. */ static char *yy_c_buf_p = (char *) 0; static int yy_init = 1; /* whether we need to initialize */ static int yy_start = 0; /* start state number */ /* Flag which is used to allow yywrap()'s to do buffer switches * instead of setting up a fresh yyin. A bit of a hack ... */ static int yy_did_buffer_switch_on_eof; void yyrestart YY_PROTO(( FILE *input_file )); void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); void yy_load_buffer_state YY_PROTO(( void )); YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); #define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); static void *yy_flex_alloc YY_PROTO(( yy_size_t )); static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); static void yy_flex_free YY_PROTO(( void * )); #define yy_new_buffer yy_create_buffer #define yy_set_interactive(is_interactive) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_is_interactive = is_interactive; \ } #define yy_set_bol(at_bol) \ { \ if ( ! yy_current_buffer ) \ yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ yy_current_buffer->yy_at_bol = at_bol; \ } #define YY_AT_BOL() (yy_current_buffer->yy_at_bol) #define yywrap() 1 #define YY_SKIP_YYWRAP typedef unsigned char YY_CHAR; FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; typedef int yy_state_type; extern char *yytext; #define yytext_ptr yytext static yy_state_type yy_get_previous_state YY_PROTO(( void )); static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); static int yy_get_next_buffer YY_PROTO(( void )); static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); /* Done after the current pattern has been matched and before the * corresponding action - sets up yytext. */ #define YY_DO_BEFORE_ACTION \ yytext_ptr = yy_bp; \ yyleng = (int) (yy_cp - yy_bp); \ yy_hold_char = *yy_cp; \ *yy_cp = '\0'; \ yy_c_buf_p = yy_cp; #define YY_NUM_RULES 111 #define YY_END_OF_BUFFER 112 static yyconst short int yy_accept[256] = { 0, 0, 0, 0, 0, 0, 0, 107, 107, 0, 0, 0, 0, 112, 93, 92, 91, 93, 74, 16, 81, 93, 86, 93, 77, 78, 84, 82, 79, 83, 93, 85, 68, 80, 17, 70, 87, 71, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 88, 89, 93, 99, 98, 99, 99, 106, 105, 106, 106, 107, 107, 107, 109, 111, 110, 111, 102, 101, 91, 73, 69, 75, 0, 0, 0, 0, 0, 0, 0, 0, 68, 72, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, 76, 98, 0, 0, 105, 0, 0, 107, 107, 110, 102, 101, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 27, 24, 65, 52, 53, 50, 55, 51, 54, 56, 57, 45, 39, 29, 30, 31, 63, 59, 61, 26, 62, 58, 60, 49, 48, 18, 19, 20, 64, 40, 25, 34, 36, 35, 37, 67, 66, 47, 28, 46, 38, 21, 22, 23, 44, 42, 32, 43, 33, 41, 0, 0, 94, 0, 103, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 13, 0, 0, 0, 0, 0, 0, 15, 0, 10, 2, 3, 0, 0, 0, 0, 0, 0, 14, 95, 96, 0, 0, 0, 0, 4, 9, 0, 0, 0, 6, 97, 104, 0, 0, 11, 0, 0, 0, 7, 5, 12, 0, 100, 0 } ; static yyconst int yy_ec[256] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 4, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 5, 6, 7, 8, 9, 10, 1, 11, 12, 13, 14, 15, 16, 17, 18, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 20, 21, 22, 23, 24, 1, 1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 36, 1, 1, 1, 1, 25, 1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 36, 1, 51, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } ; static yyconst int yy_meta[52] = { 0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 4, 1, 1, 1, 1, 1, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 1 } ; static yyconst short int yy_base[265] = { 0, 0, 0, 49, 51, 53, 55, 57, 61, 70, 72, 275, 274, 290, 293, 293, 293, 286, 265, 293, 293, 0, 293, 277, 293, 293, 293, 293, 293, 293, 50, 293, 267, 293, 293, 293, 262, 293, 42, 61, 66, 254, 243, 0, 243, 57, 53, 241, 237, 50, 65, 79, 68, 0, 0, 228, 293, 293, 275, 62, 293, 293, 274, 81, 0, 0, 273, 293, 293, 293, 272, 0, 96, 293, 293, 0, 293, 224, 243, 86, 88, 246, 228, 240, 229, 249, 293, 0, 239, 237, 228, 34, 222, 229, 232, 224, 41, 88, 219, 71, 100, 216, 102, 217, 214, 105, 213, 214, 228, 106, 107, 97, 209, 224, 107, 110, 88, 202, 113, 224, 293, 293, 105, 218, 293, 209, 216, 0, 0, 293, 0, 229, 206, 199, 212, 209, 109, 212, 197, 293, 211, 210, 205, 192, 192, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 112, 205, 293, 204, 293, 203, 201, 196, 189, 197, 197, 192, 185, 131, 181, 293, 293, 194, 191, 191, 186, 185, 180, 293, 178, 293, 293, 293, 183, 165, 144, 131, 136, 135, 293, 293, 293, 143, 142, 146, 141, 293, 293, 131, 140, 124, 293, 293, 293, 138, 136, 293, 134, 134, 119, 293, 293, 293, 121, 293, 293, 179, 184, 189, 194, 199, 141, 201, 206, 211 } ; static yyconst short int yy_def[265] = { 0, 255, 1, 256, 256, 257, 257, 258, 258, 259, 259, 260, 260, 255, 255, 255, 255, 255, 255, 255, 255, 261, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 255, 255, 255, 255, 255, 255, 255, 255, 255, 263, 263, 263, 255, 255, 255, 255, 264, 255, 255, 255, 261, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 255, 255, 255, 255, 255, 255, 255, 263, 263, 255, 264, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 262, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255 } ; static yyconst short int yy_nxt[345] = { 0, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 14, 38, 39, 40, 41, 42, 43, 43, 43, 44, 45, 43, 46, 43, 47, 48, 49, 43, 50, 51, 52, 43, 43, 43, 53, 54, 55, 57, 58, 57, 58, 61, 62, 61, 62, 65, 66, 148, 67, 65, 66, 59, 67, 59, 154, 63, 88, 63, 69, 70, 69, 70, 77, 149, 78, 79, 89, 105, 109, 80, 155, 90, 110, 81, 91, 82, 92, 122, 83, 116, 103, 123, 106, 84, 93, 94, 104, 95, 97, 98, 111, 113, 99, 96, 114, 112, 125, 117, 131, 135, 126, 156, 118, 119, 139, 159, 160, 157, 136, 115, 137, 132, 140, 161, 138, 165, 170, 176, 178, 180, 184, 186, 189, 190, 192, 181, 185, 195, 204, 196, 75, 213, 177, 179, 162, 163, 166, 167, 205, 171, 172, 214, 193, 225, 187, 188, 254, 253, 252, 251, 250, 249, 248, 226, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 227, 56, 56, 56, 56, 56, 60, 60, 60, 60, 60, 64, 64, 64, 64, 64, 68, 68, 68, 68, 68, 71, 71, 71, 71, 71, 87, 87, 127, 237, 127, 127, 127, 130, 130, 236, 130, 130, 235, 234, 233, 232, 231, 230, 229, 228, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215, 212, 211, 210, 209, 208, 207, 206, 203, 202, 201, 200, 131, 199, 198, 197, 194, 191, 183, 182, 175, 174, 173, 169, 168, 164, 158, 153, 152, 151, 150, 147, 146, 145, 85, 144, 143, 142, 141, 134, 133, 129, 128, 124, 121, 120, 108, 107, 102, 101, 100, 86, 85, 76, 74, 73, 255, 72, 72, 13, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } ; static yyconst short int yy_chk[345] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 91, 7, 8, 8, 3, 8, 4, 96, 5, 38, 6, 9, 9, 10, 10, 30, 91, 30, 30, 38, 46, 49, 30, 96, 38, 49, 30, 39, 30, 39, 59, 30, 52, 45, 59, 46, 30, 39, 39, 45, 39, 40, 40, 50, 51, 40, 39, 51, 50, 63, 52, 72, 79, 63, 97, 52, 52, 80, 99, 99, 97, 79, 51, 79, 72, 80, 100, 79, 102, 105, 109, 110, 111, 114, 115, 116, 116, 118, 111, 114, 122, 136, 122, 261, 195, 109, 110, 100, 100, 102, 102, 136, 105, 105, 195, 118, 208, 115, 115, 253, 249, 248, 247, 245, 244, 240, 208, 239, 238, 235, 234, 233, 232, 228, 227, 226, 225, 208, 256, 256, 256, 256, 256, 257, 257, 257, 257, 257, 258, 258, 258, 258, 258, 259, 259, 259, 259, 259, 260, 260, 260, 260, 260, 262, 262, 263, 224, 263, 263, 263, 264, 264, 223, 264, 264, 219, 217, 216, 215, 214, 213, 212, 209, 207, 206, 205, 204, 203, 202, 201, 200, 198, 196, 144, 143, 142, 141, 140, 138, 137, 135, 134, 133, 132, 131, 126, 125, 123, 119, 117, 113, 112, 108, 107, 106, 104, 103, 101, 98, 95, 94, 93, 92, 90, 89, 88, 85, 84, 83, 82, 81, 78, 77, 70, 66, 62, 58, 55, 48, 47, 44, 42, 41, 36, 32, 23, 18, 17, 13, 12, 11, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255 } ; static yy_state_type yy_last_accepting_state; static char *yy_last_accepting_cpos; /* The intent behind this definition is that it'll catch * any uses of REJECT which flex missed. */ #define REJECT reject_used_but_not_detected #define yymore() yymore_used_but_not_detected #define YY_MORE_ADJ 0 #define YY_RESTORE_YY_MORE_OFFSET char *yytext; // #line 1 "asm.yy" #define INITIAL 0 /* scanner for a simple assembler */ // #line 3 "asm.yy" #include #include #include "int.h" #include "membuf.h" #include "parse.h" #include "asmtab.h" #define MAX_SRC_BUFFER_DEPTH 10 static YY_BUFFER_STATE src_buffers[MAX_SRC_BUFFER_DEPTH]; static int src_buffer_depth = 0; static char *strdupped_get(char *text); static int strdupped_cmp(const void *a, const void *b); static void strdupped_free(void *a); int num_lines = 1; int push_state_skip = 0; int push_state_init = 0; int push_state_macro = 0; struct vec strdupped[1]; #define SKIP 1 #define SKIP_ALL 2 #define QUOTED_STRING 3 #define SKIP_LINE 4 #define MACROO 5 #define YY_STACK_USED 1 // #line 558 "lex.yy.c" /* Macros after this point can all be overridden by user definitions in * section 1. */ #ifndef YY_SKIP_YYWRAP #ifdef __cplusplus extern "C" int yywrap YY_PROTO(( void )); #else extern int yywrap YY_PROTO(( void )); #endif #endif #ifndef YY_NO_UNPUT static void yyunput YY_PROTO(( int c, char *buf_ptr )); #endif #ifndef yytext_ptr static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); #endif #ifdef YY_NEED_STRLEN static int yy_flex_strlen YY_PROTO(( yyconst char * )); #endif #ifndef YY_NO_INPUT #ifdef __cplusplus static int yyinput YY_PROTO(( void )); #else static int input YY_PROTO(( void )); #endif #endif #if YY_STACK_USED static int yy_start_stack_ptr = 0; static int yy_start_stack_depth = 0; static int *yy_start_stack = 0; #ifndef YY_NO_PUSH_STATE static void yy_push_state YY_PROTO(( int new_state )); #endif #ifndef YY_NO_POP_STATE static void yy_pop_state YY_PROTO(( void )); #endif #ifndef YY_NO_TOP_STATE static int yy_top_state YY_PROTO(( void )); #endif #else #define YY_NO_PUSH_STATE 1 #define YY_NO_POP_STATE 1 #define YY_NO_TOP_STATE 1 #endif #ifdef YY_MALLOC_DECL YY_MALLOC_DECL #else #if __STDC__ #ifndef __cplusplus #include #endif #else /* Just try to get by without declaring the routines. This will fail * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) * or sizeof(void*) != sizeof(int). */ #endif #endif /* Amount of stuff to slurp up with each read. */ #ifndef YY_READ_BUF_SIZE #define YY_READ_BUF_SIZE 8192 #endif /* Copy whatever the last rule matched to the standard output. */ #ifndef ECHO /* This used to be an fputs(), but since the string might contain NUL's, * we now use fwrite(). */ #define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) #endif /* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, * is returned in "result". */ #ifndef YY_INPUT #define YY_INPUT(buf,result,max_size) \ if ( yy_current_buffer->yy_is_interactive ) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ buf[n] = (char) c; \ if ( c == '\n' ) \ buf[n++] = (char) c; \ if ( c == EOF && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); \ result = n; \ } \ else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ && ferror( yyin ) ) \ YY_FATAL_ERROR( "input in flex scanner failed" ); #endif /* No semi-colon after return; correct usage is to write "yyterminate();" - * we don't want an extra ';' after the "return" because that will cause * some compilers to complain about unreachable statements. */ #ifndef yyterminate #define yyterminate() return YY_NULL #endif /* Number of entries by which start-condition stack grows. */ #ifndef YY_START_STACK_INCR #define YY_START_STACK_INCR 25 #endif /* Report a fatal error. */ #ifndef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) #endif /* Default declaration of generated scanner - a define so the user can * easily add parameters. */ #ifndef YY_DECL #define YY_DECL int yylex YY_PROTO(( void )) #endif /* Code executed at the beginning of each rule, after yytext and yyleng * have been set up. */ #ifndef YY_USER_ACTION #define YY_USER_ACTION #endif /* Code executed at the end of each rule. */ #ifndef YY_BREAK #define YY_BREAK break; #endif #define YY_RULE_SETUP \ YY_USER_ACTION YY_DECL { register yy_state_type yy_current_state; register char *yy_cp = NULL, *yy_bp = NULL; register int yy_act; // #line 32 "asm.yy" if(push_state_init) {push_state_init = 0; yy_push_state(INITIAL); } if(push_state_skip) {push_state_skip = 0; yy_push_state(SKIP); } if(push_state_macro) {push_state_macro = 0; yy_push_state(MACROO); } // #line 719 "lex.yy.c" if ( yy_init ) { yy_init = 0; #ifdef YY_USER_INIT YY_USER_INIT; #endif if ( ! yy_start ) yy_start = 1; /* first start state */ if ( ! yyin ) yyin = stdin; if ( ! yyout ) yyout = stdout; if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_load_buffer_state(); } while ( 1 ) /* loops until end-of-file is reached */ { yy_cp = yy_c_buf_p; /* Support of yytext. */ *yy_cp = yy_hold_char; /* yy_bp points to the position in yy_ch_buf of the start of * the current run. */ yy_bp = yy_cp; yy_current_state = yy_start; yy_match: do { register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 256 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } while ( yy_current_state != 255 ); yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; yy_find_action: yy_act = yy_accept[yy_current_state]; YY_DO_BEFORE_ACTION; do_action: /* This label is used only to access EOF actions. */ switch ( yy_act ) { /* beginning of action switch */ case 0: /* must back up */ /* undo the effects of YY_DO_BEFORE_ACTION */ *yy_cp = yy_hold_char; yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; case 1: YY_RULE_SETUP // #line 41 "asm.yy" return IF; YY_BREAK case 2: YY_RULE_SETUP // #line 42 "asm.yy" BEGIN(SKIP_ALL); YY_BREAK case 3: YY_RULE_SETUP // #line 43 "asm.yy" BEGIN(SKIP); YY_BREAK case 4: YY_RULE_SETUP // #line 44 "asm.yy" yy_pop_state(); YY_BREAK case 5: YY_RULE_SETUP // #line 46 "asm.yy" return INCLUDE; YY_BREAK case 6: YY_RULE_SETUP // #line 47 "asm.yy" return MACRO; YY_BREAK case 7: YY_RULE_SETUP // #line 49 "asm.yy" return DEFINED; YY_BREAK case 8: YY_RULE_SETUP // #line 50 "asm.yy" return ORG; YY_BREAK case 9: YY_RULE_SETUP // #line 51 "asm.yy" return ASMERROR; YY_BREAK case 10: YY_RULE_SETUP // #line 52 "asm.yy" return ECHO; YY_BREAK case 11: YY_RULE_SETUP // #line 53 "asm.yy" return INCBIN; YY_BREAK case 12: YY_RULE_SETUP // #line 54 "asm.yy" return INCWORD; YY_BREAK case 13: YY_RULE_SETUP // #line 55 "asm.yy" return RES; YY_BREAK case 14: YY_RULE_SETUP // #line 56 "asm.yy" return WORD; YY_BREAK case 15: YY_RULE_SETUP // #line 57 "asm.yy" return BYTE; YY_BREAK case 16: YY_RULE_SETUP // #line 59 "asm.yy" BEGIN(QUOTED_STRING); YY_BREAK case 17: YY_RULE_SETUP // #line 60 "asm.yy" BEGIN(SKIP_LINE); YY_BREAK case 18: YY_RULE_SETUP // #line 62 "asm.yy" return LDA; YY_BREAK case 19: YY_RULE_SETUP // #line 63 "asm.yy" return LDX; YY_BREAK case 20: YY_RULE_SETUP // #line 64 "asm.yy" return LDY; YY_BREAK case 21: YY_RULE_SETUP // #line 65 "asm.yy" return STA; YY_BREAK case 22: YY_RULE_SETUP // #line 66 "asm.yy" return STX; YY_BREAK case 23: YY_RULE_SETUP // #line 67 "asm.yy" return STY; YY_BREAK case 24: YY_RULE_SETUP // #line 68 "asm.yy" return AND; YY_BREAK case 25: YY_RULE_SETUP // #line 69 "asm.yy" return ORA; YY_BREAK case 26: YY_RULE_SETUP // #line 70 "asm.yy" return EOR; YY_BREAK case 27: YY_RULE_SETUP // #line 71 "asm.yy" return ADC; YY_BREAK case 28: YY_RULE_SETUP // #line 72 "asm.yy" return SBC; YY_BREAK case 29: YY_RULE_SETUP // #line 73 "asm.yy" return CMP; YY_BREAK case 30: YY_RULE_SETUP // #line 74 "asm.yy" return CPX; YY_BREAK case 31: YY_RULE_SETUP // #line 75 "asm.yy" return CPY; YY_BREAK case 32: YY_RULE_SETUP // #line 77 "asm.yy" return TSX; YY_BREAK case 33: YY_RULE_SETUP // #line 78 "asm.yy" return TXS; YY_BREAK case 34: YY_RULE_SETUP // #line 79 "asm.yy" return PHA; YY_BREAK case 35: YY_RULE_SETUP // #line 80 "asm.yy" return PLA; YY_BREAK case 36: YY_RULE_SETUP // #line 81 "asm.yy" return PHP; YY_BREAK case 37: YY_RULE_SETUP // #line 82 "asm.yy" return PLP; YY_BREAK case 38: YY_RULE_SETUP // #line 83 "asm.yy" return SEI; YY_BREAK case 39: YY_RULE_SETUP // #line 84 "asm.yy" return CLI; YY_BREAK case 40: YY_RULE_SETUP // #line 85 "asm.yy" return NOP; YY_BREAK case 41: YY_RULE_SETUP // #line 86 "asm.yy" return TYA; YY_BREAK case 42: YY_RULE_SETUP // #line 87 "asm.yy" return TAY; YY_BREAK case 43: YY_RULE_SETUP // #line 88 "asm.yy" return TXA; YY_BREAK case 44: YY_RULE_SETUP // #line 89 "asm.yy" return TAX; YY_BREAK case 45: YY_RULE_SETUP // #line 90 "asm.yy" return CLC; YY_BREAK case 46: YY_RULE_SETUP // #line 91 "asm.yy" return SEC; YY_BREAK case 47: YY_RULE_SETUP // #line 92 "asm.yy" return RTS; YY_BREAK case 48: YY_RULE_SETUP // #line 94 "asm.yy" return JSR; YY_BREAK case 49: YY_RULE_SETUP // #line 95 "asm.yy" return JMP; YY_BREAK case 50: YY_RULE_SETUP // #line 96 "asm.yy" return BEQ; YY_BREAK case 51: YY_RULE_SETUP // #line 97 "asm.yy" return BNE; YY_BREAK case 52: YY_RULE_SETUP // #line 98 "asm.yy" return BCC; YY_BREAK case 53: YY_RULE_SETUP // #line 99 "asm.yy" return BCS; YY_BREAK case 54: YY_RULE_SETUP // #line 100 "asm.yy" return BPL; YY_BREAK case 55: YY_RULE_SETUP // #line 101 "asm.yy" return BMI; YY_BREAK case 56: YY_RULE_SETUP // #line 102 "asm.yy" return BVC; YY_BREAK case 57: YY_RULE_SETUP // #line 103 "asm.yy" return BCS; YY_BREAK case 58: YY_RULE_SETUP // #line 104 "asm.yy" return INX; YY_BREAK case 59: YY_RULE_SETUP // #line 105 "asm.yy" return DEX; YY_BREAK case 60: YY_RULE_SETUP // #line 106 "asm.yy" return INY; YY_BREAK case 61: YY_RULE_SETUP // #line 107 "asm.yy" return DEY; YY_BREAK case 62: YY_RULE_SETUP // #line 108 "asm.yy" return INC; YY_BREAK case 63: YY_RULE_SETUP // #line 109 "asm.yy" return DEC; YY_BREAK case 64: YY_RULE_SETUP // #line 110 "asm.yy" return LSR; YY_BREAK case 65: YY_RULE_SETUP // #line 111 "asm.yy" return ASL; YY_BREAK case 66: YY_RULE_SETUP // #line 112 "asm.yy" return ROR; YY_BREAK case 67: YY_RULE_SETUP // #line 113 "asm.yy" return ROL; YY_BREAK case 68: YY_RULE_SETUP // #line 115 "asm.yy" { yylval.num = atoi(yytext); return NUMBER; } YY_BREAK case 69: YY_RULE_SETUP // #line 117 "asm.yy" { yylval.num = strtol(yytext + 1, NULL, 16); return NUMBER; } YY_BREAK case 70: YY_RULE_SETUP // #line 119 "asm.yy" return LT; YY_BREAK case 71: YY_RULE_SETUP // #line 120 "asm.yy" return GT; YY_BREAK case 72: YY_RULE_SETUP // #line 121 "asm.yy" return EQ; YY_BREAK case 73: YY_RULE_SETUP // #line 122 "asm.yy" return NEQ; YY_BREAK case 74: YY_RULE_SETUP // #line 123 "asm.yy" return LNOT; YY_BREAK case 75: YY_RULE_SETUP // #line 124 "asm.yy" return LAND; YY_BREAK case 76: YY_RULE_SETUP // #line 125 "asm.yy" return LOR; YY_BREAK case 77: YY_RULE_SETUP // #line 127 "asm.yy" return LPAREN; YY_BREAK case 78: YY_RULE_SETUP // #line 128 "asm.yy" return RPAREN; YY_BREAK case 79: YY_RULE_SETUP // #line 129 "asm.yy" return COMMA; YY_BREAK case 80: YY_RULE_SETUP // #line 130 "asm.yy" return COLON; YY_BREAK case 81: YY_RULE_SETUP // #line 131 "asm.yy" return HASH; YY_BREAK case 82: YY_RULE_SETUP // #line 132 "asm.yy" return PLUS; YY_BREAK case 83: YY_RULE_SETUP // #line 133 "asm.yy" return MINUS; YY_BREAK case 84: YY_RULE_SETUP // #line 134 "asm.yy" return MULT; YY_BREAK case 85: YY_RULE_SETUP // #line 135 "asm.yy" return DIV; YY_BREAK case 86: YY_RULE_SETUP // #line 136 "asm.yy" return MOD; YY_BREAK case 87: YY_RULE_SETUP // #line 138 "asm.yy" return ASSIGN; YY_BREAK case 88: YY_RULE_SETUP // #line 140 "asm.yy" return X; YY_BREAK case 89: YY_RULE_SETUP // #line 141 "asm.yy" return Y; YY_BREAK case 90: YY_RULE_SETUP // #line 143 "asm.yy" { yylval.str = strdupped_get(yytext); return SYMBOL; } YY_BREAK case 91: YY_RULE_SETUP // #line 145 "asm.yy" ++num_lines; YY_BREAK case 92: YY_RULE_SETUP // #line 147 "asm.yy" /* eat whitespace */ YY_BREAK case 93: YY_RULE_SETUP // #line 149 "asm.yy" printf("unknown character found %s\n", yytext); YY_BREAK case 94: YY_RULE_SETUP // #line 151 "asm.yy" yy_push_state(SKIP_ALL); YY_BREAK case 95: YY_RULE_SETUP // #line 152 "asm.yy" { yy_pop_state(); return IF; } YY_BREAK case 96: YY_RULE_SETUP // #line 153 "asm.yy" BEGIN(INITIAL); YY_BREAK case 97: YY_RULE_SETUP // #line 154 "asm.yy" yy_pop_state(); YY_BREAK case 98: YY_RULE_SETUP // #line 155 "asm.yy" ++num_lines; YY_BREAK case 99: YY_RULE_SETUP // #line 156 "asm.yy" YY_BREAK case 100: YY_RULE_SETUP // #line 158 "asm.yy" yy_pop_state(); YY_BREAK case 101: YY_RULE_SETUP // #line 159 "asm.yy" { yylval.str = yytext; return MACRO_STRING; } YY_BREAK case 102: YY_RULE_SETUP // #line 160 "asm.yy" { yylval.str = yytext; return MACRO_STRING; } YY_BREAK case 103: YY_RULE_SETUP // #line 162 "asm.yy" yy_push_state(SKIP_ALL); YY_BREAK case 104: YY_RULE_SETUP // #line 163 "asm.yy" yy_pop_state(); YY_BREAK case 105: YY_RULE_SETUP // #line 164 "asm.yy" ++num_lines; YY_BREAK case 106: YY_RULE_SETUP // #line 165 "asm.yy" YY_BREAK case 107: YY_RULE_SETUP // #line 167 "asm.yy" { yylval.str = strdupped_get(yytext); return STRING; } YY_BREAK case 108: YY_RULE_SETUP // #line 171 "asm.yy" ++num_lines; YY_BREAK case 109: YY_RULE_SETUP // #line 172 "asm.yy" BEGIN(INITIAL); YY_BREAK case 110: YY_RULE_SETUP // #line 174 "asm.yy" { ++num_lines; BEGIN(INITIAL); } YY_BREAK case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(SKIP): case YY_STATE_EOF(SKIP_ALL): case YY_STATE_EOF(QUOTED_STRING): case YY_STATE_EOF(SKIP_LINE): case YY_STATE_EOF(MACROO): // #line 176 "asm.yy" { if(--src_buffer_depth == 0) { yyterminate(); } else { yy_delete_buffer(YY_CURRENT_BUFFER); yy_switch_to_buffer(src_buffers[src_buffer_depth]); } } YY_BREAK case 111: YY_RULE_SETUP // #line 188 "asm.yy" ECHO; YY_BREAK // #line 1375 "lex.yy.c" case YY_END_OF_BUFFER: { /* Amount of text matched not including the EOB char. */ int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; /* Undo the effects of YY_DO_BEFORE_ACTION. */ *yy_cp = yy_hold_char; YY_RESTORE_YY_MORE_OFFSET if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) { /* We're scanning a new file or input source. It's * possible that this happened because the user * just pointed yyin at a new source and called * yylex(). If so, then we have to assure * consistency between yy_current_buffer and our * globals. Here is the right place to do so, because * this is the first action (other than possibly a * back-up) that will match for the new input source. */ yy_n_chars = yy_current_buffer->yy_n_chars; yy_current_buffer->yy_input_file = yyin; yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; } /* Note that here we test for yy_c_buf_p "<=" to the position * of the first EOB in the buffer, since yy_c_buf_p will * already have been incremented past the NUL character * (since all states make transitions on EOB to the * end-of-buffer state). Contrast this with the test * in input(). */ if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) { /* This was really a NUL. */ yy_state_type yy_next_state; yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); /* Okay, we're now positioned to make the NUL * transition. We couldn't have * yy_get_previous_state() go ahead and do it * for us because it doesn't know how to deal * with the possibility of jamming (and we don't * want to build jamming into it because then it * will run more slowly). */ yy_next_state = yy_try_NUL_trans( yy_current_state ); yy_bp = yytext_ptr + YY_MORE_ADJ; if ( yy_next_state ) { /* Consume the NUL. */ yy_cp = ++yy_c_buf_p; yy_current_state = yy_next_state; goto yy_match; } else { yy_cp = yy_last_accepting_cpos; yy_current_state = yy_last_accepting_state; goto yy_find_action; } } else switch ( yy_get_next_buffer() ) { case EOB_ACT_END_OF_FILE: { yy_did_buffer_switch_on_eof = 0; if ( yywrap() ) { /* Note: because we've taken care in * yy_get_next_buffer() to have set up * yytext, we can now set up * yy_c_buf_p so that if some total * hoser (like flex itself) wants to * call the scanner after we return the * YY_NULL, it'll still work - another * YY_NULL will get returned. */ yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; yy_act = YY_STATE_EOF(YY_START); goto do_action; } else { if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; } break; } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_match; case EOB_ACT_LAST_MATCH: yy_c_buf_p = &yy_current_buffer->yy_ch_buf[yy_n_chars]; yy_current_state = yy_get_previous_state(); yy_cp = yy_c_buf_p; yy_bp = yytext_ptr + YY_MORE_ADJ; goto yy_find_action; } break; } default: YY_FATAL_ERROR( "fatal flex scanner internal error--no action found" ); } /* end of action switch */ } /* end of scanning one token */ } /* end of yylex */ /* yy_get_next_buffer - try to read in a new buffer * * Returns a code representing an action: * EOB_ACT_LAST_MATCH - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position * EOB_ACT_END_OF_FILE - end of file */ static int yy_get_next_buffer() { register char *dest = yy_current_buffer->yy_ch_buf; register char *source = yytext_ptr; register int number_to_move, i; int ret_val; if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) YY_FATAL_ERROR( "fatal flex scanner internal error--end of buffer missed" ); if ( yy_current_buffer->yy_fill_buffer == 0 ) { /* Don't try to fill the buffer, so this is an EOF. */ if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) { /* We matched a single character, the EOB, so * treat this as a final EOF. */ return EOB_ACT_END_OF_FILE; } else { /* We matched some text prior to the EOB, first * process it. */ return EOB_ACT_LAST_MATCH; } } /* Try to read more data. */ /* First move last chars to start of buffer. */ number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; for ( i = 0; i < number_to_move; ++i ) *(dest++) = *(source++); if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) /* don't do the read, it's not guaranteed to return an EOF, * just force an EOF */ yy_current_buffer->yy_n_chars = yy_n_chars = 0; else { int num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; while ( num_to_read <= 0 ) { /* Not enough room in the buffer - grow it. */ #ifdef YY_USES_REJECT YY_FATAL_ERROR( "input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); #else /* just a shorter name for the current buffer */ YY_BUFFER_STATE b = yy_current_buffer; int yy_c_buf_p_offset = (int) (yy_c_buf_p - b->yy_ch_buf); if ( b->yy_is_our_buffer ) { int new_size = b->yy_buf_size * 2; if ( new_size <= 0 ) b->yy_buf_size += b->yy_buf_size / 8; else b->yy_buf_size *= 2; b->yy_ch_buf = (char *) /* Include room in for 2 EOB chars. */ yy_flex_realloc( (void *) b->yy_ch_buf, b->yy_buf_size + 2 ); } else /* Can't grow it, we don't own it. */ b->yy_ch_buf = 0; if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "fatal error - scanner input buffer overflow" ); yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; num_to_read = yy_current_buffer->yy_buf_size - number_to_move - 1; #endif } if ( num_to_read > YY_READ_BUF_SIZE ) num_to_read = YY_READ_BUF_SIZE; /* Read in more data. */ YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), yy_n_chars, num_to_read ); yy_current_buffer->yy_n_chars = yy_n_chars; } if ( yy_n_chars == 0 ) { if ( number_to_move == YY_MORE_ADJ ) { ret_val = EOB_ACT_END_OF_FILE; yyrestart( yyin ); } else { ret_val = EOB_ACT_LAST_MATCH; yy_current_buffer->yy_buffer_status = YY_BUFFER_EOF_PENDING; } } else ret_val = EOB_ACT_CONTINUE_SCAN; yy_n_chars += number_to_move; yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; return ret_val; } /* yy_get_previous_state - get the state just before the EOB char was reached */ static yy_state_type yy_get_previous_state() { register yy_state_type yy_current_state; register char *yy_cp; yy_current_state = yy_start; for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) { register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 256 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; } return yy_current_state; } /* yy_try_NUL_trans - try to make a transition on the NUL character * * synopsis * next_state = yy_try_NUL_trans( current_state ); */ #ifdef YY_USE_PROTOS static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) #else static yy_state_type yy_try_NUL_trans( yy_current_state ) yy_state_type yy_current_state; #endif { register int yy_is_jam; register char *yy_cp = yy_c_buf_p; register YY_CHAR yy_c = 1; if ( yy_accept[yy_current_state] ) { yy_last_accepting_state = yy_current_state; yy_last_accepting_cpos = yy_cp; } while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; if ( yy_current_state >= 256 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; yy_is_jam = (yy_current_state == 255); return yy_is_jam ? 0 : yy_current_state; } #ifndef YY_NO_UNPUT #ifdef YY_USE_PROTOS static void yyunput( int c, register char *yy_bp ) #else static void yyunput( c, yy_bp ) int c; register char *yy_bp; #endif { register char *yy_cp = yy_c_buf_p; /* undo effects of setting up yytext */ *yy_cp = yy_hold_char; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) { /* need to shift things up to make room */ /* +2 for EOB chars. */ register int number_to_move = yy_n_chars + 2; register char *dest = &yy_current_buffer->yy_ch_buf[ yy_current_buffer->yy_buf_size + 2]; register char *source = &yy_current_buffer->yy_ch_buf[number_to_move]; while ( source > yy_current_buffer->yy_ch_buf ) *--dest = *--source; yy_cp += (int) (dest - source); yy_bp += (int) (dest - source); yy_current_buffer->yy_n_chars = yy_n_chars = yy_current_buffer->yy_buf_size; if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) YY_FATAL_ERROR( "flex scanner push-back overflow" ); } *--yy_cp = (char) c; yytext_ptr = yy_bp; yy_hold_char = *yy_cp; yy_c_buf_p = yy_cp; } #endif /* ifndef YY_NO_UNPUT */ #ifdef __cplusplus static int yyinput() #else static int input() #endif { int c; *yy_c_buf_p = yy_hold_char; if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) { /* yy_c_buf_p now points to the character we want to return. * If this occurs *before* the EOB characters, then it's a * valid NUL; if not, then we've hit the end of the buffer. */ if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) /* This was really a NUL. */ *yy_c_buf_p = '\0'; else { /* need more input */ int offset = yy_c_buf_p - yytext_ptr; ++yy_c_buf_p; switch ( yy_get_next_buffer() ) { case EOB_ACT_LAST_MATCH: /* This happens because yy_g_n_b() * sees that we've accumulated a * token and flags that we need to * try matching the token before * proceeding. But for input(), * there's no matching to consider. * So convert the EOB_ACT_LAST_MATCH * to EOB_ACT_END_OF_FILE. */ /* Reset buffer status. */ yyrestart( yyin ); /* fall through */ case EOB_ACT_END_OF_FILE: { if ( yywrap() ) return EOF; if ( ! yy_did_buffer_switch_on_eof ) YY_NEW_FILE; #ifdef __cplusplus return yyinput(); #else return input(); #endif } case EOB_ACT_CONTINUE_SCAN: yy_c_buf_p = yytext_ptr + offset; break; } } } c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ *yy_c_buf_p = '\0'; /* preserve yytext */ yy_hold_char = *++yy_c_buf_p; return c; } #ifdef YY_USE_PROTOS void yyrestart( FILE *input_file ) #else void yyrestart( input_file ) FILE *input_file; #endif { if ( ! yy_current_buffer ) yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); yy_init_buffer( yy_current_buffer, input_file ); yy_load_buffer_state(); } #ifdef YY_USE_PROTOS void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) #else void yy_switch_to_buffer( new_buffer ) YY_BUFFER_STATE new_buffer; #endif { if ( yy_current_buffer == new_buffer ) return; if ( yy_current_buffer ) { /* Flush out information for old buffer. */ *yy_c_buf_p = yy_hold_char; yy_current_buffer->yy_buf_pos = yy_c_buf_p; yy_current_buffer->yy_n_chars = yy_n_chars; } yy_current_buffer = new_buffer; yy_load_buffer_state(); /* We don't actually know whether we did this switch during * EOF (yywrap()) processing, but the only time this flag * is looked at is after yywrap() is called, so it's safe * to go ahead and always set it. */ yy_did_buffer_switch_on_eof = 1; } #ifdef YY_USE_PROTOS void yy_load_buffer_state( void ) #else void yy_load_buffer_state() #endif { yy_n_chars = yy_current_buffer->yy_n_chars; yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; yyin = yy_current_buffer->yy_input_file; yy_hold_char = *yy_c_buf_p; } #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) #else YY_BUFFER_STATE yy_create_buffer( file, size ) FILE *file; int size; #endif { YY_BUFFER_STATE b; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_buf_size = size; /* yy_ch_buf has to be 2 characters longer than the size given because * we need to put in 2 end-of-buffer characters. */ b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); if ( ! b->yy_ch_buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); b->yy_is_our_buffer = 1; yy_init_buffer( b, file ); return b; } #ifdef YY_USE_PROTOS void yy_delete_buffer( YY_BUFFER_STATE b ) #else void yy_delete_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; if ( b == yy_current_buffer ) yy_current_buffer = (YY_BUFFER_STATE) 0; if ( b->yy_is_our_buffer ) yy_flex_free( (void *) b->yy_ch_buf ); yy_flex_free( (void *) b ); } #ifdef YY_USE_PROTOS void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) #else void yy_init_buffer( b, file ) YY_BUFFER_STATE b; FILE *file; #endif { yy_flush_buffer( b ); b->yy_input_file = file; b->yy_fill_buffer = 1; #if YY_ALWAYS_INTERACTIVE b->yy_is_interactive = 1; #else #if YY_NEVER_INTERACTIVE b->yy_is_interactive = 0; #else b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; #endif #endif } #ifdef YY_USE_PROTOS void yy_flush_buffer( YY_BUFFER_STATE b ) #else void yy_flush_buffer( b ) YY_BUFFER_STATE b; #endif { if ( ! b ) return; b->yy_n_chars = 0; /* We always need two end-of-buffer characters. The first causes * a transition to the end-of-buffer state. The second causes * a jam in that state. */ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; b->yy_buf_pos = &b->yy_ch_buf[0]; b->yy_at_bol = 1; b->yy_buffer_status = YY_BUFFER_NEW; if ( b == yy_current_buffer ) yy_load_buffer_state(); } #ifndef YY_NO_SCAN_BUFFER #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) #else YY_BUFFER_STATE yy_scan_buffer( base, size ) char *base; yy_size_t size; #endif { YY_BUFFER_STATE b; if ( size < 2 || base[size-2] != YY_END_OF_BUFFER_CHAR || base[size-1] != YY_END_OF_BUFFER_CHAR ) /* They forgot to leave room for the EOB's. */ return 0; b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); if ( ! b ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ b->yy_buf_pos = b->yy_ch_buf = base; b->yy_is_our_buffer = 0; b->yy_input_file = 0; b->yy_n_chars = b->yy_buf_size; b->yy_is_interactive = 0; b->yy_at_bol = 1; b->yy_fill_buffer = 0; b->yy_buffer_status = YY_BUFFER_NEW; yy_switch_to_buffer( b ); return b; } #endif #ifndef YY_NO_SCAN_STRING #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) #else YY_BUFFER_STATE yy_scan_string( yy_str ) yyconst char *yy_str; #endif { int len; for ( len = 0; yy_str[len]; ++len ) ; return yy_scan_bytes( yy_str, len ); } #endif #ifndef YY_NO_SCAN_BYTES #ifdef YY_USE_PROTOS YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) #else YY_BUFFER_STATE yy_scan_bytes( bytes, len ) yyconst char *bytes; int len; #endif { YY_BUFFER_STATE b; char *buf; yy_size_t n; int i; /* Get memory for full buffer, including space for trailing EOB's. */ n = len + 2; buf = (char *) yy_flex_alloc( n ); if ( ! buf ) YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); for ( i = 0; i < len; ++i ) buf[i] = bytes[i]; buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; b = yy_scan_buffer( buf, n ); if ( ! b ) YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); /* It's okay to grow etc. this buffer, and we should throw it * away when we're done. */ b->yy_is_our_buffer = 1; return b; } #endif #ifndef YY_NO_PUSH_STATE #ifdef YY_USE_PROTOS static void yy_push_state( int new_state ) #else static void yy_push_state( new_state ) int new_state; #endif { if ( yy_start_stack_ptr >= yy_start_stack_depth ) { yy_size_t new_size; yy_start_stack_depth += YY_START_STACK_INCR; new_size = yy_start_stack_depth * sizeof( int ); if ( ! yy_start_stack ) yy_start_stack = (int *) yy_flex_alloc( new_size ); else yy_start_stack = (int *) yy_flex_realloc( (void *) yy_start_stack, new_size ); if ( ! yy_start_stack ) YY_FATAL_ERROR( "out of memory expanding start-condition stack" ); } yy_start_stack[yy_start_stack_ptr++] = YY_START; BEGIN(new_state); } #endif #ifndef YY_NO_POP_STATE static void yy_pop_state() { if ( --yy_start_stack_ptr < 0 ) YY_FATAL_ERROR( "start-condition stack underflow" ); BEGIN(yy_start_stack[yy_start_stack_ptr]); } #endif #ifndef YY_NO_TOP_STATE static int yy_top_state() { return yy_start_stack[yy_start_stack_ptr - 1]; } #endif #ifndef YY_EXIT_FAILURE #define YY_EXIT_FAILURE 2 #endif #ifdef YY_USE_PROTOS static void yy_fatal_error( yyconst char msg[] ) #else static void yy_fatal_error( msg ) char msg[]; #endif { (void) fprintf( stderr, "%s\n", msg ); exit( YY_EXIT_FAILURE ); } /* Redefine yyless() so it works in section 3 code. */ #undef yyless #define yyless(n) \ do \ { \ /* Undo effects of setting up yytext. */ \ yytext[yyleng] = yy_hold_char; \ yy_c_buf_p = yytext + n; \ yy_hold_char = *yy_c_buf_p; \ *yy_c_buf_p = '\0'; \ yyleng = n; \ } \ while ( 0 ) /* Internal utility routines. */ #ifndef yytext_ptr #ifdef YY_USE_PROTOS static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) #else static void yy_flex_strncpy( s1, s2, n ) char *s1; yyconst char *s2; int n; #endif { register int i; for ( i = 0; i < n; ++i ) s1[i] = s2[i]; } #endif #ifdef YY_NEED_STRLEN #ifdef YY_USE_PROTOS static int yy_flex_strlen( yyconst char *s ) #else static int yy_flex_strlen( s ) yyconst char *s; #endif { register int n; for ( n = 0; s[n]; ++n ) ; return n; } #endif #ifdef YY_USE_PROTOS static void *yy_flex_alloc( yy_size_t size ) #else static void *yy_flex_alloc( size ) yy_size_t size; #endif { return (void *) malloc( size ); } #ifdef YY_USE_PROTOS static void *yy_flex_realloc( void *ptr, yy_size_t size ) #else static void *yy_flex_realloc( ptr, size ) void *ptr; yy_size_t size; #endif { /* The cast to (char *) in the following accommodates both * implementations that use char* generic pointers, and those * that use void* generic pointers. It works with the latter * because both ANSI C and C++ allow castless assignment from * any pointer type to void*, and deal with argument conversions * as though doing an assignment. */ return (void *) realloc( (char *) ptr, size ); } #ifdef YY_USE_PROTOS static void yy_flex_free( void *ptr ) #else static void yy_flex_free( ptr ) void *ptr; #endif { free( ptr ); } #if YY_MAIN int main() { yylex(); return 0; } #endif // #line 188 "asm.yy" void scanner_init() { vec_init(strdupped, sizeof(char*)); } void asm_src_buffer_push(struct membuf *buffer) { if(src_buffer_depth == MAX_SRC_BUFFER_DEPTH) { fprintf(stderr, "source buffers nested too deep\n"); exit(-1); } src_buffers[src_buffer_depth++] = YY_CURRENT_BUFFER; yy_scan_bytes(membuf_get(buffer), membuf_memlen(buffer)); } static char *strdupped_get(char *text) { char **pp; /*printf("get \"%s\" => ", text);*/ if(vec_insert_uniq(strdupped, strdupped_cmp, &text, (void*)&pp)) { /* replace the pointer to since will be reused */ *pp = strdup(text); } /*printf("%p\n", *pp);*/ return *pp; } static void strdupped_free(void *a) { char *b = *(char**)a; /*printf("free => %p \"%s\"\n", b, b);*/ free(b); } static int strdupped_cmp(const void *a, const void *b) { char *c = *(char**)a; char *d = *(char**)b; return strcmp(c, d); } void scanner_free() { vec_free(strdupped, strdupped_free); } void yycleanup() { if (YY_CURRENT_BUFFER) yy_delete_buffer(YY_CURRENT_BUFFER); if (yy_start_stack) { yy_flex_free(yy_start_stack); yy_start_stack = 0; yy_start_stack_ptr = 0; yy_start_stack_depth = 0; } } goattracker-2.72/src/asm/membufio.c0000644000000000000000000000370510774364076016011 0ustar rootroot/* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "membufio.h" #include "log.h" #include #include void read_file(const char *name, struct membuf *buf) { char block[1024]; FILE *in; int len; in = fopen(name, "rb"); if(in == NULL) { LOG(LOG_ERROR, ("Can't open file \"%s\" for input.\n", name)); exit(-1); } do { len = fread(block, 1, 1024, in); membuf_append(buf, block, len); } while(len == 1024); LOG(LOG_DEBUG, ("read %d bytes from file\n", len)); fclose(in); } void write_file(const char *name, struct membuf *buf) { FILE *out; out = fopen(name, "wb"); if(out == NULL) { LOG(LOG_ERROR, ("Can't open file \"%s\" for output.\n", name)); exit(-1); } fwrite(membuf_get(buf), 1, membuf_memlen(buf), out); fclose(out); } goattracker-2.72/src/asm/asmtab.c0000644000000000000000000025731310774364076015463 0ustar rootroot/* A Bison parser, made by GNU Bison 2.1. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 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, 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. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Written by Richard Stallman by simplifying the original so called ``semantic'' parser. */ /* All symbols defined below should begin with yy or YY, to avoid infringing on user name space. This should be done even for local variables, as they might otherwise be expanded by user macros. There are some unavoidable exceptions within include files to define necessary library symbols; they are noted "INFRINGES ON USER NAME SPACE" below. */ /* Identify Bison output. */ #define YYBISON 1 /* Bison version. */ #define YYBISON_VERSION "2.1" /* Skeleton name. */ #define YYSKELETON_NAME "yacc.c" /* Pure parsers. */ #define YYPURE 0 /* Using locations. */ #define YYLSP_NEEDED 0 /* Tokens. */ #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { INCLUDE = 258, IF = 259, DEFINED = 260, MACRO = 261, MACRO_STRING = 262, ORG = 263, ERROR = 264, ECHO = 265, INCBIN = 266, INCWORD = 267, RES = 268, WORD = 269, BYTE = 270, LDA = 271, LDX = 272, LDY = 273, STA = 274, STX = 275, STY = 276, AND = 277, ORA = 278, EOR = 279, ADC = 280, SBC = 281, CMP = 282, CPX = 283, CPY = 284, TSX = 285, TXS = 286, PHA = 287, PLA = 288, PHP = 289, PLP = 290, SEI = 291, CLI = 292, NOP = 293, TYA = 294, TAY = 295, TXA = 296, TAX = 297, CLC = 298, SEC = 299, RTS = 300, JSR = 301, JMP = 302, BEQ = 303, BNE = 304, BCC = 305, BCS = 306, BPL = 307, BMI = 308, BVC = 309, BVS = 310, INX = 311, DEX = 312, INY = 313, DEY = 314, INC = 315, DEC = 316, LSR = 317, ASL = 318, ROR = 319, ROL = 320, SYMBOL = 321, STRING = 322, LAND = 323, LOR = 324, LNOT = 325, LPAREN = 326, RPAREN = 327, COMMA = 328, COLON = 329, X = 330, Y = 331, HASH = 332, PLUS = 333, MINUS = 334, MULT = 335, DIV = 336, MOD = 337, LT = 338, GT = 339, EQ = 340, NEQ = 341, ASSIGN = 342, NUMBER = 343, vNEG = 344 }; #endif /* Tokens. */ #define INCLUDE 258 #define IF 259 #define DEFINED 260 #define MACRO 261 #define MACRO_STRING 262 #define ORG 263 #define ERROR 264 #define ECHO 265 #define INCBIN 266 #define INCWORD 267 #define RES 268 #define WORD 269 #define BYTE 270 #define LDA 271 #define LDX 272 #define LDY 273 #define STA 274 #define STX 275 #define STY 276 #define AND 277 #define ORA 278 #define EOR 279 #define ADC 280 #define SBC 281 #define CMP 282 #define CPX 283 #define CPY 284 #define TSX 285 #define TXS 286 #define PHA 287 #define PLA 288 #define PHP 289 #define PLP 290 #define SEI 291 #define CLI 292 #define NOP 293 #define TYA 294 #define TAY 295 #define TXA 296 #define TAX 297 #define CLC 298 #define SEC 299 #define RTS 300 #define JSR 301 #define JMP 302 #define BEQ 303 #define BNE 304 #define BCC 305 #define BCS 306 #define BPL 307 #define BMI 308 #define BVC 309 #define BVS 310 #define INX 311 #define DEX 312 #define INY 313 #define DEY 314 #define INC 315 #define DEC 316 #define LSR 317 #define ASL 318 #define ROR 319 #define ROL 320 #define SYMBOL 321 #define STRING 322 #define LAND 323 #define LOR 324 #define LNOT 325 #define LPAREN 326 #define RPAREN 327 #define COMMA 328 #define COLON 329 #define X 330 #define Y 331 #define HASH 332 #define PLUS 333 #define MINUS 334 #define MULT 335 #define DIV 336 #define MOD 337 #define LT 338 #define GT 339 #define EQ 340 #define NEQ 341 #define ASSIGN 342 #define NUMBER 343 #define vNEG 344 /* Copy the first part of user declarations. */ // #line 1 "asm.y" #include "int.h" #include "parse.h" #include "vec.h" #include "membuf.h" #include "log.h" #include #define YYERROR_VERBOSE static struct vec asm_atoms[1]; /* Enabling traces. */ #ifndef YYDEBUG # define YYDEBUG 1 #endif /* Enabling verbose error messages. */ #ifdef YYERROR_VERBOSE # undef YYERROR_VERBOSE # define YYERROR_VERBOSE 1 #else # define YYERROR_VERBOSE 0 #endif /* Enabling the token table. */ #ifndef YYTOKEN_TABLE # define YYTOKEN_TABLE 0 #endif #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) // #line 110 "asm.y" typedef union YYSTYPE { i32 num; char *str; struct atom *atom; struct expr *expr; } YYSTYPE; /* Line 196 of yacc.c. */ // #line 282 "asm.tab.c" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif /* Copy the second part of user declarations. */ /* Line 219 of yacc.c. */ // #line 294 "asm.tab.c" #if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) # define YYSIZE_T __SIZE_TYPE__ #endif #if ! defined (YYSIZE_T) && defined (size_t) # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) && (defined (__STDC__) || defined (__cplusplus)) # include /* INFRINGES ON USER NAME SPACE */ # define YYSIZE_T size_t #endif #if ! defined (YYSIZE_T) # define YYSIZE_T unsigned int #endif #ifndef YY_ # if YYENABLE_NLS # if ENABLE_NLS # include /* INFRINGES ON USER NAME SPACE */ # define YY_(msgid) dgettext ("bison-runtime", msgid) # endif # endif # ifndef YY_ # define YY_(msgid) msgid # endif #endif #if ! defined (yyoverflow) || YYERROR_VERBOSE /* The parser invokes alloca or malloc; define the necessary symbols. */ # ifdef YYSTACK_USE_ALLOCA # if YYSTACK_USE_ALLOCA # ifdef __GNUC__ # define YYSTACK_ALLOC __builtin_alloca # else # define YYSTACK_ALLOC alloca # if defined (__STDC__) || defined (__cplusplus) # include /* INFRINGES ON USER NAME SPACE */ # define YYINCLUDED_STDLIB_H # endif # endif # endif # endif # ifdef YYSTACK_ALLOC /* Pacify GCC's `empty if-body' warning. */ # define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) # ifndef YYSTACK_ALLOC_MAXIMUM /* The OS might guarantee only one guard page at the bottom of the stack, and a page size can be as small as 4096 bytes. So we cannot safely invoke alloca (N) if N exceeds 4096. Use a slightly smaller number to allow for a few compiler-allocated temporary stack slots. */ # define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2005 */ # endif # else # define YYSTACK_ALLOC YYMALLOC # define YYSTACK_FREE YYFREE # ifndef YYSTACK_ALLOC_MAXIMUM # define YYSTACK_ALLOC_MAXIMUM ((YYSIZE_T) -1) # endif # ifdef __cplusplus extern "C" { # endif # ifndef YYMALLOC # define YYMALLOC malloc # if (! defined (malloc) && ! defined (YYINCLUDED_STDLIB_H) \ && (defined (__STDC__) || defined (__cplusplus))) void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifndef YYFREE # define YYFREE free # if (! defined (free) && ! defined (YYINCLUDED_STDLIB_H) \ && (defined (__STDC__) || defined (__cplusplus))) void free (void *); /* INFRINGES ON USER NAME SPACE */ # endif # endif # ifdef __cplusplus } # endif # endif #endif /* ! defined (yyoverflow) || YYERROR_VERBOSE */ #if (! defined (yyoverflow) \ && (! defined (__cplusplus) \ || (defined (YYSTYPE_IS_TRIVIAL) && YYSTYPE_IS_TRIVIAL))) /* A type that is properly aligned for any stack member. */ union yyalloc { short int yyss; YYSTYPE yyvs; }; /* The size of the maximum gap between one aligned stack and the next. */ # define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1) /* The size of an array large to enough to hold all stacks, each with N elements. */ # define YYSTACK_BYTES(N) \ ((N) * (sizeof (short int) + sizeof (YYSTYPE)) \ + YYSTACK_GAP_MAXIMUM) /* Copy COUNT objects from FROM to TO. The source and destination do not overlap. */ # ifndef YYCOPY # if defined (__GNUC__) && 1 < __GNUC__ # define YYCOPY(To, From, Count) \ __builtin_memcpy (To, From, (Count) * sizeof (*(From))) # else # define YYCOPY(To, From, Count) \ do \ { \ YYSIZE_T yyi; \ for (yyi = 0; yyi < (Count); yyi++) \ (To)[yyi] = (From)[yyi]; \ } \ while (0) # endif # endif /* Relocate STACK from its old location to the new one. The local variables YYSIZE and YYSTACKSIZE give the old and new number of elements in the stack, and YYPTR gives the new location of the stack. Advance YYPTR to a properly aligned location for the next stack. */ # define YYSTACK_RELOCATE(Stack) \ do \ { \ YYSIZE_T yynewbytes; \ YYCOPY (&yyptr->Stack, Stack, yysize); \ Stack = &yyptr->Stack; \ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \ yyptr += yynewbytes / sizeof (*yyptr); \ } \ while (0) #endif #if defined (__STDC__) || defined (__cplusplus) typedef signed char yysigned_char; #else typedef short int yysigned_char; #endif /* YYFINAL -- State number of the termination state. */ #define YYFINAL 212 /* YYLAST -- Last index in YYTABLE. */ #define YYLAST 591 /* YYNTOKENS -- Number of terminals. */ #define YYNTOKENS 90 /* YYNNTS -- Number of nonterminals. */ #define YYNNTS 17 /* YYNRULES -- Number of rules. */ #define YYNRULES 193 /* YYNRULES -- Number of states. */ #define YYNSTATES 307 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */ #define YYUNDEFTOK 2 #define YYMAXUTOK 344 #define YYTRANSLATE(YYX) \ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK) /* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */ static const unsigned char yytranslate[] = { 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89 }; #if YYDEBUG /* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in YYRHS. */ static const unsigned short int yyprhs[] = { 0, 0, 3, 6, 8, 11, 15, 20, 25, 30, 35, 40, 45, 47, 49, 51, 58, 63, 68, 73, 80, 89, 93, 95, 98, 101, 104, 107, 110, 113, 116, 119, 122, 125, 128, 131, 134, 137, 140, 143, 146, 149, 152, 155, 158, 161, 164, 167, 170, 173, 176, 179, 182, 185, 188, 191, 194, 197, 200, 203, 206, 209, 212, 215, 218, 221, 224, 227, 230, 233, 236, 239, 242, 245, 248, 251, 254, 257, 260, 263, 266, 269, 272, 275, 278, 281, 284, 287, 290, 293, 296, 299, 302, 305, 308, 311, 314, 317, 320, 323, 326, 329, 332, 335, 338, 341, 344, 347, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 385, 388, 391, 394, 397, 400, 403, 406, 409, 412, 414, 416, 418, 420, 423, 426, 429, 432, 435, 438, 441, 444, 446, 449, 452, 455, 458, 460, 463, 466, 469, 472, 474, 477, 480, 483, 486, 488, 491, 494, 497, 500, 503, 505, 509, 513, 516, 521, 526, 532, 538, 542, 546, 550, 554, 558, 561, 565, 572, 574, 576, 580, 584, 587, 591, 595, 599, 603, 607 }; /* YYRHS -- A `-1'-separated list of the rules' RHS. */ static const yysigned_char yyrhs[] = { 91, 0, -1, 91, 92, -1, 92, -1, 66, 74, -1, 66, 87, 105, -1, 4, 71, 106, 72, -1, 8, 71, 105, 72, -1, 9, 71, 67, 72, -1, 10, 71, 67, 72, -1, 3, 71, 67, 72, -1, 6, 71, 67, 72, -1, 93, -1, 7, -1, 95, -1, 13, 71, 105, 73, 105, 72, -1, 14, 71, 94, 72, -1, 15, 71, 94, 72, -1, 11, 71, 67, 72, -1, 11, 71, 67, 73, 105, 72, -1, 11, 71, 67, 73, 105, 73, 105, 72, -1, 94, 73, 105, -1, 105, -1, 16, 96, -1, 16, 100, -1, 16, 101, -1, 16, 97, -1, 16, 98, -1, 16, 99, -1, 16, 103, -1, 16, 104, -1, 17, 96, -1, 17, 100, -1, 17, 102, -1, 17, 97, -1, 17, 99, -1, 18, 96, -1, 18, 100, -1, 18, 101, -1, 18, 97, -1, 18, 99, -1, 19, 100, -1, 19, 101, -1, 19, 97, -1, 19, 98, -1, 19, 99, -1, 19, 103, -1, 19, 104, -1, 20, 100, -1, 20, 102, -1, 20, 97, -1, 21, 100, -1, 21, 101, -1, 21, 97, -1, 22, 96, -1, 22, 100, -1, 22, 101, -1, 22, 97, -1, 22, 98, -1, 22, 99, -1, 22, 103, -1, 22, 104, -1, 23, 96, -1, 23, 100, -1, 23, 101, -1, 23, 97, -1, 23, 98, -1, 23, 99, -1, 23, 103, -1, 23, 104, -1, 24, 96, -1, 24, 100, -1, 24, 101, -1, 24, 97, -1, 24, 98, -1, 24, 99, -1, 24, 103, -1, 24, 104, -1, 25, 96, -1, 25, 100, -1, 25, 101, -1, 25, 97, -1, 25, 98, -1, 25, 99, -1, 25, 103, -1, 25, 104, -1, 26, 96, -1, 26, 100, -1, 26, 101, -1, 26, 97, -1, 26, 98, -1, 26, 99, -1, 26, 103, -1, 26, 104, -1, 27, 96, -1, 27, 100, -1, 27, 101, -1, 27, 97, -1, 27, 98, -1, 27, 99, -1, 27, 103, -1, 27, 104, -1, 28, 96, -1, 28, 100, -1, 28, 97, -1, 29, 96, -1, 29, 100, -1, 29, 97, -1, 31, -1, 30, -1, 32, -1, 33, -1, 34, -1, 35, -1, 36, -1, 37, -1, 38, -1, 39, -1, 40, -1, 41, -1, 42, -1, 43, -1, 44, -1, 45, -1, 46, 97, -1, 47, 97, -1, 48, 97, -1, 49, 97, -1, 50, 97, -1, 51, 97, -1, 52, 97, -1, 53, 97, -1, 54, 97, -1, 55, 97, -1, 56, -1, 57, -1, 58, -1, 59, -1, 60, 100, -1, 60, 101, -1, 60, 97, -1, 60, 98, -1, 61, 100, -1, 61, 101, -1, 61, 97, -1, 61, 98, -1, 62, -1, 62, 100, -1, 62, 101, -1, 62, 97, -1, 62, 98, -1, 63, -1, 63, 100, -1, 63, 101, -1, 63, 97, -1, 63, 98, -1, 64, -1, 64, 100, -1, 64, 101, -1, 64, 97, -1, 64, 98, -1, 65, -1, 65, 100, -1, 65, 101, -1, 65, 97, -1, 65, 98, -1, 77, 105, -1, 105, -1, 105, 73, 75, -1, 105, 73, 76, -1, 83, 105, -1, 83, 105, 73, 75, -1, 83, 105, 73, 76, -1, 71, 105, 73, 75, 72, -1, 71, 105, 72, 73, 76, -1, 105, 78, 105, -1, 105, 79, 105, -1, 105, 80, 105, -1, 105, 81, 105, -1, 105, 82, 105, -1, 79, 105, -1, 71, 105, 72, -1, 12, 71, 67, 73, 105, 72, -1, 88, -1, 66, -1, 106, 69, 106, -1, 106, 68, 106, -1, 70, 106, -1, 71, 106, 72, -1, 105, 83, 105, -1, 105, 84, 105, -1, 105, 85, 105, -1, 105, 86, 105, -1, 5, 71, 66, 72, -1 }; /* YYRLINE[YYN] -- source line where rule number YYN was defined. */ static const unsigned short int yyrline[] = { 0, 144, 144, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 156, 157, 158, 159, 160, 162, 164, 167, 168, 170, 171, 172, 173, 174, 175, 176, 177, 179, 180, 181, 182, 183, 185, 186, 187, 188, 189, 191, 192, 193, 194, 195, 196, 197, 199, 200, 201, 203, 204, 205, 207, 208, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219, 220, 221, 222, 223, 225, 226, 227, 228, 229, 230, 231, 232, 234, 235, 236, 237, 238, 239, 240, 241, 243, 244, 245, 246, 247, 248, 249, 250, 252, 253, 254, 255, 256, 257, 258, 259, 261, 262, 263, 264, 265, 266, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 296, 297, 298, 299, 301, 302, 303, 304, 306, 307, 308, 309, 311, 312, 313, 314, 315, 317, 318, 319, 320, 321, 323, 324, 325, 326, 327, 329, 330, 331, 332, 333, 335, 336, 337, 338, 339, 340, 341, 342, 343, 345, 346, 347, 348, 349, 350, 351, 352, 354, 355, 357, 358, 359, 360, 361, 362, 363, 364, 366 }; #endif #if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE /* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM. First, the terminals, then, starting at YYNTOKENS, nonterminals. */ static const char *const yytname[] = { "$end", "error", "$undefined", "INCLUDE", "IF", "DEFINED", "MACRO", "MACRO_STRING", "ORG", "ERROR", "ECHO", "INCBIN", "INCWORD", "RES", "WORD", "BYTE", "LDA", "LDX", "LDY", "STA", "STX", "STY", "AND", "ORA", "EOR", "ADC", "SBC", "CMP", "CPX", "CPY", "TSX", "TXS", "PHA", "PLA", "PHP", "PLP", "SEI", "CLI", "NOP", "TYA", "TAY", "TXA", "TAX", "CLC", "SEC", "RTS", "JSR", "JMP", "BEQ", "BNE", "BCC", "BCS", "BPL", "BMI", "BVC", "BVS", "INX", "DEX", "INY", "DEY", "INC", "DEC", "LSR", "ASL", "ROR", "ROL", "SYMBOL", "STRING", "LAND", "LOR", "LNOT", "LPAREN", "RPAREN", "COMMA", "COLON", "X", "Y", "HASH", "PLUS", "MINUS", "MULT", "DIV", "MOD", "LT", "GT", "EQ", "NEQ", "ASSIGN", "NUMBER", "vNEG", "$accept", "stmts", "stmt", "atom", "exprs", "op", "am_im", "am_a", "am_ax", "am_ay", "am_zp", "am_zpx", "am_zpy", "am_ix", "am_iy", "expr", "lexpr", 0 }; #endif # ifdef YYPRINT /* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to token YYLEX-NUM. */ static const unsigned short int yytoknum[] = { 0, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344 }; # endif /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ static const unsigned char yyr1[] = { 0, 90, 91, 91, 92, 92, 92, 92, 92, 92, 92, 92, 92, 92, 93, 93, 93, 93, 93, 93, 93, 94, 94, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, 106, 106, 106, 106, 106, 106, 106, 106, 106 }; /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ static const unsigned char yyr2[] = { 0, 2, 2, 1, 2, 3, 4, 4, 4, 4, 4, 4, 1, 1, 1, 6, 4, 4, 4, 6, 8, 3, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 1, 3, 3, 2, 4, 4, 5, 5, 3, 3, 3, 3, 3, 2, 3, 6, 1, 1, 3, 3, 2, 3, 3, 3, 3, 3, 4 }; /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state STATE-NUM when YYTABLE doesn't specify something else to do. Zero means the default is an error. */ static const unsigned char yydefact[] = { 0, 0, 0, 0, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 109, 108, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 134, 135, 136, 137, 0, 0, 146, 151, 156, 161, 0, 0, 3, 12, 14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 184, 0, 0, 0, 0, 183, 23, 26, 27, 28, 24, 25, 29, 30, 167, 0, 0, 31, 34, 35, 32, 33, 167, 36, 39, 40, 37, 38, 43, 44, 45, 41, 42, 46, 47, 50, 48, 49, 167, 53, 51, 52, 54, 57, 58, 59, 55, 56, 60, 61, 62, 65, 66, 67, 63, 64, 68, 69, 70, 73, 74, 75, 71, 72, 76, 77, 78, 81, 82, 83, 79, 80, 84, 85, 86, 89, 90, 91, 87, 88, 92, 93, 94, 97, 98, 99, 95, 96, 100, 101, 0, 102, 104, 103, 105, 107, 106, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 140, 141, 138, 139, 167, 144, 145, 142, 143, 149, 150, 147, 148, 154, 155, 152, 153, 159, 160, 157, 158, 164, 165, 162, 163, 4, 0, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 166, 180, 170, 0, 0, 0, 0, 0, 0, 0, 170, 0, 170, 0, 5, 10, 0, 187, 0, 0, 0, 0, 0, 0, 0, 0, 6, 11, 7, 8, 9, 18, 0, 0, 16, 0, 17, 0, 181, 0, 0, 168, 169, 175, 176, 177, 178, 179, 181, 0, 0, 188, 189, 190, 191, 192, 186, 185, 0, 0, 21, 0, 0, 0, 171, 172, 193, 19, 0, 15, 0, 174, 173, 0, 182, 20 }; /* YYDEFGOTO[NTERM-NUM]. */ static const short int yydefgoto[] = { -1, 63, 64, 65, 226, 66, 84, 85, 86, 87, 88, 89, 99, 90, 91, 116, 219 }; /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing STATE-NUM. */ #define YYPACT_NINF -202 static const short int yypact[] = { 339, -67, -28, -14, -202, -10, -6, -5, 1, 4, 5, 9, 8, 22, 23, 41, 48, 59, 8, 8, 8, 8, 8, 8, 38, 38, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 78, 78, 78, 78, 78, 78, 78, 78, 78, 78, -202, -202, -202, -202, 59, 59, 59, 59, 59, 59, -69, 275, -202, -202, -202, -8, 7, 16, 78, 17, 25, 30, 78, 78, 78, 27, -202, 78, 78, 78, 78, -202, -202, -202, -202, -202, -202, -202, -202, -202, 441, 78, 78, -202, -202, -202, -202, -202, 451, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 102, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 78, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 461, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, -202, 78, -202, -202, 31, 37, 7, 7, 188, 65, 44, 399, 46, 50, -59, 471, -51, 102, -36, 56, -40, 102, -202, 481, -24, 78, 78, 78, 78, 78, 410, 491, 52, 102, 57, 102, -202, 47, -202, -55, 71, 78, 78, 78, 78, 7, 7, -202, -202, -202, -202, -202, -202, 78, 78, -202, 78, -202, 62, 68, 73, 80, -202, -202, 70, 70, -202, -202, -202, -202, 69, 74, -202, 102, 102, 102, 102, -202, 117, 394, 415, 102, 78, 112, 124, -202, -202, -202, -202, 78, -202, 426, -202, -202, 431, -202, -202 }; /* YYPGOTO[NTERM-NUM]. */ static const short int yypgoto[] = { -202, -202, 134, -202, 122, -202, 140, 393, 404, 242, 154, 172, 184, 559, 568, -12, -201 }; /* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If positive, shift that token. If negative, reduce the rule which number is the opposite. If zero, do what YYDEFACT says. If YYTABLE_NINF, syntax error. */ #define YYTABLE_NINF -1 static const unsigned short int yytable[] = { 92, 100, 100, 92, 67, 210, 92, 92, 92, 92, 92, 92, 215, 262, 263, 248, 250, 279, 211, 77, 77, 265, 266, 235, 236, 237, 238, 239, 251, 252, 253, 254, 269, 270, 77, 77, 267, 266, 235, 236, 237, 238, 239, 68, 189, 189, 189, 189, 189, 189, 77, 272, 273, 77, 287, 288, 218, 69, 221, 214, 77, 70, 225, 227, 227, 71, 72, 230, 231, 232, 233, 77, 73, 78, 78, 74, 75, 216, 217, 79, 76, 240, 241, 220, 222, 80, 81, 81, 78, 78, 77, 82, 223, 93, 93, 83, 83, 224, 229, 80, 80, 81, 81, 246, 78, 94, 82, 78, 247, 93, 83, 83, 79, 281, 78, 80, 258, 81, 260, 93, 81, 168, 261, 268, 82, 78, 83, 81, 273, 83, 93, 94, 272, 255, 256, 292, 83, 257, 81, 255, 256, 293, 82, 282, 78, 296, 297, 83, 294, 93, 237, 238, 239, 95, 101, 295, 243, 81, 120, 128, 136, 144, 152, 160, 169, 172, 83, 98, 104, 109, 114, 118, 124, 132, 140, 148, 156, 164, 171, 174, 235, 236, 237, 238, 239, 255, 105, 110, 302, 119, 125, 133, 141, 149, 157, 165, 303, 213, 228, 245, 115, 0, 0, 0, 218, 249, 0, 0, 0, 0, 187, 192, 196, 200, 204, 208, 0, 0, 0, 0, 0, 0, 0, 274, 275, 276, 277, 278, 188, 193, 197, 201, 205, 209, 0, 0, 0, 0, 0, 283, 284, 285, 286, 218, 218, 0, 0, 0, 0, 0, 0, 289, 290, 0, 291, 97, 103, 108, 0, 0, 123, 131, 139, 147, 155, 163, 235, 236, 237, 238, 239, 251, 252, 253, 254, 212, 0, 0, 1, 2, 301, 3, 4, 5, 6, 7, 8, 304, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 1, 2, 0, 3, 4, 5, 6, 7, 8, 0, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 96, 102, 106, 113, 117, 121, 129, 137, 145, 153, 161, 170, 173, 107, 0, 0, 122, 130, 138, 146, 154, 162, 0, 0, 0, 0, 0, 0, 0, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 0, 0, 0, 0, 185, 190, 194, 198, 202, 206, 0, 0, 0, 0, 0, 186, 191, 195, 199, 203, 207, 298, 299, 0, 0, 0, 259, 235, 236, 237, 238, 239, 235, 236, 237, 238, 239, 279, 0, 0, 0, 0, 300, 235, 236, 237, 238, 239, 235, 236, 237, 238, 239, 305, 0, 0, 0, 0, 306, 235, 236, 237, 238, 239, 235, 236, 237, 238, 239, 234, 0, 0, 0, 0, 235, 236, 237, 238, 239, 242, 0, 0, 0, 0, 235, 236, 237, 238, 239, 244, 0, 0, 0, 0, 235, 236, 237, 238, 239, 264, 0, 0, 0, 0, 235, 236, 237, 238, 239, 271, 0, 0, 0, 0, 235, 236, 237, 238, 239, 280, 0, 0, 0, 0, 235, 236, 237, 238, 239, 111, 0, 0, 126, 134, 142, 150, 158, 166, 112, 0, 0, 127, 135, 143, 151, 159, 167 }; static const short int yycheck[] = { 12, 13, 14, 15, 71, 74, 18, 19, 20, 21, 22, 23, 5, 72, 73, 216, 217, 72, 87, 12, 12, 72, 73, 78, 79, 80, 81, 82, 83, 84, 85, 86, 72, 73, 12, 12, 72, 73, 78, 79, 80, 81, 82, 71, 56, 57, 58, 59, 60, 61, 12, 75, 76, 12, 255, 256, 68, 71, 70, 67, 12, 71, 74, 75, 76, 71, 71, 79, 80, 81, 82, 12, 71, 66, 66, 71, 71, 70, 71, 71, 71, 93, 94, 67, 67, 77, 79, 79, 66, 66, 12, 83, 67, 71, 71, 88, 88, 67, 71, 77, 77, 79, 79, 72, 66, 83, 83, 66, 71, 71, 88, 88, 71, 66, 66, 77, 72, 79, 72, 71, 79, 83, 72, 67, 83, 66, 88, 79, 76, 88, 71, 83, 75, 68, 69, 73, 88, 72, 79, 68, 69, 73, 83, 72, 66, 76, 72, 88, 75, 71, 80, 81, 82, 13, 14, 75, 168, 79, 18, 19, 20, 21, 22, 23, 24, 25, 88, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 78, 79, 80, 81, 82, 68, 14, 15, 76, 17, 18, 19, 20, 21, 22, 23, 72, 63, 76, 211, 16, -1, -1, -1, 216, 217, -1, -1, -1, -1, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 235, 236, 237, 238, 239, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, 251, 252, 253, 254, 255, 256, -1, -1, -1, -1, -1, -1, 263, 264, -1, 266, 13, 14, 15, -1, -1, 18, 19, 20, 21, 22, 23, 78, 79, 80, 81, 82, 83, 84, 85, 86, 0, -1, -1, 3, 4, 292, 6, 7, 8, 9, 10, 11, 299, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 3, 4, -1, 6, 7, 8, 9, 10, 11, -1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 15, -1, -1, 18, 19, 20, 21, 22, 23, -1, -1, -1, -1, -1, -1, -1, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, 56, 57, 58, 59, 60, 61, 72, 73, -1, -1, -1, 72, 78, 79, 80, 81, 82, 78, 79, 80, 81, 82, 72, -1, -1, -1, -1, 72, 78, 79, 80, 81, 82, 78, 79, 80, 81, 82, 72, -1, -1, -1, -1, 72, 78, 79, 80, 81, 82, 78, 79, 80, 81, 82, 73, -1, -1, -1, -1, 78, 79, 80, 81, 82, 73, -1, -1, -1, -1, 78, 79, 80, 81, 82, 73, -1, -1, -1, -1, 78, 79, 80, 81, 82, 73, -1, -1, -1, -1, 78, 79, 80, 81, 82, 73, -1, -1, -1, -1, 78, 79, 80, 81, 82, 73, -1, -1, -1, -1, 78, 79, 80, 81, 82, 15, -1, -1, 18, 19, 20, 21, 22, 23, 15, -1, -1, 18, 19, 20, 21, 22, 23 }; /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing symbol of state STATE-NUM. */ static const unsigned char yystos[] = { 0, 3, 4, 6, 7, 8, 9, 10, 11, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 91, 92, 93, 95, 71, 71, 71, 71, 71, 71, 71, 71, 71, 71, 12, 66, 71, 77, 79, 83, 88, 96, 97, 98, 99, 100, 101, 103, 104, 105, 71, 83, 96, 97, 99, 100, 102, 105, 96, 97, 99, 100, 101, 97, 98, 99, 100, 101, 103, 104, 97, 100, 102, 105, 97, 100, 101, 96, 97, 98, 99, 100, 101, 103, 104, 96, 97, 98, 99, 100, 101, 103, 104, 96, 97, 98, 99, 100, 101, 103, 104, 96, 97, 98, 99, 100, 101, 103, 104, 96, 97, 98, 99, 100, 101, 103, 104, 96, 97, 98, 99, 100, 101, 103, 104, 83, 96, 97, 100, 96, 97, 100, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 100, 101, 105, 97, 98, 100, 101, 97, 98, 100, 101, 97, 98, 100, 101, 97, 98, 100, 101, 97, 98, 100, 101, 74, 87, 0, 92, 67, 5, 70, 71, 105, 106, 67, 105, 67, 67, 67, 105, 94, 105, 94, 71, 105, 105, 105, 105, 73, 78, 79, 80, 81, 82, 105, 105, 73, 105, 73, 105, 72, 71, 106, 105, 106, 83, 84, 85, 86, 68, 69, 72, 72, 72, 72, 72, 72, 73, 73, 72, 73, 72, 67, 72, 73, 73, 75, 76, 105, 105, 105, 105, 105, 72, 73, 66, 72, 105, 105, 105, 105, 106, 106, 105, 105, 105, 73, 73, 75, 75, 76, 72, 72, 73, 72, 105, 76, 72, 105, 72, 72 }; #define yyerrok (yyerrstatus = 0) #define yyclearin (yychar = YYEMPTY) #define YYEMPTY (-2) #define YYEOF 0 #define YYACCEPT goto yyacceptlab #define YYABORT goto yyabortlab #define YYERROR goto yyerrorlab /* Like YYERROR except do call yyerror. This remains here temporarily to ease the transition to the new meaning of YYERROR, for GCC. Once GCC version 2 has supplanted version 1, this can go. */ #define YYFAIL goto yyerrlab #define YYRECOVERING() (!!yyerrstatus) #define YYBACKUP(Token, Value) \ do \ if (yychar == YYEMPTY && yylen == 1) \ { \ yychar = (Token); \ yylval = (Value); \ yytoken = YYTRANSLATE (yychar); \ YYPOPSTACK; \ goto yybackup; \ } \ else \ { \ yyerror (YY_("syntax error: cannot back up")); \ YYERROR; \ } \ while (0) #define YYTERROR 1 #define YYERRCODE 256 /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. If N is 0, then set CURRENT to the empty location which ends the previous symbol: RHS[0] (always defined). */ #define YYRHSLOC(Rhs, K) ((Rhs)[K]) #ifndef YYLLOC_DEFAULT # define YYLLOC_DEFAULT(Current, Rhs, N) \ do \ if (N) \ { \ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \ } \ else \ { \ (Current).first_line = (Current).last_line = \ YYRHSLOC (Rhs, 0).last_line; \ (Current).first_column = (Current).last_column = \ YYRHSLOC (Rhs, 0).last_column; \ } \ while (0) #endif /* YY_LOCATION_PRINT -- Print the location on the stream. This macro was not mandated originally: define only if we know we won't break user code: when these are the locations we know. */ #ifndef YY_LOCATION_PRINT # if YYLTYPE_IS_TRIVIAL # define YY_LOCATION_PRINT(File, Loc) \ fprintf (File, "%d.%d-%d.%d", \ (Loc).first_line, (Loc).first_column, \ (Loc).last_line, (Loc).last_column) # else # define YY_LOCATION_PRINT(File, Loc) ((void) 0) # endif #endif /* YYLEX -- calling `yylex' with the right arguments. */ #ifdef YYLEX_PARAM # define YYLEX yylex (YYLEX_PARAM) #else # define YYLEX yylex () #endif /* Enable debugging if requested. */ #if YYDEBUG # ifndef YYFPRINTF # include /* INFRINGES ON USER NAME SPACE */ # define YYFPRINTF fprintf # endif # define YYDPRINTF(Args) \ do { \ if (yydebug) \ YYFPRINTF Args; \ } while (0) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) \ do { \ if (yydebug) \ { \ YYFPRINTF (stderr, "%s ", Title); \ yysymprint (stderr, \ Type, Value); \ YYFPRINTF (stderr, "\n"); \ } \ } while (0) /*------------------------------------------------------------------. | yy_stack_print -- Print the state stack from its BOTTOM up to its | | TOP (included). | `------------------------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_stack_print (short int *bottom, short int *top) #else static void yy_stack_print (bottom, top) short int *bottom; short int *top; #endif { YYFPRINTF (stderr, "Stack now"); for (/* Nothing. */; bottom <= top; ++bottom) YYFPRINTF (stderr, " %d", *bottom); YYFPRINTF (stderr, "\n"); } # define YY_STACK_PRINT(Bottom, Top) \ do { \ if (yydebug) \ yy_stack_print ((Bottom), (Top)); \ } while (0) /*------------------------------------------------. | Report that the YYRULE is going to be reduced. | `------------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yy_reduce_print (int yyrule) #else static void yy_reduce_print (yyrule) int yyrule; #endif { int yyi; unsigned long int yylno = yyrline[yyrule]; YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu), ", yyrule - 1, yylno); /* Print the symbols being reduced, and their result. */ for (yyi = yyprhs[yyrule]; 0 <= yyrhs[yyi]; yyi++) YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); YYFPRINTF (stderr, "-> %s\n", yytname[yyr1[yyrule]]); } # define YY_REDUCE_PRINT(Rule) \ do { \ if (yydebug) \ yy_reduce_print (Rule); \ } while (0) /* Nonzero means print parse trace. It is left uninitialized so that multiple parsers can coexist. */ int yydebug; #else /* !YYDEBUG */ # define YYDPRINTF(Args) # define YY_SYMBOL_PRINT(Title, Type, Value, Location) # define YY_STACK_PRINT(Bottom, Top) # define YY_REDUCE_PRINT(Rule) #endif /* !YYDEBUG */ /* YYINITDEPTH -- initial size of the parser's stacks. */ #ifndef YYINITDEPTH # define YYINITDEPTH 200 #endif /* YYMAXDEPTH -- maximum size the stacks can grow to (effective only if the built-in stack extension method is used). Do not make this value too large; the results are undefined if YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH) evaluated with infinite-precision integer arithmetic. */ #ifndef YYMAXDEPTH # define YYMAXDEPTH 10000 #endif #if YYERROR_VERBOSE # ifndef yystrlen # if defined (__GLIBC__) && defined (_STRING_H) # define yystrlen strlen # else /* Return the length of YYSTR. */ static YYSIZE_T # if defined (__STDC__) || defined (__cplusplus) yystrlen (const char *yystr) # else yystrlen (yystr) const char *yystr; # endif { const char *yys = yystr; while (*yys++ != '\0') continue; return yys - yystr - 1; } # endif # endif # ifndef yystpcpy # if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) # define yystpcpy stpcpy # else /* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in YYDEST. */ static char * # if defined (__STDC__) || defined (__cplusplus) yystpcpy (char *yydest, const char *yysrc) # else yystpcpy (yydest, yysrc) char *yydest; const char *yysrc; # endif { char *yyd = yydest; const char *yys = yysrc; while ((*yyd++ = *yys++) != '\0') continue; return yyd - 1; } # endif # endif # ifndef yytnamerr /* Copy to YYRES the contents of YYSTR after stripping away unnecessary quotes and backslashes, so that it's suitable for yyerror. The heuristic is that double-quoting is unnecessary unless the string contains an apostrophe, a comma, or backslash (other than backslash-backslash). YYSTR is taken from yytname. If YYRES is null, do not copy; instead, return the length of what the result would have been. */ static YYSIZE_T yytnamerr (char *yyres, const char *yystr) { if (*yystr == '"') { size_t yyn = 0; char const *yyp = yystr; for (;;) switch (*++yyp) { case '\'': case ',': goto do_not_strip_quotes; case '\\': if (*++yyp != '\\') goto do_not_strip_quotes; /* Fall through. */ default: if (yyres) yyres[yyn] = *yyp; yyn++; break; case '"': if (yyres) yyres[yyn] = '\0'; return yyn; } do_not_strip_quotes: ; } if (! yyres) return yystrlen (yystr); return yystpcpy (yyres, yystr) - yyres; } # endif #endif /* YYERROR_VERBOSE */ #if YYDEBUG /*--------------------------------. | Print this symbol on YYOUTPUT. | `--------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yysymprint (FILE *yyoutput, int yytype, YYSTYPE *yyvaluep) #else static void yysymprint (yyoutput, yytype, yyvaluep) FILE *yyoutput; int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; if (yytype < YYNTOKENS) YYFPRINTF (yyoutput, "token %s (", yytname[yytype]); else YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]); # ifdef YYPRINT if (yytype < YYNTOKENS) YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep); # endif switch (yytype) { default: break; } YYFPRINTF (yyoutput, ")"); } #endif /* ! YYDEBUG */ /*-----------------------------------------------. | Release the memory associated to this symbol. | `-----------------------------------------------*/ #if defined (__STDC__) || defined (__cplusplus) static void yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep) #else static void yydestruct (yymsg, yytype, yyvaluep) const char *yymsg; int yytype; YYSTYPE *yyvaluep; #endif { /* Pacify ``unused variable'' warnings. */ (void) yyvaluep; if (!yymsg) yymsg = "Deleting"; YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp); switch (yytype) { default: break; } } /* Prevent warnings from -Wmissing-prototypes. */ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM); # else int yyparse (); # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void); #else int yyparse (); #endif #endif /* ! YYPARSE_PARAM */ void yycleanup(); /* The look-ahead symbol. */ int yychar; /* The semantic value of the look-ahead symbol. */ YYSTYPE yylval; /* Number of syntax errors so far. */ int yynerrs; /*----------. | yyparse. | `----------*/ #ifdef YYPARSE_PARAM # if defined (__STDC__) || defined (__cplusplus) int yyparse (void *YYPARSE_PARAM) # else int yyparse (YYPARSE_PARAM) void *YYPARSE_PARAM; # endif #else /* ! YYPARSE_PARAM */ #if defined (__STDC__) || defined (__cplusplus) int yyparse (void) #else int yyparse () ; #endif #endif { int yystate; int yyn; int yyresult; /* Number of tokens to shift before error messages enabled. */ int yyerrstatus; /* Look-ahead token as an internal (translated) token number. */ int yytoken = 0; /* Three stacks and their tools: `yyss': related to states, `yyvs': related to semantic values, `yyls': related to locations. Refer to the stacks thru separate pointers, to allow yyoverflow to reallocate them elsewhere. */ /* The state stack. */ short int yyssa[YYINITDEPTH]; short int *yyss = yyssa; short int *yyssp; /* The semantic value stack. */ YYSTYPE yyvsa[YYINITDEPTH]; YYSTYPE *yyvs = yyvsa; YYSTYPE *yyvsp; #define YYPOPSTACK (yyvsp--, yyssp--) YYSIZE_T yystacksize = YYINITDEPTH; /* The variables used to return semantic value and location from the action routines. */ YYSTYPE yyval; /* When reducing, the number of symbols on the RHS of the reduced rule. */ int yylen; YYDPRINTF ((stderr, "Starting parse\n")); yystate = 0; yyerrstatus = 0; yynerrs = 0; yychar = YYEMPTY; /* Cause a token to be read. */ /* Initialize stack pointers. Waste one element of value and location stack so that they stay on the same level as the state stack. The wasted elements are never initialized. */ yyssp = yyss; yyvsp = yyvs; goto yysetstate; /*------------------------------------------------------------. | yynewstate -- Push a new state, which is found in yystate. | `------------------------------------------------------------*/ yynewstate: /* In all cases, when you get here, the value and location stacks have just been pushed. so pushing a state here evens the stacks. */ yyssp++; yysetstate: *yyssp = yystate; if (yyss + yystacksize - 1 <= yyssp) { /* Get the current used size of the three stacks, in elements. */ YYSIZE_T yysize = yyssp - yyss + 1; #ifdef yyoverflow { /* Give user a chance to reallocate the stack. Use copies of these so that the &'s don't force the real ones into memory. */ YYSTYPE *yyvs1 = yyvs; short int *yyss1 = yyss; /* Each stack pointer address is followed by the size of the data in use in that stack, in bytes. This used to be a conditional around just the two extra args, but that might be undefined if yyoverflow is a macro. */ yyoverflow (YY_("memory exhausted"), &yyss1, yysize * sizeof (*yyssp), &yyvs1, yysize * sizeof (*yyvsp), &yystacksize); yyss = yyss1; yyvs = yyvs1; } #else /* no yyoverflow */ # ifndef YYSTACK_RELOCATE goto yyexhaustedlab; # else /* Extend the stack our own way. */ if (YYMAXDEPTH <= yystacksize) goto yyexhaustedlab; yystacksize *= 2; if (YYMAXDEPTH < yystacksize) yystacksize = YYMAXDEPTH; { short int *yyss1 = yyss; union yyalloc *yyptr = (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); if (! yyptr) goto yyexhaustedlab; YYSTACK_RELOCATE (yyss); YYSTACK_RELOCATE (yyvs); # undef YYSTACK_RELOCATE if (yyss1 != yyssa) YYSTACK_FREE (yyss1); } # endif #endif /* no yyoverflow */ yyssp = yyss + yysize - 1; yyvsp = yyvs + yysize - 1; YYDPRINTF ((stderr, "Stack size increased to %lu\n", (unsigned long int) yystacksize)); if (yyss + yystacksize - 1 <= yyssp) YYABORT; } YYDPRINTF ((stderr, "Entering state %d\n", yystate)); goto yybackup; /*-----------. | yybackup. | `-----------*/ yybackup: /* Do appropriate processing given the current state. */ /* Read a look-ahead token if we need one and don't already have one. */ /* yyresume: */ /* First try to decide what to do without reference to look-ahead token. */ yyn = yypact[yystate]; if (yyn == YYPACT_NINF) goto yydefault; /* Not known => get a look-ahead token if don't already have one. */ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */ if (yychar == YYEMPTY) { YYDPRINTF ((stderr, "Reading a token: ")); yychar = YYLEX; } if (yychar <= YYEOF) { yychar = yytoken = YYEOF; YYDPRINTF ((stderr, "Now at end of input.\n")); } else { yytoken = YYTRANSLATE (yychar); YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc); } /* If the proper action on seeing token YYTOKEN is to reduce or to detect an error, take that action. */ yyn += yytoken; if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken) goto yydefault; yyn = yytable[yyn]; if (yyn <= 0) { if (yyn == 0 || yyn == YYTABLE_NINF) goto yyerrlab; yyn = -yyn; goto yyreduce; } if (yyn == YYFINAL) YYACCEPT; /* Shift the look-ahead token. */ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc); /* Discard the token being shifted unless it is eof. */ if (yychar != YYEOF) yychar = YYEMPTY; *++yyvsp = yylval; /* Count tokens shifted since error; after three, turn off error status. */ if (yyerrstatus) yyerrstatus--; yystate = yyn; goto yynewstate; /*-----------------------------------------------------------. | yydefault -- do the default action for the current state. | `-----------------------------------------------------------*/ yydefault: yyn = yydefact[yystate]; if (yyn == 0) goto yyerrlab; goto yyreduce; /*-----------------------------. | yyreduce -- Do a reduction. | `-----------------------------*/ yyreduce: /* yyn is the number of a rule to reduce with. */ yylen = yyr2[yyn]; /* If YYLEN is nonzero, implement the default value of the action: `$$ = $1'. Otherwise, the following line sets YYVAL to garbage. This behavior is undocumented and Bison users should not rely upon it. Assigning to YYVAL unconditionally makes the parser a bit smaller, and it avoids a GCC warning that YYVAL may be used uninitialized. */ yyval = yyvsp[1-yylen]; YY_REDUCE_PRINT (yyn); switch (yyn) { case 4: // #line 145 "asm.y" { new_label((yyvsp[-1].str)); ;} break; case 5: // #line 146 "asm.y" { new_symbol_expr((yyvsp[-2].str), (yyvsp[0].expr)); ;} break; case 6: // #line 147 "asm.y" { push_if_state((yyvsp[-1].expr)); ;} break; case 7: // #line 148 "asm.y" { set_org((yyvsp[-1].expr)); ;} break; case 8: // #line 149 "asm.y" { asm_error((yyvsp[-1].str)); ;} break; case 9: // #line 150 "asm.y" { asm_echo((yyvsp[-1].str)); ;} break; case 10: // #line 151 "asm.y" { asm_include((yyvsp[-1].str)); ;} break; case 11: // #line 152 "asm.y" { push_macro_state((yyvsp[-1].str)); ;} break; case 12: // #line 153 "asm.y" { vec_push(asm_atoms, &(yyvsp[0].atom)); ;} break; case 13: // #line 154 "asm.y" { macro_append((yyvsp[0].str)) ;} break; case 14: // #line 156 "asm.y" { (yyval.atom) = (yyvsp[0].atom);} break; case 15: // #line 157 "asm.y" { (yyval.atom) = new_res((yyvsp[-3].expr), (yyvsp[-1].expr)); ;} break; case 16: // #line 158 "asm.y" { (yyval.atom) = exprs_to_word_exprs((yyvsp[-1].atom)); ;} break; case 17: // #line 159 "asm.y" { (yyval.atom) = exprs_to_byte_exprs((yyvsp[-1].atom)); ;} break; case 18: // #line 160 "asm.y" { (yyval.atom) = new_incbin((yyvsp[-1].str), NULL, NULL); ;} break; case 19: // #line 162 "asm.y" { (yyval.atom) = new_incbin((yyvsp[-3].str), (yyvsp[-1].expr), NULL); ;} break; case 20: // #line 164 "asm.y" { (yyval.atom) = new_incbin((yyvsp[-5].str), (yyvsp[-3].expr), (yyvsp[-1].expr)); ;} break; case 21: // #line 167 "asm.y" { (yyval.atom) = exprs_add((yyvsp[-2].atom), (yyvsp[0].expr)); ;} break; case 22: // #line 168 "asm.y" { (yyval.atom) = new_exprs((yyvsp[0].expr)); ;} break; case 23: // #line 170 "asm.y" { (yyval.atom) = new_op(0xA9, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 24: // #line 171 "asm.y" { (yyval.atom) = new_op(0xA5, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 25: // #line 172 "asm.y" { (yyval.atom) = new_op(0xB5, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 26: // #line 173 "asm.y" { (yyval.atom) = new_op(0xAD, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 27: // #line 174 "asm.y" { (yyval.atom) = new_op(0xBD, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 28: // #line 175 "asm.y" { (yyval.atom) = new_op(0xB9, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 29: // #line 176 "asm.y" { (yyval.atom) = new_op(0xA1, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 30: // #line 177 "asm.y" { (yyval.atom) = new_op(0xB1, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 31: // #line 179 "asm.y" { (yyval.atom) = new_op(0xA2, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 32: // #line 180 "asm.y" { (yyval.atom) = new_op(0xA6, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 33: // #line 181 "asm.y" { (yyval.atom) = new_op(0xB6, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 34: // #line 182 "asm.y" { (yyval.atom) = new_op(0xAE, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 35: // #line 183 "asm.y" { (yyval.atom) = new_op(0xBE, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 36: // #line 185 "asm.y" { (yyval.atom) = new_op(0xA0, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 37: // #line 186 "asm.y" { (yyval.atom) = new_op(0xA4, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 38: // #line 187 "asm.y" { (yyval.atom) = new_op(0xB4, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 39: // #line 188 "asm.y" { (yyval.atom) = new_op(0xAC, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 40: // #line 189 "asm.y" { (yyval.atom) = new_op(0xBC, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 41: // #line 191 "asm.y" { (yyval.atom) = new_op(0x85, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 42: // #line 192 "asm.y" { (yyval.atom) = new_op(0x95, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 43: // #line 193 "asm.y" { (yyval.atom) = new_op(0x8D, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 44: // #line 194 "asm.y" { (yyval.atom) = new_op(0x9D, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 45: // #line 195 "asm.y" { (yyval.atom) = new_op(0x99, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 46: // #line 196 "asm.y" { (yyval.atom) = new_op(0x81, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 47: // #line 197 "asm.y" { (yyval.atom) = new_op(0x91, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 48: // #line 199 "asm.y" { (yyval.atom) = new_op(0x86, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 49: // #line 200 "asm.y" { (yyval.atom) = new_op(0x96, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 50: // #line 201 "asm.y" { (yyval.atom) = new_op(0x8e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 51: // #line 203 "asm.y" { (yyval.atom) = new_op(0x84, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 52: // #line 204 "asm.y" { (yyval.atom) = new_op(0x94, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 53: // #line 205 "asm.y" { (yyval.atom) = new_op(0x8c, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 54: // #line 207 "asm.y" { (yyval.atom) = new_op(0x29, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 55: // #line 208 "asm.y" { (yyval.atom) = new_op(0x25, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 56: // #line 209 "asm.y" { (yyval.atom) = new_op(0x35, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 57: // #line 210 "asm.y" { (yyval.atom) = new_op(0x2d, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 58: // #line 211 "asm.y" { (yyval.atom) = new_op(0x3d, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 59: // #line 212 "asm.y" { (yyval.atom) = new_op(0x39, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 60: // #line 213 "asm.y" { (yyval.atom) = new_op(0x21, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 61: // #line 214 "asm.y" { (yyval.atom) = new_op(0x31, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 62: // #line 216 "asm.y" { (yyval.atom) = new_op(0x09, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 63: // #line 217 "asm.y" { (yyval.atom) = new_op(0x05, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 64: // #line 218 "asm.y" { (yyval.atom) = new_op(0x15, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 65: // #line 219 "asm.y" { (yyval.atom) = new_op(0x0d, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 66: // #line 220 "asm.y" { (yyval.atom) = new_op(0x1d, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 67: // #line 221 "asm.y" { (yyval.atom) = new_op(0x19, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 68: // #line 222 "asm.y" { (yyval.atom) = new_op(0x01, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 69: // #line 223 "asm.y" { (yyval.atom) = new_op(0x11, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 70: // #line 225 "asm.y" { (yyval.atom) = new_op(0x49, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 71: // #line 226 "asm.y" { (yyval.atom) = new_op(0x45, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 72: // #line 227 "asm.y" { (yyval.atom) = new_op(0x55, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 73: // #line 228 "asm.y" { (yyval.atom) = new_op(0x4d, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 74: // #line 229 "asm.y" { (yyval.atom) = new_op(0x5d, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 75: // #line 230 "asm.y" { (yyval.atom) = new_op(0x59, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 76: // #line 231 "asm.y" { (yyval.atom) = new_op(0x41, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 77: // #line 232 "asm.y" { (yyval.atom) = new_op(0x51, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 78: // #line 234 "asm.y" { (yyval.atom) = new_op(0x69, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 79: // #line 235 "asm.y" { (yyval.atom) = new_op(0x65, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 80: // #line 236 "asm.y" { (yyval.atom) = new_op(0x75, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 81: // #line 237 "asm.y" { (yyval.atom) = new_op(0x6D, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 82: // #line 238 "asm.y" { (yyval.atom) = new_op(0x7D, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 83: // #line 239 "asm.y" { (yyval.atom) = new_op(0x79, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 84: // #line 240 "asm.y" { (yyval.atom) = new_op(0x61, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 85: // #line 241 "asm.y" { (yyval.atom) = new_op(0x71, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 86: // #line 243 "asm.y" { (yyval.atom) = new_op(0xe9, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 87: // #line 244 "asm.y" { (yyval.atom) = new_op(0xe5, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 88: // #line 245 "asm.y" { (yyval.atom) = new_op(0xf5, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 89: // #line 246 "asm.y" { (yyval.atom) = new_op(0xeD, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 90: // #line 247 "asm.y" { (yyval.atom) = new_op(0xfD, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 91: // #line 248 "asm.y" { (yyval.atom) = new_op(0xf9, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 92: // #line 249 "asm.y" { (yyval.atom) = new_op(0xe1, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 93: // #line 250 "asm.y" { (yyval.atom) = new_op(0xf1, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 94: // #line 252 "asm.y" { (yyval.atom) = new_op(0xc9, ATOM_TYPE_OP_ARG_UI8, (yyvsp[0].expr)); ;} break; case 95: // #line 253 "asm.y" { (yyval.atom) = new_op(0xc5, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 96: // #line 254 "asm.y" { (yyval.atom) = new_op(0xd5, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 97: // #line 255 "asm.y" { (yyval.atom) = new_op(0xcD, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 98: // #line 256 "asm.y" { (yyval.atom) = new_op(0xdD, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 99: // #line 257 "asm.y" { (yyval.atom) = new_op(0xd9, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 100: // #line 258 "asm.y" { (yyval.atom) = new_op(0xc1, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 101: // #line 259 "asm.y" { (yyval.atom) = new_op(0xd1, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 102: // #line 261 "asm.y" { (yyval.atom) = new_op(0xe0, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 103: // #line 262 "asm.y" { (yyval.atom) = new_op(0xe4, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 104: // #line 263 "asm.y" { (yyval.atom) = new_op(0xec, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 105: // #line 264 "asm.y" { (yyval.atom) = new_op(0xc0, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 106: // #line 265 "asm.y" { (yyval.atom) = new_op(0xc4, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 107: // #line 266 "asm.y" { (yyval.atom) = new_op(0xcc, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 108: // #line 268 "asm.y" { (yyval.atom) = new_op0(0x9A); ;} break; case 109: // #line 269 "asm.y" { (yyval.atom) = new_op0(0xBA); ;} break; case 110: // #line 270 "asm.y" { (yyval.atom) = new_op0(0x48); ;} break; case 111: // #line 271 "asm.y" { (yyval.atom) = new_op0(0x68); ;} break; case 112: // #line 272 "asm.y" { (yyval.atom) = new_op0(0x08); ;} break; case 113: // #line 273 "asm.y" { (yyval.atom) = new_op0(0x28); ;} break; case 114: // #line 274 "asm.y" { (yyval.atom) = new_op0(0x78); ;} break; case 115: // #line 275 "asm.y" { (yyval.atom) = new_op0(0x58); ;} break; case 116: // #line 276 "asm.y" { (yyval.atom) = new_op0(0xea); ;} break; case 117: // #line 277 "asm.y" { (yyval.atom) = new_op0(0x98); ;} break; case 118: // #line 278 "asm.y" { (yyval.atom) = new_op0(0xa8); ;} break; case 119: // #line 279 "asm.y" { (yyval.atom) = new_op0(0x8a); ;} break; case 120: // #line 280 "asm.y" { (yyval.atom) = new_op0(0xaa); ;} break; case 121: // #line 281 "asm.y" { (yyval.atom) = new_op0(0x18); ;} break; case 122: // #line 282 "asm.y" { (yyval.atom) = new_op0(0x38); ;} break; case 123: // #line 283 "asm.y" { (yyval.atom) = new_op0(0x60); ;} break; case 124: // #line 285 "asm.y" { (yyval.atom) = new_op(0x20, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 125: // #line 286 "asm.y" { (yyval.atom) = new_op(0x4c, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 126: // #line 287 "asm.y" { (yyval.atom) = new_op(0xf0, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 127: // #line 288 "asm.y" { (yyval.atom) = new_op(0xd0, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 128: // #line 289 "asm.y" { (yyval.atom) = new_op(0x90, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 129: // #line 290 "asm.y" { (yyval.atom) = new_op(0xb0, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 130: // #line 291 "asm.y" { (yyval.atom) = new_op(0x10, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 131: // #line 292 "asm.y" { (yyval.atom) = new_op(0x30, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 132: // #line 293 "asm.y" { (yyval.atom) = new_op(0x50, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 133: // #line 294 "asm.y" { (yyval.atom) = new_op(0x70, ATOM_TYPE_OP_ARG_I8, (yyvsp[0].expr)); ;} break; case 134: // #line 296 "asm.y" { (yyval.atom) = new_op0(0xe8); ;} break; case 135: // #line 297 "asm.y" { (yyval.atom) = new_op0(0xca); ;} break; case 136: // #line 298 "asm.y" { (yyval.atom) = new_op0(0xc8); ;} break; case 137: // #line 299 "asm.y" { (yyval.atom) = new_op0(0x88); ;} break; case 138: // #line 301 "asm.y" { (yyval.atom) = new_op(0xe6, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 139: // #line 302 "asm.y" { (yyval.atom) = new_op(0xf6, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 140: // #line 303 "asm.y" { (yyval.atom) = new_op(0xee, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 141: // #line 304 "asm.y" { (yyval.atom) = new_op(0xfe, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 142: // #line 306 "asm.y" { (yyval.atom) = new_op(0xc6, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 143: // #line 307 "asm.y" { (yyval.atom) = new_op(0xd6, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 144: // #line 308 "asm.y" { (yyval.atom) = new_op(0xce, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 145: // #line 309 "asm.y" { (yyval.atom) = new_op(0xde, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 146: // #line 311 "asm.y" { (yyval.atom) = new_op0(0x4a); ;} break; case 147: // #line 312 "asm.y" { (yyval.atom) = new_op(0x46, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 148: // #line 313 "asm.y" { (yyval.atom) = new_op(0x56, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 149: // #line 314 "asm.y" { (yyval.atom) = new_op(0x4e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 150: // #line 315 "asm.y" { (yyval.atom) = new_op(0x5e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 151: // #line 317 "asm.y" { (yyval.atom) = new_op0(0x0a); ;} break; case 152: // #line 318 "asm.y" { (yyval.atom) = new_op(0x06, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 153: // #line 319 "asm.y" { (yyval.atom) = new_op(0x16, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 154: // #line 320 "asm.y" { (yyval.atom) = new_op(0x0e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 155: // #line 321 "asm.y" { (yyval.atom) = new_op(0x1e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 156: // #line 323 "asm.y" { (yyval.atom) = new_op0(0x6a); ;} break; case 157: // #line 324 "asm.y" { (yyval.atom) = new_op(0x66, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 158: // #line 325 "asm.y" { (yyval.atom) = new_op(0x76, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 159: // #line 326 "asm.y" { (yyval.atom) = new_op(0x6e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 160: // #line 327 "asm.y" { (yyval.atom) = new_op(0x7e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 161: // #line 329 "asm.y" { (yyval.atom) = new_op0(0x2a); ;} break; case 162: // #line 330 "asm.y" { (yyval.atom) = new_op(0x26, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 163: // #line 331 "asm.y" { (yyval.atom) = new_op(0x36, ATOM_TYPE_OP_ARG_U8, (yyvsp[0].expr)); ;} break; case 164: // #line 332 "asm.y" { (yyval.atom) = new_op(0x2e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 165: // #line 333 "asm.y" { (yyval.atom) = new_op(0x3e, ATOM_TYPE_OP_ARG_U16, (yyvsp[0].expr)); ;} break; case 166: // #line 335 "asm.y" { (yyval.expr) = (yyvsp[0].expr); ;} break; case 167: // #line 336 "asm.y" { (yyval.expr) = (yyvsp[0].expr); ;} break; case 168: // #line 337 "asm.y" { (yyval.expr) = (yyvsp[-2].expr); ;} break; case 169: // #line 338 "asm.y" { (yyval.expr) = (yyvsp[-2].expr); ;} break; case 170: // #line 339 "asm.y" { (yyval.expr) = (yyvsp[0].expr); ;} break; case 171: // #line 340 "asm.y" { (yyval.expr) = (yyvsp[-2].expr); ;} break; case 172: // #line 341 "asm.y" { (yyval.expr) = (yyvsp[-2].expr); ;} break; case 173: // #line 342 "asm.y" { (yyval.expr) = (yyvsp[-3].expr); ;} break; case 174: // #line 343 "asm.y" { (yyval.expr) = (yyvsp[-3].expr); ;} break; case 175: // #line 345 "asm.y" { (yyval.expr) = new_expr_op2(PLUS, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 176: // #line 346 "asm.y" { (yyval.expr) = new_expr_op2(MINUS, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 177: // #line 347 "asm.y" { (yyval.expr) = new_expr_op2(MULT, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 178: // #line 348 "asm.y" { (yyval.expr) = new_expr_op2(DIV, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 179: // #line 349 "asm.y" { (yyval.expr) = new_expr_op2(MOD, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 180: // #line 350 "asm.y" { (yyval.expr) = new_expr_op1(vNEG, (yyvsp[0].expr)); ;} break; case 181: // #line 351 "asm.y" { (yyval.expr) = (yyvsp[-1].expr); ;} break; case 182: // #line 352 "asm.y" { (yyval.expr) = new_expr_incword((yyvsp[-3].str), (yyvsp[-1].expr)); ;} break; case 183: // #line 354 "asm.y" { (yyval.expr) = new_expr_number((yyvsp[0].num)); ;} break; case 184: // #line 355 "asm.y" { (yyval.expr) = new_expr_symref((yyvsp[0].str)); ;} break; case 185: // #line 357 "asm.y" { (yyval.expr) = new_expr_op2(LOR, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 186: // #line 358 "asm.y" { (yyval.expr) = new_expr_op2(LAND, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 187: // #line 359 "asm.y" { (yyval.expr) = new_expr_op1(LNOT, (yyvsp[0].expr)); ;} break; case 188: // #line 360 "asm.y" { (yyval.expr) = (yyvsp[-1].expr); ;} break; case 189: // #line 361 "asm.y" { (yyval.expr) = new_expr_op2(LT, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 190: // #line 362 "asm.y" { (yyval.expr) = new_expr_op2(GT, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 191: // #line 363 "asm.y" { (yyval.expr) = new_expr_op2(EQ, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 192: // #line 364 "asm.y" { (yyval.expr) = new_expr_op2(NEQ, (yyvsp[-2].expr), (yyvsp[0].expr)); ;} break; case 193: // #line 366 "asm.y" { (yyval.expr) = new_is_defined((yyvsp[-1].str)); ;} break; default: break; } /* Line 1126 of yacc.c. */ // #line 2596 "asm.tab.c" yyvsp -= yylen; yyssp -= yylen; YY_STACK_PRINT (yyss, yyssp); *++yyvsp = yyval; /* Now `shift' the result of the reduction. Determine what state that goes to, based on the state we popped back to and the rule number reduced by. */ yyn = yyr1[yyn]; yystate = yypgoto[yyn - YYNTOKENS] + *yyssp; if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp) yystate = yytable[yystate]; else yystate = yydefgoto[yyn - YYNTOKENS]; goto yynewstate; /*------------------------------------. | yyerrlab -- here on detecting error | `------------------------------------*/ yyerrlab: /* If not already recovering from an error, report this error. */ if (!yyerrstatus) { ++yynerrs; #if YYERROR_VERBOSE yyn = yypact[yystate]; if (YYPACT_NINF < yyn && yyn < YYLAST) { int yytype = YYTRANSLATE (yychar); YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]); YYSIZE_T yysize = yysize0; YYSIZE_T yysize1; int yysize_overflow = 0; char *yymsg = 0; # define YYERROR_VERBOSE_ARGS_MAXIMUM 5 char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM]; int yyx; #if 0 /* This is so xgettext sees the translatable formats that are constructed on the fly. */ YY_("syntax error, unexpected %s"); YY_("syntax error, unexpected %s, expecting %s"); YY_("syntax error, unexpected %s, expecting %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s"); YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"); #endif char *yyfmt; char const *yyf; static char const yyunexpected[] = "syntax error, unexpected %s"; static char const yyexpecting[] = ", expecting %s"; static char const yyor[] = " or %s"; char yyformat[sizeof yyunexpected + sizeof yyexpecting - 1 + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2) * (sizeof yyor - 1))]; char const *yyprefix = yyexpecting; /* Start YYX at -YYN if negative to avoid negative indexes in YYCHECK. */ int yyxbegin = yyn < 0 ? -yyn : 0; /* Stay within bounds of both yycheck and yytname. */ int yychecklim = YYLAST - yyn; int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS; int yycount = 1; yyarg[0] = yytname[yytype]; yyfmt = yystpcpy (yyformat, yyunexpected); for (yyx = yyxbegin; yyx < yyxend; ++yyx) if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR) { if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM) { yycount = 1; yysize = yysize0; yyformat[sizeof yyunexpected - 1] = '\0'; break; } yyarg[yycount++] = yytname[yyx]; yysize1 = yysize + yytnamerr (0, yytname[yyx]); yysize_overflow |= yysize1 < yysize; yysize = yysize1; yyfmt = yystpcpy (yyfmt, yyprefix); yyprefix = yyor; } yyf = YY_(yyformat); yysize1 = yysize + yystrlen (yyf); yysize_overflow |= yysize1 < yysize; yysize = yysize1; if (!yysize_overflow && yysize <= YYSTACK_ALLOC_MAXIMUM) yymsg = (char *) YYSTACK_ALLOC (yysize); if (yymsg) { /* Avoid sprintf, as that infringes on the user's name space. Don't have undefined behavior even if the translation produced a string with the wrong number of "%s"s. */ char *yyp = yymsg; int yyi = 0; while ((*yyp = *yyf)) { if (*yyp == '%' && yyf[1] == 's' && yyi < yycount) { yyp += yytnamerr (yyp, yyarg[yyi++]); yyf += 2; } else { yyp++; yyf++; } } yyerror (yymsg); YYSTACK_FREE (yymsg); } else { yyerror (YY_("syntax error")); goto yyexhaustedlab; } } else #endif /* YYERROR_VERBOSE */ yyerror (YY_("syntax error")); } if (yyerrstatus == 3) { /* If just tried and failed to reuse look-ahead token after an error, discard it. */ if (yychar <= YYEOF) { /* Return failure if at end of input. */ if (yychar == YYEOF) YYABORT; } else { yydestruct ("Error: discarding", yytoken, &yylval); yychar = YYEMPTY; } } /* Else will try to reuse look-ahead token after shifting the error token. */ goto yyerrlab1; /*---------------------------------------------------. | yyerrorlab -- error raised explicitly by YYERROR. | `---------------------------------------------------*/ yyerrorlab: /* Pacify compilers like GCC when the user code never invokes YYERROR and the label yyerrorlab therefore never appears in user code. */ if (0) goto yyerrorlab; yyvsp -= yylen; yyssp -= yylen; yystate = *yyssp; goto yyerrlab1; /*-------------------------------------------------------------. | yyerrlab1 -- common code for both syntax error and YYERROR. | `-------------------------------------------------------------*/ yyerrlab1: yyerrstatus = 3; /* Each real token shifted decrements this. */ for (;;) { yyn = yypact[yystate]; if (yyn != YYPACT_NINF) { yyn += YYTERROR; if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR) { yyn = yytable[yyn]; if (0 < yyn) break; } } /* Pop the current state because it cannot handle the error token. */ if (yyssp == yyss) YYABORT; yydestruct ("Error: popping", yystos[yystate], yyvsp); YYPOPSTACK; yystate = *yyssp; YY_STACK_PRINT (yyss, yyssp); } if (yyn == YYFINAL) YYACCEPT; *++yyvsp = yylval; /* Shift the error token. */ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp); yystate = yyn; goto yynewstate; /*-------------------------------------. | yyacceptlab -- YYACCEPT comes here. | `-------------------------------------*/ yyacceptlab: yyresult = 0; goto yyreturn; /*-----------------------------------. | yyabortlab -- YYABORT comes here. | `-----------------------------------*/ yyabortlab: yyresult = 1; goto yyreturn; #ifndef yyoverflow /*-------------------------------------------------. | yyexhaustedlab -- memory exhaustion comes here. | `-------------------------------------------------*/ yyexhaustedlab: yyerror (YY_("memory exhausted")); yyresult = 2; /* Fall through. */ #endif yyreturn: if (yychar != YYEOF && yychar != YYEMPTY) yydestruct ("Cleanup: discarding lookahead", yytoken, &yylval); while (yyssp != yyss) { yydestruct ("Cleanup: popping", yystos[*yyssp], yyvsp); YYPOPSTACK; } #ifndef yyoverflow if (yyss != yyssa) YYSTACK_FREE (yyss); #endif return yyresult; } // #line 368 "asm.y" int yyerror (char *s) { fprintf (stderr, "line %d, %s\n", num_lines, s); return 0; } void asm_set_source(struct membuf *buffer); int assemble(struct membuf *source, struct membuf *dest) { int val; LOG_INIT_CONSOLE(LOG_NORMAL); parse_init(); yydebug = 0; asm_src_buffer_push(source); vec_init(asm_atoms, sizeof(struct atom*)); val = yyparse(); if(val == 0) { output_atoms(dest, asm_atoms); } parse_free(); vec_free(asm_atoms, NULL); yycleanup(); LOG_FREE; return val; } goattracker-2.72/src/asm/membuf.h0000644000000000000000000000413410774364076015463 0ustar rootroot#ifndef ALREADY_INCLUDED_MEMBUF #define ALREADY_INCLUDED_MEMBUF /* * Copyright (c) 2002 - 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #define STATIC_MEMBUF_INIT {0, 0, 0} struct membuf { void *buf; int len; int size; }; void membuf_init(struct membuf *sb); void membuf_clear(struct membuf *sb); void membuf_free(struct membuf *sb); void membuf_new(struct membuf **sbp); void membuf_delete(struct membuf **sbp); int membuf_memlen(struct membuf *sb); void membuf_truncate(struct membuf *sb, int len); /* returns the new len or < 0 if failure */ int membuf_trim(struct membuf *sb, int pos); void *membuf_memcpy(struct membuf *sb, const void *mem, int len); void *membuf_append(struct membuf *sb, const void *mem, int len); void *membuf_append_char(struct membuf *sb, char c); void *membuf_insert(struct membuf *sb, int offset, const void *mem, int len); void membuf_atleast(struct membuf *sb, int size); void membuf_atmost(struct membuf *sb, int size); int membuf_get_size(struct membuf *sb); void *membuf_get(struct membuf *sb); #endif goattracker-2.72/src/asm/vec.h0000644000000000000000000000542710774364076014773 0ustar rootroot#ifndef ALREADY_INCLUDED_VEC #define ALREADY_INCLUDED_VEC /* * Copyright (c) 2003 - 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "callback.h" #include "membuf.h" #include #define STATIC_VEC_INIT(EL_SIZE) {(EL_SIZE), STATIC_MEMBUF_INIT, 1} struct vec { size_t elsize; struct membuf buf; int flags; }; struct vec_iterator { struct vec *vec; int pos; }; void vec_init(struct vec *p, size_t elsize); void vec_clear(struct vec *p, cb_free * f); void vec_free(struct vec *p, cb_free * f); int vec_count(struct vec *p); void *vec_get(struct vec *p, int index); void *vec_insert(struct vec *p, int index, const void *in); void *vec_push(struct vec *p, const void *in); /** * Gets the position where the key is stored in the vector. The vector * needs to be sorted for this function to work. Returns the position, * -1 on error or a negative number that can be converted to where * it should have been if it had been inserted. insert_pos = -(val + 2) **/ int vec_find(struct vec *p, cb_cmp * f, const void *key); /** * Gets a pointer to the element that the key points to. * Returns a pointer that may be null if not found. **/ void *vec_find2(struct vec *p, cb_cmp * f, const void *key); /** * Inserts the in element in its correct position in a sorted vector. * returns 1 if insertion is successful, 0 if element is already * inserted or -1 on error. If out is not NULL it will be * dereferenced and set to the inserted element. **/ int vec_insert_uniq(struct vec *p, cb_cmp * f, const void *in, void **out); void vec_sort(struct vec *p, cb_cmp * f); void vec_get_iterator(struct vec *p, struct vec_iterator *i); void *vec_iterator_next(struct vec_iterator *i); #endif goattracker-2.72/src/asm/chnkpool.c0000644000000000000000000000576210774364076016030 0ustar rootroot/* * Copyright (c) 2003 - 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "chnkpool.h" #include "log.h" #include #include void chunkpool_init(struct chunkpool *ctx, int size) { ctx->chunk_size = size; ctx->chunk = -1; ctx->chunk_max = (0x1fffff / size) * size; ctx->chunk_pos = ctx->chunk_max; } void chunkpool_free2(struct chunkpool *ctx, cb_free *f) { while(ctx->chunk >= 0) { if(f != NULL) { do { ctx->chunk_pos -= ctx->chunk_size; f((char*)ctx->chunks[ctx->chunk] + ctx->chunk_pos); } while(ctx->chunk_pos > 0); ctx->chunk_pos = ctx->chunk_max; } free(ctx->chunks[ctx->chunk]); ctx->chunk -= 1; } ctx->chunk_size = -1; ctx->chunk_max = -1; ctx->chunk_pos = -1; } void chunkpool_free(struct chunkpool *ctx) { chunkpool_free2(ctx, NULL); } void * chunkpool_malloc(struct chunkpool *ctx) { void *p; if(ctx->chunk_pos == ctx->chunk_max) { void *m; if(ctx->chunk == CHUNKPOOL_CHUNKS_MAX - 1) { LOG(LOG_ERROR, ("out of chunks in file %s, line %d\n", __FILE__, __LINE__)); LOG(LOG_BRIEF, ("chunk_size %d\n", ctx->chunk_size)); LOG(LOG_BRIEF, ("chunk_max %d\n", ctx->chunk_max)); LOG(LOG_BRIEF, ("chunk %d\n", ctx->chunk)); exit(-1); } m = malloc(ctx->chunk_max); LOG(LOG_DEBUG, ("allocating new chunk %p\n", m)); if (m == NULL) { LOG(LOG_ERROR, ("out of memory error in file %s, line %d\n", __FILE__, __LINE__)); exit(-1); } ctx->chunk += 1; ctx->chunks[ctx->chunk] = m; ctx->chunk_pos = 0; } p = (char*)ctx->chunks[ctx->chunk] + ctx->chunk_pos; ctx->chunk_pos += ctx->chunk_size; return p; } void * chunkpool_calloc(struct chunkpool *ctx) { void *p = chunkpool_malloc(ctx); memset(p, 0, ctx->chunk_size); return p; } goattracker-2.72/src/asm/namedbuf.c0000644000000000000000000000543610774364076015772 0ustar rootroot/* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "namedbuf.h" #include "log.h" #include "vec.h" #include "membufio.h" #include struct sbe { const char *name; struct membuf mb[1]; }; static struct vec s_sbe_table[1]; static int sbe_cmp(const void *a, const void *b) { struct sbe *sbe_a; struct sbe *sbe_b; int val; sbe_a = (struct sbe*)a; sbe_b = (struct sbe*)b; val = strcmp(sbe_a->name, sbe_b->name); return val; } void sbe_free(struct sbe *e) { membuf_free(e->mb); } void named_buffer_init() { vec_init(s_sbe_table, sizeof(struct sbe)); } void named_buffer_free() { typedef void cb_free(void *a); vec_free(s_sbe_table, (cb_free*)sbe_free); } struct membuf *new_named_buffer(const char *name) { int pos; struct sbe e[1]; struct sbe *ep; struct membuf *mp; /* name is already strdup:ped */ e->name = name; pos = vec_find(s_sbe_table, sbe_cmp, e); if(pos >= 0) { /* found */ LOG(LOG_ERROR, ("buffer already exists.\n")); exit(-1); } membuf_init(e->mb); ep = vec_insert(s_sbe_table, -(pos + 2), e); mp = ep->mb; return mp; } struct membuf *get_named_buffer(const char *name) { int pos; struct sbe e[1]; struct sbe *ep; struct membuf *mp; /* name is already strdup:ped */ e->name = name; pos = vec_find(s_sbe_table, sbe_cmp, e); if(pos >= 0) { /* found */ ep = vec_get(s_sbe_table, pos); } else { membuf_init(e->mb); read_file(name, e->mb); ep = vec_insert(s_sbe_table, -(pos + 2), e); } mp = ep->mb; return mp; } goattracker-2.72/src/asm/callback.h0000644000000000000000000000240410774364076015742 0ustar rootroot#ifndef ALREADY_INCLUDED_CALLBACK #define ALREADY_INCLUDED_CALLBACK /* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ typedef int cb_cmp(const void *a, const void *b); typedef void cb_free(void *a); #endif goattracker-2.72/src/asm/expr.c0000644000000000000000000000722410774364076015164 0ustar rootroot/* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "expr.h" #include "chnkpool.h" #include "log.h" #include static struct chunkpool s_expr_pool[1]; void expr_init() { chunkpool_init(s_expr_pool, sizeof(struct expr)); } void expr_free() { chunkpool_free(s_expr_pool); } void expr_dump(int level, struct expr *e) { switch(e->expr_op) { case SYMBOL: LOG(level, ("expr 0x%08X symref %s\n", (u32)e, e->type.symref)); break; case NUMBER: LOG(level, ("expr 0x%08X number %d\n", (u32)e, e->type.number)); break; case vNEG: LOG(level, ("expr 0x%08X unary op %d, referring to 0x%08X\n", (u32)e, e->expr_op, (u32)e->type.arg1)); case LNOT: LOG(level, ("expr 0x%08X unary op %d, referring to 0x%08X\n", (u32)e, e->expr_op, (u32)e->type.arg1)); break; default: LOG(level, ("expr 0x%08X binary op %d, arg1 0x%08X, arg2 0x%08X\n", (u32)e, e->expr_op, (u32)e->type.arg1, (u32)e->expr_arg2)); } } struct expr *new_expr_op1(i16 op, struct expr *arg) { struct expr *val; if(op != vNEG && op != LNOT) { /* error, invalid unary operator */ LOG(LOG_ERROR, ("%d not allowed as unary operator\n", op)); exit(1); } val = chunkpool_malloc(s_expr_pool); val->expr_op = op; val->type.arg1 = arg; expr_dump(LOG_DEBUG, val); return val; } struct expr *new_expr_op2(i16 op, struct expr *arg1, struct expr *arg2) { struct expr *val; if(op == vNEG || op == LNOT || op == NUMBER || op == SYMBOL) { /* error, invalid binary operator */ printf("op %d, vNEG %d, NUMBER %d, SYMBOL %d\n", op, vNEG, NUMBER, SYMBOL); LOG(LOG_ERROR, ("%d not allowed as binary operator\n", op)); exit(1); } val = chunkpool_malloc(s_expr_pool); val->expr_op = op; val->type.arg1 = arg1; val->expr_arg2 = arg2; expr_dump(LOG_DEBUG, val); return val; } struct expr *new_expr_symref(const char *symbol) { struct expr *val; val = chunkpool_malloc(s_expr_pool); val->expr_op = SYMBOL; val->type.symref = symbol; expr_dump(LOG_DEBUG, val); return val; } struct expr *new_expr_number(i32 number) { struct expr *val; LOG(LOG_DEBUG, ("creating new number %d\n", number)); val = chunkpool_malloc(s_expr_pool); val->expr_op = NUMBER; val->type.number = number; expr_dump(LOG_DEBUG, val); return val; } goattracker-2.72/src/asm/log.c0000644000000000000000000001324110774364076014763 0ustar rootroot/* * Copyright (c) 2002, 2003 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * * This file is a part of the Exomizer v1.1 release * */ #include #include #include "log.h" #ifdef WIN32 #define vsnprintf _vsnprintf #endif #ifdef DJGPP #define vsnprintf(A, B, C, D) vsprintf((A),(C),(D)) #endif struct log_output { enum log_level min; enum log_level max; FILE *stream; log_formatter_f *f; }; struct log_ctx { enum log_level level; int out_len; struct log_output *out; int buf_len; char *buf; }; struct log_ctx *G_log_ctx = NULL; enum log_level G_log_level = 0; enum log_level G_log_log_level = 0; struct log_ctx *log_new(void) { struct log_ctx *ctx; ctx = malloc(sizeof(*ctx)); if (ctx == NULL) { fprintf(stderr, "fatal error, can't allocate memory for log context\n"); exit(1); } ctx->level = LOG_NORMAL; ctx->out_len = 0; ctx->out = NULL; ctx->buf_len = 0; ctx->buf = NULL; return ctx; } /* log_delete closes all added output streams * and files except for stdout and stderr */ void log_delete(struct log_ctx *ctx) { int i; for (i = 0; i < ctx->out_len; ++i) { FILE *file = ctx->out[i].stream; if (file != stderr && file != stdout) { fclose(file); } } free(ctx->out); free(ctx->buf); free(ctx); } void log_set_level(struct log_ctx *ctx, /* IN/OUT */ enum log_level level) /* IN */ { ctx->level = level; } void log_add_output_stream(struct log_ctx *ctx, /* IN/OUT */ enum log_level min, /* IN */ enum log_level max, /* IN */ log_formatter_f * default_f, /* IN */ FILE * out_stream) /* IN */ { struct log_output *out; ctx->out_len += 1; ctx->out = realloc(ctx->out, ctx->out_len * sizeof(*(ctx->out))); if (ctx->out == NULL) { fprintf(stderr, "fatal error, can't allocate memory for log output\n"); exit(1); } out = &(ctx->out[ctx->out_len - 1]); out->min = min; out->max = max; out->stream = out_stream; out->f = default_f; } void raw_log_formatter(FILE * out, /* IN */ enum log_level level, /* IN */ const char *context, /* IN */ const char *log) /* IN */ { fprintf(out, log); fflush(out); } void log_vlog(struct log_ctx *ctx, /* IN */ enum log_level level, /* IN */ const char *context, /* IN */ log_formatter_f * f, /* IN */ const char *printf_str, /* IN */ va_list argp) { int len; int i; if (ctx->level < level) { /* don't log this */ return; } len = 0; do { if (len >= ctx->buf_len) { ctx->buf_len = len + 1024; ctx->buf = realloc(ctx->buf, ctx->buf_len); if (ctx->buf == NULL) { fprintf(stderr, "fatal error, can't allocate memory for log log\n"); exit(1); } } len = vsnprintf(ctx->buf, ctx->buf_len, printf_str, argp); } while (len >= ctx->buf_len); for (i = 0; i < ctx->out_len; ++i) { struct log_output *o = &ctx->out[i]; log_formatter_f *of = f; if (level >= o->min && level <= o->max) { /* generate log for this output */ if (of == NULL) { of = o->f; } if (of != NULL) { of(o->stream, level, context, ctx->buf); } else { fprintf(o->stream, "%s\n", ctx->buf); fflush(o->stream); } } } } void log_log_default(const char *printf_str, /* IN */ ...) { va_list argp; va_start(argp, printf_str); log_vlog(G_log_ctx, G_log_log_level, NULL, raw_log_formatter, printf_str, argp); } void log_log(struct log_ctx *ctx, /* IN */ enum log_level level, /* IN */ const char *context, /* IN */ log_formatter_f * f, /* IN */ const char *printf_str, /* IN */ ...) { va_list argp; va_start(argp, printf_str); log_vlog(ctx, level, context, f, printf_str, argp); } goattracker-2.72/src/asm/log.h0000644000000000000000000000753510774364076015001 0ustar rootroot#ifndef ALREADY_INCLUDED_LOG #define ALREADY_INCLUDED_LOG /* * Copyright (c) 2002, 2003 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include #include enum log_level { LOG_MIN = -99, LOG_FATAL = -40, LOG_ERROR = -30, LOG_WARNING = -20, LOG_BRIEF = -10, LOG_NORMAL = 0, LOG_VERBOSE = 10, LOG_TRACE = 20, LOG_DEBUG = 30, LOG_DUMP = 40, LOG_MAX = 99 }; typedef void log_formatter_f(FILE * out, /* IN */ enum log_level level, /* IN */ const char *context, /* IN */ const char *); /* IN */ /* * this log output function adds nothing */ void raw_log_formatter(FILE * out, /* IN */ enum log_level level, /* IN */ const char *context, /* IN */ const char *log); /* IN */ struct log_output; struct log_ctx; struct log_ctx *log_new(void); /* log_delete closes all added output streams * and files except for stdout and stderr */ void log_delete(struct log_ctx *ctx); void log_set_level(struct log_ctx *ctx, /* IN/OUT */ enum log_level level); /* IN */ void log_add_output_stream(struct log_ctx *ctx, /* IN/OUT */ enum log_level min, /* IN */ enum log_level max, /* IN */ log_formatter_f * default_f, /* IN */ FILE * out_stream); /* IN */ void log_vlog(struct log_ctx *ctx, /* IN */ enum log_level level, /* IN */ const char *context, /* IN */ log_formatter_f * f, /* IN */ const char *printf_str, /* IN */ va_list argp); void log_log_default(const char *printf_str, /* IN */ ...); /* some helper macros */ extern struct log_ctx *G_log_ctx; extern enum log_level G_log_level; extern enum log_level G_log_log_level; #define LOG_SET_LEVEL(L) \ do { \ log_set_level(G_log_ctx, (L)); \ G_log_level = (L); \ } while(0) #define LOG_INIT(L) \ do { \ G_log_ctx = log_new(); \ log_set_level(G_log_ctx, (L)); \ G_log_level = (L); \ } while(0) #define LOG_INIT_CONSOLE(X) \ do { \ G_log_ctx = log_new(); \ log_set_level(G_log_ctx, (X)); \ G_log_level = (X); \ log_add_output_stream(G_log_ctx, LOG_WARNING, LOG_MAX, NULL, stdout); \ log_add_output_stream(G_log_ctx, LOG_MIN, LOG_WARNING - 1, NULL, stderr); \ } while(0) #define LOG_FREE log_delete(G_log_ctx) #define IS_LOGGABLE(L) (G_log_level >= (L)) #define LOG(L, M) \ do { \ if(IS_LOGGABLE(L)) { \ G_log_log_level = (L); \ log_log_default M; \ } \ } while(0) #endif goattracker-2.72/src/asm/asmtab.h0000644000000000000000000001145110774364076015457 0ustar rootroot/* A Bison parser, made by GNU Bison 2.1. */ /* Skeleton parser for Yacc-like parsing with Bison, Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 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, 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. */ /* As a special exception, when this file is copied by Bison into a Bison output file, you may use that output file without restriction. This special exception was added by the Free Software Foundation in version 1.24 of Bison. */ /* Tokens. */ # define YYTOKENTYPE #ifndef YYTOKENTYPE # define YYTOKENTYPE /* Put the tokens into the symbol table, so that GDB and other debuggers know about them. */ enum yytokentype { INCLUDE = 258, IF = 259, DEFINED = 260, MACRO = 261, MACRO_STRING = 262, ORG = 263, ASMERROR = 264, ECHO = 265, INCBIN = 266, INCWORD = 267, RES = 268, WORD = 269, BYTE = 270, LDA = 271, LDX = 272, LDY = 273, STA = 274, STX = 275, STY = 276, AND = 277, ORA = 278, EOR = 279, ADC = 280, SBC = 281, CMP = 282, CPX = 283, CPY = 284, TSX = 285, TXS = 286, PHA = 287, PLA = 288, PHP = 289, PLP = 290, SEI = 291, CLI = 292, NOP = 293, TYA = 294, TAY = 295, TXA = 296, TAX = 297, CLC = 298, SEC = 299, RTS = 300, JSR = 301, JMP = 302, BEQ = 303, BNE = 304, BCC = 305, BCS = 306, BPL = 307, BMI = 308, BVC = 309, BVS = 310, INX = 311, DEX = 312, INY = 313, DEY = 314, INC = 315, DEC = 316, LSR = 317, ASL = 318, ROR = 319, ROL = 320, SYMBOL = 321, STRING = 322, LAND = 323, LOR = 324, LNOT = 325, LPAREN = 326, RPAREN = 327, COMMA = 328, COLON = 329, X = 330, Y = 331, HASH = 332, PLUS = 333, MINUS = 334, MULT = 335, DIV = 336, MOD = 337, LT = 338, GT = 339, EQ = 340, NEQ = 341, ASSIGN = 342, NUMBER = 343, vNEG = 344 }; #endif /* Tokens. */ #define INCLUDE 258 #define IF 259 #define DEFINED 260 #define MACRO 261 #define MACRO_STRING 262 #define ORG 263 #define ASMERROR 264 #define ECHO 265 #define INCBIN 266 #define INCWORD 267 #define RES 268 #define WORD 269 #define BYTE 270 #define LDA 271 #define LDX 272 #define LDY 273 #define STA 274 #define STX 275 #define STY 276 #define AND 277 #define ORA 278 #define EOR 279 #define ADC 280 #define SBC 281 #define CMP 282 #define CPX 283 #define CPY 284 #define TSX 285 #define TXS 286 #define PHA 287 #define PLA 288 #define PHP 289 #define PLP 290 #define SEI 291 #define CLI 292 #define NOP 293 #define TYA 294 #define TAY 295 #define TXA 296 #define TAX 297 #define CLC 298 #define SEC 299 #define RTS 300 #define JSR 301 #define JMP 302 #define BEQ 303 #define BNE 304 #define BCC 305 #define BCS 306 #define BPL 307 #define BMI 308 #define BVC 309 #define BVS 310 #define INX 311 #define DEX 312 #define INY 313 #define DEY 314 #define INC 315 #define DEC 316 #define LSR 317 #define ASL 318 #define ROR 319 #define ROL 320 #define SYMBOL 321 #define STRING 322 #define LAND 323 #define LOR 324 #define LNOT 325 #define LPAREN 326 #define RPAREN 327 #define COMMA 328 #define COLON 329 #define X 330 #define Y 331 #define HASH 332 #define PLUS 333 #define MINUS 334 #define MULT 335 #define DIV 336 #define MOD 337 #define LT 338 #define GT 339 #define EQ 340 #define NEQ 341 #define ASSIGN 342 #define NUMBER 343 #define vNEG 344 #if ! defined (YYSTYPE) && ! defined (YYSTYPE_IS_DECLARED) #line 110 "asm.y" typedef union YYSTYPE { i32 num; char *str; struct atom *atom; struct expr *expr; } YYSTYPE; /* Line 1447 of yacc.c. */ #line 223 "asm.tab.h" # define yystype YYSTYPE /* obsolescent; will be withdrawn */ # define YYSTYPE_IS_DECLARED 1 # define YYSTYPE_IS_TRIVIAL 1 #endif extern YYSTYPE yylval; goattracker-2.72/src/asm/membuf.c0000644000000000000000000001100710774364076015453 0ustar rootroot/* * Copyright (c) 2002 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "membuf.h" #include #include #include void membuf_init(struct membuf *sb) { sb->buf = NULL; sb->len = 0; sb->size = 0; } void membuf_clear(struct membuf *sb) { sb->len = 0; } void membuf_free(struct membuf *sb) { if (sb->buf != NULL) { free(sb->buf); sb->buf = NULL; } sb->len = 0; sb->size = 0; } void membuf_new(struct membuf **sbp) { struct membuf *sb; sb = malloc(sizeof(struct membuf)); if (sb == NULL) { fprintf(stderr, "error, can't allocate memory\n"); exit(1); } sb->buf = NULL; sb->len = 0; sb->size = 0; *sbp = sb; } void membuf_delete(struct membuf **sbp) { struct membuf *sb; sb = *sbp; membuf_free(sb); free(sb); sb = NULL; *sbp = sb; } int membuf_memlen(struct membuf *sb) { return sb->len; } void membuf_truncate(struct membuf *sb, int len) { sb->len = len; } int membuf_trim(struct membuf *sb, int pos) { if(pos < 0 || pos > sb->len) { return -1; } if(pos == 0) { return sb->len; } if(pos != sb->len) { memmove(sb->buf, (char*)sb->buf + pos, sb->len - pos); } sb->len -= pos; return sb->len; } void *membuf_memcpy(struct membuf *sb, const void *mem, int len) { membuf_atleast(sb, len); memcpy(sb->buf, mem, len); return sb->buf; } void *membuf_append(struct membuf *sb, const void *mem, int len) { int newlen; void *p; newlen = sb->len + len; membuf_atleast(sb, newlen); p = (char *) sb->buf + sb->len; if(mem == NULL) { memset(p, 0, len); } else { memcpy(p, mem, len); } sb->len = newlen; return p; } void *membuf_append_char(struct membuf *sb, char c) { int newlen; char *p; newlen = sb->len + 1; membuf_atleast(sb, newlen); p = (char *) sb->buf + sb->len; *p = c; sb->len = newlen; return p; } void *membuf_insert(struct membuf *sb, int offset, const void *mem, int len) { int newlen; void *from; void *to; newlen = sb->len + len; membuf_atleast(sb, newlen); from = (char *) sb->buf + offset; to = (char *)from + len; memmove(to, from, sb->len - offset); memcpy(from, mem, len); sb->len = newlen; return from; } void membuf_atleast(struct membuf *sb, int len) { int size; size = sb->size; if (size == 0) size = 1; while (size < len) { size <<= 1; } if (size > sb->size) { sb->buf = realloc(sb->buf, size); if (sb->buf == NULL) { fprintf(stderr, "error, can't reallocate memory\n"); exit(1); } sb->size = size; } } void membuf_atmost(struct membuf *sb, int len) { int size; size = sb->size; while (size > len) { size >>= 1; } if (size < sb->size) { sb->buf = realloc(sb->buf, size); if (sb->buf == NULL) { fprintf(stderr, "error, can't reallocate memory\n"); exit(1); } sb->size = size; sb->len = size; } } int membuf_get_size(struct membuf *sb) { return sb->size; } void *membuf_get(struct membuf *sb) { return sb->buf; } goattracker-2.72/src/asm/parse.h0000644000000000000000000000706710774364076015332 0ustar rootroot#ifndef INCLUDED_PARSE #define INCLUDED_PARSE /* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "int.h" #include "vec.h" #include "membuf.h" #include "expr.h" #define ATOM_TYPE_OP_ARG_NONE 0 /* uses u.op */ #define ATOM_TYPE_OP_ARG_U8 1 /* uses u.op */ #define ATOM_TYPE_OP_ARG_U16 2 /* uses u.op */ #define ATOM_TYPE_OP_ARG_I8 3 /* uses u.op */ #define ATOM_TYPE_OP_ARG_UI8 4 /* uses u.op */ #define ATOM_TYPE_EXPRS 12 /* uses u.exprs */ #define ATOM_TYPE_WORD_EXPRS 10 /* uses u.exprs */ #define ATOM_TYPE_BYTE_EXPRS 11 /* uses u.exprs */ #define ATOM_TYPE_RES 13 /* uses u.res */ #define ATOM_TYPE_BUFFER 14 /* uses u.buffer */ struct op { struct expr *arg; u8 code; }; struct res { struct expr *length; struct expr *value; }; struct buffer { const char *name; i32 length; i32 skip; }; struct atom { u8 type; union { struct op op; struct vec *exprs; struct buffer buffer; struct res res; } u; }; extern int push_state_skip; extern int push_state_macro; extern int push_state_init; extern int num_lines; void parse_init(); void parse_free(); struct atom *new_op(u8 op_code, u8 op_size, struct expr *arg); struct atom *new_op0(u8 op_code); struct atom *new_exprs(struct expr *arg); struct atom *exprs_add(struct atom *atom, struct expr *arg); struct atom *exprs_to_byte_exprs(struct atom *atom); struct atom *exprs_to_word_exprs(struct atom *atom); struct atom *new_res(struct expr *len, struct expr *value); struct atom *new_incbin(const char *name, struct expr *skip, struct expr *len); struct expr *new_is_defined(const char *symbol); struct expr *new_expr_incword(const char *name, struct expr *skip); void new_symbol(const char *symbol, i32 value); void new_symbol_expr(const char *symbol, struct expr *arg); /* returns NULL if found, not otherwise, expp may be NULL. */ const char *find_symref(const char *symbol, struct expr **expp); void symbol_dump_resolved(int level, const char *symbol); void new_label(const char *label); void set_org(struct expr *arg); void push_if_state(struct expr *arg); void push_macro_state(const char *name); void macro_append(const char *text); void asm_error(const char *msg); void asm_echo(const char *msg); void asm_include(const char *msg); int assemble(struct membuf *source, struct membuf *dest); void output_atoms(struct membuf *out, struct vec *mem); void asm_src_buffer_push(struct membuf *buf); #endif goattracker-2.72/src/asm/namedbuf.h0000644000000000000000000000254010774364076015770 0ustar rootroot#ifndef NAMED_BUFFER_INCLUDED #define NAMED_BUFFER_INCLUDED /* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "membuf.h" void named_buffer_init(); void named_buffer_free(); struct membuf *new_named_buffer(const char *name); struct membuf *get_named_buffer(const char *name); #endif goattracker-2.72/src/asm/expr.h0000644000000000000000000000331010774364076015161 0ustar rootroot#ifndef ALREADY_INCLUDED_EXPR #define ALREADY_INCLUDED_EXPR /* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "int.h" #include "asmtab.h" union expr_type { i32 number; const char *symref; struct expr *arg1; }; struct expr { union expr_type type; struct expr *expr_arg2; i16 expr_op; }; void expr_init(void); void expr_free(void); struct expr *new_expr_op1(i16 op, struct expr *arg); struct expr *new_expr_op2(i16 op, struct expr *arg1, struct expr *arg2); struct expr *new_expr_symref(const char *symbol); struct expr *new_expr_number(i32 number); void expr_dump(int level, struct expr *e); #endif goattracker-2.72/src/asm/membufio.h0000644000000000000000000000246710774364076016022 0ustar rootroot#ifndef MEMBUF_IO_ALREADY_INCLUDED #define MEMBUF_IO_ALREADY_INCLUDED /* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "membuf.h" void read_file(const char *name, struct membuf *buf); void write_file(const char *name, struct membuf *buf); #endif goattracker-2.72/src/asm/vec.c0000644000000000000000000001035210774364076014757 0ustar rootroot/* * Copyright (c) 2003 - 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "vec.h" #include #define VEC_FLAG_SORTED 1 void vec_init(struct vec *p, size_t elsize) { p->elsize = elsize; membuf_init(&p->buf); p->flags = VEC_FLAG_SORTED; } void vec_clear(struct vec *p, cb_free * f) { struct vec_iterator i; void *d; vec_get_iterator(p, &i); if (f != NULL) { while ((d = vec_iterator_next(&i)) != NULL) { f(d); } } membuf_clear(&p->buf); p->flags = VEC_FLAG_SORTED; } void vec_free(struct vec *p, cb_free * f) { vec_clear(p, f); membuf_free(&p->buf); } int vec_count(struct vec *p) { int count; count = membuf_memlen(&p->buf) / p->elsize; return count; } void *vec_get(struct vec *p, int index) { char *buf; buf = (char *) membuf_get(&p->buf); buf += index * p->elsize; return (void *)buf; } void *vec_insert(struct vec *p, int index, const void *in) { void *buf; buf = membuf_insert(&p->buf, index * p->elsize, in, p->elsize); return buf; } void *vec_push(struct vec *p, const void *in) { void *out; out = membuf_append(&p->buf, in, p->elsize); p->flags &= ~VEC_FLAG_SORTED; return out; } int vec_find(struct vec *p, cb_cmp * f, const void *in) { int lo; lo = -1; if(p->flags & VEC_FLAG_SORTED) { int hi; lo = 0; hi = vec_count(p) - 1; while(lo <= hi) { int next; int val; next = (lo + hi) / 2; val = f(in, vec_get(p, next)); if(val == 0) { /* match */ lo = -(next + 2); break; } else if(val < 0) { hi = next - 1; } else { lo = next + 1; } } } return -(lo + 2); } void *vec_find2(struct vec *p, cb_cmp * f, const void *key) { void *out = NULL; int pos = vec_find(p, f, key); if(pos >= 0) { out = vec_get(p, pos); } return out; } int vec_insert_uniq(struct vec *p, cb_cmp * f, const void *in, void **outp) { int val = 0; void *out; val = vec_find(p, f, in); if(val != -1) { if(val < 0) { /* not there */ out = vec_insert(p, -(val + 2), in); val = 1; } else { out = vec_get(p, val); val = 0; } if(outp != NULL) { *outp = out; } } return val; } void vec_sort(struct vec *p, cb_cmp * f) { qsort(membuf_get(&p->buf), vec_count(p), p->elsize, f); p->flags |= VEC_FLAG_SORTED; } void vec_get_iterator(struct vec *p, struct vec_iterator *i) { i->vec = p; i->pos = 0; } void *vec_iterator_next(struct vec_iterator *i) { void *out; int count = vec_count(i->vec); if (i->pos >= count) { return NULL; } out = vec_get(i->vec, i->pos); i->pos += 1; return out; } goattracker-2.72/src/asm/int.h0000644000000000000000000000245410774364076015005 0ustar rootroot#ifndef INCLUDED_INT #define INCLUDED_INT /* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ typedef char i8; typedef short int i16; typedef int i32; typedef unsigned char u8; typedef unsigned short int u16; typedef unsigned int u32; #endif goattracker-2.72/src/asm/chnkpool.h0000644000000000000000000000320310774364076016021 0ustar rootroot#ifndef ALREADY_INCLUDED_CHUNKPOOL #define ALREADY_INCLUDED_CHUNKPOOL /* * Copyright (c) 2003 -2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "callback.h" #define CHUNKPOOL_CHUNKS_MAX 64 struct chunkpool { int chunk_size; int chunk; int chunk_pos; int chunk_max; void *chunks[64]; }; void chunkpool_init(struct chunkpool *ctx, int size); void chunkpool_free(struct chunkpool *ctx); void chunkpool_free2(struct chunkpool *ctx, cb_free *f); void * chunkpool_malloc(struct chunkpool *ctx); void * chunkpool_calloc(struct chunkpool *ctx); #endif goattracker-2.72/src/asm/parse.c0000644000000000000000000005274110774364076015324 0ustar rootroot/* * Copyright (c) 2005 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "parse.h" #include "asmtab.h" #include "log.h" #include "chnkpool.h" #include "namedbuf.h" #include "pc.h" #include static struct chunkpool s_atom_pool[1]; static struct chunkpool s_vec_pool[1]; static struct vec s_sym_table[1]; static const char *s_macro_name; struct sym_entry { const char *symbol; struct expr *expr; }; static int sym_entry_cmp(const void *a, const void *b) { struct sym_entry *sym_a; struct sym_entry *sym_b; int val; sym_a = (struct sym_entry*)a; sym_b = (struct sym_entry*)b; val = strcmp(sym_a->symbol, sym_b->symbol); return val; } void scanner_init(void); void scanner_free(void); void parse_init() { scanner_init(); chunkpool_init(s_atom_pool, sizeof(struct atom)); chunkpool_init(s_vec_pool, sizeof(struct vec)); expr_init(); vec_init(s_sym_table, sizeof(struct sym_entry)); pc_unset(); named_buffer_init(); } static void free_vec_pool(struct vec *v) { vec_free(v, NULL); } void parse_free() { named_buffer_free(); chunkpool_free(s_atom_pool); chunkpool_free2(s_vec_pool, (cb_free*)free_vec_pool); expr_free(); vec_free(s_sym_table, NULL); scanner_free(); } int is_valid_i8(i32 value) { return (value >= -128 && value <= 127); } int is_valid_u8(i32 value) { return (value >= 0 && value <= 255); } int is_valid_ui8(i32 value) { return (value >= -128 && value <= 255); } int is_valid_u16(i32 value) { return (value >= 0 && value <= 65535); } int is_valid_ui16(i32 value) { return (value >= -32768 && value <= 65535); } void dump_sym_entry(int level, struct sym_entry *se) { LOG(level, ("sym_entry 0x%08X symbol %s, expr 0x%08X\n", (u32)se, se->symbol, (u32)se->expr)); } struct expr *new_is_defined(const char *symbol) { struct expr *val; struct sym_entry e[1]; int pos; int expr_val = 0; e->symbol = symbol; pos = vec_find(s_sym_table, sym_entry_cmp, e); if(pos >= 0) { /* found */ expr_val = 1; } val = new_expr_number(expr_val); return val; } void new_symbol_expr(const char *symbol, struct expr *arg) { struct sym_entry e[1]; struct sym_entry *se; int pos; e->symbol = symbol; pos = vec_find(s_sym_table, sym_entry_cmp, e); if(pos > -1) { /* error, symbol redefinition not allowed */ LOG(LOG_ERROR, ("not allowed to redefine symbol %s\n", symbol)); exit(1); } if(pos == -1) { /* error, find failed */ LOG(LOG_ERROR, ("new_symbol_expr: vec_find() internal error\n")); exit(1); } e->expr = arg; se = vec_insert(s_sym_table, -(pos + 2), e); LOG(LOG_DEBUG, ("creating symdef: ")); dump_sym_entry(LOG_DEBUG, se); } void new_symbol(const char *symbol, i32 value) { struct expr *e; e = new_expr_number(value); new_symbol_expr(symbol, e); } const char *find_symref(const char *symbol, struct expr **expp) { struct sym_entry e[1]; struct sym_entry *ep; struct expr *exp; int pos; const char *p; p = NULL; e->symbol = symbol; pos = vec_find(s_sym_table, sym_entry_cmp, e); if(pos < -1) { static char buf[1024]; /* error, symbol not found */ sprintf(buf, "symbol %s not found", symbol); p = buf; LOG(LOG_DEBUG, ("%s\n", p)); return p; } if(pos == -1) { /* error, find failed */ LOG(LOG_ERROR, ("find_symref: vec_find() internal error\n")); exit(-1); } ep = vec_get(s_sym_table, pos); exp = ep->expr; LOG(LOG_DEBUG, ("found: ")); dump_sym_entry(LOG_DEBUG, ep); if(expp != NULL) { *expp = exp; } return p; } void new_label(const char *label) { struct sym_entry e[1]; struct sym_entry *se; int pos; e->symbol = label; pos = vec_find(s_sym_table, sym_entry_cmp, e); if(pos > -1) { /* error, symbol redefinition not allowed */ LOG(LOG_ERROR, ("not allowed to redefine label %s\n", label)); exit(1); } if(pos == -1) { /* error, find failed */ LOG(LOG_ERROR, ("new_label: vec_find() internal error\n")); exit(1); } e->expr = pc_get(); se = vec_insert(s_sym_table, -(pos + 2), e); LOG(LOG_DEBUG, ("creating label: ")); dump_sym_entry(LOG_DEBUG, se); } static void dump_sym_table(int level, struct vec *v) { struct vec_iterator i[1]; struct sym_entry *se; vec_get_iterator(v, i); while((se = vec_iterator_next(i)) != NULL) { LOG(level, ("sym_table: %s\n", se->symbol)); } } static const char *resolve_expr2(struct expr *e, i32 *valp) { struct expr *e2; i32 value; i32 value2; const char *p; p = NULL; LOG(LOG_DEBUG, ("resolve_expr: ")); expr_dump(LOG_DEBUG, e); switch (e->expr_op) { case NUMBER: /* we are already resolved */ value = e->type.number; break; case vNEG: p = resolve_expr2(e->type.arg1, &value); if(p != NULL) break; value = -value; break; case LNOT: p = resolve_expr2(e->type.arg1, &value); if(p != NULL) break; value = !value; break; case SYMBOL: p = find_symref(e->type.symref, &e2); if(p != NULL) break; if(e2 == NULL) { static char buf[1024]; /* error, symbol not found */ sprintf(buf, "symbol %s has no value.", e->type.symref); p = buf; LOG(LOG_DEBUG, ("%s\n", p)); break; } p = resolve_expr2(e2, &value); break; default: LOG(LOG_DEBUG, ("binary op %d\n", e->expr_op)); p = resolve_expr2(e->type.arg1, &value); if(p != NULL) break; /* short circuit the logical operators */ if(e->expr_op == LOR) { value = (value != 0); if(value) break; } else if(e->expr_op == LAND) { value = (value != 0); if(!value) break; } p = resolve_expr2(e->expr_arg2, &value2); if(p != NULL) break; switch(e->expr_op) { case MINUS: value -= value2; break; case PLUS: value += value2; break; case MULT: value *= value2; break; case DIV: value /= value2; break; case MOD: value %= value2; break; case LT: value = (value < value2); break; case GT: value = (value > value2); break; case EQ: value = (value == value2); break; case NEQ: value = (value != value2); break; case LOR: value = (value2 != 0); break; case LAND: value = (value2 != 0); break; default: LOG(LOG_ERROR, ("unsupported op %d\n", e->expr_op)); exit(1); } } if(p == NULL) { if(e->expr_op != NUMBER) { /* shortcut future recursion */ e->expr_op = NUMBER; e->type.number = value; } if(valp != NULL) { *valp = value; } } return p; } static i32 resolve_expr(struct expr *e) { i32 val; const char *p; p = resolve_expr2(e, &val); if(p != NULL) { LOG(LOG_ERROR, ("%s\n", p)); exit(-1); } return val; } struct expr *new_expr_incword(const char *name, struct expr *skip) { i32 word; i32 offset; long length; struct membuf *in; struct expr *expr; unsigned char *p; offset = resolve_expr(skip); in = get_named_buffer(name); length = membuf_memlen(in); if(offset < 0) { offset += length; } if(offset < 0 || offset > length - 2) { LOG(LOG_ERROR, ("Can't read word from offset %d in file \"%s\".\n", offset, name)); exit(-1); } p = membuf_get(in); p += offset; word = *p++; word |= *p++ << 8; expr = new_expr_number(word); return expr; } void set_org(struct expr *arg) { /* org assembler directive */ pc_set_expr(arg); LOG(LOG_DEBUG, ("setting .org to ???\n")); return; } void push_macro_state(const char *name) { s_macro_name = name; push_state_macro = 1; new_named_buffer(name); } void macro_append(const char *text) { struct membuf *mb; LOG(LOG_DEBUG, ("appending >>%s<< to macro\n", text)); mb = get_named_buffer(s_macro_name); membuf_append(mb, text, strlen(text)); } void push_if_state(struct expr *arg) { int val; LOG(LOG_DEBUG, ("resolving if expression\n")); val = resolve_expr(arg); LOG(LOG_DEBUG, ("if expr resolved to %d\n", val)); if(val) { push_state_init = 1; } else { push_state_skip = 1; } } struct atom *new_op(u8 op_code, u8 atom_op_type, struct expr *op_arg) { struct atom *atom; atom = chunkpool_malloc(s_atom_pool); atom->type = atom_op_type; atom->u.op.code = op_code; atom->u.op.arg = op_arg; switch(atom_op_type) { case ATOM_TYPE_OP_ARG_NONE: pc_add(1); break; case ATOM_TYPE_OP_ARG_U8: pc_add(2); break; case ATOM_TYPE_OP_ARG_U16: pc_add(3); break; case ATOM_TYPE_OP_ARG_I8: pc_add(2); atom->u.op.arg = new_expr_op2(MINUS, atom->u.op.arg, pc_get()); break; case ATOM_TYPE_OP_ARG_UI8: pc_add(2); break; default: LOG(LOG_ERROR, ("invalid op arg range %d\n", atom_op_type)); exit(1); } pc_dump(LOG_DEBUG); return atom; } struct atom *new_op0(u8 op_code) { struct atom *atom; atom = new_op(op_code, ATOM_TYPE_OP_ARG_NONE, NULL); return atom; } struct atom *new_exprs(struct expr *arg) { struct atom *atom; atom = chunkpool_malloc(s_atom_pool); atom->type = ATOM_TYPE_EXPRS; atom->u.exprs = chunkpool_malloc(s_vec_pool); vec_init(atom->u.exprs, sizeof(struct expr*)); exprs_add(atom, arg); return atom; } struct atom *exprs_add(struct atom *atom, struct expr *arg) { if(atom->type != ATOM_TYPE_EXPRS) { LOG(LOG_ERROR, ("can't add expr to atom of type %d\n", atom->type)); exit(1); } vec_push(atom->u.exprs, &arg); return atom; } struct atom *exprs_to_byte_exprs(struct atom *atom) { if(atom->type != ATOM_TYPE_EXPRS) { LOG(LOG_ERROR, ("can't convert atom of type %d to byte exprs.\n", atom->type)); exit(1); } atom->type = ATOM_TYPE_BYTE_EXPRS; pc_add(vec_count(atom->u.exprs)); return atom; } struct atom *exprs_to_word_exprs(struct atom *atom) { if(atom->type != ATOM_TYPE_EXPRS) { LOG(LOG_ERROR, ("can't convert exprs of type %d to word exprs.\n", atom->type)); exit(1); } atom->type = ATOM_TYPE_WORD_EXPRS; pc_add(vec_count(atom->u.exprs) * 2); return atom; } struct atom *new_res(struct expr *len, struct expr *value) { struct atom *atom; atom = chunkpool_malloc(s_atom_pool); atom->type = ATOM_TYPE_RES; atom->u.res.length = len; atom->u.res.value = value; pc_add_expr(len); return atom; } struct atom *new_incbin(const char *name, struct expr *skip, struct expr *len) { struct atom *atom; long length; i32 len32; i32 skip32; struct membuf *in; /* find out how long the file is */ in = get_named_buffer(name); length = membuf_memlen(in); skip32 = 0; if(skip != NULL) { skip32 = resolve_expr(skip); } if(skip32 < 0) { skip32 += length; } if(skip32 < 0 || skip32 > length) { LOG(LOG_ERROR, ("Can't read from offset %d in file \"%s\".\n", skip32, name)); exit(-1); } length -= skip32; len32 = 0; if(len != NULL) { len32 = resolve_expr(len); } if(len32 < 0) { len32 += length; } if(len32 < 0 || len32 > length) { LOG(LOG_ERROR, ("Can't read %d bytes from offset %d from file \"%s\".\n", len32, skip32, name)); exit(-1); } atom = chunkpool_malloc(s_atom_pool); atom->type = ATOM_TYPE_BUFFER; atom->u.buffer.name = name; atom->u.buffer.length = len32; atom->u.buffer.skip = skip32; if(len != NULL) { pc_add(len32); } return atom; } void asm_error(const char *msg) { LOG(LOG_ERROR, ("Error: %s\n", msg)); exit(1); } void asm_echo(const char *msg) { fprintf(stdout, "%s\n", msg); } void asm_include(const char *msg) { struct membuf *src; src = get_named_buffer(msg); asm_src_buffer_push(src); } void symbol_dump_resolved(int level, const char *symbol) { i32 value; struct expr *e; const char *p; p = find_symref(symbol, &e); if(p == NULL) { if(e != NULL) { value = resolve_expr(e); LOG(level, ("symbol \"%s\" resolves to %d ($%04X)\n", symbol, value, value)); } else { LOG(level, ("symbol \"%s\" is defined but has no value\n", symbol)); } } else { LOG(level, ("symbol \"%s\" not found\n", symbol)); } } void output_atoms(struct membuf *out, struct vec *atoms) { struct vec_iterator i[1]; struct vec_iterator i2[1]; struct atom **atomp; struct atom *atom; struct expr **exprp; struct expr *expr; struct membuf *in; const char *p; i32 value; i32 value2; dump_sym_table(LOG_DEBUG, s_sym_table); vec_get_iterator(atoms, i); while((atomp = vec_iterator_next(i)) != NULL) { atom = *atomp; LOG(LOG_DEBUG, ("yadda\n")); switch(atom->type) { case ATOM_TYPE_OP_ARG_NONE: LOG(LOG_DEBUG, ("output: $%02X\n", atom->u.op.code)); membuf_append_char(out, atom->u.op.code); break; case ATOM_TYPE_OP_ARG_U8: /* op with argument */ value = resolve_expr(atom->u.op.arg); if(!is_valid_u8(value)) { LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n", value, atom->u.op.code, atom)); exit(1); } LOG(LOG_DEBUG, ("output: $%02X $%02X\n", atom->u.op.code, value & 255)); membuf_append_char(out, atom->u.op.code); membuf_append_char(out, value); break; case ATOM_TYPE_OP_ARG_I8: /* op with argument */ value = resolve_expr(atom->u.op.arg); if(!is_valid_i8(value)) { LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n", value, atom->u.op.code, atom)); exit(1); } LOG(LOG_DEBUG, ("output: $%02X $%02X\n", atom->u.op.code, value & 255)); membuf_append_char(out, atom->u.op.code); membuf_append_char(out, value); break; case ATOM_TYPE_OP_ARG_UI8: /* op with argument */ value = resolve_expr(atom->u.op.arg); if(!is_valid_ui8(value)) { LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n", value, atom->u.op.code, atom)); exit(1); } LOG(LOG_DEBUG, ("output: $%02X $%02X\n", atom->u.op.code, value & 255)); membuf_append_char(out, atom->u.op.code); membuf_append_char(out, value); break; case ATOM_TYPE_OP_ARG_U16: /* op with argument */ value = resolve_expr(atom->u.op.arg); if(!is_valid_u16(value)) { LOG(LOG_ERROR, ("value %d out of range for op $%02X @%p\n", value, atom->u.op.code, atom)); exit(1); } value2 = value / 256; value = value % 256; LOG(LOG_DEBUG, ("output: $%02X $%02X $%02X\n", atom->u.op.code, value, value2)); membuf_append_char(out, atom->u.op.code); membuf_append_char(out, value); membuf_append_char(out, value2); break; case ATOM_TYPE_RES: /* reserve memory statement */ value = resolve_expr(atom->u.res.length); if(!is_valid_u16(value)) { LOG(LOG_ERROR, ("length %d for .res(length, value) " "is out of range\n", value)); exit(1); } value2 = resolve_expr(atom->u.res.value); if(!is_valid_ui8(value2)) { LOG(LOG_ERROR, ("value %d for .res(length, value) " "is out of range\n", value)); exit(1); } LOG(LOG_DEBUG, ("output: .RES %d, %d\n", value, value2)); while(--value >= 0) { membuf_append_char(out, value2); } break; case ATOM_TYPE_BUFFER: /* include binary file statement */ value = atom->u.buffer.skip; if(!is_valid_u16(value)) { LOG(LOG_ERROR, ("value %d for .res(length, value) " "is out of range\n", value)); exit(1); } value2 = atom->u.buffer.length; if(!is_valid_u16(value2)) { LOG(LOG_ERROR, ("length %d for .incbin(name, skip, length) " "is out of range\n", value2)); exit(1); } LOG(LOG_DEBUG, ("output: .INCBIN \"%s\", %d, %d\n", atom->u.buffer.name, value, value2)); in = get_named_buffer(atom->u.buffer.name); p = membuf_get(in); p += value; while(--value2 >= 0) { membuf_append_char(out, *p++); } break; case ATOM_TYPE_WORD_EXPRS: vec_get_iterator(atom->u.exprs, i2); while((exprp = vec_iterator_next(i2)) != NULL) { expr = *exprp; value = resolve_expr(expr); if(!is_valid_ui16(value)) { LOG(LOG_ERROR, ("value %d for .word(value, ...) " "is out of range\n", value)); } value2 = value / 256; value = value % 256; membuf_append_char(out, value); membuf_append_char(out, value2); } LOG(LOG_DEBUG, ("output: %d words\n", vec_count(atom->u.exprs))); break; case ATOM_TYPE_BYTE_EXPRS: vec_get_iterator(atom->u.exprs, i2); while((exprp = vec_iterator_next(i2)) != NULL) { expr = *exprp; value = resolve_expr(expr); if(!is_valid_ui8(value)) { LOG(LOG_ERROR, ("value %d for .byte(value, ...) " "is out of range\n", value)); } membuf_append_char(out, value); } LOG(LOG_DEBUG, ("output: %d bytes\n", vec_count(atom->u.exprs))); break; default: LOG(LOG_ERROR, ("invalid atom_type %d @%p\n", atom->type, atom)); exit(1); } } } goattracker-2.72/src/asm/pc.c0000644000000000000000000000442310774364076014606 0ustar rootroot/* * Copyright (c) 2004 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "pc.h" #include "log.h" #include static struct expr unset_value[1]; static struct expr *s_pc1; static int s_pc2; void pc_dump(int level) { } void pc_set(int pc) { s_pc1 = NULL; s_pc2 = pc; } void pc_set_expr(struct expr *pc) { s_pc1 = pc; s_pc2 = 0; } struct expr *pc_get() { struct expr *old_pc1; if(s_pc1 == unset_value) { LOG(LOG_ERROR, ("PC must be set by a .org(pc) call.\n")); exit(-1); } if(s_pc1 == NULL || s_pc2 != 0) { old_pc1 = s_pc1; s_pc1 = new_expr_number(s_pc2); s_pc2 = 0; if(old_pc1 != NULL) { s_pc1 = new_expr_op2(PLUS, s_pc1, old_pc1); } } return s_pc1; } void pc_add(int offset) { if(s_pc1 != unset_value) { s_pc2 += offset; } } void pc_add_expr(struct expr *pc) { struct expr *old_pc1; if(s_pc1 != unset_value) { old_pc1 = s_pc1; s_pc1 = pc; if(old_pc1 != NULL) { s_pc1 = new_expr_op2(PLUS, s_pc1, old_pc1); } } } void pc_unset() { pc_set_expr(unset_value); } goattracker-2.72/src/asm/pc.h0000644000000000000000000000257610774364076014622 0ustar rootroot#ifndef ALREADY_INCLUDED_PC #define ALREADY_INCLUDED_PC /* * Copyright (c) 2004 Magnus Lind. * * This software is provided 'as-is', without any express or implied warranty. * In no event will the authors be held liable for any damages arising from * the use of this software. * * Permission is granted to anyone to use this software, alter it and re- * distribute it freely for any non-commercial, non-profit purpose subject to * the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software in a * product, an acknowledgment in the product documentation would be * appreciated but is not required. * * 2. Altered source versions must be plainly marked as such, and must not * be misrepresented as being the original software. * * 3. This notice may not be removed or altered from any distribution. * * 4. The names of this software and/or it's copyright holders may not be * used to endorse or promote products derived from this software without * specific prior written permission. * */ #include "expr.h" void pc_dump(int level); void pc_set(int pc); void pc_set_expr(struct expr *pc); struct expr *pc_get(void); void pc_add(int offset); void pc_add_expr(struct expr *pc); void pc_unset(void); #endif goattracker-2.72/readme_resid.txt0000644000000000000000000000262610774364626015661 0ustar rootrootThis is reSID, a reverse engineered software emulation of the MOS6581 SID (Sound Interface Device). This chip was used in the Commodore 64 computer. reSID is free software. See the file COPYING for copying permission. reSID is a C++ library containing a complete emulation of the SID chip. This library can be linked into programs emulating the MOS6510 MPU to play music made for the Commodore 64 computer. reSID has been successfully linked into VICE, a full-fledged Commodore 64 emulator, and SIDPLAY, a popular SID tune player. The VICE home page is: http://www.cs.cmu.edu/~dsladic/vice/ A patch for SIDPLAY can be found on the SIDPLAY home page: http://www.geocities.com/SiliconValley/Lakes/5147/ Various SID emulators exist, however reSID should still be of great interest to Commodore 64 nostalgics. The emulator engine is cycle-based, emulating the internal operations of the SID chip. SID's audio filter is modeled as an actual two-integrator-loop biquadratic filter circuit. The engine has been developed based on available information on SID, sampling of the OSC3 and ENV3 registers, filter theory, and meticulous testing. In short, a scientific approach has been taken to model the SID chip as accurately as possible. To our knowledge reSID is by far the most accurate SID emulator ever created. This comes at a price; what is considered a fairly fast CPU at the time of this writing is needed to run the emulator. goattracker-2.72/authors0000644000000000000000000000030311314431160014046 0ustar rootrootAuthors of reSID. Dag Lem: Designed and programmed complete emulation engine. Antti S. Lankila: Support 6581 filter distortion, envelope & voice nonlinearities, output amp clipping effects. goattracker-2.72/goat_tracker_commands.pdf0000644000000000000000000055356511115312724017511 0ustar rootroot%PDF-1.4 % 3 0 obj <> stream x̽k9nW|Q۞-/I%Ut;$WHڣ(+ ^gi`"AH_}W}~~է?'?_i|/?{)տ@G//tK體ަ>;սb4b߹g0wO~2?;N7JҷAguίeoBEColkء<;G_K}ÌS#|// =훍L<ߞz Gq4\Z|pf\}A>1s~s1pu?;NcC[o}t%hp2b—SF_۳?Q S90w'_SŗÓjJ+Ԓ|RU^ygeʠ8ݮ̿:0GLQөv ? j4,9ou6\#lm(Wnj?iw)Nę}}2?JOIy/-n3?Ǡ$u*wdr6% ڤ$ҘՍQ'orr\Y96ޅîYr:.?k6=~I>/vМ߽Rу?Ə,؇期\WJ6)}&ɘoj+kO˾b"tx,3/6gټfNۛeEEy؏eKS[7Ngy~I=7|pjlu1r~-YE16_AfQx]u;ې7ߝ/ bcM1MU~Z ZP?͟Y >`o`ζmc8GHFfh~`<{lUW3u؍C?v .ڌקN=Ao+I㻰c׏.o(1NZC/{nMS|D &N3h~N\nF>!ɥJO^(lϮPϮ_SS<z~f͐~i??, 1)Af …nHCFAxcU {L7?ٽ4nQs%J'詟>zFGKl;GxwG,|ǧӑN^ט9McU{g:Lq|g?^l/nx1u"ŗ]i|au5 ~?v4#{-kvzN0qu%x2;~ua577ĢzM-ޕDt"GПWY|f}7ؐ䶇%N~ڷcv`N0Rʖo]etf?<z^So94迾e}Sn9_bczkz Ocԗ@9Oc8\p杬 6qXy9":hqbV3,-6r*qdbV3,-6) b:k7CG i*q nNoo; 0aXkWZlt+.oNW1]cmΰ!}aL닝w8ږbL%f9bU)Ĭ6gXZ,݋;^<;؝Vo(񥵽9iWZlt)꡿BԭZlt]x@W1]_R\`k_qT҂t^cu|h\D)[;N}2ammQ*<} #cTB~iWp8Sqq䊑F3iԸV #uEhzeJ;+F[=.tNǿh>ÀNmuhDžΉؗr߃NV ;q'FV u-Z=.tCklz؃J{zV _a'+F[=.tNԡrqvC:кbBD}]hyܧzi]1qsscE} q +<؞OՒ&1vuB" ]nfؿo~? mn/}Sx(܁àa)v<G7!2tYSBnB@8fC'U><".d Х$X@譹C"H0ddӽ ʏIa$pF|3}ڱ(@mC_0d%#p;D!cˏ3|9  F2 `ÿGln&(?EB*DP&9Ĭp '/}잗?z`TH{Hi $>@V>!NZqke5:WԶn#UB܌!S jj2ɲra7P5PP\ yk(x}ЬMŭ$YbH]!y7&KlM$'?:XiDw")=HEFj{c&;ȍגQU_'3uyܦ*lfLnnAv&3$EJn^b߱/e*rQH$F?3:Eաq7:+ұDq`K"{u#6BoSD 4JpI߽>f]_ӥ Ǎ<`,d],x~lކ {߽a@!x\>UN`LacȟW*ر`.^qS9J^f1)Gba iٍHTgܾ& rC g8Cm;=!,ޖ2H7< u OqEBR"Ҁʀ}\QY:aFi`סXJխ}`2rĠIXmh'AD; ~ڽ fЩgT0u8ܤYVYfzq,8&~jg.]`\%QZ3 ޔQ8 Z0i,c.i52#a4NNSJ X 2xrkVH1z8!WӴ&qiNv9M54 ŶMS7Gi"l: HX?`i qM1tNaJdPfr8!F*o&mA ?t9WǀC\M:{tQ`k^L-cmC3Ǵm@dG6c#iw1=05S;n*=474.;z{Vc"d@c_mڷ? G7tϽwt ӧw .-~o;.ӧv<0-i*t8ށDO_ށ&mcb]ZK][ m;09ͽsrc6@ ORvj L~UW8MisyO+iJw0,w/0 ț#X"cލ/]`qJY_C OvOte R0J(NT /L\~>=!j/+L(BgqF,Pߧ (:"pyD$5q{:A Dq@^O]tm>mEFgIw}ypp8Ƽ6 (NIZ )j&vzZ'{ͷ{-#p}ћM6r0c9f 6EFOzY>R g'bEZ8ۇܬ8zi.!;rC4ٶxUKD=Zl.=ZG/bz`vc2KUW,"pCZ` h$669-tǏʁ .0 ]Oyen L,T Q Elw! !f0۩Wz-"3k/ptMy k09VxGnr.<1T j1w8QqC~3:~60Ӛ[r@& ti ^ eC6_Cp"]M0E&'d1NN!G}V,bբn&tpeTaxۛD|Q4_=;&QHKHe8eſS@(fظ=W_ǧ乸%-#z>DaۤS[7D>V+<{?%~nì֟T# XR\7lap6En?0FaIg,֜:8ùT~xMU7qwu(?}0,2 S+|[~䫙A!}XWG7rF$yY3J9=~\}xrб,'".g'۷Qo0E ?%hCƆw = \3k;Ѿ3"R޹>ywp ~pw&~,!/jߊFɔd?<)iue?T#C? ߒK^NIǥn)QO[jn~%1{\HEoE|;Hfn9= yo!=[KO")S9oWz=6Q۷8<yqsӼ*o$ V%gM>f90eap?>Yr|/bo8hk9O7`pDMbh˸{"(`ʾ7~(VnKd??|} \> Bp R'W䂰&}Q$Ͻ+bF:䂘Mv8}#ǎDlM.iFrblu6cG4"&4 Wbo=6cGTuܹ  9n,EHGR&XӘkrA&ؐaC¼yifdžAL6 HRNI:DiܡK-`E0.[̢uk@tcM_B<4CgMۏ֩ot.m88ƍ^ڕr5s]t.k88fXھ筃W6yi fmDE&3#uWōMgG¾٦ & š<4ھ LHH[{|AhǙƑp l+F&3#,kطdkǙ‘C-' B[Cڲg.g2y߲—4e5$i$WFp^]tb¯|cr}۸dMR/FC(̭߰N,a>C145 ѽereK\ _m.@LB2?S'4D3!68l-!.fӜLٵ-aa,T{>!jX D,qLDaf"pV}c5`.;Xrlx!C#A+`p9A3KVv€YhQ"B1~mNSlaou¸'i;f .J%1W`)kcT^Svhc}Ӓӭ*अ)hC}XftϒnBM;M`Dj5q&[[YklXZ5%LZfc&{4EO&6W5-TgB6puAZxw5#\ոL VyiZK<<ÞkJӾ\pl(lOj$Ho%OIc =505ԀM8 ̀‡6O<bW%YU6TQ- aŭ/Shs.f:wx2\͝0@ԅ[y(c\y1< _ado@&$f(o&7`Kb= >6ͶQz 9|)ƣ;O2r<]b̬:"3Y}t.ŒdȢZ/lEV/L[L*:0PU߈Nf/RaJqqDսU 2}9b,t0RGw_#KrW#V#rUp|.R j(ʕQ31sߤ 5JG8~Akjlgr?Oo?1Vjd9+_YN`qZ+> hڥ*QT {e`[}0(NJ,彸z^o:c^ҠT{Q Z^jЪ'KnU!W !Ob[8Nu]~ȴ Рs6 |mF= ;aaQ[ /!mE ÷}`u"TV 4h AʪX =JG== 1¬D|5JR3]Vl~"ܚ&҈V ҬM8 Uŭ:0ѵ1讨!F#DX*=v}@,h'hۥٍ}yt%&'81sxL`Ďq,VRK C{cttؤ2J온}.|dЭU9QFLPQ4 7̑?+&\a CmϘk$cADdy)9JNbtP)gނrf/G'KЋ4\qx7F`8,LksB*V hE*H$1:o&1[NdžYSUyxD1}P>Ard.T)}e\+8ǴvX#^cku@w։ɪDUX 0ޖb:|t 0rLXHBv~yDzA,!>. ܖ]Wwdpl㺴pwg|~N@ŬyVWLc,6^f vaWsqqhvzL8¶.8JnnS<3 VU/]_eR]-]b䤾۬U֤I/x`,1(Nf}G_44Ŷ,^,6x,NЌeY֥eFyFmZdk|Zf1Vh^XdɝX < ԑOsGu+tVQ ,;Έz|''$e&v: Ol2%E vhd}qIb6\ I"%&N)˸\Un%k!LN}D %凯قGD& ɕ<#"pyb$T1R SJSh`KIRmmDɼ͹q}"iT\Uӽ-r|C:ANb"fo *QNE7kLTr^'=.gAa(30ȶv. z`AY*à[6D)!by48'n:\hCTxȉ탸v+5K&`3NXN0<:kG>]%ވE7ErEhŕWN}D<bX.4c7}~PXwylˇx/|l_}hhءYMD ./qzшP\\Qh>e/ y豏ˋryxT~z-/QMzшˉOW'X>4c`q{@9yZ} )jMwNX֗[vFN}`y}C# ݇"tU`v4SkPR@W60dKN'Hv53DH𪼝S}irexz!QԥHxMa/8Q:G*r+7<\Ɇу 0]gA_ 80fg-v2}HF\~`\וB& 2+bw3~Ԝ$guӂ^mRA?EԄ Y7Ex%ܵA#?~y:`3rw=l76"9,Z٨#8Q Wztpӣ :mHƜȌ B rH&5l_Hd`G }0{0K;I/1*餅P負%B(o'\E,If> µ͞bGXXåE_>P_MեW#ZְVw*lk镤H. \h|bhJX[]3ɱ8QC#&[I;VrѥD<Ʊ,cƵhH},RD` *"Y9 t҃D3&Xa$2284j!4?IB\\)mIN6xs( 0.Tp'H[S׳\xc$,1Hx"d4&ʆr#6Ara_1j-g. v'ع:z @8R6xҖh @VdVŀ!֢"عS6y z-jNzY:\e2ozxt w兯E'>}LoתaM HTd`ރ@cjI3kS?2}^TCUX2k끯mahZgè9 0M6,'( /~-Q;.Zu5MuM z)z uע5i| a9E8`bdž^B,X+Ok+Z%;@.  ODy[  R=z}(geO"[w.ߨ!|?9cy\^Y]^8pnՔ 'W{_7Z{wefo宊孊7(؏1O*l`J;bs=1(8ETsonD\ַ_(/Uit9NcaP6Zgbf+K[NRF1!n0aiXOj#dž1FWΉ4wb{+fUD"Z1jkihxbVOV-hn4|3ӄĿ1n祯 wQ7̱_hʩ&عDϡB:'ꨴ_AˬqrIıkIF3i #1+F[=.t޷% "Ho~8>4Q+>5 j|>=wzZNoGX; qD#x}K@y<֗ǐ>Ü[>ww/[߃Go=i%?y;Typ|S(/7p۞[öf`ǥxo5$c L歗Ymů7lJŽ>zW >:ѷ1d5K[~f^<.'KXuOZARESUky)y>RhHi,0JiO1otuN;MD4@gZe)VT\i NcXͅ%^,R5ißsOWhLihJYW>B'WÓ5}夭鯐5}%.+Ec`~n#~35]JϮ Jk*/$ݻ6{km?/e}!Y3Bg$|vY_Hgy9dxsY_Hgy9$|vY_HyiB2:7-kTj<'Py m|va_H֧t[i'I6_>/$ӎ-{i|I}!vmaM. I[م*n:ѕ}Tu~Ϯ n B=ۺPO鶮&B2<\ڲPϺ鶪ߖn~Ϯ InҩW#⾐tO;/$ӎI꾐 O;/$ӎ nm?A!ubI,2QD/,i <'Bl|"JL}vB=׷INJw{ڛWHAM^Iw׷+IM6y%ieoS('mR r6+,'mLOrȷ)~E^)w9Qƾ#<^)g򾐬O~/$a/$a/$G8&'+q- q I3YݓFCV״]o]5]֧olQIg{V`xƖv5)gl- gl% B~Ϯcf+ś>wZu%X=h+B>}hcKm?}fkB2=}fBVcxvyIgw rϮ l\}{*$|v]_HCWl]_HCWl]_H-l]Mgd|:dz:td~go]IeqiRF^J-xl|&R^ENY1鱢"1cԑ9N]1u氖 ZS+LC\ 8`21{+FZv ;u<N#Y4"8`1{+FZh1Zy0]X4&6HF]1y`ѺXuWF]1uӺXz䣂undžfcuEl69ΝEt6ʊy0#eۗaLiǬ`wX<&#Hu6Z:pQZ[+f" O mn('F}4x3֠{0QZ[+fˁ֠jb VWFվʡb6h~FV1Jkku,A0Y7L;Qh ENܨob6xmf5:E}(Qk-38_bz4x^::pyl%3FZGn10."#b#^Pl6Qs[̤tbEDwҊF{W"}b%ͪlqHV){EHT/Ҋ8jtYT>q4*-fR:QY$ qVQO["}b/GǍ"v%Y:YTL Ou#pEHEKmnU:+TbA4zHvUr6JWz\蜨#H•/Rc:Ge0 x&GulGVLG}hckhC /*8oD׸)w!Ʊ>캦1}YLfZMgG,׵Ow7\qag90c@W kT knRndäV,L \"DQct GA87 ' ncF@NlYXSڣC 9<#S2)xr2"E3e]$S(ģR9&N$ȓym,ѡxzdwcA~&0U ͘( p=KSȌ(™ l"Wӎ/^s>bɽ&]Xp9. Z^Cr-2¦g^=Yp{Mk=UrPN妘&&3/C?a*yz l Nμpwp&+{8eI2ڂ ,zbe,G 8a‚vdəO_edd|QL4ⱕ&Bƒ@~P\Dp VxǓo!) 8?±E]%^}U_Kۓ& iS]fae3aືbىUj]g[/$peF¥;1] yPG24Dxe 2B>5f9 ~/Z9^Țs}2+ًLﱈUYӪ2^' %"Wh*^%`( 1"8"e.е#JTDip&H`8 72ӗ RBݚ!D_]@yu11m PEL8JWWSF@~g. LsvR-^ԗW66Q|o_Hբ`S~&W;Ax)΋n!^%6 X j1$ t<47FCb ,lSb=|A0|& wrhb>a5&3vYdų xdEFֽl& bfZ`lf GC0/W6)O|6ǴA뷴1D\T+1`Ǡ*?D+2Dgl-u:0b=FfNֲ9n @h_~QmzO.N$VU_Lt[l5XkcѢx(=X<gA9W"Y'0W I'o ^g4-"}/bk9txCrm=\hLFC^ɲ;Dpk;D0zu~ gIżCR;L|\$na"uzUi;x/C.aya;DZ5\ԅwص;A!eh{NC"CNʜ H֩ !U$ڙs2DfV "MDfAmllAdJr]& AD} $>]D-o"縖!~]ӰUu'8V`na;AL09c\K6B@ViH`D >6^#wJhsi5,V^ڔUQr$jMpi# 0X^(xcmn0_azñ=!񙌉؛pܓ5'  y 4~|,&&J\4}NFB%_ќ b +JfZ'ˆZ5KS0jRؖA llQ`\(`:+aEIaڢTA[4٢cLlQ"1ˀDshp7S4EݤKQLQ.mˆ)J C{H3Ey츺an~ʐܖ)j)E~f,Q`H,Qjh| Q4 Qo׋=5=F?/eF9,Q̰ZD#ND׺Ya i| p>r5!9tIsjBP\ɡ`R |YQ'܋kŔ"ZVQ ֤[-B0.IDiTr5- ztǬ^Pl|>2a*#[qjs t=eD833M6. (Ćk\V S[3t'*t{dܓ !"Ua%^ /1Ep.# i%/KtJUhEh!l OL;rk\W%)Jh M0E:;N!`qRUk& z2 */Kl:_YU`aH(`SJ_6pz8e}Z4unOSFq7EQɴ_'L=j-KmS|r,g4yx J7Ɖ-`Nq 'ev gkz E;/>k7IJhg?F g1[u|4jрJZ  FfA:oa7D{&o=B`a@r4Z IPwV18z8\8bH5ob!n;sb%8nϘ1N[p}>Tly3gǀeJ8!&`/nYlV|)]t1zhG<]7&4zp!nw\TvaZZrwL8ywrJO^$^]{]`Z0(AΛ%;&[K޾ڢ0gnƜ[& I84nuRCw Vz9JyGb4<.CTC<˧2uߵ͏4^:-7:f7Ƿ'p7?u=d~|k<1?7u9-?UFo~|Q?2[iˆRy^!эe{)p߆R n!ԋo~u@rܽxv//.iyMlֆli.ˍR8iMt1enkYF0fbn)Jw= ZzF*ob xR1 !*v퐅ḽj(\âsifDzQ_S(]`1.#x&e`fM]jǎ,nyCjN.MLQ[?aS} =<X *ّE u Y*"ȮeʗO8 V6/|e#?}Y :oVUz-UD.]kEF.SgB@9z ?ֵFג7sCz  hIo3_Un0G;i䠔[ĆI (oFN{(l]/3=Kj^ O+s,.<` yZBqxYwJMR Ha5pκFhCԠ&p1)bR,>Kέ%gCÀ vB[RR47 ]LÒp>mgˆMqaeLe]6˳LޠA LK/L]6ٮrLՀ Q. 5fh31)+WjA[>cĸu睃cRSFBuI uQۢƴ9إ:UE/2`=g9[Y&&fsf&7x LHe:TK}gx&G [f2zY4nG틷 XٶP`_&hS]fTS]FZp97yW;lKf"2([г6!,sƲ25=Zy9e z[άZ2X# gptWq9%Ogp Z8˄+Ӡly4+[Jcڣ 15/n4!xm`r\5v8. # u x4!&%e؆o͔UMUӬAVA^6^Ԁ=H DSy) >ZМ8ib&)ktAlm);:cw 8 Z`d5U[cI lX($AXo$LN7m}LR/!@ KKX+IIlXð50(o,^J/PQ9LU0vp]bjKe 0i4.!np&wm++f`xʉm|QR)<ݚRP4$RpGF j,A'lYzw(В B$S%՗͚M=SNqS`<6Lib0Ip]`]1(&'M/Q-ElĬ==nqceU X#q srJX-OKYj^DQ*Z*N) B8 K(<6tiR f1Z`,D6oEo"P fBⅅ^C1R pe -0TWf;*Yޓ%%Zl_9ݤXm.yCL^پ}Ö++WSWw%U)^{xjl߅vD+7&vV/}wX{&fn-fN5 rg];ms'jo:5Qg\Ϩ4#eS0L $4˧3}2_"0sAxi[>2"%d?YJ\ex5 KmY'a&mc|Ijw7ꊱ1XV#f׳L0tqMrA+FeTL2ugVb;.WFA% @iʱI`_tQ[R J/A-jP&E*(kJ<-R7kEe`ƨ7||BGM)p_H5+7IV+0aTnQ`\  E|I~v}b(H ^ju` JN֫Q.4WN%vBG:)('oLVY'Iq6fL,59H y(‡dVQPX pւc @qs;ŊgwTRo-vd@U,H$5]ҫ&JH݀QքX)Vw &akaZrx %ɇla}WP,9fGof@IoaIZLD*ELMj U +%ub-l7b~7FzhIT*]iH6ITqfbKBÀ:0R Cq@0B 7fjSO)`P8% ig)6$Sc|3o[#~21J2cAe}hN+Q,G Up=Pv|f9~I!Im c] ^ )4i$3WLnta9G31(C&Jm4dU'ys]PL靚^U<Mˑ~P,,UPn\"6W{i.~d&^-R/ w/Jߑ0W,٧#\ѤiSY5 7z+;>rdۻ\~_e)+0ǀAd**ݞ[m^lVVBkn)k8몂=q+Bf,K:n_ɬ=,~it(_f-ۧ'4df -N]nf [,#IR v²KBCJe u8 'q r֋C6䷀ |f)`Ҹ!YS I"ׂ"=0l*C&'dLqzpKh1kH ¥Z .i,a}V!1vTVw̖b^2"b*e5RQ@"+U0s'1প$(MLx~Il_(HuH$_GPW`wBt E4!*br?!47y>y>^WB#&cLaM0M  $ [/ J@ĕiѧ) v=5jH&Z|`8 ;O҃*a)W=#FtٌX8|jX3o{JuE12vFTsToe}nz" U‘qGvJC*k#;H; c\1Y̹1 PtOɹ|&97qǒItSK j)'mGMpY G\A1\%'tܥÞz*ϧF&A=yL|Č E$m(2נPdɣ>0s)E9Sj,hp(+/ E¹~B4$Ћk}C@F{E%p'y(#PIQ.8dW(j0#;F=;m\ MMU& ҘPr5׵o^}ݦ NNpwRt{UPUEjQSeiQngV& `19Z1sPԢD-9 g%VbzƘtբHɤ}<$E3 JLκZP29XVeFubPSo+,QbRu(gE1mbnp({Xx fI>+}<oE}_`L3JLr(3*E1]1 -ppD $jQ=a66\-_z!:5FE- c6AHP%lpȭۢNzdVEWE#zQ&UCIl#(ԫgPCVfX+-\I>LiEZL{+Q+,y!i(WxŚƄ_F W_;>D;+\M\wSюrn OhJ`^^>=ZR==#Iy1ygc*6x'Ъ+t./g!ϘdUG ڎ rSZAH)h47e]ʥ83 `ʚ M9=`DLGtÒ&59"q+G>2*sZБb:[̰S--E^d=^% c&PzYIrNЄK+iZtpk\(]1NL-^cf9b7ESNzsRˆ1Jp'B:L?T-QŶɤ4](r|}']\ JQcZNui~r};KMĪEr_U2bdln;T z]EnPS4 wuz]duuպ̍Iԗ׭e]DnP[ͷU뷪]Gڊ]B`v[֏݊l٪jwlWbR1jWڪ]MCvmZ )1"KP/LgH)wa0Q*wic[m8r7gzc܅FC*waI+*wO^WYVܭ&"r}EQPX5*w"jm[`:FP\[7vj VMe]OBU)T&͔  rzջu'b "\}ǘ1A$LMW,0r7އ^mvqk)o"Iɾkq݅Sb&G16n'`FԆ13+f3fOcݍݭ2f=B p۪0ENS [d= n ~]4TywT߇=%qA[1}D;tF`J]j_G3#ƌfhtyR SOS5nOp3wB I54(ôlM~ŞIĞiu-,!ef!3Gƨ)zZf`3FK\aoW)d j'`,ň9xfq>Ћp7G/<f$ S)GdxnIH D `,|^|ָׇ+xZ.@wQvmMnq,zBz)6E=ۋE;U"Gg]剑z^Գqe쉩=a YA=۷*Z%^%!g砞 ggJ[z WJ1וl^#HYPcF IISGVBHuW$o뢫@2a6g (׾.gCU2<\2}K%xH:b,ɻg~.1F?{`JzU (#*Ɛꦫ:w*&EWA*f|@ͼ*Pi;]F5µ SU\`U/R]8rUJ|U]cTW )*yU-*0%*8墫@ .xU qUܶO{I\WLݺ t1T躊14uRAW]ʼn%*bEW15TWzGU];)TKo;s;J +1)]X2DyaFTWJVfpI^=0z+$% `e~ה.B+0]#=B*Oan6"ѫ{-|5br1aI5cnrc 1~Svp S}#Jj`r)<rR|rzϩqk~;O9Uۘ>zO89GLa#S;2%z;fݔz/13Ot_;rOSK[?Ume3&\Q/ sqfR ];Q偋1ƒ.?$;ux 'x x7W;+^|~Aa> J'_f3N>^<܏[At?B_v$de$̼EFK\D/磥pG:1fl!Bdm{!25կcnUGHx}'TF/1US|*|B4\ԽGQ>B6AnQEpz 'UJ"\G,h`s?G`CޙTS#"<9e(`3Tu[nCr3F*'X. dߥÑb`y?;'Hvdau@?º9;2cn;2oϒ`;2O̎Kg؋+JWOXkֻEmE3vd^c֎C} 0Q_J% 1IԿ=aS"iG"nYd0cjztgO4=҉=ZGyqwl`h)ƴE%W1gڡy 1q ;GؼaE<L16vlc<qLXg(ch^;$`> tOI.Lw([s`cLWL16ܱysy j\  {78εc0/<a;ibeI0mr,)"AiISaqyHajS׬S5~Ą'ȽrwI=A|~@ `S߱RzZzy] =cr9{}Q lcs=w@eLjs\NLPX3+i |YspY#$&)Wf|]P% FHT1'| Vwy?깃HGòAi{6 fڞ;Rvh{` =w*k{ ;6ϝbh<1t11f fl?շٿf X.㖥,S&.0 31+cҐHs-cxhfm'\?bؘ=C2`JV3앸cIFRr?cr>Q>\fN-#krR{XiMXr2K)X.,bXn(k3sccX+o'< 0'"Ĕ.kI僺#fˈ&Y"{c443'&%`^$smsyj^c䮽27DR~9{맽&f&ƭ얊ヰ VnoU*DնC3FQT 雊pXȪsd1ͭ܄\浪C1f&F 5CRH>ysE;Ƙey%c]>s3-G@]uGݙ^ G=oIzt\Y^@ 2M5XT;b1 _'C*)+m(\.L"W]T5dc٭t./.jYmxHCD]l\>5mB.ĺ2EJzb'n wxO_6SzY6!W5S}ȫxmǣq R/1nZی5t/8$ض b.zxUW GkiY$Eu4E;/K+L:I.n[,U]]u)4c5E<ƶN`Uq+z}_ǣZ'F\Vu2c`)؊U-lMsO6aѭ}١ < zhR) @9,]w*u)/ϱ ݄P d)ֳs clI=pwUkA@Tyf䉡JR` aKl[[Il2hp(SնC껥ݑX\̜ IDѴT(PIf"MVcD4~9z~˧y~>O8K8N. />?[(oO@}Jߣ_[ {)"s;?tH*kў2H{AO 4ć^P9k/N]{w}ҏm.RPו~/=jN?_BJz9>7icGI1$dQe~L}_J?~Lr(If?&9}\?8Lw?I?&daCm3L?6\?ooxU|LﲊI]V1?*n$mr)(uN!.byO|H&>2)wyDI);Qwyćm;eRCx?|H)]!?n}w$d~G|L$[dySݻr3I7lc]>1.z1߽)>&wY$.eӻc~U$H7;߿W||W?'C]wHw!~;$O|P|W?'*4FG{ON|L]M|L]če$>jc&>jc&>jc&>j"0l]QFl|S9j'C]wHw!;$UQIת(C]wHwU I3W$Ǜč;$TQ|*|WE(CMw(wU!;$UQ|*|v ~9#MGA/^c$Mccv֬^`Յ:ӪH]1:sHZ]ïH]1 [1BA7Fy\0ꎑV:#RWR;cU&qW ~q5HU1@֔)X Y,PWLVw"uX82S钼0,ꎱV7ֺ?j|ncc.5Bƒ1qqZꎉQ1*'[1\h}cmi 㴼s7{3uSwVw̅ZߘQ|㴼s.#P8㴼#2 8x1ZsqU[o 㴼sI}qZꎹPB3bn8-ouD=Z;hVw̅<6p=@]1W_b':&ꊉ ^a':1:uDu<[lZtetꊹr%&Pc\2+PW̕C@q\bOtsG+/1ŎW0W^b6g:!#PW̕C@q\b"j眾OtIm@]1Ct+LDGZ遺axٴ(p{APԷqdhǍu6/ Ei1qDe Ӎci1qD,3=8Q#;F[=nt#q0EЈmy]Mꆰ6+mFR\>4\BA+R.Q'\`"I/(ѓPggzf=1 |o҇1򲏧Bf-k'2Pngar 1tcF..#`d;/!1Cf%-!u&]+P !$=??/ JԸm{ 9f' ,h%y80zT1l2<*G Yd~ȃp^:+O@Ɩ͎8| I,38~8&`Tǚ69LÞȔH!eN27nE@~,ٚ|SRc3]dk"LH5k6]sAAt, =F/G6e/b"n+C.p~`=,x&5 m0VEVPf*ΰl060:,)* # w%0K1\ј ,"1E@g2 $*L<6UO-c $oB -2Z['#ǰ : "\pȠ6ix=%)` kV#pWy뚓c#V8^>or)`̘ Sl9e*fE8;ށbۘtGbl>N8y0fq,-*:DV#[̥8!Ǚ9%'rSOMWM!;D %.QOcCEvt*U|tery\"0d !^^5eՇ@.-2tG.$pZdg5,Jv,2.h]z|7¨.f,ˍ^n'7d $+cp) TEx RʟKuH_;\,”DH(c-m\fNWahy 3a 2fWȆG4Yq`>Q-rC)`w*Kv>"jtr}~^ sdQqDP!5s$EI~133RHE0JQҟwベ4Am[PD٧T UUڝ`5;9&A:Js`سi>4_jy<?ѿ *>fǍejaw_Dw\nYT S% 3F.r"D:cƷs uj 4V` +#q%&)Ѿ Cd'Y&)l5co%"!e}r[PZO~,:D*ix>cʍ. O;`b,If0<♜|U 2A*,Jc@]]3ងCrtras NȇMxUim/1&{AMu6LeGhu70v#bNJޔWy^dP *#} Sb:T7"X>anb`׮"g 0Yy,rH%۹cFz٫nTN\\Spdma UF AqV"ČL%PN%PR0A*!u@=P֙N^RLijQ@[Ktݢ9Ǿ퉯d&&tdssNQfV&{W_*_I?YP;L^%!K9(e)3?'k>.16LyśbM^֒9 REЯ&U:\!S׋=6} h0 HĹtӣN\L:Rʒf`y1 v+̞ kuikG&hp})-,yoqRY3wܘRSmjk2TMg)Yt X; pUy׬d:Z ; X͕~#o)KG cb |+j^j+]. Mp+z W8a OLFwy"LܛBa}\W=r{^ =\3S Et~jrѢ]_RzC ~BH\~^5{iǭcY~D5q >EJ@k z^aOḦ́#U!iIzh Â,%)JBa\L%fTSp1p)=}P-;Tb8Q! <13˩E[NuI1z AaWRU i%BxR*`315":&ٯuVw {eZU۸E'xEUd jo[(SȞWA *r)UdNZҩ *,=GA("GeJ[PeU} ת[PE^}T[ gT]٬9~KS jSKc|x͝K(bkl*vwӫiir*|y7z'WqAٮT-9{1T xvT«XrbFL$%Udf7[HXնelQQT}}'(lRtۤ* `WbP`* L7Jnʣ(uLlF)^]xF0JE U oXk0TޫU p˭R3Sn¸ΗX0ףY R9 `4,x̺RV)}`T/Re3rJ bUSת[X09oѷh.lB*sTtfv&1b\ruVgIU@nL[&ŵ$q>I æ8IJ6)~iM p:ۤvTİ1)IzMmR3a &)1܃̬mQIz3IUnLRO,<<rTs ={J18 SSJPډ7~oV )ސmQxirNPLCsClcj'JG㳴Qy*d &0sAYIEٍZ@6tjR|sQWY+Fs/2`Yٴ_bc傹=pT̏7b u&8)Q*QaŹ~>/ЍNwg #m&0fBU ;)8$lpg*̸E%pXHcH0ۇ30#9`y Sஈ 5 `9I,(tV%a*Rq~E7#p[nM=P`_D1.'3u>?6y~| ?*.9aWij&čX|{CY7q pBz@q#3&.IE}s n .,o,&4U.]ݧ5峫c2pX55r O5UWdNd3.fʏP&;vO%uЋ.0fV[ 4 ݥmMQ%0fEӲ'J @S(#K^؋/n=f˩*00/|zL华bj{ΘWLSnUY-b.X[ALVMüC*~곫O~[=bV?aOVOVkIV˭~eqL[=­~ V~p+Aԣ[쬗zVoգ} z!]nC(.stՃ o0o˭#~+z`F՟p]Vs\ns#(o[=\npu?[nXn+;VFfI!h=WSS0ǸF[0[ yyE<0sn<֗c#Y>< }+=ac\Źs(`s Vks !Uy N^`HgU wLTv"y`"cT ƨGU(]0nǡƀ*T0KX[0CDނ&ᖑ |E0F̧1ొ Fl\hvC0-[.~B<.9aWbbêTsRQkjg" -RWݸ95fTSՙ0-b."Ǿbv>E\'f_ UVgo D,ȲaP#]U"5E$RuMmX|_."G beWkRr(kȜ|\L3|fg 1d L;剬BNRѻIgp#S%c~UcB*Y`?}O=cY>"S3KYK'[_KwɖN|}\4I-\8^!ب6e!"8A1|z^/!؂6hX1>al84+IWB7+@1kIZ+:pbć |x3%^50pY= 8rOH)W|G W-B"I nѨwf>ɾt$kWyz^C|9^jĥiwlnݥ{c|^f @]:1R,(ۥ܆y(vDK'0"Z)vd]:Q\v&fnNBۥGt&҉]:1K'G]K'`vv$|D΍[5)+\ۥۥ K'*HX.=^SsvDR..gwj`V.xۥyr"f.=s!\dKTmYG-O,IÞh_Vzk-s} fYZ} )pVGkdqyf pr'h]SKl Z=c4_&=ܑs<۱P?$@BDdkTuv0 ~u<S`nMs5'1yUfx:w>JwL|{S3fBF;Ȩ3 0]y<79%I6WgH$:@:}`*pMa\ чd S`Öua0KUX?(1TM~%OLɥ O0 YB]`+9qNAXar%`i^)`jif'v'zJRH0WB&Y)/IFڳN^ҹ؃LUKfkUVH^~NWtgd~F=֬^c s`Dp [M9{Wfvr]FO8΃g;Si}fajdPS<3hPLEadU͒{ F’9t 2G0( 󺌂=vm8ov`g]AtO[]ֻx]b 8A g;dI=kImKz9${wYLK6f82kx1{Ud&z &ҚǴ4tA0 *$Umf!r ^Lp#;( $|X,΅W4N,ɇ\<(ÐgBf"EUH';b4ii@Ie l"{וNkdksJ.Nq/ Y/0>lt\{c9p x&f<x1;*jX:Ep:σǮȞT> x<z<xcN$l}dN|/3pyϘ#Bmw4zF3Z|{ <&%[?5|Ce,Sg,\?l}NAF=]z(|akNM+Wax':vIp=a46=S Ju-,kCLG,V*}WIWdՠƘY`8"/pP<iQˬuq ΋~ c'd'n7W` n)%p`K'&;"ΌѸciY_OpYWf$ K?kdɕƒ9;;Ȕx٨'՘"306%Tv/{dfH$Ja4zhRDneʭʉ+~uH6Gz! C/09ja#DNyJҖޘ"&͑~CFPGn.Cg.MEX<^1{/0qdEl-okc{0'i#顀.u Y<6IWu.Lwxf A drĉcbɋ:h~>K,];dOFXQ*@NO@Є$(. &/YA䢴4S,YȞ:v!=$h>_.ӼdMoh}a4{͂Ym{eJx+۔pC:F캤MY=奤3 `VQ[tS/lAQ2]Q8$`{/']+`~L( }'[5#i?+ItO/0qvcbtG8RZTf/21E_*L~]Gߏ-Eb$(XbceXq)ؗŭt?Z?Z53b@RѺ0v۲4su z6v<ю+Cw/GNA 7@x'@ >N}D7TjLKka QOx`n^8Oum +ar&'D *n 2_%#-zͱW= tOQhY܃9I[ kvj-`Znfl~;*$E:0A8@ٲ'`WqpnR$RzFt7zr- AC]HCZ,5!w7o _NlQ?*t UvѰ]1 {vw)]?;mQt` DD&r5 ?`BMO71+OD2~˝6{Dğ?I8^Ky*?jME :KEܡ]Ѽ]MsWKy)"NOD@H;L'C`CP+ ^ #̣pTL˞G0GwlPD5'%ƅwWYD a>6 D\#7ܮ:hʃ,P@lجN$jC$;M1O|GSGXdHڽl̋7TXqUU!KE"µCQG^@/yvV =O*'9jxb0m` _1n[@:y$\ޑ̡0ۡuLt}T=e~ 9%1b"7#HG(pO3?pw7"Bcope µc.6ϋ0d̾qTEf E<q1"n#'3PX"n#y 6CM"n'(:u. {'T\N4pq4G>څ=Z]C`@*R4K?3oR4!R`.EpN6P ]0z;գhE'㰋C]"գh {Ec2{|ۣh\( ZmQd^G:ѣhL*CEEwft(B܎ ӣaO*zУCܣsQӋ =&aC"P|oRޣ43ml,71?Cщ(m"nR`u* ݥYoW+B1_Z~EcR"֪ѯ[}W0z5c,ѱѷc`ukQչ(`d׀BEܻ9*D[k۽hL7 d8J&؇c{a+Ez$`,ww'g xԖ!hTT9ATNAD %~@MQ/yW/ ! k,۽C KNw:Qw"KfٺE0L M%h,H_QYRC|=i!ז2mG.ͣH*=%E Y@炾;^`?NA3}Pj |K]D癰)tuh-މFmc( yW왲NTZmk5M=cOԍᾭeY]T7T0kc0Gϰ {H:VMjmB{ ڄ'nwD\i _;&Z}<܁hIB$*QQ'jچNe+Tlj\r(}kE1wîW`$7S˔-JQ\T0/(ElRTʯ,WrT$Jg#`kĘRA3/(թysRhEYÔu+6qEHm~y$c2ir4EAfmϔiE9'2+Ao ~֋=IAg4qf9Yx|\y`ɣAV*1BSu=c,1[cr*7S .oO1[c. 卥Jqqyk+67bF2lD7c7+5.o,\ƪ7`.oG\_\6F\H 7vyd7.-K\}S|D\ެ59E5v8UuS.o\495& oϣϤ#`H\#5I#`ofV7 4:[TKx1CE6Ph!DHY6pH\TBE rvtF6\6ܱRPJ>N찴LA@֦0)UwLFz'r&X;-p]lYޓYU?v2Vy>=<^rب^wBaй. O wNuP _ۀVPꗉͳ^`&:ʈTI-e6f/Cir`r, <1ɘ vXed,DŽ8nsX i}eF7DF\*:nFF9@Bk$'1&!Ճ;b,͜G }F@*!e},ըIM]Hd: tMy@^UjÄ9Ř<&Bsg=7x`I!Ɇ~-6ww\d| JmEbˉ'ΘK^2U[맽&0t uFo๨ DOrcpDIL6Vy?!5I/M25mUzXZs߃r}%% HNjZbp{=8YIs{.:j0r+k+aZ7FvC1|m= uW%q uR. Ug2սNj,C[`LԒu-s)0lEnpGBpnmn}5)x'Dku֤ؤX1@}B#>L~! x9kC„GzD|x,ke'L(`= 0PƗ~~1Dr@=AE= pNZaw#LEnA3No)[ne|̛WcAr'VFNϢ-/b"rXY)F_t{Ⱥ`)(weM5:{2JG069S%ɶy<9\xT+FO Dl!7\2&51Rӹ O cyN2\mzwϬdI><|8B%FVe"bNj&T͐ Sy*Fg0 +Q,uCJQ -t3?cQG O, s n^0g˙T ^+rUƖ͍zUڣ׏k=~};"#n9(xcjDp}H zzG^mEjbZ!ZvBz¬+jZvnZEPj=NrsY}kk=0q+Em?|WĵXcl\rЭZ?ִpAA3O;=Zʎjs$G[==%||^O"}>m Pos=~H?ϗ4ںCiN?k7!~~D/?%s&6?|¿Ohlwq"7}V&ދoƿ[ 'e&F5o@'I2:\hH]^M?=nK ֺ6xREI-zmXo=oC/qh닝3%'6-N!)D>ڻ y d%ȇ3f% 6+ZﳒW3l+VgQcB!?ڣVaozT` tʛzc3ڻˉIn}w('QooٍӤÌ3*'v83 3E qDAT&g1̠k6X؛r3_Lou:"uuFc. qA WFu$zY8!<.NLluH $u<.ILluH uE+q,bb;D=#Hρake'>7L $c#cH&|s㴼s}c|Õwzꊉ+LD'iPɷ hǍuds~}HV']#^̑ m7*O+Ka]%c.2{thǍ22tni1qD1s]@cM뎱V+u #";F[=ntC+NƞXo! \GAϡI,RrfX>k=O Eɀ >E!>00oM6&jlicy/?2=C 4O/`}WEAaFBzl5hMK#g ֽ4JUk8z"D ΉE_4Nҙu"E:Y]~|*3Km_0d]$祊k_XeN"/Y벺NeBi9O xށ_g))}^yLS1S\iW1x'w0ރCgѪc$V7-bPs85ӎggY?vDu&܃z%nPŠl̄æ2E'6N l;l{SH/D9Ya#zz􈞝^ሞrj%ѳ L`Jl~j/pDg¹--PҎhd} r?>$7Gr~/Ӫ6lR>/'ç1c7 DR .6+Ψ6]|e]!BR1~1~6#\*xNGngVle?[}D-}Oδ֯\ E81 E]W3Wnq)x#M (T__;;ɸ_Đ̅1$m;ſeG|py\0N !m$Q )V#J&&|HZ1 FF7(i0اu%9rrS|'04i/#TUƿ&)Qg^oFxՕ7 q_5ߚ;뵆ޛcϋzl>vj>ji߯6 bBW/ՈmAXya0Bmjdpޤn3lثVߘo S5<כ sw7z{LCck.UQ'Zv1ª~7ZvmoqcX{>&[}qW}!-F1j|ǫsgo7}c=ogј:>7V|vD׻1OHZy]k1M~lܭ09:=D5柑,ӽ8f2 j9o UͅAJT쨘BŞf6ˋ:$fSf, ) ~`uO,ÌN,eNʹʇa-H/]|A~>ÒSwAdѨ9ht>ᔴ>BLX''g=$K'0hW4&LOdHW'0yFefBb[nKiEvL1M[BjhWD0/n%u=0RſVߘBݔahESL)ӐX0+BhjE0̪>;3_$ܒղ̙ $_w 3X``LXRg2դ-MopWb (A'̄,VgelZd/"lub V`_>N~"r\-ؚE l݀R`Qy cVJ\yF0J1 =GeV?(u1pE+KV?W9p,Wzg0;nRKTyƔhF3W>Ku[HXvF bm:kfԸ ϯ3'ft::5r*FYۆejI~̌~/voxv)`%+l>:Z؆5n왋o\HQi Hq\+3+!M3Nr3̬8!tL1>q̠y 4ϻkqowj۶/j1 RiAZPdQ O740Za v7#j$)M8bV177 }|.>w-302^"pۖco]qIk_q38Oh[b(CzР0OɔӀkъ@:^̻M32 pܡNItZ*N"`ȅy`6,g`IU5 7yLW#C>ϴ:^4m-dua|AL/LL]C(LxL[E3gm;FfXN:&}g/Vf)ٞ1_t/X=;3~#z aP_ s<\Ϸ;G#{=r+}|q/VGD#stFw6|v0Gv: jgS_ᨗ+iyj0,DT?wa|hmG**7FFqK0"〧0E2ofM0"ee# ; bwcF^(@6 C΄3A_$^MC7v$%Ƒ/vMXogE9rmg/*k27<Ԯ'TQ3Nvt$sEwڷK vںXM*>_8 NF;>:Jgk+ 7>ͣEac>Un{u ܪȇ`~#3a.}TZKb l%QhƬ!$_T=-*I-B1^40G1m("7YjpSWMLJ3fzRIn31>ni3s)Q>_Wm(ExJ,P2- (բd|UJ߰(Go^O<> tƅ-G!M>jz0Ӥ-Wx@4w*(t0q'0A_PDoLL4ռ]M@ǰYԖD. T--$z+toUgl hOؔXY3}}i pʗa5쇸aoY3=" 4\Ue3]G/_s]k $iHpIF>>~@.q_(!(x/`Es0>uNq&JG/ƥ} q$ɜxfd-B% H!)}3K6H?(Eʓ窄2B+p,UXbM:jI 6urCVJφ?zHn0K.|py UvfE_'UxςA ĨK y04M"12zrrHHd!Cܫx`Oqڛkfg0L~1 =8(@PE ຸE(e~>WUbD$Xy  . m'gC`X'ϟ .ubEc*w\X8ZN)`rkE@Rv9`'cPܷ ט4Gxz.hI 飼 ECy +9{%F?+](TQ&|+WZ"F4;7ivP2K"`@qo۾?68#Y9ڠTahx@ I he0p`7#zS*豼nSv|*[nzvsoJe,ko.|-[NZi-?:N벻L<@%5W~uvU'&XX(;WB ū.3~&nj'], :(Mgnsx+Rzxb=%nnၰ ŘFX-K5ǹTFq=+*e(!x$fg$dSTgU*{s7We+Z1cDfpOo'G7 i {*lExpoQ(0u/LDᏻ#PjȃQM^@,X3eJM  'lO *Y2(,=Tۼ~3/BEעYrt706&ZYb+oAb"h;7dMfb>CGEO#$˹f;[F+@GC:E]*ę'ȼn[#XF =P 8L v6Fac~b@]A %3ll օ%H*ؖ t ~`$f grk'OƙC>@E r;d__gG "/v%).@Dpx76ySMz;l'3x<#2&Ӝńza32gjP+Cf fX*&О*O 1TD.(Z} ݁(ݦht,jsR܋Ҧu8%5ӡc^,h/V6IO{&_/JZ !fgFT sf+ A6,D"tm,Qԏ[m8b}-t|gSuiXqd4aRR? hEg>:T %uYtʐ혵gneqqN|ö}N(qKt+F\z٦.0W8l n̸8uD^JvYLc]x)Y"dv*b+ӓ߉1YlquCmWRW2WN2gBlyT.`{m"\_( s:YsJ'͓ ,%Z(짴npr)IfJ /4'd>)h%p͉}n|Jt0^JUc2N.aS Ceb4op0] r&J$\گ.d_~&]쮼@oCrJRd\xAOacxFƛ'+t:{A"7.lxu$B*fI' [/OA*r9ܥx# |>宄ヷ\X4o`=/v.h= ؔE. -)S| @VQy@rK O Ca"BP v7=̀}KĤ;zF3,]ᛳ[&h"{?I^Kc$aPQlqcp>xkLgNjs2dqwݜPoP 9 p4/X$6E6\a>),J2`A/o|BrqLuf}-'4B#ƃKpWnmWW T1ژ)fb5J'UBvr [Xl-`'OͳQ5Ⱥm@>f-5\ɆLO俁O/!l{.Lgsĺn G5M*mΛsdLϴ^6/Xt!DtM1بAtX5(Pp*.vdj3;33+L}q,NnK 3\At|\s}s] rtƴE @ϮiVf\'irL%|s>kIF9/=]1  T4fˆ. !^kB`JY/)TYъQ>ț v _ab.WL$j^rE!VթƷGSזa=lAs=OU?P:ϱ٢a~ NxP} DŽQ9fUAa2@vf`33yw.'-Z[C2 Q=v .=pIf3/ :LlN:c^3qdYD%h/?]= >L:XaQ? D=/, J> ] f9Y/m&<,ǐYr2ɰZ) ܙ?\[Y 6Oc I9!3_YҊycMxN5s, ߟGZ`S0E/[`J$zӼ|S W,{(If!?j$%MMier9οh~)I$B>6`_sCIA[ کv qzRy!Sc $itW5.+ff?sSo&ZP| 5X [0`^}5%w}LonxTaGߴjpà$G|:ϻ\^~q7-c]F`8/Cp˴qq"xޏG_yD87p0oynQ# |-:I^Zyfĵ&1RA^4gPlëܥV8O=u;וaI>LI=BM VWv/6vEߞWr֐ n:NA-w)!^GDZ8&_FDC,191Μl#Ny"Ж\j@$S iryq{Q]ɩ=oZ!Mv'3`s1 Q'K{ e+'oU7m\#2sxS ~wxoc>~akN;|tg!䈩fi]xĔfeǪ.$\'` A Df6X@F8ϕPӴWGdOe1h%SՙlM=Q2!.C:"Xsr[AWǴ#}/J~*66ʒƹ#m):;hk-]Sd%WB]Myxꐷj޳I㯷8gLKZ)BBd|akg`թ1b VÔ^*%?y˨Z]H>zR6Sǧ!c&RPMy @[nIFBNX #./Vjvt ʤ$sܶO{S -bpNj0rgvF,5R92:7Ԛ4'vlcx+_{/vq ИN>. yhusL3+MwB Di.;*;MK:_V%\cWWKU h&]Cqxg&; [~S֭lfJzp [3AUW{Pt3$ h &ɽ"Zb):wYƔ(X/D*`IY3g 4]x = q}&mr{#p,Ģ}o߾hJy"/*‡ "]:V2ߜa%",Lz;DplT ~l,R%2w 3(-z`}(=FґRNx1Vq&\RӦ墕JXîZ4[7`)yJ/)QrmH2f[X,|; % Z9m+_X&)Ř}>qœvu8x?KݪB*\{W:^Ip*% M*ߝY+e!IO1]k$q/zf%69j;hmʝA 5jI7T @Xу'f_4y XQPZ(@,T(r= P?v.9a˜ f!^D$)))pI~)cb_@kYAYH .RU(ʖĹ{1VVk^8 !s#] e׺bwv8{ •~<)9TǏwP+\˻r>`,4iNSvQXjqsY\+b~D &W2z9osTYqz~)1дm oSeٚPG*HlԷ)h `4P[B>׷-Z8WA>dUJ31WjUF^f9ayoq!|OI{U"=GVlmۇ Jv Ze[It=X |5>q g@6x/hq{KKYxסT$'MhѰSz>+բњ/G`Tik̹9uWTycjh]UoWmXtܞGm>TO;լcN7=Tc6Q;KL`Αxi@hn5Y%%;5a; a& !=~ )`dEɤ*;d1?} nAE\zRPhrdw { Bb(ЬN Rݗ,^! `ʹ#Ro;LYpgɽdaaBSH*>op:7"2aYu)>Bt0D˾50PzK X0k8EG0 e if|µKǶw6ƴJkѶYyuVEtf~tL Wǟy3Bhqy- ]h*|7m#rJ0;{So3g*!`M~Wgy͠=[}BO-5aɛCi^B!L~kw qbEf~&p[ޱo4r$KAȃT\S(5p l2O%}e) P8ڼ +ɿބۋM3$V8B$7UF\M_7͞-M:gPVMjSUKmڕ@զJA׮~jӾW +u}PmMiJj(t޴/1)8i_ MRӛ47V7NЛ:" 6Im/Xwl4)8Uf 2dk<wxXG ^ ^q-&tf0f0̿m3̬籗92305 0{9,+|$Ytۡ{ a] ߿,tu -\C|ivr -[XhZ0,,lBfjڭ,nKdžYh󺎅#)ʞc)^L,~l5żiYʄ9Mm) *)]Q堭{fJ,+4Xyn42 nHx.ӠZg7 iOۍ{(._n,maDS(#H*1ohHe6JcLaY&2SDoњ9[ӲEDǝhC.{wG~|ufs5avǝjí5m; iQ-?QX.?јRx!`5L Nd]&ݍ+P,^wȻyTkR+!VV4݆xE #)P2fC[';_n4|,M>qYdN\ طTyK! bjb v!.RG2y@51)eoUlr;$6'ky% k>ݴ{V-)hz&eI8v]8 #bsF~6wU2DmgsΧ\(]Pln1͍B>lnxX gI5u.꛻(lnd.Jܛ~O'^Fڡton][r.gޛ~mnc/JC߈sn7ٗ^ZX<γܑiqʾ/)Y3D/X3 !lKn>Zd'{V=mVqVM1Zzj-M:66>ͽ&2T} P0TjPUkW UYHZ,( U@ ݟj*&CP%Dzoߗ _; U)uPžK*0lٗ:s07TP00Tᅣ\ʂIaB[礄u9-qaLPDq< =PEPŮPX0! UsC`s`"sb kQjCU2T- U U\ Bs>/sVC:PR~ UZyA-rgWg.gY*nv Uye"XP{/ ےQ0TIPE}Ok6;6{kz`Zzzh9ue #*bŦ@db)]Eecb|?w\(wD"*껧4UNu9"(Jt&:8&_OAdy.ck{]ڔ/>+ @= \0d!l:"H>=_DLE">ݓ]k(|CkmLVʯ/>@Ac0h.ӿZ1@sV뗅-ha|T F@l O6+RH?K/wu|[~gBBݏq#~) u 73uIRi}:ϋW)13fH@ ^}sJy\ oWHދ+ٷCϾK?Y.)טpWzU*XЎp`V77?J%ɯgHmA`fe´hEe/SpFpi%JX 3[b`#huͱ8w|!Eb`aWuZS>16,@GBށ_G/of,o:>"8,j ywDwRrBY`(ꑗ$N,}}MZ$qe$m=$$C$ֺ_(IOU<4ʀAI%byuc\FN:SfiyIAĝ,!IE|$=H,1BPi!>1Se4JE9II(V)Qw̭t߈W!ei&kQ5%J/Hs> aeiV#!Kcծ} (h>&J[-Ax]|&YYcDc/3?&\z484 i4W0^|ynz( 2KűۜtW\Q Ei,}Vӧ$],Q:YI4([cMyM<&[]Jo{*K}m^C 5|]*D_]X5;cw#i ,Q^3Q'v$^3ҸT&7.ʌ..@]U0Js@B]V,YOhJD/G/ =z %S\R*zqmq^GÀ#K=&ȄV"VIIC\HL4(ݞYZ}« TR @O7 X b[5sU JFƒ'^4U֑{OϥsMCY4 NF&`a PC_[uũg)*}zbxXcNdacqX6+鏻Ve(-nrڻL4:&{ qV*󮸣$VTJ?8XSp1u { 33-8^x$~M-ҽ[{2,-WYULEnOwEh,4*rEwgaTOJv54+AMS ::YK|sy/iM:9Բ ۆS4x@q]9|0W 3ۋ݌u}37C{؉?G"urv+_O}sۃ2uFw0|A i.w}+lWegH)-[n%JQYE|ʵ|^m "44zfc-rI<T F'|n~`LHS4NKoOԲlե өl >__ jo3F >3Y,fh+Mm=CpYgP̫*8rDPI̦3TT?g=C2 5C v}f}BG m Bk6C"ݙ!gB} fyyTf~"^DtK'2{>%VϫQ&WȌZD٥*c BY _}OCD~'j&N7$qVՅ>y4UM[FF&vgt@ tSlÖ\qr2NSбqnpLB 'la)9cI&̊dh?sEz$|+Ĵti?))WyN>yپNs |y#qPL`Y.7m?U_T : sq3gTdr$dZb 4s"|QmE45"¦է(9CA/ݾl]B[4_b .o@y% p*&E 7{~ VB͖^M2fIUwh N;}ST/iGs;-X%A/),5F1 Pk|m Dĵѯ1ug]׷ekL65:nukrhMZ/MWx-fbd N,xE bsCdK_l~GHELՀh*{We ġUWF/ġ5BL^Bx~fv1z!N_vH#35ԧv{|v='CԐkr[ky>ܷugj\6+Eu#&ʬVh:\}:H|n5DP Uq(nMg*_ޢ^=G@O-Y 7@FQmsY58y ݽ.xy Ϟ@yz<]/qK qޢro-]gMvz㮤q8YSZՄ9o{獦&Ϳz6=ҮE9)hOPCуdQ ۦ3gNrmboOqubΜSڝR'ҝg:[(v)ٺBof n LB!^.*#oJѻe٤0?>"2xة{0XϷKݫD8S`ñI{B lP`1O"= #rxSS`( l>9>X'=CtR&Qb*tfzndavCcXnZq `ȸXs^}vq>Og͇v5nʱ:q \5u PPz>:]w\.$: aEvMuۭNQ)K O=N+w|u!ͣO#B vzk;qLy}b̎]dǞco)oV?tr:n}`ڇطj3'Mq;gmFJ ~J&TLMLhpv>װrBcꀬ)7TpQx>*Ï"M̰ H߽488soR7L^21v6JI:P‡V1m!젢=K2 [a3t=R2j IUZ:s߹+mTWKxKaZ{YTM[ZC^ԙc@,S7+K|\@s"4 f9,2]IeEw-ME&rUd:qj:7.Zd ,]cS_w%FW-kt[X#8inh~:SȤ)ubJtL-"Nfsm~>}3J6~xɚԛ|!B'? 0OrmW,s/h6Cܟ7rBܟ q~n˲@YN$O)q6@ry0M&;␫^>__7il.)Ϲl8J@(`Ml! fZVe":R#Ji LGFwJ h[0#.0-(AtnU|[VwQ t囁3 tK,aCE98}9$_9YkiEL݂1zGP85~%eK*"UVESK㋐C2FgĢ58#v`G8GFz8#8\R Z˺Xw ΢^/DF@(܄ZF˲Qo.:HO}Inxӹܘ#Pìsl/ wM6\7c5wD5@~iB;Zk! kP,Ux#XpzsEl) qGAMR 7¾.8wG( <.f)ф8b?7Y?Z݇frwCΧ_]mć{v5P( cVax7yAvI@mv6)ђm<_mnm1kd.7ײ($ i}Od^+`kvBgq@|xlQ0آa(ښ֟k9ޭc;+lwV t~;if9mݔ*,y!@/T^]bk_C.r3.5 mYlLY0'L;{NhlYd"ff˖-l;h9٢[5$L<,&gz{|'u/D_ Q)tڟ&[Pk&VX0➚NUw3@VVOVPDk`ѡt[y^T-8D~F="?#M٘'"?_d+F?#"< U*nF@tOacYi]@Đ:_W+ArS=|dd7 >)lk~-=DIځEV/z1PIc&ϯ3"B=3bX ؓQgnFëR4[of+R#.>y6E@|ٛV@z9@e+"dZӓl摭(+\";ȆkGO==$^, H+#^3c TWGG։{hyW@X$TX8VP%@IBVG9Nc&45B_TnF@qpxÃ8M1Yunyܧ-bSŎpJ꼜*@¬,@7O Nese+IznIѱn7 ?׎U@cn;n)nįoa EUMdn>Y:'WC/h)P`7gN8H=AB!; *W."38aϸ5C$D˜IЪ F!Tm=9qrAWTs tX*plH0FvK\s(L(PF#(v:sJ5.|@ֶ/9할к{芿+ƿY4 n?_ZcB :ï+AMŲsA㭳ۍr>TF ƌNMp% k-ˍ)e:AAh7>l]-ke&Uc>]PTo#ao.4L GEqsuqDSR,8.'ittl=Ygꐲh,禅3hBmP"'>fNy RTmpp'屽`cϷ}]ogeg߈h`t'(qA9[wg~MqV)R &SÜlU>l'SGnMRWMq ?fNªd / E1>i"W/~C}?<ܛˎ1ve,Oi;$-1[?sr^ReDt{_fFVU9f ; @f\u;JHQ`Q(-4Y1; SUvR bh'; b;v b ;QvN}nG"pAφ=c=Ʉ3e&]IpS!v (eQ\fMs`vW|eGpnGJ>it?%7G[_nIZ,)(n&}o"^ޥƌKK 1cHč}?7k$Pe<0[q KNܠuiuܭ{CJl_c( |SD0즒RHB+mgfٱ۬W۬7ELkPHi6h-"Br܅/χEBeQ #B!gPI׹K%ջ+/d]#ջ7F ^DƢHvM͜ae҅Fq!޸?r<@y=W=0G.n)<u uxW[0*c#?X QrRMB{[`Q `5˩tT@XtO 'P K Crkpן (|z O.;x(@ 4qn2zN^ߝNsˣÅ x'om͎\}[W]6 lOsCt Df. ;LJSfy L }XZ+#zFRz()9)@X0{3%/%Δp˳JfC V^1&L ?XJՉ'XȬL".b6E*?5x6?d&BA&',@Xcxvb(V:fNTϗ:1@co1pS) JJ /J:fX5#~i13cXdZ"vת#ӌB@WzfI0K_+[ɼ]=diES']ϭv5NnDgۉ1]Όn3oglzflXw陱,g&"h,uW9D +IDʮmxċ܃pˎ\" y Q & ^keh-xY/ hˎ%b/ P̢_,V,5K f}]bf\bfGS@0@JwfP@e,/fVf=3) SYԏv`Rs0ҼٯI"YNMfL`b`f?+c3;C45Ewf@bf?bUombR>kp @U$e R>~@/=kX&/jI.a$5ϧ H$Tl3]AF%ًq6}zx/DX$@t|~sܭs#BER%1lk*o.CAWb~L 4|㔰 nϞzuFp؀ΕY2aiKW@u`;]tPiۯ M`Qg,8j(+} ^V%j^bY:$ *uRJ4%b!}wɰp%Y٤So ADhƽĭMA *1Vak,˰I-vDv}/8Qs,aLZ@Bj^m9 Zv~n)+%5:v :&OP ЯZ*=9%Pw7fsN##V\mz':`ȕЊ]id5k?ܴM.5cEqqM]KkBAUcCvDTʴq[`y hVSIHGS^;B<_)쏐 #d@ԣDedI~Nj jeXyVcƯgczPk'e1uQVO^Lʍ#ap5GPM=lZ9Qv" FgW T5`-슰p9u .D4{w9"miQ,ޏբf% :OF[˹+n,pZw5,x<}!($ˢ>,n"ǷJԟ`y^Al^1ڄMcVݛuqDǛ|!?WP9IT*N[a(jDqUEŦ)<_nU;mŰ]g1.)s+6/ܿk/Vϫ˜yo"ntUooT75gxg ZD9-LL]~Z@$D0N5?6bzKNU'tB~8姗u yPKkT+c]·{i*xiK+ggor:6}G<0]u}/zT58GK2I }T^]->t}/Gs—o(|T_J7N{2;;Do0N·EbS#^?BթH6C˪R ,I=lht=T_ẓLŊRhhi|w.rAѡjr]^:PY;Z^5T<̻dDnVSIW^ΰ nP S" UJuw&Ա2+de%txB=. 6A6^umxDE'uHɘ p@Ô~!gMi݈r=$e ֹVE< kJY=XH1b:W Cijijz] KS#p EUܢ }45F`ˑ`slcJSDf0$$԰wL F6zxF1_ij<]YiH=""M ?NmGeGt)4/WKtHSHSr!-R˕fh2JS/Ogz(I}(=&9Լ]]UUyU,bS۲ti0ynR_ z8c4)sDlyiGHW-ӭ\WGtL";n:{t+c!JSDPgQo* Ls* Zv*lV4*|6`KY˛vdgg62(06da^!#x_aCF2cmKڐeC 3/2aAEiUMu0Q7e_&d&d mv 8Z۫WvFl $}V1"c3FdL UfBlfBvo].4!c^&2nBfu Mv,9vf/A5.|uQLȘ2„J=;ݕpzphorp/ga͡XX]w~TV9r[.|q8YXie͂M ];5I]1LKi׌ŝ;V,.#r"A1Y\D1p=f ΢9%sY%Pp[rMBc?3-e 7ktLN/#Dnn[zroKn󹕪YnB)JB&_h"{q9 @먀 d'ܗ/Qx 4b\f~:p˲Lٝ05~#5Yz:3S-cx@*%Ae1AooiLQ~e5b:|x5e!YYBrC\+PYû99WdY.߰ ayq]J~^-ʍl ?7#6=Lq3qXV:)TwwV@$CTݕ?:G_V,Cd@m=>۶BEzomXtȇ|>6]]~}ʀmnۖi:0)9"mdw.Ú|!¯9¯o[Ms@;4VC-ɱ"Lc {y \?+}>w@s{_vnb8!ӕJDȧU@"-Bֶ4L~ZoY}AȠNT^ 1=l1ݳ~ו,aw)c;ύIA9}=誾];geK%K!^b*kx&Tyy T7|i6.L}]NLHkyCfb*=Alˋ8Z3wK]zZ+q$ߑYˍh9H r4< C%1޺1uu!ިa$BY.+rC߾SEF#8xߴ|F;Wv/䜽#߫s5D4~&3^$+k}5DޅP18vP`zԚH2Z"M"@fm3/lϙ]6}/zԹq!p\c汪S)S+3-g^͟Ƚs^dӷăͣ̚=&DDDGDT)gB^TvD&UDp&68. |r&@VPL@X")c;2s,+24]\ pI.d3} ^qVdo3ѻ3 +$rv;zFR1y+NϋĉǛ TjXýRo6y3y801AORDR҄$Kնg9WOk0<@PyJ VtRʡBoT$84*ቚx( +!^G:#)"(qۼy?7 ww7)<ztTSYd X.ڭɣ)T=\RnPnADx3RFg]U.,D"*ϥ1ff?󫮽ͿWTx48߫MII= SB ;>mq͖r8!S e|xumX L-^I`q-6q".H #@f=߶U7dGayQbgKxAwSlD:)t@m|'N'"S'awN v0Shq#4=~_e{^MIcPSR!$tR&ℙI)WG _zd, Oup-JC-.Z\h{zcqSYUKzRw(븈B .".EB͆xfߊN6K43eϺg{[I.C.pCS-ׁz_8E)l%h\QJzlq6ϯ%eԿ@tC*@T*:Oꅀ .ʗIQ*0/#I)WPtm(U)۶WȖdK jѫk?ѫP*Z'i_ Ê^¢,L v[5wpV@S߂9O*I#nMѫBl_Y"km{ ܎ og+lDcWYЂ/"km;sk0[l̨1-Alj?okT Xer2w{n%2p"aEtMfu7g6E4o(={a'6&78dF e5DŽwWe1/,Z/vg'jջcqޖ:o_9 I!/m`DτJaa2bLk +7>lw#Pls=E0O3,EdkxxiWCƻ,\IyWwiߛ{)u0KWb'Ee"s\ƻ|$GGM'=Fv2#@ }uEo2Dp $%&]#&Q,\vâ6$K!w RĻ홈wu>w j!̛^Jf^f^ \Q|F66EkˣdC}I&T[I{CƻMVJԵܻrVkyB7UI\8sT`Cٜ[CPn/CA5(N仾uM,ow/h] dE! Eޕ C-Ǿ\IxAy)ٹy1MSK ܁, oW w[ڢ.'z_5SH\W7 Rʧ+ {|Lq~qUN:dnHAn-4bm9rb dݠ&HLbDZ4rxՃ7صNp264 W5XnU_=I }bV~8q  ʪHnMM{duckjjhRW?/4h ghGtfT~g)QvHuGۘ#g}7r`sܘXN2lXx ?b89 3@r"/3e`mSk@hnDʢ7OA/ }pI5C [3'Pya6=)P-/(s"a1Ӱ 8E6 i.+7a7l1Z$;?bv:^w w# JDяyEK,3;`Ty"!WY/\fU%96>o49-ȲU{[D#7d@6;1*8(NQP|6GiQ\Skko OC4EC|]2/" pkЌdpecu5KO6B ^JX Cq$C!3s0!6%X[1o?Fq2u D*QE83~M+ܬNeC4ID|"@T>@D♝:8uN_ B uXoX~,G|Ft@b'Ra"Aqp,v!0C 6;9@< wb`zpHqO9D}a;èV2w5--c&Eij-1e䊨N+B3-m:W )qsE=3"/_Dim|o#E[v!<۲rhK\#2VJq" \M{%W=E1-B^gEi3"/b̜|і#(&1.#W>_1ڕ Y A Kc]2FH/bSnt1j]9i(2e# U3M ָ ZO>Mye&1-J+NxRWD*SS 8o 5bĞi:c_EZwU`Lqa| .c4\V*Jk~R횿h]]{}cWSג82Gj {_ 46ʉkR*=a'hyNF2SL&4),]/[*^]nTٮ'npё˺D@Ptj<^r%ƺX/N>5Y"}$xblHPH{ A\򅤢dA-ʵ|""@}1VW_:p1[& G .=GT<*W";8B'^bV"c@RKsu/VZ=/X0 W-:~C|ʋNr8:r9U]G|),CibYLlD3̯T&7ėo**Ww:;8nx33' f~(0kq n9%m8a<.A;aH(9$q9$ GX#P4C80YSrp׌0oOA{Do< [:B)s_X鴥Mxa!IW ōI/, Bgͤ'Vdo@#zu4],?5w ]?eo,EÞxdW@DW33+HϬ@q@=^]{3MRy%N!R=*Hg>soWkTΥuQx3 c#[zJZavt:@ |3~NB1y^5º6ʻ>H2.<~[i'L8PAfs{)NBL0=p4C=љ SMwkfAޠTe6h񎞔iL`.2iQ{ME/. $qe0t&K_JY'.+;|/:2)) @Qmmՙ1;=EFU /H3aQNZ"#a39s4kdcf^#1ةSt4#`0\AE/ sw0&?%=, ]:r*c[刕Yꋭ:!KjӺ$n"T#B7 bv]1:GHh!3BAPn7 x q;ƛkHJt*չuqknS6 ) ղv&U"88ڶ7Vy K1^KboC".WOZ2אOlMR2]U&z&hKOk kR~?lPJzhB{ :8i,53#RD?=V %@ 1ͻ +ZU\)[d3ߏQb;Qr@sd1^3t0~+6uY1z} D* 7o"#K Vm%"T,I^` gה# S*nT\NKT Q2%)U dJeJ嵇)nT7cwW`h,Yhk8OGsNbL~h Dž7D|#Szk V&uF;u//#ftD,=deX>|cdKzE{_d^[և2#u3tn8php,^VN|p^xRc df9FPFSc2 uaŮ8>C+8QQJtrke;47pH%NZO341RЬde͆*/o,coX/?@~nfWG+S0GIկ詩TƠ4' vuoԶ5}_흱j.t+1H&-g[ok̢w%>axE,L X)c9}ѯ`ΐ]Y Ӽ7P-}"}(M@W\gg$⹢O>0a>!T`}&DatMY蓕gѧ'zE7'$'f5>0>o?]ɹO-Df}qmWIR>$)>a͙D0"~}Ҟ>\(UYm,i˚E )C\'I9+=]9+c_'"$'"$4K}:"D(D>M}I9r}*+}}>sJrE)s@>I,t҅q?6Ldh)3䝑vJE:# c;c$%5:<~!JmP\ ? O 3"ܟd{>g" TA?VffAD;0k CxB4_34o˾X!"8%fz@ Aؠ쐗ll )ɡc  &# +3LJ&D;1 9*b@t;Hp(״;/0f ˌ,:|uqc P]GN{tƛbhŹbH jcȨf\ bϘSCǯ5~.Y\+| .`73N^|Ne6L.^H mޓnU['ncؼ:hHF !l/9wh/:-/ʖ\_&xKT!zӈ[we9k\M7YZ~jHGA4[n5 G~>X;VMSeK*y:;T;'wՓ9tQMҙ~5Yk2–kE/og&=R9DŐbҧ^=7m+M7n.'ﭽeNYAf]LF@<3Ő|G\v7B{wd) 㽶:9&#%RP=qo.FS%,Y&:Cz!0%:?Kn+xc`[wц bƊ24ag{vc]r$G& ^X~WXĨ!+2(+Gw1G Yz$a:fn̽"[2X]")NQK~@@2$m=0CNu@, b!T we.d2V6VX.𱮹~L¤hQ2bz[.R*owJU{Zw©kA7A$z2lp 5PCT;J銾Cz!;ޛȆ z Hz>$|8+bOO:nO=V6Pk`[`uI=bCMl(|Nc\a5ZyF0Vj`uˀZTW#VYRpE -mte]wB~nZ>,\'|q\Pw3?-ZZNaR{WsghFVaZW`jWk0|[f:;Sqr3rN8@?tl(ƌZP+N 'nH z9*Lj1[TrV$Zʁ))nsr^C_DFFYr17#YK vWUds$fsԍrΔ]倨-t69 qI&9|[$Ii021g;$H&9b3}ѷog 幚9nc'&G$0ɹI4Ax:IΑt,rRZh,5Y` ER`0kO)"(X[eq zcЊ`n97ZL8hװ9Kds&gq0#>=q2=Qzy?Px}Z&Hf+(9aVMxcx;+6Q3싗~ܵkշ?(xCwz@w=0=?xx|]^:JOKdy /wJU{Zw©kA7VF:VF'9" L37C3DSHɟKcbj9EX)$XZ9t¨1E}5]ހph,* Qz" E[vS kἰ~hUyIw$ɩ#Lb]!.p_*o$}mdT"q 9i#E!Z)lkY%""u*O~"bBOCztZQtћG' >PF 4"F|-GlC9r];&zb'ШW;N(6OoȉەS`3WKC,L?:vFiؤIvV'ϻ wcSVDl 4إ}]`]Zcl.nQҿimG5kSq#wmC7\<6.&΅4IK.؝h"h{j>e2!Ȇ+ j iH\7.Kp!b_Q@rGg%l~wk2 .Q-!js0!NPcB N&͍Ą4|dPo8}ߛ8obImqO+]Vؙ2 ֶ3sˁ0{I~! >,1D-;ɺ=mG; [qZ>@\x.vyD-/Lv=`<a@*xʾm㢋]+➄`>#:c>1kK|Bz-c0N`>Q~V!uZ2["3[^|#šXAq`h,,-1hq0Wq_- Qh`;i(wX--P c' 8,,,f,Z0ZMTd1@,d[nȚ}/#Ѱ\݃`7Wl7W2W~ "2""4UX1ܴ]^vPv=a[\݄W\3M9)-+~-yf|3cwXDK@5e XCmL^ w vny!wdU!n핁J{t g52 œۍm'Dd=wӆq{iVnTAљS4Bt?P4C"a J3“s1_)d:OuQ3{C(Z g<)w ]i럈D @Rzԗ8wCzdj2 ]K xTA?tV>%nׁC0{d@Fp}G"D4E>pZM!хqV.?峈:9~u=4/cʈC a#4Y,M+pa#@7hfnN?I;M~>-6WS: b5qWvʬ/!-{]0.>~ !+ sk< W]+ʿ+ B95/;B QOQ[L,%U^=/QNP{F(63 RGwEx imK@q8sJcjokB5<3=YFi\Z]wطƬLǦ1r՞(c1lpZPuǞvXDbP{YJڑ0nD8nh FϴuD0%:'k$%: %`DW5)чeu%:g(Jt*/ Jt'%:*O(3 @IJtu]߮D'Uc԰N %:#$S %:d&%: %XEPA`ItV(ѵB+":@'I֪+ч%t5%:'%:zUӗ>D'[R#nܔ ҮDZJtBΎ=D$%:O%:W %:_ %:f %:JtNLJoǁ]Zc "T 0abvo::[EUmrxͿ.VsGʧ<,WaW) _S;gzÂ6\9Ɋf aveE~kJl~E/dE{fY>I1(MG7/w&_fcOzeR sɤ,H*Oz8.WR=3?o |Ì[=ߏbۓ~[xҿ1kk4V>̇`#{§]{8`1H 7ʅ>T,-| _$_=ﺗ/m[{d2A+}m Wq=l{(i[и?7>JEnnnυC6s!ݻ'˱Or[m)h+sSf|D  b|m#lw'K{Y-=gr>_" : pZ-M-sl1 :"$K7d}jNEs^!yuOJ D2mӝTsPx=- x(c81k8=W弢wr^aOGv] ]yî;W'9qj8Nr^&a^{8*D=W+Eג  P|W0gw%j\J+9RqJ| K]a-w ң =|WU2wD]DߕX){\-%٥' Kҁ-9_Urw҅қT{)Z/3d QD3$hWfѫ<#Ǩw?QYhrk7 QT}{8h 1$+l } 3M9L3c.bDi+.bFy{f)3&v7#&vO&+7w:6~+Hmżm޿NO䲡Eym2.Qk~)5׺(L"F[%UٗSZ&a9adTSO%5&+kU4gC'lJ׵d`C$0I9@Kh3Uq%@TyECRy< 4t.)@  tss{\м c|҄^I9lLВſ夨}sQ-G$$pWTN(lDDdHMT)IRqA9 ;!(lmq a ]W@䄽 )3jyR L]iTN<"v= Ͳw< SoIu<,gI3fyzSCj }lZSܸtkJiߥҦCkmb;">_ W4ݪaD.YXr J-^P6Yǜo-O).!'8V)~utRw2c !àlҳ(J7p*;E|h* ^`ЂƟ]ڪmt3̳(&VYUՔ$tqfmk`8ï\0"8a/7ۺ+>)Sa&(vhc>>v!p4a#,)Le9ʄźa61|D@~NJW p*' \LjXQM+"kU+'_rg(px1#^ Mg·ցv[kV1-;̕MXmyePy58ޅxIHSΨvmIjwavI/x,nZz"ǑN^`VgV}Y=d]OQcEش{# Q&cf/nc>rRZ7YׂoT{F7bx";w q_ b݈-<8|:K63Iin<>|_/"<39_'^ sz6{*bS=G7 JOF(T@qB˝OȓOf. x**O ~'Y)5ӄud5Ԕԣaf[In=$x=ZEq>E+QiuyAf^- Eғ0hΊ(* 8H`g~a3ݦ5)nOU"2 xUp3ʯ?jRB Z9l69g:"6j#Žd|v F4F dfZbD@wrQ "]B|V@*lC,ѶJDa1Ic*f6kk]=-ֱyn žopơm*^̖h vtJD%2eQW'@ߧrtNARnpEdޙ"|ОDсP!o$-2x] 0 ?oK1'Z.UH,G]`AڱfoE+EX+9 MwǁO:H8}BWKx,=yOx thqE0t(;wu;ζg.Ӊ9YvߑF3H3OAxqwesn!GGKq9"V bOW{fo9L qs8|ǿ.[8!(Y\m.jYb?^c^/nϱ Znk.sUtuz D^'Y\g/mV^{Xmxf};1TKb6!>֑KFw;!'#Gg"$2nB`-xםe%M @`6v{aMqJ7gwqU&f;"QCE>aFvD1;~s8\t+f@=m4ڸ"NbBpmZvC!)JvC!vOxC!BxCqCxtCo(Z`M?z`?omcBt)jXjqE!Eu@ uX8(m T]QluY8)(F6- .|xILZI}\RRbHkS%`.I&.G,$13\ J&RN"NߚRHؾWㆎL:E#A8n~U#W# : y08"SK K_w"&n~t98BKb/4:ܪ24spC$R<}G\r[DX;?oJTĐL mz Jr5EVe3sCp,Gaf\^N"1hWV=QV@Te,m<]y}9K O#jun8 XIђ"ɔg B L ^f=nbCsCݢC+ETU'9g58i]lNz`}":S0_r08o<>ۗnMٴYM Ӳ~asĥvg? >dr=9ø<֞%էW 8X NO+3 !gba˓?U #.`Ѭ)'Wxk)9)ƢWWS#{)<9L1Ddsj bF7>rLR"bϋQkVpAaxXUk*G'U^Wӎ›IZy”`W-ߥbisn[爛l|D,խtp+Xv+ ^u]Ev]5S MFslo_ +pPv?ّUߥzҦCq㍛bǻwuށ~>UKw.iw uǦ1鄝2j 7<ղ݋;k6P4(d7g۪EBWyLBZ| [֚@X簇١od@(@΃e +b-[= *K=0:f態!B2/=+"]|W(xQϋ[/{u#9l/ldjtXz/Zo/"iw u`^i=orڲz/؜_11A2j '91AYAreƃ+l9Ӄ|sU!2&4Ӄݢ##r$$Tc3$;pI}DXQNwɏwyo%-yMk?%^ 1>[S&lsIf#*ONrd{Mbuȕ&${kI 9v"=E& udR2aЯ$א € 3GMZr-F':Roi7)qہ`D@8E$94o5Xq[EٰaqM6мu0:. hu.gŏ+I ''6lʄV@ڰ%6lE/dÆ-zJذ#ٰa\vpհalDa#MWذ9ÆMl6lDaٰ3ٰA:!6llK6lٰD&aH_a"魀dpefa#1 x u  #KqMe&lK-LZ,q7a4j4;F-LظK#q0a#͎9Ä-2ac&l,BLH&l١W%+L8&l$N&l"ZIeNqdG%.gXw4XwtFbb"ht^|G2u/]x+RKh%}6.l=cAX9MIO-4"8U Kj{*3 S(ld;2Wx`*21_Ÿ îRYZzi#2´w'9!Vced;2α'6,@bx \ILEsz,ûWuMfe9q8^EyP"&D[쩴5EzG#x0hX0Ix٦(ߥ-}A&Y!AZwz v>weٙQeBɷO׉Ǵ~?_ rrm0Lt+aU5sXl&p[lROǟ 0I˅+73x _rtyCU"dDB8ܔ+ kRh\S]{[~Bᵒx ^=; \"/q[DpI.pgI M&35;/7 ꋯ oa8۬\y\op+X.(Ӹ-dP$7ʷ|&2D"B ."YNě|kcne &Hll-&(|CRL1N\8<3_OL,;ZXGD.,wޙ_t ‰X^&TOx @y4 &vlhO"grĵB\uwH0b^!HfC,-lh"ً9"Rh@ [0Y/smh¼K1^lh>/&=#h0SU^]hD.Ww@ 3.hqgM@Ѭc#hǤ *k2 y &(G.0 &'8Lۖ8WE":~T8n |TdA.)&.T(#. IW`0$Lv(`" 0@CpG'wD ~V'ynx)vzg^v=li91}-0@͖"}Tc)mЭ6ZI k֗2RlJhX±OĽ4LjC-g1{+s~u G|,_ذ#%ܞב'𑋎\)FF=/Aiɫ Q†Ti͆TaǛܞg gt4fvofa;D~ڟ{ gp{G-؎Sn6l [D:;D%=nٕcf!8L1 6 V=;-ܞ'=(87䵮  v 0+#ܞѽg$gNgZlWr{6_ Qb:kd, 89kP/@1nK1khƊr,7%f ߋFJtjU bqTx'E&|1 K Y ZW5gl6m ~Q硋wb R&<% O T $恇̳(V³BF}~l1|٭ M/$W;k(/0DC ٮsBN0"҇˜M~0/#RosmVW,IM7/Bw}r#_ؽZ2ڨ۽<:8CA98!kϑt9y6d <k U#5 3a?Y=CeW'ιWkWDtѠ.a 9\~~| 0M,D˜ R5abcRŠ{YLOBn>/u2W洺,x#.4c9&xD;wa^%!q݄`uTj p=5Nݞӧ-Gn:dmAD Ct2vja%̗0S`2=23 QYŤzt֡iZ{g76*&؄m}Tj!xKuf 5jǘ|K''HD>oܐ;0pt^An(-G ~ȤtKX]0! G 43q9"J希~QM1W"dgrD Wti")rRߘU2vq񹊴/7*Z)ւ,ҷbdž ! +3yJvG8Ga `>zٌϚ ,Wbpa[m5a nS̕إB'1-F E`Nc$֛G:Dc02I_ B `܏ݷhfi6'$iH.t%{hTPjU%0<ʋY*HI~o8X󄐾IaEf x2嶂|C|qėl5 |IB! .2=sCY`+;$aNY} xi3:CB˗^D,K.{KKYía*UD )h"%7b,&'pi>u ^~֥b0uc6(^Xf5 oS3CJ/ߦ?ڴəa{=ch˄=F#Iμ+gއޤ!gUq3B]3D3,gޛ9Bμ7ϰ3oe[Orf%93rpd93d93w9sPμt)LHq̰rf$Dy3o!gޛ7așAw9H3L/[yyHrfe9VHt0O3ע˙wו3"ə9&g̻̰3ï#ə̘w932˙2]əA,g q̘$g$r9a85d3e3 Iμ\&gd93X33L3c}˙.y&93f]0o?BCIFdz_Feu_?7?ZǿTHP6ӐnOfDkX? zʭTUWT_b/GZ?2e[x]rG3%G q]W[V߷o?XDd߶J{V?"XhyxTXLjƫzeR+} H?X!zS ??s+|y;Q~>?s9߯#TkƟ[_Nȸmetfh̍яQcKoѺ_>&+3Ot 7PѺ.nɿ\uZ]CVPwu7=zJve&GSc퟼Lrcטߥ*Sdw&ˍ韦_j'ѿ'яklKnѿOz8;>+(ˍQGٟ"=rc~)*9wG&XOId ?5y`nW0_ J}bgɵ&^$z~5nT;<戹>1^*׎g qFFk""Y^!2b@0p_72wJhSIlXD".sr+e-&Y#O_%s| n ao=#*![VU$o=u݊/E>b*˭D񫄰znĭyU:V|Z-}*f๴hJ@܊jz^W~_IJ{K갊%\i&E>b$]iUv)_ůE>YNU1t=+!t[VU oh<.6~a@ja56`$~Nuti-^oLZ'(!RZy\ 0ڋjnDx?񫄰znĭE{`ҍ k_ctklu;&] @ܚGg.TaҽЙVUN(Qc nMkoǼGTZ޺ .~9"D:cgܺNĭ{-~ n޺ >TZ*ySݎI7Ec4ĭ{-6A0o"P٥ v_^룖\w;"_xx5TŠ|}KUpV0Q-0.j kXX>sܟ&X_|qGB^ N+&\6 Qԣ=M|Q `_1a:9oIO&\hK:V(fAp  ~6coM0ݼ|$V?+a% %fڄxxq!6V#aiDc1lybit9+\T ČqW1CIgC̠J0c]cEu /bZUyxtC7[вd vܷ-}R?"QPSMF&uK*ߙm$>tnƄFy$ -n*f1vJh7{DVE\b|;sN.~E:`+w08PBB&!D oiY񩕚0 xK͍6Zu]0f9chEg `Hw':hI!r;j1:V?f![0{8z,#]EQ/ <3% ⰸ p$3T1ȋxZ9Eՙ0am_LeE*h!vHWN\MhsUse׏ŵT[0%/o91YJI~AЦ\ѐޘ wъ[Na䧷Ǡ8xk-Ck(YCJ?d-c)C[4Y;'=d>! p37&$x0A2 FZ蛰\g!!a-zm6.U+vQCXX"8 6jvMl̒]S[+1fj95WFOru|MmzWAդ3HC1$Eqc-,V+ʜVUmb1,X d}k endstream endobj 4 0 obj 109990 endobj 2 0 obj <> endobj 12 0 obj <> /Border[0 0 0] /C[0 0 0] /A<> >> endobj 11 0 obj <> >> endobj 13 0 obj <> endobj 5 0 obj <> endobj 15 0 obj <> endobj 14 0 obj <> stream x{tUն\{O9i$$95HHH!"RBO^D\@)  Bx vEbrD) B;o'Wk\'ׄW; =LN?bC-0!"Фg˘Jd1bξ '-BE)M`nao?hA;~i[<.%i3'(햗/ȷ^3${gO?x[[ˉīuKdx-Eho07y-b/5v}αُ MBs"tz / ‡—·/<ɳx>/U| {-Aq\|K|GMr;Ly\(owȻa|B~C~G~W>+f}uuu 6g/[_ q&qθq]WW,#Hp$; %-:N;9#qΞΑQλc9t^r*.+u%ڸ:qrs=zֵuu-HǝnǭzO'4<ɞ;=G71%qu$SRRRVҀ!I#%Kz,`ɤm}-RZ6mׅK?~}{]U*5TUrvge4`~v]e5C6 44Muk!hz7ĝ^X&)]Gݲ΁ GT?Y@uM?fuǭoރtd\\\Ըqq tMo{A#hHupLqTuuR].Ru]vV۫j;+jůT*_**+*g  8x:-%16,4(00/0+0#09;/_~/^>p/ﻼ˻/?{y/؅]x¢ s.̾0}F_Ⱦ0B /sO?_//gOOsA~t~藫USd'|U]TuTQձ}UjUbUWSyJ+߫|ʷ+߬_ݕOWn|r~͊+V쭸btEvȊ+T XѦuErEpts_V|"sYY_Iia)͆a4ǰܰ&ϐe'b紇@3 CP}4)e g|yH^(GWɫ,KP_^,h -zT>F[IB#4K/ h0IFBm`kq.. "F@#-K1R;k -+k bLjD %Gv|>yz`D;^ 7At%5S,TvY]S3bLs`g5:OE鬴v{Vf12 ^l&],S8I,&P1B΋9l/ñRL3qP:;*@NKkk|pi\`0씭,ŰHsA $rV*$+ v5ʝ궦fpҠBQU-HJR`,l|rAٮҲ=遾٨j-tg}L۴TJ9 S\lV&vJd %CDۙw>mwdaA`pN3ԯ@")m)eTWyvt*/U.y7s !)RbH1R)A2L)fJr!Әi4g ,KYb1˔e4LƇA 000s'H9r!Ϙg3omlolIerA%UQTY5FդՠaI:N 'ItR>i8iTFeL(eb-2c\?eڷM0lEMko%2[h۴PMzVݧ]z>?iܸIǍ +WzEvr5®~aJr[Z_n&|LP^ R LFي]LyyMyJNT}:5m P 맜f,Dvfw=E²$=$FE7I @T H$!MmՔTC3B3/T&moa-u%z=ޕM!; ̫鿝ݑսpXH>0QRzX-ozfٛDv7޾摔/: |یBHn?&4`L5Wj.^hʼvw|:XD$&v\Hx3M֘jfܴv;Y`a+G:E3fq=칦o219nN~OAn>' yp CxYd5rbԜRfD^-|moմo(YaSkR(^%5S ֝9tXq qM `gL:NlJ9ӶEt4I-CZ•S>i;w<`#Ո#N/qڋܫ/!BEIr#(tcvRjTBZEbyXے UknhܳAu[Ztׂz'@r” NPP95kܙQVYđ'f%]iBN9]sbjEbP,Ō^ƺ÷迾gىe|<[ X![MQ5ڭWneݽɭ/My,flf 1yBHM5HF \+d!^ف@JxJrB٨)3+O+s9{g?D-|M/drrkUӥA)͙~ w SBO Ahg| L.ɚ|&adf Fh4$ "A&e# mrE'z`bl/$f%`2eX&*76+{?L˞Rǎ9oGF>BޭvW}tLNH{ȯ˚5H\co2A&LWJw#"n)zZd_.Dv-bTHTN,^A\Ȉ,YkɸOnp |dx7BvA)xS쩃u@az #Xog\ s{t:cq ~3 Q͸R} wEm^EL<2fT?q=q!{dˠeTK0~3nq*NGq^r椄ZR2NJXS OYLnJĽhѵ XCQ(±bK.u:7a'qijw#Fj$tQk|A& /Zf249NK3i]m u NEF^zL~>;ɭ 4PW.8[x) ~1g> y?mia*mf}4BȢ10sЄlNtui>xȣg2 -X=8h c+C?jUxcu/a6Œ%+c>$Xl :ƌ[x'~az`kMOm~2vϚ~uf'ewfP]g#XgÆ )[_F\[ƑVl*7ZɬƳO9jyN 2=Ճ씲C)T {`+-?Jh5vbD=2q#~cmԖBhk6}0ztͅC}'U@lj yx@hHp5A̶:͊uxm=XIgDg G< Xf0ƈmŽxiHw1~ ?tÊ/)}8킏 ݍUX q8嗢[#2xst:>p%d5F/A_Ivi[t 0FbP渪яz5ΎQla+v}.J1uw7z|C}ԯ=uA, *0j tdlLo feGsm}3`Om0uG편iwEχu"2BY ]# E~0N@6!~ :K;P ZLH&6jW4fGm d hCr(fE̅ k1>1p9>PKaX@ ։ B찠TAJx@kĪDք @2R#1҄rY':cbPƒX&0 ,4y?1;bK4{#&J۵ f983 X.S/ex[>Ҁ7:jC$n?$n&2?gjZSOw=޸k3Zl_66(tuA4}AR52DrfMU@T)͠u>~NC#}O )U`|GJb<Pjfl F|&Sikjܼɬ:zl3ȡTM y~%H/ݕ249YJs08dPJ#(6%x/4t ]}r'\w?׶b*+E-a+meڋ!n|4E!,'Pdt}*H^2}51\#=nD; K([ewdvt7uo׷j!^ݣ1ܜi:ttFuE_aiuŴP|ӈr T݀7CwJVzy+UmP&}7M?!n#uo1$/a--}oW޾MZHù5ȀfkoZ,RC!5Čް)Šx4B%S;F?m_YǭeKv{o}pk k [ Smu}Nv96J3pK=onl4nqGPYXfPVIO\ @Fx ^ޒBGG XFo#S YjaE<ЂB[ *1!5c+nW}坈Qᰜ{NXy> X77zNȯ)2 gki*@=(WOzQ$`ąh<%rJ-v f_`W %NlD6{qwۀh \هߡ`7+D@:ZYj4tXN!`ivXuC`POsnLnu%` GC2W4a>uZTO!dW /i2Z-zx岛}1^аC!RvJ-_uO|וxY=SU_jo= ԕ r!4[zXo#P+_ǫޯCQ3x-2@ ѬR?c [ax;=u~~PޒM_wn {HVqH" g wnD&LeDf  z-GȈ5ZDI !WI"7ǎ#{KGýi%4~(¤a|ߧK{k= S&~v{ ߽X|DQYL"ߥc{oiwUmݤn'ӤO roM^UF? _?&/ֆK"56im8_c'9i|\q\ZJ+'H>iY4(/-*| -II0@ /EXb4^ Q(| ٳZK>5h~1gL?.Pic{ic4x}|*S{}j5Sd$4'x'(lh4Ƈ!#!%| 48 k@tW +|/KGEs!X|9 Ql-k_0 endstream endobj 17 0 obj 8833 endobj 16 0 obj 24764 endobj 6 0 obj <> endobj 19 0 obj <> endobj 18 0 obj <> stream x{yxU{TUoI;;Kol0!%H'BX4l1"AQY* "P2FT: tq/:Wmt{~sHyΩ:u]9Yi1qN}/ozW'29-}׈,D3~fぱrmoMߝE{Wu%{(]J}I;ŷM4*.%JMͰQ-$lxYg}鏏J5IcF_V!jtLWE5ǎkv~aI'uҤt)O*^JI#gWYgR>w ?'&iy\+k~*zOdk7 .eqE\ ޮ1ɮy]\vMw;===׽]^~}O) ){xvx{x{~\h^7&{x{yz3y>}b} d_oO$H  Q 1 m $LMX6as; &W16~?՟/G''g//?q?{'&OIMkrWI4 $[jv}b!v]b IG:K]bVzGPOx=2}Ci Q^-o˯{wKG?flx9 ZA'u\\[\s lr&w3%JBCȓ]7ﻃܗ/8/X%8!8.8&X,, `nO0'L OrT)))7YUWKm_F:?`^݄fEU'FFRsK7s4=I&T%3YPkmFdr"))bQ$ vf.rS"%Q2P*uF3@A](RuԃzR6M}/R(Q*TH`BCFi 4FQ LTFi rGiM崂Vô)BПY3ZJ/6z^Wh]*A&F,4UyfP:i6!61)4WT=~)~O=q?:-Itd#F(N xeEլZTTpz짽7Hm+14_j[C(~FI4S Mn$n⸓γ03+!cCO/Bg`7` , $֔Xyu`Ķ0.h1e=1GY]1BsG?NT:Oӕt5ݔnN[mr\+*j)לkɵPj0XFbX)VMQ4UIUJ2WYm5TVJ+Jyyeƶ^ZcuZY676=1vn[wɻ]ne[ememmmmsrսkflLOH6Evޣ{ddjR%- eE0-6hPi U MIt먢~tE 3o6ihVUG-1+6;v#/D AK;L* YB­fneVnέYM0mQ,fjŦXm:㲻Pz`ù 0gr(~֕+e (0IK&V9S;nf<5n3LF} ~KcTD|^8(Mdƙ0zr> fY& <&{z:{,KM,9a0q5?!|ͣ~h\5"CkJ7v/aǥ%&(&س+_0qTvdMt^mW6ԑ@9۶ $ 9ۆeQIX6+ic6aHGm8zᨮaPhaXSSYv,3~%~+#>p'>aƴK7Ys'Uv4䖖NcI [̬\-6e:-T f4Mi6J[LU>6łM|Oe p;1qY_)k[/?%ĻD0:(ڬLb%.T1lBшU[tY-X+eY!)ۦ­zB@3JᎣMM/z𑃷` 7)›)7N5Śc-N+!p8mrs%ښcA99ʣ|QQoc3lbցUj_7~?~A98SO_ϿZȋ8FΈ^O)HeP˒x7kDWG3#2#*#:##.ÛHg$f$e"ΚS/kr*c\n&%uv5O2_o7 ewϻjރl7_~ՆF^;{fŪ9\dĚ̒JN%632JG;c-YlddD5ʢD[(6N\kģMMnjiedFI>^@uYvMm rzk[n׾Oh/3ҫ[g}?fXa]vssG=GlSYqRX=Kjб9YL\iiHW\lLͪ*; {H;[4rfCdº^:]mUk_&HY@89%Yד5i} $M39G\hI6UQEZ-**"+(l33r*lCr4I㮃EC3|HҀX#z򞊹<+g]u5;L}aߋ4qZ^v{`v ?qK>Vۉs<w`3 ;: >ֈk6aOOcߚ}%b/g1*Jq7B-:=tVsMLHhBsE5h5eLgth"{3 uLEhaxFf]ͰdvqaVX*p d_|O$+<>NyTLgGgs.!0cH 32q5ov_M:C}ߥo`(ft%nX`v (0+KquxM4709N+"w xӍfTCetJR?ʠ ew~oplF6ܰn%]Άo;6lcJf!ŋ=OXɊ/Ϯ[~bxOGq.m~԰s xSh5qA,? Lj-4&MqDI/">-}zVG ,緑 Ȃw=#=0GShl&Az!Q!=*}E2}IN8d7-* AZk5V:D!S/h >d_HeRX1{A6XLF~cFl>mels~.c.:I{X3g3s0W+ճ;*J֙U:"b`ȭb`"q>Y&Z|Y|D>Qnl=(GSD;(RE=<8R_@(AEU8"C4#"RZ>N;<ǡCCD; A{'!y15kYv`d)B DȇDL͔L<\h yQG@>4Ulg 4F3G"6`ThFCȂ8?c{u376F)`4΁u| ~yT,ʲ#k5ţF [U`OS;j/~mT0~PN+ ;xH$7!@+Vǃ1g6yIb;Hz N?@]zw'1Jm c@۱+R'-~xXGgx,$PH_#KdØ91KSt(RT<KfmXVM3OlUTP.:;-cvLՆwZ, 4ZCke'jԸ+hAԙ8$eK~=T``Akѯ3]PeI<5`ևVBO_KGF{ln$j[ĬWs_6Nh6a:2jE ,'Ls ˼Y4]u/rD٨:IA]vit9x"r+yu^ +wkdPh/P}54dUTz ФZ{|֎E>Lka0fT/kz@׏(oj'jB&:od)~Ew@&#H3FZ k?9\wm/w̕#jubguy|Ѹh_gcNVQuR[J:4зKr/qt:wV--^K7u;ҥ_4mz-o:]s,;XNNa+Z 1+B}}W26YwIH~ 07O_UX?,umtv5H5l8O,:_O,e4soib9Y*ցMlȂnFqʭʭʭʭʭʭʭʭʭʭʭʭʭʭʭʭZ")H14@&"E/Ł4h-?\5Z^S3 :(eE?!/}KÕp~{5~y2eɃ|bydeq_%|wUܭw!5?Of*L~h|v=4>3HmL S|brJRَW.)VOxE/RO%ZoPn|B[ǏPƷ"x9.Wa|ZeG+krYiRVriY%Zԣ2HFã|xWF34!|p< *xjp@2 oP 4? ny~^@Wˁ>IJrnNZ'l+xq^ x7w]2.ψM;x'uPS5Q<'sRp_sW&o.NikkSv66 8_<6ƪf+W()R,%/w<uރann^ϭLZ-ofSb^MJsGslX}(E/ endstream endobj 21 0 obj 7603 endobj 20 0 obj 20152 endobj 7 0 obj <> endobj 23 0 obj <> endobj 22 0 obj <> stream x}|E;{G BHBB 5At.%W R1`J"t(ؐ)Kk}ff>mrDD>4E$9։(DTi?:Iza}ZuicAcoQdQ:)zLh75Qt\JE|~G^xC;O!j9ĞRC_4Þim@aV;NP"S`]Ja5\bΛPh᫡r|SCZ#Fl&VϔijaeT槅hŴp^ Fh)mZ[ehj[^#vJL;=dYZr I)֙9%ֵ֕w{GǬ? xl .4MKHV!Bl 9B苡‚laº {=,9ljGaXVAxHxXx;w >.|G-Nj܈E;#.;IdSJn-yi[-VV666Ζb[dbvvTߏVE7nr+ыF%zg%7^̔31crl؊b}ܠr.?tv{G횽=^^^}}}{{ݩmt:N.OU !-bY֕`cHk.[˾PNjOuM=~ʓVViKiݲ\ iMRYӬ2!/? "X  Rp7BBꆴ 23dV!aV:칰na)A%VS3[>!|Wo ~/"b#D*⋈o#)WHmӾ~~P'=BrIyyys=6fg3͹9999999999Y wq9 9No$HO7W~IӿѿO^}{w3ߺ~t7_~u׹_~5WUvۉ{yznrZ~9˹s'Z՜rNə33gJΤ 9sI3&Q9#sF伖jМ!9sI!vNB99zl{ٿf_^<{Yi{fnx̵knfu=+'+;Z֕Yg?kw֎-Y^ϪvsWO^=~MW_ms5j>?|rZa>349thB %m賡!bW^Q8=h)=/ |"v1s[E$g 7hZ"(g>@G{) ?#?0}_&s@q`-iFtl߅A2+A;ݑ> HA c)X5 z 8 NQѿ;@i~Բ!T Z1jypjHAnF4# @*['.6N}ۀ:tPfP/]V*4y5y}d@z̀ h s@?3BVOH }@ P xD` ҽA\qH Z hj;% Ұ`r0m܂1_ o AƠ;IÐVH/E!-Е]łBאT?ŜC'#g_7^D"1 M[a [ }x`a]`>^%aב%M5 ~z,}4-k^ Kpج7)N7DuHCS8|7t=o^xnk8H`~>_B8oDŽt |H':"XO_EO@^c9D"`>/k@#{-_!u}(  _ ]lf>+_?>X%'vQv?[cзdmEqAlj+珹/?6}5_t_k[dYP sZlU6>vɀ? q, @W/4*Jӑ* ~~߰ho4:+ _WDC^V<: annP<(ha!w  ҵ@XKh#no1Ph9(Z4l2O`1[ xy62n'Cz7(4{@ xq |_ePCBV4|bb!X.cW d QSY*zX^Dr@9b1=@v_v5{c? W@co {{3v=v`#] .t& t :k:֬MlDw;I둾-'@u{u%(9A`t 0i i&%z, l俉KRZȋɇ| Q&SRzҳTc)UlT FZ @5R9*O"=G2UGTTjR-Mu(R=O jHEjLM)59ԊZSjK=L#uԅR7zS4J4۴ZGwi#e&L[i mh;v!tgFIԛ̣i5 i {R4ܯ_"~Wϟ5A &R" {FjO4g!bI4HR>3|fLF{Tg/YN|Y>h ͦ4fT^PtftOcyL2, 7d J#]CqrJ 1`]'Mfdd?NR=#.Ef/RazFEobvNۭ[ls,C:,5^e?HSAiL 4}/m>MˣR&e+=,Q"Cnvш?OK5lfʯiKS"ڣ8h(H%CGߧ,'^z-ӕ X>F$K}6~ce˟xZ̭ʨ8fkC uy?;|m/-A*݄ j9ZԮvWmN %M *b+-U &3rO6] k^.tKm%m*A!WU^4?eڴG҂n׸~E:%,,K@[]^V b~AU˪R}Ubr^'i^%)'=""Y+DLrL81 )[bjUBF47zg\Wo<F+z1y:9lUv]MOчKs1XiE Įc\"ո* WC.)an2ƹg2g0OQ]T4tWGkMzcn+Сa iS[5/i2:~S*_;aaulUFtVtt\ tQJqF"pI 6nXvڼ3e'#uRySg6c2>p+Ss3%s K,+d6y}7}2Ov{P:-e7z:,{3G|}_|d$ܖB"(00#޽{u];J ߪtE?_uJOZ"Vu:*FwQHP=G*R[z>Kh-=#UIE2%8T̕5N[ ozALǥL>ۋnm;x_q\ū6tT:(ܖ_ĝ1J;|\JjN5q^%g2om/I!RZFuv}EvkkaVEv9#]N-+wT7K ߄e8W}5ʹНjDTzUq]܇w.Ƽ"iIn]Ǧm{r!rn~Q!B,J/9k֛ҋYY/R+:>_2mAƥ~`q } Ha ƁF?y5<Ȧ%-ͺ8qiӦL嘡윽rKX[.FoOpo%;ﻻSX;z|7|7}e5NݏV0*wxѲv幊_4l4}7Ÿ)p˥lpfUamTenۥ۠wgTC {\DpQoݚ@?T<yoY?JR)>nF.p2SQMYK6jۼ%[ҳҳbҳW+h-r_}1! nbʵj8kߔ?Y6"ifFF&/u/{?I5܎3xAoΪP!3:гO-:uDtk )-t4wlb)S&:NW]9t+~\dVI@nSP?왴)XOQwpphN5￿F ߑ ]o@Tӧ/-Y&d61ou  Ip"!h0#a\:aK`lʃzJ/H^BO=\ٿyㄋG 5vtEƢ94=zli_z{򢱳ɯt>pj-%0B,ٱe+-<}I&pK7P X2=S Nk/qÊy-ms_f1G_Qɮ!5jKn)W5\b<;.آdYt=l$K73,|s\5>fd7L|p|p'ZDW~T{آlGP>*J{~\%4|]0r|՗tO5J–2eڵ$6#}v .Sf Z4slնJ5i۱MU^sĖKPOc$dl3>e>aHe8XqÂe}Joп?,MӎHq[o,7CWy|Q>BU2IrFSMKJ;1viiAb1hoĥܩI}XcR@g3XFY`.MTAdUnB}YC B~h\F9G-zW`Pe iRj+7)e6b-3v1~&֕!hݥޠ![N"=DerWi \+h寨+)^DAxUéK{r&Y(K":49ڧss <_FZ.%O|>  8- B>.9 ;,` !BC28 Owɡ8_@ Y2㔯YJg ]/tgSf'S2yM{<%>gagkA_>>* hu6" tU"GY+v3? yv#Hg =]ZS_K7e؁IG.m7i#r.C {(`op/h;o72!t}ήv^m?~I_^mS mwZP'l1%v~[mz 'yw6 J7͊Nc@o%@ky_u)8%?G 9{zv^s*{ի4]. ϫNb0zsbyQ68G!삒RY-|yY*Qlˑ @F̳b_R?#t4Ο8Xδ7s/'5̯|=p B>0֫E;1N4̀Ԣޮr)qR%T:ENzC_9./R} '#(ARq^OB%#HVxx[&6A#ΐ8QxD?=OvWA] "NX^[Ѷ99 q}Z:c;s1#eg)Ǜ@M> Ú#)nv4P Сx?x8;e:wa Lq ̧5Oos9@>#8?| ^$>|^Gĕov0QT!ױTÏ05`s!J,Me۴ [ r+FaᛷXxlאqw$6\F*',P34Zܔ[" dۯ2TJY2sj&> Ř\SL̗oCqFl_1/Kua.dkoPߓ(,!;sNsoZ%tCF_\wQJ5R5u+8Bϸ0(ϯ=8W2ޤ=N|b<ϦbʷTLJB\֎Z* þhQ ot [jIЛU'țR O|^iM׌ ~!pg<<ƼEaXIa^0(A2/oC\".hh<^^}HQB>ƾ1S+K}XӶGg3#3ؠ=O~zeh(rϛn1j*)5'Wv/!-ʞviAb]aOs槟Ÿsv"] p"t%OyM<{[$ aQ\]py}1*C׷]x X;`%OE~5UU>b+:"oIJ<7ځ7N.Y}Jc:_yV~Ԟ!yD/`uLgY z 2 b4 ^ ¼įA?DMx5J:R!]F{ƞ%ЕПJ+CwQr6}U/AaD\kmߡ~W4~VO6iTHnkqɎ8N9wh * @Oi4rqM([_:Qk#;M0r7t<{4L@`90x 7-,Ѯb7;`M|>4صƧ}||.h=ZX;}n&?7Wr42_>E kؗ7S7d/‵f H7FCį2/8x| ߗ<byHP@NsHqJfc2qybǡvV‡N86fqsDz5Ս 8|.v!7|o~8aov:R``yݢ6*:r]nAJN_Sa̷J{K_z~'Z[oHoƬ+N\nYwA5DF9o Ҕ51KJPRk v sl6v8050(SRg;C:mQ;2&|!>#l bINS1CW(V Ĭ}TDy{ 1ߗds=) b1]þ :뇽 OS7e|yk,Ƙ H;|hc?3߁O-,z8t h2vѯFϲJZ.GM344nHP,\^gC=Ug__2!q}{H@l>P]@9н\t;蛀ʟv;w@ji$7t/4в yr(mW}̹MLe_F_]YnR?=_C,\/u`RWӮe P5uLh ǩWt L:&c0PLkJȏeSG.?*uP3ހL@;\x&\O$j jhb `1}c_hj}6o.2oNg9ˌC=_?zR x u$oN,%"]׏:5%)TgLjB#Ȁ65S / > @@r&k@ p9ꞈGP}/㌸W&଒ Hޗ>gDx1JR1i󆸆 TO:mξ"Z;!7q`:z5A䥨ss\KX)ĩx6{棏=Oym/u-*ǚ|~\ R,3kS(5lƺh{C _+s!E- ڑx%pH^Gz )O΁ KTK1nILJIPz8=A# R i̝M%&<>Ekqs0ߏh> ЦsE3+o|q.bϑw0?xLϨ\s6w?k5w tfiRw/~!rn8TEjB[KF4~:L˃%yբI@׼g_PQ)s3$w[~/R >t=V@Sv fB:uFvM;=b\8KV J-CwNp}h Ph X- G+\Z< J[`?D s({j z8WHZ 1Gǩ*uW+b|¾_~he=mŵD|{j?LAAowX:PCRE>xϭxPR츶=]jH-akt(kJvu[vAFj=$Aˤ^o,jY6sϨPĢ ZMpZF\ZNgu9űOm;7xwqk{*<||bY ;e⽉xGOX3ĴY|w[ȧ$F(SSάq8C/Aߡ`i hy凰#ԡhYonyP F7/ǹ9<7G^_ 2VuŚ5oʝ_ya֫|MкCD;@^~` Ηm!E8#nw:4Ki@z9ZEUN9)~R/+%йLD|/Y6q&A:Oup-"?f=*W>ĠiZ"iqq~Qyb#h?yӀtXyA]iQp̷1XQOΗ^L/}7:˔+O\?r+:֘cҿ;)^}}'np/8&?S>uh[Ny79kAiu@;40͡#?\iirY0 gf?ܷ,51ו_)+M:,u:+_w4e3(0G;Nհ?Ř䅜*o40`bR%_; M(@{}g0 \粓HW"X\* 8ӠkqvMK96ȿy-eɴ إdep`i~>HAZ}Jy"1<\!Al%_G t2 {,Ζ^Hwh gjxkyFJ8O57i=3NS3DY^LuCycNf[W.k&H4wH3GliyOy(t`;O c1dEKL\5%ƒ *8y/i?E Wߔ;}N,S2XdsΕ.|?aͧCo qEse-Q@;TWyG;w S7~^ [[KS#+7Wwf&q6Tr0n3:*렮r 򓩔w7Uc:Pg+K@R2>y^4OK\9i!ޫL+u߿5g 0ۄ`}-s9>F|b{[)+Ҁtt`&ʈ"oIU`k7Z W ~  +#<.|@- qwORcV FZY!~AKƠGن~Nj)[ߕ~E;^'8N#-4B7r8g4=b8O&=0`\{o3d"vp͓t+.s' 6S"b{f>Ӽow*ȕox|w+C|##-q[Bnr y/XOayv wp]f_OI3/9{ZrC&\V@+ Xm%q۱ r$n]%#~|AK8soE+s46I.Y<%SO̟SyQS@|i֎>>K|ǩHǻ[?S/ⷾbNS)^)!S鋶}9Ekwp֘69E} Si>ۺ˽ma!6~I7qW o]6AlcI&<נ]&jhy-vS?439C;a3&8HA^=u!07A{Dniax_@ڟ;kH[1B B`!xxxxxxxxxxxxxxxxxxxfHD/vT@uɋH Q* uvQ~*gewuvGgDV{*~YOMg7SٯF.rt]]ϲtv2rz%]Fm٥KbEvAg|es0)ع}ξEoDZ3߼Ǿy}U1k}U}/t>Tvd N`Vf@Xqv4a:;tv@gulo 3-JݣSw]&(vFu]uQlζuζlζ$Vic)m R7F .&n.۠:;Al֮k+5V:BUlV,SWlK_VTMOb˖ˊ,͇%h8-ZhUa lA.{k>-͟M̛͟UF9:=:[g*Xzlt_uF0RPĦSӢ@6Eg'u6)MƩu6n{#% QXV6ڏa#u6" eWs0  du6 :-믳~X_d謷Βt^:Yen:뢳:G:E:kgBX[)@m kZ7-Y+_Rg--t> endobj 27 0 obj <> endobj 26 0 obj <> stream x|y`TE[^t@M'DY *b-bDM$,! $ EԌD$8 . 0JP!]~v',{/Nmԩs,ĈL9r#N|b|!&Gh`D۵9:jm^aDVo^oD =+7%_4)~>z75D i̸i#ѭ^;|x˄#.bso>i%24a&Ç1/1ydo=l?bw"~KR\J:I]wSt^g<4_ȟG[yR~N~A"o+!Cw5\Uzz:NWUWԍ+ uG}WPH=nmyڲвRb)`y,-G5 R)!&a#eB &LI07̈́v=mS#E%bs oۏګ;b {C3:N:.8.9uI g{ΞΡǜ+:_w(%Z$'M $W+u5r9]]Eg]\ﺎλ.Uw;ޝnnn}~03sEҒ&mHz=YN6%''N< y`ɓW$oIޓMRޒּQɗ^κj׮EvI,V#4}%RSh:UʀKһ҇Qh hBkihz1*yL.w4zaTu_je4=_ j]e,C֣дn"!= uM?f{=̞nhϷ?e_l^oim^iqHCw'?;.;iu6Ӝ]ΉΥ!MoNӷ$ޕVi4ЕJvuuru-qtmtǹ=۸;{CptqO 5u{(mҤI[YMM&W%MM_ZLW^]wWkxDx'/7#F`{<5Z@YŁe%E@a 01X`H@@vCM +:pkU#/GqNI\Ww_o//?/O??ΟߟS]QzgoTo\Z~ꗪsK;7\&{ܘs :m~]W '|;};|eyS'}|S|}O&&={7oa_ooooN_o_/E"|&l٭g_9sgW}lg;p϶;lM&mR{/*T~Ry#W[rwʷ*߬Qr[[*7WZYVr*+'W6w:|gy/|q3'|z3GϔrfEg}3t9=kctEdAdFdJdbdC) ?Jfb3B-$B*⾑Le("Bd%EQ4P,5@GԈ#[H ;99EnjJpTL(nԂR%Q:eP&[5eQjK=F#NNC unԝzPOE~t;iEw=4\D`4p?S!rZEz6&z^WT\5Bi+N N;h'Iަ=zAzXKShG}6"m>ơq6~C!߃G>{tʤD5͡4A&foRsPݎ qe&ǕZݩ8&Ml7ːѧX?I6Wv˓yZ"FcCK nZbSa:L'M2:#o'K~J?y`Z/!w2]+;]F"^ 4X+#F"p{ǻFQe7f84%F-֭gVCS[uZ έkT@XUi{[eۿmjs;Yî]Bdrzx.7m׭{\h]n`T]$Q87IC3f5=fp4nװAti76Rc>l.:|֡CMVmA%lF@I&Ҝ17> FEST=$ؾiH]DGSkMUgU֟@~JH4&49MIS i4S9-,Yͳl%[6dM;vt4 R)+Jy\Rc\-EޢlQl*{սƽaV|;{]9^@ 6;)ģJ\|#ްGUbJ$%f7tYyk ڷ.aa;j9ޭogoMrTCYL23X$mTZu[^0~ k{ ky;f,aFɧ[67$\dQ:ձ4&oOڹcr_0YM3fkvA/d]:ZLnm{Y9kl47._+~~C|՚5Ek'=bJ!w$n}k٫7M;azfΓoL̩_qУ,)`<8!f(Q_`bfe52ZSδibZQrCȇL *֭tZ{󕄚VZW.{'PGK6$4*1؊cJ"ZPfvjhgfYvMB\85'IbciX?3ݿkKoTt2)~WtrҨ3q;zG|Qb5]FXZ,4(2MXãʪ{gP m4N"%f6`.56AQ~:{q}聯=ŏNZ!NZbּ eJ󗯜`Je?=YťBTV@i߂ fNZ ,Ypu3N>ر_و)O=5eZ3uԔnU*iwkDQbkK-iRZV9sLxM͕UtmPֵ\"ehzo}kT+gqWtˡj>i8%~B*Uf,>fof 81_Lph<{Wu5*o' `*QdP(lpnMJVb2T=0)i0?IEeMUA`e)7pƆxZ9 d. q+Ch㉬Rd#RqV&^f=sLqeJs6WL&1LjSx*1J[X#()d7P2d==(` ]^$^wR{u/_9V^lY,~ݤS=[(Xަw(\|JJ<6F JxĶrknNjz#kn7$݃ठ7 ->g3>?X|+l0mCNӠG5ZTݪX{XT{ň ]O/Ue O'DsҕZl) 4vcCh1ô oSU1hfH&)Zť0 cTa9aF0AoS6s:EeMe56@7!6fxm#9,NIfx6EL ؑHcȘ k-# 2=(M121u/%]/E'vKs<"Ԝg jcy[|V#sUp5 $wP`+ OȽ4{a|)c5#uqJ;Ea蹿׽j뫅~1NFXSQBNJͦb=9,|q,x,P"ݏ8˖~xBO1Yγ唫%j mx!6X3$N"FaZ1bQ0Tߡ4_rEUT*d8OyX@(:=>QE M:hn$VELp; Q?C-<| ޯAJP?C-B C:,X:F?Q7nf 5.̩d?ːlq:AZ,aN.%~ ӠZjHrgN@[ڊU!iwv.(bt=5|z\.ح+\FnY'98Ph^=@<:CaxGj ,Z x擏Nꯊr::|l5N Xp<Ha)RSQCqz!d ̃`$V;i}~6vrA', p]^'TZ!^`W;˴C_ 4:e_ h4+}F y|^$|T<;pb|#Qj?״~X@ݯN}vM[}n~mV ,UXuAk"mhXMJ1 +qrU$_tFO jvtꢠ Z[ӱأSOI? v.4jOŇ|8|f1pmکUs׹Gbh;ڼ~nn{)ݠ_9݃h&E4B4P/ A0Np>C#:׼f`-g{Zzg-!^:Q>;{b/6v ETfRUyΆ} q\܏Z 1'zS teag;w r;vu-*3hNch*'i84=7|[oG҃hDÃ܍qՅw ;L.h(:D6zu)kRLEhjmN݂"|{܎HWBXq9P5khC_teY@K c]Ywʺ2wmk0Vc/L7Mg[. "hf#b6Q!b%$zpmMt #7Ɵ {ogQFԸ߃u`AkR;CA]?%7C N@&F5RlQߢs=] Aݗi# _n=Zr3U}{gJ jnM]4.bk{t@$U)vi:^_}j *^_#GF+!^ϦUq, tWXP$`SuXX.U^uu"jᥓJ10tpYLP:Dĝ@dR"%20 0f&557 0b"eG۲>IaA 3xW^~FU_ɗ) KIJ ^/%_~NS~N2O1b^8 ?t: ~X9'1?+x#;ToW¿秋ׂ'c ~2U̿"VR/)_gqt 'fS?1c6&</ D(/?G}/ {ޮP!ywG=K%7߁jhm|[/[(E eEy%l/m)/5lōʋ3T A<^ΪuV73_+s9DիZ*_Ւ`b^B)|% @^ԣWx?+2UX҉/iEa <Nj "_hㅂ/|ڔyϵ#l[2.>K)|S3?5ϰ'n,OLv2~%O  >^qޥ+揎mZ3yP% >r])*#|*)X<~!>10|4Ww ~s/1}YW>w3ޫgҫ 9J{tSzyz*x8]96sSzMrNH%svJ^'E;df+^ depyyw ֌.hd ޺75rko U+311S |h4xKSeOmԝm Mi[ho(3o"x3O9+o݂"#T%qwrGonvo6187<^8BnAl XTcјã>JpNnV`qkPvp%2Geg0+pn .0nnj# nÎpWAZ\W=g`rr]Ě@U endstream endobj 29 0 obj 9971 endobj 28 0 obj 27180 endobj 9 0 obj <> endobj 31 0 obj <> endobj 30 0 obj <> stream x|TEs&YȆB6YBLB NBoQRQ B@ H* "]*D"F$͜@}~]7̜ϔgNf#ww4yxB'* }jupL9z@uEF" G̹?;3rxՉczi/_uĬZ$U ]M>>riDst2+n ~μgd7߅ȶ a0 #3Sxu*25"\)"F,zACº^?Yl1{md'x9ޗ b~%=DwQzD,}Fߨoַ]AU-~Rf˵i+p6wuw.r.v.q>|ڹŹe+7o9;r~f[DTDNDlfqծ]]"GND׌=. _~ʺ*b\11mc30fp̘}1o|Mo1b w;}{{E/bb;v;?nW[q=ដX)=3= =<;=z~:j{ ]R& IX+H &[&Ot=>:|[#~XWz jt5]_񗺺h;j;g ]́J]runzֹyyz۰"舆]"zG8 sp\]9RW"'EStdtуI]~ Uɉ 11=,] R[1|sM$8w{;X ]y==}ٻǻۻwqr2RGmwzxceeNo{ zjfj3~2N?_oGFNE_J+ݯtJ+mJ+-4]W\i|ѕWyϟc3G?4pS;Ϳ+ߙ3ͻw5rޟy~;];yo-[7?onYyȻ?oz}ySeݓwwIyK/i^𼰼2yyAggϝ={6ƳO]w}vng ds'N;.wlܑ#rm(^ngfҙg:iٙ8U^s짇\R]5ׯ_\3Ӯ]?Nr}Zz5rcE\Rhs _`!v/k>j]n3 Ȟh`@= ȏ L~rY0,Q(l >v9H뀾po&p (KC{8'[m?}a1ɐ.[A25 cLxMXZ-@;Bd2ᙐ\{6&|.>r G_Mȭ&o7}2?E7AG&ȷL8t`—@0Е~҄/D^(ų!߯C^p'r67}>1|)$ r r rx/!1D81O[Lm&s’s>@/y7ƽmq7| 9h99E(;È00V9a{$$_O A}l: 7fDo/@nMu!O eqJH7Ɗ ΅bC^.k5B.&>eby;nTT1mёCdwBb.Ec~119>v%}pcD0cG/0cM^0>Ipc|TAUp͎1Y򃒈0-)s6)gT0c2k`L[7n5,c=fI^@ &A1kL1c0Wc}%9nĈ|1XbDo8c$7A97F70jw!7ZFN8/7Fsύ@~n͍9vc1Q7crEXbVc,v6 ƚ$z :0NQv^vļü:<;z=Bq`xPx(ƫ*n̓`} | wbt +/'rB"@:181.&`:C5Mτ!p㬛q 5a =&`M8BTKѤ tֵe00T%pN96:k5!%X$BaD ϙڗX7 !%pc'Ie֩Z&a'IOXWIC0ee US2t#=::0]}u0M°M0o򇚄.i=UBE/Pq.wpBE!EI8}U zU?¡Be8\}b )ZZ9Z~b(y[vW8L!B+cӞ 6>1'أ "f`5&5)-2)[,7ʧWeH94;U6 @[NBegBvX΂L^@B7Y KH#mFv "F %'0(,rQ$ T*QUR Vy*S5J;(1S I6աK>5ԈSԌS jI5ԎSH3uԍSIԋzSK? 4Hh0 40/!ZH#S4mʹ6Nѳ<]vz^}t+tı Ic>H4>8Ҹ!C*ӽ!#Bi4M 2!kH"MXzJI!!B4H3+aϥs;;8Cה&]̱ٱ% б;:q(ͣ%rZAKq@h==IuݭftA}RhTF)uQhF/`1нJ*Jo:#s@ 9QL*?#E:c&PY9VF9ށxR2?\_5js1E͡XX[>fPQ3@ԃNlRQid+ʝ}>J|m%_W"eW_\PrQ51M˔iʧ{5JI5ct@88ẺhVEoz攢z-V^fCQ/-eފA;7.ܫN]iԯ'jf oM\M-v^[k=_4ߕ_RJrլ6cgwtHq?#󝁶f"_ؙJUK, d 'G4j[rcsg?pOg~w+,>ǿύW4>jՁIJT*ݯMa )%un3+4Q=j\hy=8k\T”Ns>ԡKt"&cC'H5>7IobŬN'ӹ!o uRZ=DRWŦ]7Cw(B U"Q%ߕ8cXj Q/̛7w#-Fmb4 *򇱯،]I%xg%sf\' x5UX;ѾHku#l r>9"1ݑw>}R_},fo\3.ڕ ݺ4(wDtbח|?yÉk2):lxtOa&UWDYoڧ>4v)~h>;8ԆHl54ƸKqMG^RlX3­ĺMG;T~ᤑLRRC :?i{ߝ(Y#۶WFf 7-i$6ǹg;VOM,Bv-wFxVafH䟦8haq̥x]M߈ɇ5ήLw_`pOʓ۵}4VyJQv_ L'6|C';`̧J[wnŤJke~#_fg?>3sɓ)\j|k׍6㹍z8w`D৑YWy〮dy(W6xwXVkϖڰF2'X>'DDEV=;GgЀ]}3dXOКk׮[?fp'y9iQjϯU s6 })SI{y=6Jl]VJk#xJv9|}Z?).a:;W^?l4 q'zRD#Zܷ)gʍRq? 栧:LsvvUZnk@wiZvNXɎQU\?$Q:aU< >+ {,& KCAlui:wkL/4PiC]W!|5m%vWAv|k|,ni% x#Jmu2~[HXq*&5ݶٴVkf:-# ewS\[(}+I; H RU 2RAB􏡕VZ*ӠErDK'[t]h=sc~-,~ ē |@L] hnŽ6V;.Y~G -]#CiʧvB]H] JݗmBb "GorLFno6v|7=>vʾtC&@J~$~Z1NThh謭6u&?GApBX[S Y9h}kP7k >xb1Ou$A&1oWJ76u j5ץ\Jգ||z eIbTs|/\z|_xJiw;[b ol'Ǔ"?o.}]k㽤YJY/QVu&PW},.i\O:4EGx1^EK={?}TֿMZS: ֩dTm>tcTB _A2Rz)OEM_\C4<rd NV|B-<> Dk aZ}t=]-4I΃Hj5QmeB#+=RG@L\_wS[:֩IԷ%%bO~;Y{)PVyRۢO}\".Vxgi\2Nhc1]MP:;OE:zI^pfQ ]B@օ\ vIz*+P#TJe|s 6Y~gE+$*zܑ!0ɸ*p+J{!wpIE뭰z%\\U(k Yzar,,khGfffEm҈zf]wJX3n \/c/&瀢V]ښnoU\&E DbɱVs .aHYH臿BݩGz?9_cۜ[kĺ#Ş$}iZv(X7YI6>hP)5G'`?KD\rc:I xy4Kqnvr݋5wFX^dً;iȫ=uvRogkGuPr=miEcmZSnz/kuNf}ޝz8_޻K;YzLQ{Խt{|:}#tM ݋:he2d;l|Δ6]0*cD %ƋЙ]źR1n"ǬO?V?h6z}kiVD'U_>ˁXG1F?3X1ܲEi 1 /aޝx/$3feJ^G|=Z[^rka`a_ 7^Δg涐rTm?U+bѧ߼wd^3VG{niJ[VV<־rmڼ-^gYN 6qDJ\DZBOM[Mq$8߇Y;i 7;)*Z5}OaD/"Eb/ݣ7f Dd<߁yMYCMN ¯Ӌ>X ]s谨}vNsk6ݻQ}-Zq_.ZP!6-P@FS$Llc\ˍu}0M'0?Go;ݢ Q(Wu6e6Ry (H&DY4ěr\nM>j%ko{i|}RӇm(^V߯7_<_,-g1G]=yV+{\\8vP)X'Anof^iXag?^v{>]_H7Ls. yUauw8wQ[4MTNzD±4W3p}ms8L(O.eP{-;`#ީy={쾖7Y[=ͧEvyPsKRjb]o, 2+c흊5Q뱮4epWa, 7b>A[EqkeaA[6]{Ak(k6zʰl^ȫ?$,fXQi`IK^ ל4aivu3L3=㚕F`'Ay@J n VԻ=x}zc?k >YXRư,)ҫMHXj,PIh"|܈n?*`k3;ފd)j4IقR8h-yp@]c'#_0qz"P^ y +6KgqT.> uHz:>o;n.}js)l#p?H%N'KR,K_d mAg>)A;BOC~%5'0oͼy$n?B)>Y_=}}]p[Mikv/%}᷻.${ -c[FĽ7KGWh|{ɇb^B2`mAg6qI_CeN&#l2(l!ρ%t!sCc4Zd zP.[5Q3Ap-Н>Rg$A&>^ $9^K1m""ߏ@2@_qTGo5;$/m!Κé<~7ҥݵ~qCwȷ-xg=[ΪDŻzzs>ym[qخCZςs -L8VeA8e{ͣqO48.q Ll0DZ4BrIJԷM[Y9FhõSJDkx@3",Nyy2m{"^pYLYlK}d0<:c 65 + Z KjfQo(#?t) ew>7C: R­ dGh9jJ/~xTZyv=byҲ=Gsuo[=_;y=$=|%,}AUx[&}^x9x/(~[)|nn>?U؞E=w>ՕͥO|S#$%[)[w BjqjZ$PG 8@+9-?1E}CN Ue >LUWh)ء{i6f}[`*7z'um<5W`sҴU,>Oѫ"=5{ nW*h=||nݎΐe?.,H[geA[Є}@3|堋r4Htw8+F [MmだxXWj* e}"~r{iN'c-`}@Y 5ͩ.͵1 sҾw[98 w[Emxez֏a!;/}+dR|{z|Ƕ)N'>O~ĻP@5pc9ֻA0v?y`ܮ@UTksl|$a[ Lf|.H~'H,rw&QtT@A! {ynYKޟgbk˺7+E?(aYlQS%[?Ԟ,yCɀkIO,,Eʃ + +Hzi_ ;k@"oJҪkK~e K.c-6Ym+2^E_0iʐ{JY/~#r_ (:Ɯǟd;5VpU %BX>]+-y.$X_*h(*(dS{)n5&mA)ο@OE-^Ga{7,Pô@ ޟM9T௏y&p?Xr?XI(U֜<q1MRLbYp4K]"l'>(s.u}%i}1u{j:c+䳕|.POG~$=rtCatOjn;]Q%3hCP7wPyb0}sXI8C۞0uq&^ywl{O.P߸9L;}k7˺S&>?l"{v7@@b FY/aK6ڦ_/A}s͏['g[eS7[vmYrLn0Lh1+#)S܉28c;׶v[,ˬ|}m͇`L+\IƇZmi-;otBb?eaJ!$om?PqA^V"La =knHaw @(@-“p%[!C|OE׈>RR&1f3hsĵ+,-|宰(~f>Y8/f {F/P}փ ZcZ&mT@u]{/14VYH?J[b1޾?~`q>|:{@w7>@~g|D\3̖o,uz{ů,%k/y^}|~}|HZ-\|~[SoPRV k߉R=M3i QYl3PnOG}۸}7 iWې;oDӋVQ"PV/;O` q{nvdvǝ.e& +oTќq"ߘHs[h6?-GU3> ,Uyi`5 ib5!|:9RP7) ޑcizܻhm}m.!b G qB_O`O7Po,ަyw[^J7zʿ7R\KjK-TUgK͢]ַoŷ4)ׯI;Ҙ|g97|ו7ƿy__*v7r+ip[8?{Pݒqh FY5sPK-oXi7{佡7iB~f} ME!YbgEi{`~%d)w;p->WH%F񽗐:~aoA!|=Wg񍘾BߌBޘ ߎ Yss+/e XQ"bl &$.5iU"XQ1'u!VK&~|f"ԝ.?  wD0@ @ @ @ @ @ @ @ @ @Q2eRF-ğڶAj-竳jdS)*ԄR P$~Yaq2p3-!B-VEU (WߑK 'ruIp3t(NeOУ at4%D W~FXjW~@aJLim[>Q,]\d,&[Eޙی^X_7XauV`kWk3Jl? v`b` [v`w_ vη9`g /+"/-`g ixNgd~4}m]& &}U<}Ͼ8Y<>??`'g` b|R>FdzV<jD;^}D#{wwwgki2؛a ^7k;j~#ڄy?^9_*CC2`{lb/e/l^0lOE;B> NlbCeE{ =3˜\O&lBoqk1!|L mQ)ld4XeG8xz`Çl·Pb L _Z``} ֻ R{V'.zt{y[8ZuXNs;N֡oۻXֶimʰN֪eEB+Edrᬬ7XX+ eʱ2G5gsBq%`4-8B 2`6uq-4 "j` J8PP2,Qgk{ endstream endobj 33 0 obj 15312 endobj 32 0 obj 50420 endobj 10 0 obj <> endobj 35 0 obj <> endobj 34 0 obj <> stream xy tU>u!# C0D QB 2f $D#m@0Y}4**rsin%4"7I_뭷[+l[NaOgiqrOΝ:!Dz^'2>LcL͉©c'_^#Y5vң} ( 27&`VǡU' {qgιoc'MϥV8ɹs6l#1u]ĊxJ$_CEs&o.h zl73]bc7R3.9R/zK҇ItEx\Oc~Q-?#o_ߒߕ+#Gϖ-K,-+--ZJ-/Z^lyͲ۲rz;J2EFED٣5&jNԼQGlm!h[m-6۶Vl+mmU٪m?Q##E#/_k#v8;k;v甜gq:G;KrB\a.+5޵ʵεuuu7sGVXw'www/wtw;۝.r/vr?~};b37-/mc}/B9h {UJv}{|˼:nK6أ'=ҥ ؃j1g%"]~J ߑȕq|g,[}ayRa a=£FʋǦ6m&Vvq5u[m6GM;ٛ~Z{/f`~A#w$9:zS3Och| P` #j*v=: {|{nn#=psrǹ'gaM[)KLJLNx㯰-#,؃!.C⠨.)euxU,mE*ӢX \, t1ECDM$N D{~}Ui yvV;]}TVTwVݵ::KuOc.;/G\tY,{5zOz?>]]]}ܻwwww66{^5y^W^T%jnWRuꧪ)YYy3SzF{=y{=<{z{yxz{z{z==qVӥ]~nvŷ/6kS~>S?5_Go,HmIf LN2)>2 wl5@PcRSRS5HjJpE숕NrZ2VԚP,8@uDBILRWF)R>ԗQ@~zQ`ʠ!IPFY4M#iO2ZAi@ӋmLk9Ie6KNE> G0N4ƫ4Tf#4NizfXVR/H?h͗Wh=FZņz&SIy8-gY( SMY R@B KQӣjc5DmFKIZLi%S3T fm&HR͕HPUN'@9-~AvtYkoFa^< yPGRWH'O{]n)4 :~=t+iɷk9]!uyR!vHb:K3^g/JXk''S*t><C>EQY5f}lg{YixdKy6& KNCr n*V ٣rV/VPivt<:ꓑh RAB-=)iJ')'_̖tA`OSVtЍVRt^BHw E4pv%Fm2)AY,Ýqme^\,2Li^ƣer}v`zB^酾!YhoF^qz$)FNx<J &[~pfcک"ŅzUd\jvXux/+j!o7QKxi4c)͜PLŬX*rRŦbsq@)RʥJZj(5JͥhJdR%+JPi4U+d#YBU+J C#cpbw~9sp1njPpv1=11mPti̯͌;/<}xͪGML_ٮOXZbzzbAio0Oe؜'ٟ6*JoJ_X3e1%$*Ēy,+ o2Fdf's̙#ठत53W򃎈Dg݁9 ,邶rNhynݡF)QvjcfQ_fƛcAII J3,ʔ/~CK;%J*M"UU 88#$Dծ_0L``vĖRginO ;w܉QCrM]\h@j,䇙aiݹ꘰a!fuA#CbLu YE8x7Y%c6JNWLD cYqҭ鋴N:9*f]|α=84-zޡ̽yC-NDGرS3^2`tV{ ϝBSnvx`b4͊d$Ȓ(r2C`SIr#AlIndHep\3]&0aE]& ;LjWsw-F'owئmfy ggMHbPn\A,Qa!yV)[PMC$3/kbqFgȝ\+?@.ݕnBaXtYs_{s.O:lԞ[פ4P9C[km|i;';$|ub|Q6dumT)C§[5ʳʵ Q)D!XA:Ϋ13)N7[gϜ܉ObZ$/x^9k'. ڟFʘ6GWFr=-ZU峯 vV9.o—.*uJTK\$+WPL 3G>;†O,byn骜uk #~17"tЬTRLq;X#bVޗIfS~`okg3")A!v%X nn f$F$ _k-Pgh_sۚo^^K3Md4$qQ\?C$mA~2ctXbFV,RwylcF2Q K?=Kh<2T,=[Q KKiv;IR0kT YcX:0YE8bLFbQrM.j)OO:*Av^K!Y"x')ȫn4[gy%W N@:Mo0 1e..7/ADY1_&-F#ؠ$֟Nl.t;K"q63E76\&JX0,? NSǚ9DjYԏ23W_1q*Ȱg/D5`Q[FK e4Ƣo!uI~ybd.nbj5 hoɠ$m V%)~Aوs.l?@qqz3|o0l^4ߒὲ/ZSo JldखM| @  ,.?S 24Z [/A%1mb(Cb,Y/ϠM3|YL5fOr=B`/ oqg`LH@|\?3y|#):|'z0NuxD_(VrΰSOح=]oQ8kL"u(bm{)>Z1Ctس dW1AuG!>i@G.H? A _&䶆W=0#p`~XW @W TY|BXHK_+,]?=*,Yks*/΢Y 6,03\,cG)lr~B *vD8̊Ƴ; gGfOgf#gh":,5gDY/G@q@2>kg)RD~_wċA w޾~n ?}; J]8_GIn^dTu7ݤI[y1Jۈ:$5jDwxJY\FLe.,M@E7b9nu/jDԺP]$}9b{zD勀K|_]IJ`+Y+n0v L-_䋮bhm;Uh< {p\YɤHs;.?ŋ~)BjF7;kiKkGwbPMξw wK;mL)[c"]UF*;nW#+%`]/m S^0b akƷP-E4?4yY٬MfQi| eCsl8/3%|Ɵ.V*k5Ƌ bj?UJ+ʊ[|y#lX?ByBKTV%%#Tyq4\㏕EP X"/ \ 4U9G4>K3gX |OӦ)ZA|dOL*'X|7q ya<e .A ya<7BxJNY$Gʣ4>RxϮ#CP( cV> ͇5!AgOxT h9|"eޯx/ߧ GjOG)SUIݭƻj^'' QKxRVJޥOxgw;VOx{x|lox[ [Vo))-Kxƣ-Jtoq]w⋳=wعfQfQJTonSfMCfyP$+%IDDp%"k> endobj 38 0 obj <> endobj xref 0 39 0000000000 65535 f 0000185192 00000 n 0000110099 00000 n 0000000015 00000 n 0000110077 00000 n 0000110804 00000 n 0000121205 00000 n 0000130395 00000 n 0000148082 00000 n 0000159604 00000 n 0000176498 00000 n 0000110481 00000 n 0000110289 00000 n 0000110614 00000 n 0000112239 00000 n 0000112017 00000 n 0000121183 00000 n 0000121162 00000 n 0000122659 00000 n 0000122425 00000 n 0000130373 00000 n 0000130352 00000 n 0000131825 00000 n 0000131609 00000 n 0000148060 00000 n 0000148038 00000 n 0000149500 00000 n 0000149290 00000 n 0000159582 00000 n 0000159561 00000 n 0000161052 00000 n 0000160824 00000 n 0000176476 00000 n 0000176454 00000 n 0000177937 00000 n 0000177715 00000 n 0000185170 00000 n 0000185149 00000 n 0000185246 00000 n trailer <] >> startxref 185294 %%EOF goattracker-2.72/win32/0000755000000000000000000000000011604145622013413 5ustar rootrootgoattracker-2.72/win32/mod2sng.exe0000644000000000000000000003000011604144016015454 0ustar rootrootMZ@ !L!This program cannot be run in DOS mode. $PELN 8,`0@@5w 0.text8`P`.data0@`.rdata@ @0@.eh_framP$@0.bss``.idata&@0.CRT ,@0.tls 0.@0U8CfU(CfUS4B@tD$D$$Ѓ $@@ EED$1@D$`@$`@D$ ED$y`@uPs1@aD$`@D$`@$F$$C1@D$C$&`@D$C0$`@D$CP$i'U$C&U$C&USE=w;=rKD$$1[]=tY=t=u=t&tE=uD$$+tst$vи럍&1jD$$ tQn$ и\t&$иfCD$$'D$$  D$$gu U$@@RteD$@@$tD$`@$P@Ћ 1@t1$)@@cRt*D$7@@$Vt $1@ø말U$@@Qt%D$K@@$ t $P@ÍvUWVSTu } D$ A@F$WDž D$"A@F$:Å }1<$D CF<u6Cd@ @`@18C9~@=uA @`@~1f<$ d@F@`@ 9<$@`@D$,D$D\$(D$D d@D$0L$D!d@f tdD$L1D$HfS9|T$HT$H9}C`t7ع 0@*)ˆD$L)yD$H\$D"d@T$HBL$0 ʈBB#d@BC\$DL$,9\$(D$,\$$\$,;1@@=d@-D$HD`@D$(L$H8CT$,C1L$(L$DBCD$01ɉL$`vL$Dt Z]v B]]XvQD$L11pL$L Ή ZD$|$@uB__Xw$A@XwD$L1띀xu_uB^D$L11D$L1ۿpXD$L1ap\$LL$01BL$ƄIC L`@1fv dAC1ۉ"fH8JuH8JuCA`8 tډF99kI dAC dACPCPCP CPCPCPCPCP CP$CP(CP,CP0CP4CP8CP<CP@CPDCPHCPLCPPCPTCPXCP\CP`CPdCPh CPlCPpCPtCPxCP| C$C(C,C0C4C8C<C@CDCHCLCPCTCXC\C@ÍC4I3 dA΍v HKHKJuH`@\$Ha@A L`@vD$HD$H9d@H`@D$,|$,\$$\$ D$D$$1@+\$ D$D$$C \$ D$D$ $ `@ \$ D$D$ $ `@ \$ D$D$ $ `@ D$$D$Ld@@D$$=d@~)|$La@1D$$FG95d@D$$D$$D$L|$LuCD$$wD$$gD$$WD$$GD$$7D$$'D$$D$$\$ D$D$4$ D$$D$$D$$6C%L`@D$$=L`@~zD$LfD$$xT$LR dA1vD$$QFD$$AFD$$1GAuD$LL$L9 L`@$ $oA@ 1AH`@T$Ha@\$L\$01_1}$d@@D T[^_D$1@D$=A@F $< 1@H1@w=}D$D`@D$=A@F$ $XA@ $@A@ z$A@ d$%A@ NA1U(E EED$ D$D$E$j U(E EEED$ D$D$E$4 fU(E EUUEED$ D$D$E$ fU(ED$ D$D$E$ EfU(ED$ D$D$E$ EU ÐU(ED$ D$D$E$h EU U U ÍvU(ED$ D$D$E$ EU ÐU(ED$ D$D$E$EU U U ÐU1]É'UE u#UD$T$E$ t&tظ fUS0CE :v1=`@t `@] C$A@\p`@D$A@$4CD$A@p`@$Cp`@ Ct?Ct5`@] ED$D$E$CCC$p`@`@]  C CtЃ Cu] CC뚐USX5 PX1Щ 1t `@fy `@t `@t `@t `@t `@ t `@@ u.=vx!@t `@[]Á `@Ɓ `@ӐU]$Cuu D$D$@\$ $B@Et$$D$UHɉ]Éu։}u ]u}]ÍED$D$$ tvE܃t)@t$ED$ ED$@D$Eȉ$|$t$$KE܃t@tED$ ED$EԉD$Eȉ$n_\$D$$ B@&'U8`@]u}t ]u}]øB@-B@`@~ڃ B@~(=B@u5B@u B@u B@t&u\CuUC  B@s@C S9tc tuET$$B@B@:@}CUB@r ffxo)ʍ<:}U5xA)ʍ<:}Uf8U)Ϲ} B@&)U븁)U늉D$$TB@*U1@tС1@P@1@uÍUVS$)@t-t4$)@fu$@%@Z[^]Ív1ÍC$)@u뽍v'U `@t`@끐U]ÐUVS`@ue[^]$`@`@t+$u tC4$Ћ[u$`@e[^]Í&'UE tBrufZ`@u`@$`@"ϐt&`@t`@Í$`@ US`@]u 1]Í$`@`@t9uD9t@u$`@1]ËPQ$$`@qڋP`@ܐUS`@u]D$ $øt܋E$`@E C `@`@C$`@1롐%C%C%C% C%,C%\C%XC%DC%@C%PC%`C%HC%dC%4C%TC%LC%<C%C%C%C%C%C%C%C%C%C%C%C%C%C%CU$|@Ð)@@0(X`( 0Px (x`X`x XxX@8@Xx 0X0  8` p`0 Hx X@0 X`(0Px(x`X`pXXxX@8@Xx 0X0  8`p`0 HGTS!@4)@libgcc_s_dw2-1.dll__register_frame_infolibgcj-11.dll_Jv_RegisterClasses__deregister_frame_infoUsage: mod2sng [channel] [transpose] [channel] is the channel to leave out (1-4), default 4 [transpose] is the halfstep transpose added to notes, default 0rbSource open error.wbDestination open error.%dIllegal channel number.208 patterns exceeded!Converted successfully.@@@@@?@?@?@?@?@?@@@@?@@mingwm10.dll__mingwthr_remove_key_dtor__mingwthr_key_dtor @Mingw runtime failure: VirtualQuery failed for %d bytes at address %p Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. <xl "2P^p"*2<FNXbl "2P^p"*2<FNXbkDeleteCriticalSection~EnterCriticalSectionExitProcessFreeLibraryEGetLastErrorQGetModuleHandleAlGetProcAddressInitializeCriticalSection LeaveCriticalSection LoadLibraryASetUnhandledExceptionFilterTlsGetValueVirtualProtect!VirtualQuery7__getmainargsM__p__environO__p__fmodec__set_app_type_cexit _iob_onexit_setmode_winmajorGabortNatexitScalloc_fclosejfopenpfreadqfreeyfwritememcpyputssignalsscanfvfprintfKERNEL32.dllmsvcrt.dll @@0C0C``@ Cgoattracker-2.72/win32/betaconv.exe0000644000000000000000000003100011604144016015705 0ustar rootrootMZ@ !L!This program cannot be run in DOS mode. $PELN 8.`0@ H.text`P`.data0 @0.rdata@"@0@.eh_framP&@0.bss``.idataH(@0.CRT.@0.tls 0@0U@BfU0BfUS4@B@tD$D$$Ѓ $@ EED$0@D$`@$`@D$ ED$``@uP0@^D$`@D$`@$U $F,B0@D$C$``@D$C0$``@D$CP$~i'U$$B&U$$B&USE=w;=rKD$$1[]=tY=t=u=t&tE=uD$$tst$vи럍&1jD$$ mtQn$ и\t&$иfCD$$'D$$  D$$u U$@@6RteD$@@$)tD$`@$P@Ћ 0@t1$)@@Rt*D$7@@$t $ 0@ø말U$@@Qt%D$K@@$t $P@ÍvUWVS [vibdepth] [pulse] [vibdepth] decides whether to halve vibdepth (1=yes 0=no), default 0 [pulse] decides whether to halve pulse speed (1=yes 0=no), default 0 Converts GT2 early beta (47 instr.) song to GT2 current format (63 instr.) Optionally, halves vibrato depths and pulse speeds.%uERROR: Couldn't load source song.ERROR: Couldn't save destination song.mingwm10.dll__mingwthr_remove_key_dtor__mingwthr_key_dtor!@Mingw runtime failure: VirtualQuery failed for %d bytes at address %p Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. <̃܀x<|ȁ؁2B`nЂڂ  *2:BLV`jr||ȁ؁2B`nЂڂ  *2:BLV`jr|kDeleteCriticalSection~EnterCriticalSectionExitProcessFreeLibraryEGetLastErrorQGetModuleHandleAlGetProcAddressInitializeCriticalSection LeaveCriticalSection LoadLibraryASetUnhandledExceptionFilterTlsGetValueVirtualProtect!VirtualQuery7__getmainargsM__p__environO__p__fmodec__set_app_type_cexit _iob_onexit_setmode_winmajorGabortNatexitScalloc_fclosejfopenpfreadqfreeyfwritememcmpmemcpyprintfputssignalsscanfvfprintfKERNEL32.dllmsvcrt.dll!@@!@BB@`@Bgoattracker-2.72/win32/sngspli2.exe0000644000000000000000000003500011604144014015647 0ustar rootrootMZ@ !L!This program cannot be run in DOS mode. $PELN 8"6d`@@ H.text!"`P`.data@&@0.rdataLP(@0@.eh_fram`.@0.bssbp`.idataH0@0.CRT6@0.tls 8@0U@DfU0DfUS4S@tD$D$$Ѓ $@ EED$@@D$p@$p@D$ ED$Xp@uP@@>vD$p@D$p@$$& ,D@@D$C$Xp@D$C0$rXp@D$CP$^i'U$$D&U$$D&USE=w;=rKD$$1[]=tY=t=u=t&tE=uD$$tst$vи럍&1jD$$ MtQn$ и\t&$иfCD$$'D$$  D$$u kU$P@RteD$P@$ tD$p@$`@Ћ @@t1$)P@Rt*D$7P@$t $@@ø말U$P@Qt%D$KP@$}t $`@ÍvUWVS,D$dP@E$1-\$ D$D$$xB1f B1 @=t:uDAu1]v\$ D$ED$<$F;u|$,[^_ÍvUWVS$p@1ɍv @9A1 @=t:u@AuЋ$p@EvUR<@1EM@1 = p@$" 1,[^_1UWVSu] } ~d{CD$<$ ua<$tp[^_Ív$S@ [^_Ív$tQ@ [^_ÍvD$@@D$S@C $ @@~p~ @@{<$e$R@, [^_ÍvC$t 1Cf$8S@ +f@@{fUSU )BDHIJt t@[ÐU(E EED$ D$D$E$^ U(E EEED$ D$D$E$( fU(E EUUEED$ D$D$E$ fU(ED$ D$D$E$ EfU(ED$ D$D$E$ EU ÐU(ED$ D$D$E$d EU U U ÍvU(ED$ D$D$E$ EU ÐU(ED$ D$D$E$EU U U ÐU1]É'UE u#UD$T$E$ t&tظ fUS8DE :v1=p@t p@] `D$`S@lHp@D$mS@$DPDD$S@Hp@$'@DHp@ PDt?@Dt5p@] ED$D$E$C@DPD$Hp@p@] DDtЃDu] @DPD뚐USX5 PX1Щ 1t \p@fy \p@t \p@t \p@t \p@t \p@ t \p@@ u.=vx!@t \p@[]Á \p@Ɓ \p@ӐU],Duu D$D$@\$ $S@Et$$D$UHɉ]Éu։}u ]u}]ÍED$D$$ tvE܃t)@t$ED$ ED$@D$Eȉ$|$t$$[E܃t@tED$ ED$EԉD$Eȉ$~_\$D$$S@&'U8`p@]u}t ]u}]øLT@-LT@`p@~ڃ LT@~(=LT@u5PT@u TT@u XT@t&u\CuUC  LT@s@C S9tc tuET$$ T@LT@:@}CULT@r ffxo)ʍ<:}U5xA)ʍ<:}Uf8U)Ϲ} LT@&)U븁)U늉D$$S@*U @@tС @@P@ @@uÍUVS1@t-t41@fu$-@[^]Ív1ÍC1@u뽍v'U pp@tpp@끐U]ÐUVSp@ue[^]$p@p@t+$u tC4$Ћ[u$p@e[^]Í&'UE tBrufZp@up@$p@2ϐt&p@tp@Í$p@ USp@]u 1]Í$p@p@t9uD9t@u$p@1]ËPQ$$p@ڋPp@ܐUSp@u]D$ $øt܋E$p@E Cp@p@C$p@1롐%D% D%D%(D%4D%hD%LD%XD%HD%`D%PD%dD%pD%lD%tD% [length] Splits patterns of the song into smaller patterns with [length] rows, searching for possible duplicates and probably making the song take less memory. For safety reasons source & destination cannot be same, because a splitted song is harder to edit. Always keep the original! Default length is 16.ERROR: Source and destination are not allowed to be the same.%uERROR: Couldn't load source song.ERROR: Couldn't save destination song.mingwm10.dll__mingwthr_remove_key_dtor__mingwthr_key_dtor`(@Mingw runtime failure: VirtualQuery failed for %d bytes at address %p Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. <x<|2B`n  *2:BLV`hr||2B`n  *2:BLV`hr|kDeleteCriticalSection~EnterCriticalSectionExitProcessFreeLibraryEGetLastErrorQGetModuleHandleAlGetProcAddressInitializeCriticalSection LeaveCriticalSection LoadLibraryASetUnhandledExceptionFilterTlsGetValueVirtualProtect!VirtualQuery7__getmainargsM__p__environO__p__fmodec__set_app_type_cexit _iob_onexit_setmode_winmajorGabortNatexitScalloc_fclosejfopenpfreadqfreeyfwritememcpyprintfputssignalsscanfstrcmpvfprintfKERNEL32.dllmsvcrt.dll`(@ (@EE8p@Dgoattracker-2.72/win32/goattrk2.exe0000644000000000000000000230500011604144014015645 0ustar rootrootMZ@ !L!This program cannot be run in DOS mode. $PEL N 8z @@  \ .textpxz`P`.data~@`.rdata @`@.eh_framp R @0.bss@ `.idatah @0.CRTx @0.tls z @0.rsrc\ | @0U,PfUPfUS4LEItD$D$$Ѓ $@4X>+DEED$$cHD$I$ID$ ED$V`pLuPU(cHn@BUD$ID$I$BU$W P(cHD$C$U`pLD$C0$U`pLD$CP$Ui'U$P&U$P&USE=w;=rKD$$U1[]=tY=t=u=t&tE=uD$$Ttst$vи럍&1jD$$ yTtQn$ и\t&$иfCD$$+T'D$$ T D$$Su AU$HURteD$H$UtD$I$pIЋ Ht1$)HWURt*D$7H$JUt $Hø SD말U$HUQt%D$KH$Ut $pIÍv$[DUSClr8I4Iu jLtDYF$RYF9l$RYF9e$RYF9^$RYF9W$kRYF9P$TRYF9I$=RYF9B$&RYF9;$RYF94$QYF9-$QYF9&$QYF9/$QYF98$QYF9=$QYF9F$nQYF9O[Ð4ItDYFDYFDYFDYFDYFDYFDYFDYFDYFDYF YF9 4$>YF9 D$:D$$$z4Iy` YW D$ ʰHD$D$$$1vW8Il 54Iu jLtDYF4$;>YF9l 4$$>YF9 4$ >YF9 4$=YF9 4$=YF9 4$=YF9 4$=YF9 4$=YF9 4$=YF9 4$l=YF9 4$U=YF9 4$>=YF9 4$'=YF9 4$=YF9 4$<YF9 4$<YF9 D$:D$$${4IyYED$ HD$D$$$1U58Ix 54Iu jLtDYF4$:<YF9 4$#<YF94$ <YF9y4$;YF9R4$;YF9+4$;YF94$;YF94$;YF94$;YF9{4$k;YF9T4$T;YF94$=;YF9 4$&;YF9 4$;YF9 4$:YF9 4$:YF9. D$:D$$$z4Iy41ۃYD$ HD$D$$$1S8Id 54Iu jLtDYF4$?:YF9| 4$(:YF9e 4$:YF9> 4$9YF94$9YF9X4$9YF914$9YF9 4$9YF9 4$9YF9 4$p9YF9 4$Y9YF9^ 4$B9YF9 4$+9YF9X 4$9YF9% 4$8YF9 4$8YF9 D$:D$$$4Iy-YED$ HD$D$$$1Q 8I54Iu jLtDYF4$>8YF94$'8YF9 4$8YF9 4$7YF9 4$7YF9 4$7YF9h 4$7YF9A 4$7YF9 4$7YF94$o7YF94$X7YF94$A7YF94$*7YF9O4$7YF94$6YF94$6YF9D$:D$$$~4Iy YED$ %HD$D$$$1O58I54Iu jLtDYF4$>6YF9k4$'6YF94$6YF9}4$5YF94$5YF94$5YF9h4$5YF9A4$5YF9 4$5YF9k 4$o5YF9D 4$X5YF9 4$A5YF94$*5YF94$5YF9l4$4YF954$4YF9D$:D$$$~4IyYƃ< E E E t$E܉D$ ED$\$E$k4I8I<[^_D$$$4I8I<[^_EoDYFDYFDYFDYFDYFDYF DYFDYFDYF =DYFEDYFLDYFDYFZDYF a ~nCi{E< N}~E}9}NE܉EE}~Mĸ9~Љ…v}܉}EH~mMhC} NE =~EE9E}܉}E}~Mĸ9~Љ…<E܉EE}wjR~eW`C} N=~}9}EE}~MĿ9~׉EEv}܉=$IEHN}؉=YFE@N}Љ=0NEģDNNCw=LI8~$INHIu)  }̅u"~O~ U,5HIu2"~LIV~ \f"~LI]~ c Ij HI=DILIP΃kP˃SPȃ;PŃP7PPOwolYFwe@lYFTIT$$hIT$ dIT$D$LID$HID$`ID$ \ID$YFD$YF$Ovl[^_ÍS ȓNDQN~*C%}~MĿ9~׉!EH~*M%}~MĿ9~׉E]RTWK}~Mĸ9~Љ…E!=LIE~$I~FCAS$N}ȃ }O~ }ȃ }Ŀ9~׉vEEH~FMAS(N}ȃ}O~ }ȃ}Ŀ9~׉2EERxWoC,NUȃUJ~ }ȃ}ĺ9~…EE+v}̅}x4~|9wPЋ} N-=~}9}EE= N׃}UJUĺ9~GEEEvC>C{}ԋU< N}}~E}9}U܉UE}=$NUȃ UJ~ Uȃ Uĺ9~}܉}EEHMSUԋ} NU }~EU9U}܉}E}=(NUȃUJ~ UȃUĺ9~}܉}EEIR@W7SЋ} N =~}9} EE=,N׋UȃUJ~ UȃUĺ9~ EEDIsHIf LIȃQQ YQ9Q݃*PσPŃPJl[^_)#$t5@YFhfH_JVK ! PI؋ LIvA?C6PI؋ LI vx<439* N}[ QʉUU9U9=YF =YFUԉNNfxwX4~S9N} NE }~E}~Mĸ9~Љ…C EvCEԃ>~PCK{E< N} }~E}~Mĸ9~Љ… EH~PMK{E< N} }~E}~Mĸ9~Љ… E}RWC} NE =cEWfxwl4~g9bU< Nlj}N ~E N}; }O}ĺ9~… EEvC >~lCgSU܋} NU~E}=$NUȃ UJ~ Uȃ Uĺ9~ EEH~lMg{}܋U< N}L~E}=(NUȃUJ~ UȃUĺ9~' EE5R,W#C} N‰U}~E,N}ȃ}OUȃUvN~HNBNtYF@YFYF~HYFE̅LI LIfD$N$;EE؋}9};Ew}}v}}؋E9EfU=$Iw$I$8H{\S~a uUWVS]} C un\$D$$sLzsLt<;t< t< t< t<$tA1sLC$$PЀ wtPЉ7fu.v[^_1sLȃW0< wҍJ417C$JvϹUWVSYF$DD$D$$Q 1ыƄ cыƄ fыƄgD$LH$;ÅD$YF$qD$YF$aD$`I$QD$HI$AD$LI$1D$`YF$!D$hYF$D$dYF$D$DI$D$@I$D$HYF$D$lYF$D$dI$D$pYF$D$hI$D$PI$D$tYF$qD$xYF$aD$|YF$QD$YF$AD$lI$1D$TI$!D$YF$D$YF$C \$D$$sLsLt<;t< t< t< t`]FD$`]FD$OH$sLVC v\$D$$sL sLt<;t< t< t < QvC t\$D$$sLsLt<;t< t< t < vC t\$D$$sLsLt<;t< t< t < vC t\$D$$sLHsLt<;t< t< t <  vC t\$D$$sLsLt<;t< t< t < vC t\$D$$sLsLt<;t< t< t < vC t\$D$$sLpsLt<;t< t< t < vC t\$D$$sL(sLt<;t< t< t < vC tu@\$D$$sLsLt<;t< t< t < vC tD$jL$C uZ\$D$$sLsLt<;t< t< t< tpID$pID$OH$sL_v$\s}] Dž3<-|$ D$\$N4$ <$,[^_ÍvX\$$ƉD$<$|$ D$t$N$|$ D$t$N$vD$<$kvFD$$zÉD$<$|$ D$\$N$@|$ D$\$N4$"FD$$ÉD$<$|$ D$\$N$|$ D$\$N4$1,[^_ǃ@sL.insƃDsLUWVS|D$3H$@sL;ÅD\$ D$D$EE$J6Hut;Hu5DuL$ N5DuL$!N$E$E$E$E5DuL$&N5DuL$n'N5DuL$V(N\$ D$D$DuL)N$UDuL$EEEMЉ $Ẻ$}̍<89}}o E+EЋu̍N}ԉ߉C<$F;u|}9}}O}& E+EЋM̍NΉ}ԉ߉fC<$?F;u|}ԃ}9} } E@EԋM+MM̍NNẺ]v@9~'BA=:utu*\5]Ԉ@9f]}u }ȋẺEġDuLUԋMЈ"NEЃ}EHuJHuG$WM3}U9U}~}uEĉ}N@9~V=O߂Nx느Nt~ʺʍvDuLuƄ"NEЃ}74)DuL NQu 'N@|[^_f}ԍv$tF9|f}ԍv$XF9|}!E@E@Hu7EEDuL$賝$E$E$՗Ƌ=DuL$ͽ N=DuL$赽!NlYF=DuLƄ'NƄ(N $zEԉ$oE$dE$YE=DuL$HF$NEtDuL'N$E\$ D$D$DuL)N$=DuLUB"NEEЅtZ1uމ}f4$褼N4$薼ˆNNYGC;]|‰}̉u=DuL}E%t}%UUȍ$N\$ D$D$E$=EUp€ރNNFEtƆރNNFƆރNƆNe5DuL$費 N5DuL$蚻!N$舻E$}E$rE5DuL$a&N5DuL=xYF$CD$|$$k@%N5DuL$'N5DuL$(N\$ D$D$DuL)N$DuL$hEEЉ$袔Ẻ$蟺G}̍<89}z}eE+EЋM̍NΉ}ԉ߉C<$GF;u|}9}#}E+EЋu̍N}ԉ߉vC'<$F;u|}9}}MAMԋM+MM̍NNẺ]@9}'BA=:utu*\5]Ԉ@9|f]}DuLUԋMЈ"NDuLuƄ"NEЃ}xDuL"NDN=DuL'N^v4$4$ظSv}ԍv$F9|f}ԍv$褸F9|jQI1G}ȋẺE ŨNNƄ"NƂNƂNEHƀNƀNUBUčMĈ#NʀM߂NNAMȀ}EEE+E̅MỦUԅ}Aƒ~M]Ѝv]Ȉ߂NNC])}ƒ~Ѻʋuu}7UƂ߂NƂNMMȋEEUBUOMAMCẺEԉE)‰ЅHMMЙE)Eԅt}M~EUڋEȉEЉ]E]Ј߂NNC])}ȃ~ѸEMvƒ~ރNNF)uWUBUuNubE@EEEE]ЋU]ЋMM]MЉMȋEE~]M9M}{E9E}s+Eԅ+M}B~UMԋMЈ߂NNAM)E}Eԃ~ϸȋE+Eԅ~]MtP}~U]ԋ]Ј߂NNC])t}Yȃ~ٸҋ]ԁ}#MƁ߂NE@NAMȋEEeEЉEȋUUTEȉE]ԋEЉEȋUU5}NjMƁ߂NE뢋UUE UȉUUЉUȋMMUWVSN܅N111 L19}Bt#Htuڀ8uՀxuπxu1ɐyLGuN5܅NEUR<}L1EM~L1|$ D$D$ $`N|$ D$D$ $L<$¥~L1}ދ|$蛥\$ D$@D$4$$z\$ D$@D$$$S\$ D$@D$$hG9}|$9N}|v4$4$C4$פC4$̤C4$C4$趤C4$諤C4$蠤C4$蕤Ct$ D$D$)N$蠿G9}h|$NË|L$ D$D$$N^||$ D$\$$N<<$É|$ D$D$$߂N|$ D$\$$N<$辣É|$ D$D$$ރNԾ|$ D$\$$N踾<$|É|$ D$D$$݄N蒾|$ D$\$$Nv<$:Dž~EL1ۉ}|<$|$ D$D$4$2C9}6D$D$^HU$ D$D$cH}<$ƽ|$落twD$uL$sLH1D$$>Cu}3?1f}N@=t$߂NxNt~κ΀}4~ L[^_1fu@N@='tڊANyဈ@NAND$D$YH]$ؼ1ۅp|D$ D$D$ $N讼|T$ D$D$ $`N舼|L$ D$D$ $Lb|$ Dž~L1ދ|$|\$ D$@D$4$$֠\$ D$@D$$$诠\$ D$@D$$Ļ|B9vDž}9NDž}Dž }Dž}}1ۉ}|4$5}4$%}A4$}4$|}D 4$} |4$֟} \4$}A9}|}}t }HЃ}4$|舅|t$ D$D$})N$|C}B|}tp1}Ɛ}$N}$ˆNN<Pw NCF;}|}|*}tmH}} v@9:u\ 8\u芜 |8|u؊ \8\uȋ}k#N}B}}} }| $| Dž}|$VUUU)ʉ}1} } }߉<$蠝É<$薝<$|舝|}_Ot^`57g1Ɉي} }LF;}a}}9|܅N@|0|L$ D$D$<$1}DŽƄT9}@@u܉}?Dž}?1yv}$R}$Du[}ADNTv;}~} F9}A5T\}\D}} }tq}pރNNAtƁރNNA}9wƁރN}NAF9}\tN N@9}}1=N=N=u⍕}1Dž|| |Lƅ }Dž}<H uh }t\C`<\ }  }}} =o C{ }}Q Ct }C<i <9 < << 9럍vEE=fE܅M܃mKPu$T>tE؉D$EGND$E.N$v$>TEvUTR` YF9uӍJ5YF9uˍJ5YF9uˍJ5YF9uˍJ5YF9uˍJ5YF9uˍJ5YF9uˍJ5YF9uˍJ5YF9uˍJ 5YF9uˍJ 5YF9uˍJ 5YF9uˍJ 5YF9uˍJ 5YF9uˍJ5YF9uˍJ5YF9u˃ YF9Vv=ēNx*=@YFC=NDuL|$T$$B^8IB=N @I DYFN؅5ēNt@YFNȓNL[^_ÍvH18I8tu 85ēN=NNzNoNdNYNNNCN8N-N"1VNUWVS,8Iu=xi vDuL=u@=tgNJw9u㊐NI9}JNfNJw#tJwNI9}JN@=u1EHv} L1҉} Bt$X9uN9}KBuߍv}Gu}iMNN1 v@BA=th:uN9}Kf L1҉}ϐHtIw N9}IBuى}GhJiEDNNtC JHB@uE+EƀނNƀNX[^_UWVSM }E;NN9}CB@u1}>u f@=teNZw9u㊐NK9}BN̊NZw#tJwNK9}BN@=u1EPv}u; L1ۉ}fCt H9u9}ACu}Gu}!}i]NN1@BC=:u N9}A f]tU L1ۉ}fPtJw N9}BCuى}GTf L1ۉ}אPtJw 9}BCu뫉 L1ۉ}vCH9uN9}AىU}tU}iUNNHKJ99}K J HKJ9~Z[^_Ã}ނNNJ HKJH99|i]NN1@BC=9:u 9}A ߋE;Nf9~CB@u1}Buv@=INZw9uߊN9}BNɊNZw"tJwN9}BN@=uނNNƀNƀNHKJ99~K J iENNKJH9m9}J HvUSE)NN HIJt t@[fUSU] xJtM=)ЀNt N Bt@=~)[Éf)@[f1[Ív[UWVSP1ЩPEEMu\$E$EFGE^PQƀPE/%[^_USEU 11Ґ]<1 @=t8݄Nu8N@=u0 @=݄Nu뀸Nu∐݄NNHNDNN,N)~ P,N YFt* N,N$N(N[f$`H[Í ƒpÁ ,NR1fUWVS]"NEE1UN)NN B@=~)E;NMf9t tI9;M} Ef@@u׋Ut&EtE]ƍv\$<$Nu]GE#[^_EMt@eEM]OUSEU $IHNDNN N)xJ~ J NYFt, N N$N N(N N,N[f N뺐UWVS, 8Iv * v p N HNYF@N50N=HD$4$ MN$Hp% iڍNN]؉M~M:@FB)uMe N1J,N,N111ɉ1ɉUSEU HNDNN N)xH~ J NYFt, N N$N N(N N,N[É N뼐UEU  NHNDNN YFt, N N$N N(N N,NÍvUS NHN N)xG~ A NYFt) N N$N N(N N,N[f N뽐U=$I H'uLD$ uLD$D$$2E51҉ӋU؃U1)ىMvN҃U;5NENT$ND$ FD$D$H$uLGD$ uLUT$D$M܉ $EL9YFEt]G4 NQ߂NU;5Ne9HNYE MvE20N @N99|9D$ D$D$u؉4$mGhvCE ]=$ID$ HD$D$$2ZD$ND$H$uLD$ uLD$ D$$9D$ HD$D$ $2D$`ND$H$uL^D$ uLD$ D$ $9趏D$ HD$D$!$2蒏D$LD$H$uLD$ uLD$ D$!$9R=$IoYFD$D$H$uLD$ uLD$D$#$,Iu 5@YFD$ H\$D$$$趎D$ HD$D$#$ 腎lYF! LI IT$ I1\FD$ ID$D$H$uLD$ uLD$ D$$$ D$ HD$D$#$Pލ mNhNI\lNyL9~Ѓc~dD$ L$D$2H$uLD$ uLD$ D$$$Ph NNINyL9~Ѓc~dD$ L$D$2H$uLD$ uLD$ D$$$W NNIbNyL9~Ѓc~dD$ L$D$2H$uL$D$ uLD$ D$$$^|YFD$ >HD$D$$$NK\[^_ÍvރN|SANуMiv99D$ D$D$E؉$譎E&@D$D$H$uL@NfD$ D$u؉t$E$FD$D$H$uL2뤋LI&ID$ ION)ʃ\FD$ HD$D$#$ lD$ H\$D$$$ъD$ 9uDžDž9Nu׋@AB9E;E|ɉ+}]؊8+}؋u<79t]1uEEF}L[^_ÁAPtʁ~ Bt်PtۄN8܄NuN8NuƂPА@=PtP@=~銁PP뛍v)}9+}9}0@AB9E];E~}ȍ;P1ҋ}BA9t%}ߍPPڀ9t(BAGuUPMM EU  U;}w;u Uti1ҋuĉ]] B9w]U9[M؍ uȍ1P 1PƍvBGA9,]$11fUWVSE܉d\H d0PHPPP_P̩PPPPȩP@PPP,PP(PPPLPԩP4PPDPP P$PPPPĩPPةPP,P(P PlP4lP$P1󪺠PfPfЩP$IS$ISC(P5PDžDžDžDžDžDž}L}L}Lk }L1k1f7~L<ƀP yL~8 L1ƃ$PB9t8uxuxuB9uF90~L9tC3 =(PP&Pu 0P=%Puu 0PBP1DžDžDžDžDžPPtBFC=uAuσT$$${$ovVD$ dD$D$$W=sLYFD$D$nH$uLԸvLD$ uLD$D$$%VD$ HD$D$$V11,D$ Ht$|$$UlA@19ƍt6y\FD$ t$|$$lUlDIuD$ Ht$|$$lcUl,P. PNuB PD$ \$D$H$uL臷TD$uL܄Nx((Pt@P`,PLD$ sLYFD$D$H$uL/RTuuLH!߉󤃽4tNu8uL1ыD$ T$D$!HuL $|D$uLDžuL1uLы\$D$:HuL $7twtGu!1IǁuLWAVEƁuL1fǁuL)b1эuLgH߉1IǁuLPULSfǁuLEDžuL1uLыt$D$THuL $ZuLHttftfF@UEk=jL8I=;    HDIgHPu DžPPP_PPPȩP@PPP,PP(PPPLPԩP4PPDPP P$PPPPĩPPةPP,P(P PtDIt 0P$讳;1DžDž1҃}Lt }L=@Pǀ`PDPǀdPHPǀhP 9|DžLL11P9Cu<$u11Dž1Pt6kDžxDž1v=P5PPLP P,P5P=P4PP| DP P5$P=PPxP P5P1Dž@Pt6ނNS~w1N!фx 1Nt1=u P5P ȩP1DžBPt݃N!uۉ ȩP11@YʀPtډ=u払=LPt=ĩPt=Pt =Pu 1=@P!1=P!DžuLLH?uLD$ uLD$D$ $/GhYFD$D$H$uL薩D$ uLD$ D$ $F J_=jL98I=m: )uDžJDž;Dž,<0N1IL$\$$I\"T$$D$HD$H$1IL$\$$I"T$$DžDžDž6.\FD$D$H$C1IL$\$$Ic!PiN1F:M߁NJ Ѐww =PuD$D$H$}1IL$\$$I Se\FD$D$H$1IL$\$$I7 iN1F1PthBD$D$H$x1IL$\$$Iob݃NP}rp D$i=PtނNjLvD$$Tc|vUI$c II$ cUI$bII$bU$ImRISD$ I$hmID$II$KmID$+II$.mID$>II$mIID$OII$lID$]II$lID$kII$lID$yII$lID$II$slI It,It" ItItt  IIIÍvUWVS,}u] Il/g[\FۍCT`HE%%5IE̐I I117vD$ \$D$ ̐IH$ICt7 IƃhIuD$\$̐IH$I Cuɋ= It̐IH$IV IID$$AA`I1e[^_f\FT`H>EU$RؐIi]E P=+ P+v \Ft9D$D$ |$D$E $6>\FtPPU(T$U,T$U(T$ t$UT$$ jLA$\A :ԐIe[^_\FT`HKv\FT`Hf} PD$D$D$D$ D$D$$I4iP@%АID$A15\F$*^D$I$IgܐI0f$IS]IEH$IQ̐IH$IRD$ D$D$ ̐IH$I$,_hP I$fؐI3yU(It$f(I,It$zf,I0It$_f0I$IÐUEU ЋUÐUUE  ȉÐUWVS$1\D$$I7$:$I/BÃD$D$$FD$D$$F<$eƅtL|$D$$F$H|$4$(\D$$ \D$$\4$4eD$ D$<D$P$ Xu6jLD$ D$<D$P$ &$9dã(I$9d,IP1$d0I$I@ÃD$0ID$$iE$F$I!#D$I$$$I(I1f =9u$B [^_f1[^_fUWVS$I@ÃD$D$$ DD$D$$C<$cƅtL|$D$$D$E|$4$ZD$$ZD$$Z4$$c[^_U(I$It1 =9uÐUVSM U(I5$It6x2$-t' 4M ] ؉Bu[^ÍvUWVS]U1I5(I=$It;x7$2t,d) ]  ؉Bu[^_fUWVS] U1I=(I$ItEt1%%)19E~E萋M܋I(t>ut1%%)19E~E萋]EU)ЍM4{ C US ρ}{ CtLE)Щu(EtS1ȃ ЉCEt}NExt&U؋r(tX(t ]xu MA u~|t*}O(t t UBtxu E@ Mt-]܋C(t#t}xu uF E)EMAj1]UTUM4M싛X]} 1ۋ}+81ɋ}+OlOLOplh1u\h  U1ɉӋU|}} M9~U))ыE )+E)uωʋM|ˀ\Vpq1UxtрAϋA]AAE싟Auu f9~E}) )E)u΋UAAA [^_Ã]/tB6@ HAH@,H ]FH@ HIH@ hHX ; ]FIHN1 ȉF%lE)Щ=/v1]]uu)]D<WC<$gD$$ClCp[ÐfUVS]u t$$^NtClCp[^fClCp[^ÐfUUVS]u t$$u <][^rfUS]$<][UVSu 1ۍvD$t$$ ICu܃[^ÐUE@@@@@ @$@(@,@@ @0_HP@ÐfUE@@@@@ @$@(@,@@ @0_HP@ÐfUU EPfUVSEU H,uGt:@0H_HX)΁~9@P,[^fu@0H(_HX)΁~9ŁP,[^ÐfUSEM PH X0u2 _HH)Ӂ~9|[ÍvKu _HUSEM P$H(x0t[Ë _HH)Ӂ9[ÐfUSUM J)Á~9-[UE@ÐUE1҉P@ 8@&=ÐfUEE IX =IXÐUE1҉PÐUS4]C$$tICdE?C(C,jIJC0RI9C4mIC8mMC<TC@jFCD@CHACCCCC CCTCPCLC C`CXCC\@D$ ChD$$LC8]K< I$i]EM[`{u C1҉EUmKDCH Is$[X4[ÐUUE uBUS4]E CtOS 1ɉUMm5II=I[\u C1҉EUmKDCH Is$[X4[ÐC 1҉EUm5II=I[\D$ ChD$C$CC8]K< I$`]EM[`ClUS4]U ShCt,u C1҉EUmKDCH Is$[X4[ÐD$ T$C$C8]K< I$]EM[`C땐US4]E S$ I=I[dCt-u C1҉EUmKDCH Is$[X4[fD$ ChD$C$&C8]K< I$C]EM[`CfUS4]E C(EC,EC0Ct,u C1҉EUmKDCH Is$[X4[ÐD$ ChD$C$C8]K< I$]EM[`CfUS4]E CDECHCt.u C1҉EUmKDCH Is$[X4[ÍvD$ ChD$C$C8]K< I$]EM[`CfUS4]E C4EC8E$ I[IElXI]PfE@ I HIPIR4$Btu[؋fE9E}uĜ[^_1Ĝ[^_$@ݝxݝh ݅h݅x4$]]ݝx݅xEE fUVS@]C0@C0;C4-{$WCt HC @;'shkCpʁSpn1ɈKluf@;8tH Ktt{&CpSlt&tǃt{&tCC PK v {$8PH11 IKDCdPKp vPH11 I؋؃Pn vPH11 I؋؃4P&ٛٛٛ@[^ÍvCKʁSF1ɈKD$$#mC|HC|KtD$4$#ʁD$4$K#fكuكC,ككHIككʋHD¨HfFffڨF‹Pփt؃уt؃t؃<كك؃ٓ؋ٓ؋ٛ؋Xfكك؋؋ٛٛvǃ0tB; ǃS4uǃ ƃfoI@vǃtB;ǃ@%= (:uǃƃv1 fC0C`tS8BS8;S<C8{HC@mu C<CH{I1CDC1Qff¨fɋLCp%%ffC%%Of{%%%f;Kf;TLv;vPCvvD$4$|kvvك]كUكUEكt II}fE fEm]mMكxUكlك]MMmUٛكUEu7كt II}fE fEm]mEM]fEEMMmٓكe I؋`ٓtكhEٛtكhٛɅtكhٛf؋XكdE HIfD$4$K D$$@%=ǃ0 _HD$$6|C@@%C@=C`CP_HD$C0$C@Iqf1C@I]=6Oǃ @]=6C<v]=6ǃE)C@ST;`H HC@C@H%C@v;`H6H*vH%H%$;`HHvǃǃǃǃ ǃ ǃ C<4C<(C<ǃ ǃ ǃUǃEC<C<ǃ_HD$$sUWVSL]MEU U؋t+U؉@U U؃ك؃U}fU fUm]m};}LuWẺME}f؋}Oe1$F9|;}M +E܉Eeٓكك DIك I}fU fUm]mU~MfEٛ؃Um]m9EEE؋U9U,كIEuIEuǃكIEuIEuǃكIEuIEuǃIEuIEuǃ؋EЃL[^_ككU}fU fUm]m};}5U.EMEf~i1$ t4كأ DIٔ @%F9|كM M}fE fE)}؋U؋E EW$$ٓMMmUmeԋE܋+E܍4UċUJ}܅EE܋Mč<1 IuE@9EREM܅PE1 Ju Im]mE==~UfEUm]m};}EEȋU9Uk؋E؅~U1} $t4كأ DIٔ @%F9|EكeٛM كfpf2fكأ DIٛ$v1M܅1|؉E؃}1} v$FP9|E;u|@كP$$ٛM كǃǃكأ DIٛ$U EpEOE1lEكUWVS<]U t)‰M ك؃U}fU fUm]m9E}EE̋EEE؋}O1$DF9|;}U +E܉Eeٓكك DIك I}fU fUm]mU~MfEٛ؃Um]m9E"UUЋM9M,كIEuIEQكIEuIEكIEuIEIEuIEuǃ؋Eԃ<[^_Ðfكأ DIٛ$U1EEv؃1} $`FP9|9|xكR$$ٛU كǃ"ǃǃǃǃU 21كأ DIٛ$E ^EكUWVSMU Y 2 19ƃK ^  1<IـIFFF ـIy ?u12?u1r?u1r?u1r ?u1r? u1r?@u1r?u1r?u1r ?u1r$?u1r(?u1r,ރBRBRB R BRBRBRBRB R B$R$B(R(J,Z,J,R,t ]U]IU]IU]IU]Iٕ|]Iٕx]Iٕt]Iٕp]Iٕl]Iٕh]Iٕd] Iٕ`];As fٝ,BٝPBٝLB ٝHBٝDBٝ@Bٝٝ$$A ;A%1ɉ Z1 ?u1ɉJ?u1ɉJ ?u1ɉJ? u1ɉJ?@u1ɉJ?u1ɉJ?u1ɉJ ?u1ɉJ$?u1ɉJ(]?B,[^_Ð؁B(Z,B$Z(B Z$BZ BZBZBZB ZBZ BZ"Zff1? Zfr(r,r$r(r r$rr rrrrrrr rrr rr2r놐\fUWVSD]C ECECEC }CvSC|$$C SE IE IE IE IE IE IE IE IE IE đIE ȑI E ̑IC(I(C|$$SE IE IE IE IE IE IE IE IE IE đIE ȑIC 0E ̑IC(Ii@C OEC ECECD[^_ÐUS] D$ \$$ID$ \$$ID$ \$$ID$ \$$ID$ \$$fID$ \$$ HID$ \$$@*ID$ \$$ ID$ \$$ID$ \$$đID$ \$$ȑID$ \$$̑I[UEU Jt ʼnP(ú`ĉP(fUME %Q ЉAfUUE %J ȉBÐfUME %Q ЉAfUUE %J ȉBÐfUWVS8]C P{{$tCsH11CEĉD$${sIE1EEEuIEEuIEEuIEEuIEEu IEEu@IEEuʀЃ8[^_ËSЃ8[^_Ív{%E @%%fUSU} tJ 1؃ ȉB z J k.J % ˁ@ ؉ˁ ؉ˁ  ؉ˁ ؉ˁ ؉˃ ؃ BB(R,t IZ,fبt B,IZ,t B,IZ,t B,IZ,t B,IZ, t B,đIZ,@t B,ȑIZ,t B,̑IZ,[ÍvuJ fUWVS@]uuC ux{ C%C&u!S$T$$EvEC$@[^_À{$uCK  ʉS C@ C$@[^_ÃwSU{$tCKH11ȉCEĉD$$MECMKIE1EEEuIEEuIEEuIEEuIEEu IEEu@IEEuʀSC Pv6C,C,v{%U B%%f v{$u;MrPHt11 ȋI띀{%tE @%%ϐUWVS<Ë@ tv-C C%C&C$D$$zC$<[^_f{{$tCsH11CEĉD$$U{sIE1EEEUuIEEuIEEuIEEuIEEu IEEu@IEEuɀKC Hv1C,C,f{%B%% v {$u9rHHt11Ɖ I룐{%tB%%US]C(`CCC,C CCC$C ډC[ÐfUEP % с@ ȉс ȉс  ȉс ȉс ȉу ȃ fUS]CCC,C CCC$C ډGC[US]$C0$菼D$$CdH[fUVSu] \$4$KtFd[^ÐFdH[^fUVS]ut$E D$$u 0][^߼fUS]$0][BfUE E E0E錼UWVS@PS 18P4PfDžDžDžDžDžω PJ@ˉf If6t_4P =X( I@P%=OwI;@IЉI)ȋ@PF `I\tID$D$:I4$2D$D$$UbD$D$$T7D$D$$T D$D$$TD$D$$UTD$D$$*TD$D$$S`D$D$$S5D$D$$S D$D$$~S$!$!BD$B$PIrD$$XOD$AD$$Q4 %D$BD$$P D$AD$$OD$BD$$ND$AD$$M}Ri@UIAR-IR D$D$$>@QD$D$$.QvD$D$$6PKD$D$$&P $*Q D$D$$~}PD$D$$nRPD$D$$v'PD$D$$fO]$jPFD$D$$OD$D$$OD$D$$dOD$D$$9O$ "PD$D$$^NXD$D$$NN-D$D$$VND$D$$FvN$J_OD$D$$4ND$D$$ NjD$D$$M?D$D$$MD$D$$MD$D$$]MD$D$$2MD$D$$Mh$MQ$M:$M#$M D$D$$pLD$D$$PULD$D$$0*LDž~D$D$$=K6D$D$$-K B$DA$PB$ID$D$$7KD$D$$ KmD$D$$JBD$D$$JD$D$$ JD$D$$1`JD$D$$!5JD$D$$9 JkA$6IUD$B$C9D$AD$$UD$BD$$TD$AD$$SD$BD$$R@}D$$EZD$BD$$C?0D$AD$$DD$D$$zHD$D$$OH$|ID$B$IsAD$AD$A$$KID$BD$B$JD$D$A$JB$IA$IBD$B$:J $EoL$$UL1XTB$E>A$K(B$wKD$D$$5FD$D$$%[FD$D$$)0FD$D$$FfD$D$$E;D$D$$ED$D$$ED$D$$YED$D$$.ED$D$$EdD$D$$D9D$D$$DD$D$$DD$D$$WDD$D$$,DD$D$$DbD$D$$C7D$D$$C D$D$$CD$D$$UCD$D$$*CD$D$$B`D$D$$B5D$D$$B D$D$$~BD$D$$SBD$D$$(BD$D$$LA^D$D$$ A3$`B$8B$B$vB$_B$HB$1B$B{$XBd$xAM$(A6$A$hA$HA$yA$bAD$D$$7@D$D$$ @mD$D$$?BD$D$$?D$D$$?D$D$$`?D$D$$5?D$D$$ ?kD$D$$>@D$D$$>D$D$$>D$D$$^>D$D$$3>D$D$$>iD$D$$=>D$D$$=D$D$$=D$D$$\=D$D$$1=D$D$$=gD$D$$<<D$D$$<D$D$$q<D$D$$aZ<D$D$$y/<D$D$$}<eD$D$$m;:D$D$$u;D$D$$e;D$D$$iX;D$D$$Q-;D$D$$A;cD$D$$Y:8D$D$$]: D$D$$M:D$D$$UV:D$D$$E+:D$D$$I:aD$D$$96D$D$$9 D$D$$9UED$ @`HD$D$I P@$R1fUS4 WLD$$!WL PC D$D$ D$cD$WL$o!@\$D$ D$D$WL$C!j0@PE$D$$ULaH8uD$ULU $EV?EEo0D$$ULH>WL$8 E4[ÐUSM] AÉA A[ÐUVS]u SxGvt)CvS+CD$֋CC CSD$SJSyC C[^ÐUS]CxvD$谑CHCyC C[ÍvUS$]S;S tCDSȃ$[Ã{?tX$b=WL%teSJKD11Sȃ$[ÍvWLD$$&IES!E빃=WL=WL}=$=WL|WLD$]D$%I$4&I WLD$$%I =WL|WLC D$$&I =WLtWLCD$$&I RWLD$RD$%I$%Id vUWS]$u‹ 1Ѓ[_ÐU8PfE~fWfXu=WLGÐfA=WL~WLHL$L$ ҉T$D$$&IWLT$ D$XD$$&IEEf=WL~WLT$ PT$D$$&I[Ð=WLHWLT$D$$w&I+Ð=WLWLT$D$$`&IÐUD$ $VL"U$VLUVS u] Cf=E~#f=Wf=Xu;5WL~Gv [^Ðf=A;5WL5WLST$T$ D$\$$&IN뼉5WLD$ D$X\$$&I(;5WL5WLD$ CD$\$$&I [^Ð;5WLX5WLD$\$$w&I7v95WL(5WLD$\$$`&IvUVSufXtfEu'$VLfpE )؃[^Ã=WL} $ WLt$$&I"UVS ufXtBfEt;fWt4fAt-$VLfpE EC؃ [^D$AD$ WD$X\$$'I諌=WL} $VWL\$$@'IpfUS$VLf@AE؃[ÐUVSu=WL~WLt$$c'I$VL.f@W0؃[^ÐUWVS WL5HPWLU9=WLWLUt~Ҋ`+IUf`/Ituǐ`4IU 6I9t`1I=~׊3IUˍv @9IF;ur=WLUWL [^_ÍvEfUEEȊUD$D$'I P@$n$貊fUEU U EUVS$(vÅ@ @$@YCtjCC@CCC$;4WLth3C tF$TC؃[^1C؃[^fD$'ID$'I P@$耉$ĉWLWLHP WLWLqUVSu4WL@PPBPP@@$H WLWLHP WLWL3C tXF$]~=4WLSPWLPWLHP WLWL[^Ív4WL1čv1뽡 WL.4WL11yfUWVS\=,WLV5(WL0WLPWL D`HuwWLWL]̋WLUԋ=WL}Љߐ`+If`/It}ЉEԐ`4I 6I9`1I=~Ԋ3ID`Hu WL WL>$WL@4WL PWLXWLHP WLWLWL$f @9I=t G'v}ЋMԉ WL=WLȋ]`/IHP)ډDPWL=WLvv,D$(ID$'I P@$豆$$(I=DWLO=DWLs 54WLt"4WL~\ 4$蛆54WL`WL9tMtWL^WLV4WLPWLPWLHP WLWLWLWLWLWL,WL>4?*@ HP$u$"s8WLt&$s8WL1S;2|#;rCD$ ED$t$B$UCG9̃,[^_11ɋS;2|C;r>B Eu>CD$D$I$efWL$\=I U91}ECf=WfCWEE1<[^_Ív;}؍E؉D$D$pC$WLXdD$$WLx=WLY9UCCdvEq1wWLD$$=IwWL$=IE=WLE~WLPT$ T$D$$=IVv]C|$D$k=I$@^Lc=WL#@^L1}EWLD$@^L$=I2@^L1}EWvD$D$=I$XL6c=WLXL>$>I1}EE9EEE9EEE9EEE}UE}EEEEE)EEEE9EEpWLD$XL$=IXLh=WL} $bWL$=IUyD$$\LD$$ ]LD$$WLU $\LMD$C$ ]LtD$$WLfUE=fU1}ÍvUE=fU1}ÍvUE=UEU 9WL}fWLBD$ D$T$$=IU(EEED$D$pC$WLA$fUVS0uu]\$D$pC$WLU U\$)‰T$$WL}=WL0[^ÐWL$>IE=WLE~WLPT$ T$D$$=I0[^Ã=WL}1$H`=WL|WLt$$d>IYWL$>IA뷍vUWVSIE=WLE~WLPT$ T$D$$=Ix<[^_Ã=WL}1$'_=WL|WLt$$d>I8WL$>I fUVS0u] uED$D$pC$WLD$$WL5p=WLu 10[^É310[^ÐWL$=IE=WLE~WLPT$ T$D$$=I`ft$D$k=I$@^L]=WL @^LrWLD$@^L$=I@^LI=WL|WL$=I$]UWVS<}}ut$D$pC$WLÅEt$)؉D$$WL=WL <[^_ÍvWL$?IEO=WLE~WLPT$ T$D$$=I<[^_Ã=WL}1$\=WL|WL|$$>IWL$>IfUWVS,]UE u^u$lj$x,H9~+<$g40F Љ$,,[^_yЃ=WL}1$\=WL|WLD$$=I$WL\$t$$$?IfUE$=WLWLER?IUE0^L0WLbfUWS]=WL~WL\$$g?I~0^L$1IL$\$$[_fUS$=WL@UE5ue]=WL=u(WL$[Ð,WL$[WL$?IWL\$$?I맃=WL} ${ZWLD$$=I؍vUWVS,Uu $\LUÉUSEC<v=WL$ Zv$?Iv$$؃,[^_f$f$D$CD$$NC뫍v$fWL|$$?IHvUS$]$\LX@$E2$B E$[ÐUS$$\La $ ]LPCD$$YEE< uED$C$؃$[Ã=WL} $XWLD$$?IՍvUS]< uE D$C$F؃[Ã=WL} $AXWLD$$?IXfUS]< u C$z$ ؃[Ã=WL} $WWLD$$@IfUS]< u  C$$ ؃[Ã=WL} $wWWLD$$4@IUS$]$\L XU P$EO E$[fUWVS<] uE$z$DžU&]xg9|g)߉}ԅU}xm9}|m$\LUPxX t<$E EЃ<[^_Ívy=WL|1WLUT$\$$d@Iz}y=WL}B$*Vf1F1h=WL|WLD$$=I*WLED$ \$|$$@I뗐U=WL} $UWLED$$@IԐUED$D$=I P $UÐUE$EJfUWVSF릃=WLFD$$fWL$CAI.WLT$$BIUUvWLD$$4AI`v=WLsWLF$D$$BII=WL;WLF$D$$CIfWL‰D$FD$$AIU8UWLEĉD$FD$$AI WLT$ D$FD$$AIWLFD$$JAIZWLD$UĉT$$BIEEqWLUĉT$ ED$FD$$kBI]WLt$D$$CI7=WL}p$L=WLWLT$$AI=WLWLt$ VT$D$$\AIWLD$$=Iq=WLrWLD$$0BIsS=WLFWLD$$AIG'=WLWLUĉT$$AIUÍvULbLEPbLÐUELbLPbLÐUSLbL@bLtgtCPbLt2$rLbLPbL\$D$$MkãLbL؃[áPbL$3ãLbLPbL؃=WL} $KWL$hCI1܍vU=LbL@bLt EPbLfUULbL=@bLt#LbLtD$T$$M载LbLfULbL@bLPbLÐUS]E C$C[ÐUWVS]E tI1s4$1394$C[^_Ð4$0Gt։$U fsǍvUWVS,]E EtR1s4$139 4$Cu,[^_f4$GtΉ$Ufs뿍vUS]C$'13[ÐUS]C$oU Ѓ[ÐUET$ ML$U T$$KÐUS]D$E D$C$c[UWVS,]Cu,[^_ÐCE$r13Hxi1] f~9=;M $MT$E$U t}Í^9~ø),[^_Ð,[^_øoUWVS,]Cu 1,[^_ÍCE$13Hx1] f~9|=M $MT$E$U t}Í^9}Ë] v]))sM $3,[^_ÐUWVS,]Cu,[^_ÍvCE$13H1] f~9|=U$BMT$E$U t}Í^9}Ë] v]))ix.E$31UHU,[^_1D$ UT$ljD$M $fUWVS,];s4$13E4$xU T$ |$UT$$FK,[^_fUE U@UWVS];G$s179| 1[^_f;G$7C[^_ÐUWVSu] EiLiL5iLiLUiLƒ⟉iLǃ=lbL1Ҩ‰pbL=jLҁѨ t @!hbL$5hPdP'5lP`P3t eL5eLeLeLeLeLeLiLiLiLT$ D$`PD$lP$[;eLiL`bLdbLP`HT$ D$D$eL$;\`H$[^_ÅhbLf[^_ÍviL`bL cH1[^_Í6lP`Pv1UiLD$ iLD$iLD$iL$U`bLÐUeLu1 `bLu1ÍveL$:ueLÐÐUeLufeL$9eLÍvUeL$9dbLÐUEP`HÍvUSE$ÃD$D$bL$#=t cH$$1[f$$bLf ?~?˃ ˈeLJ?~?˃ ˈeLJ?~?˃ ˈeL@=u cH[Ív cH1[fUWVS]u EEEEbLWyh1Ɉ eLJM?]y^1Ɉ eLJM?RyS1Ɉ eL@=t]  ?~?< f?< 떐?< eL@=u[^_1EEEEEE vU `bLufP`HD$ D$D$eLeL$:7UWVSEM U]9s:9s65hP9s,=dP9s"9w9weLeL eLeLv[^_ÍvUWVS,]~ 5eLt ,[^_f$U?ƣeLU$?ǣeLU$?eLt-t)t%eL1ҐB9ueL{UWVS,ueLeL cH9| 1,[^_Ðu5eLt$>]t$>E $6ƃtD$D$$'ED$D$4$ ]eL4$!}=eLeLU[$s>ta11 veLR4$J!f4$?!fC4$3!fC4$'!fC4${!CGeLM;<rD$D$4$P}=eL])É$=t0\$D$4$4$D  cH,[^_Ð cH4$ 1Zv$x=ljãeL$c=eL$EO=eLUt?t;t7eL1ɍvAueL1vUVSE9eL~=5eLދt$<eLt$<[^ÐUWVSUE lbLt7=dP~% hP1ۍv׉U hPC9dP[^_Ë dP~5hP1ۉׅf1fOTOA9u{}{{v{{E9EkI뼸*f{}{}{$t]}+}}$8>8}~{}{{v {{@E9EI볍v8>8}~{}{{v {{@EI9EwEC$2E=lӍvC${}{}{$t}}+}}䐅(8>{}{{v {{@E9EvxIE9EvIFfE9EvIfE9EvIf8>{}{{v {{@EI9EwufE9EvI>f}}fU8>{}{{v{{EI9EwU jLt+ jLjLt$3jLÐUWVS,EE܋5jLpP`MtEmE܍ 1=jL6]uEf4)]t[xPujLtҡtP15T`H;E~])أxPjLto\$4$СpPu4)]u5jLuwM܅t<1M܋] f}1҈@9t~€@9u,[^_Ë=jLjLUtى(MunU܅tŋM UJ=}ftJ=~ݸfEjLtML$4$Ћ5jLpPjL=jLtvM(OuUWVS,u}]jL jLt( jLjLt$1jL5jLf jLE \E (ˆ"jLMbf1ɐAfuf$jL,jL3C0jLxP9X`HtbjLt$0jL$0jLXjLX`H~@$@ @@(Ku$'D$4jL$jL' jLpPLjL=:jLR11һ8jLf=f=wLjL@jLPjL4jLtPjLt!$E/jL pPE 1$/jLt`$& cH,[^_Ð cH jLu<jLtK${/jL1,[^_Ív cH jLt_& jLjLu1,[^_f$P3CjLAf jLfpPLjLv1$.jLv5pPLjL| cH jL3F cH jL UEjLÐUjLu&$0$xQ$^CjLD$$7%$3%E D$E$)%f1UÍvUÍvUS4nL$]v$$t,}wE$CIvdbL$$uf4[fjLUM!PUM P넊EEUfPeE<1<I%lL=E<<! lLElLElLElLElLE=ƀjLƀlLvElLUlL=ƀjLƀlL =nLu =nL{5jLjf`EUfPL lL@%lL4 lL(%lLUVS'ؙ}þgfffnLnL"nL+nL  nLș)щ nLt [^Ív)ȉ)ʉ$!fUE\`Htt"uE"vfhbLtEe"UlLÐUÍvUS]M `bLt1hPlL15lPdPlL15`P[flLlL[ÍvUlLElLE lLlLÐUlLÐUfUÍvUlLf1 f@=tjLtƀjLf$ fU1 @=tjLtƀjLff1ÍvUE=jLtƀjL1UlLt lL1UlLt lLUM``H=t$9t ``Hv9t u@ø``HUEoLÍvUWVS<] pLt$( pL$pL(pLC8pL=4pL) 4pL(pL4pLEIt cH1<[^_è SUEУ(pLEEE EE EE EԋUԉ,pLR$S(0pLUԅ11vRK {  { {  K{ { {  JKJKJ KJ KJ KJ KJ KJKJKJKJKJKJKJF;uZEУ(pLhoLtoLoLoLoLoLoLoLoLoLoLoLoLpLpLpLoL cH<[^_Ív4pLS5pLS6pLS7pLSUSUSUSU cH1fUWVS,EtD$ EI$% pLcD$ D$D$$4pL%4pLEIt cH1,[^_á pLD$ D$D$E$%uE E E Ɖ5,pLv$%ã0pL110pL<@ pLD$ D$D$E$%EU U U Љ;0pL pLD$ D$D$E$$EU U U ЉC pLD$ D$D$ =0pL<$~$F95,pL'hoLtoLoLoLoLoLoLoLoLoLoLoLoLpLpLpLoL cH,[^_f pLf cH cH1vUWVSv1;]…t1tv<"tSCu]4t EE[^_]É$L$~)F:\ufʍIzuCF\t E4ED<"t(uF1<"uE8\ttFE8\u΍&'UD$EID$ PT$ @$Í&UFIFI1Í&U]&U] Pu $ P@$pLt=pLuW=qLu ]u]$qL)FID$ tۉ$$@ t$qL$pL)FID$z t$$@m o$pL^US$L$\$$ t \tHu\$1҈D$$pL$pL,FIL$D$$pL P8FIT$ D$ \$D$$qLq$qLD$:FID$K$qL P@D$8FID$  P@1҉L$\$ T$$V 1D$ P@$8 ]pL$pL8FID$ 4 PB AB$AB(A B,AB0AB4AB8AB<$qL8FID$ ; PB@ABDABHA BLABPABTABXAB\t&'U(}} E]uE\D$$9 ~X$.t$ )؍p4$H t@t$\$$$y]¸FFI]1u}]Ë]u}]/$/D$ ig$ t$XCW$XCK$ $|$E$=$ 'UWVS $VFI t $ $`FIt}$ uq $ X$ t}\$|$$}1҉DǍ$ tM‰$\$<$(e1[^_]N $d X$ u&e[^_]%$P%(P%P%P%P%P%P%ԲP%P%زP%P%P%P%P%ܲP% P%ȲP%P%P%P%P%P%IJP%P%P%P%вP%P% P%P%̲P%,P%0PUWVS}Aw$GIvu81ۉ[^_Ívtp;p}vXFptىK{[^_Åtċp;p}fUWVSƋ nt/1A< w21ɍDAB YЀ vt[^_fB 1UWVSX ;St 1҉Z[^_Ðsp K@C҉րt: VI: 8VI: TVIo: pVI: VI: VIqVIz3JMH;Hk XAHt{}{X,r ZX09Hk PAHrZsp _u1;P @(@Z[^_ÐYЀ E1ۍQЀ w1vɍT9X t CX _t$ӍQЀ vҍQoɍTfBw1rZ1VIHTVI8VIVIpVIVIyE]#fUVSƉӅt;AvSu [u1[^f$HIvt>S@@uv~J@t8+t뽐ut@t8+ufdžUWVS,É1IMth1SU@T G9}v?>=uƃD$D$E$U 1ɊU묐,[^_UWVS,uU ]CD{9v1K tQ,[^_ÿ|$$UwUtJ{K uϋCljCS,[^_Åu vf9v9w랋$CCC gUWVSH 9_t [^_ÍQP Qnt:1JЀ w@p @ 1ɍ ҍLJ@ZЀ vtA[^_fQP Q1UWVSuH u 1[[^_fAH hvuX H 9nwЉ wP fB 0 vH 9_uQUP ynOЀ wP B 0 vP U2_]UBP NfX P U nt(΃0 wȋB 0 v뮐AH 9EBUP ͍QUP ygvUWVSX H)9| H @t9$tz ~1IIE8MusK.tX_tS$tNfp;p}0 vHFpt!ttYQ^[^_Ív1ɉ^[^_fAH f~NuH0)щH0P;P}Ӎ RHBPtAIIAUWVSH _tnu_[^_Ív1AH ZЀ wx 1ۉEҍ4B^AB< vE/H 9_uUWVSÉUtuUAvǃĜ[^_Ð$KI=MPDoƃo@MBDpƃp=LPDeƃeLBDrƃr=FLPDaƃaKBDtƃt=KPDoƃoKKBDrƃr=BPD ƃ uV vJuJ q9ufuV3b=HPDoƃoHBDpƃp=2HPDeƃeGBDrƃr=~PPDaƃa*PBDtƃt=OPDoƃoOBDrƃr=yAPD ƃ U~&}W.(,k0BPUx(1KM@T F9u(7=uƃD$D$E$t 1Ɋt뢋}G81mW:,PP.}WBEJIE:MA1=XD[@ƃ[uFP=xXD]@ƃ]MA8,@x@8>ZD)@ƃ)uV{AU8+jp_1v8+uHt ׍W@uUE@E1SU fF9u U9~⋃=)D,Pƃ,m)D ƃ 뙋uF83P:4Ph~}W:,kSBHxaS1SUT@F97S7=uƃD$D$E$tp 1pt뛍v;BD{ƃ{=;PDuƃuJ;BDnƃn=:PDnƃn:BDaƃa=P:PDmƃm9BDeƃe=9PDdƃd<BD ƃ =0<PDtƃt;BDyƃy=;PDpƃp5;BDeƃe=:PD#ƃ#uF@D$D$JI}}<$"1}щOq#1SU}}@T F9uC#7=uƃD$D$M $t 1Ɋt뢋9BD{ƃ{=9PDpƃp@BDaƃa=@PDrƃrI@BDmƃm=?PD#ƃ#UB@D$D$JIMM $1}щO!1SU}}@T F9u!7=uƃD$D$M $t 1Ɋt뢋=X*PD~ƃ~}W=GPDvƃvUGBDtƃt=GPDaƃaFBDbƃb=[FPDlƃlFBDeƃe=LPD ƃ &BDfƃf=%PDoƃo9%BDrƃr=wPD ƃ EP+Z-DBDVƃV=CPDTƃTCBDTƃT=.PD ƃ [%BDfƃf=%PDoƃo$BDrƃr=c$PD ƃ MQ>JI{"f@T F'JI$=uƃD$D$<$t 1Ɋt룋=(PDtƃtE(BDyƃy='PDpƃp'BDeƃe=+;PDiƃi:BDnƃn=:PDfƃf0:BDoƃo=ƃD$D$C$ C (JI{ @T F:JI=uƃD$D$<$t 1Ɋt룋(9BDtƃt=8PDyƃy8BDpƃp=.8PDeƃe7BDiƃi=7PDnƃn37BDfƃf=6PDoƃo(BD ƃ =S(PDfƃf(BDnƃn=P PD ƃ !BDfƃf=W!PDoƃo!BDrƃr=PD ƃ uV;JI{ @T FPJId=uƃD$D$<$t 1Ɋt룋uV:#1=uAHD(ƃ(=APD)ƃ)M96&! }Wu4BDjƃj="4PDaƃa3BDvƃv={3PDaƃa'3BD ƃ =2PDrƃr2BDeƃe=-2PDsƃs1BDoƃo=1PDuƃu21BDrƃr=0PDcƃcZ0BDeƃe=&ƃD$D$C$ 1}WWEP=h HTUBD$D$JIMM $1}щO1SU}}@T F9u[7=uƃD$D$M $t 1Ɋt뢋JI{#v@T FJIp=uƃD$D$<$t 1Ɋt룋JI{ @T FJI=uƃD$D$<$t 1Ɋt룋*BDdƃd=6*PDeƃe)BDcƃc=)PDlƃl;)BDtƃt=(PDyƃy(BDpƃp=A(PDeƃem7BD ƃ =7PD(ƃ(MQ=PD)ƃ) BD{ƃ{= PDlƃl0$BDaƃa=#PDmƃm#BDbƃb=6#PDdƃd"BDaƃa="PD(ƃ(EPf*"BD)ƃ)=!PD#ƃ#UB@D$D$JIMM $>1}щO1SU}}@T F9u_7=uƃD$D$M $t 1Ɋt뢋=nPDjƃjBDaƃa=PDvƃvsBDaƃa= PD ƃ BDCƃC=yPDlƃl%BDaƃa=PDsƃs~BDsƃs=ƃD$D$C$ C lJI{"f@T FJI=uƃD$D$<$t 1Ɋt룋}E}}EEWBUu CEXEEuuEEV}unC뮋}f EPzRIj8BD ƃ Ufz=W<HD_ƃ_<QD AƃA;BDcƃc=\;PDcƃcN9BDuƃu=8PDmƃmMQtuN6BD,ƃ,=J6pD ƃ }WH9pb=PDoƃonBDpƃp=PDeƃeBDrƃr=tPDaƃa~BDtƃt=+PDoƃo{BDrƃrMQJ aw$=7D @ƃ uVz}zU 1SU v@T F9u7=uƃD$D$M $t 1Ɋt V}WEEEEEE%EuE <l<1D Bƃ  MU$^|UMMMuuEEr9Ba9E]vBwUJuH}k}}]CljֹECMMM]BEu]uV|E}t3}OUtvO:>u|U|Z UBHM81SU v@T F9ug7=uƃD$D$M $t 1Ɋt뢋={PDvƃv'BDiƃi=PDrƃrBDtƃt=PDuƃusBDaƃa= PDlƃlBD ƃ =yPDtƃt%BDhƃh=PDuƃu]-BDnƃn= -PDkƃk,BD ƃ =c,PDtƃtBDoƃo=ƃD$D$C$ 1[MIMu~1SU@T F9u7=uƃD$D$M $t 1Ɋt뢋MQ =/PD.ƃ.CxǃE@EEUUEEMMƋ7~}UE}EMP7WUXEEUEM̉ы17qu!EЍEЉuE}}܋EU3uV:?T6}EHEE|؃}3}O}X߉ƹMMHMM|P@}x ERvEPU:35UTMI}t{}ϋu.=4D @ƃ V,8 Ou뾋JI{ @T FJIP=uƃD$D$<$t 1Ɋt룋='PDhƃh>$BDiƃi=#PDdƃd#BDdƃd=D#PDeƃe"BDnƃn="PD ƃ I"BDaƃa=!PDlƃlBDiƃi=PDaƃa$BDsƃs=ƃD$D$C$ C uvuExo1SU v@T F9u?7=uƃD$D$M $t 1Ɋt뢋QJI{#v@T FkJIx=uƃD$D$<$t 1Ɋt룋MǃuVt2u zj)<|=(PD<ƃ='PD>ƃ>UMQF@uvJ@8+t=OPD}ƃ}cv}WN=*D(@ƃ(U=g*D)@ƃ)uVWfuV"BD-ƃ-="PDiƃi;"BDnƃn=!PD-ƃ-}WAEP.ƃD$D$C$ 1P:+D=/*HD_ƃ_)QD FƃF)BDrƃr=4)PDaƃa*BDcƃc=)PDtƃtuFx }xE1SU@T F9u7=uƃD$D$M $t 1ɊtƃD$D$E$ 1eƃD$D$M $ C,- (=+PD_ƃ_+BDSƃS=N+PDaƃa*BDtƃt=}*PD ƃ :MU$N+BD:ƃ:=9+PD:ƃ:JqQ$?}O9/y%5A<0_.<1JIiƃD$D$C$ CrƃD$D$C$ CoaƃD$D$C$ 1oƃD$D$C$ Cr9ƃD$D$C$ CoƃD$D$C$ CfƃD$D$C$ CfCƃD$D$C$ CoƃD$D$C$ CfCƃD$D$C$ CrQ<)D[Bƃ[uV ="D]@ƃ]=&D @ƃ (D-Bƃ-= 'D @ƃ af :+t~HRu`XRHv}wEx9:SU*_tkF=t)@T 9)͊FƃD$D$E$t 1Ɋt렍NM~_`!ƃD$D$C$ 1zƃD$D$C$t 1t^ƃD$D$C$ 1?]ǃJI#UBPNxƃD$D$C$ CeOƃD$D$C$ CpƃD$D$C$ CyƃD$D$C$ CtUƃD$D$C$ CsƃD$D$C$ CsƃD$D$C$ CaƃD$D$C$ CluƃD$D$C$ CC!ƃD$D$C$ C ƃD$D$C$ CazƃD$D$C$ Cv'ƃD$D$C$ CaƃD$D$C$ CjƃD$D$C$ Cl`ƃD$D$C$ C{ ƃD$D$C$ CfƃD$D$C$ C GƃD$D$C$ CoqƃD$D$C$ 1WƃD$D$C$ CnƃD$D$C$ Co+ƃD$D$C$ CazƃD$D$C$ Cr&ƃD$D$C$ CeƃD$D$C$ CpƃD$D$C$ 1ƃD$D$C$ C)ƃD$D$C$ 1AƃD$D$C$ Ca ƃD$D$C$ CdƃD$D$C$ CbdƃD$D$C$ CmƃD$D$C$ CaƃD$D$C$ CuƃD$D$C$ ChƃD$D$C$ CtuƃD$D$C$ C !ƃD$D$C$ ClƃD$D$C$ CazƃD$D$C$ Cu'ƃD$D$C$ CtƃD$D$C$ CoƃD$D$C$ CtoƃD$D$C$ CrƃD$D$C$ CiƃD$D$C$ CvsƃD$D$C$ CaXƃD$D$C$ CiƃD$D$C$ CeƃD$D$C$ CpYƃD$D$C$ CyƃD$D$C$ CtƃD$D$C$ Cl_ƃD$D$C$ Cc ƃD$D$C$ CeƃD$D$C$ CddƃD$D$C$ CdEƃD$D$C$ CeƃD$D$C$ CmƃD$D$C$ CaJƃD$D$C$ CnƃD$D$C$ CnƃD$D$C$ CuPƃD$D$C$ C{ƃD$D$C$ CpgƃD$D$C$ C{ƃD$D$C$ 1ƃD$D$C$ CeƃD$D$C$ CpeƃD$D$C$ CyƃD$D$C$ CtƃD$D$C$ C jƃD$D$C$ 12ƃD$D$C$ CeƃD$D$C$ 1YƃD$D$C$ CcƃD$D$C$ CrƃD$D$C$ CuhƃD$D$C$ CoƃD$D$C$ CsƃD$D$C$ CemƃD$D$C$ CrƃD$D$C$ C ƃD$D$C$ CasƃD$D$C$ CvƃD$D$C$ CaƃD$D$C$ CjxƃD$D$C$ CoƃD$D$C$ CfƃD$D$C$ CngƃD$D$C$ CiƃD$D$C$ CeƃD$D$C$ CplƃD$D$C$ CyƃD$D$C$ CtƃD$D$C$ CoqƃD$D$C$ CfjƃD$D$C$ CnƃD$D$C$ CiƃD$D$C$ 1ڿƃD$D$C$ Cm餿ƃD$D$C$ CrQƃD$D$C$ CaƃD$D$C$ CrƃD$D$C$ Ce鼷ƃD$D$C$ CphƃD$D$C$ CoƃD$D$C$ ClƃD$D$C$ CaƃD$D$C$ C QƃD$D$C$ CnƃD$D$C$ CeƃD$D$C$ CdVƃD$D$C$ CdƃD$D$C$ CiƃD$D$C$ Cr颴ƃD$D$C$ CoOƃD$D$C$ CtƃD$D$C$ Ca騳ƃD$D$C$ CrTƃD$D$C$ CeƃD$D$C$ Cp魲ƃD$D$C$ CoZƃD$D$C$ CsƃD$D$C$ 1ƃD$D$C$ C ƃD$D$C$ 1ƃD$D$C$ CnƃD$D$C$ Ci_ƃD$D$C$ C- ƃD$D$C$ ChcƃD$D$C$ CTgƃD$D$C$ CTƃD$D$C$ CVƃD$D$C$ CtƃD$D$C$ C 7ƃD$D$C$ CkƃD$D$C$ CnƃD$D$C$ CeƃD$D$C$ Cl铹ƃD$D$C$ Cb?ƃD$D$C$ CaƃD$D$C$ Ct阸ƃD$D$C$ CvEƃD$D$C$ CrjƃD$D$C$ CoƃD$D$C$ CtïƃD$D$C$ CapƃD$D$C$ 1ƃD$D$C$ EP1WƃD$D$C$ 1SƃD$D$C$ 1"ƃD$D$C$ 1ƃD$D$C$ C,RrJI}W蚫JIRRzDR:>8 D(@ƃ(uFƃD$D$C$ 1hƃD$D$C$ 1}O96rʉ踪$LIJI]ȪJIL鷪XDl@ƃl鉪^Du@ƃu[JIߥJ~UCuƃD$D$C$ 1ƃD$D$C$ 1ƃD$D$C$ CuƃD$D$C$ 1mƃD$D$C$ MQ1 ƃD$D$C$ 1ƃD$D$C$ CaƃD$D$C$ CrfƃD$D$C$ CFƃD$D$C$ C_ƃD$D$C$ 1ƃD$D$C$ CcƃD$D$C$ CcƃD$D$C$ Cc>ƃD$D$C$ CAƃD$D$C$ C_UB@P*JI茢MA@P*:,N}O1SUT@F97=uƃD$D$E$tp 1pt뛋MMEUE}W)KI詡|ƃD$D$C$ 1ƃD$D$C$ 1UƃD$D$C$ 1ƃD$D$C$ CtƃD$D$C$ CaƃD$D$C$ CSLƃD$D$C$ C_ƃD$D$C$ 1ƃD$D$C$ C:cƃD$D$E$ 13ƃD$D$C$ 1EƃD$D$C$ 1ƃD$D$C$  1eRRƃD$D$C$ 1\ƃD$D$C$ 1EEEu9EE]fɍq@9v@M MqЉ vݍqwɍqэqɍq뻋E]u_D-@ƃ-EHZƃD$D$C$ ǃtƃD$D$C$ ǃnƃD$D$C$ ǃ@EE];}au_q}dU=u;ƃD$D$u4$t ǃtT@uFJI觜ƃD$D$C$ ǃJƃD$D$C$ ǃfUS$Ë&v ؃$[U$$LI AD  ƃ =ZHD_ƃ_AD _ƃ_=HDvƃvDAD eƃe=HDcƃcAD tƃt=/HDoƃo AD rƃr=B HD(ƃ(R=PD)ƃ)$[ÍvR_=PD ƃ rBDrƃr=VPDeƃeBDsƃs=PDtƃtXBDrƃr=PDiƃiOBDcƃc=PDtƃt$[Ë=PD ƃ BDvƃv=PDoƃo=BDlƃl=PDaƃa,BDtƃt=PDiƃiBDlƃl=/PDeƃeBD ƃ =zPDcƃc%BDoƃo=PDnƃn0 BDsƃs=ƃD$D$C$ 1v=CHD ƃ Rfn=ƃD$D$C$ 1=tIPD&ƃ&$[ËBD&ƃ&=uƃD$D$C$ 1댋BDcƃc=:PDoƃoBDmƃm=PDpƃptBDlƃl= PDeƃe BDxƃx=QPD ƃ $[Ë BDiƃi= PDmƃmBDaƃa=qPDgƃgBDiƃi=PDnƃnBDaƃa=PDrƃrRBDyƃy=ƃD$D$C$ 1(t&= HD ƃ RǗ=PD:ƃ:-BD:ƃ:=GPD*ƃ*$[fƃD$D$C$ 1DvƃD$D$C$U 1UƃD$D$C$ Cn&ƃD$D$C$ CiƃD$D$C$ Cg}ƃD$D$C$ Ca(ƃD$D$C$ CnƃD$D$C$ CoƃD$D$C$ CctƃD$D$C$ C ƃD$D$C$ 1vƃD$D$C$ CljƃD$D$C$ CiƃD$D$C$ CtƃD$D$C$U C U)vƃD$D$C$ C&ƃD$D$C$ CoƃD$D$C$ Cc_ƃD$D$C$ CeƃD$D$C$ ClyƃD$D$C$ Cp%ƃD$D$C$ CmƃD$D$C$U 1UƃD$D$C$ CsƃD$D$C$ C:ƃD$D$C$ C:lƃD$D$C$ CyJƃD$D$C$ CrGƃD$D$C$ CaƃD$D$C$U CrUvƃD$D$C$U CoUvƃD$D$C$U CtU\vƃD$D$C$U CcUvƃD$D$C$U CeUvƃD$D$C$U CvUGvƃD$D$C$U C_UvƃD$D$C$U C_UvƃD$D$C$ Cm<ƃD$D$C$ CiƃD$D$C$ Cr{ƃD$D$C$ C 'ƃD$D$C$ CrƃD$D$C$ CtAƃD$D$C$ CsƃD$D$C$ CeƃD$D$C$ Cx.ƃD$D$C$ C ƃD$D$C$ CcƃD$D$C$ CiJƃD$D$C$ CaƃD$D$C$ ClƃD$D$C$ Co\ƃD$D$C$ CvƃD$D$C$U 1U+fUWVS\ƉӅtmucts vuPKuCSCK %?&&u\[^_fu{uCSHv6CK %&t"t=u\[^_f}ă }Uĉ\[^_É}ċdžR=pD.PƆ.CX?u [vډ膊Uĉ\[^_Ð}čJ$k Eĉ\[^_ËFBD:Ɔ:=PD:Ɔ:TJD{Ɔ{AADdƆd=PDeƆeBDfƆf=GPDaƆaBDuƆu=PDlƆlLBDtƆt=PD Ɔ BDaƆa=RPDrƆrBDgƆg=PD#Ɔ#C@D$D$JI}̉}<$}1IMtj1VUf@TG9}v?T==uƆD$D$E$U 1ɊU뫋=PD}Ɔ}BD:Ɔ:=DPD:Ɔ:[ƆD$D$F$ 1dƆD$D$F$ 1ƆD$D$F$ F:ƆD$D$F$ 1%ƆD$D$F$ FgƆD$D$F$ FrƆD$D$F$ FaHƆD$D$F$ F ƆD$D$F$ FtƆD$D$F$ FlNƆD$D$F$ FuƆD$D$F$ FaƆD$D$F$ FfSƆD$D$F$ FeƆD$D$F$ FdƆD$D$F$ F{YƆD$D$F$ 1ƆD$D$F$ F:XƆD$D$F$ F}vUVS É։ʅt,AvHu1ɉJ=PD ƃ DBD[ƃ[t =PD]ƃ] [^Éȍv@8&AD  ƃ =+HD(ƃ(1ɉhBD)ƃ)ƃD$D$C$ 1vƃD$D$C$ 1vƃD$D$C$ 1v1ɉhƃD$D$C$ 1ƃD$D$C$U 1UƃD$D$C$U C UevUWVS,ÉMu~fH w$LIHt11ɋǃ1ɉe2BD(ƃ(Mt :=aPD)ƃ),[^_ÿKC< BD ƃ =)PD(ƃ(ǃ1ɉS=PD)ƃ)ƃD$D$C$ 11<(t<*=v11ƃD$D$C$ 1qƃD$D$C$ 1ƃD$D$C$ 1111AƃD$D$C$ 1MUWVS,É֋:t},[^_ÍvǀEEUR}Et\=t{PD>ƃ>,[^_ËBD ƃ oBD ƃ 끍vƃD$D$C$ 1WvƃD$D$C$ 1vƃD$D$C$ 1$vƃD$D$C$ 1vUS$Ët]tX=HD(ƃ({=t*PD)ƃ)$[Ív؃$[{ƃD$D$C$ 1fƃD$D$C$U 1UIUWVS<ËH pLucƐM뼍vAK S :EGBS 뜍vAK {,E,[^_fUWVS\ËP L<v!ƋC 8I\[^_f$ MIfzt1҉mƺC 8Iuƅ$lf؃\[^_fBS 1҉{NjC 8E1\[^_ÐBC R֍M fxC րr)V4KK@C C0$1ɉlu1땃S S;S}C RKBStAMIA$kƃC01f1ލPS Psdh؉MV…Mt&>t@t؉U;p1UȋMSs;svCFst ?HP$k C ;C$S4@C '}1ډ֐tXSЀ vhSv`Ct[DtVUtQLtLSITEMu vE1\[^_ÍvMt=$PjǀStQF 8EttV ;V$}N8E@C u`1AN F(N1;Nk FANPC xp1 C m1S1;Sk CBS@ MI@N 1҉Mĉuk TЋuċH@HЀ vuN 9_BfUWVSLË@ rt+Vt&Kt!JЀJv 1L[^_Ð$\MIfu vpC rt[VtfKu%@C C0$1ɉhu룉ut}tC ;C$}S<@C z@C C0 뭐@C C0 띉vljE䐅EC ;C$7S<@C }'@C $!^gljE볍PS PC F0$NI@C $" gljE\@C u$ fljE2@PЀ v<_t A<1҉ggljEC 8IK{$fljEҍlJIS;S1@C0C PS { HnEA< M1ҋސɍTQ@YЀ vMԅ1$$eljE5PS Hn{EA< { C 1҉ލvɍTQ@YЀ vEԅ14$jelj}@C $@eljE@C $eljEhPS H_2n51}:I?C ;C$vS<@C $d>fHK @<_90< mf@C 0 vS;S},4RsBSt)tNV8_1@C EԋS MMĉ;~FC ;C$S4@C AC AE1W :_pABS C1;C_k s@CM@NC ;C$61UWVS,Ƌ@ GTUÅUtytFt|N tfUhoZ1҉ $U1҉9Z1҉(Z1ۅx1҉$TSN0'$ T) N0$ iT$ FT$#T$ TPV PE$S_Vr~ PnEB< 1ɋf ҍLJ@ZЀ vEWN~ 1ۄG~ ]<_IM1Ɋ 1Ҁ$uvt <$tB;U|^;^k FC^xP~ ׉~ )U}냉$R71PV PE1GN_f.<Dž1ɉ1fC ǃxꉽw@t psLAc@t|9lu <<:GvsLNfOGf<$P_INVFvVF0t\u<<>PIt !v1ҍK]$HË}19‰Q\‹QT뷊C<vL<q<?11ɉfCЃ ƃxr?)}1ph a<9YRKD1=19‰/19!199ɉ9ɉ!?fUWVSPTdD NjPEĩ@t}uMtPBc@tBpPATEtLvt뱋T11Ɋ@ڃ փx0$dLPAH1vT|w_D$_IT11ɍv@ڃ ׃x8L $dNPBc@tD2lPFuTPb`[^_ÍvTsLPD1lLF,fT|dPBc@`VLTPBc@<2T11ɍv@ڃ ׃x8L $d:sL1PD2lFu sLdE@u sLPD1lF$vsLd@t!|tTLs ٍvPH`[^_ËPQH=sL>U@tEU䉕tfUWVSJ`@t zpJZG2xlLzlG?=sL-u3Xrxmzm:2=sLu3Xrxnzn.&=sLu3X r xozo"=sLu3Xrxp{zp=sL\u3XrxqGzq = sL(u3Xrxrzr= sLu3Xrxszs= sLu3X r xtzt= sLu3X$r$xuwzu= sLXu3X(r(xvCzv=sL$u3X,r,xwzw=sLu3X0r0xxzx=sLu3X4r4xyzy=sLu3X8r8xzuwzz=sLu\u3XD$%+u Ív*t)UWVSu>t1ۋDt @$(C9wu[^_(UWVS, pLuUBe[^_ÍvEX=$sL*Ɖ<$)W4$E-*QEƅt!89KDuETD뛍{ D$C!$(ƅ8t$$sL$)RRu)멉}GI=8cH$sL)VUZu sLC sLZ=pL$sLk)RD$D$sL$M) ?9vS L$$Um'ƅUt) T1 'D$sL$(SS8$sL(Q&$t 1e[^ÍvC$ Qu&f$ Rtˍve[^1UVSu] t] E[^# v[^ UE$ Rt1fj fUS$\ ËE$G R$E QE]fUE D$E$h t1Ð fUS]D$ D$D$$ C]ÐUE@$h QÐUS]$ Ru 1]fD$C$ t݉$ S]ÍvUU1 US]$ Qx-D$D$C$r ]f1]ÐUS]CCD$ D$D$$C ]ÍvUVS] Ɖ$Rt;stDD$C $uCse[^Ð$Se[^Ív$VC1e[^ÍvUS]1x;Kt Y[fC1Y[ÍvCK1Y[US]CHCt1]C$ RxD$D$C $ ]Ð%P%ijP%гP%̳P%ȳP%ԳPS\$t ([鍶S\$ wt,$t$Jǃ$ǃ([<\$\$ t$ t-$1t $Ɖ$\$t$v\$\$ t$(}1\$t$Í&tc\$$$`((~s4$f t$$t$\$Í,\$$$tBǃ(f1K}t)$$ǃ$ǃ(1ʍ&'VS\$ t$$tt|_t-$t&;(~?$u[^Í$t$1ǃ$ǃ([^ÍvvڍvL$<$P$@$D$H;]$XAl$,D$\$,$ !%tꩀ)3$3É,l$<$,tKD$/<$<$D$+9l$t"D$\<$9t<$f\<$q Af*1dž$dž(džfdžfdž؋$@$<$D$HL]1N1? 륍v/땐?(\?D$%`fDhfDEtÐ%ܳP%P%P%P%P%P%P%дP%̴P%P%PP%TP%P%DP%P%P%XP%P%xP%dP%ĴP%P%ȴP%hP%ܴP%P%*EED$ D$D$4$`Nj P@\$ D$0D$$lGI5Ut:\$4$R\$ D$D$$GIEtO f\$<$f P@D$ D$D$$LGIvF(f<$JtA$ fcv P@D$ D$-D$$GI`Ή$$RƉ\$ D$ D$$GI,\$4$P\$$ 3 v' $7UWVS,u] EE}\$4$u,v 1,[^_ÐUUu ]@,[^_f,[^_ÐUS]E D$E$\tEC C[Ð1[US$E]EEEEML$ L$M L$$REt1$[ËE$[ÐUWVSu]}$;] t-ED$4$tEGG 1[^_ÐED$4$ytEGڐUE9EDÐUWVS,U] u}|$ t$\$$UUt ,[^_ÍvB}u] EB,[^_UWVS<}M EEUu]]܋E E]$T$<$UԉMUԋMt*3USxV19uDC 1<[^_Ív;utCG8]$]] ]܉]uUUUM EG<[^_uC fE܉D$<$UԉM'UԋMtUS널UWVS,UM ]}u9t Bu}]M EB ,[^_|$$UMUMtĸ,[^_ÐUFIÐUFIÐU帿FIÐU GIÐU帰FIÐUEU 9tD@*t"R:*t**t!T$$ fx*u1f@ܐB*uU1ÐU1ÐU1ÐUEU 9tD@*t"R:*t**t!T$$fx*u1f@ܐB*uUEcICUEcIÐUS]cI$@][ UEcIUEcIUEcIÐUEdIUEdIÐUdH`H$e񐐐U`HU`HÐUdHUdHÐU塄HUHÐUe@ÐU`H[$UUEtÐUE$Bt$v$VUS]u fHtЉ$=t[$GcID$uDD$aI$=Bt$$UWS$PÅta@P1؃[_fpLt;$hHt+$cID$oDD$`I$LcH1A tyu УLcH`H=pL^$hHJ$8cID$XoDD$`I$.Bt$$UWVSu`4$ÅtJ@`1[^_fpLt:$hHt*$cID$oDD$`I$HcHv1 fA tu УHcH `cHpLQ$hHl=$cID$XoDD$`I$ Bt $$UVSB0U0J0Z4ԼӼwvu31[^fJxYZH9trB([^û)US]t.$~SԼҼww C܉$GUWVSL]$$cID$uDD$`I$:5$E4$Ut@0tP1USt(J0Z4ԼӼv0$*[ÃwJxItt*J[ÍvAuZfJ0$US]`Hr`Hr][UpLt:$hHJt\$^cID$oDD$`I$T`H̉!LcH[Btl$-`HP1!LcH=pLt$hHt$cID$XoDD$`I$둉$rUS]`cHr`Hr`][Ff pLt:$hH:tS$NcID$oDD$`I$Dف`cH !HcH[Bte$ف`cH !HcH=pLt$hHt$cID$XoDD$`I$똉$rUE@ÐU$tHU$tHUD$D$0GI$zYUS@t0S0K4ԼѼv 0$菽$fw[ܐUS]CCU PUPdHP`HP@@++C@DCUNG@HlD $>$UWVSEU}E}tČ[^_fM0MԼҼEw wE} <$褸EyM‰ƊE[a aI  aI    M37=33H37933-W} aIDAT!:PLAYER.SnALTPLAYER.S.CHARGEN.BIN.PALETTE.BIN.CURSOR.BIN6 GOATTRK2.BMP;------------------------------------------------------------------------------- ; GoatTracker V2.68 playroutine ; ; NOTE: This playroutine source code does not fall under the GPL license! ; Use it, or song binaries created from it freely for any purpose, commercial ; or noncommercial. ; ; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer. ; Does not directly compile on DASM etc. ;------------------------------------------------------------------------------- ;Defines will be inserted by the relocator here .IF (ZPGHOSTREGS == 0) mt_temp1 = zpbase+0 mt_temp2 = zpbase+1 .ELSE ghostfreqlo = zpbase+0 ghostfreqhi = zpbase+1 ghostpulselo = zpbase+2 ghostpulsehi = zpbase+3 ghostwave = zpbase+4 ghostad = zpbase+5 ghostsr = zpbase+6 ghostfiltcutlow = zpbase+21 ghostfiltcutoff = zpbase+22 ghostfiltctrl = zpbase+23 ghostfilttype = zpbase+24 mt_temp1 = zpbase+25 mt_temp2 = zpbase+26 .ENDIF ;Defines for the music data ;Patterndata notes ENDPATT = $00 INS = $00 FX = $40 FXONLY = $50 NOTE = $60 REST = $bd KEYOFF = $be KEYON = $bf FIRSTPACKEDREST = $c0 PACKEDREST = $00 ;Effects DONOTHING = $00 PORTAUP = $01 PORTADOWN = $02 TONEPORTA = $03 VIBRATO = $04 SETAD = $05 SETSR = $06 SETWAVE = $07 SETWAVEPTR = $08 SETPULSEPTR = $09 SETFILTPTR = $0a SETFILTCTRL = $0b SETFILTCUTOFF = $0c SETMASTERVOL = $0d SETFUNKTEMPO = $0e SETTEMPO = $0f ;Orderlist commands REPEAT = $d0 TRANSDOWN = $e0 TRANS = $f0 TRANSUP = $f0 LOOPSONG = $ff ;Wave,pulse,filttable comands LOOPWAVE = $ff LOOPPULSE = $ff LOOPFILT = $ff SETPULSE = $80 SETFILTER = $80 SETCUTOFF = $00 .ORG (base) ;Jump table jmp mt_init jmp mt_play .IF (SOUNDSUPPORT != 0) jmp mt_playsfx .ENDIF .IF (VOLSUPPORT != 0) jmp mt_setmastervol .ENDIF ;Author info .IF (NOAUTHORINFO == 0) authorinfopos = base + $20 checkpos1: .IF ((authorinfopos - checkpos1) > 15) mt_tick0jumptbl: .BYTE (mt_tick0_0 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_5 % 256) .BYTE (mt_tick0_6 % 256) .BYTE (mt_tick0_7 % 256) .BYTE (mt_tick0_8 % 256) .BYTE (mt_tick0_9 % 256) .BYTE (mt_tick0_a % 256) .BYTE (mt_tick0_b % 256) .BYTE (mt_tick0_c % 256) .BYTE (mt_tick0_d % 256) .BYTE (mt_tick0_e % 256) .BYTE (mt_tick0_f % 256) .ENDIF checkpos2: .IF ((authorinfopos - checkpos2) > 4) mt_effectjumptbl: .BYTE (mt_effect_0 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_3 % 256) .BYTE (mt_effect_4 % 256) .ENDIF checkpos3: .IF ((authorinfopos - checkpos3) > 1) mt_funktempotbl: .BYTE (8,5) .ENDIF ;This is pretty stupid way of filling left-out space, but .ORG ;seemed to bug checkpos4: .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF checkpos5: .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF checkpos6: .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF mt_author: .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .ENDIF ;0 Instrument vibrato mt_tick0_0: .IF (NOEFFECTS == 0) .IF (NOINSTRVIB == 0) lda mt_insvibparam-1,y jmp mt_tick0_34 .ELSE .IF (NOVIB == 0) jmp mt_tick0_34 .ENDIF .ENDIF .ENDIF ;1,2 Portamentos mt_tick0_12: .IF (NOVIB == 0) tay lda #$00 sta mt_chnvibtime,x tya .ENDIF ;3,4 Toneportamento, Vibrato mt_tick0_34: .IF (NOEFFECTS == 0) .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) sta mt_chnparam,x lda mt_chnnewfx,x sta mt_chnfx,x .ENDIF rts .ENDIF ;5 Set AD mt_tick0_5: .IF (NOSETAD == 0) .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 1) sta mt_chntempo+7 .ENDIF .IF (NUMCHANNELS > 2) sta mt_chntempo+14 .ENDIF rts .ENDIF mt_tick0_f_setchantempo: .IF (NOCHANNELTEMPO == 0) and #$7f sta mt_chntempo,x rts .ENDIF ;Continuous effect code ;0 Instrument vibrato .IF (NOINSTRVIB == 0) mt_effect_0_delay: dec mt_chnvibdelay,x mt_effect_0_donothing: jmp mt_done mt_effect_0: beq mt_effect_0_donothing ;Speed 0 = no vibrato at all lda mt_chnvibdelay,x bne mt_effect_0_delay .ELSE mt_effect_0: mt_effect_0_donothing: jmp mt_done .ENDIF ;4 Vibrato mt_effect_4: .IF (NOVIB == 0) .IF (NOCALCULATEDSPEED == 0) lda mt_speedlefttbl-1,y .IF (NONORMALSPEED == 0) bmi mt_effect_4_nohibyteclear ldy #$00 ;Clear speed highbyte sty 1) sta mt_init+5 asl adc #$00 .ENDIF sta mt_initsongnum+1 rts ;Play soundeffect -routine .IF (SOUNDSUPPORT != 0) ;Sound FX init routine mt_playsfx: sta mt_playsfxlo+1 sty mt_playsfxhi+1 lda mt_chnsfx,x ;Need a priority check? beq mt_playsfxok tya ;Check address highbyte cmp mt_chnsfxhi,x bcc mt_playsfxskip ;Lower than current -> skip bne mt_playsfxok ;Higher than current -> OK lda mt_playsfxlo+1 ;Check address lowbyte cmp mt_chnsfxlo,x bcc mt_playsfxskip ;Lower than current -> skip mt_playsfxok: lda #$01 sta mt_chnsfx,x mt_playsfxlo: lda #$00 sta mt_chnsfxlo,x mt_playsfxhi: lda #$00 sta mt_chnsfxhi,x mt_playsfxskip: rts .ENDIF ;Set mastervolume -routine .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0)) mt_setmastervol: sta mt_masterfader+1 rts .ENDIF ;Playroutine mt_play: ldx #$00 ;Channel index ;Song initialization mt_initsongnum: ldy #$00 bmi mt_filtstep txa ldx #NUMCHANNELS * 14 - 1 mt_resetloop: sta mt_chnsongptr,x ;Reset sequencer + voice dex ;variables on all channels bpl mt_resetloop .IF (ZPGHOSTREGS == 0) .IF (NUMCHANNELS == 2) sta SIDBASE+$12 .ENDIF .IF (NUMCHANNELS == 1) sta SIDBASE+$0b sta SIDBASE+$12 .ENDIF sta SIDBASE+$15 ;Reset filter cutoff lowbyte .ELSE sta 1) tya iny sta mt_chnsongnum,x ;Store index to songtable .ENDIF mt_defaulttempo: lda #DEFAULTTEMPO ;Set default tempo sta mt_chntempo,x lda #$01 sta mt_chncounter,x ;Reset counter sta mt_chninstr,x ;Reset instrument jmp mt_loadregswaveonly ;Load waveform ;Filter execution mt_filtstep: .IF (NOFILTER == 0) ldy #$00 ;See if filter stopped beq mt_filtdone .IF (NOFILTERMOD == 0) mt_filttime: lda #$00 ;See if time left for mod. bne mt_filtmod ;step .ENDIF mt_newfiltstep: lda mt_filttimetbl-1,y ;$80-> = set filt parameters beq mt_setcutoff ;$00 = set cutoff .IF (NOFILTERMOD == 0) bpl mt_newfiltmod .ENDIF mt_setfilt: asl ;Set passband sta mt_filttype+1 lda mt_filtspdtbl-1,y ;Set resonance/channel sta mt_filtctrl+1 lda mt_filttimetbl,y ;Check for cutoff setting bne mt_nextfiltstep2 ;following immediately mt_setcutoff2: iny mt_setcutoff: lda mt_filtspdtbl-1,y ;Take cutoff value sta mt_filtcutoff+1 .IF (NOFILTERMOD == 0) jmp mt_nextfiltstep mt_newfiltmod: sta mt_filttime+1 ;$01-$7f = new modulation step mt_filtmod: lda mt_filtspdtbl-1,y ;Take filt speed clc adc mt_filtcutoff+1 sta mt_filtcutoff+1 dec mt_filttime+1 bne mt_storecutoff .ENDIF mt_nextfiltstep: lda mt_filttimetbl,y ;Jump in filttable? mt_nextfiltstep2: cmp #LOOPFILT iny tya bcc mt_nofiltjump lda mt_filtspdtbl-1,y ;Take jump point mt_nofiltjump: sta mt_filtstep+1 mt_filtdone: mt_filtcutoff: lda #$00 mt_storecutoff: .IF (ZPGHOSTREGS == 0) sta SIDBASE+$16 .ELSE sta 0) || (NOFIRSTWAVECMD == 0)) lda #$ff mt_skipwave2: sta mt_chngate,x ;Reset gateflag .ELSE inc mt_chngate,x .ENDIF mt_skipwave: .IF (NOPULSE == 0) lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) beq mt_skippulse sta mt_chnpulseptr,x .IF (NOPULSEMOD == 0) lda #$00 ;Reset pulse step duration sta mt_chnpulsetime,x .ENDIF .ENDIF mt_skippulse: .IF (NOFILTER == 0) lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) beq mt_skipfilt sta mt_filtstep+1 .IF (NOFILTERMOD == 0) lda #$00 sta mt_filttime+1 .ENDIF .ENDIF mt_skipfilt: lda mt_inswaveptr-1,y ;Load waveptr sta mt_chnwaveptr,x lda mt_inssr-1,y ;Load Sustain/Release .IF (BUFFEREDWRITES == 0) sta SIDBASE+$06,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnsr,x .ELSE sta 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) lda mt_chninstr,x cmp #FIRSTNOHRINSTR ;Instrument order: .IF (NUMLEGATOINSTR > 0) bcs mt_nohr_legato ;With HR - no HR - legato .ELSE bcs mt_skiphr .ENDIF .ENDIF .IF (NUMHRINSTR > 0) lda #SRPARAM ;Hard restart .IF (BUFFEREDWRITES == 0) sta SIDBASE+$06,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnsr,x .ELSE sta 0) mt_nohr_legato: cmp #FIRSTLEGATOINSTR bcc mt_skiphr bcs mt_rest .ENDIF ;Sound FX code .IF (SOUNDSUPPORT != 0) .IF (ZPGHOSTREGS == 0) ;Sound FX code without ghostregs mt_sfxexec: lda mt_chnsfxlo,x sta 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnfx: .BYTE (0) mt_chnparam: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) mt_chnpulsetime: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .IF ((ZPGHOSTREGS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF ((BUFFEREDWRITES != 0) || (FIXEDPARAMS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnad: .BYTE (0) mt_chnsr: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) mt_chnlastnote: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE ;Optimized channel variables mt_chnsongptr: .BYTE (0) mt_chnpattptr: .BYTE (0) mt_chnpackedrest: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnpulsetime: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .ENDIF ;Songdata & frequencytable will be inserted by the relocator here ;------------------------------------------------------------------------------- ; GoatTracker V2.68 alternative SID write order playroutine ; ; NOTE: This playroutine source code does not fall under the GPL license! ; Use it, or song binaries created from it freely for any purpose, commercial ; or noncommercial. ; ; NOTE 2: This code is in the format of Magnus Lind's assembler from Exomizer. ; Does not directly compile on DASM etc. ;------------------------------------------------------------------------------- ;Defines will be inserted by the relocator here .IF (ZPGHOSTREGS == 0) mt_temp1 = zpbase+0 mt_temp2 = zpbase+1 .ELSE ghostfreqlo = zpbase+0 ghostfreqhi = zpbase+1 ghostpulselo = zpbase+2 ghostpulsehi = zpbase+3 ghostwave = zpbase+4 ghostad = zpbase+5 ghostsr = zpbase+6 ghostfiltcutlow = zpbase+21 ghostfiltcutoff = zpbase+22 ghostfiltctrl = zpbase+23 ghostfilttype = zpbase+24 mt_temp1 = zpbase+25 mt_temp2 = zpbase+26 .ENDIF ;Defines for the music data ;Patterndata notes ENDPATT = $00 INS = $00 FX = $40 FXONLY = $50 NOTE = $60 REST = $bd KEYOFF = $be KEYON = $bf FIRSTPACKEDREST = $c0 PACKEDREST = $00 ;Effects DONOTHING = $00 PORTAUP = $01 PORTADOWN = $02 TONEPORTA = $03 VIBRATO = $04 SETAD = $05 SETSR = $06 SETWAVE = $07 SETWAVEPTR = $08 SETPULSEPTR = $09 SETFILTPTR = $0a SETFILTCTRL = $0b SETFILTCUTOFF = $0c SETMASTERVOL = $0d SETFUNKTEMPO = $0e SETTEMPO = $0f ;Orderlist commands REPEAT = $d0 TRANSDOWN = $e0 TRANS = $f0 TRANSUP = $f0 LOOPSONG = $ff ;Wave,pulse,filttable comands LOOPWAVE = $ff LOOPPULSE = $ff LOOPFILT = $ff SETPULSE = $80 SETFILTER = $80 SETCUTOFF = $00 .ORG (base) ;Jump table jmp mt_init jmp mt_play .IF (SOUNDSUPPORT != 0) jmp mt_playsfx .ENDIF .IF (VOLSUPPORT != 0) jmp mt_setmastervol .ENDIF ;Author info .IF (NOAUTHORINFO == 0) authorinfopos = base + $20 checkpos1: .IF ((authorinfopos - checkpos1) > 15) mt_tick0jumptbl: .BYTE (mt_tick0_0 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_12 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_34 % 256) .BYTE (mt_tick0_5 % 256) .BYTE (mt_tick0_6 % 256) .BYTE (mt_tick0_7 % 256) .BYTE (mt_tick0_8 % 256) .BYTE (mt_tick0_9 % 256) .BYTE (mt_tick0_a % 256) .BYTE (mt_tick0_b % 256) .BYTE (mt_tick0_c % 256) .BYTE (mt_tick0_d % 256) .BYTE (mt_tick0_e % 256) .BYTE (mt_tick0_f % 256) .ENDIF checkpos2: .IF ((authorinfopos - checkpos2) > 4) mt_effectjumptbl: .BYTE (mt_effect_0 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_12 % 256) .BYTE (mt_effect_3 % 256) .BYTE (mt_effect_4 % 256) .ENDIF checkpos3: .IF ((authorinfopos - checkpos3) > 1) mt_funktempotbl: .BYTE (8,5) .ENDIF ;This is pretty stupid way of filling left-out space, but .ORG ;seemed to bug checkpos4: .IF ((authorinfopos - checkpos4) > 0) .BYTE (0) .ENDIF checkpos5: .IF ((authorinfopos - checkpos5) > 0) .BYTE (0) .ENDIF checkpos6: .IF ((authorinfopos - checkpos6) > 0) .BYTE (0) .ENDIF mt_author: .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .BYTE (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0) .ENDIF ;0 Instrument vibrato mt_tick0_0: .IF (NOEFFECTS == 0) .IF (NOINSTRVIB == 0) lda mt_insvibparam-1,y jmp mt_tick0_34 .ELSE .IF (NOVIB == 0) jmp mt_tick0_34 .ENDIF .ENDIF .ENDIF ;1,2 Portamentos mt_tick0_12: .IF (NOVIB == 0) tay lda #$00 sta mt_chnvibtime,x tya .ENDIF ;3,4 Toneportamento, Vibrato mt_tick0_34: .IF (NOEFFECTS == 0) .IF ((NOTONEPORTA == 0) || (NOPORTAMENTO == 0) || (NOVIB == 0)) sta mt_chnparam,x lda mt_chnnewfx,x sta mt_chnfx,x .ENDIF rts .ENDIF ;5 Set AD mt_tick0_5: .IF (NOSETAD == 0) .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 1) sta mt_chntempo+7 .ENDIF .IF (NUMCHANNELS > 2) sta mt_chntempo+14 .ENDIF rts .ENDIF mt_tick0_f_setchantempo: .IF (NOCHANNELTEMPO == 0) and #$7f sta mt_chntempo,x rts .ENDIF ;Continuous effect code ;0 Instrument vibrato .IF (NOINSTRVIB == 0) mt_effect_0_delay: dec mt_chnvibdelay,x mt_effect_0_donothing: jmp mt_done mt_effect_0: beq mt_effect_0_donothing ;Speed 0 = no vibrato at all lda mt_chnvibdelay,x bne mt_effect_0_delay .ELSE mt_effect_0: mt_effect_0_donothing: jmp mt_done .ENDIF ;4 Vibrato mt_effect_4: .IF (NOVIB == 0) .IF (NOCALCULATEDSPEED == 0) lda mt_speedlefttbl-1,y .IF (NONORMALSPEED == 0) bmi mt_effect_4_nohibyteclear ldy #$00 ;Clear speed highbyte sty 1) sta mt_init+5 asl adc #$00 .ENDIF sta mt_initsongnum+1 rts ;Play soundeffect -routine .IF (SOUNDSUPPORT != 0) ;Sound FX init routine mt_playsfx: sta mt_playsfxlo+1 sty mt_playsfxhi+1 lda mt_chnsfx,x ;Need a priority check? beq mt_playsfxok tya ;Check address highbyte cmp mt_chnsfxhi,x bcc mt_playsfxskip ;Lower than current -> skip bne mt_playsfxok ;Higher than current -> OK lda mt_playsfxlo+1 ;Check address lowbyte cmp mt_chnsfxlo,x bcc mt_playsfxskip ;Lower than current -> skip mt_playsfxok: lda #$01 sta mt_chnsfx,x mt_playsfxlo: lda #$00 sta mt_chnsfxlo,x mt_playsfxhi: lda #$00 sta mt_chnsfxhi,x mt_playsfxskip: rts .ENDIF ;Set mastervolume -routine .IF ((VOLSUPPORT != 0) && (NOSETMASTERVOL != 0)) mt_setmastervol: sta mt_masterfader+1 rts .ENDIF ;Playroutine mt_play: ldx #$00 ;Channel index ;Song initialization mt_initsongnum: ldy #$00 bmi mt_filtstep txa ldx #NUMCHANNELS * 14 - 1 mt_resetloop: sta mt_chnsongptr,x ;Reset sequencer + voice dex ;variables on all channels bpl mt_resetloop .IF (ZPGHOSTREGS == 0) .IF (NUMCHANNELS == 2) sta SIDBASE+$12 .ENDIF .IF (NUMCHANNELS == 1) sta SIDBASE+$0b sta SIDBASE+$12 .ENDIF sta SIDBASE+$15 ;Reset filter cutoff lowbyte .ELSE sta 1) tya iny sta mt_chnsongnum,x ;Store index to songtable .ENDIF mt_defaulttempo: lda #DEFAULTTEMPO ;Set default tempo sta mt_chntempo,x lda #$01 sta mt_chncounter,x ;Reset counter sta mt_chninstr,x ;Reset instrument jmp mt_loadregswave ;Load waveform ;Filter execution mt_filtstep: .IF (NOFILTER == 0) ldy #$00 ;See if filter stopped beq mt_filtdone .IF (NOFILTERMOD == 0) mt_filttime: lda #$00 ;See if time left for mod. bne mt_filtmod ;step .ENDIF mt_newfiltstep: lda mt_filttimetbl-1,y ;$80-> = set filt parameters beq mt_setcutoff ;$00 = set cutoff .IF (NOFILTERMOD == 0) bpl mt_newfiltmod .ENDIF mt_setfilt: asl ;Set passband sta mt_filttype+1 lda mt_filtspdtbl-1,y ;Set resonance/channel sta mt_filtctrl+1 lda mt_filttimetbl,y ;Check for cutoff setting bne mt_nextfiltstep2 ;following immediately mt_setcutoff2: iny mt_setcutoff: lda mt_filtspdtbl-1,y ;Take cutoff value sta mt_filtcutoff+1 .IF (NOFILTERMOD == 0) jmp mt_nextfiltstep mt_newfiltmod: sta mt_filttime+1 ;$01-$7f = new modulation step mt_filtmod: lda mt_filtspdtbl-1,y ;Take filt speed clc adc mt_filtcutoff+1 sta mt_filtcutoff+1 dec mt_filttime+1 bne mt_storecutoff .ENDIF mt_nextfiltstep: lda mt_filttimetbl,y ;Jump in filttable? mt_nextfiltstep2: cmp #LOOPFILT iny tya bcc mt_nofiltjump lda mt_filtspdtbl-1,y ;Take jump point mt_nofiltjump: sta mt_filtstep+1 mt_filtdone: mt_filtcutoff: lda #$00 mt_storecutoff: .IF (ZPGHOSTREGS == 0) sta SIDBASE+$16 .ELSE sta 0) || (NOFIRSTWAVECMD == 0)) lda #$ff mt_skipwave2: sta mt_chngate,x ;Reset gateflag .ELSE inc mt_chngate,x .ENDIF mt_skipwave: .IF ((BUFFEREDWRITES == 0) && (NOFIRSTWAVECMD == 0)) lda mt_chnwave,x and mt_chngate,x sta SIDBASE+$04,x .ENDIF lda mt_inswaveptr-1,y ;Load waveptr sta mt_chnwaveptr,x .IF (NOPULSE == 0) lda mt_inspulseptr-1,y ;Load pulseptr (if nonzero) beq mt_skippulse sta mt_chnpulseptr,x .IF (NOPULSEMOD == 0) lda #$00 ;Reset pulse step duration sta mt_chnpulsetime,x .ENDIF .ENDIF mt_skippulse: .IF (NOFILTER == 0) lda mt_insfiltptr-1,y ;Load filtptr (if nonzero) beq mt_skipfilt sta mt_filtstep+1 .IF (NOFILTERMOD == 0) lda #$00 sta mt_filttime+1 .ENDIF .ENDIF mt_skipfilt: lda mt_insad-1,y ;Load Attack/Decay .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 0) && (NUMNOHRINSTR > 0)) || (NUMLEGATOINSTR > 0)) lda mt_chninstr,x cmp #FIRSTNOHRINSTR ;Instrument order: .IF (NUMLEGATOINSTR > 0) bcs mt_nohr_legato ;With HR - no HR - legato .ELSE bcs mt_skiphr .ENDIF .ENDIF .IF (NUMHRINSTR > 0) lda #ADPARAM ;Hard restart .IF (BUFFEREDWRITES == 0) sta SIDBASE+$05,x .ELSE .IF (ZPGHOSTREGS == 0) sta mt_chnad,x .ELSE sta 0) mt_nohr_legato: cmp #FIRSTLEGATOINSTR bcc mt_skiphr bcs mt_rest .ENDIF ;Sound FX code .IF (SOUNDSUPPORT != 0) .IF (ZPGHOSTREGS == 0) ;Sound FX code without ghostregs mt_sfxexec: lda mt_chnsfxlo,x sta 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnfx: .BYTE (0) mt_chnparam: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) mt_chnpulsetime: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .IF ((ZPGHOSTREGS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF ((BUFFEREDWRITES != 0) || (FIXEDPARAMS == 0) || (NOCALCULATEDSPEED == 0)) mt_chnad: .BYTE (0) mt_chnsr: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) mt_chnlastnote: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnwavetime: .BYTE (0) mt_chnsfx: .BYTE (0) mt_chnsfxlo: .BYTE (0) mt_chnsfxhi: .BYTE (0) mt_chngatetimer: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF .ENDIF .ELSE ;Optimized channel variables mt_chnsongptr: .BYTE (0) mt_chnpattptr: .BYTE (0) mt_chnpackedrest: .BYTE (0) mt_chnnewnote: .BYTE (0) mt_chnwaveptr: .BYTE (0) mt_chnwave: .BYTE (0) mt_chnpulseptr: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnpulsetime: .BYTE (0) mt_chnpulselo: .BYTE (0) mt_chnpulsehi: .BYTE (0) mt_chnvibtime: .BYTE (0) mt_chnvibdelay: .BYTE (0) mt_chnfreqlo: .BYTE (0) mt_chnfreqhi: .BYTE (0) .IF (NUMCHANNELS > 1) .BYTE (0,0,0,0,0,0,0) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (0,0,0,0,0,0,0) .ENDIF mt_chnsongnum: .BYTE (0) mt_chnpattnum: .BYTE (0) mt_chntempo: .BYTE (0) mt_chncounter: .BYTE (0) mt_chnnote: .BYTE (0) mt_chninstr: .BYTE (1) mt_chngate: .BYTE ($fe) .IF (NUMCHANNELS > 1) .BYTE (1,0,0,0,0,1,$fe) .ENDIF .IF (NUMCHANNELS > 2) .BYTE (2,0,0,0,0,1,$fe) .ENDIF .ENDIF ;Songdata & frequencytable will be inserted by the relocator here <<<fff$lllllll||| 0`Ɔ8ll8vv000` 000000 0 0f<~6ll60``|```08ll8~p0`lllll|fffff|``vv ll<8ll8|l6l0fΞ>0`܆ > 0`0 ~0000`|6666666666666666666666666666667666666668l8l88l>lffff<8ll88lllll|~~`~AEINRW\bhnu|@HDHHHLHPHTHXH\H`HdHhHlHpHtHxH|HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHH H$H(H,H0H4H8HB$EPFPF @  dL #H&)*-00??8888888888888888<<<<<<<<>>????8888888888888888<<<<<<<<>>?? 8?@@@_@@```o@````pw``p@pp{@p@@p`px}@`x`xx~p||~~||p~|x`x``}xx`p@@p@{xp@p@``wpp```@o```@@_X@@@?<0/7;=>0?08?>???OW[]^@_@@_\___g@k@@m@@@@n@``o``o`ooo@@@@@`s@@@``u````v```wppwpwww`````y``ppzppp{@pp{x{{{pppp|p@pp}@px}x}}}@@x`xx~`xx~|~~~p||~~/7;=>0?08?>???OW[]^@_@@_\___g@k@m@@@@n@``o``o`ooo@@@@@`s@@@``u````v```wppwpwww`````y``ppzppp{@pp{x{{{pppp|p@pp}@px}x}}}@@x`xx~`xx~|~~~p|||~? 0xx~? 0xx~8888888888888888<<<<<<<>??<?? ^_@@@``o@@@@@@@`@@````pw@@@@@@@@```@@@````p```pppx{```p`ppppppxxxx|xxx|x||~|~~~~|~||x|xxx|xxxxpppxpp`p```{xppp```p````@@@```@@@@@@@@@wp````@@`@@@@@@@@od`@@@_^L??>;=>? ???? ^__ ___GCeno@@o@oooc@a@@@@p@@@@@p@``w`www@@`@@`@``y@@@@@@`@@@````x@``````x`ppxpy{{```````p```p`pp|`pppppp|pxx|x||}pxxxxxx|x||~|~~~|||~~~ p` pppppxxx||~~? ?_ 96 C-LLz"3DUfw}CI-CI CICI,CI0CI/CI.CI DI DIDIDIDIDIDI"DI %DI!(DI"+DI#.DI$2DI%6DIa:DInDIo@DIcBDIpDDIdFDIqHDIeJDIrLDIfNDIsPDIgRDItTDIhVDIuXDIiZDIv\DIj^DIw`DIkbDIxdDIlfDIyhDImjDIzlDI1nDI2pDI3rDI4tDI5vDI6xDI7zDI8|DI9~DI0DI-DI=DI[DI]DI;DI'DI`DI,DI.DI/DI\DI4DI2DIDIDIDIDIDIDIDIDIDIDI7DI8DI?DIEI@DpoDvDlibgcc_s_dw2-1.dll__register_frame_infolibgcj-11.dll_Jv_RegisterClasses__deregister_frame_infoLOAD SONGLOAD INSTRUMENTSAVE SONGSAVE INSTRUMENTReally Quit (y/n)?Optimize everything (y/n)?Clear orderlists (y/n)?Clear patterns (y/n)?Clear instruments (y/n)?Clear tables (y/n)?Clear songname (y/n)?Pattern length:%02d H@G@G@I@I@G@(J@G@H@G@G@G@G@G@G@G@G@G@G@F@0I@I@G@I@(J@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@G@I@ k@,k@8k@k@k@rt%fUsage: GOATTRK2 [songname] [options]Options:-Axx Set ADSR parameter for hardrestart in hex. DEFAULT=0F00-Bxx Set sound buffer length in milliseconds DEFAULT=100-Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on)-Dxx Pattern row display (0 = decimal, 1 = hexadecimal)-Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=6581-Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default)-Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz)-Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.)-Ixx Set reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) DEFAULT=off-Kxx Note-entry mode (0 = PROTRACKER 1 = DMC) DEFAULT=PROTRK.-Lxx SID memory location in hex. DEFAULT=D400-Mxx Set sound mixing rate DEFAULT=44100-Oxx Set pulseoptimization/skipping (0 = off, 1 = on) DEFAULT=on-Rxx Set realtime-effect optimization/skipping (0 = off, 1 = on) DEFAULT=on-Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.)-Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0-Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0-Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on-Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window-Zxx Set random reSID write delay in cycles (0 = off) DEFAULT=off-N Use NTSC timing-P Use PAL timing (DEFAULT)-W Write sound output to a file SIDAUDIO.RAW-? Show this info again-?? Standalone online help window%u%xSound init failed. Press any key to run without sound (notice that song timer won't start)wt;------------------------------------------------------------------------------ ;GT2 config file. Rows starting with ; are comments. Hexadecimal parameters are ;to be preceded with $ and decimal parameters with nothing. ;------------------------------------------------------------------------------ ;reSID buffer length (in milliseconds) %d ;reSID mixing rate (in Hz) %d ;Hardsid device number (0 = off) %d ;reSID model (0 = 6581, 1 = 8580) %d ;Timing mode (0 = PAL, 1 = NTSC) %d ;Packer/relocator fileformat (0 = SID, 1 = PRG, 2 = BIN) %d ;Packer/relocator player address $%04x ;Packer/relocator zeropage baseaddress $%02x ;Packer/relocator player type (0 = standard ... 3 = minimal) %d ;Key entry mode (0 = Protracker, 1 = DMC) %d ;Pattern highlight step size %d ;Speed multiplier (0 = 25Hz, 1 = 1X, 2 = 2X etc.) %d ;Use CatWeasel SID (0 = off, 1 = on) %d ;Hardrestart ADSR parameter $%04x ;reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) %d ;Hexadecimal pattern display (0 = off, 1 = on) %d ;SID baseaddress $%04x ;Finevibrato mode (0 = off, 1 = on) %d ;Pulseskipping (0 = off, 1 = on) %d ;Realtime effect skipping (0 = off, 1 = on) %d ;Random reSID write delay in cycles (0 = off) %d ;Custom SID clock cycles per second (0 = use PAL/NTSC default) %d ;HardSID interactive mode buffer size (in milliseconds, 0 = maximum/no flush) %d ;HardSID playback mode buffer size (in milliseconds, 0 = maximum/no flush) %d ;reSID-fp distortion rate %f ;reSID-fp distortion point %f ;reSID-fp distortion CF threshold %f ;reSID-fp type 3 base resistance %f ;reSID-fp type 3 base offset %f ;reSID-fp type 3 base steepness %f ;reSID-fp type 3 minimum FET resistance %f ;reSID-fp type 4 k %f ;reSID-fp type 4 b %f ;reSID-fp voice nonlinearity %f ;Window type (0 = window, 1 = fullscreen) %d ;Base pitch of A-4 in Hz (0 = use default frequencytable) %f lv@dr@Lv@,v@ v@u@u@u@u@lu@Lu@dr@,u@ u@t@t@t@t@dr@zt@Zt@:t@t@s@s@s@dr@s@@@w@}@@$VER: GoatTracker v2.72{F1@1 ?=?(@wbrbGTI3GTI4GTI5GTI2GTI!GTS3GTS4GTS5GTS2GTS!0%02Xl@P@@0@@H@@@@@@@@@@@@@@@l@@P@@@@@@@@@@@@@@@@@@@@@@@@@@@@@l@@P@8@@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@8@x@@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@x@8@x@@0@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@@@@@@@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@@@@R@h@R@@R@R@@\@x@x@@4@@@P@@@\@R@R@@@h@R@@R@R@R@R@<@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@R@@@,@@ @@L@\@@@@@@F@@@@@\@@@@@@T@Z@5@@@@v+AW+AB+A,+A+A>A>A>Aw>AY7AY7AY7AY7Am>A=AY7AY7AY7A%-60s PATH: %-60sFILTER: NAME: A:\AtAtAXA lower result and more rastertime taken).HHdHHHTHHHHDHHHH4HHH$HHHtHHHdHHHTHHHHHDHHHHH4HHHH$HtHAttack/Decay 0 is fastest attack or decay, F is slowest Sustain/Release Sustain level 0 is silent and F is the loudest. Release behaves like Attack & Decay (F slowest). Wavetable Pos Wavetable startposition. Value 00 stops the wavetable execution and is not very useful. Pulsetable Pos Pulsetable startposition. Value 00 will leave pulse execution untouched. Filtertable Pos Filtertable startposition. Value 00 will leave filter execution untouched. In most cases it makes sense to have a filter-controlling instrument only on one channel at a time. Vibrato Param Instrument vibrato parameters. An index to the speed- table, see command 4XY. Vibrato Delay How many ticks until instrument vibrato starts. Value 00 turns instrument vibrato off. HR/Gate Timer How many ticks before note start note fetch, gateoff and hard restart happen. Can be at most tempo-1. So on tempo 4 highest acceptable value is 3. Bitvalue 80 disables hard restart and bitvalue 40 disables gateoff. 1stFrame Wave Waveform used on init frame of the note, usually 09 (gate + testbit). Values 00, FE and FF have special meaning: leave waveform unchanged and additionally set gate off (FE), gate on (FF), or gate unchanged (00). HHHH(HHxHHHHhHHHHXHHHHHHHHHH8HHH(HHxHHHhHCommand 0XY: Do nothing. Databyte will always be 00. Command 1XY: Portamento up. XY is index to a 16-bit speed in speedtable. Command 2XY: Portamento down. XY is index to a 16-bit speed in speedtable. Command 3XY: Toneportamento. Raise or lower pitch until target note has been reached. XY is index to a 16-bit speed or 00 for tie note. Command 4XY: Vibrato. XY is index to speedtable. Left side value determines how long until the direction changes (speed) and right side value is the amount of pitch change each tick (depth). Command 5XY: Set attack/decay register to value XY. Command 6XY: Set sustain/release register to value XY. Command 7XY: Set waveform register to value XY. If a wavetable is actively changing the channel's waveform at the same time, will be ineffective. Command 8XY: Set wavetable pointer. 00 stops wavetable execution. Command 9XY: Set pulsetable pointer. 00 stops pulsetable execution. Command AXY: Set filtertable pointer. 00 stops filtertable execution. Command BXY: Set filter control. X is resonance and Y is channel bitmask. 00 turns filter off and also stops filtertable execution. Command CXY: Set filter cutoff to XY. Can be ineffective if the filtertable is active and also changing the cutoff. Command DXY: Set mastervolume to Y, if X is 0. If X is not 0, value XY is copied to the timing mark location, which is playeraddress+$3F. Command EXY: Funktempo. XY is an index to speedtable. Will alternate left side and right side tempo values on each pattern step. Command FXY: Set tempo. Values 03-7F set tempo on all channels, values 83-FF only on current channel (subtract 80 to get actual tempo). Tempos 00 and 01 recall the funktempos set by EXY command. HDHHHHHH4HHHH$HtHHHHHHdHHHHTHHHHHHDHHHH4HHHHH$HtHHHHdH0-9 & A-F to enter parametersSPC Play test noteSHIFT+SPC Silence test noteRET Go to table- + Select instrument/ * Select octaveBACKQUOTE Select tableSHIFT+CRSR Mark tableSHIFT+Q,W Trans. speed half/octave upSHIFT+A,S Trans. speed half/octave downSHIFT+L Convert pulse/filter limitSHIFT+N Edit name/negate value or noteSHIFT+O Optimize table (remove unused)SHIFT+R Convert absolute/relative noteSHIFT+S Smart instrument pasteSHIFT+U Unlock/lock table viewSHIFT+X,C,V Cut,copy,paste instr./tableSHIFT+DEL Delete instrument+tabledataSHIFT+RET Convert vibrato parameterpHHHHHHH H$HLHtHHHHH0HPHxHH0-9 & A-F to enter pattern numbersSPC Set start position for F2 keyBACKSPC Set end position for F2 keyRET Go to pattern (/w SHIFT=all chns.)< > Select subtune- + Insert transpose down/up commandSHIFT+CRSR LEFT/RIGHT Mark orderlistSHIFT+L Mark/unmark whole orderlistSHIFT+R Insert repeat commandSHIFT+X,C,V Cut,copy,paste orderlistSHIFT+1,2,3 Swap orderlist with chn.0HTHxHHHHH(HLHlHHEnter notes like on piano (PT or DMC)0-9 & A-F to enter commandsSPC Switch between jam/editmodeBACKSPC Insert restRET Keyoff (/w SHIFT = Keyon)< > Select patternBACKQUOTE Select channelSHIFT+SPC Play from cursor posSHIFT+CRSR Mark patternSHIFT+Q,W Transpose half/octave upSHIFT+A,S Transpose half/octave downSHIFT+E,R Copy,paste effectsSHIFT+H Make hifi vib/portaspeedSHIFT+I Invert selection/patternSHIFT+J,K Join/split patternSHIFT+L Mark/unmark whole patternSHIFT+M,N Choose highlighting stepSHIFT+O,P Shrink/expand patternSHIFT+X,C,V Cut,copy,paste patternSHIFT+Z Cycle autoadvance-modeSHIFT+1,2,3 Mute channelHH4HTHhHHHHHHHHH5HTHxHHHHH HDHcHF1 Play from beginningF2 Play from current positionF3 Play current patternF4 Stop playingF5 Go to pattern editorF6 Go to orderlist editorF7 Go to instrument/table editorF8 Go to songname editorF9 Pack, relocate & save PRG,SID etc.F10 Load song/instrumentF11 Save song/instrumentF12 This screenSHIFT+F1-F3 Follow play begin/pos/patt.SHIFT+F4 Mute current channelSHIFT+F5-F6 Change speed multiplierSHIFT+F7 Change hardrestart ADSRSHIFT+F8 Switch between 6581/8580 SIDSHIFT+, . Move song startpos & restartTAB Cycle between editing modesINS Insert row (Press on endmark toDEL Delete row change patt. length)SHIFT+ESC Clear/optimize all musicdataESC Exit programHHH0HAHZHxHHHHH H HHHhHHHHH HDHhHHHARDSID.DLLWriteToHardSIDReadFromHardSIDInitHardSID_MapperMuteHardSID_LineHardSID_DelayHardSID_WriteHardSID_FlushHardSID_SoftFlushHardSID_Lock\\.\SID6581_1wbsidaudio.rawGoatTrackergoattrk2.bmpchargen.binpalette.bincursor.bin@@??@-DT!@?pA9v?D$B$B$B$B$B$B$B$Bp$B`$BP$B@$B,$B$B$B#B#B#B#B#B#Bx#Bd#BP#B$B4B=B=B=BB>B>B0>BX>B=Bh=B@FBF@G?G$EP@HzG@WKV@9B.?$EP#@G-DT! @A^B^B^B^B_B,_B_B_BT^BBUPG?A?D@pA4?O10;drBXrBLrB@rB,rBrB rBqBqBqBqBqBqBqBxqBdqBPqB;8KP}NY?G̼̼+}a?>?`xd?,@/m?!<Y]?6?I?<s?A?=vF???iz?)m}?gAR?$h?P@UZu?"4>Ql?+m@1 s?\/> |?2?^kx? l@S???@AAABDBBBBBCD?Starting parse Stack size increased to %lu Entering state %d Reading a token: Now at end of input. Next token is%s token %s (nterm %s (ShiftingReducing stack by rule %d (line %lu), -> %s Stack now %dline %d, %s syntax errorError: discardingError: poppingmemory exhaustedCleanup: discarding lookaheadCleanup: poppingkB'BBBBTB>B(B BBBBBB^B3B BBBBvBrBGBBBƸBBpBEBBBBBBpBEBBBBBnBCBBBBBlBABBBBBjBFBBBBBeB:BBBBqBFBBBBBoBDBBBBBmBBBBBBBkB@BBBBBiB>BBBBBgBDIP66FF6666EJ6ffff6ufNp|6666N66666  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXY GJHIHW HINOPQRSTUVHI HINOPQRG89:;<= KL DGFC GJKLGGOPQR GBBGGFGGG]^CCMOOBB SCGGXXCGMMOOHBSSBGGXXGBBMHOHGOSHCSBXOLXGSKDEIXHODEISHBLHXKGPQR KOX NOPQRDLH?L89:;<=89:;<=  NOPQRSTUV$ +  !"#$%&'()*+,-./0123456789:;<=>?@AB  !"#$%&'()*+,-./0123456789:;<=>?@AB *+,-./012389:;<=89:;<=HIHNOPQRNOPQRHHNOPQRNOPQRHHNOPQRNOPQRINOPQRINOPQRINOPQRINOPQRINOPQRINOPQR\dd\C\\\\\\MM   MM  DMM EMFGHMINNJKOLPQQNNMR]]SSPPQQN^RN]SSONPQ]Q RNSQS]^$SQ%RN()S&]_e'QxSbhmrv|in.w}/s!"#agl{-0  !"#$%&'()*+,-./0123456789:;<=>  !"#$%&'()*+,-./0123456789:;<=>`fjquykz*+,12o~p mlnopqrstuvwxyz{ "# !$'(%&+,-)*./20153469:;78<=>ABC?@DEFIJKGHLMNQRSOPTUVYZ[WX\]^abc_`defhgikj|}~   Z[[\\\\\\\\\\]]]]]]]^^_______________________________________________________________________________________________________________________________________________`abcdefghiiiiiiiiiijjjjjjjjj666z6/87?@ABTUVWXYcZ[t$enderror$undefinedINCLUDEIFDEFINEDMACROMACRO_STRINGORGERRORECHOINCBININCWORDRESWORDBYTELDALDXLDYSTASTXSTYANDORAEORADCSBCCMPCPXCPYTSXTXSPHAPLAPHPPLPSEICLINOPTYATAYTXATAXCLCSECRTSJSRJMPBEQBNEBCCBCSBPLBMIBVCBVSINXDEXINYDEYINCDECLSRASLRORROLSYMBOLSTRINGLANDLORLNOTLPARENRPARENCOMMACOLONXYHASHPLUSMINUSMULTDIVMODLTGTEQNEQASSIGNNUMBERvNEG$acceptstmtsstmtatomexprsopam_imam_aam_axam_ayam_zpam_zpxam_zpyam_ixam_iyexprlexprIIIIIIIIIIIIIIII IIIIII"I&I*I.I2I6I:I>IBIFIJINIRIVIZI^IbIfIjInIrIvIzI~IIIIIIIIIIIIIIIIIIIIIIIIIIIIIII I IIII!I%I)I,I/I2I6I=IDIIIQIWI\IaIgIjIpIuI{IIIIIIII  !"#$%&'()*+,-./0123456789:;<=>?@AB[\]_GGGGGGGGGG BGMOSX`abcdeghiGS`acdfi`acdeabcdeghadfiade`abcdegh`abcdegh`abcdegh`abcdegh`abcdegh`abcdeghS`ad`adaaaaaaaaaaabdeiabdeabdeabdeabdeabdeJW\CFGijCiCCCi^i^GiiiiINOPQRiiIiIiHGjijSTUVDEHHHHHHIIHIHCHIIKLiiiiiHIBHiiiijjiiiIIKKLHHIHiLHiHH or %s, expecting %ssyntax error, unexpected %s     !"#$%&()*+-./02345789:;=>?@ACDEFGIJKLMOPQRSTUVWYZ[\]^_`bcefghijkln #(-/13:?DIPY]_behknqtwz}  "%(+.147:=@CFILORUX[^`bdfhjlnprtvxz|~ "&*.15<>@DHKOSW[_[[\\BJBWiGjHGiH GCH GCHGCHGCH]_ GiIiHG^HG^H GCH GCIiH GCIiIiH^Iii`deabcgh`dfac`deacdeabcghdfadea`deabcgh`deabcgh`deabcgh`deabcgh`deabcgh`deabcgh`da`da !"#$%&'()*+,-.a/a0a1a2a3a4a5a6a7a89:;>d>e>a>b??d?e?a?b@@d@e@a@bAAdAeAaAbMiiiIKiILSiSiIKSiILGiIKHGiHILiNiiOiiPiiQiiRiOiGiH GCIiHXBjEjjDjFjGjHiSiiTiiUiiViGBHasm/chnkpool.cout of chunks in file %s, line %d chunk_size %d chunk_max %d chunk %d allocating new chunk %p out of memory error in file %s, line %d expr 0x%08X symref %s expr 0x%08X number %d expr 0x%08X unary op %d, referring to 0x%08X expr 0x%08X binary op %d, arg1 0x%08X, arg2 0x%08X %d not allowed as unary operator op %d, vNEG %d, NUMBER %d, SYMBOL %d %d not allowed as binary operator creating new number %d %s out of dynamic memory in yy_create_buffer()out of memory expanding start-condition stackstart-condition stack underflowunknown character found %s fatal flex scanner internal error--end of buffer missedfatal error - scanner input buffer overflowinput in flex scanner failedfatal flex scanner internal error--no action foundB)BBB BB BBB'BBBBBBBBBBBBB1B;BEBOBcBmBwBBBBBBBBBBBBBBB BB!B+B5B?BIBSB]BgBUBBBBUBYBcBmBwBBBBB&B0B:BVB3B=BGBQB[BeBoByBBBBBBBBBBBB#BGB5BB-BbB4BFB B5BB BBBB B5BBB5BFB@BBqB~B~B~B~B~B~Bout of dynamic memory in yy_scan_buffer()out of dynamic memory in yy_scan_bytes()bad buffer in yy_scan_bytes()source buffers nested too deep    !"#$%&'()*+,-./012$ !"#$%&'()*+,-./012$3kkp]\[]JQ]V]MNTROS]UDPFWGZZZZZZZZZZZZZZZXY]cbccjijjkkkmonofe[IEKDHZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZLbikknfeA45273689-'?;=>:<10@("$#%CB/.&,* +!)^g  _` ah  d13579=FH"%%% %%%%%%%%%2% %%%%*=B952AOD%%>%%Q%%%`%%%VX%")XGdfijkaknXq%%i%%m%p%%%%%%%%%%%%%|%%%%w%%%y%%[`& [&.1`&1'';4-;.''-'((23('32?4HO?a44PccaO3OHPdOfimnorsttvorzzmnddffiivss~}{wuqplkjhgeb_^]\ZYXUTSRQNMFB>:70/,*)$   !"#$%&'()*+++,-+.+/01+234+++5679:9:=>=>ABCAB;C;?X?EFEFMNOYimPZnQ[R\zStg{jT]^h_aboqc`rp}u~vwsK88888<<<<<@@@@@DDDDDGGGGGWWU|yxlkfedVULJIHH fatal error, can't allocate memory for log context fatal error, can't allocate memory for log output fatal error, can't allocate memory for log log %s error, can't allocate memory error, can't reallocate memory rbCan't open file "%s" for input. read %d bytes from file wbCan't open file "%s" for output. buffer already exists. resolve_expr: symbol %s not found%s find_symref: vec_find() internal error found: sym_entry 0x%08X symbol %s, expr 0x%08X symbol %s has no value.binary op %d unsupported op %d CCjCjCjCjCjCjCjCjCTCIC:C+CCCCC_Cnot allowed to redefine symbol %s new_symbol_expr: vec_find() internal error creating symdef: not allowed to redefine label %s new_label: vec_find() internal error creating label: Can't read word from offset %d in file "%s". setting .org to ??? appending >>%s<< to macro resolving if expression if expr resolved to %d invalid op arg range %d Ct C C Ct Ccan't add expr to atom of type %d can't convert atom of type %d to byte exprs. can't convert exprs of type %d to word exprs. Can't read from offset %d in file "%s". Can't read %d bytes from offset %d from file "%s". Error: %s symbol "%s" resolves to %d ($%04X) symbol "%s" is defined but has no value symbol "%s" not found sym_table: %s yadda output: $%02X value %d out of range for op $%02X @%p output: $%02X $%02X output: $%02X $%02X $%02X length %d for .res(length, value) is out of range value %d for .res(length, value) is out of range output: .RES %d, %d length %d for .incbin(name, skip, length) is out of range output: .INCBIN "%s", %d, %d value %d for .word(value, ...) is out of range output: %d words value %d for .byte(value, ...) is out of range output: %d bytes invalid atom_type %d @%p 8CCC0CCxCxCxCxCxC@CCxC0CCPC must be set by a .org(pc) call. 9C9C:C:C:Cl:CD:C$:C9C9C :C9C9C9C9C9C9C9CBACKSPACECAPSLOCKENTERESCNUMLOCKSHIFTSCR. LOCKSPACETABF1F2F3F4F5F6F7F8F9F10F11F12ANBOCPDQERFSGTHUIVJWKXLYMZ1234567890-=[];'`,./\ALTCTRLDELETECRS. DOWNENDHOMEINSERTCRS. LEFTPAGE DOWNPAGE UPCRS. RIGHTCRS. UPWINDOWS KEYMENU KEY?DAT!rbmingwm10.dll__mingwthr_remove_key_dtor__mingwthr_key_dtorMCMingw runtime failure: VirtualQuery failed for %d bytes at address %p Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. %s: %s Fatal ErrorOut of memory - abortingrb/stdout.txtw/stderr.txtWinMain() errorDDRAW.DLLSDL_STDIO_REDIRECTmDmDmDmD8mDlDlDlDlD@mDmDmD8mDstd::exceptionstd::bad_exception__gnu_cxx::__concurrence_lock_error__gnu_cxx::__concurrence_unlock_errorstd::bad_allocpure virtual method called terminate called recursively terminate called after throwing an instance of '' terminate called without an active exception what(): _C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C<_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_C_CbCaCaCaCaCbCbCaCaCaCaCaCaCaCaCaCaCaCaCaCaCaCbCaCaCaCaCaCaCaCaCaCaCaCaCbCaCaCaCaCaCaCaCaCbCaCaCaCaCaCaCaCaCaCaCaCaCbCaCaCaCaCaCaCaCbC_GLOBAL_(anonymous namespace)construction vtable for typeinfo name for non-virtual thunk to covariant return thunk to guard variable for reference temporary for global constructors keyed to global destructors keyed to JArray[]ixcl : ulllullfalsetrue%ld...CCCҋCPCCQoChCpCqC~rCsC tCTuCuCwCCݐC5CCCCRC'hC'hC'hC0C0C0C0C0C0C0C0C0C"CdhC9CCCĂCCCCvCfCvhCiCQjCfClCfCfCTxCTxCxCzCzC{C|C{C4|C'~CfClCPkCOC!CCC}CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCDCCCDC,C\CCC,CQIGQIGQILQI LQI ZQIZQIcQIcQIuQIuQI{QI{QIQIQI QIPIQI GQIQIQIKIKIQI QI QI QI QI QI QIQIQIQIQIQIstd::allocatorallocatorstd::basic_stringbasic_stringstd::stringstd::basic_string, std::allocator >std::istreamstd::basic_istream >basic_istreamstd::ostreamstd::basic_ostream >basic_ostreamstd::iostreamstd::basic_iostream >basic_iostreamtMIMIaTITITI bTITITI sTI TIFTI i UI UI1JUI oXUI hUI1UI dUI UI2UIaN&=aS=aa&&ad&an()cm,co~dV/=dadelete[]de*dldelete.dv/eO^=eo^eq==ge>=gt>lS<<=le<=ls<<lt<mI-=mL*=mi-mlmm--nanew[]ne!=ngnt!nwnewoR|=oo||or|pL+=pl+pm->*pp++ps->qu?rM%=rS>>=rm%rs>>sizeof szatalignof azVIVIVIVIVIVIVIVIVIVIJIVIVIVIVIVIVIVIVIVIVIVIWIWIMI WI WIWIWIWIWIWIWI WI#WI&WI)WI,WIJIJI.WI1WI5WI8WI;WI>WIAWIDWIFWIIWILWIOWIRWIUWIWWIVIZWI]WI`WIcWIiWIlWIoWIUWIrWIuWIwWIzWI~WIWIWIWIWIWIWIWIWIWIWIWIWIWIWIWI MIWIWIWIWIWIWIWIWIWIWIWIMIWIWIWIWIWIWIWIDXDDDDDDDDDDDDDrDrDDrDDDDDDDDDDD<D,DDDDDrDDTDTDTDTDTDDDTDTDDTDTDTDTD,DTDTDTDTDTDTDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPDPD`DrDDrDDrDDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDrDDDDDDDrDrD$D+DrD3D:DADHDrDOD]DkDyDDnDDDpDD8DDf%D#&DV&Dr&D&D&D&D 'D3'D['D'D'D'DG(Dw(D(D(D)D)D)DB*D*D*DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DH%DF+D,D%DAD0BDhBDADADADADADADAD\BDADADbI aIHcI@aIaIbIaIHcIaI`IHcIbI aIHcI@bI aIHcIbI aIHcIbI aIbIbIbIbIN10__cxxabiv115__forced_unwindEN10__cxxabiv117__class_type_infoEN10__cxxabiv119__foreign_exceptionEN10__cxxabiv120__si_class_type_infoEN9__gnu_cxx24__concurrence_lock_errorEN9__gnu_cxx26__concurrence_unlock_errorESt13bad_exceptionSt9bad_allocSt9exceptionSt9type_info`I8nD nD~D`IpnDHnDuDuD8qDqDqDDrDrD`InDnD~D`InDnDuDuD8qDqDrDsDsD`IoDnDdtD`IXoD0oDptD`IuDhuD|tDaIuDuDtD aIuDuDtDaIvDuDuDuDtDtDzPL|~D @ BDAB FI AAA G  AAA A <dBVAB Fe AAA C AAA | (BAB F AAA $DP!BdAB EUAA  l!BaAB DXA ,&BeAB FL AAA C (x*B/AB F"AAA L8,BAB I AAA A | AAA A % AAA A <`2BAB T |  T`BAAB DxA 0<`BIAB Eg AA C RAA $p`B.AB E_AA  aB"AB DUA | $DaB;AB EpAA |  DdB'AB DA $<eBAB DZ A B $dPfBAB Dz A B $fBAB DI A C $lgBAB DF A B $hBAB D@ A D $hBAB D\ A D ,,DpAB ] D | DAD>AB z ,8IDAB F AAA C <hKDBAB Fd AAA A  AAA A ,QDAAB DT A  B , SDEAB DT A  B 4TTDYAB EM AA A  AA D ,@UD9AB D A m B ,pVD9AB D A k B ,(XDEAB D A l B 8pYDAB FM AAA C  AAA A $ 0[D%AB M D L ,4X[D^AB F AAA B | 4]DlAB EZ AA D u AA A 0PX^D0AB BY AA H AAA $^D"AB V C A  ^D.AB Df $^D*AB _ B A  _D?AB Dw H_DAB S (<`_DMAB DV C l (h_DKAB Dz C F  `DMAB DE <d`D}AB ED AA B R AA D RAA 4`DLAB De A C G A D NA (00aD[AB DT A ~ h8x̽ܳ0<Thtȵص,<Tdxȶܶ 0@N\pη,BVhzƸ޸08DN\j|ȹҹܹ ,6@JXfr~̺Ժ޺"*2<DLT\fnvƻλػ",6@JT^hr|0<Thtȵص,<Tdxȶܶ 0@N\pη,BVhzƸ޸08DN\j|ȹҹܹ ,6@JXfr~̺Ժ޺"*2<DLT\fnvƻλػ",6@JT^hr|SDL_CloseAudioSDL_CreateMutexSDL_CreateThread!SDL_Delay(SDL_EnableKeyRepeat)SDL_EnableUNICODE-SDL_Flip?SDL_GetErrorKSDL_GetTicksWSDL_InitkSDL_LoadBMP_RWpSDL_LockSurfacewSDL_OpenAudioxSDL_PauseAudiozSDL_PollEvent{SDL_PumpEvents}SDL_QuitSDL_RWFromMemSDL_SetColorsSDL_SetModuleHandleSDL_SetTimerSDL_SetVideoModeSDL_ShowCursorSDL_UnlockSurfaceSDL_UpdateRectSDL_WM_SetCaptionSDL_WM_SetIconSDL_WaitThreadSDL_getenvSDL_mutexPSDL_mutexVSDL_strlcatSDL_strlcpy&CloseHandleDCreateFileAXCreateSemaphoreAkDeleteCriticalSectiontDeviceIoControl~EnterCriticalSectionExitProcessFreeLibraryGetCommandLineAGetCurrentThreadId*GetDriveTypeA4GetFileAttributesAEGetLastErrorOGetModuleFileNameAQGetModuleHandleAlGetProcAddressGetStartupInfoAInitializeCriticalSectionInterlockedDecrementInterlockedIncrement LeaveCriticalSection LoadLibraryAvReleaseSemaphoreSetLastErrorSetUnhandledExceptionFilterSleepTlsAllocTlsFreeTlsGetValueTlsSetValueVirtualProtect!VirtualQuery*WaitForSingleObject_chdir%_getcwd*_isattyN_statP_strdupm_write7__getmainargsA__mb_cur_maxM__p__environO__p__fmodec__set_app_type_cexit_errno_filbuf_findclose_findfirst_findnext_fullpath _iob _isctype_onexit_pctype_setmode_vsnprintf_winmajorGabortNatexitPatoiScallocTceil\exit]exp_fclosebfflushcfgetcefgetsjfopenkfprintflfputcmfputspfreadqfreerfreopenufseekwftellyfwritelogmallocmemcmpmemcpymemmovepowprintfqsortrandreallocremovesetbufsetvbufsignalsinsprintfsqrtsscanfstrcatstrchrstrcmpstrcpystrlenstrrchrstrstrstrtoltolowertouppervfprintfSDL.dllKERNEL32.dll((((((msvcrt.dll<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<msvcrt.dllMCPMCPP@pLPN PN8N NhN  H( @HH{{{{{{{??{{?{{{{?{??{7{?{{{{?{?{{?{{?{{{{{?{?{{{???{????{{?{?{{{{{{{{{{{{{{Žŀ{{{{{{{ŀ{{{{ŽŽŽŽŽŽ{{{{{ŽŽŽ{{@@@{{Ž@@@@@@{Ž{{{{{ŽŽŽŽŽ{@@@{{{{@@@{ŽŽ{{555=5=5=5=ŽŽŽŽŽŽŽ555={Y]UUY]UUUUŽŽY]Y]UU{@@@{u}u}uuŽŽŽŽŽu}u}u}{@@@@@@{``ŽŽŽŽ``{{{{{}ŽŽŽŽŽŽŽŽ}@@@@@@{KŀŽC{{@ŽŀŽ@@{{{{{{ww{Žowww{@@@@@@{ŽŽ@@@@@@{{{{{{Žŀ{@@@{{{@@@ЬŽЬдЬЬдЬŽŀЬЬд{{{@@@{ààààà{@@@{{{ŽŽ{@@@@@@{{{{{{  goattracker-2.72/win32/ins2snd2.exe0000644000000000000000000003100011604144014015544 0ustar rootrootMZ@ !L!This program cannot be run in DOS mode. $PELN 8.`0@ pD.text`P`.data0@0.rdata@ @0@.eh_framP&@0.bss `@.idataDp(@0.CRT.@0.tls 0@0U@q@fU0q@fUS4C@tD$D$$Ѓ $@EED$0@D$`@$`@D$ ED$P`@uP0@ND$`@D$`@$=$6,q@0@D$C$P`@D$C0$P`@D$CP$ni'U$$q@&U$$q@&USE=w;=rKD$$1[]=tY=t=u=t&tE=uD$$tst$vи럍&1jD$$ ]tQn$ и\t&$иfCD$$'D$$  D$$u {U$@@&RteD$@@$tD$`@$P@Ћ 0@t1$)@@Rt*D$7@@$t $ 0@ø말U$@@Qt%D$K@@$t $P@ÍvUS]$`@ `@t;(`@(`@ۉ\$D$x@@`@$[f(`@t~`@D$$,}ۉ\$D$r@@`@$i(`@@(`@u(`@`@D$$ 2ۉ\$`@$[f`@D$ D$ D$$d@@mf`@D$$,(`@t @v`@D$$ UWVSTuDŽ$LD$B@U B$n£`@$41󪍌$4L$|$L$6L$|$T$ D$D$$LD$$B@t$D$+D$$B@t$B@t$tB@t$R`@$$3`@$$4`@$$5`@$k$6`@$W$7`@$C$8`@$/$9`@$$:`@$$;`@D$ D$D$$<$`@$Dž~31v`@$sF91`@$DsF9`@$Dž~81`@$ot4F91`@$St5F9`@$:Dž~21f`@$#Dt6F91`@$ Dt7F9$4$5L$+D$+`@$$`@HD$C@M A$`@$3$o$4$_D$+$M$2D$1D$,IS0<Qt҉$ F;|$,t‰$F|$,;\$t -b Produce binary output -c Produce output in CovertScript format (deprecated) Takes a GoatTracker V1.xx or V2 instrument and outputs the corresponding sound effect data as source code (default) or binary. Things that can't be converted and will result in an error: - Waveforms greater than $81 - Relative notes - Wavetable longer than 128 bytes - Absolute notes C-0 & C#0 Things that will be lost in conversion: - Wavetable loops - Pulsewidth modulation - Filter settingsrbERROR: Can't open instrumentfileGTI!GTI2GTI3GTI4GTI5ERROR: File is not a GoatTracker instrument!wtwbERROR: Can't write to output file.ERROR: Relative note or absolute C-0, C#0 foundERROR: Waveform greater than $81 foundERROR: Sound effect exceeds 255 bytesmingwm10.dll__mingwthr_remove_key_dtor__mingwthr_key_dtorp@Mingw runtime failure: VirtualQuery failed for %d bytes at address %p Unknown pseudo relocation protocol version %d. Unknown pseudo relocation bit size %d. i[ M`Q]X ETHDjM_^][_^]3[h`術_^][Ë\uSVt$ 3St t ^f3[ûFVt,t^f3[Wa3_u ^f[Ãf^[Ð 3tt @Ðt L$Ðt H$tPYÐt H(tPYÐjYÐV5džt jP}t PpW=tP׃FDt FTP׃_tVV džV^ÐL$3fAtAA3҃fQ3ҊQ‰A ÐT$SUl$ %V=W7MEuG33ۊa9AY=~VFOu33ۊayA=~VFOuZEM+‹G33ҊA=~FOu EM+‹ A9ǃ~ }FJu=uE΁ub33ҊfV 3Ҋ63ۊ^ =~ A=} AAOu\tR33ҊfV 3Ҋv3ۊ =~ A=} AAOuE+‹UPBE‰UPD(t L$QUЃ_^][ÐS\$ U%VW|$=!OWË%=*uA33Ҋ!qAQFVV MukZ33ҊaqQVFV Mu*W*OЋŠQVHuW*OЋŠQVHu=OWË%=*uM33ۊ1Y3҃Q 3ҊqF ӈVFVMuGt>33ۊqY3҃ 3ҊqF ӈVFVMuȋ\$OVUUUЉWWPB‰WPD(tSWЃ_^][ÐS\$ Ul$ %V=W M%=Eu>33Ҋ!qAQFVVOuOA33ҊaqQVFVOuEMQVHuEMQVHu=M%=EuJ33ۊ1Y3҃Q 3ҊqF ӈVFVOuCt=33Ҋa 3Ҋq3ۊY ӃVFVOuɋ\$E+‹UPBE‰UPD(tSUЃ_^][ÐL$S\$ VWu,AQ<4B+tF^D$Y+‹Ù+‹T$\$++׈YQA|$MYQAuqtg33ۃf~FD$+‹Ù+‹T$Y\$++׈YQA|$MYQAuL$ _AqPFAƉqP^D(][tT$ T$L$ ÐL$VQAҍ4PtWVNOPu_AqPFAƉqP^D(tT$L$T$ÐL$VQAҍ4PtWVNO@u_AqPFAƉqP^D(tT$L$T$ÐUl$ Vt$ WN%=tAF+t GHuF+‹VPBF‰VPD(toUVЃ_^]ÐS\$ Vt$ Nu)%=tAF+t"HQuFt AHuVPB‰VPD(t SVЃ^[ÐVt$FN+tWQAOu_VPB‰VPD(tL$ QVЃ^ÐUl$ VW|$GW 4BՁt-u=+t6QHQVVQVutQIHVuGWPBG‰WPD(tUWЃ_^]ÐUl$ VW|$GW 4BՁtIujt_QHQVQVQVVQVQVQVu&+tQHQVVQVuGWPBG‰WPD(tUWЃ_^]ÐUl$ VW|$GW 4BՁQHQVQVQVQVQVQVQVVQV QV QV QV QV QVQVuBt7QHQVQVQVVQVQVQVuɋGWPBG‰WPD(tUWЃ_^]ÐUl$ VW|$WG 4P%*ЋQ HQVQVQVQVQVQVQVQVQ V Q V Q V V QV QVQVQVQVQVQVQVQ VQ VQ Vea*ЋtOQ HQVQVQVQVQVVQVQVQV QV QV uGWPBG‰WPD(tUWЃ_^]ÐUl$ VW|$%Ot(u8Gt*QVHuG+t FHuG+‹WPBG‰WPD(tUWЃ_^]Ul$ VW|$%Ot4uPGtBQVQVQVHu!GtQVHuG+‹WPBG‰WPD(tUWЃ_^]ÐUl$ VW|$%OtLutGtfQVQVQVQVQVQVQVHu-GtQVQVQVHuG+‹WPBG‰WPD(tUWЃ_^]ÐUl$ VW|$%OtvW*ЋQVQVQVQVQVQVQVQVQV QV QV HuBW*Ћt+ QVQVQVQVQVHuՋG+‹WPBG‰WPD(tUWЃ_^]ÐD$Huha{zËHHH(tfP@PRPу3ÐT$D$L$SUVW339yPy(Ay A$?ttA(+qPFqP3tqPD( +qPFqP2tv%tNt(=u`APD(P*QPA BQPQ҉QJ( tqt t]tB 8tFJ( t7t t#ttSVRRD [ȃu$Jul$]E\$ l$\$ l$\^\$ @;Lj\$ |‹l$\$Jl$u_^][ ÐL$SUVAQ$WyD$B Q(D$Y)qGT$(I +ȋD$(υL$tg\$23ۅ~8uUE‹L$D$ D$ %;t L$(FC;|̋L$T$D$HD$u_^][ÅtO\$(23ۅ~0uUED$ L$ ;L$tFC;|ԋL$T$D$(HD$(u_^][ÐL$SUVQ$qD$$B Q(D$FT$i YW+Ay+tl\$D$ 23҅~?u D$(@D$(\$D$D$%;t \$fCfɃB;|T$(L$ D$HT$(D$u_^][ÐL$SUVQqD$(A$T$ i YP A(D$FT$Wy+ۉl$ tt\$23ۅ~Mu D$,@D$,L$L$D$%;tL$f(f)l$ @A҃C;|T$,L$$D$HT$,D$u_^][ÐL$SUVQ$qD$$B Q(D$FT$i YW+AytkD$ \$23҅~=u D$(@D$(\$D$D$%;t \$ɃB;|ËT$(L$ D$HT$(D$u_^][ÐD$Hyu]P0@xs33ɊHL$w;$`CaËb3҃JC3ɃIF3ÍI&C.C6CZCHCLL$PSUVAWy$q,D$`AT$iD$XYB3ҊW$D$H3T$LFI D$(El$<‰\$+ȋD$`ͅL$TD$@3;D$`D$8uD$@L$`D$T$`L$HT$D3ҋD$D%3ɊH3ҊPD$(T$Pt.HtHt D$'33ɊCK3Ҋ3fD$F\$3#ÊN 3ҊVL$ʉT$,V3#T$^3ɉ\$0N L$4ˋ^+3ɊN L$$3ɊN+L$ L$#ًL$$L$ L$LNj|$P+Ջl$(߃t`It7IL$,L$L$ L$$L$0L$4 ‹T$UL$|$93F 38N 9/L$,L$L$ L$$L$0L$4 ‹T$f\$`|$D$8L$<@\$`;|$D$8)L$T|$T$XD$@H|$\$D$@_^][LÐPL$TSUVWy$T$Qq,T$\AiRD$@T$,3ҊW$YT$PW T$L3ҊVT$(I \$‹T$@+ʅL$X%l$D3D$d҉D$<uD$@L$dD$T$dL$LT$HD$H%;l$,33ɊTLT$,3ɊLD$(L$Tt.HtHt D$'33ɊCK3Ҋ3fD$V\$3#ӊN ^3#\$FL$$ȉD$83F3ɉD$0N L$43+F 3ɉD$ NFL$L$#L$ L$+L$P׋|$T+L$(ǃt`It7IL$L$ L$0L$4L$8L$$ ‹T$UL$$|$93ɊN 39V :/L$L$ L$0L$4L$8L$$ L$ f\$D$d|$(T$@D$dD$<@;‰\$D$<L$Xl$|$\D$DHl$\$D$D_^][PÐQD$SUVhPX pWx|$x(JT$E‹Ճwn$I3FAH:V~V3FA:V3FA:V3FA:V3FA:V3FA:V3FA:V3FA:V뙋D$T$\_^][YÐI IfIZINIBI6I*IQD$SUVhPX pWx|$x(JT$E‹Ճ$J3҃AHfWfV~u3ҊAfWfV3ҊAfWfV3ҊAfWfV3ҊAfWfV3ҊAfWfV3ҊAfWfV3ҊAfWfVvD$T$5_^][YËJJvJfJVJFJ6J&JD$ SUVH pXPW8L$Ht$p(JT$7C‹Ӌ$HL3҃2BAG2MAT2Q3Ҋ2BG2AT2Q3Ҋ2BG2AT2Q3Ҋ2BG2AT2Q3Ҋ2BG2AT2Q3Ҋ2BG2AT2Q3Ҋ2BG2AT2Q3Ҋ2BG2AT2QT$D$T$_^][ÍIQK)KLKKKKoKQSUVW|$GO D$G_7L$O(‹D$H҉D$C‹Ӄw~$\M3҃FHQ~d3҃FQ3҃FQ3҃FQ3҃FQ3҃FQ3҃FQ3҃FQ뉋D$ K_^][YÐLL7M)MM MLL D$SUVp hPX(Wxt$p@$|$l$x JT$ E‹T$$pO3Ҋ;tFAM~k3Ҋ;tFA3Ҋ;tFA3Ҋ;tFA3Ҋ;tFA3Ҋ;tFA3Ҋ;tFA3Ҋ;tFA끋T$D$l$ʋT$ 4JT$ E‹Ճ$Oځ;tFAHځ;tFAځ;tFAځ;tFAځ;tFAځ;tFAځ;tFAځ;tFAbT$D$ʋT$ _^][ NM[NLN=N.NNNNNڋ#ڃHY>ڋ#ځ>ڋ#ځ>ڋ#ځ1l$ |$\$T$4 _^][ XD$SUVp XP(HWx\$t$|$JT$ >C‹ӃD$$Ut$(tc1u 3%3J‹ށ%+D$(+ցT$(% ÉD$HD$uUt$(tc1u 3%3J‹ށ%+D$(+ցT$(% ÉUt$(tc1u 3%3J‹ށ%+D$(+ցT$(% ÉUt$(tn1uƃ3%3ƉZ‹ށ%+D$(+ցT$(% É\$t$|$T$ l _^][Ð U8EVWHP8pL$,H L$0H@$T$PL$4HD$8 ʋP 3ҊP L$H‰L$D$ 3Nv҉D$ T$$oL$ D$HɉD$L$,AD$ $T$ G@ F@oD$8#te;uD$## щSnn`n\$abn`qg~D$L$ IɉL$ T$0D$4<4oD$8D$T$ G@ F@L$ #to;u#ыL$ #ȃ щbnn`n\$abn|$ `qg~ oD$8D$T$ G@ F@L$ #to;u#ыL$ #ȃ щbnn`n\$abn|$ `qg~ oD$8D$T$ G@ F@L$ #to;u#ыL$ #ȃ щnn`n\$abnt$ `qg~_w^]'SU0E3VWH$Q$ʁuhPE_^]ËpP8t$ p L$0D$4oD$0t$ p@T$aD$$bD$0D$4so\$0D$(D$,oL$(L$\$0D$ HɉD$ L$tZ33ff% ȋ% +D$% ЋD$fHL$33ff% ȋ% ƒ+D$% 3fNfF3fO% Ћ% L$+D$% ЃfVjAtKoo&d$(q q q q |$ol$(qo\$\$od$(q o\$^o\$0oo&d$(q Hq q q |$ol$(qo\$\$od$(q o\$^o\$0D$ L$$T$D$SUVXHP(pWx L$|$\$JT$~AD$$N$dUtwu! |%#fO3%f| | ȃ+ρ| fD$$HD$$Utwu! %|#fO3%f| | ȃ+ρ| fUtwu! %|#fO3%f| | ȃ+ρ| fUu*ʃ %|#f3%f| | ȃ+ρ| f\$|$L$T$l4^s_^][ËLD$PSUVH hPX$p,L$LHW8L$`H3CL$T3ɉD$4NFL$,3ɊK$l$L|$%\$<ɉL$@D$0JT$XED$DŃ$D$4t(Ht Ht3#33ɊGO3Ҋ3f{K k#KS##ЋD$,K KK KT$Ht:HtHt D$87D$`L$8+L$`33ҊAQ3Ҋ L$`3fD$8F\$83#ÊN 3ҊVL$ʉT$(V3#T$8^3ɉ\$ N L$$ˋ^+3ɊN L$3ɊN+L$L$8#ًL$L$L$@Nj|$H+Ջl$,߃ttItKIL$0N N L$(L$L$L$ L$ L$$ Nj|$`oL$|$`93F 38N 9IL$0N N L$(L$L$L$ L$ L$$ Nj|$`f|$`T$4D$‹\$H2 | f> | f> | f> | f> | f> | f> | f>l$|$ 4~S_^][ÐsHSUVW|$GoD$G ‹w؋G+‰l$|$D$H҉D$E‹Ճu$P f>H2 f> f> f> f> f> f> f>l$|$ 4~S_^][ÐX-D$hPÐD$ SUVHXP pL$@T$W|$ ‹\$D$H҉D$ C‹Ӄ$33ۊQTHV33ۊQT߃V33ۊQT߃V33ۊQT߃V33ۊQT߃V33ۊQT߃V33ۊQT߃V33ۊQT߃V*\$D$4_^][ÐhO6D$hPqÐD$h"PQÐD$h*P1Ð(D$,SUVhHXp,T$8P Wx$T$(P3FT$,3҉D$FWl$4T$t 3ҊW$T$D$IL$0D ED$ Ń $,D$L$<t*Ht Ht3%)!33QA3Ҋ3f)GO W#O#O OD$G#O OL$tsItAINl$N NN NN ‹T$N N ‰h3ɉD$$N D$3ɊN D$$3ҊV 9Nl$N NN NN ‹T$N N fD$l$<؋D$D$ Hl$3h\bޘT$43VRUUD$ ;t PWt$ދD$@t tUU _^][(ÌSUVt$03W;D$BD$MN\$0C9(t#@<%Phb+ xuxuxu xtyC KUhhhjPQUBF ;fSfC L$$fT$(QT$(WRSfl$4fl$6fD$:K}WkVhb著;|WRkG3jUHVGD$$D$(͚jT$"jRVVUV 6UV5UV5UV5G_ D$PG35jV5UV5jVw5@jVl5T$9|YVFu@t Vy9=;4u*<t!L$Q%G t T$RjWЃ _^ÐD$ SWPL$f|$f\$$3UVCP4;t(rP:VuP;Vu @V;t 0r0pT$3fCt$,T$‹S‹ՁL$|$t;|$ʋ̓t$,3fKL$It$,L$uы|$L$0B;^]v WQS _[Ð0SW|$<4G0;up 0Vt$HQt$T$ T$DT$D$IT$ L$t$$D$(PJWL$,T$0HL$44JL$8PD$ P^_[0ÐVt$WtuFu@t V6|YVFu@t V)7=;4u*<t!L$QG t T$RjWЃ _^Ð0t=33fHfPf0Wf@0z3ʃ_ÐS VWhӋth/3jPӋtJ3Fp4F 3F 3F`3F@3F3F 3dž`X_^[j}t V_^3[ÐjPËD$jQRÐD$HLD ÐVt$j HLT RPHLAyIAHL^ÐVt$tJ Iu~ jd[^ÐW|$@tPtPSU-V39\tT j RPՋ\ @|֋^][BtP@_ÐSUVt$$3W3Y @T|l$,3ɉXEL$%L$fD$L$L$fL$ ;t)thd.x_^][fEffMfEfD$EfL$D$fL$fL$L$#șL$3fU;} %fEUD$hVh6PjQ;tPhdY_^][SjjSB9XuhdQw_^][ËM Q B9Xuhdw_^][É\$(3j | M L$,HL E DD T RPu"T$( B@T$(|_^]AL[PhdJ_^][Ð|$uD$ jjQRD$L$WPhehQp|$3I+эD $ RPQT$Rheu_ÐSUVt$,W|$453Ɋ<:$,:\$8@t _^]3[ËD$4ȃt/ItI% % pj謣=t0uhׄyB/uhׄy&%*u3҃6 L$jQSPPj芣`3_^][Ët$4\$8ƃt6HtHj̢=t0uhׄx/uhׄxd%*uN3҃6 <,u7jW<u#ˍD$jPQVPj菢`T$jRSVPjn`3_^][Ë%=@t=pu _^]3[à \$8l$,<uCD$D$PD$D$ l$t$|$ \$$#~`SWVUx_^][áLtL$8T$,QWVRP|_^][Ð7x899D$V5hjjjjPօt;SlW=pjjL$jQׅ~T$ RjjjD$jPօu_[^ÐD$VWP\5`hh eօPu PdPL$jQֹC3@``d p t  '0,4-8.</012 34567 8$9(;,=[\ȥ<]@DaHbLcPdTeXf\g`hdihjlkpltmxn|opqrstuvwxyzģȣ̣Уԣأܣ     <_آܢԢТ̢ĢȢ  ! "$#($,%0&4'8(,-.Ĥ/0̤1Ȥ2Ԥ3Ф487;L>?^ËD$S$V$W$FfF t8t/D$PXjL$jT$QRSWu fD$ fF utF_^[WS @N_^[ÐPVt$WPjQT|$Ow3Ҋ4A$,AH"3ҊA$A_`^_n^_a^u~_b^un_c^u^_d^uN_e^u>_f^u._g^u_h^u_i^Åu_^Ð&AK@@A@@@@A@@f@z@"A  Vhhe5{jjj(?3|jtPjV <uhDej^jPDL<hwjPH43^Ë 80QjjjjhhhPPjL<uh,eCj^jPP33^Ð|tL <PjQH@x3<R@v@a3S UVWhӋ3;3j,j\Ӌ;a;Y 3󫋾FPEFHF @JF`FQn F$@UF@`nDnHnLnPFT QFXQn\F`QFpPTFtUFxF|Pdždždž`dždž@dždž  džДdždžPdždž dž(@dž,:dž0P:PVVTVh`7džE_^][UkV3_^][ÐVt$t.W=tP׃tP׃V׃_^ÐW$W} _Ĝá<SUVP|d$E%wV3ɊF$FE|EEE,EEEEEEWA <3fD$4h`jVft$BӋL$W4QVVG8Ӆt*$D$|L$xRPQWT$FRVjӅu֋ ~Dh@jQPӃ|يE^]<[w%PAG( G(3_ĜÍIEEEED$SUVW \$3ҋNL~,D83fo;l$u3fo|$ ;B;|j uP9i_^][fD$fL$ ffGfGfOlDRPDDu&PhWD_^][É<TDt_^]3[ÐL$3oSVW~IuP ff~ <Q4VRWjSH<SP8V`V_^[ÐD$ %=u$L$3A‹T$DÃÐSUVWh(  3P(4jjW-(jVjjjSWjVjjjSWSDWj833fF3ɊJ$JV_^][V_^][V _^][Ã~u.=|t=uV_^][ÿV_^][ÍI~IIIIISU$VWEt$P蜔$XM3ҊQ;GwG3ɊP$PLu |#333jRQPWjjj uPe3_^][ËU$$UT$Eu] 苬fE4$%=D$ 9'3|$83MfD$\;Q$$$D$`;D$`\$L$8jQ@D$u(D$`@t8T$8%jRD$h@D$tE' t$8E󥋼$$@tPDAWB<jPDMu$5 s끋D$%=ujjӋ$ tE5 5tE E<Rt|u<VjPH$tPD\$4E3ɀx3;,t8;t  ,Q ;u(;$t UUS c3_^][(EFM 3҉NfF fUU V^^^ ^$E;fHfNt$FUBF(MQV,EHN0$^U;t3э~(ʃ<P4jMjQjVW$W<P8V9u,;$t UQhet^3_^][Ë$C 0QM |<RP3ۅ\$uqTuhheFnhe:nD$tGD$L$PQheSuT$D$PTe3u\$ PTL$$D$(UjD$ @T$0M <RL$8 P<jPDL$,PQ$t$,L$$|$0D$(T$ ++uT$t"(j+j+D$+Ǚ+-PuTuuD$BD$L$T$\$ 3RWVD$ PD$ PQ <Q,u@DPT <Q0D$4Xt)$R5} _^]3[ËE E%_^][ÍIJJJÐ3Ð<SUVWP4t$At jPWLW$؋PS l$~3L$qNh 3fVPQSR3fVRPQWMuS<WP8_^][ÐUQ<SVWP4M}u؋]Bt}$葳3ɅU~+ߍB+ڊAPTP@;|]UME RVPBP4MjBPSLS0$3ɅU~(ߍB+ڊAPTP@;|]S$ERW EM PVQW,Uh jj4WH PQRjjSW<SP8e_^[]Ð<VP4L$QV8u$3ɉHtHp<VR8^ÐdtL<VP4裾t ddRV8D$HdQV<<VR8^ÐdtNRt,<VP4 dQV<<VR8^dPdÐdS8VW=4uIh duP+\_^[á<P׋ dQV8<VR蚽t/<P׋L$QV<<VRӋ_^H[ÿ_^H[Ð<VWP4L$QV8<VR8_^HÐ<S\$UVW3;4;t78yWW<WPP4t St4z;tPD9;t P=S!S+=<-;tC;tPՋ u3PՋ<|(r_^][ÐD$jPW|$HtN <VQ4jBPVLV0t <jjQ<VR8^_ÐD$ <;t D$uÐS\$VW|$@t jPWLW$RV h jj4VH PQRjjWV_^[Ðh`etVW(f3_^u3S VhӋW/3jӃ_tj3h0fHHH et PB F@YFXFXFXF Xdž`X^[juXt V^3[ÐVt$W=PV׃_^ÐD$Q T$6Vt$P@RjPQQ;At dž^ÐD$AÐVt$@tPAtPP ^ÐSVWt$hfWw:u_^[ápW@hHfP\$ S QHQ Bxu_^[ËK 3Cъ؊fʃ_^3[ÐhfVcufÐh`6ctVWf3_^u3S VhӋt]W/3jӃ_t?3ɉHHH F`[FZFQF [F 0[dž`X^[jUt V^3[ÐD$H tIH ËHL$n4D$ÐVt$tP^ÐUl$Vt$WN HBP :u _^]ËN 3FS؋ъD$fʃF3ɊND$ B F D$ D$l$ 4Y[_^A3]ÐVWhDg3htAD$D$PtD$u|$ vh(gWu3W_^ĔÐSVW hӋth/3j ӋtJ3F@cF 3F^FaF0aFpbF bdž]_^[j{St V_^3[ÐKhDgh\t"hPgP \(tt3Ð\tP(\ÐVWt$ =PV׃_^ÐD$`ÐT$Vt$RT$ R@PQt=x@PQP^ËD$3q ;Aj 1BT$RPQ$D$t+@PQPBT$RPQ$D$ugujjj@PQ0uJBT$RT$ RPQuD$3q ;A[^Phdg^ÐD$Vt$=xXtx=At0=@t=@XhXphXd=Wt= xX\hXHhX$hxwdwK3Ҋ`$`XdRX hFXg:Xg.Xg"PVhghhXCXuXPVhghhX^D$XD$eLI``_`_'`D$PtH@ Vj1jPRQVL^ÐVt$@AL$QL$QPR=xu(BPQPBT$RT$RPQtPhdg3^ËD$3Sq 3W\$ jS\$jSD$(AD$(@qYST$,A ‰D$,QI :QPRW,=xu9BPQP|$ jWH|$jWx@ WPD$0PQR,_[tPhh3^Ë^AÐVt$WVVt/SVH @؋ъfʃV[VV@PQH_^ÐVt$8tU@tPQB@tPAPQ^Ð3VD$W|$$D$ D$fD$D$fD$G%t>thdI_^ËL$ fGfB!D$ fGfAfWfD$ffT$ L$ D$ fD$D$%WD$DjQj(tPhPg_^ËBH}6O T$QR`HQRP;AH} _^@G _B 3^ÐSVt$,W|$,t jVWPj PWS"T$<3ɉL$D$މL$L$L$ L$$t$D$=t$4\$8L$ QL$VQW\$4P tPhi_^[ËSPR8T$ jRT$RT$8RT$@RT$0RjPQ,uBL$,|$0f{u3ʃL$ T$6QL$0RT$8QRVPL_^[hjhh-G _^[ËD$~JVt$WFyD$jPQPjT$jRPPjuOHu_^Ð(SUV<33;WL$ 95hpL$Q<T$RPL$T$QRVVVVHwD$<T$(RjP2Q$;tPhi_^][(øL4ကuHy-=3Ɉ\$@L$ T$<$:À\$uu\$tt@;ƣt~<PD$$H;ƣt׉5tD$$95@tuD$ uD$L$T$$VVQRL$0\$PHT$;u4tPRFuD$8PWSUx_^][átPQ Fuh%=@t=pu _^]3[Ê :u9T$8D$D$D$PD$ l$\$|$ T$$KH\DOL$8T$,QWSRP|_^][ðkk1ll;lSUl$VW4itFt{;PQ <R[WPQR4PQtWhhjuj|T$jjRh, _^][ÐVt$W=Vׅt_^ÐS3VWHSSSD$SPht5SSL$SQpT$ Rl9Ht_^[9Ht _^[qtn9<~fU(iPQd=t= u7upi3u hPQPRd<C;|]D$0 <hPjhQء<;L$0jQD$8hpjPR(=t= uL[pi34(iu hPQL$0jQhpjPR(u(D$4t T$0hpRx_^[ÁtMjjjD$jPht6jjL$jQp~T$ Rl_^[_^[_^3[ÐVt$jjV ^ÐW3ptx1|234567890-= qwertīyȫu̫iЫoԫpث[ܫ] 2asdfghjkl ;'`0\Ȭ< z$x(c,v0b4n8m<,@.D/H/L P4T X-\`dhlpt x!|"#,.   ̬$Ь%&'(1D L<P3ܮ65?_ÐS$ V$pF$FfF tPtGWjSL$QXjT$jD$RPSW_ufL$fN ^[Ë^[ÐVWhheG3xPPPt 3|jtJjV7 <uhDe7_^jPDD<hwjPHR 80QjjjjhhhPPjL<uh,e6_^jPPT$ R}_^_3^Ð8SUV3WUh8hP ;tPh`k_^][á(i-<;)4i8T$jRWRPQ 'D$Vh 8P؋D$PR<PSPQR43; WRPQ,;3T$D$D$D$D$D$\$D$ \$ D$$D$$RjPQ;SSSSl;ÉPQR0;G6xVQ5<G F;É5<jt(_^@]3[PhDk+_^][Sh k_^][Phhj_^][Phj_^][Phj_^][hj?4_^][Phj_^][ÐD$PF|t D<QjRHo Z<P@Y D8W3;tgSV3;t8PQ WPR0;t PӉPQ@|8PR^=8[_ÐxSUV5hh~3օt Ph~3֋h~VL$ UQUЅD$ jUPRP|sW3|$T$UD$RT$$D$$lD$(DŽ$BRPQ_|0D$T$Rh@8P|D$PQD$PRD$ PQVtt ^][x^]3[xÐSVW hӋ3hDj\Ӌ{s3󫋾FFF F`FF F F$F@FDЛFH`FLFP`FTpFXPF\pF`FpFtFxF|Pdždždž`dždž@dždž  džДdždžPdždž dž(@dž,pdž0p @Thkdž}_^[j3V_^3[ÐVW5hh~֋=dt h~Pף$h~օhthPף h d_^t $tt t3ÐdV3W=;tP׉5$5dh;tP׉5 5h_^ÐVt$WtPQ=tP׃tP׃V׃_^ÐD$Vt$=v`y=v=Wstb=@At0=@t=@L`_`P`w3ҊL$`Ā```|`h`H`,``v`j`^`R`F`t:``.`<"PVhhh``u`PVhghh`^D$`D$e(,@1|^"mOZ~f3$BrN   SUVt$W38yzx $=4|싖|| |؋Vd}_^][á<PL$WQW$;tPh~{_^][ËD$QhP8P؋D$PR;tShH@_^][á<P4-@jWj WՋȊT$WB<P8h`jj< 3N4V8PThXV\jjPR tPh(_^][Ë-P$LR <tvD3ɅtAD@ u닆L~h@jQPՃ4sV(VV(3_^][j+_^][ÐD$L$V1fJfFf;u33fFfJ+^%+^ÐSUVW|$O GTo;wW ;vUH3Ҋ$‹NPt,fHf;O u"fPf;Wu;h~~;z_h^][D$jA uPo*3_^][hff@fW fPfOfHPP P_^][΅|tV$|W[3|$󫋆D$lT$jRPQ,tPhd_^tËT$F( @F(@uF(%@=@uL$u F(F(%=u F(F(ʁu*N(3% 3 3ȁ@3ȉN(u F(̀F(D$ @jT$ RT$RPQ\D$LuD$ F,_3^tÐT$ D$3ɊHuCAw83Ҋ$|L$H~$3ËT$4P3B+HË2[4XSU$@V$HW39~t VUU`~@;tPQz%=uWWt UU$\RN$X3ҊQ;Oދ$P$TS;sS gnfC$`%=D$'3$C3fDŽ$H$T$ ;$$DŽ$ ;DŽ$\$ 5$jP@D$ u4$@tBj$$Q@D$ t' $<jRD;%%5 Cw13Ɋؗ$̗333WRQPSWWW؃ ;ZW%3_^][4Ê$\ t%5 %5 t ;<Pt|3; <VjQH9=|<RP|$;lj|$$uz9=Turhe1het$ 1;D$$tMD$L$PQheVuT$D$PTt$e3uD$D$$ PSTщL$(K T$0<jRD$(@D$4L$< P<jPDL$0PQ$|$0L$(t$4D$,T$++uT$$t$j(+j+D$(+ƙ+1Pu#TuT$uD$ BD$L$T$3ɅҋT$ D$RVWPD$$PQ <Q,D$u@DPT <Q03U=XI} _^]3[4Ë_ ^][4Ë<5DjRց%u %5 ËG$\ t%5 %5 t<Pt|u <WjQHË-؋ $P<PQRPtPh3_^][4Ë=({3PD$,D$0jD$4׋ <jQD$< <PjRPD$4P$L$4D$,T$0+hQL$0+RP<QjP, <jQP=׋ <;t50Qjd׋ <;u狼$X3ɋǙLt.$P3fP;u$T3fP;t @ uH$TjQ$XWVQPRTtSjjW$\VRPQTt3$\$L%P$TWVPQU_^][4jjUU3|$@lt$VQVPR;t-;$Lt SWh3_^][4Ë<RV@PQ ;t-;$Lt SgWhi3_^][4ËEURPQp;t-;$Lt S!Wh|#3_^][495|<PPt$;Ɖt$ut95Tulhe0'hel$ ';D$tGL$T$QRheUuD$L$P Te3ul$T$ PTL$(D$,ыL$$T$0jС<PT$<  <PjQDT$0PR$t$0L$(|$4D$,T$++t$j(+j+D$(+Ǚ+.Pu TuT$uD$L$ <UWVD$$PD$ PjQ,@DPT <jQP<R0X_^][4ËÊxS$V$Wj#ȉ FuP_^[xù3|$NfFL$$ˋV IɉD$(F@@D$ D$lD$T$ $D$` D$d@8tD$d`3ҊPT$lHL$pPT$t@D$x$tD$ r$jT$RT$ RPQtPhAD$T$ Rh@8PD$PQtWh\ D$ uD$QPR8tPh$@@t@hȄND$L$<L$jQPtPh=3|$jD$L$hD$ lQjPRdtPhDD$ jPu-D$FL$ >@@uOD$ T$R$DŽ$RPQ0t!PhNT$3Q_^[xËD$D$ NT$ _^Q3[xhhȃD$ t;$tPQVRF_^[xÐD$QuhuËT$jjRP/ÐVt$ W|$ uFujjVWFu_3^Ë%=uFH QVW }uFH$QVW }t V0B _^ÐT$S\$UVt$$CWl$0HB3҉L$$xfVFЉD$T$3fVD$ЋT$%3=‹‹ PD$PQMEQPWRtU=vu*D$$PQlWRlh`_^][Ph@L$4C0UQVSP_^][_^]3[ÐtD$|V3ҋH$qfPHщL$T$3fP$щD$dT$ T$RhjD$L$D$ djPVQ=vuVQlD$PhjL$jQVR^tPht3tÐD$D$D$D$HL$QjPRttPh3ÐÐlS\$xVWC|$ T$ p3PhD$lRPVQd=vuCPQljD$hPjVRdtPh$_^[lËD$3fK;tBKT$sfC$3A+ȋC ыL$+ȋ$%щST$0_S^3[lÐVt$ jF@PF^ÐVW|$G0jVQH=vtjjVR,=vu$GPQljVRH=vtjjVP,_^tPhȅ03ÐVt$ Ft+L$;BtPQVRF^ÐD$ L$,SUVW|$4qD$8-D3fFV\$3fN\$$@T$ӉT$ jT$hR4ىD$(L$$l$8\$4R@RT$0RPQ=vu;@PQljhBT$R4RRT$0RPQD$8HD$83_^][ ÐVt$W3H 4ur|$Ul$~DL$SY\Y\Y\OuЋ|$[F TRWUjPQ]_^ËD$L$hPQV:ǂF VhjjPQ_^ÐT$D$ ;~Ѕ~]L$SUVt$W7'+A+T$ Pψ (\ X\ L$ IL$ u_^][áT$4VWȁ<2~3Auh83 _^ËL$Qh08PtPh _^Ë$|$ 󥍰$ 󥍰D$$ L$ QjPRtVhyD$PR_^Ë$PR蟰_^ÐT$4VWȁ<2~3Auh8_^ËL$Qh08PtPh _^ËD$L$ SQjPR ؅u>$t$󥍸$󥍸$Shh6D$ PR[_^Ë$PR _^ÐS\$V34;t8%=uVV <VQP4t S9@ ;tPQr 9ptpU-W$;t9;tPՋ9u狃 8QՋ344|S<;_]t S;t P5^[ÐD$H t @QPR|ÐUMSVWEPv4b@u @K$^M Qu4VRjWHE WP8Mu,3ƃ$^΋s}ȃu 3~*~KWKWTKWT @;|ًEuh@3E ;~1UzGWPQRSPM  A;ȉM |Ջ PE4RP= Mǂ4QO_^[]ÐSVt$FF t~\$ <u VSST|eF U3~8VW|$3NfF3Ʌ~3A@:PV;|F E;|_]<uVSSXjjjjV- ^[Ðjjj<jQ ÐSUVWj$ uP3_^][Ë\$ l$ 3jD$ nFF ~uPV%>3_^][ËL$T$SQURZuV=3_^][ËV O Ѓ YV12V N~tIYUVt F _^][F _^][ÃlT$pSV$W3|$ 󫋄$$D$$D$ lD$L$D$t@@D$T D$X\$\jRT$RPQtPh3_^[lË$$Rh@8P$PQtVh\3_^[lù3|$ j󫋄$L$hD$lQjPRdt$PhV$PR_^3[lË$jPD$Xt9\$\u$_^[lh&$PR_^3[lÐlSVt$|W|$ FT$ 3PhD$l RPSQd=vuSPl jT$hRjSQdtPhz_^[lËFfL$fVD$0=YV12t=IYUVuMFfffHFfffPN3ҋFfVPF3ҋNfPF+‹Q‰A_^3[lÐD$jHPÐ D$(V3WHD$4=@j1fPHщL$T$3fPD$]ÐUhyM̀E;-u3]S\$ VW<; uAsйB  yJʀB_^-[]ÐD$ ;uA%yHȀ@ÍHyIɀA;uJy ;‹t;VWQyJʀB 4<45;u_^Ðu2t P0_(ttÐD$jjjP[3ɅÐVt$jjjV*ttu^j 3^ÐD$jjjP3ɅIÐD$L$QZÐÐL$Su\T$ V2W3ɾ tu #ANu_^D$P[ËD$ |JEu £ #ȉ L$Qp[Ð V3<uL3L$D$D$ D$L$D$ D$D$tT$RЃtD$Px^ÐD$Vhjj PF3<u.D$tL$QЃtT$R ^Ĕátt9SVtWh0PӃt PQӃGu_^[ÐVt$jVXV ^Ðtt9SVtWjPӃ=0t PQӃGu_^[ÐS$UVWD$PS{$ $QUf$,$ RPQ$($(QD$,RP$}Nht$QUSWVh_^][ÐQD$5WAz|$3_YD$ 5DzL$33Ҋ fA@=|_Y5t$ |$V3t$\$D$ 5D$K 5J=~fwFt$|^_YÐQSUV<\$ uh^][YËCdujjj t$Wt {dt$t{dt$ t{dE_% = u,M@ۋtË@RjPjU3^][YËCptKdT$ QRЃ^][YhF^][YÐU-VEdujh EduP^]ËMtt PVу63Ҹud3Ɋ Bf0ud=f0udfL0|W|$t ud|$tud|$tud_^3]ÐS\$UVj=S u^][W3򮡠_IF;v&VPu^][ã5 VSQ +P@#СRPp^]H[Ð SVW|$PQWӋu_^[;5v)VRu_^[VPW5ӡ_^[ÐSU-$VW333ȇL$PQՃu ̇u*ȇD$RPՃu ̇urttj t x_^][_^][ÐD$3SUV;WO ;E D$4;+0;!D$8;; ڋT$0;щ\$tT$L$D$(l$t||$t^CPuxu 8uxt(uPu 8uxtOuˋT$( tT$( D$( uZT$( N|$t:uxtuxtOuD$( T$(u D$(T$(Bt,uOs _^][B $s _^][fBl$|$D$ wD$ _^][ËT$(H $ CO3Ɋ CO 3|$r.рt uD$r,$t$;t y|>q_֋I^DVh ^ÐD$PVt$L$T$A ;}I$ Ph؉2ÐD$SP\$S,J‰S,;u VSg3 t7;t L@u( Wt+ȍ<ʃ_zC 5tPփCtPփCtPփC$tPփSփ^[ÐtPÐD$L$fT$ SVWy fw3u= D$D$ L$ fT$tT$ RЃtD$ P_^[ÐD$L$T$ SVWy> 3u< D$D$ L$ T$tT$ RЃtD$ Pz_^[ÐL$ %tHt3D$ D$ D$Vt$W~$ :T$3u7D$ T$ L$ tL$QЃtT$R_^ÐtV3Pu^ÐVW|$3D$D$ D$ D$ D$ tD4WPFr_^ÊL4jQ%tFr_^ÐSVWj C3SPf,jj <8(0,(D dx| ܐؐԐА̐ȐĐdhlptx||xtplhd`\XTPLHD@<840,($  x|܏ԏ̏ďth\PD8, ؎̎x l`TH< 0$$(, 048<܍@ЍDčHLPTX\|`pddhXlLp@t4x(|ԌȌth\PD8, ؋̋  $(,|0x4p8h<dD\HT@LLDP<T8X0\$` dhlpt x|ԊȊth_^\PH@8( 3[Ð3VD$3D$D$ D$uL$t$QjFC|^ÐL$| ÐD$tCÐÐD$ÐD$=C} uHÐ3T$ D$S\$ D$ D$UD$VD$ 3Wzȉl$%B=2tu=/TtJ+-,t!H 2ۈ\$,2ۈ\$,-0t HuBɀ@-3w $Tytoj@eD$[ wF$p%6%/%(%!%%% %%ȋ%BD$,%+tHt _^]3[D$D$;t9=u-r;t'8u _^]3[Á JD$%u} BL$JR D$D$\$L$ T$$t-t$t$tL$QЃtT$R_^][ÍIC ' 5.CC<t`B+ʋt; v?; v'thЃt hYÐL$3;|"D$;| 3hTÐD$ T$ÐSUl$VW!tHDtf@H f@0%=jt|=[?D$tL$T$UPQR{_^][ËL$t$+řƒ~ }AOu_^][Ë|$]t$L$3-ř3Ҋ%AFO5Au_^][?tL$T$D$UQRP_^][ËD$|$t$33Ҋo 3Ŋn3Ҋ ȁ~ }NKu_^][=th|_^][ËD$te|$t$33Ҋ/W 3Ŋ.3ҊV ȁ~ }NNKu_^][ÐUSVWWVS}u E]nsssd$oofo?iaiaoorrrkrkwKuw[^__^[]ÐUSVWWVS}u Ensss]t=$odh`oȃqqcKuw[^__^[]ÐSUVW333ۅt$P|$ D$PQD$ 4D$$uST$LhRSu>$et$LPSCt$D$ED$C;q_^][ÐD$L$SUVWh`Ph$hhQ3qq-T$D$RhVPhՅ$hA$QhhRD$(q=D$$PD$QV$$VRP׋L$QӅ$D$RhhhPpL$T$QhVRhՅuZL$D$PVVVhQD$,ׅu:T$R L$D$PVjjhQ׋T$RӋ_^][_^]3[ÐL$u TÃDS\$L3UVWj4D$DD$D$ D$$ ttx|T$(D$@L$,T$DD$0L$HT$4D$LL$8T$PD$V3fqL$ 3f) 4AfqA3^H™L$f)Ð3SD$UD$ 3f9l$(D$D$VWD$ uf|$4f;u3rL$4T$0QR]t$8 f;}34X;|ffNf|$4f;}l$44ϋX ;|ffHD$4f|$4f;u5f;uf=D$(%+t%Ht _^]3[Ê\$,D$I \$,D$I ";բtQRf5f=(7D$%u?L$(;ňL$\$ft$f|$tT$RЃtD$P_^][Ðh$`tVWf3_^u3SU- VhՋ3ۃ;W3j Ճ;É_3ɉHHFF`F ^FF QF$F@`^D^H^L^PFT QFXQ^\F`Q dž,dž0dž^][S5;t V^]3[ÐVt$W=PV׃_^ÐD$@@3ÐS\$UVW@t PD$$‹t$t$ V Azuh3_^][Ë3ыt$jjD$,jjPV)u1QRhT@苻3_^][ËL$(D$F_D$F AfVffVHƉN^][ÐÐVt$4@tP4A^ÐSUVWj( 3;uU`3_^][Ë\$$ 3CF$^FD$(;L$0;͋L$,;~ D$$\$$ùF ظVUUUT$4l$$*а*ŠT$4L$*‹|$ӈNNL$4ҁыψV ʺF^ ȸˋ\$$nVF FFFF F F F F nnnnL$,;ʼn.F Ftu 2¨tV ʨuV;F Ft%u 2¨tV t ʨuVD$0F ;Ftu 2¨tV ʨuVL$4F ;F t%u 2¨tV t ʨuV T$(D$,VT$0FVN= jl$׃t(Q׋BxuVij3_^][ËL$(unL$0ufL$,u^u:_HAB@QBHAB@^][Ë3ʃ_^][ËD$(3333҉\$|$$l$4l$t+3ɸN+ɉD$~+ ߅|$$\$D$,t#3ɺN+х~+ |$$D$0t'3ɽN+~D$4+ DžD$4D$3\$L$(#N ˋًL$N ؋AL$,#N ʋ\$$N ؋AL$0\#N ͋\$4N ؋A\GADD$;l_^][ÐVt$FtPnV8D$L$T$PD$QL$RPQgF^Ð@y D$ P0H4T$`Vt$t)W=t@tP׃P׃V׃_^Ð|$ubD$VW3xƃ%ȋ ȋƃOȋ ȋƃO  FW|_^ÐT$JfAfB3ҊQItu%%@+%%%Ð T$S3U V;WD$D$L$l$$L$(D$,z%L$ D$$L$ 33ҊGD$$+3ɊO++ȋȋ;sD$ɈD$tD$L$T$A;ʉL$|_^][ ÐT$uGD$J%Vt$J JJ J Ƌt$J J ^ ËL$T$ QL$ RQP%ÐT$u]D$J %VJ rJ#Ƌt$ J J Ƌt$J J Ƌt$J ^ËL$T$ QL$ RQPT%ÐVt$ WF|$ N #3UNT-+ʋЋD$FN #3ɊNT-+ʋЋD$FN #3ɊNT-+ʋ]ЋD$Ft+N #3_N 6+ʋ^ЋD$ËL$ _^ËD$ Q_ T$ QLT$ ^QL$DT$ÐVt$ FN UW|$#3ɊNT-+ʋЋD$FN #3ɊNT-+ʋЋD$FN #3_N]6+ʋ^ЋD$ËD$IL$JTL$^JTD$ÐT$3Ʌ~OSUVt$W|$F+t$3ۃ\^X3ۊ\(^X3ۊ\A;ʊ^X|_^][ÐS Vj ӋuP腴3^[W3jӃF_uV<jU3^[3ɉH^[ÐVt$t%FFtPF^SUVW|$o0%@=@u jWBUL$u3YGHt]3CHt5OC:WC;GK;VSW ɉEu{uw_^][3CHtSW,Eu\_^][ËT$<u :uVRPP E>uEu_^][ÊOC:tD$EP4D$PU?9_^][ÐT$ S\$Ul$VWt-M;}s 3u _^][ Q uPw3_^][Ë3~+l$SLQPRPU>F;|׋_^][ÐS\$UVt$W;F<u D$ %D$D$P 3;ʼnD$uU3_^][9nt 3ɊK$L$l$3;$3ɊNIthIG3ɊLيNN D$ 3ɊHNN 3 ؋D$ NN N ؋D$N ؋D$(O3ۊ^ ݈ O3ۊ^ L݈ O3ۊ^ L݈ ]GN\N D$ @fNN fN ؋D$N L$ ؊NN f ؋D$f(\$B;_^][Ð$VW03|$jL$D$ Q$$L$PT$VQT$ c_^ÐVt$t$WVF=tP׃V׃_^ÐV5hjփtPjփhjփtPjփ3^ÐD$hPHV5jjփ=tPjփjjփ=tPjփ^Ð V3<u.D$ tL$QЃtT$RF^ÐVW$$9=u 95=54tn;xu;p tdShjL$(j Q轱3<u6D$ |$t$tT$ RЃtD$ P|[_^Ĕ_3^ĔÐ@Vt$HW|$TFD$Gu@tWe} _^@ËT$XFSUZ33HfoڋWڋV0t$X\$`RnR3tt$\33fNt$`L$8It$`L$8xpX ˁtt L$X3fAD$8333ۊ ZۉD$L\$T1L$`A3tZʉ\$X+ȉL$TL$T3f43f#!L$Xf8IL$Xu‹D$LZt833f2fً#!zf\$TkvGMAL$X0ރ#ك!!{{ށ{{ًL$XXIL$XuNj\$Tt+33f7f#!f8D$LZ;D$t$\33fNt$`L$8It$`L$8zD$433Ɋ 3ɊJD$XɉL$TD$`L$Xݍ3+˅~+ʅ~*t$\<+;~΍4*T$Tʃ|$4L$\;D$Hut$P33fVt$TT$XJt$TT$Xn_^][4ËD$X33l$LfHfpL$X3ƉL$4D$\D$Tٍ HL$T33ۊE]ЃtO;T$\}AL$43+ʋÅ~+ƅ~+L$\<+;~ D$Ttuы%++l$\D$\% .KuT$0L$,l$Ll ;T$HL$P33fAL$TȋD$HL$TD$_^][4ËL$X33l$LfQfqT$03ΉT$4ʉL$ L$TڍT$T33fMfu|$@t$|T$ L$D$Rff~PWRVT$<+u‹D$,ut$4D$L$;T$DD$3fJ D$8HL$D$8T$ B<D$4uff@pD$@p\$Dȁt<tSRC|$<+VWuNjK0_^]Q[B30ÐL$ D$ɉD$D$T$SUVW|$L$ 7XH #HJJ H#H HJJ H ݋h#HJJ L$L$ fYL$ IL$ uL$_^][ ÐD$D$D$ T$S\$ UVt$ WD$ ;BJ #Nj#N J NN J ŋj#NN J ŋj#%%  D$(D$D$ HD$ sT$_^][ÐD$D$D$ T$S\$ UVt$ WD$ ;BJ #Nj#N J NN J ŋj#NN J ŋj#%%  D$(D$D$ HD$ sT$_^][ÐL$ D$ɉD$D$T$SUVW|$L$ 7XH #Jh#J H JJ H ݋h#JJ H ݋h#L$L$ ݉YL$ IL$ uL$_^][ÐF+@F D@KNЍDQF %NЍL N P l$DuPt^][<ËVÉT$VWJR L$,#ы L$(N%L$N T$0ՅɉD$ T$D3L$@t$t$<D$ 3t$t$<t$D$ L$t$4;}4D$WT$,T$0L$4#ƒ;u D$F;|ߋD$ t$L$;T$}8D$WT$,T$0L$4#ƒ;t D$F;|ߋD$ T$t$|$4+ϋ|$;uD$<+;ȉt$$~$3u fEf} EE+;;}ƃD$4u fMfE MEË|$ыʋT$D$$L$4+хD$$T$tnD$$T$ ;}ЃufEfU EUt$|$ȋD$$˃\$8L$+‰L$D$$uD$Ul})D$t Vh\_^][,D$ 33fCfOwSν;T$Lt$L$(D$$D$H3fPL$ʋPʁ|IT$@3frD$\$LËZ\$Lډ\$LD$Ju\$Dt$D$Hwt$Q33fWfCRQL$PQO33fWfCRQL$PQ433fWfCRQL$PQ33fWfCRQL$PQ#T$$D$(F;t$D$t T$HRGD$ t D$@P2_^]3[,Ð#Q>QYQtQL$ D$VW|$ 4ɍt JNIu_^ÐVt$ W3IL$v'Q;sS\$U][_^ÐT$SVW3\$ID$I;s+PSPv 7_^[ÐS\$VW3IFV t VSW2 _^[ÐSUl$Vt$W|$݅|s߃E-]ދ tL|LvFD$ T$L$QUVW>7D$PUVWCx|wϋl$0CE<-uMQ8_^][U8_^][ÐSUl$Vt$W|$݋ t\wv[D$ T$L$QUVWس7D$PUVWCRwrwϋl$U8_^][E0]U8_^][ÐD$ Vt$u2W3I_vjhXV t L$QPV"L$ T$ tƉD$^ÐD$SUW|$33|$ujhXW uVD8~jQ@<Qt70'|$u>^ÐSUl$ VD$WMPh3hQ\$ D$,_D$cE~Ec;]}ÍT$RG%D$$EhhPD$,@t$T$@RhhEPD$,|UD$3ɋ́4v%G I ۉG~+GGEC ;5;][L$3QD|UhhRD$0D$,0uVD$3ɋ́4v%D$ T[ I ODT[ȉODD$_^]H[ÃS\$VD$ WPhhQD$$|PT$wA$q393ɋL !34 |$$tstucL$ QhhRD$$ u=D$3ҋȊԁ I% I ЋƉ_^[_^[Ðqq2qPqPqIqq VW|$KǾ<D$ʙ3L$  ƾ<D$ Kʙ3  ƍT$D$(D$Rj hQ_^ ÐD$jjh RÐVt$$D$WPhhQ3D$,uBT$L$T$ QD$ (j hRD$ fu_^HÐD$jjhQÐD$jhh QÐD$jjhQÐ,~1V3~W=XPס,F;|_,^ÐVj tJYjPjF FɉFFFt N tuV3^jM<^ÐVt$t9F t P:Ft P*t PV^ÐVt$uhM8^ËP FN;~%N @QFsR+FP2 3^ËQ3^ÐVt$uh7^ËWPFN;~AF+~SߋN QKu[R~FPOu_3^ËQ_3^ÐVt$uhM7^ËSWP NANQ<\$S2D$$ uV R- PF PQF~#~ V RFPFHFFHQFS_[^ÐD$L$jPQ/ ÐD$SV5hWjjjjPօt4=l|$t!L$ Q׍T$ RjjjD$jPօu_^[ÐPS\$\U-VQWmCE3Ɋ$`L$lfXt jU4t,ȁu<tu~3t U4tEȁu3<t'Ee3t𿨖3ujjI`,_^]3[PD$ptD$pXt jU 4t,Ёu<tu~3t U 4tEЁu3<t'Ee3t𿨖3u6L$pQjZ`3_^][PX3;t _^]3[P<;tEt _^]3[P<T$RP |$l$t$t$<;tP T$<HL$t$t$\$djSD@t3 S PT$VR|L$T$D$+ʋT$+ЋD$px_h^HP HPH P$]3[P<h@Px <5h@Q֋<hHR֡Xu;<Pu+ <t8x@DPT5H@=L DX++t h@ <^UWV׆Ff|$p=R_^][P <D$ PQ4tu PRT<T$ RP_^]3[P&=_^`]3[P`tj_^]3[P_^,][P/ (3Ɋ$4Ёu<tu~3tuF <T$RD$D$L$ljjt -`t$p\t\4@+‹L$4+B ++D$fuft; <D$PQT$D$RPWVjWVjjn`_^]3[P4ȁu<tu~3S<P8$D$lpD$h@p~6L$dQ)D$lpD$hHpp\t"33%D$lD$lD$lD$l뱋D$pT$lPD$lQRPo`3_^][P4tvȁu<tu~3tJD$lt<jL$tjt$xVjzojjVj`io ` ȉ `_^]3[P4t=Ёu<tu~3tjj蝓`_^]t3[P-t]t)ht/L$pT$lQL$hRSQUЃ_^][PT$lRUD$pL$lT$dPQSRx_^][PU_^][Py{;w{k{U{zy z~{|}~P}v}{}}{}}<j PPjhÐ<jPPjjÐVWj1[D$3PX$Ѹt0$t /$t @2$t 1$t 4$t 3$t ,D$t -VZ_^ÐD$xÐxuPÐ(U3;t @]3(S\$8;ut ͋S>_^][Ð SU$@VWt@$$ < $8;4 tO09u QCKdt^Du7@uG0Q KdDRPFPQB$ R$ PUQcBjjjjWR ;4uNCdt$ T$QRUP&Bl$$ $UPQSSm_^][_^][ÐD$L$ T$PD$QRjPÐV5W3;SU9<t<=fX UV$88Q譱 4;tP4莱 <@;t@PӋ@QӃ@D;t PӃDFd;t PӃ~dH;t PӃHL;t PӃLU=][_^Ë Vuh^ËAxt T$RQЃ^h^Ð V3A|t(t T$RQЃ^h@^h^ÐT$ 3$T$`ËT$dËT$hËT$lËT$|ËT$tËT$pËT$xËT$ËT$ËT$ËT$ËT$ËT$ËT$ËT$ËT$h`üǻһݻ *5@KValVtL$ T$QRP ^ËD$ h|^Ð4t PhYÐ[D$ L$PQ D$,U3V5;L$3OfG3ř+AGL$ L$L$t L$3f;tD$ tSO3fQuF‹ȋ͙‹T$‹ցyJB+ʲ"ʈGF;|G E;L_^][YËG 3ۅ~{3WfoG3~\T$3ɊME;uF‹ȋ˙‹T$‹ցyJB+ʲ"ʈGF;|G C;|_^][YÐuËL$uX|Ã|4t8yL$ SV5ދ u X^[ËXW|$utWu WSЃ;XtX(tSփ|_^[ÐVj8j^Ð3tRуÐ V3W<t$ ;W>y9jQҋts4 <7jQҋt:4<XQL_^Ð tt T$RQЃ3Ð S\$(U3;݉l$ l$VWS͂SłWAVE|$ut$ S訂RIFF*=WAVED$l$,D$,;t PD$$PSE;|IL$TD$$=factT$t=LISTtt$,=fmt މ\$t'hHD$D$3l$ fHTl3Ҋ$V^ZVVBD$ T$<3C3fCt$Ph(D$fBKt$@|$DJfBdatat PD$4T$$RP L$,L$$;t&T$DD$븅u L$ hfB끋L$L$tWV |mD$ tWV|WD$<3ҊHPI#?PhPhD$#hD$$D$\$3;t S\$4|$9l$8t SS D$(t$+j+WS D$_;^t]3[ ËD$4][ D$ff fPfH PfHf fP3fhf 3Ɋhff thl33Ҋpf3Ҋpf3fA;|3ÐL$SU-V3ҋt$ fW>\$|$‹P uPo_^][f=L$(;ڍ,}GɢtGU3gft3ҊwfU3gft3ҊwfU3gft3ҊwfU%3ET$ɍT$FVtEUVVtEUV3f%…~`XCL$D$$QT$(RhzL$(F$QD$4T$4RUWFGKuL$(\$%+;؉\$D$P3_^][Ð@SVft$L$$L$,L$Tt$4t$LWD$ D$D$D$T$$T$4D$@VD$DD$HA ¿3D$,|$|$VV\7\7^^T7T73ۈVV]T$EӉl$VV\7\7^^T7T7VVT$JT$\$DT$0ӉT$0T$<ӉT$Ej@HPQHR3ҊPFQNRPQj+X Eu _^][Ë]jF8P@T$D$,dN9WGT$D$,O=IYUVt5=UYVYthl_^][ËN9GWGT$D$,FHP8L$T$,Cu@tSd} _^][ËD$tEH*T$43fKBS3BT$4ȋCȋC3ҊP3fCڙT$ҋVt$+PD$0RVRUQL$ PE QWRPU+PD$0RVRUQL$ PE QWRPUt$@$Fu@t V7dD$tL$4uT$0EQVRPIL$4QjV% 3_^][ÐD$VptDt PfFW=tP׃F tP׃FtP׃V׃_^Ð%̀@s sË333Q=L$r-=s+ȋą@P%WVS3D$ }GT$ڃD$T$D$ }GT$ڃD$T$ uL$D$3؋D$A؋L$T$D$ ud$ȋD$r;T$wr;D$vN3ҋOu؃[^_SW3D$ }GT$ ڃD$T$ D$ }T$ڃD$T$ uL$D$3D$ 3OyNS؋L$T$D$ ud$d$r;T$wr;D$ v+D$T$+D$ T$Oy؃_[SVD$ uL$D$3؋D$ Aȋ\$T$D$ ud$ȋD$r;T$wr;D$ vN3ҋ^[SD$ uL$D$ 3D$3Pȋ\$T$ D$ ud$d$r;T$ wr;D$v+D$T$+D$T$ ؃[̋D$L$ ȋL$ u D$S؋D$d$؋D$[D$u9L~. L l 0u?h Y8u3f 8h`h`4LYY=u98t0 4Vq;rtѡ8P%8Y^jX US]Vu W}u =L&tu"<t WVSЅt WVSu3NWVSSE u u7WPStu&WVSu!E } t<tWVSЉE E _^[] %h|$u=<u t$jX 6EJE(ECCDD(D8DC^DrDDDDDCCNDEDDDC===v==== >>">2>F>X>b>x>>>>>>>> ?d=V=B=.= = =<<=FEEEEEE|ErEhEEEEEEEEF F F*F4F@FFPFZFbFlF~FFFFFE@BPBdBtBBBBBBBBBB CC(C8CDCTCdCC.B BBBAAAAAAA~AhAFA8A&AAA@@@@@@@r@j@^@F@6@$@@@??????v?b?T?F?4?"?XA<<<<<v<`<P<B<0<< <;;;;?@UUUUUU?@ @a )19AJ R@Zabjs{ @a @a  @ a  ) 1 9 A)J )R@)Za)b)j)s){)1 1@1a111119 9@9a99999A A@AaA A)A1A9AAJJ JR@JZaJbJjJsJ{JR R@RaRRRRRZ Z@ZaZZZZZ b b @b ab b) b1 b9 bA jJ jR @jZ ajb jj js j{ j s s @s as s s s s { { @{ a{ { { { { @a )1ƒ9AJ R@Zabjs‹{ @a” @aœ @a )1¤9AJ R@Zabjs¬{ @a´ @a½ @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a   @ a ) 1 9 A)J) R)@Z)ab)j)s){)11 1@1a111199 9@9a9999AA A@Aa A)A1A9AAJJJ RJ@ZJabJjJsJ{JRR R@RaRRRRZZ Z@ZaZZZZ b b b@ ba b )b 1b 9b Aj Jj Rj@ Zja bj jj sj {j s s s@ sa s s s s { { {@ {a { { { { @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a @a Ł)š19AJ R@Zab́j͡s{ @aՁա @aށޡ @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a  @ a  ) 1 9 A)J )R@)Za)b)j)s){)1 1@1a111119 9@9a99999A A@AaA A)A1A9AAJJ JR@JZaJbJjJsJ{JR R@RaRRRRRZ Z@ZaZZZZZ b b @b ab b) b1 b9 bA jJ jR @jZ ajb jj js j{ j s s @s as s s s s { { @{ a{ { { { { @a )1ƒ9AJ R@Zabjs‹{ @a” @aœ @a )1¤9AJ R@Zabjs¬{ @a´ @a½ @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a   @ a ) 1 9 A)J) R)@Z)ab)j)s){)11 1@1a111199 9@9a9999AA A@Aa A)A1A9AAJJJ RJ@ZJabJjJsJ{JRR R@RaRRRRZZ Z@ZaZZZZ b b b@ ba b )b 1b 9b Aj Jj Rj@ Zja bj jj sj {j s s s@ sa s s s s { { {@ {a { { { { @a )19AJ R@Zabjs{ @a @a @a )19AJ R@Zabjs{ @a @a @a Ł)š19AJ R@Zab́j͡s{ @aՁա @aށޡ @a )19AJ R@Zabjs{ @a @ap0Ppp`|PpzDxkx{P,{@p??  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~G0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ:0yE>@33?1@_?P+X ֿ+ɿ`-k?a+oDEST`+oDESTmDEST rU<DESTmDESTmDESTmDESTmDESTmDESTmDESTmDESTDY.DEST>ikzO›NNڲi߻C+3Vt;<T9?hd:Cx8E8ZE9F6EJE(ECCDD(D8DC^DrDDDDDCCNDEDDDC===v==== >>">2>F>X>b>x>>>>>>>> ?d=V=B=.= = =<<=FEEEEEE|ErEhEEEEEEEEF F F*F4F@FFPFZFbFlF~FFFFFE@BPBdBtBBBBBBBBBB CC(C8CDCTCdCC.B BBBAAAAAAA~AhAFA8A&AAA@@@@@@@r@j@^@F@6@$@@@??????v?b?T?F?4?"?XA<<<<<v<`<P<B<0<< <;;;;waveOutWritewaveOutUnprepareHeaderwaveOutClosewaveOutPrepareHeaderwaveOutOpenwaveOutGetErrorTextA&joyGetDevCapsA*joyGetPosEx(joyGetNumDevs:mciGetErrorStringA>mciSendCommandAtimeGetTimetimeBeginPeriodtimeSetEventtimeEndPeriodtimeKillEventWINMM.dllSetThreadPriority1GetCurrentThreadeWaitForSingleObject,CloseHandleaCreateSemaphoreAReleaseSemaphoreFreeLibraryGetProcAddressGetVersionExA.LoadLibraryAFCreateEventASetEnvironmentVariableABGetEnvironmentVariableAJCreateFileASetErrorModeSetFilePointerReadFilevWriteFile=GetDriveTypeAgGetModuleHandleA]GetLocaleInfoAGetACPQMultiByteToWideCharFormatMessageAZGetLastErrorWCreateMutexAReleaseMutexeCreateThread2GetCurrentThreadId2TerminateThread~QueryPerformanceCounter)SleepKERNEL32.dllCallWindowProcADefWindowProcA!GetKeyState:GetMessageADispatchMessageAPeekMessageA"GetKeyboardLayoutLoadKeyboardLayoutA$GetKeyboardLayoutNameA&GetKeyboardStateMapVirtualKeyExAShowWindow`CreateWindowExASetWindowLongAnGetWindowLongADestroyWindowEnumDisplaySettingsA*ReleaseDC GetDCWSetForegroundWindowSetWindowPos]GetSystemMetricsAdjustWindowRectEx,GetMenuIsZoomed ChangeDisplaySettingsADestroyIconInvalidateRectGetDesktopWindow)ReleaseCaptureDSetCapture1ScreenToClient GetCursorPosGetForegroundWindowEGetParentMsgWaitForMultipleObjectsMapVirtualKeyATranslateMessageVSetFocusOSetCursorPosPostQuitMessageEndPaint BeginPaintMSetCursorAClipCursor@ClientToScreenGetClientRectAdjustWindowRecttGetWindowRectToUnicodeRegisterClassALoadImageAzSetTimerPostMessageAKillTimerWindowFromPoint PtInRectMapWindowPointsUnregisterClassAGetClassInfoAToAsciiExDestroyCursorGetCursorOCreateCursorGSetClassLongAYCreateIconFromResourceExSetWindowTextAUSER32.dllECreatePaletteGetSystemPaletteEntriesDeleteObjectjGetDIBits,CreateCompatibleBitmap2CreateDIBSectionDeleteDCBitBlt SelectObject-CreateCompatibleDC SelectPaletteSetDIBColorTableRealizePalette.SetPaletteEntrieslGetDeviceGammaRampSetDeviceGammaRampkGetDeviceCapsDescribePixelFormat0SetPixelFormatChoosePixelFormatKSwapBuffersGDI32.dllRegCloseKeyRegQueryValueExARegOpenKeyExAADVAPI32.dllstrncmpmalloc=atoi^free_ftolqsortreallocsscanfXfprintf_iobsignalraise;_CIpowstrchr_stricmpdftellbfseek]freadffwriteLfclose_strrev_pctype_isctypea__mb_cur_max_strlwrF_ltoa_ultoa_beginthreadex_endthreadex<atofstrstrMSVCRT.dll_initterm_adjust_fdivDisableThreadLibraryCallsTD.OGTJM J020P0utvu2`it !p[]p0pt p@d0P$@Jk`@мP pPPa@$0`PP0 P @ @  `P0 p`P0 0` `hppa@`@p0PIGC@HpJJ KPJJK`p0P@Ќ@_p`@^й" 0@С$Ni `b0`pp%KLLKK`L``0нPS0QURpR R@TSU6OCOOOcOqOOOOOOOOOOOPPP+P:PLP[PhP|PPPPPPPPQ#Q8QBQRQcQxQQQQQQQQR RR&R6RBRURiRRRRRRRRR SS'S4SGSXSgSxSSSSSSSSS TT+T8THTWTbTpT}TTTTTTTTUU)U;ULU`UuUUUUUUUUVV'V6VEVSVcVvVVVVVVVVVVWWW+W>WKWZWhWuWWWWWWWWWWX XX,X9XIXYXgXuXXXXXXXXXYY#Y0YAYQYcYxYYYYYYYYY ZZ/ZAZPZhZvZZZZZZZZZZZ[['[8[B[M[X[c[n[{[[[[[[  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~SDL.dllSDL_AddTimerSDL_AllocRWSDL_AudioDriverNameSDL_AudioInitSDL_AudioQuitSDL_BuildAudioCVTSDL_CDCloseSDL_CDEjectSDL_CDNameSDL_CDNumDrivesSDL_CDOpenSDL_CDPauseSDL_CDPlaySDL_CDPlayTracksSDL_CDResumeSDL_CDStatusSDL_CDStopSDL_ClearErrorSDL_CloseAudioSDL_CondBroadcastSDL_CondSignalSDL_CondWaitSDL_CondWaitTimeoutSDL_ConvertAudioSDL_ConvertSurfaceSDL_CreateCondSDL_CreateCursorSDL_CreateMutexSDL_CreateRGBSurfaceSDL_CreateRGBSurfaceFromSDL_CreateSemaphoreSDL_CreateThreadSDL_CreateYUVOverlaySDL_DelaySDL_DestroyCondSDL_DestroyMutexSDL_DestroySemaphoreSDL_DisplayFormatSDL_DisplayFormatAlphaSDL_DisplayYUVOverlaySDL_EnableKeyRepeatSDL_EnableUNICODESDL_ErrorSDL_EventStateSDL_FillRectSDL_FlipSDL_FreeCursorSDL_FreeRWSDL_FreeSurfaceSDL_FreeWAVSDL_FreeYUVOverlaySDL_GL_GetAttributeSDL_GL_GetProcAddressSDL_GL_LoadLibrarySDL_GL_LockSDL_GL_SetAttributeSDL_GL_SwapBuffersSDL_GL_UnlockSDL_GL_UpdateRectsSDL_GetAppStateSDL_GetAudioStatusSDL_GetClipRectSDL_GetCursorSDL_GetErrorSDL_GetEventFilterSDL_GetGammaRampSDL_GetKeyNameSDL_GetKeyRepeatSDL_GetKeyStateSDL_GetModStateSDL_GetMouseStateSDL_GetRGBSDL_GetRGBASDL_GetRelativeMouseStateSDL_GetThreadIDSDL_GetTicksSDL_GetVideoInfoSDL_GetVideoSurfaceSDL_GetWMInfoSDL_Has3DNowSDL_Has3DNowExtSDL_HasAltiVecSDL_HasMMXSDL_HasMMXExtSDL_HasRDTSCSDL_HasSSESDL_HasSSE2SDL_InitSDL_InitSubSystemSDL_JoystickCloseSDL_JoystickEventStateSDL_JoystickGetAxisSDL_JoystickGetBallSDL_JoystickGetButtonSDL_JoystickGetHatSDL_JoystickIndexSDL_JoystickNameSDL_JoystickNumAxesSDL_JoystickNumBallsSDL_JoystickNumButtonsSDL_JoystickNumHatsSDL_JoystickOpenSDL_JoystickOpenedSDL_JoystickUpdateSDL_KillThreadSDL_Linked_VersionSDL_ListModesSDL_LoadBMP_RWSDL_LoadFunctionSDL_LoadObjectSDL_LoadWAV_RWSDL_LockAudioSDL_LockSurfaceSDL_LockYUVOverlaySDL_LowerBlitSDL_MapRGBSDL_MapRGBASDL_MixAudioSDL_NumJoysticksSDL_OpenAudioSDL_PauseAudioSDL_PeepEventsSDL_PollEventSDL_PumpEventsSDL_PushEventSDL_QuitSDL_QuitSubSystemSDL_RWFromConstMemSDL_RWFromFPSDL_RWFromFileSDL_RWFromMemSDL_ReadBE16SDL_ReadBE32SDL_ReadBE64SDL_ReadLE16SDL_ReadLE32SDL_ReadLE64SDL_RegisterAppSDL_RemoveTimerSDL_SaveBMP_RWSDL_SemPostSDL_SemTryWaitSDL_SemValueSDL_SemWaitSDL_SemWaitTimeoutSDL_SetAlphaSDL_SetClipRectSDL_SetColorKeySDL_SetColorsSDL_SetCursorSDL_SetErrorSDL_SetEventFilterSDL_SetGammaSDL_SetGammaRampSDL_SetModStateSDL_SetModuleHandleSDL_SetPaletteSDL_SetTimerSDL_SetVideoModeSDL_ShowCursorSDL_SoftStretchSDL_ThreadIDSDL_UnloadObjectSDL_UnlockAudioSDL_UnlockSurfaceSDL_UnlockYUVOverlaySDL_UnregisterAppSDL_UpdateRectSDL_UpdateRectsSDL_UpperBlitSDL_VideoDriverNameSDL_VideoInitSDL_VideoModeOKSDL_VideoQuitSDL_WM_GetCaptionSDL_WM_GrabInputSDL_WM_IconifyWindowSDL_WM_SetCaptionSDL_WM_SetIconSDL_WM_ToggleFullScreenSDL_WaitEventSDL_WaitThreadSDL_WarpMouseSDL_WasInitSDL_WriteBE16SDL_WriteBE32SDL_WriteBE64SDL_WriteLE16SDL_WriteLE32SDL_WriteLE64SDL_getenvSDL_iconvSDL_iconv_closeSDL_iconv_openSDL_iconv_stringSDL_lltoaSDL_mutexPSDL_mutexVSDL_putenvSDL_revcpySDL_snprintfSDL_strdupSDL_strlcatSDL_strlcpySDL_strtoullSDL_ulltoaSDL_vsnprintf SDL_AUDIODRIVERSDL_VIDEODRIVERfpdffNo available audio device1 (mono) and 2 (stereo) channels supportedCouldn't create audio threadCouldn't create mixer lockSDL_OpenAudio() passed a NULL callbackSDL_AUDIO_SAMPLESSDL_AUDIO_CHANNELSSDL_AUDIO_FORMATSDL_AUDIO_FREQUENCYAudio device is already openedMSBNo buffer allocated for conversionBlit combination not supportedP<@=>>?@PA BHIJpLMOQR2(3404Error reading from BMPCompressed BMP files not supportedFile is not a Windows BMP fileBMCouldn't convert image to 24 bpp%d bpp BMP files not supportedCD-ROM subsystem not initializedCD-ROM not openedInvalid CD-ROM drive indexInvalid starting trackInvalid ending frame for track %dInvalid starting frame for track %dInvalid play length@`px|~|lFCursor hot spot doesn't lie within cursorA video mode must be set before warping mouseddp2Win95/98/NT/2000 WaveOutwaveoutwaveOutPrepareHeader()Out of memoryCouldn't create semaphorewaveOutOpen()Unsupported audio format%s%s: 00000409Couldn't create windowCouldn't get user specified windowSDL_WINDOWIDee@CWin95/98/NT/2000/CE GDIwindibcenter%d,%dSDL_VIDEO_CENTEREDSDL_VIDEO_WINDOW_POSCouldn't create DIB section(ff`WWdirect-to-disk audiodiskSDL_DISKAUDIODELAYWARNING: You are using the SDL disk writer audio driver! Writing to file [%s]. wbsdlaudio.rawSDL_DISKAUDIOFILEff ZPZSDL dummy audio driverdummy gg0\\Win95/98/2000 DirectSounddsoundDirectSoundCaptureCreateDSOUND.DLLDirectSoundCreateDirectSound GetCurrentPosition%s: %s%s: Unknown DirectSound error: 0x%xCaller doesn't have priorityNo audio device foundInvalid call for the current stateMixing buffer was lostControl requested is not availableInvalid parameterAudio device in useFunction not supportedUnsupported interface -- Is DirectX 5.0 or later installed?DirectSound LockSound buffer size must be between %d and %dDirectSound CreateSoundBufferxip74fpi74`fmousekeyboardIDirectInputDevice2::GetDeviceStateDevice not initializedInvalid parametersYour version of DirectInput needs upgrading%s: Unknown DirectInput error: 0x%xInterface not supportedUndefined error!Device not registeredDirectInputDevice::SetCooperativeLevelDirectInputDevice::SetEventNotificationCouldn't create DirectInput eventDirectInputDevice::SetPropertyDirectInputDevice::SetDataFormatDirectInputDevice::QueryInterfaceDirectInput::CreateDeviceDirectInputCreate7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7! !7" "7# #7$ $7% %7& &7' '7( (7) )7* *7+ +7, ,7- -7. .7/ /70 071 172 273 374 475 576 677 778 879 97: :7; ;7< <7= =7> >7? ?7@ @7A A7B B7C C7D D7E E7F F7G G7H H7I I7J J7K K7L L7M M7N N7O O7P P7Q Q7R R7S S7T T7U U7V V7W W7X X7Y Y7Z Z7[ [7\ \7] ]7^ ^7_ _7` `7a a7b b7c c7d d7e e7f f7g g7h h7i i7j j7k k7l l7m m7n n7o o7p p7q q7r r7s s7t t7u u7v v7w w7x x7y y7z z7{ {7| |7} }7~ ~7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 7 887   8877 77777 7$7(7,0 1 2 3 4 5 6 7 8 9 : ; < = > ? @ A B C D E F G H I J K L M N O ~~yzWin95/98/2000 DirectXdirectxDirectDrawCreateDDRAW.DLLDINPUT.DLLDirectInputCreateA%s: Unknown DirectDraw error: 0x%xSurface created in different modeUnsupported modePrimary surface already existsSurface not flippableNo emulation availableNo DirectDraw hardwareSurface was implicitly createdNo blit hardwareWindow handle is subclassedWindow handle already setExclusive mode was already setNo palette hardwareNo palette attachedInvalid surface typeDirectDraw is still drawingSurface was lostSurface busyNo flip hardwareNo cooperative level setNot 8-bit colorNot in exclusive access modeOut of video memoryInvalid pixel formatInvalid rectangleObject not foundInvalid objectException encounteredIncompatible primary surfaceInvalid caps memberOperation not supportedInterface not presentDirectDraw2::EnumDisplayModesDirectDraw::QueryInterfaceDirectDraw2::GetCapsDirectDrawSurface3::SetClipperDirectDrawClipper::SetHWndDirectDraw2::CreateClipperDirectDrawSurface3::SetPaletteDirectDraw2::CreatePalettePrimary DDRAW surface is not RGB formatDirectDrawSurface::GetSurfaceDescDirectDrawSurface::QueryInterfaceDirectDraw2::CreateSurface(PRIMARY)DirectDraw2::SetCooperativeLevelDDraw didn't use SDL surface descriptionDDraw created surface with wrong sizeDirectDrawSurface3::GetAttachedSurfaceDDraw created surface with wrong pitchDDraw didn't use SDL surface memoryDirectDrawSurface3::LockDirectDraw2::SetSurfaceDescNo room in video memoryDirectDrawSurface3::GetCapsDirectDraw2::CreateSurfaceYou must set a non-GL video mode firstIDirectDrawSurface3::BltFastBlit surfaces were lost, reload themIDirectDrawSurface3::BltIDirectDrawSurface3::SetColorKeyDirectDrawSurface3::FlipDirectDrawGammaControl::SetGammaRamp()DirectDrawSurface3::QueryInterface(GAMMA)A video mode must be set for gamma correctionDirectDrawGammaControl::GetGammaRamp() 0DDraw didn't use requested FourCC formatDirectDrawSurface3::Blt(null)Unknown SDL errorError seeking in datastreamError writing to datastreamError reading from datastreamCouldn't lock event queue Gamma ramp manipulation not supportedNo video mode has been set8,$܈ЈȈ     x UCS-4UCS4UCS-2UCS2UTF-32LEUTF32LEUTF-32BEUTF32BEUTF-32UTF32UTF-16LEUTF16LEUTF-16BEUTF16BEUTF-16UTF16UTF-8UTF8ISO-8859-1LATIN1US-ASCIIASCIIThere are %d joysticks availableJoystick hasn't been opened yetJoystick only has %d axesJoystick only has %d hatsJoystick only has %d ballsJoystick only has %d buttonsundoeuropowermenubreaksys reqprint screenhelpcomposealt grright superleft superleft metaright metaleft altright altleft ctrlright ctrlleft shiftright shiftscroll lockcaps locknumlockf15f14f13f12f11f10f9f8f7f6f5f4f3f2f1page downpage upendhomeinsertdownleftrightupequalsenter[+][-][*][/][.][9][8][7][6][5][4][3][2][1][0]world 95world 94world 93world 92world 91world 90world 89world 88world 87world 86world 85world 84world 83world 82world 81world 80world 79world 78world 77world 76world 75world 74world 73world 72world 71world 70world 69world 68world 67world 66world 65world 64world 63world 62world 61world 60world 59world 58world 57world 56world 55world 54world 53world 52world 51world 50world 49world 48world 47world 46world 45world 44world 43world 42world 41world 40world 39world 38world 37world 36world 35world 34world 33world 32world 31world 30world 29world 28world 27world 26world 25world 24world 23world 22world 21world 20world 19world 18world 17world 16world 15world 14world 13world 12world 11world 10world 9world 8world 7world 6world 5world 4world 3world 2world 1world 0deletezyxwvutsrqponmlkjihgfedcba`_^]\[@?>=<;:9876543210/.-,+*)('&$#"!spaceescapepausereturncleartabbackspaceunknown keykeyboard repeat value less than zeroSDL_MixAudio(): unknown audio format%s\%sSystem\CurrentControlSet\Control\MediaProperties\PrivateProperties\Joystick\OEMJoystick%d%sOEMName%s\%s\%sSystem\CurrentControlSet\Control\MediaResources\JoystickCurrentJoystickSettingsjoyGetPosEx%s: Unknown Multimedia system error: 0x%xCan't capture joystick inputJoystick not attachedBad device IDInvalid parameter(s)Joystick driver not presentf<`SDL dummy video driverCouldn't allocate new pixel format for requested modeCouldn't allocate buffer for requested mode1111SDL_RWFromFile(): No file or no mode specifiedCouldn't open %swin32_file_seek: invalid context/file not openedwin32_file_seek: Unknown value for 'whence'Unknown value for 'whence'Can't write to read-only memoryUnable to lock source surfaceUnable to lock destination surfaceInvalid destination blit rectangleInvalid source blit rectangleOnly works with same format surfaces0xI64Width or height is too largeSDL_UpperBlit: passed a NULL surfaceSurfaces must not be locked during blitFill rect on unsupported surface format1-bpp rect fill not yet implemented4-bpp rect fill not yet implementedEmpty destination palette%c:\mciSendCommand() error: %sPassed a NULL condition variablegapiTrackMouseEventUSER32.DLLCouldn't register application classSDL_appFailed loading %s: %sOnly cursors of dimension (%dx%d) are allowedWindows couldn't create the requested cursorCouldn't create mutexCouldn't wait on mutexPassed a NULL mutexCouldn't release mutexWaitForSingleObject() failedPassed a NULL semReleaseSemaphore() failedNot enough resources to create threadtimeSetEvent() failedWarning: Can't set %d ms timer resolutionInternal logic error: Win32 uses threaded timerWarning: Unexpected icon_256 characteristicsCouldn't create Win32 icon handleApplication not compiled with SDL %d.%d Timer already initializedMultiple timers require threaded events!You must call SDL_Init(SDL_INIT_TIMER) firstThis platform doesn't support multiple timersxe~,    No available video deviceOS doesn't support threaded eventsCouldn't create shadow surfaceGL_EXT_packed_pixelsglViewportglVertex2iglTexSubImage2DglTexParameteriglTexImage2DglTexEnvfglTexCoord2fglPushMatrixglPushClientAttribglPushAttribglPopMatrixglPopClientAttribglPopAttribglPixelStoreiglOrthoglMatrixModeglLoadIdentityglGetStringglGenTexturesglFlushglEndglEnableglDisableglColor4fglBlendFuncglBindTextureCouldn't load GL function %s: %s glBeginVideo mode smaller than requestedOpenGL not availableInvalid bits per pixel (range is {8...32})Invalid width or heightNo video mode large enough for %dx%dOpenGL active, use SDL_GL_SwapBuffers()No dynamic GL support in video driverVideo subsystem has not been initializedNo GL driver has been loadedUnknown OpenGL attributeGL_GetAttribute not supportedOpenGL video mode has not been setUnrecognized file type (not WAVE)Unknown WAVE data format: 0x%.4xMPEG Layer 3 data not supportedUnknown %d-bit PCM data formatComplex WAVE files not supportedUnknown set of MS_ADPCM coefficientsIMA ADPCM decoder can only handle %d channelswglGetSwapIntervalEXTwglSwapIntervalEXTWGL_EXT_swap_controlUnable to create GL contextUnable to set HDC pixel formatNo matching GL pixel format availableUnable to get DC for SDL_WindowUnable to reset window for OpenGL contextwglGetPixelFormatAttribivARBwglChoosePixelFormatARBWGL_ARB_pixel_formatwglGetExtensionsStringARBUnable to make GL context currentCould not retrieve OpenGL functionswglMakeCurrentwglDeleteContextwglCreateContextwglGetProcAddressCould not load OpenGL libraryOPENGL32.DLLOpenGL context already createdSDL_VIDEO_YUV_HWACCELSDL_VIDEO_YUV_DIRECTYUV overlays are not supported in OpenGL mode0@Unsupported YUV formatCan't use YUV data on non 16/24/32 bit surfacesUnsupported YUV format in blit0 H` 4VS_VERSION_INFO  ?StringFileInfo040904b0 CompanyName0FileDescriptionSDL8 FileVersion1, 2, 11, 0(InternalNameSDL`LegalCopyrightCopyright 2002 Sam Lantinga8OriginalFilenameSDL.dllRProductNameSimple DirectMedia Layer< ProductVersion1, 2, 11, 0DVarFileInfo$Translation  00;0B0M0U0q0x0}0000000001 1Q1g1o1u111111111111112B2Q2f22224445(5?5v555555516d6666667Q7X7d777e888E9v99999:A:a::::@;0t23-3Y3z3333 443444445255555555556 6'6.656;6666666666667g777S8c889;9L9@"3)313A3S3`3d3h3l3p3 9999999999::::::::%;Hp?t?x?|?????????????P\000000001m122222222>3333444 44I4P4X4h4z444445;;;;f<`<99999999: :,:::::;;;6;;;;D>>>{?$1112=<=====>????(022222d5h5l5p56>>>??8888h9P<3@3D3H33@5D5H5L5P5T5X5\55P7T7X7\7`7d7h7l7u7788888999959U99h,4044484<4@4D4H444445(555p526i6w67F89999999999999999V:;;;;;;;;W<T0(5,5054585<5@5D5H5L5P5T5X5\5`5d556,7074787<7@7D7H7L7P7T7X7\7`7d7h79><H3L3P3T3X3\3`3d3h3l3p3t3x3|333455 55555 55,00000000F1????????1080D01U11194444451888888888 99F9O9_9n999999:M:d: ;W;;;; <1Q>>>>>>?0x0;0E00011!2>2K2s22222222233323}3344Y44z5555556q666787B7777j88e99999::,:0:4:8:Z:p:w::::::::;;;&;0;:;D;N;X;b;l;v;;;;;;;;;;;;;;< <<<$<*<4<>>>$>.>8>B>L>V>`>j>t>~>>>>>>>>>>>>>? ???(?2?;?@?F?P?????@`0)0@0G0[0b0,101111111111111"2E2Y2b2x2}22222222223 333*313C33333333334 4444(424<4F4P4Z4d4n4x4444444444444444"5w55566"6.6j666666d777V8j8q88888889%9+9N9W9s9z999999: ::::p::::;u;;;;<;G>[>p>w>~>>>>>>>????@?j?n?y?}???????????????`00 0000!0*040>0J0Q0[0l0t00000001D2 3z34"4T44L55M6d66666666)7/7o7y7777778M8T8{889:9E9R9{999999999&:\:h:l:p:t:x::::::::::;;;&;-;7;H;P;[;_;g;k;s;w;;;;;;;;;<=&>7>X>z>>>>>>>>>?!?,?9?D?W?d?k?r?????????ph 00>0S0b000000000111%1/191C1M1W1a1k1u111111111111112 222)232=2G2Q2[2e2o2y22222222222222333#3-373A3K3U3_3i3s3}33333333333333 444'414;4E4O4Y4c4m4w44444444444444+5K5Y5f5|555555 66-62676<6E6M6R6t6{6666666677797?7]77788/8=8G8N8\8u8888889(9.989G9N9a9o9x9999999999::: :::;n;u;|;;;;;;;;;;;;;;;;;;< <<<(<2<<X>\>g>k>v>z>>>>>>>>>>>>>??$?(?3?7?B?F?Q?U?`?d?o?s?~????????????????\0 000&0*05090D0H0P0T0\0`0h0l0t0x00000000000000000111 11112 22222 2$2(2,2024282<2@2D2H2\3r3|33333334444!4)4.43484>4Z4p4u44455555506n6x6666'8.8|88899999S:]:f:::3;:;I;Y;c;i;u;|;;;;;;;;;;<<0!>0>K>r>>>>>>>>>>>?#?000H1l122 4k444D5e5555566 6'636V6]6r6x6}666666667%747>7b7x7~77777777777789979e9999.:F:;@;G;p;;k<=1==;>>?t 0G0k022233~334$4D4Q4445:5B5556 66i6666778888:8:V:::};D<{<< ====(>,>0>4>8>W?^?<000 00000000011 11!10171B1U1q11111111112'2-2A2G2O2Y22222222 33%363;3D3\3f3v3|33333333[4e4v4}44445$525M5W5a5n5v555555566616:6R6\6717R7c7s777777778C8888888:9F9Q9\9b9t99G:i:::::: ;;;<<<<==="=/=H=P=a=g=n==========>>5>/0^3777777777777888 88888 8$8@8888l9p9t9x999999999::9:Q:u:::;<2<<<<^== >I>>>>>>G?W?b?k???8"04000!17111112222#2'2-21272;2A2E2K2O2U2Y2_2c2i2m2s2w2}2222222222222222222222222223 3 3333!3'3+31353;3?3E3I3O3S3Y3]3c3g3m3q3w3{33333333333333333333333333344 4444!4%4+4/45494?4C4I4M4S4W4]4a4g4k4q4u4{44444444444444444444444444455 55555%5)5/53595=5C5G5M5Q5W5[5a5e5k5o5u5y55555555555555555555555555566 66666#6)6-63676=6A6G6K6Q6U6[6_6e6i6o6s6y6}6666666666666666666666666667 77777#7'7-71777;7A7E7K7O7U7Y7_7c7i7m7s7w7}7777777777777777777777777778 8 8888!8'8+81858;8?8E8I8O8S8Y8]8c8g8m8q8w8{88888888888888888888888888899 9999!9%9+9/95999?9C9I9M9S9W9]9a9g9k9q9u9{999999999999999999999999999:: :::::%:):/:3:9:=:C:G:M:Q:W:[:a:e:k:o:u:y:::::::::::::::::::::::::::;; ;;:;_;u;;;;;;;<<=o=~=======> >>>T>X>\>`>d>h>l>p>t>x>|>>>>>>>>>>>>>>>>>>>>??3?9???E?M?f?q??031333-373D3`3u3333334?4M4i444445 5W5k5555555555666+6^6z6666677!94999N9k9~999999999999999999 ::: :$:(:,:0::::::';[;l;s;;;;;;;;<<3<<<<<<<<<=q==>x>>>>>>>??a?v???????@0 00%0/0W0a0k0000 1+1z112;2f466667<<&>>000001 1#111I1a1p111111$222364333333333 T7X7\7`70,3v333378S;;<>>>>>>>??@h60>0E0^04&4-444?4|44 595F5Q555546666#7*71787e7v777&8[8b8i8p889999:%:B:>$???PpM0111112T3333414f4m4444440676~6678 88888 8$8(8,808488889V:s::;;<?`1334D4 5!6 77084888<8@8D8H8L8P8T8X8\8a888'99<<<<<<<<<<<<== ====!=%=+=/=5=9=D=~======h>>>>>>p$1!1911111111}223;333333444:55666 70777w777778b88888 99N9Z9`9999::: :&:+:4:9:A:J:Q:[:p:u:{:::::::::::;;;1;9;E;];s;};;;;<<<>^>i>t>>>>> ?9?J?`?d?h?l?p?t?x?|????????????|0000!0'010:0D0m051A1L1a1r1111111111111222!2*2N2\2h2}222222222222222233@3P3[3p333333333333334C4y4444444525N5[5f55555566!6*6X666668%8,8>8}8929O9W9f9u9{9999999:E:U:a::::::::;;B;Z;d;u;;;;;;;<<9$>1>=>t>>>>>>>>>???"?>?E?[?a????????,0 00!0G3N3U3m3v33333334 4/454a4g4m4v44444#5K5a5g5555555366667'72787E7T7f7x7}7777777777888+858>8H8S888899"929@9L9k9~99999999 :::G:}:::::::::::*;E;;;;;;;;;< <<<"<'M>[>???020R0b0000$111122222 3L3W3j3334415N5S5j55555555562676N6k6p666666667727O7T7k77777777783888O8l8q888888889939P9U9l99999999::4:9:P:m:r::::::::;;o;;;;; <1<<<=.=S=e=v==2><>S>???!0e0s000131^1111 2o2&3A333333&474L4`4 5255555566S66<7f7728r889`99 :-:E:d:m::;;4;R;x;;;;x<<<<<<<<<<<<<<<<<<<>???11111a222?3566677?7T77)8r888 9g9::2:]::::::-;8;A;J;U;b;q;;;;;;;<<.:?E?N?W?b?o?~??????#0M0\0h0o0x00001n66627=7A:o::::::";H;;;;;;1^>e>>>B?J???0111111111111222 22222 2$2(2,2024282<2@2D2H2L2P2T2p223/363A3o3t333333(474r4444444&5v55667R7a777738899)9;;;;;;;;;<<"<<315r55~88888888888889 9949F999990 L3x3333(4T444444`80<0@0D0222 2222 2(2,20242<2@2D2H2L2P2T2X2p4t4x4|4x5|555666 666666667(9,909<9@9D9H9T9x;;;;;;;;;<<(<8>(>8>H>X>h>x>>>>>>>>>??(?8?H?X?h?x?????????p00(080H0X0h0x00000000011(181H1X1h1x11111111122(282H2X2h2x22222222233(383H3X3h3x33333333344(484H4X4h4x44444444455(585H5X5h5x55555555566(686H6X6h6x66666666677(787H7X7h7x77777777788(888H8X8h8x88888888899(989H9X9h9x999999999::(:8:H:X:h:x:::::::::;;(;8;H;X;h;x;;;;;<<(<8>>><666677777778888 8(80888@8H8P8X8`8h8p8 ,303438333336999h1l1p1t1goattracker-2.72/linux/0000755000000000000000000000000011551400414013602 5ustar rootrootgoattracker-2.72/examples/0000755000000000000000000000000011551400414014261 5ustar rootrootgoattracker-2.72/examples/sfx_expl.ins0000644000000000000000000000012410774364076016644 0ustar rootrootGTI2 Explosion-FXAAgoattracker-2.72/examples/2xtest.sng0000644000000000000000000000637011314431160016230 0ustar rootrootGTS5MW Title Remix, 2x-speedCadaver10/2001    Bass GuitarI Chords  Snarez Lead.AQAA@!QAQAQAĨ # + @ &,(( @1xxxxxx~{}1111xxsz}}zttv}{zz{111ttq}{x{ssss{z11ttv}xxx}11'''''11xxsz}}z{{}1goattracker-2.72/examples/goatcompo.txt0000644000000000000000000000114711314431160017014 0ustar rootrootGoatcompo examplesongs & commandline parameters ----------------------------------------------- Randall: I'll Be A Pimp In Cabrini Green.. (cabrinigreen.sng) /e1 /s1 /a0ff0 Richard Bayliss: Everlasting Annoyance (everlasting.sng) /e0 /s1 /a0f00 Hein: GhostTrackers (ghosttrackers.sng) /e0 /s1 /a0f00 Jammer: My Own Hyperspace (hyperspace.sng) /e1 /s1 /a0ff0 Cadaver: On A Sanction From CIA (sanction.sng) /e0 /s1 /a0f00 No-XS: Sixpack Of Cola * (sixpack.sng) /e0 /s1 /a0f00 * = based on an original song by beek goattracker-2.72/examples/example3.prg0000644000000000000000000000367111051325226016522 0ustar rootroot 2061x0Щ84BϽuʽT30LH*h`   *`` / /  / -J? %JG %J -ɀ  &-    &- # /. #e--..- ԩ70Х-.XL J 0CT]`e SEHhƅHI"~2~hx)!ȐM԰U4F V|¢'?I*`[Ч@:T2Э)Sj}ԧnIF'r|)acO0/׍H1=3aMa1rlkg VfF1Ԍ G6cԊ@ft@7ͥɽ<g +x6N cC{`0123456789ABCDEFZS_ 7ni7XAp!02oLJ~`=iDk3="O`+ 4q ]`1(\K郒 ;eyNWb7jHOϟ:X]aJt'}Ξ*LN_:y]:yZbY"Q`DS:']Htƍg%QP?_a #TyQy"fϰTjnƹk\)n?@nyk'"b@ ęKmF>  UQ}oDX4re3?&n݅9\Z- K2O/{ӁXn'W}1Os,1s`(׊h ްLax"b(pq\9Lg e/n]*֞=R W MΤRfhH)0 j}N:y1+r$c tQYbwhhh 1nCI.U_GkL4ǿU/$qAFJH|_&uNm8h <$z2_T*}NԵ1:Ӊ yT>stR 6$8">gB)KC^ ѣnhq0&48^O Q$qCQu⯅0-w9nsۦvpͼ"BbCcD%e&G()JMbC; [Ȣ{ծ 3ix.$B~^AmEGmz1@XBN;b >"`W@A"bo tKv?pSX@ Y ǒƿ/a:&|~7$oHPϏ>@5" r 섽yLg֏&%+rrʇ(tJɑ%w#y>aaaG##":>hN) `> t?פ~x* Յ^>xȆ]!ג/9|~g SgН7z !*K=@35p9QcydN_ T&ex0goattracker-2.72/examples/sfx_arp2.ins0000644000000000000000000000015610774364076016545 0ustar rootrootGTI2& Arp2-FX%A@goattracker-2.72/examples/ghosttrackers.sng0000644000000000000000000002571111314431160017662 0ustar rootrootGTS5GhostTrackers!    $ #" bass+base -Hein  snare filter  slepbassJ  hat+ringX chord1 0327V chord1 0325V% chord1 0872[. chord51 2787 snare2 lowg< melod softGA soft chord 05gI melod roundMHIHAT OPENWO chord1hat 0327 VR chord1hat 0235FU chord1hat 0872g< melod snerp1g< melod snerp2nX$ chord1 0232  bass - baseGc chordsoft+hatla ringfade inMs chord1| base houseg soft chordl soft chord0485B elec piano elec pianoflute elec flute the stolen tomg melod round+hatAAAAAAA!AAAAAAAAAAAAAAAAQQQQQQQQAA!AAAAUUUUA!A!AAAAAAAAAA!AA!AA!A!A! @ @@ A߰ % .9A%Xcs   -0   @P !`(+)  A@"%H P`P @@p`p%Auux uu uxux{xsuuuxuxusx{xrAZ(:8:Aii*gu+u*o( u(u*gu*u(o( A                AZ8888 Auux uu uxu x{xsuuux  u xu{rAii*gu+u*o( u(u,gu+is  A   7           7   7  s ʽ Anxb4zxxq %xr %xynxb4zxxq޽ %wݽ %vA    ' %   ' %    A A $ " $ " $  )  $    )  $ " $ " $  ) # $    )A $ " $ " $  )  $    )  $ " $ " $    )A      7 7      7 A  $  "   ) $  $ )   $  "   ) $   )Auux  u uxu  x  {xsuuux  u xusxz{xrA 7  7 7  9      :     7 ɽ Auux  u uxu   x  {xsuuux  u xt %xxyA  $  "   ) $   )   $ "x   A    A      ( (  +    Axxxuz{x xxv xxxsuuxuu  xvvx{v{zxrvA  $    (  $  )   $    ( $   ( $A 44 44  44 44    Anzxnx zxxq %xr %xynzxnx zxxq޽ %wݽ %vAjjA 44 44         Axxxuxxxv xxxsuuxuu uxt{    xx { %A  $    (  $  )   $   % %  %Aooox{oxxooxxxxooox{oxxooxxxxAqqx{qo{x{qqxqox{~qqxqox{xx~xnzx{Aiur{iur{iur{iur{iur{iur{iur{iur{AAxݾA nA 44 44  44  AY8888  goattracker-2.72/examples/wavecmdtest.sng0000644000000000000000000000172411314431160017323 0ustar rootrootGTS5Wavetable command testCadaver2006 Covert Bitops  !* AAAgoattracker-2.72/examples/example4.prg0000644000000000000000000000541711051325226016523 0ustar rootroot 2061x0Щ84BϽu ʽ=ۊ30LHs*h`   *`` / /  / -J? %JG %J -ɀ  &-    &- # /. #e--..- ԩ70Х-.XLz su/JPqv S0 Ths(*H'@?AC+Gࠐ4 Sm|A[Qt^```SQ 8ʙ0X *Ko0F DJ@ M&Ш(S*fQZ:*O GѤO,1ѩS^76MAv;3iS^@ *!P$TaR+ kc)s#+jJyjtQ#"D[YDjJj(N:X$b0M ~ D A3LwxD[ǟ_E Yj7ՕHϰ{НJ&;{9< .hrD,T_? =&1sɪ\ ް]x?I*c-X-hKrIP+tcCu Q&AIuT* * ΍"BQ<Dv$tBMrS__6_)@a8 tNԾO$h)=咍82TR:ms `VE7OR^vHm"JTʃ2Q11:wEasP;%A@wڀzb\pLvM_P *JrCs\-}&We#p\fj"mM@d z}1;fNnggc<,:?E#@nZP0'e%9cmax7=^w.}6mvv>;?gn'v {}8CVsuu>x:3(x z z+O,yG'ts^}E {gϙf@gXsYaC_QR ҈`Ҫ`%{} Y|C@i[.I^:s;P348D~435oP1מ|Jg()O]σ 8:(s>^1> ߸@'B}'*y *s~338<5+%%+5C=Ǿ|NHFJLNq3=+_|=^#V}AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAЪ  $03 5 ;=h"""DDDD !xxxxxxxxxxxxxxxxxxxvvxvv!! !xxxxxxxxxxxxvvvvvvvvvvvv!x{{x{{x{{x{{x}}x}}x}}x}}!!! ! !!!!!goattracker-2.72/examples/tempo2test.sng0000644000000000000000000000171411314431160017102 0ustar rootrootGTS5Tempo2 test (switch POpt off!)Cadaver2006 Covert Bitops K AAAAgoattracker-2.72/examples/sfx_arp1.ins0000644000000000000000000000015610774364076016544 0ustar rootrootGTI2  Arp1-FX%Agoattracker-2.72/examples/src/0000755000000000000000000000000011551400414015050 5ustar rootrootgoattracker-2.72/examples/src/example2.s0000644000000000000000000001200110774364076016766 0ustar rootroot; Example of using playroutine 2 (gamemusic) ; ; playeraddress+0 = init music (A = tunenumber starting from 0) ; playeraddress+3 = play music ; playeraddress+6 = play sound effect (A = sound effect address lowbyte, ; Y = sound effect address highbyte, ; X = channel index 0, 7 or 14) ; ; Remember that this player uses 2 zeropage locations, so save those ; locations before calling the player, if you need all of the ZP. ; The player doesn't depend on their contents between calls at all! processor 6502 org $0800 getin = $ffe4 start: jsr initraster lda #22 sta $d018 lda #$00 jsr $1000 ;Initialize subtune 0 ldx #$00 lda #$20 clearscreen: sta $0400,x sta $0500,x sta $0600,x sta $0700,x inx bne clearscreen textloop: lda text,x jsr convertascii sta $0400,x lda #$01 sta $d800,x inx cpx #4*40 bcc textloop idle: lda currraster ldx #52 jsr printhex lda maxraster ldx #55 jsr printhex jsr getin cmp #"A" bcc idle cmp #"D"+1 bcs idle playsound: sec sbc #"A" ;Sound effect number 0-3 tax lda sfxtbllo,x ;Address in A,Y ldy sfxtblhi,x ldx #$0e ;Channel index in X jsr $1006 ;(0, 7 or 14) jmp idle printhex: pha lsr lsr lsr lsr tay lda hexnybble,y jsr convertascii sta $0400,x pla and #$0f tay lda hexnybble,y jsr convertascii sta $0401,x rts convertascii: cmp #$60 bcc ca_ok sbc #$60 ca_ok: rts initraster: sei lda #raster sta $0315 lda #50 ;Set low bits of raster sta $d012 ;position lda $d011 and #$7f ;Set high bit of raster sta $d011 ;position (0) lda #$7f ;Set timer interrupt off sta $dc0d lda #$01 ;Set raster interrupt on sta $d01a lda $dc0d ;Acknowledge timer interrupt cli irwait: lda maxraster beq irwait lda #$00 sta maxraster rts raster: nop nop nop nop nop lda $d012 sta raster_cmp+1 inc $d020 jsr $1003 ;Play music and measure lda $d012 ;rastertime it took to dec $d020 ;execute sec raster_cmp: sbc #$00 sta currraster cmp maxraster bcc raster_skip sta maxraster raster_skip: dec $d019 jmp $ea31 text: dc.b "Example 2: Game-musicroutine " dc.b "Rastertime: / " dc.b " " dc.b "Press A-D for sound effects. " hexnybble: dc.b "0123456789ABCDEF" maxraster: dc.b 0 currraster: dc.b 0 sfxtbllo: dc.b arpeggio2 dc.b >arpeggio1 dc.b >gunshot dc.b >explosion arpeggio2: include sfx_arp2.s ;The order in memory determines arpeggio1: include sfx_arp1.s ;priority when trying to override gunshot: include sfx_gun.s ;a currently playing effect explosion: include sfx_expl.s ;arpeggio2 = lowest pri. ;explosion = highest pri. org $1000 incbin example2.bin ;Playroutine & music data goattracker-2.72/examples/src/example4.bin0000644000000000000000000000606311051325226017270 0ustar rootrootLLLLШBԘԽԝ`ԩD`,э(`֍Թ֍ԩ0 /ԍ6ԍ=`)/`LҩB0 ل֐IiBJ,>Hօ-1ԵWHԨhee!eeL0 LҼ1Lҍ`ЌнEGԐFԐEԩFԩG`0/)uэ(юЪ Ѣ Ѣ/ԩ0ԝ2L|ӠE#g yѹu֍uѹhȹu֍qLaэ,ѹumqэq,hȘu֍(ѩ  Ѣ Ѣ0/ I/Թ0LIҼԹӍ>ҍGҽ$-ԹՅՅԱȱ.ȘԼ2Թ՝HԽY8`1ԩԝԽD ԩ3ԹoԩԹ|(ѩ,ѹb՝ԹUՕHՕ Lwӽ м0 D DԹȘ՝ԩDԹ0.ԹӍҼԹօLR}1)BԹWԕԕ0HD<7% F֕LҝԵyFi&ȘF֝LwӼ.ԹՅ3ՅԱ@`.iHO2ȱ`P)ȱ ԰+ȱɽ" Խ2 $3ȱԼE=3ԕ` FԅGԅ3ԩE<@Eӕ7ԕEԱ ɂEԝԕȱȱ` &&////@RuurU'9K_t-NqCtZ-|(R79ZO ѣnhq<Fgy<)D(ͺxSqBOt3   "$')+.147:>AEINRW\bhnu|#3Upnl@d gghp` \PP`0)%% @0@00  PH       @nZPQCvPZPN@zzzzzzzzzzzzzzzzzzzzzzzzzzzzH$PH)P@sZPQCuPZPCxPZPR@H$PH$PH.P@nnznnnnnnnnnpnnnnnnnnnpqpnlvvvvvvvvvvvvvxvvvvvvvvvvvxzv@ssssssssssssqsssssssssssuvxuuuuuuuuuusuxuuuuuuxxxxx zvH.H$PH$PH.PH.PH.H$PH$PH.H$PH$PH)P@nnnnnnnnnnnnlqqqqqqqqqqqqsuuuuuuuuuuuuuvvvvvqqqxxxxxP ACS@T@AC@T@AC@D@ACPTH$ PH. PH3 PH) PH8 PH. P@nnnnnnnnnnnnlqqqqqqqqqqqqsuuuuuuuuuuuuuvvvvvvvuuuuu xvT @AC@T@A C @A C T@T@O @ H$ PH. PH3 PH) PH= P@zzzzxzxxxzzzxzzzzxzxxxzzzxuuuususssuuusuuuususssuuus @T @T @T @T @@@}}}}}}}}}}zzzzxzxxxzzzxzzzzxzxxxzzz x @T @T @T @T @Bgoattracker-2.72/examples/src/example1.bin0000644000000000000000000000530511051325226017263 0ustar rootrootLL@FFMMWWWWWW`````pwCadaver LM`,(``L0 CIiJ.CPC2H hee'eeL0LL`00)ԍv(  LvE#& {4v'ȹ4qLa,4mqq,'Ș4(ԩԩ   ޭ LH=F0fiȱȱȘ^8`= (,ԹԽ @Lv @Ș0OLp}) LD? LyiޛȘԝLjl@`.iFMȱ`P)ȱ)ȱɽ }ԩԩȱԽԽ=`CtZ-|(R79ZO ѣnhq<Fgy<)D(ͺxSqBOt  "$')+.147:>AEINRW\bhnu|[r+Nm"(X .9Kq|{;{   QA@AAAAAXX(,TX&8800((@  @ pp@@00 `        OPJ @Ap@CP @@uQCPz{|C|}@R@CP@OuPuuuuuuuuuxzzzzzzzzzzwwwwwwwwwwz|||||||||||@@C@TR @@C@C@@qqqqqsssssxxxxxxxxxxwwwww|||||uuuuuuuuuuu@C@@@zzzzzzzzzzssssssssss||||||||||uuu|@C@O@@uQ CzPCPCPzz{{|||||@@@uuuuuuuuvvvvvvvv@@R CP@wwwwwwwwrrrr~~~~~~@@uuzzzzuu||||}|zzzwwww}}}||||goattracker-2.72/examples/src/example3.s0000644000000000000000000001056610774364076017005 0ustar rootroot; Example of using playroutine 1 in multispeed ; ; playeraddress+0 = init music (A = tunenumber starting from 0) ; playeraddress+3 = play music ; ; Remember that this player uses 2 zeropage locations, so save those ; locations before calling the player, if you need all of the ZP. ; The player doesn't depend on their contents between calls at all! ; ; For multispeed operation, simply call playeraddress+3 many times ; per frame. processor 6502 org 2048 getin = $ffe4 start: jsr initraster lda #22 sta $d018 lda #$00 jsr $1000 ;Initialize song 0 ldx #$00 lda #$20 clearscreen: sta $0400,x sta $0500,x sta $0600,x sta $0700,x inx bne clearscreen textloop: lda text,x jsr convertascii sta $0400,x lda #$01 sta $d800,x inx cpx #5*40 bcc textloop ldx #$00 authorloop: lda $1020,x jsr convertascii sta $0458,x inx cpx #32 bne authorloop idle: lda currraster ldx #52 jsr printhex lda maxraster ldx #55 jsr printhex jmp idle printhex: pha lsr lsr lsr lsr tay lda hexnybble,y jsr convertascii sta $0400,x pla and #$0f tay lda hexnybble,y jsr convertascii sta $0401,x rts convertascii: cmp #$60 bcc ca_ok sbc #$60 ca_ok: rts initraster: sei lda #raster sta $0315 lda #50 ;Set low bits of raster sta $d012 ;position lda $d011 and #$7f ;Set high bit of raster sta $d011 ;position (0) lda #$7f ;Set timer interrupt off sta $dc0d lda #$01 ;Set raster interrupt on sta $d01a lda $dc0d ;Acknowledge timer interrupt cli irwait: lda maxraster beq irwait lda #$00 sta maxraster rts raster: nop nop nop nop nop lda $d012 sta raster_cmp+1 inc $d020 jsr $1003 ;Play music and measure lda $d012 ;rastertime it took to dec $d020 ;execute sec raster_cmp: sbc #$00 clc adc accraster sta accraster cmp maxraster bcc raster_skip sta maxraster raster_skip: dec $d019 ldy nextraster bne raster_skip2 sty accraster sta currraster raster_skip2: tya eor #$01 tax sta nextraster lda rasterlinetbl,x sta $d012 jmp $ea31 text: dc.b "Example 3: Multispeed-musicroutine " dc.b "Rastertime: / " dc.b "Author: " dc.b " " dc.b " " hexnybble: dc.b "0123456789ABCDEF" maxraster: dc.b 0 accraster: dc.b 0 currraster: dc.b 0 nextraster: dc.b 0 rasterlinetbl: dc.b 50,210 org $1000 incbin example3.bin goattracker-2.72/examples/src/sfx_gun.s0000644000000000000000000000026410774364076016732 0ustar rootroot dc.b $00,$F9,$08,$C4,$81,$A8,$41,$C0,$81,$BE,$BC,$80,$BA,$B8,$B6,$B4 dc.b $B2,$B0,$AE,$AC,$AA,$A8,$A6,$A4,$A2,$A0,$9E,$9C,$9A,$98,$96,$94 dc.b $92,$90,$00goattracker-2.72/examples/src/sfx_arp1.s0000644000000000000000000000031410774364076017000 0ustar rootroot dc.b $0A,$00,$02,$A0,$41,$A0,$A0,$A4,$A4,$A4,$A7,$A7,$A7,$A0,$A0,$A0 dc.b $A4,$A4,$A4,$A7,$A7,$A7,$A0,$A0,$A0,$A4,$A4,$A4,$A7,$A7,$A7,$A0 dc.b $A0,$A0,$A4,$A4,$A4,$A7,$A7,$A7,$00goattracker-2.72/examples/src/sfx_arp2.s0000644000000000000000000000032010774364076016776 0ustar rootroot dc.b $00,$89,$04,$A2,$41,$A2,$A2,$A6,$A6,$A6,$40,$A9,$A9,$A9,$A2,$A2 dc.b $A2,$A6,$A6,$A6,$A9,$A9,$A9,$A2,$A2,$A2,$A6,$A6,$A6,$A9,$A9,$A9 dc.b $A2,$A2,$A2,$A6,$A6,$A6,$A9,$A9,$A9,$00goattracker-2.72/examples/src/example4.s0000644000000000000000000001301410774364076016775 0ustar rootroot; Example of using playroutine 3 (gamemusic under IO area) ; ; playeraddress+0 = init music (A = tunenumber starting from 0) ; playeraddress+3 = play music ; playeraddress+6 = play sound effect (A = sound effect address lowbyte, ; Y = sound effect address highbyte, ; X = channel index 0, 7 or 14) ; ; Under-IO player uses 27 zeropage locations :), the first 25 for SID ; ghost registers. processor 6502 org $c000 getin = $ffe4 ghostregs = $02 start: jsr initraster lda #22 sta $d018 sei dec $01 dec $01 lda #$00 jsr $d000 ;Initialize subtune 0 inc $01 inc $01 cli ldx #$00 lda #$20 clearscreen: sta $0400,x sta $0500,x sta $0600,x sta $0700,x inx bne clearscreen textloop: lda text,x jsr convertascii sta $0400,x lda #$01 sta $d800,x inx cpx #4*40 bcc textloop idle: lda currraster ldx #52 jsr printhex lda maxraster ldx #55 jsr printhex jsr getin cmp #"A" bcc idle cmp #"D"+1 bcs idle playsound: sec sbc #"A" ;Sound effect number 0-3 tax lda sfxtbllo,x ;Address in A,Y ldy sfxtblhi,x sei dec $01 dec $01 ldx #$0e ;Channel index in X jsr $d006 ;(0, 7 or 14) inc $01 inc $01 cli jmp idle printhex: pha lsr lsr lsr lsr tay lda hexnybble,y jsr convertascii sta $0400,x pla and #$0f tay lda hexnybble,y jsr convertascii sta $0401,x rts convertascii: cmp #$60 bcc ca_ok sbc #$60 ca_ok: rts initraster: sei lda #$36 sta $01 lda #raster sta $0315 lda #50 ;Set low bits of raster sta $d012 ;position lda $d011 and #$7f ;Set high bit of raster sta $d011 ;position (0) lda #$7f ;Set timer interrupt off sta $dc0d lda #$01 ;Set raster interrupt on sta $d01a lda $dc0d ;Acknowledge timer interrupt cli irwait: lda maxraster beq irwait lda #$00 sta maxraster rts raster: nop nop nop nop nop lda $d012 sta raster_cmp+1 inc $d020 lda #$34 sta $01 jsr $d003 ;Play music and measure lda #$36 ;rastertime it took sta $01 lda $d012 dec $d020 sec raster_cmp: sbc #$00 sta currraster cmp maxraster bcc raster_skip sta maxraster raster_skip: ldx #$18 raster_copyloop:lda ghostregs,x ;Copy ghostregs to SID sta $d400,x dex bpl raster_copyloop dec $d019 jmp $ea31 text: dc.b "Example 4: Under-IO game musicroutine " dc.b "Rastertime: / " dc.b " " dc.b "Press A-D for sound effects. " hexnybble: dc.b "0123456789ABCDEF" maxraster: dc.b 0 currraster: dc.b 0 sfxtbllo: dc.b arpeggio2 dc.b >arpeggio1 dc.b >gunshot dc.b >explosion arpeggio2: include sfx_arp2.s ;The order in memory determines arpeggio1: include sfx_arp1.s ;priority when trying to override gunshot: include sfx_gun.s ;a currently playing effect explosion: include sfx_expl.s ;arpeggio2 = lowest pri. ;explosion = highest pri. org $d000 incbin example4.bin ;Playroutine & music data goattracker-2.72/examples/src/example3.bin0000644000000000000000000000411411051325226017262 0ustar rootrootLL@CCJJTTTT]]]]]]]gjCadaver LJ~```L0 IiJ.CP2Hhee'eeL0LLy`00)yԍi  LoE# niȹdLTmddȘԩԩ  ~ ~ަ L#~!|$KNyȱȘyR8`~= z~vrԹnԽ @Lo @0 ݺ Ș0oLg})ZR|M L޾}ޔȘԽLcQ`|@`.}i}CJȱ`P)~ȱ&ȱɽ ~ԩԩȱ|ԽԽ=`CtZ-|(R79ZO ѣnhq<Fgy<)D(ͺxS  "$')+.147:>AEINRW\bh  [Oz+fIz  QaQQP1aQaQaQDD( HD#+ @ &,(( @   @xxxxxx~{}@HPHPHPHPHPHPHPHPOP@AC@ACPD@ACPD@xxsz}}zttv}{zz{@HPHPHPHPHPHPHPHPD@AC@ACT@ttq}{x{ssss{z@HPHPHPHPHPHPHPHP@ttv}xxx}@HPHPHPHPHPHPHPHPD@AC@ACTH'@HPHPHPHPHPHPHPHP@xxsz}}z{{}@AC@ACPD@ACPDgoattracker-2.72/examples/src/makefile0000644000000000000000000000116710774364076016600 0ustar rootrootall: ../example1.prg ../example2.prg ../example3.prg ../example4.prg ../example1.prg: example1.s example1.bin dasm example1.s -o../example1.prg -v3 -p3 pucrunch ../example1.prg ../example1.prg -x2048 ../example2.prg: example2.s example2.bin dasm example2.s -o../example2.prg -v3 -p3 pucrunch ../example2.prg ../example2.prg -x2048 ../example3.prg: example3.s example3.bin dasm example3.s -o../example3.prg -v3 -p3 pucrunch ../example3.prg ../example3.prg -x2048 ../example4.prg: example4.s example4.bin dasm example4.s -o../example4.prg -v3 -p3 pucrunch ../example4.prg ../example4.prg -x49152 goattracker-2.72/examples/src/sfx_expl.s0000644000000000000000000000022610774364076017107 0ustar rootroot dc.b $00,$FA,$08,$B8,$81,$A4,$41,$A0,$B4,$81,$98,$92,$9C,$90,$95,$9E dc.b $92,$80,$94,$8F,$8E,$8D,$8C,$8B,$8A,$89,$88,$87,$86,$84,$00goattracker-2.72/examples/src/example1.s0000644000000000000000000000770510774364076017004 0ustar rootroot; Example of using playroutine 1 (standard) ; ; playeraddress+0 = init music (A = tunenumber starting from 0) ; playeraddress+3 = play music ; ; Remember that this player uses 2 zeropage locations, so save those ; locations before calling the player, if you need all of the ZP. ; The player doesn't depend on their contents between calls at all! processor 6502 org 2048 getin = $ffe4 start: jsr initraster lda #22 sta $d018 lda #$00 jsr $1000 ;Initialize subtune 0 ldx #$00 lda #$20 clearscreen: sta $0400,x sta $0500,x sta $0600,x sta $0700,x inx bne clearscreen textloop: lda text,x jsr convertascii sta $0400,x lda #$01 sta $d800,x inx cpx #5*40 bcc textloop ldx #$00 authorloop: lda $1020,x jsr convertascii sta $0458,x inx cpx #32 bne authorloop idle: lda currraster ldx #52 jsr printhex lda maxraster ldx #55 jsr printhex jmp idle printhex: pha lsr lsr lsr lsr tay lda hexnybble,y jsr convertascii sta $0400,x pla and #$0f tay lda hexnybble,y jsr convertascii sta $0401,x rts convertascii: cmp #$60 bcc ca_ok sbc #$60 ca_ok: rts initraster: sei lda #raster sta $0315 lda #50 ;Set low bits of raster sta $d012 ;position lda $d011 and #$7f ;Set high bit of raster sta $d011 ;position (0) lda #$7f ;Set timer interrupt off sta $dc0d lda #$01 ;Set raster interrupt on sta $d01a lda $dc0d ;Acknowledge timer interrupt cli irwait: lda maxraster beq irwait lda #$00 sta maxraster rts raster: nop nop nop nop nop lda $d012 sta raster_cmp+1 inc $d020 jsr $1003 ;Play music and measure lda $d012 ;rastertime it took dec $d020 sec raster_cmp: sbc #$00 sta currraster cmp maxraster bcc raster_skip sta maxraster raster_skip: dec $d019 jmp $ea31 text: dc.b "Example 1: Standard musicroutine " dc.b "Rastertime: / " dc.b "Author: " dc.b " " dc.b " " anaal: pha pla pha pla rts hexnybble: dc.b "0123456789ABCDEF" maxraster: dc.b 0 currraster: dc.b 0 org $1000 incbin example1.bin goattracker-2.72/examples/src/example2.bin0000644000000000000000000000552011051325226017263 0ustar rootrootLLLL>``"`+29`L>0 ٳIi>J.CP2-AhHBhee'AeABeL0AABL-L~ i`UWVUVW`05)ԍl  ȝ)+,.LwE# qlȹgLW"mgg"Șԩԩ   ,+,L;@409()(4ȱа*Ș.R8`-= /"TS LQ Ș  ,0tL4}-)>hAB,C;6F mCLCymiCGȘmLQ*@i@`.iCJ.ȱ`P)ȱ&ȱɽ TS/ȱU+CԝԽTԽSԽAԽBԽ=/`VW/U &ԝԐŨȱȱԝԩ `UԹHԼUɂU !!*****4WWT7'9K_t-NqCtZ-|(R79ZO ѣnhq<Fgy<)D(ͺxSqBOt3   "$')+.147:>AEINRW\bhnu|  $(,04Oi.5K^i|)8GziL{{I !# # QAQAA@AAAAA AAA@!! AAAAH($LD@H(-27L00( $>00& ?((&0 @   $@ (`@      &'( #!$"%@sZPqZPvZPxZP_ P񚜞P񞡣PP󎐒@nZPzZPR@@@sqssqssqsssvxvxxvxxvxxvOP@@@@@vqvsvtvzvsvzxvxxvxxvxxv@C@C@O@ @ @@C@ H'H,H1H6H1@ @T@AC@R@AC@T A CT@C@ A C T@ C ACT@TAC@ACT ACT@T@ A C T@uuuuuuuuuvusuuuuuuuuuvxsvvvvvvvvvwvtvvvvvvvvOP@@@@鎐@钔@@qZPxZP OP xP @sZPzZP OP P 攽@nZPZPO O O @@goattracker-2.72/examples/sixpack.sng0000644000000000000000000002444211314431160016441 0ustar rootrootGTS5Sixpack of Colabeek - covered by No-XS    /` bass big0c - un V% base+bass main fade puls - uni  piew̌  spacy sounď spacy sound-rinG main melod tom$ sner-rawz( sner - main- high base6 base+bass main:! bass - saw( fade puls - un= pluk violinD plukviolin softZL hat + ringfluteXG, chord 029XL, chord 028x}1 flute viboXQ, chord 027X1 flute vibo tril8 base sner - soft   ~] 030~] 040~] 050x 020h 000x 060x 090x 070x 010( 03A plukviolin02C plukviolin03C plukviolin05CZV, chord 058Z[, chord 057Z`, chord 047Zj, chord 038Ze, chord 037Zj, chord 036X, chord 039AAAA!AAAAAAA!!! !AAAAAAAAAAAA@A!G!A!AAAAAAAAAAAA   AA@@AAAA       D%*   Ь=>  HMR W \ affy¢ת            e%J%000( 8x@aq:9@@@ o!!8x@ 00   """)DQ,25; B@I@PpS Y,i00iiiYI91 C ii@#P`*  `0 @ AA))*)))*)))*)))*)))*)A+++++++++,,,,-,,,-,,AxA AAAxxx{}qs x}{ x xxx{}qs }{xxv s AAAx x{}qs x }{ x x {{}qs } xxv s A  Axxx A  A Axxx{}qs x}{ x xxx{}qs }{xxv A+++++++++,,,,-,,,-,,Ax x{}qs x }{ x x {{}qs } xxsA+++++++++,,,,-,,,-AAA+++++++++,,,,-,,x ,x ,x ,AAAAA                                                              AA                                                              Ax xx{}qs x}{ x A                                                               Agoattracker-2.72/examples/transylvanian.sng0000644000000000000000000001662311314431160017672 0ustar rootrootGTS5Transylvanian WhippingCadaver2005 Covert Bitops          Harpsichord Flute Heavybass Heavybass noflt  Snare  Heavybass+BD{  Lead 1; Lead 2{ Harpsi soloQA@AAAAAبئ8800((@  @ pp@ @00 `AA pAA Auz{||}AAAuuuuuuuuuuxzzzzzzzzzzwwwwwwwwwwz|||||||||||AA   AAAqqqqqsssssxxxxxxxxxxwwwww|||||uuuuuuuuuuuAAAzzzzzzzzzzssssssssss||||||||||uuu|AAAu  zzz{{|||||AAAuuuuuuuuvvvvvvvvAA  Awwwwwwwwrrrr~~~~~~AAuuzzzzuu||||}|zzzwwww}}}||||goattracker-2.72/examples/example2.prg0000644000000000000000000000551311051325226016516 0ustar rootroot 2061x0Щ84BϽu ʽJX30LHR*h`   *`` / /  / -J? %JG %J -ɀ  &-    &- # /. #e--..- ԩ70Х-.XL  ! 0Jsuv Щ  OTO~>1R{!4F σ~>4I!Ӓa/t^Kg0q0aBF廉'頤?Q,``xMhHDh}FhV5>S7q"#F>ď,Ƨʘ:Mx 1=3 3S~@ F"062#dz)kkK{Ks,&7FW(ө_?E&YD% Dq@]>p d;D';K$ovTx{~GjP }OA^4r H kK+ ʪjJ* ɩiI)Bȸ+H) Y( HȸxhM2A3\Yob “x'E0F4xE4R4?Ns2O&F rO/逃<=Bqr%zrP+ rhWc PǶPC0'x~#0Ny$a.HHLz[\ N4xy(]V*st7Wv;~ƮK$aaܨCL8 0 wk{rCr+P;6{6ד@cㇴ ]z`I{/ӊ TR:m1`LE2 h <%z"tTt/ԘRSIzijH7:H7:CVŻ|Ta%RB1<+!3 75Hz=lNܩ!lɂbCL$00LMwJ4Tp $.Nr$Og8_kQ ҧL#Z-SyD/BMqT5< 8&>~O #jsCQuI8^*SqBOt0qs^t] YҨ(,1m +%9I]q.NrP_;BÄ>CD QZ])>R3{]Xq>K^i|wI=>^Q;@=Mt4&=$CFh"# #j (?#'( ֏Wn4z.﹨ 1I"ð>Qeef z3i}a&}uMiAGZRxa r$ y P16Z5I#?a ?w @P 00lӣ#7ABC:f8Vڛsw~َZ} 4FQGxG-+@N6NO@ q%)Ytcjry?g&@2ח~34i{BDzt5jm|H'לt|^ǣJzHJݠ@G/Uރ8ß{|w^Ũ_k׈~>ox_/9͔u̧_5 @t!G*I+4C)_A%&/8?>#$n_$w/n>̿R 1 i y ƍ ڇ RA/'N^ee k_7@tޠN!O NqzLj,v_(`*C;7*U *_m{^jLRl\L4$$4Oi J!7#oC\=bC,M!CD- H$P4#đoX`oAzgPggW?xsv ׾{;;|ݐ]{r+'*<`a|YZb>oZtNk5"ݸ=%f&e:Q FWc7yޗrVr: P׸$gawy'lP%.z#1KC:\4OI o  {Ҍ}Dr?H)<*IIl,ƢR%?goattracker-2.72/examples/example1.prg0000644000000000000000000000476611051325226016526 0ustar rootroot 2061x0Щ84BϽu ʽ30LH*h`   *`` / /  / -J? %JG %J -ɀ  &-    &- # /. #e--..- ԩ70Х-.XL |0` JWu SEHhƅHI"~2~hx)!ȐM0 R 4 Vσ~>7|4a>X!` ISJSM\hHDh}FhV5>S7q$F>_1Ƨʘ:Mx@ c9=:SS~@ F"062)02026742uIѕ;YN)|2܎ &Ff((Hhghg22jl6-yyGp] # +Y‰ swsl1,qyu^Rd|hy/g VRI? T^H@Es !F[ @w*0qՑ{< he™D Oic  j1 Hv"Uw %{' ʤS0/ʚSl@!>jcv>!D[tRJ'PvU)\RwM!R= NO٦f7$ Fa;jR>u/a x^< ŭ` ϓG(z"Yir\4Lp E/m΁s>8aMZHx ݃ϳj A.sal4qݥ7A]6ԝVcP^R6v^^^H spp$ a ;XOh&X >v:$P>o%S e;f,) Ӷ _NNj2΀șr΂j*8ee?"WniRj3!zohsyh748Y xVSB'(M(ͺWœ8ЃJ|ۦw[:numnx6  )+147:AR׭DbLjNSl?%fB%+\r6w;䞼s@hL]MOMJAfA7j :&PP?G _(XR>ɨ88o0@@(app ?#HT p_ ɴ_j@0 x`Xp}|x 4 A ǔ|xGH(@Hh}Ǹϔ|x )P?&>}><>}?%?3go)I@ KA\4|(bϹ_!bX;3)9n~Ou31Ԕ䜴_Y7A% (7Gϸ|}@ꔁ^ljG;'VơlީYI)OY$L)k_tޏMyegg3}kmw=^g}gOy.}tY/Yt]3ӊ:Y_3 fK)`CҠ#ދPAB <`r„"'>ʨ 0$$@ ?"h:Ct8h :/9 ⤽!4BT9NoCdM!|`?7~0$Uh_NO5_NLt$tϦ]"`~(SToNc)#3efԄ P#r4~2'2'C.#oo (b>kkn|}|:8x(mۃnigoattracker-2.72/examples/unleash.sng0000644000000000000000000003622311314431160016436 0ustar rootrootGTS5Unleash The F****** FuryCadaver2004 Covert Bitops6   &&&&'*-*/03<46  !!!!!!!!(+*.*14:;46  "#"#$$$%),,,,2567894y Mute Gtr.i Long gtr.  BD+Bass  Snare+Bass  Snare only  Tomdrum)  Snare flam 4. BD only4 Bass onlyk8  "Vocals": Quiet Arp.]= Powerchord{E "Vocals 2"9H Weird mute9L Weird m.nopulsIP Weird longjS Tolkki solozV Jens solojX Tolkki noHRYQA@QAAAAAAAAAAA@@A@AA@QQAA!!QAQAQCBQCBQCQA!AبԪԪ Ԫ)ئ : > $ ;JJ5? @@@@@@ @@000 44#!` @ 0@0`  @`@P`0=A AAyyyyyyyyyyyyyyyyyyy{|~~wwwwwww|{ywA iiɄx||Y|xxuA IIIIAAyyyyyyyyyyyyyyyyyyy{|~~wwwwwww||xA A          Ayyyyyyyyyyyyyyyuuuuw y|{ y w{ A         Ayyyyyyyyyyyyyyyuuuuu uuu||xA ~~~~~~~~~~ A            Arrrrrrrrrrrrrrrtttttttttttttttuuuuuuuuuuuuuuuwwwwww~~}|A             A ~~~~~~~~~~ Arrrrrrrrrrrrrrrtttttttttttttttuuuuuuuuuuuuuut~~~~|~wwwww||xA    A            A||||||||||||||~tttttttttttt~|{wyyyyyyyyyyyyyy{|uuuuuuuuwwwwwwwwA                 A     A||||||||||||||~tttttttttttt~|{wyyyyyyyyyyyyyy{|uuux|xtt||A                           AAuuuuuuuuuuwwwwyyyyyyyyyyyyy || {{ || A Y                    I      Auuuuuuuuuuwwwwyyyyyyywtttttttt}|xA              ! !!y!yy!yyyyyyyyyyyy~ y| { !yyyyyyyyyyxxyxvvs!y !o        {!  "{oo{xxxxA}}}}}}}}}}}}}}}{}}}}}}}}}}}}}}{}{G   AqqqqqqqqqqqqqqqqqqqvxxxxxxxxxxxxxxxxxxxxxvtM O I A AAuuuuuuuuuuuwwwwwwwwwwwyyyyywwwww~~~~~~~~}A 9AAuuuuuuuuuuuwwwwwwwwwwwtttttttttttttttttt}}||xAyyyyyy~t{ywwxx|Ayyyyyy~t{ywwxxxxxxwxx}||xxAyyyyy yyyyyyy yyyy yyy{|~  ~w wwww ww|{ywAy yyyy yyyyyyy yyyy yyy{|~  ~w wwww ww||xE                    A A  goattracker-2.72/examples/consultant.sng0000644000000000000000000000576411314431160017177 0ustar rootrootGTS5The ConsultantCadaver2002 Covert BitopsN     BD+Bassl Sawtooth Pulse leadK  Pulse minor arpK Pulse major arpK  Quiet pulse  BD+Hihat  BD+SnareAA!QAAAAAAAȨ  ̮`` X ```@ Au szuA AA AAsuuuusuuuuuBAIsuuuusuuuuugoattracker-2.72/examples/sfx_gun.ins0000644000000000000000000000013410774364076016466 0ustar rootrootGTI2z Gunshot-FXAĨgoattracker-2.72/examples/dojo.sng0000644000000000000000000002166411314431160015735 0ustar rootrootGTS5DojoCadaver2002 Covert Bitops      &'( #!$"%  Bassz Koto  Fluteڬ  Weird flute  Snare  Bass 2i Fast Koto Loud KotoL! Weird flute 2{# Long lead{% Long lead+nopls'# Loud Koto+noarpI) Short sound@QAQAA@AAAAA AAA@AAA!! AAAAȨ . 3 8 ='L00( $>00& ?((&0 @   $@  (`@)As q v x A AA!n z !!Asqssqssqsssvxvxxvxxvxxv!!!AvqvsvtvzvsvzxvxxvxxvxxvA! ! A - 2 7 < 7A       A                           A       A         AuuuuuuuuuvusuuuuuuuuuvxsvvvvvvvvvwvtvvvvvvvvAAAAAAAAq x A  x A  As z A   A n      goattracker-2.72/examples/hyperspace.sng0000644000000000000000000001721311314431160017140 0ustar rootrootGTS5My Own Hyperspace:P2005 :PS        !!!!!!!!!%%%%%%%%%%%%%%%2S      """""""""&&&&(*(,(*(-./03S   $#'''')+)+)+)+)+)1 @ABasrBStar Arp  Stopa  WerbelD Synchro Hihat BKlapy$  Leadr Star Arp Init&  Werbel TurboT) Formantr, Star Arp Initr3 Star Arp Init9AAAA@CAAUAA  Ʈ&  -  4 00`@`@    pP 0@4!w ~s u!!!l 0    0 @ P  P P 0  0 !  !| rs u!lll!vjvjvjvjvjvjvjvjuiuiuiuiuiuiuiui!!A!l l l llll l l l  !znznznznznznznznznznznznznznuiui!CUAC!l l l l  l l  l l  l !CC!CC!ssssuivjvvjvjvxl!      !!|p|p|p||p|p|p|pdpdpdp||||!!l      !|p|p|p||p|p|p||p|p|p|pdpd|p|!н н !ssssssup|ppp|ppr!!l l l ll lll l   !q}qqq}qqsq}qqq}qqr!  !l l l l  l l  l l  l !!m !! |  ! y    y    y    y   y    y    y    y  ! !н н x xxx !xн н !wwwwzwwwwuwwwwzwwww!!x xxx x x xxx x !  3   !x x x x x x x x !   !x x x x z z z z !    !!w                !!                              ! } !wwwwzwwwwuwbwRwwBzww2ww"!                              goattracker-2.72/examples/cabrinigreen.sng0000644000000000000000000005004511314431160017425 0ustar rootrootGTS5i'll be a pimp in cabrini green(when i grow up))<<CCA!#)&,&/  01D3458,drum+bassbass filtdown  snarebass bandfiltPU$noise in-outbass filtupI effectiU noise inu%lead%%lead delay(drum"-hihat filt snare nofilt1tom\ echo arp min7j arp minor 7j arp major 7+j7 arp minor 9jA arp major 9jK arp minor 7/5-D arp minor 7 shD arp major 7+ shD7 arp minor 9 shDA arp major 9 shYW trpu ringmodYZ pulse synch echo arp maj 7+%%lead 4 sync|t tri ringmodh echo arp maj 7+ك echo arp min5-zsweeping lead)snare+crashyt: trpu sync ! slow arp min 9 ! slow arp maj 7+ ! slow arp maj 9:sweeping echo kissj arp minor 4} tri ringmod lP pulse 3xxP tri 3xx%bass beginningāAAAAA@@@UA@@@AA@A@@@A@@@A@@@UTCA@ A@ A@ A@ AAAAAAA@@@Sߤ߭   ߤ  8 B L  ]  i i  ߭   ; P`pp`!3 0O %  1@$|0GAllxsvvx xxqqxqssx xvAA        Assxlnoq}x xstoxollttAA       x Assxlnoq}x xstoxo{lxxAA       Annz ww w nqlls pp p lqAAAmmr x y}tqosqxp oAA     Amymx y}qsvvx lAA                 Annz wznqlls pllqAlx!x x xxx x l x xx x x x xxx x A# % $ A &  & &  & & &AAAA     Al x xx x x x xxx x x x xx x x x x!A# $ % A  & &    & & & & A  & & &  & & &Axxllsxxsyxolv{xoAxxllsxxsssrr~qooA# kA  & & &      A# % $ A         AllxsllssxjjvqjjqqvA{{A''X''X''X''X''8'''X''X'''X''X''X''X''8'''X''X'Assxlnoq}x xstoxo{lxA''X''XA       AllxsllssxjjvqjqqqvxxA{{({A''X''X''X''X''8'''X''X'''X''X''X''X''8'''X'X'Allxsllssxjjq}mx A{{z"9A''X''X''X''X''8'''X''X'''H''8'x'8'h'8'X'('H'9A  &         & & A & &    Al x xx x x x xxx x o{{xx x myyxmA          A          |xA          Assxlnoq}x xstsvxAlA     )))AAsllssxjjvqjjqqvAx!myyxxqqxqssx xvA, },} v,x,v,x,x {,{ , },} v,x,v,x,x {,A* /***************************************************************A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++A{ , , ,,},{,},} , , , {,x,x A******************************}*{*************************A++++++++++++++++++++++++++++++++++}+{+++++++++++++++++++++A****************************************************************A++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++A       UxAAssxlnoq}x xstoxo{lxsgoattracker-2.72/morphos/0000755000000000000000000000000011604130742014135 5ustar rootrootgoattracker-2.72/morphos/ReadMe2Guide.rexx0000644000000000000000000000133211604130742017241 0ustar rootroot/* $VER: ReadMe2Guide 0.2 $ * Convert simple ReadMe file to AmigaGuide * Stefan Haubenthal 2010 * rx ReadMe2Guide foo.guide */ say '@database ""' say '@author "ReadMe2Guide"' say '@node Main "Main"' if ~eof(stdin) then parse pull last "0d"x prevnode="Main" do until eof(stdin) parse pull curr "0d"x if length(curr)>0 & (curr=copies("=", length(last)) | curr=copies("-", length(last))) then do if prevnode~="Main" then do /*say '@next 'compress(last,' "/')''*/ say '@endnode' say '@node 'compress(last,' "/')' "'compress(last,'"')'"' end prevnode=last end /* escape at-sign */ if pos("@", last)>0 then say insert("\", last, pos("@", last)-1) else say last last=curr end say '@endnode' goattracker-2.72/morphos/goattracker.guide.info0000644000000000000000000001617211437010346020424 0ustar rootrootPNG  IHDR@@iqgAMA|Q cHRMz%u0`:oIDATxb?H4h@,(bddH4:Fh8A+Q@% “LhI I${ȞA񨭭-= veeeUJ;۳O^ruGu _ !9|1<#+$$ãť! ;jRg/38 쬬 @j*ʖ޽y={#@Ar QXrX|}}”啅5偞Uza;P={n޺Š /7߿2|A  gϝ }D@rV RYD^iM Pz^I9 Vz slA F`K#/_11͛ ?}dcPRRbx 0;01Ã~=rypbxWTR:;Ѓ V @bf , T > #+O)AFJ X <}ϟ AHR H-YC i㾀GO޿pUiii ``|:XsAā%(k 0/`YOǏ2ܻwX&cx LiF|Bz۷my *\Xm@\  8x nfdzA XH 6Qapa0cJ?~|g+ .$A ;vbd;`9 |> q )3 cS3CGoJ l >222:f jF l /‘ \$(~=)0Kp Nuuup H >}8Ûo./|]}C`yY,HAyFDl?Hf50IZu_ft _`@\ kPI,|!p8v85}7`mT}` },(Z[Y=|pԩSϜ9\ "%`,?Wy_;0@yV׮ce`ec;YFS>}--e˗3((*0NfffeeW||j 0 l<Ep`ljꥪf "":oǎ0{X H`I0ft?=l<we``$%Ł=P 7N),`^z:W`/`P0e%bcr2Hݹ=F HM׬Ys7++Aʷ N~'yׯ ߁%$01lظAQQJQXX 5v ?gP9}mp9jP104A߿4 ` _<@$,s``L.\t8(vA"Ln RTsƠ>((1hkk ӿϟ ߁)TF2p= $ݾs,V0y+@ x:xG`q"5)p!*$%2P%mP`PP{T҃KZM `=e}6 ` &}POo_0f6[e70 1`aغu 8A*P!֮9V":FD 09p'`.HԸz <ú:P-8 .A]H7?`5Spg A F6..>S˗o /7mX?Pu@`5@$D#a&W*1"(ܠ lR`2 ý27`V&RW>L6wY !5 -wo0Lϐ dP.]?CWh@o H.@XC?A=4PŠj [kd*&&py`*#p ,PG4UٹR@)eEgd LQ,!00!,Ї\V۽s >yπR2"eXG`@ྺ~ /;/4W X=`sG 0u@ʏ?3<^ Xfp(> O|dWTby'`oA=x@yPCACTlR" Xe HPc} ,1, P+`x%P25>gda`xr `5e0JY޽w X%X@p H, ?'kǎC,0U B^ +) .WDĀ$#0ܻM@)!`z^Xp3rq0;{  ϓ4: @dϞ N>p)`MX2(`@#:PePfx)2@J\ @5Wn?5 Wfe0dd+@ׯya"gP[_/A챁zm4 Rh 'fxܲ!5+P]y P' ipqpK9  IQ~n "t1 0=$@0j6N@Aښ_a#g`mˠn<$,~0&o$MGxpTJ[Vß *:T0y lr 4 &$ 9Yի@Å%?%`9ȑ  ::6:(y<`)lc[  2R '/z;ÛN ! ?Fo~JF`_X0gyy"D:$uqAP C -@@6hd-\`]Ao1H 3Hc5] ,8fv~~`tIr')@u@Ց1z>6~l V h Vn nsNf`;pk>6`$Dw?/$ń%.x=pm: 81?) *a"`4&uP4CL O0@( "3dlɁʰ>0< 3gl x80x4sm[63|ˆUށA\Zߓat@dhb~9 Y#YpT.pe`/R73Xu=h՛>Fdd(S`cw 7Ndu{܁Ӡ* 4 e%%e + 8%o߽ Po߾5$$&HO/qM]#M?~߻}hXq5%2 9T6p P6 ĿcԸ@w1S P_e} t&xR`,'/\I))ИO݇21- nsk"cDn!Ν;c)]]1q1pK BCVg@;98h&xN=02=z8To_ee`Y <7_wРÖN= M^> rDN @ftBCB2A O*(0@[!hH)T7x&jj`\ ;X 5TZEz{lQ^)Ȁ/~e@;Dk`!@"&A )P: .,A,A Nkk+۶3W8qX}Zhq)p xZa3l<70`FC=2$" rAskR7n08~ -fW7n\bTꃚׯ_nh2 tKSKAMC\pSkȈ3 -5* @ݿ0_ wtM`<u@}Sg΀UUN<'<WZ@;8:VkP[jRv@ιg+P< X}To! un0 0KkP! Z<0 VAKg8(PV ӧN'AA=IP" M)PqxgacxrT@<p 3fO[bb* 8%gP*3<|I11q8޾{h;$@' rkXuݻA:(A@s_=h| >y TCJϞ=es1n`WZئMݽЁǎ{7Aj4j)o)((>Ah#xإeA4Ӡ={v JJd , W/|P#HK[̍O='N\jŅ}{(LR'y$E)XGA#B.:-ud-:Ќ}`xI tǎ =z eFɓ'^>t֊ˮ T}z 4`!Y@6=(iP:0 hT3>})/Pl?=oΝ6oxc l \48@d`W 4 .فMX>^^JQP2P!+=r܊ePYj޻wӊeˮ?ŋ1@J/Ha'k@Q_/@/e ^HfX'FAY…pPVѠ'cMڵޯ_`џiod R~`ggAS_٠70ف=}Up> NF*ϳg>7ws"'$#{y6 Dv  *@ oN('E@:h*0 znr;w}{u7ݻo !0#q rSS_f*(@ ہ|L/1Z# "{鿽{<شiӵcǎ= O’9lN=as~T8 EW  =z-}wƍנ389ll* J߿PU]/^>۷otk>}UYȥ901B ob@Q$~o_jժa؆y9#jȝz1A s޽{G765_t2a(= `734Hi,@kA6+hdh<8 6`tK ˟DQ `x A!((A1 $,o yb!Ɂ< 4zk 0`^\zicOn  MultiviewIENDB`goattracker-2.72/morphos/goat_tracker_commands.pdf.info0000644000000000000000000001620511604130742022114 0ustar rootrootPNG  IHDR@@iqgAMA|Q cHRMz%u0`:oIDATxb?H4h@,(bddH4:Fh8A+Q@% “LhI I${ȞA񨭭-= veeeUJ;۳O^ruGu _ !9|1<#+$$ãť! ;jRg/38 쬬 @j*ʖ޽y={#@Ar QXrX|}}”啅5偞Uza;P={n޺Š /7߿2|A  gϝ }D@rV RYD^iM Pz^I9 Vz slA F`K#/_11͛ ?}dcPRRbx 0;01Ã~=rypbxWTR:;Ѓ V @bf , T > #+O)AFJ X <}ϟ AHR H-YC i㾀GO޿pUiii ``|:XsAā%(k 0/`YOǏ2ܻwX&cx LiF|Bz۷my *\Xm@\  8x nfdzA XH 6Qapa0cJ?~|g+ .$A ;vbd;`9 |> q )3 cS3CGoJ l >222:f jF l /‘ \$(~=)0Kp Nuuup H >}8Ûo./|]}C`yY,HAyFDl?Hf50IZu_ft _`@\ kPI,|!p8v85}7`mT}` },(Z[Y=|pԩSϜ9\ "%`,?Wy_;0@yV׮ce`ec;YFS>}--e˗3((*0NfffeeW||j 0 l<Ep`ljꥪf "":oǎ0{X H`I0ft?=l<we``$%Ł=P 7N),`^z:W`/`P0e%bcr2Hݹ=F HM׬Ys7++Aʷ N~'yׯ ߁%$01lظAQQJQXX 5v ?gP9}mp9jP104A߿4 ` _<@$,s``L.\t8(vA"Ln RTsƠ>((1hkk ӿϟ ߁)TF2p= $ݾs,V0y+@ x:xG`q"5)p!*$%2P%mP`PP{T҃KZM `=e}6 ` &}POo_0f6[e70 1`aغu 8A*P!֮9V":FD 09p'`.HԸz <ú:P-8 .A]H7?`5Spg A F6..>S˗o /7mX?Pu@`5@$D#a&W*1"(ܠ lR`2 ý27`V&RW>L6wY !5 -wo0Lϐ dP.]?CWh@o H.@XC?A=4PŠj [kd*&&py`*#p ,PG4UٹR@)eEgd LQ,!00!,Ї\V۽s >yπR2"eXG`@ྺ~ /;/4W X=`sG 0u@ʏ?3<^ Xfp(> O|dWTby'`oA=x@yPCACTlR" Xe HPc} ,1, P+`x%P25>gda`xr `5e0JY޽w X%X@p H, ?'kǎC,0U B^ +) .WDĀ$#0ܻM@)!`z^Xp3rq0;{  ϓ4: @dϞ N>p)`MX2(`@#:PePfx)2@J\ @5Wn?5 Wfe0dd+@ׯya"gP[_/A챁zm4 Rh 'fxܲ!5+P]y P' ipqpK9  IQ~n "t1 0=$@0j6N@Aښ_a#g`mˠn<$,~0&o$MGxpTJ[Vß *:T0y lr 4 &$ 9Yի@Å%?%`9ȑ  ::6:(y<`)lc[  2R '/z;ÛN ! ?Fo~JF`_X0gyy"D:$uqAP C -@@6hd-\`]Ao1H 3Hc5] ,8fv~~`tIr')@u@Ց1z>6~l V h Vn nsNf`;pk>6`$Dw?/$ń%.x=pm: 81?) *a"`4&uP4CL O0@( "3dlɁʰ>0< 3gl x80x4sm[63|ˆUށA\Zߓat@dhb~9 Y#YpT.pe`/R73Xu=h՛>Fdd(S`cw 7Ndu{܁Ӡ* 4 e%%e + 8%o߽ Po߾5$$&HO/qM]#M?~߻}hXq5%2 9T6p P6 ĿcԸ@w1S P_e} t&xR`,'/\I))ИO݇21- nsk"cDn!Ν;c)]]1q1pK BCVg@;98h&xN=02=z8To_ee`Y <7_wРÖN= M^> rDN @ftBCB2A O*(0@[!hH)T7x&jj`\ ;X 5TZEz{lQ^)Ȁ/~e@;Dk`!@"&A )P: .,A,A Nkk+۶3W8qX}Zhq)p xZa3l<70`FC=2$" rAskR7n08~ -fW7n\bTꃚׯ_nh2 tKSKAMC\pSkȈ3 -5* @ݿ0_ wtM`<u@}Sg΀UUN<'<WZ@;8:VkP[jRv@ιg+P< X}To! un0 0KkP! Z<0 VAKg8(PV ӧN'AA=IP" M)PqxgacxrT@<p 3fO[bb* 8%gP*3<|I11q8޾{h;$@' rkXuݻA:(A@s_=h| >y TCJϞ=es1n`WZئMݽЁǎ{7Aj4j)o)((>Ah#xإeA4Ӡ={v JJd , W/|P#HK[̍O='N\jŅ}{(LR'y$E)XGA#B.:-ud-:Ќ}`xI tǎ =z eFɓ'^>t֊ˮ T}z 4`!Y@6=(iP:0 hT3>})/Pl?=oΝ6oxc l \48@d`W 4 .فMX>^^JQP2P!+=r܊ePYj޻wӊeˮ?ŋ1@J/Ha'k@Q_/@/e ^HfX'FAY…pPVѠ'cMڵޯ_`џiod R~`ggAS_٠70ف=}Up> NF*ϳg>7ws"'$#{y6 Dv  *@ oN('E@:h*0 znr;w}{u7ݻo !0#q rSS_f*(@ ہ|L/1Z# "{鿽{<شiӵcǎ= O’9lN=as~T8 EW  =z-}wƍנ389ll* J߿PU]/^>۷otk>}UYȥ901B ob@Q$~o_jժa؆y9#jȝz1A s޽{G765_t2a(= `734Hi,@kA6+hdh<8 6`tK ˟DQ `x A!((A1 $,o yb!Ɂ< 4zk 0`^\z!icOn`  Apdf:0IENDB`goattracker-2.72/morphos/goattracker.guide0000644000000000000000000023765211604130742017501 0ustar rootroot@database "" @author "ReadMe2Guide" @node Main "Main" GoatTracker v2.71 ----------------- Editor by Lasse rni (loorni\@gmail.com) HardSID 4U support by Tli Sndor. Uses reSID engine by Dag Lem. Uses reSID distortion / nonlinearity by Antti Lankila. Uses 6510 crossassembler from Exomizer2 beta by Magnus Lind. Uses the SDL library. GoatTracker icon by Antonio Vera. Command quick reference by Simon Bennett. Patches by Stefan A. Haubenthal, Valerio Cannone and Raine M. Ekman. Distributed under GNU General Public License (see the file COPYING for details) Covert BitOps homepage: http://covertbitops.c64.org GoatTracker 2 SourceForge.net page: http://sourceforge.net/projects/goattracker2 @endnode @node Tableofcontents "Table of contents" Table of contents ----------------- 1. General information 1.1 Warnings 1.2 Compatibility with v1.xx 2. Using GoatTracker 2.1 Command line options 2.2 Hardware support 2.3 Keyboard commands 2.3.1 General keys 2.3.2 Pattern edit mode 2.3.2.1 Protracker note-entry mode 2.3.2.2 DMC note-entry mode 2.3.3 Song edit mode 2.3.4 Instrument edit mode 2.3.5 Table edit mode 2.3.6 Songname edit mode 2.4 Mouse control 3. Song data 3.1 Orderlist data 3.2 Pattern data 3.3 Instrument data 3.4 Table data 3.4.1 Wavetable 3.4.2 Pulsetable 3.4.3 Filtertable 3.4.4 Speedtable 3.5 Playback details 3.6 Miscellaneous tips 3.6.1 Limit-based modulation steps 3.6.2 Precalculated note-independent "hifi player" portamento/vibrato 3.7 Multispeed tips 4. Using the included utilities 4.1 INS2SND2.EXE 4.2 SNGSPLI2.EXE 4.3 MOD2SNG.EXE 4.4 BETACONV.EXE 5. Using the songs outside the editor 5.1 Playroutine options 6. File/data formats description 6.1 GoatTracker v2 song (.SNG) format 6.1.1 Song header 6.1.2 Song orderlists 6.1.3 Instruments 6.1.4 Tables 6.1.5 Patterns header 6.1.6 Patterns 6.2 GoatTracker v2 instrument (.INS) format 6.3 Sound effect data format 7. Recompiling 8. Version history @endnode @node 1.Generalinformation "1. General information" 1. General information ---------------------- This program is a tracker-like C64 music editor running on Win32 or Linux platforms (using the SDL library, see http://www.libsdl.org) GoatTracker v2 adds more commands and uniform step programming tables for waveform/arpeggio, pulse effects, and filter effects. It is likely much more complex to learn & master than v1.xx. Familiarity with tracker programs in general, hexadecimal notation, and the C64's SID chip are required. Consult the C64 Programmer's Reference Guide (http://project64.c64.org) or AAY64 (http://www.the-dreams.de/aay.html) for SID chip reference. For filesize & library compatibility reasons, precompiled binaries exist only for Win32 platform. @endnode @node 1.1Warnings "1.1 Warnings" 1.1 Warnings ------------ 1. Always look at the end of this file for changes! Sometimes keyboard commands change etc. 2. Always save your songs in the .SNG-format with F11 key if you plan to continue editing! Packed & relocated songs (PRG/BIN/SID) can not be loaded back into the editor. 3. Even the reSID emulation is in some cases quite far from the output of a real SID. Especially if filters are in use, consider strongly testing your tune on a C64 or on a HardSID card. (Using filters has always been complicated because every SID tends to sound different.) 4. The editor will stop playing if: - The song restart position is illegal (beyond end of song) - The sequence of orderlist commands is incorrect * In a sequence of both TRANSPOSE & REPEAT, TRANSPOSE must come first * The last thing before a RST-endmark should be a pattern number - Gateoff timer value is too high compared to song tempo. - The song tries to jump directly onto a table row containing a jump (FF xx), either with instrument pointers or 8XY, 9XY, AXY commands. - The song tries to execute pattern commands 0XY, 8XY or EXY from the wavetable. These all are error conditions, and trying to pack/relocate such song should give an error message. 5. Using delayed wavetable or no wavechange (0x 00, where x is 0-F) in the first step of instrument wavetable is unsupported and may result in missing notes. 6. When using a playroutine with unbuffered SID-writes (Standard /w unbuffered or Minimal) and encountering ADSR-bugs after packing/relocating, you can try either: 1) Set pulse-startpos to nonzero value in the troublesome instruments and change the 1stFrame Wave parameter of some instrument slightly, for example from $09 to $0B, to disable a playroutine optimization. The idea in this is to make the noteinit routine take more CPU cycles. 2) Use a playroutine with buffered writes to pack/relocate. 3) Try hardrestart attack parameter $F for alternative SID register write order. 7. From v2.18 onwards, wavetable left side values have changed. Delay can now be maximum 16 frames (values $00-$0F), and waveform register values $00-$0F (inaudible) have been mapped to table values $E0-$EF. For example, testbit + gate would be $E9. You need to manually convert values $08-$0F from your old songs! 8. From v2.2 onwards, a new table (speedtable) has been added. The portamento, vibrato and funktempo commands use it. Old songs will be converted upon loading to use the speedtable. Note the keyboard command SHIFT+RETURN to convert the old style parameters. 9. From v2.4 onwards, pulse modulation speed has 1 bit added accuracy, so you need to double pulsespeeds when composing new songs. Old songs will be converted automatically. 10. From v2.59 onwards, gateoff timer parameter high bit disables hardrestart and bit $40 disables gateoff. Old songs & instruments will be converted automatically. 11. From v2.62 onwards, realtime calculated portamento/vibrato speeds are supported. This is activated by having the high bit ($80) set in the speed- table left side. Naturally, this means that very high portamento speeds (>= $8000) or vibrato speeds (>= $80) become unavailable, but these should not be very useful anyway. 12. From v2.68 onwards, SID write order has been tweaked for better stability regarding badlines. This has the consequence, however, that notes with attack 0 & release 1 may ADSR-bug. In this case, try hardrestart attack parameter $F for alternative SID register write order. @endnode @node 1.2Compatibilitywithv1.xx "1.2 Compatibility with v1.xx" 1.2 Compatibility with v1.xx ---------------------------- GoatTracker v2 can load v1.xx songs and instruments, but it saves only in v2 format. Some subtleties (like tricks involving instrument changes) will not play back exactly like in v1.xx. The only major feature removal is that of the arpeggio command in v2. Everything that this command does can also be done with wavetables, and the import feature converts all arpeggio commands to corresponding wavetable programs. @endnode @node 2.UsingGoatTracker "2. Using GoatTracker" 2. Using GoatTracker -------------------- @endnode @node 2.1Commandlineoptions "2.1 Command line options" 2.1 Command line options ------------------------ Start Goattracker V2 by typing GOATTRK2 in the command prompt, followed by the songname to be loaded at startup (optional) and any command line options you may want. For example "goattrk2 dojo.sng -s1 -e1" to set 1x-speed mode and SID model 8580 and to load "dojo.sng" on startup. -Axx Set hard restart ADSR parameter in hex. DEFAULT=0F00 -Bxx Set sound buffer length in milliseconds DEFAULT=100 -Cxx Use CatWeasel MK3 PCI SID (0 = off, 1 = on) -Dxx Pattern row display (0 = decimal, 1 = hexadecimal) -Exx Set emulated SID model (0 = 6581 1 = 8580) DEFAULT=6581 -Fxx Set custom SID clock cycles per second (0 = use PAL/NTSC default) -Gxx Set pitch of A-4 in Hz (0 = use default frequencytable, close to 440Hz) -Hxx Use HardSID (0 = off, 1 = HardSID ID0 2 = HardSID ID1 etc.) -Ixx Set reSID interpolation (0 = off, 1 = on, 2 = distortion, 3 = distortion & on) DEFAULT=off -Kxx Note-entry mode (0 = PROTRACKER 1 = DMC) DEFAULT=PROTRK. -Lxx SID memory location in hex. DEFAULT=D400 -Mxx Set sound mixing rate DEFAULT=44100 -Oxx Set pulse optimization/skipping (0 = off, 1 = on) DEFAULT=on -Rxx Set realtime command optimization/skipping (0 = off, 1 = on) DEFAULT=on -Sxx Set speed multiplier (0 for 25Hz, 1 for 1x, 2 for 2x etc.) -Txx Set HardSID interactive mode sound buffer length in milliseconds DEFAULT=20, max.buffering=0 -Uxx Set HardSID playback mode sound buffer length in milliseconds DEFAULT=400, max.buffering=0 -Vxx Set finevibrato conversion (0 = off, 1 = on) DEFAULT=on -Xxx Set window type (0 = window, 1 = fullscreen) DEFAULT=window -Zxx Set random reSID write delay in cycles (0 = off) DEFAULT=off -N Use NTSC timing -P Use PAL timing (DEFAULT) -W Write emulated sound output to a file SIDAUDIO.RAW -? Show command line options -?? Standalone online help window Try the command line options if there are any problems. For example, if you experience choppy audio you can increase audio buffering with -B option. SDL seems to have trouble with some soundcards under Windows; you might want to try even a 500ms buffer, or tweak the hardware acceleration level of the soundcard (from Control Panel). Also, reSID interpolation will take remarkably more CPU time and could cause the sound and/or editing to get choppy. Finevibrato mode is on by default. You can change this behaviour with -V option. Note that finevibrato mode only affects the conversion of old style vibrato parameters to speedtable format. Pulse optimization -O determines if pulsetable execution will be skipped when getting new notes or a new pattern. By default it is on. Be warned that turning it off will increase the rastertime requirements of packed/relocated songs greatly! Realtime command optimization -R determines if portamento, vibrato & instrument vibrato will be skipped on tick 0 of each pattern row. By default it is on, as this is how tracker programs have operated traditionally. Turning it off makes the commands sound same regardless of tempo but will increase rastertime use. The hard restart ADSR parameter will especially affect how rapid passages of notes will sound like. 0000 is probably too hard to be useful, except perhaps with gateoff timer value 1. 0F00 (default) is a lot softer, and 0F01 adds also a little bit of release to the gateoff phase for even softer sound. 000F makes the note start very pronounced. Hard restart parameter with attack at maximum (F) enables the use of an alternative playroutine, where waveform is written before ADSR. This can give more reliable note triggering, especially for very fast releases 0 & 1, but may change the characteristics of the note's decay & release. @endnode @node 2.2Hardwaresupport "2.2 Hardware support" 2.2 Hardware support -------------------- HardSID support is available with the /H option (use first HardSID = -H1, second = -H2 etc., return to emulated output = -H0). You must have the HardSID drivers installed to use this feature. CatWeasel MK3 PCI SID support is available with -C option (-C1 to turn on). To use the PC64 cable, you need Daniel Illgen's HardSID-DLL-Clone. Available at http://dawork.synchronus.de/ To enable better support of multispeeds and cycle-exact timing on HardSID (currently Win32 only), download an enhanced HardSID.dll: For HardSID ISA/PCI cards - http://sourceforge.net/project/showfiles.php?group_id=9266&release_id=61843 For HardSID 4U - http://www.hardsid.com Cycle-exact HardSID buffer length is separately configurable for interactive mode (-T option) & playback mode (-U option). HardSID interactive mode: Low latency mode for jamming and accurate GUI display. Interactive mode can be activated during song/pattern playback by enabling jamming (space key). HardSID playback mode: High stability mode to avoid interruptions caused by other applications/poor drivers/weaker CPU. GUI display is less accurate in this mode. Set the -U parameter to zero to achieve the maximum stability (less accurate GUI). @endnode @node 2.3Keyboardcommands "2.3 Keyboard commands" 2.3 Keyboard commands --------------------- This program is mainly operated on keyboard. For a list of keyboard commands press F12 (online help) in the tracker or see the table below: NOTE: SHIFT & CTRL are interchangeable in the commands. You can also use [ ] or ( ) instead of < >. @endnode @node 2.3.1Generalkeys "2.3.1 General keys" 2.3.1 General keys ------------------ F1 Play from beginning F2 Play from current pos. F3 Play one pattern from current pos. F4 Stop playing & silence all sounds F5 Go to pattern editor F6 Go to song editor F7 Go to instrument/table editor F8 Go to songname editor F9 Pack, relocate & save PRG,SID etc. F10 Load song (Pattern/Song/Songname mode) or instrument (Instrument mode) F11 Save song (Pattern/Song/Songname mode) or instrument (Instrument mode) F12 Online help screen. Press F12 again to toggle context mode SHIFT+F1 Play from beginning /w follow play SHIFT+F2 Play from current pos. /w follow play SHIFT+F3 Play one pattern from current pos. /w follow play SHIFT+F4 Mute current channel SHIFT+F5 Decrease speed multiplier SHIFT+F6 Increase speed multiplier SHIFT+F7 Edit hardrestart ADSR parameter SHIFT+F8 Switch between 6581 and 8580 SID models SHIFT+,. Move song startposition on all channels and restart last playmode TAB Cycle between editing modes (forwards) SHIFT+TAB Cycle between editing modes (backwards) INS Insert row (Press INS/DEL on endmark to change pattern/song length) DEL Delete row SHIFT+ESC Optimize musicdata, or clear musicdata & set default pattern length ESC Exit program @endnode @node 2.3.2Patterneditmode "2.3.2 Pattern edit mode" 2.3.2 Pattern edit mode ----------------------- - + Select instrument / * Select octave < > Select pattern BACKQUOTE Select channel 0-9 & A-F Enter parameters SPACE Switch between jam/editmode RETURN (also CAPSLOCK) Insert keyoff Enter table (when cursor is over a table-utilizing command) Enter instrument (when cursor is over a nonzero instrument number) SHIFT+RET. Insert keyon Convert portamento/vibrato/funktempo old style parameter to a speedtable entry (when cursor is over the command) Go into an empty table entry (when parameter is zero on a table-utilizing command) BACKSPACE Insert rest SHIFT+BKSP. Insert rest and clear commands SHIFT+SPACE Play from cursor position SHIFT+Q Transpose halfstep up SHIFT+A Transpose halfstep down SHIFT+W Transpose octave up SHIFT+S Transpose octave down SHIFT+O Shrink pattern (divide size by 2) SHIFT+P Expand pattern (multiply size by 2) SHIFT+J Join pattern with next pattern in orderlist SHIFT+K Split pattern from edit position SHIFT+H Calculate "hifi" left/right shifted speedtable entry for portamento or vibrato SHIFT+I Invert selection / whole pattern if no selection SHIFT+CRSR UP,DOWN Mark pattern SHIFT+CRSR LEFT,RIGHT Select pattern SHIFT+L Mark/unmark entire pattern SHIFT+M,N Choose highlighting step size SHIFT+X,C,V Cut,copy,paste pattern SHIFT+E,R Copy,paste commands SHIFT+Z Cycle autoadvance-mode For pattern joining to work properly, select the pattern you want to join with the next from the orderlist first (by pressing RETURN on it). Both joining and splitting will rearrange pattern numbers (for example if you split pattern 00, pattern 01 will be created and old patterns 01-xx will be shifted forward in the pattern order) SHIFT+SPACE will play from the pattern onwards if playback was previously stopped, but if it is pressed while in pattern play mode, it will stay in the current pattern. There are 2 modes for note entering: @endnode @node 2.3.2.1Protrackernote-entrymode "2.3.2.1 Protracker note-entry mode" 2.3.2.1 Protracker note-entry mode ---------------------------------- This is the default or activated with command line option /K0. There are two rows of a piano keyboard: Lower octave Higher octave S D G H K L 2 3 5 6 7 9 0 Z X CV B NM , . Q W ER T Y UI O P Octave (0-7) is selected with / and * keys on the numeric keypad. In this mode there are 2 different autoadvance-modes (the mode can be seen from the color of the jam/editmode indicator) GREEN - Advance when entering notes & command-databytes RED - Do not advance automatically @endnode @node 2.3.2.2DMCnote-entrymode "2.3.2.2 DMC note-entry mode" 2.3.2.2 DMC note-entry mode --------------------------- Activated with command line option /K1, there is one row of piano keyboard W E T Y U O P A S DF G H JK L and octave of a note (sets default octave at the same time) is changed with number keys 0-7. In this mode there are 3 different autoadvance-modes: GREEN - Advance when entering notes, octaves or command-databytes YELLOW - Advance when entering notes or command-databytes, not octaves RED - Do not advance automatically @endnode @node 2.3.3Songeditmode "2.3.3 Song edit mode" 2.3.3 Song edit mode -------------------- < > Select subtune - + Insert Transpose down/up command (shown as -/+ in the orderlist) 0-9 & A-F Enter pattern numbers SPACE Set start position for F2 key BACKSPACE Set end position for F2 key RETURN Go to pattern SHIFT+R Insert Repeat command (shown as "R" in the order-list) SHIFT+CRSR LEFT/RIGHT Mark orderlist SHIFT+1,2,3 Swap current channel orderlist with channel 1,2,3 SHIFT+X,C,V Cut,copy,paste channel orderlist SHIFT+L Mark/unmark entire orderlist SHIFT+SPACE Set start position on all channels SHIFT+RET. Go to pattern on all channels SHIFT+SPACE or SHIFT+BACKSPACE set the start/end mark on all channels to the same position. To clear the endmark, press BACKSPACE again on it or at/before the startmark. @endnode @node 2.3.4Instrumenteditmode "2.3.4 Instrument edit mode" 2.3.4 Instrument edit mode -------------------------- < > Select instrument - + Select instrument / * Select octave F7 Go to table editor 0-9 & A-F Enter parameters SPACE Play test note SHIFT+SPACE Silence test note RETURN Go to table position indicated by wave/pulse/filter/vibratopos. SHIFT+N Edit instrument name SHIFT+S Smart paste an instrument SHIFT+U Unlock/lock table scrolling SHIFT+X,C,V Cut,copy,paste instrument SHIFT+DEL (also SHIFT+BACKSPACE) Delete instrument & tabledata SHIFT+RET. Set tablepointer to empty position or convert old style vibrato parameter The test note will be played on the channel you last were on in the pattern editor. To hear filtering as intended, be sure to play it on a channel that has been selected for filtering in the filter parameters. Note that cut,copy,paste instrument do not touch the tabledata, just for the case you need it in another instrument. If you want to completely get rid of an instrument + its associated tabledata, press SHIFT+DEL. If wave/pulse/filter/vibrato param. is zero and you press RETURN over it, you will move to the first free location in the corresponding table. If you press SHIFT+RETURN, also the instrument parameter will be set accordingly. If vibrato parameter is nonzero and you press SHIFT+RETURN over it, it will be interpreted as an old style vibrato parameter (left nybble speed, right nybble depth) and converted to a speedtable entry. "Smart paste" will convert instrument numbers in all patterns if you "move" an instrument by cut/pasting it. @endnode @node 2.3.5Tableeditmode "2.3.5 Table edit mode" 2.3.5 Table edit mode --------------------- < > Select instrument - + Select instrument / * Select octave BACKQUOTE Select table F7 Go to instrument editor 0-9 & A-F Enter parameters SPACE Play test note SHIFT+SPACE Silence test note RETURN Go back to wave/pulse/filterpos. parameter SHIFT+Q,A Transpose speedtable portamento speed halfstep up/down SHIFT+W,S Transpose speedtable portamento speed octave up/down, or multiply/divide pulse/filterspeed by 2 SHIFT+L Convert modulation step to SHIFT+N Negate speed parameter (pulse/filtertable) or relative note (wavetable) SHIFT+O Optimize current table (remove unused entries) SHIFT+R Convert note between absolute/relative in wavetable SHIFT+U Unlock/lock table scrolling If you need to insert rows in the beginning of an instrument's wave/pulse/ filtertable, press SHIFT+INS instead of just INS: this way table pointers pointing to the table first row will not move. For easier programming of negative modulation speeds in pulse/filtertables, you can first enter a positive speed positive value ($00-$7F) and then press SHIFT+N to negate it. Conversion between relative and absolute notes will use the basenote C-0 if octave is 0, C-1 if octave is 1 and so on. When table scrolling is unlocked, each table maintains its separate view position. To indicate this mode, a "U" letter is visible in the bottom right part of the screen. By default table scrolling is locked. @endnode @node 2.3.6Songnameeditmode "2.3.6 Songname edit mode" 2.3.6 Songname edit mode ------------------------ Use cursor UP/DOWN to move between song, author & copyright strings, and other keys to edit them. @endnode @node 2.4Mousecontrol "2.4 Mouse control" 2.4 Mouse control ----------------- By clicking with the left mouse button, you can select the data to edit. By dragging with middle or right mouse button, you can mark orderlist/pattern/ tabledata. Some values like octave or subtune/pattern numbers can be incremented with the left mouse button and decremented with the right. By holding the middle/right mouse button in the status bar, a menu becomes active. Continue to hold and click with left button to select options. In the fileselector, confirm loading or entering a directory by double- clicking. Doubleclick outside the selector to cancel. @endnode @node 3.Songdata "3. Song data" 3. Song data ------------ @endnode @node 3.1Orderlistdata "3.1 Orderlist data" 3.1 Orderlist data ------------------ A song can consist of up to 32 subtunes. For each subtune's each channel, there is an orderlist which determines in what order patterns are to be played. In addition to pattern numbers, there can be TRANSPOSE & REPEAT commands and finally there is a RST (RESTART) endmark followed by restart position. The maximum length of an orderlist is 254 pattern numbers/commands + the endmark. TRANSPOSE is measured in halftones. Transpose up (shown as +X) can be 0-14 halftones and transpose down (shown as -X) can be 1-15. Transpose is automatically reset only when starting the song, not when looping. A REPEAT command (shown as RX) will repeat the pattern following it 1-16 times. "Repeat 16 times" is displayed as R0. There are some rules for orderlist command order: - If there are both TRANSPOSE and REPEAT commands before a pattern number, TRANSPOSE must come first. - The last thing before the RST-endmark must be a pattern number. If you need to reset transpose on song repeat, do it in the beginning of the repeat loop. In case of wrong order, the editor will halt playback. This tells that the resulting packed/relocated song would play incorrectly. @endnode @node 3.2Patterndata "3.2 Pattern data" 3.2 Pattern data ---------------- Patterns are single-channel only for flexibility & low memory use. They contain the actual notes, instrument changes & sound commands. A pattern can have variable length, up to 128 rows. There can be 208 different patterns in a song. The explanation of a pattern row: Note name | | Octave | | | | Instrument number ($01 - $3F, or $00 for no change) | | | | | | Command ($0 - $F) | | | | | | | | Databyte | | | | | C-1 00 0 00 The highest note available in a pattern is G#7. To reach the top three notes (A-7 to B-7), you can use transpose. In place of a normal note, there can also be one of these special "notes": ... Rest --- Key off (clear gatebit mask) +++ Key on (set gatebit mask) The actual state of the gatebit will be the gatebit mask ANDed with data from the wavetable. A key on cannot set the gatebit if it was explicitly cleared at the wavetable. Commands 1XY-4XY and FXY bear some resemblance to Soundtracker/Protracker/ Fasttracker effect commands. However, they are different in some ways, so read their descriptions! Note that there is no "databyte $00 uses the last databyte"-action in the commands. Command 0XY: Do nothing. Databyte will always be $00. Command 1XY: Portamento up. XY is an index to a 16-bit speed value in the speedtable. Command 2XY: Portamento down. XY is an index to a 16-bit speed value in the speedtable. Command 3XY: Toneportamento. Raise or lower pitch until target note has been reached. XY is an index to a 16-bit speed value in the speedtable, or $00 for "tie-note" effect (move pitch instantly to target note) Command 4XY: Vibrato. XY is an index to the speed table, where left side determines how long until the direction changes (speed) and right side determines the amount of pitch change on each tick (depth). Command 5XY: Set attack/decay register to value XY. Command 6XY: Set sustain/release register to value XY. Command 7XY: Set waveform register to value XY. If a wavetable is actively changing the channel's waveform at the same time, will be ineffective. Command 8XY: Set wavetable pointer. $00 stops wavetable execution. Command 9XY: Set pulsetable pointer. $00 stops pulsetable execution. Command AXY: Set filtertable pointer. $00 stops filtertable execution. Command BXY: Set filter control. X is resonance and Y is channel bitmask. $00 turns filter off and also stops filtertable execution. Command CXY: Set filter cutoff to XY. Can be ineffective if the filtertable is active and also changing the cutoff. Command DXY: Set mastervolume to Y, if X is $0. If X is not $0, value XY is copied to the timing mark location, which is playeraddress+$3F. Command EXY: Funktempo. XY is an index to the speedtable, tempo will alternate between left side value and right side value on subsequent pattern steps. Sets the funktempo active on all channels, but you can use the next command to override this per-channel. Command FXY: Set tempo. Values $03-$7F set tempo on all channels, values $83- $FF only on current channel (subtract $80 to get actual tempo). Tempos $00-$01 recall the funktempo values set by EXY command. Master volume is by default the maximum ($F), but it is only reset when loading a new song or clearing songdata in the editor, not every time playback starts. If you change mastervolume, you have to reset it manually in the beginning of your song. If the command is not 1XY-4XY, instrument vibrato will be active. Note that the one-shot commands 5XY-FXY allow the previous 1XY-4XY command or instrument vibrato to continue "underneath" them. In section 3.6 (hints & tips) there is an example of this. @endnode @node 3.3Instrumentdata "3.3 Instrument data" 3.3 Instrument data ------------------- You can use up to 63 different instruments in a song. Each instrument is defined by 9 parameters: Attack/Decay $0 is fastest attack or decay, $F is slowest Sustain/Release Sustain level $0 is silent and $F is the loudest. Release behaves like Attack & Decay (F slowest). Wavetable Pos Wavetable startposition. Value $00 stops the wavetable execution and is not very useful. Pulsetable Pos Pulsetable startposition. Value $00 will leave pulse execution untouched. Filtertable Pos Filtertable startposition. Value $00 will leave filter execution untouched. In most cases it makes sense to have a filter-controlling instrument only on one channel at a time. Vibrato Param Instrument vibrato parameter. An index to the speedtable, see command 4XY. Vibrato Delay How many ticks until instrument vibrato starts. Value $00 turns instrument vibrato off. HR/Gate Timer How many ticks before note start note fetch, gateoff and hard restart happen. Can be at most tempo-1. So on tempo 4 highest acceptable value is 3. Bitvalue $80 disables hard restart and bitvalue $40 disables gateoff. 1stFrame Wave Waveform used on init frame of the note, usually $09 (gate + testbit). Values $00, $FE and $FF have special meaning: leave waveform unchanged and additionally set gate off ($FE), gate on ($FF), or gate unchanged ($00). In case of illegal (too high) gateoff timer values, the song playback is stopped. ADSR settings are crucial to getting any sound at all. If all of them are zero just a very short "click" will be heard. Here is a diagram to help you visualize the Attack, Decay, Sustain & Release phases: V /\ |<- gatebit reset (key-off) at this point O / \ | L / \__________| U / |\ M / | \ E / | \ TIME ----------------------------> A D S R Some ADSR examples: A/D 09 Will produce a sound that starts from full volume right away and fades S/R 00 to silence automatically. By increasing the Decay value, the fade will last longer. A/D 00 A sound that goes very fast from full volume to sustain level 8. S/R 8A If you increase the Decay value, it will go to the sustain level slower. After key-off, starts fading out with speed A. A/D CC A sound that rises slowly to maximum volume, then decays slowly to the S/R AF sustain level A and after key-off, fades out to silence very slowly. Instrument legato works as following: When HR/Gate Timer parameter has bit $40 set, no hard restart or gateoff will be performed. When 1st Frame Wave is also $00, no 1st frame waveform will be set and gate flag is untouched. However wave/ pulse/filterpointers and ADSR are initialized normally. You can also use this in conjunction with command 8XY to set another wavetable pointer for the note. @endnode @node 3.4Tabledata "3.4 Table data" 3.4 Table data -------------- Tables control the execution of instruments' waveform/arpeggio changes, pulse modulation, and filter modulation. All the tables are controlled by the left side bytes, while the right side byte specifies additional parameters. Note that you should never jump directly onto a table jump command (FF) either with instrument parameters or pattern commands 8XY, 9XY, AXY. Otherwise, results are undefined. @endnode @node 3.4.1Wavetable "3.4.1 Wavetable" 3.4.1 Wavetable --------------- Wavetable left side: 00 Leave waveform unchanged 01-0F Delay this step by 1-15 frames 10-DF Waveform values E0-EF Inaudible waveform values $00-$0F F0-FE Execute command 0XY-EXY. Right side is parameter. FF Jump. Right side tells position ($00 = stop) Wavetable right side: 00-5F Relative notes 60-7F Negative relative notes (lower pitch) 80 Keep frequency unchanged 81-DF Absolute notes C#0 - B-7 Short explanation of waveform bitvalues: 01 = Gatebit. When on, initiates attack/decay/sustain phase. When off, initiates the release phase. 02 = Synchronize. Creates weird effects using output of another channel 04 = Ring modulation. Creates weird effects using output of another channel. Most effective with the triangle waveform. 08 = Testbit. Silences sound and resets the oscillator. 10 = Triangle waveform. 20 = Sawtooth waveform. 40 = Pulse waveform. 80 = Noise waveform. All waveforms except noise can be combined (for example triangle+pulse), but the effect will be different on 6581 and 8580 SID chips, so use caution. The way how the channels work with synchronize/ringmod: - When used on channel 1, channel 3's output modulates the sound. - When used on channel 2, channel 1's output modulates the sound. - When used on channel 3, channel 2's output modulates the sound. Wavetable delay or no wavechange should not be used in the first step of instrument wavetable. Otherwise, missing notes may be caused. On the other hand, if you use 8XY command to jump into a wavetable program, those are allowed. Using wavetable delay or a wavetable step with no frequency change allows realtime commands & instrument vibrato to be executed together with wave- table. Be warned that this has the potential for large rastertime usage! You can execute pattern commands from the wavetable. Right side is the command parameter. Note that commands 0XY (do nothing), 8XY (set wavetable pointer) and EXY (funktempo) are illegal and should not be used. When executing a command, no wave/note will be changed on the same frame. Some examples of wave tables (all examples start on table step 1) 01: 21 00 Sawtooth waveform on note's original pitch. 02: FF 00 01: 41 00 A flute sound with pulse on the first tick and triangle on all 02: 11 00 the rest. 03: FF 00 01: 41 01 A "koto" sound that is one halfstep higher on the first tick and 02: 40 00 on original pitch the next. Gatebit is also cleared on the second 03: FF 00 tick. 01: 81 D0 A snaredrum sound, using all absolute notes so it does not depend 02: 41 AA on which note it's played. Use pulsewidth 800 for best result. 03: 41 A4 04: 80 D4 05: 80 D1 06: FF 00 01: 81 DF A pulse sound on original pitch, preceded with a short noise (like 02: 41 00 a hi-hat or something) that has always an absolute pitch of B-7. 03: FF 00 01: 41 00 A 4-note looping arpeggio sound with pulse waveform. Note that 02: 00 04 waveform does not change in the looping part. 03: 00 07 04: 00 0C 05: 00 00 06: FF 02 01: 21 00 A delayed minor chord arpeggio with sawtooth waveform. Each step 02: 02 03 takes 3 ticks. 03: 02 07 04: 02 00 05: FF 02 01: 41 00 Use pulse first, but then switch between pulse & triangle every 5 02: 03 80 ticks while frequency remains unchanged (allowing for vibrato & 03: 11 80 slides). 04: 03 80 05: 41 80 06: FF 02 01: 81 CF Short noise in the beginning, sawtooth, after a short delay change 02: 21 00 sustain/release (via pattern command 6XY) to $2A. 03: 08 00 04: F6 2A 05: FF 00 @endnode @node 3.4.2Pulsetable "3.4.2 Pulsetable" 3.4.2 Pulsetable ---------------- Pulsetable left side: 01-7F Pulse modulation step. Left side indicates time and right side the speed (signed 8-bit value). 8X-FX Set pulse width. X is the high 4 bits, right side tells the 8 low bits. FF Jump. Right side tells position ($00 = stop) Some examples of pulse tables (all examples start on table step 1) 01: 88 00 Set pulse value $800 (middle) 02: FF 00 Stop pulse execution 01: 80 10 Set pulse value $010 (very thin) 02: 20 40 For 32 ticks, increase pulse with speed $0040 (64) 03: 40 E0 For 64 ticks, decrease pulse with speed $FFE0 (-32) 04: 40 20 For 64 ticks, increase pulse with speed $0020 (32) 05: FF 03 Jump back to step 03 for a nice loop @endnode @node 3.4.3Filtertable "3.4.3 Filtertable" 3.4.3 Filtertable ----------------- Filtertable left side: 00 Set cutoff, indicated by right side 01-7F Filter modulation step. Left side indicates time and right side the speed (signed 8-bit value) 80-F0 Set filter parameters. Left side high nybble tells the passband ($90 = lowpass, $A0 = bandpass etc.) and right side tells resonance/channel bitmask, as in command BXY. FF Jump. Right side tells position ($00 = stop) If "Set filter parameters" is followed by "Set cutoff" directly below, both will be executed on the same frame. Some examples of filter tables (all examples start on table step 1) 01: 90 F1 Set lowpass, resonance F, channel bitmask 1 (filter channel 1 only) 02: 00 40 Set cutoff to $40 03: FF 00 Stop filter execution 01: 80 00 No passband selected, resonance 0, bitmask 0 (no filtered channels) 02: FF 00 Stop filter execution 01: A0 87 Set bandpass, resonance 8, channel bitmask 7 (filter all channels) 02: 00 00 Set cutoff to $00 03: 7F 01 Increase cutoff with speed $01 for 127 ticks 04: 7F 01 Continue cutoff increase 05: 7F FF Then decrease back to starting position (speed $FF = -1)... 06: 7F FF 07: FF 03 ...and loop back to step 03 01: C0 F2 Set highpass, resonance F, channel bitmask 2 (filter channel 2) 02: 00 F0 Set cutoff to $F0 03: 90 F2 On the next frame, change to lowpass... 04: 00 50 ...and set cutoff $50 05: FF 00 Stop filter execution Note that the second example could also be achieved simply with pattern command B00 (set filter control, and stop filter execution, because parameter was $00) @endnode @node 3.4.4Speedtable "3.4.4 Speedtable" 3.4.4 Speedtable ---------------- The speedtable is shared by vibrato, portamento and funktempo. No jump commands exist. For vibrato: XX YY Left side tells how long until vibrato direction changes (speed), right side is the value added to pitch each tick (depth). For portamento: XX YY A 16-bit value added to pitch each tick. Left side is the MSB and the right side the LSB. For funktempo: XX YY Two 8-bit tempo values that are alternated on each pattern row, starting from the left side. For both vibrato and portamento, if XX has the high bit ($80) set, note independent vibrato depth / portamento speed calculation is enabled, and YY specifies the divisor (higher value -> lower result and more rastertime taken). Vibrato examples: 01: 03 40 Vibrato with speed $03 and depth $40. Corresponds to old vibrato parameter $34 01: 05 04 Speed $05 and depth $04. Slow shallow vibrato, suitable for bass notes. Not possible to achieve with old parameters. 01: 83 04 Speed $03, note-independent depth enabled, depth divisor 4 right- shifts (division by 16). Portamento examples: 01: 00 20 Portamento with speed $0020, corresponds to old parameter $08 (4 * $08 = $0020). 01: 01 00 Portamento with speed $0100, corresponds to old parameter $40 (4 * $40 = $0100). 01: 4F FF Portamento with speed $4fff, loops the pitch highbyte very fast so that a SEUCK-like "space" effect is heard. Not possible to achieve with old parameters. 01: 80 01 Note-independent speed enabled, speed divisor 1 rightshift (division by 2). Funktempo examples: 01: 09 06 Play tempo $09 on even pattern steps and $06 on odd steps, corresponds to old parameter $96. 01: 24 18 The same funktempo adjusted for 4x-multispeed. Not possible to achieve with old parameters. Note that you can enter old style vibrato parameters, portamento speeds and funktempo to patterns & instruments, and when cursor is over the parameter, press SHIFT+RETURN to create a new speedtable entry corresponding to that parameter. The parameter will now be overwritten by a speedtable pointer. @endnode @node 3.5Playbackdetails "3.5 Playback details" 3.5 Playback details -------------------- Each pattern row is divided into as many 50Hz/60Hz "ticks" as the tempo indicates. Some ticks are reserved for special actions, and to conserve raster- time, certain realtime effects/commands (pulse, vibrato, portamento) are skipped at the same time. Let's assume a tempo of 6 and gateoff timer value 2 and look at what happens on each tick: Tick Actions 0 - Initialization of new notes (no audible sound yet) - Orderlist advance if necessary - Pulsetable execution only if no orderlist advance - Wavetable execution - "One-shot" commands 5XY-FXY 1 - New notes become audible - Pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY 2,3 - Pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY 4 - New notes fetched from the pattern - Gateoff and hard restart for new notes (2 ticks before first frame, as gateoff timer indicates) - No pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY 5 - Pulsetable execution - Wavetable or realtime pattern commands 1XY-4XY Filtertable is executed on each tick regardless of what the channels are doing. Wavetable is never skipped, so arpeggios/drumsounds should always play OK. With the commandline parameter /O0 (or by clicking the "PO" text on the status bar) you can disable pulse skipping. This leads to increased rastertime use but can be good for example with tempo 3 tunes. Likewise, with the commandline parameter /R0 (or by clicking the "RO" text on the status bar) you can disable realtime pattern command skipping on tick 0. @endnode @node 3.6Miscellaneoustips "3.6 Miscellaneous tips" 3.6 Miscellaneous tips ---------------------- - Patterns will take less memory the less there are command changes. When the song is packed/relocated, for example a long vibrato or portamento command needs to be stored only once as long as the parameter stays the same on subsequent pattern rows. - Using instrument vibrato can make 4XY commands unnecessary and save even more memory. Use realtime calculated note-independent speed (see speedtable section) if you want the vibrato to have the same magnitude regardless of the note. - In the instrument parameters, there is no option to stop pulse execution directly. So if you have for example a sawtooth instrument, there might be an "unnecessary" pulsemodulation going on underneath and wasting rastertime. There are two ways you can stop this: 1) Make a short pulseprogram like this and use it in the instrument: 01: 80 00 Set pulse $000 02: FF 00 Stop pulse execution 2) Use pattern command 900 to stop pulse execution - If you have a realtime command (vibrato/portamento), you can put "one-shot" commands 5XY-FXY inbetween and the realtime command will be unaffected. An example: C-4 01000 --- 00401 Begin vibrato with speedtable index $01 --- 00401 --- 00401 --- 0065A Set sustain/release to $5A. Vibrato executes also on this step! --- 00401 Continue vibrato normally --- 00401 However, the vibrato would stop immediately if command 0 was encountered. - Normally tempo 3 is the fastest you can use. However, by using the funktempo command you can get tempo 2. To do this, create a following speedtable entry: 02 02, and point your funktempo command to it. You also need to use gateoff timer 1 in all instruments and disable the pulse-optimization skipping. - For very optimized songdata & player you can refrain from using any pattern commands and rely on the instruments' step-programming. Even in this case, you can set song startup default tempo with the Attack/Decay parameter of the last instrument (63), if you otherwise leave this instrument unused. @endnode @node 3.6.1Limit-basedmodulationsteps "3.6.1 Limit-based modulation steps" 3.6.1 Limit-based modulation steps ---------------------------------- You can enter pulse/filter modulation steps in limit-based format, and convert them to time-based with SHIFT+L. For example, you could enter the following in the pulsetable: 01: 84 00 Set initial pulse to $400 02: C0 10 Modulate pulse to $C00 with speed $0010 03: 40 10 Modulate pulse back to $400 with speed $0010 Now position the cursor on step 02 and press SHIFT+L twice, to convert both of the modulation steps to usual time-based steps. If necessary, the steps will be expanded to several (if the resulting time parameter is over $7F.) Remember that the player only understands time-based steps and you always have to convert limit-based steps before they play correctly! @endnode @node 3.6.2Precalculatednote-independenthifiplayerportamentovibrato "3.6.2 Precalculated note-independent hifi player portamento/vibrato" 3.6.2 Precalculated note-independent "hifi player" portamento/vibrato --------------------------------------------------------------------- From v2.62 onwards, GoatTracker actually supports realtime calculated note independent portamento and vibrato speeds, see speedtable section for this. However, this makes the player bigger and much slower. You can still also use the old method of manually precalculating needed note-independent speeds with the SHIFT+H function, which this section is about. The idea is to take the frequency difference between 2 adjacent notes in the frequency table and manipulate it by bit shifting left (multiply) or right (divide). To use, you need a portamento or vibrato command in the pattern, and the note you wish to base the calculation on on the current pattern step or before it (before it only for toneportamento) The amount of shift is determined by the command parameter. A number in the left nybble means shift left and right nybble right shift. When you press Shift+H while the cursor is on the command, a speedtable entry is created, and the parameter is replaced with a speedtable index. Some examples: C-3 00110 Take the frequency difference between C-3 & C#3 and shift it left 1 times (multiply by 2.) E-4 00000 ... 00000 G-4 00302 Take the frequency difference between E-4 & F-4 and shift it right 2 times (divide by 4.) @endnode @node 3.7Multispeedtips "3.7 Multispeed tips" 3.7 Multispeed tips ------------------- - When making multispeed songs, remember to multiply your tempos and also the gateoff timer values! For example, gateoff timer is normally 2, but in a 2X- speed tune the same gateoff length would be achieved with value 4. - If you want to keep vibrato the same compared to 1X-speed, you must multiply vibrato speed by the speed multiplier, and divide vibrato depth by the multiplier. Remember also to divide portamento and pulse/filter modulation speeds as necessary. - When importing a v1.xx multispeed song, you also need to multiply the gateoff timers. - In the instruments, using Attack 0 might result in a very silent first row of the wavetable. You could try increasing the attack, or adding one or more rows of E9 00 (testbit+gate) to the beginning of the wavetable. @endnode @node 4.Usingtheincludedutilities "4. Using the included utilities" 4. Using the included utilities ------------------------------- @endnode @node 4.1INS2SND2.EXE "4.1 INS2SND2.EXE" 4.1 INS2SND2.EXE ---------------- INS2SND2.EXE converts GoatTracker v1.xx or v2 instruments (.INS-files) into sound effects, outputting the data as source code or binary. Usage: INS2SND Options: -b output in binary -c output in CovertScript format (deprecated) Default output is C64 assembler (DASM) style source code Look at section 6.3 or run the program without parameters to see the limitations of the sound effect system. @endnode @node 4.2SNGSPLI2.EXE "4.2 SNGSPLI2.EXE" 4.2 SNGSPLI2.EXE ---------------- SNGSPLI2.EXE splits the patterns of a GoatTracker v2 song into smaller pieces for memory use optimization. It is comfortable to compose with large patterns but usually more efficient memory-wise to use small patterns. Remember! Always keep the original song because a pattern-splitted song is much harder to edit further. Usage: SNGSPLI2 [target len] For example, if a pattern is 64 rows long and the target length is 16, it will be split into 4 pieces. A pattern that falls below 2 x target length, will not be split at all. @endnode @node 4.3MOD2SNG.EXE "4.3 MOD2SNG.EXE" 4.3 MOD2SNG.EXE --------------- Dedicated exclusively to T.M.R, this program converts the pattern & orderlist data of 4-channel, 31-instrument MOD-files into GoatTracker .SNG files. You must choose one channel to leave out, and obviously instruments are not converted, except for their names. You can also specify a transpose in halfsteps. Usage: MOD2SNG [channel] [transpose] [channel] is the channel to leave out (1-4), default 4 [transpose] is the halfstep transpose added to notes, default 0 @endnode @node 4.4BETACONV.EXE "4.4 BETACONV.EXE" 4.4 BETACONV.EXE ---------------- Converts GT v2 beta songs to new format used by GT v2 RC1 onwards. Old format had 47 instruments max. and new has 63 max. Additionally, depending on what beta version you used, you can choose to halve vibrato depths and pulse speeds to make them play correct in the current version. Warning: the conversion is irreversible, so have backups if you overwrite the old versions. Usage: BETACONV [vibdepth] [pulse] [vibdepth] decides whether to halve vibdepth (1=yes 0=no), default 0 [pulse] decides whether to halve pulse speed (1=yes 0=no), default 0 @endnode @node 5.Usingthesongsoutsidetheeditor "5. Using the songs outside the editor" 5. Using the songs outside the editor ------------------------------------- Press F9 in the editor to enter the packer/relocator. Choose playroutine options, startaddress, zeropage address (need 2 consecutive locations) and file format (PRG/BIN/SID), then type the filename. If you use patterns longer than 64 rows, there is the possibility that relocation fails because of too complex patterns. Each pattern row can be 0-4 bytes packed, and the total amount of bytes per one pattern may not exceed 256. If wave/pulse/filtertables overflow past row 255 without a jump command or there are other serious errors, you get a warning screen and have to fix the error. The relocator optimizes & removes when saving: - Unused patterns - Unused instruments - Unused table-entries - Selfcontained (ie. no jumps to/from outside) duplicate parts of tables - Player code not needed in the playback of the song Look at /examples/example1.prg - example4.prg to get an idea how much these playroutines take rastertime. No promises! The basic functions independent of playroutine options are: Init music: LDA #subtunenumber ;Starting from 0 JSR startaddress Play one frame of music: JSR startaddress+3 @endnode @node 5.1Playroutineoptions "5.1 Playroutine options" 5.1 Playroutine options ----------------------- BUFFERED SID-WRITES - Instead of writing each SID value as soon as possible, waits for the end of the channel's execution on each frame and then writes the registers in one go. Improves sound stability but takes more memory & raster- time. SOUND EFFECT SUPPORT - Adds a sound effect engine for use in games. Implies buffered writes. To use, call in the following way: LDA #effect LDX #channel ;0, 7 or 14 for channels 1-3 JSR startaddress+6 The sound effects have a hardcoded priority system based on their start addresses. A sound higher up in memory (bigger address) will never be interrupted with a sound lower in memory. VOLUME CHANGE SUPPORT - Adds a routine in the player's jumptable to change the master volume level. To use, call in the following way: LDA #volume ;0-15 JSR startaddress+6 ;(startaddress+9 with sound effect support) Note that the master volume command (DXY) also modifies this same location, so it will clash if you also change the volume manually. STORE AUTHOR-INFO - Writes the "AUTHOR" string from songname editor to the location range (startaddress+$20 - startaddress+$3F). Also enables timing mark support. A timing mark is a mastervolume command (DXY) with parameter $10-$FF. This parameter will be copied into startaddress+$3F when the command is encountered in playback. USE ZEROPAGE GHOSTREGS - Instead of writing to the SID, a memory range in the zeropage is used for holding the SID register data. This can then be copied in the main program to the SID, for example to enable the playroutine & music data to reside under the I/O area. Implies buffered writes. A reverse copy loop should be used after each call to the playroutine: LDX #$18 copy: LDA ghostregs,x STA $D400,x DEX BPL copy The copy loop can also be unrolled for more speed. Note that when you use the alternative hardrestart method & playroutine (hard- restart attack parameter F) the copy loop should not be in reverse order but should be for each channel: wave, frequency, pulsewidth, and ADSR last. If you are using both sound effect support and ghostregisters, there exists a possibility of sound errors in the case that a sound effect has finished, and the same channel starts a new pulse-waveform note without setting an initial pulsewidth value (for example, like in the beginning of Sanxion loader tune). This is because the ghostregisters are shared between music & sound effect playback, and the sound effect has already overwritten the previous pulse width. DISABLE OPTIMIZATIONS - The relocator removes saved playroutine code based on what effects & commands the song uses, resulting in a smaller playroutine accordingly. If you encounter anomalies in the sound (such as ADSR bugs caused by unpredictable timing variation) you can try disabling the optimizations. Normally this is not necessary, but is included just in case. @endnode @node 6.Filedataformatsdescription "6. File/data formats description" 6. File/data formats description -------------------------------- The sections in the files appear in the sequential order in which they are described. @endnode @node 6.1GoatTrackerv2song(.SNG)format "6.1 GoatTracker v2 song (.SNG) format" 6.1 GoatTracker v2 song (.SNG) format ------------------------------------- @endnode @node 6.1.1Songheader "6.1.1 Song header" 6.1.1 Song header ----------------- Offset Size Description +0 4 Identification string GTS5 +4 32 Song name, padded with zeros +36 32 Author name, padded with zeros +68 32 Copyright string, padded with zeros +100 byte Number of subtunes @endnode @node 6.1.2Songorderlists "6.1.2 Song orderlists" 6.1.2 Song orderlists --------------------- The orderlist structure repeats first for channels 1,2,3 of first subtune, then for channels 1,2,3 of second subtune etc., until all subtunes have been gone thru. Offset Size Description +0 byte Length of this channel's orderlist n, not counting restart pos. +1 n+1 The orderlist data: Values $00-$CF are pattern numbers Values $D0-$DF are repeat commands Values $E0-$FE are transpose commands Value $FF is the RST endmark, followed by a byte that indicates the restart position @endnode @node 6.1.3Instruments "6.1.3 Instruments" 6.1.3 Instruments ----------------- Offset Size Description +0 byte Amount of instruments n Then, this structure repeats n times for each instrument. Instrument 0 (the empty instrument) is not stored. Offset Size Description +0 byte Attack/Decay +1 byte Sustain/Release +2 byte Wavepointer +3 byte Pulsepointer +4 byte Filterpointer +5 byte Vibrato param. (speedtable pointer) +6 byte Vibraro delay +7 byte Gateoff timer +8 byte Hard restart/1st frame waveform +9 16 Instrument name @endnode @node 6.1.4Tables "6.1.4 Tables" 6.1.4 Tables ------------ This structure repeats for each of the 4 tables (wavetable, pulsetable, filtertable, speedtable). Offset Size Description +0 byte Amount n of rows in the table +1 n Left side of the table +1+n n Right side of the table @endnode @node 6.1.5Patternsheader "6.1.5 Patterns header" 6.1.5 Patterns header --------------------- Offset Size Description +0 byte Number of patterns n @endnode @node 6.1.6Patterns "6.1.6 Patterns" 6.1.6 Patterns -------------- Repeat n times, starting from pattern number 0. Offset Size Description +0 byte Length of pattern in rows m +1 m*4 Groups of 4 bytes for each row of the pattern: 1st byte: Notenumber Values $60-$BC are the notes C-0 - G#7 Value $BD is rest Value $BE is keyoff Value $BF is keyon Value $FF is pattern end 2nd byte: Instrument number ($00-$3F) 3rd byte: Command ($00-$0F) 4th byte: Command databyte @endnode @node 6.2GoatTrackerv2instrument(.INS)format "6.2 GoatTracker v2 instrument (.INS) format" 6.2 GoatTracker v2 instrument (.INS) format ------------------------------------------- Offset Size Description +0 4 Identification string GTI5 +4 byte Attack/Decay +5 byte Sustain/Release +6 byte Wavepointer +7 byte Pulsepointer +8 byte Filterpointer +9 byte Vibrato param. (speedtable pointer) +10 byte Vibrato delay +11 byte Gateoff timer +12 byte Hard restart/1st frame waveform +13 16 Instrument name After the instrument data, this structure repeats for each of the 4 tables (wavetable, pulsetable, filtertable, speedtable). Offset Size Description +0 byte Amount n of rows in the table +1 n Left side of the table +1+n n Right side of the table Note that the tables are a partial snapshot of the current song the instrument was saved from, so upon loading they have to be relocated to the current free table locations. @endnode @node 6.3Soundeffectdataformat "6.3 Sound effect data format" 6.3 Sound effect data format ---------------------------- Offset Size Description +0 byte Attack/Decay +1 byte Sustain/Release +2 byte Pulse width. This value has nybbles reversed from what it looks like in the editor so a middle pulse $800 will be stored as $08, and the sound effect routine will put this value to both $D402 and $D403 registers. +3 ? Wavetable. Contains note/waveform pairs (different order than in instrument wavetable), from which the waveform can be omitted if unchanged, as the value ranges do not overlap: Value $00 ends the sound effect Values $01-$81 are waveforms Values $82-$DF are absolute notes D-0 - B-7 Note that a note cannot be omitted to store only waveform changes! As you can see, the sound effect format is very simplistic. When converting an instrument to a sound effect with INS2SND2, following things cause an error message: - If the resulting sound effect is more than 128 bytes - If the instrument's wavetable contains relative notes, absolute notes C-0 or C#0, or waveforms > 129 ($81) The instrument's pulsewidth modulation & filter settings will be completely discarded. @endnode @node 7.Recompiling "7. Recompiling" 7. Recompiling -------------- To recompile for Win32, you need the MinGW development environment, use the file src/makefile.win as makefile. To recompile for Linux, use src/makefile. In both cases you need the SDL development libraries in addition to the SDL runtime, see http://www.libsdl.org. Compile first the utilities (datafile & dat2inc) from the src/bme directory, and place them to your path. @endnode @node 8.Versionhistory "8. Version history" 8. Version history ------------------ v2.0Beta - Original public release v2.0 - Fixed crash in DMC-note entry mode. - Fixed v1.xx import pulse conversion, a case where pulse startpos was lower than the pulse low limit was not converted right. - Fixed instrument gatetimer becoming zero (can lead to tempo bugs) when cutting an instrument (SHIFT+X) - Fixed order of SID writes to make editor & C64 playroutine behave as similarly as possible. - Fixed removal of table-entries (when loading an instrument) in case another instrument uses them too. - Fixed toneportamento (3XY) with wavetable delays. - Fixed funktempo in packed/relocated songs. - Fixed behaviour of + & - keys while editing instrument name. - Fixed pattern editor transpose functions. - Added SHIFT+DEL to delete an instrument + its tabledata. - Added SHIFT+INS to insert rows on table first row without having to adjust tablepointers afterwards. - Added SHIFT+W,S for octave transpose. - Added SHIFT+1,2,3 to swap orderlists between channels. - Added SHIFT+BACKSPACE to clear a whole pattern row. - Added optimized playroutines, that will be used if all instruments have the same gateoff timer & 1st wave parameters. - Added duplicate check for v1.xx pulse conversion. - Added BETACONV-utility for conversion from beta format. - Added reSID interpolation option /I. - Added hexadecimal pattern row display option /D. - Added SID memory location parameter /L. - reSID interpolation is on by default. - Changed appearance of pattern special notes (rest, keyoff/on) - Increased amount of instruments to 63 and changed song dataformat. - v1.xx import converts arpeggios to instruments as long as there is room. - Vibrato depth changed back to same as in v1.xx. - Pulse modulation speeds are doubled. - Upon startup, songdata erase, or importing v1.xx data, gatetimer will be set to 2 * multiplier as opposed to just 2. - Optimized size & speed of all playroutines (initialization, checking for new note fetch, pulsetable execution). - Wavetable delay or no-wavechange on first step of instrument is definitely unsupported now! Protection to allow this conflicted with 3XY command. v2.01 - Added under-IO gamemusic playroutine. v2.02 - Added RETURN when instrument tableparameter (wave/pulse/filter) is 0 to get you to the first free table location. SHIFT+RETURN will additionally also set the instrument tableparameter. - Added "set mastervolume"-jump to gamemusic routines. - Improved sound effect handling, when an effect is interrupted by another (less silence between sounds). v2.03 - Added execution of realtime commands & instrument vibrato during wavetable delay. - Added wavetable right side value $80 to keep frequency unchanged (as a consequence, the note C-0 will cause the same effect). - Added relocator optimizations: all unnecessary data is stripped when packing/relocating. - Playroutines size-optimized. - Explanation of how different gatetimer values can lead to playback going out of sync (section 3.3). - reSID interpolation is no longer on by default :) v2.04 - Added a questionable 25Hz mode (/S0) - Execution of commands on wavetable delay is completely reworked and more consistent now. - Note C-0 is usable again. v2.05 - Added instrument legato feature (Hardres/1stwave parameter $00). - ADSR writes moved farther away from wave writes in the standard playroutine noteinit, lessening possibility of ADSR bugs. - Song initialization and pulsetable execution speed/sizeoptimized. v2.06 - Packer/relocator tolerates up to 256 bytes long patterns now. - Optimized playroutine sizes. v2.07 - Fixed transpose reset with F2/F3 song start (should not happen). - Fixed varying tempo on channels with F2/F3 song start. - Added warning screen to packer/relocator if table execution overflows. - Added writing of PAL/NTSC and 6581/8580 flags according to PSID V2 NG specification. - -mwindows added to linker options for no displaying of DOS prompt window (in win32 version). v2.08 - Added finevibrato mode (/V command line option). - Optimized playroutine sizes & speed. v2.09 - Fixed max.pattern length in Clear Musicdata operation. - Added Minimal playroutine. - First wave value $80 also acts as a proper legato instrument now. - Optimized playroutine sizes & speed. - SID chip type & timing (PAL/NTSC) displayed on top row. v2.1 - Added SHIFT+N for negating pulse/filter modulation speeds. - Added no-funktempo & no-octave0 optimizations to playroutines (a total of 8 sub-types for each playroutine). - Maximum speed is 16X now. - Separate song/instrument/packed song directories are remembered during session. - Pathname is displayed in the fileselector. - Filters ** and *.* display all files in the fileselector. - Song entered on commandline will be loaded at startup. - Song filename currently being edited is shown in the titlebar. - Currently edited song filename will be used as default in the "SAVE SONG" and "SAVE MUSIC+PLAYROUTINE" dialogs. - Instrument name will also be used as instrument filename as default in the "SAVE INSTRUMENT" dialog. - UPX used for compression of win32 executables. - Included a short reference of waveform bits (manual only). - Configuration file has clearer structure. v2.11 - Added SHIFT+S for smart instrument paste (converts instrument numbers in all patterns, after cut/pasting an instrument). - Added SHIFT+L which allows to write pulse/filter modulation steps and then convert them to the proper format. v2.12 - Playroutine 1 has buffered SID-writes. - Octave 0 is not disabled in routines with sound FX (no matter what the relocator says...) v2.13 - Standard playroutine now both in unbuffered and buffered flavors. v2.15 - Added SHIFT+I for inverting current pattern selection / whole pattern. v2.16 - Fixed octave selection with / * for laptop keyboards. - Empty patterns referenced in the orderlist will be saved when saving a song. - Save dialog will reappear if writing the song/instrument/executable music failed. - Optimized handling of "packed rests" in the playroutines. - Added < > for instrument selection in instrument/table edit modes. v2.17 - Fixed initialization of instrument vibrato. - Playroutines size-optimized. v2.18 - Wavetable left side values changed. Delay is now $01-$0F and inaudible waveforms (register values $00-$0F) have been mapped to table values $E0-$EF. Old songs using values $08-$0F have to be manually converted! v2.2 - Added the speedtable for more precise control of vibrato, portamento and funktempo. - Added SHIFT+O to optimize the speedtable (remove unused entries). - Added SHIFT+R to convert between absolute/relative notes in the wavetable. - Added SHIFT+RETURN in pattern/instrument editor to convert old style portamento, vibrato and funktempo parameters to speedtable entries. - SHIFT+R will paste several effect rows if there is data in pattern copybuffer. - Editing during Follow Play is possible. - Song and instrument format modified for 4 tables. Old 3-table data will be loaded but not saved anymore. v2.21 - Fixed NTSC CIA timer value for SID files. - Shift+E will copy several effect rows if pattern has been marked. v2.22 - Shift+N will also negate relative wavetable notes. - When converting oldstyle parameters to speedtable entries with SHIFT+RETURN, the speedtable view will shift to the new entry if one was created. v2.23 - Fixed SHIFT+INS in wavetable (inserts $E9 $00 now as it should). - Added SHIFT+U to unlock table scrolling. - Added SHIFT+F5/F6 to change speed multiplier. v2.24 - Added SHIFT+F7 to edit the hardrestart ADSR parameter. - Added SHIFT+F8 to switch between 6581 and 8580 SID models. v2.25 - Added detail to table overflow error message in relocator. - Added stop of playback if a tablepointer gets pointed directly to a jump (would bug in packed/relocated tune). - Added relocator error message for the above case. - Added relocator error message for illegal song restart position. - Not possible to save erroneous packed/relocated songs anymore (now that there is adequate error location). - Added SHIFT+,. to move song startposition on all channels and restart last playmode. v2.26 - Fixed relocator complaining of FF parameter in speedtable. - To increase stability, in multispeed mode relocator does not use the "same gatetimer/1st wave" optimization. - Changed Shift+O to optimize the currently edited table, not just speedtable. - Added an option to optimize everything with the SHIFT+ESC clear function. This clears unused patterns, instruments and table-entries. v2.27 - Fixed optimize function with different pattern lengths. - Added marking & copy/pasting orderlist data like patterns & tables. v2.28 - Added sort of mouse control. - Sound reinitialization when changing multiplier or other parameters is now faster. v2.29Beta - Internal reorganization. - New assembler-based relocator that leaves out unused portions of player code. - Instead of choosing a player version, one can choose combinations of player features. - Relocator does not save selfcontained duplicate parts of tables. - Added keys 0-9 & A-Z in the fileselector to move to the corresponding part of the filelist (if found). - Added SHIFT+H to calculate left/right shifted "hifi" speedtable values, according to the frequency of a note. v2.3 - Fixed songdata optimize function. - Fixed relocator with no-hardrestart instrument in slot 1. - Fixed relocator handling of effect C (Set cutoff). v2.31 - Fixed effect copy/paste. - Added possibility to disable pulseskipping with /O command line option. Warning: causes huge rastertime increase. - Tempo 2 is allowed. See the tips section (3.6) for details. v2.32 - Maximum pattern length increased to 128. Do not complain of "pattern too complex" errors :) - Optimized playroutine init in case of only 1 subtune. v2.33 - Fixed a bug where relocator was checking pattern 208 (illegal). - Optimized playroutine in case there is no keyoff/keyon used. - Optimized playroutine in case there are no pattern effects used. - Optimized playroutine channel variables in case there is no transpose, repeat, wavedelay and pattern effects. - If not using the last instrument (63), you can control song startup default tempo by using its Attack/Decay parameter. v2.34 - Added relocator optimization for using 1 or 2 channels only. To enable, you must use only channels 1 or 1,2 and not be using sound effect support or zeropage ghostregs. - Turning off buffered writes in relocator options works now even if sound effects or zeropage ghostregs are selected (they will be turned off too). v2.35 - Auto-creation of speedtable entries will always generate a new entry (except for song loading), duplicate values will be optimized by the relocator. - Pressing SHIFT+RETURN over a speedtable-using pattern command while the parameter is zero, goes to the next empty speedtable entry and sets the command parameter to point to that entry. v2.4 - Added one bit of accuracy to pulse modulation speed. A new song- format (identifier GTS4) reflects this, old songs will be converted upon loading. - Added possibility to execute pattern commands from the wavetable. v2.41 - Fixed player code assembly errors when using some pattern commands only from the wavetable. - Fixed player code bug with command B when command A is not used. - Fixed SHIFT+O removing table entries pointed to from wavetable pattern commands. v2.42 - Fixed frequency table size determination. - Changed behaviour of keyoff in pattern editing changed to use releasenote() like the instrument editor. - Added SHIFT+RETURN when parameter is zero to get you into an empty table entry for 8, 9 and A pattern commands as well. - Added adjustment of table views when changing instrument number in unlocked table scrolling mode. - Added RETURN over nonzero instrument number (in patterns) to go editing that instrument. v2.43 - Added duplicate pattern detection/removal to song optimize. - Added pattern shrink/expand (SHIFT+O,P). - Added pattern join/split (SHIFT+J,K). v2.44 - Fixed editor playroutine to not execute tick n commands, when a command has already been executed through the wavetable. v2.45 - Added possibility to disable realtime pattern command optimization at tick 0 (/Rxx command line option or click the "RO" text on the statusbar) for tempo-independent portamento & vibrato. - To make room on the status bar for the realtime optimization status indicator, finevibrato & pulse optimization indicators have been shortened to "FV" and "PO". v2.46 - Added transpose of speedtable portamento speeds (SHIFT+Q,A,W,S) SHIFT+W,S (octave transpose, multiply/divide by 2) also work in pulse & filtertable. - When editing the wavetable, RETURN & SHIFT+RETURN work for wave- table executed commands as in patterns (go to table position pointed by command, create new speedtable entries) v2.47 - Added experimental random delay to write of reSID registers, in order to make potential ADSR-bugging on C64 audible. The amount of delay in cycles can be adjusted with /Z command line option. - SHIFT+L in pulsetable creates repeated "set tempo" commands if speed is greater than 127. v2.48 - Fixed playroutine to use configurable baseaddress again. v2.49 - Added /G command line option, guard 1stwave/gatetimer parameters. When this is on (default), only silent waveforms can be entered as firstwave (only thing that makes sense) and editing gatetimer of one instrument affects all of them, as otherwise bugs in playback result easily. Use /G0 to turn off. v2.5 - Fixed "optimize everything" removing the tempo setting in instrument 63. - Fixed default tempo of multispeed tunes in packer/relocator. v2.51 - Fixed packing of empty patterns when not using any effects. - Fixed differing gatetimer value in instruments causing playback going out of sync. - /G command line option no longer has to keep gatetimer values the same. - Added high bit of gatetimer value to control whether wavetable execution starts right on the note init frame. If used, will cause significant rastertime increase. v2.52 - SHIFT+ENTER in orderlist view takes the next available pattern if pressed on a repeat or transpose command. - Added SHIFT+SPACE in pattern editor to start playback on a specific pattern row. v2.53 - Fixed F3 to always play the currently visible patterns. - Added BACKSPACE in the orderlist editor to set playback end position. Only effective when starting playback from position, not beginning. v2.54 - Fixed SHIFT+F3. - Changed SHIFT+, . to update the pattern view. - Changed SHIFT+SPACE to remain in pattern playback mode, if it was active. v2.55 - Added BACKSPACE in the fileselector to go to the parent dir. v2.56 - Song filename cleared on songdata erase. - Added /F to set custom SID clock frequency. - Graphics output routines no longer compare text screen buffer to previous to find out if it should be updated. v2.57 - Added alternative hardrestart method & playroutine that is used when HR attack parameter is at maximum (FF00 or F800 for example) - this can in theory give better reliability. v2.58 - Cleanup, removal of a few questionable features: * Gatetimer high bit to start wavetable immediately * Guard 1stwave parameter v2.59 - Songformat version update (GTS5/GTI5) - Gateoff timer parameter bits control now hardrestart disable ($80) & gateoff disable ($40). - 1stFrame Wave can be any from $01-$8F, $00 to leave both waveform & gateflag unchanged, or $FE / $FF to control gateflag but leave waveform unchanged. v2.6 - Fixed pattern default length selection display when decrementing from a length of 100 or higher. - Fixed mouse selection of pattern when adjusting an adjacent channel. - Fixed help screen instructions. - Changed resolution to 800x600. - Changed all songname rows to be displayed at the same time. - Changed mouse control to allow pattern column selection even when left mouse button is held down. - Changed speed of PageUp/PageDown scrolling to be faster. - Optimized graphics output. - BME library is no longer needed. v2.61 - Added the backquote key (top-left on keyboard) to select channel in pattern edit mode, and to select table in table edit mode. Use with SHIFT to go backwards. - Added SHIFT+channel number to mute channels in pattern edit mode. v2.62 - Added possibility for realtime calculated note independent (hifi) portamento & vibrato. Warning: has potential for huge rastertime increase. v2.63 - Fixed note independent portamento & vibrato to use the last note set in wavetable for calculations, instead of the last note in patterndata. v2.64 - Fixed paste in table (SHIFT+V) working also without SHIFT pressed. v2.65 - Fixed raw keycodes over 511 interpreted as some other keys in the 0-511 range. v2.66Beta - Initial cycle-exact HardSID support (Win32 only) - Permit running without sound. v2.67 - Configurable cycle-exact HardSID buffer length (separate for inter- active and playback mode, see /T and /U command line options) v2.68 - Fixed set tempo -command overwriting frequencytable in 1 or 2 channel modes. - Fixed sound uninit crash with multicore processors (?) - SID register write order tweaked to resemble JCH NewPlayer 21. - Unbuffered playroutine optimized & modified to resemble buffered mode timing more. - New reSID-fp engine (with distortion & nonlinearity) from Antti Lankila integrated. Activated with /I command line option parameters 2 & 3. - Command quick reference by Simon Bennett included. v2.69 - Fixed click bug in reSID audio output. - Newest reSID-fp code integrated. - reSID-fp filter parameters adjustable from the configuration file. v2.70 - Hotfix for the new HardSID UPlay/Uno devices from Tli Sndor. - Fixed possible crash on some versions of the HardSID dll. v2.71 - Added keycode fix patch from Valerio Cannone. - Added fullscreen switch patch from Raine M. Ekman (see /X option) - Added context mode to online help patch from Raine M. Ekman. @endnode goattracker-2.72/morphos/goattrk2.info0000644000000000000000000000150411314431154016546 0ustar rootrootPNG  IHDR  IDATxV=H[Qn^\ 2J' ]!:f*vP)4K]tpwB],4[!'9޼D!ݛsxJPJU)֮vsA9cj{1d7$I4q7fXk-G>,BDZWX{ꈈ1F?Nkj er皎5Ua 2ѻWt~2⚚@PaeF$yʫ8NӴ nPѬ:Oͮdp*.!Ycѥ;g4}Bc c̪d>ny $I[k2 g$"LQ֚fgbi~ZT8kE0Dj13Jߺ,bs6nQgT1cw&L8Ys{ݎy2i,wq}@{u FZ ۽=2}Ye9Zk1E1E:1Z7}!>$g׷:|`z}+#T |U:D+ quՑ9ԗq-Ɂݗi 1#Oa &oQaʙd}Su_J&©ǣP-Igh64wУR6Lv/{=y oą q#*[} 3^{J JyfO/V=@auW=xy߷`aFXfƗp2<{7Ǘځ>9`AQSvIENDB`goattracker-2.72/readme_sdl.txt0000644000000000000000000000066410774364626015335 0ustar rootrootPlease distribute this file with the SDL runtime environment: The Simple DirectMedia Layer (SDL for short) is a cross-platfrom library designed to make it easy to write multi-media software, such as games and emulators. The Simple DirectMedia Layer library source code is available from: http://www.libsdl.org/ This library is distributed under the terms of the GNU LGPL license: http://www.gnu.org/copyleft/lesser.html