---
# System prepended metadata

title: 'MAME, Ghidra & Apollo notes'

---

# 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 &reg: 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);
            ```