1 // license:BSD-3-Clause
2 // copyright-holders:R. Belmont
3 /*
4 vboy.c - Virtual Boy audio emulation
5
6 By Richard Bannister and Gil Pedersen.
7 MESS device adaptation by R. Belmont
8 */
9
10 #include "emu.h"
11 #include "vboy.h"
12
13 // device type definition
14 DEFINE_DEVICE_TYPE(VBOYSND, vboysnd_device, "vboysnd", "Virtual Boy Audio")
15
16 //#define LAME_COMPILER_BUG
17
18 #define SxINT 0x00
19 #define SxLRV 0x04
20 #define SxFQL 0x08
21 #define SxFQH 0x0c
22 #define SxEV0 0x10
23 #define SxEV1 0x14
24 #define SxRAM 0x18
25
26 #define SxINTb 0x400+SxINT
27 #define SxLRVb 0x400+SxLRV
28 #define SxFQLb 0x400+SxFQL
29 #define SxFQHb 0x400+SxFQH
30 #define SxEV0b 0x400+SxEV0
31 #define SxEV1b 0x400+SxEV1
32 #define SxRAMb 0x400+SxRAM
33
34 #define S5SWP 0x51c
35 #define SST0P 0x580
36
37 static const uint16_t outTbl[64][32] = {
38 { 0x0000, 0xffe0, 0xffc0, 0xffa0, 0xff80, 0xff60, 0xff40, 0xff20, 0xff00, 0xfee0, 0xfec0, 0xfea0, 0xfe80, 0xfe60, 0xfe40, 0xfe20,
39 0xfe00, 0xfde0, 0xfdc0, 0xfda0, 0xfd80, 0xfd60, 0xfd40, 0xfd20, 0xfd00, 0xfce0, 0xfcc0, 0xfca0, 0xfc80, 0xfc60, 0xfc40, 0xfc20},
40 { 0x0000, 0xffe1, 0xffc2, 0xffa3, 0xff84, 0xff65, 0xff46, 0xff27, 0xff08, 0xfee9, 0xfeca, 0xfeab, 0xfe8c, 0xfe6d, 0xfe4e, 0xfe2f,
41 0xfe10, 0xfdf1, 0xfdd2, 0xfdb3, 0xfd94, 0xfd75, 0xfd56, 0xfd37, 0xfd18, 0xfcf9, 0xfcda, 0xfcbb, 0xfc9c, 0xfc7d, 0xfc5e, 0xfc3f},
42 { 0x0000, 0xffe2, 0xffc4, 0xffa6, 0xff88, 0xff6a, 0xff4c, 0xff2e, 0xff10, 0xfef2, 0xfed4, 0xfeb6, 0xfe98, 0xfe7a, 0xfe5c, 0xfe3e,
43 0xfe20, 0xfe02, 0xfde4, 0xfdc6, 0xfda8, 0xfd8a, 0xfd6c, 0xfd4e, 0xfd30, 0xfd12, 0xfcf4, 0xfcd6, 0xfcb8, 0xfc9a, 0xfc7c, 0xfc5e},
44 { 0x0000, 0xffe3, 0xffc6, 0xffa9, 0xff8c, 0xff6f, 0xff52, 0xff35, 0xff18, 0xfefb, 0xfede, 0xfec1, 0xfea4, 0xfe87, 0xfe6a, 0xfe4d,
45 0xfe30, 0xfe13, 0xfdf6, 0xfdd9, 0xfdbc, 0xfd9f, 0xfd82, 0xfd65, 0xfd48, 0xfd2b, 0xfd0e, 0xfcf1, 0xfcd4, 0xfcb7, 0xfc9a, 0xfc7d},
46 { 0x0000, 0xffe4, 0xffc8, 0xffac, 0xff90, 0xff74, 0xff58, 0xff3c, 0xff20, 0xff04, 0xfee8, 0xfecc, 0xfeb0, 0xfe94, 0xfe78, 0xfe5c,
47 0xfe40, 0xfe24, 0xfe08, 0xfdec, 0xfdd0, 0xfdb4, 0xfd98, 0xfd7c, 0xfd60, 0xfd44, 0xfd28, 0xfd0c, 0xfcf0, 0xfcd4, 0xfcb8, 0xfc9c},
48 { 0x0000, 0xffe5, 0xffca, 0xffaf, 0xff94, 0xff79, 0xff5e, 0xff43, 0xff28, 0xff0d, 0xfef2, 0xfed7, 0xfebc, 0xfea1, 0xfe86, 0xfe6b,
49 0xfe50, 0xfe35, 0xfe1a, 0xfdff, 0xfde4, 0xfdc9, 0xfdae, 0xfd93, 0xfd78, 0xfd5d, 0xfd42, 0xfd27, 0xfd0c, 0xfcf1, 0xfcd6, 0xfcbb},
50 { 0x0000, 0xffe6, 0xffcc, 0xffb2, 0xff98, 0xff7e, 0xff64, 0xff4a, 0xff30, 0xff16, 0xfefc, 0xfee2, 0xfec8, 0xfeae, 0xfe94, 0xfe7a,
51 0xfe60, 0xfe46, 0xfe2c, 0xfe12, 0xfdf8, 0xfdde, 0xfdc4, 0xfdaa, 0xfd90, 0xfd76, 0xfd5c, 0xfd42, 0xfd28, 0xfd0e, 0xfcf4, 0xfcda},
52 { 0x0000, 0xffe7, 0xffce, 0xffb5, 0xff9c, 0xff83, 0xff6a, 0xff51, 0xff38, 0xff1f, 0xff06, 0xfeed, 0xfed4, 0xfebb, 0xfea2, 0xfe89,
53 0xfe70, 0xfe57, 0xfe3e, 0xfe25, 0xfe0c, 0xfdf3, 0xfdda, 0xfdc1, 0xfda8, 0xfd8f, 0xfd76, 0xfd5d, 0xfd44, 0xfd2b, 0xfd12, 0xfcf9},
54 { 0x0000, 0xffe8, 0xffd0, 0xffb8, 0xffa0, 0xff88, 0xff70, 0xff58, 0xff40, 0xff28, 0xff10, 0xfef8, 0xfee0, 0xfec8, 0xfeb0, 0xfe98,
55 0xfe80, 0xfe68, 0xfe50, 0xfe38, 0xfe20, 0xfe08, 0xfdf0, 0xfdd8, 0xfdc0, 0xfda8, 0xfd90, 0xfd78, 0xfd60, 0xfd48, 0xfd30, 0xfd18},
56 { 0x0000, 0xffe9, 0xffd2, 0xffbb, 0xffa4, 0xff8d, 0xff76, 0xff5f, 0xff48, 0xff31, 0xff1a, 0xff03, 0xfeec, 0xfed5, 0xfebe, 0xfea7,
57 0xfe90, 0xfe79, 0xfe62, 0xfe4b, 0xfe34, 0xfe1d, 0xfe06, 0xfdef, 0xfdd8, 0xfdc1, 0xfdaa, 0xfd93, 0xfd7c, 0xfd65, 0xfd4e, 0xfd37},
58 { 0x0000, 0xffea, 0xffd4, 0xffbe, 0xffa8, 0xff92, 0xff7c, 0xff66, 0xff50, 0xff3a, 0xff24, 0xff0e, 0xfef8, 0xfee2, 0xfecc, 0xfeb6,
59 0xfea0, 0xfe8a, 0xfe74, 0xfe5e, 0xfe48, 0xfe32, 0xfe1c, 0xfe06, 0xfdf0, 0xfdda, 0xfdc4, 0xfdae, 0xfd98, 0xfd82, 0xfd6c, 0xfd56},
60 { 0x0000, 0xffeb, 0xffd6, 0xffc1, 0xffac, 0xff97, 0xff82, 0xff6d, 0xff58, 0xff43, 0xff2e, 0xff19, 0xff04, 0xfeef, 0xfeda, 0xfec5,
61 0xfeb0, 0xfe9b, 0xfe86, 0xfe71, 0xfe5c, 0xfe47, 0xfe32, 0xfe1d, 0xfe08, 0xfdf3, 0xfdde, 0xfdc9, 0xfdb4, 0xfd9f, 0xfd8a, 0xfd75},
62 { 0x0000, 0xffec, 0xffd8, 0xffc4, 0xffb0, 0xff9c, 0xff88, 0xff74, 0xff60, 0xff4c, 0xff38, 0xff24, 0xff10, 0xfefc, 0xfee8, 0xfed4,
63 0xfec0, 0xfeac, 0xfe98, 0xfe84, 0xfe70, 0xfe5c, 0xfe48, 0xfe34, 0xfe20, 0xfe0c, 0xfdf8, 0xfde4, 0xfdd0, 0xfdbc, 0xfda8, 0xfd94},
64 { 0x0000, 0xffed, 0xffda, 0xffc7, 0xffb4, 0xffa1, 0xff8e, 0xff7b, 0xff68, 0xff55, 0xff42, 0xff2f, 0xff1c, 0xff09, 0xfef6, 0xfee3,
65 0xfed0, 0xfebd, 0xfeaa, 0xfe97, 0xfe84, 0xfe71, 0xfe5e, 0xfe4b, 0xfe38, 0xfe25, 0xfe12, 0xfdff, 0xfdec, 0xfdd9, 0xfdc6, 0xfdb3},
66 { 0x0000, 0xffee, 0xffdc, 0xffca, 0xffb8, 0xffa6, 0xff94, 0xff82, 0xff70, 0xff5e, 0xff4c, 0xff3a, 0xff28, 0xff16, 0xff04, 0xfef2,
67 0xfee0, 0xfece, 0xfebc, 0xfeaa, 0xfe98, 0xfe86, 0xfe74, 0xfe62, 0xfe50, 0xfe3e, 0xfe2c, 0xfe1a, 0xfe08, 0xfdf6, 0xfde4, 0xfdd2},
68 { 0x0000, 0xffef, 0xffde, 0xffcd, 0xffbc, 0xffab, 0xff9a, 0xff89, 0xff78, 0xff67, 0xff56, 0xff45, 0xff34, 0xff23, 0xff12, 0xff01,
69 0xfef0, 0xfedf, 0xfece, 0xfebd, 0xfeac, 0xfe9b, 0xfe8a, 0xfe79, 0xfe68, 0xfe57, 0xfe46, 0xfe35, 0xfe24, 0xfe13, 0xfe02, 0xfdf1},
70 { 0x0000, 0xfff0, 0xffe0, 0xffd0, 0xffc0, 0xffb0, 0xffa0, 0xff90, 0xff80, 0xff70, 0xff60, 0xff50, 0xff40, 0xff30, 0xff20, 0xff10,
71 0xff00, 0xfef0, 0xfee0, 0xfed0, 0xfec0, 0xfeb0, 0xfea0, 0xfe90, 0xfe80, 0xfe70, 0xfe60, 0xfe50, 0xfe40, 0xfe30, 0xfe20, 0xfe10},
72 { 0x0000, 0xfff1, 0xffe2, 0xffd3, 0xffc4, 0xffb5, 0xffa6, 0xff97, 0xff88, 0xff79, 0xff6a, 0xff5b, 0xff4c, 0xff3d, 0xff2e, 0xff1f,
73 0xff10, 0xff01, 0xfef2, 0xfee3, 0xfed4, 0xfec5, 0xfeb6, 0xfea7, 0xfe98, 0xfe89, 0xfe7a, 0xfe6b, 0xfe5c, 0xfe4d, 0xfe3e, 0xfe2f},
74 { 0x0000, 0xfff2, 0xffe4, 0xffd6, 0xffc8, 0xffba, 0xffac, 0xff9e, 0xff90, 0xff82, 0xff74, 0xff66, 0xff58, 0xff4a, 0xff3c, 0xff2e,
75 0xff20, 0xff12, 0xff04, 0xfef6, 0xfee8, 0xfeda, 0xfecc, 0xfebe, 0xfeb0, 0xfea2, 0xfe94, 0xfe86, 0xfe78, 0xfe6a, 0xfe5c, 0xfe4e},
76 { 0x0000, 0xfff3, 0xffe6, 0xffd9, 0xffcc, 0xffbf, 0xffb2, 0xffa5, 0xff98, 0xff8b, 0xff7e, 0xff71, 0xff64, 0xff57, 0xff4a, 0xff3d,
77 0xff30, 0xff23, 0xff16, 0xff09, 0xfefc, 0xfeef, 0xfee2, 0xfed5, 0xfec8, 0xfebb, 0xfeae, 0xfea1, 0xfe94, 0xfe87, 0xfe7a, 0xfe6d},
78 { 0x0000, 0xfff4, 0xffe8, 0xffdc, 0xffd0, 0xffc4, 0xffb8, 0xffac, 0xffa0, 0xff94, 0xff88, 0xff7c, 0xff70, 0xff64, 0xff58, 0xff4c,
79 0xff40, 0xff34, 0xff28, 0xff1c, 0xff10, 0xff04, 0xfef8, 0xfeec, 0xfee0, 0xfed4, 0xfec8, 0xfebc, 0xfeb0, 0xfea4, 0xfe98, 0xfe8c},
80 { 0x0000, 0xfff5, 0xffea, 0xffdf, 0xffd4, 0xffc9, 0xffbe, 0xffb3, 0xffa8, 0xff9d, 0xff92, 0xff87, 0xff7c, 0xff71, 0xff66, 0xff5b,
81 0xff50, 0xff45, 0xff3a, 0xff2f, 0xff24, 0xff19, 0xff0e, 0xff03, 0xfef8, 0xfeed, 0xfee2, 0xfed7, 0xfecc, 0xfec1, 0xfeb6, 0xfeab},
82 { 0x0000, 0xfff6, 0xffec, 0xffe2, 0xffd8, 0xffce, 0xffc4, 0xffba, 0xffb0, 0xffa6, 0xff9c, 0xff92, 0xff88, 0xff7e, 0xff74, 0xff6a,
83 0xff60, 0xff56, 0xff4c, 0xff42, 0xff38, 0xff2e, 0xff24, 0xff1a, 0xff10, 0xff06, 0xfefc, 0xfef2, 0xfee8, 0xfede, 0xfed4, 0xfeca},
84 { 0x0000, 0xfff7, 0xffee, 0xffe5, 0xffdc, 0xffd3, 0xffca, 0xffc1, 0xffb8, 0xffaf, 0xffa6, 0xff9d, 0xff94, 0xff8b, 0xff82, 0xff79,
85 0xff70, 0xff67, 0xff5e, 0xff55, 0xff4c, 0xff43, 0xff3a, 0xff31, 0xff28, 0xff1f, 0xff16, 0xff0d, 0xff04, 0xfefb, 0xfef2, 0xfee9},
86 { 0x0000, 0xfff8, 0xfff0, 0xffe8, 0xffe0, 0xffd8, 0xffd0, 0xffc8, 0xffc0, 0xffb8, 0xffb0, 0xffa8, 0xffa0, 0xff98, 0xff90, 0xff88,
87 0xff80, 0xff78, 0xff70, 0xff68, 0xff60, 0xff58, 0xff50, 0xff48, 0xff40, 0xff38, 0xff30, 0xff28, 0xff20, 0xff18, 0xff10, 0xff08},
88 { 0x0000, 0xfff9, 0xfff2, 0xffeb, 0xffe4, 0xffdd, 0xffd6, 0xffcf, 0xffc8, 0xffc1, 0xffba, 0xffb3, 0xffac, 0xffa5, 0xff9e, 0xff97,
89 0xff90, 0xff89, 0xff82, 0xff7b, 0xff74, 0xff6d, 0xff66, 0xff5f, 0xff58, 0xff51, 0xff4a, 0xff43, 0xff3c, 0xff35, 0xff2e, 0xff27},
90 { 0x0000, 0xfffa, 0xfff4, 0xffee, 0xffe8, 0xffe2, 0xffdc, 0xffd6, 0xffd0, 0xffca, 0xffc4, 0xffbe, 0xffb8, 0xffb2, 0xffac, 0xffa6,
91 0xffa0, 0xff9a, 0xff94, 0xff8e, 0xff88, 0xff82, 0xff7c, 0xff76, 0xff70, 0xff6a, 0xff64, 0xff5e, 0xff58, 0xff52, 0xff4c, 0xff46},
92 { 0x0000, 0xfffb, 0xfff6, 0xfff1, 0xffec, 0xffe7, 0xffe2, 0xffdd, 0xffd8, 0xffd3, 0xffce, 0xffc9, 0xffc4, 0xffbf, 0xffba, 0xffb5,
93 0xffb0, 0xffab, 0xffa6, 0xffa1, 0xff9c, 0xff97, 0xff92, 0xff8d, 0xff88, 0xff83, 0xff7e, 0xff79, 0xff74, 0xff6f, 0xff6a, 0xff65},
94 { 0x0000, 0xfffc, 0xfff8, 0xfff4, 0xfff0, 0xffec, 0xffe8, 0xffe4, 0xffe0, 0xffdc, 0xffd8, 0xffd4, 0xffd0, 0xffcc, 0xffc8, 0xffc4,
95 0xffc0, 0xffbc, 0xffb8, 0xffb4, 0xffb0, 0xffac, 0xffa8, 0xffa4, 0xffa0, 0xff9c, 0xff98, 0xff94, 0xff90, 0xff8c, 0xff88, 0xff84},
96 { 0x0000, 0xfffd, 0xfffa, 0xfff7, 0xfff4, 0xfff1, 0xffee, 0xffeb, 0xffe8, 0xffe5, 0xffe2, 0xffdf, 0xffdc, 0xffd9, 0xffd6, 0xffd3,
97 0xffd0, 0xffcd, 0xffca, 0xffc7, 0xffc4, 0xffc1, 0xffbe, 0xffbb, 0xffb8, 0xffb5, 0xffb2, 0xffaf, 0xffac, 0xffa9, 0xffa6, 0xffa3},
98 { 0x0000, 0xfffe, 0xfffc, 0xfffa, 0xfff8, 0xfff6, 0xfff4, 0xfff2, 0xfff0, 0xffee, 0xffec, 0xffea, 0xffe8, 0xffe6, 0xffe4, 0xffe2,
99 0xffe0, 0xffde, 0xffdc, 0xffda, 0xffd8, 0xffd6, 0xffd4, 0xffd2, 0xffd0, 0xffce, 0xffcc, 0xffca, 0xffc8, 0xffc6, 0xffc4, 0xffc2},
100 { 0x0000, 0xffff, 0xfffe, 0xfffd, 0xfffc, 0xfffb, 0xfffa, 0xfff9, 0xfff8, 0xfff7, 0xfff6, 0xfff5, 0xfff4, 0xfff3, 0xfff2, 0xfff1,
101 0xfff0, 0xffef, 0xffee, 0xffed, 0xffec, 0xffeb, 0xffea, 0xffe9, 0xffe8, 0xffe7, 0xffe6, 0xffe5, 0xffe4, 0xffe3, 0xffe2, 0xffe1},
102 { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
103 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
104 { 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
105 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017, 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f},
106 { 0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e, 0x0010, 0x0012, 0x0014, 0x0016, 0x0018, 0x001a, 0x001c, 0x001e,
107 0x0020, 0x0022, 0x0024, 0x0026, 0x0028, 0x002a, 0x002c, 0x002e, 0x0030, 0x0032, 0x0034, 0x0036, 0x0038, 0x003a, 0x003c, 0x003e},
108 { 0x0000, 0x0003, 0x0006, 0x0009, 0x000c, 0x000f, 0x0012, 0x0015, 0x0018, 0x001b, 0x001e, 0x0021, 0x0024, 0x0027, 0x002a, 0x002d,
109 0x0030, 0x0033, 0x0036, 0x0039, 0x003c, 0x003f, 0x0042, 0x0045, 0x0048, 0x004b, 0x004e, 0x0051, 0x0054, 0x0057, 0x005a, 0x005d},
110 { 0x0000, 0x0004, 0x0008, 0x000c, 0x0010, 0x0014, 0x0018, 0x001c, 0x0020, 0x0024, 0x0028, 0x002c, 0x0030, 0x0034, 0x0038, 0x003c,
111 0x0040, 0x0044, 0x0048, 0x004c, 0x0050, 0x0054, 0x0058, 0x005c, 0x0060, 0x0064, 0x0068, 0x006c, 0x0070, 0x0074, 0x0078, 0x007c},
112 { 0x0000, 0x0005, 0x000a, 0x000f, 0x0014, 0x0019, 0x001e, 0x0023, 0x0028, 0x002d, 0x0032, 0x0037, 0x003c, 0x0041, 0x0046, 0x004b,
113 0x0050, 0x0055, 0x005a, 0x005f, 0x0064, 0x0069, 0x006e, 0x0073, 0x0078, 0x007d, 0x0082, 0x0087, 0x008c, 0x0091, 0x0096, 0x009b},
114 { 0x0000, 0x0006, 0x000c, 0x0012, 0x0018, 0x001e, 0x0024, 0x002a, 0x0030, 0x0036, 0x003c, 0x0042, 0x0048, 0x004e, 0x0054, 0x005a,
115 0x0060, 0x0066, 0x006c, 0x0072, 0x0078, 0x007e, 0x0084, 0x008a, 0x0090, 0x0096, 0x009c, 0x00a2, 0x00a8, 0x00ae, 0x00b4, 0x00ba},
116 { 0x0000, 0x0007, 0x000e, 0x0015, 0x001c, 0x0023, 0x002a, 0x0031, 0x0038, 0x003f, 0x0046, 0x004d, 0x0054, 0x005b, 0x0062, 0x0069,
117 0x0070, 0x0077, 0x007e, 0x0085, 0x008c, 0x0093, 0x009a, 0x00a1, 0x00a8, 0x00af, 0x00b6, 0x00bd, 0x00c4, 0x00cb, 0x00d2, 0x00d9},
118 { 0x0000, 0x0008, 0x0010, 0x0018, 0x0020, 0x0028, 0x0030, 0x0038, 0x0040, 0x0048, 0x0050, 0x0058, 0x0060, 0x0068, 0x0070, 0x0078,
119 0x0080, 0x0088, 0x0090, 0x0098, 0x00a0, 0x00a8, 0x00b0, 0x00b8, 0x00c0, 0x00c8, 0x00d0, 0x00d8, 0x00e0, 0x00e8, 0x00f0, 0x00f8},
120 { 0x0000, 0x0009, 0x0012, 0x001b, 0x0024, 0x002d, 0x0036, 0x003f, 0x0048, 0x0051, 0x005a, 0x0063, 0x006c, 0x0075, 0x007e, 0x0087,
121 0x0090, 0x0099, 0x00a2, 0x00ab, 0x00b4, 0x00bd, 0x00c6, 0x00cf, 0x00d8, 0x00e1, 0x00ea, 0x00f3, 0x00fc, 0x0105, 0x010e, 0x0117},
122 { 0x0000, 0x000a, 0x0014, 0x001e, 0x0028, 0x0032, 0x003c, 0x0046, 0x0050, 0x005a, 0x0064, 0x006e, 0x0078, 0x0082, 0x008c, 0x0096,
123 0x00a0, 0x00aa, 0x00b4, 0x00be, 0x00c8, 0x00d2, 0x00dc, 0x00e6, 0x00f0, 0x00fa, 0x0104, 0x010e, 0x0118, 0x0122, 0x012c, 0x0136},
124 { 0x0000, 0x000b, 0x0016, 0x0021, 0x002c, 0x0037, 0x0042, 0x004d, 0x0058, 0x0063, 0x006e, 0x0079, 0x0084, 0x008f, 0x009a, 0x00a5,
125 0x00b0, 0x00bb, 0x00c6, 0x00d1, 0x00dc, 0x00e7, 0x00f2, 0x00fd, 0x0108, 0x0113, 0x011e, 0x0129, 0x0134, 0x013f, 0x014a, 0x0155},
126 { 0x0000, 0x000c, 0x0018, 0x0024, 0x0030, 0x003c, 0x0048, 0x0054, 0x0060, 0x006c, 0x0078, 0x0084, 0x0090, 0x009c, 0x00a8, 0x00b4,
127 0x00c0, 0x00cc, 0x00d8, 0x00e4, 0x00f0, 0x00fc, 0x0108, 0x0114, 0x0120, 0x012c, 0x0138, 0x0144, 0x0150, 0x015c, 0x0168, 0x0174},
128 { 0x0000, 0x000d, 0x001a, 0x0027, 0x0034, 0x0041, 0x004e, 0x005b, 0x0068, 0x0075, 0x0082, 0x008f, 0x009c, 0x00a9, 0x00b6, 0x00c3,
129 0x00d0, 0x00dd, 0x00ea, 0x00f7, 0x0104, 0x0111, 0x011e, 0x012b, 0x0138, 0x0145, 0x0152, 0x015f, 0x016c, 0x0179, 0x0186, 0x0193},
130 { 0x0000, 0x000e, 0x001c, 0x002a, 0x0038, 0x0046, 0x0054, 0x0062, 0x0070, 0x007e, 0x008c, 0x009a, 0x00a8, 0x00b6, 0x00c4, 0x00d2,
131 0x00e0, 0x00ee, 0x00fc, 0x010a, 0x0118, 0x0126, 0x0134, 0x0142, 0x0150, 0x015e, 0x016c, 0x017a, 0x0188, 0x0196, 0x01a4, 0x01b2},
132 { 0x0000, 0x000f, 0x001e, 0x002d, 0x003c, 0x004b, 0x005a, 0x0069, 0x0078, 0x0087, 0x0096, 0x00a5, 0x00b4, 0x00c3, 0x00d2, 0x00e1,
133 0x00f0, 0x00ff, 0x010e, 0x011d, 0x012c, 0x013b, 0x014a, 0x0159, 0x0168, 0x0177, 0x0186, 0x0195, 0x01a4, 0x01b3, 0x01c2, 0x01d1},
134 { 0x0000, 0x0010, 0x0020, 0x0030, 0x0040, 0x0050, 0x0060, 0x0070, 0x0080, 0x0090, 0x00a0, 0x00b0, 0x00c0, 0x00d0, 0x00e0, 0x00f0,
135 0x0100, 0x0110, 0x0120, 0x0130, 0x0140, 0x0150, 0x0160, 0x0170, 0x0180, 0x0190, 0x01a0, 0x01b0, 0x01c0, 0x01d0, 0x01e0, 0x01f0},
136 { 0x0000, 0x0011, 0x0022, 0x0033, 0x0044, 0x0055, 0x0066, 0x0077, 0x0088, 0x0099, 0x00aa, 0x00bb, 0x00cc, 0x00dd, 0x00ee, 0x00ff,
137 0x0110, 0x0121, 0x0132, 0x0143, 0x0154, 0x0165, 0x0176, 0x0187, 0x0198, 0x01a9, 0x01ba, 0x01cb, 0x01dc, 0x01ed, 0x01fe, 0x020f},
138 { 0x0000, 0x0012, 0x0024, 0x0036, 0x0048, 0x005a, 0x006c, 0x007e, 0x0090, 0x00a2, 0x00b4, 0x00c6, 0x00d8, 0x00ea, 0x00fc, 0x010e,
139 0x0120, 0x0132, 0x0144, 0x0156, 0x0168, 0x017a, 0x018c, 0x019e, 0x01b0, 0x01c2, 0x01d4, 0x01e6, 0x01f8, 0x020a, 0x021c, 0x022e},
140 { 0x0000, 0x0013, 0x0026, 0x0039, 0x004c, 0x005f, 0x0072, 0x0085, 0x0098, 0x00ab, 0x00be, 0x00d1, 0x00e4, 0x00f7, 0x010a, 0x011d,
141 0x0130, 0x0143, 0x0156, 0x0169, 0x017c, 0x018f, 0x01a2, 0x01b5, 0x01c8, 0x01db, 0x01ee, 0x0201, 0x0214, 0x0227, 0x023a, 0x024d},
142 { 0x0000, 0x0014, 0x0028, 0x003c, 0x0050, 0x0064, 0x0078, 0x008c, 0x00a0, 0x00b4, 0x00c8, 0x00dc, 0x00f0, 0x0104, 0x0118, 0x012c,
143 0x0140, 0x0154, 0x0168, 0x017c, 0x0190, 0x01a4, 0x01b8, 0x01cc, 0x01e0, 0x01f4, 0x0208, 0x021c, 0x0230, 0x0244, 0x0258, 0x026c},
144 { 0x0000, 0x0015, 0x002a, 0x003f, 0x0054, 0x0069, 0x007e, 0x0093, 0x00a8, 0x00bd, 0x00d2, 0x00e7, 0x00fc, 0x0111, 0x0126, 0x013b,
145 0x0150, 0x0165, 0x017a, 0x018f, 0x01a4, 0x01b9, 0x01ce, 0x01e3, 0x01f8, 0x020d, 0x0222, 0x0237, 0x024c, 0x0261, 0x0276, 0x028b},
146 { 0x0000, 0x0016, 0x002c, 0x0042, 0x0058, 0x006e, 0x0084, 0x009a, 0x00b0, 0x00c6, 0x00dc, 0x00f2, 0x0108, 0x011e, 0x0134, 0x014a,
147 0x0160, 0x0176, 0x018c, 0x01a2, 0x01b8, 0x01ce, 0x01e4, 0x01fa, 0x0210, 0x0226, 0x023c, 0x0252, 0x0268, 0x027e, 0x0294, 0x02aa},
148 { 0x0000, 0x0017, 0x002e, 0x0045, 0x005c, 0x0073, 0x008a, 0x00a1, 0x00b8, 0x00cf, 0x00e6, 0x00fd, 0x0114, 0x012b, 0x0142, 0x0159,
149 0x0170, 0x0187, 0x019e, 0x01b5, 0x01cc, 0x01e3, 0x01fa, 0x0211, 0x0228, 0x023f, 0x0256, 0x026d, 0x0284, 0x029b, 0x02b2, 0x02c9},
150 { 0x0000, 0x0018, 0x0030, 0x0048, 0x0060, 0x0078, 0x0090, 0x00a8, 0x00c0, 0x00d8, 0x00f0, 0x0108, 0x0120, 0x0138, 0x0150, 0x0168,
151 0x0180, 0x0198, 0x01b0, 0x01c8, 0x01e0, 0x01f8, 0x0210, 0x0228, 0x0240, 0x0258, 0x0270, 0x0288, 0x02a0, 0x02b8, 0x02d0, 0x02e8},
152 { 0x0000, 0x0019, 0x0032, 0x004b, 0x0064, 0x007d, 0x0096, 0x00af, 0x00c8, 0x00e1, 0x00fa, 0x0113, 0x012c, 0x0145, 0x015e, 0x0177,
153 0x0190, 0x01a9, 0x01c2, 0x01db, 0x01f4, 0x020d, 0x0226, 0x023f, 0x0258, 0x0271, 0x028a, 0x02a3, 0x02bc, 0x02d5, 0x02ee, 0x0307},
154 { 0x0000, 0x001a, 0x0034, 0x004e, 0x0068, 0x0082, 0x009c, 0x00b6, 0x00d0, 0x00ea, 0x0104, 0x011e, 0x0138, 0x0152, 0x016c, 0x0186,
155 0x01a0, 0x01ba, 0x01d4, 0x01ee, 0x0208, 0x0222, 0x023c, 0x0256, 0x0270, 0x028a, 0x02a4, 0x02be, 0x02d8, 0x02f2, 0x030c, 0x0326},
156 { 0x0000, 0x001b, 0x0036, 0x0051, 0x006c, 0x0087, 0x00a2, 0x00bd, 0x00d8, 0x00f3, 0x010e, 0x0129, 0x0144, 0x015f, 0x017a, 0x0195,
157 0x01b0, 0x01cb, 0x01e6, 0x0201, 0x021c, 0x0237, 0x0252, 0x026d, 0x0288, 0x02a3, 0x02be, 0x02d9, 0x02f4, 0x030f, 0x032a, 0x0345},
158 { 0x0000, 0x001c, 0x0038, 0x0054, 0x0070, 0x008c, 0x00a8, 0x00c4, 0x00e0, 0x00fc, 0x0118, 0x0134, 0x0150, 0x016c, 0x0188, 0x01a4,
159 0x01c0, 0x01dc, 0x01f8, 0x0214, 0x0230, 0x024c, 0x0268, 0x0284, 0x02a0, 0x02bc, 0x02d8, 0x02f4, 0x0310, 0x032c, 0x0348, 0x0364},
160 { 0x0000, 0x001d, 0x003a, 0x0057, 0x0074, 0x0091, 0x00ae, 0x00cb, 0x00e8, 0x0105, 0x0122, 0x013f, 0x015c, 0x0179, 0x0196, 0x01b3,
161 0x01d0, 0x01ed, 0x020a, 0x0227, 0x0244, 0x0261, 0x027e, 0x029b, 0x02b8, 0x02d5, 0x02f2, 0x030f, 0x032c, 0x0349, 0x0366, 0x0383},
162 { 0x0000, 0x001e, 0x003c, 0x005a, 0x0078, 0x0096, 0x00b4, 0x00d2, 0x00f0, 0x010e, 0x012c, 0x014a, 0x0168, 0x0186, 0x01a4, 0x01c2,
163 0x01e0, 0x01fe, 0x021c, 0x023a, 0x0258, 0x0276, 0x0294, 0x02b2, 0x02d0, 0x02ee, 0x030c, 0x032a, 0x0348, 0x0366, 0x0384, 0x03a2},
164 { 0x0000, 0x001f, 0x003e, 0x005d, 0x007c, 0x009b, 0x00ba, 0x00d9, 0x00f8, 0x0117, 0x0136, 0x0155, 0x0174, 0x0193, 0x01b2, 0x01d1,
165 0x01f0, 0x020f, 0x022e, 0x024d, 0x026c, 0x028b, 0x02aa, 0x02c9, 0x02e8, 0x0307, 0x0326, 0x0345, 0x0364, 0x0383, 0x03a2, 0x03c1}
166 };
167
168 static const int8_t outLvlTbl[16][16] = {
169 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
170 { 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2},
171 { 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4},
172 { 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 5, 5, 5, 6, 6},
173 { 0, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8},
174 { 0, 1, 2, 2, 3, 4, 4, 5, 6, 6, 7, 7, 8, 9, 9, 10},
175 { 0, 1, 2, 3, 4, 4, 5, 6, 7, 7, 8, 9, 10, 10, 11, 12},
176 { 0, 1, 2, 3, 4, 5, 6, 7, 7, 7, 8, 10, 11, 12, 13, 14},
177 { 0, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
178 { 0, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 17},
179 { 0, 2, 3, 4, 6, 7, 8, 9, 11, 12, 13, 14, 16, 17, 18, 19},
180 { 0, 2, 3, 5, 6, 7, 9, 10, 12, 13, 14, 16, 17, 18, 20, 21},
181 { 0, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19, 20, 22, 23},
182 { 0, 2, 4, 5, 7, 9, 10, 12, 14, 15, 17, 18, 20, 22, 23, 25},
183 { 0, 2, 4, 6, 8, 9, 11, 13, 15, 16, 18, 20, 22, 23, 25, 27},
184 { 0, 2, 4, 6, 8, 10, 12, 14, 16, 17, 19, 21, 23, 25, 27, 29}
185 };
186
mgetb(uint8_t * ptr)187 static inline uint8_t mgetb(uint8_t *ptr) { return *ptr; }
mputb(uint8_t * ptr,int8_t data)188 static inline void mputb(uint8_t *ptr, int8_t data) { *ptr = data; }
189
190 //**************************************************************************
191 // LIVE DEVICE
192 //**************************************************************************
193
194 //-------------------------------------------------
195 // vboysnd_device - constructor
196 //-------------------------------------------------
197
vboysnd_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)198 vboysnd_device::vboysnd_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
199 : device_t(mconfig, VBOYSND, tag, owner, clock)
200 , device_sound_interface(mconfig, *this)
201 {
202 }
203
204 //-------------------------------------------------
205 // device_start - device-specific startup
206 //-------------------------------------------------
207
device_start()208 void vboysnd_device::device_start()
209 {
210 uint32_t rate = clock() / 120;
211 // create the stream
212 m_stream = stream_alloc(0, 2, rate);
213
214 m_timer = timer_alloc(0, nullptr);
215 m_timer->adjust(attotime::zero, 0, rate ? attotime::from_hz(rate / 4) : attotime::never);
216
217 for (int i=0; i<2048; i++)
218 waveFreq2LenTbl[i] = ((2048 - i) * 32) / 120;
219 for (int i=0; i<32; i++)
220 waveTimer2LenTbl[i] = (i+1) * 120;
221 for (int i=0; i<8; i++)
222 waveEnv2LenTbl[i] = (i + 1) * 4 * 120;
223
224 for (int i = 0; i < 5; i++)
225 memset(&snd_channel[i], 0, sizeof(s_snd_channel));
226
227 memset(m_aram, 0, 0x600);
228 }
229
230
231 //-------------------------------------------------
232 // device_clock_changed
233 //-------------------------------------------------
234
device_clock_changed()235 void vboysnd_device::device_clock_changed()
236 {
237 uint32_t rate = clock() / 120;
238 m_stream->set_sample_rate(rate);
239
240 m_timer->adjust(attotime::zero, 0, rate ? attotime::from_hz(rate / 4) : attotime::never);
241 }
242
243
244 //-------------------------------------------------
245 // device_reset - device-specific reset
246 //-------------------------------------------------
247
device_reset()248 void vboysnd_device::device_reset()
249 {
250 m_stream->update();
251
252 int i;
253
254 for (i=0; i<4; i++)
255 snd_channel[i].playing = false;
256 }
257
258 //-------------------------------------------------
259 // device_timer - called when our device timer expires
260 //-------------------------------------------------
261
device_timer(emu_timer & timer,device_timer_id tid,int param,void * ptr)262 void vboysnd_device::device_timer(emu_timer &timer, device_timer_id tid, int param, void *ptr)
263 {
264 m_stream->update();
265 }
266
267 //-------------------------------------------------
268 // sound_stream_update - handle update requests for
269 // our sound stream
270 //-------------------------------------------------
271
sound_stream_update(sound_stream & stream,std::vector<read_stream_view> const & inputs,std::vector<write_stream_view> & outputs)272 void vboysnd_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
273 {
274 int len, i, j, channel;
275
276 auto &outL = outputs[0];
277 auto &outR = outputs[1];
278
279 len = outL.samples();
280
281 // if (mgetb(m_aram+SST0P) & 0x1) // Sound Stop Reg
282 // goto end;
283
284 for (channel=0; channel<5; channel++)
285 {
286 float size;
287 int k = 0, waveAddr;
288
289 i = channel * 0x40;
290 snd_channel[channel].sample_len = waveFreq2LenTbl[((mgetb(m_aram+SxFQHb+i) & 0x7) << 8) | mgetb(m_aram+SxFQLb+i)];
291 waveAddr = (mgetb(m_aram + SxRAMb + i) & 0x3) << 7;
292
293 size = (float)snd_channel[channel].sample_len / 32.0f;
294 for (j=0; j<32;)
295 {
296 int8_t byte = mgetb(m_aram + waveAddr + (j++ << 2)) & 0x3f;
297 // int8_t nbyte = mgetb(m_aram + waveAddr + (j << 2)) & 0x3f;
298 int end = (int)(((float)j)*size);
299 float val, add;
300
301 val = (float)byte;
302 add = /*(nbyte-byte)/(end-k)*/ 0.0; // no interpolation
303
304 for (; k<end; k++, val+=add)
305 {
306 #ifdef LAME_COMPILER_BUG
307 if ((int32_t)&snd_channel[channel].sample[k] == (int32_t)&snd_channel[channel].offset)
308 Debugger();
309 #endif
310 snd_channel[channel].sample[k] = ((uint8_t)val);
311 }
312 }
313 }
314
315 for (j=0; j<len; j++)
316 {
317 int32_t note_left = 0;
318 int32_t note_right = 0;
319
320 // process first 4 sound channels
321 for (i=0; i</*5*/5; i++)
322 {
323 uint8_t outLeft, outRight;
324 const int16_t *outTblPtr;
325 // uint8_t env0, env1;
326 s_snd_channel *channel = &snd_channel[i];
327
328 if (!channel->playing)
329 continue;
330
331 outLeft = outLvlTbl[channel->volLeft][channel->envelope];
332 outRight = outLvlTbl[channel->volRight][channel->envelope];
333 // env1 = ((uint8_t)mgetb(m_aram+SxEV1b+i*0x40));
334 if (channel->env1 & 0x01)
335 {
336 channel->env_time++;
337
338 // env0 = ((uint8_t)mgetb(m_aram+SxEV0b+i*0x40));
339 if (channel->env_time >= channel->env_steptime /*waveEnv2LenTbl[env0 & 0x7]*/)
340 {
341 // it's time for a step
342 channel->env_time = 0;
343 if (channel->env0 & 0x08)
344 {
345 // step up
346 channel->envelope++;
347 if (channel->envelope >= 0xf)
348 {
349 if (channel->env1 & 0x02) channel->envelope = channel->env0 >> 4;
350 else { channel->env1 &= ~0x01; channel->envelope = 0xf; }
351 }
352 }
353 else
354 {
355 // step down
356 channel->envelope--;
357 if (channel->envelope <= 0)
358 {
359 if (channel->env1 & 0x02) channel->envelope = channel->env0 >> 4;
360 else { channel->env1 &= ~0x01; channel->envelope = 0x0; }
361 }
362 }
363 }
364 }
365
366 outTblPtr = (int16_t *) outTbl[channel->sample[channel->offset]];
367 if (outLeft) note_left += outTblPtr[outLeft ];
368 if (outRight) note_right += outTblPtr[outRight];
369 channel->offset++;
370
371 if (channel->offset >= channel->sample_len)
372 channel->offset = 0;
373
374 if (channel->time > 0)
375 {
376 channel->time--;
377 if (channel->time <= 0)
378 channel->playing = false;
379 }
380 }
381
382
383 // scale to 16 bits
384 note_left = (note_left << 5) | ((note_left >> 6) & 0x1f);
385 note_right = (note_right << 5) | ((note_right >> 6) & 0x1f);
386
387 outL.put_int_clamp(j, (int16_t)note_left, 32768);
388 outR.put_int_clamp(j, (int16_t)note_right, 32768);
389 }
390 }
391
392 //-------------------------------------------------
393 // read - read from the chip's registers and internal RAM
394 //-------------------------------------------------
395
read(offs_t offset)396 uint8_t vboysnd_device::read(offs_t offset)
397 {
398 m_stream->update();
399 return m_aram[offset];
400 }
401
402 //-------------------------------------------------
403 // write - write to the chip's registers and internal RAM
404 //-------------------------------------------------
405
write(offs_t offset,uint8_t data)406 void vboysnd_device::write(offs_t offset, uint8_t data)
407 {
408 int freq, i;
409 // int waveAddr;
410 int volReg, intervalReg;
411 int channel, ouroffs;
412
413 mputb((uint8_t *)m_aram+offset, data);
414 if (offset < 0x400)
415 return;
416
417 channel = (offset-0x400) >> 6;
418 ouroffs = offset & 0x3f;
419
420 ///process_sound(cpu.vcount);
421
422 if (channel == 6 && ouroffs == 0)
423 {
424 if (mgetb(m_aram+SST0P) & 0x1)
425 for (i=0; i<4; i++)
426 snd_channel[i].playing = 0;
427 return;
428 }
429
430 // Extract frequencies and build the wave for the first 4 sound sources
431 i = channel * 0x40;
432 switch (ouroffs)
433 {
434 case SxLRV:
435 if (channel < 5)
436 {
437 volReg = mgetb(m_aram + SxLRVb + i); // 6-4-4 - L/R output level setting
438 if (snd_channel[channel].playing)
439 {
440 snd_channel[channel].volLeft = ((uint8_t)volReg) >> 4;
441 snd_channel[channel].volRight = ((uint8_t)volReg) & 0xf;
442 break;
443 }
444 }
445 case SxINT:
446 if (channel < 5)
447 {
448 uint8_t env0, env1;
449 // find out if the sound is playing
450 intervalReg = mgetb(m_aram + SxINTb + i); // 6-4-6 - Sound Interval
451 volReg = mgetb(m_aram + SxLRVb + i); // 6-4-4 - L/R output level setting
452
453 if (((intervalReg & 0x80) == 0) || (volReg == 0))
454 {
455 snd_channel[channel].playing = false;
456 return;
457 }
458 snd_channel[channel].playing = true;
459
460 // 6-4-1 - Waveform address comes from SxRAM.
461 // waveAddr = (mgetb(m_aram + SxRAMb + i) & 0x3) << 7;
462
463 // 6-4-15 - Frequency comes from here
464 freq = ((mgetb(m_aram+SxFQHb+i) & 0x7) << 8) | mgetb(m_aram+SxFQLb+i);
465
466 env0 = mgetb(m_aram+SxEV0b+i); env1 = mgetb(m_aram+SxEV1b+i);
467 snd_channel[channel].env0 = env0;
468 snd_channel[channel].env1 = env1;
469 snd_channel[channel].volLeft = ((uint8_t)volReg) >> 4;
470 snd_channel[channel].volRight = ((uint8_t)volReg) & 0xf;
471 snd_channel[channel].env_steptime = (env1 & 0x1) ? waveEnv2LenTbl[env0 & 0x7] : 0;
472 snd_channel[channel].sample_len = waveFreq2LenTbl[freq];
473
474 snd_channel[channel].offset = 0;
475 snd_channel[channel].time = (intervalReg & 0x20) ? waveTimer2LenTbl[intervalReg & 0x1f] : 0;
476 snd_channel[channel].envelope = ((uint8_t)mgetb(m_aram+SxEV0b+i)) >> 4;
477 snd_channel[channel].env_time = 0;
478 }
479 else
480 {
481 intervalReg = mgetb(m_aram + SxINTb + i); // 6-4-6 - Sound Interval
482 volReg = mgetb(m_aram + SxLRVb + i); // 6-4-4 - L/R output level setting
483
484 if (((intervalReg & 0x80) == 0) || (volReg == 0))
485 {
486 // snd_channel[channel].playing = false;
487 return;
488 }
489 // Debugger(); // uses white noise
490 // snd_channel[channel].playing = true;
491 }
492 break;
493
494 case SxEV0:
495 if (channel < 5)
496 if (snd_channel[channel].playing)
497 snd_channel[channel].envelope = ((uint8_t)mgetb(m_aram+SxEV0b+i)) >> 4;
498 break;
499 }
500 }
501