Skip to content

Commit d85a261

Browse files
committed
Add the ability to modify and save the ROM via the Cocoa memory view. Closes #685
1 parent 2f4a6f2 commit d85a261

File tree

4 files changed

+71
-19
lines changed

4 files changed

+71
-19
lines changed

Cocoa/Document.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,6 @@ enum model {
9494
- (int)loadStateFile:(const char *)path noErrorOnNotFound:(bool)noErrorOnFileNotFound;
9595
- (NSString *)captureOutputForBlock: (void (^)())block;
9696
- (NSFont *)debuggerFontOfSize:(unsigned)size;
97+
- (void)setROMModified;
9798
@end
9899

Cocoa/Document.m

Lines changed: 43 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ @implementation Document
120120
__weak NSThread *_emulationThread;
121121

122122
GBCheatSearchController *_cheatSearchController;
123+
124+
bool _romModified;
123125
}
124126

125127
static void boot_rom_load(GB_gameboy_t *gb, GB_boot_rom_t type)
@@ -1095,11 +1097,6 @@ - (void)initMemoryView
10951097
self.memoryBankItem.enabled = false;
10961098
}
10971099

1098-
+ (BOOL)autosavesInPlace
1099-
{
1100-
return true;
1101-
}
1102-
11031100
- (NSString *)windowNibName
11041101
{
11051102
// Override returning the nib file name of the document
@@ -1295,20 +1292,22 @@ - (int)loadROM
12951292
}
12961293

