moe-bius/opmplay/lxmplay/opmplay.h

137 lines
3.1 KiB
C
Raw Normal View History

2024-04-05 16:28:31 -04:00
#pragma once
#include <stdint.h>
#include "opmfile.h"
// OPMPlay setup defines
#define OPMPLAY_ENABLE_STDIO
#ifdef OPMPLAY_ENABLE_STDIO
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#endif
// LXMPlay import defines
#define opmplay_memcpy memcpy
#define opmplay_memset memset
#define opmplay_memcmp memcmp
#define opmplay_alloc malloc
#define opmplay_memfree free
#define opmplay_debug_printf(...) printf(__VA_ARGS__)
#ifdef __cplusplus
extern "C" {
#endif
// general enums
enum {
2025-08-12 09:59:39 -04:00
OPMPLAY_MAX_CHANNLES = 16,
2024-04-06 13:02:09 -04:00
OPMPLAY_MAX_STACK_DEPTH = 4,
2024-04-05 16:28:31 -04:00
};
// return error codes
enum {
OPMPLAY_ERR_OK = 0,
OPMPLAY_ERR_END_OF_STREAM = 1,
OPMPLAY_ERR_BAD_FILE_STRUCTURE = -1,
OPMPLAY_ERR_MEMALLOC = -2,
OPMPLAY_ERR_NULLPTR = -3,
OPMPLAY_ERR_NO_SOUNDRAM = -4,
OPMPLAY_ERR_DEVICE = -5,
OPMPLAY_ERR_BAD_PARAMETER = -6,
OPMPLAY_ERR_IO = -7,
OPMPLAY_ERR_UNKNOWN = -20,
};
enum {
OPMPLAY_IO_USER = 0,
OPMPLAY_IO_FILE = 1,
OPMPLAY_IO_MEMORY = 2,
};
// file I/O structs
struct opmplay_io_t {
uint32_t type; // i/o type
union {
void* buf;
#ifdef OPMPLAY_ENABLE_STDIO
FILE* io;
#endif
};
uint32_t size;
// internal
uint32_t offset;
uint32_t(*read)(opmplay_io_t* io, void* dst, uint32_t size); // returns bytes read
uint32_t(*seek)(opmplay_io_t* io, uint32_t offset); // returns 0 if success
};
2024-04-06 13:02:09 -04:00
struct opmplay_channel_stack_t {
2025-08-12 09:59:39 -04:00
const uint8_t* ptr;
uint16_t frames_to_play;
2024-04-06 13:02:09 -04:00
};
2024-04-05 16:28:31 -04:00
struct opmplay_channel_context_t {
2024-04-06 13:02:09 -04:00
// stack
opmplay_channel_stack_t stack[OPMPLAY_MAX_STACK_DEPTH];
2025-08-12 09:59:39 -04:00
uint16_t stack_pos;
2024-04-05 16:28:31 -04:00
// stream data
struct {
2025-08-12 09:59:39 -04:00
uint16_t samples_to_play;
uint16_t delay;
uint16_t reload;
2024-04-05 16:28:31 -04:00
2025-08-12 09:59:39 -04:00
const uint8_t* data;
const uint8_t* ptr;
const uint8_t* loop; // if active
2024-04-05 16:28:31 -04:00
} stream;
2025-08-13 07:49:14 -04:00
// private stuff
uint8_t block; // cached block register
2024-04-05 16:28:31 -04:00
};
struct opmplay_context_t {
// LXM file header
opm_header_t header;
// channel context
opmplay_channel_context_t channels[OPMPLAY_MAX_CHANNLES];
2024-04-05 16:28:31 -04:00
// position data
struct {
2025-08-12 09:59:39 -04:00
uint16_t frame;
uint16_t frame_looped;
2024-04-05 16:28:31 -04:00
uint32_t samples;
} pos;
2025-08-13 07:49:14 -04:00
// private stuff
uint8_t ssg_r7[2]; // cached SSG mask register
uint8_t extch3_block[2][3]; // cached extch3 block
2024-04-05 16:28:31 -04:00
};
// init context
2025-08-12 09:59:39 -04:00
int opmplay_init(opmplay_context_t* ctx);
2024-04-05 16:28:31 -04:00
// free context
int opmplay_free(opmplay_context_t* ctx);
// load file header
int opmplay_load_header(opmplay_context_t* ctx, opmplay_io_t* io);
// load file contents
int opmplay_load_module(opmplay_context_t* ctx, opmplay_io_t* io);
// reset to start
int opmplay_rewind(opmplay_context_t* ctx);
// play one tick, render changes to opl3 device
2024-09-02 02:55:54 -04:00
int opmplay_tick(opmplay_context_t* ctx);
2024-04-05 16:28:31 -04:00
#ifdef __cplusplus
}
#endif