annotate ym2612.c @ 359:cc39629e8d06

YM2612 WIP snapshot before register refactor
author Mike Pavone <pavone@retrodev.com>
date Mon, 27 May 2013 09:54:58 -0700
parents a8ee7934a1f8
children b7c3facee762
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>
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
4 #include "ym2612.h"
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
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
6 #define BUSY_CYCLES 17
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 #define TIMERA_UPDATE_PERIOD 144
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
8
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
9 #define REG_TIMERA_HIGH 0x03 // 0x24
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
10 #define REG_TIMERA_LOW 0x04 // 0x25
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
11 #define REG_TIMERB 0x05 // 0x26
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
12 #define REG_TIME_CTRL 0x06 // 0x27
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
13 #define REG_DAC 0x0A // 0x2A
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
14 #define REG_DAC_ENABLE 0x0B // 0x2B
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
15
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
16 //offset to add to "shared" regs when looking for them in Part I
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
17 #define REG_SHARED 0x10
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
18
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
19
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
20 #define REG_ALG_FEEDBACK (0xB0-0x30)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
21 #define REG_ATTACK_KS (0x50-0x30)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
22 #define REG_DECAY_AM (0x60-0x30)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
23 #define REG_SUSTAIN_RATE (0x70-0x30)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
24
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
25
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
26 #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
27 #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
28 #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
29 #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
30 #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
31 #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
32
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
33 #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
34 #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
35
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
36 enum {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
37 PHASE_ATTACK,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
38 PHASE_DECAY,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
39 PHASE_SUSTAIN,
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
40 PHASE_RELEASE
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
41 };
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
42
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
43 uint8_t did_tbl_init = 0;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
44 //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
45 //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
46 //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
47 #define SINE_TABLE_SIZE 512
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
48 uint16_t sine_table[SINE_TABLE_SIZE];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
49 //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
50 //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
51 //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
52 #define POW_TABLE_SIZE (1 << 13)
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
53 uint16_t pow_table[POW_TABLE_SIZE];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
54
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
55
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
56 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
57 {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
58 return value * (1 << dec_bits) + 0.5;
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
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
61 void ym_init(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
62 {
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
63 memset(context, 0, sizeof(*context));
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
64 if (!did_tbl_init) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
65 //populate sine table
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
66 for (int32_t i = 0; i < 512; i++) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
67 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
68
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
69 //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
70 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
71 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
72 //populate power table
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
73 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
74 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
75 int32_t tmp = round_fixed_point(linear, 11);
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
76 int32_t shift = (i >> 8) - 2;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
77 if (shift < 0) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
78 tmp <<= 0-shift;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
79 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
80 tmp >>= shift;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
81 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
82 pow_table[i] = tmp;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
83 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
84 }
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
85 }
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
86
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
87 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
88 {
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
89 for (; context->current_cycle < to_cycle; context->current_cycle += 6) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
90 uint32_t update_cyc = context->current_cycle % 144;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
91 //Update timers at beginning of 144 cycle period
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
92 if (!update_cyc && context->part1_regs[REG_TIME_CTRL] & BIT_TIMERA_ENABLE) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
93 if (context->timer_a) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
94 context->timer_a--;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
95 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
96 if (context->part1_regs[REG_TIME_CTRL] & BIT_TIMERA_OVEREN) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
97 context->status |= BIT_STATUS_TIMERA;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
98 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
99 context->timer_a = (context->part1_regs[REG_TIMERA_HIGH] << 2) | (context->part1_regs[REG_TIMERA_LOW] & 0x3);
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
100 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
101 if (context->part1_regs[REG_TIME_CTRL] & BIT_TIMERB_ENABLE) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
102 uint32_t b_cyc = (context->current_cycle / 144) % 16;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
103 if (!b_cyc) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
104 if (context->timer_b) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
105 context->timer_b--;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
106 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
107 if (context->part1_regs[REG_TIME_CTRL] & BIT_TIMERB_OVEREN) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
108 context->status |= BIT_STATUS_TIMERB;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
109 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
110 context->timer_b = context->part1_regs[REG_TIMERB];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
111 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
112 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
113 }
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
114 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
115 //Update Envelope Generator
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
116 if (update_cyc == 0 || update_cyc == 72) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
117 uint32_t env_cyc = context->current_cycle / 72;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
118 uint32_t op = env_cyc % 24;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
119 env_cyc /= 24;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
120 uint8_t rate;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
121 switch(context->env_phase[op])
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 case PHASE_ATTACK:
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
124 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_ATTACK_KS + op] : context->part2_regs[REG_ATTACK_KS + op - 3]) & 0x1F;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
125 break;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
126 case PHASE_DECAY:
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
127 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_DECAY_AM + op] : context->part2_regs[REG_DECAY_AM + op - 3]) & 0x1F;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
128 break;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
129 case PHASE_SUSTAIN:
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
130 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_SUSTAIN_RATE + op] : context->part2_regs[REG_SUSTAIN_RATE + op - 3]) & 0x1F;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
131 break;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
132 case PHASE_RELEASE:
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
133 rate = (op < 3 ? context->part1_regs[REG_SHARED + REG_DECAY_AM + op] : context->part2_regs[REG_DECAY_AM + op - 3]) << 1 & 0x1E | 1;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
134 break;
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 if (rate) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
137 //apply key scaling
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
138 uint8_t shift = (op < 3 ?
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
139 context->part1_regs[REG_SHARED + REG_ATTACK_KS + op] :
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
140 context->part2_regs[REG_ATTACK_KS + op - 3]
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
141 ) >> 6;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
142 uint8_t ks = context->keycode[op] >> (3 - shift);
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
143 rate = rate*2 + ks;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
144 if (rate > 63) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
145 rate = 63;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
146 }
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
147 }
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
148 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
149 //Update Phase Generator
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
150 uint32_t channel = update_cyc / 24;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
151 if (channel != 6 || !(context->part1_regs[REG_DAC_ENABLE] & 0x80)) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
152 uint32_t op = (update_cyc) / 6;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
153 uint8_t alg;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
154 if (op < 3) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
155 alg = context->part1_regs[REG_SHARED + REG_ALG_FEEDBACK + op] & 0x7;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
156 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
157 alg = context->part2_regs[REG_ALG_FEEDBACK + op-3] & 0x7;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
158 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
159 context->phase_counter[op] += context->phase_inc[op];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
160 uint16_t phase = context->phase_counter[op] >> 10 & 0x3FF;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
161 //TODO: Modulate phase if necessary
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
162 uint16_t output = pow_table[sine_table[phase & 0x1FF] + context->envelope[op]];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
163 if (phase & 0x200) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
164 output = -output;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
165 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
166 context->op_out[op] = output;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
167 //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
168 if (op % 4 == 3) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
169 if (alg < 4) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
170 context->channel_out[channel] = context->op_out[channel * 4 + 3];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
171 } else if(alg == 4) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
172 context->channel_out[channel] = context->op_out[channel * 4 + 3] + context->op_out[channel * 4 + 1];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
173 } else {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
174 output = 0;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
175 for (uint32_t op = ((alg == 7) ? 0 : 1) + channel*4; op < (channel+1)*4; op++) {
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
176 output += context->op_out[op];
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
177 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
178 context->channel_out[channel] = output;
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
179 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
180 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
181 }
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
182
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
183 }
359
cc39629e8d06 YM2612 WIP snapshot before register refactor
Mike Pavone <pavone@retrodev.com>
parents: 288
diff changeset
184 if (context->current_cycle >= context->write_cycle + BUSY_CYCLES) {
288
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
185 context->status &= 0x7F;
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
186 }
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
187 }
a8ee7934a1f8 Add a YM2612 stub implementation with just timers and status registers so that games that depend on it can run.
Mike Pavone <pavone@retrodev.com>
parents:
diff changeset
188
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
189 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
190 {
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
191 if (address >= 0x21 && address < 0xB7) {
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
192 context->selected_reg = context->part1_regs + address - 0x21;
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
193 } else {
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
194 context->selected_reg = NULL;
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
195 }
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
196 }
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
197
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
198 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
199 {
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
200 if (address >= 0x30 && address < 0xB7) {
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
201 context->selected_reg = context->part1_regs + address - 0x30;
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
202 } else {
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
203 context->selected_reg = NULL;
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
204 }
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
205 }
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
206
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
207 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
208 {
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
209 if (context->selected_reg && !(context->status & 0x80)) {
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
210 *context->selected_reg = 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
211 context->write_cycle = context->current_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
212 context->selected_reg = NULL;//TODO: Verify this
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
213 }
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
214 }
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
215
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
216 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
217 {
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
218 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
219 }
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
220