Llegó el momento de una nueva Flashparty. Muchas intros últimamente de 256 bytes, mucho MIDI para el audio pero acá se juega fuerte: Adlib de posta, nada de los trucos con MIDI que hacen otras producciones.

Otres decían que no se podía porque setear los registros, inicializar y configurar OPL2 (soportada por la SoundBlaster 16) ocupaba demasiado espacio para una produccion de 256b.

Con respecto a que es exactamente todo esto del sizecoding y la demoscene podés leer una introduccion en este post anterior.

También podes bajar esta producción llamada microtonal con el código fuente completo de scene.org.

Acá la producción final. Recordá; Audio y Video en 256 bytes!:

Introducción

Desde cero, el primer objetivo era hacer sonar algo en msdos evitando usar los trucos con MIDI que se pueden leer en el sitio de sizecoding.org. En esta producción de 256 bytes para msdos usé el Modo 13. El munshkr codeó el fmtribe, que es una drum-machine/synth que hace uso extensivo de OPL. De su código, compilé una versión reducida con djgpp solamente configurando los IN/OUT y dándole play al metrónomo que fmtribe tiene incorporado. Extrayendo el metrónomo para tener una configuración básica del OPL2, este fue mi punto de partida para tener algo que suene. En un principio, lo que hice fue compilar con djgpp esta sección de codigo "mínima" y fijarme el output del código en assembly x86. El programa completo para hacer andar el metrónomo de fmtribe en un .com ocupaba si mal no recuerdo, alrededor de 1 Kilobyte.

Demasiado grande para una producción de 256 bytes, ¿no? AIGHT!, hold my beer.

Escribiendo registros…

Escencialmente, para hacer andar OPL2 es necesario crear:

  • data de instrumentos en un solo operador
  • un loop para ejecutarlos
  • decirle a OPL2 cuando una nota esta ON u OFF.

Aquí debajo, está la subrutina para setear los instrumentos…


adlib_set_instrument:

    ; adlib_write requires: 
    ; al - reg
    ; bl - val
    ; from the previous loop, cx is 0
    ; so we initialize the counter with cl, saving 1 byte!
    mov cl, 10  ; 10 values for carrier and modulator
    mov si, instrument_data
        .loop1:
        lodsw
        mov bl, ah
        call adlib_write
        loop .loop1

… con su data necesaria:

instrument_data:
; OP1 Modulator
db 0x20, 0x87     ; m_am_vib_eg
db 0x40, 0x40     ; m_ksl_volume
db 0x60, 0x81     ; m_attack_decay
db 0x80, 0xf3     ; m_sustain_release
db 0xe0, 0x00     ; m_waveform

; OP1 Carrier
db 0x23, 0xa5     ; c_am_vib_eg
db 0x43, 0x0b     ; c_ksl_volume
db 0x63, 0xf1     ; c_attack_decay
db 0x83, 0x1f     ; c_sustain_release
db 0xe3, 0x00     ; c_waveform

Esto es lo primero que hacemos. Configurar los instrumentos. Para más información sobre como funciona FM y OPL2 fijate en este mismo sitio la página de resources donde cuelgo documentación de todo lo que trata este blog.

… eficientemente?

OPL necesita una tabla de "frecuencias" donde se define el pitch de cada una de las notas que el chip necesita para poder "afinarse". El tema es que el programador tiene que escribir la tabla de los pitches perfectamente asi cada frecuencia corresponde con todas las notas que hay en la música. El tema es que esta tabla ocupa demasiado espacio, entonces aproximamos con el siguiente algoritmo la tabla de frecuencias para acercarse lo mas posible a el DoReMiFaSolLaSi (y sus sostenidos/bemoles) haciendo que esta obra se llame microtonal. Siendo que no podemos pegarle exactamente a las frecuencias, las aproximamos.

gen_notes_frequencies:

    ; if you substract each note from the real frequency table
    ; you'll notice that there is 16 to 19 elements of distance
    ; between each element. 

    ; the notes generated by this algorithm 
    ; are going to generate very-near frequencies
    ; from the correct ones, so the notes will be actually
    ; a bit out of tune. But we can argue that this is actually
    ; NOT out of tune but a microtonal OPL music approach ;D

    mov ax, 0x16b   ; (Note Db)
    mov cl, 12      ; 12 notes ; assuming cx = 0, saving 1 byte
    mov di, notes
        .loop1:
        stosw
        add al, 16  ; distance between notes
        loop .loop1

La magia de este algoritmo es que genera una tabla de frecuencias cercana a las notas comunes, ahorrando un monton de espacio de una tabla de frecuencias que debería ser hardcodeada. ¿Desafinamos el chip? ¡No! ¡Esto es música microtonal! ¡El último grito de la demoscene latinoamericana!

Otras Cosas

También en esta producción hay unas rutinas que tratan de escribir en pantalla un mensaje y generar un efecto visual. Los detalles de estas rutinas son bastante irrelevantes porque esta producción se trataba más de el audio que de el video. El código fuente esta disponible pero no creo que la parte gráfica, al menos en esta producción, sea la parte central.

De todas maneras, usé un par de trucos inspirados en otras producciones de otros demosceners para poder escribir un poquito de texto y mostrar algo en la pantalla, y que no sea solamente audio.

Asi que, tenemos en 256 bytes para msdos, audio y gráficos con texto. ¿Que tal? ;D

Mejoras futuras

Hay algunas cosas donde se podría reducir aun más el tamaño de esta produccion, como usar stack adressing o también hacer un secuanciador con el Intel 8253 PIT en vez de estar loopeando a mano, pero hubo un momento donde dije "bueno, esto yastá" y yastuvo. :D

Concluyendo

Quizás parece que esto que escribí lo hice al toque-roque, y algunas partes pueden ser que si, pero esta producción llevó varios meses de desarrollo en los momentitos libres que tenía.

Espero que este blogpost le sirva a los otros sizecoders latinoamericanos que andan pululando por ahi, y si tenés alguna pregunta sobre esto o alguna otra cosa relacionada con el sizecoding, escribime abajo en la caja de comentarios.

¡Salut!

Referencias