2
* ds12c887rtc.c - DS12C887 RTC based cartridge emulation.
5
* Marco van den Heuvel <blackystardust68@yahoo.com>
7
* This file is part of VICE, the Versatile Commodore Emulator.
8
* See README for copyright notice.
10
* This program is free software; you can redistribute it and/or modify
11
* it under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful,
16
* but WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
* GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
33
#include "c64export.h"
35
#include "cartridge.h"
38
#include "ds12c887rtc.h"
42
#include "resources.h"
46
#include "translate.h"
49
DS12C887 RTC Cartridge
51
This cartridge is an RTC interface.
53
When inserted into the cart port the cart uses 2 registers,
54
one for setting the register being addressed and 1 for
55
reading/writing the RTC register. The base address can be
56
relocated to the following : $D500, $D600, $D700, $DE00, $DF00.
60
static int ds12c887rtc_enabled = 0;
62
/* RTC base address */
63
static int ds12c887rtc_base_address;
65
/* ---------------------------------------------------------------------*/
67
/* Some prototypes are needed */
68
static BYTE ds12c887rtc_read(WORD addr);
69
static void ds12c887rtc_store(WORD addr, BYTE byte);
71
static io_source_t ds12c887rtc_device = {
72
CARTRIDGE_NAME_DS12C887RTC,
81
CARTRIDGE_DS12C887RTC,
86
static io_source_list_t *ds12c887rtc_list_item = NULL;
88
static c64export_resource_t export_res = {
89
CARTRIDGE_NAME_DS12C887RTC, 0, 0, &ds12c887rtc_device, NULL, CARTRIDGE_DS12C887RTC
92
/* ds12c887 context */
93
static rtc_ds12c887_t *ds12c887rtc_context = NULL;
96
/* FIXME: Implement saving/setting/loading of the offset */
97
static time_t ds12c887rtc_offset = 0;
100
/* FIXME: Implement saving/loading of the ram */
101
static char ds12c887rtc_ram[128];
103
/* ---------------------------------------------------------------------*/
105
int ds12c887rtc_cart_enabled(void)
107
return ds12c887rtc_enabled;
110
static int set_ds12c887rtc_enabled(int val, void *param)
112
if (!ds12c887rtc_enabled && val) {
113
if (c64export_add(&export_res) < 0) {
116
ds12c887rtc_list_item = io_source_register(&ds12c887rtc_device);
117
ds12c887rtc_context = ds12c887_init((BYTE *)ds12c887rtc_ram, &ds12c887rtc_offset);
118
ds12c887rtc_enabled = 1;
119
} else if (ds12c887rtc_enabled && !val) {
120
if (ds12c887rtc_list_item != NULL) {
121
c64export_remove(&export_res);
122
io_source_unregister(ds12c887rtc_list_item);
123
ds12c887rtc_list_item = NULL;
124
ds12c887_destroy(ds12c887rtc_context);
126
ds12c887rtc_enabled = 0;
131
static int set_ds12c887rtc_base(int val, void *param)
134
int old = ds12c887rtc_enabled;
136
if (val == ds12c887rtc_base_address) {
140
if (addr == 0xffff) {
141
if (machine_class == VICE_MACHINE_VIC20) {
149
set_ds12c887rtc_enabled(0, NULL);
154
if (machine_class != VICE_MACHINE_VIC20) {
155
ds12c887rtc_device.start_address = (WORD)addr;
156
ds12c887rtc_device.end_address = (WORD)(addr + 1);
157
export_res.io1 = &ds12c887rtc_device;
158
export_res.io2 = NULL;
164
if (machine_class != VICE_MACHINE_VIC20) {
165
ds12c887rtc_device.start_address = (WORD)addr;
166
ds12c887rtc_device.end_address = (WORD)(addr + 1);
167
export_res.io1 = NULL;
168
export_res.io2 = &ds12c887rtc_device;
173
/* FIXME: $d100/$d200/$d300 base address handling still needs to be implemented */
180
if (machine_class != VICE_MACHINE_VIC20) {
181
ds12c887rtc_device.start_address = (WORD)addr;
182
ds12c887rtc_device.end_address = (WORD)(addr + 1);
183
export_res.io1 = NULL;
184
export_res.io2 = NULL;
191
if (machine_class != VICE_MACHINE_VIC20 && machine_class != VICE_MACHINE_C128) {
192
ds12c887rtc_device.start_address = (WORD)addr;
193
ds12c887rtc_device.end_address = (WORD)(addr + 1);
194
export_res.io1 = NULL;
195
export_res.io2 = NULL;
202
if (machine_class == VICE_MACHINE_VIC20) {
203
ds12c887rtc_device.start_address = (WORD)addr;
204
ds12c887rtc_device.end_address = (WORD)(addr + 1);
213
ds12c887rtc_base_address = val;
216
set_ds12c887rtc_enabled(1, NULL);
221
void ds12c887rtc_reset(void)
223
if (ds12c887rtc_context) {
224
ds12c887_reset(ds12c887rtc_context);
228
int ds12c887rtc_enable(void)
230
return resources_set_int("DS12C887RTC", 1);
233
void ds12c887rtc_detach(void)
235
resources_set_int("DS12C887RTC", 0);
238
/* ---------------------------------------------------------------------*/
240
static BYTE ds12c887rtc_read(WORD addr)
243
ds12c887rtc_device.io_source_valid = 1;
244
return ds12c887_read(ds12c887rtc_context);
247
ds12c887rtc_device.io_source_valid = 0;
252
static void ds12c887rtc_store(WORD addr, BYTE byte)
255
ds12c887_store_data(ds12c887rtc_context, byte);
257
ds12c887_store_address(ds12c887rtc_context, byte);
261
/* ---------------------------------------------------------------------*/
263
static const resource_int_t resources_int[] = {
264
{ "DS12C887RTC", 0, RES_EVENT_STRICT, (resource_value_t)0,
265
&ds12c887rtc_enabled, set_ds12c887rtc_enabled, NULL },
266
{ "DS12C887RTCbase", 0xffff, RES_EVENT_NO, NULL,
267
&ds12c887rtc_base_address, set_ds12c887rtc_base, NULL },
271
int ds12c887rtc_resources_init(void)
273
return resources_register_int(resources_int);
276
void ds12c887rtc_resources_shutdown(void)
278
if (ds12c887rtc_context) {
279
ds12c887_destroy(ds12c887rtc_context);
283
/* ---------------------------------------------------------------------*/
285
static const cmdline_option_t cmdline_options[] =
287
{ "-ds12c887rtc", SET_RESOURCE, 0,
288
NULL, NULL, "DS12C887RTC", (resource_value_t)1,
289
USE_PARAM_STRING, USE_DESCRIPTION_ID,
290
IDCLS_UNUSED, IDCLS_ENABLE_DS12C887RTC,
292
{ "+ds12c887rtc", SET_RESOURCE, 0,
293
NULL, NULL, "DS12C887RTC", (resource_value_t)0,
294
USE_PARAM_STRING, USE_DESCRIPTION_ID,
295
IDCLS_UNUSED, IDCLS_DISABLE_DS12C887RTC,
297
{ "-ds12c887rtcbase", SET_RESOURCE, 1,
298
NULL, NULL, "DS12C887RTCbase", NULL,
299
USE_PARAM_ID, USE_DESCRIPTION_ID,
300
IDCLS_P_BASE_ADDRESS, IDCLS_DS12C887RTC_BASE,
305
int ds12c887rtc_cmdline_options_init(void)
307
return cmdline_register_options(cmdline_options);
310
/* ---------------------------------------------------------------------*/
312
#define CART_DUMP_VER_MAJOR 0
313
#define CART_DUMP_VER_MINOR 0
314
#define SNAP_MODULE_NAME "CARTDS12C887RTC"
316
int ds12c887rtc_snapshot_write_module(snapshot_t *s)
318
snapshot_module_t *m;
320
m = snapshot_module_create(s, SNAP_MODULE_NAME,
321
CART_DUMP_VER_MAJOR, CART_DUMP_VER_MINOR);
326
/* FIXME: Implement the RTC snapshot part */
328
|| (SMW_DW(m, (DWORD)ds12c887rtc_base_address) < 0)) {
329
snapshot_module_close(m);
333
snapshot_module_close(m);
337
int ds12c887rtc_snapshot_read_module(snapshot_t *s)
340
snapshot_module_t *m;
341
int temp_ds12c887rtc_address;
343
m = snapshot_module_open(s, SNAP_MODULE_NAME, &vmajor, &vminor);
348
if ((vmajor != CART_DUMP_VER_MAJOR) || (vminor != CART_DUMP_VER_MINOR)) {
349
snapshot_module_close(m);
353
/* FIXME: Implement the RTC snapshot part */
355
|| (SMR_DW_INT(m, &temp_ds12c887rtc_address) < 0)) {
356
snapshot_module_close(m);
360
snapshot_module_close(m);
362
/* HACK set address to an invalid value, then use the function */
363
ds12c887rtc_base_address = -1;
364
set_ds12c887rtc_base(temp_ds12c887rtc_address, NULL);
366
return ds12c887rtc_enable();