学研TV BOYエミュレータをつくる その5

TV BOYエミュレータを更新しました。求む!エミュレータ開発者。

ソフトは6種類(各3,800円)が発売されたそうです。

  • 市街戦200X年(ふつうに遊べる!)
  • ミスターボム(ふつうに遊べる!)
  • エキサイトインベーダー(ゲーム開始直後フリーズ)
  • ロボタンウォーズ(ゲーム開始後キー入力できない)
  • 地対空大作戦(サウンドが鳴らない)
  • フロッガー(タイトルでフリーズ)

ソースコード差分は以下になります。

takeda-toshiya.my.coocan.jp

/*
    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);
    register_event_by_clock(this, 0, 4096, 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 & 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 (event) return; // speed down
    
    if (down==1 && (d_cpu->port[0].wreg & 0x01)==0) {
         d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x04);
        // frogger
        if (rom[0x0ff4]==0xfa && rom[0x0ff5]==0xd7) down =0;
    }
    if (up==1 && (d_cpu->port[0].wreg & 0x01)==0) {
        d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x02);
        // frogger
        if (rom[0x0ff4]==0xfa && rom[0x0ff5]==0xd7) up =0;
    }
    if (left==1 && (d_cpu->port[0].wreg & 0x01)==0) {
        d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x08);
        // frogger
        if (rom[0x0ff4]==0xfa && rom[0x0ff5]==0xd7) left =0;
    }
    if (right==1 && (d_cpu->port[0].wreg & 0x01)==0) {
        d_cpu->write_signal(SIG_MC6801_PORT_2, 0x00, 0x10);
        // frogger
        if (rom[0x0ff4]==0xfa && rom[0x0ff5]==0xd7) right =0;
    }
}

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;
}

FP技能士3級に挑戦してみた!

老後の資金計画のために、FP技能士2級資格をとろうと思いまずは問題集を買いました。しかしよくよく調べると、最初からFP技能士2級を受験する事はできないそうです。

仕方がないのでYouTubeと過去問で勉強して3級から受験しようと思います。

www.youtube.com

過去問を繰り返しといて、毎回60点とれるようになれば合格すると思います。

fp3-siken.com

YouTubeの授業と対策サイトの過去問で合格しました!来年は簿記に挑戦したいと思います。

www.youtube.com

www.youtube.com

www.youtube.com

www.youtube.com

www.youtube.com

www.youtube.com

ちょっとだけDirectX11その2

表題の書籍のサンプルプログラムをSharpDXで書いてみる。

f:id:tanam:20210206092224p:plain

using System;
using SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D;
using SharpDX.Direct3D11;
using SharpDX.DXGI;
using SharpDX.Windows;
using Buffer = SharpDX.Direct3D11.Buffer;
using Device = SharpDX.Direct3D11.Device;

namespace Sankaku
{
    /// <summary>
    ///   SharpDX port of SharpDX-MiniTri Direct3D 11 Sample
    /// </summary>
    internal static class Program
    {
        [STAThread]
        private static void Main()
        {
            var form = new RenderForm("SharpDX - Direct3D 11 サンプル Sankaku01");

            // SwapChain description
            var desc = new SwapChainDescription()
            {
                BufferCount = 1,
                ModeDescription =
                                   new ModeDescription(640, 480,
                                                       new Rational(60, 1), Format.R8G8B8A8_UNorm),
                IsWindowed = true,
                OutputHandle = form.Handle,
                SampleDescription = new SampleDescription(1, 0),
                SwapEffect = SwapEffect.Discard,
                Usage = Usage.RenderTargetOutput
            };

            // Create Device and SwapChain
            Device device;
            SwapChain swapChain;
            Device.CreateWithSwapChain(DriverType.Hardware, DeviceCreationFlags.None, desc, out device, out swapChain);
            var context = device.ImmediateContext;

            // Ignore all windows events
//            var factory = swapChain.GetParent<Factory>();
//            factory.MakeWindowAssociation(form.Handle, WindowAssociationFlags.IgnoreAll);

            // New RenderTargetView from the backbuffer
            var backBuffer = Texture2D.FromSwapChain<Texture2D>(swapChain, 0);
            var renderView = new RenderTargetView(device, backBuffer);

            // Compile Vertex and Pixel shaders
            var vertexShaderByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "VS", "vs_4_0", ShaderFlags.None, EffectFlags.None);
            var vertexShader = new VertexShader(device, vertexShaderByteCode);

            var pixelShaderByteCode = ShaderBytecode.CompileFromFile("MiniTri.fx", "PS", "ps_4_0", ShaderFlags.None, EffectFlags.None);
            var pixelShader = new PixelShader(device, pixelShaderByteCode);

            // Layout from VertexShader input signature
            var layout = new InputLayout(
                device,
                ShaderSignature.GetInputSignature(vertexShaderByteCode),
                new[]
                    {
                        new InputElement("POSITION", 0, Format.R32G32B32A32_Float, 0, 0),
                        new InputElement("COLOR", 0, Format.R32G32B32A32_Float, 16, 0)
                    });

            // Instantiate Vertex buiffer from vertex data
            //            var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[]
            //                                  {
            //                                      new Vector4(0.0f, 0.5f, 0.5f, 1.0f), new Vector4(1.0f, 0.0f, 0.0f, 1.0f),
            //                                      new Vector4(0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 1.0f, 0.0f, 1.0f),
            //                                      new Vector4(-0.5f, -0.5f, 0.5f, 1.0f), new Vector4(0.0f, 0.0f, 1.0f, 1.0f)
            //                                  });

            var vertices = Buffer.Create(device, BindFlags.VertexBuffer, new[]
                                  {
                                      new Vector4(0.0f, 1.5f, 0.5f, 2.0f), new Vector4(1.0f, 1.0f, 1.0f, 2.0f),
                                      new Vector4(1.0f, -1.0f, 0.5f, 2.0f), new Vector4(1.0f, 1.0f, 1.0f, 2.0f),
                                      new Vector4(-1.0f, -1.0f, 0.5f, 2.0f), new Vector4(1.0f, 1.0f, 1.0f, 2.0f)
                                  });
            
            // Prepare All the stages
            context.InputAssembler.InputLayout = layout;
            context.InputAssembler.PrimitiveTopology = PrimitiveTopology.TriangleList;
            context.InputAssembler.SetVertexBuffers(0, new VertexBufferBinding(vertices, 32, 0));
            context.VertexShader.Set(vertexShader);
            context.Rasterizer.SetViewport(new Viewport(0, 0, 640, 480, 0.0f, 1.0f));
            context.PixelShader.Set(pixelShader);
            context.OutputMerger.SetTargets(renderView);

            // Main loop
            RenderLoop.Run(form, () =>
            {
                context.ClearRenderTargetView(renderView, new Color(0.0f, 0.5f, 0.7f, 1.0f));
                context.Draw(3, 0);
                swapChain.Present(0, PresentFlags.None);
            });

            // Release all resources
            vertexShaderByteCode.Dispose();
            vertexShader.Dispose();
            pixelShaderByteCode.Dispose();
            pixelShader.Dispose();
            vertices.Dispose();
            layout.Dispose();
            renderView.Dispose();
            backBuffer.Dispose();
            context.ClearState();
            context.Flush();
            device.Dispose();
            context.Dispose();
            swapChain.Dispose();
//            factory.Dispose();
        }
    }
}

第二種電気工事士の資格に挑戦してみる その5

ついに第二種電気工事士の資格取得しました!

さっそく免状交付のために、神奈川県電気工事工業組合本部事務局に行ってきました。

  • 受験用写真 800円
  • 免許用写真 800円
  • 住民票 300円
  • 神奈川県収入証紙 5300円

ちょっとだけDirectX11

表題の書籍でDirectX11の勉強をはじめる。

https://www.kohgakusha.co.jp/books/detail/978-4-7775-1501-1

ひっかかったのはDXSDK_Jun10のサンプルをビルドする必要があると言う事。

C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Samples\C++\Effects11

ここで作成されるEffects11.libをリネームして配置する必要がありました。

C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include\d3dx11effect.h
C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x86\d3dx11effects.lib

サンプルプログラムをSharpDXで書いてみました。

using System;
using System.Windows.Forms;
using SharpDX;
using SharpDX.Direct2D1;
using SharpDX.DirectWrite;
using SharpDX.DXGI;
using SharpDX.Windows;
using TextAntialiasMode = SharpDX.Direct2D1.TextAntialiasMode;
using AlphaMode = SharpDX.Direct2D1.AlphaMode;
using Factory = SharpDX.Direct2D1.Factory;

namespace HelloApp
{

    /// <summary>
    /// Shows how to use DirectWrite to render simple text.
    /// Port of DirectWrite sample SimpleHelloWorld from Windows 7 SDK samples
    /// http://msdn.microsoft.com/en-us/library/dd742738%28v=VS.85%29.aspx
    /// </summary>
    public class Program
    {
        private FormWindowState _currentFormWindowState;
        private Form _form;
        public Factory Factory2D { get; private set; }
        public SharpDX.DirectWrite.Factory FactoryDWrite { get; private set; }
        public WindowRenderTarget RenderTarget2D { get; private set; }
        public SolidColorBrush SceneColorBrush { get; private set; }
        public TextFormat TextFormat { get; private set; }
        public RectangleF ClientRectangle { get; private set; }
        protected IntPtr DisplayHandle
        {
            get
            {
                return _form.Handle;
            }
        }
        protected void Initialize()
        {
            Factory2D = new SharpDX.Direct2D1.Factory();
            FactoryDWrite = new SharpDX.DirectWrite.Factory();
            HwndRenderTargetProperties properties = new HwndRenderTargetProperties();
            properties.Hwnd = DisplayHandle;
            properties.PixelSize = new SharpDX.Size2(640, 480);
            properties.PresentOptions = PresentOptions.None;
            RenderTarget2D = new WindowRenderTarget(Factory2D, new RenderTargetProperties(new PixelFormat(Format.Unknown, AlphaMode.Premultiplied)), properties);
            RenderTarget2D.AntialiasMode = AntialiasMode.PerPrimitive;
            SceneColorBrush = new SolidColorBrush(RenderTarget2D, Color.White);
            TextFormat = new TextFormat(FactoryDWrite, "メイリオ", 50) { TextAlignment = TextAlignment.Center, ParagraphAlignment = ParagraphAlignment.Center };
            RenderTarget2D.TextAntialiasMode = TextAntialiasMode.Cleartype;
            ClientRectangle = new RectangleF(0, 0, 640, 480);
            SceneColorBrush.Color = Color.Black;               
        }
        protected void Draw()
        {
            RenderTarget2D.Clear(Color.White);
            RenderTarget2D.DrawText("Hello, World!", TextFormat, ClientRectangle, SceneColorBrush);
        }

        private void HandleResize(object sender, EventArgs e)
        {
            if (_form.WindowState == FormWindowState.Minimized)
            {
                return;
            }

        }
        protected virtual Form CreateForm()
        {
            return new RenderForm("Direct2D Hello Application")
            {
                ClientSize = new System.Drawing.Size(640, 480)
            };
        }

        public void Run()
        {
            _form = CreateForm();
            Initialize();

            bool isFormClosed = false;
            bool formIsResizing = false;

            _form.Resize += (o, args) =>
            {
                if (_form.WindowState != _currentFormWindowState)
                {
                    HandleResize(o, args);
                }

                _currentFormWindowState = _form.WindowState;
            };

            _form.ResizeBegin += (o, args) => { formIsResizing = true; };
            _form.ResizeEnd += (o, args) =>
            {
                formIsResizing = false;
                HandleResize(o, args);
            };

            _form.Closed += (o, args) => { isFormClosed = true; };

            RenderLoop.Run(_form, () =>
            {
                if (isFormClosed)
                {
                    return;
                }
                RenderTarget2D.BeginDraw();
                Draw();
                RenderTarget2D.EndDraw();
            });
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Program program = new Program();
            program.Run();
        }
    }
}