#include bool gb_init(GB *gb, SDL_Renderer *renderer) { gb->io = r_io_new (); if (!gb->io) { goto fail_io; } gb->io->va = true; gb->io->autofd = false; gb->io->overlay = false; gb->io->cachemode = false; gb->io->p_cache = 0; gb->anal = r_anal_new (); if (!gb->anal) { goto fail_anal; } r_io_bind (gb->io, &gb->anal->iob); r_anal_use (gb->anal, "gb"); if (!gb_dma_init (&gb->dma, gb->io)) { goto fail_dma; } if (!(gb_timers_init (&gb->timers, gb->io) && gb_joypad_init (&gb->joypad, gb->io) && gb_interrupts_init (&gb->interrupts, gb->io, gb->anal->reg))) { goto fail_gb; } gb->ppu = gb_ppu_open (gb->io, renderer); if (!gb->ppu) { goto fail_gb; } gb_esil_setup (gb); return true; fail_gb: gb_dma_fini (&gb->dma, gb->io); fail_dma: r_anal_free (gb->anal); fail_anal: r_io_free (gb->io); fail_io: gb[0] = (const GB){0}; return false; } void gb_fini(GB *gb) { if (!gb) { return; } if (gb->anal) { r_arch_esilcb (gb->anal->arch, R_ARCH_ESIL_ACTION_FINI); r_anal_free (gb->anal); } if (gb->ppu && gb->io) { gb_ppu_close (gb->ppu, gb->io); } if (!gb->io) { return; } gb_interrupts_fini (&gb->interrupts, gb->io); gb_joypad_fini (&gb->joypad, gb->io); gb_timers_fini (&gb->timers, gb->io); gb_dma_fini (&gb->dma, gb->io); r_io_free (gb->io); gb[0] = (const GB){0}; }