libmsx
C library for MSX
Loading...
Searching...
No Matches

#include <opll_buf.h> Buffered access to OPLL registers. More...

+ Collaboration diagram for OPLL Buffer:

Functions

void OPLL_init (void)
 MSX Initialize internal buffer for OPLL.
 
void OPLL_put (uint8_t reg, uint8_t val)
 MSX Put a pair of OPLL register number and its value to the internal buffer.
 
void OPLL_rhythm_mode (bool on)
 MSX Turn RHYTHM mode on/off.
 
void OPLL_rhythm (uint8_t val)
 MSX Key-on/off RHYTHM set.
 
void OPLL_stop (struct OPLL *opll)
 MSX Stop (Pause) playing sound on OPLL
 
void OPLL_play (struct OPLL *opll)
 MSX Play sound on OPLL
 

Variables

uint8_t opll_buffer [64]
 MSX Cache of OPLL registers.
 

Detailed Description

#include <opll_buf.h> Buffered access to OPLL registers.

Provides simple APIs for sound driver developpers.

Example
The following code shows a sound driver/replayer template for the MSX-MUSIC (OPLL).

// -*- coding: utf-8-unix -*-
/*
* Copyright (c) 2021-2024 Daishi Mori (mori0091)
*
* This software is released under the MIT License.\n
* See https://github.com/mori0091/libmsx/blob/main/LICENSE
*
* GitHub libmsx project\n
* https://github.com/mori0091/libmsx
*/
#include <msx.h>
#include <opll_buf.h>
#define LO_BYTE(x) (uint8_t)((x) & 0xff)
#define HI_BYTE(x) (uint8_t)(((x) >> 8) & 0xff)
#define SUS_OFF (0)
#define KEY_OFF (0)
#define SUS_ON (uint16_t)(1 << 13)
#define KEY_ON (uint16_t)(1 << 12)
#define BLOCK(x) (uint16_t)((x) << 9)
#define F_NUM(x) (uint16_t)(x)
#define INST(x) (uint8_t)((x) << 4)
#define VOL(x) (uint8_t)((x) & 0x0f)
static struct OPLL opll;
static bool paused;
// Initialize the replayer.
void init(void) {
if (OPLL_find(&opll)) {
// Enable OPLL.
// This must be called at least once.
OPLL_enable(&opll);
// Initialize internal buffer.
// 6 channels + RHYTHM mode
}
}
// Main routine of the replayer.
// \note This shall be called every VSYNC timing from interrupt handler.
void play(void) {
if (!opll.slot) return;
if (paused) return;
// Apply buffered values to the OPLL registers.
OPLL_play(&opll);
// Decode one frame of music data and set them to buffers.
// (Rewrite this block for developping yourown sound driver / replayer)
{
static uint8_t t = 0;
// One beat period at 120 bpm.
const uint8_t len = msx_get_vsync_frequency() * 60 / 120;
if (!t) {
// ch1 : O4 G, INST=3, VOL=0
// \note
// VOL(0) means maximum volume, VOL(15) means minimum volume.
// VOL(a) means "-3a dB of the maximum volume" (i.e. Vmax * 10^(-0.3a))
uint16_t x = (SUS_OFF | KEY_ON | BLOCK(4) | F_NUM(257));
OPLL_put(0x30, (INST(3) | VOL(0)));
OPLL_put(0x20, HI_BYTE(x));
OPLL_put(0x10, LO_BYTE(x));
}
else if (t == len * 4/5) {
// ch1: KEY-OFF
uint16_t x = (SUS_OFF | KEY_OFF | BLOCK(4) | F_NUM(257));
// OPLL_put(0x30, (INST(3) | VOL(0)));
OPLL_put(0x20, HI_BYTE(x));
// OPLL_put(0x10, LO_BYTE(x));
}
t++;
if (t == len) {
t = 0;
}
}
}
// Start / Resume the replayer.
void start(void) {
paused = false;
}
// Pause the replayer.
void pause(void) {
paused = true;
OPLL_stop(&opll);
__asm__("ei");
}
// Return whether the replayer is paused or not.
bool is_paused(void) {
return paused;
}
// Stop the replayer.
void stop(void) {
pause();
// Re-initialize internal buffer.
// (if needed)
}
void main(void) {
// Initialize our replayer.
init();
// Set our replayer `play()` to VSYNC handler
// Start our replayer.
start();
uint8_t pressed = false;
for (;;) {
uint8_t joy = joypad_get_state(0);
uint8_t clicked = pressed & ~joy;
pressed = joy;
if (pressed & (VK_UP | VK_DOWN | VK_LEFT | VK_RIGHT)) {
// Any of the arrow keys were pressed.
__asm__("di");
// All rhythm sets are set to KEY-ON status.
OPLL_rhythm(0x1f);
__asm__("ei");
}
if (clicked & (VK_UP | VK_DOWN | VK_LEFT | VK_RIGHT)) {
// Any of the arrow keys were released.
__asm__("di");
// All rhythm sets are set to KEY-OFF status.
__asm__("ei");
}
if (clicked & VK_FIRE_0) {
// SPACE key was released.
if (is_paused()) {
start();
}
else {
pause();
}
}
}
}
uint8_t msx_get_vsync_frequency(void)
MSX Returns VSYNC frequency in Hz.
Definition bios.h:78
uint8_t joypad_get_state(uint8_t controller)
MSX Get the status of the joystick buttons and levers.
#define VK_UP
Bitmask for UP direction of joystick or UP arrow key.
Definition input.h:40
#define VK_FIRE_0
Bitmask for trigger button #1 or SPACE key.
Definition input.h:68
#define VK_LEFT
Bitmask for LEFT direction of joystick or LEFT arrow key.
Definition input.h:54
#define VK_RIGHT
Bitmask for RIGHT direction of joystick or RIGHT arrow key.
Definition input.h:61
#define VK_DOWN
Bitmask for DOWN direction of joystick or DOWN arrow key.
Definition input.h:47
void await_vsync(void)
MSX Waits for next VSYNC interrupt.
void set_vsync_handler(void(*handler)(void))
MSX Register user defined VSYNC interrupt handler.
void OPLL_init(void)
MSX Initialize internal buffer for OPLL.
void OPLL_stop(struct OPLL *opll)
MSX Stop (Pause) playing sound on OPLL
void OPLL_put(uint8_t reg, uint8_t val)
MSX Put a pair of OPLL register number and its value to the internal buffer.
void OPLL_rhythm(uint8_t val)
MSX Key-on/off RHYTHM set.
void OPLL_play(struct OPLL *opll)
MSX Play sound on OPLL
void OPLL_rhythm_mode(bool on)
MSX Turn RHYTHM mode on/off.
uint8_t OPLL_find(struct OPLL *opll)
MSX Find OPLL sound chip.
void OPLL_enable(const struct OPLL *opll)
MSX Enable OPLL sound chip.
OPLL Handle.
Definition opll.h:74
Using #include <msx.h> includes almost all C header files in libmsx, for ease to use.
Buffered access to OPLL registers.

