AdLib Programmierung

Antworten
Benutzeravatar
zatzen
DOS-Kenner
Beiträge: 493
Registriert: Di 17. Apr 2012, 05:10
Wohnort: bei Köln
Kontaktdaten:

AdLib Programmierung

Beitrag von zatzen »

Die AdLib Karte ist praktisch das, was für den Amiga der Paula Chip und für den C64 der SID ist.
Sie ermöglicht fast ohne Prozessorlast mehrkanälige Musik und Soundeffekte.
Möglicherweise ist erst die Spitze des Eisbergs ihrer Fähigkeiten bekannt, und es gibt noch mehr Möglichkeiten zur Erzeugung von komplexeren und organischeren Klängen. Immerhin ist der Yamaha OPL-3 Chip in der Lage, Sprache zu synthetisieren, und das ist sehr komplex.
Hier habe ich mal grundlegende Ansteuerungsroutinen für Pascal in einer Unit zusammengetragen.
Mir war bisher nicht bewusst, dass die AdLib auch detektiert werden kann.
Ich habe alles in Assembler geschrieben, Parameter müssen den Prozeduren über Register übergeben werden, so wie das z.B. auch bei BIOS-Funktionen ist. Das hat technisch mehrere Vorteile.
Ich werde diese Unit noch weiterbauen und sie in einem AdLib Tracker (Musikprogramm) verwenden, den ich schreiben möchte, und der anders klingen wird als man es bisher von der AdLib gewohnt ist.

Code: Alles auswählen

Unit ADLIB;

(* Unit for accessing the AdLib Card *)
(* Version 1 by Zatzen 6 Jan 2022 *)


INTERFACE

Var
 ADL_detected: ByteBool;
 ADL_either_timer_exp: ByteBool;
 ADL_timer1_exp: ByteBool;
 ADL_timer2_exp: ByteBool;

Procedure AdLib_status;
Procedure AdLib_reset_Timers_and_INTs;
Procedure AdLib_detect;
Procedure AdLib_clear_registers;


IMPLEMENTATION


Procedure AdLib_status; ASSEMBLER;
ASM

  MOV DX, 0388H
  IN AL, DX

  MOV ADL_either_timer_exp, AL
  MOV ADL_timer1_exp, AL
  MOV ADL_timer2_exp, AL

  AND ADL_either_timer_exp, 10000000B
  AND ADL_timer1_exp, 01000000B
  AND ADL_timer2_exp, 00100000B

END;

Procedure AdLib_selectREG; ASSEMBLER;
(* AL: Number of Register *)
ASM

  MOV DX, 0388H
  OUT DX, AL

  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX

END;

Procedure AdLib_dataWRITE; ASSEMBLER;
(* AL: Value *)
ASM

  MOV DX, 0389H
  OUT DX, AL

  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  IN AL, DX
  (* 36x, unrolled to keep this as quick as possible *)

END;

Procedure AdLib_reset_Timers_and_INTs; ASSEMBLER;
(* Reset both timers and interrupts *)
ASM

  (* Reset both timers by writing 60h to register 4 *)
  MOV AL, 4
  CALL AdLib_selectREG
  MOV AL, 060H
  CALL AdLib_dataWRITE

  (* Enable the interrupts by writing 80h to register 4 *)
  MOV AL, 080H
  CALL AdLib_dataWRITE

END;

Procedure AdLib_detect; ASSEMBLER;
ASM

  (* Reset both timers and interrupts *)
  CALL AdLib_reset_Timers_and_INTs;

  (* Read the status Register (port 388h. Store the result *)
  DEC DX
  IN AL, DX
  MOV BH, AL

  (* Write FFh to register 2 (Timer 1) *)
  MOV AL, 2
  CALL AdLib_selectREG
  MOV AL, 0FFH
  CALL AdLib_dataWRITE

  (* Start timer 1 by writing 21h to register 4 *)
  MOV AL, 4
  CALL AdLib_selectREG
  MOV AL, 021H
  CALL AdLib_dataWRITE

  (* Delay for at least 80 microseconds *)
  MOV CX, 07FH
  @LOOP:

    IN AL, DX

  LOOP @LOOP

  (* Read the status register (port 388h). Store the result *)
  DEC DX
  IN AL, DX
  MOV BL, AL

  (* Reset both timers and interrupts *)
  CALL AdLib_reset_Timers_and_INTs;

  (* Test the stored results by ANDing them with E0h. *)
  AND BX, 0E0E0H

  (* BH should be 0, BL should be C0H *)
  (* AL = 0 if no AdLib detected, AL = 1 if AdLib detected *)
  XOR AL, AL
  CMP BX, 0C0H
  JNE @SKIP
  INC AL
  @SKIP:
  MOV ADL_detected, AL

END;

Procedure AdLib_clear_registers; ASSEMBLER;
ASM

  MOV CX, 0F5H
  @LOOP:
    MOV AL, CL
    CALL AdLib_selectREG
    XOR AL, AL
    CALL AdLib_dataWRITE
  DEC CX
  JNZ @LOOP

END;


begin
end.

(* Thanks to Jeffrey S. Lee for his Documentation *)
(* "Programming the AdLib/Sound Blaster FM Music Chips" *)
(* Version 2.1 (24 Feb 1992) *)
(* http://www.shipbrook.net/jeff/sb.html *)
mov ax, 13h
int 10h
Benutzeravatar
b20a9
617K-Frei-Haber
Beiträge: 303
Registriert: Mi 16. Apr 2014, 23:54

Re: AdLib Programmierung

Beitrag von b20a9 »

Hallo Zatzen, ich verstehe leider nichts vom Programmieren, bin aber dafür ein um so größer FM-musik fan:-) Bin sehr gespannt, was du dem YM3812/YM-262 noch entlocken kannst und würde mich freuen, wenn du uns über deine Fortschritte hier auf dem Laufenden hältst. Ich denke auch, das die Fähigkeiten des Synths bei weitem nicht ausgenutzt wurden, was mich aber aufgrund der anspruchsvollen Programmierung wohl auch nicht weiter verwundert. Nicht jeder Musiker ist auch Programmierer und umgekehrt. Persönlich bin ich ein großer Fan von Hannes Seiferts Stücken, und sein Tracker war damals glaube ich auch Wegweisend. Aber wie gesagt ich bin nur Konsument und nicht Creator was das angeht:-) Viel Erfolg!
SNI PCD-4VL 486 DX2/66 , 32MB RAM, Miro PCM12, 3com Etherlink III , FDD + HDD. DOS 6 + WIN 95
Antworten