-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathym2612.h
151 lines (136 loc) · 3.91 KB
/
ym2612.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
Copyright 2013 Michael Pavone
This file is part of BlastEm.
BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
*/
#ifndef YM2612_H_
#define YM2612_H_
#include <stdint.h>
#include <stdio.h>
#include "serialize.h"
#define NUM_PART_REGS (0xB7-0x30)
#define NUM_CHANNELS 6
#define NUM_OPERATORS (4*NUM_CHANNELS)
#define YM_OPT_WAVE_LOG 1
typedef struct {
uint32_t phase_counter;
uint16_t envelope;
int16_t output;
uint16_t total_level;
uint16_t sustain_level;
uint8_t rates[4];
uint8_t key_scaling;
uint8_t multiple;
uint8_t detune;
uint8_t am;
uint8_t env_phase;
uint8_t ssg;
uint8_t inverted;
} ym_operator;
typedef struct {
FILE * logfile;
uint16_t fnum;
int16_t output;
int16_t op1_old;
uint8_t block_fnum_latch;
uint8_t block;
uint8_t keycode;
uint8_t algorithm;
uint8_t feedback;
uint8_t ams;
uint8_t pms;
uint8_t lr;
uint8_t keyon;
} ym_channel;
typedef struct {
uint16_t fnum;
uint8_t block;
uint8_t block_fnum_latch;
uint8_t keycode;
} ym_supp;
#define YM_PART1_START 0x21
#define YM_PART2_START 0x30
#define YM_REG_END 0xB8
#define YM_PART1_REGS (YM_REG_END-YM_PART1_START)
#define YM_PART2_REGS (YM_REG_END-YM_PART2_START)
typedef struct {
int16_t *audio_buffer;
int16_t *back_buffer;
uint64_t buffer_fraction;
uint64_t buffer_inc;
uint32_t clock_inc;
uint32_t buffer_pos;
uint32_t sample_rate;
uint32_t sample_limit;
uint32_t current_cycle;
//TODO: Condense the next two fields into one
uint32_t write_cycle;
uint32_t busy_cycles;
uint32_t lowpass_alpha;
ym_operator operators[NUM_OPERATORS];
ym_channel channels[NUM_CHANNELS];
uint16_t timer_a;
uint16_t timer_a_load;
uint16_t env_counter;
ym_supp ch3_supp[3];
int16_t last_left;
int16_t last_right;
uint8_t timer_b;
uint8_t sub_timer_b;
uint8_t timer_b_load;
uint8_t ch3_mode;
uint8_t current_op;
uint8_t current_env_op;
uint8_t timer_control;
uint8_t dac_enable;
uint8_t lfo_enable;
uint8_t lfo_freq;
uint8_t lfo_counter;
uint8_t lfo_am_step;
uint8_t lfo_pm_step;
uint8_t csm_keyon;
uint8_t status;
uint8_t selected_reg;
uint8_t selected_part;
uint8_t part1_regs[YM_PART1_REGS];
uint8_t part2_regs[YM_PART2_REGS];
} ym2612_context;
enum {
REG_LFO = 0x22,
REG_TIMERA_HIGH = 0x24,
REG_TIMERA_LOW,
REG_TIMERB,
REG_TIME_CTRL,
REG_KEY_ONOFF,
REG_DAC = 0x2A,
REG_DAC_ENABLE,
REG_DETUNE_MULT = 0x30,
REG_TOTAL_LEVEL = 0x40,
REG_ATTACK_KS = 0x50,
REG_DECAY_AM = 0x60,
REG_SUSTAIN_RATE = 0x70,
REG_S_LVL_R_RATE = 0x80,
REG_SSG_EG = 0x90,
REG_FNUM_LOW = 0xA0,
REG_BLOCK_FNUM_H = 0xA4,
REG_FNUM_LOW_CH3 = 0xA8,
REG_BLOCK_FN_CH3 = 0xAC,
REG_ALG_FEEDBACK = 0xB0,
REG_LR_AMS_PMS = 0xB4
};
void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, uint32_t sample_limit, uint32_t options, uint32_t lowpass_cutoff);
void ym_reset(ym2612_context *context);
void ym_free(ym2612_context *context);
void ym_adjust_master_clock(ym2612_context * context, uint32_t master_clock);
void ym_run(ym2612_context * context, uint32_t to_cycle);
void ym_address_write_part1(ym2612_context * context, uint8_t address);
void ym_address_write_part2(ym2612_context * context, uint8_t address);
void ym_data_write(ym2612_context * context, uint8_t value);
uint8_t ym_read_status(ym2612_context * context);
uint8_t ym_load_gst(ym2612_context * context, FILE * gstfile);
uint8_t ym_save_gst(ym2612_context * context, FILE * gstfile);
void ym_print_channel_info(ym2612_context *context, int channel);
void ym_print_timer_info(ym2612_context *context);
void ym_serialize(ym2612_context *context, serialize_buffer *buf);
void ym_deserialize(deserialize_buffer *buf, void *vcontext);
#endif //YM2612_H_