1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
// license:BSD-3-Clause
// copyright-holders:Curt Coder
/*********************************************************************
cbm_crt.c
Commodore C64 cartridge images in .CRT format
This format was introduced in the CCS64 emulator by Per Hakan
Sundell.
Header info based on the VICE manual chapter 15.11, which in turn
is based on CRT.txt rev 1.14 compiled by Peter Schepers, with
additional contributions by Per Hakan Sundell, Markus Brenner,
and Marco Van Den Heuvel.
Relevant links:
http://vice-emu.sourceforge.net/vice_15.html#SEC300
http://ist.uwaterloo.ca/~schepers/formats/CRT.TXT (version 1.13, outdated)
Header Contents (bytes $0000-003F):
Bytes $0000-000F - 16-byte cartridge signature "C64 CARTRIDGE" (padded with spaces)
$0010-0013 - File header length
$0014-0015 - Cartridge version (high/low, presently 01.00)
$0016-0017 - Cartridge hardware type ($0000, high/low), see below
$0018 - Cartridge port EXROM line status (0 = inactive, 1 = active)
$0019 - Cartridge port GAME line status (0 = inactive, 1 = active)
$001A-001F - Reserved for future use
$0020-003F - 32-byte cartridge name (uppercase, padded with null characters)
CHIP Packet Contents (starting from $0040; there can be multiple CHIP packets
in a single CRT file):
Bytes $0040-0043 - Contained ROM signature "CHIP"
$0044-0047 - Total packet length (ROM image size and header combined) (high/low format)
$0048-0049 - Chip type (0 = ROM, 1 = RAM (no ROM data), 2 = Flash ROM)
$004A-004B - Bank number
$004C-004D - Starting load address (high/low format)
$004E-004F - ROM image size in bytes (high/low format, typically $2000 or $4000)
$0050-xxxx - ROM data
*********************************************************************/
#include "emu.h" // fatalerror
#include "corefile.h"
#include "cbm_crt.h"
//**************************************************************************
// MACROS/CONSTANTS
//**************************************************************************
#define LOG 0
// slot names for the C64 cartridge types
static const char * CRT_C64_SLOT_NAMES[_CRT_C64_COUNT] =
{
"standard", // 0 - Normal cartridge
UNSUPPORTED, // 1 - Action Replay
UNSUPPORTED, // 2 - KCS Power Cartridge
"final3", // 3 - Final Cartridge III
"simons_basic", // 4 - Simons' BASIC
"ocean", // 5 - Ocean type 1
UNSUPPORTED, // 6 - Expert Cartridge
"fun_play", // 7 - Fun Play, Power Play
"super_games", // 8 - Super Games
UNSUPPORTED, // 9 - Atomic Power
"epyxfastload", // 10 - Epyx Fastload
"westermann", // 11 - Westermann Learning
"rex", // 12 - Rex Utility
"final", // 13 - Final Cartridge I
"magic_formel", // 14 - Magic Formel
"system3", // 15 - C64 Game System, System 3
"warp_speed", // 16 - Warp Speed
"dinamic", // 17 - Dinamic
"zaxxon", // 18 - Zaxxon, Super Zaxxon (SEGA)
"magic_desk", // 19 - Magic Desk, Domark, HES Australia
UNSUPPORTED, // 20 - Super Snapshot V5
"comal80", // 21 - Comal-80
"struct_basic", // 22 - Structured BASIC
"ross", // 23 - Ross
"ep64", // 24 - Dela EP64
"ep7x8", // 25 - Dela EP7x8
"dela_ep256", // 26 - Dela EP256
"rex_ep256", // 27 - Rex EP256
"mikroasm", // 28 - Mikro Assembler
UNSUPPORTED, // 29 - Final Cartridge Plus
UNSUPPORTED, // 30 - Action Replay 4
"stardos", // 31 - Stardos
"easyflash", // 32 - EasyFlash
UNSUPPORTED, // 33 - EasyFlash Xbank
UNSUPPORTED, // 34 - Capture
UNSUPPORTED, // 35 - Action Replay 3
UNSUPPORTED, // 36 - Retro Replay
UNSUPPORTED, // 37 - MMC64
UNSUPPORTED, // 38 - MMC Replay
"ide64", // 39 - IDE64
UNSUPPORTED, // 40 - Super Snapshot V4
"ieee488", // 41 - IEEE-488
UNSUPPORTED, // 42 - Game Killer
"prophet64", // 43 - Prophet64
"exos", // 44 - EXOS
UNSUPPORTED, // 45 - Freeze Frame
UNSUPPORTED, // 46 - Freeze Machine
UNSUPPORTED, // 47 - Snapshot64
"super_explode", // 48 - Super Explode V5.0
"magic_voice", // 49 - Magic Voice
UNSUPPORTED, // 50 - Action Replay 2
"mach5", // 51 - MACH 5
UNSUPPORTED, // 52 - Diashow-Maker
"pagefox", // 53 - Pagefox
UNSUPPORTED, // 54 - ?
"silverrock" // 55 - Silverrock
};
//**************************************************************************
// IMPLEMENTATION
//**************************************************************************
//-------------------------------------------------
// cbm_crt_get_card - get slot interface card
//-------------------------------------------------
std::string cbm_crt_get_card(util::core_file &file)
{
// read the header
cbm_crt_header header;
file.read(&header, CRT_HEADER_LENGTH);
if (memcmp(header.signature, CRT_SIGNATURE, 16) == 0)
{
UINT16 hardware = pick_integer_be(header.hardware, 0, 2);
return std::string(CRT_C64_SLOT_NAMES[hardware]);
}
return std::string();
}
//-------------------------------------------------
// cbm_crt_read_header - read cartridge header
//-------------------------------------------------
bool cbm_crt_read_header(util::core_file &file, size_t *roml_size, size_t *romh_size, int *exrom, int *game)
{
// read the header
cbm_crt_header header;
file.read(&header, CRT_HEADER_LENGTH);
if (memcmp(header.signature, CRT_SIGNATURE, 16) != 0)
return false;
UINT16 hardware = pick_integer_be(header.hardware, 0, 2);
*exrom = header.exrom;
*game = header.game;
if (LOG)
{
osd_printf_verbose("Name: %s\n", header.name);
osd_printf_verbose("Hardware: %04x\n", hardware);
osd_printf_verbose("Slot device: %s\n", CRT_C64_SLOT_NAMES[hardware]);
osd_printf_verbose("EXROM: %u\n", header.exrom);
osd_printf_verbose("GAME: %u\n", header.game);
}
// determine ROM region lengths
while (!file.eof())
{
cbm_crt_chip chip;
file.read(&chip, CRT_CHIP_LENGTH);
UINT16 address = pick_integer_be(chip.start_address, 0, 2);
UINT16 size = pick_integer_be(chip.image_size, 0, 2);
UINT16 type = pick_integer_be(chip.chip_type, 0, 2);
if (LOG)
{
osd_printf_verbose("CHIP Address: %04x\n", address);
osd_printf_verbose("CHIP Size: %04x\n", size);
osd_printf_verbose("CHIP Type: %04x\n", type);
}
switch (address)
{
case 0x8000: *roml_size += size; break;
case 0xa000: *romh_size += size; break;
case 0xe000: *romh_size += size; break;
default: osd_printf_verbose("Invalid CHIP loading address!\n"); break;
}
file.seek(size, SEEK_CUR);
}
return true;
}
//-------------------------------------------------
// cbm_crt_read_data - read cartridge data
//-------------------------------------------------
bool cbm_crt_read_data(util::core_file &file, UINT8 *roml, UINT8 *romh)
{
UINT32 roml_offset = 0;
UINT32 romh_offset = 0;
file.seek(CRT_HEADER_LENGTH, SEEK_SET);
while (!file.eof())
{
cbm_crt_chip chip;
file.read(&chip, CRT_CHIP_LENGTH);
UINT16 address = pick_integer_be(chip.start_address, 0, 2);
UINT16 size = pick_integer_be(chip.image_size, 0, 2);
switch (address)
{
case 0x8000: file.read(roml + roml_offset, size); roml_offset += size; break;
case 0xa000: file.read(romh + romh_offset, size); romh_offset += size; break;
case 0xe000: file.read(romh + romh_offset, size); romh_offset += size; break;
}
}
return true;
}
|