git.y1.nz

SameBoy

Accurate GB/GBC emulator
download: https://git.y1.nz/archives/sameboy.tar.gz
README | Files | Log | Refs | LICENSE

commit d5ff93af3bcd3f1e0845d2ee5b7080307d1ebfe8
parent c06e320b9579a5b8c1177ca1218ed8c87d57798c
Author: Lior Halphon <LIJI32@gmail.com>
Date:   Mon, 30 Jan 2023 22:42:03 +0200

Emulate GB printer timer, letting one emulate the mini game in Hello Kitty Pocket Camera. Closes #290

Diffstat:
MCocoa/Document.h1+
MCocoa/Document.m22++++++++++++++++++----
MCocoa/Document.xib11++++++++++-
MCore/gb.h1+
MCore/printer.c21+++++++++++----------
MCore/printer.h5++++-
MCore/timing.c18++++++++++++++++--
7 files changed, 61 insertions(+), 18 deletions(-)

diff --git a/Cocoa/Document.h b/Cocoa/Document.h @@ -35,6 +35,7 @@ @property (nonatomic, strong) IBOutlet GBPaletteView *paletteView; @property (nonatomic, strong) IBOutlet GBObjectView *objectView; @property (nonatomic, strong) IBOutlet NSPanel *printerFeedWindow; +@property (nonatomic, strong) IBOutlet NSProgressIndicator *printerSpinner; @property (nonatomic, strong) IBOutlet NSImageView *feedImageView; @property (nonatomic, strong) IBOutlet NSTextView *debuggerSideViewInput; @property (nonatomic, strong) IBOutlet NSTextView *debuggerSideView; diff --git a/Cocoa/Document.m b/Cocoa/Document.m @@ -180,6 +180,12 @@ static void printImage(GB_gameboy_t *gb, uint32_t *image, uint8_t height, [self printImage:image height:height topMargin:top_margin bottomMargin:bottom_margin exposure:exposure]; } +static void printDone(GB_gameboy_t *gb) +{ + Document *self = (__bridge Document *)GB_get_user_data(gb); + [self printDone]; +} + static void setWorkboyTime(GB_gameboy_t *gb, time_t t) { [[NSUserDefaults standardUserDefaults] setInteger:time(NULL) - t forKey:@"GBWorkboyTimeOffset"]; @@ -2060,9 +2066,9 @@ static bool is_path_writeable(const char *path) [self reloadVRAMData: nil]; } -- (void) printImage:(uint32_t *)imageBytes height:(unsigned) height - topMargin:(unsigned) topMargin bottomMargin: (unsigned) bottomMargin - exposure:(unsigned) exposure +- (void)printImage:(uint32_t *)imageBytes height:(unsigned) height + topMargin:(unsigned) topMargin bottomMargin: (unsigned) bottomMargin + exposure:(unsigned) exposure { uint32_t paddedImage[160 * (topMargin + height + bottomMargin)]; memset(paddedImage, 0xFF, sizeof(paddedImage)); @@ -2073,6 +2079,7 @@ static bool is_path_writeable(const char *path) [currentPrinterImageData appendBytes:paddedImage length:sizeof(paddedImage)]; /* UI related code must run on main thread. */ dispatch_async(dispatch_get_main_queue(), ^{ + [_printerSpinner startAnimation:nil]; self.feedImageView.image = [Document imageFromData:currentPrinterImageData width:160 height:currentPrinterImageData.length / 160 / sizeof(imageBytes[0]) @@ -2087,6 +2094,13 @@ static bool is_path_writeable(const char *path) } +- (void)printDone +{ + dispatch_async(dispatch_get_main_queue(), ^{ + [_printerSpinner stopAnimation:nil]; + }); +} + - (void)printDocument:(id)sender { if (self.feedImageView.image.size.height == 0) { @@ -2135,7 +2149,7 @@ static bool is_path_writeable(const char *path) [self disconnectLinkCable]; [self performAtomicBlock:^{ accessory = GBAccessoryPrinter; - GB_connect_printer(&gb, printImage); + GB_connect_printer(&gb, printImage, printDone); }]; } diff --git a/Cocoa/Document.xib b/Cocoa/Document.xib @@ -35,6 +35,7 @@ <outlet property="osdView" destination="MX4-l2-7NE" id="Am7-fq-uvu"/> <outlet property="paletteView" destination="ZuP-AU-0pA" id="ef6-27-Bci"/> <outlet property="printerFeedWindow" destination="NdE-0B-WCf" id="yVK-cS-NOJ"/> + <outlet property="printerSpinner" destination="rrz-Uh-Nae" id="CI8-Y2-s3l"/> <outlet property="tilemapImageView" destination="LlK-tV-bjv" id="nSY-Xd-BjZ"/> <outlet property="tilemapMapButton" destination="YIJ-Qc-SIZ" id="BB7-Gg-7XP"/> <outlet property="tilemapPaletteButton" destination="loB-0k-Qff" id="2Or-7l-6vn"/> @@ -680,11 +681,19 @@ <toolbarItem implicitItemIdentifier="NSToolbarPrintItem" explicitItemIdentifier="Print" id="mtd-zS-DXa"/> <toolbarItem implicitItemIdentifier="NSToolbarSpaceItem" id="AoG-LH-J4b"/> <toolbarItem implicitItemIdentifier="NSToolbarFlexibleSpaceItem" id="Q0x-n5-Q2Y"/> + <toolbarItem implicitItemIdentifier="E8F74F8F-6DE2-4774-A690-F71D92CD932E" label="" paletteLabel="" tag="-1" sizingBehavior="auto" id="CJX-Ff-7iQ"> + <nil key="toolTip"/> + <progressIndicator key="view" wantsLayer="YES" maxValue="100" displayedWhenStopped="NO" indeterminate="YES" style="spinning" id="rrz-Uh-Nae"> + <rect key="frame" x="0.0" y="14" width="32" height="32"/> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> + </progressIndicator> + </toolbarItem> </allowedToolbarItems> <defaultToolbarItems> <toolbarItem reference="CBz-1N-o0Q"/> - <toolbarItem reference="Q0x-n5-Q2Y"/> <toolbarItem reference="mtd-zS-DXa"/> + <toolbarItem reference="Q0x-n5-Q2Y"/> + <toolbarItem reference="CJX-Ff-7iQ"/> </defaultToolbarItems> </toolbar> <point key="canvasLocation" x="-159" y="356"/> diff --git a/Core/gb.h b/Core/gb.h @@ -710,6 +710,7 @@ struct GB_gameboy_internal_s { GB_write_memory_callback_t write_memory_callback; GB_boot_rom_load_callback_t boot_rom_load_callback; GB_print_image_callback_t printer_callback; + GB_printer_done_callback_t printer_done_callback; GB_workboy_set_time_callback workboy_set_time_callback; GB_workboy_get_time_callback workboy_get_time_callback; GB_execution_callback_t execution_callback; diff --git a/Core/printer.c b/Core/printer.c @@ -5,7 +5,7 @@ have my own GB Printer to figure it out myself. It also does not currently emulate communication timeout, which means that a bug - might prevent the printer operation until the GameBoy is restarted. + might prevent the printer operation until the Game Boy is restarted. Also, field mask values are assumed. */ @@ -30,6 +30,9 @@ static void handle_command(GB_gameboy_t *gb) image[i] = colors[(palette >> (gb->printer.image[i] * 2)) & 3]; } + // One second per 8-pixel row + gb->printer.time_remaining = gb->printer.image_offset / 160 * GB_get_unmultiplied_clock_rate(gb) / 256 / 8; + if (gb->printer_callback) { gb->printer_callback(gb, image, gb->printer.image_offset / 160, gb->printer.command_data[1] >> 4, gb->printer.command_data[1] & 7, @@ -70,7 +73,7 @@ static void handle_command(GB_gameboy_t *gb) } -static void byte_recieve_completed(GB_gameboy_t *gb, uint8_t byte_received) +static void byte_receive_completed(GB_gameboy_t *gb, uint8_t byte_received) { gb->printer.byte_to_send = 0; switch (gb->printer.command_state) { @@ -156,16 +159,13 @@ static void byte_recieve_completed(GB_gameboy_t *gb, uint8_t byte_received) gb->printer.byte_to_send = 0; } else { + if (gb->printer.status == 6 && gb->printer.time_remaining == 0) { + gb->printer.status = 4; /* Done */ + } gb->printer.byte_to_send = gb->printer.status; } break; case GB_PRINTER_COMMAND_STATUS: - - /* Printing is done instantly, but let the game recieve a 6 (Printing) status at least once, for compatibility */ - if (gb->printer.status == 6) { - gb->printer.status = 4; /* Done */ - } - gb->printer.command_state = GB_PRINTER_COMMAND_MAGIC1; handle_command(gb); return; @@ -197,7 +197,7 @@ static void serial_start(GB_gameboy_t *gb, bool bit_received) gb->printer.byte_being_received |= bit_received; gb->printer.bits_received++; if (gb->printer.bits_received == 8) { - byte_recieve_completed(gb, gb->printer.byte_being_received); + byte_receive_completed(gb, gb->printer.byte_being_received); gb->printer.bits_received = 0; gb->printer.byte_being_received = 0; } @@ -211,10 +211,11 @@ static bool serial_end(GB_gameboy_t *gb) return ret; } -void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback) +void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback, GB_printer_done_callback_t done_callback) { memset(&gb->printer, 0, sizeof(gb->printer)); GB_set_serial_transfer_bit_start_callback(gb, serial_start); GB_set_serial_transfer_bit_end_callback(gb, serial_end); gb->printer_callback = callback; + gb->printer_done_callback = done_callback; } diff --git a/Core/printer.h b/Core/printer.h @@ -13,6 +13,8 @@ typedef void (*GB_print_image_callback_t)(GB_gameboy_t *gb, uint8_t bottom_margin, uint8_t exposure); +typedef void (*GB_printer_done_callback_t)(GB_gameboy_t *gb); + typedef struct { @@ -56,8 +58,9 @@ typedef struct uint8_t bits_received; uint8_t byte_being_received; bool bit_to_send; + uint64_t time_remaining; } GB_printer_t; -void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback); +void GB_connect_printer(GB_gameboy_t *gb, GB_print_image_callback_t callback, GB_printer_done_callback_t done_callback); #endif diff --git a/Core/timing.c b/Core/timing.c @@ -165,8 +165,22 @@ static void increase_tima(GB_gameboy_t *gb) void GB_serial_master_edge(GB_gameboy_t *gb) { - if (unlikely(gb->printer_callback && (gb->printer.command_state || gb->printer.bits_received))) { - gb->printer.idle_time += 1 << gb->serial_mask; + if (gb->printer_callback) { + unsigned ticks = 1 << gb->serial_mask; + if (unlikely((gb->printer.command_state || gb->printer.bits_received))) { + gb->printer.idle_time +=ticks; + } + if (unlikely(gb->printer.time_remaining)) { + if (gb->printer.time_remaining <= ticks) { + gb->printer.time_remaining = 0; + if (gb->printer_done_callback) { + gb->printer_done_callback(gb); + } + } + else { + gb->printer.time_remaining -= ticks; + } + } } gb->serial_master_clock ^= true;

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.