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