Author Topic: 1024b Midi Sound System (mss)  (Read 5196 times)

0 Members and 1 Guest are viewing this topic.

Offline saida

  • C= 64
  • **
  • Posts: 57
  • Karma: 8
    • View Profile
    • saidas webpage
1024b Midi Sound System (mss)
« on: September 14, 2006 »
Finally decided to release it. I hope that someone will use it and make nice 1k demos with music! :)
Here are the source. Asm syntax is masm.
you will need this instrument list:
http://www.hd.chalmers.se/~Saida/titan/instruments.txt

Compiled version of the source:
http://www.hd.chalmers.se/~Saida/titan/mss.exe

you should add code to kick this off as a seperate thread with high priority...the music varies a lot with cpu load.

;
;  1024b Midi Sound System (mss)
;==============================================================================
;  @@ Programmed by: Martin Gustafsson - saida/titan^rebels
;  @@ Filename:      mss.asm
;  @@ Version:       3.1
;  @@ Date:          2006-09-14
;  @@ Web:           http://saida.lava.nu
;  @@ Mail:          saida at lava dot nu
;
;  If you use any of this code, please give me proper credits.
;
;  compile syntax:
;  \masm32\bin\ml /c /coff /nologo "mss.asm"
;  \masm32\bin\Link /SUBSYSTEM:WINDOWS /WS:AGGRESSIVE "mss.obj" /section:.text,RWE /MERGE:.rdata=.data /MERGE:.text=.data
;==============================================================================

; HISTORY
;==============================================================================
; Version 3.1 - Optimized code size. Fixed some bugs.
;             - Decided to go public with the midiSystem.   
;
; Version 3.0 - Big change! Now using 1 byte per tone only!
;             bit 7   = instrument (1 or 0)
;             bit 6-5 = length 0 1 2 3   
;             bit 4-0 = tone data.
;
; Version 2.0 - Some code cleanups.
;             - Optimized code size again. Tunes is now stored in another way.
;               Set bit7 of toneByte to 1/0
;             - Removed the data section. Exe now compiles to 1024b! \ :D /
;             - Rearanged code to compress better with com-packers.
;             - Fixed sleep bug between loops.
;             - Added support for 2 different instruments!       
;
; Version 1.0 - First release.
;             - One instrument support.
;             - two bytes per note.
;
;==============================================================================

; The 1024b Midi Sound System was used in these 1k demos:
; got balls?
; http://www.pouet.net/prod.php?which=18733
;
; rotor
; http://www.pouet.net/prod.php?which=17342

; MISC INFO
;==============================================================================
; Some information and thoughts behind the Init system:
; -----------------------------------------------------------------------------
; - First of all, let edi point to our data area, so we can use
;   edi instead of big memory adresses in the code.
; - Second, take usage of the fact, that eax is 0 when the program starts.
;   ok, this saves us what - 2 bytes... if you really done care about 2 bytes:
;   uncomment the "xor eax, eax" line at the start...
;
; Some information and thoughts behind the Player part:
; -----------------------------------------------------------------------------
; - Ok, edi is still used as the data pointer.
; - EDI and ESI does not change when calling the external dll functions, so
;   that is why I choosed ESI as a counter instead of ecx.
;   Now, i dont have to push and pop the counter register all the time! \ :D /
; - Another thing -> A byte is copied into AL from [EDI:ESI].
;   Then is the Length information is handled by BL register
;   The tone data in ah is then proccessed and pushed to the stack.
;   Next step is to see if the bit7 of AH is 1 or 0.
;   If bit7=0 then, instrument 0 is set. Else the instrument 1 is used.
;   The insrtument data is pushed to stack, and since we allready pushed the
;   tone data information to the stack, a double call to midi is done.
;   If a note byte would be 0, the song pattern loops.
;
; Limits etc
; -----------------------------------------------------------------------------
; The player does not play well if you have a high cpu load. This could be
; fixed (ofcourse it will cost you a lot of bytes) - by using GetTickCount
; instead of Sleep.     
;
; Dont forget!
; -----------------------------------------------------------------------------
; We are writing data to the code segment!
; If the code segment isnt set to be RWE - the program will not work!
; (RWE = Readable, Writable, Executable)
; If you use the compile lines at the top of this document, you should be fine.
;
; To get your final code smaller:
; -----------------------------------------------------------------------------
; rewrite the code so you set the instrument with the MOV instruction,
; rather than storing it in the fake-data-section, and then wasting bytes on
; getting that data.
; To do this: change the following lines.
; ORIGINAL LINE:
;                   mov bx, word ptr [edi-16+(2*ebx)]
; CHANGE TO:
;                   mov bx, word ptr [edi-8+(2*ebx)]
;
;
; ORIGINAL LINES:
;                   mov eax, [edi-8]                ; use instrument 0
;                   js @@bss_INSTRUMENT_DONE        ; Jump if bit7 is 1.
;                   mov eax, [edi-4]                ; else, use instrument 1
; CHANGE TO:
;                   mov eax, #dd_instrument_0       ; use instrument 0
;                   js @@bss_INSTRUMENT_DONE        ; Jump if bit7 is 1.
;                   mov eax, #dd_instrument_1       ; else, use instrument 1
;
; (and dont forget to remove the stuff in the fakedata section):
; @@bss_Instruments:                                REMOVE
;    dd 12594625      ; instrument index 0            REMOVE
;    dd 12594625      ; instrument index 1            REMOVE
;
;
; if you know you are only using instrument 0, you can remove this line to:
; and ebx, 00000011b                     
;==============================================================================

   .486
   .MODEL flat, stdcall
   
   includelib \masm32\lib\kernel32.lib ; Sleep call
   includelib \masm32\lib\winmm.lib    ; midi calls
   
   Sleep PROTO :DWORD
   midiOutOpen PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
   midiOutShortMsg PROTO :DWORD,:DWORD
   
   option casemap:none
   
