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 <iostream>
22 #include <iomanip>
23 
24 #include "kc/system.h"
25 
26 #include "kc/kc.h"
27 #include "kc/ports4.h"
28 #include "kc/memory4.h"
29 
30 #include "libdbg/dbg.h"
31 
32 #define memory ((Memory4 *)memory)
33 
Ports4(void)34 Ports4::Ports4(void)
35 {
36   for (int a = 0;a < NR_PORTS;a++)
37     inout[a] = -1;
38 }
39 
~Ports4(void)40 Ports4::~Ports4(void)
41 {
42 }
43 
44 byte_t
in(word_t addr)45 Ports4::in(word_t addr)
46 {
47   byte_t a = addr & 0xff;
48   byte_t val = inout[a];
49 
50   switch (a)
51     {
52     case 0x84:
53     case 0x86:
54       break;
55     default:
56       DBG(0, form("KCemu/internal_error",
57 		  "Ports4: called in() with undefined address %04xh\n",
58 		  addr));
59       break;
60     }
61 
62   DBG(2, form("KCemu/Ports/4/in",
63 	      "Ports4: in() addr = %04x (returning %02x)\n",
64 	      addr, val));
65 
66   return val;
67 }
68 
69 void
out(word_t addr,byte_t val)70 Ports4::out(word_t addr, byte_t val)
71 {
72   byte_t a = addr & 0xff;
73 
74   DBG(2, form("KCemu/Ports/4/out",
75               "Ports4: out() addr = %04x, val = %02x\n",
76               addr, val));
77 
78   switch (a)
79     {
80     case 0x84:
81       if (inout[0x84] < 0)
82 	inout[0x84] = ~val;
83       change_0x84(inout[0x84] ^ val, val);
84       break;
85     case 0x86:
86       if (inout[0x86] < 0)
87 	inout[0x86] = ~val;
88       change_0x86(inout[0x86] ^ val, val);
89       break;
90     default:
91       DBG(0, form("KCemu/internal_error",
92 		  "Ports4: called out() with undefined address %04xh (val = %02xh)\n",
93 		  addr, val));
94       break;
95     }
96 
97   inout[addr & 0xff] = val;
98 }
99 
100 void
change_0x84(byte_t changed,byte_t val)101 Ports4::change_0x84(byte_t changed, byte_t val)
102 {
103   if (changed & 0x01)
104     {
105       DBG(2, form("KCemu/Ports/4/change/84",
106                   "Ports 0x84: display screen %d\n",
107                   val & 1));
108       memory->displaySCREEN_1(val & 0x01);
109     }
110   if (changed & 0x02)
111     {
112       DBG(2, form("KCemu/Ports/4/change/84",
113                   "Ports 0x84: pixel/ color %d\n",
114                   (val >> 1) & 1));
115       memory->enableCOLOR(val & 0x02);
116     }
117   if (changed & 0x04)
118     {
119       DBG(2, form("KCemu/Ports/4/change/84",
120                   "Ports 0x84: access screen %d\n",
121                   (val >> 2) & 1));
122       memory->enableSCREEN_1(val & 0x04);
123     }
124   if (changed & 0x08)
125     {
126       DBG(2, form("KCemu/Ports/4/change/84",
127                   "Ports 0x84: high resolution %d\n",
128                   (val >> 3) & 1));
129     }
130   if (changed & 0xf0)
131     {
132       DBG(2, form("KCemu/Ports/4/change/84",
133                   "Ports 0x84: access RAM8 segment %d\n",
134                   (val >> 4) & 0x0f));
135       memory->selectRAM_8((val >> 4) & 0x0f);
136     }
137 }
138 
139 void
change_0x86(byte_t changed,byte_t val)140 Ports4::change_0x86(byte_t changed, byte_t val)
141 {
142   if (changed & 0x01)
143     {
144       DBG(2, form("KCemu/Ports/4/change/86",
145                   "Ports 0x86: RAM 4 %d\n",
146                   val & 1));
147       memory->enableRAM_4(val & 0x01);
148     }
149   if (changed & 0x02)
150     {
151       DBG(2, form("KCemu/Ports/4/change/86",
152                   "Ports 0x86: write protect RAM 4 %d\n",
153                   (val >> 1) & 1));
154       memory->protectRAM_4(val & 0x02);
155     }
156   if (changed & 0x04)
157     {
158       DBG(2, form("KCemu/Ports/4/change/86",
159                   "Ports 0x86: unused 0x04 %d\n",
160                   (val >> 2) & 1));
161     }
162   if (changed & 0x08)
163     {
164       DBG(2, form("KCemu/Ports/4/change/86",
165                   "Ports 0x86: unused 0x08 %d\n",
166                   (val >> 3) & 1));
167     }
168   if (changed & 0x10)
169     {
170       DBG(2, form("KCemu/Ports/4/change/86",
171                   "Ports 0x86: unused 0x10 %d\n",
172                   (val >> 4) & 1));
173     }
174   if (changed & 0x60)
175     {
176       DBG(2, form("KCemu/Ports/4/change/86",
177                   "Ports 0x86: BASIC/USER ROM bank %d\n",
178                   (val >> 5) & 3));
179       memory->selectROM_C((val >> 5) & 3);
180     }
181   if (changed & 0x80)
182     {
183       DBG(2, form("KCemu/Ports/4/change/86",
184                   "Ports 0x86: CAOS C %d\n",
185                   (val >> 7) & 1));
186       memory->enableCAOS_C(val & 0x80);
187     }
188 }
189