Function Documentation

◆ OPLL_init()

void OPLL_init ( void  )

MSX Initialize internal buffer for OPLL.

This must be called at least once before OPLL_stop() or OPLL_play().

◆ OPLL_put()

void OPLL_put ( uint8_t  reg,
uint8_t  val 
)

MSX Put a pair of OPLL register number and its value to the internal buffer.

Put the pair of OPLL register #reg and its value val into the internal FIFO buffer. Then, by calling OPLL_play(), all values in the FIFO buffer are written to OPLL.

Parameters
regOPLL register number
  • 0x00..0x07 : INSTURUMENT DATA registers
  • 0x0e : RHYTHM control register
  • 0x0f : TEST register
  • 0x10..0x18 : F-Number (LSB 8 bits) registers
  • 0x20..0x28 : SUS/KEY/BLOCK/F-Number (MSB) registers
  • 0x30..0x38 : INSTRUMENT/VOLUME registers
vala value to be written to the register.

◆ OPLL_rhythm_mode()

void OPLL_rhythm_mode ( bool  on)

MSX Turn RHYTHM mode on/off.

Parameters
onSpecify the mode:
  • true : 6 channels + RHYTHM mode.
  • false : 9 channels mode.

◆ OPLL_rhythm()

void OPLL_rhythm ( uint8_t  val)

MSX Key-on/off RHYTHM set.

Parameters
valKey-on/off switch for each RHYTHM set:
  • bit #0 : HH (high-hat)
  • bit #1 : TOP-CY (cymbal)
  • bit #2 : TOM (tom-tom)
  • bit #3 : SD (snare drum)
  • bit #4 : BD (bass drum)
Precondition
The mode shall be 6 channels + RHYTHM mode.
See also
OPLL_rhythm_mode()

◆ OPLL_stop()

void OPLL_stop ( struct OPLL opll)

MSX Stop (Pause) playing sound on OPLL

Parameters
opllpointer to the OPLL handle.
Postcondition
Interrupt is disabled.
See also
OPLL_find()
Note
This function simply sets all channels to KEY-OFF.

◆ OPLL_play()

void OPLL_play ( struct OPLL opll)

MSX Play sound on OPLL

This function applies the values in the internal buffer to OPLL.

Parameters
opllpointer to the OPLL handle.
Postcondition
Interrupt is disabled.
See also
OPLL_find()

Variable Documentation

◆ opll_buffer

uint8_t opll_buffer[64]
extern

MSX Cache of OPLL registers.

See also
OPLL_put()