.code

ProgramEntryPoint:
;------------------------------------------------------------------------------
; Initiate sound system
;------------------------------------------------------------------------------
    ;xor eax, eax                       ; uncomment this to loose 2 bytes :P
                                        ; eax should be zero at start.

    ; Setup esi/edi, so it points at data section
    ;==========================================================================       
        mov edi, offset bss_hMidi       ; use mov instead of lea. (smaller)

    ; Open midi device
    ;==========================================================================               
        push eax                        ; PUSH 0
        push eax                        ; PUSH 0
        push eax                        ; PUSH 0
        dec eax
        push eax                        ; PUSH 0xFFFFFFFF (MIDI_MAPPER)            
        push edi                        ; ( EDI is offset to hMidi )                  
        CALL midiOutOpen                ; call midiOutOpen
;------------------------------------------------------------------------------
; Playing part of sound system
;------------------------------------------------------------------------------

    ; Reset counter ESI that helps EDI to point at the music data
    ;==========================================================================
        ; xor eax, eax ; REMOVED! -> EAX should be zero if midiOutOpen was ok!
      ; if you are conserned by compatible/non-crashing demos. uncomment the
      ; "xor eax, eax" above...
    @@bss_RESET_SONG:               
        mov esi, edi                    ; set esi to point at fake data section
        LODSD                           ; Same as "add esi,4". (destoys eax)
                                        ; esi is now = offset "tone data"       
    ; Get new tone data from our array
    ;==========================================================================
    @@bss_LOAD_NEXT:               
        LODSB                           ; get BYTE from ES:ESI (the array)
        xchg ah, al   
        xor ebx,ebx                     ; set to zero before.
        add bl, ah                      ; if ah is zero, that means that we
                                        ; want to loop the song.
        jz @@bss_RESET_SONG             ; are we done? -> loop and play again.
       
        ; <get tone length in ms into ebx.>
        ; the data is in bl: ?TTx xxxx. after shr, its xxxx x?TT
        shr bl, 5                       
        ; remove additional ? data from byte (instrument could be 1)
        and ebx, 00000011b             

        ; extract millisecond sleep from length-array.
        mov bx, word ptr [edi-16+(2*ebx)]
       
    ; Setup eax for a call to midiOutShortMsg (to play a tone)
    ;==========================================================================
      ; here is the place where you can offset the midiNotes!
      ; (you can only use 0-31 midi notes)
      ;-----------------------
      ; add eax, SomeOffset
      ;-- OR:
      ; sub eax, SomeOffset
      ;-----------------------
        mov ecx, eax                    ; save toneData to ECX

        ; mask tone in eax with magic numbers..
        and ax, 0001111100000000b
        or eax, 00000000011111110010000010010001b       
        push eax                        ; push tone to play.          ##1 >---|
        push dword ptr [edi]            ; push handle to hMidi        ##1 >---|
                                        ;                                     |
    ; Was instrument should we use? 1 or 0?                                   |
    ;======================================================================== |
        xchg eax, ecx                   ; Restore toneData to eax.            |
        sahf                            ; pushes AH to flags.(SF=Bit7 in ah)  |
        mov eax, [edi-8]                ; use instrument 0                    |
        js @@bss_INSTRUMENT_DONE        ; Jump if bit7 is 1.                  |
        mov eax, [edi-4]                ; else, use instrument 1              |
                                        ;                                     |   
    ; Tell MIDI to change instrument for us.                                  |
    ;======================================================================== |
    @@bss_INSTRUMENT_DONE:              ;                                     |
        push eax                        ; push the instrument      ##2 >--|   |
        push dword ptr [edi]            ; push handle to hMidi     ##2 >--|   |   
        call midiOutShortMsg            ; <-------------------------------/   |
        call midiOutShortMsg            ; <-----------------------------------/

    ; Wait for the tone to play. Tone length is stored in BL
    ;==========================================================================
        push ebx                        ; ebx = sleep time
        call Sleep                      ; wait for tone to finish
         
        jmp @@bss_LOAD_NEXT             ; Repeat the procedure       

