comparison sega_mapper.c @ 2052:3748a2a8a4b7

Support Sega mapper without 'SEGA SSF' in header or ROM DB entry and implement a subset of the extended Sega mapper implemented in the Mega Everdrive when 'SEGA SSF' is present
author Michael Pavone <pavone@retrodev.com>
date Sat, 01 Jan 2022 18:54:46 -0800
parents d60f2d7c02a5
children b6fdedd3b070
comparison
equal deleted inserted replaced
2051:97bfb6089274 2052:3748a2a8a4b7
1 #include "genesis.h" 1 #include "genesis.h"
2 #include "util.h"
2 3
3 uint16_t read_sram_w(uint32_t address, m68k_context * context) 4 uint16_t read_sram_w(uint32_t address, m68k_context * context)
4 { 5 {
5 genesis_context * gen = context->system; 6 genesis_context * gen = context->system;
6 address &= gen->save_ram_mask; 7 address &= gen->save_ram_mask;
41 } 42 }
42 43
43 m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value) 44 m68k_context * write_sram_area_w(uint32_t address, m68k_context * context, uint16_t value)
44 { 45 {
45 genesis_context * gen = context->system; 46 genesis_context * gen = context->system;
47 if (gen->mapper_type == MAPPER_SEGA_MED_V2) {
48 if (gen->bank_regs[8] & 0x20) {
49 uint32_t bank = address >> 19;
50 address &= 0x7FFFF;
51 context->mem_pointers[gen->mapper_start_index + bank][address >> 1] = value;
52 }
53 return context;
54 }
46 if ((gen->bank_regs[0] & 0x3) == 1) { 55 if ((gen->bank_regs[0] & 0x3) == 1) {
47 address &= gen->save_ram_mask; 56 address &= gen->save_ram_mask;
48 switch(gen->save_type) 57 switch(gen->save_type)
49 { 58 {
50 case RAM_FLAG_BOTH: 59 case RAM_FLAG_BOTH:
85 } 94 }
86 } 95 }
87 return context; 96 return context;
88 } 97 }
89 98
99 static void* write_med_ram_w(uint32_t address, void *vcontext, uint16_t value, uint16_t bank)
100 {
101 m68k_context *context = vcontext;
102 genesis_context * gen = context->system;
103 if (gen->bank_regs[8] & 0x20) {
104 context->mem_pointers[gen->mapper_start_index + bank][address >> 1] = value;
105 address += bank * 0x80000;
106 m68k_invalidate_code_range(gen->m68k, address, address + 2);
107 }
108 return vcontext;
109 }
110
111 void* write_med_ram0_w(uint32_t address, void *vcontext, uint16_t value)
112 {
113 return write_med_ram_w(address, vcontext, value, 0);
114 }
115
116 void* write_med_ram1_w(uint32_t address, void *vcontext, uint16_t value)
117 {
118 return write_med_ram_w(address, vcontext, value, 1);
119 }
120
121 void* write_med_ram2_w(uint32_t address, void *vcontext, uint16_t value)
122 {
123 return write_med_ram_w(address, vcontext, value, 2);
124 }
125
126 void* write_med_ram3_w(uint32_t address, void *vcontext, uint16_t value)
127 {
128 return write_med_ram_w(address, vcontext, value, 3);
129 }
130
131 void* write_med_ram4_w(uint32_t address, void *vcontext, uint16_t value)
132 {
133 return write_med_ram_w(address, vcontext, value, 4);
134 }
135
136 void* write_med_ram5_w(uint32_t address, void *vcontext, uint16_t value)
137 {
138 return write_med_ram_w(address, vcontext, value, 5);
139 }
140
141 void* write_med_ram6_w(uint32_t address, void *vcontext, uint16_t value)
142 {
143 return write_med_ram_w(address, vcontext, value, 6);
144 }
145
146 void* write_med_ram7_w(uint32_t address, void *vcontext, uint16_t value)
147 {
148 return write_med_ram_w(address, vcontext, value, 7);
149 }
150
151 static void* write_med_ram_b(uint32_t address, void *vcontext, uint8_t value, uint16_t bank)
152 {
153 m68k_context *context = vcontext;
154 genesis_context * gen = context->system;
155 if (gen->bank_regs[8] & 0x20) {
156 ((uint8_t*)context->mem_pointers[gen->mapper_start_index + bank])[address ^ 1] = value;
157 address += bank * 0x80000;
158 m68k_invalidate_code_range(gen->m68k, address, address + 1);
159 }
160 return vcontext;
161 }
162
163 void* write_med_ram0_b(uint32_t address, void *vcontext, uint8_t value)
164 {
165 return write_med_ram_b(address, vcontext, value, 0);
166 }
167
168 void* write_med_ram1_b(uint32_t address, void *vcontext, uint8_t value)
169 {
170 return write_med_ram_b(address, vcontext, value, 1);
171 }
172
173 void* write_med_ram2_b(uint32_t address, void *vcontext, uint8_t value)
174 {
175 return write_med_ram_b(address, vcontext, value, 2);
176 }
177
178 void* write_med_ram3_b(uint32_t address, void *vcontext, uint8_t value)
179 {
180 return write_med_ram_b(address, vcontext, value, 3);
181 }
182
183 void* write_med_ram4_b(uint32_t address, void *vcontext, uint8_t value)
184 {
185 return write_med_ram_b(address, vcontext, value, 4);
186 }
187
188 void* write_med_ram5_b(uint32_t address, void *vcontext, uint8_t value)
189 {
190 return write_med_ram_b(address, vcontext, value, 5);
191 }
192
193 void* write_med_ram6_b(uint32_t address, void *vcontext, uint8_t value)
194 {
195 return write_med_ram_b(address, vcontext, value, 6);
196 }
197
198 void* write_med_ram7_b(uint32_t address, void *vcontext, uint8_t value)
199 {
200 return write_med_ram_b(address, vcontext, value, 7);
201 }
202
90 m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value) 203 m68k_context * write_bank_reg_w(uint32_t address, m68k_context * context, uint16_t value)
91 { 204 {
92 genesis_context * gen = context->system; 205 genesis_context * gen = context->system;
93 address &= 0xE; 206 address &= 0xE;
94 address >>= 1; 207 address >>= 1;
95 gen->bank_regs[address] = value;
96 if (!address) { 208 if (!address) {
97 if (value & 1) { 209 if (gen->mapper_type == MAPPER_SEGA_MED_V2) {
210 if (!value & 0x8000) {
211 //writes without protection bit set are ignored
212 return context;
213 }
214 gen->bank_regs[8] = value >> 8;
215 void *new_ptr = gen->cart + 0x40000*(value & 0x1F);
216 if (context->mem_pointers[gen->mapper_start_index] != new_ptr) {
217 m68k_invalidate_code_range(gen->m68k, 0, 0x80000);
218 context->mem_pointers[gen->mapper_start_index] = new_ptr;
219 }
220 } else if (value & 1) {
98 //Used for games that only use the mapper for SRAM 221 //Used for games that only use the mapper for SRAM
99 if (context->mem_pointers[gen->mapper_start_index]) { 222 if (context->mem_pointers[gen->mapper_start_index]) {
100 gen->mapper_temp = context->mem_pointers[gen->mapper_start_index]; 223 gen->mapper_temp = context->mem_pointers[gen->mapper_start_index];
101 } 224 }
102 context->mem_pointers[gen->mapper_start_index] = NULL; 225 context->mem_pointers[gen->mapper_start_index] = NULL;
114 for (int i = 4; i < 8; i++) 237 for (int i = 4; i < 8; i++)
115 { 238 {
116 context->mem_pointers[gen->mapper_start_index + i] = gen->cart + 0x40000*gen->bank_regs[i]; 239 context->mem_pointers[gen->mapper_start_index + i] = gen->cart + 0x40000*gen->bank_regs[i];
117 } 240 }
118 } 241 }
119 } else if (gen->mapper_type == MAPPER_SEGA) { 242 } else if (gen->mapper_type != MAPPER_SEGA_SRAM) {
120 void *new_ptr = gen->cart + 0x40000*value; 243 uint32_t mask = ((gen->mapper_type == MAPPER_SEGA_MED_V2 ? (16 *1024 * 1024) : nearest_pow2(gen->header.info.rom_size)) >> 1) - 1;
244 void *new_ptr = gen->cart + ((0x40000*value) & mask);
121 if (context->mem_pointers[gen->mapper_start_index + address] != new_ptr) { 245 if (context->mem_pointers[gen->mapper_start_index + address] != new_ptr) {
122 m68k_invalidate_code_range(gen->m68k, address * 0x80000, (address + 1) * 0x80000); 246 m68k_invalidate_code_range(gen->m68k, address * 0x80000, (address + 1) * 0x80000);
123 context->mem_pointers[gen->mapper_start_index + address] = new_ptr; 247 context->mem_pointers[gen->mapper_start_index + address] = new_ptr;
124 } 248 }
125 } 249 }
250 gen->bank_regs[address] = value;
126 return context; 251 return context;
127 } 252 }
128 253
129 m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value) 254 m68k_context * write_bank_reg_b(uint32_t address, m68k_context * context, uint8_t value)
130 { 255 {
131 if (address & 1) { 256 genesis_context * gen = context->system;
257 if (gen->mapper_type == MAPPER_SEGA_MED_V2) {
258 address &= 0xF;
259 if (!address) {
260 //not sure if this is correct, possible byte sized writes are always rejected to $A130F0
261 write_bank_reg_w(address, context, value << 8 | value);
262 } else if (address > 2 && (address & 1)) {
263 write_bank_reg_w(address, context, value);
264 }
265 } else if (address & 1) {
132 write_bank_reg_w(address, context, value); 266 write_bank_reg_w(address, context, value);
133 } 267 }
134 return context; 268 return context;
135 } 269 }
136 270
137 void sega_mapper_serialize(genesis_context *gen, serialize_buffer *buf) 271 void sega_mapper_serialize(genesis_context *gen, serialize_buffer *buf)
138 { 272 {
139 save_buffer8(buf, gen->bank_regs, sizeof(gen->bank_regs)); 273 save_buffer8(buf, gen->bank_regs, gen->mapper_type == MAPPER_SEGA_MED_V2 ? sizeof(gen->bank_regs) : sizeof(gen->bank_regs) - 1);
140 } 274 }
141 275
142 void sega_mapper_deserialize(deserialize_buffer *buf, genesis_context *gen) 276 void sega_mapper_deserialize(deserialize_buffer *buf, genesis_context *gen)
143 { 277 {
144 for (int i = 0; i < sizeof(gen->bank_regs); i++) 278 if (gen->mapper_type == MAPPER_SEGA_MED_V2) {
145 { 279 uint16_t reg0 = load_int8(buf);
146 write_bank_reg_w(i * 2, gen->m68k, load_int8(buf)); 280 for (int i = 1; i < sizeof(gen->bank_regs) - 1; i++)
147 } 281 {
148 } 282 write_bank_reg_w(i * 2, gen->m68k, load_int8(buf));
283 }
284 reg0 |= load_int8(buf) << 8;
285 write_bank_reg_w(0, gen->m68k, reg0);
286 } else {
287 for (int i = 0; i < sizeof(gen->bank_regs) - 1; i++)
288 {
289 write_bank_reg_w(i * 2, gen->m68k, load_int8(buf));
290 }
291 }
292 }