これからエミュレータで対応していきます。
これからエミュレータで対応していきます。
VRAM($1000-$17FF)、ROM($F000-$FFFF)の想定で書いていきます。
hello.cint memset(p, x, y) char *p; char x; int y; { int i; for (i=0; i<y; i++,p++) { *p=x; } return 0; } int main() { char *p; char *q; p="HELLO WORLD"; q=0x2000; *q=0x20; memset(0x1000, ' ', 0x800); for (q=0x1000; *p != 0; q++, p++) { *q = *p; } return 0; }
MS-DOSで開発します。
>msdos C3PO.EXE HELLO >notepad hello.src
hello.srcを編集してhello.txtで保存します。DOS用8ビットCPUクロスアセンブラでSレコード形式を作成します。
>msdos X6801.EXE hello 6801 Cross Assembler Version 3.12 Copyright(C) Arcpit Co.,LTD.1990. All rights reserved. Object Filename [HELLO.S] : Source Listting [NUL.LST] : Cross Reference [NUL.CRF] : Symbol Table [NUL.MAP] : ^L 2020- 6- 7 6801 Assembler Page 1 File:HELLO.TXT 1 ; INCLUDE 630X.LIB 2 ; 3 ;***** C3PO for 6301/3 version 3.06c MSDOS ***** Nishiy 4 ; *** Copyright (c) S.Nishiyama Mar 14 1992 5 ;*** 1 int memset(p, x, y) 6 ;*** 2 char *p; 7 ;*** 3 char x; 8 ;*** 4 int y; 9 ;*** 5 { 10 ;*** 6 int i; 11 ;*** 7 for (i=0; i<y; i++,p++) { 12 ; CSEG 13 ; GLOBAL _memset 14 F000 ORG $F000 15 00FF STACK EQU $FF 16 F000 8E00FF START LDS #STACK 17 F003 2035 BRA _main 18 F005 _memset: 19 F005 3C PSHX 20 F006 30 TSX 21 F007 37 PSHB 22 F008 36 PSHA 23 F009 34 DES 24 F00A 34 DES 25 F00B 4F CLRA 26 F00C 5F CLRB 27 F00D 30 TSX 28 F00E ED00 STD 0,X 29 F010 L3: 30 F010 EC08 LDD 8,X 31 F012 A300 SUBD 0,X 32 F014 2F19 BLE L2 33 ;*** 8 *p=x; 34 F016 4F CLRA 35 F017 E605 LDAB 5,X 36 F019 EE02 LDX 2,X 37 F01B E700 STAB 0,X 38 F01D 30 TSX 39 ;*** 9 } 40 ;*** 10 return 0; 41 F01E L4: 42 F01E EC00 LDD 0,X 43 F020 C30001 ADDD #1 44 F023 ED00 STD 0,X 45 F025 EC02 LDD 2,X 46 F027 C30001 ADDD #1 47 F02A ED02 STD 2,X 48 F02C 7EF010 JMP L3 49 F02F L2: 50 F02F 4F CLRA 51 F030 5F CLRB 52 ;*** 11 } 53 F031 7EF034 JMP L1 54 F034 L1: 55 F034 31 INS 56 F035 31 INS 57 F036 31 INS 58 F037 31 INS ^L 2020- 6- 7 6801 Assembler Page 2 File:HELLO.TXT 59 F038 38 PULX 60 F039 39 RTS 61 ;** Local value mapping information 62 ;** i EQU 0 63 ;** y EQU 8 64 ;** x EQU 5 65 ;** p EQU 2 66 ;* Function67 ;* Executive step count 8 68 ;* Used stack size ===6 Byte=== ^L 2020- 6- 7 6801 Assembler Page 3 File:HELLO.TXT 70 ;*** 12 71 ;*** 13 int main() 72 ;*** 14 { 73 ;*** 15 char *p; 74 ;*** 16 char *q; 75 ;*** 17 p="HELLO WORLD"; 76 ; GLOBAL _main 77 F03A _main: 78 F03A 3C PSHX 79 F03B 30 TSX 80 F03C 34 DES 81 F03D 34 DES 82 F03E 34 DES 83 F03F 34 DES 84 F040 3C PSHX 85 F041 30 TSX 86 F042 CCF093 LDD #S0 87 F045 ED04 STD 4,X 88 ;*** 18 q=0x2000; 89 F047 CC2000 LDD #8192 90 F04A ED02 STD 2,X 91 ;*** 19 *q=0x20; 92 F04C EE02 LDX 2,X 93 F04E C620 LDAB #$20 94 F050 E700 STAB 0,X 95 F052 30 TSX 96 ;*** 20 memset(0x1000, ' ', 0x800); 97 F053 CC0800 LDD #2048 98 F056 37 PSHB 99 F057 36 PSHA 100 F058 CE0020 LDX #32 101 F05B 05 ASLD 102 F05C BDF005 JSR _memset 103 F05F 31 INS 104 F060 31 INS 105 F061 30 TSX 106 ;*** 21 for (q=0x1000; *p != 0; q++, p+ 107 F062 CC1000 LDD #4096 108 F065 ED02 STD 2,X 109 F067 L7: 110 F067 EE04 LDX 4,X 111 F069 4F CLRA 112 F06A E600 LDAB 0,X 113 F06C 30 TSX 114 F06D 271B BEQ L6 115 ;*** 22 *q = *p; 116 F06F EE04 LDX 4,X 117 F071 E600 LDAB 0,X 118 F073 30 TSX 119 F074 EE02 LDX 2,X 120 F076 E700 STAB 0,X 121 F078 30 TSX 122 ;*** 23 } 123 ;*** 24 return 0; 124 F079 L8: 125 F079 EC02 LDD 2,X 126 F07B C30001 ADDD #1 127 F07E ED02 STD 2,X ^L 2020- 6- 7 6801 Assembler Page 4 File:HELLO.TXT 128 F080 EC04 LDD 4,X 129 F082 C30001 ADDD #1 130 F085 ED04 STD 4,X 131 F087 7EF067 JMP L7 132 F08A 20FE L6: BRA L6 133 ;*** 25 } 134 F08C 7EF08F JMP L5 135 F08F L5: 136 F08F 38 PULX 137 F090 35 TXS 138 F091 38 PULX 139 F092 39 RTS 140 ;** Local value mapping information 141 ;** q EQU 2 142 ;** p EQU 4 143 ;* Function 144 ;* Executive step count 12 145 ;* Used stack size ===14 Byte=== ^L 2020- 6- 7 6801 Assembler Page 5 File:HELLO.TXT 147 ;*** 26 148 F093 S0: 149 F093 48454C4C4F20 FCB 72,69,76,76,79,32,87,79 574F 150 F09B 524C4400 FCB 82,76,68,0 151 ;* Direct page size 0 152 ;* Global segment size 0 153 ;* Character size 12 154 ;* Executive step count 20 155 ;* Error count 0 156 FFFE ORG $FFFE 157 FFFE F000 FDB START 158 0000 END ^L 2020- 6- 7 6801 Assembler Page 6 File:HELLO.TXT SYMBOL TABLE: L1 F034 L2 F02F L3 F010 L4 F01E L5 F08F L6 F08A L7 F067 L8 F079 S0 F093 STACK 00FF START F000 _main F03A _memset F005 ^L 2020- 6- 7 6801 Assembler Page 7 File:HELLO.TXT 0 Error(s) detected. LINES : 158 LABELS : 13 LAST PROGRAM ADDRESS : $FFFD LAST DATA ADDRESS : $0000
SRecord 1.64でhello.sをhello.binに変換します。
>srec_cat hello.S -offset -0xF000 -o hello.bin -binary
世にも珍しいVCSじゃない方のTV BOYエミュレータです。
ソースコード差分は以下になります。
vm.h
// GAKKEN TV BOY #ifdef _TVBOY #include "tvboy/tvboy.h" #endif
tvboy.h
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2020.06.13 [ virtual machine ] */ #ifndef _TVBOY_H_ #define _TVBOY_H_ #define DEVICE_NAME "GAKKEN TV BOY" #define CONFIG_NAME "tvboy" // device informations for virtual machine #define FRAMES_PER_SEC 60 #define LINES_PER_FRAME 262 #define CPU_CLOCKS 3579545 / 4 #define SCREEN_WIDTH 256 #define SCREEN_HEIGHT 192 #define HAS_MC6801 #define MC6847_VRAM_INV 0x40 // device informations for win32 #define USE_CART 1 #define USE_SOUND_VOLUME 2 #define USE_DEBUGGER #define USE_STATE #include "../../common.h" #include "../../fileio.h" #include "../vm_template.h" #ifdef USE_SOUND_VOLUME static const _TCHAR *sound_device_caption[] = { _T("PCM"), }; #endif class EMU; class DEVICE; class EVENT; class MC6847; class MC6800; class PCM1BIT; class MEMORY; class VM : public VM_TEMPLATE { protected: // EMU* emu; // devices EVENT* event; MC6847* vdp; MC6800* cpu; PCM1BIT* pcm; MEMORY* memory; public: // ---------------------------------------- // initialize // ---------------------------------------- VM(EMU* parent_emu); ~VM(); // ---------------------------------------- // for emulation class // ---------------------------------------- // drive virtual machine void reset(); void run(); double get_frame_rate() { return FRAMES_PER_SEC; } #ifdef USE_DEBUGGER // debugger DEVICE *get_cpu(int index); #endif // draw screen void draw_screen(); // sound generation void initialize_sound(int rate, int samples); uint16_t* create_sound(int* extra_frames); int get_sound_buffer_ptr(); #ifdef USE_SOUND_VOLUME void set_sound_device_volume(int ch, int decibel_l, int decibel_r); #endif // user interface void open_cart(int drv, const _TCHAR* file_path); void close_cart(int drv); bool is_cart_inserted(int drv); // notify key void key_down(int code, bool repeat); void key_up(int code); bool is_frame_skippable(); void update_config(); bool process_state(FILEIO* state_fio, bool loading); // ---------------------------------------- // for each device // ---------------------------------------- // devices DEVICE* get_device(int id); // DEVICE* dummy; // DEVICE* first_device; // DEVICE* last_device; }; #endif
tvboy.cpp
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2020.06.13 [ 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); memory = new MEMORY(this, emu); memory->set_context_cpu(cpu); memory->set_context_vdp(vdp); pcm = new PCM1BIT(this, emu); cpu->set_context_port1(pcm, SIG_PCM1BIT_SIGNAL, 0x20, 0); 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); // cpu bus cpu->set_context_mem(memory); #ifdef USE_DEBUGGER cpu->set_context_debugger(new DEBUGGER(this, emu)); #endif pcm = new PCM1BIT(this, emu); // 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); } 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; }
memory.h
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2020.06.13 [ memory ] */ #ifndef _MEMORY_H_ #define _MEMORY_H_ #include "../vm.h" #include "../../emu.h" #include "../device.h" #include "../mc6800.h" #include "../mc6847.h" #define SIG_MEMORY_PORT_1 0 class MEMORY : public DEVICE { private: MC6800 *d_cpu; MC6847 *d_vdp; uint8_t rom[0x1000]; uint8_t ram[0x1000]; 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); void event_callback(int event_id, int err); 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
memory.cpp
/* GAKKEN TV BOY Emulator 'yaTVBOY' Author : tanam Date : 2020.06.13 [ 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(0x2000, 0xefff, wdmy, rdmy); SET_BANK(0xf000, 0xffff, wdmy, rom ); // register event register_event_by_clock(this, 0, 256, true, NULL); event = false; 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==1) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x04); } if (down==1 && d_cpu->port[0].wreg==2) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x04); } if (shot1==1 && d_cpu->port[0].wreg==1) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x02); } if (up==1 && d_cpu->port[0].wreg==2) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x02); } if (left==1 && d_cpu->port[0].wreg==2) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x08); } if (right==1 && d_cpu->port[0].wreg==2) { d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x10); } } void MEMORY::event_callback(int event_id, int err) { if (event) { d_cpu->write_signal(SIG_CPU_IRQ, 1, 1); event = false; } else { d_cpu->write_signal(SIG_CPU_IRQ, 0, 1); event = true; } } void MEMORY::key_down(int code) { if (code==0x20) { shot1 =1; } if (code==0x11) { shot2 =1; } if (code==0x25) { left =1; } if (code==0x26) { up =1; } if (code==0x27) { right =1; } if (code==0x28) { down =1; } } void MEMORY::key_up(int code) { if (code==0x20) { shot1 =0; } if (code==0x11) { shot2 =0; } if (code==0x25) { left =0; } if (code==0x26) { up =0; } if (code==0x27) { right =0; } if (code==0x28) { down =0; } } void MEMORY::open_cart(const _TCHAR* file_path) { FILEIO* fio = new FILEIO(); if(fio->Fopen(file_path, FILEIO_READ_BINARY)) { fio->Fread(rom, sizeof(rom), 1); 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; }
まずはSource Code Archive (4/6/2020)をダウンロードします。
http://takeda-toshiya.my.coocan.jp/common/index.html
好きなディレクトリに展開して、以下のプロジェクトを開きます。
source\vc++2008\pc6001.vcproj
追加のインクルードディレクトリとライブラリディレクトリを指定してビルドできるはずです。
C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (December 2004)\include C:\Program Files (x86)\Microsoft DirectX 9.0 SDK (December 2004)\lib\x86
Common Source Code Projectのpc6001をコピーして編集していきます。
source\vc++2008\pc6001.vcproj source\src\res\pc6001.rc \pc6001.ico source\src\vm\vm.h source\src\vm\pc6001\display.cpp display.h floppy.cpp floppy.h joystick.cpp joystick.h memory.cpp memory.h memory_draw.cpp pc6001.cpp pc6001.h psub.cpp psub.h sub.cpp sub.h timer.cpp timer.h
ディレクトリ構成は以下のようになります。
source\vc++2008\tvboy.vcproj source\src\res\tvboy.rc tvboy.ico source\src\vm\vm.h source\src\vm\event.cpp event.h mc6800.cpp mc6800.h mc6847.cpp mc6847.h pcm1bit.cpp pcm1bit.h source\src\vm\tvboy\memory.cpp memory.h tvboy.cpp tvboy.h
tvboy.rc
// Microsoft Visual C++ generated resource script. // #include "resource.h" #define APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 2 resource. // #include "afxres.h" ///////////////////////////////////////////////////////////////////////////// #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// // Japanese resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_JPN) #ifdef _WIN32 LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT #pragma code_page(932) #endif //_WIN32 #ifdef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // TEXTINCLUDE // 1 TEXTINCLUDE DISCARDABLE BEGIN "resource.h\0" END 2 TEXTINCLUDE DISCARDABLE BEGIN "#include ""afxres.h""\r\n" "\0" END 3 TEXTINCLUDE DISCARDABLE BEGIN "\r\n" "\0" END #endif // APSTUDIO_INVOKED #endif // Japanese resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // English (U.S.) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) #ifdef _WIN32 LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US #pragma code_page(1252) #endif //_WIN32 ///////////////////////////////////////////////////////////////////////////// // // Accelerator // IDR_ACCELERATOR1 ACCELERATORS DISCARDABLE BEGIN VK_RETURN, ID_ACCEL_SCREEN, VIRTKEY, ALT, NOINVERT VK_APPS, ID_ACCEL_SPEED, VIRTKEY, NOINVERT VK_APPS, ID_ACCEL_ROMAJI, VIRTKEY, CONTROL, NOINVERT END ///////////////////////////////////////////////////////////////////////////// // // Menu // IDR_MENU1 MENU DISCARDABLE BEGIN POPUP "Control" BEGIN MENUITEM "Reset", ID_RESET MENUITEM SEPARATOR MENUITEM "CPU x1", ID_CPU_POWER0 MENUITEM "CPU x2", ID_CPU_POWER1 MENUITEM "CPU x4", ID_CPU_POWER2 MENUITEM "CPU x8", ID_CPU_POWER3 MENUITEM "CPU x16", ID_CPU_POWER4 MENUITEM "Full Speed", ID_FULL_SPEED MENUITEM SEPARATOR MENUITEM "Paste", ID_AUTOKEY_START MENUITEM "Stop", ID_AUTOKEY_STOP MENUITEM "Romaji to Kana", ID_ROMAJI_TO_KANA MENUITEM SEPARATOR POPUP "Save State" BEGIN MENUITEM "State 0", ID_SAVE_STATE0 MENUITEM "State 1", ID_SAVE_STATE1 MENUITEM "State 2", ID_SAVE_STATE2 MENUITEM "State 3", ID_SAVE_STATE3 MENUITEM "State 4", ID_SAVE_STATE4 MENUITEM "State 5", ID_SAVE_STATE5 MENUITEM "State 6", ID_SAVE_STATE6 MENUITEM "State 7", ID_SAVE_STATE7 MENUITEM "State 8", ID_SAVE_STATE8 MENUITEM "State 9", ID_SAVE_STATE9 END POPUP "Load State" BEGIN MENUITEM "State 0", ID_LOAD_STATE0 MENUITEM "State 1", ID_LOAD_STATE1 MENUITEM "State 2", ID_LOAD_STATE2 MENUITEM "State 3", ID_LOAD_STATE3 MENUITEM "State 4", ID_LOAD_STATE4 MENUITEM "State 5", ID_LOAD_STATE5 MENUITEM "State 6", ID_LOAD_STATE6 MENUITEM "State 7", ID_LOAD_STATE7 MENUITEM "State 8", ID_LOAD_STATE8 MENUITEM "State 9", ID_LOAD_STATE9 END MENUITEM SEPARATOR MENUITEM "Debug Main CPU", ID_OPEN_DEBUGGER0 MENUITEM "Close Debugger", ID_CLOSE_DEBUGGER MENUITEM SEPARATOR MENUITEM "Exit", ID_EXIT END POPUP "Cart" BEGIN MENUITEM "Insert", ID_OPEN_CART1 MENUITEM "Eject", ID_CLOSE_CART1 MENUITEM SEPARATOR MENUITEM "Recent", ID_RECENT_CART1 END POPUP "Host" BEGIN MENUITEM "Rec Movie 60fps", ID_HOST_REC_MOVIE_60FPS MENUITEM "Rec Movie 30fps", ID_HOST_REC_MOVIE_30FPS MENUITEM "Rec Movie 15fps", ID_HOST_REC_MOVIE_15FPS MENUITEM "Rec Sound", ID_HOST_REC_SOUND MENUITEM "Stop", ID_HOST_REC_STOP MENUITEM "Capture Screen", ID_HOST_CAPTURE_SCREEN MENUITEM SEPARATOR POPUP "Screen" BEGIN MENUITEM "Window x1", ID_SCREEN_WINDOW MENUITEM "Fullscreen 640x400", ID_SCREEN_FULLSCREEN MENUITEM SEPARATOR MENUITEM "Fullscreen Stretch 1", ID_SCREEN_FULLSCREEN_DOTBYDOT MENUITEM "Fullscreen Stretch 2", ID_SCREEN_FULLSCREEN_STRETCH MENUITEM "Fullscreen Stretch 4", ID_SCREEN_FULLSCREEN_FILL MENUITEM SEPARATOR MENUITEM "Rotate 0deg", ID_SCREEN_ROTATE_0 MENUITEM "Rotate +90deg", ID_SCREEN_ROTATE_90 MENUITEM "Rotate 180deg", ID_SCREEN_ROTATE_180 MENUITEM "Rotate -90deg", ID_SCREEN_ROTATE_270 END POPUP "Sound" BEGIN MENUITEM "2000Hz", ID_SOUND_FREQ0 MENUITEM "4000Hz", ID_SOUND_FREQ1 MENUITEM "8000Hz", ID_SOUND_FREQ2 MENUITEM "11025Hz", ID_SOUND_FREQ3 MENUITEM "22050Hz", ID_SOUND_FREQ4 MENUITEM "44100Hz", ID_SOUND_FREQ5 MENUITEM "48000Hz", ID_SOUND_FREQ6 MENUITEM "96000Hz", ID_SOUND_FREQ7 MENUITEM SEPARATOR MENUITEM "50msec", ID_SOUND_LATE0 MENUITEM "100msec", ID_SOUND_LATE1 MENUITEM "200msec", ID_SOUND_LATE2 MENUITEM "300msec", ID_SOUND_LATE3 MENUITEM "400msec", ID_SOUND_LATE4 MENUITEM SEPARATOR MENUITEM "Realtime Mix", ID_SOUND_STRICT_RENDER MENUITEM "Light Weight Mix", ID_SOUND_LIGHT_RENDER MENUITEM SEPARATOR MENUITEM "Volume", ID_SOUND_VOLUME END MENUITEM SEPARATOR MENUITEM "Use Direct3D9", ID_HOST_USE_D3D9 MENUITEM "Wait Vsync", ID_HOST_WAIT_VSYNC MENUITEM "Use DirectInput", ID_HOST_USE_DINPUT MENUITEM "Disable Windows 8 DWM", ID_HOST_DISABLE_DWM MENUITEM "Show Status Bar", ID_HOST_SHOW_STATUS_BAR END END ///////////////////////////////////////////////////////////////////////////// // // Icon // // Icon with lowest ID value placed first to ensure application icon // remains consistent on all systems. IDI_ICON1 ICON DISCARDABLE "phc20.ico" #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////// // // Dialog // IDD_VOLUME DIALOG DISCARDABLE 0, 0, 250, 90 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Volume" FONT 9, "MS PGothic" BEGIN LTEXT "Sound Device #1",IDC_VOLUME_CAPTION0,6,6,60,8 CONTROL "",IDC_VOLUME_PARAM_L0,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,70,6,175,12 CONTROL "",IDC_VOLUME_PARAM_R0,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,70,21,175,12 LTEXT "Sound Device #2",IDC_VOLUME_CAPTION1,6,36,60,8 CONTROL "",IDC_VOLUME_PARAM_L1,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,70,36,175,12 CONTROL "",IDC_VOLUME_PARAM_R1,"msctls_trackbar32",TBS_AUTOTICKS | WS_TABSTOP,70,51,175,12 DEFPUSHBUTTON "OK",IDOK,70,70,50,14 DEFPUSHBUTTON "Reset",IDC_VOLUME_RESET,130,70,50,14 END #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// // // Generated from the TEXTINCLUDE 3 resource. // ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED
きっかけは以下の記事です。
https://qiita.com/rukihena/items/a30f07f93ca1718dff8e
2003年に新築した一戸建ても色々がたが来て、コンセントなど自分でできるものは取り換えたい!と思い立ちました。
まずは引き返せないように申し込みます。インターネット申し込みだと9300円かかりました。
https://uketsuke.shiken.or.jp/mohshi/FIC1010.do
工具は自分で用意する必要があるため以下を購入しました。11595円かかりました。
https://www.amazon.co.jp/dp/B079JFJHSM/
部材セットはDVDつきの第二種電気工事士技能試験「準備万端試験対策セット」をメルカリで5000円で購入。2019年の対策セットですが、2020年も試験範囲が同じなので問題ないと思っています。
筆記試験と技能試験があるのですが、まずは工具が届くまでは、技能試験の動画を見てイメージトレーニングをしています。HOZAN最高!
動画を見て、合格クリップ(P-926 629円)、合格マルチツール(DK-200 667円)、プレートはずし器(WV-8400 420円)などを追加購入しました。足りない部材は都度ホームセンターなどで調達予定。
Android NDKをつかってRETRONFREAK5でHello, Worldしてみます。
まずはAndroid NDK(android-ndk-r10e-windows-x86_64.zip)をダウンロードします。
サンプルプログラムを書き換えます。
>cd \android-ndk-r10e\samples\hello-jni >..\..\ndk-build
RETRONFREAK5に転送して実行します。
>adb push \android-ndk-r10e\samples\hello-jni\libs\armeabi\hello-jni /hello-jni >adb shell #busybox chmod +x /hello-jni #/hello-jni Hello, World.
Application.mk
APP_ABI := armeabi
Android.mk
# Copyright (C) 2009 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c #include $(BUILD_SHARED_LIBRARY) include $(BUILD_EXECUTABLE)
hello-jni.c
/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ #include <string.h> #include <jni.h> /* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * * apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java */ jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) { //#if defined(__arm__) // #if defined(__ARM_ARCH_7A__) // #if defined(__ARM_NEON__) // #if defined(__ARM_PCS_VFP) // #define ABI "armeabi-v7a/NEON (hard-float)" // #else // #define ABI "armeabi-v7a/NEON" // #endif // #else // #if defined(__ARM_PCS_VFP) // #define ABI "armeabi-v7a (hard-float)" // #else // #define ABI "armeabi-v7a" // #endif // #endifexit // #else #define ABI "armeabi" // #endif //#elif defined(__i386__) // #define ABI "x86" //#elif defined(__x86_64__) // #define ABI "x86_64" //#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */ // #define ABI "mips64" //#elif defined(__mips__) // #define ABI "mips" //#elif defined(__aarch64__) // #define ABI "arm64-v8a" //#else // #define ABI "unknown" //#endif return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI "."); } int main(void) { printf("Hello, World.\n"); return 0; }
RETRONFREAK5のSERIAL(DNA)を取得します。
/* * RETROFREAK GETDNA */ #include <stdio.h> #include <fcntl.h> #include <sys/ioctl.h> #define RKNAND_SYS_STORGAE_DATA_LEN 512 #define SN_SECTOR_OP_TAG 0x41444E53 // SNDA #define RKNAND_GET_SN_SECTOR _IOW('d', 3, unsigned int) typedef struct tagRKNAND_SYS_STORGAE { unsigned long tag; unsigned long len; unsigned char data[RKNAND_SYS_STORGAE_DATA_LEN]; }RKNAND_SYS_STORGAE; int main(void) { int i; RKNAND_SYS_STORGAE sysData; for (i=0; i<512; i++) sysData.data[i]=0xff; int sys_fd = open("/dev/rknand_sys_storage",O_RDWR,0); if(sys_fd < 0){ printf("rknand_sys_storage open fail\n"); return -1; } //sn sysData.tag = SN_SECTOR_OP_TAG; sysData.len = RKNAND_SYS_STORGAE_DATA_LEN; int ret = ioctl(sys_fd, RKNAND_GET_SN_SECTOR, &sysData); if(ret) { printf("get sn fail\n"); return -1; } for (i=480; i<496; i++) printf("%02x", sysData.data[i]); printf("\n"); return 0; }
RETRON5をCFWでRETROFREAKにしてみます。
上記CFW(RETRONFREAK5)で本体をアップデートします。コントローラケーブルをPCにつなぐとADB接続でrootが有効になります。
カートリッジを読み込むと/mnt/ramに元のバイナリデータが生成されます。
>adb pull /mnt/ram >cd ram >dir dump.NES