|  |  |  | @@ -46,7 +46,7 @@ iwram: Iwram, | 
		
	
		
			
				|  |  |  |  | ewram: Ewram, | 
		
	
		
			
				|  |  |  |  | io: Io, | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | cpu: ?*Arm7tdmi, | 
		
	
		
			
				|  |  |  |  | cpu: *Arm7tdmi, | 
		
	
		
			
				|  |  |  |  | sched: *Scheduler, | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | pub fn init(self: *Self, allocator: Allocator, sched: *Scheduler, cpu: *Arm7tdmi, paths: FilePaths) !void { | 
		
	
	
		
			
				
					
					|  |  |  | @@ -82,9 +82,9 @@ pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T { | 
		
	
		
			
				|  |  |  |  |         // General Internal Memory | 
		
	
		
			
				|  |  |  |  |         0x00 => blk: { | 
		
	
		
			
				|  |  |  |  |             if (address < Bios.size) | 
		
	
		
			
				|  |  |  |  |                 break :blk self.bios.dbgRead(T, self.cpu.?.r[15], aligned_addr); | 
		
	
		
			
				|  |  |  |  |                 break :blk self.bios.dbgRead(T, self.cpu.r[15], aligned_addr); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             break :blk self.readOpenBus(T, address); | 
		
	
		
			
				|  |  |  |  |             break :blk self.openBus(T, address); | 
		
	
		
			
				|  |  |  |  |         }, | 
		
	
		
			
				|  |  |  |  |         0x02 => self.ewram.read(T, aligned_addr), | 
		
	
		
			
				|  |  |  |  |         0x03 => self.iwram.read(T, aligned_addr), | 
		
	
	
		
			
				
					
					|  |  |  | @@ -109,48 +109,63 @@ pub fn dbgRead(self: *const Self, comptime T: type, address: u32) T { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             break :blk @as(T, value) * multiplier; | 
		
	
		
			
				|  |  |  |  |         }, | 
		
	
		
			
				|  |  |  |  |         else => self.readOpenBus(T, address), | 
		
	
		
			
				|  |  |  |  |         else => self.openBus(T, address), | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | fn readIo(self: *const Self, comptime T: type, unaligned_address: u32) T { | 
		
	
		
			
				|  |  |  |  |     const maybe_value = io.read(self, T, forceAlign(T, unaligned_address)); | 
		
	
		
			
				|  |  |  |  |     return if (maybe_value) |value| value else self.readOpenBus(T, unaligned_address); | 
		
	
		
			
				|  |  |  |  |     return if (maybe_value) |value| value else self.openBus(T, unaligned_address); | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  | fn readOpenBus(self: *const Self, comptime T: type, address: u32) T { | 
		
	
		
			
				|  |  |  |  |     const r15 = self.cpu.?.r[15]; | 
		
	
		
			
				|  |  |  |  | fn openBus(self: *const Self, comptime T: type, address: u32) T { | 
		
	
		
			
				|  |  |  |  |     const r15 = self.cpu.r[15]; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |     const word = blk: { | 
		
	
		
			
				|  |  |  |  |         // If u32 Open Bus, read recently fetched opcode (PC + 8) | 
		
	
		
			
				|  |  |  |  |         if (!self.cpu.?.cpsr.t.read()) break :blk self.dbgRead(u32, r15 + 4); | 
		
	
		
			
				|  |  |  |  |         // If Arm, get the most recently fetched instruction (PC + 8) | 
		
	
		
			
				|  |  |  |  |         if (!self.cpu.cpsr.t.read()) break :blk self.cpu.pipe.stage[1].?; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         const page = @truncate(u8, r15 >> 24); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         // PC + 2 = stage[0] | 
		
	
		
			
				|  |  |  |  |         // PC + 4 = stage[1] | 
		
	
		
			
				|  |  |  |  |         // PC + 6 = Need a Debug Read for this? | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |         switch (page) { | 
		
	
		
			
				|  |  |  |  |             // EWRAM, PALRAM, VRAM, and Game ROM (16-bit) | 
		
	
		
			
				|  |  |  |  |             0x02, 0x05, 0x06, 0x08...0x0D => { | 
		
	
		
			
				|  |  |  |  |                 // (PC + 4) | 
		
	
		
			
				|  |  |  |  |                 const halfword = self.dbgRead(u16, r15 + 2); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                 break :blk @as(u32, halfword) << 16 | halfword; | 
		
	
		
			
				|  |  |  |  |                 const halfword: u32 = @truncate(u16, self.cpu.pipe.stage[1].?); | 
		
	
		
			
				|  |  |  |  |                 break :blk halfword << 16 | halfword; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             // BIOS or OAM (32-bit) | 
		
	
		
			
				|  |  |  |  |             0x00, 0x07 => { | 
		
	
		
			
				|  |  |  |  |                 // Aligned: (PC + 6) | (PC + 4) | 
		
	
		
			
				|  |  |  |  |                 // Unaligned: (PC + 4) | (PC + 2) | 
		
	
		
			
				|  |  |  |  |                 const offset: u32 = if (address & 3 == 0b00) 2 else 0; | 
		
	
		
			
				|  |  |  |  |                 const aligned = address & 3 == 0b00; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                 break :blk @as(u32, self.dbgRead(u16, r15 + 2 + offset)) << 16 | self.dbgRead(u16, r15 + offset); | 
		
	
		
			
				|  |  |  |  |                 // TODO: What to do on PC + 6? | 
		
	
		
			
				|  |  |  |  |                 const high: u32 = if (aligned) self.dbgRead(u16, r15 + 4) else @truncate(u16, self.cpu.pipe.stage[1].?); | 
		
	
		
			
				|  |  |  |  |                 const low: u32 = @truncate(u16, self.cpu.pipe.stage[@boolToInt(aligned)].?); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                 break :blk high << 16 | low; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             // IWRAM (16-bit but special) | 
		
	
		
			
				|  |  |  |  |             0x03 => { | 
		
	
		
			
				|  |  |  |  |                 // Aligned: (PC + 2) | (PC + 4) | 
		
	
		
			
				|  |  |  |  |                 // Unaligned: (PC + 4) | (PC + 2) | 
		
	
		
			
				|  |  |  |  |                 const offset: u32 = if (address & 3 == 0b00) 2 else 0; | 
		
	
		
			
				|  |  |  |  |                 const aligned = address & 3 == 0b00; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                 break :blk @as(u32, self.dbgRead(u16, r15 + 2 - offset)) << 16 | self.dbgRead(u16, r15 + offset); | 
		
	
		
			
				|  |  |  |  |                 const high: u32 = @truncate(u16, self.cpu.pipe.stage[1 - @boolToInt(aligned)].?); | 
		
	
		
			
				|  |  |  |  |                 const low: u32 = @truncate(u16, self.cpu.pipe.stage[@boolToInt(aligned)].?); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |                 break :blk high << 16 | low; | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             else => { | 
		
	
		
			
				|  |  |  |  |                 log.err("THUMB open bus read from 0x{X:0>2} page @0x{X:0>8}", .{ page, address }); | 
		
	
		
			
				|  |  |  |  |                 @panic("invariant most-likely broken"); | 
		
	
		
			
				|  |  |  |  |             }, | 
		
	
		
			
				|  |  |  |  |             else => unreachable, | 
		
	
		
			
				|  |  |  |  |         } | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  | @@ -167,9 +182,9 @@ pub fn read(self: *Self, comptime T: type, address: u32) T { | 
		
	
		
			
				|  |  |  |  |         // General Internal Memory | 
		
	
		
			
				|  |  |  |  |         0x00 => blk: { | 
		
	
		
			
				|  |  |  |  |             if (address < Bios.size) | 
		
	
		
			
				|  |  |  |  |                 break :blk self.bios.read(T, self.cpu.?.r[15], aligned_addr); | 
		
	
		
			
				|  |  |  |  |                 break :blk self.bios.read(T, self.cpu.r[15], aligned_addr); | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             break :blk self.readOpenBus(T, address); | 
		
	
		
			
				|  |  |  |  |             break :blk self.openBus(T, address); | 
		
	
		
			
				|  |  |  |  |         }, | 
		
	
		
			
				|  |  |  |  |         0x02 => self.ewram.read(T, aligned_addr), | 
		
	
		
			
				|  |  |  |  |         0x03 => self.iwram.read(T, aligned_addr), | 
		
	
	
		
			
				
					
					|  |  |  | @@ -194,7 +209,7 @@ pub fn read(self: *Self, comptime T: type, address: u32) T { | 
		
	
		
			
				|  |  |  |  |  | 
		
	
		
			
				|  |  |  |  |             break :blk @as(T, value) * multiplier; | 
		
	
		
			
				|  |  |  |  |         }, | 
		
	
		
			
				|  |  |  |  |         else => self.readOpenBus(T, address), | 
		
	
		
			
				|  |  |  |  |         else => self.openBus(T, address), | 
		
	
		
			
				|  |  |  |  |     }; | 
		
	
		
			
				|  |  |  |  | } | 
		
	
		
			
				|  |  |  |  |  | 
		
	
	
		
			
				
					
					|  |  |  |   |