1 /*
2     sat_hw.c - Saturn sound hardware glue/emulation/whatever
3 
4     supported: main RAM (512 KB)
5     	       SCSP + timers
6 	       MC68000 CPU
7 
8     Copyright (c) 2007, R. Belmont and Richard Bannister.
9 
10     All rights reserved.
11 
12     Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
13 
14     * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
15     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
16     * Neither the names of R. Belmont and Richard Bannister nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
17 
18     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21     A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22     CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23     EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24     PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25     PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26     LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27     NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28     SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 */
30 
31 #include <stdio.h>
32 
33 #include "ao.h"
34 #include "scsp.h"
35 #include "sat_hw.h"
36 #include "m68k.h"
37 #include "m68kcpu.h"
38 
scsp_irq(m68ki_cpu_core * cpu,int irq)39 static void scsp_irq(m68ki_cpu_core *cpu, int irq)
40 {
41 	if (irq > 0)
42 	{
43 		m68k_set_irq(cpu, irq);
44 	}
45 }
46 
47 #define MIXER_PAN_LEFT    1
48 #define MIXER_PAN_RIGHT   2
49 #define MIXER(level,pan) ((level & 0xff) | ((pan & 0x03) << 8))
50 #define YM3012_VOL(LVol,LPan,RVol,RPan) (MIXER(LVol,LPan)|(MIXER(RVol,RPan) << 16))
51 
52 #if 0
53 static struct SCSPinterface scsp_interface =
54 {
55 	1,
56 	{ sat_ram, },
57 	{ YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT) },
58 	{ scsp_irq, },
59 };
60 #endif
61 
sat_hw_init(m68ki_cpu_core * cpu)62 void sat_hw_init(m68ki_cpu_core *cpu)
63 {
64 //	m68k_init();
65 	m68k_set_cpu_type(cpu, M68K_CPU_TYPE_68000);
66 	m68k_pulse_reset(cpu);
67     struct SCSPinterface scsp_interface;
68 	scsp_interface.num = 1;
69 	scsp_interface.region[0] = cpu->sat_ram;
70 	scsp_interface.mixing_level[0] = YM3012_VOL(100, MIXER_PAN_LEFT, 100, MIXER_PAN_RIGHT);
71 	scsp_interface.irq_callback[0] = scsp_irq;
72 	scsp_interface.cpu = cpu;
73 
74 	cpu->SCSP = SCSP_Start(&scsp_interface);
75 }
76 
sat_hw_free(struct m68ki_cpu_core_s * cpu)77 void sat_hw_free(struct m68ki_cpu_core_s *cpu) {
78     SCSP_Exit (cpu->SCSP);
79 }
80 
81 /* M68k memory handlers */
82 
m68k_read_memory_8(m68ki_cpu_core * cpu,unsigned int address)83 unsigned int m68k_read_memory_8(m68ki_cpu_core *cpu, unsigned int address)
84 {
85 	if (address < (512*1024))
86 		return cpu->sat_ram[address^1];
87 
88 	if (address >= 0x100000 && address < 0x100c00)
89 	{
90 		int foo = SCSP_0_r(cpu->SCSP, (address - 0x100000)/2, 0);
91 
92 		if (address & 1)
93 			return foo & 0xff;
94 		else
95 			return foo>>8;
96 	}
97 
98 	printf("R8 @ %x\n", address);
99 	return 0;
100 }
101 
m68k_read_memory_16(m68ki_cpu_core * cpu,unsigned int address)102 unsigned int m68k_read_memory_16(m68ki_cpu_core *cpu, unsigned int address)
103 {
104 	if (address < (512*1024))
105 	{
106 		return mem_readword_swap((unsigned short *)(cpu->sat_ram+address));
107 	}
108 
109 	if (address >= 0x100000 && address < 0x100c00)
110 		return SCSP_0_r(cpu->SCSP, (address-0x100000)/2, 0);
111 
112 	printf("R16 @ %x\n", address);
113 	return 0;
114 }
115 
m68k_read_memory_32(m68ki_cpu_core * cpu,unsigned int address)116 unsigned int m68k_read_memory_32(m68ki_cpu_core *cpu, unsigned int address)
117 {
118 	if (address < 0x80000)
119 	{
120 		return cpu->sat_ram[address+2] | cpu->sat_ram[address+3]<<8 | cpu->sat_ram[address]<<16 | cpu->sat_ram[address+1]<<24;
121 	}
122 
123 	printf("R32 @ %x\n", address);
124 	return 0;
125 }
126 
m68k_write_memory_8(m68ki_cpu_core * cpu,unsigned int address,unsigned int data)127 void m68k_write_memory_8(m68ki_cpu_core *cpu, unsigned int address, unsigned int data)
128 {
129 	if (address < 0x80000)
130 	{
131 		cpu->sat_ram[address^1] = data;
132 		return;
133 	}
134 
135 	if (address >= 0x100000 && address < 0x100c00)
136 	{
137 		address -= 0x100000;
138 		if (address & 1)
139 			SCSP_0_w(cpu->SCSP, address>>1, data, 0xff00);
140 		else
141 			SCSP_0_w(cpu->SCSP, address>>1, data<<8, 0x00ff);
142 		return;
143 	}
144 }
145 
m68k_write_memory_16(m68ki_cpu_core * cpu,unsigned int address,unsigned int data)146 void m68k_write_memory_16(m68ki_cpu_core *cpu, unsigned int address, unsigned int data)
147 {
148 	if (address < 0x80000)
149 	{
150 		cpu->sat_ram[address+1] = (data>>8)&0xff;
151 		cpu->sat_ram[address] = data&0xff;
152 		return;
153 	}
154 
155 	if (address >= 0x100000 && address < 0x100c00)
156 	{
157 		SCSP_0_w(cpu->SCSP, (address-0x100000)>>1, data, 0x0000);
158 		return;
159 	}
160 }
161 
m68k_write_memory_32(m68ki_cpu_core * cpu,unsigned int address,unsigned int data)162 void m68k_write_memory_32(m68ki_cpu_core *cpu, unsigned int address, unsigned int data)
163 {
164 	if (address < 0x80000)
165 	{
166 		cpu->sat_ram[address+1] = (data>>24)&0xff;
167 		cpu->sat_ram[address] = (data>>16)&0xff;
168 		cpu->sat_ram[address+3] = (data>>8)&0xff;
169 		cpu->sat_ram[address+2] = data&0xff;
170 		return;
171 	}
172 
173 	if (address >= 0x100000 && address < 0x100c00)
174 	{
175 		address -= 0x100000;
176 		SCSP_0_w(cpu->SCSP, address>>1, data>>16, 0x0000);
177 		SCSP_0_w(cpu->SCSP, (address>>1)+1, data&0xffff, 0x0000);
178 		return;
179 	}
180 }
181