; END OF .CODE SECTION
;******************************************************************************

; size measure tool code (outputs size when compiling):
;------------------------------------------------------------------------------
   codelen  TEXTEQU  %($-ProgramEntryPoint)
   % echo <code_size> codelen bytes
;------------------------------------------------------------------------------

;------------------------------------------------------------------------------
; Faked .DATA section (makes exe smaller ...sometimes...)
; you can move this stuff to data section... but dont EVER move the data around
;------------------------------------------------------------------------------
;   music is stored like this (one byte per note):
;       ILLT TTTT
; bits  7654 3210
; where:
; I = Instrument index
; L = Length-of-note-index
; T = midi note
;
; SET THE BYTE TO -ZERO- TO LOOP FROM THE START OF THE SONG.

; lengths are in milliseconds.
@@bss_lengths:
    dw 240          ; lengh index 0.
    dw 1            ; lengh index 1
    dw 0            ; lengh index 2
    dw 0            ; lengh index 3

@@bss_Instruments:
    dd 12594625     ; instrument index 0
    dd 12594625     ; instrument index 1

@@bss_dataStart:
    bss_hMidi dd ?  ; handle to midi out.

; the song starts here (some test music i did):
;i
   db 10000101b;
   db 10101001b;play fast (use length index 1)
   db 10001100b
;a
   db 10000000b
   db 10101001b;play fast
   db 10001100b

;i
   db 10000101b
   db 10101001b;play fast
   db 10001100b
;a
   db 10000000b
   db 10101001b;play fast
   db 10001100b
;i
   db 10000101b
   db 10101001b;play fast
   db 10001100b
;a
   db 10000000b
   db 10101001b;play fast
   db 10001100b
   db 10000101b

; bam bam bam
   db 10000000b   
   db 10000010b
   db 10000100b

   db 00000000b ;loop from first note.
                           
end ProgramEntryPoint
« Last Edit: September 14, 2006 by saida »

Offline Rbz

  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 2757
  • Karma: 493
    • View Profile
    • https://www.rbraz.com/
Re: 1024b Midi Sound System (mss)
« Reply #1 on: September 14, 2006 »
That's really great, thanks for share it  :)


And  :hi: to DBF/GVY forum !
Challenge Trophies Won:

Offline saida

  • C= 64
  • **
  • Posts: 57
  • Karma: 8
    • View Profile
    • saidas webpage
Re: 1024b Midi Sound System (mss)
« Reply #2 on: September 14, 2006 »
thank you   :cheers:

Offline Shockwave

  • good/evil
  • Founder Member
  • DBF Aficionado
  • ********
  • Posts: 17426
  • Karma: 499
  • evil/good
    • View Profile
    • My Homepage
Re: 1024b Midi Sound System (mss)
« Reply #3 on: September 14, 2006 »
Props Saida for posting the source, thank you very much. Have some good Karma.
Shockwave ^ Codigos
Challenge Trophies Won:

Offline Clyde

  • A Little Fuzzy Wuzzy
  • DBF Aficionado
  • ******
  • Posts: 7271
  • Karma: 71
    • View Profile
Re: 1024b Midi Sound System (mss)
« Reply #4 on: September 14, 2006 »
Yeah cheers dude, I'm sure my partner in code: Rbraz will be concockting some rather neat stuff in the future :)

And :hi: aboard from myself.

Cheers and all the very best to you,
Clyde.
Still Putting The IT Into Gravy
If Only I Knew Then What I Know Now.

Challenge Trophies Won: