libmsx
C library for MSX
Loading...
Searching...
No Matches
opll_buf.h File Reference

Buffered access to OPLL registers. More...

#include <opll.h>
#include <stdbool.h>
+ Include dependency graph for opll_buf.h:

Go to the source code of this file.

Macros

#define OPLL_BUF_H_
 

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

Buffered access to OPLL registers.

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.

Definition in file opll_buf.h.

Macro Definition Documentation

◆ OPLL_BUF_H_

#define OPLL_BUF_H_

Definition at line 25 of file opll_buf.h.