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 ^ 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;
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 
115 // To switch modes, the game sets a register then reboots the tms32010
bsmt2kResetCpu()116 void bsmt2kResetCpu()
117 {
118 	tms32010_reset();
119 }
120 
bsmt2kExit()121 void bsmt2kExit()
122 {
123 	tms32010_exit();
124 
125 	DACExit();
126 }
127 
bsmt2kScan(INT32 nAction,INT32 * pnMin)128 void bsmt2kScan(INT32 nAction, INT32 *pnMin)
129 {
130 	tms32010_scan(nAction);
131 
132 	DACScan(nAction, pnMin);
133 
134 	SCAN_VAR(write_pending);
135 	SCAN_VAR(write_data);
136 	SCAN_VAR(register_select);
137 	SCAN_VAR(rom_address);
138 	SCAN_VAR(rom_bank);
139 	SCAN_VAR(data_left);
140 	SCAN_VAR(data_right);
141 }
142 
bsmt2kInit(INT32 clock,UINT8 * tmsrom,UINT8 * tmsram,UINT8 * data,INT32 size,void (* cb)())143 void bsmt2kInit(INT32 clock, UINT8 *tmsrom, UINT8 *tmsram, UINT8 *data, INT32 size, void (*cb)())
144 {
145 	bsmt2k_clock = clock;
146 
147 	tms32010_rom = (UINT16*)tmsrom; // 0x1000 words (0x2000 bytes)
148 	tms32010_ram = (UINT16*)tmsram; // 0x100 words (0x200 bytes)
149 
150 	datarom = data;
151 	datarom_len = size;
152 
153 	ready_callback = cb;
154 
155 	tms32010_init();
156 	tms32010_set_write_port_handler(bsmt2k_write_port);
157 	tms32010_set_read_port_handler(bsmt2k_read_port);
158 
159 	DACInit(0, 0, 0, BSMTSyncDAC);
160 	DACSetRoute(0, 0.60, BURN_SND_ROUTE_BOTH);
161 	DACStereoMode(0);
162 }
163 
bsmt2kNewFrame()164 void bsmt2kNewFrame()
165 {
166 	tms32010NewFrame();
167 }
168