タイトーメモリーズで遊ぶイベントです。
MSXBOOKで遊ぼう会(ヨコハマ)
MSXBOOKで厳かに遊ぶイベントです。
ハッシュタグ(2025/7/19)
- あかはな(akahana1701D)
- しばた(shibatax)
- しょーご(shogo83715541)
- たなむ(tanam1972)
- なおい(HENAHENA1)
- ぴの(delikea)
- ぽいぽい(poipoi_007)
学研TV BOYエミュレータをつくる その7
いぬふとさんの拡張カートリッジに対応するために学研TV BOYエミュレータを更新しました。 http://inufuto.web.fc2.com/8bit/hardware/
- 市街戦200X年(ふつうに遊べる!)
- ミスターボム(ふつうに遊べる!)
- エキサイトインベーダー(ふつうに遊べる!)
- ロボタンウォーズ(ふつうに遊べる!)
- 地対空大作戦(サウンドが鳴らない)
- フロッガー(タイトルでフリーズ)
ソースコード差分は以下になります。
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2025.01.28 [ memory ] */ #ifndef _MEMORY_H_ #define _MEMORY_H_ #include "../vm.h" #include "../../emu.h" #include "../device.h" #include "../mc6800.h" #include "../mc6847.h" // #include "../pcm1bit.h" #define SIG_MEMORY_PORT_1 0 class MEMORY : public DEVICE { private: MC6800 *d_cpu; MC6847* d_vdp; uint8_t rom[0x8000]; // ext rom uint8_t ram[0x8000]; // ext ram uint8_t vram[0x1000]; uint8_t wdmy[0x400]; uint8_t rdmy[0x400]; uint8_t* wbank[64]; uint8_t* rbank[64]; int shot1; int shot2; int up; int down; int left; int right; bool event; bool inserted; public: MEMORY(VM_TEMPLATE* parent_vm, EMU* parent_emu) : DEVICE(parent_vm, parent_emu) { set_device_name(_T("Memory Bus")); } ~MEMORY() {} // common functions void initialize(); void reset(); void write_data8(uint32_t addr, uint32_t data); uint32_t read_data8(uint32_t addr); void write_signal(int id, uint32_t data, uint32_t mask); bool process_state(FILEIO* state_fio, bool loading); // unique functions void key_down(int code); void key_up(int code); void set_context_cpu(MC6800* device) { d_cpu = device; } void set_context_vdp(MC6847* device) { d_vdp = device; } void open_cart(const _TCHAR* file_path); void close_cart(); bool is_cart_inserted() { return inserted; } uint8_t* get_vram() { return vram; } }; #endif
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2025.01.28 [ memory ] */ #include "memory.h" #define SET_BANK(s, e, w, r) { \ int sb = (s) >> 10, eb = (e) >> 10; \ for(int i = sb; i <= eb; i++) { \ if((w) == wdmy) { \ wbank[i] = wdmy; \ } else { \ wbank[i] = (w) + 0x400 * (i - sb); \ } \ if((r) == rdmy) { \ rbank[i] = rdmy; \ } else { \ rbank[i] = (r) + 0x400 * (i - sb); \ } \ } \ } void MEMORY::initialize() { memset(rom, 0xff, sizeof(rom)); memset(rdmy, 0xff, sizeof(rdmy)); // set memory map SET_BANK(0x0000, 0x0fff, ram, ram ); SET_BANK(0x1000, 0x1fff, vram, vram); SET_BANK(0x4000, 0x5fff, ram+0x4000, ram + 0x4000); SET_BANK(0x6000, 0x7fff, wdmy, rdmy); SET_BANK(0x8000, 0xffff, wdmy, rom ); inserted = false; } void MEMORY::reset() { memset(ram, 0, sizeof(ram)); for (int i=0; i<sizeof(vram); i++) { vram[i]=rand() % 256; } d_vdp->write_signal(SIG_MC6847_AS, 0x00, 0x08); d_vdp->write_signal(SIG_MC6847_AG, 0x10, 0x10); d_vdp->write_signal(SIG_MC6847_CSS, 0x20, 0x20); d_vdp->write_signal(SIG_MC6847_GM, 0x00, 0x02); d_vdp->write_signal(SIG_MC6847_GM, 0x01, 0x01); d_vdp->write_signal(SIG_MC6847_INTEXT, 0x00, 0x04); shot1 = shot2 = up = down = left = right = 0; } void MEMORY::write_data8(uint32_t addr, uint32_t data) { addr &= 0xffff; if(addr >= 0x80 && addr < 0x100) { d_cpu->ram[addr-0x80]=data; } if(addr == 0x2000) { d_vdp->write_signal(SIG_MC6847_AS, data, 0x08); d_vdp->write_signal(SIG_MC6847_AG, data, 0x10); d_vdp->write_signal(SIG_MC6847_CSS, data, 0x20); d_vdp->write_signal(SIG_MC6847_GM, data << 1, 0x02); d_vdp->write_signal(SIG_MC6847_GM, data >> 1, 0x01); d_vdp->write_signal(SIG_MC6847_INTEXT, data, 0x04); return; } wbank[addr >> 10][addr & 0x3ff] = data; } uint32_t MEMORY::read_data8(uint32_t addr) { addr &= 0xffff; if(addr >= 0x80 && addr < 0x100) { return d_cpu->ram[addr-0x80]; } return rbank[addr >> 10][addr & 0x3ff]; } void MEMORY::write_signal(int id, uint32_t data, uint32_t mask) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x1E, 0x1E); if (shot2 == 1 && (d_cpu->port[0].wreg & 0x01) == 1) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x04); } if (shot1 == 1 && (d_cpu->port[0].wreg & 0x01) == 1) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x02); } if (down == 1 && (d_cpu->port[0].wreg & 0x01) == 0) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x04); } if (up == 1 && (d_cpu->port[0].wreg & 0x01) == 0) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x02); } if (left == 1 && (d_cpu->port[0].wreg & 0x01) == 0) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x08); } if (right == 1 && (d_cpu->port[0].wreg & 0x01) == 0) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x10); } } void MEMORY::key_down(int code) { if (code==VK_C) { // POWKIDDY A20 shot1 =1; } if (code==VK_D) { // POWKIDDY A20 shot2 =1; } if (code==VK_LEFT) { left =1; } if (code==VK_UP) { up =1; } if (code==VK_RIGHT) { right =1; } if (code==VK_DOWN) { down =1; } } void MEMORY::key_up(int code) { if (code==VK_C) { // POWKIDDY A20 shot1 =0; } if (code==VK_D) { // POWKIDDY A20 shot2 =0; } if (code==VK_LEFT) { left =0; } if (code==VK_UP) { up =0; } if (code==VK_RIGHT) { right =0; } if (code==VK_DOWN) { down =0; } } void MEMORY::open_cart(const _TCHAR* file_path) { FILEIO* fio = new FILEIO(); if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { // GAKKEN ROMS if (0x1000 == fio->Fread(rom, 1, sizeof(rom))) { // ROBOTAN WARS if (rom[0x06f0]==0x96 && rom[0x06f1]==0x19) { rom[0x06f0]=0x86; rom[0x06f1]=0x10; } memcpy(rom + 0x7000, rom, 0x1000); } fio->Fclose(); inserted = true; } delete fio; } void MEMORY::close_cart() { memset(rom, 0xff, sizeof(rom)); inserted = false; } #define STATE_VERSION 1 bool MEMORY::process_state(FILEIO* state_fio, bool loading) { if(!state_fio->StateCheckUint32(STATE_VERSION)) { return false; } if(!state_fio->StateCheckInt32(this_device_id)) { return false; } state_fio->StateArray(ram, sizeof(ram), 1); state_fio->StateArray(vram, sizeof(vram), 1); return true; }
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2025.01.28 [ virtual machine ] */ #include "tvboy.h" #include "../../emu.h" #include "../device.h" #include "../event.h" #include "../mc6847.h" #include "../mc6800.h" #include "../pcm1bit.h" #ifdef USE_DEBUGGER #include "../debugger.h" #endif #include "memory.h" // ---------------------------------------------------------------------------- // initialize // ---------------------------------------------------------------------------- VM::VM(EMU* parent_emu) : VM_TEMPLATE(parent_emu) { // create devices first_device = last_device = NULL; dummy = new DEVICE(this, emu); // must be 1st device event = new EVENT(this, emu); // must be 2nd device vdp = new MC6847(this, emu); cpu = new MC6800(this, emu); pcm = new PCM1BIT(this, emu); memory = new MEMORY(this, emu); memory->set_context_cpu(cpu); memory->set_context_vdp(vdp); cpu->set_context_port1(pcm, SIG_PCM1BIT_SIGNAL, 0x40, 0); cpu->set_context_port1(memory, SIG_MEMORY_PORT_1, 0x0F, 0); // set contexts event->set_context_cpu(cpu); event->set_context_sound(pcm); vdp->set_vram_ptr(memory->get_vram(), 0x800); vdp->set_context_cpu(cpu); vdp->set_context_vsync(cpu, SIG_CPU_IRQ, 0x01); vdp->set_context_hsync(cpu, SIG_MC6801_PORT_1, 0x80); // cpu bus cpu->set_context_mem(memory); #ifdef USE_DEBUGGER cpu->set_context_debugger(new DEBUGGER(this, emu)); #endif // initialize all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->initialize(); } } VM::~VM() { // delete all devices for(DEVICE* device = first_device; device;) { DEVICE *next_device = device->next_device; device->release(); delete device; device = next_device; } } DEVICE* VM::get_device(int id) { for(DEVICE* device = first_device; device; device = device->next_device) { if(device->this_device_id == id) { return device; } } return NULL; } // ---------------------------------------------------------------------------- // drive virtual machine // ---------------------------------------------------------------------------- void VM::reset() { // reset all devices for(DEVICE* device = first_device; device; device = device->next_device) { device->reset(); } } void VM::run() { event->drive(); } // ---------------------------------------------------------------------------- // debugger // ---------------------------------------------------------------------------- #ifdef USE_DEBUGGER DEVICE *VM::get_cpu(int index) { if(index == 0) { return cpu; } return NULL; } #endif // ---------------------------------------------------------------------------- // draw screen // ---------------------------------------------------------------------------- void VM::draw_screen() { vdp->draw_screen(); } // ---------------------------------------------------------------------------- // notify key // ---------------------------------------------------------------------------- void VM::key_down(int code, bool repeat) { memory->key_down(code); // POWKIDDY A20 // if (code==VK_L) this->open_cart(0,"/sdcard/Download/emulator/tvboyROM/CART/chitaikuu.bin"); // if (code==VK_X) this->open_cart(0,"/sdcard/Download/emulator/tvboyROM/CART/robotan.bin"); // if (code==VK_Y) this->open_cart(0,"/sdcard/Download/emulator/tvboyROM/CART/einvader.bin"); // if (code==VK_RETURN) this->open_cart(0,"/sdcard/Download/emulator/tvboyROM/CART/mrbomb.bin"); // if (code==VK_B) this->open_cart(0,"/sdcard/Download/emulator/tvboyROM/CART/shigaisen.bin"); // if (code==VK_R) this->open_cart(0,"/sdcard/Download/emulator/tvboyROM/CART/frogger.bin"); // if (code==VK_Z) this->~VM(); } void VM::key_up(int code) { memory->key_up(code); } // ---------------------------------------------------------------------------- // soud manager // ---------------------------------------------------------------------------- void VM::initialize_sound(int rate, int samples) { // init sound manager event->initialize_sound(rate, samples); pcm->initialize_sound(rate, 8000); } uint16_t* VM::create_sound(int* extra_frames) { return event->create_sound(extra_frames); } int VM::get_sound_buffer_ptr() { return event->get_sound_buffer_ptr(); } #ifdef USE_SOUND_VOLUME void VM::set_sound_device_volume(int ch, int decibel_l, int decibel_r) { if(ch == 0) { pcm->set_volume(0, decibel_l, decibel_r); } } #endif // ---------------------------------------------------------------------------- // user interface // ---------------------------------------------------------------------------- void VM::open_cart(int drv, const _TCHAR* file_path) { if(drv == 0) { memory->open_cart(file_path); reset(); } } void VM::close_cart(int drv) { if(drv == 0) { memory->close_cart(); reset(); } } bool VM::is_cart_inserted(int drv) { if(drv == 0) { return memory->is_cart_inserted(); } else { return false; } } bool VM::is_frame_skippable() { return event->is_frame_skippable(); } void VM::update_config() { for(DEVICE* device = first_device; device; device = device->next_device) { device->update_config(); } } #define STATE_VERSION 3 bool VM::process_state(FILEIO* state_fio, bool loading) { if(!state_fio->StateCheckUint32(STATE_VERSION)) { return false; } for(DEVICE* device = first_device; device; device = device->next_device) { const _TCHAR *name = char_to_tchar(typeid(*device).name() + 6); // skip "class " int len = (int)_tcslen(name); if(!state_fio->StateCheckInt32(len)) { return false; } if(!state_fio->StateCheckBuffer(name, len, 1)) { return false; } if(!device->process_state(state_fio, loading)) { return false; } } return true; }
AMBERNIC RG351V
ゲームボーイが好きです。Linuxで動くRG351Vでアルカディアを動かす方法をメモします。
https://jp.anbernic.com/products/anbernic-rg351v
まずはAMBERELECというCFWを導入します。
AMBERELECでアルカディアを動かす方法を伝授しましょう。アルカディアのHASHファイルが必要になります。
<software name="doraemon">
<description>Doraemon</description>
<year>1983</year>
<publisher>Bandai</publisher>
<part name="cart" interface="arcadia_cart">
<dataarea name="rom" size="8192">
<rom name="doraemon.bin" size="8192" crc="62c45881" sha1="a16fda96d00c8b08bb362f2573a45939aa6be051" offset="0000" />
</dataarea>
</part>
</software>
アルカディアのROMファイル名およびHASH値はarcadia.xmlの記載に合わせる必要があります。
/roms/bios/mame/hash/arcadia.xml
ROMファイルを置く場所も決まっています。
電子ゲームで遊ぼう会(ヨコハマ)
電子ゲームで遊ぶイベントです。
ハッシュタグ(2025/2/22)
- きゅらたろう(qurataro)
- こめ(okome_chanoi)
- さぶろう(SBRSNPI)
- しばた(shibatax)
- しょーご(shogo83715541)
- せい(Sei_soft)
- たなむ(tanam1972)
- とむ(Izk_tom)
- ぴすた(pista_TM)
- ぽいぽい(poipoi_007)
- まえだ(hiropapa00)