home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-387-Vol-3of3.iso / p / pps110.zip / PPSSRC.ZIP / PPSLOAD.ASM < prev    next >
Assembly Source File  |  1992-04-25  |  24KB  |  547 lines

  1. ;┌───────────────────────────────────────────────────────────────────────────┐
  2. ;│  FILENAME: PPSLOAD.ASM   Version 1.00                     │
  3. ;│                                         │
  4. ;│  DATE    : April 27, 1992                             │
  5. ;│                                                                           │
  6. ;│  Ideal Mode -- Turbo Assembler v2.01 and above                 │
  7. ;│                                                                           │
  8. ;│  DESCRIPTION: This file includes all routines for loading Amiga modules.  │
  9. ;└───────────────────────────────────────────────────────────────────────────┘
  10.  
  11.     ideal                ; Use TASM's Ideal mode.
  12.     model    Small,Pascal        ; Define the memory model.
  13.     P286                ; Set up for 286 instructions.
  14.     jumps                ; Have TASM automatically resolve out-
  15.                     ; of-range jumps.
  16.  
  17.     include "pps.inc"
  18.  
  19. codeseg
  20.  
  21. ;╒═══════════════════════════════════════════════════════════════════════════╕
  22. ;│ NAME       : sd_SetupMinor                             │
  23. ;│                                                                           │
  24. ;│ ENTRY      : None                                                         │
  25. ;│                                                                           │
  26. ;│ RETURN     : None                                                         │
  27. ;│                                                                           │
  28. ;│ DESCRIPTION: Sets up the counter variables, frequency values, and clears  │
  29. ;│        several sections of memory.                     │
  30. ;│                                         │
  31. ;│              *** Written by Joshua C. Jensen                              │
  32. ;╘═══════════════════════════════════════════════════════════════════════════╛
  33. proc    sd_SetupMinor
  34.     uses    ds,es
  35.     mov    ax,@data        ; Make sure the data segment is set
  36.         mov     ds,ax                   ; to the main data segment in which
  37.     mov    es,ax            ; all of our variables are stationed.
  38.     mov    [Word mt_PatternPos],0    ; Start at beginning of block.
  39.     mov    [Byte mt_SongPos],0    ; Start at beginning of song.
  40.     mov    [Byte mt_counter],0    ; Set the counter to zero so that
  41.                                         ; when it begins counting, it doesn't
  42.                                         ; skip part of a note.
  43.  
  44.         ; ──── Clear out segment, offset, etc. pointers before we play, so it
  45.         ; ──── doesn't "screech" on the first note.
  46.     mov    di,offset Channel1Seg    ; Set a pointer to Channel1Seg.
  47.     xor    ax,ax
  48.     mov    cx,16            ; Get structure size.
  49.     shl    cx,1            ; In total, we have Size*4 bytes to clear
  50.     rep    stosw            ; (four channels), so multiplying it
  51.                     ; by two will make CX = Size * 2 and we
  52.                                         ; will be clearing by moving Word 0's
  53.                                         ; into the structure, thus making it
  54.                     ; Size * 4.
  55.     call    sd_SetFreq
  56.     call    sd_SetMaxVolume
  57.     mov    [Byte ModuleLoaded],1    ; If we've made it this far, then the
  58.                                         ; module was loaded correctly.
  59.         ret                             ; Exit.
  60. endp    sd_SetupMinor
  61.  
  62. ;╒═══════════════════════════════════════════════════════════════════════════╕
  63. ;│ NAME       : sd_GetHighestBlock                                           │
  64. ;│                                                                           │
  65. ;│ ENTRY      : None                                                         │
  66. ;│                                                                           │
  67. ;│ RETURN     : AL - Highest block                                           │
  68. ;│                                                                           │
  69. ;│ DESCRIPTION: This code will return the highest block in a sequence.       │
  70. ;│              That is, it will return the largest number of patterns to    │
  71. ;│              load from or save to a file.                                 │
  72. ;│                                         │
  73. ;│              *** Written by Joshua C. Jensen                              │
  74. ;╘═══════════════════════════════════════════════════════════════════════════╛
  75. proc    sd_GetHighestBlock
  76.     uses    ds
  77.  
  78.         mov     ax,@data                ; Make sure the data segment is set
  79.         mov     ds,ax                   ; to the main data segment in which
  80.                                         ; all of our variables are stationed.
  81.  
  82.     mov    si,[SequenceOffset]    ; Set SI to the sequence location in
  83.                                         ; the header.
  84.     add    si,offset Header
  85.         mov     cx,128                  ; 128 (127) sequences total to search
  86.                                         ; through.
  87.         xor     ax,ax
  88.  
  89.     ; ──── In the following search, AH is going to store the highest block
  90.     ; ──── found so far.  AL is used for comparisons.  CX is the counter.
  91. @@SetHighestBlock:
  92.     mov    ah,al            ; Store the higher block number
  93.     jmp    @@BotLoop
  94. @@SearchLoop:
  95.     lodsb
  96.     cmp    al,ah            ; Compare against the largest block.
  97.         jg      @@SetHighestBlock       ; Is it greater than our stored value?
  98. @@BotLoop:
  99.     loop    @@SearchLoop
  100.     mov    al,ah
  101.     inc    al            ; Increment the highest block by one
  102.                                         ; so when the loader loads them in or
  103.                                         ; the blocks are saved, it takes care
  104.                                         ; of them all.
  105.         xor     ah,ah                   ; Clear ah.
  106.  
  107.         ret
  108. endp    sd_GetHighestBlock
  109.  
  110. ;╒═══════════════════════════════════════════════════════════════════════════╕
  111. ;│ NAME       : sd_ClearInstrumentLocations                                  │
  112. ;│                                                                           │
  113. ;│ ENTRY      : None                                                         │
  114. ;│                                                                           │
  115. ;│ RETURN     : None                                                         │
  116. ;│                                                                           │
  117. ;│ DESCRIPTION: The following code is going to zero out the instrument       │
  118. ;│              segment locations, so old values aren't sitting there.       │
  119. ;│                                         │
  120. ;│              *** Written by Joshua C. Jensen                              │
  121. ;╘═══════════════════════════════════════════════════════════════════════════╛
  122. proc    sd_ClearInstrumentLocations
  123.         push    ds
  124.  
  125.         mov     ax,@data                ; Make sure the data segment is set
  126.         mov     ds,ax                   ; to the main data segment in which
  127.     mov    es,ax            ; all of our variables are stationed.
  128.  
  129.     xor    ax,ax
  130.     mov    cx,31            ; Get the number of instruments.
  131.     mov    di,offset InsLoc    ; Set BX to the offset of the
  132.                                         ; instrument locations.
  133. @@ZeroInstruments:
  134.     rep    stosw
  135.  
  136.     mov    [Byte TypeOfSample],0    ; We have found no greater than 64k
  137.                                         ; samples yet.
  138.         pop     ds
  139.         ret
  140. endp    sd_ClearInstrumentLocations
  141.  
  142. ;╒═══════════════════════════════════════════════════════════════════════════╕
  143. ;│ NAME       : sd_ClearPatternLocations                     │
  144. ;│                                                                           │
  145. ;│ ENTRY      : None                                                         │
  146. ;│                                                                           │
  147. ;│ RETURN     : None                                                         │
  148. ;│                                                                           │
  149. ;│ DESCRIPTION: The following code is going to zero out the pattern          │
  150. ;│              segment locations, so old values aren't sitting there.       │
  151. ;│                                         │
  152. ;│              *** Written by Joshua C. Jensen                              │
  153. ;╘═══════════════════════════════════════════════════════════════════════════╛
  154. proc    sd_ClearPatternLocations
  155.         push    ds
  156.  
  157.         mov     ax,@data                ; Make sure the data segment is set
  158.         mov     ds,ax                   ; to the main data segment in which
  159.     mov    es,ax            ; all of our variables are stationed.
  160.  
  161.     xor    ax,ax
  162.         mov     cx,64                   ; 64 Pattern Locations to clear
  163.     mov    di,offset PatternLoc    ; Set BX to the offset of the
  164.                                         ; pattern locations.
  165. @@ZeroPatterns:
  166.     rep    stosw
  167.  
  168.         pop     ds
  169.         ret
  170. endp    sd_ClearPatternLocations
  171.  
  172. ;╒═══════════════════════════════════════════════════════════════════════════╕
  173. ;│ NAME       : sd_LoadPatterns                          │
  174. ;│                                                                           │
  175. ;│ ENTRY      : AX - Number of patterns.                     │
  176. ;│        BX - File Handle.                         │
  177. ;│                                         │
  178. ;│ RETURN     : Carry set - there was an error.                  │
  179. ;│                                                                           │
  180. ;│ DESCRIPTION: This will read the patterns from the module.             │
  181. ;│                                         │
  182. ;│              *** Written by Joshua C. Jensen                              │
  183. ;╘═══════════════════════════════════════════════════════════════════════════╛
  184. proc    sd_LoadPatterns
  185.     uses    ds
  186.     mov    dx,@data
  187.         mov     ds,dx
  188.         mov     es,dx
  189.  
  190.         push    bx                      ; Push the handle.
  191.     push    ax            ; Push num to do.
  192.  
  193.         call    sd_ClearPatternLocations
  194.  
  195.         ; ──── Each block is 400h bytes long or 1k.  By shifting $400 right
  196.         ; ──── 4 times (dividing it by 16) we can figure out how many
  197.         ; ──── paragraphs of memory it is going to require.
  198.         mov     bx,1024                 ; Set BX to 400h.
  199.         shr     bx,4                    ; Shift it right four times.
  200.         inc     bx                      ; Add one more paragraph for safety.
  201.                                         ; In all reality, if there are 64
  202.                                         ; patterns, this only adds an
  203.                                         ; additional 16k to the module.
  204.                                         ; Cut this line if that memory is
  205.                                         ; needed.
  206.  
  207.         mov     di,offset PatternLoc    ; Set DI to PatternLoc so we can store
  208.                                         ; pattern segments as we allocate them.
  209.     pop    cx            ; Set CX to highest pattern.
  210.  
  211.     push    cx            ; Save...
  212.  
  213.     ; ──── This is where we begin allocating all of the blocks.
  214. @@BlockAllocLoop:
  215.         push    bx                      ; Save BX - Size to allocate.
  216.         mov     ax,4800h                ; Allocate the memory.
  217.         int     21h
  218.         jnb     @@BlockAllocatedOK      ; No problem with allocation.
  219.         mov     [Byte Fatal],1
  220.         mov     ax,3                    ; Set Couldn't Allocate Block flag.
  221.     stc
  222.     ret
  223. @@BlockAllocatedOK:
  224.         stosw                           ; ES:DI -- Store segment in list.
  225.     pop    bx
  226.     loop    @@BlockAllocLoop
  227.  
  228.     ; ──── This is where we begin allocating all of the blocks.
  229.         pop     cx                      ; Pop the Num blocks counter.
  230.     mov    si,offset PatternLoc    ; Set SI to PatternLoc so we can read
  231.                     ; pattern segments.
  232.     xor    dx,dx            ; Load all segments at 0 offset.
  233.     pop    bx            ; Pop the handle.
  234.  
  235. @@BlockReadLoop:
  236.         push    cx                      ; Save CX - Highest Block Counter.
  237.  
  238.     push    ds
  239.     lodsw                ; Read pattern segment.
  240.     mov    ds,ax
  241.     mov    cx,1024         ; (400h bytes).
  242.         mov     ax,3F00h                ; Load in the block.
  243.         int     21h
  244.         jnb     @@BlockReadOK           ; No problem reading the block
  245.     pop    cx cx            ; We had a problem loading the block.
  246.         mov     ax,4                    ; Set Couldn't Read Block flag.
  247.     stc
  248.     ret
  249.  
  250. @@BlockReadOK:
  251.     pop    ds
  252.     pop    cx            ; Restore the bytes to allocate and
  253.                                         ; restore the counter.
  254.         loop    @@BlockReadLoop         ; Keep going until we've allocated
  255.                                         ; all the blocks.
  256.         clc
  257.     ret
  258. endp    sd_LoadPatterns
  259.  
  260. ;╒═══════════════════════════════════════════════════════════════════════════╕
  261. ;│ NAME       : sd_LoadSamples                             │
  262. ;│                                                                           │
  263. ;│ ENTRY      : BX - File Handle.                         │
  264. ;│                                         │
  265. ;│ RETURN     : Carry set - there was an error.                  │
  266. ;│                                                                           │
  267. ;│ DESCRIPTION: This will read the samples from the module.             │
  268. ;│                                         │
  269. ;│              *** Written by Joshua C. Jensen                              │
  270. ;╘═══════════════════════════════════════════════════════════════════════════╛
  271. proc    sd_LoadSamples
  272.     uses    ds
  273.     local    Handle:word
  274.     mov    [Handle],bx
  275.     mov    dx,@data
  276.         mov     ds,dx
  277.         mov     es,dx
  278.  
  279.     call    sd_ClearInstrumentLocations
  280.  
  281.     ; ──── Now we are going to read all the samples into memory.  SI is
  282.         ; ──── the current location in the header of the length field for the
  283.         ; ──── samples.
  284.         mov     si,2Ah                  ; Start at sample length field.
  285.                                         ; If you were to calculate an offset,
  286.                                         ; 2Ah would be this location.  I can't
  287.                                         ; use a structure to determine this,
  288.                                         ; because we have two kinds of modules
  289.                                         ; to support (15 and 31 instruments).
  290.  
  291.         mov     di,offset InsLoc        ; Set BX to be a pointer to the
  292.                                         ; instrument segment list.
  293.         mov     cx,[NumberInstruments]  ; Set CX to be the counter.  Load it
  294.                                         ; with the highest number of
  295.                                         ; instruments.
  296.     xor    dx,dx            ; Set offset to 0.
  297.  
  298. @@SampleReadLoop:
  299.         push    cx                      ; Store the counter.
  300.  
  301.     mov    bx,[si+offset Header+4] ; Get the repeat from the header.
  302.     xchg    bl,bh            ; On the Amiga, word values are
  303.                                         ; swapped from the IBM.  Swap it to
  304.                                         ; the correct IBM position.
  305.     mov    [si+offset Header+4],bx ; Store it back to the header.
  306.     mov    bx,[si+offset Header+6] ; Get the repeat length from the header.
  307.     xchg    bl,bh
  308.     mov    [si+offset Header+6],bx ; Store it back to the header.
  309.     mov    bx,[si+offset Header]    ; Get the length from the header.
  310.     xchg    bl,bh
  311.     mov    [si+offset Header],bx    ; Store it back to the header.
  312.  
  313.     or    bx,bx            ; See if the length is actually zero.
  314.         jnz     @@InstrumentExists      ; It not, do something about it.
  315.         add     di,2
  316.         jmp     @@DoneInstrument
  317.  
  318. @@InstrumentExists:
  319.     cmp    bx,8000h        ; Is the length greater than 8000h?
  320.         jnb     @@ReadSample64          ; Yes, jump to @@ReadSample64.
  321.  
  322.     push    bx            ; Save the length.
  323.  
  324.         ; ──── Samples vary in length.  By shifting the length right
  325.         ; ──── 4 times (dividing it by 16) we can figure out how many
  326.         ; ──── paragraphs of memory it is going to require.
  327.  
  328.         ; ──── The length in a sample that is less than 64k has been divided
  329.         ; ──── by two.  The reason for this is because a sample that is
  330.         ; ──── greater than 64k appears in the length field as a value
  331.         ; ──── greater than or equal to 8000h.  If it is this, then we know
  332.         ; ──── we have found a >64k sample.
  333.  
  334.         ; ──── When we find a >64k sample, we subtract from the length 8000h.
  335.         ; ──── Then we multiply it by 2 and store the value.  We then load in
  336.         ; ──── 64k of the sample and restore our saved length and load that
  337.         ; ──── in.
  338.     shr    bx,4            ; Shift the length right four times.
  339.     inc    bx            ; Add an extra paragraph for safety.
  340.     shl    bx,1
  341.         mov     ax,4800h                ; Allocate the memory.
  342.         int     21h
  343.     pop    cx            ; Restore the length.
  344.         jnb     @@SampleAllocatedOK     ; No problem with the allocation.
  345.  
  346.         pop     cx                      ; Pop used registers off the stack.
  347.         mov     [Byte Fatal],1
  348.         mov     ax,5                    ; Set Couldn't Allocate Sample flag.
  349.     stc
  350.     ret
  351.  
  352. @@SampleAllocatedOK:
  353.         stosw                           ; Store segment in list.
  354.  
  355.         push    ds                      ; Save data segment for later.
  356.         mov     ds,ax                   ; Load the allocated segment into DS.
  357.         shl     cx,1                    ; Double the length so we don't cut
  358.                                         ; off half of the sample.
  359.         mov     bx,[Handle]
  360.         mov     ax,3F00h                ; Read it in.
  361.         int     21h
  362.         pop     ds                      ; Restore the data segment.
  363.         jnb     @@DoneInstrument        ; No problems reading the sample.
  364.  
  365.         pop     cx                      ; Pop used registers off the stack.
  366.         mov     ax,6                    ; Set Couldn't Read Sample flag.
  367.     stc
  368.     ret
  369.  
  370. @@DecSize:
  371.         mov     ax,[si+offset Header]
  372.         dec     ax
  373.         dec     ax
  374.         dec     ax
  375.         mov     [si+offset Header],ax
  376. @@DoneInstrument:
  377.         pop     cx                      ; Restore counter.
  378.     add    si,30            ; Size of sample structure.
  379.         loop    @@SampleReadLoop
  380.     clc
  381.     ret
  382.  
  383. @@ReadSample64:
  384.     pop    cx            ; Pop used registers.
  385.     mov    [Byte TypeOfSample],1    ; Signify the greater than 64k sample.
  386.         mov     ax,9
  387.     stc
  388.     ret
  389. endp    sd_LoadSamples
  390.  
  391. ;╒═══════════════════════════════════════════════════════════════════════════╕
  392. ;│ NAME       : sd_SetModuleSize                         │
  393. ;│                                                                           │
  394. ;│ ENTRY      : BX - File Handle.                         │
  395. ;│                                         │
  396. ;│ RETURN     : Carry set - there was an error.                  │
  397. ;│                                                                           │
  398. ;│ DESCRIPTION: This will determine the size of the module...15 or 31 ins.   │
  399. ;│                                         │
  400. ;│              *** Written by Joshua C. Jensen                              │
  401. ;╘═══════════════════════════════════════════════════════════════════════════╛
  402. proc    sd_SetModuleSize
  403.         call    sd_Set15Ins             ; Assume 15 instruments.
  404.         mov     cx,0
  405.         mov     dx,438h
  406.         mov     ax,4200h                ; Reposition file pointer.
  407.         int     21h
  408.         jnb     @@GetTheMK
  409.         mov     ax,2                    ; Set Couldn't Read Header flag.
  410.     stc
  411.     ret
  412. @@GetTheMK:
  413.         mov     dx,offset Header        ; If there is a M.K. or FLT4 at this
  414.         mov     cx,4                    ; position, then it is 31 ins.
  415.         mov     ax,3f00h
  416.         int     21h
  417.         jnb     @@DoCompare
  418.         mov     ax,2
  419.     stc
  420.     ret
  421. @@DoCompare:
  422.         mov     ax,[Word Header]
  423.     xchg    ah,al            ; Amiga swap.
  424.     cmp    ax,"M."                 
  425.         jz      @@Its31
  426.     cmp    ax,"FL"
  427.         jnz     @@LoadHeader
  428. @@Its31:
  429.         call    sd_Set31Ins
  430. @@LoadHeader:
  431.         mov     cx,0
  432.         mov     dx,0
  433.         mov     ax,4200h                ; Reposition file pointer to beginning.
  434.         int     21h
  435.     clc
  436.     ret
  437. endp    sd_SetModuleSize
  438.  
  439. ;╒═══════════════════════════════════════════════════════════════════════════╕
  440. ;│ NAME       : sd_LoadModule                                                │
  441. ;│                                                                           │
  442. ;│ ENTRY      : DS:DX -- Pointer to ASCIIZ filename of module to be loaded.  │
  443. ;│                                                                           │
  444. ;│ RETURN     : AX - Error Flag                                              │
  445. ;│                1 - Couldn't open module                                   │
  446. ;│                2 - Couldn't read header                                   │
  447. ;│                3 - Couldn't allocate block                                │
  448. ;│                4 - Couldn't read block                                    │
  449. ;│                5 - Couldn't allocate sample                               │
  450. ;│                6 - Couldn't read sample                                   │
  451. ;│                7 - Couldn't close module                                  │
  452. ;│          8 - Couldn't determine size                                │
  453. ;│          9 - >64k sample.                         │
  454. ;│                                                                           │
  455. ;│              Carry set -- Error                                           │
  456. ;│              Carry clear -- Module loaded successfully                    │
  457. ;│                                                                           │
  458. ;│ DESCRIPTION: This procedure handles all module loading for the player.    │
  459. ;│              It ensures that pointers are set up properly.                │
  460. ;│                                                                           │
  461. ;│              sd_LoadModule distinguishes between less than 64k samples    │
  462. ;│        and greater than 64k samples.  It also detects whether a     │
  463. ;│        module is 15 or 31 instruments.  However, >64k sample         │
  464. ;│        support doesn't exist because I haven't had time to          │
  465. ;│        reimplement it.                          │
  466. ;│                                                                           │
  467. ;│              *** Written by Joshua C. Jensen                              │
  468. ;╘═══════════════════════════════════════════════════════════════════════════╛
  469. proc    sd_LoadModule
  470.     uses    ds
  471.     local    Handle:word
  472.  
  473.     mov    ax,3D00h        ; Open the module file.
  474.     int    21h            ; Everything is fine if carry is not
  475.     jnb    @@ModuleOpenOK        ; set.
  476.  
  477.         mov     ax,1                    ; Set Couldn't Open Module flag.
  478.     jmp    @@Abort
  479. @@ModuleOpenOK:
  480.     mov    [Handle],ax
  481.     mov    ax,@data
  482.     mov    ds,ax
  483.     mov    [Byte Fatal],0        ; No fatal error yet.
  484.         mov     [Byte ModuleLoaded],0   ; We haven't loaded a module yet.
  485.         mov     [Byte mt_speed],6       ; Standard module playing speed.
  486.         mov     [Byte MStatus],1        ; Set music status to not playing.
  487.  
  488.     mov    bx,[Handle]
  489.     call    sd_SetModuleSize
  490.     jb    @@Abort
  491.  
  492.     ; ──── We're now going to load in the header.  The reason CX is
  493.         ; ──── obtaining its information from HeaderSize is because the
  494.         ; ──── size of the header varies from 15 instrument to 31 instrument
  495.         ; ──── modules.
  496.     mov    cx,[HeaderSize]     ; Number of bytes to read.
  497.         mov     dx,offset Header        ; Offset of our storage for the header.
  498.     mov    bx,[Handle]
  499.     mov    ax,3F00h        ; Load in the header
  500.         int     21h
  501.         jnb     @@HeaderLoadedOK        ; If we didn't fail, skip the next part.
  502.  
  503.         mov     ax,2                    ; Set Couldn't Read Header flag.
  504.         jmp     @@Abort                 ; Abort.
  505.  
  506. @@HeaderLoadedOK:
  507.         call    sd_GetHighestBlock      ; Find the highest block.
  508.         mov     [NumBlocks],al          ; Store it for later use.
  509.  
  510.     mov    bx,[Handle]
  511.     call    sd_LoadPatterns
  512.     jb    @@LoadFail        ; There was a major error.
  513.  
  514.     mov    bx,[Handle]
  515.     call    sd_LoadSamples
  516.     jb    @@LoadFail
  517.  
  518.     mov    bx,[Handle]        ; Close the module file.
  519.     mov    ax,3E00h
  520.     int    21h
  521.         jnb     @@FinishUp              ; No problems closing the module.
  522.         mov     ax,7                    ; Something happened...don't know what.
  523.         jmp     @@LoadFail              ; Abort.
  524.  
  525. @@FinishUp:
  526.     call    sd_SetupMinor        ; Set up the final values.
  527.         ret                             ; Exit
  528.  
  529. @@Abort:
  530.         stc
  531.         ret
  532.  
  533.         ; ──── @@LoadFail is called when there is an error after some memory
  534.         ; ──── allocation has been done.
  535. @@LoadFail:
  536.         push    ax                      ; Save the error flag.
  537.         call    sd_CloseAllMusic        ; Close down EVERYTHING.
  538.         pop     ax                      ; Restore the error flag.
  539.         stc                             ; Set the carry flag.
  540.         ret                             ; Exit;
  541. endp    sd_LoadModule
  542.  
  543. ;───────────────────────────────────────────────────────────────────────────────
  544.  
  545. end
  546.  
  547.