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 <string.h>
21 #include <fstream>
22 #include <iostream>
23 
24 #include "kc/system.h"
25 
26 #include "kc/kc.h"
27 #include "kc/mod_disk.h"
28 
29 #include "libdbg/dbg.h"
30 
ModuleDisk(ModuleDisk & tmpl)31 ModuleDisk::ModuleDisk(ModuleDisk &tmpl) : ModuleROM(tmpl)
32 {
33   _val = 0;
34   _slot = tmpl._slot;
35 }
36 
ModuleDisk(const char * rom_key,const char * name,byte_t id,int slot)37 ModuleDisk::ModuleDisk(const char *rom_key, const char *name, byte_t id, int slot) :
38   ModuleROM(rom_key, name, id)
39 {
40   _val = 0;
41   _slot = slot;
42 }
43 
~ModuleDisk(void)44 ModuleDisk::~ModuleDisk(void)
45 {
46 }
47 
48 word_t
get_addr(byte_t val)49 ModuleDisk::get_addr(byte_t val)
50 {
51   return (val & 0x20) ? 0xe000 : 0xc000;
52 }
53 
54 /*
55  *  SWITCH FC kk-------------------
56  *                                |
57  *                                |
58  *          ---------------------------------
59  *   Bit    | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
60  *          ---------------------------------
61  *                    |           |       |          Bit  1/0
62  *                    |           |       ---- ROM       on/off
63  *                    |           ----------- Kopplung   on/off
64  *                    ------------------- Basisadresse E000/C000
65  *
66  */
67 void
m_out(word_t addr,byte_t val)68 ModuleDisk::m_out(word_t addr, byte_t val)
69 {
70   bool unreg, reg;
71 
72   if (((_val & 0x25) ^ (val & 0x25)) == 0)
73     return;
74 
75   word_t map_addr = get_addr(val);
76 
77   DBG(2, form("KCemu/ModuleDisk/out",
78 	      "ModuleDisk::out(): %s: addr = %04x, val = %02x, old val = %02x\n",
79               get_name(), addr, val, _val));
80 
81   // The module interface allows us to snoop on slots F8 and FC at
82   // the same time. So we can disable the memory of the not accessed
83   // slot.
84   reg = unreg = false;
85   if (((addr >> 8) & 0xfc) != _slot)
86     {
87       DBG(2, form("KCemu/ModuleDisk/out",
88                   "ModuleDisk::out(): %s: I/O to module on other port detected!\n",
89                   get_name()));
90       reg = false;
91       unreg = true;
92     }
93   else
94     {
95       if ((_val & 0x20) ^ (val & 0x20))
96         {
97           DBG(2, form("KCemu/ModuleDisk/out",
98                       "ModuleDisk::out(): %s: new map address is %04x\n",
99                       get_name(), map_addr));
100           reg = unreg = true;
101         }
102 
103       if ((_val & 0x04) ^ (val & 0x04))
104         {
105           DBG(2, form("KCemu/ModuleDisk/out",
106                       "ModuleDisk::out(): %s: shared memory is now %s\n",
107                       get_name(), (val & 0x04) ? "on" : "off"));
108         }
109 
110       if ((_val & 0x01) ^ (val & 0x01))
111         {
112           if (val & 1)
113             reg = true;
114           else
115             reg = false;
116         }
117 
118     }
119 
120   if (unreg)
121     if (_group)
122       {
123         if (_group) memory->unregister_memory(_group);
124         _group = 0;
125       }
126 
127   if (reg)
128     _group = memory->register_memory(get_name(), map_addr, _size,
129                                      _rom, (addr >> 8), true);
130 
131   _val = val;
132 }
133 
134 ModuleInterface *
clone(void)135 ModuleDisk::clone(void)
136 {
137   return new ModuleDisk(*this);
138 }
139