mirror of
https://github.com/mamedev/mame.git
synced 2024-09-28 03:20:58 +02:00
sega/sega_beena.cpp: Emulated Advanced Pico BEENA and TV Ocha-Ken. (#11213)
Basic functionality is supported, making most games playable. StoryWare display is not yet implemented. Game-specific peripherals are not emulated. There are still some issues with graphics. emu/ioport.h: Fixed rarely-used PORT_CROSSHAIR_MAPPER and PORT_CROSSHAIR_MAPPER_MEMBER macros. cpu/arm7: Added AP2010 CPU device. sound/ap2010pcm.cpp: Added basic AP2010 PCM audio output device. Systems promoted to working ------------------------ Sega Advanced Pico BEENA New working systems ------------------------ Sega TV Ocha-Ken
This commit is contained in:
parent
e2eb4551ce
commit
ba621ec24d
10 changed files with 2521 additions and 83 deletions
|
@ -194,6 +194,8 @@ if CPUS["ARM7"] then
|
|||
MAME_DIR .. "src/devices/cpu/arm7/arm7.h",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/arm7thmb.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/arm7ops.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/ap2010cpu.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/ap2010cpu.h",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/lpc210x.cpp",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/lpc210x.h",
|
||||
MAME_DIR .. "src/devices/cpu/arm7/upd800468.cpp",
|
||||
|
|
|
@ -112,7 +112,6 @@ if (SOUNDS["AC97"]~=null) then
|
|||
end
|
||||
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
-- Apple custom sound chips
|
||||
--@src/devices/sound/asc.h,SOUNDS["ASC"] = true
|
||||
|
@ -1656,3 +1655,15 @@ if (SOUNDS["NN71003F"]~=null) then
|
|||
MAME_DIR .. "src/devices/sound/nn71003f.h",
|
||||
}
|
||||
end
|
||||
|
||||
---------------------------------------------------
|
||||
-- AP2010
|
||||
--@src/devices/sound/ap2010pcm.h,SOUNDS["AP2010"] = true
|
||||
---------------------------------------------------
|
||||
|
||||
if (SOUNDS["AP2010"]~=null) then
|
||||
files {
|
||||
MAME_DIR .. "src/devices/sound/ap2010pcm.cpp",
|
||||
MAME_DIR .. "src/devices/sound/ap2010pcm.h",
|
||||
}
|
||||
end
|
||||
|
|
43
src/devices/cpu/arm7/ap2010cpu.cpp
Normal file
43
src/devices/cpu/arm7/ap2010cpu.cpp
Normal file
|
@ -0,0 +1,43 @@
|
|||
// license:BSD-3-Clause
|
||||
// copyright-holders:QUFB
|
||||
/***************************************************************************
|
||||
|
||||
ARM7TDMI CPU component of the AP2010 LSI
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "ap2010cpu.h"
|
||||
|
||||
DEFINE_DEVICE_TYPE(AP2010CPU, ap2010cpu_device, "ap2010cpu", "AP2010 CPU")
|
||||
|
||||
ap2010cpu_device::ap2010cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: arm7_cpu_device(mconfig, AP2010CPU, tag, owner, clock, 4, ARCHFLAG_T, ENDIANNESS_BIG)
|
||||
{ }
|
||||
|
||||
void ap2010cpu_device::add_hotspot(offs_t pc)
|
||||
{
|
||||
if (m_hotspot_select < std::size(m_hotspot)) {
|
||||
m_hotspot[m_hotspot_select] = pc;
|
||||
m_hotspot_select++;
|
||||
}
|
||||
}
|
||||
|
||||
void ap2010cpu_device::execute_run()
|
||||
{
|
||||
for (size_t i = 0; i < ARM7_MAX_HOTSPOTS; i++) {
|
||||
if (m_hotspot[i] == 0) {
|
||||
break;
|
||||
}
|
||||
if (m_hotspot[i] == pc()) {
|
||||
int32_t icount = *m_icountptr;
|
||||
if (icount > 30) {
|
||||
eat_cycles(icount - 30);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
arm7_cpu_device::execute_run();
|
||||
}
|
36
src/devices/cpu/arm7/ap2010cpu.h
Normal file
36
src/devices/cpu/arm7/ap2010cpu.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
// license:BSD-3-Clause
|
||||
// copyright-holders:QUFB
|
||||
/***************************************************************************
|
||||
|
||||
ARM7TDMI CPU component of the AP2010 LSI
|
||||
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef MAME_CPU_ARM7_AP2010CPU_H
|
||||
#define MAME_CPU_ARM7_AP2010CPU_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "arm7.h"
|
||||
#include "arm7core.h"
|
||||
|
||||
class ap2010cpu_device : public arm7_cpu_device
|
||||
{
|
||||
public:
|
||||
ap2010cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
void add_hotspot(offs_t pc);
|
||||
|
||||
protected:
|
||||
// device_execute_interface overrides
|
||||
virtual void execute_run() override;
|
||||
|
||||
private:
|
||||
uint32_t m_hotspot_select = 0;
|
||||
uint32_t m_hotspot[ARM7_MAX_HOTSPOTS];
|
||||
};
|
||||
|
||||
// device type definition
|
||||
DECLARE_DEVICE_TYPE(AP2010CPU, ap2010cpu_device)
|
||||
|
||||
#endif // MAME_CPU_ARM7_AP2010CPU_H
|
227
src/devices/sound/ap2010pcm.cpp
Normal file
227
src/devices/sound/ap2010pcm.cpp
Normal file
|
@ -0,0 +1,227 @@
|
|||
// license:BSD-3-Clause
|
||||
// copyright-holders:QUFB
|
||||
/**********************************************************************
|
||||
|
||||
PCM audio functions of the AP2010 LSI
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#include "emu.h"
|
||||
|
||||
#include "ap2010pcm.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#define VERBOSE (0)
|
||||
#include "logmacro.h"
|
||||
|
||||
// device type definition
|
||||
DEFINE_DEVICE_TYPE(AP2010PCM, ap2010pcm_device, "ap2010pcm", "AP2010 PCM")
|
||||
|
||||
ap2010pcm_device::ap2010pcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
|
||||
: device_t(mconfig, AP2010PCM, tag, owner, clock)
|
||||
, device_sound_interface(mconfig, *this)
|
||||
, m_sample_rate(0)
|
||||
, m_fifo_size(0)
|
||||
, m_fifo_head(0)
|
||||
, m_fifo_tail(0)
|
||||
, m_fifo_fast_size(0)
|
||||
, m_fifo_fast_head(0)
|
||||
, m_fifo_fast_tail(0)
|
||||
, m_stream(nullptr)
|
||||
{ }
|
||||
|
||||
void ap2010pcm_device::device_start()
|
||||
{
|
||||
m_regs = make_unique_clear<uint32_t[]>(0x40/4);
|
||||
|
||||
m_sample_rate = 8000;
|
||||
|
||||
std::fill(std::begin(m_fifo_data), std::end(m_fifo_data), 0);
|
||||
std::fill(std::begin(m_fifo_fast_data), std::end(m_fifo_fast_data), 0);
|
||||
|
||||
m_stream = stream_alloc(0, 1, m_sample_rate);
|
||||
|
||||
save_pointer(NAME(m_regs), 0x40/4);
|
||||
|
||||
save_item(NAME(m_volume));
|
||||
|
||||
save_item(NAME(m_sample_rate));
|
||||
|
||||
save_item(NAME(m_fifo_data));
|
||||
save_item(NAME(m_fifo_size));
|
||||
save_item(NAME(m_fifo_head));
|
||||
save_item(NAME(m_fifo_tail));
|
||||
|
||||
save_item(NAME(m_fifo_fast_data));
|
||||
save_item(NAME(m_fifo_fast_size));
|
||||
save_item(NAME(m_fifo_fast_head));
|
||||
save_item(NAME(m_fifo_fast_tail));
|
||||
}
|
||||
|
||||
void ap2010pcm_device::sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs)
|
||||
{
|
||||
auto &buffer = outputs[0];
|
||||
buffer.fill(0);
|
||||
|
||||
int16_t sample = 0;
|
||||
uint16_t sample_empty_count = 0;
|
||||
uint16_t fifo_size = m_fifo_size;
|
||||
uint16_t fifo_fast_size = m_fifo_fast_size;
|
||||
for (size_t i = 0; i < buffer.samples(); i++) {
|
||||
if (m_fifo_fast_size) {
|
||||
sample = fifo_fast_pop();
|
||||
} else if (m_fifo_size) {
|
||||
sample = fifo_pop();
|
||||
} else {
|
||||
sample = 0;
|
||||
sample_empty_count++;
|
||||
}
|
||||
|
||||
buffer.put_int(i, sample * m_volume, 32768);
|
||||
}
|
||||
if (fifo_size && sample_empty_count) {
|
||||
LOG("pcm 0s = %d (had %d + fast %d, needed %d)\n", sample_empty_count, fifo_size, fifo_fast_size, buffer.samples());
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ap2010pcm_device::reg_r(offs_t offset)
|
||||
{
|
||||
offset &= 0x3f;
|
||||
if (offset == 0) {
|
||||
// PCM data (0x5001000c) only received when 0x50010000 & 1 != 0;
|
||||
// PCM parameters (0x50010010, 0x50010018) only received when 0x50010000 & 4 != 0;
|
||||
return (m_regs[0x4/4] != 0) ? 0x0f : 0;
|
||||
} else if (offset == 0x4/4 && m_fifo_size > 0x1ff) {
|
||||
// TODO: Verify in hardware, bit 1 might be cleared while busy playing?
|
||||
return m_regs[offset] & 0xfffffffe;
|
||||
} else if (offset == 0x1c/4) {
|
||||
uint32_t fifo_size = m_fifo_size;
|
||||
LOG("pcm asked size -> %d\n", fifo_size);
|
||||
|
||||
if (fifo_size > 0x1ff) {
|
||||
// FIXME: Expected max length, what happens if more data is streamed?
|
||||
fifo_size = 0x1ff;
|
||||
} else if (fifo_size > 1) {
|
||||
/*
|
||||
Workaround to avoid missing samples during data stream:
|
||||
|
||||
while (dVar1 = read_volatile_4(PCM_CTRL), (dVar1 & 1) != 0) {
|
||||
len = read_volatile_4(PCM_BUFLEN);
|
||||
len_diff = 0x13e - (len & 0x1ff);
|
||||
cVar2 = read_volatile_1(w_sound_test_var1);
|
||||
if (cVar2 == '\x10') {
|
||||
if (len_diff < 1) {
|
||||
return in_lr;
|
||||
}
|
||||
pcm_write_1x_data();
|
||||
}
|
||||
...
|
||||
}
|
||||
*/
|
||||
fifo_size -= 2;
|
||||
}
|
||||
return fifo_size;
|
||||
}
|
||||
|
||||
return m_regs[offset];
|
||||
}
|
||||
|
||||
void ap2010pcm_device::reg_w(offs_t offset, uint32_t data, uint32_t mem_mask)
|
||||
{
|
||||
offset &= 0x3f;
|
||||
COMBINE_DATA(&m_regs[offset]);
|
||||
|
||||
m_stream->update();
|
||||
|
||||
switch (offset) {
|
||||
case 0x4/4:
|
||||
if ((data & 0x78) == 0x78) {
|
||||
m_sample_rate = 8000 * (1 + BIT(data, 1));
|
||||
m_stream->set_sample_rate(m_sample_rate);
|
||||
|
||||
// When a new stream starts, stop playback of previous stream
|
||||
m_fifo_size = 0;
|
||||
m_fifo_head = 0;
|
||||
m_fifo_tail = 0;
|
||||
|
||||
LOG("pcm stream start, rate = %d\n", m_sample_rate);
|
||||
}
|
||||
break;
|
||||
case 0xc/4:
|
||||
if (ACCESSING_BITS_16_31) {
|
||||
fifo_push((data & 0xffff0000U) >> 16);
|
||||
}
|
||||
if (ACCESSING_BITS_0_15) {
|
||||
fifo_push(data & 0x0000ffffU);
|
||||
}
|
||||
break;
|
||||
// These samples are always played first
|
||||
case 0x10/4:
|
||||
if (ACCESSING_BITS_16_31) {
|
||||
fifo_fast_push((data & 0xffff0000U) >> 16);
|
||||
}
|
||||
if (ACCESSING_BITS_0_15) {
|
||||
fifo_fast_push(data & 0x0000ffffU);
|
||||
}
|
||||
break;
|
||||
// Panning. TODO: Identify bits for each channel
|
||||
case 0x14/4:
|
||||
LOG("pcm pan = %08x\n", data);
|
||||
break;
|
||||
// Volume control. When video output is disabled, it's possible to adjust volume
|
||||
// using the 2 touch areas on the bottom-left of the Storyware. Range 0..345
|
||||
case 0x18/4:
|
||||
m_volume = std::min(((data & 0x1ff00000U) >> 20) / 345.0f, 1.0f);
|
||||
LOG("pcm vol = %08x -> %d\n", data, m_volume);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t ap2010pcm_device::fifo_pop()
|
||||
{
|
||||
uint16_t sample = m_fifo_data[m_fifo_head];
|
||||
m_fifo_head = (m_fifo_head + 1) & (FIFO_MAX_SIZE - 1);
|
||||
m_fifo_size--;
|
||||
return sample;
|
||||
}
|
||||
|
||||
uint16_t ap2010pcm_device::fifo_fast_pop()
|
||||
{
|
||||
uint16_t sample = m_fifo_fast_data[m_fifo_fast_head];
|
||||
m_fifo_fast_head = (m_fifo_fast_head + 1) & (FIFO_MAX_SIZE - 1);
|
||||
m_fifo_fast_size--;
|
||||
return sample;
|
||||
}
|
||||
|
||||
void ap2010pcm_device::fifo_push(uint16_t sample)
|
||||
{
|
||||
if (sample == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// trash old data
|
||||
if (m_fifo_size > FIFO_MAX_SIZE - 1) {
|
||||
fifo_pop();
|
||||
}
|
||||
|
||||
m_fifo_data[m_fifo_tail] = sample;
|
||||
m_fifo_tail = (m_fifo_tail + 1) & (FIFO_MAX_SIZE - 1);
|
||||
m_fifo_size++;
|
||||
}
|
||||
|
||||
void ap2010pcm_device::fifo_fast_push(uint16_t sample)
|
||||
{
|
||||
if (sample == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// trash old data
|
||||
if (m_fifo_fast_size > FIFO_MAX_SIZE - 1) {
|
||||
fifo_fast_pop();
|
||||
}
|
||||
|
||||
m_fifo_fast_data[m_fifo_fast_tail] = sample;
|
||||
m_fifo_fast_tail = (m_fifo_fast_tail + 1) & (FIFO_MAX_SIZE - 1);
|
||||
m_fifo_fast_size++;
|
||||
}
|
65
src/devices/sound/ap2010pcm.h
Normal file
65
src/devices/sound/ap2010pcm.h
Normal file
|
@ -0,0 +1,65 @@
|
|||
// license:BSD-3-Clause
|
||||
// copyright-holders:QUFB
|
||||
/**********************************************************************
|
||||
|
||||
PCM audio functions of the AP2010 LSI
|
||||
|
||||
According to the Advanced Pico Beena's 2005-04-05 press release, it supports
|
||||
CELP with sample rates 8kHz and 16kHz. It is used as output for OGG files,
|
||||
which are decoded by the BIOS to signed 16-bit big endian PCM.
|
||||
|
||||
**********************************************************************/
|
||||
|
||||
#ifndef MAME_SOUND_AP2010PCM_H
|
||||
#define MAME_SOUND_AP2010PCM_H
|
||||
|
||||
#pragma once
|
||||
|
||||
class ap2010pcm_device : public device_t, public device_sound_interface
|
||||
{
|
||||
public:
|
||||
static constexpr feature_type imperfect_features() { return feature::SOUND; }
|
||||
|
||||
ap2010pcm_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
|
||||
|
||||
uint32_t reg_r(offs_t offset);
|
||||
void reg_w(offs_t offset, uint32_t data, uint32_t mem_mask = ~0);
|
||||
|
||||
protected:
|
||||
// device_t implementation
|
||||
virtual void device_start() override;
|
||||
|
||||
// device_sound_interface implementation
|
||||
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
|
||||
|
||||
private:
|
||||
// FIXME: Games check this against 0x1ff, but samples are lost with that limit
|
||||
static inline constexpr uint16_t FIFO_MAX_SIZE = 0x800;
|
||||
|
||||
uint16_t fifo_pop();
|
||||
uint16_t fifo_fast_pop();
|
||||
void fifo_push(uint16_t sample);
|
||||
void fifo_fast_push(uint16_t sample);
|
||||
|
||||
std::unique_ptr<uint32_t[]> m_regs;
|
||||
|
||||
float m_volume;
|
||||
|
||||
uint32_t m_sample_rate;
|
||||
|
||||
uint16_t m_fifo_data[FIFO_MAX_SIZE];
|
||||
uint16_t m_fifo_size;
|
||||
uint16_t m_fifo_head;
|
||||
uint16_t m_fifo_tail;
|
||||
|
||||
uint16_t m_fifo_fast_data[FIFO_MAX_SIZE];
|
||||
uint16_t m_fifo_fast_size;
|
||||
uint16_t m_fifo_fast_head;
|
||||
uint16_t m_fifo_fast_tail;
|
||||
|
||||
sound_stream *m_stream;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(AP2010PCM, ap2010pcm_device)
|
||||
|
||||
#endif // MAME_SOUND_AP2010PCM_H
|
|
@ -1223,10 +1223,10 @@ ATTR_COLD void INPUT_PORTS_NAME(_name)(device_t &owner, ioport_list &portlist, s
|
|||
configurer.field_set_crosshair(CROSSHAIR_AXIS_##axis, altaxis, scale, offset);
|
||||
|
||||
#define PORT_CROSSHAIR_MAPPER(_callback) \
|
||||
configurer.field_set_crossmapper(ioport_field_crossmap_delegate(_callback, #_callback, DEVICE_SELF, (device_t *)nullptr));
|
||||
configurer.field_set_crossmapper(ioport_field_crossmap_delegate(owner, DEVICE_SELF, _callback, #_callback));
|
||||
|
||||
#define PORT_CROSSHAIR_MAPPER_MEMBER(_device, _class, _member) \
|
||||
configurer.field_set_crossmapper(ioport_field_crossmap_delegate(&_class::_member, #_class "::" #_member, _device, (_class *)nullptr));
|
||||
configurer.field_set_crossmapper(ioport_field_crossmap_delegate(owner, _device, &_class::_member, #_class "::" #_member));
|
||||
|
||||
// how many optical counts for 1 full turn of the control
|
||||
#define PORT_FULL_TURN_COUNT(_count) \
|
||||
|
|
12
src/mame/layout/beena.lay
Normal file
12
src/mame/layout/beena.lay
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<!--
|
||||
license:CC0-1.0
|
||||
-->
|
||||
<mamelayout version="2">
|
||||
<view name="Single Screen">
|
||||
<bounds x="0" y="0" width="704" height="480" />
|
||||
<screen index="0">
|
||||
<bounds left="0" top="0" right="704" bottom="480" />
|
||||
</screen>
|
||||
</view>
|
||||
</mamelayout>
|
|
@ -39255,6 +39255,7 @@ sderby2 // (c) 1985
|
|||
|
||||
@source:sega/sega_beena.cpp
|
||||
beena //
|
||||
tvochken //
|
||||
|
||||
@source:sega/sega_sawatte.cpp
|
||||
sawatte //
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue