home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Party 1994: Try This At Home
/
disk_image.bin
/
source
/
solarsrc
/
solarium.asm
< prev
next >
Wrap
Assembly Source File
|
1994-06-18
|
47KB
|
878 lines
; ///////////////////////////////////////////////////////////////////////////
; //// ////
; //// ▄██████ ▄█████▄ ███ ███ ██████▄ ███ ███ ███ ███ ███ ////
; //// ███ ███ ███ ███ █████ ███ ███ ███ ███ ███ ████ ████ ////
; //// ▀█████▄ ███ ███ ███ ███ ███ ██████▀ ███ ███ ███ ███ █ ███ ////
; //// ███ ███ ███ ███ ███ ███ ███▀██▄ ███ ███ ███ ███ ███ ////
; //// ██████▀ ▀█████▀ ███████ ███ ███ ███ ▀██ ███ ▀█████▀ ███ ███ ////
; //// ////
; //// Copyright (C) 1994 Altair/Anarchy-PC ////
; //// ////
; //// ////
; //// ////
; //// Coding: Altair ////
; //// Music: Modified HSC-Tracker tune ////
; //// ////
; //// Program requires 386 and VGA for operating. It has been tested ////
; //// with 486/33Mhz (no localbus) where scroller took half frame with ////
; //// 70Hz screen update. Player is quite slow, but it has been mainly ////
; //// optimized for size like everything else but scroller. Three tips: ////
; //// VGA detecting and 'zeros to end' were taken from Future Crews ////
; //// StarPort II and processor detecting from Tietokone-Magazine, but ////
; //// everything else is self-studied and self-created. Solarium uses ////
; //// alot of variables, which are included into the code itself. When ////
; //// you do something like that in your own programs, remember that ////
; //// value is not necessarely in the code at the time when the command ////
; //// performs. There is no speedup with computers above 286 and those ////
; //// don't shrink the code either. I must have a headache, when I made ////
; //// the code using that kind of variables (: In the code might be ////
; //// some parts which could be optimized in smaller size or done other ////
; //// ways better, but I have changed this code many times and haven't ////
; //// probably noticed everything. You can use parts of this code in ////
; //// your own programs if you like, but it would be nice for you to ////
; //// mention where have you got your source materials. ////
; //// I have used TASM and TLINK to create the original SOLARIUM.COM. ////
; //// ////
; //// Program consist of following operations: ////
; //// - allocate memory ////
; //// - detect processor ////
; //// - unpack music ////
; //// - detect VGA ////
; //// - clear scrolling-area ////
; //// - initialize adlib ////
; //// - make Cos-wave ////
; //// - precalculate the track of the scrollers ////
; //// ∙ calculate the screen address for each vertical line ////
; //// ∙ calculate the source position for each pixel ////
; //// ∙ calculate the shading for each vertical pixel line ////
; //// - set the music routine to the timer interrupt ////
; //// - set the new key interrupt (disable pause etc.) ////
; //// - create the characters ////
; //// - set palette ////
; //// - intro-loop ////
; //// ∙ test if ESC pressed ////
; //// ∙ write text to scrolling-area ////
; //// ∙ draw scroll to the screen ////
; //// ∙ wait vertical retrace ////
; //// - return old interrupts ////
; //// - return to DOS ////
; //// ////
; ///////////////////////////////////////////////////////////////////////////
Code Segment
Assume Cs:Code,Ds:Code
Org 0100h
Start: .186
Push Cs
Pop Ds
Mov Bx,2113h ; allocate memory for operations
Mov Ah,4Ah ; which SOLARIUM.COM uses
Int 21h ; (pattern etc.)
Jc GoodBye
Push Sp ; is the processor 80186?
Pop Bx
Cmp Bx,Sp
Je Not80186
GoodBye: Call InitializeAdlib; quiet adlib
Mov Ax,0003h ; set text-mode
Int 10h
Push 0B800h
Pop Es
Xor Di,Di
Mov Si,Offset BBSInfoText
Mov Ah,0Dh
WriteBBSText: Mov Al,Cs:[Si]
Or Al,Al
Jnz NoColorChange
Inc Ah
NoColorChange: StosW
Inc Si
Cmp Si,Offset BBSInfoTextEnd
Jb WriteBBSText
Mov Ax,4C00h
Int 21h ; return to DOS
Not80186: .286
Mov Bx,0F000h ; is it 80286?
Push Bx
PopF
PushF
Pop Bx
And Bx,0F000h
Je GoodBye ; if it's 80286 -> bye
.386
Add Ax,1000h
Mov Word Ptr [ScrollDataBegin+0001h],Ax
Add Ax,0C80h
Mov Fs,Ax ; segment for scroller-info
Add Ax,33h ; save segment for scrolling-area
Mov Word Ptr [TextSegment+0001h],Ax; here
Mov Es,Ax
Add Ax,70h
Mov Gs,Ax
; Unpack all patterns
Mov Word Ptr [PatternsSegment+0001h],Ax
Mov Bx,Channels*64*4*Patterns-1
Mov Di,Channels
ResetInstruments: Mov [Di+InstrumentInfo-0001h],Bl
Dec Di
Jnz ResetInstruments
ClearPatterns: Mov Byte Ptr Gs:[Bx],0FFh
Dec Bx
Jns ClearPatterns
Mov Byte Ptr [TrackCounter+0001h],00h
Mov Si,Offset Pattern00
MakeTrack: Mov Dx,[Si]
Inc Si
Cmp Dl,0FFh
Je NoNotes
Inc Si
Mov Bl,Dh
And Bl,0Fh
Shl Bl,02h
TrackCounter: Mov Bh,77h
Mov Ah,Dh
And Ah,70h
Shr Ah,02h
Add Dh,Dh
Jc CopyTrack
Mov Cx,[Di+ChannelInfo]
NextGroup: Mov Dh,Dl
And Dl,1Fh
Mov Bp,Dx
LoopStoring: Push Si
ReadCommand: Mov Al,[Si]
Inc Si
Mov Dh,Al
Shr Al,04h
And Dh,0Fh
Cmp Al,0Eh
Je SetOctaveOrSpace
Ja SetInstrument
Push Cx
Cmp Al,07h
Jb DontIncOctave
Inc Cl
Sub Al,07h
DontIncOctave: Shl Cl,02h
Add Al,Al
Mov Gs:[Bx],Ax
Mov Gs:[Bx+02h],Cx
Pop Cx
Inc Dh
Shl Dh,02h
Add Bl,Dh
Jc TrackFull
ExtraCommandReturn: Dec Dl
Jns ReadCommand
Mov Dx,Bp
Pop Si
Sub Bp,2000h
Jnc LoopStoring
And Bp,001Fh
Add Si,Bp
Inc Si
Mov Dl,[Si]
Inc Si
Jmp NextGroup
SetOctave: Mov Cl,Dh
Dec Cl
Jmp ExtraCommandReturn
SetInstrument: Mov Ch,Dh
Jmp ExtraCommandReturn
CopyTrack: Push Si
Shl Dx,08h
Mov Si,Dx
CopyingLoop: Mov Al,Gs:[Si]
Mov Cx,Gs:[Si+02h]
Mov Gs:[Bx],Ax
Mov Gs:[Bx+02h],Cx
Add Si,04h
Add Bl,04h
Jnc CopyingLoop
Pop Si
Jmp NoNotes
SetOctaveOrSpace: Test Dh,08h
Jz SetOctave
Shl Dh,06h
Add Bl,Dh
Jnc ExtraCommandReturn
TrackFull: Pop Si
And Bp,001Fh
Add Si,Bp
Inc Si
Mov [Di+ChannelInfo],Cx
NoNotes: Inc Byte Ptr [TrackCounter+0001h]
Sub Di,02h
Jnc DontZeroChl
Mov Di,0010h
DontZeroChl: Cmp Si,Offset SongDataEnd
Jb MakeTrack
; Detect VGA
Mov Ax,1A00h
Int 10h ; is the display VGA?
Cmp Al,1Ah
Jne GoodBye ; if not VGA -> bye
; Clear the scrolling-area
Mov Di,06FFh ; the length of scrolling-area -2
ClearAreaLoop: Mov Byte Ptr Es:[Di],00h
Dec Di
Jns ClearAreaLoop
Call InitializeAdlib
; There is a packed cosine-wave in the end of this program and below program
; unpacks it to the SCROLLERSTRACK.
Push Cs
Pop Es
Mov Si,Offset PackedTrack
Mov Di,Offset ScrollersTrack
Mov Cx,0029h
UnpackTrackLoop1: LodsB
UnpackTrackLoop2: Mov Ah,Al
And Ah,0Fh
Jz UnpackTrackLoop1
UnpackTrackLoop3: Mov Ds:[Di],Ch
Inc Di
Dec Ah
Jnz UnpackTrackLoop3
Inc Ch
Shr Al,04h
Dec Cl
Jnz UnpackTrackLoop2
Mov Cl,0A0h
Mov Si,Offset ScrollersTrack+009Fh
MakeEndOfTheTrack: MovsB ; copy table in reverse order
Dec Si
Dec Si
Dec Cl ; repeat 160 times
Jnz MakeEndOfTheTrack
; Calculate the precalculation tables for scroller. First calculate the
; shadow of the scroller by deriving. This is possible, because scrollers
; track follows the function of cosine. Derived value means the steedness
; of the function in some place of it, so the value is in range -1 and +1
; and the angle of lightsource is naturaly 45 degrees to right and front
; from the the scroller. After this, store also the height of every 4th
; vertical line in the scroller (4 next vertical lines has always a same
; heigh, because this make writing to screen memory alot of faster).
; Then precalculate the screen address of all those 80 vertical line groups.
; Begin address of those line group information tables is 000Ah. Information
; tables don't begin at zero, because this makes scroller-routine little
; faster. Maybe it has no meaning, but it won't make the code longer (:
Mov Di,000Ah ; Di=pointter in table
Xor Cx,Cx ; Cx=x coordinate of vertical line
DeriveDWordLoop: Mov Bx,Cx ; Dcosx=-sinx, so take the
Sub Bx,50h ; right value from the table,
Cmp Cx,4Fh ; where is a half of the
Ja IsInRange ; cosine wave. Move to Bx
Mov Bx,004Fh ; value, where in the table
Sub Bx,Cx ; the derived value can be find.
; In this case x=Cx*(360/320)
; what means that value in the
; position 0=0 degrees, 1=1.125,
; 2=2.25 etc.
IsInRange: Xor Ax,Ax
Mov Al,ScrollersTrack[Bx] ; Ax=Dcos*20+20
Shl Ax,04h ; make derived value to fit in
Sub Ax,0140h ; the range 1-31. If there
Mov Bl,15h ; is more colors, shading don't
Idiv Bl ; look good.
Add Al,10h
Mov Dl,Al
Ror Edx,08h
Inc Cx
Test Cl,03h ; make shadow for 4 lines
Jnz DeriveDWordLoop; at the time (DoubleWord)
Mov Fs:[Di],Edx; store 4 shadows to the table
Mov Bx,Cx ; Bx=Cx-4
Sub Bx,04h
Xor Ax,Ax ; set to Ax the cosine value,
Mov Al,ScrollersTrack[Bx]; which equals the Cx and
Shr Al,01h ; divide it by 2
Mov Bx,Ax ; calculate to Bx the heigh of
Add Bx,Bx ; the scroller at the screen at
Add Bx,28h ; Cx and then store it (4 lines)
Mov Fs:[Di+04h],Bx
Neg Ax ; calculate the begin address of
Add Ax,0087h ; the line group (line group
Mov Bp,0140h ; consists 4 vertical lines)
Mul Bp
Add Ax,Cx
Sub Ax,04h
Mov Fs:[Di+06h],Ax
Mov Ax,Cx ; to the end of this line group
Shr Ax,01h ; information store the segment,
Dec Ax ; where are the addresses where
Dec Ax ; pixels will be taken. The
Mul Bp ; addresses will be calculated
Shr Ax,04h ; when this table is ready
ScrollDataBegin: Add Ax,7777h ; add to the segment the base
Mov Fs:[Di+08h],Ax; segment and store it
Add Di,0Ah ; calculate next line group
Cmp Cx,Bp ; information, if any group left
Jb DeriveDWordLoop
; Precalculate now the source addresses for every pixel in the scroller.
; Scroller consist 27408 pixels and one address takes a word. One line group
; will be stored to its own segment, and I don't want to make this code
; any longer so every segment has same size (80*4*2 bytes=640 bytes, because
; at the highest place of the scroller the height is 80 pixels).
Xor Si,Si ; Si=x coordinate of vertical line
Xor Cx,Cx ; Cx=x coordinate of source
Xor Bp,Bp ; Bp=decimal part of Cx
Xor Bx,Bx ; Bx=(line group number+1)*10
CalculateDataLoop1: Xor Di,Di ; Di=source address store place
Add Bx,000Ah ; One line group info length
CalculateDataLoop2: Push Bx
Mov Gs,Fs:[Bx+08h] ; Get source address segment
Mov Bx,Fs:[Bx+04h] ; Get line group height
Xor Ax,Ax ; Calculate adding value to Ax
Mov Dx,0007h ; Height of the font is 7 pixels
Div Bx ; Ax=carry add value
Push Di
Push Cx
Or Di,Di
Jnz NoSwap1
Mov Di,06h
Jmp FillOneYLine
NoSwap1: Cmp Di,06h
Jne FillOneYLine
Xor Di,Di
FillOneYLine: Mov Gs:[Di],Cx ; Save address to source addresses
Add Dx,Ax ; Increase y-coordinate with carry
Jnc DontAddY
Inc Ch
DontAddY: Add Di,08h ; Next address where to save
Dec Bx ; Save next pixel if any left
Jnz FillOneYLine
Pop Cx
Pop Di
; Calculate adding value which moves the reading pointer in scrolling-area.
; There must notice, that the steedness of position and z position will affect
; to the value. Below program will calculate that value. The adding value
; comes from following equation:
; A:=(1.707106781-(Abs(20-Table[I])*0.035355339))*(16/(Table[I]+40));
; where I is the x-coordinate of vertical line and table points to
; the table SCROLLERSTRACK.
Mov Ax,0014h ; Take absolute value of this
Sub Al,ScrollersTrack[Si]; subtraction,
Jns DontNeg ; if the value in Al will be in
Neg Al ; range 0-20
DontNeg: Mov Dx,090Dh ; Multiply the value by
Mul Dx ; Cos45*65536/20=090Dh
Neg Ax ; Subtract this value from
Add Ax,0B505h ; Cos45*65536=B505h
Inc Dx ; Move to Dx 1 and multibly
Shld Dx,Ax,04h ; 32 bit value by 16
Mov Bl,ScrollersTrack[Si] ; Then divide the value
Add Bl,28h ; by the length of vertical line
Div Bx ; Bh is zero because of above loop
Add Bp,Ax ; Add to Bp the result and add
Adc Cx,00h ; Cx(=source address) with carry
Inc Di
Inc Di
Inc Si
Pop Bx
Test Si,03h ; calculate 4 vertical lines to
Jnz CalculateDataLoop2; same segment
Cmp Si,0140h ; repeat until all 320 lines
Jb CalculateDataLoop1; are calculated
; set screen mode 320x200x256
Mov Ax,0013h
Int 10h
; Start playing
Cli
Xor Ax,Ax
Mov Ds:[TempoCounter],Al; zero tempocounter
Mov Byte Ptr Ds:[Row+0001h],Al; and row number
Mov Word Ptr Ds:[SongPosition+0001h],Offset SongOrder
Push Ax
Pop Gs
Mov Eax,Gs:[8*4]
Mov Ds:[OldTimerInt],Eax
Mov Al,34h ; timer interrupt request 70Hz
Out 43h,Al
Mov Al,95h
Out 40h,Al
Mov Al,42h
Out 40h,Al
Push Cs ; set player interrupt
Pop Ax
Rol Eax,10h
Mov Ax,Offset Player
Mov Gs:[8*4],Eax
; Set new key interrupt
Mov Edx,Gs:[9*4]
Mov Ds:[OldKeyInt],Edx
Mov Ax,Offset KeyInterrupt
Mov Gs:[9*4],Eax
Sti
; Get characters
Push 0A000h
Pop Ds
Mov Ax,0220h ; first character is space
Xor Dx,Dx ; cursor position is 0,0
Mov Di,Offset Fonts ; offset to store characters
MoveNewCharacter: Xor Si,Si ; character screen address
Mov Bx,001Fh ; the color of characters is 31
PushA ; this line is for AMI-BIOS
Int 10h
PopA ; this line is for AMI-BIOS
PushA ; this line is for AMI-BIOS
Mov Ah,0Eh ; write character at cursor
Int 10h
PopA ; this line is for AMI-BIOS
Mov Ch,08h ; copy 8 horizontal lines and
MoveCharacterLoop2: Mov Cl,08h ; 8 vertical lines
MoveCharacterLoop1: MovsB ; double the width of a character
Dec Si
MovsB
Dec Cl
Jnz MoveCharacterLoop1
Add Si,0138h ; do next line
Dec Ch
Jnz MoveCharacterLoop2
Inc Al ; copy characters 32-127
Jns MoveNewCharacter
Push Ds
Pop Es ; Es=0A000h
Push Cs
Pop Ds ; Ds=Cs
Mov Ax,0013h ; clear screen
Int 10h
; Palette setting routine sets the color of the text purple
Mov Dx,03C8h
Mov Al,01h
Out Dx,Al
Inc Dx
Mov Ah,07h
SetPaletteLoop: Mov Al,Ah
Out Dx,Al
Xor Al,Al
Out Dx,Al
Mov Al,Ah
Out Dx,Al
Inc Ah
Cmp Ah,26h
Jb SetPaletteLoop
Xor Cx,Cx ; scrollers position
Xor Bx,Bx ; text counter
Mov Di,0080h ; position to write font
IntroLoop:
KeyValue: Mov Al,00h ; check, if ESC pressed
Cmp Al,01h
Jne NoESC
; Stop playing
Cli ; set timer interrupt to occur
Mov Al,34h ; 18.2 times/second
Out 43h,Al
Xor Al,Al
Out 40h,Al
Out 40h,Al
Push 00h
Pop Gs ; Return old timer interrupt and
Mov Eax,Ds:[OldTimerInt]
Mov Gs:[8*4],Eax; old key interrupt
Mov Eax,Ds:[OldKeyInt]
Mov Gs:[9*4],Eax
Sti
Jmp GoodBye
NoESC: Mov Gs,Word Ptr [TextSegment+0001h]
Test Cl,0Fh ; test, if font must be writen
Jnz DontPutFont
Xor Ax,Ax ; write font
Mov Al,ScrollText[Bx] ; read font to write
Mov Si,Ax ; calculate the address of the
Sub Si,20h ; font in the code segment
Shl Si,07h
Add Si,Offset Fonts+0060h
Mov Bp,Di ; set to Bp the position of font
Mov Dh,07h ; copy 7 lines and
Loop2: Mov Dl,10h ; 16 columns
Loop1: Mov Al,Ds:[Si]
Mov Gs:[Bp],Al
Inc Si
Inc Bp
Dec Dl
Jnz Loop1
Add Bp,00F0h ; next line address
Sub Si,20h
Dec Dh
Jnz Loop2
Inc Bx ; increase text counter
Cmp Bx,ScrollTextEnd-ScrollText
Jb DontPutFont; if all fonts has been writed
Xor Bx,Bx ; start text at the beginning
DontPutFont: Push Bx ; save value of text counter
Mov Ah,07h ; move one vertical line in
Mov Bx,Di ; the scrolling-area to left
CopyVerticalLine: Mov Al,Gs:[Bx] ; so scroller seems to be
Mov Gs:[Bx-80h],Al; continuing
Inc Bh
Dec Ah
Jnz CopyVerticalLine
Inc Cx ; add scroller position and
Inc Di ; draw/move position
Or Cl,Cl ; If Cl>127, zero counters
Jns NoZeroing
Xor Cx,Cx
Mov Di,0080h
NoZeroing: Push Di
; Below routine writes the text to the scroller using those tables, which
; the program created before.
Mov Word Ptr [ScrollLinePointer+0001h],0316h
Mov Si,0320h
TextSegment: Push 7777h ; move to Ds the scrolling-area
Pop Ds ; segment
ScrollLineLoop: Mov Edx,Fs:[Si]; read shading to Edx
Mov Bx,Fs:[Si+04h]; line group height to Bp
Dec Bx ; decrease it and multiply by 8
Shl Bx,03h ; so we get the address
Mov Di,Fs:[Si+06h]; get linegroup write address
Mov Gs,Fs:[Si+08h]; get source address segment
ScrollMainLoop: Mov Si,Gs:[Bx+04h]; get two source addresses
Add Si,Cx
Mov Al,Ds:[Si]
Mov Si,Gs:[Bx]
Add Si,Cx
Mov Ah,Ds:[Si]
Rol Eax,10h
Mov Si,Gs:[Bx+06h]
Add Si,Cx
Mov Al,Ds:[Si]
Mov Si,Gs:[Bx+02h]
Add Si,Cx
Mov Ah,Ds:[Si]
And Eax,Edx ; make shadow for those bytes
Mov Es:[Di],Eax; and store to screen memory
Add Di,0140h ; move one line down and get
Sub Bx,08h ; next information if any left
Jnc ScrollMainLoop
ScrollLinePointer: Mov Si,7777h
Sub Word Ptr Cs:[ScrollLinePointer+0001h],0Ah
Jnc ScrollLineLoop; loop this 80 times
Push Cs ; move Cs to Ds
Pop Ds
Mov Dx,03DAh
Cli
WaitVR: In Al,Dx
And Al,08h
Jz WaitVR
Sti
Pop Di ; restore write position and
Pop Bx ; text counter
Jmp IntroLoop
InitializeAdlib Proc Near
Mov Ax,2001h ; initialize Adlib
Call AdlibCommand
Mov Ax,0008h ; set right mode and key split
Call AdlibCommand
Mov Al,0B0h
QuietChannelLoop: Call AdlibCommand
Inc Al
Cmp Al,0BEh
Jb QuietChannelLoop
Ret
InitializeAdlib EndP
AdlibCommand Proc Near ; Al=command, Ah=data
PushA
Mov Dx,0388h ; command port
Mov Cl,05h
Call WriteAndWait
Inc Dx ; data port
Mov Al,Ah
Mov Cl,10h
Call WriteAndWait
PopA
Ret
WriteAndWait: Out Dx,Al
WaitAdlibLoop: In Al,Dx
Dec Cl
Jnz WaitAdlibLoop
Ret
AdlibCommand EndP
Player Proc Near
PushA
Push Ds
Push Es
Push Cs
Pop Ds
Dec Ds:[TempoCounter]; test if next row
Jns DontChangeRows
Mov Ds:[TempoCounter],07h; tempo is 7
Xor Bp,Bp
PatternsSegment: Push 7777h ; Move to Es the segment of
Pop Es ; patterns
Row: Mov Bl,77h ; Bl=Row number*4
Mov Al,Channels*16
SongPosition: Mov Si,7777h ; one track takes 256 bytes, so
Mul Byte Ptr Ds:[Si]; set pattern nr*channels
Mov Bh,Ah ; to Bh
SetChannelsLoop: Mov Cx,Es:[Bx] ; Cl=note value, Ch=volume
Cmp Cl,0FFh ; If no note, set next track
Je NoNote
Mov Dx,Es:[Bx+02h]; Dl=octave, Dh=instrument
Mov Ax,Bp
Add Al,0B0h
Call AdlibCommand
Mov Al,Ss:[Bp+AdlibAddress]
Add Al,20h
Cmp Byte Ptr Ss:[Bp+InstrumentInfo],Dh
Je DontChangeInst
Mov Byte Ptr Ss:[Bp+InstrumentInfo],Dh
Sub Al,20h ; set instrument, if it's not same
Movzx Di,Dh ; as before
Add Di,Offset Instrument
SetInstrumentLoop: Add Al,1Dh
Mov Ah,Ds:[Di]
Call AdlibCommand
Add Al,03h
Mov Ah,Ds:[Di+Instruments]
Add Di,Instruments*2
Call AdlibCommand
Or Al,Al
Jns SetInstrumentLoop
Add Al,40h
Jnc SetInstrumentLoop
Push Ax
Mov Ax,Bp
Add Al,0C0h
Mov Ah,Ds:[Di]
Call AdlibCommand
Pop Ax
DontChangeInst: Add Al,20h ; set volume of the instrument
Mov Ah,Ch
Call AdlibCommand
Movzx Di,Cl ; set new note to channel
Mov Ax,Bp
Add Al,0A0h
Mov Ah,Byte Ptr Ds:[Di+NoteValue]
Call AdlibCommand
Add Al,10h
Mov Ah,Byte Ptr Ds:[Di+Offset Notevalue+0001h]
Or Ah,Dl
Call AdlibCommand
NoNote: Inc Bh
Inc Bp
Cmp Bp,Channels; do all channels
Jb SetChannelsLoop
Add Bl,04h ; increase row
Adc Si,00h ; if last row, increase song pos.
Cmp Si,Offset SongOrder+SongLength
Jb NoRestart
Mov Si,Offset SongOrder+Restart
NoRestart: Mov Word Ptr Ds:[SongPosition+0001h],Si
Mov Byte Ptr Ds:[Row+0001h],Bl
DontChangeRows: Pop Es
Pop Ds
Mov Al,20h ; send EOI to IRQ-chip
Out 20h,Al
PopA
Iret
Player EndP
KeyInterrupt Proc Near
Push Ax
Mov Al,20h ; EOI
Out 20h,Al
In Al,60h
Mov Byte Ptr Cs:[KeyValue+0001h],Al
Pop Ax
Iret
KeyInterrupt EndP
ScrollText Db ' THE SOLARIUM - ANARCHY SFHQ - THE BBS '
Db 'SERVES 24h A DAY AND OFFERS 1GB HARD DISK '
Db 'SPACE FOR YOUR USE WITH 16800 ZYXEL! '
Db 'CALL +358-31-3170851 NOW!!! '
ScrollTextEnd Label
BBSInfoText Db 'Solarium',00h,00h,'+358-31-3170851'
BBSInfoTextEnd Label
PackedTrack Db 09Ch,056h,044h,034h,043h,023h,033h,023h
Db 033h,032h,023h,023h,033h,023h,033h,033h
Db 043h,044h,054h,086h,008h
AdlibAddress Db 003h,004h,005h,00Bh,00Ch,00Dh,013h,014h,015h
NoteValue Dw 2157h ; C-x
Dw 2181h ; D-x
Dw 21B0h ; E-x
Dw 21CAh ; F-x
Dw 2202h ; G-x
Dw 2241h ; A-x
Dw 2287h ; B-x
Instruments Equ 09h
Instrument Db 008h,0C2h,0C8h,0E2h,0EFh,0E0h,0C4h,0E2h,0C0h
Db 0E2h,0E2h,0E2h,0E2h,0E0h,0C0h,0E4h,0E2h,0E4h
Db 020h,01Ah,020h,010h,000h,000h,017h,00Eh,000h
Db 000h,006h,00Ah,008h,000h,000h,000h,000h,000h
Db 0F4h,015h,095h,0F4h,070h,0A8h,084h,0AFh,0F0h
Db 0F6h,054h,076h,0F6h,077h,0F6h,075h,0F6h,0F7h
Db 0F7h,0F9h,0F7h,0F4h,089h,058h,0F7h,0F6h,084h
Db 0F7h,0F7h,0F8h,0F7h,0F9h,0F8h,0F7h,0F6h,0F6h
Db 002h,000h,002h,000h,000h,000h,000h,001h,000h
Db 001h,000h,000h,000h,003h,000h,001h,000h,000h
Db 000h,006h,006h,00Ch,00Eh,008h,004h,008h,00Ch
Channels Equ 09h
Patterns Equ 07h
SongLength Equ 0Bh
ReStart Equ 05h
SongOrder Db 000h,010h,010h,020h,020h,030h,040h,050h,050h
Db 060h,060h
Pattern00 Db 0FFh ; Track 00
Db 0FFh ; Track 01
Db 005h,000h ; Track 02
Db 0E3h,0F1h
Db 05Fh,0EAh,047h,057h
Db 002h,080h ; Track 03
Db 011h,010h ; Track 04
Db 0E4h,0F2h
Db 073h,057h,061h,081h,053h,02Bh,073h,071h,081h
Db 091h,071h,081h,061h,063h,043h,027h
Db 01Ch,033h ; Track 05
Db 0E4h,0F2h
Db 072h,070h,052h,052h,051h,061h,081h,052h,050h
Db 022h,022h,022h,022h,072h,070h,071h,081h,091h
Db 071h,081h,061h,062h,060h,042h,040h,022h,021h
Db 0FFh ; Track 06
Db 015h,060h ; Track 07
Db 0E6h,0F4h
Db 071h,075h,073h,073h,071h,075h,072h,070h,073h
Db 071h,075h,072h,072h,071h,071h,075h,072h,070h
Db 071h,071h
Db 0FFh ; Track 08
Pattern01 Db 0FFh ; Track 09
Db 0FFh ; Track 0A
Db 002h,080h ; Track 0B
Db 002h,080h ; Track 0C
Db 004h,090h ; Track 0D
Db 005h,0B0h ; Track 0E
Db 062h,000h ; Track 0F
Db 0E2h,0F3h
Db 053h
Db 0E0h
Db 053h
Db 003h
Db 043h,043h,053h,053h
Db 007h,0E0h ; Track 10
Db 0FFh ; Track 11
Pattern02 Db 0A5h,000h ; Track 12
Db 0E3h,0F0h
Db 051h,091h,0A1h,0C1h
Db 007h
Db 041h,081h,091h,0B1h,051h,091h,0A1h,0C1h
Db 4Ah,000h ; Track 13
Db 0E3h,0F7h
Db 051h,051h,0C1h,0C0h,051h,051h,050h,0C1h,0C1h
Db 008h
Db 051h,051h,0C1h,050h,051h,050h,051h,0C1h,0C1h
Db 0A0h,000h ; Track 14
Db 057h
Db 001h
Db 047h,057h
Db 014h,080h ; Track 15
Db 004h,090h ; Track 16
Db 005h,0B0h ; Track 17
Db 00Fh,080h ; Track 18
Db 007h,0E0h ; Track 19
Db 00Bh,000h ; Track 1A
Db 0E2h,0F5h
Db 000h,000h,000h,002h,000h,000h,001h,000h,004h
Db 0EBh
Pattern03 Db 0FFh ; Track 1B
Db 013h,080h ; Track 1C
Db 0FFh ; Track 1D
Db 0FFh ; Track 1E
Db 0FFh ; Track 1F
Db 0FFh ; Track 20
Db 067h,00h ; Track 21
Db 0E1h,051h,050h,050h,0B0h,050h,0B0h,0C0h
Db 067h
Db 0E2h,011h,010h,010h,070h,010h,070h,080h
Db 0FFh ; Track 22
Db 0FFh ; Track 23
Pattern04 Db 0FFh ; Track 24
Db 013h,080h ; Track 25
Db 0FFh ; Track 26
Db 0FFh ; Track 27
Db 0FFh ; Track 28
Db 0E1h,034h ; Track 29
Db 0E2h
Db 007h
Db 021h,080h ; Track 2A
Db 0E2h,004h ; Track 2B
Db 0E2h,0F8h
Db 007h
Db 08Bh,000h ; Track 2C
Db 001h,070h,070h,071h,070h,000h,070h,000h,001h
Db 071h,070h,070h
Pattern05 Db 0FFh ; Track 2D
Db 0FFh ; Track 2E
Db 044h,000h ; Track 2F
Db 0E4h,0F0h
Db 090h,080h,070h
Db 003h
Db 060h,051h,023h,0E9h
Db 042h
Db 010h,020h,030h
Db 003h
Db 050h,071h,014h,0E9h
Db 02Fh,0A2h ; Track 30
Db 02Fh,0C5h ; Track 31
Db 029h,0B0h ; Track 32
Db 021h,080h ; Track 33
Db 02Bh,080h ; Track 34
Db 02Ch,080h ; Track 35
Pattern06 Db 063h,000h ; Track 36
Db 0E2h
Db 052h,052h,051h
Db 062h
Db 012h,012h,011h
Db 011h,030h ; Track 37
Db 0F6h
Db 023h,021h,051h,083h,093h,023h,021h,011h,027h
Db 013h,051h,011h,051h,041h,031h,021h,01Fh
Db 02Bh,000h ; Track 38
Db 090h,080h,070h,090h,080h,070h,090h,080h,070h
Db 060h,051h,023h
Db 042h
Db 010h,020h,030h
Db 002h
Db 050h,071h,013h
Db 042h
Db 080h,090h,0A0h
Db 002h
Db 0B0h,0C1h,083h
Db 038h,0A2h ; Track 39
Db 038h,0C5h ; Track 3A
Db 029h,0B0h ; Track 3B
Db 021h,080h ; Track 3C
Db 02Bh,080h ; Track 3D
Db 02Ch,080h ; Track 3E
SongDataEnd Label
; --- Cut below bytes off from compiled COM file ---
ScrollersTrack Db 0140h Dup(00h)
TempoCounter Db 00h
OldTimerInt Dd 00000000h
OldKeyInt Dd 00000000h
ChannelInfo Dw Channels Dup(0000h)
InstrumentInfo Db Channels Dup(00h)
Fonts Db 3000h Dup(00h)
Code EndS
End Start