From d9384e62075a9a4d23536e667393fd72b0253289 Mon Sep 17 00:00:00 2001 From: "Jeffrey Lim @ Vision" Date: Sun, 23 Mar 2014 13:30:03 +0800 Subject: [PATCH] Initial commit. Import of documentation, keyboard, network and VSound code. Other code still needs cleaning up a bit before importing --- InternalDocumentation/CHANNEL.TXT | 279 ++ InternalDocumentation/CONFIG.TXT | 54 + InternalDocumentation/MMTECH.TXT | 143 + InternalDocumentation/NETWORK.TXT | 126 + InternalDocumentation/OBJECT.TXT | 233 ++ Keyboard/BE.ASM | 637 +++++ Keyboard/CA.ASM | 609 +++++ Keyboard/CH.ASM | 620 +++++ Keyboard/DE.ASM | 616 +++++ Keyboard/DK.ASM | 616 +++++ Keyboard/ES.ASM | 620 +++++ Keyboard/FI.ASM | 618 +++++ Keyboard/FR.ASM | 613 +++++ Keyboard/IT.ASM | 588 +++++ Keyboard/KEYBOARD.TXT | 12 + Keyboard/NO.ASM | 614 +++++ Keyboard/PO.ASM | 610 +++++ Keyboard/SE.ASM | 612 +++++ Keyboard/UK.ASM | 596 +++++ Keyboard/US.ASM | 598 +++++ Network/DEBUG.INC | 130 + Network/DRHEAD.INC | 19 + Network/EXECOM.COM | Bin 0 -> 1248 bytes Network/IPX.ASM | 3583 +++++++++++++++++++++++++ Network/MIPX.BAT | 5 + Network/NETDRIVE.ASM | 47 + Network/REQPROC.INC | 32 + Network/USERNAME.INC | 6 + Network/VTABLE.INC | 10 + README.md | 14 + ReleaseDocumentation/BUGS.TXT | 39 + ReleaseDocumentation/CONTRIB.TXT | 595 +++++ ReleaseDocumentation/DRIVERS.TXT | 577 ++++ ReleaseDocumentation/FILES.TXT | 33 + ReleaseDocumentation/FILE_ID.DIZ | 12 + ReleaseDocumentation/FILTERS.TXT | 143 + ReleaseDocumentation/HINTS.TXT | 572 ++++ ReleaseDocumentation/IMPULSE.FAQ | 261 ++ ReleaseDocumentation/IT.TXT | 2199 ++++++++++++++++ ReleaseDocumentation/IT256.ICO | Bin 0 -> 2998 bytes ReleaseDocumentation/ITTECH.TXT | 901 +++++++ ReleaseDocumentation/ITVSOUND.TXT | 70 + ReleaseDocumentation/MIDI.TXT | 400 +++ ReleaseDocumentation/NETWORK.TXT | 71 + ReleaseDocumentation/README.TXT | 72 + ReleaseDocumentation/SUMMARY.TXT | 296 +++ ReleaseDocumentation/UPDATE.TXT | 592 +++++ Tutorial/IT_TUTORIAL.EXE | Bin 0 -> 95898 bytes Tutorial/TUTE.IT | Bin 0 -> 75997 bytes VSound/Server/SERVER.C | 511 ++++ VSound/VXD/DEBUG.INC | 1156 ++++++++ VSound/VXD/MVSOUND.BAT | 3 + VSound/VXD/SHELL.INC | 139 + VSound/VXD/VMM.INC | 4074 +++++++++++++++++++++++++++++ VSound/VXD/VSOUND.ASM | 679 +++++ VSound/VXD/VSOUND.DEF | 38 + 56 files changed, 26693 insertions(+) create mode 100755 InternalDocumentation/CHANNEL.TXT create mode 100755 InternalDocumentation/CONFIG.TXT create mode 100755 InternalDocumentation/MMTECH.TXT create mode 100755 InternalDocumentation/NETWORK.TXT create mode 100755 InternalDocumentation/OBJECT.TXT create mode 100755 Keyboard/BE.ASM create mode 100755 Keyboard/CA.ASM create mode 100755 Keyboard/CH.ASM create mode 100755 Keyboard/DE.ASM create mode 100755 Keyboard/DK.ASM create mode 100755 Keyboard/ES.ASM create mode 100755 Keyboard/FI.ASM create mode 100755 Keyboard/FR.ASM create mode 100755 Keyboard/IT.ASM create mode 100755 Keyboard/KEYBOARD.TXT create mode 100755 Keyboard/NO.ASM create mode 100755 Keyboard/PO.ASM create mode 100755 Keyboard/SE.ASM create mode 100755 Keyboard/UK.ASM create mode 100755 Keyboard/US.ASM create mode 100755 Network/DEBUG.INC create mode 100755 Network/DRHEAD.INC create mode 100755 Network/EXECOM.COM create mode 100755 Network/IPX.ASM create mode 100755 Network/MIPX.BAT create mode 100755 Network/NETDRIVE.ASM create mode 100755 Network/REQPROC.INC create mode 100755 Network/USERNAME.INC create mode 100755 Network/VTABLE.INC create mode 100644 README.md create mode 100755 ReleaseDocumentation/BUGS.TXT create mode 100755 ReleaseDocumentation/CONTRIB.TXT create mode 100755 ReleaseDocumentation/DRIVERS.TXT create mode 100755 ReleaseDocumentation/FILES.TXT create mode 100755 ReleaseDocumentation/FILE_ID.DIZ create mode 100755 ReleaseDocumentation/FILTERS.TXT create mode 100755 ReleaseDocumentation/HINTS.TXT create mode 100755 ReleaseDocumentation/IMPULSE.FAQ create mode 100755 ReleaseDocumentation/IT.TXT create mode 100755 ReleaseDocumentation/IT256.ICO create mode 100755 ReleaseDocumentation/ITTECH.TXT create mode 100755 ReleaseDocumentation/ITVSOUND.TXT create mode 100755 ReleaseDocumentation/MIDI.TXT create mode 100755 ReleaseDocumentation/NETWORK.TXT create mode 100755 ReleaseDocumentation/README.TXT create mode 100755 ReleaseDocumentation/SUMMARY.TXT create mode 100755 ReleaseDocumentation/UPDATE.TXT create mode 100755 Tutorial/IT_TUTORIAL.EXE create mode 100755 Tutorial/TUTE.IT create mode 100755 VSound/Server/SERVER.C create mode 100755 VSound/VXD/DEBUG.INC create mode 100755 VSound/VXD/MVSOUND.BAT create mode 100755 VSound/VXD/SHELL.INC create mode 100755 VSound/VXD/VMM.INC create mode 100755 VSound/VXD/VSOUND.ASM create mode 100755 VSound/VXD/VSOUND.DEF diff --git a/InternalDocumentation/CHANNEL.TXT b/InternalDocumentation/CHANNEL.TXT new file mode 100755 index 0000000..ba79c60 --- /dev/null +++ b/InternalDocumentation/CHANNEL.TXT @@ -0,0 +1,279 @@ + Host Channel Structure + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0000: Flags MskNteInsVolCmd&ValOCm&ValVCm&ValMChMPrNt2Smp + Ĵ +0010:DKLEFGO00I00J00M00N00P00Q00T00S00OxHW00VCEGOESFx GOE = Gxx + Ĵ with old +0020:HCNCUCVSeLTrSCOffstPLRPLCPWFPPoPDpPSpLPnLViCP CV effects + Ĵ +0030:VChTCDTooRTCPorta FrequencyVWFVPoVDpVSpTWFTPoTDpTSp + Ĵ +0040: Misc Effect Data............................................. + + + Flags: + Update Mode + 2 Bits (0-3) + 0: Don't update effect + 1: Update effect if channel is on + 2: Always update effect + + Channel On + 1 Bit (4) + 0: Channel is off + 1: Channel is on + + Channel Cut ; No longer implemented + 1 Bit (8) + 0: No Channel Cut command + 1: Channel Cut command issued + + Slide in progress (Commands G/L) + 1 Bit (16) + 0: No slide in progress + 1: Slide in progress + + Freeplay note (ie. Don't check channel on/off) + 1 Bit (32) + 0: Not freeplay -> Check channel + 1: Freeplay -> Don't check channel + + +64 = row updated. + + + 128 = Apply random volume + + +256 Volume column effect requires updating if channel on + +512 Volume column effect requires updating always. + +32768 = Dont' touch in interrupt! + + Decoding Data + Msk, Nte, Ins, Vol, Cmd&Val, ONt, OIn, OVl, OCm&Val + Msk = Read mask: Bit 0 or 4 = Note read + Bit 1 or 5 = Instrument read + Bit 2 or 6 = Volume read + Bit 3 or 7 = Command/Command Value read + + Smp & Nt2 + Sample Number (zero based) and Note (after translation if using inst.) + + CP. = Channel Pan + CV. = Channel Volume + + SCN = Slave Channel Number + CUC = Command Update Count. For playmode 0 + SCOffst = Slave channel number offset + + VWF = Vibrato wave form + TWF = Tremelo wave form + PWF = Panning wave form + + PLR = Pattern loop row + PLC = pattern loop count. + + VSe = Volume set + + LVi = Last vibrato. + LTr = Last tremelo. + Dir = Porta direction + RTC = Retrig count + Too = tremor on/off ; on = 1 + TCD = tremor count down + + OxH = High order Offset for yxx00h + + VCh = Volume change (For Command D) + + + + Slave Channel Structure + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0000: Flags Device specific...............LpMLpD Left Volume + Ĵ +0010: Frequency Frequency Set BitViPViDepth RVol/MIDIFSet + Ĵ +0020:FV VolVS CVlSVlFP FadeOutDCTDCAPanPS OldSampleOffset + Ĵ +0030:InsOffsNteInsSmpOffsSmpFPPHCOffstHCNNNAMChMPr MBank + Ĵ +0040: Loop Beginning Loop End SmpErr.16bVol Sample Offset + Ĵ +0050:VEnvelopeValue VEnvelopeDelta VEnvPosCurVEnNNextVETfiltera + Ĵ +0060:PEnvelopeValue PEnvelopeDelta PEnvPosCurVEnNNextPETfilterb + Ĵ +0070:PtEnvelopeValuePtEnvelopeDeltaPtEvPosCurPtENNxtPtETfilterc + + + For MIDI, [SI+0Bh] = Pattern note + + Reqd values: VEnvValue (DWord), VEnvDelta (DWord), VEnvPos (Word), NextVEnvNode + PEnvValue (DWord), PEnvDelta (DWord), PEnvPos (Word), NextPEnvNode + PtEnvValue (DWord), PtEnvDelta (DWord), PtEnvPos (Word), NextPtEnv + + Reqd flags: VolEnvOn, PEnvOn, PtEnvOn + + FP = final pan. + FPP = final playing pan, taking into account reverse. + + MBank also doubled as Filter freq, resonance + + Flags: + Channel On + 1 Bit (1) + 0: Channel is off + 1: Channel is on + Recalculate panning (2) + + Note Off (ie. Sustain) + 1 Bit (4) + 0: No Note Off command (ie. Sustain on) + 1: Note Off command issued (ie. Sustain off) + FadeOut + 1 Bit (8) + 0: No FadeOut command + 1: Apply FadeOut + Recalculate volume + 1 Bit (16) + 0: Volume doesn't need to be calculated + 1: Volume needs to be recalculated + Frequency change + 1 Bit (32) + 0: Frequency has NOT changed + 1: Frequency HAS changed + Recalculate Final volume... + 1 Bit (64) + 0: Final volume does not need to be calculated + 1: Final volume DOES need to be calculated. + + Central pan... + 1 Bit (128) + 0: Use whatever is given. + 1: Always use central pan (for sample list/instrument list) + + New note! + 1 Bit (256) + 0: No new note + 1: New note to play. + + Note stop (cut) ; IMPORTANT FOR GUS!!! + 1 Bit (512) + 0: note NOT cut + 1: Note CUT + + Loop changed. (1024) + + Channel muted (2048) ; 2^11 + + Vol Envelope on (4096) ; 1000h + Pan Envelope on (8192) ; 2000h + Pitch Envelope on (16384) ; 4000h + + Pan value changed ; 8000h + Recalculate final pan + + LpM + LoopMode + 0: No Loop + 8: Forwards Loop + 24: Ping Pong Loop ; Values are just for GUS convenience + + LpD + LoopDirection (for ping pong), ; 0 = forwards, 1 = backwards. + + FadeOut = Fadeout Count (0-255) + CVl = Channel Volume + HCN = Host Channel Number. +128 if "disowned" + Smp = Sample number + Pan: 0->64, 100 = Surround, >= 128 = muted. + FnV: Final Volume + + Bit: 2 = 16, 0 = 8. + + ViD: Vibrato Depth + ViS: Vibrato Speed + + VEP: Volume Envelope position + VEV: Volume Envelope value + + Ins: Instrument number (0 based, 0FFh if none) + Smp: Sample number (0 based) + + Frequency = Final note frequency. Incorportes vibrato + Frequency Set = Calculated Frequency of note. Calculated once when played + Altered by effects E,F,G,L + + VS = Volume Set. Similar to Frequency Set. Affected by D,K,L + Vol = Volume. Altered by effects R,I + + + + Sound Blaster Output Structure + + 0 1 2 3 4 5 6 7 8 9 + +0000:(Flags) Skip Value Vol x MixMode + + + For non-looped samples, 44h is LENGTH. + + Sound Blaster Pro Output Structure + + 0 1 2 3 4 5 6 7 8 9 + +0000:(Flags) Skip Value LVlRVlMixMode + + + Skip Value + 16.16 bit fixed point + + Vol/LVl/RVl + Output Volume / Left Volume / Right Volume + Accounts for: + Channel Volume + Global Volume + Sample Global Volume + Fade Out + + MMd: 0 If Left only + 1 If right only + 2 if Left = Right + 3 if Panned + 4 if Surround + 5 if position update. + + + +32 for 16 bit samples + +8 for looped + +24 for ping pong. + + UltraSound Output Structure + + 0 1 2 3 4 5 6 7 8 9 + +0000:(Flags)LastVolFreqval + + + Frequency Value used in dynamic GUS drivers + + AWE32 Output Structure + + 0 1 2 3 4 5 6 7 8 9 + +0000:(Flags) x x Freqvalue + + + Frequency Value used in floating point AWE32 drivers + + SAM Output Structure + + 0 1 2 3 4 5 6 7 8 9 + +0000:(Flags)opn x + + + opn = 1 if voice is opened, 0 if not. + diff --git a/InternalDocumentation/CONFIG.TXT b/InternalDocumentation/CONFIG.TXT new file mode 100755 index 0000000..17d12a6 --- /dev/null +++ b/InternalDocumentation/CONFIG.TXT @@ -0,0 +1,54 @@ +Configuration file for IT.EXE + +Offset Length Meaning +0 70 Module directory +70 70 Sample directory +140 70 Instrument directory +210 1 Keyboard style + +211 3*16 Palette information + +259 50 Display window setup + Structure is 6*8 bytes, followed by 1 word = number of windows + Structure of each 8 byte record is: + Word: Method. (0 = volume bars, 1 = 5 track view, etc) + Byte: Top channel + Byte: Top line on screen + Word: Length of window + Word: Display memory offset of top left of window. + +309 217 bytes so far Pattern edit setup. + + Offset (W = word, B = byte) + + 309 W - MUST be 0 (key signatures not defined) + 311 W - number of channels to edit (5, but recalculated + whenever the screen changes) + 313 B - Row hilight minor (eg. every 4) + 314 B - Row hilight major (eg. every 16) + 315 B - Edit mask. Bit 0 = edit ins, 1 = edit vol, 2 = edit FX + 316 B - View division (1= show divisions) + 317 W - Number of 'viewed' channels + 319 100W - Channel viewmethods. First word = channel + Second word = method + Methods: 0 = full edit + 1 = compressed edit + 2 = extra compressed edit + 3 = 3-character selective edit + 4 = 2 character selective edit + + 0FFFFh indicates end of list + + 519 B - View-channel cursor tracking (1 = on) + 520 B - Effect/Effectvalue link (1 = on) + 521 B - Flags. Bit 0 = centralise cursor + Bit 1 = hilight current row + Bit 2 = fast volume changes + Bit 3 = MIDI Quantize to tick + Bit 4 = MIDI program base 1 + Bit 5 = MIDI record note-offs + Bit 6 = MIDI record velocity + Bit 7 = MIDI Record aftertouch + 522 B - MIDIAmplification + 523 B - MIDICentral note + 524 W - Fast volume amplification diff --git a/InternalDocumentation/MMTECH.TXT b/InternalDocumentation/MMTECH.TXT new file mode 100755 index 0000000..085e4ca --- /dev/null +++ b/InternalDocumentation/MMTECH.TXT @@ -0,0 +1,143 @@ + +Here's something that might help you... I wrote it quite fast but it should +be accurate ;) However, there's probably a lot of stuff here that you don't +need/understant for now... but keep all this, you'll need it soon ;) + +--> This is NOT the "official" Tehcnical stuff.... + +File Header: + + offset type/size comment + ------ --------- --------------------------------- + 0 char[8] Signature: 'ziRCONia' + + 8 word file header size (from offset 10, not counting this + word) + 10 word version 0xyyzh (x.yy) (displayed in hex. no conversion) + z: 0 nothing + 1-0eh revision a to n (-may- be useful...) + 0fh Beta + 12 word number of blocks within file + 14 dword total length of unpacked file + 18 dword file offset where is located the "block offset table" + 22 word dummy... must currently be 0ffffH + + + The block offset table is simply N_of_Block dwords which are the + absolute position of each block in the file. Each of those blocks have + the following header: + + 0 dword unpacked size + 4 dword compressed size + 8 dword XOR check (see note below) + 12 word number of "sub-blocks" (nblk) + 14 word flags (see below) + 16 word number of translation table entry } for compression + 18 word start number of bit } don't mind them + for now... + 20 sub-block[nblk] Sub-blocks of data info. + + each sub-block has the following info: + 0 dword absolute position in uncompressed file + 4 dword size of uncompressed block + all "nblk" sub-block info are stored right after the block header. + + Those small blocks are only non-contiguous blocks of the "same type" + grouped together within one bigger block for better compression. + + - XOR check: instead of implementing a CRC, I coded a XOR check. + How it works: a dword variable is set to 0, and XORed + with every complete 4 bytes of the original data of the + "bigblock". Remaining bytes (i.e, size of bigblock is + not a multiple of 4) are simply ignored. This is only + to implement a minimal check of destination when + decompressing. + + - Flags: this is a 16 bits field: + + 15 14 13 12 11 10 9 8 + Ŀ + 0 0 0 0 0 0 Abs16 M/S + + 7 6 5 4 3 2 1 0 + Ŀ + R T y p e R 8/16DeltaComp. + + bits marked as "0" MUST be 0 (they are reserved for future + extensions...) Every "1" must be considered as invalid or + unsupported feature (compressed by a newer version of MMCMP) + bits marked as "R" are reserved (used during compression processing + and they don't mean much within the file...) No check should be + performed on those bits. + + - Comp.: 0: not compressed + 1: compressed + - Delta: 0: data is not changed + 1: data is Delta (every byte or word is the difference + between itself and the previous one. First byte or word + is compared to 0. + - 8/16: 0: 8 bits compression scheme + 1: 16 bits compression scheme + - M/S: 0: mono + 1: stereo (not implemented yet) MUST BE 0 + + - Abs16 Whithin compression algorithm, 16 bits samples are + converted to deltas and transformed a bit so there's + no negative numbers. However, some trackers already + convert data to deltas, but there's still the little + transformation to do. + 0: don't do it + 1: do it + Note: This bit IS NOT checked if Delta bit is 1, but + should be 0 in this case. May only be set if + Delta bit is 0. + + - Type: This field doesn't really serve any purpose ;) but + helping identify type of data in this block. There's + no strict identifier but the following block types are + used by MMCMP (warning: do not expect the following to + always be true... data of different types for us (e.g + instrument header and sample header) may be interpreted + as the same type of block (they are contiguous, or + similar, etc...) for better compression.) The three + bits are stored in the order you would expect (MSB at + left, LSB at right) + + 0: Module identifier: the firsts bytes of a module + (this type must NOT be used for anything else...) + 1: Module header: anything useful in the header, which + is not in block-type 0 (actually not used by MMCMP) + 2: instrument header + 3: sample header + 4: patterns + 5: sample + 6: no definition yet... + 7: remaining (every part of the module that hasn't + been thrown into the "block list" (i.e probably + don't fit under any block types...) + + Note that MMCMP sorting scheme puts block of type 0 + first and type 7 last. This is also some sort of + priority. As for now, know that block of type 0 is + UNIQUE and is the FIRST. + + +Scanning files: + + 1. Check if installed and disable MMTSR + 2. Open module + 3. Check signature. If not 'ziRCONia' jump to 11 + 4. read "block offset table" offset field (dword at offset 18) + (and any other info you would like to read) + 5. jump to this position within the file + 6. read the first entry of the table (position of block 0) + 7. jump to this position within the file + 8. read the block header. + 9. If block-type field is not 0, jump to 6 and read the next entry + instead. (the first block should be of type 0. If not, there's + probably no block of this type...) + 10.Read the uncompressed data (it should not have the compressed flag + set) + 11.reenable MMTSR if installed + 12.Do what you would do with the header info and close module if you + wish... diff --git a/InternalDocumentation/NETWORK.TXT b/InternalDocumentation/NETWORK.TXT new file mode 100755 index 0000000..5b09dc5 --- /dev/null +++ b/InternalDocumentation/NETWORK.TXT @@ -0,0 +1,126 @@ + + Network protocol for Impulse Tracker + +Impulse Tracker will only interface with similar versions of IT. + +Block format + +Offset Size Meaning +0 Word Block type +2 Word Block length +4 Data Basic data, depending on block type. +x+[2] Word CRC Check + +Block types + + +Block type 0 - Acknowledge receipt - targeted + + +Offset Size Meaning +0 Word Block type received +2 Word Status + +Status: Bit 0 = Off = OK, On = resend + + +Block type 1 - Ping + + +Offset Size Meaning +0 String "Impulse Tracker 2.?? Ping Packet" + + +Block type 2 - Pattern data packet - global + + +Offset Size Meaning +0 Byte Pattern number +1 Byte Row +2 Byte Column +3 Byte Data mask +4 Varies Data + +Data mask + Bit 0: Note + Bit 1: Instrument + Bit 2: Volume + Bit 3: Effect + Bit 4: Effect data + +Absence of information does NOT imply clearing. + + +Block type 3 - Pattern data block packet - global + + +Offset Size Meaning +0 Byte Pattern number +1 Byte Block width +2 Byte Block height +3 Varies Data + +Data is a block_width * block_height array as structured: + +Data mask: + Bit 0: Note + Bit 1: Instrument + Bit 2: Volume + Bit 3: Effect + Bit 4: Effect data + +Absence of information DOES imply clearing. + + +Block type 4 - "Song Segment variable" modification - global + + +Offset Size Meaning +0 Word Offset in SongSegment +2 Word Length of data +4 Varies Data + + +Block type 5 - Sample data - global + + +Offset Size Meaning +0 Word Sample number +4 DWord Offset in sample +8 Varies Data + + +Block type 6 - Chat packet - targeted/global + + +Offset Size Meaning +0 Word Length of data +2 Varies Data + + + + Functions required of the drivers + + +Initialise - basic setup code. Return error if driver unavailable in current + environment. +Connect Interface - provides connection interface, sets up a tracking + connection, returns a handle +Management Interface - provides management interface for connection, + status information etc. +Disconnect - shut down a tracking connection to a particular handle +MaximumPacketSize - returns the maximum size in bytes that the driver can + process at any time. +Send data - given handle (0 = send to all), data packet (a maximum size as + returned by MaximumPacketsize) +Receive data poll - called frequently by the main program to check for + incoming data. Approx. 2nd highest priority (after + sound driver IRQ) + + + Functions provided to the drivers + + +ProcessDataReveived - called when any data is received. +UnloadDriver - remove driver from memory (when no connections exist any longer) +Alert - when data is not being transferred. diff --git a/InternalDocumentation/OBJECT.TXT b/InternalDocumentation/OBJECT.TXT new file mode 100755 index 0000000..ea0f0ad --- /dev/null +++ b/InternalDocumentation/OBJECT.TXT @@ -0,0 +1,233 @@ +Object Types + + Type 0: Box + Offset 0: DW 0 + Offset 2-5: DB Left/Top/Right/Bottom coordinates + Offset 6: DB Style. + + Style Variables + 0: Thin box, dark all around + 1: Thin box, light all around + 2: Thick box, dark all around + 3: Thick box, light all around + 4: Thin box, 'Up' + 5: Thin box, 'Down' + 6: Thick box, 'Up' + 7: Thick box, 'Down' + 8: Within thin box, 'Up' + 9: Within thin box, 'Down' + 10: Within thick box, 'Up' + 11: Within thick box, 'Down' + 12: Within thin box, dark } + 13: Within thin box, light } Empty boxes. + 14: Within thick box, dark } + 15: Within thick box, light } + +16 = empty within. + + Type 1: Text + Offset 0: DW 1 + Offset 2,3: DB X/Y coordinates + Offset 4: DB Colour + Offset 5: [Text] + + Type 2: Button + Offset 0: DW 2 + Offset 2-9: DW Up/Down/Left/Right associations + Offset 10: DW ButtonUsageType + Offset 12-15: [UsageType Data] + Offset 16: DW ButtonEffectType + Offset 18-27: [ButtonEffectType Data] + Offset 28-31: DB Left/Top/Right/Bottom coordinates + Offset 32: DB Button Style (refer to box style) + Offset 33: DB Button flags + Bit 0: Up/Down flag (0=up, 1=down) + Bit 1: + Offset 34: [Button Text] + + ButtonUsageType Variable + 0: Normal press-release buttons + Data: None + 1: Toggle press/release buttons + Data: None + 2: Radio button effect (one of selection) + Data: DW Min list range, Max list range + + ButtonEffectType + 0: Return Value + Data: DW Return Value + 1: New Object List + Data: DD DWord Ptr ObjectList + 2: Call Function + Data: DD DWord Ptr Function + 3: Set Button variable + Data: DW VariableOffset + DW Value + 4: Jump to Function + Data DD DWord Ptr Function + 5: Set variable + Data DD DWord Ptr Function, returning ES:DI with mem location + DW Value to set it to/check for + DW 2 * Value to pass to function + 6: Check variable, and jump to function + Data DD DWord Ptr Function, returning ES:DI with mem location + DW Value to set it to/check for + DD Function to jump to + + Type 3: Empty + Type 4: Empty + + Type 5: Select Direct Screen + Offset 0: DW 5 + Offset 2: DB Mode (0=Buffered, 1=Direct) + + Type 6: Redefine Characters + Offset 0: DW 6 + Offset 2: DW FirstCharacterToDefine + Offset 4: DW NumberOfCharactersToDefine + Offset 6: [CharacterDefinitionTable] + + Type 7: Empty + + Type 8: Call Far Function + Offset 0: DW 8 + Offset 2: DD DWord Ptr (Pre)Function + + Type 9: Thumb bar + Offset 0: DW 9 + Offset 2: DB X/Y coordinates + Offset 4: DW MinRange, MaxRange + Offset 8: DW WriteData1, WriteData2 + Offset 12: DW Up/Down/Tab/Shift-Tab associations + DW PgUp/PgDn + + WriteData1: + 0:Panning + 1:GetPEVariables + 2:Sample Variables + 3:GetMusicVariables (Song) + 4:Channel Volume settings + 5:LoadSampleVariables + 6:InstrumentVariables + 7:Screen Variables (eg. palette) + 8:Inst (segment) variable + 9:Driver segment, WriteData2 = offset + + Type 10: Infoline + Offset 0: DW 10 + Offset 2: [Text] + + Type 11: Set help context + Offset 0: DW 11 + Offset 2: DW HelpContextNumber + + Type 12: OrderListData + Offset 0: DW 12 + Offset 2: DB X/Y coordinates + Offset 4: DW Length of list (vertical) + Offset 6-9: DW Left/Right associations + + Type 13: 3 Num Entry + Offset 0: DW 13 + Offset 2: DB X/Y coordinates + Offset 4: DW Ptr Info 1 + Offset 6: DW Ptr Info 2 + Offset 8: DD DWord Ptr CheckFunction (0=none) + Offset 12: DW Up/Down/Right/Left associations + + Ptr Info 1: + 0: Instrument header. Ptr Info 2 = offset + + + Type 14: Scalable Thumb bar + Offset 0: DW 14 + Offset 2: DB X/Y coordinates + Offset 4: DW MinRange, MaxRange + Offset 8: DW WriteData1, WriteData2 + Offset 12: DW Up/Down/Tab/Shift-Tab associations + DW PgUp/PgDn + Offset 24 DW DisplayLength + + WriteData1: + 0:Panning + 1:GetPEVariables + 2:Sample Variables + 3:GetMusicVariables (Song) + 4:Channel Volume settings + 5:LoadSampleVariables + 6:InstrumentVariables + 7:Screen Variables (eg. palette) + 8:Inst (segment) variable + 9:Driver segment, WriteData2 = offset + + Type 15: Call Far Function 2 + Offset 0: DW 15 + Offset 2: DD DWord Ptr PreFunction + Offset 6: DD DWord Ptr DrawFunction + Offset 10: DD DWord Ptr Postfunction + + Type 16: String Input + Offset 0: DW 16 + Offset 2: DB X/Y coordinates + Offset 4: DW LocationFunctionNumber1, LocationFunctionNumber2 + Offset 8: DW Size (Length, including terminating null) + Offset 10: DD DWord Ptr FunctionOnEnter (0 = no function) + Offset 14: DW Up/Down/Tab/Shift-Tab associations + + LocationFunctionNumber1 + 0: Disk segment, LFN2 = Offset + 1: SamplePtr. + 2: Instrument segment, LFN2 = Offset + 3: Load Sample Ptr. + 4: Music (song) segment, LFN2 = offset + 5: Function segment, LFN2 = offset + 6: Instrument Ptr. + + Type 17: Toggle + Offset 0: DW 17 + Offset 2: DB X/Y coordinates + Offset 4: DW Ptr Info 1 + Offset 6: DW Ptr Info 2 + Offset 8: DB Bit Toggle + Offset 9: DW Up/Down/Right/Left associations + + Ptr Info 1: + 0: Sample header. Ptr Info 2 = offset in header. + 1: Pattern segment (code). Ptr Info 2 = offset. + 2: Music (song) segment. Ptr Info 2 = offset + 3: Load sample header. Ptr info 2 = offset in header. + 4: Instrument header. Ptr Info 2 = offset in header. + + Type 18: 5NumEntry + Offset 0: DW 18 + Offset 2: DB X/Y coordinates + Offset 4: DW Ptr Info 1 + Offset 6: DW Ptr Info 2 + Offset 8: DD DWord Ptr CheckFunction (0=none) + Offset 12: DW Up/Down/Right/Left associations + + Ptr Info 1: + 0: Sample header. Ptr Info 2 = offset. + 1: Sample load header. Ptr Info 2 = offset. + 2: Inst Segment (for sample resize). + + +Main menu return values. + 0: Function not handled + 1: Redraw screen + 2: Goto prefunction + 3: Goto keyboard input + 4: Handled, return value. + 5: New list in CX:DX, SI contains new action + +;------------ + +Special string data: + ; 0 = End of string + ; 13 = Next line + ; 10 = Toggle character sets + ; 0FFh, x, n = repeat character n 'x' times + ; 0FEh, x = set colour to x + ; 0FDh, 'D' = show decimal number + ; 0FDh, 'X' = show hex number + ; 0FDh, 'S' = show signed number + ; 0FDh, 'L' = show long number diff --git a/Keyboard/BE.ASM b/Keyboard/BE.ASM new file mode 100755 index 0000000..3f5f11f --- /dev/null +++ b/Keyboard/BE.ASM @@ -0,0 +1,637 @@ + + .model tiny + .code + +; Copyrights +; Impulse Tracker v2.14 *BELGIAN* Keyboard Definition File +; Copyright (C) 1998, SiDEWiNDER / DiMENSiON X +; +; You can use this source code as a base for your own keyboard driver, if you +; want to. (BUT NOT FOR A BELGIAN ONE OFCOURSE!!!!!) +; +; Read BE.TXT for more details!! +; +; Contact +; My Email: sidewind@mail.dma.be +; My Homepage: http://fly.to/SiDEWiNDER +; DiMENSiON X WHQ: http://travel.to/DiMENSiON.X +; +; Assembling +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; & + DB 0 + DW '&' + DB 3 ; 1 + DW '1' + DB 7 ; | + DW '|' + DB 0FFh + + DB 3 ; + DB 0 + DW '' + DB 3 ; 2 + DW '2' + DB 7 ; @ + DW '@' + DB 0FFh + + DB 4 ; " + DB 0 + DW '"' + DB 3 ; 3 + DW '3' + DB 7 ; # + DW '#' + DB 0FFh + + DB 5 ; ' + DB 0 + DW '''' + DB 3 ; 4 + DW '4' + DB 0FFh + + DB 6 ; ( + DB 0 + DW '(' + DB 3 ; 5 + DW '5' + DB 0FFh + + DB 7 ; paragraph, translated into $, should be OK... + DB 0 + DW '$' + DB 3 ; 6 + DW '6' + DB 7 ; ^ + DW '^' + DB 0FFh + + DB 8 ; + DB 0 + DW '' + DB 3 ; 7 + DW '7' + DB 0FFh + + DB 9 ; ! + DB 0 + DW '!' + DB 3 ; 8 + DW '8' + DB 0FFh + + DB 10 ; + DB 0 + DW '' + DB 3 ; 9 + DW '9' + DB 7 ; { + DW '{' + DB 0FFh + + DB 11 ; + DB 0 + DW '' + DB 3 ; 0 + DW '0' + DB 7 ; } + DW '}' + DB 0FFh + + DB 12 ; ) + DB 0 + DW ')' + DB 3 ; + DW '' + DB 0FFh + + DB 13 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 17 ; Z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; (sirconflexe)-dead-key... + DB 0 + DW '^' + DB 3 ; (trema)-dead-key... + DW '' + DB 7 ; [ + DW '[' + DB 0FFh + + DB 27 ; $ + DB 0 + DW '$' + DB 3 ; * + DW '*' + DB 7 ; ] + DW ']' + DB 0FFh + + DB 30 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; M + DB 1 + DW 'M' + DB 2 ; m + DW 'm' + DB 0FFh + + DB 40 ; + DB 0 + DW '' + DB 3 ; % + DW '%' + DB 7 ; ` + DW '`' + DB 0FFh + + DB 41 ; + DB 0 + DW '' + DB 0FFh + + DB 43 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 7 ; ' + DW '''' + DB 0FFh + + DB 44 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; , + DB 0 + DW ',' + DB 1 + DW '?' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; ; + DB 0 + DW ';' + DB 3 ; . + DW '.' + DB 0FFh + + DB 52 ; : + DB 0 + DW ':' + DB 3 ; / + DW '/' + DB 0FFh + + DB 53 ; = + DB 0 + DW '=' + DB 3 ; + + DW '+' + DB 7 ; ~ + DW '~' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 7 ; \ + DW '\' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/CA.ASM b/Keyboard/CA.ASM new file mode 100755 index 0000000..88a3544 --- /dev/null +++ b/Keyboard/CA.ASM @@ -0,0 +1,609 @@ + .model tiny + .code +; +; Canadian french keyboard layout for IT by Delta X +; En passant: Salut tous les franais dans le monde!! :) +; +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; @ + DW '"' + DB 7 + DW '@' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '/' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; ^ + DW '?' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '&' + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; * + DW '*' + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ( + DW '(' + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; ) + DW ')' + DB 0FFh + + DB 12 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 13 ; = + DB 0 + DW '=' + DB 3 ; + + DW '+' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; [ + DB 0 + DW '[' + DB 3 ; { + DW '{' + DB 7 + DW '[' + DB 0FFh + + DB 27 ; ] + DB 0 + DW ']' + DB 3 ; } + DW '}' + DB 7 + DW ']' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; ; + DB 0 + DW ';' + DB 3 ; : + DW ':' + DB 7 + DW '~' + DB 0FFh + + DB 40 ; ' + DB 0 + DW "`" + DB 3 ; " + DW "'" + DB 7 + DW '{' + DB 0FFh + + DB 41 ; ` + DB 0 + DW '#' + DB 3 ; ~ + DW '|' + DB 7 + DW '\' + DB 0FFh + + DB 43 ; \ + DB 0 + DW '<' + DB 3 ; | + DW '>' + DB 7 + DW '}' + DB 0FFh + + DB 44 ; z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW "'" + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW '>' + DB 0FFh + + DB 53 ; / + DB 0 + DW '' + DB 3 + DW '' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/CH.ASM b/Keyboard/CH.ASM new file mode 100755 index 0000000..f99397a --- /dev/null +++ b/Keyboard/CH.ASM @@ -0,0 +1,620 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; + + DW '+' + DB 7 ;| + DW '|' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 7 ;@ + DW '@' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; * + DW '*' + DB 7 + DW '#' ;# + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; + DW '' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 7 + DW '' ; + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; / + DW '/' + DB 7 ; + DW '' + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 7 ; + DW '' + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 0FFh + + DB 12 ; ' + DB 0 + DW "'" + DB 3 ; ? + DW '?' + DB 7 ; + DW '' + DB 0FFh + + DB 13 ; ^ + DB 0 + DW '^' + DB 3 ; ` + DW '`' + DB 7 ; ~ + DW '~' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 7 ;[ + DW '[' + DB 0FFh + + DB 27 ; + DB 0 + DW '' + DB 3 ; ! + DW '!' + DB 7 ; ] + DW ']' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW '' + DB 7 ;{ + DW '{' + DB 0FFh + + + DB 41 ; $ + DB 0 + DW '$' + DB 3 ; + DW '' + DB 7 ;} + DW '}' + DB 0FFh + + DB 43 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 7 ; \ + DW '\' + DB 0FFh + + DB 44 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 ; / + DB 0 + DW '-' + DB 3 + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/DE.ASM b/Keyboard/DE.ASM new file mode 100755 index 0000000..c0f202a --- /dev/null +++ b/Keyboard/DE.ASM @@ -0,0 +1,616 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '#' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '/' + DB 7 + DW '{' ; { + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 7 + DW '[' ; [ + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 7 + DW ']' ; ] + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 7 + DW '}' ; } + DB 0FFh + + DB 12 ; + DB 0 + DW '' + DB 3 ; ? + DW '?' + DB 7 + DW '\' ; \ + DB 0FFh + + DB 13 ; ' + DB 0 + DW "'" + DB 3 ; ` + DW "`" + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 7 ; Alt-Gr-Q (Alt-Ctrl-Q) + DW '@' + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1ah + DB 5 ; Alt-Z + DW 2c00h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 27 ; + + DB 0 + DW '+' + DB 3 ; * + DW '*' + DB 7 + DW '~' ; ~ + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW '' + DB 0FFh + + DB 41 + DB 0 + DW "^" + DB 3 + DW "" + DB 0FFh + + DB 43 ; # + DB 0 + DW '#' + DB 3 ; ' + DW "'" + DB 0FFh + + DB 44 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 7 + DW '|' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/DK.ASM b/Keyboard/DK.ASM new file mode 100755 index 0000000..c9d68bd --- /dev/null +++ b/Keyboard/DK.ASM @@ -0,0 +1,616 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 7 + DW "@" ; @ + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '#' + DB 7 + DW '' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '' + DB 7 + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '/' + DB 7 + DW '{' ; { + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 7 + DW '[' ; [ + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 7 + DW ']' ; ] + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 7 + DW '}' ; } + DB 0FFh + + DB 12 ; + + DB 0 + DW '+' + DB 3 ; ? + DW '?' + DB 0FFh + + DB 13 ; ' + DB 0 + DW "" + DB 3 ; ` + DW "`" + DB 7 + DW '|' ; | + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Z + DW 19h + DB 5 ; Alt-Z + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 27 ; . + DB 0 + DW '' + DB 3 ; ~ + DW '^' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW '' + DB 0FFh + + DB 41 + DB 0 + DW "" + DB 3 + DW "" + DB 0FFh + + DB 43 ; * + DB 0 + DW "'" + DB 3 ; ' + DW "*" + DB 0FFh + + DB 44 ; Y + DB 1 + DW 'Z' + DB 2 ; y + DW 'z' + DB 4 ; Ctrl-Y + DW 1ah + DB 5 ; Alt-Y + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 43 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 7 + DW '\' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/ES.ASM b/Keyboard/ES.ASM new file mode 100755 index 0000000..40d3f58 --- /dev/null +++ b/Keyboard/ES.ASM @@ -0,0 +1,620 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 5 ; | + DW '|' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 5 ; @ + DW '@' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; + DW '' + DB 5 ; # + DW '#' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 5 ; ~ + DW '~' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 5 ; + DW '' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; / + DW '/' + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 0FFh + + DB 12 ; ' + DB 0 + DW "'" + DB 3 ; ? + DW '?' + DB 0FFh + + DB 13 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; ` + DB 0 + DW '`' + DB 3 ; ^ + DW '^' + DB 5 ; [ + DW '[' + DB 0FFh + + DB 27 ; + + DB 0 + DW '+' + DB 3 ; * + DW '*' + DB 5 ; ] + DW ']' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 40 ; ' + DB 0 + DW "'" + DB 3 ; + DW '' + DB 5 ; { + DW '{' + DB 0FFh + + DB 41 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 5 ; \ + DW '\' + DB 0FFh + + DB 43 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 5 ; } + DW '}' + DB 0FFh + + DB 44 ; z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 ; ; + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 ; : + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/FI.ASM b/Keyboard/FI.ASM new file mode 100755 index 0000000..6c630a4 --- /dev/null +++ b/Keyboard/FI.ASM @@ -0,0 +1,618 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 7 + DW "@" ; @ + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '#' + DB 7 + DW '' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '' + DB 7 + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; / + DW '/' + DB 7 + DW '{' ; { + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 7 + DW '[' ; [ + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 7 + DW ']' ; ] + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 7 + DW '}' ; } + DB 0FFh + + DB 12 ; + + DB 0 + DW '+' + DB 3 ; ? + DW '?' + DB 7 ; \ + DW '\' + DB 0FFh + + DB 13 ; ' + DB 0 + DW "" + DB 3 ; ` + DW "`" + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 27 ; . + DB 0 + DW '' + DB 3 ; ^ + DW '^' + DB 7 ; ~ + DW '~' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW '' + DB 0FFh + + DB 41 + DB 0 + DW "`" + DB 3 + DW "" + DB 0FFh + + DB 43 ; ' + DB 0 + DW "'" + DB 3 ; * + DW "*" + DB 0FFh + + DB 44 ; Z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 ; m + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 ; ; + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 ; : + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 7 + DW '|' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/FR.ASM b/Keyboard/FR.ASM new file mode 100755 index 0000000..88b4fed --- /dev/null +++ b/Keyboard/FR.ASM @@ -0,0 +1,613 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '&' + DB 3 ; ! + DW '1' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '' + DB 3 ; " + DW '2' + DB 7 + DW "~" ; @ + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '"' + DB 3 ; # + DW '3' + DB 7 + DW "#" + DB 0FFh + + DB 5 ; 4 + DB 0 + DW "'" + DB 3 ; $ + DW '4' + DB 7 + DW '{' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '(' + DB 3 ; % + DW '5' + DB 7 + DW '[' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '-' + DB 3 ; & + DW '6' + DB 7 + DW '|' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '' + DB 3 ; + DW '7' + DB 7 + DW '`' ; + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '_' + DB 3 ; + DW '8' + DB 7 + DW '\' ; + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '' + DB 3 ; + DW '9' + DB 7 + DW '^' ; + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '' + DB 3 ; = + DW '0' + DB 7 + DW '@' ; } + DB 0FFh + + DB 12 ; + + DB 0 + DW ')' + DB 3 ; ? + DW '' + DB 7 + DW ']' + DB 0FFh + + DB 13 ; ' + DB 0 + DW "=" + DB 3 ; ` + DW "+" + DB 7 + DW '}' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'A' + DB 2 ; q + DW 'a' + DB 4 ; Ctrl-Q + DW 1h + DB 5 ; Alt-Q + DW 1E00h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'Z' + DB 2 ; w + DW 'z' + DB 4 ; Ctrl-W + DW 19h + DB 5 ; Alt-W + DW 1500h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Z + DW 19h + DB 5 ; Alt-Z + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '^' + DB 3 ; + DW '' + DB 0FFh + + DB 27 ; . + DB 0 + DW '$' + DB 3 ; ~ + DW '' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'Q' + DB 2 ; a + DW 'q' + DB 4 ; Ctrl-A + DW 11h + DB 5 ; Alt-A + DW 1000h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 1 + DW 'M' + DB 2 ; + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW '%' + DB 0FFh + + DB 41 ; ' + DB 0 + DW "*" + DB 3 ; * + DW "" + DB 0FFh + + DB 43 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 0FFh + + DB 44 ; Y + DB 1 + DW 'W' + DB 2 ; y + DW 'w' + DB 4 ; Ctrl-Y + DW 17h + DB 5 ; Alt-Y + DW 1100h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 0 + DW ',' + DB 3 + DW '?' + DB 0FFh + + DB 51 ; , + DB 0 + DW ';' + DB 3 + DW '.' + DB 0FFh + + DB 52 ; . + DB 0 + DW ':' + DB 3 + DW '/' + DB 0FFh + + DB 53 ; - + DB 0 + DW '!' + DB 3 + DW '!' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/IT.ASM b/Keyboard/IT.ASM new file mode 100755 index 0000000..2c4e3a7 --- /dev/null +++ b/Keyboard/IT.ASM @@ -0,0 +1,588 @@ + .model tiny + .code + +; FIXED Italian keyboard configuration file for Impulse Tracker 2 +; fixed by DjM of Digital Things (DiT) +; why: Italian keyboard has no '`' key; with this configuration file +; note off command can be entered with '\' key (like in FastTracker 2) +; or with the similar ' (apostrophe) key +; to type \ and ' in message editor, use Right Alt + key + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 86 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; Chr(156) + DW 9Ch + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; / + DW '/' + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 0FFh + + DB 12 ; ' used as ` + DB 0 + DW '`' + DB 3 ; ? + DW '?' + DB 7 ; to type ' in message editor + DW 27h + DB 0FFh + + DB 13 ; Chr(141) + DB 0 + DW 8Dh + DB 3 ; ^ + DW '^' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; Chr(138) + DB 0 + DW 8Ah + DB 3 ; Chr(130) + DW 82h + DB 7 ; [ + DW '[' + DB 0FFh + + DB 27 ; + + DB 0 + DW '+' + DB 3 ; * + DW '*' + DB 7 ; ] + DW ']' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; Chr(149) + DB 0 + DW 95h + DB 3 ; Chr(135) + DW 87h + DB 7 ; @ + DW '@' + DB 0FFh + + DB 40 ; Chr(133) + DB 0 + DW 85h + DB 3 ; Chr(248) + DW 0F8h + DB 7 ; # + DW '#' + DB 0FFh + + DB 41 ; \ used as ` + DB 0 + DW "`" + DB 3 ; | + DW "|" + DB 7 ; to type \ in message editor + DW '\' + DB 0FFh + + DB 43 ; Chr(151) + DB 0 + DW 97h + DB 3 ; Chr(21) + DW 15h + DB 0FFh + + DB 44 ; z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 83 ; keypad . + DB 8 + DW '.' + DB 0FFh + + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/KEYBOARD.TXT b/Keyboard/KEYBOARD.TXT new file mode 100755 index 0000000..3f70cfe --- /dev/null +++ b/Keyboard/KEYBOARD.TXT @@ -0,0 +1,12 @@ + +This ZIP contains several different keyboard configurations for Impulse +Tracker. To use a particular configuration file, copy the appropriate file +to KEYBOARD.CFG + +eg. to use a German keyboard configuration (DE.KBD), do + COPY DE.KBD KEYBOARD.CFG + +Make sure that KEYBOARD.CFG is in the same directory as IT.EXE + +An example of how to create your own keyboard file is included in the form +of US.ASM diff --git a/Keyboard/NO.ASM b/Keyboard/NO.ASM new file mode 100755 index 0000000..26484ea --- /dev/null +++ b/Keyboard/NO.ASM @@ -0,0 +1,614 @@ + + .model tiny + .code + +; This keyboard configuration created by Benjamin Bruheim + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 7 + DW "@" ; @ + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '#' + DB 7 + DW '' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '' + DB 7 + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '/' + DB 7 + DW '{' ; { + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 7 + DW '[' ; [ + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 7 + DW ']' ; ] + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 7 + DW '}' ; } + DB 0FFh + + DB 12 ; + + DB 0 + DW '+' + DB 3 ; ? + DW '?' + DB 0FFh + + DB 13 ; ' + DB 0 + DW "\" + DB 3 ; ` + DW "`" + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-y + DW 19h + DB 5 ; Alt-y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 27 ; . + DB 0 + DW '' + DB 3 ; ~ + DW '^' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW "" + DB 3 ; + DW "" + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW "" + DB 0FFh + + DB 41 + DB 0 + DW "|" + DB 3 + DW "" + DB 0FFh + + DB 43 ; ' + DB 0 + DW "'" + DB 3 ; * + DW "*" + DB 0FFh + + DB 44 ; Z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-z + DW 1ah + DB 5 ; Alt-z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/PO.ASM b/Keyboard/PO.ASM new file mode 100755 index 0000000..4ac21d5 --- /dev/null +++ b/Keyboard/PO.ASM @@ -0,0 +1,610 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 + DB 0 + DW '1' + DB 3 + DW '!' + DB 0FFh + + DB 3 + DB 0 + DW '2' + DB 3 + DW '"' + DB 5 + DW '@' + DB 0FFh + + DB 4 + DB 0 + DW '3' + DB 3 + DW '#' + DB 0FFh + + DB 5 + DB 0 + DW '4' + DB 3 + DW '$' + DB 0FFh + + DB 6 + DB 0 + DW '5' + DB 3 + DW '%' + DB 0FFh + + DB 7 + DB 0 + DW '6' + DB 3 + DW '&' + DB 0FFh + + DB 8 + DB 0 + DW '7' + DB 3 + DW '/' + DB 5 + DW '{' + DB 0FFh + + DB 9 + DB 0 + DW '8' + DB 3 + DW '(' + DB 5 + DW '[' + DB 0FFh + + DB 10 + DB 0 + DW '9' + DB 3 + DW ')' + DB 5 + DW ']' + DB 0FFh + + DB 11 + DB 0 + DW '0' + DB 3 + DW '=' + DB 5 + DW '}' + DB 0FFh + + DB 12 + DB 0 + DW '''' + DB 3 + DW '?' + DB 0FFh + + DB 13 + DB 0 + DW '<' + DB 3 + DW '>' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 + DB 0 + DW '+' + DB 3 + DW '*' + DB 0FFh + + DB 27 + DB 0 + DW '''' + DB 3 + DW '`' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 + DB 0 + DW 'c' ; porque o nao funciona no IT + DB 3 + DW 'C' ; porque o nao funciona no IT + DB 0FFh + + DB 40 + DB 0 + DW "o" ; porque o nao funciona no IT + DB 3 + DW 'a' ; porque o nao funciona no IT + DB 0FFh + + DB 41 + DB 0 + DW '\' + DB 3 + DW '|' + DB 0FFh + + DB 43 + DB 0 + DW '~' + DB 3 + DW '^' + DB 0FFh + + DB 44 ; z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 + DB 0 + DW '-' + DB 3 + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; a new key generated by me, for + DB 0 ; the Portuguese keyboard. + DW '<' ; It's located between the + DB 3 ; LShift and the Z key... + DW '>' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/SE.ASM b/Keyboard/SE.ASM new file mode 100755 index 0000000..8b141cd --- /dev/null +++ b/Keyboard/SE.ASM @@ -0,0 +1,612 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 7 + DW "@" ; @ + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '#' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 7 + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; & + DW '&' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '/' + DB 7 + DW '{' ; { + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; ( + DW '(' + DB 7 + DW '[' ; [ + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ) + DW ')' + DB 7 + DW ']' ; ] + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; = + DW '=' + DB 7 + DW '}' ; } + DB 0FFh + + DB 12 ; + + DB 0 + DW '+' + DB 3 ; ? + DW '?' + DB 0FFh + + DB 13 ; ' + DB 0 + DW "'" + DB 3 ; ` + DW "`" + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Z + DW 19h + DB 5 ; Alt-Z + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 27 ; . + DB 0 + DW '.' + DB 3 ; ~ + DW '~' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; + DB 0 + DW '' + DB 3 ; + DW '' + DB 0FFh + + DB 40 ; + DB 0 + DW "" + DB 3 ; + DW '' + DB 0FFh + + DB 41 + DB 0 + DW "^" + DB 3 + DW "+" + DB 0FFh + + DB 43 ; * + DB 0 + DW '*' + DB 3 ; ' + DW "'" + DB 0FFh + + DB 44 ; Y + DB 1 + DW 'Z' + DB 2 ; y + DW 'z' + DB 4 ; Ctrl-Y + DW 1ah + DB 5 ; Alt-Y + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW ';' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW ':' + DB 0FFh + + DB 53 ; - + DB 0 + DW '-' + DB 3 + DW '_' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 43 ; < + DB 0 + DW '<' + DB 3 ; > + DW '>' + DB 7 + DW '|' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/UK.ASM b/Keyboard/UK.ASM new file mode 100755 index 0000000..5896ee6 --- /dev/null +++ b/Keyboard/UK.ASM @@ -0,0 +1,596 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; " + DW '"' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; + DW '' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; ^ + DW '^' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '&' + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; * + DW '*' + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ( + DW '(' + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; ) + DW ')' + DB 0FFh + + DB 12 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 13 ; = + DB 0 + DW '=' + DB 3 ; + + DW '+' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; [ + DB 0 + DW '[' + DB 3 ; { + DW '{' + DB 0FFh + + DB 27 ; ] + DB 0 + DW ']' + DB 3 ; } + DW '}' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; ; + DB 0 + DW ';' + DB 3 ; : + DW ':' + DB 0FFh + + DB 40 ; ' + DB 0 + DW "'" + DB 3 ; @ + DW '@' + DB 0FFh + + DB 41 + DB 0 + DW "`" + DB 0FFh + + DB 43 ; # + DB 0 + DW '#' + DB 3 ; ~ + DW '~' + DB 0FFh + + DB 44 ; z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW '<' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW '>' + DB 0FFh + + DB 53 ; / + DB 0 + DW '/' + DB 3 + DW '?' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 86 ; \ + DB 0 + DW '\' + DB 3 ; | + DW '|' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Keyboard/US.ASM b/Keyboard/US.ASM new file mode 100755 index 0000000..49a22d8 --- /dev/null +++ b/Keyboard/US.ASM @@ -0,0 +1,598 @@ + + .model tiny + .code + +; to create the file: +; TASM +; TLINK /TDC +; REN .COM KEYBOARD.CFG +; +; Structure is: +; Keycode (1 byte) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; Condition (1 byte) +; Return value (1 word) +; . +; . +; . +; 0FFh <-- end of condition/return value list +; +; Keycode is the value in the keypress table in IT on Ctrl-F1 (remember the +; values on the keypress table are in HEX..) +; +; Condition is one of the following +; 0 = requires NO Shift/Ctrl/Alt/..., +; 1 = if Shift and key while caps lock OFF *OR* CAPS lock ON, no ctrl/alt +; 2 = if Shift and key while caps lock ON *OR* CAPS lock OFF, no ctrl/alt +; 3 = if Shift +; 4 = if Ctrl +; 5 = if left/right Alt +; 6 = if Left Alt +; 7 = if Right Alt +; 8 = if Numlock on, no ctrl/alt +; 9 = if Numlock off, no ctrl/alt +; 0FFh = end of list. +; +; Return value is the character, or a DOS character value + +ORG 100h + +FileStart: + +FileLength DW Offset EndKeyboardTable - Offset StartKeyboardTable + +StartKeyboardTable: + + DB 2 ; 1 + DB 0 + DW '1' + DB 3 ; ! + DW '!' + DB 0FFh + + DB 3 ; 2 + DB 0 + DW '2' + DB 3 ; @ + DW '@' + DB 0FFh + + DB 4 ; 3 + DB 0 + DW '3' + DB 3 ; # + DW '#' + DB 0FFh + + DB 5 ; 4 + DB 0 + DW '4' + DB 3 ; $ + DW '$' + DB 0FFh + + DB 6 ; 5 + DB 0 + DW '5' + DB 3 ; % + DW '%' + DB 0FFh + + DB 7 ; 6 + DB 0 + DW '6' + DB 3 ; ^ + DW '^' + DB 0FFh + + DB 8 ; 7 + DB 0 + DW '7' + DB 3 ; & + DW '&' + DB 0FFh + + DB 9 ; 8 + DB 0 + DW '8' + DB 3 ; * + DW '*' + DB 0FFh + + DB 10 ; 9 + DB 0 + DW '9' + DB 3 ; ( + DW '(' + DB 0FFh + + DB 11 ; 0 + DB 0 + DW '0' + DB 3 ; ) + DW ')' + DB 0FFh + + DB 12 ; - + DB 0 + DW '-' + DB 3 ; _ + DW '_' + DB 0FFh + + DB 13 ; = + DB 0 + DW '=' + DB 3 ; + + DW '+' + DB 0FFh + + DB 14 ; Backspace + DB 4 ; Ctrl-Backspace + DW 127 + DB 0FFh + + DB 15 ; Tab + DB 3 ; ShiftTab + DW 0F00h + DB 0FFh + + DB 16 ; Q + DB 1 + DW 'Q' + DB 2 ; q + DW 'q' + DB 4 ; Ctrl-Q + DW 11h + DB 5 ; Alt-Q + DW 1000h + DB 0FFh + + DB 17 ; W + DB 1 + DW 'W' + DB 2 ; w + DW 'w' + DB 4 ; Ctrl-W + DW 17h + DB 5 ; Alt-W + DW 1100h + DB 0FFh + + DB 18 ; E + DB 1 + DW 'E' + DB 2 ;e + DW 'e' + DB 4 ; Ctrl-E + DW 5 + DB 5 ; Alt-E + DW 1200h + DB 0FFh + + DB 19 ; R + DB 1 + DW 'R' + DB 2 ; r + DW 'r' + DB 4 ; Ctrl-R + DW 12h + DB 5 ; Alt-R + DW 1300h + DB 0FFh + + DB 20 ; T + DB 1 + DW 'T' + DB 2 ; t + DW 't' + DB 4 ; Ctrl-T + DW 14h + DB 5 ; Alt-T + DW 1400h + DB 0FFh + + DB 21 ; Y + DB 1 + DW 'Y' + DB 2 ; y + DW 'y' + DB 4 ; Ctrl-Y + DW 19h + DB 5 ; Alt-Y + DW 1500h + DB 0FFh + + DB 22 ; U + DB 1 + DW 'U' + DB 2 ; u + DW 'u' + DB 4 ; Ctrl-U + DW 15h + DB 5 ; Alt-U + DW 1600h + DB 0FFh + + DB 23 ; I + DB 1 + DW 'I' + DB 2 ; i + DW 'i' + DB 4 ; Ctrl-I + DW 9 + DB 5 ; Alt-I + DW 1700h + DB 0FFh + + DB 24 ; O + DB 1 + DW 'O' + DB 2 ; o + DW 'o' + DB 4 ; Ctrl-O + DW 0Fh + DB 5 ; Alt-O + DW 1800h + DB 0FFh + + DB 25 ; P + DB 1 + DW 'P' + DB 2 ; p + DW 'p' + DB 4 ; Ctrl-P + DW 10h + DB 5 ; Alt-P + DW 1900h + DB 0FFh + + DB 26 ; [ + DB 0 + DW '[' + DB 3 ; { + DW '{' + DB 0FFh + + DB 27 ; ] + DB 0 + DW ']' + DB 3 ; } + DW '}' + DB 0FFh + + DB 30 ; A + DB 1 + DW 'A' + DB 2 ; a + DW 'a' + DB 4 ; Ctrl-A + DW 1 + DB 5 ; Alt-A + DW 1E00h + DB 0FFh + + DB 31 ; S + DB 1 + DW 'S' + DB 2 ; s + DW 's' + DB 4 ; Ctrl-S + DW 13h + DB 5 ; Alt-S + DW 1F00h + DB 0FFh + + DB 32 ; D + DB 1 + DW 'D' + DB 2 ; d + DW 'd' + DB 4 ; Ctrl-D + DW 4 + DB 5 ; Alt-D + DW 2000h + DB 0FFh + + DB 33 ; F + DB 1 + DW 'F' + DB 2 ; f + DW 'f' + DB 4 ; Ctrl-F + DW 6 + DB 5 ; Alt-F + DW 2100h + DB 0FFh + + DB 34 ; G + DB 1 + DW 'G' + DB 2 ; g + DW 'g' + DB 4 ; Ctrl-G + DW 7 + DB 5 ; Alt-G + DW 2200h + DB 0FFh + + DB 35 ; H + DB 1 + DW 'H' + DB 2 ; h + DW 'h' + DB 4 ; Ctrl-H + DW 8 + DB 5 ; Alt-H + DW 2300h + DB 0FFh + + DB 36 ; J + DB 1 + DW 'J' + DB 2 ; j + DW 'j' + DB 4 ; Ctrl-J + DW 0Ah + DB 5 ; Alt-J + DW 2400h + DB 0FFh + + DB 37 ; K + DB 1 + DW 'K' + DB 2 ; k + DW 'k' + DB 4 ; Ctrl-K + DW 0Bh + DB 5 ; Alt-K + DW 2500h + DB 0FFh + + DB 38 ; L + DB 1 + DW 'L' + DB 2 ; l + DW 'l' + DB 4 ; Ctrl-L + DW 0Ch + DB 5 ; Alt-L + DW 2600h + DB 0FFh + + DB 39 ; ; + DB 0 + DW ';' + DB 3 ; : + DW ':' + DB 0FFh + + DB 40 ; ' + DB 0 + DW "'" + DB 3 ; " + DW '"' + DB 0FFh + + DB 41 ; ` + DB 0 + DW '`' + DB 3 ; ~ + DW '~' + DB 0FFh + + DB 43 ; \ + DB 0 + DW '\' + DB 3 ; | + DW '|' + DB 0FFh + + DB 44 ; z + DB 1 + DW 'Z' + DB 2 ; z + DW 'z' + DB 4 ; Ctrl-Z + DW 1Ah + DB 5 ; Alt-Z + DW 2C00h + DB 0FFh + + DB 45 ; X + DB 1 + DW 'X' + DB 2 ; x + DW 'x' + DB 4 ; Ctrl-X + DW 1Ah + DB 5 ; Alt-X + DW 2D00h + DB 0FFh + + DB 46 ; C + DB 1 + DW 'C' + DB 2 ; c + DW 'c' + DB 4 ; Ctrl-C + DW 3 + DB 5 ; Alt-C + DW 2E00h + DB 0FFh + + DB 47 ; V + DB 1 + DW 'V' + DB 2 ; v + DW 'v' + DB 4 ; Ctrl-V + DW 16h + DB 5 ; Alt-V + DW 2F00h + DB 0FFh + + DB 48 ; B + DB 1 + DW 'B' + DB 2 ; b + DW 'b' + DB 4 ; Ctrl-B + DW 2 + DB 5 ; Alt-B + DW 3000h + DB 0FFh + + DB 49 ; N + DB 1 + DW 'N' + DB 2 ; n + DW 'n' + DB 4 ; Ctrl-N + DW 0Eh + DB 5 ; Alt-N + DW 3100h + DB 0FFh + + DB 50 ; M + DB 1 + DW 'M' + DB 2 + DW 'm' + DB 4 ; Ctrl-M + DW 0Dh + DB 5 ; Alt-M + DW 3200h + DB 0FFh + + DB 51 ; , + DB 0 + DW ',' + DB 3 + DW '<' + DB 0FFh + + DB 52 ; . + DB 0 + DW '.' + DB 3 + DW '>' + DB 0FFh + + DB 53 ; / + DB 0 + DW '/' + DB 3 + DW '?' + DB 0FFh + + DB 55 ; XT/AT printscreen, Enhanced keyboard * + DB 0 + DW '*' + DB 0FFh + + DB 57 ; Spacebar + DB 0 + DW ' ' + DB 3 + DW ' ' + DB 0FFh + + DB 71 ; Keypad 7 + DB 8 + DW '7' + DB 10 + DW 7 + DB 0FFh + + DB 72 ; Keypad 8 + DB 8 + DW '8' + DB 10 + DW 8 + DB 0FFh + + DB 73 ; Keypad 9 + DB 8 + DW '9' + DB 10 + DW 9 + DB 0FFh + + DB 74 ; Grey - + DB 0 + DW '-' + DB 0FFh + + DB 75 ; Keypad 4 + DB 8 + DW '4' + DB 10 + DW 4 + DB 0FFh + + DB 76 ; Keypad 5 + DB 8 + DW '5' + DB 10 + DW 5 + DB 0FFh + + DB 77 ; Keypad 6 + DB 8 + DW '6' + DB 10 + DW 6 + DB 0FFh + + DB 78 ; Grey + + DB 0 + DW '+' + DB 0FFh + + DB 79 ; Keypad 1 + DB 8 + DW '1' + DB 10 + DW 1 + DB 0FFh + + DB 80 ; Keypad 2 + DB 8 + DW '2' + DB 10 + DW 2 + DB 0FFh + + DB 81 ; Keypad 3 + DB 8 + DW '3' + DB 10 + DW 3 + DB 0FFh + + DB 82 ; Keypad 0 + DB 8 + DW '0' + DB 10 + DW 0 + DB 0FFh + + DB 83 + DB 8 + DW '.' + DB 0FFh + + DB 128+35h ; Grey / + DB 0 + DW '/' + DB 0FFh + + DB 0FFh + +EndKeyboardTable: + +End FileStart diff --git a/Network/DEBUG.INC b/Network/DEBUG.INC new file mode 100755 index 0000000..93f45f6 --- /dev/null +++ b/Network/DEBUG.INC @@ -0,0 +1,130 @@ +; +; Debug macro. To write to the file, use "Trace " +; + +IF TRACEENABLED + +IF CREATENEWLOGFILE +FirstTime DB 0 +ENDIF + +LogFileName DB "Logfile.Txt", 0 + +; + +Proc WriteDebugFile + + PushA + Push DS + + Push CS + Pop DS + + Mov DX, Offset LogFileName + +IF CREATENEWLOGFILE + + Cmp DS:FirstTime, 0 + JNE WriteDebugFile1 + + Mov AH, 3Ch + Xor CX, CX + Int 21h + JC WriteDebugFileEnd + + Mov DS:FirstTime, 1 + XChg AX, BX + Jmp WriteDebugFile2 + + WriteDebugFile1: + +ENDIF + Mov AX, 3D02h + Int 21h + JC WriteDebugFileEnd + + XChg AX, BX + + Mov AX, 4202h + Xor CX, CX + Xor DX, DX + Int 21h ; Move to end of file + +WriteDebugFile2: + Mov AH, 40h + Mov CX, 82 + Mov DX, SI + Int 21h + + Mov AH, 3Eh + Int 21h + +WriteDebugFileEnd: + Pop DS + PopA + Ret + +EndP WriteDebugFile + +; + +Trace Macro LogMessage + Local X, Y + + PushF + Push SI + Jmp Y + X: + DB LogMessage + DB 80-($-Offset X) Dup (0) + DB 0Dh, 0Ah + Y: + Mov SI, Offset X + Call WriteDebugFile + Pop SI + PopF + + EndM + +; + +ELSE + +; + +Trace Macro LogMessage + EndM + +; + +ENDIF + +IF SCREENTRACEENABLED + +ScreenTrace Macro Value + Mov Byte Ptr [FS:0], Value + EndM + +ScreenTraceStart Macro + Push FS + Push 0B800h + Pop FS + EndM + +ScreenTraceEnd Macro + Pop FS + EndM + +ELSE + +ScreenTrace Macro Value + EndM + +ScreenTraceStart Macro + EndM + +ScreenTraceEnd Macro + EndM + +ENDIF + diff --git a/Network/DRHEAD.INC b/Network/DRHEAD.INC new file mode 100755 index 0000000..d4b0f37 --- /dev/null +++ b/Network/DRHEAD.INC @@ -0,0 +1,19 @@ + +NUMREQUIREDVARIABLES EQU 16 ; Number of bytes required from IT.EXE by Driver +NUMREQUIREDFUNCTIONS EQU 32 ; Number of functions (DD Offsets) required by + ; Network driver +NUMPROVIDEDVARIABLES EQU 16 ; Number of bytes provided from driver to IT.EXE +NUMPROVIDEDFUNCTIONS EQU 16 ; Number of functions (DW Offsets) provided by + ; Network driver + +ID DB "Impulse Tracker Network Driver" + DB 26 + DB (62 - ($-Offset ID)) Dup (0) + DB 13, 10 + +DriverID DB DRIVERIDSTRING + DB (62 - ($ - Offset DriverID)) Dup (0) + +LengthOfDriver DW Offset EndDriver - Offset StartDriver + + diff --git a/Network/EXECOM.COM b/Network/EXECOM.COM new file mode 100755 index 0000000000000000000000000000000000000000..dc9924543eea3e59ec6e2b36cf473010fdefd41e GIT binary patch literal 1248 zcmdT?-%Aux6drf?qHZW;AU>3w4T)rPTeB>6-PLT%#Wd*$Nn$YWUUg`k*=Fvz`DW}( zG!Q-ZScEURJuJ+_x(`|uk<|8}5Ya=W_98<;1z8l*xwDn{&>zsi%(?e`-#zDi-<_Xx zQ$psJ`E>PACIk~T^Eb)Hz9Poz%#`;{5RK?f#+oJ=`H%h_n8~HK-Wy}RPT&k z;cTKaxq;}6{X8eM=Q~Kjr;}{S+701uJuzQdk=Ys{|Bh!p*>Zc*{5;=4W{L1+I{m~m zjUU(abk=<}+(3FS7=xYZa1#-XGZ+tJ>`8}PFdV~eJH`;kHX^XHt2~q#`^?%yB3(Am;LOnpZJ^G2+lt%Ol|whPPctZxy%<u-%Td)}NrSs z2*>_%{|qC-geXf12t)^>&KStT!88gYz7nJ3I%xE=A!(8_iYr--i%e1#q;-PM#P}s% z2}Mc@O*qN8nxLT5(Q&GVpz6qoP90F862oo~MB(`5&R~(_+zu?uR25`V8>O%} z&~>U8QmP>*0PRsH@J#c;o_Zv2N=C(rf7y}JP>bW)rsH@RRrA7)fdc?tYI0JOM#mWJ zjn_kC%aInq8&t114: 16 bytes name followed by 12 bytes address (3 sets) +; Max size = 115 bytes. + +; Note: If Destination of Intro was FF:FF:FF:FF:FF:FF (ie. broadcast) +; Then a reply intro must be made + +; Remove: +; Offset 0: DB 2 ; Block type - size = 1 +; Called when a person gains a maximum limit of 3 extra connections +; Or does not wish to be listed in the IPX screen any further. + +; Quit: +; Offset 0: DB 3 ; Block type - size = 1 +; Called when a person unloads the IPX driver for any reason. +; Causes removal from group and removal from listings + +; Talk: +; Offset 0: DB 4 ; Block type, talk +; Offset 1: 16 bytes ; Sender name +; Offset 17: 60 bytes ; Message + +; Close connection ; Remove oneself from the group. +; Offset 0: DB 5 +; Causes removal from group + +; Request connection +; Offset 0: DB 6 +; Offset 1: 16 bytes ; Sender name +; Only nodes with no connections can request connections + +; Accept/Reject connection +; Offset 0: DB 7 +; Offset 1: DB Number of connections including this one. 0 = reject +; Offset 2: Other user information (name (16), full address(12)) +; Reply from requested node. + +; Confirm connection +; Offset 0: DB 8 +; Offset 1: DB Confirm 0 = cancelled +; Offset 2: UserName (16), Full Address (12) +; Add this to the connection list +; Send out this information to anyone already connected to this group. + +; Request intro +; Offset 0: DB 9 + +; Notes: +; The IPX driver will automatically open port 'IT' (4945h) to listen +; for general/maintenance broadcasts (Socket1). Listening packets at +; socket 2 will (only) receive a maximum of 128 bytes. +; A dedicated (dynamically allocated) socket will be used for all music data. +; (Socket2). Socket2 will be able to receive the MAXDATASIZE (1024 bytes) +; Initiate/Terminate connection requests are handled through Socket1 +; Once established, the IPX driver will use 4 packets for listening. +; Each send packet will be timestamped in order to have a maximum timeout, +; after which an error message is generated, giving the user the option to +; drop the participant. +; Acknowledgement packets will be sent for everything received at Socket2 to +; Socket1 of the sender. + +; Required functions: +; GetBuffer(NumberOfBytes) - returns pointer +; SetBuffer(NumberOfBytes, Data) +; GetTimer - returns number of ticks since program startup in EAX. +; Generic Function Handler +; S_GetDestination +; S_DrawString +; SetInfoLine + +; Variables required: +; GlobalKeyList + +; Provided functions: +; DriverScreen +; Poll (Update procedure) + +; Note: IT's network handler will send data to: +; either 0 -> everyone +; or individual connections. +; + +MAXIMUMUSERS EQU 4 +TIMEOUT EQU 10 +SENDTIMEOUT EQU 182 ; 10 seconds +RETRYTIMEOUT EQU 36 ; 2 seconds +MAINTENANCETIMEOUT EQU 18 ; 1 second + +TRACEENABLED EQU 0 +SCREENTRACEENABLED EQU 0 +CREATENEWLOGFILE EQU 1 + +;Ŀ +; Externals +; + +; + + +; + +Segment IPX PARA Public 'Code' USE16 + Assume CS:IPX, DS:Nothing, ES:Nothing + +ORG 0 +StartDriver: + +include vtable.inc +include reqproc.inc + +IPXEntryAddress Label DWord + DW Offset F_Nothing ; Done so that it won't crash if there's +Seg14 DW 0 ; no IPX due to call to Poll + +IPXMaximumPacketSize DW 0 +IPXRetryCount DW 0 + +IntroBlockInformation Label ; **************************************** + DB 1 ; Block type +NumberOfConnections DB 0 + +IF FIXEDUSERNAME + include username.inc +ELSE + CONFIGURATIONOFFSET EQU $+128 + CONFIGURATIONSIZE EQU 16 + UserName DB 16 Dup (0) + IPXLocalAddress Label + IPXNetworkAddress DD 0 ; Do not change order + IPXNodeAddress DW 0, 0, 0 ; + IPXSocket DW 0 ; Dynamic socket +ENDIF + +UserName1 DB 16 Dup (0) +UserAddress1 DB 10 Dup (0) +UserSocket1 DW 0 +UserName2 DB 16 Dup (0) +UserAddress2 DB 10 Dup (0) +UserSocket2 DW 0 +UserName3 DB 16 Dup (0) +UserAddress3 DB 10 Dup (0) ; size = 26*4+2=106 +UserSocket3 DW 0 + +AcknowledgementBlockInformation Label ; ************************************ + DB 0 +PacketID DB 0 ; Size = 2 + +ByteBlockInformation Label +ByteBlock DB 0 + +OldNumberOfConnections DB 0 + +MessageReceived DB 0 +IFE FIXEDUSERNAME +DriverName DB "ITIPX.NET", 0 +ENDIF + +ALIGN 2 + +OldNumNodes DW 0 +NumNodes DW 0 +TopNode DW 0 +CurrentNode DW 0 + +NoReply DB 0 +SendingData DB 0 +SendTime DD 0 +RetryTime DD 0 +LastPacketSize DW 0 + +; ---- Interface stuff -------------------------------------------------------- + +RequestConnectionBox DW 0 + DB 27, 24, 54, 32 + DB 3 + +RequestConnectionText DW 1 + DB 29, 27 + DB 20h + DB "Connection request from:", 13 + DB " " +ConnectionRequestName DB 16 Dup (0) +ConnectionRequestAddress DB 12 Dup (0) +ConnectionRequest DB 0 ; Bit 0 = requesting a connection + ; Bit 1 = connection requested, waiting + ; for reply. + ; Bit 2 = connection accepted, waiting + ; for verification. + ; Bit 7 = leave connetion request box + +IPXHeaderText DW 1 + DB 36, 25 + DB 23h + DB "IPX Driver", 0 + +AcceptButton DW 2 + DW 0FFFFh, 0FFFFh, 4, 4 + DW 0 + DW 0, 0 + DW 0 + DW 1 ; Returns 1 + DW 0, 0, 0, 0 + DB 28, 29, 39, 31 + DB 8 + DB 0 + DB " Accept", 0 + +RejectButton DW 2 + DW 0FFFFh, 0FFFFh, 3, 3 + DW 0 + DW 0, 0 + DW 0 + DW 0 ; Returns 0 + DW 0, 0, 0, 0 + DB 41, 29, 52, 31 + DB 8 + DB 0 + DB " Reject", 0 + +ConnectionRequestList DW 3 + DW IdleFunctionList2 + DW ESCReturn0List + DW RequestConnectionBox + DW IPXHeaderText + DW RequestConnectionText + DW AcceptButton + DW RejectButton + DW 0 + +WaitforConnectList DW 2 + DW IdleFunctionList2 ; Needs check for connection + DW ESCReturn0List ; No global keys. + DW NoIPXBox + DW WaitforConnectText + DW CancelButton + DW 0 + +ConnectionRejectedList DW 2 + DW IdleFunctionList + DW ESCReturn0List + DW NoIPXBox + DW ConnectionRejectedText + DW OKButton + DW 0 + +ConnectionCancelledList DW 2 + DW IdleFunctionList + DW ESCReturn0List + DW NoIPXBox + DW ConnectionCancelledText + DW OKButton + DW 0 + +WaitforConnectText DW 1 + DB 28, 27 + DB 20h + DB "Requesting Connection...", 0 + + +FullScreenBox DW 0 + DB 0, 0, 79, 49 + DB 4 + +NoIPXBox DW 0 + DB 25, 25, 54, 32 + DB 3 + +NoIPXText DW 1 + DB 28, 27 + DB 20h + DB "IPX Network not detected", 0 + +ConnectionRejectedText DW 1 + DB 31, 27 + DB 20h + DB "Connection refused", 0 + +ConnectionCancelledText DW 1 + DB 30, 27 + DB 20h + DB "Connection cancelled", 0 + +NoSocketText DW 1 + DB 27, 27 + DB 20h + DB "IPX Socket request failure", 0 + +IFE FIXEDUSERNAME +UserNameBox DW 0 + DB 31, 29, 48, 31 + DB 27 + +UserNameText DW 1 + DB 29, 27 + DB 20h + DB "Please enter your name", 0 +ENDIF + +ESCReturn0List DB 0 + DW 101h + DW Offset F_Return0 +KeyListSeg1 DW 0 + DB 0FFh + +IFE FIXEDUSERNAME +UserNameInput DW 16 + DB 32, 30 +StringSeg1 DW 0 + DW Offset UserName + DW 16 + DW Offset F_Return1 +StringSeg2 DW 0 + DW 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh +ENDIF + +FillHeader DW 8 +FillHeader2 DD 0 + +DrawHeader DW 8 +DrawHeader2 DD 0 + +OKButton DW 2 + DW 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 0 + DW 0 ; Returns 0 + DW 0, 0, 0, 0 + DB 35, 29, 44, 31 + DB 8 + DB 0 + DB " OK", 0 + +CancelButton DW 2 + DW 0FFFFh, 0FFFFh, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 0 + DW 0 ; Returns 0 + DW 0, 0, 0, 0 + DB 34, 29, 45, 31 + DB 8 + DB 0 + DB " Cancel", 0 + +SocketErrorList DW 2 + DW Near Ptr IdleFunctionList + DW 0 + DW Near Ptr NoIPXBox + DW Near Ptr NoSocketText + DW Near Ptr OKButton + DW Near Ptr FillHeader + DW 0 + +NoIPXMessageList DW 2 + DW Near Ptr IdleFunctionList + DW Near Ptr ESCReturn0List + DW Near Ptr NoIPXBox + DW Near Ptr NoIPXText + DW Near Ptr OKButton + DW Near Ptr FillHeader + DW 0 + +IFE FIXEDUSERNAME +IPXGetName Label + DW 5 + DW Near Ptr IdleFunctionList + DW Near Ptr ESCReturn0List + + DW Near Ptr DrawHeader + DW Near Ptr FillHeader + DW Near Ptr NoIPXBox + DW Near Ptr UserNameText + DW Near Ptr UserNameBox + DW Near Ptr UserNameInput + + DW 0 +ENDIF + +IPXConnectedScreen Label + DW 5 + DW Near Ptr IdleFunctionList2 + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox + DW Near Ptr DrawHeader + DW Near Ptr FillHeader + DW Near Ptr IPXHeader + + DW Near Ptr ConnectionDetailMsg + DW Near Ptr LeaveSessionButton + DW Near Ptr ShowConnectionDetails + + DW Near Ptr MessageBox + DW Near Ptr MessageEnterBox + DW Near Ptr SendMessageText + DW Near Ptr GroupMessageInput + + DW Near Ptr ShowConnectMessages + DW Near Ptr PacketsSentMessage + DW Near Ptr PacketsReceivedMessage + DW Near Ptr PacketsFailedMessage + DW Near Ptr PacketsRetryMessage + DW Near Ptr PacketsAckMessage + + DW 0 + +PacketsSentMessage DW 1 + DB 2, 33 + DB 20h + DB "Packets sent: ", 0FDh, "D", 0 +PacketsSent DW 0 + +PacketsReceivedMessage DW 1 + DB 2, 34 + DB 20h + DB "Packets rcvd: ", 0FDh, "D", 0 +PacketsReceived DW 0 + +PacketsFailedMessage DW 1 + DB 2, 35 + DB 20h + DB "Packets fail: ", 0FDh, "D", 0 +PacketsFailed DW 0 + +PacketsRetryMessage DW 1 + DB 2, 36 + DB 20h + DB "Packets rtry: ", 0FDh, "D", 0 +PacketsRetry DW 0 + +PacketsAckMessage DW 1 + DB 2, 32 + DB 20h + DB "Acks Rcvd: ", 0FDh, "D", 0 +PacketsAck DW 0 + +ConnectionDetailMsg DW 1 + DB 2, 13 + DB 23h + DB "Connection Details", 0 + +LeaveSessionButton DW 2 + DW 10, 10, 0FFFFh, 0FFFFh + DW 0 + DW 0, 0 + DW 4 + DW Offset IPX_LeaveSession +Seg19 DW 0 + DW 0, 0, 0 + DB 61, 12, 78, 14 + DB 8 + DB 0 + DB " Leave", 0 + +ShowConnectionDetails DW 8 + DW Offset IPX_ShowConnectionDetails +Seg20 DW 0 + +IPXScreen Label + DW 5 + DW Near Ptr IdleFunctionList2 + DW Near Ptr GlobalKeyLink + + DW Near Ptr FullScreenBox + DW Near Ptr DrawHeader + DW Near Ptr FillHeader + DW Near Ptr IPXHeader + + DW Near Ptr NodeBox + DW Near Ptr ConnectNetworkList + + DW Near Ptr UnloadDriverButton + + DW Near Ptr MessageBox + DW Near Ptr MessageEnterBox + DW Near Ptr SendMessageText + DW Near Ptr ConnectMessageInput + + DW Near Ptr ShowConnectMessages + + DW 0 + +IPXQueueScreen DW 0 + +IPXHeader DW 10 + DB "IPX Network Driver", 0 + +NodeBox DW 0 + DB 2, 12, 52, 36 + DB 27 + +MessageBox DW 0 + DB 2, 37, 78, 46 + DB 27 + +MessageEnterBox DW 0 + DB 15, 47, 78, 49 + DB 27 + +SendMessageText DW 1 + DB 3, 48 + DB 20h + DB "Send Message", 0 + +ConnectMessageInput DW 16 ; String input + DB 16, 48 +Seg16 DW 0 + DW Offset MessageEntryArea + DW 56 + DW Offset IPX_SendMessage +Seg17 DW 0 + DW 5, 5, 5, 6 + +GroupMessageInput DW 16 ; String input + DB 16, 48 +Seg21 DW 0 + DW Offset MessageEntryArea + DW 56 + DW Offset IPX_SendGroupMessage +Seg22 DW 0 + DW 5, 5, 5, 6 + +ShowConnectMessages DW 8 + DW Offset IPX_DisplayMessages +Seg18 DW 0 + +UnloadDriverButton DW 2 + DW 0FFFFh, 10, 5, 10 + DW 0 + DW 0, 0 + DW 4 + DW Offset IPX_Shutdown +Seg15 DW 0 + DW 0, 0, 0 + DB 61, 12, 78, 14 + DB 8 + DB 0 + DB " Disconnect", 0 + +IdleFunctionList DD 0 + DD 0 + +ConnectNetworkList DW 15 +DrawConnectNetworkList DW Offset IPX_DrawConnect +Seg11 DW 0 +PreConnectNetworkList DW Offset IPX_PreConnect +Seg12 DW 0 +PostConnectNetworkList DW Offset IPX_PostConnect +Seg13 DW 0 + +IdleFunctionList2 DD 0 + DW Offset IdleCheck +IdleSeg DW 0 + DD 0 + +GlobalKeyLink DB 7 +GlobalKeyLink2 DD 0 + +Label ConnectKeys Byte + DB 0 + DW 1C8h ; Up arrow + DW IPX_ConnectUp + + DB 0 + DW 1D0h ; Down arrow + DW IPX_ConnectDown + + DB 0 ; PgUp + DW 1C9h + DW IPX_ConnectPgUp + + DB 0 ; PgDn + DW 1D1h + DW IPX_ConnectPgDn + + DB 0 + DW 1C7h + DW IPX_ConnectHome + + DB 0 + DW 1CFh + DW IPX_ConnectEnd + + DB 0 ; Tab + DW 10Fh + DW IPX_ConnectTab + + DB 0 + DW 11Ch + DW IPX_ConnectEnter + + DB 0FFh + +; + +MessageBlock DB 4 +MessageSenderName DB 16 Dup (0) +MessageEntryArea DB 56 Dup (0) + +MessageData DB 72*8 Dup (0) + +InfoListMessage DB 64 Dup (0) +ConnectionNumberMsg DB "Connection Number ", 0FDh, "D", 0Dh + DB " User name: ", 0 +ConnectionAddressMsg DB " User address: ", 0 +UnknownPacketMessage DB "IPX Error: Unknown Packet Type Received", 0 + +; This prompt needs to be reworded. +AutoRejectMessage DB "IPX AutoRejectConnection: " +ClosedMessage DB "IPX ClosedConnection: " +AutoDropMessage DB "IPX DropConnection: " + +; + +Macro_MaintenanceRHeader Macro Index + MaintenanceRHeader&Index& Label + DW 0 ; Checksum + DW 0 ; Length + DB 0 ; Transport Control + DB 4 ; Packet type + DB 12 Dup (0) ; Destination Address + DB 12 Dup (0) ; Source Address + MaintenanceRData&Index& Label + DB 128 Dup (0) + +EndM + + IndexCounter = 1 + Rept 4 + Macro_MaintenanceRHeader %IndexCounter + IndexCounter = IndexCounter+1 + EndM + +MaintenanceSendHeaderBroadcast Label + DW 0 ; Checksum + DW 0 ; Length + DB 0 ; Transport Control + DB 4 ; Packet type + DB 0, 0, 0, 0 ; Destination net address + DB 0FFh, 0FFh, 0FFh, 0FFh, 0FFh, 0FFh ; Node address - broadcast + DW 'IT' ; Destination socket + DB 12 Dup (0) ; Source Address + +MaintenanceSendHeaderDirected Label + DW 0 ; Checksum + DW 0 ; Length + DB 0 ; Transport Control + DB 4 ; Packet type +MaintenanceDirectedDestination Label + DB 12 Dup (0) ; Destination address + DB 12 Dup (0) ; Source Address + +MaintenanceECB1 Label + DD 0 ; Link Address - IPX controlled + DW Offset MaintenanceESR +MESeg1 DW 0 + DB 0 ; In use flag - IPX controlled + DB 0 ; Completion code - IPX controlled + DW 'IT' ; Socket Number - Required + DB 16 Dup (0) ; IPX workspace - IPX controlled + DB 6 Dup (0) ; Immediate address - IPX controlled + DW 2 ; Fragment count - Required + DW Offset MaintenanceRHeader1 +Seg1 DW 0 + DW 30 ; Fragment size 1 + DW Offset MaintenanceRData1 +Seg2 DW 0 + DW 128 ; Fragment size 2 + +MaintenanceECB2 Label + DD 0 ; Link Address - IPX controlled + DW Offset MaintenanceESR +MESeg2 DW 0 + DB 0 ; In use flag - IPX controlled + DB 0 ; Completion code - IPX controlled + DW 'IT' ; Socket Number - Required + DB 16 Dup (0) ; IPX workspace - IPX controlled + DB 6 Dup (0) ; Immediate address - IPX controlled + DW 2 ; Fragment count - Required + DW Offset MaintenanceRHeader2 +Seg3 DW 0 + DW 30 ; Fragment size 1 + DW Offset MaintenanceRData2 +Seg4 DW 0 + DW 128 ; Fragment size 2 + +MaintenanceECB3 Label + DD 0 ; Link Address - IPX controlled + DW Offset MaintenanceESR +MESeg3 DW 0 + DB 0 ; In use flag - IPX controlled + DB 0 ; Completion code - IPX controlled + DW 'IT' ; Socket Number - Required + DB 16 Dup (0) ; IPX workspace - IPX controlled + DB 6 Dup (0) ; Immediate address - IPX controlled + DW 2 ; Fragment count - Required + DW Offset MaintenanceRHeader3 +Seg5 DW 0 + DW 30 ; Fragment size 1 + DW Offset MaintenanceRData3 +Seg6 DW 0 + DW 128 ; Fragment size 2 + +MaintenanceECB4 Label + DD 0 ; Link Address - IPX controlled + DW Offset MaintenanceESR +MESeg4 DW 0 + DB 0 ; In use flag - IPX controlled + DB 0 ; Completion code - IPX controlled + DW 'IT' ; Socket Number - Required + DB 16 Dup (0) ; IPX workspace - IPX controlled + DB 6 Dup (0) ; Immediate address - IPX controlled + DW 2 ; Fragment count - Required + DW Offset MaintenanceRHeader4 +Seg7 DW 0 + DW 30 ; Fragment size 1 + DW Offset MaintenanceRData4 +Seg8 DW 0 + DW 128 ; Fragment size 2 + +MaintenanceSendECB Label + DD 0 ; Link Address - IPX controlled + DD 0 +SendECBInUse Label Byte + DB 0 ; In use flag - IPX controlled + DB 0 ; Completion Code - IPX controlled + DW 'IT' ; Socket Number - Required + DB 16 Dup (0) ; IPX workspace - IPX controlled +MSendDest DB 6 Dup (0FFh); Immediate address - broadcast + DW 2 ; Fragment count - Required +MaintenanceSendHeader DW 0 +Seg9 DW 0 + DW 30 ; Fragment size 1 +MaintenanceSendDataOffset DW 0 +Seg10 DW 0 +MaintenanceSendDataSize DW 0 + +; + +MaintenanceSData DB 128 Dup (0) + +; + + +;Data packet definitions. + +Zero DB 0 +Ten DB 10 + +NUMBEROFLISTENINGPACKETS EQU 4 +MAXDATASIZE EQU 1024 + +Macro_DataReceiveBlock Macro Index + DataReceiveHeader&Index& Label + DW 0 ; Checksum + DW 0 ; Length + DB 0 ; Transport Control + DB 4 ; Packet type + DB 12 Dup (0) ; Destination Address + DB 12 Dup (0) ; Source Address + DataReceive&Index& Label + DB MAXDATASIZE Dup (0) + + DataReceiveECB&Index& Label + DD 0 ; Link Address -IPX controlled + DW Offset DataESR + DataSegA&Index& DW 0 + DB 0 ; In use flag -IPX controlled + DB 0 ; Completion code-IPX controlled + DSocket&Index& DW 0 ; Socket Number -Required + DB 16 Dup (0) ; IPX workspace -IPX controlled + DB 6 Dup (0) ; Immediate addr -IPX controlled + DW 2 ; Fragment count -Required + DW Offset DataReceiveHeader&Index& + DataSegB&Index& DW 0 + DW 30 ; Fragment Size 1 + DW Offset DataReceive&Index& + DataSegC&Index& DW 0 + DW MAXDATASIZE ; Fragment size 2 + +EndM + +Macro_SendAckBlock Macro Index + + SendAckHeader&Index& Label + DW 0 ; Checksum + DW 0 ; Length + DB 0 ; Transport Control + DB 4 ; Packet type + DB 10 Dup (0) ; Destination Address + DW 'IT' + DB 12 Dup (0) ; Source Address + + SendAckECB&Index& Label + DD 0 ; Link Address -IPX controlled + DD 0 ; ESR Address -None + DB 0 ; In use flag -IPX controlled + DB 0 ; Completion code-IPX controlled + DW 'IT' ; Socket Number -Required + DB 16 Dup (0) ; IPX workspace -IPX controlled + DB 6 Dup (0) ; Immediate addr -IPX controlled + DW 2 ; Fragment count -Required + DW Offset SendAckHeader&Index& + SendAckA&Index& DW 0 + DW 30 ; Fragment Size 1 + DW Offset Zero ; Offset 42 = 2Ah + SendAckB&Index& DW 0 + DW 1 + +EndM + + IndexCounter = 1 + Rept NUMBEROFLISTENINGPACKETS + Macro_DataReceiveBlock %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + + IndexCounter = 1 + Rept (MAXIMUMUSERS-1) + Macro_SendAckBlock %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + + +Macro_DataSendBlock Macro Index + DataSendHeader&Index& Label + DW 0 ; Checksum + DW 0 ; Length + DB 0 ; Transport Control + DB 4 ; Packet type + DB 12 Dup (0) ; Destination Address + DB 12 Dup (0) ; Source Address + + DataSendECB&Index& Label + DD 0 ; Link Address -IPX controlled + DW Offset SendDataESR + SDataSegA&Index& DW 0 + DB 0 ; In use flag -IPX controlled + SResult&Index& DB 0 ; Completion code-IPX controlled + SDSocket&Index& DW 0 ; Socket Number -Required + DB 16 Dup (0) ; IPX workspace -IPX controlled + DB 6 Dup (0) ; Immediate addr -IPX controlled + DW 2 ; Fragment count -Required + DW Offset DataSendHeader&Index& + SDataSegB&Index& DW 0 + DW 30 ; Fragment Size 1 + DW Offset DataSend + SDataSegC&Index& DW 0 + DW MAXDATASIZE ; Fragment size 2 +EndM + + DataSend DB MAXDATASIZE Dup (0) + + IndexCounter = 1 + Rept 3 + Macro_DataSendBlock %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + +; +; RELOCATION TABLE +; + +Macro_DataSegments Macro Index + DW Offset DataSegA&Index& + DW Offset DataSegB&Index& + DW Offset DataSegC&Index& +EndM + +Macro_AckSegments Macro Index + DW Offset SendAckA&Index& + DW Offset SendAckB&Index& +EndM + +Macro_SDataSegments Macro Index + DW Offset SDataSegA&Index& + DW Offset SDataSegB&Index& + DW Offset SDataSegC&Index& +EndM + +RelocationTable Label Word + DW Offset Seg1, Offset Seg2, Offset Seg3, Offset Seg4 + DW Offset Seg5, Offset Seg6, Offset Seg7, Offset Seg8 + DW Offset Seg9, Offset Seg10 +IFE FIXEDUSERNAME + DW Offset StringSeg1, Offset StringSeg2 +ENDIF + DW Offset MESeg1, Offset MESeg2, Offset MESeg3, Offset MESeg4 + Dw Offset KeyListSeg1, Offset IdleSeg, Offset Seg11, Offset Seg12 + DW Offset Seg13, Offset Seg14, Offset Seg15, Offset Seg16 + DW Offset Seg17, Offset Seg18, Offset Seg19, Offset Seg20 + DW Offset Seg21, Offset Seg22 + + IndexCounter = 1 + Rept NUMBEROFLISTENINGPACKETS + Macro_DataSegments %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + + IndexCounter = 1 + Rept (MAXIMUMUSERS-1) + Macro_AckSegments %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + + IndexCounter = 1 + Rept 3 + Macro_SDataSegments %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + + DW 0 + +; + +include debug.inc + +; + +Proc F_Nothing Far + + Xor AX, AX + Ret + +EndP F_Nothing + +; + +Proc F_Return0 Far + + Xor DX, DX + Mov AX, 4 + + Ret + +EndP F_Return0 + +; + +Proc F_Return1 Far + + Cmp Byte Ptr [CS:UserName], 0 + JE F_Return0 + + Mov DX, 1 + Mov AX, 4 + Ret + +EndP F_Return1 + +; + +Proc IdleCheck Far + + Push CS + Pop DS + Assume DS:IPX + + Mov AL, ConnectionRequest + And ConnectionRequest, 0Fh + + Test AL, 1 + JZ IdleCheckConnectionRequestBit1 + +IdleCheckConnectionRequestBit0: ; OK.. connection around + Test AL, AL + JNS IdleNoRedraw + + Mov DX, 1 ; Return 1. + Jmp IdleCheckReturnValue + +IdleCheckConnectionRequestBit1: ; If connection is cancelled before + Test AL, 2 + JZ IdleCheckNoConnectionRequest + + Test AL, AL ; Acceptance or Rejection. + JNS IdleNoRedraw + + Mov DX, 2 + +IdleCheckReturnValue: + Mov AX, 5 + Mov DI, 4 + Ret + +IdleCheckNoConnectionRequest: + Mov AL, NumberOfConnections + Cmp OldNumberOfConnections, AL + Mov OldNumberOfConnections, AL + JE IdleCheck3 + +; Mov AX, 5 +; Mov DI, 1 ; Redraw +; Ret + Jmp IPX_DriverScreen + +IdleCheck3: + Mov AX, NumNodes + Cmp AX, OldNumNodes + Mov OldNumNodes, AX + JE IdleCheck1 + +IdleCheck2: + Mov AX, 1 + Ret + +IdleCheck1: + Cmp MessageReceived, 0 + Mov MessageReceived, 0 + JNE IdleCheck2 + +IdleNoRedraw: + Xor AX, AX + Ret + +EndP IdleCheck + Assume DS:Nothing + +; + +Proc TransferDestinationAddress ; SI = Header + + Push AX + Push CX + Push SI + Push DI + + Add SI, 12h + Mov DI, Offset MaintenanceDirectedDestination + Mov CX, 10/2 + Rep MovsW + Mov AX, 'IT' + StosW + + Pop DI + Pop SI + Pop CX + Pop AX + Ret + +EndP TransferDestinationAddress + +; + +Proc NodeSearch ; DS gets set to DiskDataArea + ; Given EAX:EDX = Node address + ; Returns carry if found and BX = address + Assume DS:IPX + + Mov CX, NumNodes + Mov DS, DiskDataArea + Assume DS:Nothing + +; ClC +; Ret + + Xor BX, BX + JCXZ NodeSearch2 + +NodeSearch1: + Cmp [BX+20], EAX + JNE NodeSearch3 + Cmp [BX+24], EDX + JNE NodeSearch3 + + StC + Ret + +NodeSearch3: + Add BX, 32 + Loop NodeSearch1 +; Dec CX +; JNZ NodeSearch1 + +NodeSearch2: + Ret + +EndP NodeSearch + +; + +Proc CheckFromSelf + + Push SI + Push DI + + Add SI, 12h ; Source internetwork address + Mov DI, Offset IPXLocalAddress + Mov CX, 10 + RepE CmpSB + + Pop DI + Pop SI + + Ret + +EndP CheckFromSelf + +; + +Proc ConnectionReject + + Mov DI, Offset MaintenanceSData + Mov AX, 7 + StosW + Call IPX_MaintenanceSendData + Ret + +EndP ConnectionReject + +; + +Proc FindConnection ; Returns carry set if not found, + ; BX = address, AX = connection number + ; 0 = first connect + Assume DS:IPX + + Push CX + Push SI + Push DI + + Xor AX, AX + Add SI, 18 ; Address of sender + Mov DI, Offset UserAddress1 + +FindConnection1: + Cmp AL, NumberOfConnections + JAE FindConnection2 + + Mov CX, 10 + Push SI + RepE CmpsB + Pop SI + JE FindConnection3 + + Add DI, CX + Inc AX + Add DI, 16+12-10 + Jmp FindConnection1 + +FindConnection2: + StC + +FindConnection3: + LEA BX, [DI-26] + + Pop DI + Pop SI + Pop CX + Ret + +EndP FindConnection + +; + +Proc RemoveFromGroup ; Assumes DS = CS = IPX + + Call FindConnection + JC RemoveFromGroupEnd + + PushA + Push ES + + Push DS + Pop ES + + Mov AH, 6 + Mul AH + Mov BX, AX + + Mov SI, Offset ClosedMessage + Mov DI, Offset InfoListMessage + Mov CX, 22/2 + Rep MovsW + Mov SI, [SendPacketInformation+BX] + Sub SI, 16 + Mov CX, 16/2 + Rep MovsW + Mov BX, 100 + Mov SI, Offset InfoListMessage + Call IT_SetInfoLine + + Pop ES + PopA + +Proc RemoveFromGroup2 + Assume DS:IPX + + Push AX + + Mov AH, NumberOfConnections + Sub AH, AL + + Mov DI, BX + LEA SI, [BX+28] + + Dec NumberOfConnections + Mov AL, 28/2 + Mul AH + + Mov CX, AX + Rep MovsW + +; Remove from ack list + Pop CX + + Mov AX, 0FFFEh + ShL AL, CL ; AL = mask for 'upper' bits + ShL AH, CL + Not AH ; AH = mask for 'lower' bits + Mov CL, SendingData + And AL, CL + And AH, CL + ShR AL, 1 + Or AL, AH + Mov SendingData, AL + +RemoveFromGroupEnd: + Ret + +EndP RemoveFromGroup2 +EndP RemoveFromGroup + Assume DS:Nothing + +; + +Proc SendDataOK ; Returns carry if data is still + ; pending to send. + Assume DS:IPX + + Xor AX, AX + Mov AL, NumberOfConnections + + Test AL, AL + JZ SendDataOK_Fail + + Cmp SResult1, 0 + JNE SendDataOK_Fail + Dec AX + JZ SendDataOK_End + + Cmp SResult2, 0 + JNE SendDataOK_Fail + Dec AX + JZ SendDataOK_End + + Cmp SResult3, 0 + JE SendDataOK_End + +SendDataOK_Fail: + StC + +SendDataOK_End: + Ret + +EndP SendDataOK + Assume DS:Nothing + +; + +Macro_AckOffsets Macro Index + DW Offset SendAckHeader&Index&+6 + DW Offset SendAckECB&Index& +EndM + +AckOffsets Label + IndexCounter = 1 + Rept (MAXIMUMUSERS-1) + Macro_AckOffsets %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + +PacketReceived DB 0 + +Proc DataESR Far + + PushF + PushAD + Push DS + + ScreenTraceStart + + Push ES + Push SI + + Push CS + Pop DS + Assume DS:IPX ; Also ES = IPX + + ScreenTrace '0' + + ClD + + Mov PacketReceived, 1 + Inc PacketsReceived + + Trace "R: ESR" + ScreenTrace '1' + + Cmp Byte Ptr [SI+9], 0 ; Received packet successfully? + JNE DESRBadPacket + + Mov DI, [SI+2Ah] ; Offset to fragment 2 + Mov SI, [SI+24h] ; Offset to fragment 1 (ie. header) + Mov CX, [SI+2] + XChg CH, CL + Sub CX, 30 + + ScreenTrace '2' + + Call FindConnection + JC DESRRelisten + + ScreenTrace '3' + +; Send acknowledgement + PushA + Push DS + Push ES + + Mov BX, AX + Mov SI, DI + Call IT_ReceiveData + + ScreenTrace '4' + + Pop ES + Pop DS + PopA + + PushF + Mov BX, AX + ShL BX, 2 + + Mov EAX, [SI+12h] + Mov ECX, [SI+16h] + Mov DX, [SI+1Ah] + + Mov DI, [AckOffsets+BX] + StosD + Mov [DI], ECX + Mov [DI+4], DX + Mov SI, [AckOffsets+BX+2] + Mov [SI+28], ECX + Mov [SI+32], DX + + Mov Word Ptr [SI+2Ah], Offset Zero + + PopF + JNC DESRNoBadPacket + +DESRBadPacket: + ScreenTrace '5' + + Mov Word Ptr [SI+2Ah], Offset Ten + Inc PacketsFailed + +DESRNoBadPacket: + ScreenTrace '6' + + Mov BX, 3 + Call [DWord Ptr IPXEntryAddress] + + ScreenTrace '7' + Trace "R: Source recognised" + + Jmp DESRRelisten + +DESRRelisten: + ScreenTrace '8' + Pop SI + Pop ES + + Trace "R: Packet relisten to socket" + + Mov BX, 4 ; Relisten to the socket. + Call [DWord Ptr IPXEntryAddress] + + ScreenTrace '9' + + ScreenTraceEnd + + Pop DS + PopAD + PopF + Ret + +EndP DataESR + Assume DS:Nothing + +; + +Proc SendDataGivenBX ; Given BX = Offset to SendPacketInfo stuff + + Mov SI, [BX] + Mov DI, [BX+2] + Mov CX, 6 + Rep MovsW + + Sub SI, 8 + Mov DI, [BX+4] + Add DI, 28 ; Immediate address + + MovsW + MovsW + MovsW + + Inc PacketsSent + + Push AX + Push BX + Mov SI, [BX+4] + Mov BX, LastPacketSize + Mov AX, IPXSocket + Mov [SI+0Ah], AX ; Socket Number + Mov [SI+2Eh], BX + Mov BX, 3 + Call [DWord Ptr IPXEntryAddress] + + Pop BX + Pop AX + + Ret + +EndP SendDataGivenBX + +; + +SendPacketInformation DW Offset UserAddress1, Offset DataSendHeader1+6, Offset DataSendECB1 + DW Offset UserAddress2, Offset DataSendHeader2+6, Offset DataSendECB2 + DW Offset UserAddress3, Offset DataSendHeader3+6, Offset DataSendECB3 + +Proc SendITData Near + + PushAD + PushF + Push DS + Push ES + + Push CS + Push CS + Pop ES + Pop DS + Assume DS:IPX + + Cmp SendingData, 0 + JNE SendITDataCheckTime + + Mov AX, MAXDATASIZE + Mov DI, Offset DataSend + Call IT_SendData + Test CX, CX + JZ SendITDataEnd ; No Network Data to send + + Call IT_GetTime ; Returns EAX + Mov SendTime, EAX + Mov RetryTime, EAX + + Mov LastPacketSize, CX + + Mov AL, NumberOfConnections + Mov BX, Offset SendPacketInformation + + Test AL, AL + JZ SendITDataEnd + + Test DL, DL + JNZ SendITDataSingle + +; Have to send to all connections + + Mov CL, AL + Mov CH, 1 + ShL CH, CL + Dec CH + Mov SendingData, CH + +SendITData1: + Trace "Sending broadcast packet" + + Call SendDataGivenBX + + Add BX, 6 + Dec AL + + JNZ SendITData1 + + Jmp SendITDataEnd + +SendITDataSingle: + Trace "Sending single packet" + + Cmp DL, AL + JA SendITDataEnd ; Invalid destination + + Mov CL, AL + Mov CH, 1 + Dec CX + ShL CH, CL + Mov SendingData, CH + +; Have to send to single destination + Mov AL, 6 + Mul DL ; AX = Destination*6 + + Add BX, AX + Sub BX, 6 + Call SendDataGivenBX + Jmp SendITDataEnd + +SendITDataCheckTime: + Mov DL, NumberOfConnections + Test DL, DL + JZ SendITDataEnd + + Call IT_GetTime + Mov EBX, EAX + Mov ECX, EAX + Sub EBX, RetryTime + Sub ECX, SendTime + + Cmp EBX, RETRYTIMEOUT + JB SendITDataEnd + +; Check for true timeout.. drop if so. + Cmp ECX, SENDTIMEOUT + JA SendITDataTimeout + +; Else retry sending packet. + Mov RetryTime, EAX + + Mov AL, SendingData + Mov BX, Offset SendPacketInformation + +SendITDataRetry: + ShR AL, 1 + JNC SendITDataRetry2 + + Call SendDataGivenBX + Inc PacketsRetry + +SendITDataRetry2: + Add BX, 6 + Dec DL + JNZ SendITDataRetry + + Jmp SendITDataEnd + +SendITDataTimeout: + Xor AX, AX ; AX = connection number + Mov DH, SendingData + +SendITDataTimeout1: + ShR DH, 1 + JNC SendITDataTimeout2 + + Mov AH, 6 + Mul AH + Mov BX, AX + + Mov SI, Offset AutoDropMessage + Mov DI, Offset InfoListMessage + Mov CX, 20/2 + Rep MovsW + Mov SI, [SendPacketInformation+BX] + Sub SI, 16 + Mov CX, 16/2 + Rep MovsW + Mov BX, 100 + Mov SI, Offset InfoListMessage + Call IT_SetInfoLine + + Call RemoveFromGroup2 + Jmp SendITDataEnd + +SendITDataTimeout2: + Inc AX + Dec DL + JNZ SendITDataTimeout1 + +SendITDataEnd: + Pop ES + Pop DS + PopF + PopAD + + Ret + +EndP SendITData + +; + +Proc SendDataESR Far + + Push DS + PushF + + ScreenTraceStart + + Push CS + Pop DS + Assume DS:IPX ; Also ES = IPX + ClD + + Trace "S: ESR" + ScreenTrace 'A' + + Cmp Byte Ptr [SI+9], 0 ; Received packet successfully? + JNE SDESRResend + + ScreenTrace 'B' + Call SendITData + + ScreenTrace 'C' + + ScreenTraceEnd + + PopF + Pop DS + Ret + +SDESRResend: + Inc PacketsFailed + + ScreenTrace 'D' + + Mov BX, 3 + Call [DWord Ptr IPXEntryAddress] + + ScreenTrace 'E' + + ScreenTraceEnd + + PopF + Pop DS + Ret + +EndP SendDataESR + Assume DS:Nothing + +; + +MAXIMUMBLOCKTYPE = 10 + +MESRBlockOffsets Label Word + DW Offset MESRBlockType0, Offset MESRBlockType1 + DW Offset MESRBlockType2, Offset MESRBlockType3 + DW Offset MESRBlockType4, Offset MESRBlockType5 + DW Offset MESRBlockType6, Offset MESRBlockType7 + DW Offset MESRBlockType8, Offset MESRBlockType9 + DW Offset MESRBLockType10 + +; + +Proc MaintenanceESR Far ; Given ES:SI = ECB + + PushF + PushAD + + ScreenTraceStart + + Push DS + Push SI + + ClD + + Push CS + Pop DS + Assume DS:IPX ; Also ES = IPX + + ScreenTrace 'a' + + Cmp Byte Ptr [SI+9], 0 ; Received packet successfully? + JNE MESRRelisten + + ScreenTrace 'b' + + Mov DI, [SI+2Ah] ; Offset to fragment 2 + Mov SI, [SI+24h] ; Offset to fragment 1 (ie. header) + + Mov DX, [DI] ; DL = block type + Mov BX, DX + And BX, 0FFh + Cmp BL, MAXIMUMBLOCKTYPE + JA MESRBlockTypeUnknown + Add BX, BX + Jmp [MESRBlockOffsets+BX] + +MESRBlockType0: ; Acknowledgement + ScreenTrace 'c' + + Call FindConnection + JC MESRBlockType0End + + Inc PacketsAck + Mov CX, AX + Mov AL, 0FEh + + RoL AL, CL + And SendingData, AL + + ScreenTrace 'd' + + Call SendITData + +MESRBlockType0End: + ScreenTrace 'e' + + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType1: ; Intro + ScreenTrace 'f' +; Cmp NumberOfConnections, 3 ; Don't respond if 3 connections already! +; JE MESRBlockType1End + + ; Ignore packets from self........ + + Call CheckFromSelf + JE MESRBlockType1End + + ScreenTrace 'g' + + ; ................................. + +; Now check whether destination was broadcast... + + Cmp Byte Ptr [DI+1], 0 + JNE MESRBlockType1NoReply + + Cmp Word Ptr [SI+0Ah], 0FFFFh + JNE MESRBlockType1NoReply + Cmp DWord Ptr [SI+0Ch], 0FFFFFFFFh + JNE MESRBlockType1NoReply + + Cmp NoReply, 0 + JNE MESRBlockType1End +; Yes it was broadcast.. now reply.. + + ScreenTrace 'h' + + Mov AL, 1 + Call SendConnectionData + + ScreenTrace 'i' + +MESRBlockType1NoReply: + ScreenTrace 'j' + +; Don't log if we don't want to log (ie. only log if current mode = 24) + +; Cmp NumberOfConnections, 0 +; JNE MESRBlockType1End + Call IT_GetCurrentMode + Cmp AL, 24 + JNE MESRBlockType1End + + ScreenTrace 'k' + +; Don't log if already logged.. + + Mov EAX, [SI+20] ; Sender's ID + Mov EDX, [SI+24] + + Call NodeSearch + JC MESRBlockType1End + + ScreenTrace 'l' + +; Don't have the node -> log it! + + LEA SI, [DI+2] + Push CS + Push DS + Pop ES + Pop DS + + Mov DI, NumNodes + Xor DX, DX + + Cmp DI, 2000 + JA MESRBlockType1End + + LodsB + + ShL DI, 5 + Mov DL, AL + + Inc DX + + Xor AX, AX + Add NumNodes, DX + +MESRBlockType1Transfer: + StosW + Mov CX, 26/2 + Rep MovsW + Inc AX + Add DI, 4 + Dec DX + JNZ MESRBlockType1Transfer + +MESRBlockType1End: + ScreenTrace 'm' + + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType3: ; Quit ; Have to say farewell to direct connections + ; also. Should cascade to MESRBlockType2 + ScreenTrace 'n' + Call RemoveFromGroup + +;****************************************************************************** + +MESRBlockType2: ; Remove ; Only significant on connect driver screen + ScreenTrace 'o' + + Cmp NumberOfConnections, 0 + JNE MESRBlockType2End + Call IT_GetCurrentMode + Cmp AL, 24 + JNE MESRBlockType2End + + ScreenTrace 'p' + + Mov EAX, [SI+20] ; Sender's ID + Mov EDX, [SI+24] + + Call NodeSearch + JNC MESRBlockType2End ; DS = DiskData + + ScreenTrace 'q' + + Push DS + Pop ES + + Mov CX, CS:NumNodes + Mov DI, BX + ShL CX, 5 + LEA SI, [BX+32] + Xor AX, AX + + Sub CX, DI + Rep MovsB + + Mov CX, 32/2 + Rep StosW + + Mov SI, BX + +MESRBlockType2a: + Cmp [SI], AX + JE MESRBlockType2b + + Dec Word Ptr [SI] + Add SI, 32 + Jmp MESRBlockType2a + +MESRBlockType2b: + ScreenTrace 'r' + + ShR BX, 5 + + Push CS + Pop DS + + Dec NumNodes + Cmp BX, CurrentNode + JAE MESRBlockType2End + + Dec CurrentNode + +MESRBlockType2End: + ScreenTrace 's' + + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType4: ; Message + ScreenTrace 't' + + Call CheckFromSelf + JE MESRBlockType4End + +; If NumberOfConnections = 0 && CurrentMode = 24, then check that name is logged + Cmp NumberOfConnections, 0 + JNE MESRBlockType4_6 + + Call IT_GetCurrentMode + Cmp AL, 24 + JNE MESRBlockType4_3 + + Push DS + Push ES + + Mov EAX, [SI+20] ; Sender's ID + Mov EDX, [SI+24] + + Call NodeSearch + JC MESRBlockType4_4 + +; Couldn't find node. + Push DI + Push SI + + Push CS + Push DS + Pop ES + Pop DS + + LEA SI, [DI+1] + Mov DI, NumNodes + Cmp DI, 2000 + JA MESRBlockType4_5 + + ShL DI, 5 + Xor AX, AX + + StosW + Mov CX, 16/2 + Rep MovsW + + Pop SI + Push SI + + Add SI, 18 + Mov CX, 10/2 + Rep MovsW + + Inc NumNodes + +MESRBlockType4_5: + Pop SI + Pop DI + +MESRBlockType4_4: + Pop ES + Pop DS + + Jmp MESRBlockType4_3 + +MESRBlockType4_6: + ; Have connections.. only accept messages from group + Call FindConnection + JC MESRBlockType4End + +MESRBlockType4_3: + Mov MessageReceived, 1 + + Push DI + + Mov SI, Offset MessageData+72 + Mov DI, Offset MessageData + Mov CX, (72*7)/2 + Rep MovsW + + Pop SI + LodsB + Mov CX, 72/2 + Rep MovsW + + Call IT_GetCurrentMode + Cmp AL, 24 + JE MESRBlockType4End + + Sub SI, 72 + Mov DI, Offset InfoListMessage + + Mov CX, 61 + + Push SI + +MESRBlockType4_1: + LodsB + StosB + Test AL, AL + LoopNZ MESRBlockType4_1 + + Pop SI + Mov Word Ptr [DI-1], ':'+ ' '*100h + Inc DI + Add SI, 16 + Mov AX, 0FEh+2300h + StosW + +MESRBlockType4_2: + LodsB + StosB + Test AL, AL + LoopNZ MESRBlockType4_2 + Xor AL, AL + StosB + + Mov BX, 150 + Mov SI, Offset InfoListMessage + Call IT_SetInfoLine + +MESRBlockType4End: + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType5: + Call RemoveFromGroup + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType6: ; Request connection + ; auto reject if: + ; This node is requesting a connection + ; Someone else is requesting a connection + ; NumConnections already = 3 + Cmp NumberOfConnections, 3 + JE MESRBlockType6AutoReject + Test ConnectionRequest, 0Fh + JNE MESRBlockType6AutoReject + + Or ConnectionRequest, 2 ; Mark that someone is requesting a con + +; Else prompt user +; Save connection request address + + Push DI + + Add SI, 18 ; Save address of connection requester + Mov DI, Offset ConnectionRequestAddress + Mov CX, 12/2 + Rep MovsW + + Pop DI + + Inc DI + Mov SI, DI + Xor AL, AL + Mov CX, 16 + Push CX + RepNE ScasB ; DI = one after 0 found + Pop CX + Sub DI, SI + Mov DX, DI + Sub CX, DI + ShR CX, 1 + + Mov DI, Offset ConnectionRequestName + + Mov AL, ' ' + Rep StosB + + Mov CX, DX + Rep MovsB + + Mov IPXQueueScreen, 1 + + Jmp MESRBlockTypeFinished + +MESRBlockType6AutoReject: + Call MaintenanceWaitforSend + Call TransferDestinationAddress + + Push DI + Mov SI, Offset AutoRejectMessage + Mov DI, Offset InfoListMessage + Mov CX, 26/2 + Rep MovsW + Pop SI + Inc SI + Mov CX, 16/2 + Rep MovsW + Mov BX, 100 + Mov SI, Offset InfoListMessage + Call IT_SetInfoLine + Call ConnectionReject + +MESRBlockType6End: + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType7: ; Accept/Reject connection +; First verify that sender is the same as ConnectionRequestAddress and that +; connectionRequest Bit 0 is set. if not, then send negative confirmation + + Test [ConnectionRequest], 1 + JZ MESRBlockType7Reject + + Push SI + Push DI + + Mov CX, 10/2 + Add SI, 18 ; Sender's address + Mov DI, Offset ConnectionRequestAddress + RepE CmpsW + + Pop DI + Pop SI + + JNE MESRBlockType7Reject + +; OK.. +; Connection rejected if DH = 0 + + Or ConnectionRequest, 80h ; Leave wait for connection request + ; screen + ShR DX, 8 + JZ MESRBlockTypeFinished + + Call MaintenanceWaitforSend + Call TransferDestinationAddress + +; Connection accepted if DH != 0 +; Then copy DH*28 lots of bytes starting at UserName1 +; And set NumberOfConnections to DH +; Then call IT_EstablishConnection + + Mov NumberOfConnections, DL + LEA SI, [DI+2] + Mov DI, Offset UserName1 + +MESRBlockType7Accepted: + Mov CX, 28/2 + Rep MovsW + Dec DX + JNZ MESRBlockType7Accepted + +; Send positive ack + + Mov SI, Offset UserName + Mov DI, Offset MaintenanceSData + Mov AX, 108h + Mov CX, 28/2 + StosW + Rep MovsW + Call IPX_MaintenanceSendData + + Call IT_NewConnection + + Jmp MESRBlockTypeFinished + +MESRBlockType7Reject: + Test DH, DH ; If connection rejected, dont' send + ; Further response. + JZ MESRBlockType7End + + Mov DI, Offset MaintenanceSData + Mov AX, 8 + StosW + Call IPX_MaintenanceSendData + +MESRBlockType7End: + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType8: ; Confirm connection + + ; Check whether connection was requested and whether this cancellation + ; is from that sender. + +; If Confirm connection is from ConnectionRequestAddress and ConnectRequest & 2 +; *OR* Confirm connection is from someone in the current group +; Then add user to user list, increment NumberOfConnections + + Cmp NumberOfConnections, 3 + JE MESRBlockType8End + + Call FindConnection ; Was it from the group? + JNC MESRBlockType8AddUser ; Yes -> Add user + + Push SI + Push DI + + Add SI, 12h + Mov DI, Offset ConnectionRequestAddress + Mov CX, 12/2 + RepE CmpsW + + Pop DI + Pop SI + JNE MESRBlockType8End + + Test DH, DH ; Cancelled? + JZ MESRBlockType8ScreenRefresh + +; If received from group, then don't send +; If not received from group, then send to rest of group. + ; Establish connection + ; If NumConnections != 0 + ; then send connection establishment to all + ; other connected users. +; Send to the rest of the group! + Mov AL, NumberOfConnections + + Push AX + Inc AL + Call IT_EstablishConnection + Pop AX + + Test AL, AL + JZ MESRBlockType8AddUser + + Call MaintenanceWaitforSend + + Push DI + + Mov SI, DI + Mov DI, Offset MaintenanceSData + Mov CX, 30/2 + Rep MovsW + + Mov SI, Offset UserAddress1 + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderDirected + Mov [MaintenanceSendDataOffset], Offset MaintenanceSData + Mov [MaintenanceSendDataSize], 30 + +MESRBlockType8Group1: + + Push AX + Push SI + + Mov DI, Offset MaintenanceDirectedDestination + Mov CX, 10/2 + Rep MovsW + Mov AX, 'IT' + StosW + + Call SendMaintenancePacket + + Pop SI + Pop AX + + Dec AL + JZ MESRBlockType8GroupEnd + + Add SI, 28 + Call MaintenanceWaitforSend + Jmp MESRBlockType8Group1 + +MESRBlockType8GroupEnd: + Pop DI + +MESRBlockType8AddUser: + LEA SI, [DI+2] + Mov AL, 28 + Mul NumberOfConnections + + Mov DI, AX + Add DI, Offset UserName1 + Mov CX, 28/2 + Rep MovsW + + Inc NumberOfConnections + +MESRBlockType8ScreenRefresh: + Or ConnectionRequest, 80h + +MESRBlockType8End: + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType9: ; Request intro +; Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderDirected + Mov AL, 1 + Call SendConnectionData + + Jmp MESRBlockTypeFinished + +;****************************************************************************** + +MESRBlockType10: ; Resend data + Call FindConnection + JC MESRBlockType10End + + Inc PacketsRetry + + Mov AH, 6 + Mul AH + Mov BX, AX + Add BX, Offset SendPacketInformation + Call SendDataGivenBX + +MESRBlockType10End: + Jmp MESRBlockTypeFinished + +MESRBlockTypeUnknown: + Mov BX, 72 + Mov SI, Offset UnknownPacketMessage + Call IT_SetInfoLine + +MESRBlockTypeFinished: +; Should process the info, respond if necessary and set the packet back +; for listening. + +MESRRelisten: + Push CS + Push CS + Pop ES + Pop DS + + Pop SI + + ScreenTrace 'z' + + Mov BX, 4 ; Relisten to the socket. + Call [DWord Ptr IPXEntryAddress] + + ScreenTrace 'Z' + + Pop DS + ScreenTraceEnd + + PopAD + PopF + Ret + +EndP MaintenanceESR + Assume DS:Nothing + +; + +Proc MaintenanceWaitForSend + + PushF + PushAD + Push DS + + ScreenTraceStart + + Push CS + Pop DS + Assume DS:IPX + + Call IT_GetTime ; Returns EAX + Mov EDX, EAX + +SendMaintenancePacket1: + Cmp [SendECBInUse], 0 + JE SendMaintenancePacket2 + + StI + + Mov BX, 0Ah ; IPX processing. + Call [DWord Ptr IPXEntryAddress] + + Mov EBX, EDX + Call IT_GetTime + Sub EBX, EAX + Cmp EBX, MAINTENANCETIMEOUT + JB SendMaintenancePacket1 + +; Error message! + +SendMaintenancePacket2: + ScreenTraceEnd + + Pop DS + PopAD + PopF + Ret + +EndP MaintenanceWaitForSend + Assume DS:Nothing + +; + +Proc SendMaintenancePacket + + PushAD + Push DS + Push ES + + Push CS + Push CS + Pop ES + Pop DS + Assume DS:IPX + + Call MaintenanceWaitForSend + + Mov SI, [MaintenanceSendHeader] + Mov DI, Offset MSendDest + Add SI, 10 + MovsW + MovsW + MovSW + + Mov BX, 3 + Mov SI, Offset MaintenanceSendECB + Call [DWord Ptr IPXEntryAddress] + + Pop ES + Pop DS + PopAD + Ret + +EndP SendMaintenancePacket + Assume DS:Nothing + +; + +Proc DetectIPXNetwork Far ; IPX detection. + + Push CS + Pop DS + Assume DS:IPX + +IF FIXEDUSERNAME + Mov CX, 18 + Mov SI, Offset UserName +ELSE + Xor CX, CX +ENDIF + Call IT_DecodeUserName + + Mov AX, 7A00h + Int 2Fh + + Sub AL, 0FFh + JC DetectIPXNetwork1 + + Mov [Word Ptr IPXEntryAddress], DI + Mov [Word Ptr IPXEntryAddress+2], ES + + Mov BX, 1Ah + Call [DWord Ptr IPXEntryAddress] + + Mov [IPXMaximumPacketSize], AX + Mov [IPXRetryCount], CX + + Push CS + Pop ES + + Mov BX, 9 + Mov SI, Offset IPXLocalAddress + Call [DWord Ptr IPXEntryAddress] + + ClC + +DetectIPXNetwork1: + Ret + +EndP DetectIPXNetwork + Assume DS:Nothing + +; + +Macro_SetupListenDataPackets Macro Index + Mov DSocket&Index&, DX +EndM + +Macro_ListenDataPackets Macro Index + Mov SI, Offset DataReceiveECB&Index& + Call [DWord Ptr IPXEntryAddress] +EndM + +Proc IPX_Initialise Far + + Push CS + Pop DS + Assume DS:IPX + + Trace "IPX: Initialise" + + Mov SI, Offset RelocationTable + +IPX_RelocationFixup: + LodsW + Test AX, AX + JZ IPX_RelocationEnd + Mov BX, AX + Mov [BX], DS + + Jmp IPX_RelocationFixup + +IPX_RelocationEnd: + Mov EAX, IT_DrawHeader + Mov EBX, IT_FillHeader + Mov ECX, IdleUpdateInfoLine + Mov EDX, GlobalKeyList + + Mov DrawHeader2, EAX + Mov FillHeader2, EBX + Mov IdleFunctionList, ECX + Mov IdleFunctionList2, ECX + Mov GlobalKeyLink2, EDX + + Call DetectIPXNetwork + JNC IPX_Initialise1 + + Push DS + Push Offset NoIPXMessageList + Jmp IPX_InitialiseReturn + +IPX_Initialise1: + Xor AL, AL + Xor BX, BX ; Open socket + Mov DX, 'IT' + Call [DWord Ptr IPXEntryAddress] + Test AL, AL + JNZ IPX_InitialiseError1 + + Xor AL, AL + Xor BX, BX + Xor DX, DX + Call [DWord Ptr IPXEntryAddress] + Test AL, AL + JNZ IPX_InitialiseError2 + + Mov IPXSocket, DX + + IndexCounter = 1 + Rept NUMBEROFLISTENINGPACKETS + Macro_SetupListenDataPackets %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + +IPX_Initialise2: + +IFE FIXEDUSERNAME +; OK.. ask for user name. + Push DS + Push Offset IPXGetName + Call IT_FunctionHandler + + Push CS + Pop DS + + Test DX, DX + JNZ IPX_Initialise3 + Jmp IPX_Shutdown1 + +IPX_Initialise3: +ENDIF + +; Setup to listen for packets! + + Push CS + Pop ES + Mov BX, 4 + + Mov SI, Offset MaintenanceECB1 + Call [DWord Ptr IPXEntryAddress] + + Mov SI, Offset MaintenanceECB2 + Call [DWord Ptr IPXEntryAddress] + + Mov SI, Offset MaintenanceECB3 + Call [DWord Ptr IPXEntryAddress] + + Mov SI, Offset MaintenanceECB4 + Call [DWord Ptr IPXEntryAddress] + + IndexCounter = 1 + Rept NUMBEROFLISTENINGPACKETS + Macro_ListenDataPackets %IndexCounter + IndexCounter = IndexCounter + 1 + EndM + + Jmp IPX_DriverScreen + +IPX_InitialiseError2: ; Close socket. + Mov BX, 1 + Mov DX, 'IT' + Call [DWord Ptr IPXEntryAddress] + +IPX_InitialiseError1: + Push DS + Push Offset SocketErrorList + +IPX_InitialiseReturn: + Call IT_FunctionHandler + Jmp IT_UnloadDriver + +EndP IPX_Initialise + Assume DS:Nothing + +; + +Proc BroadcastMaintenanceByte ; Given AL + + Call MaintenanceWaitforSend + Mov [ByteBlock], AL + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderBroadcast + Mov [MaintenanceSendDataOffset], Offset ByteBlockInformation + Mov [MaintenanceSendDataSize], 1 + Call SendMaintenancePacket + + Ret + +EndP BroadcastMaintenanceByte + +; + +Proc IPX_DriverScreen Far + + Push CS + Pop DS + Assume DS:IPX + + Mov ES, DiskDataArea + Xor DI, DI + Mov CX, 32768 + Xor AX, AX + Rep StosW + + Cmp NumberOfConnections, 0 + JE IPX_DriverScreen1 + +; Alternative screens here for post-connection. + + Mov AX, 5 + Mov SI, 1 + Mov DI, AX + Mov DX, Offset IPXConnectedScreen + Mov CX, CS + + Ret + +IPX_DriverScreen1: + Mov OldNumNodes, 0 + Mov NumNodes, 0 + Mov CurrentNode, 0 + +; Call MaintenanceWaitforSend +; Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderBroadcast + Xor AX, AX + Call SendConnectionData + + Mov AX, 5 + Mov SI, 1 + Mov DI, AX + Mov DX, Offset IPXScreen + Mov CX, CS + + Ret + +EndP IPX_DriverScreen + Assume DS:Nothing + +; + +Proc IPX_Shutdown Far ; Shutdown has to: + ; free all allocated + ; Transmit logoff message + ; release any allocated sockets + ; Unload driver +IFE FIXEDUSERNAME + Call IT_GotoHomeDirectory +ENDIF + Push CS + Pop DS + Assume DS:IPX + +IFE FIXEDUSERNAME + ; Now to save config into driver file. + Mov AX, 3D02h ; Read write access + Mov DX, Offset DriverName + Int 21h + JC SaveConfiguration2 + + Mov BX, AX + + Mov AX, 4200h + Xor CX, CX + Mov DX, Offset CONFIGURATIONOFFSET + Int 21h + JC SaveConfiguration1 + + Mov AH, 40h + Mov CX, CONFIGURATIONSIZE + Mov DX, Offset UserName + Int 21h + +SaveConfiguration1: + Mov AH, 3Eh + Int 21h + +SaveConfiguration2: +ENDIF + Mov AL, 3 ; Block type 3 = quit + Call BroadcastMaintenanceByte + +IPX_Shutdown1: +; Free both sockets + Mov BX, 1 + + Mov DX, 'IT' ; Release maintenance socket. + Call [DWord Ptr IPXEntryAddress] + + Mov DX, IPXSocket + Call [DWord Ptr IPXEntryAddress] + + Jmp IT_UnloadDriver + +EndP IPX_Shutdown + Assume DS:Nothing + +; + +Proc IPX_LeaveSession Far + + Mov AL, 5 ; Log off from group. + Call BroadcastMaintenanceByte + + Mov CS:NumberOfConnections, 0 + + Jmp IPX_DriverScreen + +EndP IPX_LeaveSession + +; + +Proc IPX_Update Far + + Push CS + Pop DS + Assume DS:IPX + + Xor AX, AX + XChg IPXQueueScreen, AX + + Test AX, 1 + JZ IPX_Update2 + + Push AX + + ; For Connection requests.. + And ConnectionRequest, 0Fh + + Call IT_S_SaveScreen + Push CS + Push Offset ConnectionRequestList + Call IT_FunctionHandler + + Push CS + Push CS + Pop DS + Pop ES + + Call IT_S_RestoreScreen + + ; Transfer destination address + Mov SI, Offset ConnectionRequestAddress + Mov DI, Offset MaintenanceDirectedDestination + Mov CX, 12/2 + Rep MovsW + + Cmp DX, 1 + JB IPX_UpdateConnectionReject + JA IPX_UpdateConnectionCancelled + +IPX_UpdateConnectionAccept: +; Have to send complete info about all connnections back +; including socket numbers + Mov AH, NumberOfConnections + Mov DI, Offset MaintenanceSData + Mov AL, 7 + Mov SI, Offset UserName + Inc AH + Mov CX, ((16+12)*3)/2 + StosW + Rep MovsW + Call IPX_MaintenanceSendData + + Jmp IPX_UpdateConnectionEnd + +IPX_UpdateConnectionReject: + Call ConnectionReject + Jmp IPX_UpdateConnectionEnd + +IPX_UpdateConnectionCancelled: + Push CS + Push Offset ConnectionCancelledList + Call IT_FunctionHandler + Call IT_S_RestoreScreen + +IPX_UpdateConnectionEnd: + And ConnectionRequest, Not 2 + Pop AX + +IPX_Update3: + Mov BX, 0Ah ; Relinquish control + Call [DWord Ptr IPXEntryAddress] + + Mov AX, 1 + Ret ; Redraw required. + +IPX_Update2: + Call SendITData + + Call IT_GetCurrentMode + Cmp AL, 24 + JE IPX_Update3 + +IPX_UpdateEnd: + Mov BX, 0Ah ; Relinquish control + Call [DWord Ptr IPXEntryAddress] + + Xor AX, AX + XChg AL, PacketReceived + Ret + +EndP IPX_Update + Assume DS:Nothing + +; + +Proc IPX_DrawHexNumber ; Given AL = Number + + LodsB + Mov DH, AL + ShR AL, 4 + Cmp AL, 10 + SBB AL, 69h + DAS + StosW + Mov AL, DH + And AL, 0Fh + Cmp AL, 10 + SBB AL, 69h + DAS + StosW + + Ret + +EndP IPX_DrawHexNumber + +; + +Proc IPX_DrawAddress + + Mov CX, 3 + +IPX_DrawAddress1: + Call IPX_DrawHexNumber + Mov AL, ':' + StosW + Loop IPX_DrawAddress1 + Call IPX_DrawHexNumber + Mov AL, ' ' + StosW + + Mov CX, 5 + +IPX_DrawAddress2: + Call IPX_DrawHexNumber + Mov AL, ':' + StosW + Loop IPX_DrawAddress2 + Call IPX_DrawHexNumber + + Ret + +EndP IPX_DrawAddress + +; + +Proc IPX_DrawConnect Far + + Push CS + Pop DS + Assume DS:IPX + + Call IT_S_GetDestination ; Gets ES + + Mov AX, 168+200h + Mov DI, (13*80+22)*2 + Mov CX, 23 + +IPX_DrawConnect2: + StosW + Add DI, 158 + Loop IPX_DrawConnect2 + + Cmp [NumNodes], 0 + JNE IPX_DrawConnect1 + + Ret + +IPX_DrawConnect1: + Mov SI, [TopNode] + Mov DX, [NumNodes] + Mov BX, [CurrentNode] + + Cmp BX, DX + JB IPX_DrawConnectClip3 + + Mov BX, DX + Dec BX + Mov [CurrentNode], BX + +IPX_DrawConnectClip3: + +; Need to make sure they're within bounds. + Cmp BX, SI + JAE IPX_DrawConnectClip1 + + Mov SI, BX + +IPX_DrawConnectClip1: + LEA DI, [SI+22] + Cmp BX, DI + JBE IPX_DrawConnectClip2 + + LEA SI, [BX-22] + +IPX_DrawConnectClip2: + Mov DI, (13*80+3)*2 + Mov [TopNode], SI + + Sub DX, SI + JZ IPX_DrawConnectEnd + + ShL SI, 5 + + Mov DS, [DiskDataArea] + Assume DS:Nothing + + Cmp DX, 23 + JB IPX_DrawConnectClip + + Mov DX, 23 + +IPX_DrawConnectClip: + Push DI + + LodsW + + Mov AH, 3 + Mov CX, 16 + + Test AL, AL + JZ IPX_DrawConnectUserName + + Add DI, 4 + +IPX_DrawConnectUserName: + LodsB + StosW + Loop IPX_DrawConnectUserName + + Pop DI + + Add DI, 40 + + Call IPX_DrawAddress + + Add SI, 4 + Add DI, 62 + + Dec DL + JNZ IPX_DrawConnectClip + + Mov CL, 0E0h + Jmp IPX_PreConnectChain + +IPX_DrawConnectEnd: + Ret + +EndP IPX_DrawConnect + +; + +Proc IPX_PreConnect Far + + Mov CL, 30h + +IPX_PreConnectChain: + Push CS + Pop DS + Assume DS:IPX + + Cmp [NumNodes], 0 + JE IPX_PreConnectEnd + + Mov AX, [CurrentNode] + Sub AX, [TopNode] + Add AX, 13 + Mov BX, 160 + Mul BX + + Call IT_S_GetDestination + + Mov DL, CL + Mov DH, CL + Or DH, 2 + + LEA DI, [EAX+6] + Mov CX, 49 + +IPX_PreConnectScreen1: + Mov AX, [ES:DI] + Mov AH, DL + Cmp CX, 49-19 + JNE IPX_PreConnectScreen2 + + Mov AH, DH + +IPX_PreConnectScreen2: + StosW + Loop IPX_PreConnectScreen1 + +IPX_PreConnectEnd: + Ret + +EndP IPX_PreConnect + Assume DS:Nothing + +; + +Proc IPX_PostConnect Far + + Push CS + Pop DS + Assume DS:IPX + + Mov SI, Offset ConnectKeys + Call IT_FunctionDivider + JC IPX_PostConnect1 + + Jmp [Word Ptr SI] + +IPX_PostConnect1: + Xor AX, AX + Ret + Xor AX, AX + Ret + +EndP IPX_PostConnect + +; + +Proc IPX_ConnectUp Far + Assume DS:IPX + + Mov AX, 1 + + Sub CurrentNode, AX + AdC CurrentNode, 0 + + Ret + +EndP IPX_ConnectUp + Assume DS:Nothing + +; + +Proc IPX_ConnectDown Far + Assume DS:IPX + + Mov AX, 1 + Add CurrentNode, AX + Ret + +EndP IPX_ConnectDown + Assume DS:Nothing + +; + +Proc IPX_ConnectPgUp Far + Assume DS:IPX + + Mov AX, CurrentNode + Sub AX, 24 + JNC IPX_ConnectPgUp1 + + Xor AX, AX + +IPX_ConnectPgUp1: + Mov CurrentNode, AX + + Mov AX, 1 + Ret + +EndP IPX_ConnectPgUp + Assume DS:Nothing + +; + +Proc IPX_ConnectPgDn Far + Assume DS:IPX + + Add CurrentNode, 24 + + Mov AX, 1 + Ret + +EndP IPX_ConnectPgDn + Assume DS:Nothing + +; + +Proc IPX_ConnectHome Far + + Mov CurrentNode, 0 + Mov AX, 1 + Ret + +EndP IPX_ConnectHome + +; + +Proc IPX_ConnectEnd Far + + Mov CurrentNode, 1000 + + Mov AX, 1 + Ret + +EndP IPX_ConnectEnd + +; + +Proc IPX_ConnectTab Far + Assume DS:IPX + + Mov AX, 6 + StosW + + Mov AX, 1 + Ret + +EndP IPX_ConnectTab + Assume DS:Nothing + +; + +Proc IPX_GetDestinationAddress + + Push CS + Push CS + Pop DS + Pop ES + Assume DS:IPX + + Cmp NumNodes, 1 + JB IPX_GetDestinationAddress1 + + Mov SI, CurrentNode + Mov DI, Offset MaintenanceDirectedDestination + ShL SI, 5 + Mov CX, 10/2 + Add SI, 18 ; SI = offset to node address + + Push DS + Mov DS, DiskDataArea + + Rep MovsW + Mov AX, 'IT' + StosW ; Destination socket is maintenance socket. + + Pop DS + ClC + +IPX_GetDestinationAddress1: + Ret + +EndP IPX_GetDestinationAddress + Assume DS:Nothing + +; + +Proc IPX_MaintenanceSendData + + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderDirected + +Proc IPX_MaintenanceSendDataNoHeader + Sub DI, Offset MaintenanceSData + Mov [MaintenanceSendDataOffset], Offset MaintenanceSData + Mov [MaintenanceSendDataSize], DI + + Call SendMaintenancePacket + + Ret + +EndP IPX_MaintenanceSendDataNoHeader +EndP IPX_MaintenanceSendData + +; + +Proc SendConnectionData + Assume DS:IPX + + PushA + Push DS + Pop ES + + Call MaintenanceWaitforSend + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderBroadcast + + Test AX, AX + JZ SendConnectionData2 + + Call TransferDestinationAddress + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderDirected + +SendConnectionData2: + Mov DI, Offset MaintenanceSData + Mov SI, Offset IntroBlockInformation + MovsB + StosB + MovSB + Mov DL, NumberOfConnections + +SendConnectionData1: + Mov CX, (16+10)/2 + Rep MovsW + LodsW + Dec DL + JNS SendConnectionData1 + + + Call IPX_MaintenanceSendDataNoHeader + PopA + Ret + +EndP SendConnectionData + Assume DS:Nothing + +; + +Proc IPX_ConnectEnter Far ; Have to request a connection + + Call IPX_GetDestinationAddress + JC IPX_ConnectEnter1 + Assume DS:IPX + + Or ConnectionRequest, 1 + + Push DS + Mov DS, DiskDataArea + Assume DS:Nothing + + Sub SI, 26 + Mov DI, Offset ConnectionRequestName + Mov CX, 26/2 + Rep MovsW + Pop DS + Assume DS:IPX + + Mov SI, Offset UserName + Mov DI, Offset MaintenanceSData + Mov AL, 6 + StosB + Mov CX, 16/2 + Rep MovsW + + Call IPX_MaintenanceSendData + + Push DS + Push Offset WaitforConnectList + Call IT_FunctionHandler + + Push CS + Push CS + Pop DS + Pop ES + + And ConnectionRequest, Not 1 + +; If DX = 0, then connection was cancelled +; If DX = 1, then either connected or cancelled. + + Test DX, DX + JNZ IPX_ConnectEnter2 + +; Connection cancelled. + Mov SI, Offset ConnectionRequestAddress + Mov DI, Offset MaintenanceDirectedDestination + Mov CX, 10/2 + Rep MovsW + Mov AX, 'IT' + StosW + + Mov DI, Offset MaintenanceSData + Mov AX, 8 + StosW + Call IPX_MaintenanceSendData + Jmp IPX_ConnectEnter1 + +IPX_ConnectEnter2: + Cmp NumberOfConnections, 0 + JNE IPX_ConnectEnter3 + +; Connection rejected + + Push DS + Push Offset ConnectionRejectedList + Call IT_FunctionHandler + Jmp IPX_ConnectEnter1 + +IPX_ConnectEnter3: +; Connection established + +IPX_ConnectEnter1: + Mov AX, 1 + Ret + +EndP IPX_ConnectEnter + +; + +Proc IPX_SendGroupMessage Far + + Push CS + Pop DS + + Cmp MessageEntryArea, 0 + JE IPX_SendMessageEnd + + Mov SI, Offset UserName + Mov DI, Offset MessageSenderName + Mov CX, 16/2 + Rep MovsW + + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderDirected + Mov [MaintenanceSendDataOffset], Offset MessageBlock + Mov [MaintenanceSendDataSize], 73 + + Mov SI, Offset UserAddress1 + Mov DL, NumberOfConnections + +IPX_SendGroupMessage1: + Mov DI, Offset MaintenanceDirectedDestination + Mov CX, 10/2 + Rep MovsW + Mov AX, 'IT' + StosW + + Call SendMaintenancePacket + Add SI, 18 + + Dec DL + JNZ IPX_SendGroupMessage1 + + Jmp IPX_SendMessageChain + +; + +Proc IPX_SendMessage Far + + Push CS + Pop DS + + Cmp MessageEntryArea, 0 + JE IPX_SendMessageEnd + + Mov SI, Offset UserName + Mov DI, Offset MessageSenderName + Mov CX, 16/2 + Rep MovsW + + Mov [MaintenanceSendHeader], Offset MaintenanceSendHeaderBroadcast + Mov [MaintenanceSendDataOffset], Offset MessageBlock + Mov [MaintenanceSendDataSize], 73 + Call SendMaintenancePacket + +; Wait until sent, then does this.. + +IPX_SendMessageChain: + Call MaintenanceWaitForSend + + Mov SI, Offset MessageData+72 + Mov DI, Offset MessageData + Mov CX, 72*7/2 + Rep MovsW + Mov SI, Offset MessageSenderName + Mov CX, 72/2 + Rep MovsW + + Xor AX, AX + Mov DI, Offset MessageEntryArea + Mov CX, 56/2 + Rep StosW + +IPX_SendMessageEnd: + Mov AX, 1 + Ret + +EndP IPX_SendMessage +EndP IPX_SendGroupMessage + + +; + +Proc IPX_ShowConnectionDetails Far + + Push CS + Pop DS + Assume DS:IPX + + MOv DX, 1 + Mov DI, (4+15*80)*2 + Mov BX, Offset UserName1 + Call IT_S_GetDestination + +IPX_ShowConnectionDetailsLoop: + +; Want to show: +; Connection %d +; User name: %s +; User address: [hex] +; (Bytes transferred) + + Push DX + + Mov AH, 20h + Mov SI, Offset ConnectionNumberMsg + Call IT_S_DrawString + + Mov SI, BX + Mov CX, 16 + +IPX_ShowConnectionDetails1: + LodsB + StosW + Loop IPX_ShowConnectionDetails1 + + Push SI + + Add DI, 104 + Mov SI, Offset ConnectionAddressMsg + Call IT_S_DrawString + + Pop SI + + Call IPX_DrawAddress + + Mov AL, ' ' + StosW + + Call IPX_DrawHexNumber + Call IPX_DrawHexNumber + + Mov BX, SI + Add DI, 62+160 + + Pop DX + + Inc DX + + Cmp DL, NumberOfConnections + JBE IPX_ShowConnectionDetailsLoop + + Ret + +EndP IPX_ShowConnectionDetails + Assume DS:Nothing + +; + +Proc IPX_DisplayMessages Far + + Push CS + Pop DS + Assume DS:IPX + + Call IT_S_GetDestination + + Mov CX, 8 + Mov DI, (38*80+3)*2 + Mov SI, Offset MessageData + +IPX_DisplayMessages1: + Cmp Byte Ptr [SI], 0 + JE IPX_DisplayMessages4 + + Push SI + Push DI + + Push SI + Mov AH, 3 + +IPX_DisplayMessages2: + LodSB + Test AL, AL + JZ IPX_DisplayMessages5 + StosW + Jmp IPX_DisplayMessages2 + +IPX_DisplayMessages5: + Pop SI + Add SI, 16 + + Mov AL, ':' + StosW + Mov AL, ' ' + StosW + + Mov AH, 2 + +IPX_DisplayMessages3: + LodsB + StosW + Test AL, AL + JNZ IPX_DisplayMessages3 + + Pop DI + Pop SI + +IPX_DisplayMessages4: + Add SI, 72 + Add DI, 160 + Loop IPX_DisplayMessages1 + + Ret + +EndP IPX_DisplayMessages + Assume DS:Nothing + +; + +Proc IPX_ConnectionStatus Far; Returns 0 if not connected + ; Otherwise returns connection count + + Mov AL, CS:NumberOfConnections + Ret + +EndP IPX_ConnectionStatus + +; + +EndDriver: + +ProvidedVariableTableStart: + DB NUMPROVIDEDVARIABLES-($-ProvidedVariableTableStart) Dup (0) + +ProvidedProcedureTableStart: + DW Offset IPX_Initialise + DW Offset IPX_Shutdown + DW Offset IPX_DriverScreen + DW Offset IPX_Update + DW Offset IPX_ConnectionStatus + + DW NUMPROVIDEDFUNCTIONS - ($-ProvidedProcedureTableStart)/4 Dup (0) + + +; + +EndS + +End diff --git a/Network/MIPX.BAT b/Network/MIPX.BAT new file mode 100755 index 0000000..c3b9e56 --- /dev/null +++ b/Network/MIPX.BAT @@ -0,0 +1,5 @@ +tasm /m /la /ut310 ipx +tlink /3 ipx +execom ipx itipx.net +copy itipx.net .. + diff --git a/Network/NETDRIVE.ASM b/Network/NETDRIVE.ASM new file mode 100755 index 0000000..b394f42 --- /dev/null +++ b/Network/NETDRIVE.ASM @@ -0,0 +1,47 @@ + + .386P + +Segment DriverHeader PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +;***** Driver Header ******* + +include drhead.inc + +EndS + +Segment Driver PARA Public 'Code' Use16 + Assume CS:Driver, DS:Nothing + +ORG 0 +StartDriver: + +include vtable.inc + +;******** Required ProcedureTable ************* + +include reqproc.inc + +; + +EndDriver: + +;******** Provided Variable Table ************* + +ProvidedVariableStart: + DB NUMPROVIDEDVARIABLES-($-ProvidedVariableStart) Dup (0) + +;******** Provided Procedure Table ************* + +ProvidedTableStart: + DW Offset Initialise + DW Offset Shutdown + DW Offset DriverScreen + DW Offset Update + DW Offset ConnectionStatus +ProvidedTableEnd: + DW NUMPROVIDEDFUNCTIONS-(ProvidedTableEnd-ProvidedTableStart)/2 Dup (0) + +EndS + +End diff --git a/Network/REQPROC.INC b/Network/REQPROC.INC new file mode 100755 index 0000000..4f1e436 --- /dev/null +++ b/Network/REQPROC.INC @@ -0,0 +1,32 @@ + +ProcedureTableStart Label + +IT_UnloadDriver DD ? +IT_FunctionHandler DD ? +IT_FunctionDivider DD ? + +IT_ReceiveData DD ? +IT_SendData DD ? +IT_EstablishConnection DD ? + +IT_GotoHomeDirectory DD ? +IT_GetTime DD ? +IT_SetInfoLine DD ? + +IT_DrawHeader DD ? +IT_FillHeader DD ? + +IT_S_GetDestination DD ? +IT_S_DrawString DD ? +IT_S_SaveScreen DD ? +IT_S_RestoreScreen DD ? + +IT_GetCurrentMode DD ? + +IT_NewConnection DD ? + +IT_DecodeUserName DD ? + + DD NUMREQUIREDFUNCTIONS - ($-ProcedureTableStart)/4 Dup (0) + + diff --git a/Network/USERNAME.INC b/Network/USERNAME.INC new file mode 100755 index 0000000..56dcaf0 --- /dev/null +++ b/Network/USERNAME.INC @@ -0,0 +1,6 @@ +UserName DB 0FFh, 014h, 04Fh, 0F0h, 047h, 0C8h, 09Fh, 0DCh, 063h, 000h, 03Fh, 0FCh, 0AEh, 0FCh, 0AEh, 0FCh +IPXLocalAddress Label +UserKey DW 0141Eh +IPXNetworkAddress DW 0 ; Combines with previous line +IPXNodeAddress DW 0, 0, 0 +IPXSocket DW 0 diff --git a/Network/VTABLE.INC b/Network/VTABLE.INC new file mode 100755 index 0000000..9ee92e1 --- /dev/null +++ b/Network/VTABLE.INC @@ -0,0 +1,10 @@ + +VariableTableStart Label + +GlobalKeyList DD ? +IdleUpdateInfoLine DD ? +DiskDataArea DW ? ; Segment + + DB NUMREQUIREDVARIABLES-($-VariableTableStart) Dup (0) + + diff --git a/README.md b/README.md new file mode 100644 index 0000000..7a4bb49 --- /dev/null +++ b/README.md @@ -0,0 +1,14 @@ +# Impulse Tracker # + +Full source code for Impulse Tracker, including sound drivers, network drivers, and some supporting documentation + +## Pre-Requisite Software ## + +To build Impulse Tracker, you will need: + +* Turbo Assembler v4.1 +* Turbo Link v3.01 +* Borland MAKE v4.0 +* A DOS environment + +Once you have these, building IT.EXE should be just a single call to `MAKE` diff --git a/ReleaseDocumentation/BUGS.TXT b/ReleaseDocumentation/BUGS.TXT new file mode 100755 index 0000000..d571358 --- /dev/null +++ b/ReleaseDocumentation/BUGS.TXT @@ -0,0 +1,39 @@ + +OK.. here's a list of the known problems - please don't write to me about them! + +1) Apparently, many problems have been encountered with QEMM... I really + don't know what's going wrong here at the moment (I haven't had any + experience with QEMM myself), but try using the following line in your + CONFIG.SYS file. If this still doesnt' work, I would recommend that you + steer clear of QEMM if possible for the meantime. + + DEVICE=\QEMM.SYS DMA=64, HANDLES=255 + +2) With the GUS, 16-bit samples > 256k will *NOT* be played correctly. This is + due to a 'quirk' of the GUS - something that I don't know how to easily fix. + This does *NOT* occur with 8-bit samples. (This is the same problem that + you'll find in FastTracker II also) + +3) The "Active Channels" indication is *NOT* always 100% accurate (it's + even affected by stuff played in muted channels.....) Also, on a GUS or + AWE32, the program requires the hardware to provide the 'end of note + indication', whereas the mixing routines are calculated internally... + hence, if the hardware provides the indication a little later than expected, + another channel is allocated - what this means is that the value as played + on wavetable cards *MAY* differ from the value played on software-mixed + cards. This difference is minor (ie. 2 channels at most, unless you *TRY* + to setup a special situation) + +4) There is no 'enforce Amiga limits' option in IT (Which was in ST3) so + pitches of notes exceeding the Amiga limit will not be suitably played. + +5) If your system behaves unexpectedly in IT, it *MAY* be necessary to + specify the complete parameter list on the command line. This should NOT + be a problem in most cases, but it has been known to occur. + +6) In Windows '95, if you shell to DOS when using SB on a high IRQ, then + playback may stop! I've got no idea as to why this happens, but it seems + to restore itself after loading another module (on a SB16) + +7) If you Shell to DOS with insufficient memory available, WEIRD things may + occur... diff --git a/ReleaseDocumentation/CONTRIB.TXT b/ReleaseDocumentation/CONTRIB.TXT new file mode 100755 index 0000000..8c60373 --- /dev/null +++ b/ReleaseDocumentation/CONTRIB.TXT @@ -0,0 +1,595 @@ + + To all of the following people listed, I offer my heartfelt thanks. + Impulse Tracker would not be the same without them. + + --------------------------------- + Demosongs for Impulse Tracker + --------------------------------- + + IT1.00 - "Firestorm" - Chris Jarvis + IT1.01 - "Pale Dreams" - Chris Jarvis + IT1.03 - "Firepower" - Chris Jarvis + IT1.05 - "Sidewalk" - Chris Jarvis + IT1.06 - "Creation of Gaia" - Sherman Wu (ZaStaR) + IT2.00 - "Fallen World" - Chris Jarvis + IT2.01 - "A Hidden Fate" - Chris Jarvis + IT2.04 - "Winter's Dream" - Andy Sega (Necros) + IT2.08 - "Acid Dreams" - Liam Widdowson (Legend) + IT2.14 - "Blue Flame" - Chris Jarvis + + + ----------------------------------------- + Additional Coding for Impulse Tracker + ----------------------------------------- + + Impulse Tracker Font Customiser - Sherman Wu (ZaStaR) + Impulse Tracker Text Importer - Sherman Wu (ZaStaR) + Music Module Compression - Emmanual Giasson (Zirconia) + Keyboard Configuration files - Stefan Kucharik (Eliot) + + + ---------------------- + Website Management + ---------------------- + + USA Site - Shawn Mativetsky (Shawn202) + http://www.noisemusic.org/it + UK Site - Andi Simpson (Imminent) + http://www.mixbbs.demon.co.uk + European Site - Joost Baaij (CH:ilm) + (no longer operational) + Spanish Site - Javier Gutierrez + http://www.musica.org/impulse + Music and Tracking Site - Matthias Ziegs (MAZ) + http://www.maz-sound.com + IT Resource Central - Matthew Gardner + http://www.unidev.com/~logic/music/it + + + ---------------------- + Documentation Help + ---------------------- + + ASCII Logos - Ze`ev Nissan (Cruel Creator) + FILE_ID.DIZ - Ze`ev Nissan (Cruel Creator) + MIDI Output documentation - Andre Pang (Ozone) + + +-------------------------------------------------------------------------------- + + Hardware Thanks + + (Sorted alphabetically by company name) + + --------------------------------------- + +Company: Advanced Micro Devices (AMD) +Received: Interwave Board +Website: http://www.amd.com +Notes: AMD has discontinued the production of the Interwave chips. + Nonetheless, thank-you to Christopher Cox for his excellent service. + + --------------------------------------- + +Company: Creative Laboratories +Received: Sound Blaster AWE32 +Website: http://www.creaf.com + + --------------------------------------- + +Company: Hanmesoft / Hoontech, Korea +Received: Sound Track '97 + Sound Track '97 PCI +Website: http://www.hoontech.com +Notes: The Sound Track '97 PCI is the worlds first fully SBPro and WSS + compatible PCI card and has some of the best features ever seen + on a soundcard! For bangs per buck, it's hard to beat one of these! + + Thanks go to Haejin Park and to Seungho Pak! + + --------------------------------------- + +Company: Synergy Advanced Technology (Taiwan) +Received: ViperMAX +Website: http://www.synergy.ca/pctoybox +Notes: For a fully compatible Gravis UltraSound card with perfect Sound + Blaster compatibility, check out the ViperMAX cards - providing + the best of two worlds without the troubles of PnP. + + Special thanks go to James Hsu, Synergy Advanced Technology. + + --------------------------------------- + +Company: TerraTec International +Received: AudioSystem EWS64XL + SoundSystem Maestro 32/96 + SoundSystem Maestro 16/96 + SoundSystem Gold 16/96 + SoundSystem Base1 +Website: http://www.terratec.de +Notes: Terratec produces extremely high quality soundcards to cover + everyone's needs - check out their high end EWS64XL cards! + + Thanks go to the entire Terratec Team, especially Kay Bruns, + Wim Roegels and Sascha Kamps - 3 of the team that I've had + the pleasure to come in contact with! + + +-------------------------------------------------------------------------------- + + Contributions + ----------------- + +(sorted in alphabetical order, listing is Full Name / Alias / Country + notes) + +Name Alias Country Notes +------------------------------------------------------------------------------- + + Dire Portugal + KjWise Iceland +Egor Abramov Russia +Habib Al-Assaad +Tony Allen UK MEGA HUGE contribution, thanks! +Simon Altman P'Wolverine Australia +Tal Amir Israel +Asbjoern Andersen Mystical Denmark +Steven Anderson USA Big contribution, thanks! +Mikael Andersson Sweden +Thomas Andersson Divion Sweden +Peter Andries Belgium +Jose Angel Spain +Tor Erik Arntzen Norway +Nicolas Arrouet Onix4MAN France +Patrick Arzul Sth Africa Big contribution, thanks! +Tal Asa +Peter Askelf Sweden +Hans-Joachim Backe Germany +Martin Bahner Norway +Erick Baker USA Big contribution, thanks! +Rodger Ballard Saqquara USA +Brandon Bannerman Catspaw USA +John Barger USA MEGA HUGE contribution, thanks!! +Alex Barnell England +Matthew Barnes USA +Jayson Barrons USA +Claus Bartels Germany +Jonathan Bartlett +Michael Baumann Germany +David Benjamin USA +Brian Bennetts Daedalus USA +Vaughan Bentley South Africa +John Bergman USA Big contribution, thanks! +Jeff Best Australia +Allen Bettilyon Tremlo USA +Bastiaan Bijl Thanatos Netherlands +Mike Blaine +Christian Bode Germany +Lembrecht Bodo Germany +Fabian Boes Germany +Vicente Beltran Boil Razz Spain +Zozo Bogyo Hungary Big contribution, thanks! +Nathan Bonfiglio Ash Please contact me! +Eman Borg Malta +Gianluca Bove Yello '73 Italy +Martin Boverhof Netherlands +Alexander Brandon Siren USA +Yannis Brown Yannis Australia +Remko Brugman Digistorm Netherlands +Michael Buchholtz Germany Big contribution, thanks! +Jrg Burbach Germany +Mike Burrell MikPos Canada +Clay Busker USA Big contribution, thanks! +Jeremy Butcher Netherlands +Robert Buecker III USA +Gunnar Buettner Germany +Jim Cairns Canada +Rimas Campe USA +Mike Cantelon Foolish Bird Canada +Isaac Carrasco Spain Big contribution, thanks! +Edward Cashin USA +Zach Cappelletti Shams Kitz USA +Michael Carlsson Silverstance Sweden +Christopher Castiglione USA +Nilton Catsillo Chile +Hector Chang ZoneSeek Canada Big contribution, thanks! +Eric Charlent Spher-X France +Eric Chavanon France +Andy Chen USA +Charles Cho Deadsoul USA Big contribution, thanks! +Kenny Chou USA +Rick Christy GrymmJack USA +Rogier Claessens Netherlands Big contribution, thanks! +Jeff Clement Canada +David Clipperton Canada +Mike Cody USA +Shoshi Cohen Israel +Caleb Coppock USA Big contribution, thanks! +Ben Cormier Canada +David Cornish Australia Big contribution, thanks! +Martin Cosgrave UK +Antony Cowderoy UK +David Cox-Espenlaub USA +Matt Cramer USA +Jim Crawford Pfister USA +Dan Cunningham Pentatonic USA Big contribution, thanks! +Daniel Cunningham Ireland +David Cuny USA +Nicholas Dahlin Denmark +Chad Dahlquist +Christopher Daniel USA +Tristan Daniel Jesus2099 France +Thomas Daniels III USA MEGA HUGE contribution, thanks! +Ben Dany +Tulio Guimaraes da Silva Brazil HUGE contribution, thanks! +Dave Davis USA +Tomer Dayan Israel +Fabio De Araujo Neves Brazil +Benoit De Greift Eagle Belgium +David Dean Sector4 Australia +Pierre Decourcelles France Big contribution, thanks! +Barthelemy Defossez France +Guy Detienne Belgium +John Dietzel USA +John Di Giacomo USA +Luciano Di Lucrezia Spectrum Big contribution, thanks! +Nick Dinges Germany +Robin Dittwald Satixu Germany +Siem Doodeman Netherlands +Asaf Dor +Stephen Dredge Australia +Andrew Dun Australia +Dave Dunger Australia +Andrew Durk USA +Florian Dvorski Thunk Germany +Brendan Ebel USA +Adam Ebringer Australia +Michael Edwards UK +John Ehmann Canada +Richard Eijkenbroek Netherlands +Michael Elis Isreal +Garrett Ellis USA +Irad Eshel Israel +Scott Esposto USA +Alexander Ewering Internal Germany +Gary Feinmesser England +Nick Feldman UK +Jim Fergusson USA +Robin Fernandes France +Dan Fetherstonhaugh England +Reuben Firmin Rubz Scotland Big contribution, thanks! +Kyle Fischer USA +Edward Flick USA +Brad Folkens USA +Adam Frank USA +Andrew Franks Derelict USA +Graham Freeman Australia +Calvin French Canada +Joseph Freund Australia +David Friberg USA +Matt Friedly Subliminal USA +Richard Funke Norway +James Furness UK +Robert Gage Australia +Miles Gannett USA +Peter Gaywood UK +Christopher General Canada +Giovanni Giampieri Italy Big contribution, thanks! +Slavko Glamocanin Slovenia +Owen Godwin USA +Markus Goetz Cookie Jar Germany Big contribution, thanks! +John Goforth USA +David Goodale Canada +Ferdinand Gozum DJ USA +Jeff Graham USA HUGE contribution, thanks! +Joseph Graham BrianXavier USA +Micah Greenlay USA +Lorenzo Grifi Italy +Sebastian Grillmaier Wayfinder Germany +Moritz Grimm Maxx Germany +Karsten Grombach Germany Big contribution, thanks! +Ariel Gross Stalker USA HUGE contribution, thanks! +Sylvian Guiraud France Big contribution, thanks! +Joe Hahn USA +Peter Hajba Skaven Finland +Doris Hamburger USA +Tim Hamers Netherlands +David Hamilton England +Eric Hamilton Dilvish USA Big contribution, thanks! +John Harris USA +Todd Hartley Tronster USA +Ian Haskin SiN Canada +John Hastie USA +Joshua Hastey Ith USA +Thomas Havelka USA +David Hays D-Range USA +Axel Hedfors Sweden +Brett Helgeson Australia Big contribution, thanks! +Greg Heo Canada Big contribution, thanks! +Liam Hesse Lemm England +Anthony Hicks USA +Robert Hilpert Germany MEGA HUGE contribution, thanks! +Erik Hjelmvik Tweety Sweden +Jason Hlisic isotone Australia Big contribution, thanks! +John Hobson USA +Rune Holm TitanStar Norway +Krystal Holstein USA Big contribution, thanks! +Alexandre Holzhey Brazil +Aake Honkaniemi PAH Finland Big contribution, thanks! +Raymon Hoving Finland +Troy Howard USA Big contribution, thanks! +Ben Howell Rhythm USA +Shu Hung Canada Big contribution, thanks! +Ryan Hunt Pinion USA +David Hunter USA +Steve Hunter UK Big contribution, thanks! +Samuel Hurst Australia +Kohan Ikin Australia +Sam Izzo Jestyr Australia +Shane Jackson MetaMan Canada +Keith Jagielski USA +Daniel Janiak Redrick Slovakia Big contribution, thanks! +Marko Janssen Netherlands +Simon Jarosch Vivid Germany +Chris Jarvis Australia +Dave Jeavons Realclean Australia HUGE contribution, thanks! +James Jeen Australia +Joshua Jersild USA +Jan Jirak Czechoslovakia +Robert Johnson Xenopraxis +Mischa Jonker Netherlands +Ben Just Australia Big contribution, thanks! +Jaakko Kaivosoja Finland +Steffen Kamprath Germany +Frank Kane USA +Ben Kapper Netherlands +Ilpo Karkkainen Griffin Finland +Tero Karkinen Finland +Thomas Karolczak Mindflyer XS +Cole Kelley USA +Keith Kelly Syrinx USA +Mehran Khalili Screamager Luxembourg +Leonard Khiroug USA +Richard Kidwell USA +Thomas Kim USA +David Klande Germany +Martin Kleinman Brain Netherlands +Martin Klossek Germany +Bart Knol Armadon Netherlands +Stephen Knowles USA +Odd Henry Knutsen Netherlands +Henning Koch Germany +Alexander Koenig Germany +David Kondrad USA +Zaf Korbetis Australia Big contribution, thanks! +Evan Korzon USA +Christopher Kowalski USA +Kristof Kowalski Cyntax Australia +Kevin Krebs Canada +Bert Kroes Netherlands +Peter Kunath Germany MEGA HUGE contribution, thanks! +Rich La Bonte Flatrich USA +Michael Ladanyi Canada +Brian J LaMattina USA +Perttu Lamminmki Finland +William Lamy willbe France +Adam Langdon-Thomas UK +Janet Lankester USA +Patrick Lea Australia +Jon Leahy UK HUGE contribution, thanks! +Steven LeBeau USA +Eliot Lee PrOtoCoL USA Big contribution, thanks! +Nicolas Leveille Knos France +Buzz Libre USA +Rik Ling USA +Randy Locklair USA MEGA HUGE contribution, thanks! +Michael Loftus USA MEGA HUGE contribution, thanks! +Kris Long USA +Jerome Majewski USA HUGE contribution, thanks! +Sami Mkinen Finland +Don Manton Canada +Peter Mares South Africa +Anthony Marin Verminator USA +Norman Mark Nothing More Canada +Alexander Martin Germany +Mike Ma'rton Hungary +Akos Matte Bat & Cyborg Hungary +Lucas Higa Mattsson Sweden +Nicola McAleer Ireland +Brad McKinnon EtherWizard USA Big contribution, thanks! +Ray McManus USA +Keith McNally Canada +Glen McNiece Australia +Vincent Meijer Netherlands +Mitchell Menghi Australia +David Menkes Behemoth USA +Mike Merker Canada +Jonathan Mesiano-Crookston Canada +Christopher Micali Zephyr USA +John Michael-Lloyd USA Big contribution, thanks! +Chris Michetti Canada +Pekka Mikkola Finland +Alex Milla Spain +Matthew Miller Australia HUGE contribution, thanks! +Tracey Miller Australia Big contribution, thanks! +Matthew Mitchell USA Big contribution, thanks! +Chun-Yan Miu Hong Kong +Mauro Molinari DjM Italy +Lutz Mller Germany +Jo Moore USA +Freddy Mousseau France +Marten Mons Netherlands +F. Edmund Mueller USA +Markus Mueller G42 Germany Big contribution, thanks! +Paul Munson Canada +Aaron Murray USA +Eric Nadeau Canada +Riley Nagler USA +Tirone Nel South Africa +Frank Nentwich Germany +Mikkel Nordberg Denmark HUGE contribution, thanks! +Gary Norris USA +Fumihiro Odaki Japan +Michiyasu Odaki Japan +John O'Laughlin USA +Anthony Oetzmann AiRON Germany +Xavier Orengo USA +Frido Otten Cybertron Netherlands Big contribution, thanks! +Olli Paasovaara Finland +Robert Pain UK +Jonathan Pak Maelstrom Australia +Andre Pang Ozone Australia +Adam Parker USA +Jourden Parks AllenKray USA +Kiran Patil USA Big contribution, thanks! +Stefan Pavlov +Christian Pfaff Germany Big contribution, thanks! +Jean-Luc Pedneault Canada +Nick Pelling UK +P-J Perrussel-Morin CyberNitrox France Big contribution, thanks! +Chaim Peter-Chester USA +Claus Peterson Denmark Big contribution, thanks! +Felix Petrescu Waka X Romania +Henri Pihkala Estonia +Jason Phelps USA Big contribution, thanks! +Miklavz Pirnat +Eddie Plaskur Mexican Beans Australia +Harout Pogossian HP +Eric Pomerleau O'Realitea Canada +Pascal Q. Porcupine Spikey USA Big contribution, thanks! +William Price USA +Alexander Rahm Germany HUGE contribution, thanks! +Hazhir Ranjram Balk USA +Alessandro Rascazzo Antitesi Italy +Pasi Rastas Finland +Justin Ray Zinc Canada +Tobias Reckhard Jester Germany +Jimmy Redfern Jimmy Ireland +Justin Reid Stein USA +Viktor Rez Hungary +Owyn Richen +Dan Richters USA Big contribution, thanks! +Jay Ridley Australia +Michael Riegel USA +Todd Rieger USA Big contribution, thanks! +James Rimmer USA +Brendan Robert USA +Jeff Robinson USA +Josh Rodman K8to USA MEGA HUGE contribution, thanks! +Jens Roeben Germany +Nick Rose Phantasm Canada +Ryan Ross Canada +Benjamin Rumbaugh USA +Keijo Ruonamaa Gze Finland +Geert Rutten Loonatic Netherlands +Hannu Salonen Salomon Finland +Kevin Salt Netherlands +Mark Sanders USA +Denis dos Santos Brazil +Adi Sapir Doc Israel +Janne Savolainen Finland +Ben Saylor USA Big contribution, thanks! +Konrad Schandera iCEWiND GERMANY +H.R. Scheper-Keuter Josuf Netherlands +Gerben Schmidt Netherlands +Martin Schmidt Germany +Daniel Schwab Germany +Wolfgang Schwarz Germany Big contribution, thanks! +Matthew Scott USA +Kristian Sergiejew Poland +Saurin Shah Nebula USA +Jarrod Sharp Australia +Dan Shaw USA +Ryan Shaw USA +Shaul Shentai Israel HUGE contribution, thanks! +Philip Shipley USA +Oren Shomron Isreal +Josh Silvey USA +Morten Skarstad Norway +Peter Skeide Norway MEGA HUGE contribution, thanks! +Steven Slater Canada +Martijn Sneijder Netherlands +Trond Smevik Poke Norway +Greg Smith Canada +Zachary Smith Dr. Zachary USA +Christoph Sllner AGENT S Germany +Scott Sorenson USA +Nicolas Soudee Zoner USA Big contribution, thanks! +Michael Soutar MSoutar Australia +Kasper Souren Netherlands +Patrick Stacey Australia +Nick Stanfield UK +Andrew Ryan Stinnett USA +Ian Stocker RabiteMan USA Big contribution, thanks! +Mark Straver Moonchild Netherlands +Jer Sypult USA +Charles Tabourot France +Ravon Tamar RavEon Israel +Patrice Tarabbia Mercure France +Jason Le Sueur Tatum USA Big contribution, thanks! +Thor Teague USA +Michael Teehan USA Big contribution, thanks! +Michel ten Voorde Netherlands +Franck Theuex France Big contribution, thanks! +Michael Thomas USA +Sebastian Thomas Scotland +Jaymz Thompson +Philip Thompson UK +Franz Thues Germany +Gabriele Tittarelli T.S.P. Italy +Jason Tracer Electric Keet USA +Nash Trajkowski Australia +Eric Tremblay DeltaX Canada +Brad Turcotte Canada +Michael Twarkowsky Germany +Asbjorn Ulsberg Norway +Martin Underwood UK +Jani Visnen Finland +Mathew Valente TSSF Canada +David Van Dromme Stormlord Belgium +Ryan Van Eerdewijk Canada +Marti Van Lin +Erik Van Hengstum Netherlands +Ernst Van Rossum Netherlands +Filip Van Schoor Cantaloup Belgium +Jan Van Stiphout +Maarten Van Strien Crystal Score Netherlands +Jos vd Geest Netherlands +Oscar Vela Spain +Markus Visti Finland +Ganesh Viswanathan Genosha India +Benjamin Vogt Australia +Edwin Volkmer Netherlands +Vincent Voois Vv Netherlands MEGA HUGE contribution, thanks! +Fredrik Von Braun Sweden +Arno Vryman Netherlands +Petri Vuorio Finland +Ben Waddington Australia Big contribution, thanks! +Gerd Wagner Germany +Chris Wallace CTS USA +Thomas Walter Subsonic Australia +Adrian Ward England HUGE contribution, thanks! +Timothy Weller Flukey USA +Bill Wells USA +Mike Wells USA +Inyoung Whang USA +Jemi White Australia +Brian Wickman CD USA +Liam Widdowson Legend Australia +Gene Wie Psibelius USA Big contribution, thanks! +David Wiernicki Perisoft USA Big contribution, thanks! +John Williams Jackal USA +John Wilson USA +Tobias Wilton Sweden Big contribution, thanks! +Mathias Wintzer +Marco Wotschadlo Germany +Doug Wright Netriangle USA +Fuming Wu Adi Taiwan +Takeshi Yamamoto Japan Huge contribution, thanks! +Shane Yates AlphaRISC Australia +David Zearing USA +Daniel Zegiel USA +Matthias Ziegs MAZ Germany + +... where's your name? :) + + diff --git a/ReleaseDocumentation/DRIVERS.TXT b/ReleaseDocumentation/DRIVERS.TXT new file mode 100755 index 0000000..0e8e9a9 --- /dev/null +++ b/ReleaseDocumentation/DRIVERS.TXT @@ -0,0 +1,577 @@ + + Notes about the sound drivers + + Be sure to check the driver screen (Shift-F5) of your soundcard! + + I often get asked what soundcard I believe is the best. + + My favourite soundcard is the SBLive! produced by Creative Labs. + + + + Driver Summary + +Driver Def/Max Quick- Stereo Bits Mixing Rate/Resolution + Channels select MIDI In/Out available? + +VSound Driver 64/256 Auto Yes 16 8kHz to 64kHz +VSound Driver MMX 128/256 Auto Yes 16 8kHz to 64kHz + For more details on the VSound drivers, check ITVSOUND.TXT + +PC Speaker 64/256 /S1 No 5-7 12->44kHz +DAC on LPT 64/256 No 8 12->44kHz +GUS, Hardware * 32/32 /S7 Yes 16 19->44kHz (A) +GUSMAX, Software * 64/256 Yes 16 8->64kHz +Interwave, Hardware * 32/32 /S8 Yes 16 44kHz, MIDI In + Out +Sound Blaster 1.0 * 64/256 /S2 No 8 12kHz->22kHz +Sound Blaster 2.0 * 64/256 /S3 No 8 12kHz->44kHz +Sound Blaster Pro * 64/256 /S4 Yes 8 6kHz->22kHz (B) + No 8 12kHz->44kHz (B) +Sound Blaster 16 * 64/256 /S5 Yes 16 12kHz->44kHz, MIDI In +Sound Blaster AWE 32* 30/30 Yes 16 44kHz, MIDI In + Out +Pro Audio Spectrum 64/256 /S9 Yes 8 12->44kHz +Pro Audio Spectrum 16 64/256 /S10 Yes 16 12->44kHz +Windows Sound System * 64/256 /S11 Yes 16 8->64kHz +ESS 1868 AudioDrive * 64/256 /S12 Yes 16 22->56.8kHz, MIDI In +ESS 1688 AudioDrive 64/256 Yes 16 8->48kHz +EWS64 Codec * 64/256 /S13 Yes 16 8->48kHz +Ensoniq SoundscapeVIVO* 64/256 /S14 Yes 16 8->48kHz +SoundTrack PCI * 64/256 Yes 16 8->48kHz + +MPU401 MIDI Driver - /S19 - - MIDI In + Out + +Disk Writer * 256/256 /S20 Yes 16 8->64kHz + +* = Driver will play in the background of Windows '95 + +Notes +A) Depends on number of channels used. The hiquality GUS driver reinitialises + the GUS continually to use as few channels as necessary. Some GUS cards + cannot cope with this and you will need to use the alternative ITGUSLO.DRV + instead. +B) The mixing rate of the SBPro depends on whether playback is stereo or mono + + + +PC Speaker (ITPCSPKR.DRV) + + Nothing much else to say here, except... GET A SOUND CARD! :) + + Note: On the info page, using the 'variables' display WILL distort + PC Speaker output. Also, it has been found that the Info Page + screens and the Pattern Editor cause a noticeably higher amount + of hiss through the speaker. + + Note: This driver *MAY NOT* work on laptop's piezo-electric speakers. + + Note: No driver screen available. + + Note: Not for use with Win95 + + + +DAC on LPT 1/2 Drivers + + These drivers are almost exactly the same as the PC speaker drivers, + with only minor modifications. + + To use these, run IT /sITLPT1.DRV or IT /sITLPT2.DRV - depending on + which LPT you have your DAC plugged into. + + Note: If you're interested in building your own parallel port DAC, + check out: http://www.dnc.net/users/collver/dac.htm + or: ftp://ftp.informatik.hu-berlin.de/pub/os/linux/hu-sound/ + + Note: No driver screen available. + + Note: On the info page, using the 'variables' display WILL distort + PC Speaker output. Also, it has been found that the Info Page + screens and the Pattern Editor cause a noticeably higher amount + of hiss through the speaker. + + + + +Gravis UltraSound, Hardware mixing (ITGUS.DRV) + + This file actually contains two drivers in one file. The first is + accessed just by using IT (with no command line parameters, or with + /s7 for Gravis UltraSound). This is equivalent to the original + internal driver that came with previous versions of Impulse Tracker. + + The second driver is selected by providing the correct IRQ for the + GF1 chip. (The second-to-last number of your ULTRASND environment + variable). This is an IRQ driven routine, which means that it'll + work in the background of Windows '95. But note that the timing for + this is NOT as accurate as the timing in the first driver. There is + also a possibility that multitasking OSs can sometimes (although + rarely) cause some settings to the GUS to be missed (which will cause + a note to play unexpectedly). This can be fixed just by restarting + playback. There is NO check for the correctness of the IRQ provided. + Note that the IRQ driven routine doesn't seem to work on all + computers either.. :( + + The Gravis UltraSound *CANNOT* cope with 16-bit samples greater than + 256k-bytes. This is equivalent to 128k-length samples. Also, 16-bit + samples cannot cross 256k boundaries on the GUS, meaning that the + amount of memory you have on the card may decrease by more than you + expect when you load a 16-bit sample. + + You cannot choose the mixing rate for the GUS - the mixing rate is + dependent on the number of channels playing. This driver continuously + reinitialises the GUS to use as few channels as possible. You can + further restrict the number of channels used with /Lxx on the command + line of Impulse Tracker. + +Gravis UltraSound 2, Hardware mixing (ITGUS2.DRV) + + If the first Gravis UltraSound driver clicks continuously when nothing + is supposed to be playing, use this driver ("IT /sITGUS2.DRV"). + + This driver file also contains two drivers - check above on how to + access the second driver. + +Gravis UltraSound Lo-freq, Hardware mixing (ITGUSLO.DRV) + + Only use this driver if notes do *NOT* finish playing off correctly + on your GUS. ("IT /sITGUSLO.DRV" or copy ITGUSLO.DRV over ITGUS.DRV) + This driver does not try to continuously reinitialise the card to use + a minimum number of channels like the above two drivers do. + + + +Gravis Ultrasound MAX - Software mixing (ITGUSMAX.DRV) + + This device has ONLY been included because it works for SOME people. + It has NEVER worked under Win95 with GUS drivers installed as far as + I know. If it doesn't work for you - I'm sorry, you'll have to use + the hardware drivers. Don't write to me and complain if they don't + work for you - you probably won't get a reply. + + To use this driver, you MUST specify your GUSMAX's Codec IRQ *AND* + DMA on the command line as: + + IT /sITGUSMAX.DRV /i /d + + If you want to specify a port (which should be auto-detected OK), + the port is of the Codec, NOT the GUS's Base Address. + (ie. 32Ch NOT 220h) + + Note: After some testing, it *seems* that you'll need an ULTRINIT + of version 2.28a or above to use this driver... + +Here's part of an EMail that I received from Jarkko Seppanen on how he got +ITGUSMAX.DRV working: + +I just found a weird way to make the GUS MAX software mixer to work (for me, +at least). I normally use DMA 6 for playback and DMA 7 for recording. I was +playing around with IT and trying to get the driver to work and changed +both DMAs to 1. And for my surprise it started to work. Next I tried it +with both DMAs 6, with the same result. But the funny thing is, when I +first play a song with both DMAs the same and then change them back to the +original (6 and 7), it still works. I'm using IT v2.11 with ultrinit v2.31. + + + +InterWave Driver - Hardware mixing (ITIW.DRV) + (This includes GUS PnP, GUS PnP Pro, WavExtreme 32 Pro + more) + + You *NEED* to have RAM onboard your soundcard to use this driver, + otherwise your Interwave card will NOT be detected. + + This file actually contains two drivers in one file. The first is + accessed just by using IT (with no command line parameters, or with + /s8 for AMD Interwave IC). This is similar to the original internal + GUS driver that came with previous versions of Impulse Tracker. + + The second driver is selected by providing the correct IRQ for the + Interwave chip. (This is the value given in Windows'95/settings/ + control panel/system/Interwave SYNTH/IRQ). This is an IRQ driven + routine, which means that it'll work in the background of Windows '95. + But note that the timing for this is NOT as accurate as the timing in + the first driver. There is also a possibility that multitasking OSs + can sometimes (although rarely) cause some settings to the GUS to be + missed (which will cause a note to play unexpectedly). This can be + fixed just by restarting playback (or reinitialising in severe cases). + + There is NO check for the correctness of the IRQ provided. + + The Interwave driver contains handlers for two different memory modes + on the Interwave - the more memory efficient mode is where the amount + of ram is directly compatible with the interwave, the second is where + the DRAM configuration is NOT directly compatible with the interwave + and the driver has to handle the RAM slightly more explicitly, which + causes the loss of memory-usage efficiency. + + Here are the modes directly compatible with the interwave: + + Bank 0 Bank 1 Bank 2 Bank 3 Total + 256Kb 0 0 0 256Kb + 256Kb 256Kb 0 0 512Kb + 256Kb 256Kb 256Kb 256Kb 1MB + 256Kb 1MB 0 0 1.25MB + 256Kb 1MB 1MB 1MB 3.25MB + 256Kb 256Kb 1MB 0 1.5MB + 256Kb 256Kb 1MB 1MB 2.5MB + 1MB 0 0 0 1MB + 1MB 1MB 0 0 2MB + 1MB 1MB 1MB 1MB 4MB + 4MB 0 0 0 4MB + * 4MB 4MB 0 0 8MB + * 4MB 4MB 4MB 4MB 16MB + + * These modes cannot be handled by the first driver, so are actually + handled in the second mode. + + The mixing rate for the Interwave driver is fixed at 44100Hz + (CD quality) + + Bug warning: If the sound does NOT play properly, you may need to + run IWINIT before running Impulse Tracker + + + +Sound Blaster 1.0 driver (ITSB.DRV) + + The Sound Blaster has a mixing range of 12000->21739 Hz. You CANNOT + hear any stereo (or surround) effects with this driver, because the + Sound Blaster does NOT support stereo. + + Hardware detection routines are used for Address (eg. 220h), + environment is checked for IRQ and DMA. + + Command line arguments for IRQ and DMA are NOT checked but assumed + correct IF this driver is explicitly selected + (IT /s2 or IT /sITSB.DRV). + +Sound Blaster 2.0 driver (ITSB2.DRV) + + The Sound Blaster 2 driver is basically the same as the Pro driver + with stereo options removed... (ie SB2 cannot do stereo). The + mixing range is from 12000 to 43478 Hz. + + Hardware detection routines are used for Address (eg. 220h), + environment is checked for IRQ and DMA. + + Command line arguments for IRQ and DMA are NOT checked but assumed + correct IF this driver is explicitly selected (IT /s3 or + IT /sITSB2.DRV). + +Sound Blaster Pro driver (ITSBPRO.DRV) + + The Sound Blaster Pro has a mixing range of 12000->43478 in mono mode, + or 6000->21739 in stereo mode. + + Hardware detection routines are used for Address (eg. 220h), + environment is checked for IRQ and DMA. + + Command line arguments for IRQ and DMA are NOT checked but assumed + correct IF this driver is explicitly selected + (IT /s4 or IT /sITSBPRO.DRV). + +Sound Blaster 16 driver (ITSB16.DRV, ITSB16B.DRV, ITSB16C.DRV) + + The Sound Blaster 16 has a mixing range of 12000->45454 in either mono + or stereo modes. + + If you specify this driver ( IT /s5 or IT /sITSB16.DRV ) AND an IRQ + or DMA, IT will try to *FORCE* the SB16 to use the IRQ/DMA. + + eg. On my system, I have my SB16 configured to IRQ 2, DMA 5, but I + can force it to use IRQ 7, DMA 0 with IT /s5 /i7 /d0 + + Hardware detection routines are used for all Address, IRQ and DMA. + + Note: If you select either of the 32-bit mixing modes, then volumes + between 0->32768 are used internally instead of 0->128. + + The second driver, ITSB16B.DRV is a cut down version of the main + driver which does NOT have the advanced mixing options - the only + benefit of this is that it requires less memory. To use this, type: + "IT /sITSB16B.DRV". If you want to have this file automatically used + just copy it over ITSB16.DRV. + + To get MIDI input, I had to do this in Win95: + + Goto "My Computer", right click -> properties -> device manager -> + sound, video and multimedia -> SB16/AWE32 DSP + + Now go to the "resources" tab, and unclick "Use automatic settings" + + Either: + 1) Change your MIDI port from 300h to 330h or + 2) Select a 'basic configuration' which doesn't include the MIDI port + + ( 3) Get an updated driver from Creative Labs, if they've fixed it ) + + Click OK, then click OK on the warning message. + + There is a good chance that it should work now. I believe this is a + bug in the older Win95 SB16 drivers. (I *know* that the SB16 driver + I have prevents MIDI in DOS boxes and is the cause of these problems + because if I remove it, MIDI works flawlessly in DOS boxes in in Win95) + +;---------- ITSB16C.DRV -------- + + I finally managed to encounter a computer which wouldn't accept IT's + old SB16 drivers - and hence I created ITSB16C.DRV. + If you run ITSB16.DRV and the playback cursor does NOT move, then + you MUST close your Win95 box (or restart your computer), *then* run: + + IT /sITSB16C.DRV + + This driver is similar to ITSB16B.DRV in that it is a cut down + version of the full SB16 driver, but this one also has the MIDI + input disabled (which seems to be causing all the problems on the + cards which just won't 'play') + + + +Sound Blaster AWE 32 drivers (ITAWE32.DRV, ITAWE32B.DRV) + + The Sound Blaster AWE 32 driver directly uses the EMU8000 synth chip. + This synth chip has several limitations which you should be aware of: + + It can only use 16-bit samples. + 8 bit samples are automatically converted by IT (so that's not a + problem), but your free memory may decrease by double of what you + expect. (eg. you will need at least 1MB of memory to load 512k + of 8 bit samples) + + It doesn't support ping pong loops or no loops. + IT will automatically expand ping pong loops and will pad non-looped + samples with silence, but this makes sample sustain loops impossible + to implement fully. It also means that ping pong looped samples + could take up to double the memory of forwards looped samples. + + Sustain loops will NOT operate on the AWE32 driver. Instead, they + will be treated as NORMAL loops. + + If you change the loop type from none->forwards or + forwards->ping pong or ping pong->none, you WILL need to reload + the samples each time (Ctrl-G). If you change the loop points on + a sample, you *will* have to reload the samples (Ctrl-G) + + Has a limited frequency range - from the programming information, + it seems that it is impossible to play a note at above 176kHz. + This equates to any notes 2 octaves above middle C (or higher) for + a sample at 44kHz. If a note is not played because of this + frequency limitation, a message will show at the top of the screen + indicating that the frequency range has been exceeded. + + Note: The Address used for the SB AWE 32 is the address of the EMU8000, + NOT the address of your SB. (for command line params, eg A660) + + Note: This driver is NOT used as a default, as many users would benefit + more from the SB16 driver. (I recommend having at least 2MB + of memory if you want to use this driver). Run "IT /s6" if you + do want to use this driver. + + Note: This driver can operate in Win95. In this mode, it uses a + different mechanism which allows the playing of music in the + background, but timing is *NOT* as accurate here (accurate to + around 100 milli seconds as opposed to 800 nano seconds per + frame) + + Note: The second driver, ITAWE32B.DRV, is for people who do *NOT* have + a floating point unit (ie. 386, 486SX computers). ITAWE32.DRV + is preferred as it requires less memory. + + To access ITAWE32B.DRV, run "IT /sITAWE32B.DRV" + + + +Pro Audio Spectrum (ITPAS.DRV) +Pro Audio Spectrum 16 (ITPAS16.DRV) + + BIG thanks to Pelusa for VITAL programming information for this!! + BIG thanks to MZ/PoP for lending me a PAS16 to stuff around with!! + + Note: These drivers will *NOT* work in the background of Win95, + although they will work fine in the foreground. + + Note: You NEED to have the MVSOUND.SYS driver installed for these + to operate or a Window's system driver. + + + +Windows Sound System (ITWSS.DRV, ITWSS2.DRV) + + Again, BIG thanks to Pelusa for VITAL programming information for this! + + ITWSS is a 16-bit driver, with output frequencies ranging from 8kHz to + 64kHz (!). Mixing speeds above 48kHz *MAY* not work on all Windows + Sound System Cards. + + ITWSS.DRV is a completely IRQ driven routine. Although this may not be + compatible with *ALL* soundcards, it permits background playback in + Windows'95 and is FAR MORE EFFICIENT than ITWSS2.DRV. ITWSS2.DRV should + be used if ITWSS doesn't operate properly. + + Note: There is *NO* autodetection on IRQ/DMA. You *will* need to set + these on the command line if they are not IRQ7/DMA1. + + If you *DO* specify IRQ and/or DMA, then it must be DMA 0, 1 or 3, + and IRQ 7, 9 10 or 11. Impulse Tracker will attempt to SET the DMA/IRQ + of your WSS card to these values, in a similar manner to how the SB16 + driver operates. + + + +ESS ES1868 AudioDrive (ITES1868.DRV) + + The drivers for the ESS ES1868 AudioDrive use the PnP registers to + detect/configure this soundcard. If you have disabled the PnP on the + card the driver may not work... + + The default mixing rate is 44kHz, although the card can handle up to 56kHz + + Thanks go out to Diablo for pointing me in the right direction to find + the programming information and Andrew Lee for lending me a card to + program with! + + + +ESS ES1688 AudioDrive (ITES1688.DRV) + + This driver was written for Synergy ViperMAX / GUS Extreme soundcards, + so that the codec may be used to write songs > 1MB large. + + Thanks go to James Hsu / Synergy for providing me with a card to work on. + + + +EWS64 XL Codec (ITEWSCOD.DRV) + + Like the ESS ES1868 Audiodrive, this card uses the PnP registers to + detect/configure the soundcard. The default mixing rate is set at 48kHz + + Big thanks go out to the entire TerraTec team for providing me with a + card to use - especially Kay "Mod4Win" Bruns. + + Notes: + The settings within the EWS64 Codec driver are saved upon exiting. + + The "Reverb Types" are: + 0: Room1 + 1: Room2 + 2: Room3 + 3: Hall1 + 4: Hall2 + 5: Plate + 6: Delay + 7: Pan Delay + + The parameter "Reverb Feedback" only has meaning for Reverb Types Delay + and Pan Delay (6 and 7) + + The "Chorus Types" are: + 0: Chorus1 + 1: Chorus2 + 2: Chorus3 + 4: Feedback Chorus + 5: Flanger + 6: Short Delay + 7: Feedback Delay + + Note: Chorus will only work with EWS64 XL rev 1.1 or greater + + + +Ensoniq SoundscapeVIVO (ITVIVO.DRV) + + The drivers for the Ensoniq SoundscapeVIVO use the PnP registers to + detect/configure this soundcard. If you have disabled the PnP on the + card the driver may not work... + + The default mixing rate is 48kHz. + + + +Sound Track PCI Codec (ITSTCODE.DRV) + + This driver uses the PCI registers to autodetect the card. Unfortunately + this does not always seem to be the correct value, hence you may have to + override the parameters on the command line. (The computer *MAY* hang if + the correct values are not available!) + + Sound Track 97 PCI and Sound Track 42 PCI cards are handled by this driver. + + The 'extra' settings of reverb, chorus, echo, equalizer and surround are + not available on the ST42 cards. SRS settings are available. + + Notes: + The settings within the ST97 PCI Codec driver are saved upon exiting. + + The "Reverb Types" are: + 0: Room1 + 1: Room2 + 2: Room3 + 3: Hall1 + 4: Hall2 + 5: Plate + 6: Delay + 7: Pan Delay + + The parameter "Reverb Feedback" only has meaning for Reverb Types Delay + and Pan Delay (6 and 7) + + The "Chorus Types" are: + 0: Chorus1 + 1: Chorus2 + 2: Chorus3 + 4: Feedback Chorus + 5: Flanger + 6: Short Delay + 7: Feedback Delay + + Huge thanks go to Hanmesoft Corporation for providing me with this awesome + card to work on! (check out http://www.hoontech.com) + + + +MPU401 MIDI Driver + + The MPU401 MIDI driver provides a MIDI Driver to support MIDI Input and + MIDI Output on general soundcards. It does NOT support sample playback + at all. Trying to play a sample will result in the note being 'terminated' + immediately. + + To use this driver, you may need to provide the MIDI port on the command + line; + + eg. "IT /s19 /a360" + + Addresses 330h and 300h are checked if a port is NOT specified. + + + +Disk Writer + + The ITWAV.DRV included with distribution IT is a mono-only + example device. To use it, run IT /sITWAV.DRV or IT /s20 + + The full ITWAV.DRV file which *IS* capable of stereo output + is NOT available for public distribution. Contact me if you + wish to obtain this - it will NOT be made available without + some sort of (monetary) agreement (US$30 for non-profit use) + + Details + 16 bit Stereo/Mono output + 22kHz to 64kHz output frequency + 16 bit quadratic spline interpolation (65536x 'oversampling') + 32 bit mixing + Logarithmic volume ramping with 32768 internal volumes levels. + Sample cut click removal techniques + Resonant filtering + + To use the disk writer, run: "IT /sITWAV.DRV" or "IT /s20". + The files will be created in the same directory as IT.EXE, + and will be of .WAV format. You can change the destination + directory on the diskwriter's driver screen (Shift-F5.) + + It is greatly suggested to use a disk cache to improve the + writing speed. + + + diff --git a/ReleaseDocumentation/FILES.TXT b/ReleaseDocumentation/FILES.TXT new file mode 100755 index 0000000..57f463f --- /dev/null +++ b/ReleaseDocumentation/FILES.TXT @@ -0,0 +1,33 @@ + + Impulse Tracker Version 2.14 + +In the Impulse Tracker ZIP, you should find the following files: + + IT.EXE - The whole program! + IT.TXT - User's manual to Impulse Tracker + IT.DOC - User's manual in Microsoft Word format + CONTRIB.TXT - List of contributions - where's your name?? + DRIVERS.TXT - List of sound drivers for Impulse Tracker + various notes. + If you have a question related to sound quality, sound cards + or sound card specific questions, check this DOC first. + UPDATE.TXT - History of Impulse Tracker. + HINTS.TXT - Just a little compilation of hints for new composers. + FILE_ID.DIZ - Compulsory description file :) + FILES.TXT - You should know what this is by now! + BUGS.TXT - A list of a few known things that are wrong. + SUMMARY.TXT - A convenient, small reference that I recommend ANYONE to + print out. + MIDI.TXT - MIDI Out information written by Andre Pang + (Ozone/Vault) + IMPULSE.FAQ - Frequently Asked Questions file. + ITMIDI.CFG - Basic configuration file for MIDI Output + KEYBOARD.ZIP - Alternative keyboard definition files + source to create + your own + + *.DRV - Sound driver files for Impulse Tracker + +If you do distribute this program (and please do!), then I would be most +grateful if you keep ALL of the files intact. + + - Jeffrey Lim + (Pulse) diff --git a/ReleaseDocumentation/FILE_ID.DIZ b/ReleaseDocumentation/FILE_ID.DIZ new file mode 100755 index 0000000..33fb9a7 --- /dev/null +++ b/ReleaseDocumentation/FILE_ID.DIZ @@ -0,0 +1,12 @@ +Ŀ + Impulse Tracker v2.14 +Ĵ + MOD, 669, S3M, MTM, XM, IT supported + 8/16 bit samples, ping pong loops + 64 Channel/256 Tracks, Full panning + Volume/Pan/Frequency envelopes + Huge variety of soundcards supported + Huge variety of sample formats supported + 10 Stage pattern editing undo buffer + Internal message editor + diff --git a/ReleaseDocumentation/FILTERS.TXT b/ReleaseDocumentation/FILTERS.TXT new file mode 100755 index 0000000..447c049 --- /dev/null +++ b/ReleaseDocumentation/FILTERS.TXT @@ -0,0 +1,143 @@ + + Impulse Tracker and Resonant Filters + +Wanna know how to get resonant filters working in IT? Read on. + +Implementation +-------------- +So far, resonant filters have only been coded into the MMX drivers - so any +soundcard which has an MMX driver for IT will support resonant filters. Of +course, this means that your computer has to have MMX before you can run them. +To hear resonant filtering, you'll first need to select "Filtered" mixing on +Shift-F5. + +Do NOT write to me about non MMX resonant filtering. + +Resonant filters CANNOT be included with hardware GUS / Interwave drivers. The +reason is because these chips do not support resonant filtering in their mixing +algorithms. + +The AWE 32 driver has *approximate* support to IT's software resonant +filtering. Songs written using resonant filters on the AWE32 will not sound +exactly the same with other drivers. + +The diskwriter has all resonant filtering code, of course. (No MMX required) + +Note that the only external player to have resonant filtering implemented is +MikIT. If you use any other player to play your songs that use resonant +filtering (including earlier versions of IT), they will not be played +correctly. + +First note +---------- +If you do use filtering in your songs, you probably should embed your MIDI +Output configuration into the .IT file. This makes the file slightly bigger, +but it ensures that your song will be played correctly on any filter-capable +driver on any computer. This is selected by turning the "Embed MIDI Data" +on the MIDI screen (Shift-F1) to "on". + +Simple filters +-------------- +For most users, this is all that you will need to know. + +The default configuration for IT (copy ITMIDI.CFG to your IT directory) will +recognise Z00->Z7F as set filter cutoff frequency and Z80->Z8F as set filter +resonance. + Z00 is the lowest filter cutoff, Z7F is the highest filter cutoff + Z80 is the least resonance, Z8F is the highest resonance + +If you wish to reconfigure the resonant filters or perhaps create some extra +shortcuts, then read below! + +How the drivers recognise filters +--------------------------------- +The drivers know what to filter by intercepting MIDI messages. This does NOT +mean that filters will require any sort of MIDI equipment, just that the +mechanism to instruct the driver to filter a particular note within IT itself +is made via the MIDI interface. + +The instructions that the drivers understand so far are: + F0 F0 00 - Set filter cutoff frequency to + F0 F0 01 - Set Q factor (resonance) of filter to + +In each of these cases, is between 00 and 7Fh. Values above 7Fh are +ignored. Note that if filter cutoff is set to 7F and Q is set to 0, then no +filters are applied. + +How to tell the drivers these Instructions +------------------------------------------ +OK.. so how can we tell the drivers these instructions? + +For a full explanation, check MIDI.TXT - a short explanation is provided here. + +First of all, go to the MIDI Output configuration screen in IT. Do this by +pressing Shift-F1, then clicking on the "MIDI Output Configuration" button. + +You will see several MIDI configurations, then SF0->SFF then Z80-ZFF (that +bottom window is scrollable). + +Using Z80 to ZFF +---------------- +Z80->ZFF are the easiest to explain.. so I'll explain them first. + +If you type in "F0 F0 01 3F" next to Z80 (make sure that you have the letters +in upper case), then whenever you use Z80 in a pattern, "F0 F0 01 3F" will be +sent to the driver. If you refer back to what instructions the driver +understands, you'll see that this means "Set filter resonance to 3F". + +A few more examples: + Z81 = F0 F0 00 40 - set filter cutoff frequency to 40h + Z82 = F0 F0 01 20 - set filter resonance to 20h + Z83 = F0 F0 00 10 - set filter cutoff frequency to 10h + +Using SF0->SFF +-------------- +SF0->SFF are slightly more difficult to explain.. but hopefully a few examples +will make their usage clear. + +When you use Z00 to Z7F in a pattern, they do not directly translate in the +same way as the Z80->ZFF do. Instead, they set a variable internally called +'z' that gets substituted into one of the SFx commands. + +Example 1 - If you set SF0 = F0 F0 00 z (on the MIDI Output configuration) + +Then using Z01 will cause "F0 F0 00 01" to be sent. + Z01 = F0 F0 00 01 - Set filter cutoff frequency to 1, as above. + Z10 = F0 F0 00 10 - Set filter cutoff frequency to 10h + Z30 = F0 F0 00 30 - Set filter cutoff frequency to 30h + Z50 = F0 F0 00 50 - Set filter cutoff frequency to 50h + +Example 2 - If you define: + SF0 = F0 F0 00 z + SF1 = F0 F0 01 z + +Then: + SF0 - Set Zxx to use SF0 + Z30 = F0 F0 00 30 - Set filter cutoff frequency to 30h + Z50 = F0 F0 00 50 - Set filter cutoff frequency to 50h + SF1 - Set Zxx to use SF1 + Z20 = F0 F0 01 20 - Set filter resonance to 20h + Z3F = F0 F0 01 3F - Set filter resonance to 3Fh + Z50 = F0 F0 01 50 - Set filter resonance to 50h + SF0 - Set Zxx to use SF0 + Z30 = F0 F0 00 30 - Set filter cutoff frequency to 30h + Z10 = F0 F0 00 10 - Set filter cutoff frequency to 10h + SF1 - Set Zxx to use SF1 + Z20 = F0 F0 01 20 - Set filter resonance to 20h + Z30 = F0 F0 01 30 - Set filter resonance to 30h + +Note that the default startup configuration for each channel is SF0, so the +first SF0 in example 2 is unnecessary. + +Resetting the Filters +--------------------- +Since the filters are driver related (and IT.EXE really doesn't know about +their existance), they are not reset automatically when you stop/play a song. +If a MIDI Reset (FFh), MIDI Start (FAh) or MIDI Stop (FCh) message is +received, then the driver will reset all of it's internal tables. The default +configuration will send both MIDI Reset and MIDI Stop commands. + +Final Notes +----------- +Umm.. Enjoy :) + - Jeffrey Lim diff --git a/ReleaseDocumentation/HINTS.TXT b/ReleaseDocumentation/HINTS.TXT new file mode 100755 index 0000000..8197211 --- /dev/null +++ b/ReleaseDocumentation/HINTS.TXT @@ -0,0 +1,572 @@ + + +Hints for Composers + -- Pulse + +Well, I'm not the best person to ask for hints, but here are a few anyway. + +1) Never release your first song. There are very few people who are gifted + enough to really make a quality song the first time - it's all practice + and experience! Once you *HAVE* finished a song, listen to it a couple + of days after... see whether you can view it from another point of view. + +2) For channel echoes, use the Mxx command in a second column - this will + save you from adjusting volume related effects (ie. you can leave all the + Dxx commands alone, and it'll sound right) + +3) Don't be afraid to create multiple instruments from the same sample! The + reason for why I created instruments the way I did was so that you could + have different *articulations* of the same sample. You can achieve this + by playing around with the envelopes, fadeout, NNA - whatever. + +4) Listen to other tracked music. Try and learn how other composers have + achieved the sound they did. Experiment yourself. + +5) Start by writing music that *YOU* really like listening to - don't try and + write am orchestral piece if you don't listen to it - it'll show. + +6) Take the time to tune all your samples as accurately as possible! To do + this, play a long, clear, looped sample, then move to another channel + (using '.') and tune ALL your other samples to this one sample (so they + all have the same reference). Many potentially excellent modules have + been spoilt because they were poorly tuned. Of course, this doesn't + count the cases where samples are intentionally slightly sharp or flat + for effect (which should be the rarity instead of a rule). + +7) Try to avoid having too many samples at central panning - if you modify + the initial panning - you should be able to 'fill' out the sound with + very little extra effort. Or perhaps if you use instruments, you may + want to play around with instrument's default panning... + Pitch pan separation also provides a very convenient way to achieve a + nice pan. + +8) To find the 'perfect' loop: + + a) If you have a GUS/IW, first turn the loop off, then reload all GUS + samples (so that their entire waveform is loaded). + b) Now, select either a forwards or ping pong loop. Only select forwards + if you have a sample which has the same amplitude at both ends. If + you have a sample which has vibrato incorporated into the sample, then + you'll probably find ping pong loops inappropriate. If the sample has + an obvious reoccuring shape to it's waveform, try to account for that + when you select your initial guess at a loop. + c) Play a note at a MUCH higher pitch than you'd normally play it at. + Then, hold down '+' (or '-') on on of the loop boundaries to find a + region of lowest clicking. Then adjust it carefully (one byte at a + time) until you find the best loop location. You will normally need + to change both beginning and end points of a ping pong loop to find + a nice loop, whereas forwards loops usually only require either loop + end or beginning to be modified. + d) Now that you have a decent loop at this pitch, decrease the pitch + (typically by an octave) + e) Repeat steps (c) and (d) until you have a nice loop at the pitch that + that sample is played at. + f) Once you've finished and if you're using a GUS, press Ctrl-G (to + reload the Gravis' samples) and do a final check that you have an + appropriate loop. + + This method works very well MOST of the time - don't forget that the '+' + and '-' keys can be used to easily modify the loop - and the changed loop + is taken into account when you change it (ie. you don't need to replay the + sample). + +9) If you want to make a song realistic, try to imagine how the instrument + would be played. Pretend you are a musician when you write a part.. + Also, if you use an instrument such as a piano, try to use more than a + single piano note - a real piano will ALWAYS have more than one note + playing at a time - use some chords, etc. + +10) For a nice fill to the sound, try to balance the usage of low and high + frequencies. Songs with too much bass and too little treble sound rough, + songs with too much treble and too little bass sound insubstantial. + + + +Hints for New Composers +-- John Hawksley (a.k.a. Greebo) + +1) Listen! + +2) Spend a day figuring out every feature of the tracker. + Yes, I'm talking about all the effects and all the keys. + ST3 is widely acknowledged to be a bitch to learn, but is (sorry, + *was*) the most powerful tracker out. Once you have all the + keys and functions sorted, you'll be ripping around IT's in + no time. You can leave the advanced instrument stuff for now. + +3) Listen to other tracks, find out how the nice-sounding bits are + done. (ie look at the effects and volume/pan column). + +4) Be different. A lot of .MODs are in the same style. Sure, if you + like this and feel comfortable with it, then go for it! But if you + want to create a new feel -- do that too. People are always ready + to try new styles. I personaly enjoy arranging (that covers + a lot of styles) but you might like composing rock tracks, for + instance. So do it! + +5) Samples. Be selective. Sort all your samples into directories. + If you have an editor, the trim thein sample; try to remove the + noise or click at the start. Remember -- samples are the building + blocks from which we craft music. If the samples are bad, + the music will be too. + +6) Tune the samples! When you rip a sample or create one yourself + try to do it at the same pitch, or tune it (using the speed value) + so that everything is uniform. This will save much hair-pulling + later as you try to figure out why half the piece seems to be + in G# major and half is in Dflat minor. + +6) Chords. Originaly, people used to sample whole chords to save + sample space. Now we've got this wonderful IT with it's gazillions + of channels. From ST3 onwards, I have been contructing chords + from notes because I had the space to do so. The sound is better + and is more of a professional approach. + However (there's always a 'but'): be very careful! If you decide + to construct a chord rather than use a single sample, some + musicianship is required. Simple major chords are easy, but + inversions really add to a piece. If you are able to do it this + way (look at some piano parts to any of my stuff, for instance), + you'll get s professional, crafted sound. But it does take + a long time before you'll get a smooth flowing part. + +7) Saving. Okay, so IT hasn't crashed on me yet, but when (if) it + does, I'm not going to loose an hours work. Save regularly. + Never use IT or ST3 under the GUI in 95 and under Windows 3.1; + I found that occaisionaly, windows would do some swapping while + ST3 was saving and the module would be corrupt; but ST3 said + it was saved ok. Lesson learnt. + +8) Releasing. FTP sites are hard to come by these days. Probably + the best method of release is to uuencode your work and + post it to alt.binaries.sounds.mods newsgroup. + + +Hope these are of some help. Remember to visit the Mod Resource Web +at http://www.armory.com/~greebo/mod.html + +I can be contacted at greebo@armory.com. + +Good luck! + +John H. + + + +Hints for Composers +-- ToalNkor / Realtech + + TIP FOR LOADING EITHER LEFT OR RIGHT CHANNEL OF A STEREO SAMPLE : + + Load the sample as usual and then follow these steps : + + If you want the LEFT channel : Just divide the length by 2 + by using Ctrl-F. This will delete one byte out of two, and therefore + only the "first" sample (the left one) will remain ! + + If you want the RIGHT channel : Cut the first and last byte of the + sample (By looping it and using Ctrl-B and Ctrl-L). If the original + sample sise was X, then the actual size should be X-2. From now on, + just follow the same indications as for the left channel and tadaa... + your Right channel sample is ready for use ! + + After all these operations, dont't forget to multiply the mixfrequency + by two to get the original samplingfrequency back ! + + + + Hints for New Composers + -- StereoMan + + 1) The easiest way to produce flanging like effect is to play same sample in + two channels (they must have exactly the same pan-position) and lower or + higher the playing frequency of one of the samples - ie: + + 1 2 2 (1 is same) + ... .. .. Xpp... .. .. Xpp ... .. .. Xpp + xxx ii xx ...xxx ii xx EE1 or xxx ii xx u11 + ... .. .. ...... .. .. ... ... .. .. u00 + u00 and so on. + has the same value in the two channels. + is your instrument number. + is the note you play the sample in. + + 2) You can use the above mentioned effect, but instead of having the channels + with the same pan position you can put them as Left and Right (full) ie: + + ... .. .. X00... .. .. XFF| + . . . + + this will give you a smooth three dimensional sound. + + Note: This effect has not been tested on SurrounD equipment - the results + are li'l unpredictable. + + + 3) Quite a good way to make reverb-like-echos is shown below: + + Let's say You have some sequence playing in one channel. Put the same into + another channel and insert one or two (or more) rows before the beginning. + Now set all volumes to zero (alt-v) and clear volumes which are not + associated with notes (alt-w). Then apply a Dx0 effect (x=1..4 or more) + for example: + + n1. i. .. ...... .. .. ... The results are very good. + n2. i. .. ...n1. i. 00 D20 Once you get used to this you can + ... .. .. ...n2. i. 00 D.. achieve !very! smooth sound. + n3. i. .. ...... .. .. D.. + ... .. .. ...n3. i. 00 D.. The samples must not be too short + n4 i. .. ...... .. .. D.. so Dx0 can take effect. + ... .. .. ...n4. i. 00 D.. + + + 4) If you make the above channels with different pan positions (x22 and xDD) + or (x80, s91) - the results are stunning :) + + + 5) Take your time to read the whole help (yes, the whole of it) - you'll + be surprised to find what hides under your keyboard :) + + + 6) Make your tunes as small as possible. People are not quite happy to find + they have a 3 or 4 Megs of crap on their already full HD drives. + Remember: the smaller = the easiest to spread. + + + 7) NEVER start tracking if you're not into the right mood to track. You'll + only loose time and perhaps make another crappy tune. + + + 8) Funny, but I've found that making your own color scheme truly inspires! + + + 9) Experiment! Play around with the effects, envelopes and NNAs. They all + make music sound more realistic! + + + + George Marinov a.k.a. StereoMan - + + + +Hints for composers +-- Ilpo Karkkainen + +- If you listen only one kind of music, it will shut your mind from others. Be + versatile. When you listen lots of different kinds of music styles, it also + makes your composing a lot more wider and colorful. + +- When listening to music generally, try to sometimes consentrate to something + specific, for example backing vocals or drums. It helps you realize the whole. + It's also good to try listen what different notes there are in a chord that + you hear. At least to me, it has been very helful in chord progression. + +- Details make the whole. Use them wisely, though. Too much details make the + song sound bad. I've noticed that in some of my songs. + + + + Onix4MAN's hints + + + 1) CLEANING A WAV FILE UNDER IT. + 2) CREATING NEW SAMPLES WITH IT. + 3) 3 (4?) METHODS TO MAKE YOUR MODS SOUND MORE SPACIAL.. + + + +1) CLEANING A BAD SAMPLE UNDER IT: +----------------------------------- + +To clean up samples that click at their start (or end) because the waveform +has an error at its start (still or end), without going under a wav-editor: + + -turn on Loop + -start the loop at 100 bytes for samples > 10000 kb + 50 bytes for samples < 10000 kb + -then do 'ALT-B': Pre-Loop Cut Sample + -then turn off the loop + -do the same at the end of the sample with 'ALT-L' if the wav clicks + at its end + + The numbers of bytes given is OK for often met clicks, if your + sample is really bad, just increase it... ;) + + + +2) CREATING NEW SAMPLES WITH IT: +-------------------------------- + + -You simply have to edit one pattern composed of several samples. + (eg. Compose a Break-Beat on that pattern) + -Put this pattern at order 000. + -Save this module. + -Restart IT in Disk-Writer mode. + -Load your module. + -Play it: it is now being written as a wav file on your disk. + -Restart IT normally. + -Load that new sample and use hint 1) if it has a blank at its end to + shorten it. + + +3) 3 (4?) METHODS TO MAKE YOUR MODS SOUND MORE SPACIAL..: +--------------------------------------------------------- + + -Let's start with the 4th method: it's the Surround.. :) + But if your card can't afford surround.. Use one of the 3 following + methods: + + These methods are in fact three times the same but with 3 different way. + I'm sure you knew at least the first (and probably the 2nd too) ;) + These 3 methods require 2 channels. + +For the 2 firsts, you have to set the panning of the Sample/Instrument +somewhere (in 'Order list and panning' or on the Sample List [F3], but +you'll have to load twice the sample, or on the Instrument List [F4], +or on the Pattern Editor itself [F2], but you busy the volume column or +the command column..) +In the following examples, I've set the Panning in the Volume column +(press the key below Escape to do this) + + a) row CHANNEL 1 CHANNEL 2 + 000 C-5 01 00 .00 ... .. .. .00 + 001 ... .. .. .00 C-5 01 64 .00 + 002 ... .. .. .00 ... .. .. .00 + + + b) row CHANNEL 1 CHANNEL 2 + 000 C-5 01 00 .00 C-5 01 64 SDx + 001 ... .. .. .00 ... .. .. .00 + + With 'x < Speed Value' This second method is more precise! + You can even write SD0 (ie. 0 as x) + + + c) The last method is the more interesting if you knew the others, + because it does waste your volume column neither the command + column! So they remain free for other effects! :) + + * This time, you have to be controlled by Instruments (F12 to select + this). + * Then you will need exactly the too same instruments: + - On F4 Screen, select a blank lign and type 'Alt-P' + - Type the lign where your instrument is... Validate!.. + * Then push the panning button: + -set the pan to 00 for your first instrument + -set the pan to 64 for your second instrument + * Then FOR ONLY ONE of those 2 instruments: + Press the Pitch Button and go to edit the envelop: + + -First node: tick 00 ;) + value 00 + + -Second node: tick 01 + value 'Whatever_you_want', (-)1 or (-)2 suggested + + -Last (3rd) node: tick 02 + value 00 + + Doing this, you've created a delay between your 2 instruments. + To end, place them on the same row on the pattern editor (F2): + + row CHANNEL 1 CHANNEL 2 + 000 C-5 01 .. .00 C-5 02 .. .00 + 001 ... .. .. .00 ... .. .. .00 + + Notes: + ====== + *) You don't have to set the pan to its maximum (00 and 64/FF). + You had better do it for one of your smp/inst. And then, for another + choose 16 and 48 (decimal), or... + + *) The third method works because we do not hear the pitch change + in most cases since it is quite quick, but I suggest you do not + use this method for a piano because it's an example where you'll + hear the pitch change and it will sound very ugly: BAAaah! ;) + But it work with Violin and many others. + It may also depend on the speed of your song (time between ticks).. + + + - Nicolas ARROUET (Onix4MAN) o4m@mail.cpod.fr + + + +Hints for new composers. +- Nacho Segura + +About quality of sound, cognitive science, a more convenient composing, sound +experiments and degrees of freedom. + +1) Some composers (trackers) recommend to work with 128 rows and half the +speed (the less the faster). It's supposed that this gives you more control over +the tracks, but that's not totally true. + + - The track doubles its length, so you see the half. You have to move + more times and jump more lines every time. Is it important? Register in a + sheet (or two) how many times do you jump through the pattern. + + - I've examined several songs that use this technique, and this is my + conclusion: THEY DON'T NEED IT!!! Even lines are empty or have + effects. + +The small amount of control gained doesn't compensate the ergonomical +problems. The easiest the best, less interferences between you and the music. +Rookies could think that it only makes you be slower. This is a problem, but +it's not THE PROBLEM. When you forget twelve times what the hell did you write +in top of the pattern and in which track you'll understand... + + +2) Work. Lots of trackers are proud to say that they are very fast. That's not a +virtue, it means less work, less variety, a shorter melody, much less chords, no +harmony, sounds not perfectly adjusted, and the most important thing: +Repetitions until the Eternity. You haved lasted two months writing this four +minutes long song? Show me what you did, I'm really interested! + + +3) Discover Scroll-Lock. Load a song, press play, see what happens with the +cursor... and press some notes. +Cool!!! Isn't it? + + +4) Never use 8-bits or low-quality samples if you can avoid it. The quality of a +song depends on the quality of sounds. "More memory than expected" is better +than "crappier than expected". + + +5) Analogic synthetised instruments can produce strange interactions. An +example: WARMPAD.PAT (a Gravis Patch) sounds really nice, but this chord +produces a strange noise that doesn't exists when we play the same notes +separately: C-3, D#-3 and F-3. Upper octaves don t provocate this phenomenon. +NOTE: There are several versions of Gravis patches. + + +6) Use a global volume as high as possible. It not only gives you a better +signal-to-noise relation. It also gives to IT more degrees of freedom for +volume fades. +Make an experiment: Plug the headphones directly to your soundcard, set the +global volume to 5-8 and make a fade out from 64 to 0 (don't use envelopes, +make it in the volume comlumn of the pattern). You should listen the volume +JUMPING (not sliding, jumping!). In Scream Tracker is even worse. + + +7) Don't be messy allocating tracks (channels, columns... you know). All the +percussion grouped in adjacent tracks, the chord grouped, an empty column (or +more) separating every group of instruments, so you can write fastly this new +idea appeared two seconds ago, without having to go to "Track 21". It also +allows you to write and remix fastly. Everything has its own place and you can +disorder and reallocate patterns without knowing if that loop has been cut, or +where do I have to put a NoteCut command (^^^) to shutdown the analogic +looped bass. It seems more complex when you begin (pattern is wider), but it's +much better, easier to use. + + +8) Print the manual and bind it. And when you have done this, RTFM (you +know, READ THE #%&@$# MANUAL!!). You'll be surprised. + + +9) Make an economic contribution. I think he has worked hardly and Impulse +Tracker is the only tracker that gives tracker songs a proffesional sound and +accoustic. Don't be apologized for sending eight dollars. Is better than zero. +Even if you don't want the ITWAV.DRV you should contribute, at least with a +simbolic quantity. He has won it. + + + +Hints for composers +-- Joakim "Acoustic" Back + +1) Dont use the same bassline, piano chords or whatever the whole song. + Remember that a real drummer wont just sit there like a drummachine, + nature will make him tap sometimes and he realy wants to make + some fills sometimes. + +2) Feel the music. You dont use hammering industrial drums in a soft, + smooth gentle song. And dont place a soft panflute in a blasting + hardcore song. + +3) Use the right volume. Keeping the volume low on an instrument and then + suddenly higher creates a feel of power and rush. Use it. + +4) There are different ways to make a solo stand out. + a) high volume. Having a high volume will instantly keep it in the + focus. Be aware that to high volume will make it stand out to much + and maybe not fit in the picture anymore. + + b) high or low pitch. If you have a lot low and middle note instruments + the solo will be clear and bright as high pitched. As said in other + hints, keeping the others too low or too high will sound terrible. + +5) If you play the piano and have a midi keyboard - use the midi support! + This will make you see that you play the piano with a lot more feeling + than when you track a song with the computer-keyboard. + +6) Accept failure. Dont get all angry just because your song went totaly + nuts. This happends all the time. Your songs will be better and better + the more you use IT. + +7) Use IT alot! Play around with IT, make crazy songs. This will make you + learn ITs features and ways to make nice effects. You wont understand IT + by reading the effects from Axx to Zxx, or reading hints like these, but + mostly by using the effects and using IT, only training will get you to + the top. IT is like a sport, people that dont use it, dont get a thing + about it, but when you get the hang of it, its going to flow. + +8) Learn IT in steps. Begin with some simple samples and a few patterns, + then learn a few simple effects like Exx and Fxx. When you have learned + them, go to a new step. Wait with the instruments (F4). + +9) Make a keychart. Write down some of the keys on a piece of paper, after + a few days you will probably know most of them. When you know almost + all you will understand that using only the keyboard is MUCH faster than + the mouse. + +Thanks for reading, I hope it will help you somehow. +/ Acoustic +n98joab@tycho.helsingborg.se + + + +Hints for Composers +- Maarten Van Stien +- Crystal Score / The Black Lotus + +He! ye like simple solutions? Here's one! + +You might have used the diskwriter for simple drumloops! You also might have +loaded the wav in programs like Soundforge (the king!) to add nice nice stuff +like reverb, eq, dynamics etc... + +As you might guess when you write one period containing a drumloop and you +add reverb, then the start of the sample doesn't have reverb at all, while the +end of the drumloop as tons of reverb. Apart from the fact that it sounds lame +in most cases, LOOPING the sample sounds like hell! So what you do is +diskwriting the same loop twice or more. Then add reverb in your sample editor +and you'll notice that the second period contains the 'reverb' of the first +period. This second period can be looped perfectly. As long as you know where +to find the looping-points! + +Now, for simple drumloops with a little bit of reverb it's dead simple. +But for complex loops with TONS of reverb/delay/crap&more it might be quit +difficult! + +Solution: +* make an extra .IT with the same BPM/frames as your drumloop .IT +* add a simple, short and immediatly-starting sample at the beginning of each + period (in most cases: on pos 000, 016, 032, 048 etc.). These are some sorta + metronome instruments I guess.. +* diskwrite +* find the first sample of the 'metronome-instruments' in a sample editor. +* add markers at that place. +* Mute/Silence the samples so that your metronome-wav ONLY contains markers +* copy your complex drumloops or whatever-loops in mem. like ctrl-c +* MIX to the metronome wav. + +Now you have markers in your complex drumloops! And if you did the above stuff +right, you have perfect loops! + +Make sure the metronome-samples start immediatly! Otherwise use the offset +command (C-4 10 63 O10) or something.. + +ok.. have a nice diskwrite! + +Crystal Score/The Black Lotus +Maarten.Vanstrien@student-kmt.hku.nl diff --git a/ReleaseDocumentation/IMPULSE.FAQ b/ReleaseDocumentation/IMPULSE.FAQ new file mode 100755 index 0000000..48f474c --- /dev/null +++ b/ReleaseDocumentation/IMPULSE.FAQ @@ -0,0 +1,261 @@ + + +*** PLEASE take the time to check quickly through this document BEFORE *** +*** you write to me. If the answer to your questions lies within here, *** +*** do NOT expect a reply at all. *** + +This document is currently incomplete. + +1. Getting Impulse Tracker working. + 1.1 Requirements to run IT + 1.2 Insufficient memory messages + 1.3 "Mix data not allocated" + 1.4 Video characters scrambled + 1.5 Impulse Tracker often hangs + 1.6 Files won't load/take a long time to load! + 1.7 Impulse Tracker doesn't support my soundcard! + 1.8 The sound breaks up/computer slows down when playing songs! + 1.9 Microsoft Windows and Impulse Tracker + +2. Using Impulse Tracker + 2.1 Loading external samples + +3. Miscellaneous + 3.1 What are these CACHE.ITS and CACHE.ITI files?? + 3.2 Distribution sites. + +4. Future versions of Impulse Tracker - Not written yet + +1.1 Requirements of IT + + ------------------------------ + NOTE WIN95 USERS -> READ LATER + ------------------------------ + + Impulse Tracker requires a 386+ PC and > 500k of memory. Impulse + Tracker uses EMS memory. To setup EMS memory, use the following lines + in your CONFIG.SYS file: + + DEVICE=\HIMEM.SYS + DEVICE=\EMM386.EXE RAM H=255 + + Do *NOT* have "NOEMS" or "FRAME=NONE" on the same line as EMM386.EXE + + Also shove these lines in, if they're not already there: + + DOS=HIGH,UMB <--- just to get yourself a little more memory + STACKS=0,0 <--- Some computers require this to prevent crashing + + I cannot guarantee that IT will work with QEMM, but Leszek Clapinski + wrote to me with this advice (thanks!): + In your config.sys, use: + DEVICE=\QEMM386.SYS DMA=64 HANDLES=255 FORCEEMS + Then use "IT -P2" + + I recommend that you also devicehigh and Load-high (LH) as many + possible drivers, so that you have more conventional memory to play + around with. + + ----------- + Win95 Users + ----------- + + If you are a Win95 user, you're probably best off not having HIMEM.SYS + *OR* EMM386.EXE in your CONFIG.SYS file. If you *do* have EMM386, + make sure you do NOT have "noems" as a parameter. + + Win95's internal EMS handling routines *DO* automatically provide + the optimum environment for IT, so you should be able to ignore the + settings given above. + +1.2 Insufficient memory messages + + If you get Insufficient Memory messages at the soundcard + initialisation, read section 1.3 + + If you do not have enough conventional memory, the program will + exit to DOS almost immediately. If you *JUST* have enough conventional + memory, then there may not be enough memory left over to load the + sound driver(s) ( -> No sound card detected ) + +1.3 "Mix Data not allocated" messages + + All non-wavetable cards require extra *conventional* memory to be + allocated in order for them to run appropriately. The amount requires + differs between the drivers and depends also on the mixing speed (the + higher the mix speed, the more memory required). If you get this + message, try to free up some conventional memory. + +1.4 Video character's scrambled + + Some video cards (esp Matrox cards) did not follow the VGA register + standard correctly. Impulse Tracker tries to detecting whether + you have such a card, but if this is not successful, run IT /v2 + for Matrox compatibility mode. + +1.5 Impulse Tracker often hangs + + Impulse Tracker may not operate securely in anything other than + DOS and Windows 95 (these are the two systems that IT has been + extensively tested on) - QEMM/Command shells (eg 4DOS/NDOS) have + been known to cause errors in many situations. + + Aside from these, if Impulse Tracker hangs on you, please write to + me immediately, with a full description of what happens/how you can + make it happen. (Including the version of IT that you use!) + + If you get a blank screen when you run Impulse Tracker, try using + command line parameters to specify your soundcard and port/irq/dma. + The autodetect procedures seem pretty reliable, but there's a chance + that they may be interfering/interacting with unexpected hardware. + +1.6 Files won't load/take a long time to load! + + Some music modules are actually compressed with a program called + MMCMP. Under normal conditions, these files can be decompressed + automatically, under the following situations, they _cannot_: + + 1) You do NOT have EMM386 loaded - the decompression routines + require EMS memory, so if you do not have EMS, you cannot + load these files. + 2) You are running Impulse Tracker through Windows 3.xx - + Windows 3.xx prevents programs from doing certain things... + including the setup routines that the decompressor requires + to run - so these files cannot be loaded under Windows 3.xx + + These files will take longer to load, as they are compressed and are + decompressed to disk first. + +1.7 Impulse Tracker doesn't support my soundcard! + + There may be two reasons for this: + 1) Impulse Tracker really doesn't support your soundcard. + 2) Impulse Tracker supposedly does support your soundcard but + you can't get it to work. + + 1) Solution: Convince your soundcard manufacturer to send me a sound + card to play with AS WELL AS all the programming information. + Alternatively, find a soundcard that Impulse Tracker *DOES* + support - you can pick up some decent soundcards really cheaply. + + 2) First of all, check that you have enough memory. If you have + a low amount of FreeMem once you load Impulse Tracker, it probably + means that there wasn't enough memory to load the sound driver file + which will automatically cause a detect failure. + + Unfortunately, not all 100% compatible (esp "100% SBPro compatible") + soundcards are REALLY 100% compatible. If the drivers do not detect + your soundcard, then try specifying full command line parameters. + If it still doesn't work, then I'm sorry - there's nothing I can do + about this. Hassle your sound card manufacturer to make decent + eqiupment. + + Impulse Tracker uses SB cards in a different *MODE* of playback + from most programs so that they are more efficient and also so + that they can operate in the background of Windows 95. So just + because your soundcard works in another program, it doesn't mean + that it's 100% compatible. (this is for all of you who may think + "But this card works in other programs, why doesn't it work in IT?") + + For Sound Blaster cards, make sure you have the BLASTER environment + variable set in order for IT to detect your card reliably + (SB16/AWE32 excluded, as these use hardware routines). + +1.8 The sound breaks up/computer slows down when playing songs! + + (This section only deals with software mixed cards, ie. almost + every soundcard except native GUS, Interwave and EMU8000) + + Sound output from the computer requires HEAVY computation - up to + 64 thousand calculations per second PER NOTE playing. If your computer + is unable to keep up with this, the sound will have very obvious + chunks in it and your computer will slow down noticeably. + + Solutions: + 1) If you're running Impulse Tracker under windows, you may find + that running it from a DOS bootup provides a SIGNIFICANT increase + the capabilities of your computer in this respect (3x faster + in DOS than Win95 for me) + 2) Limit the number of notes you can have simultaneously via the + command line (/Lxx) - eg. "IT /L32" will limit playback to + 32 simultaneous notes maximum. + 3) Lower the number of calculations required per second per note. + This is done by changing the "mixing speed" via the command line: + eg: "IT /m32000" will cause 32000 calculations per second per note + to be made. "IT /m22000" will cause 22000 calculations per second + per note to be made. Check drivers.txt to find the range of + mixing speed values that your soundcard can manage. + 4) Get a faster computer :) + +1.9 Microsoft Windows and Impulse Tracker + + Microsoft Windows 3.xx and Impulse Tracker is a definite no-no. + I do NOT guarantee ANYTHING under this configuration. I probably + also will not fixup any problems that occur in Impulse Tracker + that only occur under Windows 3.xx + + Microsft Windows '95 and Impulse Tracker *SHOULD* work fine. + If no sound card can be detected under Windows '95, check first that + you have no other program using your soundcard (or another DOS window + still open that used your soundcard). + + Only certain soundcards can play in the background of Windows '95 for + technical reasons. Please read the relevant section of DRIVERS.DOC + for your soundcard. + + Some people have found that Impulse Tracker will hang after a few + minutes under Windows '95. Disabling virtual memory may solve this + problem. To disable Virtual Memory, right click on My Computer, + Properties, Performance, Virtual Memory and check the "disable" box. + +2.1 Loading external samples + + To load in another sample so that you can use it in your composition, + go to the sample-list page (F3), then press "Enter". You will be + taken to the "load sample" screen, where you can test out and select + samples from a wide variety of formats. This includes: + .IFF, .WAV, .S3I, .ITS, .RAW, and TX Wave .Wxx formats. + + You can even load samples DIRECTLY OUT of other modules. In the sample + loader, navigate to a drive/directory which contains modules, and you + will see that they can opened as 'libraries.' So far, support for + external sample loading from modules is available for: + .MOD, .MTM, .S3M, .XM, .669, .PTM, .FAR and of course, .IT + + .PAT and .KRZ instruments can also be loaded as sample libraries at + the moment. + +3.1 What are these CACHE.ITS and CACHE.ITI files? + + Whenever you load a sample or instrument, Impulse Tracker has to + load all the files to find out their contents, to determine + parameters such as sample format, bit fields, etc. CACHE.ITS and + CACHE.ITI are files created by Impulse Tracker so that on subsequent + usage, this information can be loaded almost instantaneously from + a single file, rather than having to reload all the information + again. + + These may be deleted without disrupting program usage, but they will + be recreated when you attempt to load samples/instruments from the + directory. + +3.2 Distribution Sites + + To get the latest versions of IT on the web, check out: + + USA Site - Shawn Mativetsky (Shawn202) + http://www.noisemusic.org/it + UK Site - Andi Simpson (Imminent) + http://www.mixbbs.demon.co.uk + Spanish Site - Javier Gutierrez + http://www.musica.org/impulse + Music and Tracking Site - Matthias Ziegs (MAZ) + http://www.maz-sound.com + IT Resource Central - Matthew Gardner + http://www.unidev.com/~logic/music/it + + Please don't write to me to become a distribution site - the sites + above should be sufficient, and I don't think it is necessary to + have BBS distributions since the use of the internet has become + so widespread. + diff --git a/ReleaseDocumentation/IT.TXT b/ReleaseDocumentation/IT.TXT new file mode 100755 index 0000000..ff5a069 --- /dev/null +++ b/ReleaseDocumentation/IT.TXT @@ -0,0 +1,2199 @@ + + +. ..s..s.s.ssss. +: ::$::$:$:$$$$$ +` ``````'.$$$ .$$$ $$$$$$$$$$ .$$$ .$$ .$$$ .$$$$$$$$$$ .$$$$$$$$ + . . . .$$$$ .$$$$ .$$$$ $$$ .$$'.$$$' .$$'.$$$'.$$$$' .$$'.$$$' .$$' + . . . .$$$$'.$$$$$ .$$'.$ $$$ .$$'.$$$' .$$'.$$$'.$$$$' .$$'.$$$' .$$' + . . . .$$$$'.$$$$'$ .$$'.$$ $$$ .$$'.$$$' .$$'.$$$'.$$$$' .$$$' +. . . .$$$$'.$$$$'.$ .$$' $$$ $$$$$$'.$$$' .$$'.$$$' $$$$$$$$$$'.$$$$$' + . . .$$$$'.$$$$' $$.$$' $$$ $$$ .$$$' .$$'.$$$' .$$'.$$$' .. + . . .$$$$'.$$$$' $$$$' $$$ $$$ .$$$' .$$'.$$$' .$ .$$'.$$$' .$$' +. . .$$$$'.$$$$' $$$' $$$ $$$ .$$$' .$$'.$$$' .$$ .$$'.$$$' .$$' + . .$$$$'.$$$$' $$' $$$ $$$ $$$$$$$$$' $$$$$$$$$$$ $$$'.$$$$$$$$' .cC! + + .. .. + .s$$$$$. .sssssssssssssssssssssssssssssssssssssssssssssssssss. .$$$$$s. + `$$. `$$. .ssss. .ssss. .ssss. .sss. .s ss .sss. .ssss. .$$' .$$' + `$$ `$$ ss.`$ $. ``$ $' .$$ $. `$ $$.s' $. `$ $. ``$ $$' $$' + ds.`$ ds.`$ $$ ' $$ss' $ss$$ $$ $$S $$ $$ss' $'.sb $'.sb + $$$$.$ $$$.$ $$ $$`s. $ $$ $$..$ $$`s. $$..$ $$`s. $.$$$ $.$$$$ + Y$$$$'.$$$$'.cC! `' `' `$$$$.`$$$$Y + `' `' `' `' `' + + + User's Manual + + + + 1. Introduction + 1.1 What is Impulse Tracker? + 1.2 About Impulse Tracker + 1.3 Running Impulse Tracker + 1.4 Technical information about Impulse Tracker + + 2. Using Impulse Tracker + 2.1 Playing songs + 2.2 Pattern editor + 2.3 Order list, channel panning & volume + 2.4 Samples + 2.4.1 Information about samples + 2.4.2 Sample functions + 2.5 Instruments + 2.6 Song Variables + 2.7 Hey! This program looks like Scream Tracker 3!!! + 2.8 Gravis UltraSound / Interwave / AWE32 users. + + 3. Before you write to me (Important notes) + + 4. Closing words + + 5. How to get the latest version of Impulse Tracker + + 6. Legal stuff + + + ** Please note that this document hasn't been udpated in a long time. + ** Some information may be missing, which may be present in supplementary + ** files such as DRIVERS.TXT, FILTERS.TXT, MIDI.TXT, UPDATE.TXT, etc. + + 1. Introduction + If you are familiar with tracker programs, then you could probably + skip through most of this document. (I strongly suggest that ANYONE + print out SUMMARY.TXT though, for a list of effects and editing + commands.) For those of you who have had experience with Scream + Tracker 3, read section 2.7. This should detail most of the major + differences between Scream Tracker 3 and Impulse Tracker. For those + of you who are unfamiliar with tracker programs it would probably be + best to print out this document, and then refer to it as you work + with the program. + + Check out the file UPDATE.TXT. If this document contains conflicting + information with what's listed in UPDATE.TXT, then follow what + UPDATE.TXT contains, as I may have forgotten to update this text. + + 1.1 What is Impulse Tracker? + Impulse Tracker is a program used to create high quality music + without the requirements of specialised, expensive equipment. The + hardware requirements should be easily met: Any IBM 386+ compatible + computer (although a 486+ is recommended), and a VGA or higher video + card. If you want to hear sound, you'll need one of the following: + + Sound Blaster series (or most compatibles) + Pro Audio Spectrum + Windows Sound System + ESS ES1868 AudioDrive + Ensoniq SoundscapeVIVO + EWS64XL Soundcards + Gravis UltraSound + Interwave based board + Generic MPU401 for MIDI Input/Output + DAC on LPT1/LPT2 + PC Speaker + + Note that stereo effects (including surround sound) can only be + experienced on software mixed stereo cards. Hardware mixed soundcards + support panning, but do not support surround sound. + + You'll need about 500k of conventional memory to get the program + running - about 600k to have it load almost any song (as long as you + have an EMM driver - samples are stored in EMS when possible, otherwise + the songs that you are able to load will be limited even further!). + If you use EMM386.EXE, add "H=255" at the end of it to prevent + "Out of memory" messages when you still have EMS remaining. If + you're using some other memory manager, check it's documentation + to see how to increase the number of "memory handles". + + Impulse Tracker supports direct control over 64 channels, and can + load and play the following formats: S3M, MTM, MOD and of course, + IT. At the moment, modules can only be saved in the IT and S3M + formats. + + The number of channels playable on hardware mixed soundcards is + limited by the hardware. Check DRIVERS.TXT for specific details + on your soundcard hardware. + + The Gravis UltraSound can only play 32 channels, although this + shouldn't be too much of a limitation. Note that if you put notes + in channels 33->64 in sample mode using a Gravis, you WILL NOT hear + these notes! (There's an explanation of sample mode much later on, + just keep it in mind if you own a Gravis UltraSound - it shouldn't + cause any problems.) The same restriction applies for the Sound + Blaster AWE 32, but to 30 channels. (ie. notes in channels 31->64 + will not cause any sound) + + + 1.2 About Impulse Tracker. + Impulse Tracker began simply as an extension to Scream Tracker 3 + (which should be quite obvious to Scream Tracker 3 users, due to + the interface.) At first, I only intended a couple of extra + features (eg. proper panning and a couple of other interesting + functions), but with the release of Fast Tracker 2, it became obvious + that there were many areas in which Scream Tracker could be improved. + In spite of all the limitations of Scream Tracker 3 (in comparison + to Fast Tracker 2, which offered Volume/Panning Envelopes, 16-bit + samples, Samples > 64k, an in built sampler, proper stereo panning + on SB16, etc. etc), there were still more .S3M releases than there + were .XM releases! And the reason must have been within the way + you WRITE music with Scream Tracker 3. That's why I've used the same + simple and QUICK interface that Scream Tracker 3 offered. And I've + also incorporated all the power of Fast Tracker 2 and more! + + The Tracker was written in 100% Assembler. All the routines are of + my own coding (That's why some of them suck so much :) ). + The program was written on and off during 1995, but most of the + work was completed in the summer holidays of '96. The source code + is over 100,000 lines long and occupies over 3MB. The Tracker runs + entirely in text mode (!) with some neat remapping of characters + (that's why I haven't been able to use colours to help in some places + ie. making the volume envelope nodes a different colour would have + made it easier to use!). + + 1.3 Running Impulse Tracker. + + Win95 Users - ignore all this HIMEM and EMM386 stuff.. as long as + you don't have "noems" or "noframe" as a parameter to EMM386 in your + config.sys file, it'll work fine. If you have no idea what I'm talking + about, you can probably assume it's fine :) (unless you get "out of + memory messages") + + Impulse Tracker uses EMS. If you want to be able to load large songs, + you need the following lines in your CONFIG.SYS file (on your boot + drive) + + DEVICE=\HIMEM.SYS + DEVICE=\EMM386.EXE RAM H=255 + + eg. if the files are in your C:\DOS directory, you need this: + + DEVICE=C:\DOS\HIMEM.SYS + DEVICE=C:\DOS\EMM386.EXE RAM H=255 + + + If you use QEMM, use the following line instead: + + DEVICE=\QEMM.SYS DMA=64, HANDLES=255 + + If you want to run Impulse Tracker in Windows 95, check out WIN95.TXT + + To find out details about the driver for your soundcard, check through + DRIVERS.TXT. + + Most users should not require any command line switches, however + the following are available: + + SFilename.Drv - Sets sound driver to use. eg. IT /sITIW.DRV + this may become necessary as new sound drivers + are released. + + S# Set sound card + S0 = No sound card (silent mode) + S1 = PC Speaker + S2 = Sound Blaster + S3 = Sound Blaster 2 + S4 = Sound Blaster Pro + S5 = Sound Blaster 16 + S6 = Sound Blaster AWE 32 + S7 = Gravis UltraSound + S8 = Interwave + S9 = Pro Audio Spectrum + S10 = Pro Audio Spectrum 16 + S11 = Windows Sound System + S20 = .WAV writer device + + If this parameter is omitted, then a (hardware) detection + routine is used. Check DRIVERS.TXT for specific information + on the various drivers. + + Axxx Set Base Address of sound card (hex) + D# Set DMA of sound card (decimal) + I## Set IRQ of sound card (decimal) + + M##### Set Mixspeed. Values are accepted between 0->65535, + however, the soundcards have hardware limits which will + override the command line switch. Again, check DRIVERS.TXT + for specific information on your sound driver. + + L### Limit number of active channels + + When you limit the number of channels, you are limiting the + number of notes that you can hear on playback. In a "Sample" + controlled song (explained later), the result is that if you + play a 16 channel piece with the limit at 4 channels, then + you will lose the last 12 channels! Even if the first 4 + are not playing anything. In an instrument controlled song, + the result is that you will hear 4 notes at most, which can + be controlled from any of the 64 channels, excess notes will + be lost. (The reason for this is within the channel + allocation routines.) + + Note that the hardware mixed devices (eg. Gravis UltraSound, + AMD Interwave and Sound Blaster AWE32) cannot play more + than a certain number of channels (drivers.TXT will provide + the exact details). + + If you are new to tracking and didn't understand what I was + just talking about, hilight this section with a marker + (you've printed this out, right?), and in your dabblings, + if you notice that some notes aren't being played, reread + this section. It should make sense by then, and the reason + hopefully lies in the above paragraphs. + + V1 Override VGA detection routine.. in case you DO have a + VGA and the program doesn't recognise it. If characters + look weird, you may need to use this switch to override + the Matrox mode autodetect. + + V2 Force Matrox mode. Use this switch if you get garbled stuff + appearing on your screen + + R Reverse stereo channels. + This is only really useful on the SB16. (Swaps left/right + outputs). The Sound Blaster Pro stereo setting routines + aren't accurate, and will sometimes set the left to left + and right to right (how it's supposed to be), and + sometimes set the left to right and right to left (how + it's not supposed to be :) ). + You can also switch left/right channels in IT by pressing + Alt-R on the info page. + + C Control playback in DOS Shell. + When this option is on, the following keys will operate + within the DOS Shell: + + Right-Alt: Stop playback + Right-Ctrl: Play song (if not already playing) + Grey Plus: Increase global volume + Grey Minus: Decrease global volume + + Warning: There are problems on some computers with this + enabled! If your keboard locks up, it may be + necessary to press the left ctrl/alt to "unfreeze" + it... sometimes (other times.. I don't know!) + + F Disable file colour distinctions. + When this is on, all file colours will appear the same as + the background colour. This is just to make it easier to + redo the palette to your liking more easily. + + 1.4 Technical Information + + Formats supported + Modules: + MOD (M.K., M!K!, 4CHN, 6CHN, 8CHN, xxCH, FLT4, FLT8) + 669 (Composer 669, Unis669) + MTM (MMEdit files) + S3M (Scream Tracker 3 files) + XM (Fast Tracker 2 files, DigiTracker 3 files) + IT (Impulse Tracker 1.xx, 2.xx files) + + Samples: + S3I (Scream tracker sample, 8 bit or 16 bit) + IFF (Fast tracker 2 sample, 8 bit or 16 bit) + WAV (Microsoft WAV, 8 bit or 16 bit) + Wxx (TX Wave format samples) + ITS (Impulse tracker sample, 8 bit or 16 bit) + RAW (Raw sample information, assumed 8 bit) + PAT (Gravis UltraSound patches) + KRZ (Kurzweil Synth files) + MOD (Samples from almost all .MOD formats) + PTM (Samples from Poly Tracker modules) + 669 (Samples from 669 and 669 Enhanced modules) + FAR (Samples from Farandole composer modules) + MTM (Samples from MMEdit modules) + S3M (Samples from Scream Tracker 3 modules) + XM (Samples from Fast Tracker 2 modules) + IT (Samples from Impulse Tracker 1.xx, 2.xx modules) + + Instruments: + XI (Instruments from Fast Tracker 2) + ITI (Instruments from Impulse Tracker) + XM (Instruments from Fast Tracker 2 modules) + IT (Instruments from Impulse Tracker 1.xx, 2.xx modules) + + Modules + 99 Samples maximum + 99 Instruments maximum + 200 Patterns maximum (from 32-200 rows per pattern) + 256 Orders maximum + 64 Channels under direct control + 256 Channels maximum for virtual control (64 max default) + + Samples + 8/16 bit samples + Maximum size around 4MB + No Loop/Forwards/Ping pong loop + Default pan for samples (optional) + Vibrato parameters + + Instruments + 25-point Volume/Panning/Pitch envelopes + Default pan for instruments (optional) + Pitch pan separation + Volume / panning swing + Virtual controls (*REALLY* worth understanding) + MIDI Output controls + + Sound Devices + Generic MPU401 + Sound Blaster 1.xx, 2.xx (8 bit mono) + Sound Blaster Pro (8 bit stereo) + Sound Blaster 16 (16 bit stereo, MIDI In supported) + Sound Blaster AWE 32 (16 bit stereo, hardware mixing, MIDI In & + MIDI Out supported) + Pro Audio Spectrum (8 bit stereo) + Pro Audio Spectrum 16 (16 bit stereo) + Windows Sound System card (16 bit stereo) + ESS ES1688 AudioDrive (16 bit stereo) + ESS ES1868 AudioDrive (16 bit stereo, MIDI In supported) + ESS ES1869 AudioDrive (16 bit stereo) + Gravis UltraSound (16 bit stereo, hardware mixing) + Interwave based board (eg. GUS PnP, Dynasonix, 16 bit stereo, + hardware mixing, MIDI In & MIDI Out + supported) + EWS64XL (Codec driver, 16 bit stereo) + Sound Track '97 PCI (16 bit stereo) + DAC on LPT1/LPT2 (8 bit mono) + PC Speaker (very final option not recommended... ) + + MIDI Output + Supports 128 MIDI Macros + Supports 16 parmaeterised MIDI Macros + Internal handling of conflicting notes + Fully configurable output messages + + + 2. Using Impulse Tracker + Before any specific details of how to use the tracker, it may be + worth knowing these few "editing" keys: + + When using Thumbbars. + Pressing Left and Right arrows will shift the values left/right + Holding down Ctrl while pressing left/right will move them quicker + And Shift-Left/Right will move them even quicker.... + But just typing in a number will get you directly to the desired value! + + String (text) entry. + Nothing special here (and the routines need to be rewritten), but + pressing Ctrl-Backspace will clear the entire text.. + + Numerical entries (of the 7 digit or 3 digit variety) + Pressing '+' or '-' will increase/decrease the value by 1. This is + especially useful when modifying loop values. + + 2.1 Playing songs + If you are like most of us, you would have run the program first, + and probably figured out how to do this yourself. Songs are simply + loaded by pressing F9 at any time (to invoke the file load menu) + and then selecting a song by pressing Enter. You can also type the + first few characters of a filename, and a "search" will be made for + the first match. + + Note that on all the file menus in Impulse Tracker, you can also + delete files by pressing Delete. + + After loading a song, use F5 to play it and F8 to stop. The Info + Page should appear, and you can cycle through views using + PgUp/PgDn. Separate view windows can be created by pressing Insert + (and removed by pressing delete) and these separate windows can + each have a different view method. + + Details (ranges follow in brackets): + Frequency - the speed (pitch) at which the sample is played in + samples per second + Position - the offset in a sample (in bytes) + Smp - The sample currently being played (1->99) + FVl - The final volume of the sample, taking into account + all the scaling factors (viz global volume, sample vol, + envelope volume, channel volume and fadeout) (0->128) + CV - Channel volume (0->64) + SV - Sample volume (0->64) + VE - Envelope volume (0->64) + Fde - Fadeout component (0->512) + Pn - Panning (0->64, Su = surround) + PE - Panning envelope value (0->32) + NNA - The current NNA (Cut/Con/Off/Fde) + Tot - The total number of active virtual channels 'owned' by + the channel + + If you're looking for some songs to play, check out the following + places: + ftp.cdrom.com/pub/demos/music [huge collection!] + kosmic.wit.com/kosmic/songs + ftp.uni-muenster.de/pub/sounds + archie.au/pub/aminet/mods + + 2.2 Pattern editor (F2) + The pattern editor allows you to edit patterns. For those of you + who are familiar with music, patterns can be thought of as "bars", + and the order in which these "bars" are played is determined by + order list. For those of you who are not familiar with music, + consider patterns as a small collection of notes. Impulse Tracker + supports up to 200 different patterns - it *IS* quite a lot more + than it may initially sound! + + Each pattern can range in length between 32 and 200 rows. You can + change this value by using the "Pattern Editor Configuration" screen by + pressing F2 when alredy in the Pattern Editor. (If you want to change + the number of rows of several consecutive patterns, use Ctrl-F2) + The other options available are the base octave (explained later), + the skip value (also explained later), the row hilight major and + minor (which determines the distance between the emphasized rows) + and the command/commandvalue link/split option, which determines + whether when editing, the cursor should move downwards when entering + an effect, or across to the effect value columns. + + The pattern editor appears normally as 5 'channel' columns as such: + (You can configure the pattern editor .. press F1 in the pattern + editor, then page down to find the Track View options.) + + Ŀ + C-5 01 23 A02E-5 02 64 D01 .00 .00 .00 + .00 .00 .00 .00 .00 + .00 .00 .00 .00 .00 + .00 .00 .00 .00 .00 + .00 .00 .00 .00 .00 + .00 .00 .00 .00 .00 + ^ ^ ^ ^ + Component Columns: 1 2 3 4 + + What the component columns mean: + 1) The first column contains the note and octave of the note. + Notes are entered by using the keyboard as such: + + (Note) C# D# F# G# A# C# D# F# G# A# C# D# + + + (What you SD GHJ 23 567 90 + type) + Z X C V B N M Q W E R T Y U I O P + + (Note) C D E F G A B C D E F G A B C D E + (Octave 0) (Octave 1) (Octave 2) + + (For those of you with AZERTY keyboards, you will find that + the keys should work as positioned on the keyboard, rather + than having to figure out QWERTY equivalents) + + The octave of the note is determined by adding the BaseOctave + to the Octave of the note played. The BaseOctave can be + adjusted by pressing the Grey keys '/' or '*' or using + Ctrl-Up Arrow or Ctrl-Down Arrow. + + The range of notes is from C-0 to B-9. The 'middle' note is + considered as C-5 + + Pressing '1' on the note column will enter a notecut command. + This causes any note in the column to immediately stop. + + Pressing '`' (the note below ESC) on the note colume will enter a + noteoff command. This causes all sustain points to be released + (Explained in samples and instruments in more detail.) + + At the bottom of the channel is an 'edit mask'. This highlights + what will be affected when you type anything in. Note that + typing a note in can affect more than just a note - normally + it's set to enter an instrument and volume with it! You can easily + tell IT to enter an effect with it also by changing the + channel mask with ',' (comma) on columns 2, 3 and 4. + + Examples of interpretation: + + C-4 01 . - will play note C octave 4, instrument 1 + D-4 . - will play note D, octave 4, instrument 1 + 02 . - Will play note D, octave 4, instrument 2 + E-4 . - will play note E, octave 4, instrument 2 + G-6 12 . - will play note G, octave 6, instrument 12 + + 2) The second column contains the sample/instrument, depending on + whether the tracker is operating in sample mode, or instrument + mode. Valid ranges are from 01->99 (decimal). + + 3) The third column contains the volume or panning of the note. + To toggle between entry of volumes and panning, press '`' + + Volumes. + 0 is the softest (ie. nothing) and 64 (decimal!) is the loudest. + If no volume is specified, then the default volume for the sample + is used. (Note that effects *CANNOT* raise the volume above 64) + + The volume scale works linearly - ie. one note played at a + volume of 64 will be the same 'loudness' as 4 of the same note, + one played at a volume of 10, another at a volume of 30, + another at a volume of 20 and another at a volume of 4. + (10+30+20+4 = 64) + But if you have a choice, always go for the single note (it + will require less processing (occupy less channels), and also + sound better in quality, due to roundings that occur in processing + softer volumes). + + Panning. + Panning controls appear in a different colour to the volume + controls. For panning in this column, 0 represents far left, and + 64 represents far right. If you have an Xxx effect at the same + time, the Xxx will take precedence over this column. + + It is more efficient filesize-wise to use a panning control in + this column rather than in the effect column. + + Volume, Panning & Effect?? + OK. So you want to do something tricky. Well, it's possible to + get all 3 of these how you want with a little meddling with + the channel volume control - just place one before the row with + an appropriate value (remember that the range is 0->40 HEX) such + that the channel volume scales the default volume to the desired + value.... What I mean is that if you want to play a note at volume + 32, pan 48, with vibrato H81, then you can do the following: + + M20 - Set channel volume to HALF. + C-4 01 48 H81 - The 48 is a pan command - this assumes that + the default volume for sample/instrument 1 + is 64. + + Volume Column Effects + In IT208 and higher, some extra functions are available in the + volume column. These allow you to slide the volume up/down and + pitch up/down, just like the final column effects. If you aren't + familiar with the rest of the editor, leave this section out for + now and come back after you have become acquainted to column + (4) of the editor - the effects column. + + Volume column effects are selected by pressing A-H in the first + column of the effects. + + Ax = fine volume slide up by x + Bx = fine volume slide down by x + Cx = volume slide up by x + Dx = volume slide down by x + Ex = pitch slide down by x + Fx = pitch slide up by x + Gx = portamento to note with speed x + Hx = vibrato with depth x + + In all cases, if x is 0, then the effect memory is used (as + explained in (4) + + The memory for Ax/Bx/Cx/Dx are shared, as is the memory for + Ex/Fx. + + 4) The final column contains effect data. For those of you who are + just starting, I would advise you to leave this section until + later, when you have already dabbled with entering notes, and + want some special features. It's easy to get caught up with all + these special features and you can 'overdo' the effects. + And it will sound absolutely pathetic. + + Trust me, I know - I've done it :) + + Effects are entered by typing 'a'-'z', then a hex value + (see later for an explanation of hex numbers) as the final two + entries. The effects allow you to a wide variety of functions + that are otherwise impossible to obtain. + + Due to the repetitive nature of some effects, there is a + 'memory' so that instead of typing: + + G12 It is easier to G12 + G12 use: G00 + G12 G00 + G12 G00 + G12 G00 + G12 G00 + G12 G00 + + The following effects 'memorise' their previous values: + (D/K/L), (E/F/G), (HU), I, J, N, O, S, T, W + + Note: Bracketed commands share the same 'memory' value. So + + E12 can be written as: E12 + F12 F00 + E12 E00 + F12 F00 + C-4 01 G12 C-4 01 G00 + + Commands H and U are linked even more closely. + If you use H00 or U00, then the previous vibrato, no matter + whether it was set with Hxx or Uxx will be used. So: + + H81 Is the same as: H81 + U00 H81 + U83 U83 + U00 U83 + H00 U83 + + Hex Numbers + Note: Impulse Tracker works ENTIRELY with decimal numbers + EXCEPT for the effects column. + + Instead of using a decimal system (ie. base 10), it is more + natural for the computer to work with hexadecimal (often + abbreviated to simply 'Hex') - numbers which operate in base + 16. The first 9 numbers in hex are denoted by '1' to '9' and + the next 6 are denoted by 'A' to 'F'. So if you count in hex, + it will be as follows: (0), 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, + C, D, E, F, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B, + 1C, 1D, 1E, 1F, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 2A etc. + + To convert a hex number to decimal, multiply the 'tens' column + by 16 and add the value of the second column. ie. 32 Hex = + 3*16+2 = 50 decimal. 2A hex = 2*16+10 = 42. (because A = 10) + The maximum number that you can represent with two Hex digits + is FF = 255 decimal. + + Hope that this makes SOME sense :) + + Effects. + + Axx Set Speed. + + I prefer to think of this command as "Set Frames per Row". + Normally, the tracker operates at around 50 frames a + second. If the rows were played at this speed, then a huge + amount of space would be required to enter the pattern data. + Instead, setting the 'speed' of the song will cause the + tracker to wait on the current row for 'xx' frames. Hence, + setting the speed at 50 (decimal = 32hex) will cause each + row to last about a second - quite a long time! The default + is A06. The initial speed can be set in the variables + screen on F12. + + If two Axx commands are given in the same row, then the + command in the higher channel (by number) will take effect. + + Bxx Jump to order. + + Causes the song to jump to order xx (hex). This is often + used to create looping songs. + + If two Bxx commands are given, then the command in the + higher channel will take effect. + + Cxx Break to row. + + The Command Cxx signifies the end of the current pattern, + and also that the next pattern should be played from row + xx (hex) + + If two Cxx commands are given... you know :) + + D0x Volume slide down + + The volume slide down command causes the volume of the + note to be reduced by x for each frame after (for that + row). ie. If you have a note at volume 64, with command + D01 and speed A06, then the final volume will be 64-5=59. + A note at volume 32 with command D02 at speed A05 will + result in a volume of 24. + + For greater S3M compatibility, D0F will cause the volume + to drop by 15 EVERY frame, instead of just off-note frames. + + Here's a full frame-by-frame description which should provide + greater understanding: + + At 'speed' 4: + C-4 01 .. D04 + + What this does is: + Frame 1: Plays C-4 with instrument 1 + Frame 2: Lowers the volume by 4 + Frame 3: Lowers the volume by 4 + Frame 4: Lowers the volume by 4 + + The next frame will be controlled by the next row of + information. + + Dx0 Volume slide up. + + Operates exactly the same way as D0x, but slides the + volume up by 'x'. Volumes cannot exceed 64 (checked + and limited internally). + + For greater S3M compatibility, DF0 will cause the volume + to rise by 15 EVERY frame, instead of just off-note frames. + + DFx Fine volume slide down. + + Takes the volume down by x at the start of the row. + + DxF Fine volume slide up. + + Takes the volume up by x at the start of the row. + + Exx Pitch slide down + + The pitch will slide down with speed xx (hex). In linear + frequency mode, a pitch slide down by a particular value + will always cause the same "pitch interval" - this does + not occur in Amiga frequency mode. Valid ranges for xx + are between 0 and 0DFh (as > 0E0h will be interpreted as + fine slides) + + EFx Fine pitch slide down + + Slides the pitch down by x at the start of the row. + + EEx Extra fine pitch slide down + + Same as EFx, but 4 times finer. (ie. EE4 is equivalent to + EF1) + + Fxx Pitch Slide up + FFx Fine Pitch slide up + FEx Extra fine pitch slide up + + Operates in the same manner as the Exx commands, but + slides the pitch up. If the pitch gets 'too high', then + the channel is turned off. + + Gxx Portamento to note. + + This command requires 2 parameters: A note to slide to + and a speed. Example: + + C-4 01 .00 + G-4 01 G08 + G00 + G00 + + This will cause the note C-4 to slide to G-4 with speed 8. + + You *CAN* change the sample that the note is sliding to. + It is a good idea to make sure that the C5Speed of the + samples is similar, if you want to try this! The new sample + will play from it's beginning. + + Hxy Vibrato with speed x, depth y + + Causes the frequency to osciallte with depth 'y' at speed + 'x' which causes an interesting effect. Don't get carried + away with it though! If you specify EITHER x or y as 0, then + the previous value will be used. + + Ixy Tremor with ontime x, offtime y. + + Causes the volume of the instrument to remain normal for + x frames, then sets the volume to 0 for y frames. + + Jxy Arpeggio with halftones x, y. + + This causes the note to quickly cycle through three notes - + the note playing, a note x halftones above, and a note y + halftones above. This causes an effect similar to old + C-64 chords. + + Example: C-4 01 J47 will cause the notes C-4, E-4 and + G-4 to be cycled. + + Kxx Dual command: Vibrato + Dxx (Volume slide) + + Note: The vibrato could have been set with either Hxx or + Uxx + + Lxx Dual Command: G00 + Dxx (Portamento to and Volume slide) + + Mxx Set channel volume + + Each channel has a volume range from 0->40h. The lower + the value, the softer the notes in the channel. This + command is convenient for making 'echoes'... you won't have + to modify the echoing channel from the original, except + for placing a M20 at the top of it! + + Values greater than 40h are ignored at playtime. + + N0x, Nx0, NFx, NxF Slide channel volume commands + + These commands work in the same manner as the slide + volume commands, but operate on the channel volume, + rather than directly on the note volume. + + Oxx Set sample offset. + + This will cause a sample to be played from offset yxx00h. + This is useful to skip past the first part of a sample + which may have a loud hit, or to start a speech sample + half way through. + + If you specify a value PAST the end of a sample, then the + command is ignored. + + The "y" part of yxx00h is set with command "SAy" + + Example: + ... .. .. SA5 + C-4 01 .. O10 + + This will play note C-4, instrument 1 at offset 51000hex + + Note to programmers: Oxx for 16-bit samples will move + to the xx00h*2 position in the sample - ie. the 'xx00th' + sample. + + P0x, Px0, PFx, PxF Slide panning commands. + + These work in the same maner as the slide volume + commands, but operate on the channel panning. P0x slides + the panning right, while Px0 slides the panning left. + + Qxy Retriggers a note after y frames with volume modifier x. + + This will cause a sample to be replayed from it's + beginning after every y frames. 'x' can be any of the + following: + + Value Effect on volume each retrig. + 0 No change + 1 -1 + 2 -2 + 3 -4 + 4 -8 + 5 -16 + 6 *2/3 + 7 *1/2 + 8 No change + 9 +1 + A +2 + B +4 + C +8 + D +16 + E *3/2 + F *2 + + Rxy Tremelo with speed x, depth y + + This command acts similarly to the vibrato command, but + affects the note volume, instead of the pitch. If you specify + EITHER x or y as 0, then the previous value will be used. + + S3x Sets vibrato waveform to x + S4x Sets tremelo waveform to x + S5x Sets panbrello waveform to x + + Values for x: 0 = sine wave + 1 = square wave + 2 = Ramp down + 3 = Random! + + S70 Past note cut + S71 Past note off + S72 Past note fade + + With the loss of 1-1 correspondence of editing channels + to internal playing channels, these commands provide + control over notes that have already been played by a + channel. + + Example: + Consider the following situation, where instrument + 1, notes C-4 & D-4 map to a looped sample, and the + New Note Action is set to continue. + + C-4 01 64 . + D-4 01 64 . + E-4 01 64 . <--- Use S70 here! + + Ordinarily, control would be lost over C-4 and D-4, but + using command S70 at the point indicated, the notes C-4 + and D-4 would be stopped immediately when the note E-4 + plays. + + Similarly, note off commands and Fadeout commands can + also be issued. + + Note: You *MUST* be in instrument mode for these + to have any significance. + + S6x Pattern delay for x ticks. + + S73 Set NNA to note cut + S74 Set NNA to continue + S75 Set NNA to note off + S76 Set NNA to note fade + + These options allow you to override the default NNA for a + particular NOTE (ie. it does not affect the instrument) + See section 2.5 for an explanation of NNAs. + + Note: You *MUST* be in instrument mode for these to have + any effect. + + S77 Turn Volume envelope off. + + Stops the processing of the volume envelope. This is for the + times that you don't want to use the volume envelope that + you've created. + + S78 Turn volume envelope on. + + Sometimes, you'll decide that it's better not to use the + volume envelope for most cases, but you may just want to + use it a few times - this is the command that lets you + do that! + + Note: You *MUST* be in instrument mode for this to work. + + S8x Set panning position + + Set panning position, S80 is leftmost, S8F is rightmost. + This is an obsolete command, provided only for ST3 + compatibility. Use command Xxx instead. + + S91 Set surround sound! + + For those of you who are lucky enough to have a dolby + surround sound decoder (myself not included - so if ya + wanna send me something.....), this *should* cause the + sound to come from the surround speaker. This is a + pseudo-panning command, and issuing either Xxx or S8x + will cause the surround sound to be reset. + + If you try and play Surround Sound on a GUS, Interwave + or AWE32, it will be played as a central pan. + + SAy Set high-offset. Check Oxx for an example. + + SB0 Set loopback point + SBx Loop x times. + + This pattern space-saving feature will cause the pattern + to be looped x times back to the last SB0. Note that you + can only loop within the pattern! Also, each channel has + it's own loop-back information... so you HAVE to have the + SB0 and SBx in the same channel for it to operate. + + SCx Note cut after x frames + + This will cause a note to be immediately stopped after x + frames. It is similar to issuing a "^^^" in the note column, + just that it has a finer control over timing. + + SDx Note delay for x frames + + Actually, this command works like "interpretation" delay + for x frames. Any data - note, sample/instrument or volume + in the channel will not be interpreted until x frames into + the row. + + SEx Pattern delay for x rows + + This will cause a "pause" on the row for effectively x rows + longer. + + Note that if TWO pattern delay commands are issued, then + the only the command in the higher channel will be considered. + + Txx Set tempo to xx + + Valid ranges are between 20h and 0FFh. The higher the + value, the faster the playback. This essentially + determines the time length of each frame, by the following + formulas: + Frames per minute = 24*Tempo + equivalently: + Frames per second = 0.4*Tempo + + T0x Tempo slide down + T1x Tempo slide up + + Tempo slides up and down are used to smoothly modify the + speed of the song. The tempo is modified by x every + non-row frame. + + Uxy Fine vibrato with speed x, depth y + + Same as vibrato, but 4 times finer in depth. + + Vxx Set Global volume + + Valid ranges are between 0 and 80h. All notes playing are + affected by this change. + Values greater than 80h are ignored at playtime. + + W0x, Wx0, WFx, WxF Slide global volume + + Similar to the Dxx commands, but operate on the global + volume. Useful when fading out songs. + + Xxx Set panning position + + Sets the panning position anywhere from left to right (X00 + is left, XFF is right). + + Yxy Panbrello with speed x, depth y. + + What the hell is panbrello? Well, it's a word that I coined + late one night after a friend suggested that there should + be a random pan position command. I decided.. why not - I'll + make the vibrato/tremelo equivalent of panning! And so you + have here, 'panbrello.' What this does is instead of + oscillating frequency (pitch) or volume, it oscillates the + panning position about the 'set' panning position for a + channel. This is for you techno freaks out there who want + another function to stuff around with! :) + + The random pan position can be achieved by setting the + waveform to 3 (ie. a S53 command). In this case *ONLY*, the + speed actually is interpreted as a delay in frames before + another random value is found. so S14 will be a very QUICK + panbrello, and S44 will be a slower panbrello. With any + other waveform, the higher the value for x, the faster the + panbrello, like vibrato and tremelo. If you don't know what + I'm talking about, check out the stereo-indicators on the + info page (don't forget that you have to be in stereo mode!) + + If you specify EITHER x or y as 0, then the previous value + will be used. + + 5) Editing Functions + + For a complete list of available functions, check the help screen + for the pattern editor (on F1) + + Ctrl-Backspace IMPORTANT! This one will save you a lot of + frustration - it's a 10-stage listed Undo + function! + + Grey Plus Advance to next pattern + Grey Minus Goto previous pattern + Shift-GPlus Advance 4 patterns + Shift-GMinus Go back 4 patterns + Ctrl-GPlus Go to the next order's pattern + Ctrl-GMinus Go to the previous order's pattern + + Alt-Delete Remove an entire row from the pattern + Alt-Insert Insert an entire row into the pattern + + '.' erase data. + Space will enter the previous data for that column. + '4' play the note under the cursor. + '8' play entire row. + Ctrl-F6 play pattern from the current row. + Ctrl-F7 Set playback mark - this will be the position that + subsequent playback will occur when you press F7. + Remove the mark by pressing Ctrl-F7 on the row + that is already 'marked.' + + Alt-0 -> 9 Quick select "skip value" + The skip value is the number of rows that the + editor advances by when a note is entered - this + makes it easy to enter notes on alternate rows + (press alt-2 first!) + + If the skip value is 0, then the editor will + advance to the next channel (making it easier to + enter chords) + + If the skip value is 0, AND template mode is on, + then entering a note will cause the editor to + advance by the length of the template block. + + Alt-Enter Store current pattern in memory + Alt-Backspace Restore current pattern + + 6) Block Functions + Alt-B Mark top left of block + Alt-E Mark bottom right of block + Alt-L Mark entire column (channel) + Alt-L*2 Mark entire pattern + Alt-D Mark the minor row hilight number of rows. Pressing + this repeatedly doubles the length of the block. + eg. Pressing Alt-D once may mark out 16 rows, + pressing it twice will mark 16 rows. + + Alt-A Transpose all the notes in the block a semitone + down If no block is marked, then the current note + will be transposed a semitone down. + Alt-C Copy marked block into the clipboard + Alt-F Double the length of the selected block + Alt-G Halve the length of the selected block + Alt-I Toggle Template mode... read part 8 + Alt-J Volume Amplifier... modify the volume controls + between 0 and 200% + Alt-K Slide volume... if you want to manually control a + fadeout, or fadein, then set the volumes at the + extreme ends of the blocks, then press Alt-K ONCE! + Alt-K*2 Remove all volume controls in the selected block + Alt-M Mix clipboard with pattern data.. try it out, and + you'll understand (it's like an advanced paste + command - it'll only copy the data IF there is nothing + on the row it is copying to.) + Pressing this two times will copy the data if there's + nothing in the same FIELD (not just same row). + Alt-N Toggle Multichannel mode.. Multichannel mode allows + you to select for each channel whether it should be + part of the multichannel list. If you enter a note + while on a channel which is in the multichannel + list, then the editor will advance to the next + channel. + Alt-N*2 Multichannel menu. + Alt-O Overwrite pattern data with clipboard. Like paste, + but without the "insert" part :) + Alt-P Paste clipboard into pattern at current position + Alt-Q Transpose all the notes in the block a semitone up + If no block is marked, then the current note will + be transposed a semitone up. + Alt-S Set all the instrument (sample) values to the + current instrument (sample) within a block + Alt-U Unmark block / release clipboard from memory. + Alt-V Set all the volume controls to the current + Alt-W Remove all volumes not associated with a note/inst + Alt-X Slide command value. Similar to Alt-K (slide + volume). This command can be convenient to slide + the panning from one position to another, or to + slide global volume effects, channel volume, sample + offsets... whatever... + + Alt-X*2 Erase all effect data in the selected block! + Alt-Y Swap selected block with a samesized/shaped block + starting at the current position. Swap blocks + CANNOT overlap. + Alt-Z Cut current block. + Warning: If you don't have enough memory, the + current block WILL be erased, although there is no + record of it in the clipboard.... + + 7) Track View functions + + Sometimes you just want to know what you've put in those tracks + that are currently off the screen... these functions allow you + to do just that! + + Alt-T Cycle Track view mode. + Alt-R Remove all track views + Alt-H Remove track view divisions (allows you to view 36 + channels!) + Ctrl-0 Remove current track from track view + Ctrl-1->5 Quick select a track view for current channel. + + 8) Templates + + Templates are an invention to make entering repeated + 'sequences' easier. Often, you may want to enter a note with + the same effects following each note. eg. + + C-4 01 00 D10 } + D00 } + D00 } Enter this.... + D00 } + D02 } + D00 } + D-4 01 00 D10 } + D00 } + D00 } + D00 } + D02 } + D00 } Use the templates to enter this! + E-4 01 00 D10 } + D00 } + D00 } + D00 } + D02 } + D00 } + etc.. + + With templates, this can be done by entering the first 'block', + then marking it and copying it into the clipboard (using + Alt-C). Toggle the template mode by pressing Alt-I to Template: + Overwrite, then go to the start of the second block, and press + the key for D-4 (normally X). The whole block will be filled + in! This is easiest to understand if you print this section out + and try it in the editor. + + The templates can also include other notes, which will be + translated accordingly, and can span several channels. + + A VERY neat use of templates is to enter multiple notes: + (eg. octaves, different samples, left/right stereo sample + pairs...) + + C-4 01 32 .00 C-5 02 32 .00 } Enter this... + G-4 01 32 .00 G-5 02 32 .00 } + D#4 01 32 .00 D#5 02 32 .00 } + C-4 01 32 .00 C-5 02 32 .00 } And use Templates here! + G-4 01 32 .00 G-5 02 32 .00 } + D#4 01 32 .00 D#5 02 32 .00 } + + Templates can span more than one row and one channel - you + can template blocks of any size. + + 2.3 Order List, Channel panning & volume. (F11) + After creating patterns, the tracker has to know what order to + play them back in. The order list is the means by which this is + done. Another wording of the Order List which may make it simper + to understand is the "Pattern sequence list." ie. the sequence in + which the patterns are played back. + Simply enter the patterns into the list in the order they + should be played, and voila! - you have a new piece of music. + (as long as you have something in the patterns, of course!). The + "---" marks the end of a song, and "+++" is simply a marker which + is skipped (for ST3 support). Pressing N on a row will enter the + previous order's pattern+1. eg. Entering 000, then pressing 'n' 5 + times will enter 000 (which you typed), then 1, 2, 3, 4 and 5. + + Initial channel panning and volume is the panning and volume that + each channel is set to whenever the song is reset. It will not + affect anything currently playing. On the panning list, you can + also mute channels by pressing spacebar. Pressing S will select + the initial 'panning' as surround sound. The initial channel + volumes can be accessed by pressing F11 once you are already on + the Order list and channel panning screen. + + 2.4 Samples + + 2.4.1 Information about Samples + Samples are the raw sound information. They can be of *anything* + you like - normally a musical instrument of some sort, but you + could have voice samples or sound effects too! + + Impulse Tracker accepts 8-bit or 16-bit samples. It can import + several different formats, which are detailed in section 1.4 + + If you import a 16-bit file which isn't recognised, you have to + use the following steps: + + 1) Press Alt-A (to convert signed/unsigned) and convert the + data. + 2) Press Alt-Q (to toggle to 16-bit) and DON'T convert + the data + 3) If the sample is unsigned, you will then need to convert + it AGAIN by pressing Alt-A (and selecting yes to convert + data) + + Samples have the following information: A name, a default volume, + a global volume, vibrato information, loop information and a + frequency + + The default volume of a sample is the volume at which a sample is + played, IF no volume is specifier. + + The global volume is the modifier by which ALL occurrences of the + current sample are scaled by. + + Vibrato information - the vibrato speed is the speed at which the + vibrato oscillates. Although it is possible to enter values 0->64, + the best effects are obtained by entering values around 24-48. The + vibrato depth determines the maximum deviation from the mean + frequency. The vibrato rate determines how quickly the vibrato is + applied. Higher values cause the vibrato to be applied more + quickly, a low value like 1 can take many seconds before the + vibrato is noticed. + + Loop information. Samples can be looped to provide a continuous + sound. The loop beginning and the loop end must be specified, and + the loop method (either forwards or ping pong) must be set. + (Toggle by pressing spacebar). The loop boundaries can also be + modified using '+' or '-' (even while the sample is playing!) + + Sustain loops are the loops used as long as no note off command is + encountered. In the sample tester, releasing a key provides a note + off command to the player. Once a note off command is issued, the + normal loops apply. The idea behind sustain loops originated after + listening to some synthesizers which provided 'after note' sounds + - like fingers lifting off guitar strings. With sustain loops, you + can have a guitar sound in the sustain loop, with the end of the + sample containing the 'finger off' sound. This way, you should be + able to achieve a new degree of realism. The best way to do this + is to have a reasonably small sustain loop, and a section after it + containing the note-off sound, possibly looped. (The sustain loop + should ideally be less than 1/20th of a second, so that you have + reasonably good control over the timing of the note-off, but this + is not always possible) + + Example: If you have a sample with no sample loop, but a sustain + loop around bytes 19000-20000, then while no noteoff + command is issued, then the sample will loop between + 19000 and 20000. Once a noteoff command is received, + then the sample will be played until it's end and then + will stop. + + If you have a sample of length 64000 with a ping pong + loop around the whole sample (0->64000) and a sustain + ping pong loop around bytes 20000-30000, then the + sample will loop backwards and forwards between 20000 + and 30000 until a noteoff command is received, after + which it will loop between 0 and 64000 (backwards and + forwards). + + It is recommended that you do NOT have a ping pong sustain loop + going to a forwards loop or no loop and that if you DO have a + sustain loop AND a normal loop, that the sustain loop lies + within the normal loop (for ping pong), or that the normal loop + end is after the sustain loop end (for forward's loop) (think + about what you're asking it to do in these cases carefully... + it should make sense - the tracker can still handle the cases + when this is not adhered to, but the resulting note-off effect + can vary greatly depending on timing and pitch!) + + The frequency of a sample determines its pitch. The higher the + frequency, the higher the pitch. The frequency can be doubled or + halved by pressing Alt-Grey Plus/Minus to cause an octave + rise/decrease. For the technically inclined out there, the + frequency is the number of bytes per second that have to be played + for a C-5. You can increase the frequency by one semitone by + pressing Ctrl-Grey Plus or decrease it by a semitone with + Ctrl-Grey Minus. + + To load in a sample, go to the entry in which you want to load it + then press enter. The sample library should appear. You can test + out any sample just by "playing" notes on the keyboard while you + are on top of the sample. Load a sample into the sample list by + pressing enter. Of course, if you don't have any samples, no + samples will appear :) + + Where can I get samples from?? + + You can steal ('rip') samples from modules by going to the sample + in the sample list, then pressing Alt-O. Scream Tracker 3 samples + can be saved by pressing Alt-T (vibrato, global volume + susloop + information lost) or raw samples can be saved by pressing Alt-W + (all variables lost!) + + Warning: Be careful where you rip samples from!! Some people don't + welcome it at all! And in some cases, sample ripping may be a breach + of copyright - this mainly a concern when you use commercial samples) + + There are also many great sample 'packs' available... try a local + music BBS, or the bigger FTP sites. + + Some synthesizers have patch files (eg. Kurzweil 2000 as .KRZ) which + are available through the internet. You can download these, and + convert them with an appropriate utility (I recommend Convert 1.4 - + convrt14.zip on ftp.cdrom.com/pub/demos/programs/convert and use + it to convert the files to .S3I format - even for 16 bit samples). + I don't know what sort of copyright these samples have. *YOU* have + to read any text accompanying the files to find this out. + + Finally, you can make your OWN samples! With a sampler (eg. + Digiplay 3.0) or with some other tracker (eg. Fast Tracker 2), you + are able to record information through the microphone socket of + the computer! + + Note: The length of a sample is *NOT* necessarily the number of bytes + it occupies! The length quoted is the quantity of SAMPLE INFORMATION. + If you have an 8 bit sample, then the size in bytes IS the same as + the length. If you have a 16-bit sample, then the size in bytes + is DOUBLE the length. + + 2.4.2 Sample Functions + + Alt-A and Alt-Q provide basic sample-conversion functions. Alt-A + will convert a sample to or from unsigned to signed format. Alt-Q + will allow you to change a sample between 8 and 16 bits. + + If you want to remove the part of a sample before a loop or after the + end of a loop, you can use Pre-loop cut sample (Alt-B) or Post-Loop + cut sample (Alt-L) + + To reverse a sample, use Alt-G. This can produce interesting effects. + + If you are working to a size limit, check out the functions Alt-E + and Alt-F. These functions allow you to resize the sample to whatever + size you would like! (Note that there is a reduction in quality + associated with a reduction in size). Alt-E will resize the samples + WITH interpolation, Alt-F will resize the samples WITHOUT + interpolation. + + To decrease the volume of a sample, the best way for 8 bit samples + is to reduce the Sample's GLOBAL volume. For 16-bit samples, it's + better to just attenuate the sample (ie. use Alt-M to 75%). The + sample will retain greater quality if you follow these guidelines. + + Alt-M is used to amplify a sample to between 0 and 400%. The default + value for Alt-M which appears is the maximum the sample can be + modified without creating clipping distortions. + + To exchange two samples *in the sample list only*, use Alt-X. To + swap two samples *even in the pattern data*, use Alt-S. + + 2.5 Instruments + + For those who have never used a tracker before, I strongly suggest + that you skip this section for now - learn how to 'use' samples + first. After that, you'll should be able to understand and hopefully + fully appreciate the power that instruments can provide. + + To enable instruments, go to the song variables (F12), and press + on the "Instruments" button after then "Control" prompt. This *MUST* + be done in order to use ANY instrument function (including special + note effects, viz S7x). + + The instrument parameters are split into four screens - one for + each of general options, volume options, panning options and pitch + options. To select the appropriate screen, just whack enter on any + of the four buttons at the top of the instrument list. + + Instruments are collections of samples (or just a single sample). + The translation of samples is controlled by the column in the + centre of the screen on the general options page which shows what + note/sample pair a single instrument note will be translated to. + Example: If you're on instrument 1, and the note translation table + appears as such: + + C-5C-5 01 + C#5C-5 02 + D-5D-4 03 + D#5D#4 03 + + Then entering "C-5 01" into a pattern will cause sample 1 to be + played at pitch C-5, "C#5 01", wil cause sample 2, to be played a + pitch C-5, "D-5 01" will cause Sample 3 to play at D-4, "D#5 01" + will cause Sample 3 pitch D#4 to play... get the idea? + + Why would you want to combine several samples into one instrument? + Well, one very good reason is that it makes it easier to enter + drum parts - you no longer have to change the 'instrument' if you + want another sample. And also, combining them into one instrument + makes them easier to manage - you can specify a volume envelope, + NNA or FadeOut which will apply for ALL of the samples in the + list. + + Another reason is if you want a very high quality sounding + 'instrument.' If you wanted to go overboard, you could sample + every single note on a piano separately, and set up the note + translation table to point to each sample accordingly - you'd + get a very, very nice sound - if you don't run out of memory + first. Or patience :) + + When you save an instrument to disk, all the related samples are + stored with it. This means that you can setup a 'drum kit' instrument, + and to load it into another song, you only need to select that + instrument and all the samples will be loaded for you. + + The Fadeout value for each instrument determines how quickly the + volume of the instrument decays under any of the following + conditions: + 1) NNA "FadeOut" is selected, and another note is played. (see + later in this section for info about NNAs) + 2) The end of a volume envelope is reached. + 3) A note off command is encountered, without a volume envelope. + 4) A note off command is encountered, and the 'normal' volume + envelope loop is on. + + The larger the fadeout value, the quicker the volume decays. + + Each instrument also has an associated volume/pan/pitch envelope! + The volume envelope is editing by selecting the node (left/right + arrows) then picking it up (with enter), moving it around (using + arrows, or Alt-Arrows for quicker control), then pressing enter + again to "put down the node". Nodes can be inserted or deleted + (with the keys insert and delete!). Note that the envelope will + only be used if the envelope flag is set to "on" (just below the + envelope graph).. + + Remember that you have to be in instrument mode for this all to work! + + There are 3 pieces of information for each Envelope graph - + the node number (hopefully obvious), the time of the node (the + number of 'ticks' or 'frames' that elapse before the node point) + and the value of a node (also hopefully obvious). So the x-axis + is time, and the y-axis is volume/pan/pitch - simple, really! + + You can also specify envelope loops and sustain loops. These + operate in the same manner as the sample loops, but the numbers + refer to node numbers. + + The powerful feature of this tracker, though, is not the + envelopes by themselves - it's the New Note Actions! What these + options do is allow you to select what should happen to an + instrument when another note is played in the same column. If NNA + "Cut" is selected, then the previous note will immediately be + stopped (like in all other trackers). If NNA "Continue" is + selected, then the note will continue playing! This is especially + useful for Drum Parts, where there may be a long-ish snare sample + - you can go on ahead and put a bass drum in the very next row + after it - the snare drum will still complete playing! NNA "Note + Off" issues a note off command to a note when a new note is played + in the channel. This is particularly useful in combination with + volume envelopes and volume envelope sustain loops. NNA "Note + Fade" causes the current note to fade out with the fadeout value + when a new note is played. + + WARNING!! + New Note Actions are EXTREMELY powerful, but they CAN cause + problems if you are not careful. Selecting NNA Fade with a fade + value of 0, or note continue with a looped sample (no volume + envelope) or anything which can cause a quick build up of + allocated channels can easily hang a slow computer (or even a + quick one, for that matter!) I tried to put checks against this, + but they always triggered too late - "past the point of no return" + where the CPU becomes so bogged down with processing the + information, that it can't do or try to do anything else. (The + tracker has *MANY* calculations to do - the most time consuming + are the mixing routines, which require the processor to process as + many bytes as the mixing speed per second for EACH note ie. a + mixing speed of 44kHz means that for each note playing, 44000 + calculations have to be made EVERY second... so with 64 channels + 'active' at the maximum mixing rate for a SB16, almost 3 MILLION + calculations have to be done EVERY second to produce the sound (in + mono)!!! (My 486 can cope with this, but my 386 just dies!) + + Duplicate Check Type (DCT) / Duplicate Check Action (DCA) + DCT = Off/Note/Sample/Instrument, DCA = Cut/Off/Fade + + When the duplicate check type is enabled, then repetitions of the same + instrument¬e/sample (or just repititions of the same instrument) + pair in a particular channel will cause the previous occurence of + the instrument¬e/sample pair to be cut or faded (depending on + the DCA) + + Example: If the DCT is set to note, and DCA is set to Cut, then the + asterixed notes will cut out the tilda notes + Ŀ + C-4 01 ~ C-4 02 ~ C-4 03 } + D-4 01 C-4 02 * ~ D-4 03 } Nothing get's cut. + C-4 01 * C-4 02 * C-4 02 } + + + This option was included to help limit the number of active channels, + and is especially useful for drum tracks. + + Another nifty application of Duplicity checks is the following + example: You can have a separate sample for each string of a guitar + and setup and instrument to accomodate this. Setting the NNA to + continue, the DCT to sample and the DCA to fade (with a relatively + quick fadeout) means that whenever you play a new note, the previous + note will continue to play on. BUT! If a previous note of the same + instrument has the same sample as the new note being played, then + it will be faded out - this closely relates to what you hear when + someone plays a guitar - when they play the same string, they have + to put their fingers down on the string, which causes the last note + *on that string* to fade out. + + I sincerely hope that these options do not cause the death of brilliant + 4 channel music - that would be a great shame! There is truly an art in + making a decent sound in as few channels as possible! (If you're new to + this sorta thing, then it'll grow upon you...) + + For interest's sake... + Channels are turned off internally under any of the following + conditions: + 1) The end of a sample is reached (quite obvious) + 2) When the end of a volume envelope is reached, and the final + envelope volume is 0 + 3) When the fadeout value for a channel causes it to become silent. + 4) When a duplicate note is played when DNT is set to Note and DCA is + set to cut for the instrument. + 5) When a notecut is issued (obvious) + 6) When a channel is moved to the background (using NNAs) + AND the volume is 0. + + Out of all the functions provided for the Samples and Instruments, + perhaps the only one that requires explanation is the "Update + Pattern Data" function. This function was written for people who + have already written music in MOD/S3M/MTM formats, and want to + combine their percussion parts into a single instrument. The way + to do this is to set up the instrument->note/sample table, and + then use the "Update Pattern Data" function. What this does is + search through all the patterns for all occurrences of the + note/sample pairs that appear in the instrument->note/sample + table, and replace it with the appropriate note/INSTRUMENT pair. + Sounds quite complicated... sorry :) + + Example: + If you originally have the following setup + + Sample 1 = Bass Drum + Sample 2 = Snare Drum + Sample 3 = Closed Hihat + Sample 4 = Open Hihat + + And the following column within any pattern: + + C-5 01 . + C-5 03 . + C-5 03 . + C-5 03 . + C-5 02 . + C-5 04 . + C-5 01 . + C-5 04 . + C-5 01 . + + You can combine these four samples into one instrument by + creating the instrument->note/sample table with the + following entries: (say for instrument 10) + + C-5C-5 01 + C#5C-5 <--- just an empty slot... + D-5C-5 02 + D#5C-5 + E-5C-5 03 + F-5C-5 04 + + And using the update pattern data command will produce the + following + + C-5 10 . + E-5 10 . + E-5 10 . + E-5 10 . + D-5 10 . + F-5 10 . + C-5 10 . + F-5 10 . + C-5 10 . + + 2.6 Song Variables + + Most of the options on this screen should be quite obvious, but they + are explained here for clarity. + + Song Name - should be obvious. Shove whatever you like in here :) + + Inital tempo - The tempo that the piece starts with. The tempo + calculation is explained under the set tempo + command (Txx) + + Inital speed - The speed that the song starts with. The speed + calculation is explained under the set speed + command (Axx) + + Global volume - This scales all the volumes in the song. It may be + necessary to change this value if there is overload + occuring (in the form of crackles in the music) - + especially on the Gravis UltraSound, as it is a + non-mixing device, and not scaled by the mixing + volume. + + Mixing volume - This value affects mixing sound devices (ie. + all Sound Blaster cards + PC Speaker). + + Separation - The separation determines how far apart the left/right + panning sounds. It is suggested that for a stereo + system (where the speakers are relatively close together) + that the separation be around its maximum (ie. 128). + For a stereo system where the speakers are placed a + large distance apart, a value of 80 may suit better. + A suggested separation for headphones is around 40. + This value has no significance unless stereo playback + is selected. + + Old Effects - When Impulse Tracker was first written, some effects + were interpreted differently from other formats, most + notably vibrato. When you turn this ON, then it effects + will be interpreted how the used to be in ST3/MMEdit/... + but when it's off, it'll operate how it use to in + previous versions. + + Differences: + The Vibrato (and Tremelo) used in IT is smoother than + how it was implemented in MOD/S3M/etc. It is updated + EVERY frame and hence is independant of song speed, + whereas the standard vibrato WAS dependant upon song + speed. Vibrato is two times 'deeper' with Old Effects + on. + + Sample offset commands past the end of a sample in IT + were ignored, whereas with Old Effects on, the sample + is played from it's end point. + + Control - This is the option that lets you use Instruments! + When Control Sample is selected, then all the instrument + information is ignored. The query to initialise + instruments, if accepted, will copy all the sample + names to the instruments (if the samples exist) and set + up the Note Translation Table for each instrument to point + to a sample. + + Playback - Mono: When you select mono playback, all stereo commands + are essentially ignored. If you are using a SBPro, + selecting Mono provides a higher quality output + than selecting Stereo and using a central pan. + + Stereo: This is the option to go for! + Note that stereo mode requires more processing + power than mono (unless you are using a hardware + driver) + + Pitch Slides - Amiga: This is the mode to choose for compatibility + with S3Ms, MODs, MTMs, XMs... when you select + amiga pitch slides, you'll often have to + experiment to find the adequate slide value. + + - Linear: With the linear slides, a certain slide value + will always cause the same music "interval" + change. An example of what this means is if + you slide up a note with speed 8 (ie. F08) at + speed 5, then the result will be that the + note is raised a tone. Everytime. So a C-4 + will rise to a D-4, C-5 will rise to a D-5. + (It's not like this with amiga slides! A + C-4 *MAY* rise to a D-4, but if it does then + the C-5 will rise to a note around E-5!!) + + The benefit of linear slides is that if you + slide a pair of notes at the same speed, they + will maintain the same interval (pitch + difference) throughout. Also, if you modulate + (transpose) a pattern, you will not have to + modify any slide values. + + Directories - this shows the current song/sample/instrument + directories. If you want to save the current directories + as the default to have on bootup, then press enter + on the Save button. Note that this save function also + saves the palette, keyboard type, info page layout + and pattern editing preferences to IT.CFG + + 2.7 Scream Tracker 3 Users + This section is just for users of Scream Tracker 3 who would like to know + the differences between ST3 and IT without working through the whole + document. In a nutshell: + + 1) Differences in use. + a) The Order List, Panning and Variables used to be on F1. In IT, + F1 has been reserved for the Help Screen, F11 for the order list + and panning, F12 for the variables. + If you REALLY do find this too inconvenient, use the command line + switch -k to swap the interpretation of the keys F1 and F11... + no text will be updated tho (and it does seem sorta weird!) + b) Samples now have associated Vibrato information and a global + volume. The global volume affects all instances of the sample + throughout the song. This is useful when you replace a sample, + which is at a different volume from the original - you can just + adjust the global volumes of the samples to suit. + d) Block functions are no longer restricted to one column. This also + means that when you copy entire patterns, you will have to go to + the top left of the pattern. Also, you will have to set the number + of rows in the destination pattern to the appropriate number if + it is different from the source. + This difference may take some getting used to - you may often + find yourself doing several block functions in a single columns + when you could actually have done it across the whole block! + * To mark blocks, you can use Alt-B and Alt-E, or Shift+Movement * + e) In the pattern editor, the following commands have changed: + 1) Alt-T : Track View has been upgraded. Alt-T will cycle + through all of the possible 5 viewmethods. You can + use Ctrl-1 to Ctrl-5 to quick select a view, or + Ctrl-0 to remove a view. Press Left-Ctrl+Shift 1->4 + to select a 'different way to edit' :) + 2) Alt-X : Pressing Alt-X once will slide the effect data value + in a block (useful for controlling global volume, + panning or sample offsets in some cases). Pressing + Alt-X twice will cause all of the effect data to be + deleted as in Scream Tracker 3 + 3) Alt-K : Pressing Alt-K once will slide the volumes. Pressing + Alt-K TWICE will remove all volume controls in the + block. (Works like Alt-X, but on the volume column) + 4) Alt-I : Cycle Template control. + 5) Alt-J : Volume amplifier. Select an amplification between + 0 and 200%. + 6) Alt-H : Now toggles view divisions on/off. Makes it possible + to view/edit up to 36 channels in the pattern editor!!! + 7) Alt-Z : Originally the Zap command (if pressed twice)... now + it is effectively a "Block Cut" command. It will + copy the block into the clipboard, and then wipe the + block clean. + 8) Alt-V : Will set all the volumes in the block to the default. + 9) Alt-W : Will remove ALL volumes not attached to a + note/instrument Therefore, the old Alt-V command can + be simulated using Alt-V then Alt-W. The reason for + doing this was so that the Alt-K, Alt-W combination + would slide all the volumes with notes/instruments + associated. + f) There is no chord edit feature in IT. I considered the chord + edit feature of ST3 useless and a bad influence on new trackers :) + g) Patterns can be from 32 to 200 rows! (Under Pattern edit config + on F2, or Ctrl-F2) + h) Pressing spacebar in the pattern editor will cause the previously + entered note/instrument/volume/efffect/effectvalue to be entered. + Quite convenient. Hopefully. + i) Alt-F10 now solos a channel instead of toggling all of the + channels on/off. On the InfoPage, you can use 's' to solo + channels, and 'q' to toggle channels. I felt that this was more + usable than the original. + j) The infopage itself has become upgraded... press PgUp/PgDn to + cycle through view methods, "Insert" to add a window, "Delete" + to remove the currently highlighted window, Tab to move between + windows, Alt-Up/Down to move the base of the window up/down. + k) To increase the sample frequency by an octave in the sample + list, press Alt-Grey '+' or Alt-Grey '-' to decrease the + frequency by an octave. To change it by semi-tones, use Ctrl-Grey + '+' and Ctrl-Grey '-' + l) The Sample library is accesible from all screens in the program + by pressing Ctrl-F3. The Instrument library is accesible on + Ctrl-F4. + m) Each channel has an associated volume. Echoes can be created by + just copying one channel onto another, then setting the "channel + volume" (Command Mxx) + n) When channels are muted, all commands are still interpreted, but + the notes aren't played. What this means is that commands such + as Axx, Bxx, Cxx, SBx, Vxx, Txx, Mxx, Nxx will be processed even + if they are in a muted channel. + o) Pressing Ctrl-Grey Plus and Ctrl-Grey Minus in the pattern + editor will go to the next/previous pattern according to the + order list! + p) Samples have sustain loops + Ping Pong loops supported + q) Note off command & Note cut command implemented... Note cut is + exactly like ST3's ^^^ (and appears like it too!) Note off + appears as "" and releases sustain points. + r) You can enter panning values (between 0 and 64) in the volume + column. Do this by pressing '`' to toggle between entry of + panning/volume values. + s) You can use samples >64k and 16 bit samples!!! + t) When you use a skip value of 0, the cursor will move across to + the next channel. This is a very convenient way to enter chords, + especially when combined with the multi-channel selection (whack + Alt-N twice) + + 2) Differences in interpretation of notedata. + a) Global volume changes will affect ALL of the notes playing. In + ST3, global volume changes only affected new notes. The range + for the global volume command is from 0 to 80h + b) If you specify an instrument without a note, then in ST3, the + volume is set to the default volume. In IT, the volume will be + set to the default volume *IF* the instrument specified is the + SAME as the currently playing instrument. Otherwise, the new + sample will be played from it's beginning. + c) Command X (Set panning, not REALLY implemented in ST3) now has + range from 0 to 0FFh. + d) Command C (Break to row) now works in HEX. This is so that you + can jump to any row in the (next) pattern. + e) New commands: + M: Set channel volume + N: Slide channel volume + P: Slide panning + S5x: Set panbrello waveform and reset panbrello position + S6x: Pattern delay for x frames. + S7x: Instrument related controls (8 different controls here) + S91: Surround sound on! + SAy: Set high offset + T0x: Tempo slide down + T1x: Tempo slide up. + W: Global volume slide. + X: Set pan position. + Yxy: Panbrello + f) If you use the portamento to command (Gxx) to a different sample + in ST3, the sample offset is undetermined. In Impulse Tracker, + the sample will be played from it's start. + g) The commands Hxx and Uxx will cause a vibrato half the depth + of ST3 if "Old Effects" option is OFF and the vibrato in IT is + also smoother than the vibrato in ST3. + + 3) The greatest difference is the implementation of instruments. Read + section 2.5 for more information. + + 4) Saving S3M modules. + + The following guidelines have to be followed to compose 100% + compatible S3M modules. + + General Stuff + 1) *Pitch slide mode MUST be amiga. + 2) *All initial channel volumes MUST be 64 + 3) *No instruments functions can be used. If you ARE in + instrument mode, however, Impulse Tracker will translate + the pattern data according to the Note Translation Tables. + 4) The song message is *NOT* saved in S3M format. + + Pattern stuff + 1) *The total number of patterns MUST NOT exceed 100. + 2) *The number of rows in each pattern MUST be 64 + 3) *Data is only translated within the first 16 channels. + 4) *All notes must lie within the range of C-1 to B-8 + 5) Several commands will not be interpreted by a standard + S3M player (viz. Mxx, Nxx, Pxx, S5x, S6x, S7x, S91, SAy, Wxx, + Yxx). + Also, you should have Old Effects (on the variable list) + put to *ON* if you want to write S3M files. + 6) *Panning controls in the volume column are NOT stored. + + Sample stuff + 1) *No sustain or ping pong loops can be used + 2) *No sample vibrato can be used + 3) *The sample global volume must be 64. + + 4) The Scream Tracker 3 module format supports 16 bit samples + and samples >64k although the actual program did NOT. + Note that *MOST* players probably ignore these fields + and it is likely that the module will NOT be played correctly + by a standard S3M player if it contains samples >64k and/or + 16 bit samples. + + All conditions with an asterix preceding them are checked at save + time. + + Note that both note off () and note cut (^^^) will get translated + to a note cut (^^^) in S3M format. + + 2.8 Gravis UltraSound / Interwave / AWE32 users. + + For hardware mixed devices (eg. Gravis UltraSound, Interwave and + AWE32), there are some limitations that are outlined here. + + I've already mentioned a few things throughout the DOC about hardware + mixing, but I'll reiterate them here with a few more points. + + 1) The maximum number of notes that you CAN play with a GUS and + Interwave is 32. The maximum number of the AWE32 is *30*. + + This was incorporated by effectively limiting the number of active + channels to 32/30. So if you play a 64 channel song which is using + control:Samples, then you will LOSE the last 32/34 channels. If you + are playing a 64 channel song with control:Instruments, you + shouldn't miss out on too much. This shouldn't really be a + problem in 99.9% of the cases. + + 2) The GUS playback quality is dependent on the maximum limit of active + channels. The GUS can be initialised to play anywhere between + 14 and 32 channels. Values above 32 are reduced to 32, and values + below 14 are increased to 14. The lower the number of channels, the + higher the playback quality. (14 channels will give 44100 Hz, with + 16-bit interpolation - very, very nice quality!). The default + GUS driver dynamically chooses a particular number of channels. + This doesn't ALWAYS work with all cards, so if you don't like the + transition of sample quality as the channels increase, or your + GUS seems to stop notes unexpectedly, use the other driver(s). + + 3) The GUS/Interwave/AWE32 routines occupy less memory than the mixing + routines. You will have about 30k-100k more of memory to play + around with. + + 4) The memory allocation routines are very simple and not very + versatile. When you are working through the sample library, samples + are NOT always deallocated when you move on to the next sample! If + you get the message "Out of soundcard RAM", then it may be necessary + to press Ctrl-G (or select Reload Samples from the samples menu) to + reorganise the samples in memory. Sorry about the inconvenience. + + 5) Changing the mixing volume does NOT affect these cards. + It may be necessary to reduce the global volume to remove crackle + if the output is overloading. + + 6) The surround sound option will cause the sample to be played with + a central panning. This is because I don't know how to get hardware + surround without wasting a lot of memory and channels. + + 7) The panning positions are reduced to a scale of 0->15 in the GUS, + so fine alterations in the panning may go unnoticed. The Interwave + and AWE32 permit 256 pan positions + + + 3. Before you write to me. (Important notes) + + I would very much like to get feedback on this program, but I am already + aware of several problems (?). + + 1) If you're going to write because the program looks 'too' much like + Scream Tracker 3, then don't :) I've used Scream Tracker. I loved + using it - it was the best, easiest, most convenient program ever, + so why not adopt it's design????? + + 2) The program could easily crash if you try to load a corrupted + module. If you've got some modules that you know are corrupted, try + to resist the temptation of testing the stability of the program.... + in many cases it'll die :) + + 3) A couple of people have asked about ASCII characters > 128. I'm + sorry - I can't let you have 'em on anywhere else except the message + editor. The reason is because I've used a lot of the characters for + 'graphics' - real time character generation. (the ASCII characters > + 128 don't really exist anymore) + + 4) If you 'overload' your CPU... the subsequent playback can also + become distorted! To fix this, reinitialise your sound driver with + Ctrl-I. + + 5) The help screens have only been defined for the following screens: + a) Pattern Editor + b) Sample List + c) Instrument List + d) Info Page + e) Order list and panning + f) Order list and channel volumes + g) Message editor + + I didn't think it necessary to include help screens for the other + screens, but if you feel strongly about including help on certain + points/screens, then I suppose I could make the effort... + + 6) If you have a bug to report, please check through BUGS.TXT first to + see if it's listed, and also check through this document - the problem + may be in the understanding of how the program works! Otherwise, + contact me, AND LET ME KNOW WHAT VERSION YOU ARE USING! + + 7) Any further GUS click removal is very difficult to achieve. ST3's + GUS click removal requires double the number of channels on the GUS + to be used and I can't allocate any more! Try out the alternative + GUS drivers first + + 8) Got suggestions for IT? At the moment, I'm really sorry - I barely + have enough spare time myself. I can't promise to add any suggestions + you make, but please send them along anyway. + +You can contact me by writing to: + Jeffrey Lim + 9 Wilgena Avenue + Myrtle Bank + South Australia 5064 + +EMail account: + pulse@cyburbia.net.au + WARNING!!! + If you ask me anything which is obviously contained within this document or + the FAQ, I will reply with RTFM (Read the #$%@#$% Manual). Sorry, but I hate + idiots who can't be bothered to take their time to have a quick look through + this document and write to me with stupid messages which have recently become + a chore to answer (You'd understand if you received 4000+ EMails...) + BUT! + If there *is* something that you HAVE made an effort to understand/look for, + then don't hesistate to write to me. The worst that can happen is that I + reply with RTFM :) +********ALSO******** + If you have an incorrect reply-address, don't expect to receive anything. + If you are reporting a bug, let me know what version you are using. + + If you find any major problem with the tracker, please try to find the + circumstances which cause it to trigger - if you can't, don't worry - write + to me anyway. It's just that it's much easier if I know a likely cause of + the error. (Don't worry if it seems that the cause is very, very remote - + I had a problem in my GUS playback routines which originally caused my + palette configuration screen to hang - now that's obscure!) + + Send money! I don't demand that you send me anything, (and I don't like + spoiling a program by shoving in reminder messages), but if you *DO* use + the program and think that it's worth contributing a small amount towards, + then please do so... it would be GREATLY appreciated. Remember.... even a + few dollars will be appreciated! It's very unlikely that I'll make a huge + profit (I doubt I could get close to sufficient money from this program to + make it even worth $1 for every hour I put in!). I won't be sending out any + nice thankyou notes, or bound manuals... but I will include your names in + the future versions of the tracker and I will EMail you each new version the + minute the are released if you wish. + + I believe that software *SHOULD* be cheap - you've spent perhaps a few + thousand getting your computer, so you wouldn't want to spend TOO much + more on programs! If you think this program is worth $5, then send $5. + If you think it's worth $10, then send $10. If you think it's worth + $1,000,000,000... don't let me stop you :) + + So... get together with a couple of friends and send me $10... If you send + me a significant amount, I'll put together a "special contributor's" list.. + (Oeeerrrrr :) ) + + Methods of payment: + International Money Orders - (NOT postal orders though!) + Cash (Make sure it's securely wrapped!) - it doesn't have to be Australian + currency, although it'd be nice if it could be! + Bank Transfer - EMail me for my details + + + 4. Closing Words + + I would like to thank the following people: + + Psi: For introducing me to tracking with the brilliant Scream Tracker 3 + Purple Motion: For being my music hero.... I still think + "When the Heaven's Fall" is *THE* best S3M ever written. + Red Haze: For constantly bugging me to get the tracker done, and for + his effort in testing out the program and making suggestions. + (He's directly responsible for the inclusion of Ping Pong + loops - I originally couldn't be bothered :) ) + Also extensive testing of later versions of IT... + The WALKER: For his flow of ideas & beta testing and getting the PoP + DiskMag finished.... tomorrow. Or is that next week? + OK... so he has done it. Finally.... 6 months late. :) + Perception: For his constant support over the many years he ran his BBS + Psibelius: For being the nice friendly Epinicion founder that he is. + Dominic: For his thoroughness in beta testing the program, and providing + suggestions. (He came up with more than double the number of + suggestions than almost anyone else... even though many of + them were not finally implemented :) ) + Chris Jarvis: For his effort in beta testing the tracker and producing + Firestorm (released with v1.00 of the tracker) + Pale Dreams! (released with v1.01 of the tracker) + Firepower (released with v1.03 of the tracker) + Sidewalk (released with v1.05 of the tracker) and + Fallen World (released with v2.01 of the tracker) + These are ALL amazing pieces of work! (Yes, I'm jealous!) + Zilym Limms: For his technical help with the tracker and his love of + Fast Tracker 2. Hahaha. :) + Also for his information and source code for the PAS 16. + Benjamin Bruheim: For his super list of contributions to v1.01 + ZaStaR: For his effort in putting together ITF - the font customiser! + and ITTXT - the text file importer for IT's messages! + Also for being the willing target of a barrage of beta + versions, a great contributor of ideas, a musician with whom + I could exchange work and for being a great dude all round! + Emmanuel Giasson: For creating the utilities MMCMP/MMUNCMP/MMTSR - + the music module compressor! + Diablo: For creating the Impulse Tracker directories on ftp.cdrom.com! + Siren: For providing me a contact to obtain an Interwave card! + AMD: For providing me with an Interwave card to program for! + + To the other beta testers: + Eric Bonython Phorte + Alistair Watts Julian Ellis + Alex Bates David Rohrsheim + Delta X GD (Grave Digger) + Andy Chen ShawnM + Clef Emmanuel Giasson + KXMode + + And anybody there who uses this program!!! + + Big thanks and thumbs up to Advanced Gravis for releasing their + Software Developer's Kit (SDK) free of charge! + + Congratulations to Creative Labs for finally releasing their SDKs + free of charge! + + Especially *BIG* thanks to AMD for providing me with an Interwave + card to use and the SDK! + + Finally... I have a request..... + If *YOU* write something with this program... share it with the + rest of the world!!! + + If you have an iNet account, you can upload your songs to: + ftp.cdrom.com/pub/demos/incoming/music/songs/it + - remember to ZIP up your song, to use a *lower* case filename + and to also upload a short description of your song in a .txt + file, otherwise your file will just be deleted. + + If you know of any other places where modules can be uploaded to, + let me know and I'll include them in the above list. + + 5. How to get the latest version of Impulse Tracker + + There are several places around the internet where you can find the + latest version of Impulse Tracker: + + 1) ftp.cdrom.com/pub/demos/incoming/music/programs } Check (1) first! + 2) ftp.cdrom.com/pub/demos/music/programs/trackers } + + 3) http://www.noisemusic.org/it + - American Site + 4) http://www.maz-sound.com + - Music and Tracking Site + 5) http://www.unidev.com/~logic/music/it + - IT Resource Central + 6) http://www.musica.org/impulse + - Spanish Site + 7) http://www.mixbbs.demon.co.uk + - UK Site + + If you want to have the latest version sent to you via EMail, or at least + be notified of new releases, then you'll have to send $omething to me :) + Check section 3 on how to contact me. + + + 6. Legal stuff + + No matter what happens, no matter how bad, I'm not going to be held + responsible. + + That's basically the same as any other license agreement, except you + should be able to understand this one without an interpreter :) + + YOU MAY NOT CHARGE ANYTHING FOR THIS PROGRAM - DISTRIBUTORS WHO + ARE INTERESTED IN THIS PROGRAM MUST WRITE TO ME FIRST AND HAVE MY + APPROVAL! (yeah, even by snail mail if you don't have EMail access). + + USE OF THIS PROGRAM COMMERCIALLY IS EXPRESSLY FORBIDDEN WITHOUT WRITTEN + AND SIGNED APPROVAL FROM ME. COMMERCIAL USE INVOLVES ANY USE OF IMPULSE + TRACKER IN WHICH MONEY IS INVOLVED (SPECIFICALLY THE CREATION OF ANY + MUSIC WHERE PAYMENT IS INVOLVED). THIS PROGRAM IS ONLY FREEWARE FOR + NON-COMMERCIAL USE. diff --git a/ReleaseDocumentation/IT256.ICO b/ReleaseDocumentation/IT256.ICO new file mode 100755 index 0000000000000000000000000000000000000000..45db9b02eca16efb0f01faa10865f06864a35cce GIT binary patch literal 2998 zcmcK6F=!%77{Ku_=M|5ql2*P5z?z#UTMG-^JIXR?1u_ew)G`FlC!D zKWpPT^>uxpv-v5lk1I3mthCwJ`n74F-%ai${PK?kp_0K=Njp$d_mz}JN^FOHu4{K9 z(!3R^U5S(%BKe90GyE9e$9M1zd=+~}J;fj6kMK5rA5YxD0N=*f@g=;Cm9JF1-~}&u zsmKgJ#`p0Zd;?#_pYa_$#UJC3@HT!QAL6I@0Po{Rcn9y`yZ9!)hA-puc!gJZg;#im zSNN|S6OLPsD~<+7#rP0E#RqsFKf>$i4!VnOqHE|fI#2u=evI$qJNO2^ia*1j;*ar1 zcpJZuC+=W?Z{zFu65dY84!=P&{21TIckm5-)fRO|Hc!dsG1)vKn>N|p$A|bSKEV6< z5#GV`12F00oA?^OjL+-eIK09uyuvHIVm&;r36JZR$92WyYVf!!6_F4>#RqsFKf*is zgzY0U{21TIckm5-6`!zuh#SZN-^SPRCA^JKN>HF?_%XhZ@8HR_s&ZqS6BMWrKg9=l zA3wsAoP-1g{0$gT+tfO>M760&33_>Xk>}@Ud3=17hldBbzrUB8n;UT)N3O50rQ7Yw z<>jR`n@zd6xR6?{Cgv+?{^CT@wCHnDa86GfiPXTJF6W%{3%{qd-`#_I_5GdR*#hJZgl zUQe&*WHbwi+D}`IH@6VY?^8^yZN{5LFUPY2U$14G@vHeWIoR_4%>#($k8(&`el-7y zJ1ENkd;2FF?H|k9)5Y4O!4T74?jL=389t?VsZ2`;Hv5a!OS}oqXRmLfe$m352(y

128) All volumes are adjusted by this + MV: Mix volume (0->128) During mixing, this value controls + the magnitude of the wave being mixed. + IS: Initial Speed of song. + IT: Initial Tempo of song + Sep: Panning separation between channels (0->128, 128 is max sep.) + PWD: Pitch wheel depth for MIDI controllers + Chnl Vol: Volume for each channel. Ranges from 0->64 + Chnl Pan: Each byte contains a panning value for a channel. Ranges from + 0 (absolute left) to 64 (absolute right). 32 = central pan, + 100 = Surround sound. + +128 = disabled channel (notes will not be played, but note + that effects in muted channels are + still processed) + Orders: This is the order in which the patterns are played. + Valid values are from 0->199. + 255 = "---", End of song marker + 254 = "+++", Skip to next order + + + Old Impulse Instrument Format (cmwt < 200h) + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0000: 'I''M''P''I' DOS FileName (12345678.123) + Ĵ +0010: 00hFlgVLSVLESLSSLE x x FadeOutNNADNCTrkVersNoS x + Ĵ +0020: Instrument Name, max 26 bytes, includes NUL................... + Ĵ +0030: ....................................... x x x x x x + Ĵ +0040: Note-Sample/Keyboard Table, Length = 240 bytes................ + Ĵ + + Ĵ +0130: Volume envelope (200 bytes)................................... + Ĵ + + Ĵ +01F8: Node points (25x2 bytes)...... + + + Total length of old instrument header is 554 bytes. + + Flg: Bit 0. On = Use volume envelope + Bit 1. On = Use volume loop + Bit 2. On = Use sustain volume loop + VLS: Volume loop start (node number) + VLE: Volume loop end (node number) + SLS: Sustain loop start (node number) + SLE: Sustain loop end (node number) + FadeOut: Ranges between 0 and 64, but the fadeout "Count" is 512. + Fade applied when: + 1) Note fade NNA is selected and triggered (by another note) + 2) Note off NNA is selected with no volume envelope + or volume envelope loop + 3) Volume envelope end is reached + + DNC: Duplicate note check (0 = Off, 1 = On) + NNA: New note action: + 0 = Note cut + 1 = Note continue + 2 = Note off + 3 = Note fade + + TrkVers: Tracker version used to save the instrument. This is only + used in the instrument files. + NoS: Number of samples associated with instrument. This is only + used in the instrument files. + + Note-Sample/Keyboard Table. + Each note of the instrument is first converted to a sample number + and a note (C-0 -> B-9). These are stored as note/sample pairs + (note first, range 0->119 for C-0 to B-9, sample ranges from + 1-99, 0=no sample) + + Volume envelope: Values from 0->64, 0FFh indicating end of envelope. + (after which note fade applies) + + Node data: Tick THEN magnitude + + + + Impulse Instrument Format + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0000: 'I''M''P''I' DOS FileName (12345678.123) + Ĵ +0010: 00hNNADCTDCAFadeOutPPSPPCGbVDfPRV RP TrkVersNoS x + Ĵ +0020: Instrument Name, max 26 bytes, includes NUL................... + Ĵ +0030: .......................................IFCIFRMChMPrMIDIBnk + Ĵ +0040: Note-Sample/Keyboard Table, Length = 240 bytes................ + Ĵ + + Ĵ +0130: Envelopes..................................................... + Ĵ + + NNA = New Note Action + 0 = Cut 1 = Continue + 2 = Note off 3 = Note fade + + DCT = Duplicate Check Type + 0 = Off 1 = Note + 2 = Sample 3 = Instrument + + DCA: Duplicate Check Action + 0 = Cut + 1 = Note Off + 2 = Note fade + + FadeOut: Ranges between 0 and 128, but the fadeout "Count" is 1024 + See the Last section on how this works. + Fade applied when: + 1) Note fade NNA is selected and triggered (by another note) + 2) Note off NNA is selected with no volume envelope + or volume envelope loop + 3) Volume envelope end is reached + + PPS: Pitch-Pan separation, range -32 -> +32 + PPC: Pitch-Pan center: C-0 to B-9 represented as 0->119 inclusive + + GbV: Global Volume, 0->128 + DfP: Default Pan, 0->64, &128 => Don't use + RV: Random volume variation (percentage) + RP: Random panning variation (panning change - not implemented yet) + + MCh = MIDI Channel + MPr = MIDI Program (Instrument) + + TrkVers: Tracker version used to save the instrument. This is only + used in the instrument files. + NoS: Number of samples associated with instrument. This is only + used in the instrument files. + + Note-Sample/Keyboard Table. + Each note of the instrument is first converted to a sample number + and a note (C-0 -> B-9). These are stored as note/sample byte pairs + (note first, range 0->119 for C-0 to B-9, sample ranges from + 1-99, 0=no sample) + + Envelope layout + + Envelopes: 3 structures, first for volume (130h), second for + panning (182h), third for pitch (1D4h). + + Each is structured as such: + + 0 1 2 3 4 5 6....... + Ŀ +xxxx: FlgNumLpBLpESLBSLE Node points, 25 sets, 75 bytes.... x + Ĵ + + Flg: Bit 0: Envelope on/off, 1 = on, 0 = off + Bit 1: Loop on/off, 1 = on, 0 = off + Bit 2: SusLoop on/off, 1 = on, 0 = off + + Num = Number of node points + + LpB = Loop beginning SLB = Sustain loop beginning + LpE = Loop end SLE = Sustain loop end + + Node point = 1 byte for y-value + (0->64 for vol, -32->+32 for panning or pitch) + 1 word (2 bytes) for tick number (0->9999) + + Total length of an instrument is 547 bytes, but 554 bytes are + written, just to simplify the loading of the old format. (Hence + there are 7 'wasted' bytes per instrument) + + + + Impulse Sample Format + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0000: 'I''M''P''S' DOS Filename (12345678.123) + Ĵ +0010: 00hGvLFlgVol Sample Name, max 26 bytes, includes NUL....... + Ĵ +0020: .......................................................CvtDfP + Ĵ +0030: Length Loop Begin Loop End C5Speed + Ĵ +0040: SusLoop Begin SusLoop End SamplePointer ViSViDViRViT + + +The cache file has the following pieces of information added on: + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0050: File Size Date Time Fmt........................... + + + Fmt. 0 = unchecked. 1 = directory, 2 = it sample, 3 = st sample + + + GvL: Global volume for instrument, ranges from 0->64 + Flg: Bit 0. On = sample associated with header. + Bit 1. On = 16 bit, Off = 8 bit. + Bit 2. On = stereo, Off = mono. Stereo samples not supported yet + Bit 3. On = compressed samples. + Bit 4. On = Use loop + Bit 5. On = Use sustain loop + Bit 6. On = Ping Pong loop, Off = Forwards loop + Bit 7. On = Ping Pong Sustain loop, Off = Forwards Sustain loop + Vol: Default volume for instrument + + Length: Length of sample in no. of samples NOT no. of bytes + LoopBeg: Start of loop (no of samples in, not bytes) + Loop End: Sample no. AFTER end of loop + C5Speed: Number of bytes a second for C-5 (ranges from 0->9999999) + SusLBeg: Start of sustain loop + SusLEnd: Sample no. AFTER end of sustain loop + + SmpPoint: 'Long' Offset of sample in file. + + ViS: Vibrato Speed, ranges from 0->64 + ViD: Vibrato Depth, ranges from 0->64 + ViT: Vibrato waveform type. + 0=Sine wave + 1=Ramp down + 2=Square wave + 3=Random (speed is irrelevant) + ViR: Vibrato Rate, rate at which vibrato is applied (0->64) + + The depth of the vibrato at any point is worked out in the following + way: + Every processing cycle, the following occurs: + 1) Mov AX, [SomeVariableNameRelatingToVibrato] + 2) Add AL, Rate + 3) AdC AH, 0 + 4) AH contains the depth of the vibrato as a fine-linear slide. + 5) Mov [SomeVariableNameRelatingToVibrato], AX ; For the next + ; cycle. + + For those that don't understand assembly, then the depth is + basically the running-sum of the rate divided by 256. + + Sample vibrato uses a table 256-bytes long + + Convert - bits other than bit 0 are used internally for the loading + of alternative formats. + Bit 0: + Off: Samples are unsigned } IT 2.01 and below use unsigned samples + On: Samples are signed } IT 2.02 and above use signed samples + Bit 1: + Off: Intel lo-hi byte order for 16-bit samples } Safe to ignore + On: Motorola hi-lo byte order for 16-bit samples } these values... + Bit 2: } + Off: Samples are stored as PCM values } + On: Samples are stored as Delta values } + Bit 3: } + On: Samples are stored as byte delta values } + (for PTM loader) } + Bit 4: } + On: Samples are stored as TX-Wave 12-bit values } + Bit 5: } + On: Left/Right/All Stereo prompt } + Bit 6: Reserved + Bit 7: Reserved + + DfP - Default Pan. Bits 0->6 = Pan value, Bit 7 ON to USE (opposite of inst) + + + + Impulse Pattern Format + + 0 1 2 3 4 5 6 7 8 9 A B C D E F + Ŀ +0000: Length Rows x x x x Packed data................ + Ĵ + + Length: Length of packed pattern, not including the 8 byte header + Note that the pattern + the 8 byte header will ALWAYS + be less than 64k + Rows: Number of rows in this pattern (Ranges from 32->200) + + Patterns are unpacked by the following pseudocode... (this may look + horrible, but in practise, it's just as convenient as the S3M + pattern format for playback (but not for display)) + + GetNextChannelMarker: + Read byte into channelvariable. + if(channelvariable = 0) then end of row + Channel = (channelvariable-1) & 63 ; Channel is 0 based. + if(channelvariable & 128) then read byte into maskvariable + else maskvariable = previousmaskvariable for current channel + + if(maskvariable & 1), then read note. (byte value) + // Note ranges from 0->119 (C-0 -> B-9) + // 255 = note off, 254 = notecut + // Others = note fade (already programmed into IT's player + // but not available in the editor) + + if(maskvariable & 2), then read instrument (byte value) + // Instrument ranges from 1->99 + + if(maskvariable & 4), then read volume/panning (byte value) + // Volume ranges from 0->64 + // Panning ranges from 0->64, mapped onto 128->192 + // Prepare for the following also: + // 65->74 = Fine volume up + // 75->84 = Fine volume down + // 85->94 = Volume slide up + // 95->104 = Volume slide down + // 105->114 = Pitch Slide down + // 115->124 = Pitch Slide up + // 193->202 = Portamento to + // 203->212 = Vibrato + + Effects 65 is equivalent to D0F, 66 is equivalent to D1F -> 74 = D9F + Similarly for 75-84 (DFx), 85-94 (Dx0), 95->104 (D0x). + + (Fine) Volume up/down all share the same memory (NOT shared with Dxx + in the effect column tho). + + Pitch slide up/down affect E/F/(G)'s memory - a Pitch slide + up/down of x is equivalent to a normal slide by x*4 + + Portamento to (Gx) affects the memory for Gxx and has the equivalent + slide given by this table: + + SlideTable DB 1, 4, 8, 16, 32, 64, 96, 128, 255 + + Vibrato uses the same 'memory' as Hxx/Uxx. + + if(maskvariable & 8), then read command (byte value) and commandvalue + // Valid ranges from 0->31 (0=no effect, 1=A, 2=B, 3=C, etc.) + + if(maskvariable & 16), then note = lastnote for channel + if(maskvariable & 32), then instrument = lastinstrument for channel + if(maskvariable & 64), then volume/pan = lastvolume/pan for channel + if(maskvariable & 128), then { + command = lastcommand for channel and + commandvalue = lastcommandvalue for channel + } + Goto GetNextChannelMarker + + + + Mathematics + +Abbreviations: + FV = Final Volume (Ranges from 0 to 128). In versions 1.04+, mixed output + devices are reduced further to a range from 0 to 64 due to lack of + memory. + Vol = Volume at which note is to be played. (Ranges from 0 to 64) + SV = Sample Volume (Ranges from 0 to 64) + IV = Instrument Volume (Ranges from 0 to 128) + CV = Channel Volume (Ranges from 0 to 64) + GV = Global Volume (Ranges from 0 to 128) + VEV = Volume Envelope Value (Ranges from 0 to 64) + +In Sample mode, the following calculation is done: + FV = Vol * SV * CV * GV / 262144 ; Note that 262144 = 2^18 + ; So bit shifting can be done. + +In Instrument mode the following procedure is used: + + 1) Update volume envelope value. Check for loops / end of envelope. + 2) If end of volume envelope (ie. position >= 200 or VEV = 0FFh), then turn + on note fade. + 3) If notefade is on, then NoteFadeComponent (NFC) = NFC - FadeOut + ; NFC should be initialised to 1024 when a note is played. + 4) FV = Vol * SV * IV * CV * GV * VEV * NFC / 2^41 + +Linear slides work like this: + Final frequency = Original frequency * 2^(SlideValue/768) + +(I used a lookup table for the multipliers here) + +For command Exx, SlideValue = -4*EffectValue +For command EEx, SlideValue = -EffectValue +For command Fxx, SlideValue = 4*EffectValue +For command FEx, SlideValue = EffectValue + +Note that sample vibrato always uses Linear slides. + +Notes about effects (as compared to other module formats) + +C This is now in *HEX*. (Used to be in decimal in ST3) +E/F/G/H/U You need to check whether the song uses Amiga/Linear slides. +H/U Vibrato in Impulse Tracker is two times finer than in + any other tracker and is updated EVERY tick. + If "Old Effects" is *ON*, then the vibrato is played in the + normal manner (every non-row tick and normal depth) +E/F/G These commands ALL share the same memory. +Oxx Offsets to samples are to the 'xx00th' SAMPLE. (ie. for + 16 bit samples, the offset is xx00h*2) + Oxx past the sample end will be ignored, unless "Old Effects" + is ON, in which case the Oxx will play from the end of the + sample. +Yxy This uses a table 4 times larger (hence 4 times slower) than + vibrato or tremelo. If the waveform is set to random, then + the 'speed' part of the command is interpreted as a delay. + +If you read through this document and there are ANY points which you have +troubles with (and have to try out), then let me know - because someone +else will have the same questions - and I'd like to make this DOC as easy +to understand as possible. + +For Panning.... + Here's the rough procedure used: + + NotePan = ChannelPan + if InstrumentPan=On then NotePan = InstrumentPan + NotePan = NotePan+(InstrumentNote-PPCenter)*PPSeparation/8 + +Pitch Envelopes + Each value on the envelope equates to half a semitone. This is interpolated + 64 times for smooth pitch sliding. Positive values indicate a pitch variation + UP of x semitones, negative values indicate a pitch variation down. + + General Info + +The player in Impulse Tracker 'allocates' channels to notes whenever they +are *PLAYED*. In sample mode, the allocation is simple: + Virtual Channel (number) = 'Host' channel (number) + +In instrument mode, the following procedure is used: + + Check if channel is already playing ---Yes--> set 'background' flag on. + | 'Trigger' NNA. If NNA=cut, + No then use this virtual + | channel. + | | + |<------------------ else -----------------/ + | + v + Search and find the first non-active virtual channel. + | + Non-active channel found? ----Yes----> Use this for playback. + | + No + | + v + Search through and find the channel of lowest volume that is in the # + 'background' (ie. no longer controlled directly) # + | # + Background channel found? ----Yes----> Use this for playback. # + | # + No # + | # + v # + Return error - the note is *NOT* allocated a channel, and hence is not # + played. # + + This is actually quite a simple process... just that it's another of + those 'hassles' to have to write... + + ### Note: This is by far the simplest implementation of congestion + resolution. IT 2.03 and above have a greatly enhanced + method which more selectively removes the most insignificant + channel. Obviously, there is no best way to do this - I + encourage you to experiment and find new algorithms for + yourself. + + + + Internal Tables + +FineSineData Label Byte + DB 0, 2, 3, 5, 6, 8, 9, 11, 12, 14, 16, 17, 19, 20, 22, 23 + DB 24, 26, 27, 29, 30, 32, 33, 34, 36, 37, 38, 39, 41, 42, 43, 44 + DB 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 56, 57, 58, 59 + DB 59, 60, 60, 61, 61, 62, 62, 62, 63, 63, 63, 64, 64, 64, 64, 64 + DB 64, 64, 64, 64, 64, 64, 63, 63, 63, 62, 62, 62, 61, 61, 60, 60 + DB 59, 59, 58, 57, 56, 56, 55, 54, 53, 52, 51, 50, 49, 48, 47, 46 + DB 45, 44, 43, 42, 41, 39, 38, 37, 36, 34, 33, 32, 30, 29, 27, 26 + DB 24, 23, 22, 20, 19, 17, 16, 14, 12, 11, 9, 8, 6, 5, 3, 2 + DB 0, -2, -3, -5, -6, -8, -9,-11,-12,-14,-16,-17,-19,-20,-22,-23 + DB -24,-26,-27,-29,-30,-32,-33,-34,-36,-37,-38,-39,-41,-42,-43,-44 + DB -45,-46,-47,-48,-49,-50,-51,-52,-53,-54,-55,-56,-56,-57,-58,-59 + DB -59,-60,-60,-61,-61,-62,-62,-62,-63,-63,-63,-64,-64,-64,-64,-64 + DB -64,-64,-64,-64,-64,-64,-63,-63,-63,-62,-62,-62,-61,-61,-60,-60 + DB -59,-59,-58,-57,-56,-56,-55,-54,-53,-52,-51,-50,-49,-48,-47,-46 + DB -45,-44,-43,-42,-41,-39,-38,-37,-36,-34,-33,-32,-30,-29,-27,-26 + DB -24,-23,-22,-20,-19,-17,-16,-14,-12,-11, -9, -8, -6, -5, -3, -2 + +FineRampDownData Label Byte + DB 64, 63, 63, 62, 62, 61, 61, 60, 60, 59, 59, 58, 58, 57, 57, 56 + DB 56, 55, 55, 54, 54, 53, 53, 52, 52, 51, 51, 50, 50, 49, 49, 48 + DB 48, 47, 47, 46, 46, 45, 45, 44, 44, 43, 43, 42, 42, 41, 41, 40 + DB 40, 39, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 33, 33, 32 + DB 32, 31, 31, 30, 30, 29, 29, 28, 28, 27, 27, 26, 26, 25, 25, 24 + DB 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 19, 18, 18, 17, 17, 16 + DB 16, 15, 15, 14, 14, 13, 13, 12, 12, 11, 11, 10, 10, 9, 9, 8 + DB 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 2, 2, 1, 1, 0 + DB 0, -1, -1, -2, -2, -3, -3, -4, -4, -5, -5, -6, -6, -7, -7, -8 + DB -8, -9, -9,-10,-10,-11,-11,-12,-12,-13,-13,-14,-14,-15,-15,-16 + DB -16,-17,-17,-18,-18,-19,-19,-20,-20,-21,-21,-22,-22,-23,-23,-24 + DB -24,-25,-25,-26,-26,-27,-27,-28,-28,-29,-29,-30,-30,-31,-31,-32 + DB -32,-33,-33,-34,-34,-35,-35,-36,-36,-37,-37,-38,-38,-39,-39,-40 + DB -40,-41,-41,-42,-42,-43,-43,-44,-44,-45,-45,-46,-46,-47,-47,-48 + DB -48,-49,-49,-50,-50,-51,-51,-52,-52,-53,-53,-54,-54,-55,-55,-56 + DB -56,-57,-57,-58,-58,-59,-59,-60,-60,-61,-61,-62,-62,-63,-63,-64 + +FineSquareWave Label Byte + DB 128 Dup (64), 128 Dup (0) + +EmptyPattern Label + DW 64, 64, 0, 0 + DB 64 Dup (0) + +; + +PitchTable Label DWord ; Values are 16.16 bit + DW 2048, 0, 2170, 0, 2299, 0, 2435, 0, 2580, 0, 2734, 0 ; C-0 + DW 2896, 0, 3069, 0, 3251, 0, 3444, 0, 3649, 0, 3866, 0 ;>B-0 + + DW 4096, 0, 4340, 0, 4598, 0, 4871, 0, 5161, 0, 5468, 0 ; C-1 + DW 5793, 0, 6137, 0, 6502, 0, 6889, 0, 7298, 0, 7732, 0 ;>B-1 + + DW 8192, 0, 8679, 0, 9195, 0, 9742, 0, 10321, 0, 10935, 0 + DW 11585, 0, 12274, 0, 13004, 0, 13777, 0, 14596, 0, 15464, 0 + + DW 16384, 0, 17358, 0, 18390, 0, 19484, 0, 20643, 0, 21870, 0 + DW 23170, 0, 24548, 0, 26008, 0, 27554, 0, 29193, 0, 30929, 0 + + DW 32768, 0, 34716, 0, 36781, 0, 38968, 0, 41285, 0, 43740, 0 + DW 46341, 0, 49097, 0, 52016, 0, 55109, 0, 58386, 0, 61858, 0 + + DW 0, 1, 3897, 1, 8026, 1, 12400, 1, 17034, 1, 21944, 1 + DW 27146, 1, 32657, 1, 38496, 1, 44682, 1, 51236, 1, 58179, 1 + + DW 0, 2, 7794, 2, 16051, 2, 24800, 2, 34068, 2, 43888, 2 + DW 54292, 2, 65314, 2, 11456, 3, 23828, 3, 36936, 3, 50823, 3 + + DW 0, 4, 15588, 4, 32103, 4, 49600, 4, 2601, 5, 22240, 5 + DW 43048, 5, 65092, 5, 22912, 6, 47656, 6, 8336, 7, 36110, 7 + + DW 0, 8, 31176, 8, 64205, 8, 33663, 9, 5201, 10, 44481, 10 + DW 20559, 11, 64648, 11, 45823, 12, 29776, 13, 16671, 14, 6684, 15 + + DW 0, 16, 62352, 16, 62875, 17, 1790, 19, 10403, 20, 23425, 21 + DW 41118, 22, 63761, 23, 26111, 25, 59552, 26, 33342, 28, 13368, 30 + +FineLinearSlideUpTable Label ; Values are 16.16 bit + DW 0, 1, 59, 1, 118, 1, 178, 1, 237, 1 ; 0->4 + DW 296, 1, 356, 1, 415, 1, 475, 1, 535, 1 ; 5->9 + DW 594, 1, 654, 1, 714, 1, 773, 1, 833, 1 ; 10->14 + DW 893, 1 ; 15 + +LinearSlideUpTable Label ; Value = 2^(Val/192), Values are 16.16 bit + DW 0, 1, 237, 1, 475, 1, 714, 1, 953, 1 ; 0->4 + DW 1194, 1, 1435, 1, 1677, 1, 1920, 1, 2164, 1 ; 5->9 + DW 2409, 1, 2655, 1, 2902, 1, 3149, 1, 3397, 1 ; 10->14 + DW 3647, 1, 3897, 1, 4148, 1, 4400, 1, 4653, 1 ; 15->19 + DW 4907, 1, 5157, 1, 5417, 1, 5674, 1, 5932, 1 ; 20->24 + DW 6190, 1, 6449, 1, 6710, 1, 6971, 1, 7233, 1 ; 25->29 + DW 7496, 1, 7761, 1, 8026, 1, 8292, 1, 8559, 1 ; 30->34 + DW 8027, 1, 9096, 1, 9366, 1, 9636, 1, 9908, 1 ; 35->39 + DW 10181, 1, 10455, 1, 10730, 1, 11006, 1, 11283,1 ; 40->44 + DW 11560, 1, 11839, 1, 12119, 1, 12400, 1, 12682,1 ; 45->49 + DW 12965, 1, 13249, 1, 13533, 1, 13819, 1, 14106,1 ; 50->54 + DW 14394, 1, 14684, 1, 14974, 1, 15265, 1, 15557,1 ; 55->59 + DW 15850, 1, 16145, 1, 16440, 1, 16737, 1, 17034,1 ; 60->64 + DW 17333, 1, 17633, 1, 17933, 1, 18235, 1, 18538,1 ; 65->69 + DW 18842, 1, 19147, 1, 19454, 1, 19761, 1, 20070,1 ; 70->74 + DW 20379, 1, 20690, 1, 21002, 1, 21315, 1, 21629,1 ; 75->79 + DW 21944, 1, 22260, 1, 22578, 1, 22897, 1, 23216,1 ; 80->84 + DW 23537, 1, 23860, 1, 24183, 1, 24507, 1, 24833,1 ; 85->89 + DW 25160, 1, 25488, 1, 25817, 1, 26148, 1, 26479,1 ; 90->94 + DW 26812, 1, 27146, 1, 27481, 1, 27818, 1, 28155,1 ; 95->99 + DW 28494, 1, 28834, 1, 29175, 1, 29518, 1, 29862,1 ; 100->104 + DW 30207, 1, 30553, 1, 30900, 1, 31248, 1, 31599,1 ; 105->109 + DW 31951, 1, 32303, 1, 32657, 1, 33012, 1, 33369,1 ; 110->114 + DW 33726, 1, 34085, 1, 34446, 1, 34807, 1, 35170,1 ; 115->119 + DW 35534, 1, 35900, 1, 36267, 1, 36635, 1, 37004,1 ; 120->124 + DW 37375, 1, 37747, 1, 38121, 1, 38496, 1, 38872,1 ; 125->129 + DW 39250, 1, 39629, 1, 40009, 1, 40391, 1, 40774,1 ; 130->134 + DW 41158, 1, 41544, 1, 41932, 1, 42320, 1, 42710,1 ; 135->139 + DW 43102, 1, 43495, 1, 43889, 1, 44285, 1, 44682,1 ; 140->144 + DW 45081, 1, 45481, 1, 45882, 1, 46285, 1, 46690,1 ; 145->149 + DW 47095, 1, 47503, 1, 47917, 1, 48322, 1, 48734,1 ; 150->154 + DW 49147, 1, 49562, 1, 49978, 1, 50396, 1, 50815,1 ; 155->159 + DW 51236, 1, 51658, 1, 52082, 1, 52507, 1, 52934,1 ; 160->164 + DW 53363, 1, 53793, 1, 54224, 1, 54658, 1, 55092,1 ; 165->169 + DW 55529, 1, 55966, 1, 56406, 1, 56847, 1, 57289,1 ; 170->174 + DW 57734, 1, 58179, 1, 58627, 1, 59076, 1, 59527,1 ; 175->179 + DW 59979, 1, 60433, 1, 60889, 1, 61346, 1, 61805,1 ; 180->184 + DW 62265, 1, 62727, 1, 63191, 1, 63657, 1, 64124,1 ; 185->189 + DW 64593, 1, 65064, 1, 0, 2, 474, 2, 950, 2 ; 190->194 + DW 1427, 2, 1906, 2, 2387, 2, 2870, 2, 3355, 2 ; 195->199 + DW 3841, 2, 4327, 2, 4818, 2, 5310, 2, 5803, 2 ; 200->204 + DW 6298, 2, 6795, 2, 7294, 2, 7794, 2, 8296, 2 ; 205->209 + DW 8800, 2, 9306, 2, 9814, 2, 10323, 2, 10835,2 ; 210->214 + DW 11348, 2, 11863, 2, 12380, 2, 12899, 2, 13419,2 ; 215->219 + DW 13942, 2, 14467, 2, 14993, 2, 15521, 2, 16051,2 ; 220->224 + DW 16583, 2, 17117, 2, 17653, 2, 18191, 2, 18731,2 ; 225->229 + DW 19273, 2, 19817, 2, 20362, 2, 20910, 2, 21460,2 ; 230->234 + DW 22011, 2, 22565, 2, 23121, 2, 23678, 2, 24238,2 ; 235->239 + DW 24800, 2, 25363, 2, 25929, 2, 25497, 2, 27067,2 ; 240->244 + DW 27639, 2, 28213, 2, 28789, 2, 29367, 2, 29947,2 ; 245->249 + DW 30530, 2, 31114, 2, 31701, 2, 32289, 2, 32880, 2 ; 250->254 + DW 33473, 2, 34068, 2 ; 255->256 + +FineLinearSlideDownTable Label ; Values are 0.16 bit + DW 65535, 65477, 65418, 65359, 65300, 65241, 65182, 65359 ; 0->7 + DW 65065, 65006, 64947, 64888, 64830, 64772, 64713, 64645 ; 8->15 + +LinearSlideDownTable Label ; Values are 0.16 bit + DW 65535, 65300, 65065, 64830, 64596, 64364, 64132, 63901 ; 0->7 + DW 63670, 63441, 63212, 62984, 62757, 62531, 62306, 62081 ; 8->15 + DW 61858, 61635, 61413, 61191, 60971, 60751, 60532, 60314 ; 16->23 + DW 60097, 59880, 59664, 59449, 59235, 59022, 58809, 58597 ; 24->31 + DW 58386, 58176, 57966, 57757, 57549, 57341, 57135, 56929 ; 32->39 + DW 56724, 56519, 56316, 56113, 55911, 55709, 55508, 55308 ; 40->47 + DW 55109, 54910, 54713, 54515, 54319, 54123, 53928, 53734 ; 48->55 + DW 53540, 53347, 53155, 52963, 52773, 52582, 52393, 52204 ; 56->63 + DW 52016, 51829, 51642, 51456, 51270, 51085, 50901, 50718 ; 64->71 + DW 50535, 50353, 50172, 49991, 49811, 49631, 49452, 49274 ; 72->79 + DW 49097, 48920, 48743, 48568, 48393, 48128, 48044, 47871 ; 80->87 + DW 47699, 47527, 47356, 47185, 47015, 46846, 46677, 46509 ; 88->95 + DW 46341, 46174, 46008, 45842, 45677, 45512, 45348, 45185 ; 96->103 + DW 45022, 44859, 44698, 44537, 44376, 44216, 44057, 43898 ;104->111 + DW 43740, 43582, 43425, 43269, 43113, 42958, 42803, 42649 ;112->119 + DW 42495, 42342, 42189, 42037, 41886, 41735, 41584, 41434 ;120->127 + DW 41285, 41136, 40988, 40840, 40639, 40566, 40400, 40253 ;128->135 + DW 40110, 39965, 39821, 39678, 39535, 39392, 39250, 39109 ;136->143 + DW 38968, 38828, 38688, 38548, 38409, 38271, 38133, 37996 ;144->151 + DW 37859, 37722, 37586, 37451, 37316, 37181, 37047, 36914 ;152->159 + DW 36781, 36648, 36516, 36385, 36254, 36123, 35993, 35863 ;160->167 + DW 35734, 35605, 35477, 35349, 35221, 35095, 34968, 34842 ;168->175 + DW 34716, 34591, 34467, 34343, 34219, 34095, 33973, 33850 ;176->183 + DW 33728, 33607, 33486, 33365, 33245, 33125, 33005, 32887 ;184->191 + DW 32768, 32650, 32532, 32415, 32298, 32182, 32066, 31950 ;192->199 + DW 31835, 31720, 31606, 31492, 31379, 31266, 31153, 31041 ;200->207 + DW 30929, 30817, 30706, 30596, 30485, 30376, 30226, 30157 ;208->215 + DW 30048, 29940, 29832, 29725, 29618, 29511, 29405, 29299 ;216->223 + DW 29193, 29088, 28983, 28879, 28774, 28671, 28567, 28464 ;224->231 + DW 28362, 28260, 28158, 28056, 27955, 27855, 27754, 27654 ;232->239 + DW 27554, 27455, 27356, 27258, 27159, 27062, 26964, 26867 ;240->247 + DW 26770, 26674, 26577, 26482, 26386, 26291, 26196, 26102 ;248->255 + DW 26008 ; 256 + +; + + Effect Info + +Here's about all the info I can think of for effects. "Process" variables are +variables used internally by effects to control the direction of playback.. +This section has not been completed yet. + +First, here is the rough flow chart for processing information, it's not fully +detailed, but all of the important steps are outlined. + + Ŀ + Set note volume to volume set for each channel + Set note frequency to frequency set for each channel + + + Ŀ + Decrease tick counter Yes + Is tick counter 0 ? Ŀ + + + No Ŀ + Ŀ Tick counter = Tick counter set + Update effects for each (the current 'speed') + channel as required. Decrease Row counter. + Is row counter 0? + + No + Yes + + Ŀ Ŀ + Call update-effects for Row counter = 1 + each channel. + Increase ProcessRow + Is ProcessRow > NumberOfRows? + + Yes No + Ŀ + ProcessRow = BreakRow + BreakRow = 0 + Increase ProcessOrder + while Order[ProcessOrder] = 0xFEh, + increase ProcessOrder + if Order[ProcessOrder] = 0xFFh, + ProcessOrder = 0 + CurrentPattern = Order[ProcessOrder] + + + + + Ŀ + CurrentRow = ProcessRow + Update Pattern Variables (includes jumping to + the appropriate row if requried and getting + the NumberOfRows for the pattern) + + + + + Ŀ Yes Ŀ + Instrument mode? Ĵ Update Envelopes as required + Update fadeout as required + Calculate final volume if req + No (Sample mode) Calculate final pan if req + Process sample vibrato if req + Ŀ + Calculate final volume if required + Calculate final pan if requried + Process sample vibrato if required + + + + + + Ŀ + Output sound!!! + + +Axx Set Tempo + + if (xx != 0) { + Maxtick = xx; + Currenttick = xx; + } + +Bxx Jump to Order + + ProcessOrder = xx - 1; + ProcessRow = 0xFFFE; // indicates new pattern internally for IT... + +Cxx Break to Row + + BreakRow = xx; + ProcessRow = 0xFFFE; + +Dxx Volume slide down + + if (xx == 0) then xx = last xx for (Dxx/Kxx/Lxx) for this channel. + + Order of testing: Dx0, D0x, DxF, DFx + +Dx0 Set effect update for channel enabled if channel is ON. + If x = F, then slide up volume by 15 straight away also (for S3M compat) + Every update, add x to the volume, check and clip values > 64 to 64 +D0x Set effect update for channel enabled if channel is ON. + If x = F, then slide down volume by 15 straight away also (for S3M) + Every update, subtract x from the volume, check and clip values < 0 to 0 +DxF Add x to volume straight away. Check and clip values > 64 to 64 +DFx Subtract x from volume straight away. Check and clip values < 0 to 0 + +Hxy Vibrato + + if (x != 0) { + speed = 4*x; + } + if (y != 0) { + depth = y * 4; + if(OldEffects) depth <<= 1; + } + Set effect update for channel enabled if channel is ON. + Goto InitVibrato (explained later) + +Ixy Tremor, ontime x, offtime y + + if (x != 0) { + ontime = x; + if (oldeffects) ontime++; + } + if (y != 0) { + offtime = y; + if (oldeffects) offtime++; + } + +Nxx Channel volume slide down + + if (xx == 0) then xx = last Nxx for this channel. + + Order of testing: Nx0, N0x, NxF, NFx + +Nx0 Set effect update for channel enabled. + Every update, add x to the volume, check and clip values > 64 to 64 +N0x Set effect update for channel enabled. + Every update, subtract x from the volume, check and clip values < 0 to 0 +NxF Add x to volume straight away. Check and clip values > 64 to 64 +NFx Subtract x from volume straight away. Check and clip values < 0 to 0 + +Uxy Fine Vibrato + + if (x != 0) { + speed = 4*x; + } + if (y != 0) { + depth = y; + if(OldEffects) depth <<= 1; + } + Set effect update for channel enabled if channel is ON. + Goto InitVibrato (explained later) + +Wxx Global volume slide down + + if (xx == 0) then xx = last Wxx for this channel. + + Order of testing: Wx0, W0x, WxF, WFx + +Wx0 Set effect update for channel enabled. + Every update, add x to the volume, check and clip values > 128 to 128 +W0x Set effect update for channel enabled. + Every update, subtract x from the volume, check and clip values < 0 to 0 +WxF Add x to volume straight away. Check and clip values > 128 to 128 +WFx Subtract x from volume straight away. Check and clip values < 0 to 0 + +.. sorry this is incomplete.. diff --git a/ReleaseDocumentation/ITVSOUND.TXT b/ReleaseDocumentation/ITVSOUND.TXT new file mode 100755 index 0000000..ac4ae57 --- /dev/null +++ b/ReleaseDocumentation/ITVSOUND.TXT @@ -0,0 +1,70 @@ + +What is VSound? +--------------- +VSound is a virtual sound driver for Impulse Tracker. It actually uses +Microsoft's DirectSound to provide output on ANY soundcard supported by +Windows '95 or Windows '98. It does NOT support Windows NT. + +It does take a little effort to setup and doesn't perform quite as well +as the native drivers, so if you have a SB16, ESS or some other card +directly supported by IT, don't bother messing around VSound. If you have +a SBPro compatible card, some PCI card or anything else that isn't being +used to its maximum capabilities, then give these files a try. + +How to use these files +---------------------- +You MUST have DirectX installed. It was written with the DirectX6 SDK, +although I'm pretty sure DirectSound 5 is sufficient. + +1. Copy ITVSOUND.VXD into your Windows\System directory + (normally C:\WINDOWS\SYSTEM) + + Note that the file may NOT show up in Window's Explorer since they have + a system extension (.VXD). Use DOS, or enable (unhide) system files in + your Explorer configuration. + +2. In your Windows directory (normally C:\WINDOWS), edit your SYSTEM.INI file + and include the line: + device=itvsound.vxd + anywhere in the [386Enh] section + +3. Reboot your computer + +4. Run Server.EXE + +5. Run "IT" + +Configuring the driver +---------------------- +The driver can be configured by modifying Window's Registry by running +"regedit" (which comes with Windows). The variables can be found at: + "KHEY_LOCAL_MACHINE\Software\Jeffrey Lim\Impulse Tracker VSound Server" + +The 4 variables are: + BufferSize - The size of the DirectSound buffer in kb. + Permitted ranges from 4 to 64, default 24 + BufferThreshold - The size of the buffer that IT tries to maintain in kb. + Permitted ranges from 2 to 32, default 21 + BufferType - 0 = DualBuffer (BufferSize is logically split into 2 sections) + 1 = QuadBuffer (BufferSize is logically split into 4 sections) + 2 = OctBuffer (BufferSize is logically split into 8 sections) + (recommended, default) + MixSpeed - Mixing rate to be used in Hz. + Permitted ranges from 11025 to 64000, default 44100 + +You will need to restart the server before these changes take effect. + +Known Problems +-------------- +1. This driver only works with Win95 and Win98, NOT WinNT (I'll try a WinNT + driver sometime). + +2. There is an obvious latency due to the size of the buffers and the delay + that is inherent to DirectSound. Reducing the BufferSize and BufferThreshold + values can reduce this latency, however, smaller values can also cause the + sound to break up. + + Try using the values: + 1. BufferSize=16, BufferThreshold=14, BufferType=2, MixSpeed=44100 + + diff --git a/ReleaseDocumentation/MIDI.TXT b/ReleaseDocumentation/MIDI.TXT new file mode 100755 index 0000000..77c5562 --- /dev/null +++ b/ReleaseDocumentation/MIDI.TXT @@ -0,0 +1,400 @@ + +------------------------------------- +## Impulse Tracker MIDI Supplement ## +------------------------------------- + +Introduction +============ + +The biggest new addition to Impulse Tracker 2.12 has been support for +sending data out through the MIDI protocol. Earlier versions of Impulse +Tracker (IT) have had support for incoming MIDI data, so it was possible to +play on a 'MIDIfied' keyboard and have IT 'track' all the notes down in the +pattern in realtime. + +MIDI out, however, is a completely different ballgame. You in fact don't +have to read this supplement at all if you wish to get MIDI working, but in +order to gain full usage of MIDI out, you will have to read this in order +to understand how IT's MIDI support fully works + + +MIDI Support & Soundcards (Modified by Pulse) +============================================= + +At present, the only sound devices IT supports for MIDI output are the AMD +InterWave and the Creative Labs Sound Blaster AWE32. Support for other +soundcards is via the generic MPU401 driver. To use this driver, you must +run "IT /S19 /A

" where
is the address of your MPU401 +compatible card (eg. "IT /S19 /A330"). Note that the generic MPU401 driver +does *NOT* support sample playback at all. + +MIDI And AWE32 Soundcards (Pulse) +--------------------------------- + +I have found that the Windows '95 drivers for the AWE32 are somewhat buggy. +On my computer, I can use MIDI In/Out in Impulse Tracker *IF* I disable the +MIDI support within Windows '95. Otherwise, it is simply not recognised. To +disable the MIDI support in Windows '95, right click on "My Computer", +"Properties", "Device Configuration", "Sound, Video & Game Controllers". +Double click on "Creative Labs SB16 or AWE32" and go to the resources. +Uncheck the "Use Automatic Settings" box if it is set and change the basic +configuration to one that does NOT include the MIDI Ports 300h or 330h. +(For example, Basic Configuration 0 has only 220h, 5, 1, 5 on my computer + and IT works fine in a DOS Box) + + +Enabling MIDI +============= + +To enable MIDI output, you must first have IT on Instrument control mode +rather than Sample control mode. To do this, press F12 to go to the Song +Variables screen and switch control to 'Instruments' if you haven't already +done so. + + +MIDI & Instruments +================== + +MIDI Channel +------------ + +New to the Pitch section of the Instrument screen (press F4 and select the +"Pitch" button) are the sliders "MIDI Channel", "MIDI Program" and "MIDI +Bank". Once the MIDI Channel value for that instrument is set to a value +other than zero, IT will send out MIDI data whenever that instrument is +encountered in a pattern, on that particular MIDI Channel. What data IT +actually sends through the MIDI port will be a note on command, although +this will be discussed in more detail later. + +MIDI Program/MIDI Bank +---------------------- + +The MIDI Program and MIDI Bank sliders work in a similar manner to each +other. If they have a value set to -1, IT will not transmit a program change +message nor a bank change message for that instrument. If you specifically +set a MIDI Program for that instrument, IT will send a 'program change' +message along with the 'note on' message. + +The MIDI Bank instrument setting is also the same; IT will not send a bank +change message if the MIDI Bank slider is set to Off (ie: has a value of +-01). If the MIDI Bank setting is active for that instrument, IT will send +it along with the note on message as well. + +Summary +------- + +IT will always send a 'note on' command for a particular MIDI channel +whenever a MIDI instrument is encountered in the pattern. (A MIDI instrument +is simply an instrument where the MIDI Channel value has been set to +something other than "Off"). IT will also send a program change command and/or +a bank change command along with the note on command if they are set active. + + +More Advanced MIDI +================== + +How MIDI Works +-------------- + +MIDI is not a file format (like IT is a module format) nor is it even a file +layout. MIDI is a computer protocol (or language) which is used to +communicate between devices . You may like to think of it as a network, +where the MIDI cables are the cables you lay between computers, and MIDI is +the network protocol (such as Novell NetWare, Windows Networking or TCP/IP) +used to communicate between the sound devices. When an instrument is said to +be 'MIDI compliant', that means that it has support for the MIDI protocol +and understands MIDI messages. + +The .MID file format is simply a way to store these messages. It is a +collection of MIDI data, and when a .MID file is run through a MIDI player, +all the MIDI player does is send the data in the .MID file out through the +computer's MIDI port. In a network analogy, if you can imagine that every +single transaction run through the network was being logged to a file on +your hard disk; that every single byte was being recorded to a logfile, this +is what a .MID file is. + +An example of MIDI Communication in IT +-------------------------------------- + +You've read above that when IT encounters a MIDI instrument in the +patterndata, it sends a 'note on' command, which is defined in the MIDI +protocol to be 'Play this note on this MIDI channel at this particular +velocity'. (Velocity is similar to volume ). If you play a MIDI instrument +which is mapped to MIDI channel 2 at C-5 with a velocity of 64, the actual +data which IT sends out to the MIDI port resembles something like this (in +hex): + + Note On with parameters; + MIDI Channel: 2 + Note: C-5 + Velocity: 64 + + Data that IT sends out (hex): 91 3C 40 + Data that IT sends out (decimal): 145 60 64 + +We'll run through each of these three bytes step by step. + +The first byte (91 in hex, or 91h) is the actual 'Note on' command. It tells +the receiving MIDI device that the data which follows is part of the 'note +on' data. An analogy which trackers may find useful is the effect column. +There, you have an effect command and effect data; for example, the effect +'G20' can be split up into two parts--'G' and '20'. The 'G' part is the +actual effect command which tells IT that you wish to perform a portamento, +and the '20' part is the effect data, or in this case the spe ed at which +the portamento should occur. In this MIDI example, the '9' is the MIDI +command and the '1 3C 40' is the rest of the data for that command. + +Now, the second digit (1 in our example) specifies the MIDI channel. MIDI +channels are 0-based; that is, if you want to send to MIDI channel 6, IT +specifies 05 for the actual data. MIDI channel 10 is 09h, MIDI channel 14 is +0Dh, etc. Here we're sending to MIDI channel 2, so the value sent out over +MIDI is 01h. + +The second byte (3Ch) is actually the note to send (C-5 here). In MIDI, all +command (parameter) data is between a scale of 00h-7Fh (or 0-127 in +decimal). Notes are transmitted the same way - via numbers. If you imagine +C-1 is sent with a value of 00h, C#1 i s 01h, D-2 is 02h, etc, then the note +we want to play, C-5, has a value of 3Ch (60 decimal). + +Now the first and second bytes are done with, the third byte should be +fairly easy to understand. This byte represents the velocity at which the +note should be played. In our case, we want a velocity of 64, which +translates to 40h, and so this is the value which is sent out. + +So to recap, we have three bytes for the note on command, "91 3C 40". + + Byte 1: 91 == Note on command (on MIDI channel #2) + Byte 2: 3C == Note on data (Note to play, C-5) + Byte 3: 40 == Note on data (Velocity of 64 decimal) + +Configuring IT's MIDI out data +------------------------------ + +Keeping the above example in mind, press Shift-F1 to get to IT's MIDI screen +and press the 'MIDI Output Configuration' button. This will take you to IT's +MIDI out engine. Now, if you examine the 'Note On' field, it reads: + + 9c n v + +This can be correlated to our above example of '91 3C 40'. Now, the 'c n v' +in the Note On field corresponds to 'channel', 'note' and 'velocity'. Think +of them as variables; IT will substitute the appropriate channel, note and +velocity values which it encounters in the MIDI instrument information +and/or patterndata. + +If you now actually defined a MIDI instrument to play on MIDI channel 2, and +you played it in a pattern at C-5 with velocity 64, all IT does is read the +'Note On' field from the MIDI configuration screen and substitute '1' for +'c', '3C' (C-5) for 'n' and '64' for 'v'. Therefore, IT will read '9c n v' +and replace it with '91 3C 40'. + +In any of the MIDI output fields, lowercase letters represent variables (or +subsitutions which IT should make) and uppercase letters or numbers are +constants which IT writes to the MIDI port directly without any change. +Therefore, these fields are case se nsitive--for the note on command, '9c n +v' is blatantly different to '9C n v'. 9c represents 'send byte 09 followed +by the MIDI channel byte', whereas 9C represents 'send the byte 9C'. + +In short, 0-9 and A-F are treated as hexadecimal constants and will be +passed through directly. Lowercase letters will be treated as variables and +substituted accordingly. Note that variables are regarded as 'full bytes' by +themselves and are never part of an actual byte sequence except for the +variable 'c', so '9n' is exactly the same as '09 n' or '9 n'; all of them +will expand to the sequence '09 '. 'c' is the only value +that takes on a nibble (4-byte) value, due to the MIDI protocol definition. +This means that 9c will actually become one byte when expanded, with the +lower digit representing the channel. + +IT MIDI Variables +----------------- + +c: MIDI channel + + This is simply the MIDI channel of which the instrument is set + to, 0-based. Note that this is the only nibble sized variable. + +m: note value (instrument) + A value from 00-7Fh representing the note to be played, where + C-5 is 60h. This is the note entered in the pattern, not the + translated value. + +n: note value (sample) + + A value from 00-7Fh representing the note to be played, where + C-5 is 60h. This is the note after instrument translations have + been applied. + +o: Offset value + + Extra parameter than can be sent via Oxx commands. + +v: velocity + + The MIDI velocity of the note. + +u: volume + + Volume is similar to velocity, except that velocity does not + take the volume envelope and fadeout values into account, whereas the + 'u' volume variable does. + +x: pan set + + Sends a MIDI panning value. This does not take into account +panning envelopes. + +y: calculated pan + + Sends a MIDI panning value which does take into account +panning envelopes. + +a: high byte of bank select +b: low byte of bank select + + These commands are only really useful in the bank change +field. + +z: macro data + + (See section on macros for full explanation). + +Configuring MIDI Output for Your Keyboard +----------------------------------------- + +In the basic IT distribution, the only fields which have any data are 'Note +on', 'Note Off' and 'Program Change'. The reason for this is that these are +the only commands which are set as standards by MIDI. MIDI commands such as +Change Pan, Bank Select , e tc all differ from synth to synth. There's not +much which can be done to solve this, you will have to look up your synth's +manual to find out the exact MIDI commands it needs to issue a panning +change, bank select, etc. + +Some values which you may wish to try, however, will be: + + Change pan: Bc 0A x + Bank select: Bc 0 a 20 b + +These may or may not work. If they do, then great, but if they don't, you +will have to actually RTFM *gasp* in order to get these other commands +working. + + +Effect Commands & Macros +======================== + +Now that IT's MIDI engine is understood and the basis of MIDI communication +has been laid down, perhaps the most powerful function of IT's MIDI engine, +macros, will be explained. + +Standard Effects +---------------- + +Firstly, at the moment there is NO support for standard IT effect commands +(such as pitch slide, portamento, vibrato etc) to work via MIDI. This may or +may not be implemented in future. Currently, however, if you perform an E01 +effect on a note, nothing w ill happen as far as the MIDI aspect of the +instrument is concerned. + +Macro Effects - SFx +------------------- + +The SFx command, previously used in the .MOD format as "FunkRepeat", has +been changed in IT to allow for the functioning of MIDI macros. The unused +Zxx command will also now play a part in MIDI functioning. + +To understand how this works, it's best to take an example into account. At +the beginning of this supplement, the MIDI sequence '91 3C 40' was used +which was a Note On, MIDI channel #2 played at C-5 with a velocity of 64. +This was represented in IT's MIDI configuration as '9c n v', so it made the +appropriate substitutions to '91 3C 40'. + +The Macro Setup section of IT's MIDI Output Configuration screen can be used +to define your own custom MIDI command/data sequences. These can be +absolutely anything you like, from a MIDI SysEx command to a Note On +command. In fact, to start off, we'll tak e a Note On sequence as an example +and we will attempt to emulate the same '91 3C 40' bytes, except that we'll +make this sequence ourselves rather than letting IT do the work for us. + +How SFx and Zxx commands relate +------------------------------- + +Firstly, remember that IT substitutes values when it encounters variables. +If you glance at the above section on IT MIDI Variables, you'll notice that +the 'z' variable represents macro data. Now that this '91 3C 40' sequence +has been driven into our he ads, try setting the SF0 macro field on IT's +MIDI Output Configuration screen to '91 3C z'. + +Remember that the third byte in the MIDI sequence (40 in our normal +example) is the velocity to send with the Note On message. The SF0 macro +field you've just defined means that IT will read any Zxx effects and +replace the 'z' variable in the SF0 macro with the 'xx' value from the Zxx +effect. To enable the macro, simply put in a SF0 along with a Note On in the +pattern data. Now, all values from Z00 to Z7F will substitute for 'z' +accordingly. So, to show that our SF0 sequence will reproduce the exact same +thing as our Note On command: + + C-5 01 SF0 (this will play the note on command as usual, and + specify that the SF0 macro sequence should be + hooked to Zxx effects). + ... .. ... + ... .. ... + ... .. ... + ... .. Z40 (this will trigger our SF0 sequence with a 'z' + value of 40h). + +The above patterndata should produce a note on event at row 0 in the +pattern, and again at row 4. Now, try replacing the Z40 effect with Z7F and +IT will substitute 'z' with '7F', or a velocity of 7Fh (127 decimal) in our +SF0 sequence. The result should be that you'll hear a Note On with velocity +64 on row 0, and a Note On with velocity 127 on row 4; ie: the second note +triggered will be twice as loud. The The sequence that IT will send will be +'91 3C 7F'. + +SFx commands summary +-------------------- + +Our example above of using a 'note on' command sequence for an SFx effect is +rather pointless, since IT does this effect itself. However, it has +hopefully served its purpose by demonstrating how effects work. + +The SFx commands, as you can see, can be redefined to absolutely any MIDI +data at all. This can be something simple like a pitch slide, a complex +SysEx 'set filter to aftertouch' command, or whatever you like. The +possibilities are endless and are only li mited by what your synth can do; +IT's SFx/Zxx combination is customisable enough to handle nearly any MIDI +data you wish to output. + +If you wish to take advantage of these commands, you will have to look up +the manual for your synth and get stuck into the MIDI/SysEx section. Please +do not come to any IT support people asking for help on this subject because +every synth is different. + +Z80 -> ZFF commands +------------------- + +The Z80 to ZFF commands are also macro sequences, but they have no 'z' +variable to substitute for. They are not 'hooked' to any SFx effects, they +are straight, direct macro sequences. For example, if you have a MIDI +controllable effects unit (such as an Alesis MidiVerb), you may wish to +assign the Z80 command to set a up a certain value for the reverb delay +length. Later in the song, you can issue a Z81 command to change the reverb +delay or turn it off altogether. + +To summarise, the Z80 to ZFF commands are similar to SFx macro sequences, +but they do not have any extra parameters (whereas the SFx macro's 'z' +variables are controlled by Z00 to Z7F). + + +Contact Information +=================== + +If there are any problems with this textfile, email ozone@post1.com or +pulse@cyburbia.net.au + + __/\___/\_/\____/\____/\ .. . Andre Pang % vault ...: + + / /__ / \_ \_ __) :.. mailto:ozone@post1.com . ....: +( : / (__: ) | | _)_ : . http://www.mindflux.com.au/ .: + \___( ______/|__;__|_____| :. irc: #trax (irc.neato.org) ..: + \/ - #ozone + diff --git a/ReleaseDocumentation/NETWORK.TXT b/ReleaseDocumentation/NETWORK.TXT new file mode 100755 index 0000000..9660d11 --- /dev/null +++ b/ReleaseDocumentation/NETWORK.TXT @@ -0,0 +1,71 @@ + + + Networked Impulse Tracker + + +What is Networked Impulse Tracker? +---------------------------------- + +Networked Impulse Tracker is simply that - a session of Impulse Tracker where +multiple composers can all edit the same song at the same time! It may sound +a little bizarre, but networked sessions can be both extremely fun and +productive. + + +Requirements +------------ + + 1. Impulse Tracker, 7 Apr 99 or later + + 2. Impulse Tracker Network driver file. (*.NET) + + 3. Some form of network supported by the network driver file. + +To Use +------ +To initiate a Network session, Press Shift-ESC. A list of available drivers +will be shown. Select one with Enter. + + +ITIPX.NET +--------- + +ITIPX.NET is an IPX Network driver for Impulse Tracker. It is recommended that +this is used over a LAN (ie. you will need a network card in your computer). +Although Kali will work (IPX over the internet), performance will probably be +unacceptable for most people through a modem. + +The IPX driver *will not be stable* under Win95. Upgrade to Win98. +To install IPX to run under Windows, go to Start Menu->Settings->Control Panel. +Select Network, and under the Configuration Tab, press Add, then select + Protocol->Microsoft->IPX/SPX Compatible Protocol + +The IPX driver will list the available sessions in the left hand box. Select +a session to join by pressing Enter. + +The Username that the IPX driver transmits is associated with each driver file. +The public distribution identifies itself as "Unregistered". Different +usernames are availble for US$10 each. Payment can be made via Kagi at +http://order.kagi.com/?4ZM + +Please specify a username, maximum length 15 characters, or else one will be +chosen for you. Updated versions of the driver, if made, will be provided free +of charge. However, changing your username will still cost $10. + +'Normal' usage of this driver should run quite stably. However, if you try hard +to make it crash, I'm sure you will be able to. + +Note that connections will be automatically dropped if queued packets fail to +be transmitted for more than 10 seconds. + +General Notes +------------- +Impulse Tracker supports a maximum of 4 users per session. Extra users will +be automatically discarded. + +Many functions have been disabled under network mode. You will receive warning +messages in these cases. + +Do *NOT* use hardware mixed drivers for networked sessions. This specifically +means the AWE32, GUS and Interwave drivers. Since networked sessions can +change samples 'behind your back', these drivers will not update correctly. diff --git a/ReleaseDocumentation/README.TXT b/ReleaseDocumentation/README.TXT new file mode 100755 index 0000000..2b9a5b4 --- /dev/null +++ b/ReleaseDocumentation/README.TXT @@ -0,0 +1,72 @@ + +This package contains 6 files + +1. IT.EXE - This can be considered IT214 Patch #4. Includes a few bugfixes + and some minor enhancements. Registered users should use their + own IT.EXE + +2. ITVSOUND.MMX - Virtual Sound Driver for Impulse Tracker. This is a MMX + driver and will not work on non MMX computers. + +3. ITVSOUND.DRV - Virtual Sound Driver for Impulse Tracker. This is a non-MMX + driver and should work on all computers. + +4. ITVSOUND.VXD - Driver to connect ITVSOUND.MMX to the server. + +5. SERVER.EXE - Windows server to connect to DirectSound + +6. README.TXT - This file. + +How to use these files +---------------------- +You MUST have DirectX installed. It was written with the DirectX6 SDK, +although I'm pretty sure DirectSound 5 is sufficient. + +1. Copy ITVSOUND.VXD into your Windows\System directory + (normally C:\WINDOWS\SYSTEM) + +2. In your Windows directory (normally C:\WINDOWS), edit your SYSTEM.INI file + and include the line: + device=itvsound.vxd + anywhere in the [386Enh] section + +3. Reboot your computer + +4. Run Server.EXE + +5. Run "IT" + +Configuring the driver +---------------------- +The driver can be configured by modifying Window's Registry by running +"regedit" (which comes with Windows). The variables can be found at: + "KHEY_LOCAL_MACHINE\Software\Jeffrey Lim\Impulse Tracker VSound Server" + +The 4 variables are: + BufferSize - The size of the DirectSound buffer in kb. + Permitted ranges from 4 to 64, default 24 + BufferThreshold - The size of the buffer that IT tries to maintain in kb. + Permitted ranges from 2 to 32, default 21 + BufferType - 0 = DualBuffer (BufferSize is logically split into 2 sections) + 1 = QuadBuffer (BufferSize is logically split into 4 sections) + 2 = OctBuffer (BufferSize is logically split into 8 sections) + (recommended, default) + MixSpeed - Mixing rate to be used in Hz. + Permitted ranges from 11025 to 64000, default 44100 + +You will need to restart the server before these changes take effect. + +Known Problems +-------------- +1. This driver only works with Win95 and Win98, NOT WinNT (I'll try a WinNT + driver sometime). + +2. There is an obvious latency due to the size of the buffers and the delay + that is inherent to DirectSound. Reducing the BufferSize and BufferThreshold + values can reduce this latency, however, smaller values can also cause the + sound to break up. + + Try using the values: + 1. BufferSize=16, BufferThreshold=14, BufferType=2, MixSpeed = 44100 + + diff --git a/ReleaseDocumentation/SUMMARY.TXT b/ReleaseDocumentation/SUMMARY.TXT new file mode 100755 index 0000000..f33749b --- /dev/null +++ b/ReleaseDocumentation/SUMMARY.TXT @@ -0,0 +1,296 @@ + + Summary Information - Command Line + + -SFilename.Drv - Set soundcard driver + + -Sxx Quick set sound card + 0 = No Sound + 1 = PC Speaker + 2 = Sound Blaster 1.xx + 3 = Sound Blaster 2.xx + 4 = Sound Blaster Pro + 5 = Sound Blaster 16 + 6 = Sound Blaster AWE 32 + 7 = Gravis UltraSound + 8 = Interwave IC + 9 = Pro Audio Spectrum + 10 = Pro Audio Spectrum 16 + 11 = Windows Sound System + 12 = ESS ES1868 AudioDrive + 13 = EWS64 XL Codec + 19 = Generic MPU401 driver + 20 = Disk writer device + + -Axxx Set sound card's address (hexadecimal) + -D# Set DMA channel (decimal) + -I## Set IRQ number (decimal) + + -M##### Set mixing speed (decimal) + -L### Limit number of channels + + -C Control playback in DOS Shell (with Grey +/-, Right Alt & Right Ctrl) + -F Disable file-colour distinctions + -K Exchange F1 and F11 keys + -Px Pattern memory allocation strategy. + -P0 = Try to store patterns in conventional memory first, EMS is + only used once conventional memory runs out. + Not recommended, but those of you who use IT in Windows 3.xx + should try this option if you get EMS errors. (I recommend + that you don't use IT under Windows 3.xx at all) + -P1 = Use one block of EMS for all patterndata. + This is the most memory efficient of all the pattern + storage modes - (this is also the default) + -P2 = Use EMS blocks for each pattern + This is a VERY wasteful but 'safe' memory allocation scheme. + -R Reverse channels (flip left-right), same as Alt-R on the info page. + -T1 Disable usage time indication + -T2 Enable timeslice release + -V1 Override VGA detection/Matrox detection. + -V2 Force matrox compatibility mode (use with -v1) + -V3 Wait for vertical retraces + -X1 Disable internal MMTSR + -X2 Disable mouse + -X3 Disable drive map detection + -X4 Disable cache file creation + + + Summary Information - Effects, alphabetically + + Volume Column Effects + Ax - Volume slide up + Bx - Volume slide down + Cx - Fine volume slide up + Dx - Fine volume slide down + Ex - Pitch slide down + Fx - Pitch slide up + Gx - Portament to + Hx - Vibrato with speed x + + General Effects + Axx - Set speed (set number of frames per row) + Bxx - Jump to order + Cxx - Break to row xx of (next) pattern + Dxy - Volume slide, x=0 down; y=0 up; x=F fine down; y=F fine up + Exx - Pitch slide down by xx + EFx - Fine pitch slide down by x + EEx - Extra fine pitch slide down by x + Fxx - Pitch slide up by xx + FFx - Fine pitch slide down by x + FEx - Extra fine pitch slide down by x + Gxx - Portamento to note with speed xx + Hxy - Vibrato with speed x, depth y + Ixy - Tremor with ontime x, offtime y + Jxy - Arpeggio with halftones x and y + Kxy - Dual command: H00 and Dxy + Lxy - Dual command: G00 and Dxy + Mxx - Set channel volume to xx (0->40h) + Nxy - Channel volume slide, x=0 down; y=0 up; x=F fine down; y=F fine up + Oxx - Set sample offset to xx00h + Pxy - Panning slide, x=0 right; y=0 left; x=F fine right; y=F fine left + Qxy - Retrigger note every y frames with volume modifier x + Values for x: + 0: (nothing) 4: -8 8: (nothing) C: +8 + 1: -1 5: -16 9: +1 D: +16 + 2: -2 6: *2/3 A: +2 E: *3/2 + 3: -4 7: *1/2 B: +4 F: *2 + Rxy - Tremelo with speed x, depth y + S3x - Set vibrato waveform + S4x - Set tremelo waveform + S5x - Set panbrello waveform + Waveforms for x in S3x, S4x and S5x: + 0 = Sine 2 = Square + 1 = Ramp down 3 = Random + S6x - Pattern delay for x frames + S7x - Instrument functions + Values for x in S7x: + 0: Past note cut 5: Set NNA to note off + 1: Past note off 6: Set NNA to note fade + 2: Past note fade 7: Turn off volume envelope + 3: Set NNA to note cut 8: Turn on volume envelope + 4: Set NNA to continue + S8x - Set pan position + S91 - Set surround sound + SB0 - Set loopback point + SBx - Loop x times to loopback point + SCx - Note cut after x frames + SDx - Note delay for x frames + SEx - Pattern delay for x rows + SFx - Select parameterised MIDI Macro + T0x - Tempo slide down by x + T1x - Tempo slide up by x + Txx - Set tempo (20h->0FFh) + Uxy - Fine vibrato with speed x, depth y + Vxx - Set global volume to xx (0->80h) + Wxx - Global volume slide, x=0 down; y=0 up; x=F fine down; y=F fine up + Xxx - Set panning position (0->0FFh) + Yxy - Panbrello with speed x, depth y + Zxx - MIDI Macro - check MIDI.TXT + + Summary Information - Effects, categorically + +Note: Not all effects are listed here. + +Speed Control + Axx - Set speed + T0x - Tempo slide down by x + T1x - Tempo slide up by x + Txx - Set tempo (20h->0FFh) + S6x - Pattern delay for x frames + SEx - Pattern delay for x rows + +Position Control + Bxx - Jump to order + Cxx - Break to row xx of (next) pattern + SB0 - Set pattern loopback point + SBx - Loop pattern x times + +Volume Control + Ax - Volume slide up + Bx - Volume slide down + Cx - Fine volume slide up + Dx - Fine volume slide down + Dxy - Volume slide, x=0 down; y=0 up; x=F fine down; y=F fine up + Ixy - Tremor with ontime x, offtime y + Mxx - Set channel volume to xx (0->40h) + Nxy - Channel volume slide, x=0 down; y=0 up; x=F fine down; y=F fine up + Vxx - Set global volume to xx (0->80h) + Wxx - Global volume slide, x=0 down; y=0 up; x=F fine down; y=F fine up + Rxy - Tremelo with speed x, depth y + S4x - Set tremelo waveform + +Panning Control + Xxx - Set panning position (0->0FFh) + S8x - Set pan position + S91 - Set surround sound + Pxy - Panning slide, x=0 right; y=0 left; x=F fine right; y=F fine left + Yxy - Panbrello with speed x, depth y + S5x - Set panbrello waveform + +Pitch Control + Exx - Pitch slide down by xx + EFx - Fine pitch slide down by x + EEx - Extra fine pitch slide down by x + Ex - Pitch slide down + Fxx - Pitch slide up by xx + FFx - Fine pitch slide up by x + FEx - Extra fine pitch slide up by x + Fx - Pitch slide up + Gxx - Portamento to note with speed xx + Gx - Portamento to + Hxy - Vibrato with speed x, depth y + Hx - Vibrato with speed x + Uxy - Fine vibrato with speed x, depth y + S3x - Set vibrato waveform + Jxy - Arpeggio with halftones x and y + + Summary Information - Pattern Editor 1 + +Data Entry + Alt-0 -> Alt-9 Set skipvalue to 0-9 + . (period) Clear field(s) + 1 Note cut (^^^) + ` Note off () / panning toggle (in volume column) + Spacebar Use last (default) note/instrument/volume/effect/effectvalue + + + + SD GHJ 23 567 90 + + Z X C V B N M Q W E R T Y U I O P + + +Pattern selection + +, - Next/Previous pattern (*) + Shift +, - Next/Previous 4 patterns (*) + Ctrl +, - Next/Previous order's pattern (*) + +Miscellaneous + Enter Get default note/instrument/volume/effect + '<' or Ctrl-Up Decrease instrument + '>' or Ctrl-Down Increase instrument + Grey '/' Decrease octave + Grey '*' Increase octave + ',' (comma) Toggle edit mask for current field + + Ins/Del Insert/Delete a row to/from current channel + Alt-Ins/Del Insert/Delete an entire row from pattern (*) + Alt-N Toggle Multichannel + 2*Alt-N Multichannel selection menu + Alt-Enter Store pattern data + Alt-Backspace Revert pattern data (*) + Ctrl-Backspace Undo - any function with (*) can be undone. + + Ctrl-F2 Set (multiple) pattern length + +Cursor Control + Up/Down Move up/down by the skipvalue + Ctrl-Home/End Move up/down by 1 row + Alt-Up/Down Slide pattern up/down by 1 row + Alt-Left/Right Move forwards/backwards one channel + Ctrl-Left/Right Move left/right between track columns + Tab/Shift-Tab Move forwards/backwards to note column + PgUp/PgDn Move up/down by n lines (n=Row hilight major) + Ctrl-PgUp/PgDn Move to top/bottom of pattern + Home Move to start of column/start of line/start of pattern + End Move to end of column/end of line/end of pattern + Backspace Move to previous position (accounts for Multichannel) + + Ctrl-C Toggle centralise cursor option. + +Track View Functions + Alt-T Cycle current track's view + Alt-R Remove all track views + Alt-H Toggle track-view divisions + Ctrl-0 Deselect current track + Ctrl-1 - Ctrl-5 View current track in scheme 1-5 + Ctrl-Left/Right Move left/right between track columns + + Left-Ctrl & + Left-Shift 1-4 Quick setup view scheme (and enable cursor-tracking) + + Ctrl-T Toggle view-channel cursor tracking + + Summary Information - Pattern Editor 2 + +Block functions. + Shift-Movement Mark block + Alt-B Mark beginning of block + Alt-E Mark end of block + Alt-D Quick mark n/2n/4n/... lines (n=Row Hilight Major) + Alt-L Mark entire column/pattern + + Alt-U Unmark block/release clipboard + + Alt-Q Raise notes by a semitone (*) + Alt-A Lower notes by a semitone (*) + + Alt-S Set instrument (*) + Alt-V Set volume/panning (*) + Alt-W Wipe volume/panning not associated with a note/instrument (*) + Alt-K Slide volume/panning column (*) + 2*Alt-K Wipe all volume/panning controls (*) + Alt-J Volume amplifier (*) / Fast Volume attenuate (*) + Alt-Z Cut block (*) + Alt-X Slide effect value (*) + 2*Alt-X Wipe all effect & effect value data (*) + + Alt-C Copy block into clipboard + Alt-P Paste data from clipboard (*) + Alt-O Overwrite with data from clipboard (*) + Alt-M Mix data from clipboard with pattern data (*) + + Alt-F Double block length (*) + Alt-G Halve block length (*) + + Alt-I Select template mode / Fast volume amplify (*) + Ctrl-J Toggle fast volume amplification with Alt-J/Alt-I + +Playback functions + 4 Play note under cursor + 8 Play row + + Ctrl-F6 Play pattern from current row + Ctrl-F7 Set/Clear playback mark (for use with F7) + + Alt-F9 Toggle current channel on/off + Alt-F10 Solo current channel on/off diff --git a/ReleaseDocumentation/UPDATE.TXT b/ReleaseDocumentation/UPDATE.TXT new file mode 100755 index 0000000..16dd3cb --- /dev/null +++ b/ReleaseDocumentation/UPDATE.TXT @@ -0,0 +1,592 @@ + +Contributors Additions + - IT215 file format saving. Note that this is an alternative compression + format and is often better, but not always. Public releases of IT214 + Patch 1 and later can read IT215 compressed files. There is also a + version of MikIT that can read IT215 compression. + - Sample sorting enabled. On the sample/instrument list screens, files will + be priority sorted alphabetically if you don't move the cursor. If you + do move the cursor, then you can force a resort once all the files have + been loaded by pressing Alt-S. + - Reordering of order list with Alt-R while on the order list screen + (easier to try it out, than to try to explain it) + - Row lock in pattern editor if holding shift - very useful for chords + (ie. use Shift+note) + - 10 configurable 'preset' envelopes slots + - Extra instrument filter controls (under pitch menu). + - Alt-W on the sample list saves as .WAV format, not .RAW + - Individual Sample/Instrument solo. + - Personalised Network username + +Contributions of US$30 or more + - Stereo Diskwriter + - MIDI .IT -> .MID converter + + +Bug fixes to Network version + - Correct data transmitted on: + 1. Pattern Undo (Ctrl-Backspace) + 2. Block Mix (Alt-M) + - EMS Error 83h during network sessions + +IT214 Network + - This includes the first version of Networked Impulse Tracker. Check + NETWORK.TXT for more information. + + - ITSB16B.MMX for SBLive! users which shouldn't require reinitialisation. + +IT214 Patch 4 - This release has been made entirely for the VSOUND drivers, + which will allow you to setup IT to run under Windows '95/'98 + with *ANY* soundcard. Check ITVSOUND.TXT for more information. + + - Addition: Included command line option /V3 to wait for vertical retrace. + - Addition: Included command line option /X4 to disable cache file creation. + + - Bug fix: Several fixes to the MIDI Out implementation + - Bug fix: S3M saver sometimes caused crash problems and pattern errors + - Bug fix: SCx and Qxx commands and will work with MIDI Out instruments + - Bug fix: 64 channel view doesn't skip channels with only volume-effects + + - Driver news: 4-band EQ in diskwriter + Minor miscellaneous upgrades + Fixes to MMX drivers that clicked on 0 volume (oops) + + Clarification (only because I saw some arguments on usenet) + - the MMX drivers use 32-bit precision mixing, not 16-bit. + +IT214 Patch 3 - Merry XMas guys! + + - If anyone who has contributed has NOT received an EMail from me, please + write to me! I've sent out EMails to every one of you.. but a few + addresses have changed.. or I could have accidentally missed you (huge + apologies if so) + + - Bug fix: IFF loader + - Bug fix: XM modules with no patterns won't crash IT. (Apologies to the + GroovyCompo Organisers - for those interested in online music + tracking competitions, check http://www.groove.org) + - Bug fix: CACHE files stored on CDROMs will now work, irrespective of + their datestamp. Thanks to Humanoid/Prophecy for the Morbid Minds + CD on which I could finally test these routines! + - Bug fix: Obscure bug on instrument list under rare circumstances causing + playing notes to do weird things. + + - Driver news: Updated driver format (incompatible with previous ITs) + Resonant filters - check FILTERS.TXT for information. + This stuff has been released basically so that contributors + can distribute their songs that use filters.. + - MMX drivers implemented. + - WAV driver - time accuracy improved + - can specify destination directory (on shift-F5) + - handles resonant filters + +IT214 Patch 2 + - Bug Fix: 16-bit samples of an exact multiple of 32768 bytes in size were + getting corrupted on saving. + - Bug fix: MIDI Macros (unparameterised) were somehow disabled somewhere + after IT212.. now reenabled + +IT214 Patch 1 + - Bug fix: EMM4.0 mode reenabled + - Bug fix: Volume envelopes were skipping some ticks (sounded too fast) + - Bug fix: Slight problems with the wav writer fixed + - Bug fix: S3M saving bug fixed (was introduced in IT214 due to a 'bug + report') + - Other miscellaneous fixups + +IT214 - Version jump to make sure samples don't get screwed up by the + prerelease (IT213) loader. This is the FINAL public release. Apart + from bugfixes/new soundcard drivers, don't expect to see anything in + the future... + + - Samples are now compressed on the fly when saved and loaded from disk. + Note that this is NOT the same as using MMCMP. + + - Several unimportant (debug) procedures removed to make slightly more + memory available. + + - Driver news: Diskwriter interpolation changed from quadratic spline + to cubic spline. (Requires a FPU) + +IT213 Update + - Modification: Sample panning reset to override instrument panning due to + demand. + + - Update: .IFF loader updated. Should deal with almost any .IFF file now. + + - Update: EMS Stability improved + + - Update: Several miscellaneous changes + + - Update: If old effects is *ON*, then a looped volume envelope will NOT + include the last node (for XM compat) + + - Update: More memory available (Help text was manually compressed) + + - Row hilight information is now stored within the .IT module.. + + - Automatic MIDI Pitch wheel handling. Vibrato, pitch slides, portamentos + all handled. + + + - MIDI Configuration can be embedded into .IT files. + (Option is on Shift-F1) + + - Driver news: Terratec EWS64 XL Codec software mixing driver + Terratec Maestro 32/96 Codec software mixing driver + Terratec Maestro 16/96 Codec software mixing driver + Ensoniq SoundscapeVIVO Codec software mixing driver + Sound Track PCI Codec software mixing driver + ES1688 Audiodrive Codec software mixing driver (for ViperMAX) + MPU401 generic driver. + Direct to Disk writer now uses logarithmic volume ramping + and quadratic spline interpolation + Read DRIVERS.TXT for information on all of these. + +IT212 Update - Special thanks go out to all those that did stability testing + of the beta versions of IT212. + + - Bug fix: "Available Samples" in the instrument loading screen will be + correct if you're loading an instrument from within a module. + + - Bug fix: Sample files will store default pan values. + + - Bug fix: Trying to show pattern data past the end of a pattern will + not crash IT anymore. This could have occurred before if the + number of rows in a pattern were reduced during playback, then + switching to the info page. + + - Bug fix: Deleting samples/instruments "within" a module has been disabled + (as it should be), so that the module itself cannot be deleted. + + - Bug fix: Default sample pan will override instrument pan whether "Old + Effects" is on or off. + + - .669 Loader, since Snowman is collecting 'em :) + This loader hasn't been extensively tested, maily because Composd.Exe + will not run on my machine (64MB is "Not enough extended memory" ?!?! ). + Most songs should play though.. Please don't bug me to update the loader + any further - you won't get a reply. + + - *Much* better memory handling for patterns. EMM386 parameter H=255 + should not be required in MOST cases now (you will only need it if + you use a large number of samples (ie. > 50) ). You should also have + more FreeMem to work with. Beta testers have noted that QEMM shows even + more stability problems in this version than previous versions - please + avoid QEMM as it DOES cause crashing for as yet unknown reasons. The old + memory allocation routines can still be found if you have EMS problems by + using /P2 on the command line. + + - Keyboard handling on instrument lists has been improved to handle + multiple keypresses/releases. (but not on sample list due to usability) + + - Default volume display in *NORMAL* (5 channel) pattern editor if you press + Ctrl-V. If you use a custom font, you will need to upgrade your font set + with FONTUPGR to see this properly. + Example: + C-4 01 .. ... <-- what volume is this?? + + Press Ctrl-V: + C-4 01 [32] ... <-- it'll show that the default volume of + sample/instrument 1 is 32. + + Alt-K has been upgraded to 'pick up' these default values. (So that you + can also slide from volume 0 to the sample's default without having to + explicitly key in the value). + + - Automatic filename extension replacement on Ctrl-S, so that if you press + Ctrl-S after loading a .MOD, .669, .MTM or .XM, the filename will be + automatically modified to have a .IT extension. + + - CDRom check for CACHE.IT? files. If you burn a CDRom of samples or + instruments, include the CACHE.ITI and CACHE.ITS files from IT211+ and + they should accelerate loading of sample and instrument names on all + future versions of IT. + < Not tested, since I can't :( > + + - 64 channel miniview on the info page. (note: doesn't show all fields) + + - Note dots added on the info page. + (You may have to update your info page settings by re-saving all prefs) + + - Changed the old Alt-C on the instrument list to Alt-W (wipe data) + New Alt-C removes the instrument name and filename, but does NOT + remove the instrument parameters (like the Alt-C on the sample list) + + - MIDI OUTPUT! + Fully configurable output + 16 parameterised macros + 128 constant macros + Check MIDI.TXT for details. (Big thanks to Ozone for writing this) + + - Soundcard Driver news + Inserted a new algorithm into the direct-to-disk writer to remove + clicks at the end of samples in cases of Note Cut commands, Note Cut NNA + and instantaneous sample changes in sample mode. For those who have + sent me money and would like to receive the upgrade, EMail me. + ESS ES1868 AudioDrive driver. This will NOT support any other ESS + chipsets than the ES1868. Do not write to me asking for support for + other ESS chips unless you are willing to buy me a card (or send me + the money to do so). This driver supports mixing rates up to 56.8kHz + (16 bit, stereo) and it also supports MIDI In. + AWE32 driver update: More accurate tempo control and less clicks under + Win95 + TB Tropez users: I received an EMail telling me that the GUSMAX drivers + were working fully with the TB Tropez cards! See how + it works... + Sound drivers for the ST97 and EWS64 coming... as soon as I get them + working.... + + Other news: It seems that some people really don't care how much work + I've put into IT - Warez versions of the full ITWAV.DRV + are being sought after. Let me make this clear: Distribution + of the full version of ITWAV.DRV is NOT appreciated and if I + ever find the full version anywhere, IT will no longer be + publically released. + + +IT211 Update - Not so much this time, as I have been working full time, so + since IT has been sitting on my HDD without changes for a + couple of weeks, I decided to release the update anyway. + + - Saving a song with Ctrl-S or from the menu will not prompt about + 'overwriting' the file. + + - Compatibility Gxx volume fadeout fixed. + + - Matrox autodetection fixed to set mouse cursor properly also. + + - You can press 'L' or 'R' on the "load stereo sample" prompt to select + left or right channels. + + - Increased file-header 'load-buffer' so that more Sound Forge .WAV files + should be recognised. + + - Bug fix to: swap samples/instruments, insert/remove sample/instrument + and update instrument *could* have caused the current + editing pattern to skip being modified. + + - Bug fix: Pressing delete on a non-note column in template mode should + work as expected. + + - Note: If you delete your old IT.CFG files and run IT afresh, you'll + get an extra 'line' on the infopage to work with. + + - .KRZ sample-library loader. Note that this does NOT support multiple + .KR* files (ie. .KR1, .KR2, .KR3). To use these files, you will have + to run MERGEKRZ.EXE (supplied) to create a single .KRZ file. + (BIG thanks to Markus Jonnson for the info!) + + - .PAT sample-library loader. + + - Creating a 'host instrument' after loading a sample will first attempt + to use an instrument of the same number as the sample before finding + the first empty instrument. + + - Holding down Caps Lock in the pattern editor will allow you to play + notes without entering them into the patterns. + + Driver modifications + - Bug fix for SB16 drivers which caused patterns not to 'play'. For those + that still have troubles with the SB16 driver, read DRIVERS.TXT + - For those of you who couldn't get the GUSMAX driver working, check out + DRIVERS.TXT also :) + - The ITWAV.DRV file now writes proper .WAV files instead of .RAW + - ITAWE32.DRV uses floating point calculations to reduce memory usage. + ITAWE32B.DRV (the old driver) still exists for people who don't have + math coprocessors + + +IT210 Update - some MAJOR fixes here. + + - Approximate song length on Ctrl-P. Note that *some* soundcards will + require reinitialisation after this (almost all won't). The time given + is the 'ideal' time for the playback of the song and should correspond + *exactly* to GUS/AWE non-IRQ playback times. + + - A few more player bug fixes for XM compatibility + + - IT won't crash if you try to load instruments from an 'empty' drive + (eg. disk not inserted or no files present) + + - In the pattern editor, Insert/Delete, Note Cut/Note Off/Note Delete + are all 'template aware' - they will span more than 1 channel if + you are editing in template mode and the template has height 1. + Also, 'picking up' data with Enter will turn off Template mode's except + for "Template-Notes Only" + + - Volume column effects Ex/Fx/Gx in combination with effect Jxx should + operate as expected now. + + - Deleting a file on the instrument list will update the instrument cache + file appropriately. + + - Sample/Instrument cache file time check fixed. + + - Slight modification to the handling of SBx commands to prevent + infinite loops. + + - Simple crash recovery mechanism should you ever encounter a problem. + (You shouldn't need it!) This is on Ctrl-Alt-Del in DOS or + Ctrl-Alt-Ins in Windows. It is not guaranteed to work, but if it works + once, then I guess that the amount of time I spent on it was worth it + (~10 minutes). + + For the technically minded lot, what it does is it tries to 'kick start' + the tracker again directly from the keyboard interrupt handler. + + - Loading a stereo WAV file will cause a pop-up menu to appear to select + loading the left or right channels. + + - GUSMAX users interested in using software mixing, check out DRIVERS.TXT + + - Memory corruption error found and fixed which produced 3-sets of invalid + values in the order list/instruments (main reason for this release!) + +IT209 Update + + ************************* FONT FILES REQUIRE UPDATING ********************* + If you have your own custom font file, you will need to change character + number 184 to 190. If you have used one of the 'standard' font sets, you + will need to run ITF and grab an updated file. Failure to do so will just + make the sample page look stuffed - You have been warned :) + *************************************************************************** + + Many Many MANY miscellaneous fixes to the XM loader and playback routines + -> XM support should be *MUCH* better now. + Volume effects have been debugged... hopefully :) + + Some major errors fixed around (ie. dumping to DOS from the Instrument + screen, Pattern's not updating in memory correctly (which went wrong in + IT208) ) + + Added default sample pan to the sample list (default instrument pan WILL + override this if present). Note that using default pan is the equivalent + of using a 'set pan' effect on that row - the channel will be set to the + default sample pan. + + You can change whether the info page displays sample names or instrument + names by pressing 'i' + +IT208 Update + + So much so quickly? Well, I had exams. And when I have exams, I code, 'cos + it's better than having to study :) + + ************************* FONT FILES REQUIRE UPDATING ********************* + If you have your own custom font file, you will need to change character + number 184 to. If you have used one of the 'standard' font sets, you will + need to run ITF and grab an updated file. Failure to do so will just make + the info page and 10-channel editor look stuffed - You have been warned :) + *************************************************************************** + + - Bug fix: Keyboard configuration files could have cause MAJOR problems... + fixed! + + - Bug fix: Some files with the .MOD ID "CH" which actually were NOT MODs + were being identified as "Fast Tracker 2" modules. + (You may have to delete your CACHE.ITS files to force IT to + refresh it's data) + + - Bug fixes: MIDI input won't corrupt input on the order list + MIDI input won't interfere with button presses + MIDI input won't insert effect SDF into patterns when recording + where inappropriate. + + - Old Left Ctrl+Shift-1 'removed', Left-Ctrl+Shift 1->4 still work - and + have been updated. + + PROPER 10-channel editing mode available (complete with half sized cursors!) + as well as some minor logic improvements. (Try Left-Ctrl+Shift 2) + + - ";" and "'" made to change the samples/instrument in the pattern editor + as '<' and '>' do - just much easier to do so on American keyboards. + + - Dragging mouse nodes past boundaries is more accurate. + + - "Channel details" display (on the infopage) *can* show the 64th channel + (oops in IT207) + + - Matrox bug autodetection (Many thanks to Csaba Pankaczy for working with + me on this!) + + - Message system hooked to a timer (ie. all those messages that appear + towards the top of the screen).. so that they will last a consistent + amount of time (independent of machine). + + - Player Improvement: NNA mechanism will eliminate channels on two extra + conditions now (no difference to playback, but should + maximise channel usage) + + - Improvement: Persistence of cache files through different sessions of IT + - ie. once the sample/instrument cache files are created, they + are NOT recreated unless necessary. + + - Root "\" directory has replaced "." directory on all loading screens. + + - Several Template input related functions improved. Also, Block-Cut in + template mode won't overwrite your clipboard if you're working with + templates. + + - Template: "Notes only" added. This is different from the other templates + in that it will NOT copy the template's instruments, volumes or effects. + Instead, it will change it's instrument/volume/effect according to the + last used instrument/volume/effect, and will insert whatever is speicfied + by the edit mask. + + - Addition: Volume Column effects, Ax, Bx, Cx, Dx, Ex, Fx, Gx and Hx!!!! + + Ax = Fine volume slide up by x + Bx = Fine volume slide down by x + Cx = Volume slide up by x + Dx = Volume slide down by x + Ex = Pitch slide down by x + Fx = Pitch slide up by x + Gx = Portamento to note with speed x + Hx = Vibrato with depth x + + Note that the pitch/portamento scale here is DIFFERENT from the standard + effect slideup/down + +* Note that if you use these in your songs, IT < 2.08 will NOT play them +* correctly... (in fact, it'll probably play it extremely painfully) + + - Alt Up/Down/Ins/Del added to the note translation table. + + - Minor modifications around the tracker + + - Windows Sound System Driver! (Operates at mixing rates up to 64kHz!) + Impulse Tracker has the greatest soundcard support of any tracker by far! + + - Old Effects will 'unlink' the memory of Gxx from Exx/Fxx + + - XM LOADING!!!!!!!!!! + + Don't write to me complaining about incompatibilities - I am aware of + lots of them and you probably won't get a reply. :) *MOST* songs should + have a near perfect conversion tho... + + - Big safety feature!! Playback dying because of overload? Bad NNA selection? + F8 *should* stop playback immediately now! (in DOS). + + In Windows '95, there may be a noticeable stall before playback stops + (ie. several seconds), or it may not function at all... + +IT207 update + + - Some bug fixes to MIDI input. + - Ctrl-PgUp/PgDn on the sample list will redraw the waveforms + - Jxx memory should work fine (The memory didn't operate if the channel + wasn't active before) + - Template limits should be correctly applied. (ie. clipped within + C-0 and B-9) + - Going to a pattern from the Info Page ('G') will also go to the + current order playing. + - MIDI input can be enabled/disabled in the pattern editor with + Alt-Scroll Lock + - MOD in-module sample library loop points fixed. + - Envelope drawing algorithm slightly more tolerant of corrupt information + - Mouse envelope routines slightly improved for more accurate handling of + nodes. + - Added Message editor to main menu. + - Added 10 channel view to the info page (you may need to reset your info- + page settings and "save your preferences") + - Squished up the info page view to get a couple of extra lines! :) + - Ctrl-F7 on the order list will set the next pattern to play (at request + of ChuckB) - for DJ use + - Due to Win95's unstable disk-EMS routines, if you load a MMTSRed sample, + instrument or module (sample library), playback *will* stop to prevent + corruption of samples currently in memory. + - Notes in templates of height 1 will be played back in the pattern editor + (very useful for "multi sample" note entry) + - Added effects T0x and T1x for Tempo slide down and tempo slide up. + - Added .IT and .XM *INSTRUMENT* library support. Note that .ITs that + aren't in instrument mode or have no instruments will NOT be shown on + the instrument loader list. + - Added Alt-Ins and Alt-Del on the sample and instrument lists to add + in samples/instruments + + **** NOTE: /Sx command line parameters have been changed around just for + neatness. CHECK SUMMARY.TXT FOR NEW /Sx VALUES OR RUN "IT /?" *** + +IT 2.06 + + - Update: Yet another update to the EMS routines.. for those of you who + couldn't be bothered to read the FAQ. + + Also new command line switch: + /Px - Set pattern memory allocation strategy. + Check SUMMARY.TXT for info on this. + + - Minor update: The 10-stage undo buffer will now use EMS memory under most + circumstances. + + - Minor update: S3M and IT loader routines slightly modified for more + efficient memory usage. + + - Minor update: "Song modified" flag logic slightly modified. + + - Minor update: .WAV loader slightly improved. (should read any 8 or 16-bit + format.) + + - Minor Addition: IT will now release time slices to multitasking OS/s + if you specify /T2 on the command line. + If you are using the MIDI input capabilities of IT, you + SHOULD NOT enable this (timing gets effected badly) + + - Minor Addition: Set pattern length command on Ctrl-F2 (can set multiple + patterns) + + - Minor Addition: Command line switch /T1 to disable "usage time" indication + + - Addition: TX Wave loader for .W?? samples (eg. from Kosmic's sample dirs) + Note: These are actually 12-bit samples, which are converted to + 16-bit at load time. + + - Addition: .MOD sample library loader. + + This "only" recognises the following MOD Identifications - + "M.K.", "M!K!", "FLT4", "FLT8", "4CHN", "6CHN", "8CHN" + And FT2's extended MOD identification, "xxCH" + + If you have an "Old Amiga-MOD format" MOD (which doesn't have an + ID), then you'll have to save it as another format if you want + to rip directly from it. + + So sample library support in total: + .MOD, .669, .FAR, .MTM, .S3M, .PTM, .XM, .IT + + - Addition: Intelligent MIDI Input for SB16 and Interwave cards! + MIDI options screen is on Shift-F1 (those of you who have IT.CFG + from older versions of IT *WILL* need to visit this screen at + least once if you want to use MIDI - "Save All Preferences" will + save these settings) + + In the pattern editor, Ctrl-Z is "Change MIDI playback trigger." + Normally, it is quite difficult to start at a row/pattern with + MIDI - this options allow you to control whether a pattern or + song should START playing when you play the first note. + + (IT will play either from the start of the current pattern or + the song starting from the current row depending on your choice) + Once this is done, the trigger is immediately unset, so you will + have to setup this trigger again if you want to use it. + + Note that this *will* turn on pattern tracing. To disable it, + use Scroll-Lock. + + ****** NOTE ****** + + SB16's MIDI input is somewhat 'iffy'. If you stop receiving + MIDI input, you need to reinit the soundcard (Ctrl-I) (possibly + several times). I don't know why it does this. Dont' write + to me about it, 'cos I have spent MANY MANY hours on this little + problem and I don't want to know about it. Also, in Win95, I + found it necessary to change my SB16's configuration to EXCLUDE + the MIDI port (and I used a Microsoft MPU401 driver instead), + otherwise MIDI input was ignored. + + Sorry, no GUS MIDI at the moment, as I couldn't get it working. + Please do NOT write to me about this, you will not get a reply. + An updated GUS driver will be released if/when I get it working. diff --git a/Tutorial/IT_TUTORIAL.EXE b/Tutorial/IT_TUTORIAL.EXE new file mode 100755 index 0000000000000000000000000000000000000000..5e4ade935891758b2319f529f687ddf70c8afc4f GIT binary patch literal 95898 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®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 literal 0 HcmV?d00001 diff --git a/Tutorial/TUTE.IT b/Tutorial/TUTE.IT new file mode 100755 index 0000000000000000000000000000000000000000..3670081c0ae0cb2d3ea38f3091314804b79ce0bd GIT binary patch literal 75997 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 gKBBK7UidaRm!@0()s0(^ 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
-SY?5gL}Gx0x_FYbSE92 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
Eb%{v^_u7L|;K+b|!*Ks`Sq4osQNqC; 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 +#include +#include +#include +#include + +/* +Registry keys: + BufferSize : in kb. maximum of 64 + BufferThreshold : in kb. maximum of 32 + BufferType : 0->2 for DualBuffer,QuadBuffer,OctBuffer + MixSpeed : in Hz, maximum of 48000. +*/ + +// Registry values. +static int BufferSize = 24; +static int BufferThreshold = 21; +static int BufferType = 2; +static int MixSpeed = 44100; + +// Registry Key stuff. +const char *RegistryKey = "Software\\Jeffrey Lim\\Impulse Tracker VSound Server"; +const char *RegistryKeyBufferSize = "BufferSize"; +const char *RegistryKeyBufferThreshold = "BufferThreshold"; +const char *RegistryKeyBufferType = "BufferType"; +const char *RegistryKeyMixSpeed = "MixSpeed"; + +// Other stuff. +const static LPCTSTR lpszAppName = "VSound Server"; +const static LPCTSTR lpszTitleBar = "Impulse Tracker VSound Server"; +static HRESULT hr; + +static void *BufferUpdateThreadHandle; +static int BufferUpdateThreadID; + +static int Quitting = 0; + +static HANDLE NotifyEventHandle; +static LPDIRECTSOUND lpDS; +static LPDIRECTSOUNDBUFFER lpPDSB, lpSDSB; +static PCMWAVEFORMAT pcmwf = +{ + { + WAVE_FORMAT_PCM, + 2, + 44100, + 4*44100, + 4 + }, + 16 +}; + +HINSTANCE g_hInst; +HWND g_hWnd; + +char TextBuffer[80]; + +static short int ServerPort = 0x401; +static short int DataPort = 0x402; + +static int SoundBufferSize; +static int SoundBufferBlockSize; +static int SoundBufferBlockMask; + +char *BufferTypes[] = +{ + "DualBuffer", + "QuadBuffer", + "OctBuffer" +}; + +const char *ServerID = "ITSERVER"; +const char *NoServer = + "Unable to find VSound.VxD\n" \ + "\n" \ + "Please read the documentation on how to setup VSound.VxD"; + +const char *ServerActive = + "VSound server is active.\n" \ + "\n" + "Please shut down Impulse Tracker first"; + +void __cdecl trace(char *Message, ...) +{ + va_list argptr; + + va_start(argptr, Message); + vsprintf(TextBuffer, Message, argptr); + + PostMessage(g_hWnd, WM_PAINT, 0, 0); +} + +static void VSound_Reset() +{ + _outp(ServerPort, 0); +} + +static void VSound_Identify() +{ + int i, j; + char ServerString[60]; + short int TempValues[2]; + char *BufferInfo = (char*) (&TempValues); + + sprintf(ServerString, "DirectSound VSoundServer 1.0, %dkb %s", BufferSize, BufferTypes[BufferType]); + + j = strlen(ServerString); + for(i = 0; i < 8; i++) _outp(ServerPort, ServerID[i]); + for(i = 0; i < j; i++) _outp(ServerPort, ServerString[i]); + for( ; i < 60; i++) _outp(ServerPort, ' '); + + TempValues[0] = BufferThreshold * 1024; + TempValues[1] = MixSpeed; + for(i = 0; i < 4; i++) _outp(ServerPort, BufferInfo[i] ^ 0xFF); +} + +static int VSound_Detect() +{ + int i; + char Buffer[8]; + + for(i = 0; i < 8; i++) Buffer[i] = _inp(ServerPort); + return memcmp(ServerID, Buffer, sizeof(Buffer)) == 0; +} + +static int VSound_Connected() +{ + if(!Quitting) return _inp(ServerPort); + else return 0; +} + +static void Error(char *Message) +{ + VSound_Reset(); + MessageBox(g_hWnd, Message, "VSound Server Error!", MB_OK); + exit(1); +} + +static void CheckHResult(char *Message) +{ + if(hr) Error(Message); +} + +DWORD WINAPI BufferUpdateThread(void *Parameter) +{ + int UpdatePosition = 0; + int PlayPosition; + int Len1, Len2; + void *Buf1, *Buf2; + int LastBlock; + int Active = 0; + +/* + hr = SetThreadPriority(BufferUpdateThreadHandle, THREAD_PRIORITY_TIME_CRITICAL); + if(!hr) + { + trace("Error code: %d", GetLastError()); + Error("SetThreadPriority failed"); + return; + } + + hr = SetPriorityClass((HANDLE) BufferUpdateThreadID, REALTIME_PRIORITY_CLASS); + if(!hr) { + trace("Error code: %d", GetLastError()); + Error("SetPriorityClass failed"); + return; + } +*/ + + while(1) + { + int CurrentBlock; + int NumberOfBlocks; + + WaitForMultipleObjects(1, // count of object handle array + &NotifyEventHandle, // Handle of event created to signal buffer position updates + FALSE, // return if at least one event is signalled + INFINITE); + + hr = lpSDSB->lpVtbl->GetCurrentPosition(lpSDSB, &PlayPosition, NULL); + CheckHResult("GetCurrentPosition failed"); + + CurrentBlock = PlayPosition / SoundBufferBlockSize; + NumberOfBlocks = (CurrentBlock - LastBlock) & SoundBufferBlockMask; + if(NumberOfBlocks == 0) continue; + + hr = lpSDSB->lpVtbl->Lock(lpSDSB, UpdatePosition, NumberOfBlocks*SoundBufferBlockSize, &Buf1, &Len1, &Buf2, &Len2, 0); + CheckHResult("Lock failed"); + + if(VSound_Connected() != Active) + { + Active = ~Active; + if(Active) + trace("Server active"); + else + trace("Server ready"); + } + +// Update buffer here. + __asm + { + Push EDI + Mov DX, [DataPort] + + Mov EDI, [Buf1] + Mov ECX, [Len1] + Rep InsB + + Mov EDI, [Buf2] + Mov ECX, [Len2] + Rep InsB + + Pop EDI + } + + hr = lpSDSB->lpVtbl->Unlock(lpSDSB, Buf1, Len1, Buf2, Len2); + CheckHResult("Unlock failed"); + + LastBlock = CurrentBlock; + UpdatePosition = LastBlock*SoundBufferBlockSize; + } + + return 0; +} + +void VSound_InitDSound() +{ + int i, NumberOfNotifications; + DSBUFFERDESC DSBDesc; + DSBPOSITIONNOTIFY DSBPositionNotify[8]; + LPDIRECTSOUNDNOTIFY lpDSNotify; + int Len1, Len2; + char *Buf1, *Buf2; + + NumberOfNotifications = 2 << BufferType; + SoundBufferSize = BufferSize*1024; + SoundBufferBlockSize = SoundBufferSize / NumberOfNotifications; + SoundBufferBlockMask = NumberOfNotifications - 1; + + trace("CreateEvemt"); + NotifyEventHandle = CreateEvent(NULL, // Security attributes + FALSE, // Manual reset = FALSE + FALSE, // Signal initial state = FALSE + NULL); // Name + if(!NotifyEventHandle) Error("CreateEvent failed"); + + trace("DirectSoundCreate"); + hr = DirectSoundCreate(NULL, &lpDS, NULL); + CheckHResult("DirectSoundCreate failed"); + + trace("SetCooperativeLevel"); + hr = lpDS->lpVtbl->SetCooperativeLevel(lpDS, GetActiveWindow(), DSSCL_PRIORITY); + CheckHResult("SetCooperativeLevel failed"); + + trace("CreateSoundBuffer (Primary)"); + memset(&DSBDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out. + DSBDesc.dwSize = sizeof(DSBUFFERDESC); + DSBDesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + DSBDesc.dwBufferBytes = 0; + DSBDesc.lpwfxFormat = NULL; + hr = lpDS->lpVtbl->CreateSoundBuffer(lpDS, &DSBDesc, &lpPDSB, NULL); + CheckHResult("CreateSoundBuffer (Primary) failed"); + + trace("SetFormat"); + pcmwf.wf.nSamplesPerSec = MixSpeed; + pcmwf.wf.nAvgBytesPerSec = MixSpeed * 4; + hr = lpPDSB->lpVtbl->SetFormat(lpPDSB, (void*) &pcmwf); + CheckHResult("SetFormat failed"); + + memset(&DSBDesc, 0, sizeof(DSBUFFERDESC)); // Zero it out. + DSBDesc.dwSize = sizeof(DSBUFFERDESC); + DSBDesc.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | + DSBCAPS_GETCURRENTPOSITION2 | + DSBCAPS_STICKYFOCUS | + DSBCAPS_LOCSOFTWARE; + DSBDesc.dwBufferBytes = SoundBufferSize; + DSBDesc.lpwfxFormat = (void*) &pcmwf; + trace("CreateSoundBuffer (Secondary)"); + hr = lpDS->lpVtbl->CreateSoundBuffer(lpDS, &DSBDesc, &lpSDSB, NULL); + CheckHResult("CreateSoundBuffer (Secondary) failed"); + + trace("QueryInterface"); + hr = lpSDSB->lpVtbl->QueryInterface(lpSDSB, &IID_IDirectSoundNotify, &lpDSNotify); + CheckHResult("Error obtaining DirectSoundNotify interface"); + + trace("SetNotificationPositions"); + for(i = 0; i < NumberOfNotifications; i++) + { + DSBPositionNotify[i].dwOffset = i*SoundBufferBlockSize; + DSBPositionNotify[i].hEventNotify = NotifyEventHandle; + } + hr = lpDSNotify->lpVtbl->SetNotificationPositions(lpDSNotify, NumberOfNotifications, DSBPositionNotify); + CheckHResult("SetNotificationPositions failed"); + + trace("Lock (Clear)"); + hr = lpSDSB->lpVtbl->Lock(lpSDSB, 0, 0, &Buf1, &Len1, &Buf2, &Len2, DSBLOCK_ENTIREBUFFER); + CheckHResult("Lock failed"); + + trace("Clearing buffer"); + memset(Buf1, 0, Len1); + + trace("Unlock (Clear)"); + hr = lpSDSB->lpVtbl->Unlock(lpSDSB, Buf1, Len1, Buf2, Len2); + CheckHResult("Unlocked failed"); + + trace("Creating sound thread"); + BufferUpdateThreadHandle = CreateThread(NULL, // Security atributes + 0, // Stack size + BufferUpdateThread, // Pointer to thread starting function + 0, // Parameter to new thread + 0, // Creation flags + &BufferUpdateThreadID); + + hr = SetThreadPriority(BufferUpdateThreadHandle, THREAD_PRIORITY_TIME_CRITICAL); + if(!hr) Error("SetThreadPriority failed"); + +// Set process to realtime priority. +/* + hr = SetPriorityClass((DWORD) _getpid(), REALTIME_PRIORITY_CLASS); + if(!hr) Error("SetPriorityClass failed"); +*/ + trace("Play"); + hr = lpSDSB->lpVtbl->Play(lpSDSB, 0, 0, DSBPLAY_LOOPING); + CheckHResult("Play failed"); + + VSound_Identify(); + trace("Server ready"); +} + +LRESULT CALLBACK WndProc(HWND hWnd, UINT Message, WPARAM wParam, LPARAM lParam) +{ + switch(Message) + { + case WM_PAINT: + { + HDC hDC; + PAINTSTRUCT Paint; + RECT Rectangle; + + GetClientRect(hWnd, &Rectangle); + InvalidateRect(hWnd, &Rectangle, TRUE); + + hDC = BeginPaint(hWnd, &Paint); + + SetBkMode(hDC, TRANSPARENT); + + Rectangle.left += 5; + Rectangle.right -= 5; + + DrawText(hDC, TextBuffer, strlen(TextBuffer), &Rectangle, DT_VCENTER | DT_SINGLELINE | DT_LEFT); + EndPaint(hWnd, &Paint); + return 0; + } + break; + + case WM_DESTROY: + case WM_CLOSE: + if(VSound_Connected()) + { + MessageBox(hWnd, ServerActive, "Error!", MB_OK); + return 0; + } + VSound_Reset(); + Quitting = 1; + PostQuitMessage(0); + } + + return DefWindowProc(hWnd, Message, wParam, lParam); +} + +int GetRegistryInteger(const char *KeyName, int Default) +{ + HKEY hkey; + int ReturnValue; + int Size = 4; + + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, + RegistryKey, + 0, + (LPTSTR) lpszAppName, + 0, + KEY_ALL_ACCESS, + NULL, + &hkey, + NULL + ) == ERROR_SUCCESS) + { + if((hr = RegQueryValueEx(hkey, KeyName, 0, 0, (LPBYTE) &ReturnValue, &Size)) == ERROR_SUCCESS) + { + RegCloseKey(hkey); + return ReturnValue; + } + + RegSetValueEx(hkey, KeyName, 0, REG_DWORD, (LPBYTE) &Default, sizeof(Default)); + RegCloseKey(hkey); + return Default; + } + Error("Unable to access Windows registry"); +} + +void SetRegistryInteger(const char *KeyName, int Value) +{ + HKEY hkey; + + if(RegCreateKeyEx(HKEY_LOCAL_MACHINE, + RegistryKey, + 0, + (LPTSTR) lpszAppName, + 0, + KEY_ALL_ACCESS, + NULL, + &hkey, + NULL + ) == ERROR_SUCCESS) + { + RegSetValueEx(hkey, KeyName, 0, REG_DWORD, (LPBYTE) &Value, sizeof(Value)); + RegCloseKey(hkey); + } + +} + +void GetRegistry() +{ + BufferSize = GetRegistryInteger(RegistryKeyBufferSize, 24); + if(BufferSize < 4 || BufferSize > 64) + { + BufferSize = 24; + SetRegistryInteger(RegistryKeyBufferSize, BufferSize); + } + + BufferThreshold = GetRegistryInteger(RegistryKeyBufferThreshold, 21); + if(BufferThreshold < 2 || BufferThreshold > 32) + { + BufferThreshold = BufferSize >> 1; + SetRegistryInteger(RegistryKeyBufferThreshold, BufferThreshold); + } + + BufferType = GetRegistryInteger(RegistryKeyBufferType, 2); + if(BufferType < 0 || BufferType > 2) + { + BufferType = 2; + SetRegistryInteger(RegistryKeyBufferType, BufferType); + } + + MixSpeed = GetRegistryInteger(RegistryKeyMixSpeed, 44100); + if(MixSpeed < 11025) MixSpeed = 11025; + if(MixSpeed > 64000) MixSpeed = 64000; + SetRegistryInteger(RegistryKeyMixSpeed, MixSpeed); +} + +int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) +{ + MSG msg; + WNDCLASSEX wc; + + g_hInst = hInstance; + + // Window Class parameters. + wc.style = CS_HREDRAW | CS_VREDRAW; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = NULL; + wc.hCursor = LoadCursor(NULL, IDC_ARROW);; + wc.hbrBackground= (HBRUSH) (COLOR_WINDOW); + wc.lpszMenuName = lpszAppName; + wc.lpszClassName= lpszAppName; + wc.cbSize = sizeof(WNDCLASSEX); + wc.hIconSm = NULL; + + if(RegisterClassEx(&wc)) + { + // Create window. + g_hWnd = CreateWindow( + lpszAppName, + lpszTitleBar, + WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE, + CW_USEDEFAULT, + CW_USEDEFAULT, + 280, + 50, + NULL, + NULL, + hInstance, + NULL + ); + if(g_hWnd) + { + // Lets first see if the VSound server exists. + + if(!VSound_Detect()) + { + trace("Connect to VSound.VxD failed"); + MessageBox(NULL, NoServer, "Error!", MB_OK); + exit(1); + } + + GetRegistry(); + VSound_InitDSound(); + + while( GetMessage(&msg, NULL, 0, 0)) + { + TranslateMessage(&msg); + DispatchMessage(&msg); + } + return (msg.wParam); + } + } + return 1; +} diff --git a/VSound/VXD/DEBUG.INC b/VSound/VXD/DEBUG.INC new file mode 100755 index 0000000..b6fdb06 --- /dev/null +++ b/VSound/VXD/DEBUG.INC @@ -0,0 +1,1156 @@ +;**************************************************************************** +; * +; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +; PURPOSE. * +; * +; Copyright (C) 1993-95 Microsoft Corporation. All Rights Reserved. * +; * +;**************************************************************************** + +NOBUGBUG EQU 1 + + + + + + + + + + +BUGBUG macro d, id, note +endm + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +IsDebugOnlyLoaded macro lab + local var, magic +_DBOSTART segment +var label byte +_DBOSTART ends + db 0F7h, 05h + dd OFFSET32 magic +magic dd OFFSET32 var - (MAXSYSTEMLADDR + 1) +ifnb + jz lab +endif + endm + + + + + + + + + + +DPublic MACRO arg +if DEBLEVEL GT DEBLEVELRETAIL + public arg +endif + ENDM + + + + + + + + + + + + + + + +Assumes_Fall_Through MACRO L +ifndef MASM6 +IF2 + IFDEF profileall + IF (?prolog_&L - $) GT 3 + %OUT ERROR: Fall through to &L invalid + .ERR + ENDIF + ELSE + IF (L - $) GT 3 + %OUT ERROR: Fall through to &L invalid + .ERR + ENDIF + ENDIF +ENDIF +else + IFDEF profileall +.errnz ((?prolog_&L - $) GT 3), + ELSE +.errnz ((L - $) GT 3), + ENDIF +endif + + ENDM + + +ifndef Not_VxD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +??avh_parse_one_arg macro arg + ifidni , + ??_fUsesFlagsPushfd equ <> + ??_fUsesFlagsPopfd equ <> + elseifnb + ??_debLevel = arg + endif +endm + +??avh_parse_args macro DL, fUSES_FLAGS + ??_fUsesFlagsPushfd equ + ??_fUsesFlagsPopfd equ + ??_debLevel = DEBLEVELNORMAL + ??avh_parse_one_arg
+ ??avh_parse_one_arg +endm + +Assert_VM_Handle MACRO R, DL, fUSES_FLAGS + LOCAL l1 + +IF DEBLEVEL GT DEBLEVELRETAIL + + ??avh_parse_args
, + +IF DEBLEVEL GE ??_debLevel + +IFNDEF WIN31COMPAT +IF DEBLEVEL LT DEBLEVELMAX + ??_fUsesFlagsPushfd + cmp [R].CB_Signature, VMCB_ID + je SHORT l1 +ENDIF +ENDIF + +IFDIFI , + push ebx + mov ebx, R +ENDIF + VMMCall Debug_Test_Valid_Handle +IFDIFI , + pop ebx +ENDIF + +IFNDEF WIN31COMPAT +IF DEBLEVEL LT DEBLEVELMAX +l1: + ??_fUsesFlagsPopfd +ENDIF +ENDIF + +ENDIF + +ENDIF + ENDM + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Assert_Thread_Handle MACRO R, DL, fUSES_FLAGS + LOCAL l1 + +IF DEBLEVEL GT DEBLEVELRETAIL + + ??avh_parse_args
, + +IF DEBLEVEL GE ??_debLevel + +IF DEBLEVEL LT DEBLEVELMAX + ??_fUsesFlagsPushfd + cmp dword ptr [R.TCB_Signature], SCHED_OBJ_ID_THREAD + je SHORT l1 +ENDIF + +IFDIFI , + push edi + mov edi, R +ENDIF + VMMCall Debug_Test_Valid_Thread_Handle +IFDIFI , + pop edi +ENDIF + +IF DEBLEVEL LT DEBLEVELMAX +l1: + ??_fUsesFlagsPopfd +ENDIF + +ENDIF + +ENDIF + ENDM + + + + + + + + + + + + + + + + + +Assert_Cur_Thread_Handle MACRO R, DL + LOCAL myDebLevel + LOCAL OK + +IF DEBLEVEL GT DEBLEVELRETAIL + +IFB
+ myDebLevel EQU DEBLEVELNORMAL +ELSE + myDebLevel EQU
+ENDIF + +IF DEBLEVEL GE myDebLevel + +IFDIFI , + push edi + mov edi, R +ENDIF + VMMCall Debug_Test_Cur_Thread +IFDIFI , + pop edi +ENDIF + +ENDIF + +ENDIF + ENDM + + + + + + + + + + + + + +Debug_Printf macro fmt, args, dl + local fmtlab, myDebLevel + +ife ?_DBOCODE + ??_fDoit = VMM_TRUE +else + ??_fDoit = FALSE +endif + +if DEBLEVEL GT DEBLEVELRETAIL + +ifb
+ myDebLevel EQU +else + myDebLevel EQU
+endif + +if DEBLEVEL GE myDebLevel + ??_fDoit = VMM_TRUE +endif + +endif + +if ??_fDoit + +ife ?_DBOCODE + +VxD_DEBUG_ONLY_DATA_SEG +fmtlab db fmt, 0 +VxD_DEBUG_ONLY_DATA_ENDS + +else + +ifdef VMMSYS + +VMM_LOCKED_DATA_SEG +fmtlab db fmt, 0 +VMM_LOCKED_DATA_ENDS + +else + +VxD_LOCKED_DATA_SEG +fmtlab db fmt, 0 +VxD_LOCKED_DATA_ENDS + +endif + +endif + + ifb + VMMCall _Debug_Printf_Service, <(OFFSET32 fmtlab), esp> + else + VMMCall _Debug_Printf_Service, <(OFFSET32 fmtlab), esp, args> + endif + +endif + + endm + + + + + + + +CHECK_EOL MACRO f, x, ln + ifdifi , + ifdifi , + ifdifi , + ifdifi , + %OUT Line ln: Unknown symbol (x) in f, taken as NOEOL + endif + endif + endif + endif + +ENDM + +??_Gen_String macro lbl:req, str:req + ife ?_ICODE + ??_segName textequ <_IDATA> + elseife ?_PCODE + ??_segName textequ <_PDATA> + elseife ?_SCODE + ??_segName textequ <_SDATA> + elseife ?_DBOCODE + ??_segName textequ <_DBODATA> + else + ??_segName textequ <_LDATA> + endif + + ??_segName segment + lbl db str + ife ??_nocrlf + db 0dh,0ah + endif + db 0 + ??_segName ends +endm + + +??Trace_Debug_Helper macro typ, str, arg1, arg2 + local string + + ife ?_DBOCODE + ??_fDoit = VMM_TRUE + else + ??_fDoit = 0 + endif + + if (DEBLEVEL GT DEBLEVELRETAIL) OR ??_fDoit + + ??_nocrlf = 0 + ??_debLevel = DEBLEVELNORMAL + + irp x, + ifnb + if ((.TYPE x) AND 20h) GT 0 + ??_debLevel = x + else + Check_EOL , , %(@Line) + ??_nocrlf = 1 + endif + endif + endm + + if DEBLEVEL GE ??_debLevel + ??_fDoit = VMM_TRUE + endif + + endif + + if ??_fDoit + + irpc c, str + ifidn , <"> + ??_is_string = 1 + else + ifidni , <'> + ??_is_string = 1 + else + ??_is_string = 0 + endif + endif + exitm + endm + + if ??_is_string + ??_Gen_String string, + ??_debug_out_str textequ + else + ??_debug_out_str textequ + endif + + ifdef WIN31COMPAT + pushfd + pushad + mov esi, ??_debug_out_str + VMMCall Out_Debug_String + ifidni , + VMMCall Test_Debug_Installed + jz SHORT $+4 + int 1 + endif + popad + popfd + else + push ??_debug_out_str + ifidni , + VMMCall _Debug_Out_Service + else + VMMCall _Trace_Out_Service + endif + endif + + endif + + endm + + + + + + + + + + + + + + + + +irp cond, + +Trace_Out&cond macro str, arg1, arg2 + ?trace_out ,jn&cond, , + endm + +Trace_OutN&cond macro str, arg1, arg2 + ?trace_out ,j&cond, , + endm + +endm + +Trace_Out MACRO str, arg1, arg2 + ??Trace_Debug_Helper , , , +endm + +Trace_OutECXZ macro str, arg1, arg2 + local l1,l2 +if (DEBLEVEL GT DEBLEVELRETAIL) or (?_DBOCODE eq 0) + jecxz l1 + jmp short l2 +l1: Trace_Out , , +l2: +endif + endm + +Trace_OutECXNZ macro str, arg1, arg2 + ?trace_out ,jecxz, , + endm + +Trace_OutEAXz macro str, arg1, arg2 + local l1 +if (DEBLEVEL GT DEBLEVELRETAIL) or (?_DBOCODE eq 0) + or eax,eax + jnz short l1 + Trace_Out , , +l1: +endif + endm + +Trace_OutEAXnz macro str, arg1, arg2 + local l1 +if (DEBLEVEL GT DEBLEVELRETAIL) or (?_DBOCODE eq 0) + or eax,eax + jz short l1 + Trace_Out , , +l1: +endif + endm + +?trace_out macro str, jmpop, arg1, arg2 + Local nomsg +if (DEBLEVEL GT DEBLEVELRETAIL) or (?_DBOCODE eq 0) + jmpop short nomsg + Trace_Out ,, +nomsg: +endif + endm + + + + + + + + + + + + + + + + + + +irp cond, + +Debug_Out&cond ¯o str, arg1 + ?debug_out ,jn&cond, + &endm + +Debug_OutN&cond ¯o str, arg1 + ?debug_out ,j&cond, + &endm + +endm + +Debug_Out MACRO str, arg1, arg2 + ??Trace_Debug_Helper , , , +endm + +Debug_OutECXZ macro str, arg1 + local l1,l2 +if DEBLEVEL GT DEBLEVELRETAIL + jecxz l1 + jmp short l2 +l1: Debug_Out , +l2: +endif + endm + +Debug_OutECXNZ macro str, arg1 + ?debug_out ,jecxz, + endm + +Debug_OutEAXz macro str, arg1 + local l1 +if DEBLEVEL GT DEBLEVELRETAIL + or eax,eax + jnz short l1 + Debug_Out , +l1: +endif + endm + +Debug_OutEAXnz macro str, arg1 + local l1 +if DEBLEVEL GT DEBLEVELRETAIL + or eax,eax + jz short l1 + Debug_Out , +l1: +endif + endm + +?debug_out macro str,jmpop, arg1 + Local nomsg +if DEBLEVEL GT DEBLEVELRETAIL + jmpop short nomsg + Debug_Out , +nomsg: +endif + endm + + + + + + + + +Queue_Out MACRO S, V1, V2, DL + LOCAL Str_Off + LOCAL MyDebLevel + +IF DEBLEVEL GT DEBLEVELRETAIL + +IFB
+ myDebLevel = DEBLEVELNORMAL +ELSE + myDebLevel = DL +ENDIF + +IF DEBLEVEL GE myDebLevel + +_LDATA SEGMENT +Str_Off db S, 0dh,0ah, 0 +_LDATA ENDS + + push esi +IFNB + IF TYPE V1 GT 0 + push dword ptr V1 + ELSE + push V1 + ENDIF +ELSE + push eax +ENDIF +IFNB + IF TYPE V2 GT 0 + push dword ptr V2 + ELSE + push V2 + ENDIF +ELSE + push ebx +ENDIF + mov esi, OFFSET32 Str_Off + VMMCall Queue_Debug_String + pop esi +ENDIF + +ENDIF + ENDM + + + + + + + + +Mono_Out MACRO S, nocrlf + LOCAL Str_Off +IF DEBLEVEL GT DEBLEVELRETAIL +_LDATA SEGMENT +Str_Off db S +IFB + db 0dh,0ah +ENDIF + db 0 +_LDATA ENDS + + pushfd + pushad + mov esi, OFFSET32 Str_Off + VMMCall Out_Mono_String + popad + popfd +ENDIF + ENDM + + + + + + + + +Mono_Out_At MACRO Row, Col, S, nocrlf + LOCAL Str_Off +IF DEBLEVEL GT DEBLEVELRETAIL +_LDATA SEGMENT +Str_Off db S +IFB + db 0dh,0ah +ENDIF + db 0 +_LDATA ENDS + + pushfd + pushad + mov dx, (Row SHL 8)+Col + VMMCall Set_Mono_Cur_Pos + mov esi, OFFSET32 Str_Off + VMMCall Out_Mono_String + popad + popfd +ENDIF + ENDM + + + + + + + + + + +Assert_Ints_Disabled MACRO DL + +IFB
+ ??_debLevel = DEBLEVELNORMAL +ELSE + ??_debLevel = DL +ENDIF + +IF DEBLEVEL GE ??_debLevel + +ifndef ??_aidMessage + _LDATA segment + ??_aidMessage db "ERROR: Ints enabled at Assert_Ints_Disabled" + db 0Dh, 0Ah, 0 + _LDATA ends +endif + pushfd + test byte ptr [esp+1], IF_Mask SHR 8 + .if !ZERO? + push OFFSET32 ??_aidMessage + VMMCall _Debug_Out_Service + .endif + popfd +ENDIF + ENDM + + + + + + + + +Assert_Ints_Enabled MACRO DL + +IFB
+ ??_debLevel = DEBLEVELNORMAL +ELSE + ??_debLevel = DL +ENDIF + +IF DEBLEVEL GE ??_debLevel + +ifndef ??_aieMessage + _LDATA segment + ??_aieMessage db "ERROR: Ints disabled at Assert_Ints_Enabled" + db 0Dh, 0Ah, 0 + _LDATA ends +endif + pushfd + test byte ptr [esp+1], IF_Mask SHR 8 + .if ZERO? + push OFFSET32 ??_aieMessage + VMMCall _Debug_Out_Service + .endif + popfd +ENDIF + ENDM + + + + + + + + + + + + + + + + + +Assert_Cur_VM_Handle MACRO R, DL + LOCAL OK + LOCAL myDebLevel + +IF DEBLEVEL GT DEBLEVELRETAIL + +IFB
+ myDebLevel = DEBLEVELNORMAL +ELSE + myDebLevel = DL +ENDIF + +IF DEBLEVEL GE myDebLevel + +IFDIFI , + push ebx + mov ebx, R +ENDIF + VMMCall Debug_Test_Cur_VM +IFDIFI , + pop ebx +ENDIF + +ENDIF + +ENDIF + ENDM + + +Assert_Client_Ptr MACRO Reg, DL + LOCAL myDebLevel +IF DEBLEVEL GT DEBLEVELRETAIL + +IFB
+ myDebLevel = DEBLEVELNORMAL +ELSE + myDebLevel = DL +ENDIF + +IF DEBLEVEL GE myDebLevel +IFDIFI , + push ebp + mov ebp, Reg +ENDIF + VMMCall Validate_Client_Ptr +IFDIFI , + pop ebp +ENDIF +ENDIF + +ENDIF + ENDM + +endif + + + + + + + + + + + + + + + + + + + + + + + +irp cond, + +TRAP&cond ¯o + ?trap jn&cond + &endm + +TRAPn&cond ¯o + ?trap j&cond + &endm + +TRAPFATAL&cond ¯o + ?trap jn&cond, FATAL + &endm + +TRAPFATALn&cond ¯o + ?trap j&cond, FATAL + &endm +endm + +TRAP macro +if DEBLEVEL GT DEBLEVELRETAIL + int 3 +endif + endm + +TRAPFATAL macro + local l +if DEBLEVEL GT DEBLEVELRETAIL +l: int 3 + jmp short l +endif + endm + +TRAPecxz macro + local l1,l2 +if DEBLEVEL GT DEBLEVELRETAIL + jecxz l1 + jmp short l2 +l1: int 3 +l2: +endif + endm + +TRAPecxnz macro + ?trap jecxz + endm + +?trap macro jmpop, fatal + Local l, n +if DEBLEVEL GT DEBLEVELRETAIL + jmpop short n +l: int 3 +ifnb + jmp short l +endif +n: +endif + endm + +ifndef Not_VxD + + + + +Dump_Struc_Head MACRO +if DEBLEVEL GT DEBLEVELRETAIL + Trace_Out " Base Address Offs Value Field name" +ENDIF + ENDM + +Dump_Struc MACRO Base, X +if DEBLEVEL GT DEBLEVELRETAIL + pushfd + pushad + lea esi, [Base] + mov ecx, X + lea edx, [esi+ecx] + +IF SIZE X EQ 6 + mov bx, WORD PTR [edx+4] + mov eax, DWORD PTR [edx] + Trace_Out "#ESI #EDX #CX #BX:#EAX &X" +ELSE +IF SIZE X EQ 4 + mov eax, DWORD PTR [edx] + Trace_Out "#ESI #EDX #CX #EAX &X" +ELSE +IF SIZE X EQ 2 + mov ax, WORD PTR [edx] + Trace_Out "#ESI #EDX #CX #AX &X" +ELSE + mov al, BYTE PTR [edx] + Trace_Out "#ESI #EDX #CX #AL &X" +ENDIF +ENDIF +ENDIF + + popad + popfd +ENDIF + ENDM + +BeginDoc + + + + + + + + + + + + + + + + + + + + + + + + + + + +EndDoc + +Begin_Touch_1st_Meg MACRO DL + LOCAL myDebLevel +IF DEBLEVEL GT DEBLEVELRETAIL +IFB
+ myDebLevel = DEBLEVELMAX +ELSE + myDebLevel = DL +ENDIF +IF DEBLEVEL GE myDebLevel + VMMCall Enable_Touch_1st_Meg +ENDIF +ENDIF + ENDM + + + +End_Touch_1st_Meg MACRO DL + LOCAL myDebLevel +IF DEBLEVEL GT DEBLEVELRETAIL +IFB
+ myDebLevel = DEBLEVELMAX +ELSE + myDebLevel = DL +ENDIF +IF DEBLEVEL GE myDebLevel + VMMCall Disable_Touch_1st_Meg +ENDIF +ENDIF + ENDM + +endif + +IFDEF DEBUG +TrashThis Macro l:vararg + ?TrashThisVal equ <0FFFFFF80h> + ?TrashThisValSet = 0 + for r, + or r, ?TrashThisVal + ife ?TrashThisValSet + if (OPATTR r) and 10h + ?TrashThisVal equ + ?TrashThisValSet = 1 + endif + endif + endm +endm +ELSE +TrashThis Macro l:vararg +endm +ENDIF + + +ifndef Not_VxD + +if DEBLEVEL GT DEBLEVELRETAIL + +ENTER_NOBLOCK MACRO + push DFS_ENTER_NOBLOCK + VMMCall _Debug_Flags_Service + ENDM + +EXIT_NOBLOCK MACRO + push DFS_EXIT_NOBLOCK + VMMCall _Debug_Flags_Service + ENDM + +Assert_CLD MACRO + pushfd + test dword ptr [esp], DF_MASK + Debug_OutNZ "Direction flag is not clear." + popfd + ENDM + +Assert_Might_Block MACRO + push DFS_TEST_BLOCK + VMMCall _Debug_Flags_Service + ENDM + +Assert_Not_Nest_Exec MACRO + push DFS_TEST_NEST_EXEC + VMMCall _Debug_Flags_Service + ENDM + +ELSE + +ENTER_NOBLOCK EQU <> +EXIT_NOBLOCK EQU <> +Assert_CLD EQU <> +Assert_Might_Block EQU <> +Assert_Not_Nest_Exec EQU <> + +ENDIF + + +ifdef Begin_Service_Table +Begin_Service_Table DEBUG +DEBUG_Service DEBUG_Get_Version, LOCAL +DEBUG_Service DEBUG_Fault, LOCAL +DEBUG_Service DEBUG_CheckFault, LOCAL +DEBUG_Service _DEBUG_LoadSyms +End_Service_Table DEBUG +endif +endif diff --git a/VSound/VXD/MVSOUND.BAT b/VSound/VXD/MVSOUND.BAT new file mode 100755 index 0000000..b41eb84 --- /dev/null +++ b/VSound/VXD/MVSOUND.BAT @@ -0,0 +1,3 @@ +ml -Fl -DBLD_COFF -DIS_32 -W2 -c -Cx -Zm -DMASM6 vsound.asm +link /VXD /NOD /OUT:VSOUND.VxD /MAP:VSOUND.MAP /DEF:VSOUND.DEF vsound +copy vsound.vxd \windows\system\itvsound.vxd diff --git a/VSound/VXD/SHELL.INC b/VSound/VXD/SHELL.INC new file mode 100755 index 0000000..7083661 --- /dev/null +++ b/VSound/VXD/SHELL.INC @@ -0,0 +1,139 @@ +;**************************************************************************** +; * +; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +; PURPOSE. * +; * +; Copyright (C) 1993-95 Microsoft Corporation. All Rights Reserved. * +; * +;**************************************************************************** + +ifndef _SHELL_H +_SHELL_H EQU 1 +ifndef Not_VxD +Begin_Service_Table SHELL +SHELL_Service SHELL_Get_Version, LOCAL +SHELL_Service SHELL_Resolve_Contention, LOCAL +SHELL_Service SHELL_Event, LOCAL +SHELL_Service SHELL_SYSMODAL_Message, LOCAL +SHELL_Service SHELL_Message, LOCAL +ifndef WIN30COMPAT +SHELL_Service SHELL_GetVMInfo, LOCAL +endif +ifndef WIN31COMPAT +SHELL_Service _SHELL_PostMessage, LOCAL +SHELL_Service _SHELL_ShellExecute +SHELL_Service _SHELL_PostShellMessage +SHELL_Service SHELL_DispatchRing0AppyEvents, LOCAL +SHELL_Service SHELL_Hook_Properties, LOCAL +SHELL_Service SHELL_Unhook_Properties, LOCAL +SHELL_Service SHELL_Update_User_Activity, LOCAL +SHELL_Service _SHELL_QueryAppyTimeAvailable, LOCAL +SHELL_Service _SHELL_CallAtAppyTime, LOCAL +SHELL_Service _SHELL_CancelAppyTimeEvent +SHELL_Service _SHELL_BroadcastSystemMessage, LOCAL +SHELL_Service _SHELL_HookSystemBroadcast, LOCAL +SHELL_Service _SHELL_UnhookSystemBroadcast, LOCAL +SHELL_Service _SHELL_LocalAllocEx, LOCAL +SHELL_Service _SHELL_LocalFree, LOCAL +SHELL_Service _SHELL_LoadLibrary, LOCAL +SHELL_Service _SHELL_FreeLibrary, LOCAL +SHELL_Service _SHELL_GetProcAddress, LOCAL +SHELL_Service _SHELL_CallDll, LOCAL +SHELL_Service _SHELL_SuggestSingleMSDOSMode +SHELL_Service SHELL_CheckHotkeyAllowed +SHELL_Service _SHELL_GetDOSAppInfo +endif +End_Service_Table SHELL +ifndef WIN31COMPAT +SBH_CALL_ORDER_DEFAULT EQU 0 +SBH_CALL_ORDER_REGISTRY EQU 30000000H +SBH_CALL_ORDER_CONFIGMG EQU 40000000H +endif +MB_OK EQU 00H +MB_OKCANCEL EQU 01H +MB_ABORTRETRYIGNORE EQU 02H +MB_YESNOCANCEL EQU 03H +MB_YESNO EQU 04H +MB_RETRYCANCEL EQU 05H +MB_ICONHAND EQU 10H +MB_ICONEXCLAMATION EQU 30H +MB_ICONASTERISK EQU 40H +MB_DEFBUTTON1 EQU 00H +MB_DEFBUTTON2 EQU 100H +MB_DEFBUTTON3 EQU 200H +MB_APPLMODAL EQU 00H +MB_SYSTEMMODAL EQU 1000H +MB_NOFOCUS EQU 8000H +MB_ASAP EQU 80000000H +MB_NOWINDOW EQU 40000000H +MB_HANGSYS EQU 20000000H +ifndef WIN31COMPAT +MB_APPYTIME EQU 10000000H +endif +IDOK EQU 1 +IDCANCEL EQU 2 +IDABORT EQU 3 +IDRETRY EQU 4 +IDIGNORE EQU 5 +IDYES EQU 6 +IDNO EQU 7 +SE_WP_PrtScBoost EQU 00100000H +SE_WP_PrtScBoostBit EQU 20 +SE_WP_DispUpdBoost EQU 00200000H +SE_WP_DispUpdBoostBit EQU 21 +ifndef WIN31COMPAT +SPM_UM_DoNotWaitForCrit EQU 00020000H +SPM_UM_DoNotWaitForCritBit EQU 17 +SPM_UM_AlwaysSchedule EQU 00080000H +SPM_UM_AlwaysScheduleBit EQU 19 +endif +SGVMI_Windowed EQU 00000004H +SGVMI_ALTTABdis EQU 00000020H +SGVMI_ALTESCdis EQU 00000040H +SGVMI_ALTSPACEdis EQU 00000080H +SGVMI_ALTENTERdis EQU 00000100H +SGVMI_ALTPRTSCdis EQU 00000200H +SGVMI_PRTSCdis EQU 00000400H +SGVMI_CTRLESCdis EQU 00000800H +SGVMI_HasHotKey EQU 00004000H +SGVMI_Polling EQU 00001000H +SGVMI_FastPaste EQU 00020000H +SGVMI_NoHMA EQU 00002000H +SGVMI_XMS_Lock EQU 00010000H +SGVMI_EMS_Lock EQU 00008000H +SGVMI_V86_Lock EQU 00040000H +SGVMI_ClsExit EQU 40000000H +endif +ifndef WIN31COMPAT +ifndef Not_VxD +LMEM_FIXED EQU 0000H +LMEM_ZEROINIT EQU 0040H +LPTR EQU (LMEM_FIXED OR LMEM_ZEROINIT) +LMEM_STRING EQU 00010000H +LMEM_OEM2ANSI EQU 00020000H +QAAFL_APPYAVAIL EQU 00000001H +QAAFL_APPYNOW EQU 00000002H +CAAFL_RING0 EQU 00000001H +CAAFL_TIMEOUT EQU 00000002H +endif + +SHEXPACKET STRUC +shex_dwTotalSize DD ? +shex_dwSize DD ? +shex_ibOp DD ? +shex_ibFile DD ? +shex_ibParams DD ? +shex_ibDir DD ? +shex_dwReserved DD ? +shex_nCmdShow DD ? +SHEXPACKET ENDS +SGDAIF_COMPARENAME EQU 0 +SGDAIF_TESTAPPBIT EQU 1 +SGDAIF_LASTVALID EQU 1 +SGDAIR_SUCCESS EQU 0 +SGDAIR_NOMATCH EQU 1 +SGDAIR_BADFUNCTION EQU 2 +endif +endif diff --git a/VSound/VXD/VMM.INC b/VSound/VXD/VMM.INC new file mode 100755 index 0000000..db98bb2 --- /dev/null +++ b/VSound/VXD/VMM.INC @@ -0,0 +1,4074 @@ +;**************************************************************************** +; * +; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +; PURPOSE. * +; * +; Copyright (C) 1993-95 Microsoft Corporation. All Rights Reserved. * +; * +;**************************************************************************** + +ifndef _VMM_ +_VMM_ EQU 1 +FALSE EQU 0 +VMM_TRUE EQU (NOT FALSE) +DEBLEVELRETAIL EQU 0 +DEBLEVELNORMAL EQU 1 +DEBLEVELMAX EQU 2 +ifndef DEBLEVEL +ifdef DEBUG +DEBLEVEL EQU DEBLEVELNORMAL +else +DEBLEVEL EQU DEBLEVELRETAIL +endif +endif +ifndef WIN31COMPAT +WIN40SERVICES EQU 1 +endif +ifdef MASM6 +ifndef NO_MASM6_OPTIONS + + + + option oldmacros +ifndef NEWSTRUCTS + option oldstructs +endif + option noscoped + option segment:flat + option offset:flat + option proc:private +endif +endif + + + + +IFDEF MASM6 +BeginDoc MACRO + ENDM +EndDoc MACRO + ENDM + +BeginMsg MACRO + ENDM +EndMsg MACRO + ENDM +ELSE +BeginDoc EQU <> +EndDoc EQU <> + +BeginMsg EQU <> +EndMsg EQU <> +ENDIF + +UNDEFINED_DEVICE_ID EQU 00000H +VMM_DEVICE_ID EQU 00001H +DEBUG_DEVICE_ID EQU 00002H +VPICD_DEVICE_ID EQU 00003H +VDMAD_DEVICE_ID EQU 00004H +VTD_DEVICE_ID EQU 00005H +V86MMGR_DEVICE_ID EQU 00006H +PAGESWAP_DEVICE_ID EQU 00007H +PARITY_DEVICE_ID EQU 00008H +REBOOT_DEVICE_ID EQU 00009H +VDD_DEVICE_ID EQU 0000AH +VSD_DEVICE_ID EQU 0000BH +VMD_DEVICE_ID EQU 0000CH +VKD_DEVICE_ID EQU 0000DH +VCD_DEVICE_ID EQU 0000EH +VPD_DEVICE_ID EQU 0000FH +BLOCKDEV_DEVICE_ID EQU 00010H +VMCPD_DEVICE_ID EQU 00011H +EBIOS_DEVICE_ID EQU 00012H +BIOSXLAT_DEVICE_ID EQU 00013H +VNETBIOS_DEVICE_ID EQU 00014H +DOSMGR_DEVICE_ID EQU 00015H +WINLOAD_DEVICE_ID EQU 00016H +SHELL_DEVICE_ID EQU 00017H +VMPOLL_DEVICE_ID EQU 00018H +VPROD_DEVICE_ID EQU 00019H +DOSNET_DEVICE_ID EQU 0001AH +VFD_DEVICE_ID EQU 0001BH +VDD2_DEVICE_ID EQU 0001CH +WINDEBUG_DEVICE_ID EQU 0001DH +TSRLOAD_DEVICE_ID EQU 0001EH +BIOSHOOK_DEVICE_ID EQU 0001FH +INT13_DEVICE_ID EQU 00020H +PAGEFILE_DEVICE_ID EQU 00021H +SCSI_DEVICE_ID EQU 00022H +MCA_POS_DEVICE_ID EQU 00023H +SCSIFD_DEVICE_ID EQU 00024H +VPEND_DEVICE_ID EQU 00025H +APM_DEVICE_ID EQU 00026H +VPOWERD_DEVICE_ID EQU APM_DEVICE_ID +VXDLDR_DEVICE_ID EQU 00027H +NDIS_DEVICE_ID EQU 00028H +BIOS_EXT_DEVICE_ID EQU 00029H +VWIN32_DEVICE_ID EQU 0002AH +VCOMM_DEVICE_ID EQU 0002BH +SPOOLER_DEVICE_ID EQU 0002CH +WIN32S_DEVICE_ID EQU 0002DH +DEBUGCMD_DEVICE_ID EQU 0002EH +CONFIGMG_DEVICE_ID EQU 00033H +DWCFGMG_DEVICE_ID EQU 00034H +SCSIPORT_DEVICE_ID EQU 00035H +VFBACKUP_DEVICE_ID EQU 00036H +ENABLE_DEVICE_ID EQU 00037H +VCOND_DEVICE_ID EQU 00038H +ISAPNP_DEVICE_ID EQU 0003CH +BIOS_DEVICE_ID EQU 0003DH +IFSMgr_Device_ID EQU 00040H +VCDFSD_DEVICE_ID EQU 00041H +MRCI2_DEVICE_ID EQU 00042H +PCI_DEVICE_ID EQU 00043H +PELOADER_DEVICE_ID EQU 00044H +EISA_DEVICE_ID EQU 00045H +DRAGCLI_DEVICE_ID EQU 00046H +DRAGSRV_DEVICE_ID EQU 00047H +PERF_DEVICE_ID EQU 00048H +AWREDIR_DEVICE_ID EQU 00049H +ETEN_Device_ID EQU 00060H +CHBIOS_Device_ID EQU 00061H +VMSGD_Device_ID EQU 00062H +VPPID_Device_ID EQU 00063H +VIME_Device_ID EQU 00064H +VHBIOSD_Device_ID EQU 00065H +BASEID_FOR_NAMEBASEDVXD EQU 0f000H +BASEID_FOR_NAMEBASEDVXD_MASK EQU 0fffH +VMM_INIT_ORDER EQU 000000000H +DEBUG_INIT_ORDER EQU 000000000H +DEBUGCMD_INIT_ORDER EQU 000000000H +PERF_INIT_ORDER EQU 000900000H +APM_INIT_ORDER EQU 001000000H +VPOWERD_INIT_ORDER EQU APM_INIT_ORDER +BIOSHOOK_INIT_ORDER EQU 006000000H +VPROD_INIT_ORDER EQU 008000000H +VPICD_INIT_ORDER EQU 00C000000H +VTD_INIT_ORDER EQU 014000000H +VXDLDR_INIT_ORDER EQU 016000000H +ENUMERATOR_INIT_ORDER EQU 016800000H +ISAPNP_INIT_ORDER EQU ENUMERATOR_INIT_ORDER +EISA_INIT_ORDER EQU ENUMERATOR_INIT_ORDER +PCI_INIT_ORDER EQU ENUMERATOR_INIT_ORDER +BIOS_INIT_ORDER EQU ENUMERATOR_INIT_ORDER+1 +CONFIGMG_INIT_ORDER EQU ENUMERATOR_INIT_ORDER+0FFFFH +VCDFSD_INIT_ORDER EQU 016F00000H +IOS_INIT_ORDER EQU 017000000H +PAGEFILE_INIT_ORDER EQU 018000000H +PAGESWAP_INIT_ORDER EQU 01C000000H +PARITY_INIT_ORDER EQU 020000000H +REBOOT_INIT_ORDER EQU 024000000H +EBIOS_INIT_ORDER EQU 026000000H +VDD_INIT_ORDER EQU 028000000H +VSD_INIT_ORDER EQU 02C000000H +VCD_INIT_ORDER EQU 030000000H +COMMDRVR_INIT_ORDER EQU (VCD_INIT_ORDER-1) +PRTCL_INIT_ORDER EQU (COMMDRVR_INIT_ORDER-2) +MODEM_INIT_ORDER EQU (COMMDRVR_INIT_ORDER-3) +PORT_INIT_ORDER EQU (COMMDRVR_INIT_ORDER-4) +VMD_INIT_ORDER EQU 034000000H +VKD_INIT_ORDER EQU 038000000H +VPD_INIT_ORDER EQU 03C000000H +BLOCKDEV_INIT_ORDER EQU 040000000H +MCA_POS_INIT_ORDER EQU 041000000H +SCSIFD_INIT_ORDER EQU 041400000H +SCSIMASTER_INIT_ORDER EQU 041800000H +INT13_INIT_ORDER EQU 042000000H +VMCPD_INIT_ORDER EQU 048000000H +BIOSXLAT_INIT_ORDER EQU 050000000H +VNETBIOS_INIT_ORDER EQU 054000000H +DOSMGR_INIT_ORDER EQU 058000000H +DOSNET_INIT_ORDER EQU 05C000000H +WINLOAD_INIT_ORDER EQU 060000000H +VMPOLL_INIT_ORDER EQU 064000000H +UNDEFINED_INIT_ORDER EQU 080000000H +WIN32_INIT_ORDER EQU UNDEFINED_INIT_ORDER +VCOND_INIT_ORDER EQU UNDEFINED_INIT_ORDER +WINDEBUG_INIT_ORDER EQU 081000000H +VDMAD_INIT_ORDER EQU 090000000H +V86MMGR_INIT_ORDER EQU 0A0000000H +IFSMgr_Init_Order EQU 10000H+V86MMGR_Init_Order +FSD_Init_Order EQU 00100H+IFSMgr_Init_Order +VFD_INIT_ORDER EQU 50000H+IFSMgr_Init_Order +UNDEF_TOUCH_MEM_INIT_ORDER EQU 0A8000000H +SHELL_INIT_ORDER EQU 0B0000000H + + + + + + +IO_Delay macro +jmp $+2 +ENDM + +VXD_FAILURE EQU 0 +VXD_SUCCESS EQU 1 + +Pushad_Struc STRUC +Pushad_EDI DD ? +Pushad_ESI DD ? +Pushad_EBP DD ? +Pushad_ESP DD ? +Pushad_EBX DD ? +Pushad_EDX DD ? +Pushad_ECX DD ? +Pushad_EAX DD ? +Pushad_Struc ENDS +ifndef Not_VxD +??_CUR_CODE_SEG = 0 + +??_LCODE = 1 +??_ICODE = 2 +??_PCODE = 3 +??_SCODE = 4 +??_DBOCODE = 5 +??_16ICODE = 6 +??_RCODE = 7 +??_LOCKABLECODE = 8 + +?_LCODE equ <(??_CUR_CODE_SEG MOD 16) - ??_LCODE> +?_ICODE equ <(??_CUR_CODE_SEG MOD 16) - ??_ICODE> +?_PCODE equ <(??_CUR_CODE_SEG MOD 16) - ??_PCODE> +?_SCODE equ <(??_CUR_CODE_SEG MOD 16) - ??_SCODE> +?_DBOCODE equ <(??_CUR_CODE_SEG MOD 16) - ??_DBOCODE> +?_16ICODE equ <(??_CUR_CODE_SEG MOD 16) - ??_16ICODE> +?_RCODE equ <(??_CUR_CODE_SEG MOD 16) - ??_RCODE> +?_LOCKABLECODE equ <(??_CUR_CODE_SEG MOD 16) - ??_LOCKABLECODE> + +ifndef NO_SEGMENTS + + + + + +IFDEF MASM6 +_FLAT EQU FLAT +ELSE +_FLAT EQU USE32 +ENDIF + + +_LTEXT SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_LTEXT ENDS + +_TEXT SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_TEXT ENDS + + +_PTEXT SEGMENT DWORD PUBLIC _FLAT 'PCODE' +_PTEXT ENDS + + + +MakeCodeSeg MACRO seglist, classname, grpname, iseg + + IRP segname, + +IFNB + segname SEGMENT DWORD PUBLIC _FLAT "&classname&CODE" +ELSE + segname SEGMENT DWORD PUBLIC _FLAT "&segname&CODE" +ENDIF + +IFB +VxD_&&segname&&_CODE_SEG MACRO +segname SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_PCODE + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + + ENDM +ELSE +VxD_&&segname&&_CODE_SEG MACRO +segname SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + iseg + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + + ENDM +ENDIF + +VxD_&&segname&&_CODE_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +segname ENDS + ENDM + +segname ENDS + +IFNDEF BLD_COFF +IFNB + _&grpname GROUP segname +ELSE + _&&segname GROUP segname +ENDIF +ENDIF + + ENDM + + ENDM + +MakeCodeSeg , \ + LOCKABLE, LOCKABLE, ??_LOCKABLECODE +MakeCodeSeg INT21 +MakeCodeSeg SYSEXIT +MakeCodeSeg RARE +MakeCodeSeg W16 +MakeCodeSeg W32 +MakeCodeSeg VMCREATE +MakeCodeSeg VMDESTROY +MakeCodeSeg THCREATE +MakeCodeSeg THDESTROY +MakeCodeSeg VMSUSPEND +MakeCodeSeg VMRESUME +MakeCodeSeg PNP +MakeCodeSeg DOSVM + + + + + + + + + + + +DefLockableCodeBegin MACRO name, private +VxD_LOCKABLE_BEGIN_CODE_SEG +IFB + PUBLIC name +ENDIF +name LABEL NEAR +VxD_LOCKABLE_BEGIN_CODE_ENDS +ifndef WIN31COMPAT +if DEBLEVEL +VxD_LOCKED_DATA_SEG + PUBLIC name&_Debug_Flags +name&_Debug_Flags DD DFS_TEST_BLOCK +VxD_LOCKED_DATA_ENDS +??_debug_flags equ +endif +endif + ENDM + + + + + + + + + +DefLockableCodeEnd MACRO name, private +VxD_LOCKABLE_END_CODE_SEG +IFB + PUBLIC name +ENDIF +name LABEL NEAR +VxD_LOCKABLE_END_CODE_ENDS + ENDM + + + + + +CodeLockFlags MACRO name +ifndef WIN31COMPAT +if DEBLEVEL + ifndef name&_Debug_Flags + VxD_LOCKED_DATA_SEG + extrn name&_Debug_Flags:dword + VxD_LOCKED_DATA_ENDS + ??_debug_flags equ + endif +endif +endif + ENDM + + + + + + +MarkCodeLocked MACRO +ifndef WIN31COMPAT +if DEBLEVEL +ifdef ??_debug_flags + pushfd + and ??_debug_flags,NOT DFS_TEST_BLOCK + popfd +endif +endif +endif + ENDM + + + + + + +MarkCodeUnlocked MACRO +ifndef WIN31COMPAT +if DEBLEVEL +ifdef ??_debug_flags + pushfd + or ??_debug_flags,DFS_TEST_BLOCK + popfd +endif +endif +endif + ENDM + + + +_ITEXT SEGMENT DWORD PUBLIC _FLAT 'ICODE' +_ITEXT ENDS + + +_LDATA SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_LDATA ENDS + +_DATA SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_DATA ENDS + + +_PDATA SEGMENT DWORD PUBLIC _FLAT 'PDATA' +_PDATA ENDS + + +_IDATA SEGMENT DWORD PUBLIC _FLAT 'ICODE' +_IDATA ENDS + + +_BSS SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_BSS ENDS + +CONST SEGMENT DWORD PUBLIC _FLAT 'LCODE' +CONST ENDS + +_TLS SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_TLS ENDS + + +_STEXT SEGMENT DWORD PUBLIC _FLAT 'SCODE' +_STEXT ENDS + + +_SDATA SEGMENT DWORD PUBLIC _FLAT 'SCODE' +_SDATA ENDS + + +_DBOSTART SEGMENT DWORD PUBLIC _FLAT 'DBOCODE' +_DBOSTART ENDS + + +_DBOCODE SEGMENT DWORD PUBLIC _FLAT 'DBOCODE' +_DBOCODE ENDS + + +_DBODATA SEGMENT DWORD PUBLIC _FLAT 'DBOCODE' +_DBODATA ENDS + +if DEBLEVEL + +_PATHSTART SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_PATHSTART ENDS + + +_PATHDATA SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_PATHDATA ENDS + + +_PATHEND SEGMENT DWORD PUBLIC _FLAT 'LCODE' +_PATHEND ENDS +endif + + +_16ICODE SEGMENT WORD USE16 PUBLIC '16ICODE' +_16ICODE ENDS + + +_RCODE SEGMENT WORD USE16 PUBLIC 'RCODE' +_RCODE ENDS + +IFNDEF BLD_COFF +_LGROUP GROUP _LTEXT, _TEXT, _LDATA, _DATA, _BSS, CONST, _TLS +_IGROUP GROUP _ITEXT, _IDATA +_SGROUP GROUP _STEXT, _SDATA +_DBOGROUP GROUP _DBOSTART, _DBOCODE, _DBODATA +IF DEBLEVEL +_PGROUP GROUP _PATHSTART, _PATHDATA, _PATHEND +ENDIF +ENDIF + +endif + + ASSUME CS:FLAT, DS:FLAT, ES:FLAT, SS:FLAT + +OFFSET32 EQU + + +BeginDoc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EndDoc + +Begin_Service_Table MACRO Device_Name, Def_Segment + +IFDEF Device_Name&_Name_Based + IFNDEF @@NextInternalID + @@NextInternalID = 0 + ENDIF + @@NextInternalID = (@@NextInternalID + 1) + Device_Name&_Internal_ID = @@NextInternalID + BASEID_FOR_NAMEBASEDVXD + DefineVxDName Device_Name, %Device_Name&_Internal_ID +ENDIF + +IFB + BST2 Device_Name, VxD +ELSE + BST2 Device_Name, Def_Segment +ENDIF + ENDM + +DefineVxDName MACRO Device_Name, InternalID + @@VxDName&InternalID EQU <___&Device_Name&STable> +ENDM + + +BST2 MACRO Device_Name, Def_Segment + +Num_&Device_Name&_Services = 0 + +IFDEF Create_&Device_Name&_Service_Table + +Def_Segment&_LOCKED_DATA_SEG + +Device_Name&_Service_Table LABEL DWORD + +Device_Name&_Service MACRO Procedure, Local_Seg, Condition +LOCAL $$&Procedure + + IFNB + $$&&Procedure MACRO extern + IFDEF &Condition + IFNB + EXTRN Procedure:NEAR + ELSE + dd OFFSET32 Procedure + ENDIF + ELSE + IFB + dd 0 + ENDIF + ENDIF + ENDM + ENDIF + + IFDIFI , + PUBLIC _&&Procedure + IF1 + _&&Procedure LABEL DWORD + ENDIF + IFDIFI , + IFNB +Local_Seg&&_SEG + ELSE +Def_Segment&_CODE_SEG + ENDIF + IFNB + $$&&Procedure extern + ELSE + EXTRN Procedure:NEAR + ENDIF + IFNB +Local_Seg&&_ENDS + ELSE +Def_Segment&_CODE_ENDS + ENDIF + ENDIF + IFNB + $$&&Procedure + ELSE + dd OFFSET32 Procedure + ENDIF + + IFDEF Device_Name&_Name_Based + @@&&Procedure = (Device_Name&_Internal_ID SHL 16) + Num_&Device_Name&_Services + ELSE + @@&&Procedure = (Device_Name&_Device_ID SHL 16) + Num_&Device_Name&_Services + ENDIF + ELSE + dd 0 + ENDIF + Num_&Device_Name&_Services = Num_&Device_Name&_Services + 1 + IFNB + Purge $$&&Procedure + ENDIF + ENDM + +ELSE + + + +IFDEF Device_Name&_Name_Based + +Device_Name&_Service MACRO Procedure, Local_Seg, Condition + + + IFDIFI , + @@&&Procedure = (Device_Name&_Internal_ID SHL 16) + Num_&Device_Name&_Services + ENDIF + Num_&Device_Name&_Services = Num_&Device_Name&_Services + 1 + + ENDM +ELSE + +Device_Name&_Service MACRO Procedure, Local_Seg, Condition + + IFDIFI , + @@&&Procedure = (Device_Name&_Device_ID SHL 16) + Num_&Device_Name&_Services + ENDIF + Num_&Device_Name&_Services = Num_&Device_Name&_Services + 1 + + ENDM +ENDIF + +ENDIF + + ENDM + + + +End_Service_Table MACRO Device_Name, Def_Segment + + PURGE Device_Name&_Service + +IFDEF Create_&Device_Name&_Service_Table + +IFB +VxD_LOCKED_DATA_ENDS +ELSE +Def_Segment&_LOCKED_DATA_ENDS +ENDIF + +ENDIF + + ENDM + +GetVxDServiceOrdinal macro reg,service + mov reg,@@&service + endm + +GetVxDServiceAddress macro reg,service + mov reg,OFFSET32 service + endm + + + + + + + + + + + + + + + + + + +Begin_Win32_Services MACRO VxDName +ifndef Create_Win32_Services + Create_Win32_Services = 0 +endif + .errb , + ??w32svcno = 0 +if Create_Win32_Services +VxDName&_Win32_Services label dword + dd csvc&VxDName, 0 +endif + ??inw32svc = 1 + + VxDName&_Win32_Service MACRO Name + .erre ??inw32svc, + if Create_Win32_Services + dd OFFSET32 Name,cparm&&Name + endif + @32&&Name equ ((VxDName&_Device_ID SHL 16) + ??w32svcno) + ??w32svcno = ??w32svcno + 1 + ENDM + ENDM + + + + + + + + + + +End_Win32_Services MACRO VxDName + .errb , +if Create_Win32_Services + csvc&VxDName equ ($ - VxDName&_Win32_Services)/8 - 1 +endif + ??inw32svc = 0 + PURGE VxDName&_Win32_Service + ENDM + + + + + + + + + + + +Declare_Win32_Service MACRO Name, cParms +ifndef Create_Win32_Services + Create_Win32_Services = 0 +endif +if Create_Win32_Services + ?merge ,,,,,<_>,,<@>,%(cParms*4 + 8) + ?merge ,,,,, +VxD_CODE_SEG + ?merge ,,,,,<_>,,<@>,%(cParms*4 + 8),<:NEAR> +VxD_CODE_ENDS +endif + ENDM + + + + + + + + + + + + +Win32call MACRO Service, CallBack +ifndef Create_Win32_Services + Create_Win32_Services = 0 +endif +ife Create_Win32_Services + mov eax,@32&Service +ifdef IS_16 + movzx esp,sp +endif + call fword ptr [CallBack] +ifdef DEBUG + int 3 +endif +endif + ENDM + + + + + + + +Dword_Align MACRO Seg_Name + LOCAL segn +IFDEF MASM6 + align 4 +ELSE +IFNB + segn equ Seg_Name +ELSE +IFE ?_LCODE + segn equ <_LTEXT> +ELSE +IFE ?_ICODE + segn equ <_ITEXT> +ELSE +IFE ?_PCODE + segn equ <_PTEXT> +ELSE +IFE ?_SCODE + segn equ <_STEXT> +ELSE +.err +ENDIF +ENDIF +ENDIF +ENDIF +ENDIF +IF (($-OFFSET segn:0) MOD 4) +db 4 - (($-OFFSET segn:0) MOD 4) DUP (90h) +ENDIF +ENDIF + ENDM + + +BeginDoc + + + + + + + + + + + + + + + + + +EndDoc + +Fatal_Error MACRO Msg_Ptr, Exit_Flags + pushad +IFB + xor esi, esi +ELSE + mov esi, Msg_Ptr +IFB + xor eax, eax +ELSE + mov eax, Exit_Flags +ENDIF +ENDIF + VMMCall Fatal_Error_Handler + ENDM + +EF_Hang_On_Exit EQU 1h + + +cb_s STRUC +CB_VM_Status DD ? +CB_High_Linear DD ? +CB_Client_Pointer DD ? +CB_VMID DD ? +CB_Signature DD ? +cb_s ENDS +VMCB_ID EQU 62634D56H +VMSTAT_EXCLUSIVE_BIT EQU 00H +VMSTAT_EXCLUSIVE EQU (1 SHL VMSTAT_EXCLUSIVE_BIT) +VMSTAT_BACKGROUND_BIT EQU 01H +VMSTAT_BACKGROUND EQU (1 SHL VMSTAT_BACKGROUND_BIT) +VMSTAT_CREATING_BIT EQU 02H +VMSTAT_CREATING EQU (1 SHL VMSTAT_CREATING_BIT) +VMSTAT_SUSPENDED_BIT EQU 03H +VMSTAT_SUSPENDED EQU (1 SHL VMSTAT_SUSPENDED_BIT) +VMSTAT_NOT_EXECUTEABLE_BIT EQU 04H +VMSTAT_NOT_EXECUTEABLE EQU (1 SHL VMSTAT_NOT_EXECUTEABLE_BIT) +VMSTAT_PM_EXEC_BIT EQU 05H +VMSTAT_PM_EXEC EQU (1 SHL VMSTAT_PM_EXEC_BIT) +VMSTAT_PM_APP_BIT EQU 06H +VMSTAT_PM_APP EQU (1 SHL VMSTAT_PM_APP_BIT) +VMSTAT_PM_USE32_BIT EQU 07H +VMSTAT_PM_USE32 EQU (1 SHL VMSTAT_PM_USE32_BIT) +VMSTAT_VXD_EXEC_BIT EQU 08H +VMSTAT_VXD_EXEC EQU (1 SHL VMSTAT_VXD_EXEC_BIT) +VMSTAT_HIGH_PRI_BACK_BIT EQU 09H +VMSTAT_HIGH_PRI_BACK EQU (1 SHL VMSTAT_HIGH_PRI_BACK_BIT) +VMSTAT_BLOCKED_BIT EQU 0AH +VMSTAT_BLOCKED EQU (1 SHL VMSTAT_BLOCKED_BIT) +VMSTAT_AWAKENING_BIT EQU 0BH +VMSTAT_AWAKENING EQU (1 SHL VMSTAT_AWAKENING_BIT) +VMSTAT_PAGEABLEV86BIT EQU 0CH +VMSTAT_PAGEABLEV86_BIT EQU VMSTAT_PAGEABLEV86BIT +VMSTAT_PAGEABLEV86 EQU (1 SHL VMSTAT_PAGEABLEV86BIT) +VMSTAT_V86INTSLOCKEDBIT EQU 0DH +VMSTAT_V86INTSLOCKED_BIT EQU VMSTAT_V86INTSLOCKEDBIT +VMSTAT_V86INTSLOCKED EQU (1 SHL VMSTAT_V86INTSLOCKEDBIT) +VMSTAT_IDLE_TIMEOUT_BIT EQU 0EH +VMSTAT_IDLE_TIMEOUT EQU (1 SHL VMSTAT_IDLE_TIMEOUT_BIT) +VMSTAT_IDLE_BIT EQU 0FH +VMSTAT_IDLE EQU (1 SHL VMSTAT_IDLE_BIT) +VMSTAT_CLOSING_BIT EQU 10H +VMSTAT_CLOSING EQU (1 SHL VMSTAT_CLOSING_BIT) +VMSTAT_TS_SUSPENDED_BIT EQU 11H +VMSTAT_TS_SUSPENDED EQU (1 SHL VMSTAT_TS_SUSPENDED_BIT) +VMSTAT_TS_MAXPRI_BIT EQU 12H +VMSTAT_TS_MAXPRI EQU (1 SHL VMSTAT_TS_MAXPRI_BIT) +VMSTAT_USE32_MASK EQU (VMSTAT_PM_USE32 OR VMSTAT_VXD_EXEC) + +tcb_s STRUC +TCB_Flags DD ? +TCB_Reserved1 DD ? +TCB_Reserved2 DD ? +TCB_Signature DD ? +TCB_ClientPtr DD ? +TCB_VMHandle DD ? +TCB_ThreadId DW ? +TCB_PMLockOrigSS DW ? +TCB_PMLockOrigESP DD ? +TCB_PMLockOrigEIP DD ? +TCB_PMLockStackCount DD ? +TCB_PMLockOrigCS DW ? +TCB_PMPSPSelector DW ? +TCB_ThreadType DD ? +TCB_pad1 DW ? +TCB_pad2 DB ? +TCB_extErrLocus DB ? +TCB_extErr DW ? +TCB_extErrAction DB ? +TCB_extErrClass DB ? +TCB_extErrPtr DD ? +tcb_s ENDS +SCHED_OBJ_ID_THREAD EQU 42434854H +THFLAG_SUSPENDED_BIT EQU 03H +THFLAG_SUSPENDED EQU (1 SHL THFLAG_SUSPENDED_BIT) +THFLAG_NOT_EXECUTEABLE_BIT EQU 04H +THFLAG_NOT_EXECUTEABLE EQU (1 SHL THFLAG_NOT_EXECUTEABLE_BIT) +THFLAG_THREAD_CREATION_BIT EQU 08H +THFLAG_THREAD_CREATION EQU (1 SHL THFLAG_THREAD_CREATION_BIT) +THFLAG_THREAD_BLOCKED_BIT EQU 0AH +THFLAG_THREAD_BLOCKED EQU (1 SHL THFLAG_THREAD_BLOCKED_BIT) +THFLAG_RING0_THREAD_BIT EQU 1CH +THFLAG_RING0_THREAD EQU (1 SHL THFLAG_RING0_THREAD_BIT) +THFLAG_CHARSET_BITS EQU 10H +THFLAG_CHARSET_MASK EQU (3 SHL THFLAG_CHARSET_BITS) +THFLAG_ANSI EQU (0 SHL THFLAG_CHARSET_BITS) +THFLAG_OEM EQU (1 SHL THFLAG_CHARSET_BITS) +THFLAG_UNICODE EQU (2 SHL THFLAG_CHARSET_BITS) +THFLAG_RESERVED EQU (3 SHL THFLAG_CHARSET_BITS) +THFLAG_EXTENDED_HANDLES_BIT EQU 12H +THFLAG_EXTENDED_HANDLES EQU (1 SHL THFLAG_EXTENDED_HANDLES_BIT) +THFLAG_OPEN_AS_IMMOVABLE_FILE_BIT EQU 13H +THFLAG_OPEN_AS_IMMOVABLE_FILE EQU (1 SHL THFLAG_OPEN_AS_IMMOVABLE_FILE_BIT) + +pmcb_s STRUC +PMCB_Flags DD ? +PMCB_Parent DD ? +pmcb_s ENDS + +VMFaultInfo STRUC +VMFI_EIP DD ? +VMFI_CS DW ? +VMFI_Ints DW ? +VMFaultInfo ENDS +Begin_Service_Table VMM, VMM +VMM_Service Get_VMM_Version, LOCAL +VMM_Service Get_Cur_VM_Handle +VMM_Service Test_Cur_VM_Handle +VMM_Service Get_Sys_VM_Handle +VMM_Service Test_Sys_VM_Handle +VMM_Service Validate_VM_Handle +VMM_Service Get_VMM_Reenter_Count +VMM_Service Begin_Reentrant_Execution +VMM_Service End_Reentrant_Execution +VMM_Service Install_V86_Break_Point +VMM_Service Remove_V86_Break_Point +VMM_Service Allocate_V86_Call_Back +VMM_Service Allocate_PM_Call_Back +VMM_Service Call_When_VM_Returns +VMM_Service Schedule_Global_Event +VMM_Service Schedule_VM_Event +VMM_Service Call_Global_Event +VMM_Service Call_VM_Event +VMM_Service Cancel_Global_Event +VMM_Service Cancel_VM_Event +VMM_Service Call_Priority_VM_Event +VMM_Service Cancel_Priority_VM_Event +VMM_Service Get_NMI_Handler_Addr +VMM_Service Set_NMI_Handler_Addr +VMM_Service Hook_NMI_Event +VMM_Service Call_When_VM_Ints_Enabled +VMM_Service Enable_VM_Ints +VMM_Service Disable_VM_Ints +VMM_Service Map_Flat +VMM_Service Map_Lin_To_VM_Addr +VMM_Service Adjust_Exec_Priority +VMM_Service Begin_Critical_Section +VMM_Service End_Critical_Section +VMM_Service End_Crit_And_Suspend +VMM_Service Claim_Critical_Section +VMM_Service Release_Critical_Section +VMM_Service Call_When_Not_Critical +VMM_Service Create_Semaphore +VMM_Service Destroy_Semaphore +VMM_Service Wait_Semaphore +VMM_Service Signal_Semaphore +VMM_Service Get_Crit_Section_Status +VMM_Service Call_When_Task_Switched +VMM_Service Suspend_VM +VMM_Service Resume_VM +VMM_Service No_Fail_Resume_VM +VMM_Service Nuke_VM +VMM_Service Crash_Cur_VM +VMM_Service Get_Execution_Focus +VMM_Service Set_Execution_Focus +VMM_Service Get_Time_Slice_Priority +VMM_Service Set_Time_Slice_Priority +VMM_Service Get_Time_Slice_Granularity +VMM_Service Set_Time_Slice_Granularity +VMM_Service Get_Time_Slice_Info +VMM_Service Adjust_Execution_Time +VMM_Service Release_Time_Slice +VMM_Service Wake_Up_VM +VMM_Service Call_When_Idle +VMM_Service Get_Next_VM_Handle +VMM_Service Set_Global_Time_Out +VMM_Service Set_VM_Time_Out +VMM_Service Cancel_Time_Out +VMM_Service Get_System_Time +VMM_Service Get_VM_Exec_Time +VMM_Service Hook_V86_Int_Chain +VMM_Service Get_V86_Int_Vector +VMM_Service Set_V86_Int_Vector +VMM_Service Get_PM_Int_Vector +VMM_Service Set_PM_Int_Vector +VMM_Service Simulate_Int +VMM_Service Simulate_Iret +VMM_Service Simulate_Far_Call +VMM_Service Simulate_Far_Jmp +VMM_Service Simulate_Far_Ret +VMM_Service Simulate_Far_Ret_N +VMM_Service Build_Int_Stack_Frame +VMM_Service Simulate_Push +VMM_Service Simulate_Pop +VMM_Service _HeapAllocate +VMM_Service _HeapReAllocate +VMM_Service _HeapFree +VMM_Service _HeapGetSize +HEAPZEROINIT EQU 00000001H +HEAPZEROREINIT EQU 00000002H +HEAPNOCOPY EQU 00000004H +HEAPLOCKEDIFDP EQU 00000100H +HEAPSWAP EQU 00000200H +HEAPINIT EQU 00000400H +HEAPCLEAN EQU 00000800H +VMM_Service _PageAllocate +VMM_Service _PageReAllocate +VMM_Service _PageFree +VMM_Service _PageLock +VMM_Service _PageUnLock +VMM_Service _PageGetSizeAddr +VMM_Service _PageGetAllocInfo +VMM_Service _GetFreePageCount +VMM_Service _GetSysPageCount +VMM_Service _GetVMPgCount +VMM_Service _MapIntoV86 +VMM_Service _PhysIntoV86 +VMM_Service _TestGlobalV86Mem +VMM_Service _ModifyPageBits +VMM_Service _CopyPageTable +VMM_Service _LinMapIntoV86 +VMM_Service _LinPageLock +VMM_Service _LinPageUnLock +VMM_Service _SetResetV86Pageable +VMM_Service _GetV86PageableArray +VMM_Service _PageCheckLinRange +VMM_Service _PageOutDirtyPages +VMM_Service _PageDiscardPages +PAGEZEROINIT EQU 00000001H +PAGEUSEALIGN EQU 00000002H +PAGECONTIG EQU 00000004H +PAGEFIXED EQU 00000008H +PAGEDEBUGNULFAULT EQU 00000010H +PAGEZEROREINIT EQU 00000020H +PAGENOCOPY EQU 00000040H +PAGELOCKED EQU 00000080H +PAGELOCKEDIFDP EQU 00000100H +PAGESETV86PAGEABLE EQU 00000200H +PAGECLEARV86PAGEABLE EQU 00000400H +PAGESETV86INTSLOCKED EQU 00000800H +PAGECLEARV86INTSLOCKED EQU 00001000H +PAGEMARKPAGEOUT EQU 00002000H +PAGEPDPSETBASE EQU 00004000H +PAGEPDPCLEARBASE EQU 00008000H +PAGEDISCARD EQU 00010000H +PAGEPDPQUERYDIRTY EQU 00020000H +PAGEMAPFREEPHYSREG EQU 00040000H +PAGENOMOVE EQU 10000000H +PAGEMAPGLOBAL EQU 40000000H +PAGEMARKDIRTY EQU 80000000H +MAPV86_IGNOREWRAP EQU 00000001H +VMM_Service _GetNulPageHandle +VMM_Service _GetFirstV86Page +VMM_Service _MapPhysToLinear +VMM_Service _GetAppFlatDSAlias +VMM_Service _SelectorMapFlat +VMM_Service _GetDemandPageInfo +VMM_Service _GetSetPageOutCount +GSPOC_F_GET EQU 00000001H +VMM_Service Hook_V86_Page +VMM_Service _Assign_Device_V86_Pages +VMM_Service _DeAssign_Device_V86_Pages +VMM_Service _Get_Device_V86_Pages_Array +VMM_Service MMGR_SetNULPageAddr +VMM_Service _Allocate_GDT_Selector +VMM_Service _Free_GDT_Selector +VMM_Service _Allocate_LDT_Selector +VMM_Service _Free_LDT_Selector +VMM_Service _BuildDescriptorDWORDs +VMM_Service _GetDescriptor +VMM_Service _SetDescriptor +BDDEXPLICITDPL EQU 00000001H +ALDTSPECSEL EQU 00000001H +VMM_Service _MMGR_Toggle_HMA +MMGRHMAPHYSICAL EQU 00000001H +MMGRHMAENABLE EQU 00000002H +MMGRHMADISABLE EQU 00000004H +MMGRHMAQUERY EQU 00000008H +VMM_Service Get_Fault_Hook_Addrs +VMM_Service Hook_V86_Fault +VMM_Service Hook_PM_Fault +VMM_Service Hook_VMM_Fault +VMM_Service Begin_Nest_V86_Exec +VMM_Service Begin_Nest_Exec +VMM_Service Exec_Int +VMM_Service Resume_Exec +VMM_Service End_Nest_Exec +VMM_Service Allocate_PM_App_CB_Area, VMM_ICODE +VMM_Service Get_Cur_PM_App_CB +VMM_Service Set_V86_Exec_Mode +VMM_Service Set_PM_Exec_Mode +VMM_Service Begin_Use_Locked_PM_Stack +VMM_Service End_Use_Locked_PM_Stack +VMM_Service Save_Client_State +VMM_Service Restore_Client_State +VMM_Service Exec_VxD_Int +VMM_Service Hook_Device_Service +VMM_Service Hook_Device_V86_API +VMM_Service Hook_Device_PM_API +VMM_Service System_Control +VMM_Service Simulate_IO +VMM_Service Install_Mult_IO_Handlers +VMM_Service Install_IO_Handler +VMM_Service Enable_Global_Trapping +VMM_Service Enable_Local_Trapping +VMM_Service Disable_Global_Trapping +VMM_Service Disable_Local_Trapping +VMM_Service List_Create +VMM_Service List_Destroy +VMM_Service List_Allocate +VMM_Service List_Attach +VMM_Service List_Attach_Tail +VMM_Service List_Insert +VMM_Service List_Remove +VMM_Service List_Deallocate +VMM_Service List_Get_First +VMM_Service List_Get_Next +VMM_Service List_Remove_First +LF_ASYNC_BIT EQU 0 +LF_ASYNC EQU (1 SHL LF_ASYNC_BIT) +LF_USE_HEAP_BIT EQU 1 +LF_USE_HEAP EQU (1 SHL LF_USE_HEAP_BIT) +LF_ALLOC_ERROR_BIT EQU 2 +LF_ALLOC_ERROR EQU (1 SHL LF_ALLOC_ERROR_BIT) +LF_SWAP EQU (LF_USE_HEAP+(1 SHL 3)) +VMM_Service _AddInstanceItem +VMM_Service _Allocate_Device_CB_Area +VMM_Service _Allocate_Global_V86_Data_Area, VMM_ICODE +VMM_Service _Allocate_Temp_V86_Data_Area, VMM_ICODE +VMM_Service _Free_Temp_V86_Data_Area, VMM_ICODE +GVDAWordAlign EQU 00000001H +GVDADWordAlign EQU 00000002H +GVDAParaAlign EQU 00000004H +GVDAPageAlign EQU 00000008H +GVDAInstance EQU 00000100H +GVDAZeroInit EQU 00000200H +GVDAReclaim EQU 00000400H +GVDAInquire EQU 00000800H +GVDAHighSysCritOK EQU 00001000H +GVDAOptInstance EQU 00002000H +GVDAForceLow EQU 00004000H +TVDANeedTilInitComplete EQU 00000001H +VMM_Service Get_Profile_Decimal_Int, VMM_ICODE +VMM_Service Convert_Decimal_String, VMM_ICODE +VMM_Service Get_Profile_Fixed_Point, VMM_ICODE +VMM_Service Convert_Fixed_Point_String, VMM_ICODE +VMM_Service Get_Profile_Hex_Int, VMM_ICODE +VMM_Service Convert_Hex_String, VMM_ICODE +VMM_Service Get_Profile_Boolean, VMM_ICODE +VMM_Service Convert_Boolean_String, VMM_ICODE +VMM_Service Get_Profile_String, VMM_ICODE +VMM_Service Get_Next_Profile_String, VMM_ICODE +VMM_Service Get_Environment_String, VMM_ICODE +VMM_Service Get_Exec_Path, VMM_ICODE +VMM_Service Get_Config_Directory, VMM_ICODE +VMM_Service OpenFile, VMM_ICODE +VMM_OPENFILE_BUF_SIZE EQU 260 +VMM_Service Get_PSP_Segment, VMM_ICODE +VMM_Service GetDOSVectors, VMM_ICODE +VMM_Service Get_Machine_Info +GMIF_80486_BIT EQU 10H +GMIF_80486 EQU (1 SHL GMIF_80486_BIT) +GMIF_PCXT_BIT EQU 11H +GMIF_PCXT EQU (1 SHL GMIF_PCXT_BIT) +GMIF_MCA_BIT EQU 12H +GMIF_MCA EQU (1 SHL GMIF_MCA_BIT) +GMIF_EISA_BIT EQU 13H +GMIF_EISA EQU (1 SHL GMIF_EISA_BIT) +GMIF_CPUID_BIT EQU 14H +GMIF_CPUID EQU (1 SHL GMIF_CPUID_BIT) +VMM_Service GetSet_HMA_Info +VMM_Service Set_System_Exit_Code +VMM_Service Fatal_Error_Handler +VMM_Service Fatal_Memory_Error +VMM_Service Update_System_Clock +VMM_Service Test_Debug_Installed +VMM_Service Out_Debug_String +VMM_Service Out_Debug_Chr +VMM_Service In_Debug_Chr +VMM_Service Debug_Convert_Hex_Binary +VMM_Service Debug_Convert_Hex_Decimal +VMM_Service Debug_Test_Valid_Handle +VMM_Service Validate_Client_Ptr +VMM_Service Test_Reenter +VMM_Service Queue_Debug_String +VMM_Service Log_Proc_Call +VMM_Service Debug_Test_Cur_VM +VMM_Service Get_PM_Int_Type +VMM_Service Set_PM_Int_Type +VMM_Service Get_Last_Updated_System_Time +VMM_Service Get_Last_Updated_VM_Exec_Time +VMM_Service Test_DBCS_Lead_Byte +.errnz @@Test_DBCS_Lead_Byte - 100D1h + +VMM_Service _AddFreePhysPage, VMM_ICODE +VMM_Service _PageResetHandlePAddr +VMM_Service _SetLastV86Page, VMM_ICODE +VMM_Service _GetLastV86Page +VMM_Service _MapFreePhysReg +VMM_Service _UnmapFreePhysReg +VMM_Service _XchgFreePhysReg +VMM_Service _SetFreePhysRegCalBk, VMM_ICODE +VMM_Service Get_Next_Arena, VMM_ICODE +VMM_Service Get_Name_Of_Ugly_TSR, VMM_ICODE +VMM_Service Get_Debug_Options, VMM_ICODE +AFPP_SWAPOUT EQU 0001H +PCP_CHANGEPAGER EQU 1H +PCP_CHANGEPAGERDATA EQU 2H +PCP_VIRGINONLY EQU 4H +GNA_HIDOSLINKED EQU 0002H +GNA_ISHIGHDOS EQU 0004H +VMM_Service Set_Physical_HMA_Alias, VMM_ICODE +VMM_Service _GetGlblRng0V86IntBase, VMM_ICODE +VMM_Service _Add_Global_V86_Data_Area, VMM_ICODE +VMM_Service GetSetDetailedVMError +GSDVME_PRIVINST EQU 00010001H +GSDVME_INVALINST EQU 00010002H +GSDVME_INVALPGFLT EQU 00010003H +GSDVME_INVALGPFLT EQU 00010004H +GSDVME_INVALFLT EQU 00010005H +GSDVME_USERNUKE EQU 00010006H +GSDVME_DEVNUKE EQU 00010007H +GSDVME_DEVNUKEHDWR EQU 00010008H +GSDVME_NUKENOMSG EQU 00010009H +GSDVME_OKNUKEMASK EQU 80000000H +GSDVME_INSMEMV86 EQU 00020001H +GSDVME_INSV86SPACE EQU 00020002H +GSDVME_INSMEMXMS EQU 00020003H +GSDVME_INSMEMEMS EQU 00020004H +GSDVME_INSMEMV86HI EQU 00020005H +GSDVME_INSMEMVID EQU 00020006H +GSDVME_INSMEMVM EQU 00020007H +GSDVME_INSMEMDEV EQU 00020008H +GSDVME_CRTNOMSG EQU 00020009H +VMM_Service Is_Debug_Chr +VMM_Service Clear_Mono_Screen +VMM_Service Out_Mono_Chr +VMM_Service Out_Mono_String +VMM_Service Set_Mono_Cur_Pos +VMM_Service Get_Mono_Cur_Pos +VMM_Service Get_Mono_Chr +VMM_Service Locate_Byte_In_ROM, VMM_ICODE +VMM_Service Hook_Invalid_Page_Fault +VMM_Service Unhook_Invalid_Page_Fault +IPF_PGDIR EQU 00000001H +IPF_V86PG EQU 00000002H +IPF_V86PGH EQU 00000004H +IPF_INVTYP EQU 00000008H +IPF_PGERR EQU 00000010H +IPF_REFLT EQU 00000020H +IPF_VMM EQU 00000040H +IPF_PM EQU 00000080H +IPF_V86 EQU 00000100H +VMM_Service Set_Delete_On_Exit_File +VMM_Service Close_VM +CVF_CONTINUE_EXEC_BIT EQU 0 +CVF_CONTINUE_EXEC EQU (1 SHL CVF_CONTINUE_EXEC_BIT) +VMM_Service Enable_Touch_1st_Meg +VMM_Service Disable_Touch_1st_Meg +VMM_Service Install_Exception_Handler +VMM_Service Remove_Exception_Handler +VMM_Service Get_Crit_Status_No_Block + +.errnz @@Get_Crit_Status_No_Block - 100F1h + +ifdef WIN40SERVICES +VMM_Service _GetLastUpdatedThreadExecTime +VMM_Service _Trace_Out_Service +VMM_Service _Debug_Out_Service +VMM_Service _Debug_Flags_Service +endif +DFS_LOG_BIT EQU 0 +DFS_LOG EQU (1 SHL DFS_LOG_BIT) +DFS_PROFILE_BIT EQU 1 +DFS_PROFILE EQU (1 SHL DFS_PROFILE_BIT) +DFS_TEST_CLD_BIT EQU 2 +DFS_TEST_CLD EQU (1 SHL DFS_TEST_CLD_BIT) +DFS_NEVER_REENTER_BIT EQU 3 +DFS_NEVER_REENTER EQU (1 SHL DFS_NEVER_REENTER_BIT) +DFS_TEST_REENTER_BIT EQU 4 +DFS_TEST_REENTER EQU (1 SHL DFS_TEST_REENTER_BIT) +DFS_NOT_SWAPPING_BIT EQU 5 +DFS_NOT_SWAPPING EQU (1 SHL DFS_NOT_SWAPPING_BIT) +DFS_TEST_BLOCK_BIT EQU 6 +DFS_TEST_BLOCK EQU (1 SHL DFS_TEST_BLOCK_BIT) +DFS_RARE_SERVICES EQU 0FFFFFF80H +DFS_EXIT_NOBLOCK EQU (DFS_RARE_SERVICES+0) +DFS_ENTER_NOBLOCK EQU (DFS_RARE_SERVICES+DFS_TEST_BLOCK) +DFS_TEST_NEST_EXEC EQU (DFS_RARE_SERVICES+1) +ifdef WIN40SERVICES +VMM_Service VMMAddImportModuleName +VMM_Service VMM_Add_DDB +VMM_Service VMM_Remove_DDB +VMM_Service Test_VM_Ints_Enabled +VMM_Service _BlockOnID +VMM_Service Schedule_Thread_Event +VMM_Service Cancel_Thread_Event +VMM_Service Set_Thread_Time_Out +VMM_Service Set_Async_Time_Out +VMM_Service _AllocateThreadDataSlot +VMM_Service _FreeThreadDataSlot +MUTEX_MUST_COMPLETE EQU 1 +MUTEX_NO_CLEANUP_THREAD_STATE EQU 2 +VMM_Service _CreateMutex +VMM_Service _DestroyMutex +VMM_Service _GetMutexOwner +VMM_Service Call_When_Thread_Switched +VMM_Service VMMCreateThread +VMM_Service _GetThreadExecTime +VMM_Service VMMTerminateThread +VMM_Service Get_Cur_Thread_Handle +VMM_Service Test_Cur_Thread_Handle +VMM_Service Get_Sys_Thread_Handle +VMM_Service Test_Sys_Thread_Handle +VMM_Service Validate_Thread_Handle +VMM_Service Get_Initial_Thread_Handle +VMM_Service Test_Initial_Thread_Handle +VMM_Service Debug_Test_Valid_Thread_Handle +VMM_Service Debug_Test_Cur_Thread +VMM_Service VMM_GetSystemInitState +VMM_Service Cancel_Call_When_Thread_Switched +VMM_Service Get_Next_Thread_Handle +VMM_Service Adjust_Thread_Exec_Priority +VMM_Service _Deallocate_Device_CB_Area +VMM_Service Remove_IO_Handler +VMM_Service Remove_Mult_IO_Handlers +VMM_Service Unhook_V86_Int_Chain +VMM_Service Unhook_V86_Fault +VMM_Service Unhook_PM_Fault +VMM_Service Unhook_VMM_Fault +VMM_Service Unhook_Device_Service +VMM_Service _PageReserve +VMM_Service _PageCommit +VMM_Service _PageDecommit +VMM_Service _PagerRegister +VMM_Service _PagerQuery +VMM_Service _PagerDeregister +VMM_Service _ContextCreate +VMM_Service _ContextDestroy +VMM_Service _PageAttach +VMM_Service _PageFlush +VMM_Service _SignalID +VMM_Service _PageCommitPhys +VMM_Service _Register_Win32_Services +VMM_Service Cancel_Call_When_Not_Critical +VMM_Service Cancel_Call_When_Idle +VMM_Service Cancel_Call_When_Task_Switched +VMM_Service _Debug_Printf_Service +VMM_Service _EnterMutex +VMM_Service _LeaveMutex +VMM_Service Simulate_VM_IO +VMM_Service Signal_Semaphore_No_Switch +VMM_Service _ContextSwitch +VMM_Service _PageModifyPermissions +VMM_Service _PageQuery +VMM_Service _EnterMustComplete +VMM_Service _LeaveMustComplete +VMM_Service _ResumeExecMustComplete +THREAD_TERM_STATUS_CRASH_PEND EQU 1 +THREAD_TERM_STATUS_NUKE_PEND EQU 2 +THREAD_TERM_STATUS_SUSPEND_PEND EQU 4 +VMM_Service _GetThreadTerminationStatus +VMM_Service _GetInstanceInfo +INSTINFO_NONE EQU 0 +INSTINFO_SOME EQU 1 +INSTINFO_ALL EQU 2 +VMM_Service _ExecIntMustComplete +VMM_Service _ExecVxDIntMustComplete +VMM_Service Begin_V86_Serialization +VMM_Service Unhook_V86_Page +VMM_Service VMM_GetVxDLocationList +VMM_Service VMM_GetDDBList +VMM_Service Unhook_NMI_Event +VMM_Service Get_Instanced_V86_Int_Vector +VMM_Service Get_Set_Real_DOS_PSP +GSRDP_Set EQU 0001H +VMM_Service Call_Priority_Thread_Event +VMM_Service Get_System_Time_Address +VMM_Service Get_Crit_Status_Thread +VMM_Service Get_DDB +VMM_Service Directed_Sys_Control +VMM_Service _RegOpenKey +VMM_Service _RegCloseKey +VMM_Service _RegCreateKey +VMM_Service _RegDeleteKey +VMM_Service _RegEnumKey +VMM_Service _RegQueryValue +VMM_Service _RegSetValue +VMM_Service _RegDeleteValue +VMM_Service _RegEnumValue +VMM_Service _RegQueryValueEx +VMM_Service _RegSetValueEx +ifndef REG_SZ +REG_SZ EQU 0001H +REG_BINARY EQU 0003H +endif +ifndef HKEY_LOCAL_MACHINE +HKEY_CLASSES_ROOT EQU 80000000H +HKEY_CURRENT_USER EQU 80000001H +HKEY_LOCAL_MACHINE EQU 80000002H +HKEY_USERS EQU 80000003H +HKEY_PERFORMANCE_DATA EQU 80000004H +HKEY_CURRENT_CONFIG EQU 80000005H +HKEY_DYN_DATA EQU 80000006H +endif +VMM_Service _CallRing3 +VMM_Service Exec_PM_Int +VMM_Service _RegFlushKey +VMM_Service _PageCommitContig +VMM_Service _GetCurrentContext +VMM_Service _LocalizeSprintf +VMM_Service _LocalizeStackSprintf +VMM_Service Call_Restricted_Event +VMM_Service Cancel_Restricted_Event +VMM_Service Register_PEF_Provider, VMM_ICODE +VMM_Service _GetPhysPageInfo +VMM_Service _RegQueryInfoKey +VMM_Service MemArb_Reserve_Pages +PHYSINFO_NONE EQU 0 +PHYSINFO_SOME EQU 1 +PHYSINFO_ALL EQU 2 +VMM_Service Time_Slice_Sys_VM_Idle +VMM_Service Time_Slice_Sleep +VMM_Service Boost_With_Decay +VMM_Service Set_Inversion_Pri +VMM_Service Reset_Inversion_Pri +VMM_Service Release_Inversion_Pri +VMM_Service Get_Thread_Win32_Pri +VMM_Service Set_Thread_Win32_Pri +VMM_Service Set_Thread_Static_Boost +VMM_Service Set_VM_Static_Boost +VMM_Service Release_Inversion_Pri_ID +VMM_Service Attach_Thread_To_Group +VMM_Service Detach_Thread_From_Group +VMM_Service Set_Group_Static_Boost +VMM_Service _GetRegistryPath, VMM_ICODE +VMM_Service _GetRegistryKey +REGTYPE_ENUM EQU 0 +REGTYPE_CLASS EQU 1 +REGTYPE_VXD EQU 2 +REGKEY_OPEN EQU 0 +REGKEY_CREATE_IFNOTEXIST EQU 1 +ASSERT_RANGE_NULL_BAD EQU 00000000H +ASSERT_RANGE_NULL_OK EQU 00000001H +ASSERT_RANGE_NO_DEBUG EQU 80000000H +ASSERT_RANGE_BITS EQU 80000001H +VMM_Service Cleanup_Thread_State +VMM_Service _RegRemapPreDefKey +VMM_Service End_V86_Serialization +VMM_Service _Assert_Range +VMM_Service _Sprintf +VMM_Service _PageChangePager +VMM_Service _RegCreateDynKey +VMM_Service _RegQueryMultipleValues +VMM_Service Boost_Thread_With_VM +BOOT_CLEAN EQU 00000001H +BOOT_DOSCLEAN EQU 00000002H +BOOT_NETCLEAN EQU 00000004H +BOOT_INTERACTIVE EQU 00000008H +VMM_Service Get_Boot_Flags +VMM_Service Set_Boot_Flags +VMM_Service _lstrcpyn +VMM_Service _lstrlen +VMM_Service _lmemcpy +VMM_Service _GetVxDName +VMM_Service Force_Mutexes_Free +VMM_Service Restore_Forced_Mutexes +VMM_Service _AddReclaimableItem +VMM_Service _SetReclaimableItem +VMM_Service _EnumReclaimableItem +VMM_Service Time_Slice_Wake_Sys_VM +VMM_Service VMM_Replace_Global_Environment +VMM_Service Begin_Non_Serial_Nest_V86_Exec +VMM_Service Get_Nest_Exec_Status +VMM_Service Open_Boot_Log +VMM_Service Write_Boot_Log +VMM_Service Close_Boot_Log +VMM_Service EnableDisable_Boot_Log +VMM_Service _Call_On_My_Stack +VMM_Service Get_Inst_V86_Int_Vec_Base +VMM_Service _lstrcmpi +VMM_Service _strupr +VMM_Service Log_Fault_Call_Out +VMM_Service _AtEventTime +endif +End_Service_Table VMM, VMM +RS_RECLAIM EQU 00000001H +RS_RESTORE EQU 00000002H +RS_DOSARENA EQU 00000004H + +ReclaimStruc STRUC +RS_Linear DD ? +RS_Bytes DD ? +RS_CallBack DD ? +RS_RefData DD ? +RS_HookTable DD ? +RS_Flags DD ? +ReclaimStruc ENDS + +frmtx STRUC +frmtx_pfrmtxNext DD ? +frmtx_hmutex DD ? +frmtx_cEnterCount DD ? +frmtx_pthcbOwner DD ? +frmtx_htimeout DD ? +frmtx ENDS + +vmmfrinfo STRUC +vmmfrinfo_frmtxDOS DB SIZE frmtx DUP (?) +vmmfrinfo_frmtxV86 DB SIZE frmtx DUP (?) +vmmfrinfo_frmtxOther DB SIZE frmtx DUP (?) +vmmfrinfo ENDS + +DemandInfoStruc STRUC +DILin_Total_Count DD ? +DIPhys_Count DD ? +DIFree_Count DD ? +DIUnlock_Count DD ? +DILinear_Base_Addr DD ? +DILin_Total_Free DD ? +DIPage_Faults DD ? +DIPage_Ins DD ? +DIPage_Outs DD ? +DIPage_Discards DD ? +DIInstance_Faults DD ? +DIPagingFileMax DD ? +DIPagingFileInUse DD ? +DICommit_Count DD ? +DIReserved DD 2 DUP (?) +DemandInfoStruc ENDS + +InstDataStruc STRUC +InstLinkF DD 0 +InstLinkB DD 0 +InstLinAddr DD ? +InstSize DD ? +InstType DD ? +InstDataStruc ENDS +INDOS_FIELD EQU 100H +ALWAYS_FIELD EQU 200H +OPTIONAL_FIELD EQU 400H + +IPF_Data STRUC +IPF_LinAddr DD ? +IPF_MapPageNum DD ? +IPF_PTEEntry DD ? +IPF_FaultingVM DD ? +IPF_Flags DD ? +IPF_Data ENDS + +Exception_Handler_Struc STRUC +EH_Reserved DD ? +EH_Start_EIP DD ? +EH_End_EIP DD ? +EH_Handler DD ? +Exception_Handler_Struc ENDS +PR_PRIVATE EQU 80000400H +PR_SHARED EQU 80060000H +PR_SYSTEM EQU 80080000H +PR_FIXED EQU 00000008H +PR_4MEG EQU 00000001H +PR_STATIC EQU 00000010H +PD_ZEROINIT EQU 00000001H +PD_NOINIT EQU 00000002H +PD_FIXEDZERO EQU 00000003H +PD_FIXED EQU 00000004H +PC_FIXED EQU 00000008H +PC_LOCKED EQU 00000080H +PC_LOCKEDIFDP EQU 00000100H +PC_WRITEABLE EQU 00020000H +PC_USER EQU 00040000H +PC_INCR EQU 40000000H +PC_PRESENT EQU 80000000H +PC_STATIC EQU 20000000H +PC_DIRTY EQU 08000000H +PCC_ZEROINIT EQU 00000001H +PCC_NOLIN EQU 10000000H +ifndef _WINNT_ + +_MEMORY_BASIC_INFORMATION STRUC +mbi_BaseAddress DD ? +mbi_AllocationBase DD ? +mbi_AllocationProtect DD ? +mbi_RegionSize DD ? +mbi_State DD ? +mbi_Protect DD ? +mbi_Type DD ? +_MEMORY_BASIC_INFORMATION ENDS +PAGE_NOACCESS EQU 01H +PAGE_READONLY EQU 02H +PAGE_READWRITE EQU 04H +MEM_COMMIT EQU 1000H +MEM_RESERVE EQU 2000H +MEM_FREE EQU 10000H +MEM_PRIVATE EQU 20000H +endif + +pd_s STRUC +pd_virginin DD ? +pd_taintedin DD ? +pd_cleanout DD ? +pd_dirtyout DD ? +pd_virginfree DD ? +pd_taintedfree DD ? +pd_dirty DD ? +pd_type DD ? +pd_s ENDS +PD_SWAPPER EQU 0 +PD_PAGERONLY EQU 1 +PD_NESTEXEC EQU 2 +endif +PAGESHIFT EQU 12 +PAGESIZE EQU (1 SHL PAGESHIFT) +PAGEMASK EQU (PAGESIZE-1) +MAXSYSTEMLADDR EQU (0ffbfffffH) +MINSYSTEMLADDR EQU (0c0000000H) +MAXSHAREDLADDR EQU (0bfffffffH) +MINSHAREDLADDR EQU (80000000H) +MAXPRIVATELADDR EQU (7fffffffH) +MINPRIVATELADDR EQU (00400000H) +MAXDOSLADDR EQU (003fffffH) +MINDOSLADDR EQU (00000000H) +MAXSYSTEMPAGE EQU (MAXSYSTEMLADDR SHR PAGESHIFT) +MINSYSTEMPAGE EQU (MINSYSTEMLADDR SHR PAGESHIFT) +MAXSHAREDPAGE EQU (MAXSHAREDLADDR SHR PAGESHIFT) +MINSHAREDPAGE EQU (MINSHAREDLADDR SHR PAGESHIFT) +MAXPRIVATEPAGE EQU (MAXPRIVATELADDR SHR PAGESHIFT) +MINPRIVATEPAGE EQU (MINPRIVATELADDR SHR PAGESHIFT) +MAXDOSPAGE EQU (MAXDOSLADDR SHR PAGESHIFT) +MINDOSPAGE EQU (MINDOSLADDR SHR PAGESHIFT) +CBPRIVATE EQU (1+MAXPRIVATELADDR-MINPRIVATELADDR) +CBSHARED EQU (1+MAXSHAREDLADDR-MINSHAREDLADDR) +CBSYSTEM EQU (1+MAXSYSTEMLADDR-MINSYSTEMLADDR) +CBDOS EQU (1+MAXDOSLADDR-MINDOSLADDR) +CPGPRIVATE EQU (1+MAXPRIVATEPAGE-MINPRIVATEPAGE) +CPGSHARED EQU (1+MAXSHAREDPAGE-MINSHAREDPAGE) +CPGSYSTEM EQU (1+MAXSYSTEMPAGE-MINSYSTEMPAGE) +CPGDOS EQU (1+MAXDOSPAGE-MINDOSPAGE) +IFDEF DEBUG +DebFar EQU NEAR PTR +ELSE +DebFar EQU SHORT +ENDIF + +ifndef Not_VxD +SYS_CRITICAL_INIT EQU 0000H +DEVICE_INIT EQU 0001H +INIT_COMPLETE EQU 0002H +SYS_VM_INIT EQU 0003H +SYS_VM_TERMINATE EQU 0004H +SYSTEM_EXIT EQU 0005H +SYS_CRITICAL_EXIT EQU 0006H +CREATE_VM EQU 0007H +VM_CRITICAL_INIT EQU 0008H +VM_INIT EQU 0009H +VM_TERMINATE EQU 000AH +VM_NOT_EXECUTEABLE EQU 000BH +DESTROY_VM EQU 000CH +VNE_CRASHED_BIT EQU 00H +VNE_CRASHED EQU (1 SHL VNE_CRASHED_BIT) +VNE_NUKED_BIT EQU 01H +VNE_NUKED EQU (1 SHL VNE_NUKED_BIT) +VNE_CREATEFAIL_BIT EQU 02H +VNE_CREATEFAIL EQU (1 SHL VNE_CREATEFAIL_BIT) +VNE_CRINITFAIL_BIT EQU 03H +VNE_CRINITFAIL EQU (1 SHL VNE_CRINITFAIL_BIT) +VNE_INITFAIL_BIT EQU 04H +VNE_INITFAIL EQU (1 SHL VNE_INITFAIL_BIT) +VNE_CLOSED_BIT EQU 05H +VNE_CLOSED EQU (1 SHL VNE_CLOSED_BIT) +VM_SUSPEND EQU 000DH +VM_RESUME EQU 000EH +SET_DEVICE_FOCUS EQU 000FH +BEGIN_MESSAGE_MODE EQU 0010H +END_MESSAGE_MODE EQU 0011H +REBOOT_PROCESSOR EQU 0012H +QUERY_DESTROY EQU 0013H +DEBUG_QUERY EQU 0014H +BEGIN_PM_APP EQU 0015H +BPA_32_BIT EQU 01H +BPA_32_BIT_FLAG EQU 1 +END_PM_APP EQU 0016H +DEVICE_REBOOT_NOTIFY EQU 0017H +CRIT_REBOOT_NOTIFY EQU 0018H +CLOSE_VM_NOTIFY EQU 0019H +CVNF_CRIT_CLOSE_BIT EQU 0 +CVNF_CRIT_CLOSE EQU (1 SHL CVNF_CRIT_CLOSE_BIT) +POWER_EVENT EQU 001AH +SYS_DYNAMIC_DEVICE_INIT EQU 001BH +SYS_DYNAMIC_DEVICE_EXIT EQU 001CH +CREATE_THREAD EQU 001DH +THREAD_INIT EQU 001EH +TERMINATE_THREAD EQU 001FH +THREAD_Not_Executeable EQU 0020H +DESTROY_THREAD EQU 0021H +PNP_NEW_DEVNODE EQU 0022H +W32_DEVICEIOCONTROL EQU 0023H +DIOC_GETVERSION EQU 0H +DIOC_OPEN EQU DIOC_GETVERSION +DIOC_CLOSEHANDLE EQU -1 +SYS_VM_TERMINATE2 EQU 0024H +SYSTEM_EXIT2 EQU 0025H +SYS_CRITICAL_EXIT2 EQU 0026H +VM_TERMINATE2 EQU 0027H +VM_NOT_EXECUTEABLE2 EQU 0028H +DESTROY_VM2 EQU 0029H +VM_SUSPEND2 EQU 002AH +END_MESSAGE_MODE2 EQU 002BH +END_PM_APP2 EQU 002CH +DEVICE_REBOOT_NOTIFY2 EQU 002DH +CRIT_REBOOT_NOTIFY2 EQU 002EH +CLOSE_VM_NOTIFY2 EQU 002FH +GET_CONTENTION_HANDLER EQU 0030H +KERNEL32_INITIALIZED EQU 0031H +KERNEL32_SHUTDOWN EQU 0032H +MAX_SYSTEM_CONTROL EQU 0032H +BEGIN_RESERVED_PRIVATE_SYSTEM_CONTROL EQU 70000000H +END_RESERVED_PRIVATE_SYSTEM_CONTROL EQU 7FFFFFFFH +endif +SYSSTATE_PRESYSCRITINIT EQU 00000000H +SYSSTATE_PREDEVICEINIT EQU 10000000H +SYSSTATE_PREINITCOMPLETE EQU 20000000H +SYSSTATE_VXDINITCOMPLETED EQU 40000000H +SYSSTATE_KERNEL32INITED EQU 50000000H +SYSSTATE_KERNEL32TERMINATED EQU 0A0000000H +SYSSTATE_PRESYSVMTERMINATE EQU 0B0000000H +SYSSTATE_PRESYSTEMEXIT EQU 0E0000000H +SYSSTATE_PRESYSTEMEXIT2 EQU 0E4000000H +SYSSTATE_PRESYSCRITEXIT EQU 0F0000000H +SYSSTATE_PRESYSCRITEXIT2 EQU 0F4000000H +SYSSTATE_POSTSYSCRITEXIT2 EQU 0FFF00000H +SYSSTATE_PREDEVICEREBOOT EQU 0FFFF0000H +SYSSTATE_PRECRITREBOOT EQU 0FFFFF000H +SYSSTATE_PREREBOOTCPU EQU 0FFFFFF00H +BeginDoc + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EndDoc + + + + + + + + + + + + +??_pf_Check equ 1 +??_pf_ArgsUsed equ 2 +??_pf_Entered equ 4 +??_pf_Left equ 8 +??_pf_Returned equ 16 + +??_pushed = 0 +??_align = 0 +??_ends equ <> + +BeginProc macro Name, P1, P2, P3, P4, P5, P6, P7, LastArg + local Profile_Data, prelabeldata, ??_hookvar + ??_frame = 0 + ??_aframe = 0 + ??_initaframe = 0 + ??_numargs = 0 + ??_numlocals = 0 + ??_numlocalsymbols = 0 + ??_procflags = 0 + ??_esp = 0 + ??_pushed = 0 + ??_align = 0 + ??_hook = 0 + ??_hookarg = 0 + ??_service = 0 + ??_async_service = 0 +IF DEBLEVEL GT DEBLEVELNORMAL + ??_log = DFS_LOG + ??_profile = DFS_PROFILE + ??_test_cld = DFS_TEST_CLD +ELSE + ??_log = 0 +IFDEF DEBUG +IFDEF profileall +IF ?_ICODE + ??_profile = DFS_PROFILE +ELSE + ??_profile = 0 +ENDIF +ELSE + ??_profile = 0 +ENDIF +ELSE + ??_profile = 0 +ENDIF + ??_test_cld = 0 +ENDIF + ??_might_block = 0 + ??_test_reenter = 0 + ??_never_reenter = 0 + ??_not_swapping = 0 + ??_prolog_disabled = 0 + ??_public = 1 + ??_cleanoff = 0 + ??_ccall = 0 + ??_pcall = 0 + ??_scall = 0 + ??_w32svc = 0 + ??_fleave = FALSE + + ??_name equ + + .errnb ??_ends, + .errnb , + + + irp arg, + if ??_hookarg + ??_hookarg = 0 + ??_hookvar equ + elseifdef ?&&arg&&_BeginProc + ?&&arg&&_BeginProc + elseifdef VxD_&&arg&&_CODE_SEG + ??_ends textequ + VxD_&&arg&&_CODE_SEG + else + .err + endif + endm + + + ifndef Not_VxD + ife ??_service + ifndef profileall + ??_profile = 0 + endif + ifdef VMMSYS + ??_prolog_disabled = 1 + endif + else + ??_test_cld = DFS_TEST_CLD + endif + + ife ?_16ICODE + ??_prolog_disabled = 1 + else + ife ?_RCODE + ??_prolog_disabled = 1 + else + ife ?_PCODE + ??_might_block = DFS_TEST_BLOCK + endif + if ??_service + ife ??_async_service + ??_test_reenter = DFS_TEST_REENTER + endif + endif + endif + endif + endif + + if ??_esp + + ??_basereg equ + ??_initaframe = 4 + else + + ??_basereg equ + ??_initaframe = 8 + endif + @Caller equ + + ??_cleanoff = ??_pcall or ??_scall + + + ??_dfs = ??_never_reenter + ??_test_reenter + ??_not_swapping + \ + ??_log + ??_profile + ??_test_cld + ??_might_block + + if ??_prolog_disabled + ??_dfs = 0 + endif + + + + ifndef Not_VxD + + if ??_hook + if ??_align + Dword_Align + endif + prelabeldata: + ifndef ??_hookvar + .err + endif + jmp short Name + jmp [??_hookvar] + ifdef DEBUG + Profile_Data dd 0 + endif + if ??_align + .errnz ($ - prelabeldata) mod 4 + endif + endif + + ifdef DEBUG + ?prolog_&Name label near + if (??_service OR ??_profile) AND (??_hook EQ 0) + jmp short Name + if ??_align + Dword_Align + endif + + IF ?_ICODE + ifdef profileall + ?ProfileHeader_BeginProc Profile_Data, %@filename + else + Profile_Data dd 0 + endif + ELSE + Profile_Data dd 0 + ENDIF + + endif + endif + + if ??_align + Dword_Align + endif + + endif + + Name proc near + + + + ife ??_pcall or ??_ccall or ??_scall + if ??_public + public Name + else + ifdef DEBUG + % ?merge @FileName,$,Name,: + % ?merge public,,,,,@FileName,$,Name + endif + endif + endif + if ??_ccall + if ??_public + _&Name equ Name + ifdef Not_VxD + public C Name + else + public _&Name + endif + endif + endif + if ??_pcall + if ??_public + ?toupper Name + ?merge public,,,,%?upper + endif + endif + + + ifndef Not_VxD + ifdef DEBUG + if ??_dfs EQ DFS_LOG + VMMCall Log_Proc_Call + else + if ??_dfs EQ DFS_TEST_REENTER + VMMCall Test_Reenter + else + if ??_dfs or ?_LOCKABLECODE eq 0 + ifdef WIN31COMPAT + if ??_dfs AND DFS_LOG + VMMCall Log_Proc_Call + endif + if ??_dfs AND DFS_TEST_REENTER + VMMCall Test_Reenter + endif + else + ife ?_LOCKABLECODE + ifdef ??_debug_flags + push ??_debug_flags + if ??_dfs + pushfd + or dword ptr [esp+4],??_dfs + popfd + endif + VMMCall _Debug_Flags_Service + elseif ??_dfs + push ??_dfs + VMMCall _Debug_Flags_Service + endif + else + push ??_dfs + VMMCall _Debug_Flags_Service + endif + endif + else + ifdef profileall + IncProfileCount + endif + endif + endif + endif + endif + endif + + + +endm + + + + + + +?_BeginProc macro +endm + +?PUBLIC_BeginProc macro + ??_public = 1 +endm + +?LOCAL_BeginProc macro + ??_public = 0 +endm + +?HIGH_FREQ_BeginProc macro + ??_align = 1 +endm + +?HOOK_PROC_BeginProc macro + ??_hook = 1 + ??_hookarg = 1 +endm + +?SERVICE_BeginProc macro + ??_service = 1 + .erre ?_16ICODE, + .erre ?_RCODE, +endm + +?ASYNC_SERVICE_BeginProc macro + ??_service = 1 + ??_async_service = 1 + .errnz ?_LCODE, +endm + +?NO_LOG_BeginProc macro + ??_log = 0 +endm + +?NO_PROFILE_BeginProc macro + ??_profile = 0 +endm + +?NO_TEST_CLD_BeginProc macro + ??_test_cld = 0 +endm + +?TEST_BLOCK_BeginProc macro + ??_might_block = DFS_TEST_BLOCK +endm + +?TEST_REENTER_BeginProc macro + ??_test_reenter = DFS_TEST_REENTER +endm + +?NEVER_REENTER_BeginProc macro + ??_never_reenter = DFS_NEVER_REENTER +endm + +?NOT_SWAPPING_BeginProc macro + ??_not_swapping = DFS_NOT_SWAPPING +endm + +?NO_PROLOG_BeginProc macro + ??_prolog_disabled = 1 +endm + +?ESP_BeginProc macro + ??_esp = VMM_TRUE + ifndef Not_VxD + .erre ?_16ICODE, + .erre ?_RCODE, + endif +endm + +?CCALL_BeginProc macro + ??_ccall = 1 +endm + +?PCALL_BeginProc macro + ??_pcall = 1 +endm + +?SCALL_BeginProc macro + ??_scall = 1 +endm + +?ICALL_BeginProc macro + ??_scall = 1 +endm + +?W32SVC_BeginProc macro + ??_scall = 1 + ??_w32svc = 1 +endm + +ifdef DEBUG +ifdef profileall +?ProfileHeader_BeginProc macro PL, filename +ifndef _&filename&__proc_list + _&filename&__proc_list = 0 + PUBLIC _&filename&__proc_list +endif + dd OFFSET32 _&filename&__proc_list +PL dd 0 +_&filename&__proc_list = PL +endm +endif + +IncProfileCount macro + if ??_service OR ??_profile + inc dword ptr [??_name-4] + else + ifndef profileall + .err + endif + endif +endm +else +IncProfileCount macro +endm +endif + + + + + + + + + + + + + + + + +ArgVar macro name,length,used + ??_numargs = ??_numargs + 1 + if ??_pcall + ?mkarg , , , %??_numargs + else + ?argvar , , + endif + ??_procflags = ??_procflags OR ??_pf_Check + endm + +?mkarg macro name, length, used, num + .xcref ?MKA&num + ?deflocal + ?MKA&num ¯o + ?argvar , , + &endm + ??_aframe = ??_aframe + 4 + endm + .xcref ?mkarg + +?argvar macro name,length,used + local a + ifidni , + a = ??_aframe + ??_aframe = ??_aframe + 4 + ?setname , , + elseifidni , + a = ??_aframe + ??_aframe = ??_aframe + 4 + ?setname , , + elseifidni , + a = ??_aframe + ??_aframe = ??_aframe + 4 + ?setname , , + ?setname ,, + ?setname ,, + ?setname ,, + ?setname ,, + ?setname ,, + ?setname ,, + else + a = ??_aframe + ??_aframe = ??_aframe + ((length + 3)/4)*4 + ?setname , <[??_basereg+??_initaframe+a]>, + endif +endm + + + + + + +?setname macro name, value, used + ?deflocal + ifidni , + name equ _inaccessible_NOTUSED_ + else + name equ value + ??_procflags = ??_procflags OR ??_pf_ArgsUsed OR ??_pf_Check + endif +endm + + + + + + + + + + + + + + + + + + + +LocalVar macro name,length,flag + local a + ??_numlocals = ??_numlocals + 1 + ??_pad = 1 + ifidni , + ??_pad = 0 + endif + ifidni , + ??_frame = ??_frame + 1 + 3 * ??_pad + a = ??_frame + ?deflocal + name equ byte ptr [??_basereg-a] + elseifidni , + ??_frame = ??_frame + 2 + 2 * ??_pad + a = ??_frame + ?deflocal + name equ word ptr [??_basereg-a] + elseifidni , + ??_frame = ??_frame + 4 + a = ??_frame + ?deflocal + name equ dword ptr [??_basereg-a] + name&l equ word ptr [??_basereg-a] + name&ll equ byte ptr [??_basereg-a] + name&lh equ byte ptr [??_basereg-a+1] + name&h equ word ptr [??_basereg-a+2] + name&hl equ byte ptr [??_basereg-a+2] + name&hh equ byte ptr [??_basereg-a+3] + else + ??_frame = ??_frame + ((length + 3)/4)*4 + a = ??_frame + ?deflocal + name equ [??_basereg-a] + endif + ??_procflags = ??_procflags OR ??_pf_Check +endm + +?deflocal macro name + irp nm, + ??_numlocalsymbols = ??_numlocalsymbols + 1 + ?dodeflocal , %(??_numlocalsymbols) + endm +endm + .xcref ?deflocal + +?dodeflocal macro name, num + .xcref ?LOC&num + ?LOC&num ¯o + name equ <__inaccessible__NOTINSCOPE__> + &endm + endm + .xcref ?dodeflocal + + + +EnterProc macro + .errnz ??_frame and 3, + if ??_scall + if ??_public + ifdef Not_VxD + ?merge %??_name,@,%(??_aframe),,label,near + ?merge public,,,,C,%??_name,@,%(??_aframe) + else + ?merge _,%??_name,@,%(??_aframe),label,near + ?merge public,,,,,_,%??_name,@,%(??_aframe) + endif + endif + endif + if ??_pcall + ??_aframe = 0 + ?count = ??_numargs + rept ??_numargs + ?invprg ,%?count + ?count = ?count - 1 + endm + endif + ??_fleave = FALSE + if ??_esp + if ??_frame + sub esp, ??_frame + ??_pushed = ??_pushed + ??_frame + ??_fleave = VMM_TRUE + endif + else + if ??_frame eq 0 + if (??_aframe eq 0) OR ((??_procflags AND ??_pf_ArgsUsed) EQ 0) + ifdef DEBUG + push ebp + mov ebp,esp + ??_fleave = VMM_TRUE + endif + else + push ebp + mov ebp,esp + ??_fleave = VMM_TRUE + endif + else + enter ??_frame, 0 + ??_fleave = VMM_TRUE + endif + endif + ??_procflags = ??_procflags OR ??_pf_Entered +endm + + + + + + + + + + + + + + + +LeaveProc macro flags + if ??_fleave + if ??_esp + ifidni , + lea esp,[esp + ??_frame] + else + add esp,??_frame + endif + else + leave + endif + endif + ??_procflags = ??_procflags OR ??_pf_Left +endm + + + + + + + +Return macro + if ??_cleanoff OR ??_w32svc + if ??_w32svc AND (??_aframe LT 8) + ret 8 + else + ret ??_aframe + endif + else + ret + endif + ??_procflags = ??_procflags OR ??_pf_Returned + endm + + + + +EndProc macro Name, Flag + Name endp +if ??_w32svc + if ??_aframe lt 8 + cparm&Name equ 0 + else + cparm&Name equ (??_aframe/4 - 2) + endif +endif +if ??_procflags AND ??_pf_Left +if ??_fleave +if ??_esp + ??_pushed = ??_pushed - ??_frame +endif +endif +endif +ifdifi , + if ??_pushed ne 0 + %out Warning: stack not balanced in Name + endif + if ??_procflags AND ??_pf_Check + ife ??_procflags AND ??_pf_Entered + %out Warning: ArgVar/LocalVar without EnterProc in Name + endif + ife ??_procflags AND ??_pf_Left + %out Warning: ArgVar/LocalVar without LeaveProc in Name + endif + ife ??_procflags AND ??_pf_Returned + %out Warning: ArgVar/LocalVar without Return in Name + endif + endif +endif +ifdifi , + ?count = 0 + rept ??_numlocalsymbols + ?count = ?count + 1 + ?invprg ,%?count + endm +endif + ??_ends + ??_ends equ <> + endm + + + + + + + +cCall macro name, arglst, flags + ife .TYPE name + CondExtern name, near + endif + PushCParams , + call name + ClearCParams + endm + .xcref cCall + + + + + + +pCall macro name, arglst + local ??saved + ife .TYPE name + ?toupper name + else + ?upper equ + endif + CondExtern %?upper, near + ??saved = ??_pushed + irp x, + push x + ??_pushed = ??_pushed + 4 + endm + call ?upper + ??_pushed = ??saved + endm + .xcref pCall + + + + + + + +sCall macro name, arglst + local ??saved + ??saved = ??_pushed + PushCParams + ?scall name, %(??_argc * 4) + ??_pushed = ??saved + endm + .xcref sCall + + + + + +iCall equ + + + + + + + + + + + + + + +IFNDEF STANDARD_CCALL +NONSTANDARD_CCALL = 1 +ENDIF + +PushCParams macro arglst, flags + ??_argc = 0 +IFDEF NONSTANDARD_CCALL + ??_popargs = 0 +ELSE + ??_popargs = ??_align EQ 0 +ENDIF + ifidni , + ??_popargs = 1 + elseifidni , + ??_popargs = 0 + endif + + irp x, + ??_argc = ??_argc + 1 + ?marg ,%??_argc + endm + ?count = ??_argc + rept ??_argc + ?invprg ,%?count + ?count = ?count - 1 + endm + endm + + + + + + + + + + + + + + + + +ClearCParams macro fPreserveFlags + if ??_argc ne 0 + if (??_popargs) AND (??_argc LE 2) + rept ??_argc + pop ecx + endm + else + ifidni , + lea esp, [esp][??_argc * 4] + else + add esp,??_argc * 4 + endif + endif + endif + ??_pushed = ??_pushed - (??_argc * 4) + endm + + + +?marg macro name, num + .xcref + .xcref ?AM&num + .cref + ?AM&num ¯o + push name + ??_pushed = ??_pushed + 4 + &endm + endm + .xcref ?marg + + + +?invprg macro name1, name2 + name1&name2 + purge name1&name2 + endm + .xcref ?invprg + + + +?scall macro name1, name2 + CondExtern _&name1&@&name2, near + call _&name1&@&name2 + endm + .xcref ?scall + + + +?merge macro l1, l2, l3, l4, op, r1, r2, r3, r4, r5, r6, r7, r8, r9 + l1&l2&l3&l4 op r1&r2&r3&r4&r5&r6&r7&r8&r9 + endm + + + +?toupper macro s + ?upper equ <> + irpc x, + if '&x' GE 'a' + if '&x' LE 'z' + ?t1 substr ,'&x'-'a'+1,1 + ?upper catstr ?upper,?t1 + else + ?upper catstr ?upper,<&x> + endif + else + ?upper catstr ?upper,<&x> + endif + endm + endm + .xcref + + + + + + +CondExtern macro name,dist + ifdef MASM6 + ifndef name + externdef name:dist + endif + else + if2 + ifndef name + extrn name:dist + endif + endif + endif +endm + + + +SaveReg macro reglist + irp reg, + ifidni , + pushfd + ??_pushed = ??_pushed + 4 + else + ifidni , + pushad + ??_pushed = ??_pushed + SIZE Pushad_Struc + else + push reg + ??_pushed = ??_pushed + 4 + endif + endif + endm +endm + + + + + + + +RestoreReg macro reglist + irp reg, + ifidni , + popfd + ??_pushed = ??_pushed - 4 + else + ifidni , + popad + ??_pushed = ??_pushed - SIZE Pushad_Struc + else + pop reg + ??_pushed = ??_pushed - 4 + endif + endif + endm +endm + +ifdef DEBUG +Begin_Profile_List macro devname +ifdef profileall +VxD_DATA_SEG + db 'PROCLIST' +PUBLIC devname&_Proc_Profile_List +devname&_Proc_Profile_List label dword +endif +endm + +Profile_Link macro modname +ifdef profileall +ifdifi ,@filename +EXTRN _&modname&__proc_list:near +endif + dd OFFSET32 _&modname&__proc_list +endif +endm + +End_Profile_List macro +ifdef profileall + dd 0 +VxD_DATA_ENDS +endif +endm + + +endif +ifndef Not_VxD +RESERVED_LOW_BOOST EQU 00000001H +CUR_RUN_VM_BOOST EQU 00000004H +LOW_PRI_DEVICE_BOOST EQU 00000010H +HIGH_PRI_DEVICE_BOOST EQU 00001000H +CRITICAL_SECTION_BOOST EQU 00100000H +TIME_CRITICAL_BOOST EQU 00400000H +RESERVED_HIGH_BOOST EQU 40000000H +PEF_WAIT_FOR_STI_BIT EQU 0 +PEF_WAIT_FOR_STI EQU (1 SHL PEF_WAIT_FOR_STI_BIT) +PEF_WAIT_NOT_CRIT_BIT EQU 1 +PEF_WAIT_NOT_CRIT EQU (1 SHL PEF_WAIT_NOT_CRIT_BIT) +PEF_DONT_UNBOOST_BIT EQU 2 +PEF_DONT_UNBOOST EQU (1 SHL PEF_DONT_UNBOOST_BIT) +PEF_ALWAYS_SCHED_BIT EQU 3 +PEF_ALWAYS_SCHED EQU (1 SHL PEF_ALWAYS_SCHED_BIT) +PEF_TIME_OUT_BIT EQU 4 +PEF_TIME_OUT EQU (1 SHL PEF_TIME_OUT_BIT) +PEF_WAIT_NOT_HW_INT_BIT EQU 5 +PEF_WAIT_NOT_HW_INT EQU (1 SHL PEF_WAIT_NOT_HW_INT_BIT) +PEF_WAIT_NOT_NESTED_EXEC_BIT EQU 6 +PEF_WAIT_NOT_NESTED_EXEC EQU (1 SHL PEF_WAIT_NOT_NESTED_EXEC_BIT) +PEF_WAIT_IN_PM_BIT EQU 7 +PEF_WAIT_IN_PM EQU (1 SHL PEF_WAIT_IN_PM_BIT) +PEF_THREAD_EVENT_BIT EQU 8 +PEF_THREAD_EVENT EQU (1 SHL PEF_THREAD_EVENT_BIT) +PEF_WAIT_FOR_THREAD_STI_BIT EQU 9 +PEF_WAIT_FOR_THREAD_STI EQU (1 SHL PEF_WAIT_FOR_THREAD_STI_BIT) +PEF_RING0_EVENT_BIT EQU 10 +PEF_RING0_EVENT EQU (1 SHL PEF_RING0_EVENT_BIT) +PEF_WAIT_CRIT_BIT EQU 11 +PEF_WAIT_CRIT EQU (1 SHL PEF_WAIT_CRIT_BIT) +PEF_WAIT_CRIT_VM_BIT EQU 12 +PEF_WAIT_CRIT_VM EQU (1 SHL PEF_WAIT_CRIT_VM_BIT) +PEF_PROCESS_LAST_BIT EQU 13 +PEF_PROCESS_LAST EQU (1 SHL PEF_PROCESS_LAST_BIT) +PEF_WAIT_NOT_TIME_CRIT_BIT EQU PEF_WAIT_NOT_HW_INT_BIT +PEF_WAIT_NOT_TIME_CRIT EQU PEF_WAIT_NOT_HW_INT +PEF_WAIT_NOT_PM_LOCKED_STACK_BIT EQU PEF_WAIT_NOT_NESTED_EXEC_BIT +PEF_WAIT_NOT_PM_LOCKED_STACK EQU PEF_WAIT_NOT_NESTED_EXEC +BLOCK_SVC_INTS_BIT EQU 0 +BLOCK_SVC_INTS EQU (1 SHL BLOCK_SVC_INTS_BIT) +BLOCK_SVC_IF_INTS_LOCKED_BIT EQU 1 +BLOCK_SVC_IF_INTS_LOCKED EQU (1 SHL BLOCK_SVC_IF_INTS_LOCKED_BIT) +BLOCK_ENABLE_INTS_BIT EQU 2 +BLOCK_ENABLE_INTS EQU (1 SHL BLOCK_ENABLE_INTS_BIT) +BLOCK_POLL_BIT EQU 3 +BLOCK_POLL EQU (1 SHL BLOCK_POLL_BIT) +BLOCK_THREAD_IDLE_BIT EQU 4 +BLOCK_THREAD_IDLE EQU (1 SHL BLOCK_THREAD_IDLE_BIT) +BLOCK_FORCE_SVC_INTS_BIT EQU 5 +BLOCK_FORCE_SVC_INTS EQU (1 SHL BLOCK_FORCE_SVC_INTS_BIT) + +Client_Reg_Struc STRUC +Client_EDI DD ? +Client_ESI DD ? +Client_EBP DD ? +Client_res0 DD ? +Client_EBX DD ? +Client_EDX DD ? +Client_ECX DD ? +Client_EAX DD ? +Client_Error DD ? +Client_EIP DD ? +Client_CS DW ? +Client_res1 DW ? +Client_EFlags DD ? +Client_ESP DD ? +Client_SS DW ? +Client_res2 DW ? +Client_ES DW ? +Client_res3 DW ? +Client_DS DW ? +Client_res4 DW ? +Client_FS DW ? +Client_res5 DW ? +Client_GS DW ? +Client_res6 DW ? +Client_Alt_EIP DD ? +Client_Alt_CS DW ? +Client_res7 DW ? +Client_Alt_EFlags DD ? +Client_Alt_ESP DD ? +Client_Alt_SS DW ? +Client_res8 DW ? +Client_Alt_ES DW ? +Client_res9 DW ? +Client_Alt_DS DW ? +Client_res10 DW ? +Client_Alt_FS DW ? +Client_res11 DW ? +Client_Alt_GS DW ? +Client_res12 DW ? +Client_Reg_Struc ENDS + +Client_Word_Reg_Struc STRUC +Client_DI DW ? +Client_res13 DW ? +Client_SI DW ? +Client_res14 DW ? +Client_BP DW ? +Client_res15 DW ? +Client_res16 DD ? +Client_BX DW ? +Client_res17 DW ? +Client_DX DW ? +Client_res18 DW ? +Client_CX DW ? +Client_res19 DW ? +Client_AX DW ? +Client_res20 DW ? +Client_res21 DD ? +Client_IP DW ? +Client_res22 DW ? +Client_res23 DD ? +Client_Flags DW ? +Client_res24 DW ? +Client_SP DW ? +Client_res25 DW ? +Client_res26 DD 5 DUP (?) +Client_Alt_IP DW ? +Client_res27 DW ? +Client_res28 DD ? +Client_Alt_Flags DW ? +Client_res29 DW ? +Client_Alt_SP DW ? +Client_Word_Reg_Struc ENDS + +Client_Byte_Reg_Struc STRUC +Client_res30 DD 4 DUP (?) +Client_BL DB ? +Client_BH DB ? +Client_res31 DW ? +Client_DL DB ? +Client_DH DB ? +Client_res32 DW ? +Client_CL DB ? +Client_CH DB ? +Client_res33 DW ? +Client_AL DB ? +Client_AH DB ? +Client_Byte_Reg_Struc ENDS +?UnionSize = 0 +if size Client_Reg_Struc gt ?UnionSize + ?UnionSize = size Client_Reg_Struc +endif +CRS equ <(byte ptr 0)> + +if size Client_Word_Reg_Struc gt ?UnionSize + ?UnionSize = size Client_Word_Reg_Struc +endif +CWRS equ <(byte ptr 0)> + +if size Client_Byte_Reg_Struc gt ?UnionSize + ?UnionSize = size Client_Byte_Reg_Struc +endif +CBRS equ <(byte ptr 0)> + + +tagCLIENT_STRUC STRUC + DB ?UnionSize dup(?) +tagCLIENT_STRUC ENDS + +IF 0 +.ERRNZ Client_SP - Client_ESP +.ERRNZ Client_AL - Client_EAX + +endif +DYNA_LINK_INT EQU 20H + + + + + + + + + + + + +DeclareNonstandardCcallService macro arglst + irp x, + ??_nonstandardccall_&x = 1 + endm +endm + + + + + + + +DeclareNonstandardCcallService <_BlockOnID, _LocalizeSprintf> +DeclareNonstandardCcallService <_SetLastV86Page, _Assert_Range> + +BeginDoc + + + + + + + + + + + + + +EndDoc + + +BeginDoc + + + + + + + + +EndDoc + +DefTable MACRO vt, vn + vt EQU +ENDM + +GenDD2 MACRO vt, sn, jf + dd OFFSET32 vt[sn+jf] +ENDM + +GenDD MACRO P, vid, snum, jflag + LOCAL vtable +IFDEF @@VxDName&vid + Deftable vtable, %@@VxDName&vid + EXTRN vtable:DWORD + GenDD2 %vtable, snum, jflag +ELSE + dd @@&P+jflag +ENDIF + +ENDM + + +VxDCall MACRO P, Param, flags + ??_vxdid = (@@&P SHR 16) + ??_servicenum = (@@&P AND 0FFFFh) + ifdef ??_nonstandardccall_&P + PushCParams , + else + PushCParams , + endif + int Dyna_Link_Int + GenDD P, %??_vxdid, %??_servicenum, 0 + ifdef ??_nonstandardccall_&P + ClearCParams PRESERVE_FLAGS + else + ClearCParams + endif + ENDM + +VxDJmp MACRO P, Param + ??_vxdid = (@@&P SHR 16) + ??_servicenum = (@@&P AND 0FFFFh) + .errnb , + int Dyna_Link_Int + GenDD P, %??_vxdid, %??_servicenum, DL_Jmp_Mask + ENDM + +DL_Jmp_Mask EQU 8000h +DL_Jmp_Bit EQU 0Fh + +VMMCall MACRO P, Param + .ERRNZ (@@&P SHR 16) - VMM_DEVICE_ID + VxDCall

, + ENDM + +VMMJmp MACRO P, Param + .ERRNZ (@@&P SHR 16) - VMM_DEVICE_ID + VxDJmp

, + ENDM + +BeginDoc + + + + + + + + + + + + + + + + + + + + + + + + + + + + +EndDoc + + + + +VxD_CODE_SEG EQU +VxD_CODE_ENDS EQU + + +VxD_LOCKED_CODE_SEG MACRO +_LTEXT SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_LCODE + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + + ENDM + +VxD_LOCKED_CODE_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_LTEXT ENDS + ENDM + + + + +VxD_PAGEABLE_CODE_SEG MACRO +_PTEXT SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_PCODE + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + + ENDM + +VxD_PAGEABLE_CODE_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_PTEXT ENDS + ENDM + + + + +VxD_DEBUG_ONLY_CODE_SEG MACRO +_DBOCODE SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_DBOCODE + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + ENDM + +VxD_DEBUG_ONLY_CODE_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_DBOCODE ENDS + ENDM + + + + +VxD_INIT_CODE_SEG MACRO +_ITEXT SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_ICODE + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + ENDM + +VxD_INIT_CODE_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_ITEXT ENDS + ENDM + +VxD_ICODE_SEG equ VxD_INIT_CODE_SEG +VxD_ICODE_ENDS equ VxD_INIT_CODE_ENDS + + + + +VxD_DATA_SEG EQU +VxD_DATA_ENDS EQU + +VxD_LOCKED_DATA_SEG MACRO NO_ALIGN +_LDATA SEGMENT +IFB + ALIGN 4 +ENDIF + ENDM + +VxD_LOCKED_DATA_ENDS MACRO +_LDATA ENDS + ENDM + + + + +VxD_IDATA_SEG MACRO +_IDATA SEGMENT + ENDM +VxD_IDATA_ENDS MACRO +_IDATA ENDS + ENDM + + + + +VxD_PAGEABLE_DATA_SEG MACRO NO_ALIGN +_PDATA SEGMENT +IFB + ALIGN 4 +ENDIF + ENDM + +VxD_PAGEABLE_DATA_ENDS MACRO +_PDATA ENDS + ENDM + + + + +VxD_STATIC_CODE_SEG MACRO +_STEXT SEGMENT +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_SCODE + ASSUME cs:FLAT, ds:FLAT, es:FLAT, ss:FLAT + + ENDM + +VxD_STATIC_CODE_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_STEXT ENDS + ENDM + + + + +VxD_STATIC_DATA_SEG MACRO NO_ALIGN +_SDATA SEGMENT +IFB + ALIGN 4 +ENDIF + ENDM + +VxD_STATIC_DATA_ENDS MACRO +_SDATA ENDS + ENDM + + + +VxD_DEBUG_ONLY_DATA_SEG MACRO NO_ALIGN +_DBODATA SEGMENT +IFB + ALIGN 4 +ENDIF + ENDM + +VxD_DEBUG_ONLY_DATA_ENDS MACRO +_DBODATA ENDS + ENDM + + + + +VxD_16BIT_INIT_SEG MACRO +_16ICODE SEGMENT +ASSUME CS:_16ICODE, DS:NOTHING, ES:NOTHING, SS:NOTHING +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_16ICODE + ENDM + +VxD_16BIT_INIT_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_16ICODE ENDS + ENDM + + + +VxD_REAL_INIT_SEG MACRO +_RCODE SEGMENT +ASSUME CS:_RCODE, DS:_RCODE, ES:_RCODE, SS:_RCODE +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHL 4 + ??_RCODE + ENDM + +VxD_REAL_INIT_ENDS MACRO +??_CUR_CODE_SEG = ??_CUR_CODE_SEG SHR 4 +_RCODE ENDS + ENDM + +endif +ifndef DDK_VERSION +ifdef WIN31COMPAT +DDK_VERSION EQU 30AH +else +DDK_VERSION EQU 400H +endif +endif + +VxD_Desc_Block STRUC +DDB_Next DD ? +DDB_SDK_Version DW DDK_VERSION +DDB_Req_Device_Number DW UNDEFINED_DEVICE_ID +DDB_Dev_Major_Version DB 0 +DDB_Dev_Minor_Version DB 0 +DDB_Flags DW 0 +DDB_Name DB " " +DDB_Init_Order DD UNDEFINED_INIT_ORDER +DDB_Control_Proc DD ? +DDB_V86_API_Proc DD 0 +DDB_PM_API_Proc DD 0 +DDB_V86_API_CSIP DD 0 +DDB_PM_API_CSIP DD 0 +DDB_Reference_Data DD ? +DDB_Service_Table_Ptr DD 0 +DDB_Service_Table_Size DD 0 +DDB_Win32_Service_Table DD 0 +DDB_Prev DD 'Prev' +DDB_Size DD SIZE(VxD_Desc_Block) +DDB_Reserved1 DD 'Rsv1' +DDB_Reserved2 DD 'Rsv2' +DDB_Reserved3 DD 'Rsv3' +VxD_Desc_Block ENDS +ifndef Not_VxD +DDB_SYS_CRIT_INIT_DONE_BIT EQU 0 +DDB_SYS_CRIT_INIT_DONE EQU (1 SHL DDB_SYS_CRIT_INIT_DONE_BIT) +DDB_DEVICE_INIT_DONE_BIT EQU 1 +DDB_DEVICE_INIT_DONE EQU (1 SHL DDB_DEVICE_INIT_DONE_BIT) +DDB_HAS_WIN32_SVCS_BIT EQU 14 +DDB_HAS_WIN32_SVCS EQU (1 SHL DDB_HAS_WIN32_SVCS_BIT) +DDB_DYNAMIC_VXD_BIT EQU 15 +DDB_DYNAMIC_VXD EQU (1 SHL DDB_DYNAMIC_VXD_BIT) +DDB_DEVICE_DYNALINKED_BIT EQU 13 +DDB_DEVICE_DYNALINKED EQU (1 SHL DDB_DEVICE_DYNALINKED_BIT) +BeginDoc + + + + + + + +EndDoc +Declare_Virtual_Device MACRO Name, Major_Ver, Minor_Ver, Ctrl_Proc, Device_Num, Init_Order, V86_Proc, PM_Proc, Reference_Data + LOCAL V86_API_Offset, PM_API_Offset, Serv_Tab_Offset, Serv_Tab_Len, Ref_Data_Offset + +dev_id_err MACRO + +IFNDEF Name&_Name_Based +.err +ENDIF + ENDM + +IFB + V86_API_Offset EQU 0 +ELSE + IFB + dev_id_err + ENDIF + V86_API_Offset EQU +ENDIF + +IFB + PM_API_Offset EQU 0 +ELSE + IFB + dev_id_err + ENDIF + PM_API_Offset EQU +ENDIF + +IFDEF Name&_Service_Table + IFB + dev_id_err + ELSE + IFE Device_Num - UNDEFINED_DEVICE_ID + dev_id_err + ENDIF + ENDIF + Serv_Tab_Offset EQU + Serv_Tab_Len EQU Num_&Name&_Services +ELSE + Serv_Tab_Offset EQU 0 + Serv_Tab_Len EQU 0 +ENDIF + +IFNB + .erre (Device_Num LT BASEID_FOR_NAMEBASEDVXD), +ENDIF + +IFB + Ref_Data_Offset EQU 0 +ELSE + Ref_Data_Offset EQU +ENDIF + +IFDEF DEBUG +VxD_IDATA_SEG + db 0dh, 0ah, 'D_E_B_U_G===>' + db "&Name", '<===', 0dh, 0ah +VxD_IDATA_ENDS +ENDIF + +VxD_LOCKED_DATA_SEG + +PUBLIC Name&_DDB +Name&_DDB VxD_Desc_Block <,,Device_Num,Major_Ver,Minor_Ver,,"&Name",Init_Order,\ + OFFSET32 Ctrl_Proc, V86_API_Offset, PM_API_Offset, \ + ,,Ref_Data_Offset,Serv_Tab_Offset, Serv_Tab_Len> + +VxD_LOCKED_DATA_ENDS + + ENDM + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Begin_Control_Dispatch MACRO VxD_Name, p1, p2 +??_cd_low = 0FFFFFFFFh +??_cd_high = 0 + +BeginProc VxD_Name&_Control, p1, p2, LOCKED +ENDM + +End_Control_Dispatch MACRO VxD_Name + LOCAL ignore, table + +procoff MACRO num +IFDEF ??_cd_&&num + dd OFFSET32 ??_cd_&&num +ELSE + dd OFFSET32 ignore +ENDIF +ENDM + +IF ??_cd_low EQ ??_cd_high + cmp eax, ??_cd_low + ?merge ,,,,,, %(??_cd_low) + clc + ret +ELSE +IF ??_cd_low GT 0 + sub eax, ??_cd_low +ENDIF + cmp eax, ??_cd_high - ??_cd_low + 1 + jae short ignore + jmp [eax*4+table] +ignore: + clc + ret + +table label dword + REPT ??_cd_high - ??_cd_low + 1 + procoff %(??_cd_low) + ??_cd_low = ??_cd_low + 1 + ENDM +ENDIF + +EndProc VxD_Name&_Control + +PURGE procoff +PURGE Begin_Control_Dispatch +PURGE Control_Dispatch +PURGE End_Control_Dispatch +ENDM + +BeginDoc + + + + + + + + + + + + + + + + + + + + +EndDoc +Control_Dispatch MACRO Service, Procedure, callc, arglst + LOCAL Skip_Interseg_Jump + +.errnz ?_LCODE, + +IFB + +IFDEF ??_cd_low +Equate_Service MACRO Serv +??_cd_&&Serv equ Procedure +ENDM + +Equate_Service %(Service) + +IF Service LT ??_cd_low +??_cd_low = Service +ENDIF +IF Service GT ??_cd_high +??_cd_high = Service +ENDIF + +PURGE Equate_Service + +ELSE + cmp eax, Service + jz Procedure +ENDIF + +ELSE + + cmp eax, Service + jne SHORT Skip_Interseg_Jump + callc Procedure, +IF Service EQ PNP_NEW_DEVNODE + stc +ELSE + cmp eax,1 +ENDIF + ret +Skip_Interseg_Jump: + +ENDIF + + ENDM + +BYTE_INPUT EQU 000H +BYTE_OUTPUT EQU 004H +WORD_INPUT EQU 008H +WORD_OUTPUT EQU 00CH +DWORD_INPUT EQU 010H +DWORD_OUTPUT EQU 014H +OUTPUT_BIT EQU 2 +OUTPUT EQU (1 SHL OUTPUT_BIT) +WORD_IO_BIT EQU 3 +WORD_IO EQU (1 SHL WORD_IO_BIT) +DWORD_IO_BIT EQU 4 +DWORD_IO EQU (1 SHL DWORD_IO_BIT) +STRING_IO_BIT EQU 5 +STRING_IO EQU (1 SHL STRING_IO_BIT) +REP_IO_BIT EQU 6 +REP_IO EQU (1 SHL REP_IO_BIT) +ADDR_32_IO_BIT EQU 7 +ADDR_32_IO EQU (1 SHL ADDR_32_IO_BIT) +REVERSE_IO_BIT EQU 8 +REVERSE_IO EQU (1 SHL REVERSE_IO_BIT) +IO_SEG_MASK EQU 0FFFF0000H +IO_SEG_SHIFT EQU 10H +BeginDoc + + + + + + +EndDoc +Dispatch_Byte_IO MACRO In_Proc, Out_Proc + LOCAL Byte_IO + cmp ecx, Byte_Output + jbe SHORT Byte_IO + VMMJmp Simulate_IO +Byte_IO: +IFIDNI , + je Out_Proc +ELSE +IFIDNI , + jb In_Proc +ELSE + je Out_Proc + jmp In_Proc +ENDIF +ENDIF + ENDM + +BeginDoc + + + + + + + +EndDoc +Emulate_Non_Byte_IO MACRO + LOCAL Byte_IO + cmp ecx, Byte_Output + jbe SHORT Byte_IO + VMMJmp Simulate_IO +Byte_IO: + ENDM + +BeginDoc + + + + + + + + +EndDoc + + +VxD_IOT_Hdr STRUC +VxD_IO_Ports DW ? +VxD_IOT_Hdr ENDS + +VxD_IO_Struc STRUC +VxD_IO_Port DW ? +VxD_IO_Proc DD ? +VxD_IO_Struc ENDS +.ERRNZ SIZE VxD_IOT_Hdr - 2 +Begin_VxD_IO_Table MACRO Table_Name +PUBLIC Table_Name +Table_Name LABEL WORD + +ifndef MASM6 +IF2 +IFNDEF Table_Name&_Entries +.err +ENDIF + dw Table_Name&_Entries +ELSE + dw ? +ENDIF +ELSE + dw Table_Name&_Entries +ENDIF + + ENDM + +.ERRNZ SIZE VxD_IO_Struc - 6 +VxD_IO MACRO Port, Proc_Name + dw Port + dd OFFSET32 Proc_Name + ENDM + +End_VxD_IO_Table MACRO Table_Name + +IFNDEF Table_Name +.err +ELSE + Table_Name&_Entries EQU (($-Table_Name)-2) / (SIZE VxD_IO_Struc) +IF Table_Name&_Entries LE 0 +.err +ENDIF +ENDIF + ENDM + + + + + + + + + + + + + +Push_Client_State MACRO Can_Trash_EDI + sub esp, SIZE Client_Reg_Struc + ??_pushed = ??_pushed + SIZE Client_Reg_Struc + ifidni , + mov edi, esp + VMMCall Save_Client_State + else + push edi + lea edi, [esp+4] + VMMCall Save_Client_State + pop edi + endif + ENDM + +Pop_Client_State MACRO Can_Trash_ESI + ifdifi , + push esi + lea esi, [esp+4] + VMMCall Restore_Client_State + pop esi + else + mov esi, esp + VMMCall Restore_Client_State + endif + add esp, SIZE Client_Reg_Struc + ??_pushed = ??_pushed - SIZE Client_Reg_Struc + ENDM + +BeginDoc + + + + + + + + + + + + + + +EndDoc + +CallRet MACRO P1, P2 +IFDEF DEBUG +IFIDNI , + call P2 +ELSE + call P1 +ENDIF + ret +ELSE + jmp P1 P2 +ENDIF + ENDM + +BeginDoc + + + + + + +EndDoc + +IFDEF DEBUG + +VxDCallRet macro p:req + VxDCall p + ret +endm + +VMMCallRet macro p:req + VMMCall p + ret +endm + +ELSE + +VxDCallRet equ +VMMCallRet equ + +ENDIF + + + +PClient_DS equ WORD PTR -4 +PClient_ES equ WORD PTR -8 +PClient_FS equ WORD PTR -12 +PClient_GS equ WORD PTR -16 + + + + + + + + + + + +Client_Ptr_Flat MACRO Reg_32, Cli_Seg, Cli_Off, Can_Trash_EAX + +IFDIFI , + IFDIFI , + xchg Reg_32, eax + ENDIF +ENDIF +IFB + mov ax, (Client_&Cli_Seg * 100h) + 0FFh +ELSE + mov ax, (Client_&Cli_Seg * 100h) + Client_&Cli_Off +ENDIF + VMMCall Map_Flat + +IFDIFI , + xchg Reg_32, eax +ENDIF + + ENDM + + + +VxDint MACRO Int_Number + if (OPATTR Int_Number) AND 4 + push Int_Number + else + push DWORD PTR Int_Number + endif + VMMCall Exec_VxD_Int + ENDM + +VxDintMustComplete MACRO Int_Number + if (OPATTR Int_Number) AND 4 + push Int_Number + else + push DWORD PTR Int_Number + endif + VMMCall _ExecVxDIntMustComplete + ENDM + + + +endif +DUPLICATE_DEVICE_ID_BIT EQU 0 +DUPLICATE_DEVICE_ID EQU (1 SHL DUPLICATE_DEVICE_ID_BIT) +DUPLICATE_FROM_INT2F_BIT EQU 1 +DUPLICATE_FROM_INT2F EQU (1 SHL DUPLICATE_FROM_INT2F_BIT) +LOADING_FROM_INT2F_BIT EQU 2 +LOADING_FROM_INT2F EQU (1 SHL LOADING_FROM_INT2F_BIT) +DEVICE_LOAD_OK EQU 0 +ABORT_DEVICE_LOAD EQU 1 +ABORT_WIN386_LOAD EQU 2 +NO_FAIL_MESSAGE_BIT EQU 15 +NO_FAIL_MESSAGE EQU (1 SHL NO_FAIL_MESSAGE_BIT) +LDRSRV_GET_PROFILE_STRING EQU 0 +LDRSRV_GET_NEXT_PROFILE_STRING EQU 1 +LDRSRV_RESERVED EQU 2 +LDRSRV_GET_PROFILE_BOOLEAN EQU 3 +LDRSRV_GET_PROFILE_DECIMAL_INT EQU 4 +LDRSRV_GET_PROFILE_HEX_INT EQU 5 +LDRSRV_COPY_EXTENDED_MEMORY EQU 6 +LDRSRV_GET_MEMORY_INFO EQU 7 +LDRSRV_RegOpenKey EQU 100H +LDRSRV_RegCreateKey EQU 101H +LDRSRV_RegCloseKey EQU 102H +LDRSRV_RegDeleteKey EQU 103H +LDRSRV_RegSetValue EQU 104H +LDRSRV_RegQueryValue EQU 105H +LDRSRV_RegEnumKey EQU 106H +LDRSRV_RegDeleteValue EQU 107H +LDRSRV_RegEnumValue EQU 108H +LDRSRV_RegQueryValueEx EQU 109H +LDRSRV_RegSetValueEx EQU 10AH +LDRSRV_RegFlushKey EQU 10BH +LDRSRV_COPY_INIT EQU 1 +LDRSRV_COPY_LOCKED EQU 2 +LDRSRV_COPY_PAGEABLE EQU 3 +RCODE_OBJ EQU -1 +LCODE_OBJ EQU 01H +LDATA_OBJ EQU 02H +PCODE_OBJ EQU 03H +PDATA_OBJ EQU 04H +SCODE_OBJ EQU 05H +SDATA_OBJ EQU 06H +CODE16_OBJ EQU 07H +LMSG_OBJ EQU 08H +PMSG_OBJ EQU 09H +DBOC_OBJ EQU 0BH +DBOD_OBJ EQU 0CH +ICODE_OBJ EQU 11H +IDATA_OBJ EQU 12H +ICODE16_OBJ EQU 13H +IMSG_OBJ EQU 14H + +ObjectLocation STRUC +OL_LinearAddr DD ? +OL_Size DD ? +OL_ObjType DB ? +ObjectLocation ENDS +MAXOBJECTS EQU 25 + +Device_Location_List STRUC +DLL_DDB DD ? +DLL_NumObjects DB ? +DLL_ObjLocation DB SIZE ObjectLocation * 1 DUP (?) +Device_Location_List ENDS +PE_BIT EQU 0 +PE_MASK EQU (1 SHL PE_BIT) +MP_BIT EQU 1 +MP_MASK EQU (1 SHL MP_BIT) +EM_BIT EQU 2 +EM_MASK EQU (1 SHL EM_BIT) +TS_BIT EQU 3 +TS_MASK EQU (1 SHL TS_BIT) +ET_BIT EQU 4 +ET_MASK EQU (1 SHL ET_BIT) +PG_BIT EQU 31 +PG_MASK EQU (1 SHL PG_BIT) +CF_BIT EQU 0 +CF_MASK EQU (1 SHL CF_BIT) +PF_BIT EQU 2 +PF_MASK EQU (1 SHL PF_BIT) +AF_BIT EQU 4 +AF_MASK EQU (1 SHL AF_BIT) +ZF_BIT EQU 6 +ZF_MASK EQU (1 SHL ZF_BIT) +SF_BIT EQU 7 +SF_MASK EQU (1 SHL SF_BIT) +TF_BIT EQU 8 +TF_MASK EQU (1 SHL TF_BIT) +IF_BIT EQU 9 +IF_MASK EQU (1 SHL IF_BIT) +DF_BIT EQU 10 +DF_MASK EQU (1 SHL DF_BIT) +OF_BIT EQU 11 +OF_MASK EQU (1 SHL OF_BIT) +IOPL_MASK EQU 3000H +IOPL_BIT0 EQU 12 +IOPL_BIT1 EQU 13 +NT_BIT EQU 14 +NT_MASK EQU (1 SHL NT_BIT) +RF_BIT EQU 16 +RF_MASK EQU (1 SHL RF_BIT) +VM_BIT EQU 17 +VM_MASK EQU (1 SHL VM_BIT) +AC_BIT EQU 18 +AC_MASK EQU (1 SHL AC_BIT) +VIF_BIT EQU 19 +VIF_MASK EQU (1 SHL VIF_BIT) +VIP_BIT EQU 20 +VIP_MASK EQU (1 SHL VIP_BIT) + + + + + + +IFDEF MASM6 +loopde EQU +loopdne EQU +loopdz EQU +loopdnz EQU +ELSE +loopd EQU +loopde EQU +loopdne EQU +loopdz EQU +loopdnz EQU +ENDIF + +P_SIZE EQU 1000H +P_PRESBIT EQU 0 +P_PRES EQU (1 SHL P_PRESBIT) +P_WRITEBIT EQU 1 +P_WRITE EQU (1 SHL P_WRITEBIT) +P_USERBIT EQU 2 +P_USER EQU (1 SHL P_USERBIT) +P_ACCBIT EQU 5 +P_ACC EQU (1 SHL P_ACCBIT) +P_DIRTYBIT EQU 6 +P_DIRTY EQU (1 SHL P_DIRTYBIT) +P_AVAIL EQU (P_PRES+P_WRITE+P_USER) +PG_VM EQU 0 +PG_SYS EQU 1 +PG_RESERVED1 EQU 2 +PG_PRIVATE EQU 3 +PG_RESERVED2 EQU 4 +PG_RELOCK EQU 5 +PG_INSTANCE EQU 6 +PG_HOOKED EQU 7 +PG_IGNORE EQU 0FFFFFFFFH +D_PRES EQU 080H +D_NOTPRES EQU 0 +D_DPL0 EQU 0 +D_DPL1 EQU 020H +D_DPL2 EQU 040H +D_DPL3 EQU 060H +D_SEG EQU 010H +D_CTRL EQU 0 +D_GRAN_BYTE EQU 000H +D_GRAN_PAGE EQU 080H +D_DEF16 EQU 000H +D_DEF32 EQU 040H +D_CODE EQU 08H +D_DATA EQU 0 +D_X EQU 0 +D_RX EQU 02H +D_C EQU 04H +D_R EQU 0 +D_W EQU 02H +D_ED EQU 04H +D_ACCESSED EQU 1 +RW_DATA_TYPE EQU (D_PRES+D_SEG+D_DATA+D_W) +R_DATA_TYPE EQU (D_PRES+D_SEG+D_DATA+D_R) +CODE_TYPE EQU (D_PRES+D_SEG+D_CODE+D_RX) +D_PAGE32 EQU (D_GRAN_PAGE+D_DEF32) +SELECTOR_MASK EQU 0FFF8H +SEL_LOW_MASK EQU 0F8H +TABLE_MASK EQU 04H +RPL_MASK EQU 03H +RPL_CLR EQU (NOT RPL_MASK) +IVT_ROM_DATA_SIZE EQU 500H +endif diff --git a/VSound/VXD/VSOUND.ASM b/VSound/VXD/VSOUND.ASM new file mode 100755 index 0000000..9d0007e --- /dev/null +++ b/VSound/VXD/VSOUND.ASM @@ -0,0 +1,679 @@ +PAGE 58,132 + + .386p + +; +; Client has: +; States -> state is set by writing to port +; data is retrieved by reading from port +; +; State 0: Get Identification "ITVXDDRV" +; State 1: Get Server string (64 bytes) +; State 2: Get buffer used +; State 3: Reset Client +; State 4: Get debug value +; State 5: Get TSC +; +; +; Server interface: +; Write 0 to reset +; If read, returns "ITSERVER", else 01h if Server has been validated. +; Needs to receive "ITSERVER" to validate. +; If validated, receives server string of max 64 bytes, no 0 permitted. +; + + + .XLIST + INCLUDE VMM.Inc + INCLUDE Debug.Inc + INCLUDE Shell.inc + .LIST + + VSound_Client_Address EQU 400h + VSound_Server_Address EQU 401h + VSound_Data_Address EQU 402h + + VSOUND_CLIENTSTATES EQU 7 + VSOUND_BUFFERSIZE EQU (64*1024) + +;****************************************************************************** +; V I R T U A L D E V I C E D E C L A R A T I O N +;****************************************************************************** + +Declare_Virtual_Device VSOUND, 1, 0, VSOUND_Control, Undefined_Device_ID ,,, + +;****************************************************************************** +; L O C A L D A T A +;****************************************************************************** + + +VxD_LOCKED_DATA_SEG + +VSound_Data DB VSOUND_BUFFERSIZE Dup (0) +VSound_HeadPointer DD 0 +VSound_TailPointer DD 0 + +VSound_Client DD 0 +VSound_Server DD 0 +VSound_ClientCallback DD 0 + +VSound_ID DB "ITVXDDRV" +VSound_State DD 0 +VSound_BufferUsed DD 0 +VSound_StatePos DD 0 + +VSound_ServerID DB "ITSERVER" +VSound_ServerInPos DD 0 +VSound_ServerOutPos DD 0 +VSound_ServerValid DD 0 + +VSound_DebugValue DD 0 +VSound_TimeStamp1 DD 0 +VSound_TimeStamp2 DD 0 + +VSound_InTable DD Offset32 VSound_Identification + DD Offset32 VSound_GetServerString + DD Offset32 VSound_GetBufferUsed + DD Offset32 VSound_GetDebugValue + DD Offset32 VSound_Get0 + DD Offset32 VSound_GetDebugValue + DD Offset32 VSound_GetTSC + +VSound_OutTable DD Offset32 VSound_Out_ResetStatePos + DD Offset32 VSound_Out_ResetStatePos + DD Offset32 VSound_Out_GetBufferUsed + DD Offset32 VSound_Out_ResetClient + DD Offset32 VSound_Out_SetCallbackAddress + DD Offset32 VSound_Out_ResetStatePos + DD Offset32 VSound_Out_GetTSC + +VSound_ServerString DB 64 Dup (0) + +VxD_LOCKED_DATA_ENDS + + +;****************************************************************************** +; I N I T I A L I Z A T I O N C O D E +;****************************************************************************** + +VxD_IDATA_SEG + +Begin_Vxd_IO_Table IO_Table + Vxd_IO VSound_Client_Address, VSound_Client_Hook + Vxd_IO VSound_Server_Address, VSound_Server_Hook + Vxd_IO VSound_Data_Address, VSound_Data_Hook +End_Vxd_IO_Table IO_Table + +VxD_IDATA_ENDS + +VxD_ICODE_SEG + + +;****************************************************************************** +; +; VSOUND_Device_Init +; +; DESCRIPTION: +; +; This routine is called during Windows startup. It needs to +; install the I/O handler for our device, and set up the system +; VM as the default owner. +; +; +;============================================================================== + +BeginProc VSOUND_Device_Init + + Xor EAX, EAX + Mov VSound_Client, EAX ; no current owner + Mov VSound_Server, EAX ; no current owner + Mov VSound_ClientCallback, EAX ; No callback + + Mov EDI, OFFSET32 IO_Table + VMMCall Install_Mult_IO_Handlers + + Ret + +EndProc VSOUND_Device_Init + +VxD_ICODE_ENDS + + +;++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +VxD_CODE_SEG + +;****************************************************************************** +; +; VSOUND_Destroy_VM +; +; DESCRIPTION: +; +; This routine is called when a VM is destroyed. We need to check +; to see if the VM in question is the current owner of the device. +; +;============================================================================== + +BeginProc VSOUND_Destroy_VM + + Xor EAX, EAX + + Cmp EBX, VSound_Client ; Destroying device owner? + JNE Short VDM_Client + + Mov VSound_Client, EAX + Mov VSound_ClientCallback, EAX + +VDM_Client: + Cmp EBX, VSound_Server + JNE VDM_Server + + Mov VSound_Server, EAX + Mov VSound_ServerValid, EAX + +VDM_Server: + ClC + Ret + +EndProc VSOUND_Destroy_VM + +VxD_CODE_ENDS + + +;****************************************************************************** + +VxD_LOCKED_CODE_SEG + +;****************************************************************************** +; +; VSound_Control +; +; DESCRIPTION: +; +; This is a call-back routine to handle the messages that are sent +; to VxD's to control system operation. +; +;============================================================================== +BeginProc VSound_Control + + Control_Dispatch Device_Init, VSound_Device_Init + Control_Dispatch Destroy_VM, VSound_Destroy_VM + + ClC + Ret + +EndProc VSound_Control + +VxD_LOCKED_CODE_ENDS + + +VxD_CODE_SEG + +;***************************************************************************** +; +; VSound_Client_Hook +; +; DESCRIPTION: +; +; This routine is called for every I/O access to our port. First, +; it checks to see if the VM issuing the I/O is the current owner. +; If not, it displays a dialog box so the user can decide what to +; do. +; +;***************************************************************************** + +VSound_Identification: + Pop EAX + Push ECX + Mov ECX, VSound_StatePos + + Mov AL, [VSound_ID+ECX] + Inc ECX + And ECX, 7 + Mov VSound_StatePos, ECX + + Pop ECX + Ret + +VSound_GetServerString: + Pop EAX + Push ECX + Mov ECX, VSound_StatePos + + Mov AL, [VSound_ServerString+ECX] + Inc ECX + And ECX, 63 + Mov VSound_StatePos, ECX + + Pop ECX + Ret + +VSound_GetBufferUsed: + Pop EAX + Push ECX + Mov ECX, VSound_StatePos + + Xor ECX, 1 + Mov AL, [Byte Ptr VSound_BufferUsed+ECX] + Mov VSound_StatePos, ECX + + Pop ECX + Ret + +VSound_GetTSC: + Pop EAX + Push ECX + Mov ECX, VSound_StatePos + + Mov AL, [Byte Ptr VSound_TimeStamp1+ECX] + Inc ECX + And ECX, 7 + + Mov VSound_StatePos, ECX + + Pop ECX + Ret + +VSound_Get0: + Xor AL, AL + + Pop ECX + Ret + +VSound_GetDebugValue: + Pop EAX + Push ECX + Mov ECX, VSound_StatePos + + Mov AL, [Byte Ptr VSound_DebugValue+ECX] + Inc ECX + And ECX, 3 + + Mov VSound_StatePos, ECX + + Pop ECX + Ret + +BeginProc VSound_Client_Hook + +;--------------------------------------------------------------------- +; Resolve Contention +;--------------------------------------------------------------------- + + Push EAX + + Mov EAX, VSound_Client + + Cmp VSound_ServerValid, 0 + JE NoValidServer + + Cmp EAX, EBX ; Is the request from the + JE Process_IO ; current owner? + + Test EAX, EAX ; Was there a previous owner? + JZ New_Owner + +NoValidServer: + Pop EAX + + Dispatch_Byte_IO Fall_Through, + + Mov AL, 80h + +Blocked_IO: + Ret + +New_Owner: + Mov VSound_Client, EBX + Mov VSound_ClientCallback, 0 + +Process_IO: + Pop EAX + + Dispatch_Byte_IO Fall_Through, + + Push EAX + Mov EAX, VSound_State + Cmp EAX, VSOUND_CLIENTSTATES + JAE VSound_Unknown + + Jmp [VSound_InTable+EAX*4] + +VSound_Unknown: + Pop EAX + Xor AL, AL + Ret + +VSound_Out: + Push EAX + Mov Byte Ptr VSound_State, AL + And EAX, 0FFh + + Cmp EAX, VSOUND_CLIENTSTATES + JAE VSound_Out_Nothing + + Jmp [VSound_OutTable+EAX*4] + +VSound_Out_GetTSC: + DB 0Fh + DB 31h ; RdTSC + Mov VSound_TimeStamp1, EAX + Mov VSound_TimeStamp2, EDX + Jmp VSound_Out_ResetStatePos + +VSound_Out_GetBufferUsed: + Mov EAX, VSound_TailPointer + Sub EAX, VSound_HeadPointer + And EAX, VSOUND_BUFFERSIZE-1 + Mov VSound_BufferUsed, EAX + +VSound_Out_ResetStatePos: + Mov VSound_StatePos, 0 + +VSound_Out_Nothing: + Pop EAX + Ret + +VSound_Out_ResetClient: + Xor EAX, EAX + Mov VSound_Client, EAX + Mov VSound_ClientCallback, EAX + + Pop EAX + + Ret + +VSound_Out_SetCallbackAddress: + Mov AX, [EBP+CLIENT_REG_STRUC.CLIENT_CS] + ShL EAX, 16 + Mov AX, [EBP+CLIENT_REG_STRUC.CLIENT_BX] + + Mov VSound_ClientCallback, EAX + + Pop EAX + Ret + +EndProc VSound_Client_Hook + +;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +;-------------------------------------------------------------------- + +BeginProc VSound_Server_Hook + + Push EAX + + Mov EAX, VSound_Server + + Cmp EAX, EBX ; Is the request from the + JE Process_Server_IO ; current owner? + + Test EAX, EAX ; Was there a previous owner? + JZ New_Server + + Pop EAX + + Dispatch_Byte_IO Fall_Through, + + Mov AL, 80h + +Server_Blocked_IO: + Ret + +New_Server: + Mov VSound_Server, EBX + +Process_Server_IO: + Pop EAX + + Dispatch_Byte_IO Fall_Through, + + Cmp VSound_ServerValid, 1 + JE VSound_Server_Validated + + Mov ECX, VSound_ServerInPos + Mov AL, [VSound_ServerID+ECX] + Inc ECX + And ECX, 7 + Mov VSound_ServerInPos, ECX + Ret + +VSound_Server_Validated: + Mov ECX, VSound_Client + Add ECX, 0FFFFFFFFh + SBB AL, AL ; Returns 0 if not connected, 0FFh if connected + Ret + +VSound_Server_Out: + Test AL, AL ; Reset? + JZ VSound_Server_Reset + + Mov ECX, VSound_ServerOutPos + + Cmp VSound_ServerValid, 1 + JE VSound_ReceiveServerString + + Cmp [VSound_ServerID+ECX], AL + JE VSound_ValidByte + + Mov VSound_ServerOutPos, 0 + Ret + +VSound_ValidByte: + Inc ECX + And ECX, 7 + Mov VSound_ServerOutPos, ECX + JNZ VSound_ServerNotValidated + + Mov VSound_ServerValid, 1 + +VSound_ServerNotValidated: + Ret + +VSound_ReceiveServerString: + Mov [VSound_ServerString+ECX], AL + Inc ECX + And ECX, 63 + Mov VSound_ServerOutPos, ECX + Ret + +VSound_Server_Reset: + Xor ECX, ECX + Mov VSound_Server, ECX + Mov VSound_ServerValid, ECX + Mov VSound_ServerInPos, ECX + Mov VSound_ServerOutPos, ECX + + Ret + +EndProc VSound_Server_Hook + +;--------------------------------------------------------------------- + +BeginProc VSound_Data_Hook + + Cmp EBX, VSound_Server + JE VSound_Data_Server + + Cmp EBX, VSound_Client + JE VSound_Data_Client + + Ret + +VSound_Data_Client: + Cmp CX, String_IO or Rep_IO or Byte_Output + JNE Data_Client_Simulate + + PushAD + Push ES + PushF + + ClI + + Push DS + Pop ES + + ShR ECX, 16 ; ECX = segment. + Mov EAX, [EBP+CLIENT_REG_STRUC.CLIENT_ECX] + + ShL ECX, 4 + Mov ESI, [EBP+CLIENT_REG_STRUC.CLIENT_ESI] + + And ESI, 0FFFFh + Mov EDI, VSound_TailPointer + + Add ESI, ECX ; ESI = data source. + And EAX, 0FFFFh ; EAX = byte count + + Test EAX, 3 ; Must be multiple of 4 bytes + JNZ VSound_DataClientExit + + LEA EDX, [EDI+EAX] + Add EDI, Offset VSound_Data + + Cmp EDX, VSOUND_BUFFERSIZE + JB VSound_DataClient1 + + Mov ECX, VSOUND_BUFFERSIZE + LEA EAX, [EDX-VSOUND_BUFFERSIZE] + + Sub ECX, VSound_TailPointer + ShR ECX, 2 + + Rep MovsD + + Mov EDI, Offset VSound_Data + +VSound_DataClient1: + ShR EAX, 2 + And EDX, VSOUND_BUFFERSIZE-1 + + Mov ECX, EAX + Mov VSound_TailPointer, EDX + + Rep MovsD + +VSound_DataClientExit: + PopF + Pop ES + PopAD + +Data_Client_Simulate: + Ret + +VSound_Data_Server: + +; +; The server will only receive data if: +; 1) A Rep InsB instruction is used. No other instruction will work +; 2) The ECX count is a multiple of 4 +; 3) The ECX count must be less than BUFFERSIZE + + Cmp CX, String_IO or Rep_IO or Addr_32_IO or Byte_Input + JNE Data_Server_Simulate + + PushAD + Push ES + PushF + + ClI + + ShR ECX, 16 + Mov ES, CX + + Mov EAX, [EBP+CLIENT_REG_STRUC.CLIENT_ECX] + Mov EDI, [EBP+CLIENT_REG_STRUC.CLIENT_EDI] + + Test EAX, 3 + JNZ VSound_DataServerExit + + Cmp EAX, VSOUND_BUFFERSIZE + JAE VSound_DataServerExit + +; Want minimum of bytes available and bytes requested + Mov ESI, VSound_HeadPointer + Mov EBX, VSound_TailPointer + + Sub EBX, ESI + And EBX, VSOUND_BUFFERSIZE-1 ; EBX = bytes available + ; EAX = bytes requested + Cmp EBX, EAX + JB VSound_DataServer1 + + Mov EBX, EAX + +VSound_DataServer1: ; EBX = bytes to transfer + Sub EAX, EBX ; EAX = bytes to zero + LEA EDX, [ESI+EBX] + + ShR EBX, 2 ; EBX = dwords to transfer + Add ESI, Offset VSound_Data + + Cmp EDX, VSOUND_BUFFERSIZE ; Does it span the buffer boundary? + JB VSound_DataServer2 + + LEA EBX, [EDX-VSOUND_BUFFERSIZE] + Mov ECX, VSOUND_BUFFERSIZE + + ShR EBX, 2 + Sub ECX, VSound_HeadPointer + + ShR ECX, 2 + + Rep MovsD + + Mov ESI, Offset VSound_Data + +VSound_DataServer2: + ShR EAX, 2 + Mov ECX, EBX + Rep MovsD + + Mov ECX, EAX + And EDX, VSOUND_BUFFERSIZE-1 + + Xor EAX, EAX + Mov VSound_HeadPointer, EDX + + Rep StosD + +; ECX = 0 + Mov EBX, VSound_Client + Cmp VSound_ClientCallback, ECX + JE VSound_DataServerExit + Test EBX, EBX + JZ VSound_DataServerExit + + Mov EBP, [EBX+CB_S.CB_Client_Pointer] + + VMMCall Set_Execution_Focus + JC VSound_DataServerExit + + Push_Client_State + + VMMCall Begin_Nest_V86_Exec + + MovZX EDX, Word Ptr [VSound_ClientCallback] + MovZX ECX, Word Ptr [VSound_ClientCallback+2] + VMMCall Simulate_Far_Call + VMMCall Resume_Exec + + VMMCall End_Nest_Exec + + Pop_Client_State + +VSound_DataServerExit: + PopF + Pop ES + PopAD + +Data_Server_Simulate: + Ret + +EndProc VSound_Data_Hook + +;--------------------------------------------------------------------- + +VxD_CODE_ENDS + + + END diff --git a/VSound/VXD/VSOUND.DEF b/VSound/VXD/VSOUND.DEF new file mode 100755 index 0000000..ca8329d --- /dev/null +++ b/VSound/VXD/VSOUND.DEF @@ -0,0 +1,38 @@ +;**************************************************************************** +; * +; THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY * +; KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE * +; IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR * +; PURPOSE. * +; * +; Copyright (C) 1993-95 Microsoft Corporation. All Rights Reserved. * +; * +;**************************************************************************** + +VXD VSOUND + +DESCRIPTION 'VSOUND Impulse Tracker Virtual Soundcard driver for for Microsoft Windows' + +SEGMENTS + _LPTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE + _LTEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE + _LDATA CLASS 'LCODE' PRELOAD NONDISCARDABLE + _TEXT CLASS 'LCODE' PRELOAD NONDISCARDABLE + _DATA CLASS 'LCODE' PRELOAD NONDISCARDABLE + CONST CLASS 'LCODE' PRELOAD NONDISCARDABLE + _TLS CLASS 'LCODE' PRELOAD NONDISCARDABLE + _BSS CLASS 'LCODE' PRELOAD NONDISCARDABLE + _ITEXT CLASS 'ICODE' DISCARDABLE + _IDATA CLASS 'ICODE' DISCARDABLE + _PTEXT CLASS 'PCODE' NONDISCARDABLE + _PDATA CLASS 'PDATA' NONDISCARDABLE SHARED + _STEXT CLASS 'SCODE' RESIDENT + _SDATA CLASS 'SCODE' RESIDENT + _DBOSTART CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING + _DBOCODE CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING + _DBODATA CLASS 'DBOCODE' PRELOAD NONDISCARDABLE CONFORMING + _16ICODE CLASS '16ICODE' PRELOAD DISCARDABLE + _RCODE CLASS 'RCODE' + +EXPORTS + VSOUND_DDB @1