annotate ym2612.c @ 376:f6def5cdf1b4

Fix key scaling
author Mike Pavone <pavone@retrodev.com>
date Sun, 02 Jun 2013 21:52:42 -0700
parents d42a8a3e4894
children da8d53dc914b
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
1 #include <string.h>
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
2 #include <math.h>
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
3 #include <stdio.h>
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
4 #include <stdlib.h>
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
5 #include "ym2612.h"
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
6 #include "render.h"
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
7
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
8 //#define DO_DEBUG_PRINT
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
9 #ifdef DO_DEBUG_PRINT
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
10 #define dfprintf fprintf
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
11 #define dfopen(var, fname, mode) var=fopen(fname, mode)
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
12 #else
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
13 #define dfprintf
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
14 #define dfopen(var, fname, mode)
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
15 #endif
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
16
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
17 #define BUSY_CYCLES 17
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
18 #define OP_UPDATE_PERIOD 144
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
19
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
20 enum {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
21 REG_TIMERA_HIGH = 0x24,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
22 REG_TIMERA_LOW,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
23 REG_TIMERB,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
24 REG_TIME_CTRL,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
25 REG_KEY_ONOFF,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
26 REG_DAC = 0x2A,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
27 REG_DAC_ENABLE,
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
28
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
29 REG_DETUNE_MULT = 0x30,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
30 REG_TOTAL_LEVEL = 0x40,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
31 REG_ATTACK_KS = 0x50,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
32 REG_DECAY_AM = 0x60,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
33 REG_SUSTAIN_RATE = 0x70,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
34 REG_S_LVL_R_RATE = 0x80,
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
35
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
36 REG_FNUM_LOW = 0xA0,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
37 REG_BLOCK_FNUM_H = 0xA4,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
38 REG_FNUM_LOW_CH3 = 0xA8,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
39 REG_BLOCK_FN_CH3 = 0xAC,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
40 REG_ALG_FEEDBACK = 0xB0,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
41 REG_LR_AMS_PMS = 0xB4
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
42 };
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
43
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
44 #define BIT_TIMERA_ENABLE 0x1
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
45 #define BIT_TIMERB_ENABLE 0x2
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
46 #define BIT_TIMERA_OVEREN 0x4
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
47 #define BIT_TIMERB_OVEREN 0x8
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
48 #define BIT_TIMERA_RESET 0x10
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
49 #define BIT_TIMERB_RESET 0x20
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
50
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
51 #define BIT_STATUS_TIMERA 0x1
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
52 #define BIT_STATUS_TIMERB 0x2
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
53
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
54 enum {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
55 PHASE_ATTACK,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
56 PHASE_DECAY,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
57 PHASE_SUSTAIN,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
58 PHASE_RELEASE
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
59 };
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
60
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
61 uint8_t did_tbl_init = 0;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
62 //According to Nemesis, real hardware only uses a 256 entry quarter sine table; however,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
63 //memory is cheap so using a half sine table will probably save some cycles
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
64 //a full sine table would be nice, but negative numbers don't get along with log2
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
65 #define SINE_TABLE_SIZE 512
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
66 uint16_t sine_table[SINE_TABLE_SIZE];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
67 //Similar deal here with the power table for log -> linear conversion
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
68 //According to Nemesis, real hardware only uses a 256 entry table for the fractional part
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
69 //and uses the whole part as a shift amount.
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
70 #define POW_TABLE_SIZE (1 << 13)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
71 uint16_t pow_table[POW_TABLE_SIZE];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
72
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
73 uint16_t rate_table_base[] = {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
74 //main portion
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
75 0,1,0,1,0,1,0,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
76 0,1,0,1,1,1,0,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
77 0,1,1,1,0,1,1,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
78 0,1,1,1,1,1,1,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
79 //top end
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
80 1,1,1,1,1,1,1,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
81 1,1,1,2,1,1,1,2,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
82 1,2,1,2,1,2,1,2,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
83 1,2,2,2,1,2,2,2,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
84 };
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
85
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
86 uint16_t rate_table[64*8];
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
87
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
88 #define MAX_ENVELOPE 0xFFC
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
89 #define YM_DIVIDER 2
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
90 #define CYCLE_NEVER 0xFFFFFFFF
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
91
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
92 uint16_t round_fixed_point(double value, int dec_bits)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
93 {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
94 return value * (1 << dec_bits) + 0.5;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
95 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
96
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
97 FILE * debug_file = NULL;
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
98 uint32_t first_key_on=0;
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
99
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
100 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t clock_rate, uint32_t sample_limit)
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
101 {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
102 dfopen(debug_file, "ym_debug.txt", "w");
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
103 memset(context, 0, sizeof(*context));
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
104 context->audio_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
105 context->back_buffer = malloc(sizeof(*context->audio_buffer) * sample_limit*2);
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
106 context->buffer_inc = (double)sample_rate / (double)(clock_rate/OP_UPDATE_PERIOD);
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
107 context->sample_limit = sample_limit*2;
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
108 context->write_cycle = CYCLE_NEVER;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
109 for (int i = 0; i < NUM_OPERATORS; i++) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
110 context->operators[i].envelope = MAX_ENVELOPE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
111 context->operators[i].env_phase = PHASE_RELEASE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
112 }
369
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
113 //some games seem to expect that the LR flags start out as 1
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
114 for (int i = 0; i < NUM_CHANNELS; i++) {
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
115 context->channels[i].lr = 0xC0;
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
116 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
117 if (!did_tbl_init) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
118 //populate sine table
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
119 for (int32_t i = 0; i < 512; i++) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
120 double sine = sin( ((double)(i*2+1) / SINE_TABLE_SIZE) * M_PI_2 );
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
121
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
122 //table stores 4.8 fixed pointed representation of the base 2 log
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
123 sine_table[i] = round_fixed_point(-log2(sine), 8);
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
124 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
125 //populate power table
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
126 for (int32_t i = 0; i < POW_TABLE_SIZE; i++) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
127 double linear = pow(2, -((double)((i & 0xFF)+1) / 256.0));
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
128 int32_t tmp = round_fixed_point(linear, 11);
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
129 int32_t shift = (i >> 8) - 2;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
130 if (shift < 0) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
131 tmp <<= 0-shift;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
132 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
133 tmp >>= shift;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
134 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
135 pow_table[i] = tmp;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
136 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
137 //populate envelope generator rate table, from small base table
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
138 for (int rate = 0; rate < 64; rate++) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
139 for (int cycle = 0; cycle < 8; cycle++) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
140 uint16_t value;
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
141 if (rate < 2) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
142 value = 0;
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
143 } else if (rate >= 60) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
144 value = 8;
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
145 } else if (rate < 8) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
146 value = rate_table_base[((rate & 6) == 6 ? 16 : 0) + cycle];
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
147 } else if (rate < 48) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
148 value = rate_table_base[(rate & 0x3) * 8 + cycle];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
149 } else {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
150 value = rate_table_base[32 + (rate & 0x3) * 8 + cycle] << ((rate - 48) >> 2);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
151 }
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
152 rate_table[rate * 8 + cycle] = value;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
153 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
154 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
155 }
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
156 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
157
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
158 #define YM_VOLUME_DIVIDER 1
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
159
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
160 void ym_run(ym2612_context * context, uint32_t to_cycle)
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
161 {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
162 //printf("Running YM2612 from cycle %d to cycle %d\n", context->current_cycle, to_cycle);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
163 //TODO: Fix channel update order OR remap channels in register write
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
164 for (; context->current_cycle < to_cycle; context->current_cycle += 6) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
165 //Update timers at beginning of 144 cycle period
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
166 if (!context->current_op && context->timer_control & BIT_TIMERA_ENABLE) {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
167 if (context->timer_a) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
168 context->timer_a--;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
169 } else {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
170 if (context->timer_control & BIT_TIMERA_OVEREN) {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
171 context->status |= BIT_STATUS_TIMERA;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
172 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
173 context->timer_a = context->timer_a_load;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
174 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
175 if (context->timer_control & BIT_TIMERB_ENABLE) {
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
176 uint32_t b_cyc = (context->current_cycle / OP_UPDATE_PERIOD) % 16;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
177 if (!b_cyc) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
178 if (context->timer_b) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
179 context->timer_b--;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
180 } else {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
181 if (context->timer_control & BIT_TIMERB_OVEREN) {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
182 context->status |= BIT_STATUS_TIMERB;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
183 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
184 context->timer_b = context->timer_b_load;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
185 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
186 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
187 }
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
188 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
189 //Update Envelope Generator
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
190 if (!(context->current_op % 3)) {
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
191 uint32_t env_cyc = context->env_counter;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
192 uint32_t op = context->current_env_op;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
193 ym_operator * operator = context->operators + op;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
194 ym_channel * channel = context->channels + op/4;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
195 uint8_t rate;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
196 for(;;) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
197 rate = operator->rates[operator->env_phase];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
198 if (rate) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
199 uint8_t ks = channel->keycode >> operator->key_scaling;;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
200 rate = rate*2 + ks;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
201 if (rate > 63) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
202 rate = 63;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
203 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
204 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
205 //Deal with "infinite" rates
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
206 //According to Nemesis this should be handled in key-on instead
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
207 if (rate >= 62 && operator->env_phase == PHASE_ATTACK) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
208 operator->env_phase = PHASE_DECAY;
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
209 operator->envelope = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
210 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
211 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
212 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
213 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
214 uint32_t cycle_shift = rate < 0x30 ? ((0x2F - rate) >> 2) : 0;
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
215 if (first_key_on) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
216 dfprintf(debug_file, "Operator: %d, env rate: %d (2*%d+%d), env_cyc: %d, cycle_shift: %d, env_cyc & ((1 << cycle_shift) - 1): %d\n", op, rate, operator->rates[operator->env_phase], channel->keycode >> operator->key_scaling,env_cyc, cycle_shift, env_cyc & ((1 << cycle_shift) - 1));
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
217 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
218 if (!(env_cyc & ((1 << cycle_shift) - 1))) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
219 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
220 //envelope value is 10-bits, but it will be used as a 4.8 value
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
221 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle] << 2;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
222 if (operator->env_phase == PHASE_ATTACK) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
223 //this can probably be optimized to a single shift rather than a multiply + shift
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
224 if (first_key_on) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
225 dfprintf(debug_file, "Changing op %d envelope %d by %d(%d * %d) in attack phase\n", op, operator->envelope, (~operator->envelope * envelope_inc) >> 4, ~operator->envelope, envelope_inc);
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
226 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
227 operator->envelope += (~operator->envelope * envelope_inc) >> 4;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
228 operator->envelope &= MAX_ENVELOPE;
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
229 if (!operator->envelope) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
230 operator->envelope = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
231 operator->env_phase = PHASE_DECAY;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
232 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
233 } else {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
234 if (first_key_on) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
235 dfprintf(debug_file, "Changing op %d envelope %d by %d in %s phase\n", op, operator->envelope, envelope_inc,
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
236 operator->env_phase == PHASE_SUSTAIN ? "sustain" : (operator->env_phase == PHASE_DECAY ? "decay": "release"));
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
237 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
238 operator->envelope += envelope_inc;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
239 //clamp to max attenuation value
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
240 if (operator->envelope > MAX_ENVELOPE) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
241 operator->envelope = MAX_ENVELOPE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
242 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
243 if (operator->env_phase == PHASE_DECAY && operator->envelope >= operator->sustain_level) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
244 //operator->envelope = operator->sustain_level;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
245 operator->env_phase = PHASE_SUSTAIN;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
246 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
247 }
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
248 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
249 context->current_env_op++;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
250 if (context->current_env_op == NUM_OPERATORS) {
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
251 context->current_env_op = 0;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
252 context->env_counter++;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
253 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
254 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
255
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
256 //Update Phase Generator
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
257 uint32_t channel = context->current_op / 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
258 if (channel != 5 || !context->dac_enable) {
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
259 uint32_t op = context->current_op;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
260 //printf("updating operator %d of channel %d\n", op, channel);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
261 ym_operator * operator = context->operators + op;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
262 ym_channel * chan = context->channels + channel;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
263 //TODO: Modulate phase by LFO if necessary
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
264 operator->phase_counter += operator->phase_inc;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
265 uint16_t phase = operator->phase_counter >> 10 & 0x3FF;
371
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
266 int16_t mod = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
267 switch (op % 4)
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
268 {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
269 case 0://Operator 1
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
270 //TODO: Feedback
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
271 break;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
272 case 1://Operator 3
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
273 switch(chan->algorithm)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
274 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
275 case 0:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
276 case 2:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
277 //modulate by operator 2
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
278 mod = context->operators[op+1].output >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
279 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
280 case 1:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
281 //modulate by operator 1+2
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
282 mod = (context->operators[op-1].output + context->operators[op+1].output) >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
283 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
284 case 5:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
285 //modulate by operator 1
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
286 mod = context->operators[op-1].output >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
287 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
288 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
289 case 2://Operator 2
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
290 if (chan->algorithm != 1 && chan->algorithm != 2 || chan->algorithm != 7) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
291 //modulate by Operator 1
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
292 mod = context->operators[op-2].output >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
293 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
294 break;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
295 case 3://Operator 4
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
296 switch(chan->algorithm)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
297 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
298 case 0:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
299 case 1:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
300 case 4:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
301 //modulate by operator 3
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
302 mod = context->operators[op-2].output >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
303 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
304 case 2:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
305 //modulate by operator 1+3
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
306 mod = (context->operators[op-3].output + context->operators[op-2].output) >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
307 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
308 case 3:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
309 //modulate by operator 2+3
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
310 mod = (context->operators[op-1].output + context->operators[op-2].output) >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
311 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
312 case 5:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
313 //modulate by operator 1
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
314 mod = context->operators[op-3].output >> 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
315 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
316 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
317 break;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
318 }
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
319 uint16_t env = operator->envelope + operator->total_level;
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
320 if (env > MAX_ENVELOPE) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
321 env = MAX_ENVELOPE;
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
322 }
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
323 if (first_key_on) {
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
324 dfprintf(debug_file, "op %d, base phase: %d, mod: %d, sine: %d, out: %d\n", op, phase, mod, sine_table[(phase+mod) & 0x1FF], pow_table[sine_table[phase & 0x1FF] + env]);
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
325 }
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
326 phase += mod;
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
327
371
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
328 int16_t output = pow_table[sine_table[phase & 0x1FF] + env];
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
329 if (phase & 0x200) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
330 output = -output;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
331 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
332 operator->output = output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
333 //Update the channel output if we've updated all operators
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
334 if (op % 4 == 3) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
335 if (chan->algorithm < 4) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
336 chan->output = operator->output;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
337 } else if(chan->algorithm == 4) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
338 chan->output = operator->output + context->operators[channel * 4 + 1].output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
339 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
340 output = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
341 for (uint32_t op = ((chan->algorithm == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
342 output += context->operators[op].output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
343 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
344 chan->output = output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
345 }
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
346 if (first_key_on) {
371
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
347 int16_t value = context->channels[channel].output & 0x3FE0;
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
348 if (value & 0x2000) {
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
349 value |= 0xC000;
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
350 }
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
351 dfprintf(debug_file, "channel %d output: %d\n", channel, value / YM_VOLUME_DIVIDER);
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
352 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
353 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
354 //puts("operator update done");
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
355 }
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
356 context->current_op++;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
357 if (context->current_op == NUM_OPERATORS) {
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
358 context->current_op = 0;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
359 context->buffer_fraction += context->buffer_inc;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
360 if (context->buffer_fraction > 1.0) {
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
361 context->buffer_fraction -= 1.0;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
362 context->audio_buffer[context->buffer_pos] = 0;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
363 context->audio_buffer[context->buffer_pos + 1] = 0;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
364 for (int i = 0; i < NUM_CHANNELS; i++) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
365 int16_t value = context->channels[i].output & 0x3FE0;
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
366 if (value & 0x2000) {
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
367 value |= 0xC000;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
368 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
369 if (context->channels[i].lr & 0x80) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
370 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER;
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
371 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
372 if (context->channels[i].lr & 0x40) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
373 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER;
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
374 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
375 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
376 context->buffer_pos += 2;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
377 if (context->buffer_pos == context->sample_limit) {
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
378 render_wait_ym(context);
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
379 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
380 }
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
381 }
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
382 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
383 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) {
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
384 context->status &= 0x7F;
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
385 context->write_cycle = CYCLE_NEVER;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
386 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
387 //printf("Done running YM2612 at cycle %d\n", context->current_cycle, to_cycle);
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
388 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
389
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
390 void ym_address_write_part1(ym2612_context * context, uint8_t address)
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
391 {
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
392 //printf("address_write_part1: %X\n", address);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
393 context->selected_reg = address;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
394 context->selected_part = 0;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
395 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
396
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
397 void ym_address_write_part2(ym2612_context * context, uint8_t address)
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
398 {
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
399 //printf("address_write_part2: %X\n", address);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
400 context->selected_reg = address;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
401 context->selected_part = 1;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
402 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
403
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
404 uint8_t fnum_to_keycode[] = {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
405 //F11 = 0
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
406 0,0,0,0,0,0,0,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
407 //F11 = 1
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
408 2,3,3,3,3,3,3,3
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
409 };
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
410
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
411 //table courtesy of Nemesis
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
412 uint32_t detune_table[][4] = {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
413 {0, 0, 1, 2}, //0 (0x00)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
414 {0, 0, 1, 2}, //1 (0x01)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
415 {0, 0, 1, 2}, //2 (0x02)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
416 {0, 0, 1, 2}, //3 (0x03)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
417 {0, 1, 2, 2}, //4 (0x04)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
418 {0, 1, 2, 3}, //5 (0x05)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
419 {0, 1, 2, 3}, //6 (0x06)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
420 {0, 1, 2, 3}, //7 (0x07)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
421 {0, 1, 2, 4}, //8 (0x08)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
422 {0, 1, 3, 4}, //9 (0x09)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
423 {0, 1, 3, 4}, //10 (0x0A)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
424 {0, 1, 3, 5}, //11 (0x0B)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
425 {0, 2, 4, 5}, //12 (0x0C)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
426 {0, 2, 4, 6}, //13 (0x0D)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
427 {0, 2, 4, 6}, //14 (0x0E)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
428 {0, 2, 5, 7}, //15 (0x0F)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
429 {0, 2, 5, 8}, //16 (0x10)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
430 {0, 3, 6, 8}, //17 (0x11)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
431 {0, 3, 6, 9}, //18 (0x12)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
432 {0, 3, 7,10}, //19 (0x13)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
433 {0, 4, 8,11}, //20 (0x14)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
434 {0, 4, 8,12}, //21 (0x15)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
435 {0, 4, 9,13}, //22 (0x16)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
436 {0, 5,10,14}, //23 (0x17)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
437 {0, 5,11,16}, //24 (0x18)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
438 {0, 6,12,17}, //25 (0x19)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
439 {0, 6,13,19}, //26 (0x1A)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
440 {0, 7,14,20}, //27 (0x1B)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
441 {0, 8,16,22}, //28 (0x1C)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
442 {0, 8,16,22}, //29 (0x1D)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
443 {0, 8,16,22}, //30 (0x1E)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
444 {0, 8,16,22}
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
445 }; //31 (0x1F)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
446
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
447 void ym_update_phase_inc(ym2612_context * context, ym_operator * operator, uint32_t op)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
448 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
449 uint32_t chan_num = op / 4;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
450 //printf("ym_update_phase_inc | channel: %d, op: %d\n", chan_num, op);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
451 //base frequency
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
452 ym_channel * channel = context->channels + chan_num;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
453 uint32_t inc = channel->fnum;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
454 if (!channel->block) {
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
455 inc >>= 1;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
456 } else {
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
457 inc <<= (channel->block-1);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
458 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
459 //detune
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
460 uint32_t detune = detune_table[channel->keycode][operator->detune & 0x3];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
461 if (operator->detune & 0x40) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
462 inc -= detune;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
463 //this can underflow, mask to 17-bit result
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
464 inc &= 0x1FFFF;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
465 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
466 inc += detune;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
467 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
468 //multiple
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
469 if (operator->multiple) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
470 inc *= operator->multiple;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
471 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
472 //0.5
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
473 inc >>= 1;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
474 }
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
475 //printf("phase_inc for operator %d: %d, block: %d, fnum: %d, detune: %d, multiple: %d\n", op, inc, channel->block, channel->fnum, detune, operator->multiple);
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
476 operator->phase_inc = inc;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
477 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
478
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
479 void ym_data_write(ym2612_context * context, uint8_t value)
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
480 {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
481 if (context->selected_reg < 0x21 || context->selected_reg > 0xB6 || (context->selected_reg < 0x30 && context->selected_part)) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
482 return;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
483 }
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
484 dfprintf(debug_file, "write of %X to reg %X in part %d\n", value, context->selected_reg, context->selected_part+1);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
485 if (context->selected_reg < 0x30) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
486 //Shared regs
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
487 switch (context->selected_reg)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
488 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
489 //TODO: Test reg and LFO
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
490 case REG_TIMERA_HIGH:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
491 context->timer_a_load &= 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
492 context->timer_a_load |= value << 2;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
493 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
494 case REG_TIMERA_LOW:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
495 context->timer_a_load &= 0xFFFC;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
496 context->timer_a_load |= value & 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
497 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
498 case REG_TIMERB:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
499 context->timer_b_load = value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
500 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
501 case REG_TIME_CTRL:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
502 context->timer_control = value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
503 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
504 case REG_KEY_ONOFF: {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
505 uint8_t channel = value & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
506 if (channel < NUM_CHANNELS) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
507 for (uint8_t op = channel * 4, bit = 0x10; op < (channel + 1) * 4; op++, bit <<= 1) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
508 if (value & bit) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
509 first_key_on = 1;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
510 //printf("Key On for operator %d in channel %d\n", op, channel);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
511 context->operators[op].phase_counter = 0;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
512 context->operators[op].env_phase = PHASE_ATTACK;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
513 context->operators[op].envelope = MAX_ENVELOPE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
514 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
515 //printf("Key Off for operator %d in channel %d\n", op, channel);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
516 context->operators[op].env_phase = PHASE_RELEASE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
517 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
518 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
519 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
520 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
521 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
522 case REG_DAC:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
523 if (context->dac_enable) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
524 context->channels[5].output = (((int16_t)value) - 0x80) << 6;
369
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
525 //printf("DAC Write %X(%d)\n", value, context->channels[5].output);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
526 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
527 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
528 case REG_DAC_ENABLE:
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
529 //printf("DAC Enable: %X\n", value);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
530 context->dac_enable = value & 0x80;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
531 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
532 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
533 } else if (context->selected_reg < 0xA0) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
534 //part
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
535 uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
536 //channel in part
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
537 if ((context->selected_reg & 0x3) != 0x3) {
370
5f215603d001 Fix register to operator mapping. Fix rate table generation. Add TL to envelope value rather than using it as a limit for the attack phase.
Mike Pavone <pavone@retrodev.com>
parents: 369
diff changeset
538 op += 4 * (context->selected_reg & 0x3) + ((context->selected_reg & 0xC) / 4);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
539 //printf("write targets operator %d (%d of channel %d)\n", op, op % 4, op / 4);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
540 ym_operator * operator = context->operators + op;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
541 switch (context->selected_reg & 0xF0)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
542 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
543 case REG_DETUNE_MULT:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
544 operator->detune = value >> 4 & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
545 operator->multiple = value & 0xF;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
546 ym_update_phase_inc(context, operator, op);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
547 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
548 case REG_TOTAL_LEVEL:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
549 operator->total_level = (value & 0x7F) << 5;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
550 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
551 case REG_ATTACK_KS:
376
f6def5cdf1b4 Fix key scaling
Mike Pavone <pavone@retrodev.com>
parents: 374
diff changeset
552 operator->key_scaling = 3 - (value >> 6);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
553 operator->rates[PHASE_ATTACK] = value & 0x1F;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
554 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
555 case REG_DECAY_AM:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
556 //TODO: AM flag for LFO
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
557 operator->rates[PHASE_DECAY] = value & 0x1F;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
558 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
559 case REG_SUSTAIN_RATE:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
560 operator->rates[PHASE_SUSTAIN] = value & 0x1F;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
561 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
562 case REG_S_LVL_R_RATE:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
563 operator->rates[PHASE_RELEASE] = (value & 0xF) << 1 | 1;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
564 operator->sustain_level = value & 0xF0 << 4;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
565 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
566 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
567 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
568 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
569 uint8_t channel = context->selected_reg & 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
570 if (channel != 3) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
571 if (context->selected_part) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
572 channel += 3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
573 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
574 //printf("write targets channel %d\n", channel);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
575 switch (context->selected_reg & 0xFC)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
576 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
577 case REG_FNUM_LOW:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
578 context->channels[channel].block = context->channels[channel].block_fnum_latch >> 3 & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
579 context->channels[channel].fnum = (context->channels[channel].block_fnum_latch & 0x7) << 8 | value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
580 context->channels[channel].keycode = context->channels[channel].block << 2 | fnum_to_keycode[context->channels[channel].fnum >> 7];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
581 ym_update_phase_inc(context, context->operators + channel*4, channel*4);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
582 ym_update_phase_inc(context, context->operators + channel*4+1, channel*4+1);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
583 ym_update_phase_inc(context, context->operators + channel*4+2, channel*4+2);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
584 ym_update_phase_inc(context, context->operators + channel*4+3, channel*4+3);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
585 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
586 case REG_BLOCK_FNUM_H:{
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
587 context->channels[channel].block_fnum_latch = value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
588 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
589 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
590 //TODO: Channel 3 special/CSM modes
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
591 case REG_ALG_FEEDBACK:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
592 context->channels[channel].algorithm = value & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
593 context->channels[channel].feedback = value >> 3 & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
594 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
595 case REG_LR_AMS_PMS:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
596 context->channels[channel].pms = value & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
597 context->channels[channel].ams = value >> 4 & 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
598 context->channels[channel].lr = value & 0xC0;
369
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
599 //printf("Write of %X to LR_AMS_PMS reg for channel %d\n", value, channel);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
600 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
601 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
602 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
603 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
604
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
605 context->write_cycle = context->current_cycle;
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
606 context->status |= 0x80;
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
607 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
608
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
609 uint8_t ym_read_status(ym2612_context * context)
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
610 {
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
611 return context->status;
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
612 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
613