forked from snesrev/zelda3
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcart.c
112 lines (98 loc) · 3.69 KB
/
cart.c
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
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#include "cart.h"
#include "snes.h"
static uint8_t cart_readLorom(Cart* cart, uint8_t bank, uint16_t adr);
static void cart_writeLorom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val);
static uint8_t cart_readHirom(Cart* cart, uint8_t bank, uint16_t adr);
static void cart_writeHirom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val);
Cart* cart_init(Snes* snes) {
Cart* cart = (Cart *)malloc(sizeof(Cart));
cart->snes = snes;
cart->type = 0;
cart->rom = NULL;
cart->romSize = 0;
cart->ramSize = 0x2000;
cart->ram = (uint8_t *)malloc(cart->ramSize);
return cart;
}
void cart_free(Cart* cart) {
free(cart);
}
void cart_reset(Cart* cart) {
if(cart->ramSize > 0 && cart->ram != NULL) memset(cart->ram, 0, cart->ramSize); // for now
}
void cart_saveload(Cart *cart, SaveLoadFunc *func, void *ctx) {
func(ctx, cart->ram, cart->ramSize);
}
void cart_load(Cart* cart, int type, uint8_t* rom, int romSize, int ramSize) {
cart->type = type;
if(cart->rom != NULL) free(cart->rom);
cart->rom = (uint8_t*)malloc(romSize);
cart->romSize = romSize;
assert(ramSize == cart->ramSize);
memset(cart->ram, 0, ramSize);
cart->ramSize = ramSize;
memcpy(cart->rom, rom, romSize);
}
uint8_t cart_read(Cart* cart, uint8_t bank, uint16_t adr) {
if (cart->type == 1)
return cart_readLorom(cart, bank, adr);
switch(cart->type) {
case 0: return cart->snes->openBus;
case 1:
case 2: return cart_readHirom(cart, bank, adr);
}
return cart->snes->openBus;
}
void cart_write(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val) {
switch(cart->type) {
case 0: break;
case 1: cart_writeLorom(cart, bank, adr, val); break;
case 2: cart_writeHirom(cart, bank, adr, val); break;
}
}
static uint8_t cart_readLorom(Cart* cart, uint8_t bank, uint16_t adr) {
if(adr >= 0x8000) {
// adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff
return cart->rom[((bank << 15) | (adr & 0x7fff)) & (cart->romSize - 1)];
}
if(((bank >= 0x70 && bank < 0x7e) || bank >= 0xf0) && adr < 0x8000 && cart->ramSize > 0) {
// banks 70-7e and f0-ff, adr 0000-7fff
return cart->ram[(((bank & 0xf) << 15) | adr) & (cart->ramSize - 1)];
}
if(bank & 0x40) {
// adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff
return cart->rom[((bank << 15) | (adr & 0x7fff)) & (cart->romSize - 1)];
}
return cart->snes->openBus;
}
static void cart_writeLorom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val) {
if(((bank >= 0x70 && bank < 0x7e) || bank > 0xf0) && adr < 0x8000 && cart->ramSize > 0) {
// banks 70-7e and f0-ff, adr 0000-7fff
cart->ram[(((bank & 0xf) << 15) | adr) & (cart->ramSize - 1)] = val;
}
}
static uint8_t cart_readHirom(Cart* cart, uint8_t bank, uint16_t adr) {
bank &= 0x7f;
if(bank < 0x40 && adr >= 0x6000 && adr < 0x8000 && cart->ramSize > 0) {
// banks 00-3f and 80-bf, adr 6000-7fff
return cart->ram[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (cart->ramSize - 1)];
}
if(adr >= 0x8000 || bank >= 0x40) {
// adr 8000-ffff in all banks or all addresses in banks 40-7f and c0-ff
return cart->rom[(((bank & 0x3f) << 16) | adr) & (cart->romSize - 1)];
}
return cart->snes->openBus;
}
static void cart_writeHirom(Cart* cart, uint8_t bank, uint16_t adr, uint8_t val) {
bank &= 0x7f;
if(bank < 0x40 && adr >= 0x6000 && adr < 0x8000 && cart->ramSize > 0) {
// banks 00-3f and 80-bf, adr 6000-7fff
cart->ram[(((bank & 0x3f) << 13) | (adr & 0x1fff)) & (cart->ramSize - 1)] = val;
}
}