1 // license:BSD-3-Clause
2 // copyright-holders:Barry Rodewald
3 /*********************************************************************
4 
5     fmt_icmem.cpp
6 
7     FM Towns IC Memory Card
8     PCMCIA SRAM Memory Cards, up to 64MB supported
9 
10 *********************************************************************/
11 
12 #include "emu.h"
13 #include "emuopts.h"
14 #include "fmt_icmem.h"
15 
16 // device type definition
17 DEFINE_DEVICE_TYPE(FMT_ICMEM, fmt_icmem_device, "fmt_icmem", "FM Towns IC Memory Card")
18 
19 //-------------------------------------------------
20 //  fmt_icmem_device - constructor
21 //-------------------------------------------------
22 
fmt_icmem_device(const machine_config & mconfig,const char * tag,device_t * owner,uint32_t clock)23 fmt_icmem_device::fmt_icmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
24 	: device_t(mconfig, FMT_ICMEM, tag, owner, clock),
25 		device_image_interface(mconfig, *this),
26 		m_writeprotect(*this,"icmem"),
27 		m_change(false),
28 		m_attr_select(false),
29 		m_detect(false),
30 		m_bank(0)
31 {
32 }
33 
34 
35 static INPUT_PORTS_START( fmt_icmem )
36 	PORT_START("icmem")
37 	PORT_CONFNAME(0x01, 0x00, "IC Memory Card Write Protect")
DEF_STR(Off)38 	PORT_CONFSETTING(0x00, DEF_STR( Off ))
39 	PORT_CONFSETTING(0x01, DEF_STR( On ))
40 INPUT_PORTS_END
41 
42 
43 //-------------------------------------------------
44 //  device_start - device-specific startup
45 //-------------------------------------------------
46 
47 void fmt_icmem_device::device_start()
48 {
49 	m_memcard_ram = std::make_unique<uint8_t[]>(0x1000000);
50 	m_bank = 0;
51 	m_detect = false;
52 	m_change = false;
53 	save_item(NAME(m_change));
54 	save_item(NAME(m_detect));
55 	save_item(NAME(m_bank));
56 }
57 
device_input_ports() const58 ioport_constructor fmt_icmem_device::device_input_ports() const
59 {
60 	return INPUT_PORTS_NAME(fmt_icmem);
61 }
62 
call_load()63 image_init_result fmt_icmem_device::call_load()
64 {
65 	memset(m_memcard_ram.get(), 0xff, 0x1000000);
66 	fseek(0, SEEK_SET);
67 	size_t ret = fread(m_memcard_ram.get(), 0x1000000);
68 
69 	if(ret != length())
70 		return image_init_result::FAIL;
71 
72 	m_change = true;
73 	m_detect = true;
74 	return image_init_result::PASS;
75 }
76 
call_unload()77 void fmt_icmem_device::call_unload()
78 {
79 	fseek(0, SEEK_SET);
80 	if(!m_writeprotect->read())
81 		fwrite(m_memcard_ram.get(), 0x1000000);
82 	m_change = true;
83 	m_detect = false;
84 }
85 
call_create(int format_type,util::option_resolution * format_options)86 image_init_result fmt_icmem_device::call_create(int format_type, util::option_resolution *format_options)
87 {
88 	memset(m_memcard_ram.get(), 0xff, 0x1000000);
89 
90 	size_t ret = fwrite(m_memcard_ram.get(), 0x1000000);
91 	if(ret != 0x1000000)
92 		return image_init_result::FAIL;
93 
94 	m_change = true;
95 	m_detect = true;
96 	return image_init_result::PASS;
97 }
98 
99 
static_mem_read(offs_t offset)100 uint8_t fmt_icmem_device::static_mem_read(offs_t offset)
101 {
102 	return m_memcard_ram[offset];
103 }
104 
static_mem_write(offs_t offset,uint8_t data)105 void fmt_icmem_device::static_mem_write(offs_t offset, uint8_t data)
106 {
107 	m_memcard_ram[offset] = data;
108 }
109 
mem_read(offs_t offset)110 uint8_t fmt_icmem_device::mem_read(offs_t offset)
111 {
112 	return m_memcard_ram[(m_bank*0x100000) + offset];
113 }
114 
mem_write(offs_t offset,uint8_t data)115 void fmt_icmem_device::mem_write(offs_t offset, uint8_t data)
116 {
117 	m_memcard_ram[(m_bank*0x100000) + offset] = data;
118 }
119 
120 // Memory Card status:
121 //  bit 0 - 0 = Write Enable, 1 = Write Protect
122 //  bit 1,2 - Card Detect - 00 = Card Inserted, 11 = No card inserted, 10 or 01 = Card error?
123 //  bit 3,4,5 - not memory card related (EEPROM and backup battery level)
124 //  bit 6 - unknown
125 //  bit 7 - 1 = card changed, flips back to 0 when read
status_r()126 uint8_t fmt_icmem_device::status_r()
127 {
128 	uint8_t ret = 0x00;
129 
130 	ret |= (m_writeprotect->read() & 0x01);
131 	if(is_readonly())  // if image is read-only, then set write protect.
132 		ret |= 0x01;
133 	if(!m_detect)
134 		ret |= 0x06;
135 	if(m_change)
136 		ret |= 0x80;
137 	m_change = false;
138 
139 	return ret;
140 }
141 
142 // Memory Card bank select (0x490)
143 //  bit 0-5: bank select (bits 0-3 not used in non-386SX systems?)
144 // Attribute/Common memory select (0x491)
145 //  bit 0: 0 = common memory, 1 = attribute memory (TODO)
146 //  bit 7: 0 indicates that card is JEIDA v4 compliant
bank_r(offs_t offset)147 uint8_t fmt_icmem_device::bank_r(offs_t offset)
148 {
149 	switch(offset)
150 	{
151 	case 0:
152 		return m_bank & 0x0f;
153 	case 1:
154 		return m_attr_select ? 1 : 0;
155 	}
156 	return 0xff;
157 }
158 
bank_w(offs_t offset,uint8_t data)159 void fmt_icmem_device::bank_w(offs_t offset, uint8_t data)
160 {
161 	switch(offset)
162 	{
163 	case 0:
164 		m_bank = data & 0x0f;
165 		break;
166 	case 1:
167 		m_attr_select = data & 0x01;
168 		break;
169 	}
170 }
171 
172