home *** CD-ROM | disk | FTP | other *** search
/ The Party 1994: Try This At Home / disk_image.bin / source / solarsrc / solarium.asm < prev    next >
Assembly Source File  |  1994-06-18  |  47KB  |  878 lines

  1. ; ///////////////////////////////////////////////////////////////////////////
  2. ; ////                                                                   ////
  3. ; ////  ▄██████ ▄█████▄ ███        ███    ██████▄ ███ ███ ███ ███   ███  ////
  4. ; ////  ███     ███ ███ ███       █████   ███ ███ ███ ███ ███ ████ ████  ////
  5. ; ////  ▀█████▄ ███ ███ ███      ███ ███  ██████▀ ███ ███ ███ ███ █ ███  ////
  6. ; ////      ███ ███ ███ ███     ███   ███ ███▀██▄ ███ ███ ███ ███   ███  ////
  7. ; ////  ██████▀ ▀█████▀ ███████ ███   ███ ███ ▀██ ███ ▀█████▀ ███   ███  ////
  8. ; ////                                                                   ////
  9. ; ////               Copyright (C) 1994 Altair/Anarchy-PC                ////
  10. ; ////                                                                   ////
  11. ; ////                                                                   ////
  12. ; ////                                                                   ////
  13. ; ////  Coding: Altair                                                   ////
  14. ; ////   Music: Modified HSC-Tracker tune                                ////
  15. ; ////                                                                   ////
  16. ; //// Program requires 386 and VGA for operating. It has been tested    ////
  17. ; //// with 486/33Mhz (no localbus) where scroller took half frame with  ////
  18. ; //// 70Hz screen update. Player is quite slow, but it has been mainly  ////
  19. ; //// optimized for size like everything else but scroller. Three tips: ////
  20. ; //// VGA detecting and 'zeros to end' were taken from Future Crews     ////
  21. ; //// StarPort II and processor detecting from Tietokone-Magazine, but  ////
  22. ; //// everything else is self-studied and self-created. Solarium uses   ////
  23. ; //// alot of variables, which are included into the code itself. When  ////
  24. ; //// you do something like that in your own programs, remember that    ////
  25. ; //// value is not necessarely in the code at the time when the command ////
  26. ; //// performs. There is no speedup with computers above 286 and those  ////
  27. ; //// don't shrink the code either. I must have a headache, when I made ////
  28. ; //// the code using that kind of variables (: In the code might be     ////
  29. ; //// some parts which could be optimized in smaller size or done other ////
  30. ; //// ways better, but I have changed this code many times and haven't  ////
  31. ; //// probably noticed everything. You can use parts of this code in    ////
  32. ; //// your own programs if you like, but it would be nice for you to    ////
  33. ; //// mention where have you got your source materials.                 ////
  34. ; //// I have used TASM and TLINK to create the original SOLARIUM.COM.   ////
  35. ; ////                                                                   ////
  36. ; //// Program consist of following operations:                          ////
  37. ; ////   - allocate memory                                               ////
  38. ; ////   - detect processor                                              ////
  39. ; ////   - unpack music                                                  ////
  40. ; ////   - detect VGA                                                    ////
  41. ; ////   - clear scrolling-area                                          ////
  42. ; ////   - initialize adlib                                              ////
  43. ; ////   - make Cos-wave                                                 ////
  44. ; ////   - precalculate the track of the scrollers                       ////
  45. ; ////       ∙ calculate the screen address for each vertical line       ////
  46. ; ////       ∙ calculate the source position for each pixel              ////
  47. ; ////       ∙ calculate the shading for each vertical pixel line        ////
  48. ; ////   - set the music routine to the timer interrupt                  ////
  49. ; ////   - set the new key interrupt (disable pause etc.)                ////
  50. ; ////   - create the characters                                         ////
  51. ; ////   - set palette                                                   ////
  52. ; ////   - intro-loop                                                    ////
  53. ; ////       ∙ test if ESC pressed                                       ////
  54. ; ////       ∙ write text to scrolling-area                              ////
  55. ; ////       ∙ draw scroll to the screen                                 ////
  56. ; ////       ∙ wait vertical retrace                                     ////
  57. ; ////   - return old interrupts                                         ////
  58. ; ////   - return to DOS                                                 ////
  59. ; ////                                                                   ////
  60. ; ///////////////////////////////////////////////////////////////////////////
  61.  
  62. Code                    Segment
  63.                         Assume   Cs:Code,Ds:Code
  64.                         Org      0100h
  65.   Start:                .186
  66.                         Push     Cs
  67.                         Pop      Ds
  68.                         Mov      Bx,2113h   ; allocate memory for operations
  69.                         Mov      Ah,4Ah     ;  which SOLARIUM.COM uses
  70.                         Int      21h        ;  (pattern etc.)
  71.                         Jc       GoodBye
  72.                         Push     Sp         ; is the processor 80186?
  73.                         Pop      Bx
  74.                         Cmp      Bx,Sp
  75.                         Je       Not80186
  76.     GoodBye:            Call     InitializeAdlib; quiet adlib
  77.                         Mov      Ax,0003h   ; set text-mode
  78.                         Int      10h
  79.                         Push     0B800h
  80.                         Pop      Es
  81.                         Xor      Di,Di
  82.                         Mov      Si,Offset BBSInfoText
  83.                         Mov      Ah,0Dh
  84.     WriteBBSText:       Mov      Al,Cs:[Si]
  85.                         Or       Al,Al
  86.                         Jnz      NoColorChange
  87.                         Inc      Ah
  88.     NoColorChange:      StosW
  89.                         Inc      Si
  90.                         Cmp      Si,Offset BBSInfoTextEnd
  91.                         Jb       WriteBBSText
  92.                         Mov      Ax,4C00h
  93.                         Int      21h        ; return to DOS
  94.     Not80186:           .286
  95.                         Mov      Bx,0F000h  ; is it 80286?
  96.                         Push     Bx
  97.                         PopF
  98.                         PushF
  99.                         Pop      Bx
  100.                         And      Bx,0F000h
  101.                         Je       GoodBye    ; if it's 80286 -> bye
  102.                         .386
  103.                         Add      Ax,1000h
  104.                         Mov      Word Ptr [ScrollDataBegin+0001h],Ax
  105.                         Add      Ax,0C80h
  106.                         Mov      Fs,Ax      ; segment for scroller-info
  107.                         Add      Ax,33h     ; save segment for scrolling-area
  108.                         Mov      Word Ptr [TextSegment+0001h],Ax;  here
  109.                         Mov      Es,Ax
  110.                         Add      Ax,70h
  111.                         Mov      Gs,Ax
  112. ; Unpack all patterns
  113.                         Mov      Word Ptr [PatternsSegment+0001h],Ax
  114.                         Mov      Bx,Channels*64*4*Patterns-1
  115.                         Mov      Di,Channels
  116.     ResetInstruments:   Mov      [Di+InstrumentInfo-0001h],Bl
  117.                         Dec      Di
  118.                         Jnz      ResetInstruments
  119.     ClearPatterns:      Mov      Byte Ptr Gs:[Bx],0FFh
  120.                         Dec      Bx
  121.                         Jns      ClearPatterns
  122.                         Mov      Byte Ptr [TrackCounter+0001h],00h
  123.                         Mov      Si,Offset Pattern00
  124.     MakeTrack:          Mov      Dx,[Si]
  125.                         Inc      Si
  126.                         Cmp      Dl,0FFh
  127.                         Je       NoNotes
  128.                         Inc      Si
  129.                         Mov      Bl,Dh
  130.                         And      Bl,0Fh
  131.                         Shl      Bl,02h
  132.     TrackCounter:       Mov      Bh,77h
  133.                         Mov      Ah,Dh
  134.                         And      Ah,70h
  135.                         Shr      Ah,02h
  136.                         Add      Dh,Dh
  137.                         Jc       CopyTrack
  138.                         Mov      Cx,[Di+ChannelInfo]
  139.     NextGroup:          Mov      Dh,Dl
  140.                         And      Dl,1Fh
  141.                         Mov      Bp,Dx
  142.     LoopStoring:        Push     Si
  143.     ReadCommand:        Mov      Al,[Si]
  144.                         Inc      Si
  145.                         Mov      Dh,Al
  146.                         Shr      Al,04h
  147.                         And      Dh,0Fh
  148.                         Cmp      Al,0Eh
  149.                         Je       SetOctaveOrSpace
  150.                         Ja       SetInstrument
  151.                         Push     Cx
  152.                         Cmp      Al,07h
  153.                         Jb       DontIncOctave
  154.                         Inc      Cl
  155.                         Sub      Al,07h
  156.     DontIncOctave:      Shl      Cl,02h
  157.                         Add      Al,Al
  158.                         Mov      Gs:[Bx],Ax
  159.                         Mov      Gs:[Bx+02h],Cx
  160.                         Pop      Cx
  161.                         Inc      Dh
  162.                         Shl      Dh,02h
  163.                         Add      Bl,Dh
  164.                         Jc       TrackFull
  165.     ExtraCommandReturn: Dec      Dl
  166.                         Jns      ReadCommand
  167.                         Mov      Dx,Bp
  168.                         Pop      Si
  169.                         Sub      Bp,2000h
  170.                         Jnc      LoopStoring
  171.                         And      Bp,001Fh
  172.                         Add      Si,Bp
  173.                         Inc      Si
  174.                         Mov      Dl,[Si]
  175.                         Inc      Si
  176.                         Jmp      NextGroup
  177.     SetOctave:          Mov      Cl,Dh
  178.                         Dec      Cl
  179.                         Jmp      ExtraCommandReturn
  180.     SetInstrument:      Mov      Ch,Dh
  181.                         Jmp      ExtraCommandReturn
  182.     CopyTrack:          Push     Si
  183.                         Shl      Dx,08h
  184.                         Mov      Si,Dx
  185.       CopyingLoop:      Mov      Al,Gs:[Si]
  186.                         Mov      Cx,Gs:[Si+02h]
  187.                         Mov      Gs:[Bx],Ax
  188.                         Mov      Gs:[Bx+02h],Cx
  189.                         Add      Si,04h
  190.                         Add      Bl,04h
  191.                         Jnc      CopyingLoop
  192.                         Pop      Si
  193.                         Jmp      NoNotes
  194.     SetOctaveOrSpace:   Test     Dh,08h
  195.                         Jz       SetOctave
  196.                         Shl      Dh,06h
  197.                         Add      Bl,Dh
  198.                         Jnc      ExtraCommandReturn
  199.     TrackFull:          Pop      Si
  200.                         And      Bp,001Fh
  201.                         Add      Si,Bp
  202.                         Inc      Si
  203.                         Mov      [Di+ChannelInfo],Cx
  204.     NoNotes:            Inc      Byte Ptr [TrackCounter+0001h]
  205.                         Sub      Di,02h
  206.                         Jnc      DontZeroChl
  207.                         Mov      Di,0010h
  208.     DontZeroChl:        Cmp      Si,Offset SongDataEnd
  209.                         Jb       MakeTrack
  210. ; Detect VGA
  211.                         Mov      Ax,1A00h
  212.                         Int      10h        ; is the display VGA?
  213.                         Cmp      Al,1Ah
  214.                         Jne      GoodBye    ; if not VGA -> bye
  215. ; Clear the scrolling-area
  216.                         Mov      Di,06FFh   ; the length of scrolling-area -2
  217.     ClearAreaLoop:      Mov      Byte Ptr Es:[Di],00h
  218.                         Dec      Di
  219.                         Jns      ClearAreaLoop
  220.                         Call     InitializeAdlib
  221.  
  222. ; There is a packed cosine-wave in the end of this program and below program
  223. ; unpacks it to the SCROLLERSTRACK.
  224.  
  225.                         Push     Cs
  226.                         Pop      Es
  227.                         Mov      Si,Offset PackedTrack
  228.                         Mov      Di,Offset ScrollersTrack
  229.                         Mov      Cx,0029h
  230.     UnpackTrackLoop1:   LodsB
  231.     UnpackTrackLoop2:   Mov      Ah,Al
  232.                         And      Ah,0Fh
  233.                         Jz       UnpackTrackLoop1
  234.     UnpackTrackLoop3:   Mov      Ds:[Di],Ch
  235.                         Inc      Di
  236.                         Dec      Ah
  237.                         Jnz      UnpackTrackLoop3
  238.                         Inc      Ch
  239.                         Shr      Al,04h
  240.                         Dec      Cl
  241.                         Jnz      UnpackTrackLoop2
  242.                         Mov      Cl,0A0h
  243.                         Mov      Si,Offset ScrollersTrack+009Fh
  244.     MakeEndOfTheTrack:  MovsB               ; copy table in reverse order
  245.                         Dec      Si
  246.                         Dec      Si
  247.                         Dec      Cl         ; repeat 160 times
  248.                         Jnz      MakeEndOfTheTrack
  249.  
  250. ; Calculate the precalculation tables for scroller. First calculate the
  251. ; shadow of the scroller by deriving. This is possible, because scrollers
  252. ; track follows the function of cosine. Derived value means the steedness
  253. ; of the function in some place of it, so the value is in range -1 and +1
  254. ; and the angle of lightsource is naturaly 45 degrees to right and front
  255. ; from the the scroller. After this, store also the height of every 4th
  256. ; vertical line in the scroller (4 next vertical lines has always a same
  257. ; heigh, because this make writing to screen memory alot of faster).
  258. ; Then precalculate the screen address of all those 80 vertical line groups.
  259. ; Begin address of those line group information tables is 000Ah. Information
  260. ; tables don't begin at zero, because this makes scroller-routine little
  261. ; faster. Maybe it has no meaning, but it won't make the code longer (:
  262.  
  263.                         Mov      Di,000Ah   ; Di=pointter in table
  264.                         Xor      Cx,Cx      ; Cx=x coordinate of vertical line
  265.     DeriveDWordLoop:    Mov      Bx,Cx      ; Dcosx=-sinx, so take the
  266.                         Sub      Bx,50h     ;  right value from the table,
  267.                         Cmp      Cx,4Fh     ;  where is a half of the
  268.                         Ja       IsInRange  ;  cosine wave. Move to Bx
  269.                         Mov      Bx,004Fh   ;  value, where in the table
  270.                         Sub      Bx,Cx      ;  the derived value can be find.
  271.                                             ;  In this case x=Cx*(360/320)
  272.                                             ;  what means that value in the
  273.                                             ;  position 0=0 degrees, 1=1.125,
  274.                                             ;  2=2.25 etc.
  275.     IsInRange:          Xor      Ax,Ax
  276.                         Mov      Al,ScrollersTrack[Bx] ; Ax=Dcos*20+20
  277.                         Shl      Ax,04h     ; make derived value to fit in
  278.                         Sub      Ax,0140h   ;  the range 1-31. If there
  279.                         Mov      Bl,15h     ;  is more colors, shading don't
  280.                         Idiv     Bl         ;  look good.
  281.                         Add      Al,10h
  282.                         Mov      Dl,Al
  283.                         Ror      Edx,08h
  284.                         Inc      Cx
  285.                         Test     Cl,03h     ; make shadow for 4 lines
  286.                         Jnz      DeriveDWordLoop;  at the time (DoubleWord)
  287.                         Mov      Fs:[Di],Edx; store 4 shadows to the table
  288.                         Mov      Bx,Cx      ; Bx=Cx-4
  289.                         Sub      Bx,04h
  290.                         Xor      Ax,Ax      ; set to Ax the cosine value,
  291.                         Mov      Al,ScrollersTrack[Bx]; which equals the Cx and
  292.                         Shr      Al,01h     ;  divide it by 2
  293.                         Mov      Bx,Ax      ; calculate to Bx the heigh of
  294.                         Add      Bx,Bx      ;  the scroller at the screen at
  295.                         Add      Bx,28h     ;  Cx and then store it (4 lines)
  296.                         Mov      Fs:[Di+04h],Bx
  297.                         Neg      Ax         ; calculate the begin address of
  298.                         Add      Ax,0087h   ;  the line group (line group
  299.                         Mov      Bp,0140h   ;  consists 4 vertical lines)
  300.                         Mul      Bp
  301.                         Add      Ax,Cx
  302.                         Sub      Ax,04h
  303.                         Mov      Fs:[Di+06h],Ax
  304.                         Mov      Ax,Cx      ; to the end of this line group
  305.                         Shr      Ax,01h     ;  information store the segment,
  306.                         Dec      Ax         ;  where are the addresses where
  307.                         Dec      Ax         ;  pixels will be taken. The
  308.                         Mul      Bp         ;  addresses will be calculated
  309.                         Shr      Ax,04h     ;  when this table is ready
  310.     ScrollDataBegin:    Add      Ax,7777h   ; add to the segment the base
  311.                         Mov      Fs:[Di+08h],Ax;  segment and store it
  312.                         Add      Di,0Ah     ; calculate next line group
  313.                         Cmp      Cx,Bp      ;  information, if any group left
  314.                         Jb       DeriveDWordLoop
  315.  
  316. ; Precalculate now the source addresses for every pixel in the scroller.
  317. ; Scroller consist 27408 pixels and one address takes a word. One line group
  318. ; will be stored to its own segment, and I don't want to make this code
  319. ; any longer so every segment has same size (80*4*2 bytes=640 bytes, because
  320. ; at the highest place of the scroller the height is 80 pixels).
  321.  
  322.                         Xor      Si,Si      ; Si=x coordinate of vertical line
  323.                         Xor      Cx,Cx      ; Cx=x coordinate of source
  324.                         Xor      Bp,Bp      ; Bp=decimal part of Cx
  325.                         Xor      Bx,Bx      ; Bx=(line group number+1)*10
  326.     CalculateDataLoop1: Xor      Di,Di      ; Di=source address store place
  327.                         Add      Bx,000Ah   ; One line group info length
  328.     CalculateDataLoop2: Push     Bx
  329.                         Mov      Gs,Fs:[Bx+08h] ; Get source address segment
  330.                         Mov      Bx,Fs:[Bx+04h] ; Get line group height
  331.                         Xor      Ax,Ax      ; Calculate adding value to Ax
  332.                         Mov      Dx,0007h   ; Height of the font is 7 pixels
  333.                         Div      Bx         ; Ax=carry add value
  334.                         Push     Di
  335.                         Push     Cx
  336.                         Or       Di,Di
  337.                         Jnz      NoSwap1
  338.                         Mov      Di,06h
  339.                         Jmp      FillOneYLine
  340.     NoSwap1:            Cmp      Di,06h
  341.                         Jne      FillOneYLine
  342.                         Xor      Di,Di
  343.     FillOneYLine:       Mov      Gs:[Di],Cx ; Save address to source addresses
  344.                         Add      Dx,Ax      ; Increase y-coordinate with carry
  345.                         Jnc      DontAddY
  346.                         Inc      Ch
  347.     DontAddY:           Add      Di,08h     ; Next address where to save
  348.                         Dec      Bx         ; Save next pixel if any left
  349.                         Jnz      FillOneYLine
  350.                         Pop      Cx
  351.                         Pop      Di
  352.  
  353. ; Calculate adding value which moves the reading pointer in scrolling-area.
  354. ; There must notice, that the steedness of position and z position will affect
  355. ; to the value. Below program will calculate that value. The adding value
  356. ; comes from following equation:
  357. ; A:=(1.707106781-(Abs(20-Table[I])*0.035355339))*(16/(Table[I]+40));
  358. ; where I is the x-coordinate of vertical line and table points to
  359. ; the table SCROLLERSTRACK.
  360.  
  361.                         Mov      Ax,0014h   ; Take absolute value of this
  362.                         Sub      Al,ScrollersTrack[Si];  subtraction,
  363.                         Jns      DontNeg    ;  if the value in Al will be in
  364.                         Neg      Al         ;  range 0-20
  365.     DontNeg:            Mov      Dx,090Dh   ; Multiply the value by
  366.                         Mul      Dx         ;  Cos45*65536/20=090Dh
  367.                         Neg      Ax         ; Subtract this value from
  368.                         Add      Ax,0B505h  ;  Cos45*65536=B505h
  369.                         Inc      Dx         ; Move to Dx 1 and multibly
  370.                         Shld     Dx,Ax,04h  ;  32 bit value by 16
  371.                         Mov      Bl,ScrollersTrack[Si] ; Then divide the value
  372.                         Add      Bl,28h     ; by the length of vertical line
  373.                         Div      Bx         ; Bh is zero because of above loop
  374.                         Add      Bp,Ax      ; Add to Bp the result and add
  375.                         Adc      Cx,00h     ;  Cx(=source address) with carry
  376.                         Inc      Di
  377.                         Inc      Di
  378.                         Inc      Si
  379.                         Pop      Bx
  380.                         Test     Si,03h     ; calculate 4 vertical lines to
  381.                         Jnz      CalculateDataLoop2;  same segment
  382.                         Cmp      Si,0140h   ; repeat until all 320 lines
  383.                         Jb       CalculateDataLoop1;  are calculated
  384.  
  385. ; set screen mode 320x200x256
  386.                         Mov      Ax,0013h
  387.                         Int      10h
  388. ; Start playing
  389.                         Cli
  390.                         Xor      Ax,Ax
  391.                         Mov      Ds:[TempoCounter],Al; zero tempocounter
  392.                         Mov      Byte Ptr Ds:[Row+0001h],Al; and row number
  393.                         Mov      Word Ptr Ds:[SongPosition+0001h],Offset SongOrder
  394.                         Push     Ax
  395.                         Pop      Gs
  396.                         Mov      Eax,Gs:[8*4]
  397.                         Mov      Ds:[OldTimerInt],Eax
  398.                         Mov      Al,34h     ; timer interrupt request 70Hz
  399.                         Out      43h,Al
  400.                         Mov      Al,95h
  401.                         Out      40h,Al
  402.                         Mov      Al,42h
  403.                         Out      40h,Al
  404.                         Push     Cs         ; set player interrupt
  405.                         Pop      Ax
  406.                         Rol      Eax,10h
  407.                         Mov      Ax,Offset Player
  408.                         Mov      Gs:[8*4],Eax
  409. ; Set new key interrupt
  410.                         Mov      Edx,Gs:[9*4]
  411.                         Mov      Ds:[OldKeyInt],Edx
  412.                         Mov      Ax,Offset KeyInterrupt
  413.                         Mov      Gs:[9*4],Eax
  414.                         Sti
  415. ; Get characters
  416.                         Push     0A000h
  417.                         Pop      Ds
  418.                         Mov      Ax,0220h   ; first character is space
  419.                         Xor      Dx,Dx      ; cursor position is 0,0
  420.                         Mov      Di,Offset Fonts ; offset to store characters
  421.     MoveNewCharacter:   Xor      Si,Si      ; character screen address
  422.                         Mov      Bx,001Fh   ; the color of characters is 31
  423.                         PushA               ; this line is for AMI-BIOS
  424.                         Int      10h
  425.                         PopA                ; this line is for AMI-BIOS
  426.                         PushA               ; this line is for AMI-BIOS
  427.                         Mov      Ah,0Eh     ; write character at cursor
  428.                         Int      10h
  429.                         PopA                ; this line is for AMI-BIOS
  430.                         Mov      Ch,08h     ; copy 8 horizontal lines and
  431.     MoveCharacterLoop2: Mov      Cl,08h     ;  8 vertical lines
  432.     MoveCharacterLoop1: MovsB               ; double the width of a character
  433.                         Dec      Si
  434.                         MovsB
  435.                         Dec      Cl
  436.                         Jnz      MoveCharacterLoop1
  437.                         Add      Si,0138h   ; do next line
  438.                         Dec      Ch
  439.                         Jnz      MoveCharacterLoop2
  440.                         Inc      Al         ; copy characters 32-127
  441.                         Jns      MoveNewCharacter
  442.                         Push     Ds
  443.                         Pop      Es         ; Es=0A000h
  444.                         Push     Cs
  445.                         Pop      Ds         ; Ds=Cs
  446.                         Mov      Ax,0013h   ; clear screen
  447.                         Int      10h
  448.  
  449. ; Palette setting routine sets the color of the text purple
  450.  
  451.                         Mov      Dx,03C8h
  452.                         Mov      Al,01h
  453.                         Out      Dx,Al
  454.                         Inc      Dx
  455.                         Mov      Ah,07h
  456.     SetPaletteLoop:     Mov      Al,Ah
  457.                         Out      Dx,Al
  458.                         Xor      Al,Al
  459.                         Out      Dx,Al
  460.                         Mov      Al,Ah
  461.                         Out      Dx,Al
  462.                         Inc      Ah
  463.                         Cmp      Ah,26h
  464.                         Jb       SetPaletteLoop
  465.                         Xor      Cx,Cx      ; scrollers position
  466.                         Xor      Bx,Bx      ; text counter
  467.                         Mov      Di,0080h   ; position to write font
  468.     IntroLoop:
  469.     KeyValue:           Mov      Al,00h     ; check, if ESC pressed
  470.                         Cmp      Al,01h
  471.                         Jne      NoESC
  472. ; Stop playing
  473.                         Cli                 ; set timer interrupt to occur
  474.                         Mov      Al,34h     ;  18.2 times/second
  475.                         Out      43h,Al
  476.                         Xor      Al,Al
  477.                         Out      40h,Al
  478.                         Out      40h,Al
  479.                         Push     00h
  480.                         Pop      Gs         ; Return old timer interrupt and
  481.                         Mov      Eax,Ds:[OldTimerInt]
  482.                         Mov      Gs:[8*4],Eax;  old key interrupt
  483.                         Mov      Eax,Ds:[OldKeyInt]
  484.                         Mov      Gs:[9*4],Eax
  485.                         Sti
  486.                         Jmp      GoodBye
  487.     NoESC:              Mov      Gs,Word Ptr [TextSegment+0001h]
  488.                         Test     Cl,0Fh     ; test, if font must be writen
  489.                         Jnz      DontPutFont
  490.                         Xor      Ax,Ax      ; write font
  491.                         Mov      Al,ScrollText[Bx] ; read font to write
  492.                         Mov      Si,Ax      ; calculate the address of the
  493.                         Sub      Si,20h     ;  font in the code segment
  494.                         Shl      Si,07h
  495.                         Add      Si,Offset Fonts+0060h
  496.                         Mov      Bp,Di      ; set to Bp the position of font
  497.                         Mov      Dh,07h     ; copy 7 lines and
  498.     Loop2:              Mov      Dl,10h     ;  16 columns
  499.     Loop1:              Mov      Al,Ds:[Si]
  500.                         Mov      Gs:[Bp],Al
  501.                         Inc      Si
  502.                         Inc      Bp
  503.                         Dec      Dl
  504.                         Jnz      Loop1
  505.                         Add      Bp,00F0h   ; next line address
  506.                         Sub      Si,20h
  507.                         Dec      Dh
  508.                         Jnz      Loop2
  509.                         Inc      Bx         ; increase text counter
  510.                         Cmp      Bx,ScrollTextEnd-ScrollText
  511.                         Jb       DontPutFont; if all fonts has been writed
  512.                         Xor      Bx,Bx      ;  start text at the beginning
  513.     DontPutFont:        Push     Bx         ; save value of text counter
  514.                         Mov      Ah,07h     ; move one vertical line in
  515.                         Mov      Bx,Di      ;  the scrolling-area to left
  516.     CopyVerticalLine:   Mov      Al,Gs:[Bx] ;  so scroller seems to be
  517.                         Mov      Gs:[Bx-80h],Al;  continuing
  518.                         Inc      Bh
  519.                         Dec      Ah
  520.                         Jnz      CopyVerticalLine
  521.                         Inc      Cx         ; add scroller position and
  522.                         Inc      Di         ;  draw/move position
  523.                         Or       Cl,Cl      ; If Cl>127, zero counters
  524.                         Jns      NoZeroing
  525.                         Xor      Cx,Cx
  526.                         Mov      Di,0080h
  527.     NoZeroing:          Push     Di
  528.  
  529. ; Below routine writes the text to the scroller using those tables, which
  530. ; the program created before.
  531.  
  532.                         Mov      Word Ptr [ScrollLinePointer+0001h],0316h
  533.                         Mov      Si,0320h
  534.     TextSegment:        Push     7777h      ; move to Ds the scrolling-area
  535.                         Pop      Ds         ;  segment
  536.     ScrollLineLoop:     Mov      Edx,Fs:[Si]; read shading to Edx
  537.                         Mov      Bx,Fs:[Si+04h]; line group height to Bp
  538.                         Dec      Bx         ; decrease it and multiply by 8
  539.                         Shl      Bx,03h     ;  so we get the address
  540.                         Mov      Di,Fs:[Si+06h]; get linegroup write address
  541.                         Mov      Gs,Fs:[Si+08h]; get source address segment
  542.     ScrollMainLoop:     Mov      Si,Gs:[Bx+04h]; get two source addresses
  543.                         Add      Si,Cx
  544.                         Mov      Al,Ds:[Si]
  545.                         Mov      Si,Gs:[Bx]
  546.                         Add      Si,Cx
  547.                         Mov      Ah,Ds:[Si]
  548.                         Rol      Eax,10h
  549.                         Mov      Si,Gs:[Bx+06h]
  550.                         Add      Si,Cx
  551.                         Mov      Al,Ds:[Si]
  552.                         Mov      Si,Gs:[Bx+02h]
  553.                         Add      Si,Cx
  554.                         Mov      Ah,Ds:[Si]
  555.                         And      Eax,Edx    ; make shadow for those bytes
  556.                         Mov      Es:[Di],Eax;  and store to screen memory
  557.                         Add      Di,0140h   ; move one line down and get
  558.                         Sub      Bx,08h     ;  next information if any left
  559.                         Jnc      ScrollMainLoop
  560.     ScrollLinePointer:  Mov      Si,7777h
  561.                         Sub      Word Ptr Cs:[ScrollLinePointer+0001h],0Ah
  562.                         Jnc      ScrollLineLoop; loop this 80 times
  563.                         Push     Cs         ; move Cs to Ds
  564.                         Pop      Ds
  565.                         Mov      Dx,03DAh
  566.                         Cli
  567.     WaitVR:             In       Al,Dx
  568.                         And      Al,08h
  569.                         Jz       WaitVR
  570.                         Sti
  571.                         Pop      Di         ; restore write position and
  572.                         Pop      Bx         ;  text counter
  573.                         Jmp      IntroLoop
  574.  
  575.   InitializeAdlib       Proc     Near
  576.                         Mov      Ax,2001h   ; initialize Adlib
  577.                         Call     AdlibCommand
  578.                         Mov      Ax,0008h   ; set right mode and key split
  579.                         Call     AdlibCommand
  580.                         Mov      Al,0B0h
  581.     QuietChannelLoop:   Call     AdlibCommand
  582.                         Inc      Al
  583.                         Cmp      Al,0BEh
  584.                         Jb       QuietChannelLoop
  585.                         Ret
  586.   InitializeAdlib       EndP
  587.  
  588.   AdlibCommand          Proc     Near       ; Al=command, Ah=data
  589.                         PushA
  590.                         Mov      Dx,0388h   ; command port
  591.                         Mov      Cl,05h
  592.                         Call     WriteAndWait
  593.                         Inc      Dx         ; data port
  594.                         Mov      Al,Ah
  595.                         Mov      Cl,10h
  596.                         Call     WriteAndWait
  597.                         PopA
  598.                         Ret
  599.     WriteAndWait:       Out      Dx,Al
  600.       WaitAdlibLoop:    In       Al,Dx
  601.                         Dec      Cl
  602.                         Jnz      WaitAdlibLoop
  603.                         Ret
  604.   AdlibCommand          EndP
  605.  
  606.   Player                Proc     Near
  607.                         PushA
  608.                         Push     Ds
  609.                         Push     Es
  610.                         Push     Cs
  611.                         Pop      Ds
  612.                         Dec      Ds:[TempoCounter]; test if next row
  613.                         Jns      DontChangeRows
  614.                         Mov      Ds:[TempoCounter],07h; tempo is 7
  615.                         Xor      Bp,Bp
  616.     PatternsSegment:    Push     7777h      ; Move to Es the segment of
  617.                         Pop      Es         ;  patterns
  618.     Row:                Mov      Bl,77h     ; Bl=Row number*4
  619.                         Mov      Al,Channels*16
  620.     SongPosition:       Mov      Si,7777h   ; one track takes 256 bytes, so
  621.                         Mul      Byte Ptr Ds:[Si];  set pattern nr*channels
  622.                         Mov      Bh,Ah      ;  to Bh
  623.     SetChannelsLoop:    Mov      Cx,Es:[Bx] ; Cl=note value, Ch=volume
  624.                         Cmp      Cl,0FFh    ; If no note, set next track
  625.                         Je       NoNote
  626.                         Mov      Dx,Es:[Bx+02h]; Dl=octave, Dh=instrument
  627.                         Mov      Ax,Bp
  628.                         Add      Al,0B0h
  629.                         Call     AdlibCommand
  630.                         Mov      Al,Ss:[Bp+AdlibAddress]
  631.                         Add      Al,20h
  632.                         Cmp      Byte Ptr Ss:[Bp+InstrumentInfo],Dh
  633.                         Je       DontChangeInst
  634.                         Mov      Byte Ptr Ss:[Bp+InstrumentInfo],Dh
  635.                         Sub      Al,20h     ; set instrument, if it's not same
  636.                         Movzx    Di,Dh      ;  as before
  637.                         Add      Di,Offset Instrument
  638.     SetInstrumentLoop:  Add      Al,1Dh
  639.                         Mov      Ah,Ds:[Di]
  640.                         Call     AdlibCommand
  641.                         Add      Al,03h
  642.                         Mov      Ah,Ds:[Di+Instruments]
  643.                         Add      Di,Instruments*2
  644.                         Call     AdlibCommand
  645.                         Or       Al,Al
  646.                         Jns      SetInstrumentLoop
  647.                         Add      Al,40h
  648.                         Jnc      SetInstrumentLoop
  649.                         Push     Ax
  650.                         Mov      Ax,Bp
  651.                         Add      Al,0C0h
  652.                         Mov      Ah,Ds:[Di]
  653.                         Call     AdlibCommand
  654.                         Pop      Ax
  655.     DontChangeInst:     Add      Al,20h     ; set volume of the instrument
  656.                         Mov      Ah,Ch
  657.                         Call     AdlibCommand
  658.                         Movzx    Di,Cl      ; set new note to channel
  659.                         Mov      Ax,Bp
  660.                         Add      Al,0A0h
  661.                         Mov      Ah,Byte Ptr Ds:[Di+NoteValue]
  662.                         Call     AdlibCommand
  663.                         Add      Al,10h
  664.                         Mov      Ah,Byte Ptr Ds:[Di+Offset Notevalue+0001h]
  665.                         Or       Ah,Dl
  666.                         Call     AdlibCommand
  667.     NoNote:             Inc      Bh
  668.                         Inc      Bp
  669.                         Cmp      Bp,Channels; do all channels
  670.                         Jb       SetChannelsLoop
  671.                         Add      Bl,04h     ; increase row
  672.                         Adc      Si,00h     ; if last row, increase song pos.
  673.                         Cmp      Si,Offset SongOrder+SongLength
  674.                         Jb       NoRestart
  675.                         Mov      Si,Offset SongOrder+Restart
  676.     NoRestart:          Mov      Word Ptr Ds:[SongPosition+0001h],Si
  677.                         Mov      Byte Ptr Ds:[Row+0001h],Bl
  678.     DontChangeRows:     Pop      Es
  679.                         Pop      Ds
  680.                         Mov      Al,20h     ; send EOI to IRQ-chip
  681.                         Out      20h,Al
  682.                         PopA
  683.                         Iret
  684.   Player                EndP
  685.  
  686.   KeyInterrupt          Proc     Near
  687.                         Push     Ax
  688.                         Mov      Al,20h     ; EOI
  689.                         Out      20h,Al
  690.                         In       Al,60h
  691.                         Mov      Byte Ptr Cs:[KeyValue+0001h],Al
  692.                         Pop      Ax
  693.                         Iret
  694.   KeyInterrupt          EndP
  695.  
  696.   ScrollText            Db       '    THE SOLARIUM - ANARCHY SFHQ - THE BBS '
  697.                         Db       'SERVES 24h A DAY AND OFFERS 1GB HARD DISK '
  698.                         Db       'SPACE FOR YOUR USE WITH 16800 ZYXEL!   '
  699.                         Db       'CALL +358-31-3170851 NOW!!!  '
  700.   ScrollTextEnd         Label
  701.   BBSInfoText           Db       'Solarium',00h,00h,'+358-31-3170851'
  702.   BBSInfoTextEnd        Label
  703.  
  704.   PackedTrack           Db       09Ch,056h,044h,034h,043h,023h,033h,023h
  705.                         Db       033h,032h,023h,023h,033h,023h,033h,033h
  706.                         Db       043h,044h,054h,086h,008h
  707.   AdlibAddress          Db       003h,004h,005h,00Bh,00Ch,00Dh,013h,014h,015h
  708.   NoteValue             Dw       2157h      ; C-x
  709.                         Dw       2181h      ; D-x
  710.                         Dw       21B0h      ; E-x
  711.                         Dw       21CAh      ; F-x
  712.                         Dw       2202h      ; G-x
  713.                         Dw       2241h      ; A-x
  714.                         Dw       2287h      ; B-x
  715.   Instruments           Equ      09h
  716.   Instrument            Db       008h,0C2h,0C8h,0E2h,0EFh,0E0h,0C4h,0E2h,0C0h
  717.                         Db       0E2h,0E2h,0E2h,0E2h,0E0h,0C0h,0E4h,0E2h,0E4h
  718.                         Db       020h,01Ah,020h,010h,000h,000h,017h,00Eh,000h
  719.                         Db       000h,006h,00Ah,008h,000h,000h,000h,000h,000h
  720.                         Db       0F4h,015h,095h,0F4h,070h,0A8h,084h,0AFh,0F0h
  721.                         Db       0F6h,054h,076h,0F6h,077h,0F6h,075h,0F6h,0F7h
  722.                         Db       0F7h,0F9h,0F7h,0F4h,089h,058h,0F7h,0F6h,084h
  723.                         Db       0F7h,0F7h,0F8h,0F7h,0F9h,0F8h,0F7h,0F6h,0F6h
  724.                         Db       002h,000h,002h,000h,000h,000h,000h,001h,000h
  725.                         Db       001h,000h,000h,000h,003h,000h,001h,000h,000h
  726.                         Db       000h,006h,006h,00Ch,00Eh,008h,004h,008h,00Ch
  727.  
  728.   Channels              Equ      09h
  729.   Patterns              Equ      07h
  730.   SongLength            Equ      0Bh
  731.   ReStart               Equ      05h
  732.   SongOrder             Db       000h,010h,010h,020h,020h,030h,040h,050h,050h
  733.                         Db       060h,060h
  734.  
  735.   Pattern00             Db       0FFh       ; Track 00
  736.                         Db       0FFh       ; Track 01
  737.                         Db       005h,000h  ; Track 02
  738.                         Db       0E3h,0F1h
  739.                         Db       05Fh,0EAh,047h,057h
  740.                         Db       002h,080h  ; Track 03
  741.                         Db       011h,010h  ; Track 04
  742.                         Db       0E4h,0F2h
  743.                         Db       073h,057h,061h,081h,053h,02Bh,073h,071h,081h
  744.                         Db       091h,071h,081h,061h,063h,043h,027h
  745.                         Db       01Ch,033h  ; Track 05
  746.                         Db       0E4h,0F2h
  747.                         Db       072h,070h,052h,052h,051h,061h,081h,052h,050h
  748.                         Db       022h,022h,022h,022h,072h,070h,071h,081h,091h
  749.                         Db       071h,081h,061h,062h,060h,042h,040h,022h,021h
  750.                         Db       0FFh       ; Track 06
  751.                         Db       015h,060h  ; Track 07
  752.                         Db       0E6h,0F4h
  753.                         Db       071h,075h,073h,073h,071h,075h,072h,070h,073h
  754.                         Db       071h,075h,072h,072h,071h,071h,075h,072h,070h
  755.                         Db       071h,071h
  756.                         Db       0FFh       ; Track 08
  757.   Pattern01             Db       0FFh       ; Track 09
  758.                         Db       0FFh       ; Track 0A
  759.                         Db       002h,080h  ; Track 0B
  760.                         Db       002h,080h  ; Track 0C
  761.                         Db       004h,090h  ; Track 0D
  762.                         Db       005h,0B0h  ; Track 0E
  763.                         Db       062h,000h  ; Track 0F
  764.                         Db       0E2h,0F3h
  765.                         Db       053h
  766.                         Db       0E0h
  767.                         Db       053h
  768.                         Db       003h
  769.                         Db       043h,043h,053h,053h
  770.                         Db       007h,0E0h  ; Track 10
  771.                         Db       0FFh       ; Track 11
  772.   Pattern02             Db       0A5h,000h  ; Track 12
  773.                         Db       0E3h,0F0h
  774.                         Db       051h,091h,0A1h,0C1h
  775.                         Db       007h
  776.                         Db       041h,081h,091h,0B1h,051h,091h,0A1h,0C1h
  777.                         Db       4Ah,000h   ; Track 13
  778.                         Db       0E3h,0F7h
  779.                         Db       051h,051h,0C1h,0C0h,051h,051h,050h,0C1h,0C1h
  780.                         Db       008h
  781.                         Db       051h,051h,0C1h,050h,051h,050h,051h,0C1h,0C1h
  782.                         Db       0A0h,000h  ; Track 14
  783.                         Db       057h
  784.                         Db       001h
  785.                         Db       047h,057h
  786.                         Db       014h,080h  ; Track 15
  787.                         Db       004h,090h  ; Track 16
  788.                         Db       005h,0B0h  ; Track 17
  789.                         Db       00Fh,080h  ; Track 18
  790.                         Db       007h,0E0h  ; Track 19
  791.                         Db       00Bh,000h  ; Track 1A
  792.                         Db       0E2h,0F5h
  793.                         Db       000h,000h,000h,002h,000h,000h,001h,000h,004h
  794.                         Db       0EBh
  795.   Pattern03             Db       0FFh       ; Track 1B
  796.                         Db       013h,080h  ; Track 1C
  797.                         Db       0FFh       ; Track 1D
  798.                         Db       0FFh       ; Track 1E
  799.                         Db       0FFh       ; Track 1F
  800.                         Db       0FFh       ; Track 20
  801.                         Db       067h,00h   ; Track 21
  802.                         Db       0E1h,051h,050h,050h,0B0h,050h,0B0h,0C0h
  803.                         Db       067h
  804.                         Db       0E2h,011h,010h,010h,070h,010h,070h,080h
  805.                         Db       0FFh       ; Track 22
  806.                         Db       0FFh       ; Track 23
  807.   Pattern04             Db       0FFh       ; Track 24
  808.                         Db       013h,080h  ; Track 25
  809.                         Db       0FFh       ; Track 26
  810.                         Db       0FFh       ; Track 27
  811.                         Db       0FFh       ; Track 28
  812.                         Db       0E1h,034h  ; Track 29
  813.                         Db       0E2h
  814.                         Db       007h
  815.                         Db       021h,080h  ; Track 2A
  816.                         Db       0E2h,004h  ; Track 2B
  817.                         Db       0E2h,0F8h
  818.                         Db       007h
  819.                         Db       08Bh,000h  ; Track 2C
  820.                         Db       001h,070h,070h,071h,070h,000h,070h,000h,001h
  821.                         Db       071h,070h,070h
  822.   Pattern05             Db       0FFh       ; Track 2D
  823.                         Db       0FFh       ; Track 2E
  824.                         Db       044h,000h  ; Track 2F
  825.                         Db       0E4h,0F0h
  826.                         Db       090h,080h,070h
  827.                         Db       003h
  828.                         Db       060h,051h,023h,0E9h
  829.                         Db       042h
  830.                         Db       010h,020h,030h
  831.                         Db       003h
  832.                         Db       050h,071h,014h,0E9h
  833.                         Db       02Fh,0A2h  ; Track 30
  834.                         Db       02Fh,0C5h  ; Track 31
  835.                         Db       029h,0B0h  ; Track 32
  836.                         Db       021h,080h  ; Track 33
  837.                         Db       02Bh,080h  ; Track 34
  838.                         Db       02Ch,080h  ; Track 35
  839.   Pattern06             Db       063h,000h  ; Track 36
  840.                         Db       0E2h
  841.                         Db       052h,052h,051h
  842.                         Db       062h
  843.                         Db       012h,012h,011h
  844.                         Db       011h,030h  ; Track 37
  845.                         Db       0F6h
  846.                         Db       023h,021h,051h,083h,093h,023h,021h,011h,027h
  847.                         Db       013h,051h,011h,051h,041h,031h,021h,01Fh
  848.                         Db       02Bh,000h  ; Track 38
  849.                         Db       090h,080h,070h,090h,080h,070h,090h,080h,070h
  850.                         Db       060h,051h,023h
  851.                         Db       042h
  852.                         Db       010h,020h,030h
  853.                         Db       002h
  854.                         Db       050h,071h,013h
  855.                         Db       042h
  856.                         Db       080h,090h,0A0h
  857.                         Db       002h
  858.                         Db       0B0h,0C1h,083h
  859.                         Db       038h,0A2h  ; Track 39
  860.                         Db       038h,0C5h  ; Track 3A
  861.                         Db       029h,0B0h  ; Track 3B
  862.                         Db       021h,080h  ; Track 3C
  863.                         Db       02Bh,080h  ; Track 3D
  864.                         Db       02Ch,080h  ; Track 3E
  865.   SongDataEnd           Label
  866.  
  867. ; --- Cut below bytes off from compiled COM file ---
  868.  
  869.   ScrollersTrack        Db       0140h Dup(00h)
  870.   TempoCounter          Db       00h
  871.   OldTimerInt           Dd       00000000h
  872.   OldKeyInt             Dd       00000000h
  873.   ChannelInfo           Dw       Channels Dup(0000h)
  874.   InstrumentInfo        Db       Channels Dup(00h)
  875.   Fonts                 Db       3000h Dup(00h)
  876. Code                    EndS
  877.                         End      Start
  878.