# MAME, Ghidra & Apollo notes
## Getting gdb working with MAME
patch at the end of this doc to mame, to fix side effects. Also tells mame to listen to INADDR_ANY, and not just localhost.
Docker container with gdb-multiarch (works on arm64 macs with `colima` + docker):
```
docker run --net host --rm --name multiarch skysider/multiarch-docker
```
Then create a "gdb" binary script somewhere on localhost that contains the following and make it executable:
```
#!/bin/sh
docker exec -it multiarch gdb-multiarch --nh -i mi2 -iex "target remote host.docker.internal:23946" -iex "set endian big" $*
```
This is the script you'll tell Ghidra to use. Edit `~/.ssh/config`, and add:
```
Host localhost
RequestTTY force
```
Run MAME with `-debug -debugger gdbstub`, i.e.:
```
./dn3500d dn3500 -uimodekey F12 -window -nomax -mouse -oslog -disk1 dn3500_sr10.4.awd -skip_gameinfo -sound none -debug -debugger gdbstub
```
In Ghidra, open the debugger tool. Select `Debugger > Debug domain_os_blah > in GDB via SSH`. Set `localhost` as the host, set your gdb script path, and hit Connect.
Ghidra will pop up another dialog box asking you for a program to debug. I just hit Cancel here, since gdb is going to ignore any `file` etc commands. You should now be stopped.
Finally, you need to map `domain_os` (or whatever) in manually. Open the Modules window, hit the little document icon to create a manual mapping, hit +, leave RAM at 0 base and set the address to `0xf0000000`. NOTE: this assumes that your domain_os has proper mappings set, as created by the apollo map file reader python script. Hit Apply.
At this point you should be able to set breakpoints at kernel addresses; e.g. navigate to `KDB_$INIT`, right click and select "Toggle Breakpoint". Hit the green "go" arrow in the debugger window.
You should be able to interact with MAME normally; once you `EX DOMAIN_OS`, the debugger should stop at your breakpoint.
### mame patch
```
diff --git src/mame/apollo/apollo.cpp src/mame/apollo/apollo.cpp
index 74b7734551f..ed695ab215c 100644
--- src/mame/apollo/apollo.cpp
+++ src/mame/apollo/apollo.cpp
@@ -262,6 +262,9 @@ uint32_t apollo_state::apollo_instruction_hook(offs_t offset)
void apollo_state::apollo_bus_error()
{
+ if (machine().side_effects_disabled())
+ return;
+
m_maincpu->set_input_line(M68K_LINE_BUSERROR, ASSERT_LINE);
m_maincpu->set_input_line(M68K_LINE_BUSERROR, CLEAR_LINE);
@@ -275,9 +278,11 @@ void apollo_state::cpu_space_map(address_map &map)
u16 apollo_state::apollo_irq_acknowledge(offs_t offset)
{
- m_maincpu->set_input_line(offset+1, CLEAR_LINE);
-
- MLOG2(("apollo_irq_acknowledge: interrupt level=%d", offset+1));
+ if (!machine().side_effects_disabled())
+ {
+ m_maincpu->set_input_line(offset+1, CLEAR_LINE);
+ MLOG2(("apollo_irq_acknowledge: interrupt level=%d", offset+1));
+ }
if (offset+1 == 6)
return apollo_pic_get_vector();
@@ -473,6 +478,8 @@ uint32_t apollo_state::apollo_unmapped_r(offs_t offset, uint32_t mem_mask)
m68000_base_device *m68k = m_maincpu;
+ const bool side_effects_disabled = machine().side_effects_disabled();
+
if ((address & 0xfff00000) == 0xfa800000 && VERBOSE < 2) {
// ?
} else if ((address & 0xfff00ff7) == 0xfd800000 && VERBOSE < 2) {
@@ -487,12 +494,16 @@ uint32_t apollo_state::apollo_unmapped_r(offs_t offset, uint32_t mem_mask)
// omit logging for Bus error test address in DN3500 boot prom and self_test
} else if (address == 0x0000ac00 && VERBOSE < 2) {
// omit logging for Bus error test address in DN3000 boot prom
- } else {
+ } else if (!side_effects_disabled) {
SLOG1(("unmapped memory dword read from %08x with mask %08x (ir=%04x)", address , mem_mask, m68k->state_int(M68K_IR)));
}
- /* unmapped; access causes a bus error */
- apollo_bus_error();
+ if (!side_effects_disabled)
+ {
+ /* unmapped; access causes a bus error */
+ apollo_bus_error();
+ }
+
return 0xffffffff;
}
@@ -500,8 +511,11 @@ void apollo_state::apollo_unmapped_w(offs_t offset, uint32_t data, uint32_t mem_
{
SLOG(("unmapped memory dword write to %08x = %08x & %08x", offset * 4, data, mem_mask));
- /* unmapped; access causes a bus error */
- apollo_bus_error();
+ if (!machine().side_effects_disabled())
+ {
+ /* unmapped; access causes a bus error */
+ apollo_bus_error();
+ }
}
/***************************************************************************
diff --git src/osd/modules/debugger/debuggdbstub.cpp src/osd/modules/debugger/debuggdbstub.cpp
index 409b6fa3bbb..5fea1462405 100644
--- src/osd/modules/debugger/debuggdbstub.cpp
+++ src/osd/modules/debugger/debuggdbstub.cpp
@@ -474,6 +474,7 @@ static const std::map<std::string, const gdb_register_map &> gdb_register_maps =
{ "arm7_le", gdb_register_map_arm7 },
{ "r4600", gdb_register_map_r4600 },
{ "ppc601", gdb_register_map_ppc601 },
+ { "m68030", gdb_register_map_m68020pmmu },
{ "m68020pmmu", gdb_register_map_m68020pmmu },
{ "m68000", gdb_register_map_m68000 },
{ "z80", gdb_register_map_z80 },
@@ -777,12 +787,12 @@ void debug_gdbstub::wait_for_debugger(device_t &device, bool firststop)
osd_printf_info("gdbstub: could not find register [%s]\n", reg.gdb_name);
}
-#if 0
+#if 0
for ( const auto ®: m_gdb_registers )
osd_printf_info(" %3d (%d) %d %d [%s]\n", reg.gdb_regnum, reg.state_index, reg.gdb_bitsize, reg.gdb_type, reg.gdb_name);
#endif
- std::string socket_name = string_format("socket.localhost:%d", m_debugger_port);
+ std::string socket_name = string_format("socket.0.0.0.0:%d", m_debugger_port);
std::error_condition const filerr = m_socket.open(socket_name);
if ( filerr )
fatalerror("gdbstub: failed to start listening on port %d\n", m_debugger_port);
```