1 // FBAlpha BSMT2000 emulation, based on code written by Aaron Giles
2 #include "burnint.h"
3 #include "tms32010.h"
4 #include "dac.h"
5 
6 static UINT32 bsmt2k_clock = 0;
7 
8 static INT32 write_pending = 0;
9 static UINT16 write_data = 0;
10 static UINT16 register_select = 0;
11 static UINT16 rom_address = 0;
12 static UINT8 rom_bank = 0;
13 static UINT8 *datarom = NULL;
14 static INT32 datarom_len = 0;
15 static void (*ready_callback)() = NULL;
16 static UINT16 data_left = 0;
17 static UINT16 data_right = 0;
18 
bsmt2k_write_reg(UINT16 data)19 void bsmt2k_write_reg(UINT16 data)
20 {
21 	register_select = data;
22 }
23 
bsmt2k_write_data(UINT16 data)24 void bsmt2k_write_data(UINT16 data)
25 {
26 	write_data = data;
27 	write_pending = 1;
28 }
29 
bsmt2k_read_status()30 INT32 bsmt2k_read_status()
31 {
32 	return write_pending ? 0 : 1;
33 }
34 
BSMTSyncDAC()35 static INT32 BSMTSyncDAC()
36 {
37 	return (INT32)(float)(nBurnSoundLen * (tms32010TotalCycles() / (bsmt2k_clock / (nBurnFPS / 100.0000))));
38 }
39 
bsmt2k_update()40 void bsmt2k_update()
41 {
42 	DACUpdate(pBurnSoundOut, nBurnSoundLen);
43 }
44 
update_stream()45 static void update_stream()
46 {
47 	DACWrite16Stereo(0, data_left, data_right);
48 }
49 
bsmt2k_write_port(INT32 port,UINT16 data)50 static void bsmt2k_write_port(INT32 port, UINT16 data)
51 {
52 	switch (port)
53 	{
54 		case 0:
55 			rom_address = data;
56 		return;
57 
58 		case 1:
59 			rom_bank = data;
60 		return;
61 
62 		case 3:
63 			data_left = data;
64 			update_stream();
65 		return;
66 
67 		case 7:
68 			data_right = data;
69 			update_stream();
70 		return;
71 	}
72 }
73 
bsmt2k_read_port(INT32 port)74 static UINT16 bsmt2k_read_port(INT32 port)
75 {
76 	switch (port)
77 	{
78 		case 0:
79 			return register_select;
80 
81 		case 1:
82 			write_pending = 0;
83 			if (ready_callback)
84 				ready_callback();
85 			return write_data;
86 
87 		case 2: {
88 			INT32 addr = (rom_bank << 16) + rom_address;
89 			if (addr >= datarom_len) return 0;
90 			return (INT16)(datarom[addr] << 8);
91 		}
92 
93 		case TMS32010_BIO:
94 			return (write_pending) ? 1 : 0;
95 	}
96 
97 	return 0;
98 }
99 
bsmt2kReset()100 void bsmt2kReset()
101 {
102 	tms32010_reset();
103 
104 	DACReset();
105 
106 	write_pending = 0;
107 	write_data = 0;
108 	register_select = 0;
109 	rom_address = 0;
110 	rom_bank = 0;
111 	data_left = 0;
112 	data_right = 0;
113 }
114 
bsmt2kResetCpu()115 void bsmt2kResetCpu()
116 {
117 	tms32010_reset();
118 }
119 
bsmt2kExit()120 void bsmt2kExit()
121 {
122 	tms32010_exit();
123 
124 	DACExit();
125 }
126 
bsmt2kScan(INT32 nAction,INT32 * pnMin)127 void bsmt2kScan(INT32 nAction, INT32 *pnMin)
128 {
129 	tms32010_scan(nAction);
130 
131 	DACScan(nAction, pnMin);
132 
133 	SCAN_VAR(write_pending);
134 	SCAN_VAR(write_data);
135 	SCAN_VAR(register_select);
136 	SCAN_VAR(rom_address);
137 	SCAN_VAR(rom_bank);
138 	SCAN_VAR(data_left);
139 	SCAN_VAR(data_right);
140 }
141 
bsmt2kInit(INT32 clock,UINT8 * tmsrom,UINT8 * tmsram,UINT8 * data,INT32 size,void (* cb)())142 void bsmt2kInit(INT32 clock, UINT8 *tmsrom, UINT8 *tmsram, UINT8 *data, INT32 size, void (*cb)())
143 {
144 	bsmt2k_clock = clock;
145 
146 	tms32010_rom = (UINT16*)tmsrom; // 0x1000 words (0x2000 bytes)
147 	tms32010_ram = (UINT16*)tmsram; // 0x100 bytes
148 
149 	datarom = data;
150 	datarom_len = size;
151 
152 	ready_callback = cb;
153 
154 	tms32010_init();
155 	tms32010_set_write_port_handler(bsmt2k_write_port);
156 	tms32010_set_read_port_handler(bsmt2k_read_port);
157 
158 	DACInit(0, 0, 0, BSMTSyncDAC);
159 	DACSetRoute(0, 0.60, BURN_SND_ROUTE_BOTH);
160 	DACStereoMode(0);
161 }
162 
bsmt2kNewFrame()163 void bsmt2kNewFrame()
164 {
165 	tms32010NewFrame();
166 }
167