1 // license:BSD-3-Clause
2 // copyright-holders:Fabio Priuli
3 /***********************************************************************************************************
4 
5 
6  NES/Famicom cartridge emulation for Hosenkan PCBs
7 
8 
9  ***********************************************************************************************************/
10 
11 
12 #include "emu.h"
13 #include "hosenkan.h"
14 
15 #include "video/ppu2c0x.h"      // this has to be included so that IRQ functions can access ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE
16 #include "screen.h"
17 
18 
19 #ifdef NES_PCB_DEBUG
20 #define VERBOSE 1
21 #else
22 #define VERBOSE 0
23 #endif
24 
25 #define LOG_MMC(x) do { if (VERBOSE) logerror x; } while (0)
26 
27 
28 //-------------------------------------------------
29 //  constructor
30 //-------------------------------------------------
31 
32 DEFINE_DEVICE_TYPE(NES_HOSENKAN, nes_hosenkan_device, "nes_hosenkan", "NES Cart HOSENKAN PCB")
33 
34 
nes_hosenkan_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)35 nes_hosenkan_device::nes_hosenkan_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
36 	: nes_nrom_device(mconfig, NES_HOSENKAN, tag, owner, clock)
37 	, m_irq_count(0)
38 	, m_irq_count_latch(0)
39 	, m_irq_clear(0)
40 	, m_irq_enable(0)
41 	, m_latch(0)
42 {
43 }
44 
45 
46 
47 
device_start()48 void nes_hosenkan_device::device_start()
49 {
50 	common_start();
51 	save_item(NAME(m_irq_enable));
52 	save_item(NAME(m_irq_count));
53 	save_item(NAME(m_irq_count_latch));
54 	save_item(NAME(m_irq_clear));
55 	save_item(NAME(m_latch));
56 }
57 
pcb_reset()58 void nes_hosenkan_device::pcb_reset()
59 {
60 	m_chr_source = m_vrom_chunks ? CHRROM : CHRRAM;
61 	prg32((m_prg_chunks - 1) >> 1);
62 	chr8(0, m_chr_source);
63 
64 	m_latch = 0;
65 	m_irq_enable = 0;
66 	m_irq_count = m_irq_count_latch = 0;
67 	m_irq_clear = 0;
68 }
69 
70 
71 
72 /*-------------------------------------------------
73  mapper specific handlers
74  -------------------------------------------------*/
75 
76 /*-------------------------------------------------
77 
78  Bootleg Board by Hosenkan
79 
80  Games: Pocahontas, Super Donkey Kong
81 
82  iNES: mapper 182
83 
84  In MESS: Supported.
85 
86  -------------------------------------------------*/
87 
88 // same as MMC3!
hblank_irq(int scanline,int vblank,int blanked)89 void nes_hosenkan_device::hblank_irq( int scanline, int vblank, int blanked )
90 {
91 	if (scanline < ppu2c0x_device::BOTTOM_VISIBLE_SCANLINE)
92 	{
93 		int prior_count = m_irq_count;
94 		if ((m_irq_count == 0) || m_irq_clear)
95 			m_irq_count = m_irq_count_latch;
96 		else
97 			m_irq_count--;
98 
99 		if (m_irq_enable && !blanked && (m_irq_count == 0) && (prior_count || m_irq_clear))
100 		{
101 			LOG_MMC(("irq fired, scanline: %d\n", scanline));
102 			hold_irq_line();
103 		}
104 	}
105 	m_irq_clear = 0;
106 }
107 
write_h(offs_t offset,uint8_t data)108 void nes_hosenkan_device::write_h(offs_t offset, uint8_t data)
109 {
110 	LOG_MMC(("hosenkan write_h, offset: %04x, data: %02x\n", offset, data));
111 
112 	switch (offset & 0x7003)
113 	{
114 		case 0x0001:
115 			set_nt_mirroring(BIT(data, 0) ? PPU_MIRROR_HORZ : PPU_MIRROR_VERT);
116 			break;
117 		case 0x2000:
118 			m_latch = data;
119 			break;
120 		case 0x4000:
121 			switch (m_latch)
122 			{
123 				case 0:
124 					chr2_0(data >> 1, CHRROM);
125 					break;
126 				case 1:
127 					chr1_5(data, CHRROM);
128 					break;
129 				case 2:
130 					chr2_2(data >> 1, CHRROM);
131 					break;
132 				case 3:
133 					chr1_7(data, CHRROM);
134 					break;
135 				case 4:
136 					prg8_89(data);
137 					break;
138 				case 5:
139 					prg8_ab(data);
140 					break;
141 				case 6:
142 					chr1_4(data, CHRROM);
143 					break;
144 				case 7:
145 					chr1_6(data, CHRROM);
146 					break;
147 			}
148 			break;
149 		case 0x6003:
150 			if (data)
151 			{
152 				m_irq_count = data;
153 				m_irq_enable = 1;
154 			}
155 			else
156 				m_irq_enable = 0;
157 			break;
158 	}
159 }
160