137 lines
3.1 KiB
C
137 lines
3.1 KiB
C
#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 {
|
|
OPMPLAY_MAX_CHANNLES = 16,
|
|
OPMPLAY_MAX_STACK_DEPTH = 4,
|
|
};
|
|
|
|
// 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
|
|
};
|
|
|
|
struct opmplay_channel_stack_t {
|
|
const uint8_t* ptr;
|
|
uint16_t frames_to_play;
|
|
};
|
|
|
|
struct opmplay_channel_context_t {
|
|
// stack
|
|
opmplay_channel_stack_t stack[OPMPLAY_MAX_STACK_DEPTH];
|
|
uint16_t stack_pos;
|
|
|
|
// stream data
|
|
struct {
|
|
uint16_t samples_to_play;
|
|
uint16_t delay;
|
|
uint16_t reload;
|
|
|
|
const uint8_t* data;
|
|
const uint8_t* ptr;
|
|
const uint8_t* loop; // if active
|
|
} stream;
|
|
|
|
// private stuff
|
|
uint8_t block; // cached block register
|
|
};
|
|
|
|
struct opmplay_context_t {
|
|
// LXM file header
|
|
opm_header_t header;
|
|
|
|
// channel context
|
|
opmplay_channel_context_t channels[OPMPLAY_MAX_CHANNLES];
|
|
|
|
// position data
|
|
struct {
|
|
uint16_t frame;
|
|
uint16_t frame_looped;
|
|
uint32_t samples;
|
|
} pos;
|
|
|
|
// private stuff
|
|
uint8_t ssg_r7[2]; // cached SSG mask register
|
|
uint8_t extch3_block[2][3]; // cached extch3 block
|
|
};
|
|
|
|
|
|
// init context
|
|
int opmplay_init(opmplay_context_t* ctx);
|
|
|
|
// 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
|
|
int opmplay_tick(opmplay_context_t* ctx);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|