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