12971294
NSString *rom_warnings = [self captureOutputForBlock:^{
1298-
GB_debugger_clear_symbols(&_gb);
1299-
if ([[[fileName pathExtension] lowercaseString] isEqualToString:@"isx"]) {
1300-
ret = GB_load_isx(&_gb, fileName.UTF8String);
1301-
if (!self.isCartContainer) {
1302-
GB_load_battery(&_gb, [[self.fileURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"ram"].path.UTF8String);
1295+
if (!_romModified) {
1296+
GB_debugger_clear_symbols(&_gb);
1297+
if ([[[fileName pathExtension] lowercaseString] isEqualToString:@"isx"]) {
1298+
ret = GB_load_isx(&_gb, fileName.UTF8String);
1299+
if (!self.isCartContainer) {
1300+
GB_load_battery(&_gb, [[self.fileURL URLByDeletingPathExtension] URLByAppendingPathExtension:@"ram"].path.UTF8String);
1301+
}
1302+
}
1303+
else if ([[[fileName pathExtension] lowercaseString] isEqualToString:@"gbs"]) {
1304+
__block GB_gbs_info_t info;
1305+
ret = GB_load_gbs(&_gb, fileName.UTF8String, &info);
1306+
[self prepareGBSInterface:&info];
1307+
}
1308+
else {
1309+
ret = GB_load_rom(&_gb, [fileName UTF8String]);
13031310
}
1304-
}
1305-
else if ([[[fileName pathExtension] lowercaseString] isEqualToString:@"gbs"]) {
1306-
__block GB_gbs_info_t info;
1307-
ret = GB_load_gbs(&_gb, fileName.UTF8String, &info);
1308-
[self prepareGBSInterface:&info];
1309-
}
1310-
else {
1311-
ret = GB_load_rom(&_gb, [fileName UTF8String]);
13121311
}
13131312
if (GB_save_battery_size(&_gb)) {
13141313
if (!is_path_writeable(self.savPath.UTF8String)) {
@@ -1468,6 +1467,12 @@ - (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)anItem
14681467
else if ([anItem action] == @selector(reloadROM:)) {
14691468
return !_gbsTracks;
14701469
}
1470+
else if ([anItem action] == @selector(saveDocument:)) {
1471+
return _romModified;
1472+
}
1473+
else if ([anItem action] == @selector(saveDocumentAs:)) {
1474+
return _romModified && !self.isCartContainer;
1475+
}
14711476

14721477
return [super validateUserInterfaceItem:anItem];
14731478
}
@@ -2915,6 +2920,8 @@ - (IBAction)reloadROM:(id)sender
29152920
[self stop];
29162921
}
29172922

2923+
_romModified = false;
2924+
[self updateChangeCount:NSChangeCleared];
29182925
[self loadROM];
29192926

29202927
if (wasRunning) {
@@ -2969,6 +2976,24 @@ - (IBAction)debuggerButtonPressed:(NSButton *)sender
29692976
[self queueDebuggerCommand:sender.alternateTitle];
29702977
}
29712978

2979+
- (void)setROMModified
2980+
{
2981+
_romModified = true;
2982+
[self updateChangeCount:NSChangeDone];
2983+
}
2984+
2985+
- (BOOL)writeToFile:(NSString *)path ofType:(NSString *)type
2986+
{
2987+
if ([type isEqualToString:@"Game Boy Cartridge"]) {
2988+
if (![[NSFileManager defaultManager] copyItemAtPath:self.fileName toPath:path error:nil]) return false;
2989+
path = self.romPath;
2990+
if (!path) return false;
2991+
}
2992+
size_t size;
2993+
uint8_t *data = GB_get_direct_access(&_gb, GB_DIRECT_ACCESS_ROM, &size, NULL);
2994+
return [[NSData dataWithBytesNoCopy:data length:size freeWhenDone:false] writeToFile:path atomically:true];
2995+
}
2996+
29722997
+ (NSArray<NSString *> *)readableTypes
29732998
{
29742999
NSMutableSet *set = [NSMutableSet setWithArray:[super readableTypes]];

Cocoa/GBMemoryByteArray.m

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,17 @@ - (void)insertByteSlice:(HFByteSlice *)slice inRange:(HFRange)range
179179
case 0x5:
180180
case 0x6:
181181
case 0x7: {
182-
return; // ROM not writeable
182+
uint16_t bank;
183+
size_t size;
184+
uint8_t *data = GB_get_direct_access(gb, range.location < 0x4000? GB_DIRECT_ACCESS_ROM0 : GB_DIRECT_ACCESS_ROM, &size, &bank);
185+
if (_mode != GBMemoryEntireSpace && range.location >= 0x4000) {
186+
bank = self.selectedBank & (size / 0x4000 - 1);
187+
}
188+
uint8_t sliceData[range.length];
189+
[slice copyBytes:sliceData range:HFRangeMake(0, range.length)];
190+
memcpy(data + bank * 0x4000 + (range.location & 0x3FFF), sliceData, range.length);
191+
[_document setROMModified];
192+
break;
183193
}
184194
case 0x8:
185195
case 0x9: {

Cocoa/MainMenu.xib

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,21 @@
113113
<action selector="performClose:" target="-1" id="HmO-Ls-i7Q"/>
114114
</connections>
115115
</menuItem>
116+
<menuItem title="Save ROM Modifications" secondaryImage="square.and.arrow.down" catalog="system" keyEquivalent="s" id="Qru-qh-5Z6">
117+
<connections>
118+
<action selector="saveDocument:" target="-1" id="pnc-7c-MfV"/>
119+
</connections>
120+
</menuItem>
121+
<menuItem title="Save ROM Modifications As…" secondaryImage="square.and.arrow.down.on.square" catalog="system" keyEquivalent="S" id="VfB-dj-N2W">
122+
<connections>
123+
<action selector="saveDocumentAs:" target="-1" id="WoY-vv-bxg"/>
124+
</connections>
125+
</menuItem>
126+
<menuItem title="Reload ROM" secondaryImage="arrow.trianglehead.2.counterclockwise.rotate.90" catalog="system" keyEquivalent="R" id="taf-tK-jqI">
127+
<connections>
128+
<action selector="reloadROM:" target="-1" id="Uyv-4C-cYd"/>
129+
</connections>
130+
</menuItem>
116131
</items>
117132
</menu>
118133
</menuItem>
@@ -636,6 +651,7 @@
636651
<image name="speaker.slash" catalog="system" width="14" height="16"/>
637652
<image name="speaker.wave.3" catalog="system" width="22" height="15"/>
638653
<image name="square.and.arrow.down" catalog="system" width="15" height="17"/>
654+
<image name="square.and.arrow.down.on.square" catalog="system" width="18" height="20"/>
639655
<image name="square.and.arrow.up" catalog="system" width="15" height="18"/>
640656
<image name="text.page.badge.magnifyingglass" catalog="system" width="15" height="18"/>
641657
<image name="wrench.and.screwdriver" catalog="system" width="19" height="18"/>

0 commit comments

Comments
 (0)