龙芯的声卡驱动导致MAME模拟器segment fault?
EMCA
编译好的MAME模拟器可以显示管理界面
但是运行任何游戏都会显示segment fault,退出时也会发生segment fault
用gdb调试,发现出问题的是sound.cpp,发生segment fault后打印backtrace显示如下信息
(gdb) backtrace
#0 0x0000000000000078 in ?? ()
#1 0x0000000121d58d40 in util::detail::delegate_base<delegate_late_bind, void, sound_stream&, std::vector<read_stream_view, std::allocator<read_stream_view> > const&, std::vector<write_stream_view, std::allocator<write_stream_view> >&>::operator() (this=0x124b1c000, this=0x124b1c000, args#2=std::vector of length 1, capacity 1 = {...},
args#1=std::vector of length 0, capacity 0, args#0=...) at ../../../../../src/lib/util/delegate.h:760
#2 sound_stream::update_view (this=this@entry=0x124b1bee0, start=..., end=..., outputnum=<optimized out>, outputnum@entry=0) at ../../../../../src/emu/sound.cpp:742
#3 0x0000000121d5905c in sound_stream::update (this=0x124b1bee0) at ../../../../../src/emu/attotime.h:100
#4 0x000000012012d6e0 in non-virtual thunk to dac_byte_device_base::write(unsigned char) () at /usr/include/c++/8/ext/new_allocator.h:86
#5 0x0000000120c9bb44 in devcb_write<unsigned char, (unsigned char)255>::operator()(unsigned int, unsigned char, unsigned char) ()
at /usr/include/c++/8/bits/shared_ptr_base.h:404
#6 0x00000001202bce94 in addressable_latch_device::update_bit (this=0x1241dff00) at ../../../../../src/devices/machine/74259.cpp:216
#7 addressable_latch_device::enable_w (state=0, this=0x1241dff00) at ../../../../../src/devices/machine/74259.cpp:184
#8 addressable_latch_device::write_bit (d=<optimized out>, offset=<optimized out>, this=0x1241dff00) at ../../../../../src/devices/machine/74259.cpp:153
#9 addressable_latch_device::write_d0 (this=0x1241dff00, offset=<optimized out>, data=<optimized out>) at ../../../../../src/devices/machine/74259.cpp:241
#10 0x0000000120c3f534 in tms99xx_device::cru_output_operation (this=0x1241cd500) at ../../../../../src/lib/util/coretmpl.h:594
#11 0x0000000120c4534c in tms99xx_device::execute_run (this=0x1241cd500) at ../../../../../src/devices/cpu/tms9900/tms9900.cpp:1254
#12 0x0000000121d2b560 in device_execute_interface::run (this=0x1241cd7f0) at ../../../../../src/emu/diexec.h:189
#13 device_scheduler::timeslice (this=this@entry=0xffffff6128) at ../../../../../src/emu/schedule.cpp:456
#14 0x0000000121cc1e34 in running_machine::run (this=this@entry=0xffffff0ef0, quiet=quiet@entry=false) at ../../../../../src/emu/machine.cpp:348
#15 0x000000012273bee0 in mame_machine_manager::execute (this=this@entry=0x124059e20) at ../../../../../src/frontend/mame/mame.cpp:288
#16 0x00000001227e0c74 in cli_frontend::start_execution (this=this@entry=0xffffff6938, manager=manager@entry=0x124059e20, args=std::vector of length 3, capacity 3 = {...})
at ../../../../../src/frontend/mame/clifront.cpp:277
#17 0x00000001227e106c in cli_frontend::execute (this=this@entry=0xffffff6938, args=std::vector of length 3, capacity 3 = {...})
at ../../../../../src/frontend/mame/clifront.cpp:293
#18 0x00000001227385cc in emulator_info::start_frontend (options=..., osd=..., args=std::vector of length 3, capacity 3 = {...})
at ../../../../../src/frontend/mame/mame.cpp:453
#19 0x00000001200d3b68 in main (argc=<optimized out>, argv=<optimized out>) at ../../../../../src/osd/sdl/sdlmain.cpp:100
(gdb)
看调试信息似乎是mame的声音处理导致的segment fault,是否是龙芯声卡驱动不支持这种纯用时间轴实现的游戏?但我的另一块板子,板载的格兰菲的声卡,却无此问题。
而且在新世界系统里用龙芯板载声卡有同样的问题,所以怀疑应当是声卡驱动的问题
EMCA
最新进展,显示了画面,但是还是在初始化声卡时崩溃,
同样是访问内存0x78时发生segment fault,不知道是不是触发了内存保护
EMCA
希望将来能成功运行,可以买个龙芯派玩三国战纪
lizhuojian
EMCA 手持3a6000期待中
EMCA
昨天闲来无事,追踪了下bug来源,感觉与声卡驱动的关联不大,有可能是C++ STL库里Vector的实现和龙芯系统的内存管理机制的冲突造成的
由于MAME是模拟器,而且似乎是实时解释执行的,会将被模拟的主机上的一些端口的读写操作映射成本地的端口调用,类似这样(以之前运行的looping游戏的源码looping.cpp为例)
looping_state::map(address_map &map)
{
... map(0xf800, 0xf800).mirror(0x03fc).portr("P1").w(FUNC(looping_state::out_0_w)); ...
}
将被模拟主机的0xf800端口的写操作映射至looping_state::out_0_w方法
其中map(<start>, <end>)是一个操作符重载(重载了“()”),是这样实现的
address_map_entry &address_map::operator()(offs_t start, offs_t end)
{
address_map_entry *ptr = new address_map_entry(*m_device, *this, start, end);
m_entrylist.append(*ptr);
return *ptr;
}
然后looping_state::looping函数中使用m_maincpu->set_addrmap(AS_PROGRAM, &looping_state::map)方法将looping_state::map中定义的端口操作处理函数写入模拟器的端口动作表m_address_map
函数set_addrmap在dimemory.cpp中是这样实现的
void device_memory_interface::set_addrmap(int spacenum, address_map_constructor map)
{
assert(0 <= spacenum); if (spacenum >= int(m_address_map.size())) m_address_map.resize(spacenum + 1); m_address_map[spacenum] = std::move(map);
}
先调整m_address_map这个vector的大小然后将本地函数等信息用std::move填进去,怀疑segment fault就是在这个环节里造成的
接下来的模拟器地址0x78读操作引发segment fault的问题就涉及龙芯系统的内存管理机制和STL库里vector类型的实现问题了,m_address_map这个vector变量在返回端口处理函数时大概率引发了内存保护问题,这超出了我的能力,到这里只能把问题上报
liudidi
EMCA 最新的275仍然是这个问题,看起来官方可能不会解决了。
EMCA
liudidi 异常发生在delegate.h,应该是/src/lib/util/delegate.h和delegate.cpp里的问题,里面有三种工作机制,根据软硬件架构不同编译器会选取不同的工作机制
#define MAME_DELEGATE_TYPE_COMPATIBLE 0
#define MAME_DELEGATE_TYPE_ITANIUM 1
#define MAME_DELEGATE_TYPE_MSVC 2
感觉这个bug和MAME源码关系不大,似乎还是因为龙芯的内存保护机制,导致0x0000000000000078这块内存里的指令或数据无法访问,这个要么和编译器有关要么和系统有关,由于MAME代码里用了大量的C++模板,很难调试而且让人感觉很费解,具体问题我正在看
liudidi
mame弄不好,raine稍修改下到是可以运行。
gainer
手持3a6000期待中