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-2025 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()