1 /*
2 * KCemu -- The emulator for the KC85 homecomputer series and much more.
3 * Copyright (C) 1997-2010 Torsten Paul
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #include <stdio.h>
21 #include <string.h>
22
23 #include "kc/system.h"
24
25 #include "kc/kc.h"
26 #include "kc/mod_segm.h"
27
ModuleSegmentedMemory(ModuleSegmentedMemory & tmpl)28 ModuleSegmentedMemory::ModuleSegmentedMemory(ModuleSegmentedMemory &tmpl) :
29 ModuleInterface(tmpl.get_name(), tmpl.get_id(), tmpl.get_type())
30 {
31 _val = 0;
32 _group = NULL;
33 _master = false;
34 _is_rom = tmpl._is_rom;
35 _segments = tmpl.get_segment_count();
36 _segment_size = tmpl.get_segment_size();
37
38 if (is_rom())
39 {
40 _mem = tmpl._mem;
41 set_valid(true);
42 }
43 else
44 {
45 int mem_size = get_segment_count() * get_segment_size();
46 _mem = new byte_t[mem_size];
47 if (_mem)
48 {
49 reset(true);
50 set_valid(true);
51 }
52 }
53 }
54
ModuleSegmentedMemory(const char * name,byte_t id,int segments,int segment_size)55 ModuleSegmentedMemory::ModuleSegmentedMemory(const char *name, byte_t id, int segments, int segment_size) :
56 ModuleInterface(name, id, KC_MODULE_KC_85_3)
57 {
58 _val = 0;
59 _mem = NULL;
60 _group = NULL;
61 _master = true;
62 _is_rom = false;
63 _segments = segments;
64 _segment_size = segment_size;
65
66 set_valid(true);
67 }
68
ModuleSegmentedMemory(const char * name,byte_t id,int segments,int segment_size,const char * filename)69 ModuleSegmentedMemory::ModuleSegmentedMemory(const char *name, byte_t id, int segments, int segment_size, const char *filename) :
70 ModuleInterface(name, id, KC_MODULE_KC_85_3)
71 {
72 int mem_size = segments * segment_size;
73
74 _val = 0;
75 _group = NULL;
76 _master = true;
77 _is_rom = true;
78 _segments = segments;
79 _segment_size = segment_size;
80 _mem = new byte_t[mem_size];
81
82 set_valid(Memory::load_rom(filename, _mem, mem_size, false));
83 }
84
~ModuleSegmentedMemory(void)85 ModuleSegmentedMemory::~ModuleSegmentedMemory(void)
86 {
87 if (_group)
88 memory->unregister_memory(_group);
89 if (_master && _mem)
90 delete[] _mem;
91 }
92
93 bool
is_rom(void)94 ModuleSegmentedMemory::is_rom(void)
95 {
96 return _is_rom;
97 }
98
99 int
get_segment_count(void)100 ModuleSegmentedMemory::get_segment_count(void)
101 {
102 return _segments;
103 }
104
105 int
get_segment_size(void)106 ModuleSegmentedMemory::get_segment_size(void)
107 {
108 return _segment_size;
109 }
110
111 void
m_out(word_t addr,byte_t val)112 ModuleSegmentedMemory::m_out(word_t addr, byte_t val)
113 {
114 if (_val == val)
115 return;
116
117 _val = val;
118
119 if (_group)
120 {
121 memory->unregister_memory(_group);
122 _group = NULL;
123 }
124
125 if (_val & 1)
126 {
127 char buf[100];
128
129 int idx = get_segment_index(addr, val);
130 word_t mem = get_base_address(addr, val);
131 bool ro = is_rom() ? true : (_val & 2) == 0;
132
133 snprintf(buf, sizeof(buf), "%s (%d)", get_name(), idx);
134 _group = memory->register_memory(buf,
135 mem,
136 get_segment_size(),
137 &_mem[idx * get_segment_size()],
138 0x10,
139 ro);
140 }
141 }
142
143 void
reset(bool power_on)144 ModuleSegmentedMemory::reset(bool power_on)
145 {
146 if (is_rom())
147 return;
148
149 if (power_on)
150 Memory::scratch_mem(_mem, get_segment_count() * get_segment_size());
151 }
152