annotate ym2612.c @ 381:7815ebbbd705

Fix modulation shift value
author Mike Pavone <pavone@retrodev.com>
date Mon, 03 Jun 2013 23:44:11 -0700
parents 1c8d74f2ab0b
children b904859964e5
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
380
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
100 void ym_init(ym2612_context * context, uint32_t sample_rate, uint32_t master_clock, uint32_t clock_div, 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);
380
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
106 context->buffer_inc = ((double)sample_rate / (double)master_clock) * clock_div * 6;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
107 context->clock_inc = clock_div * 6;
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
108 context->sample_limit = sample_limit*2;
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
109 context->write_cycle = CYCLE_NEVER;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
110 for (int i = 0; i < NUM_OPERATORS; i++) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
111 context->operators[i].envelope = MAX_ENVELOPE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
112 context->operators[i].env_phase = PHASE_RELEASE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
113 }
369
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
114 //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
115 for (int i = 0; i < NUM_CHANNELS; i++) {
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
116 context->channels[i].lr = 0xC0;
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
117 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
118 if (!did_tbl_init) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
119 //populate sine table
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
120 for (int32_t i = 0; i < 512; i++) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
121 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
122
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
123 //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
124 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
125 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
126 //populate power table
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
127 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
128 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
129 int32_t tmp = round_fixed_point(linear, 11);
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
130 int32_t shift = (i >> 8) - 2;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
131 if (shift < 0) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
132 tmp <<= 0-shift;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
133 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
134 tmp >>= shift;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
135 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
136 pow_table[i] = tmp;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
137 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
138 //populate envelope generator rate table, from small base table
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
139 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
140 for (int cycle = 0; cycle < 8; cycle++) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
141 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
142 if (rate < 2) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
143 value = 0;
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
144 } else if (rate >= 60) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
145 value = 8;
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
146 } 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
147 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
148 } else if (rate < 48) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
149 value = rate_table_base[(rate & 0x3) * 8 + cycle];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
150 } 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
151 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
152 }
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
153 rate_table[rate * 8 + cycle] = value;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
154 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
155 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
156 }
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
157 }
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
158
377
da8d53dc914b Initial stab at feedback
Mike Pavone <pavone@retrodev.com>
parents: 376
diff changeset
159 #define YM_VOLUME_DIVIDER 2
381
7815ebbbd705 Fix modulation shift value
Mike Pavone <pavone@retrodev.com>
parents: 380
diff changeset
160 #define YM_MOD_SHIFT 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
161
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
162 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
163 {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
164 //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
165 //TODO: Fix channel update order OR remap channels in register write
380
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
166 for (; context->current_cycle < to_cycle; context->current_cycle += context->clock_inc) {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
167 //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
168 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
169 if (context->timer_a) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
170 context->timer_a--;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
171 } else {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
172 if (context->timer_control & BIT_TIMERA_OVEREN) {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
173 context->status |= BIT_STATUS_TIMERA;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
174 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
175 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
176 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
177 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
178 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
179 if (!b_cyc) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
180 if (context->timer_b) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
181 context->timer_b--;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
182 } else {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
183 if (context->timer_control & BIT_TIMERB_OVEREN) {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
184 context->status |= BIT_STATUS_TIMERB;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
185 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
186 context->timer_b = context->timer_b_load;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
187 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
188 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
189 }
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
190 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
191 //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
192 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
193 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
194 uint32_t op = context->current_env_op;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
195 ym_operator * operator = context->operators + op;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
196 ym_channel * channel = context->channels + op/4;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
197 uint8_t rate;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
198 for(;;) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
199 rate = operator->rates[operator->env_phase];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
200 if (rate) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
201 uint8_t ks = channel->keycode >> operator->key_scaling;;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
202 rate = rate*2 + ks;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
203 if (rate > 63) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
204 rate = 63;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
205 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
206 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
207 //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
208 //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
209 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
210 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
211 operator->envelope = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
212 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
213 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
214 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
215 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
216 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
217 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
218 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
219 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
220 if (!(env_cyc & ((1 << cycle_shift) - 1))) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
221 uint32_t update_cycle = env_cyc >> cycle_shift & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
222 //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
223 uint16_t envelope_inc = rate_table[rate * 8 + update_cycle] << 2;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
224 if (operator->env_phase == PHASE_ATTACK) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
225 //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
226 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
227 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
228 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
229 operator->envelope += (~operator->envelope * envelope_inc) >> 4;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
230 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
231 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
232 operator->envelope = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
233 operator->env_phase = PHASE_DECAY;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
234 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
235 } 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
236 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
237 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
238 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
239 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
240 operator->envelope += envelope_inc;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
241 //clamp to max attenuation value
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
242 if (operator->envelope > MAX_ENVELOPE) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
243 operator->envelope = MAX_ENVELOPE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
244 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
245 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
246 //operator->envelope = operator->sustain_level;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
247 operator->env_phase = PHASE_SUSTAIN;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
248 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
249 }
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
250 }
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++;
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
252 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
253 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
254 context->env_counter++;
362
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 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
257
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
258 //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
259 uint32_t channel = context->current_op / 4;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
260 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
261 uint32_t op = context->current_op;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
262 //printf("updating operator %d of channel %d\n", op, channel);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
263 ym_operator * operator = context->operators + op;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
264 ym_channel * chan = context->channels + channel;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
265 //TODO: Modulate phase by LFO if necessary
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
266 operator->phase_counter += operator->phase_inc;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
267 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
268 int16_t mod = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
269 switch (op % 4)
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
270 {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
271 case 0://Operator 1
377
da8d53dc914b Initial stab at feedback
Mike Pavone <pavone@retrodev.com>
parents: 376
diff changeset
272 if (chan->feedback) {
378
92947faa258a Adjust shift for feedback
Mike Pavone <pavone@retrodev.com>
parents: 377
diff changeset
273 mod = operator->output >> (9-chan->feedback);
377
da8d53dc914b Initial stab at feedback
Mike Pavone <pavone@retrodev.com>
parents: 376
diff changeset
274 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
275 break;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
276 case 1://Operator 3
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
277 switch(chan->algorithm)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
278 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
279 case 0:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
280 case 2:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
281 //modulate by operator 2
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
282 mod = context->operators[op+1].output >> YM_MOD_SHIFT;
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 1:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
285 //modulate by operator 1+2
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
286 mod = (context->operators[op-1].output + context->operators[op+1].output) >> YM_MOD_SHIFT;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
287 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
288 case 5:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
289 //modulate by operator 1
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
290 mod = context->operators[op-1].output >> YM_MOD_SHIFT;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
291 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
292 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
293 case 2://Operator 2
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
294 if (chan->algorithm != 1 && chan->algorithm != 2 || chan->algorithm != 7) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
295 //modulate by Operator 1
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
296 mod = context->operators[op-2].output >> YM_MOD_SHIFT;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
297 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
298 break;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
299 case 3://Operator 4
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
300 switch(chan->algorithm)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
301 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
302 case 0:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
303 case 1:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
304 case 4:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
305 //modulate by operator 3
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
306 mod = context->operators[op-2].output >> YM_MOD_SHIFT;
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 2:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
309 //modulate by operator 1+3
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
310 mod = (context->operators[op-3].output + context->operators[op-2].output) >> YM_MOD_SHIFT;
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 3:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
313 //modulate by operator 2+3
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
314 mod = (context->operators[op-1].output + context->operators[op-2].output) >> YM_MOD_SHIFT;
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 case 5:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
317 //modulate by operator 1
379
3218e2f8d685 Make shift value of operator output to modulation input a define
Mike Pavone <pavone@retrodev.com>
parents: 378
diff changeset
318 mod = context->operators[op-3].output >> YM_MOD_SHIFT;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
319 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
320 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
321 break;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
322 }
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
323 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
324 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
325 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
326 }
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 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
328 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
329 }
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
330 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
331
371
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
332 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
333 if (phase & 0x200) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
334 output = -output;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
335 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
336 operator->output = output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
337 //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
338 if (op % 4 == 3) {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
339 if (chan->algorithm < 4) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
340 chan->output = operator->output;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
341 } else if(chan->algorithm == 4) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
342 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
343 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
344 output = 0;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
345 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
346 output += context->operators[op].output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
347 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
348 chan->output = output;
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
349 }
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
350 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
351 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
352 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
353 value |= 0xC000;
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
354 }
0f8a759f1ff4 Use signed ints for things that represent signed values in YM2612 core
Mike Pavone <pavone@retrodev.com>
parents: 370
diff changeset
355 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
356 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
357 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
358 //puts("operator update done");
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
359 }
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
360 context->current_op++;
380
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
361 context->buffer_fraction += context->buffer_inc;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
362 if (context->buffer_fraction > 1.0) {
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
363 context->buffer_fraction -= 1.0;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
364 context->audio_buffer[context->buffer_pos] = 0;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
365 context->audio_buffer[context->buffer_pos + 1] = 0;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
366 for (int i = 0; i < NUM_CHANNELS; i++) {
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
367 int16_t value = context->channels[i].output & 0x3FE0;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
368 if (value & 0x2000) {
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
369 value |= 0xC000;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
370 }
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
371 if (context->channels[i].lr & 0x80) {
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
372 context->audio_buffer[context->buffer_pos] += value / YM_VOLUME_DIVIDER;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
373 }
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
374 if (context->channels[i].lr & 0x40) {
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
375 context->audio_buffer[context->buffer_pos+1] += value / YM_VOLUME_DIVIDER;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
376 }
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
377 }
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
378 context->buffer_pos += 2;
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
379 if (context->buffer_pos == context->sample_limit) {
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
380 render_wait_ym(context);
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
381 }
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
382 }
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
383 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
384 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
385 }
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 }
380
1c8d74f2ab0b Make the PSG and YM2612 use the master clock internal with an increment based on clock divider so that they stay perflectly in sync. Run both the PSG and YM2612 whenver one of them needs to be run.
Mike Pavone <pavone@retrodev.com>
parents: 379
diff changeset
387 if (context->current_cycle >= context->write_cycle + (BUSY_CYCLES * context->clock_inc / 6)) {
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 context->status &= 0x7F;
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
389 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
390 }
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
391 //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
392 }
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
393
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
394 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
395 {
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
396 //printf("address_write_part1: %X\n", address);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
397 context->selected_reg = address;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
398 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
399 }
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
400
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
401 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
402 {
364
62177cc39049 Incredibly broken YM2612 support plus a fix to Z80 bus request
Mike Pavone <pavone@retrodev.com>
parents: 362
diff changeset
403 //printf("address_write_part2: %X\n", address);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
404 context->selected_reg = address;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
405 context->selected_part = 1;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
406 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
407
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
408 uint8_t fnum_to_keycode[] = {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
409 //F11 = 0
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
410 0,0,0,0,0,0,0,1,
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
411 //F11 = 1
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
412 2,3,3,3,3,3,3,3
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
413 };
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
414
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
415 //table courtesy of Nemesis
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
416 uint32_t detune_table[][4] = {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
417 {0, 0, 1, 2}, //0 (0x00)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
418 {0, 0, 1, 2}, //1 (0x01)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
419 {0, 0, 1, 2}, //2 (0x02)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
420 {0, 0, 1, 2}, //3 (0x03)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
421 {0, 1, 2, 2}, //4 (0x04)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
422 {0, 1, 2, 3}, //5 (0x05)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
423 {0, 1, 2, 3}, //6 (0x06)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
424 {0, 1, 2, 3}, //7 (0x07)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
425 {0, 1, 2, 4}, //8 (0x08)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
426 {0, 1, 3, 4}, //9 (0x09)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
427 {0, 1, 3, 4}, //10 (0x0A)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
428 {0, 1, 3, 5}, //11 (0x0B)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
429 {0, 2, 4, 5}, //12 (0x0C)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
430 {0, 2, 4, 6}, //13 (0x0D)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
431 {0, 2, 4, 6}, //14 (0x0E)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
432 {0, 2, 5, 7}, //15 (0x0F)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
433 {0, 2, 5, 8}, //16 (0x10)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
434 {0, 3, 6, 8}, //17 (0x11)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
435 {0, 3, 6, 9}, //18 (0x12)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
436 {0, 3, 7,10}, //19 (0x13)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
437 {0, 4, 8,11}, //20 (0x14)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
438 {0, 4, 8,12}, //21 (0x15)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
439 {0, 4, 9,13}, //22 (0x16)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
440 {0, 5,10,14}, //23 (0x17)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
441 {0, 5,11,16}, //24 (0x18)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
442 {0, 6,12,17}, //25 (0x19)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
443 {0, 6,13,19}, //26 (0x1A)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
444 {0, 7,14,20}, //27 (0x1B)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
445 {0, 8,16,22}, //28 (0x1C)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
446 {0, 8,16,22}, //29 (0x1D)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
447 {0, 8,16,22}, //30 (0x1E)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
448 {0, 8,16,22}
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
449 }; //31 (0x1F)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
450
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
451 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
452 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
453 uint32_t chan_num = op / 4;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
454 //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
455 //base frequency
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
456 ym_channel * channel = context->channels + chan_num;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
457 uint32_t inc = channel->fnum;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
458 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
459 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
460 } else {
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
461 inc <<= (channel->block-1);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
462 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
463 //detune
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
464 uint32_t detune = detune_table[channel->keycode][operator->detune & 0x3];
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
465 if (operator->detune & 0x40) {
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 //this can underflow, mask to 17-bit result
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
468 inc &= 0x1FFFF;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
469 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
470 inc += detune;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
471 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
472 //multiple
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
473 if (operator->multiple) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
474 inc *= operator->multiple;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
475 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
476 //0.5
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
477 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
478 }
365
3ba3b6656fff Actually save the shifted phase inc after applying the block shift
Mike Pavone <pavone@retrodev.com>
parents: 364
diff changeset
479 //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
480 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
481 }
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
482
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 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
484 {
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
485 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
486 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
487 }
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
488 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
489 if (context->selected_reg < 0x30) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
490 //Shared regs
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
491 switch (context->selected_reg)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
492 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
493 //TODO: Test reg and LFO
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
494 case REG_TIMERA_HIGH:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
495 context->timer_a_load &= 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
496 context->timer_a_load |= value << 2;
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_TIMERA_LOW:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
499 context->timer_a_load &= 0xFFFC;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
500 context->timer_a_load |= value & 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
501 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
502 case REG_TIMERB:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
503 context->timer_b_load = value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
504 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
505 case REG_TIME_CTRL:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
506 context->timer_control = value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
507 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
508 case REG_KEY_ONOFF: {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
509 uint8_t channel = value & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
510 if (channel < NUM_CHANNELS) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
511 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
512 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
513 first_key_on = 1;
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
514 //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
515 context->operators[op].phase_counter = 0;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
516 context->operators[op].env_phase = PHASE_ATTACK;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
517 context->operators[op].envelope = MAX_ENVELOPE;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
518 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
519 //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
520 context->operators[op].env_phase = PHASE_RELEASE;
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 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
523 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
524 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
525 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
526 case REG_DAC:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
527 if (context->dac_enable) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
528 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
529 //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
530 }
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 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
533 //printf("DAC Enable: %X\n", value);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
534 context->dac_enable = value & 0x80;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
535 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
536 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
537 } else if (context->selected_reg < 0xA0) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
538 //part
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
539 uint8_t op = context->selected_part ? (NUM_OPERATORS/2) : 0;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
540 //channel in part
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
541 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
542 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
543 //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
544 ym_operator * operator = context->operators + op;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
545 switch (context->selected_reg & 0xF0)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
546 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
547 case REG_DETUNE_MULT:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
548 operator->detune = value >> 4 & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
549 operator->multiple = value & 0xF;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
550 ym_update_phase_inc(context, operator, op);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
551 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
552 case REG_TOTAL_LEVEL:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
553 operator->total_level = (value & 0x7F) << 5;
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_ATTACK_KS:
376
f6def5cdf1b4 Fix key scaling
Mike Pavone <pavone@retrodev.com>
parents: 374
diff changeset
556 operator->key_scaling = 3 - (value >> 6);
362
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
557 operator->rates[PHASE_ATTACK] = 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_DECAY_AM:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
560 //TODO: AM flag for LFO
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
561 operator->rates[PHASE_DECAY] = value & 0x1F;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
562 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
563 case REG_SUSTAIN_RATE:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
564 operator->rates[PHASE_SUSTAIN] = value & 0x1F;
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 case REG_S_LVL_R_RATE:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
567 operator->rates[PHASE_RELEASE] = (value & 0xF) << 1 | 1;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
568 operator->sustain_level = value & 0xF0 << 4;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
569 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
570 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
571 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
572 } else {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
573 uint8_t channel = context->selected_reg & 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
574 if (channel != 3) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
575 if (context->selected_part) {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
576 channel += 3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
577 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
578 //printf("write targets channel %d\n", channel);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
579 switch (context->selected_reg & 0xFC)
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
580 {
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
581 case REG_FNUM_LOW:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
582 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
583 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
584 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
585 ym_update_phase_inc(context, context->operators + channel*4, channel*4);
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
586 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
587 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
588 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
589 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
590 case REG_BLOCK_FNUM_H:{
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
591 context->channels[channel].block_fnum_latch = value;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
592 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
593 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
594 //TODO: Channel 3 special/CSM modes
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
595 case REG_ALG_FEEDBACK:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
596 context->channels[channel].algorithm = value & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
597 context->channels[channel].feedback = value >> 3 & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
598 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
599 case REG_LR_AMS_PMS:
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
600 context->channels[channel].pms = value & 0x7;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
601 context->channels[channel].ams = value >> 4 & 0x3;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
602 context->channels[channel].lr = value & 0xC0;
369
fc820ab1394b Fix left/right enable default value
Mike Pavone <pavone@retrodev.com>
parents: 365
diff changeset
603 //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
604 break;
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
605 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
606 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
607 }
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
608
b7c3facee762 YM2612 WIP update
Mike Pavone <pavone@retrodev.com>
parents: 359
diff changeset
609 context->write_cycle = context->current_cycle;
374
d42a8a3e4894 Fix YM2612 busy flag
Mike Pavone <pavone@retrodev.com>
parents: 371
diff changeset
610 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
611 }
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 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
614 {
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
615 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
616 }
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
617