├── .appveyor.yml
├── .github
└── workflows
│ └── pvs-studio.yml
├── .gitignore
├── LICENSE
├── README.md
├── astyle-cpp-options
├── emulator
├── !astyle.bat
├── !version.bat
├── BKBTL-VS2015.sln
├── BKBTL-VS2015.vcxproj
├── BKBTL-VS2015.vcxproj.filters
├── Common.cpp
├── Common.h
├── ConsoleView.cpp
├── DebugView.cpp
├── Dialogs.cpp
├── Dialogs.h
├── DisasmView.cpp
├── Emulator.cpp
├── Emulator.h
├── Joystick.cpp
├── Joystick.h
├── KeyboardView.cpp
├── Main.cpp
├── Main.h
├── MainWindow.cpp
├── MemoryMapView.cpp
├── MemoryView.cpp
├── ScreenView.cpp
├── Settings.cpp
├── SoundGen.cpp
├── SoundGen.h
├── SpriteView.cpp
├── TapeView.cpp
├── TeletypeView.cpp
├── ToolWindow.cpp
├── ToolWindow.h
├── Views.h
├── emubase
│ ├── Board.cpp
│ ├── Board.h
│ ├── Defines.h
│ ├── Disasm.cpp
│ ├── Emubase.h
│ ├── Floppy.cpp
│ ├── Processor.cpp
│ ├── Processor.h
│ └── SoundAY.cpp
├── manifest.xml
├── res
│ ├── BKBTL.ico
│ ├── BKBTL.rc
│ ├── Keyboard.png
│ ├── Keyboard11m.png
│ ├── Toolbar.bmp
│ ├── resource.h
│ └── small.ico
├── stdafx.cpp
├── stdafx.h
└── util
│ ├── BitmapFile.cpp
│ ├── BitmapFile.h
│ ├── WavPcmFile.cpp
│ └── WavPcmFile.h
└── roms
├── b11m_bos.rom
├── b11m_ext.rom
├── b11m_mstd.rom
├── basic10_1.rom
├── basic10_2.rom
├── basic10_3.rom
├── basic11m_0.rom
├── basic11m_1.rom
├── disk_253.rom
├── disk_326.rom
├── disk_327.rom
├── focal.rom
├── monit10.rom
└── tests.rom
/.appveyor.yml:
--------------------------------------------------------------------------------
1 |
2 | init:
3 | - git config --global core.autocrlf input
4 |
5 | clone_folder: C:\projects\bkbtl
6 | shallow_clone: true
7 |
8 | matrix:
9 | fast_finish: false
10 |
11 | configuration:
12 | - Debug
13 | - Release
14 | - Product
15 |
16 | environment:
17 | matrix:
18 | - toolchain: msvc15
19 | project_name: emulator\BKBTL-VS2015.sln
20 | platform: x86
21 | APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
22 | # - toolchain: msvc17
23 | # project_name: emulator\BKBTL-VS2015.sln
24 | # platform: x86
25 | # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
26 | # - toolchain: msvc19
27 | # project_name: emulator\BKBTL-VS2015.sln
28 | # platform: x86
29 | # APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
30 |
31 | build:
32 | project: $(project_name)
33 |
--------------------------------------------------------------------------------
/.github/workflows/pvs-studio.yml:
--------------------------------------------------------------------------------
1 | name: PVS-Studio analysis
2 |
3 | on: workflow_dispatch
4 |
5 | defaults:
6 | run:
7 | shell: cmd
8 |
9 | jobs:
10 | build-analyze:
11 | runs-on: windows-latest
12 | steps:
13 | - name: Checkout
14 | uses: actions/checkout@v3
15 | - name: Download PVS Studio
16 | uses: suisei-cn/actions-download-file@v1.3.0
17 | with:
18 | url: https://files.pvs-studio.com/PVS-Studio_setup.exe
19 | target: .\Distrib
20 | - name: Install PVS Studio
21 | run: |
22 | .\Distrib\PVS-Studio_setup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /COMPONENTS=Core
23 | - name: Configure PVS Studio
24 | run: |
25 | "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" credentials -u ${{ secrets.PVS_STUDIO_USERNAME }} -n ${{ secrets.PVS_STUDIO_KEY }}
26 | - name: Run PVS Studio
27 | run: |
28 | mkdir Results
29 | "C:\Program Files (x86)\PVS-Studio\PVS-Studio_Cmd.exe" -t .\emulator\BKBTL-VS2015.sln -e %GITHUB_WORKSPACE% -o .\Results\BKBTL.plog
30 | continue-on-error: true
31 | - name: Convert the report
32 | run: |
33 | "C:\Program Files (x86)\PVS-Studio\PlogConverter.exe" -t Html,Totals -o .\Results\ -r D:\Work\MyProjects\bkbtl -d V536,V1042 .\Results\BKBTL.plog
34 | - name: Upload the report
35 | uses: actions/upload-artifact@v3
36 | with:
37 | name: BKBTL-PVS
38 | path: .\Results\
39 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | Debug
2 | Product
3 | Release
4 | *.ncb
5 | *.suo
6 | *.user
7 | *.suppress
8 | *.sdf
9 | *.opensdf
10 | *.VC.db
11 | *.VC.opendb
12 | .vs
13 | ipch
14 | *.rom
15 | trace.log
16 | /emulator/Version.h
17 | BKBTL.APS
18 | trace.log
19 | *.dsk
20 | *.img
21 | *.bkd
22 | *.lst
23 | *.txt
24 | *.bkst
25 | /x-*
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | GNU LESSER GENERAL PUBLIC LICENSE
2 | Version 3, 29 June 2007
3 |
4 | Copyright (C) 2007 Free Software Foundation, Inc.
5 | Everyone is permitted to copy and distribute verbatim copies
6 | of this license document, but changing it is not allowed.
7 |
8 |
9 | This version of the GNU Lesser General Public License incorporates
10 | the terms and conditions of version 3 of the GNU General Public
11 | License, supplemented by the additional permissions listed below.
12 |
13 | 0. Additional Definitions.
14 |
15 | As used herein, "this License" refers to version 3 of the GNU Lesser
16 | General Public License, and the "GNU GPL" refers to version 3 of the GNU
17 | General Public License.
18 |
19 | "The Library" refers to a covered work governed by this License,
20 | other than an Application or a Combined Work as defined below.
21 |
22 | An "Application" is any work that makes use of an interface provided
23 | by the Library, but which is not otherwise based on the Library.
24 | Defining a subclass of a class defined by the Library is deemed a mode
25 | of using an interface provided by the Library.
26 |
27 | A "Combined Work" is a work produced by combining or linking an
28 | Application with the Library. The particular version of the Library
29 | with which the Combined Work was made is also called the "Linked
30 | Version".
31 |
32 | The "Minimal Corresponding Source" for a Combined Work means the
33 | Corresponding Source for the Combined Work, excluding any source code
34 | for portions of the Combined Work that, considered in isolation, are
35 | based on the Application, and not on the Linked Version.
36 |
37 | The "Corresponding Application Code" for a Combined Work means the
38 | object code and/or source code for the Application, including any data
39 | and utility programs needed for reproducing the Combined Work from the
40 | Application, but excluding the System Libraries of the Combined Work.
41 |
42 | 1. Exception to Section 3 of the GNU GPL.
43 |
44 | You may convey a covered work under sections 3 and 4 of this License
45 | without being bound by section 3 of the GNU GPL.
46 |
47 | 2. Conveying Modified Versions.
48 |
49 | If you modify a copy of the Library, and, in your modifications, a
50 | facility refers to a function or data to be supplied by an Application
51 | that uses the facility (other than as an argument passed when the
52 | facility is invoked), then you may convey a copy of the modified
53 | version:
54 |
55 | a) under this License, provided that you make a good faith effort to
56 | ensure that, in the event an Application does not supply the
57 | function or data, the facility still operates, and performs
58 | whatever part of its purpose remains meaningful, or
59 |
60 | b) under the GNU GPL, with none of the additional permissions of
61 | this License applicable to that copy.
62 |
63 | 3. Object Code Incorporating Material from Library Header Files.
64 |
65 | The object code form of an Application may incorporate material from
66 | a header file that is part of the Library. You may convey such object
67 | code under terms of your choice, provided that, if the incorporated
68 | material is not limited to numerical parameters, data structure
69 | layouts and accessors, or small macros, inline functions and templates
70 | (ten or fewer lines in length), you do both of the following:
71 |
72 | a) Give prominent notice with each copy of the object code that the
73 | Library is used in it and that the Library and its use are
74 | covered by this License.
75 |
76 | b) Accompany the object code with a copy of the GNU GPL and this license
77 | document.
78 |
79 | 4. Combined Works.
80 |
81 | You may convey a Combined Work under terms of your choice that,
82 | taken together, effectively do not restrict modification of the
83 | portions of the Library contained in the Combined Work and reverse
84 | engineering for debugging such modifications, if you also do each of
85 | the following:
86 |
87 | a) Give prominent notice with each copy of the Combined Work that
88 | the Library is used in it and that the Library and its use are
89 | covered by this License.
90 |
91 | b) Accompany the Combined Work with a copy of the GNU GPL and this license
92 | document.
93 |
94 | c) For a Combined Work that displays copyright notices during
95 | execution, include the copyright notice for the Library among
96 | these notices, as well as a reference directing the user to the
97 | copies of the GNU GPL and this license document.
98 |
99 | d) Do one of the following:
100 |
101 | 0) Convey the Minimal Corresponding Source under the terms of this
102 | License, and the Corresponding Application Code in a form
103 | suitable for, and under terms that permit, the user to
104 | recombine or relink the Application with a modified version of
105 | the Linked Version to produce a modified Combined Work, in the
106 | manner specified by section 6 of the GNU GPL for conveying
107 | Corresponding Source.
108 |
109 | 1) Use a suitable shared library mechanism for linking with the
110 | Library. A suitable mechanism is one that (a) uses at run time
111 | a copy of the Library already present on the user's computer
112 | system, and (b) will operate properly with a modified version
113 | of the Library that is interface-compatible with the Linked
114 | Version.
115 |
116 | e) Provide Installation Information, but only if you would otherwise
117 | be required to provide such information under section 6 of the
118 | GNU GPL, and only to the extent that such information is
119 | necessary to install and execute a modified version of the
120 | Combined Work produced by recombining or relinking the
121 | Application with a modified version of the Linked Version. (If
122 | you use option 4d0, the Installation Information must accompany
123 | the Minimal Corresponding Source and Corresponding Application
124 | Code. If you use option 4d1, you must provide the Installation
125 | Information in the manner specified by section 6 of the GNU GPL
126 | for conveying Corresponding Source.)
127 |
128 | 5. Combined Libraries.
129 |
130 | You may place library facilities that are a work based on the
131 | Library side by side in a single library together with other library
132 | facilities that are not Applications and are not covered by this
133 | License, and convey such a combined library under terms of your
134 | choice, if you do both of the following:
135 |
136 | a) Accompany the combined library with a copy of the same work based
137 | on the Library, uncombined with any other library facilities,
138 | conveyed under the terms of this License.
139 |
140 | b) Give prominent notice with the combined library that part of it
141 | is a work based on the Library, and explaining where to find the
142 | accompanying uncombined form of the same work.
143 |
144 | 6. Revised Versions of the GNU Lesser General Public License.
145 |
146 | The Free Software Foundation may publish revised and/or new versions
147 | of the GNU Lesser General Public License from time to time. Such new
148 | versions will be similar in spirit to the present version, but may
149 | differ in detail to address new problems or concerns.
150 |
151 | Each version is given a distinguishing version number. If the
152 | Library as you received it specifies that a certain numbered version
153 | of the GNU Lesser General Public License "or any later version"
154 | applies to it, you have the option of following the terms and
155 | conditions either of that published version or of any later version
156 | published by the Free Software Foundation. If the Library as you
157 | received it does not specify a version number of the GNU Lesser
158 | General Public License, you may choose any version of the GNU Lesser
159 | General Public License ever published by the Free Software Foundation.
160 |
161 | If the Library as you received it specifies that a proxy can decide
162 | whether future versions of the GNU Lesser General Public License shall
163 | apply, that proxy's public statement of acceptance of any version is
164 | permanent authorization for you to choose that version for the
165 | Library.
166 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # bkbtl - BKBTL emulator, Win32 version
2 |
3 | [](https://www.gnu.org/licenses/lgpl-3.0)
4 | [](https://ci.appveyor.com/project/nzeemin/bkbtl)
5 | [](https://www.codefactor.io/repository/github/nzeemin/bkbtl)
6 |
7 | 
8 |
9 |
10 | ## На русском / In Russian
11 |
12 | **BKBTL** — **BK Back to Life!** — это проект эмуляции советского бытового компьютера [БК-0010/БК-0011](http://ru.wikipedia.org/wiki/БК), построенного на 16-разрядном процессоре К1801ВМ1, совместимом по системе команд с семейством PDP-11. Проект начат 14 ноября 2009 года. Основан на коде проекта [UKNCBTL](https://github.com/nzeemin/ukncbtl).
13 |
14 | В проект BKBTL входят репозитории:
15 | * **bkbtl** — Windows-версия. Написана под Win32 и требует поддержки Юникода, поэтому набор версий Windows — 2000/2003/2008/XP/Vista/7.
16 | * [**bkbtl-qt**](https://github.com/nzeemin/bkbtl-qt) — Qt-версия. Работает под Windows, Linux и Mac OS X. В Qt-версии нет поддержки звука, нет окна карты памяти, нет поддержки внешнего джойстика; в остальном возможности те же.
17 | * [**bkbtl-testbench**](https://github.com/nzeemin/bkbtl-testbench) — тестовый стенд для регрессионного тестирования.
18 | * [**bkbtl-doc**](https://github.com/nzeemin/bkbtl-doc) — документация и скриншоты.
19 |
20 | ### Состояние эмулятора
21 |
22 | Бета-версия. Многие игры пока не работают. Дисковод более-менее работает в конфигурации БК-0011М.
23 |
24 | Поддерживаются конфигурации:
25 | БК-0010.01+Бейсик, БК-0010.01+Фокал+тесты, БК-0010.01+дисковод, БК-0011М+тесты, БК-0011М+дисковод.
26 |
27 | Эмулируется:
28 | * БК-0010.01 и БК-0011М
29 | * процессор (тест 791401 проходит, тест 791404 НЕ проходит)
30 | * материнская плата (частично, тест памяти 791323 НЕ проходит)
31 | * экран — черно-белый, цветной, усеченный режим, палитры цветного режима БК-0011
32 | * клавиатура — маппинг PC-клавиатуры на БК-клавиатуру зависит от переключателя РУС/ЛАТ в БК (но размаплены не все клавиши)
33 | * чтение с магнитофона (из файла формата WAV), запись на магнитофон (в WAV-файл)
34 | * звук пьезодинамика БК
35 | * Covox
36 | * джойстик (клавиши NumPad, внешний джойстик)
37 | * ИРПС на регистрах 177560..0177566 (пока только передача данных в отладочное окно) — используется для прогона тестов
38 | * дисковод (более-менее в конфигурации БК-0011М)
39 | * AY-3-8910
40 |
41 | Планируется сделать:
42 |
43 | * сделать правильную систему прерываний процессора (пока сделано ближе к ВМ2)
44 | * прогон тестов 791404 и 791323, отладка работы машины на них
45 | * доделать маппинг клавиатуры
46 | * программируемый таймер (нужно доделать)
47 | * мышь
48 |
49 |
50 | ## In English
51 |
52 | **BKBTL** — **BK Back to Life!** — is [BK0010/BK0011](http://en.wikipedia.org/wiki/Elektronika_BK) emulator.
53 | The emulation project started on Nov. 14, 2009 and based on [UKNCBTL](https://github.com/nzeemin/ukncbtl) code.
54 | BK is soviet home computer based on 16-bit PDP-11 compatible processor K1801VM1.
55 |
56 | The BKBTL project consists of:
57 | * [**bkbtl**](https://github.com/nzeemin/bkbtl) — Win32 version, for Windows.
58 | * [**bkbtl-qt**](https://github.com/nzeemin/bkbtl-qt) is Qt based BKBTL branch, works under Windows, Linux and Mac OS X.
59 | * [**bkbtl-testbench**](https://github.com/nzeemin/bkbtl-testbench) — test bench for regression testing.
60 | * [**bkbtl-doc**](https://github.com/nzeemin/bkbtl-doc) — documentation and screenshots.
61 | * Project wiki: https://github.com/nzeemin/bkbtl-doc/wiki
62 |
63 | Current status: Beta, under development.
64 |
65 | Emulated:
66 | * BK-0010.01 and BK-0011M
67 | * CPU
68 | * Motherboard
69 | * Screen — black and white mode, color mode, short mode, BK0011 color mode palettes
70 | * Keyboard (but mapped not all BK keys)
71 | * Reading from tape (WAV file), writing to tape (WAV file)
72 | * Sound
73 | * Joystick (numpad keys, external joystick)
74 | * Covox
75 | * Floppy drive (at least in BK11M configuration)
76 | * Programmable timer (partially)
77 |
78 |
--------------------------------------------------------------------------------
/astyle-cpp-options:
--------------------------------------------------------------------------------
1 | ## Formatting options for
2 | ## Astyle - Source code indenter, formatter, and beautifier for C, C++, and Java Source Code
3 | ## http://astyle.sourceforge.net/
4 |
5 | # Indent as C/C++
6 | --mode=c
7 | # Use CRLF line end style
8 | --lineend=windows
9 |
10 | # Allman style formatting/indenting uses broken brackets
11 | --style=break
12 |
13 | # Indent using 4 spaces per indent
14 | --indent=spaces=4
15 | --indent-namespaces
16 | # Indent 'case X:' blocks from the 'case X:' headers. Case statements not enclosed in blocks are NOT indented.
17 | --indent-cases
18 |
19 | --min-conditional-indent=0
20 | --max-instatement-indent=8
21 |
22 | # Insert space padding around operators
23 | --pad-oper
24 | # Insert space padding after paren headers only (e.g. 'if', 'for', 'while'...)
25 | --pad-header
26 |
27 | --break-closing-brackets
28 |
29 | # Don't break one-line blocks
30 | --keep-one-line-blocks
31 | # Don't break complex statements and multiple statements residing on a single line
32 | --keep-one-line-statements
33 |
--------------------------------------------------------------------------------
/emulator/!astyle.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | set ASTYLEEXE=c:\bin\astyle.exe
3 | set ASTYLEOPT=-n -Q --options=..\astyle-cpp-options
4 | %ASTYLEEXE% %ASTYLEOPT% emubase\*.h emubase\*.cpp Util\*.h Util\*.cpp
5 | %ASTYLEEXE% %ASTYLEOPT% *.h *.cpp --exclude=Version.h --exclude=stdafx.h --exclude=stdafx.cpp
6 |
--------------------------------------------------------------------------------
/emulator/!version.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
4 | set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
5 | REM echo Year: %YYYY%
6 |
7 | REM set YYYY=2020
8 | REM git log --tags --simplify-by-decoration --pretty="format:%%cI %%d" | find /c "%YYYY%"
9 |
10 | set VERMINOR=
11 | for /f "tokens=* USEBACKQ" %%a in (
12 | `git log --tags --simplify-by-decoration --pretty^=^"format^:%%cI^" ^| find ^/c ^"%YYYY%^"`
13 | ) do set VERMINOR=%%a
14 | REM echo Version minor: %VERMINOR%
15 | set /A VERMINOR=%VERMINOR%+1
16 | REM echo %VERMINOR%
17 |
18 | echo Version: %YYYY%.%VERMINOR%
19 |
20 | for /f %%i in ('git rev-list HEAD --count') do set REVISION=%%i
21 | set /A REVISION=%REVISION%+0
22 | echo Revision: %REVISION%
23 |
24 | echo. > Version.h
25 | echo #define APP_VERSION_STRING "%YYYY%.%VERMINOR%" >> Version.h
26 | echo. >> Version.h
27 | echo #define APP_REVISION %REVISION% >> Version.h
28 |
--------------------------------------------------------------------------------
/emulator/BKBTL-VS2015.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BKBTL", "BKBTL-VS2015.vcxproj", "{50C37290-5770-42A8-B0A1-88571C4214FD}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|x86 = Debug|x86
11 | Product|x86 = Product|x86
12 | Release|x86 = Release|x86
13 | EndGlobalSection
14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
15 | {50C37290-5770-42A8-B0A1-88571C4214FD}.Debug|x86.ActiveCfg = Debug|Win32
16 | {50C37290-5770-42A8-B0A1-88571C4214FD}.Debug|x86.Build.0 = Debug|Win32
17 | {50C37290-5770-42A8-B0A1-88571C4214FD}.Product|x86.ActiveCfg = Product|Win32
18 | {50C37290-5770-42A8-B0A1-88571C4214FD}.Product|x86.Build.0 = Product|Win32
19 | {50C37290-5770-42A8-B0A1-88571C4214FD}.Release|x86.ActiveCfg = Release|Win32
20 | {50C37290-5770-42A8-B0A1-88571C4214FD}.Release|x86.Build.0 = Release|Win32
21 | EndGlobalSection
22 | GlobalSection(SolutionProperties) = preSolution
23 | HideSolutionNode = FALSE
24 | EndGlobalSection
25 | EndGlobal
26 |
--------------------------------------------------------------------------------
/emulator/BKBTL-VS2015.vcxproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | Win32
7 |
8 |
9 | Product
10 | Win32
11 |
12 |
13 | Release
14 | Win32
15 |
16 |
17 |
18 | BKBTL
19 | {50C37290-5770-42A8-B0A1-88571C4214FD}
20 | BKBTL
21 | Win32Proj
22 |
23 |
24 |
25 | Application
26 | v120_xp
27 | Unicode
28 | true
29 |
30 |
31 | Application
32 | v120_xp
33 | Unicode
34 | true
35 |
36 |
37 | Application
38 | v120_xp
39 | Unicode
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | $(SolutionDir)$(Configuration)\
56 | $(Configuration)\
57 | false
58 | true
59 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)
60 |
61 |
62 | $(SolutionDir)$(Configuration)\
63 | $(Configuration)\
64 | false
65 | true
66 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)
67 |
68 |
69 | $(SolutionDir)$(Configuration)\
70 | $(Configuration)\
71 | false
72 | true
73 | $(VC_IncludePath);$(WindowsSDK_IncludePath);$(ProjectDir)
74 |
75 |
76 |
77 | Disabled
78 | WIN32;_DEBUG;_WINDOWS;%(PreprocessorDefinitions)
79 | true
80 | EnableFastChecks
81 | MultiThreadedDebug
82 | Use
83 | Level4
84 | ProgramDatabase
85 | stdafx.h
86 |
87 |
88 | Vfw32.lib;comctl32.lib;winmm.lib;advapi32.lib;Windowscodecs.lib;%(AdditionalDependencies)
89 | true
90 | Windows
91 | false
92 |
93 | MachineX86
94 | true
95 |
96 |
97 | manifest.xml;%(AdditionalManifestFiles)
98 |
99 |
100 |
101 |
102 | WIN32;NDEBUG;_WINDOWS;%(PreprocessorDefinitions)
103 | MultiThreaded
104 | Use
105 | Level4
106 | ProgramDatabase
107 |
108 |
109 | Vfw32.lib;comctl32.lib;winmm.lib;Windowscodecs.lib;%(AdditionalDependencies)
110 | true
111 | Windows
112 | true
113 | true
114 | false
115 |
116 | MachineX86
117 |
118 |
119 | manifest.xml;%(AdditionalManifestFiles)
120 |
121 |
122 |
123 |
124 | Updating Version.h file...
125 | "!version.bat"
126 |
127 |
128 | WIN32;NDEBUG;_WINDOWS;PRODUCT;%(PreprocessorDefinitions)
129 | MultiThreaded
130 | Use
131 | Level3
132 | ProgramDatabase
133 |
134 |
135 | Vfw32.lib;comctl32.lib;winmm.lib;Windowscodecs.lib;%(AdditionalDependencies)
136 | true
137 | Windows
138 | true
139 | true
140 | false
141 |
142 | MachineX86
143 | true
144 |
145 |
146 | manifest.xml;%(AdditionalManifestFiles)
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
171 |
172 | Create
173 | Create
174 | Create
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
--------------------------------------------------------------------------------
/emulator/BKBTL-VS2015.vcxproj.filters:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {7d452430-e1ea-4900-a898-bba738f6c517}
6 |
7 |
8 | {500e3849-29dd-4d33-a2d2-cc45c9d34dac}
9 |
10 |
11 | {10e7b8b1-4f0b-4b55-a01a-11cbd357109a}
12 |
13 |
14 |
15 |
16 | emubase
17 |
18 |
19 | emubase
20 |
21 |
22 | emubase
23 |
24 |
25 | emubase
26 |
27 |
28 | util
29 |
30 |
31 | util
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | emubase
58 |
59 |
60 | emubase
61 |
62 |
63 | emubase
64 |
65 |
66 | emubase
67 |
68 |
69 | util
70 |
71 |
72 | util
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 | res
98 |
99 |
100 |
--------------------------------------------------------------------------------
/emulator/Common.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Common.cpp
12 |
13 | #include "stdafx.h"
14 | #include "Main.h"
15 | #include "Views.h"
16 |
17 | //////////////////////////////////////////////////////////////////////
18 |
19 |
20 | BOOL AssertFailedLine(LPCSTR lpszFileName, int nLine)
21 | {
22 | TCHAR buffer[360];
23 | _sntprintf(buffer, sizeof(buffer) / sizeof(TCHAR) - 1,
24 | _T("ASSERTION FAILED\n\nFile: %S\nLine: %d\n\n")
25 | _T("Press Abort to stop the program, Retry to break to the debugger, or Ignore to continue execution."),
26 | lpszFileName, nLine);
27 | int result = MessageBox(NULL, buffer, _T("ASSERT"), MB_ICONSTOP | MB_ABORTRETRYIGNORE);
28 |
29 | switch (result)
30 | {
31 | case IDRETRY:
32 | return TRUE;
33 | case IDIGNORE:
34 | return FALSE;
35 | case IDABORT:
36 | PostQuitMessage(255);
37 | }
38 | return FALSE;
39 | }
40 |
41 | void AlertInfo(LPCTSTR sMessage)
42 | {
43 | ::MessageBox(NULL, sMessage, g_szTitle, MB_OK | MB_ICONINFORMATION | MB_TOPMOST);
44 | }
45 | void AlertWarning(LPCTSTR sMessage)
46 | {
47 | ::MessageBox(NULL, sMessage, g_szTitle, MB_OK | MB_ICONEXCLAMATION | MB_TOPMOST);
48 | }
49 | void AlertWarningFormat(LPCTSTR sFormat, ...)
50 | {
51 | const size_t buffersize = 512;
52 | TCHAR buffer[buffersize];
53 |
54 | va_list ptr;
55 | va_start(ptr, sFormat);
56 | _vsntprintf_s(buffer, buffersize, buffersize - 1, sFormat, ptr);
57 | va_end(ptr);
58 |
59 | ::MessageBox(NULL, buffer, g_szTitle, MB_OK | MB_ICONEXCLAMATION | MB_TOPMOST);
60 | }
61 | BOOL AlertOkCancel(LPCTSTR sMessage)
62 | {
63 | int result = ::MessageBox(NULL, sMessage, g_szTitle, MB_OKCANCEL | MB_ICONQUESTION | MB_TOPMOST);
64 | return (result == IDOK);
65 | }
66 |
67 |
68 | //////////////////////////////////////////////////////////////////////
69 | // DebugPrint and DebugLog
70 |
71 | #if defined(PRODUCT)
72 |
73 | void DebugPrint(LPCTSTR) {}
74 | void DebugPrintFormat(LPCTSTR, ...) {}
75 | void DebugLogClear() {}
76 | void DebugLogCloseFile() {}
77 | void DebugLog(LPCTSTR) {}
78 | void DebugLogFormat(LPCTSTR, ...) {}
79 |
80 | #else
81 |
82 | void DebugPrint(LPCTSTR message)
83 | {
84 | if (g_hwndConsole == NULL)
85 | return;
86 |
87 | ConsoleView_Print(message);
88 | }
89 |
90 | void DebugPrintFormat(LPCTSTR pszFormat, ...)
91 | {
92 | const size_t buffersize = 512;
93 | TCHAR buffer[buffersize];
94 |
95 | va_list ptr;
96 | va_start(ptr, pszFormat);
97 | _vsntprintf_s(buffer, buffersize, buffersize - 1, pszFormat, ptr);
98 | va_end(ptr);
99 |
100 | DebugPrint(buffer);
101 | }
102 |
103 | const LPCTSTR TRACELOG_FILE_NAME = _T("trace.log");
104 | const LPCTSTR TRACELOG_NEWLINE = _T("\r\n");
105 |
106 | HANDLE Common_LogFile = NULL;
107 |
108 | void DebugLogCreateFile()
109 | {
110 | if (Common_LogFile == NULL)
111 | {
112 | Common_LogFile = ::CreateFile(TRACELOG_FILE_NAME,
113 | GENERIC_WRITE, FILE_SHARE_READ, NULL,
114 | CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
115 | }
116 | }
117 |
118 | void DebugLogCloseFile()
119 | {
120 | if (Common_LogFile == NULL)
121 | return;
122 |
123 | ::CloseHandle(Common_LogFile);
124 | Common_LogFile = NULL;
125 | }
126 |
127 | void DebugLogClear()
128 | {
129 | DebugLogCreateFile();
130 |
131 | if (Common_LogFile != NULL)
132 | {
133 | // Trunkate to zero length
134 | ::SetFilePointer(Common_LogFile, 0, 0, 0);
135 | ::SetEndOfFile(Common_LogFile);
136 | }
137 | }
138 |
139 | void DebugLog(LPCTSTR message)
140 | {
141 | DebugLogCreateFile();
142 |
143 | SetFilePointer(Common_LogFile, 0, NULL, FILE_END);
144 |
145 | int nLength = lstrlen(message) * sizeof(TCHAR);
146 |
147 | char ascii[256]; *ascii = 0;
148 | WideCharToMultiByte(CP_ACP, 0, message, nLength, ascii, 256, NULL, NULL);
149 |
150 | DWORD dwBytesWritten = 0;
151 | //WriteFile(Common_LogFile, message, dwLength, &dwBytesWritten, NULL);
152 | WriteFile(Common_LogFile, ascii, strlen(ascii), &dwBytesWritten, NULL);
153 |
154 | //dwLength = lstrlen(TRACELOG_NEWLINE) * sizeof(TCHAR);
155 | //WriteFile(Common_LogFile, TRACELOG_NEWLINE, dwLength, &dwBytesWritten, NULL);
156 | }
157 |
158 | void DebugLogFormat(LPCTSTR pszFormat, ...)
159 | {
160 | const size_t buffersize = 512;
161 | TCHAR buffer[buffersize];
162 |
163 | va_list ptr;
164 | va_start(ptr, pszFormat);
165 | _vsntprintf_s(buffer, buffersize, buffersize - 1, pszFormat, ptr);
166 | va_end(ptr);
167 |
168 | DebugLog(buffer);
169 | }
170 |
171 | #endif // !defined(PRODUCT)
172 |
173 |
174 | //////////////////////////////////////////////////////////////////////
175 |
176 |
177 | // Названия регистров процессора
178 | const TCHAR* REGISTER_NAME[] = { _T("R0"), _T("R1"), _T("R2"), _T("R3"), _T("R4"), _T("R5"), _T("SP"), _T("PC") };
179 |
180 |
181 | HFONT CreateMonospacedFont()
182 | {
183 | HFONT font;
184 | LOGFONT logfont; memset(&logfont, 0, sizeof(logfont));
185 | logfont.lfHeight = 12;
186 | logfont.lfWeight = FW_NORMAL;
187 | logfont.lfCharSet = DEFAULT_CHARSET;
188 | logfont.lfOutPrecision = OUT_DEFAULT_PRECIS;
189 | logfont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
190 | logfont.lfQuality = DEFAULT_QUALITY;
191 | logfont.lfPitchAndFamily = FIXED_PITCH;
192 |
193 | Settings_GetDebugFontName(logfont.lfFaceName);
194 | font = CreateFontIndirect(&logfont);
195 | if (font != NULL)
196 | return font;
197 |
198 | _tcscpy_s(logfont.lfFaceName, 32, _T("Lucida Console"));
199 | font = CreateFontIndirect(&logfont);
200 | if (font != NULL)
201 | return font;
202 |
203 | _tcscpy_s(logfont.lfFaceName, 32, _T("Courier"));
204 | font = CreateFontIndirect(&logfont);
205 | if (font != NULL)
206 | return font;
207 |
208 | return NULL;
209 | }
210 |
211 | HFONT CreateDialogFont()
212 | {
213 | HFONT font = CreateFont(
214 | 14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE,
215 | DEFAULT_CHARSET,
216 | OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY,
217 | VARIABLE_PITCH,
218 | _T("MS Shell Dlg 2"));
219 |
220 | return font;
221 | }
222 |
223 | void GetFontWidthAndHeight(HDC hdc, int* pWidth, int* pHeight)
224 | {
225 | TEXTMETRIC tm;
226 | GetTextMetrics(hdc, &tm);
227 | if (pWidth != NULL)
228 | *pWidth = tm.tmAveCharWidth;
229 | if (pHeight != NULL)
230 | *pHeight = tm.tmHeight;
231 | }
232 |
233 | // Print octal 16-bit value to buffer
234 | // buffer size at least 7 characters
235 | void PrintOctalValue(TCHAR* buffer, WORD value)
236 | {
237 | for (int p = 0; p < 6; p++)
238 | {
239 | int digit = value & 7;
240 | buffer[5 - p] = _T('0') + (TCHAR)digit;
241 | value = (value >> 3);
242 | }
243 | buffer[6] = 0;
244 | }
245 | // Print hex 16-bit value to buffer
246 | // buffer size at least 5 characters
247 | void PrintHexValue(TCHAR* buffer, WORD value)
248 | {
249 | for (int p = 0; p < 4; p++)
250 | {
251 | int digit = value & 15;
252 | buffer[3 - p] = (digit < 10) ? _T('0') + (TCHAR)digit : _T('a') + (TCHAR)(digit - 10);
253 | value = (value >> 4);
254 | }
255 | buffer[4] = 0;
256 | }
257 | // Print binary 16-bit value to buffer
258 | // buffer size at least 17 characters
259 | void PrintBinaryValue(TCHAR* buffer, WORD value)
260 | {
261 | for (int b = 0; b < 16; b++)
262 | {
263 | int bit = (value >> b) & 1;
264 | buffer[15 - b] = bit ? _T('1') : _T('0');
265 | }
266 | buffer[16] = 0;
267 | }
268 |
269 | // Parse octal value from text
270 | BOOL ParseOctalValue(LPCTSTR text, WORD* pValue)
271 | {
272 | WORD value = 0;
273 | TCHAR* pChar = (TCHAR*) text;
274 | for (int p = 0; ; p++)
275 | {
276 | if (p > 6) return FALSE;
277 | TCHAR ch = *pChar; pChar++;
278 | if (ch == 0) break;
279 | if (ch < _T('0') || ch > _T('7')) return FALSE;
280 | value = (value << 3);
281 | TCHAR digit = ch - _T('0');
282 | value += digit;
283 | }
284 | *pValue = value;
285 | return TRUE;
286 | }
287 |
288 | void DrawOctalValue(HDC hdc, int x, int y, WORD value)
289 | {
290 | TCHAR buffer[7];
291 | PrintOctalValue(buffer, value);
292 | TextOut(hdc, x, y, buffer, (int) _tcslen(buffer));
293 | }
294 | void DrawHexValue(HDC hdc, int x, int y, WORD value)
295 | {
296 | TCHAR buffer[7];
297 | PrintHexValue(buffer, value);
298 | TextOut(hdc, x, y, buffer, (int) _tcslen(buffer));
299 | }
300 | void DrawBinaryValue(HDC hdc, int x, int y, WORD value)
301 | {
302 | TCHAR buffer[17];
303 | PrintBinaryValue(buffer, value);
304 | TextOut(hdc, x, y, buffer, 16);
305 | }
306 |
307 | void CopyTextToClipboard(LPCTSTR text)
308 | {
309 | ASSERT(text != nullptr);
310 | size_t bufferLength = (_tcslen(text) + 1) * sizeof(TCHAR);
311 |
312 | // Prepare global memory object for the text
313 | HGLOBAL hglbCopy = ::GlobalAlloc(GMEM_MOVEABLE, bufferLength);
314 | LPTSTR lptstrCopy = (LPTSTR)::GlobalLock(hglbCopy);
315 | memcpy(lptstrCopy, text, bufferLength);
316 | ::GlobalUnlock(hglbCopy);
317 |
318 | // Send the text to the Clipboard
319 | ::OpenClipboard(g_hwnd);
320 | ::EmptyClipboard();
321 | ::SetClipboardData(CF_UNICODETEXT, hglbCopy);
322 | ::CloseClipboard();
323 | }
324 |
325 | // BK to Unicode conversion table
326 | const TCHAR BK_CHAR_CODES[] =
327 | {
328 | 0x3C0, 0x2534, 0x2665, 0x2510, 0x2561, 0x251C, 0x2514, 0x2550, 0x2564, 0x2660, 0x250C, 0x252C, 0x2568, 0x2193, 0x253C, 0x2551,
329 | 0x2524, 0x2190, 0x256C, 0x2191, 0x2663, 0x2500, 0x256B, 0x2502, 0x2666, 0x2518, 0x256A, 0x2565, 0x2567, 0x255E, 0x2192, 0x2593,
330 | 0x44E, 0x430, 0x431, 0x446, 0x434, 0x435, 0x444, 0x433, 0x445, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E,
331 | 0x43F, 0x44F, 0x440, 0x441, 0x442, 0x443, 0x436, 0x432, 0x44C, 0x44B, 0x437, 0x448, 0x44D, 0x449, 0x447, 0x44A,
332 | 0x42E, 0x410, 0x411, 0x426, 0x414, 0x415, 0x424, 0x413, 0x425, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E,
333 | 0x41F, 0x42F, 0x420, 0x421, 0x422, 0x423, 0x416, 0x412, 0x42C, 0x42B, 0x417, 0x428, 0x42D, 0x429, 0x427, 0x42A,
334 | };
335 | // Translate one KOI8-R character to Unicode character
336 | TCHAR Translate_BK_Unicode(BYTE ch)
337 | {
338 | if (ch < 32) return _T('·');
339 | if (ch < 127) return (TCHAR) ch;
340 | if (ch == 127) return (TCHAR) 0x25A0;
341 | if (/*ch >= 128 &&*/ ch < 160) return _T('·');
342 | return BK_CHAR_CODES[ch - 160];
343 | }
344 |
345 | // KOI7-R (Russian) to Unicode conversion table
346 | const TCHAR KOI7R_CODES[] =
347 | {
348 | 0x44E, 0x430, 0x431, 0x446, 0x434, 0x435, 0x444, 0x433, 0x445, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D, 0x43E,
349 | 0x43F, 0x44F, 0x440, 0x441, 0x442, 0x443, 0x436, 0x432, 0x44C, 0x44B, 0x437, 0x448, 0x44D, 0x449, 0x447, 0x44A,
350 | 0x42E, 0x410, 0x411, 0x426, 0x414, 0x415, 0x424, 0x413, 0x425, 0x418, 0x419, 0x41A, 0x41B, 0x41C, 0x41D, 0x41E,
351 | 0x41F, 0x42F, 0x420, 0x421, 0x422, 0x423, 0x416, 0x412, 0x42C, 0x42B, 0x417, 0x428, 0x42D, 0x429, 0x427, 0x42A,
352 | };
353 | // Translate one KOI7 character to Cyrillic Unicode character
354 | TCHAR Translate_KOI7R_Unicode(BYTE ch)
355 | {
356 | if (ch < 64 || ch >= 128) return (TCHAR) ch;
357 | return KOI7R_CODES[ch - 64];
358 | }
359 |
360 |
361 | //////////////////////////////////////////////////////////////////////
362 | // Path funcations
363 |
364 | LPCTSTR GetFileNameFromFilePath(LPCTSTR lpfilepath)
365 | {
366 | LPCTSTR lpfilename = _tcsrchr(lpfilepath, _T('\\'));
367 | if (lpfilename == NULL)
368 | return lpfilepath;
369 | else
370 | return lpfilename + 1;
371 | }
372 |
373 |
374 | //////////////////////////////////////////////////////////////////////
375 |
--------------------------------------------------------------------------------
/emulator/Common.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Common.h
12 |
13 | #pragma once
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 | #ifdef _DEBUG
18 | #define APP_VERSION_STRING "DEBUG"
19 | #define APP_REVISION 0
20 | #elif !defined(PRODUCT)
21 | #define APP_VERSION_STRING "RELEASE"
22 | #define APP_REVISION 0
23 | #else
24 | #include "Version.h"
25 | #endif
26 |
27 | //////////////////////////////////////////////////////////////////////
28 | // Assertions checking - MFC-like ASSERT macro
29 |
30 | #ifdef _DEBUG
31 |
32 | BOOL AssertFailedLine(LPCSTR lpszFileName, int nLine);
33 | #define ASSERT(f) (void) ((f) || !AssertFailedLine(__FILE__, __LINE__) || (DebugBreak(), 0))
34 | #define VERIFY(f) ASSERT(f)
35 |
36 | #else // _DEBUG
37 |
38 | #define ASSERT(f) ((void)0)
39 | #define VERIFY(f) ((void)f)
40 |
41 | #endif // !_DEBUG
42 |
43 |
44 | //////////////////////////////////////////////////////////////////////
45 | // Alerts
46 |
47 | void AlertInfo(LPCTSTR sMessage);
48 | void AlertWarning(LPCTSTR sMessage);
49 | void AlertWarningFormat(LPCTSTR sFormat, ...);
50 | BOOL AlertOkCancel(LPCTSTR sMessage);
51 |
52 |
53 | //////////////////////////////////////////////////////////////////////
54 | // DebugPrint
55 |
56 | void DebugPrint(LPCTSTR message);
57 | void DebugPrintFormat(LPCTSTR pszFormat, ...);
58 | void DebugLogClear();
59 | void DebugLogCloseFile();
60 | void DebugLog(LPCTSTR message);
61 | void DebugLogFormat(LPCTSTR pszFormat, ...);
62 |
63 |
64 | //////////////////////////////////////////////////////////////////////
65 |
66 |
67 | // Processor register names
68 | const TCHAR* REGISTER_NAME[];
69 |
70 | const int BK_SCREEN_WIDTH = 512;
71 | const int BK_SCREEN_HEIGHT = 256;
72 |
73 |
74 | HFONT CreateMonospacedFont();
75 | HFONT CreateDialogFont();
76 |
77 | void GetFontWidthAndHeight(HDC hdc, int* pWidth, int* pHeight);
78 |
79 | void PrintOctalValue(TCHAR* buffer, WORD value);
80 | void PrintHexValue(TCHAR* buffer, WORD value);
81 | void PrintBinaryValue(TCHAR* buffer, WORD value);
82 |
83 | BOOL ParseOctalValue(LPCTSTR text, WORD* pValue);
84 |
85 | void DrawOctalValue(HDC hdc, int x, int y, WORD value);
86 | void DrawHexValue(HDC hdc, int x, int y, WORD value);
87 | void DrawBinaryValue(HDC hdc, int x, int y, WORD value);
88 |
89 | TCHAR Translate_BK_Unicode(BYTE ch);
90 | TCHAR Translate_KOI7R_Unicode(BYTE ch);
91 |
92 | void CopyTextToClipboard(LPCTSTR text);
93 |
94 | LPCTSTR GetFileNameFromFilePath(LPCTSTR lpfilepath);
95 |
96 |
97 | //////////////////////////////////////////////////////////////////////
98 |
--------------------------------------------------------------------------------
/emulator/Dialogs.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Dialogs.h
12 |
13 | #pragma once
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 |
18 | void ShowAboutBox();
19 | void ShowCommandLineHelpBox();
20 |
21 | // Input octal value
22 | // strTitle - dialog caption
23 | // strPrompt - label text
24 | BOOL InputBoxOctal(HWND hwndOwner, LPCTSTR strTitle, WORD* pValue);
25 |
26 | BOOL ShowSaveDialog(HWND hwndOwner, LPCTSTR strTitle, LPCTSTR strFilter, LPCTSTR strDefExt, TCHAR* bufFileName);
27 | BOOL ShowOpenDialog(HWND hwndOwner, LPCTSTR strTitle, LPCTSTR strFilter, TCHAR* bufFileName);
28 |
29 | void ShowLoadBinDialog();
30 |
31 | void ShowSettingsDialog();
32 | BOOL ShowSettingsColorsDialog();
33 |
34 |
35 | //////////////////////////////////////////////////////////////////////
36 |
--------------------------------------------------------------------------------
/emulator/Emulator.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Emulator.h
12 |
13 | #pragma once
14 |
15 | #include "emubase/Board.h"
16 |
17 | //////////////////////////////////////////////////////////////////////
18 |
19 |
20 | const int MAX_BREAKPOINTCOUNT = 16;
21 | const int MAX_WATCHESCOUNT = 16;
22 |
23 | extern CMotherboard* g_pBoard;
24 | extern BKConfiguration g_nEmulatorConfiguration; // Current configuration
25 | extern bool g_okEmulatorRunning;
26 |
27 | extern uint8_t* g_pEmulatorRam; // RAM values - for change tracking
28 | extern uint8_t* g_pEmulatorChangedRam; // RAM change flags
29 | extern uint16_t g_wEmulatorCpuPC; // Current PC value
30 | extern uint16_t g_wEmulatorPrevCpuPC; // Previous PC value
31 |
32 |
33 | //////////////////////////////////////////////////////////////////////
34 |
35 |
36 | bool Emulator_Init();
37 | bool Emulator_InitConfiguration(BKConfiguration configuration);
38 | BKConfiguration Emulator_GetConfiguration();
39 | LPCTSTR Emulator_GetConfigurationName();
40 | void Emulator_Done();
41 |
42 | bool Emulator_AddCPUBreakpoint(uint16_t address);
43 | bool Emulator_RemoveCPUBreakpoint(uint16_t address);
44 | void Emulator_SetTempCPUBreakpoint(uint16_t address);
45 | const uint16_t* Emulator_GetCPUBreakpointList();
46 | bool Emulator_IsBreakpoint();
47 | bool Emulator_IsBreakpoint(uint16_t address);
48 | void Emulator_RemoveAllBreakpoints();
49 |
50 | bool Emulator_AddWatch(uint16_t address);
51 | const uint16_t* Emulator_GetWatchList();
52 | bool Emulator_RemoveWatch(uint16_t address);
53 | void Emulator_RemoveAllWatches();
54 |
55 | void Emulator_SetSound(bool soundOnOff);
56 | void Emulator_SetCovox(bool covoxOnOff);
57 | void Emulator_SetSoundAY(bool onoff);
58 | void Emulator_Start();
59 | void Emulator_Stop();
60 | void Emulator_Reset();
61 | bool Emulator_SystemFrame();
62 | void Emulator_ProcessJoystick();
63 | uint32_t Emulator_GetUptime(); // BK uptime, in seconds
64 | void Emulator_SetSpeed(uint16_t realspeed);
65 |
66 | void Emulator_GetScreenSize(int scrmode, int* pwid, int* phei);
67 | const uint32_t * Emulator_GetPalette(int screenMode);
68 | void Emulator_PrepareScreenRGB32(void* pBits, int screenMode);
69 |
70 | // Update cached values after Run or Step
71 | void Emulator_OnUpdate();
72 | uint16_t Emulator_GetChangeRamStatus(uint16_t address);
73 |
74 | bool Emulator_SaveImage(LPCTSTR sFilePath);
75 | bool Emulator_LoadImage(LPCTSTR sFilePath);
76 |
77 |
78 | //////////////////////////////////////////////////////////////////////
79 |
--------------------------------------------------------------------------------
/emulator/Joystick.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Joystick.cpp
12 |
13 | #include "stdafx.h"
14 | #include
15 | #include "Joystick.h"
16 |
17 | //////////////////////////////////////////////////////////////////////
18 |
19 |
20 | int g_nJoystickCurrent = 0; // Number of current joystick: 1 or 2; 0 = none
21 | JOYCAPS g_JoystickCaps; // Capabilities of the current joystick
22 |
23 |
24 | //////////////////////////////////////////////////////////////////////
25 |
26 |
27 | void Joystick_Init()
28 | {
29 | }
30 | void Joystick_Done()
31 | {
32 | }
33 |
34 | BOOL Joystick_SelectJoystick(int joystickNum)
35 | {
36 | if (joystickNum == 0)
37 | {
38 | g_nJoystickCurrent = 0;
39 | return TRUE;
40 | }
41 |
42 | UINT numDevs = joyGetNumDevs();
43 | if (numDevs == 0)
44 | return FALSE;
45 |
46 | UINT joystick;
47 | if (joystickNum == 1)
48 | joystick = JOYSTICKID1;
49 | else if (joystickNum == 2)
50 | joystick = JOYSTICKID2;
51 | else
52 | return FALSE;
53 |
54 | MMRESULT result;
55 | JOYINFO joyinfo;
56 | result = joyGetPos(joystick, &joyinfo);
57 | if (result != JOYERR_NOERROR)
58 | return FALSE;
59 | result = joyGetDevCaps(joystick, &g_JoystickCaps, sizeof(g_JoystickCaps));
60 | if (result != JOYERR_NOERROR)
61 | return FALSE;
62 |
63 | g_nJoystickCurrent = joystickNum;
64 | return TRUE;
65 | }
66 |
67 | UINT Joystick_GetJoystickState()
68 | {
69 | UINT joystick;
70 | if (g_nJoystickCurrent == 1)
71 | joystick = JOYSTICKID1;
72 | else if (g_nJoystickCurrent == 2)
73 | joystick = JOYSTICKID2;
74 | else
75 | return 0;
76 |
77 | JOYINFO joyinfo;
78 | MMRESULT result = joyGetPos(joystick, &joyinfo);
79 | if (result != JOYERR_NOERROR)
80 | return 0;
81 |
82 | UINT state = 0;
83 | // Buttons
84 | if (joyinfo.wButtons & JOY_BUTTON1) state |= JOYSTICK_BUTTON1;
85 | if (joyinfo.wButtons & JOY_BUTTON2) state |= JOYSTICK_BUTTON2;
86 | if (joyinfo.wButtons & JOY_BUTTON3) state |= JOYSTICK_BUTTON3;
87 | if (joyinfo.wButtons & JOY_BUTTON4) state |= JOYSTICK_BUTTON4;
88 |
89 | // Position
90 | UINT xCenter = (g_JoystickCaps.wXmax - g_JoystickCaps.wXmin) / 2 + g_JoystickCaps.wXmin;
91 | UINT xLeft = (g_JoystickCaps.wXmin + xCenter) / 2;
92 | UINT xRight = (g_JoystickCaps.wXmax + xCenter) / 2;
93 | if (joyinfo.wXpos < xLeft) state |= JOYSTICK_LEFT;
94 | if (joyinfo.wXpos > xRight) state |= JOYSTICK_RIGHT;
95 |
96 | UINT yCenter = (g_JoystickCaps.wYmax - g_JoystickCaps.wYmin) / 2 + g_JoystickCaps.wYmin;
97 | UINT yTop = (g_JoystickCaps.wYmin + yCenter) / 2;
98 | UINT yBottom = (g_JoystickCaps.wYmax + yCenter) / 2;
99 | if (joyinfo.wYpos < yTop) state |= JOYSTICK_UP;
100 | if (joyinfo.wYpos > yBottom) state |= JOYSTICK_DOWN;
101 |
102 | return state;
103 | }
104 |
105 |
106 | //////////////////////////////////////////////////////////////////////
107 |
--------------------------------------------------------------------------------
/emulator/Joystick.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Joystick.h
12 | //
13 |
14 | #pragma once
15 |
16 | //////////////////////////////////////////////////////////////////////
17 |
18 |
19 | // "Standard" SWCorp. joystick
20 | //#define JOYSTICK_BUTTON1 00001
21 | //#define JOYSTICK_BUTTON2 00002
22 | //#define JOYSTICK_BUTTON3 00004
23 | //#define JOYSTICK_BUTTON4 00010
24 | //#define JOYSTICK_RIGHT 00020
25 | //#define JOYSTICK_DOWN 00040
26 | //#define JOYSTICK_LEFT 01000
27 | //#define JOYSTICK_UP 02000
28 |
29 | // "Break House" joystick
30 | #define JOYSTICK_BUTTON1 0x01
31 | #define JOYSTICK_BUTTON2 0x02
32 | #define JOYSTICK_BUTTON3 0x04
33 | #define JOYSTICK_BUTTON4 0x08
34 | #define JOYSTICK_LEFT 0x10
35 | #define JOYSTICK_DOWN 0x20
36 | #define JOYSTICK_RIGHT 0x40
37 | #define JOYSTICK_UP 0x80
38 |
39 | void Joystick_Init();
40 | void Joystick_Done();
41 |
42 | BOOL Joystick_SelectJoystick(int joystickNum);
43 | UINT Joystick_GetJoystickState();
44 |
45 |
46 | //////////////////////////////////////////////////////////////////////
47 |
--------------------------------------------------------------------------------
/emulator/Main.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // BKBTL.cpp : Defines the entry point for the application.
12 |
13 | #include "stdafx.h"
14 | #include
15 | #include
16 | #include
17 | #include
18 | #include
19 | #include
20 | #include
21 |
22 | #include "Main.h"
23 | #include "Emulator.h"
24 | #include "Views.h"
25 | #include "Joystick.h"
26 | #include "util/BitmapFile.h"
27 |
28 |
29 | //////////////////////////////////////////////////////////////////////
30 | // Global Variables
31 |
32 | HINSTANCE g_hInst = NULL; // current instance
33 | HWND g_hwnd = NULL;
34 | long m_nMainLastFrameTicks = 0;
35 |
36 |
37 | //////////////////////////////////////////////////////////////////////
38 | // Forward declarations
39 |
40 | BOOL InitInstance(HINSTANCE, int);
41 | void DoneInstance();
42 | void ParseCommandLine();
43 |
44 | LPCTSTR g_CommandLineHelp =
45 | _T("Usage: BKBTL [options]\r\n\r\n")
46 | _T("Command line options:\r\n\r\n")
47 | _T("/h /help\r\n\tShow command line options (this box)\r\n")
48 | _T("/autostart /autostarton\r\n\tStart emulation on window open\r\n")
49 | _T("/noautostart /autostartoff\r\n\tDo not start emulation on window open\r\n")
50 | _T("/debug /debugon /debugger\r\n\tSwitch to debug mode\r\n")
51 | _T("/nodebug /debugoff\r\n\tSwitch off the debug mode\r\n")
52 | _T("/sound /soundon\r\n\tTurn sound on\r\n")
53 | _T("/nosound /soundoff\r\n\tTurn sound off\r\n")
54 | _T("/diskN:filePath\r\n\tAttach disk image, N=0..3\r\n");
55 |
56 |
57 | //////////////////////////////////////////////////////////////////////
58 |
59 |
60 | int APIENTRY _tWinMain(
61 | HINSTANCE hInstance,
62 | HINSTANCE hPrevInstance,
63 | LPTSTR lpCmdLine,
64 | int nCmdShow)
65 | {
66 | UNREFERENCED_PARAMETER(hPrevInstance);
67 | UNREFERENCED_PARAMETER(lpCmdLine);
68 |
69 | #ifdef _DEBUG
70 | _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF);
71 | int n = 0;
72 | _CrtSetBreakAlloc(n);
73 | #endif
74 |
75 | g_hInst = hInstance; // Store instance handle in our global variable
76 |
77 | LARGE_INTEGER nFrameStartTime;
78 | nFrameStartTime.QuadPart = 0;
79 |
80 | // Initialize global strings
81 | LoadString(g_hInst, IDS_APP_TITLE, g_szTitle, MAX_LOADSTRING);
82 | LoadString(g_hInst, IDC_APPLICATION, g_szWindowClass, MAX_LOADSTRING);
83 | MainWindow_RegisterClass();
84 |
85 | // Perform application initialization
86 | if (! InitInstance(hInstance, nCmdShow))
87 | return FALSE;
88 |
89 | HACCEL hAccelTable = ::LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_APPLICATION));
90 |
91 | if (Option_ShowHelp)
92 | ::PostMessage(g_hwnd, WM_COMMAND, ID_HELP_COMMAND_LINE_HELP, NULL);
93 |
94 | LARGE_INTEGER nPerformanceFrequency;
95 | ::QueryPerformanceFrequency(&nPerformanceFrequency);
96 |
97 | TIMECAPS caps;
98 | VERIFY(!::timeGetDevCaps(&caps, sizeof(caps)));
99 | VERIFY(!::timeBeginPeriod(caps.wPeriodMin));
100 |
101 | // Main message loop
102 | MSG msg;
103 | for (;;)
104 | {
105 | ::QueryPerformanceCounter(&nFrameStartTime);
106 |
107 | if (!g_okEmulatorRunning)
108 | ::Sleep(1);
109 | else
110 | {
111 | if (!Emulator_SystemFrame()) // Breakpoint hit
112 | {
113 | Emulator_Stop();
114 | // Turn on degugger if not yet
115 | if (!Settings_GetDebug())
116 | ::PostMessage(g_hwnd, WM_COMMAND, ID_VIEW_DEBUG, 0);
117 | else
118 | ::FlashWindow(g_hwnd, TRUE);
119 | }
120 |
121 | ScreenView_RedrawScreen();
122 | }
123 |
124 | // Process all queue
125 | while (::PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ))
126 | {
127 | if (msg.message == WM_QUIT)
128 | goto endprog;
129 |
130 | if (::TranslateAccelerator(g_hwnd, hAccelTable, &msg))
131 | continue;
132 |
133 | ::TranslateMessage(&msg);
134 | ::DispatchMessage(&msg);
135 | }
136 |
137 | if (g_okEmulatorRunning && !Settings_GetSound())
138 | {
139 | WORD speed = Settings_GetRealSpeed();
140 | if (speed == 0)
141 | ::Sleep(0); // Speed MAX, consume 100% of one CPU core
142 | else
143 | {
144 | LONGLONG nFrameDelay;
145 | switch (speed)
146 | {
147 | case 0x7ffd: nFrameDelay = 1000ll / FRAMERATE * 10; break; // Speed 10%
148 | case 0x7ffe: nFrameDelay = 1000ll / FRAMERATE * 4; break; // Speed 25%
149 | case 0x7fff: nFrameDelay = 1000ll / FRAMERATE * 2; break; // Speed 50%
150 | case 2: nFrameDelay = 1000ll / FRAMERATE / 2; break; // Speed 200%
151 | case 3: nFrameDelay = 1000ll / FRAMERATE / 4; break; // Speed 400%
152 | default: // Speed 100%
153 | nFrameDelay = 1000ll / FRAMERATE; // 1000 millisec / 50 = 20 millisec
154 | break;
155 | }
156 |
157 | for (;;)
158 | {
159 | LARGE_INTEGER nFrameFinishTime; // Frame start time
160 | ::QueryPerformanceCounter(&nFrameFinishTime);
161 | LONGLONG nTimeElapsed = (nFrameFinishTime.QuadPart - nFrameStartTime.QuadPart)
162 | * 1000ll / nPerformanceFrequency.QuadPart;
163 | if (nTimeElapsed <= 0 || nTimeElapsed >= nFrameDelay)
164 | break;
165 | LONGLONG nDelayRemaining = nFrameDelay - nTimeElapsed;
166 | ::Sleep((DWORD)(nDelayRemaining / 2));
167 | }
168 | }
169 | }
170 |
171 | //// Time bomb for perfomance analysis
172 | //if (Emulator_GetUptime() >= 300) // 5 minutes
173 | // ::PostQuitMessage(0);
174 | }
175 | endprog:
176 |
177 | ::timeEndPeriod(caps.wPeriodMin);
178 | DoneInstance();
179 |
180 | #ifdef _DEBUG
181 | if (_CrtDumpMemoryLeaks())
182 | ::MessageBeep(MB_ICONEXCLAMATION);
183 | #endif
184 |
185 | return (int) msg.wParam;
186 | }
187 |
188 |
189 | //
190 | // FUNCTION: InitInstance(HINSTANCE, int)
191 | //
192 | // PURPOSE: Saves instance handle and creates main window
193 | //
194 | // COMMENTS:
195 | //
196 | // In this function, we save the instance handle in a global variable and
197 | // create and display the main program window.
198 | //
199 | BOOL InitInstance(HINSTANCE /*hInstance*/, int /*nCmdShow*/)
200 | {
201 | INITCOMMONCONTROLSEX ics; ics.dwSize = sizeof(ics);
202 | ics.dwICC = ICC_WIN95_CLASSES;
203 | InitCommonControlsEx(&ics);
204 |
205 | BitmapFile_Init();
206 |
207 | #if !defined(PRODUCT)
208 | DebugLogClear();
209 | #endif
210 | Settings_Init();
211 | Joystick_Init();
212 | Joystick_SelectJoystick(Settings_GetJoystick());
213 |
214 | ParseCommandLine(); // Override settings by command-line option if needed
215 |
216 | if (!Emulator_Init())
217 | return FALSE;
218 |
219 | int conf = Settings_GetConfiguration();
220 | if (conf == 0) conf = BK_CONF_BK0010_BASIC;
221 | if (!Emulator_InitConfiguration((BKConfiguration)conf))
222 | return FALSE;
223 |
224 | Emulator_SetSound(Settings_GetSound() != 0);
225 | Emulator_SetSpeed(Settings_GetRealSpeed());
226 | Emulator_SetCovox(Settings_GetSoundCovox() != 0);
227 | Emulator_SetSoundAY(Settings_GetSoundAY() != 0);
228 |
229 | if (!CreateMainWindow())
230 | return FALSE;
231 |
232 | return TRUE;
233 | }
234 |
235 | // Instance finalization
236 | void DoneInstance()
237 | {
238 | ScreenView_Done();
239 | DisasmView_Done();
240 |
241 | Emulator_Done();
242 |
243 | Joystick_Done();
244 |
245 | BitmapFile_Done();
246 |
247 | Settings_Done();
248 | }
249 |
250 | void ParseCommandLine()
251 | {
252 | LPTSTR commandline = ::GetCommandLine();
253 |
254 | int argnum = 0;
255 | LPTSTR* args = CommandLineToArgvW(commandline, &argnum);
256 |
257 | for (int curargn = 1; curargn < argnum; curargn++)
258 | {
259 | LPTSTR arg = args[curargn];
260 |
261 | if (_tcscmp(arg, _T("/help")) == 0 || _tcscmp(arg, _T("/h")) == 0)
262 | {
263 | Option_ShowHelp = true;
264 | }
265 | else if (_tcscmp(arg, _T("/autostart")) == 0 || _tcscmp(arg, _T("/autostarton")) == 0)
266 | {
267 | Settings_SetAutostart(TRUE);
268 | }
269 | else if (_tcscmp(arg, _T("/autostartoff")) == 0 || _tcscmp(arg, _T("/noautostart")) == 0)
270 | {
271 | Settings_SetAutostart(FALSE);
272 | }
273 | else if (_tcscmp(arg, _T("/debug")) == 0 || _tcscmp(arg, _T("/debugon")) == 0 || _tcscmp(arg, _T("/debugger")) == 0)
274 | {
275 | Settings_SetDebug(TRUE);
276 | }
277 | else if (_tcscmp(arg, _T("/debugoff")) == 0 || _tcscmp(arg, _T("/nodebug")) == 0)
278 | {
279 | Settings_SetDebug(FALSE);
280 | }
281 | else if (_tcscmp(arg, _T("/sound")) == 0 || _tcscmp(arg, _T("/soundon")) == 0)
282 | {
283 | Settings_SetSound(TRUE);
284 | }
285 | else if (_tcscmp(arg, _T("/soundoff")) == 0 || _tcscmp(arg, _T("/nosound")) == 0)
286 | {
287 | Settings_SetSound(FALSE);
288 | }
289 | else if (_tcslen(arg) > 7 && _tcsncmp(arg, _T("/disk"), 5) == 0) // "/diskN:filePath", N=A..D
290 | {
291 | if (arg[5] >= _T('A') && arg[5] <= _T('D') && arg[6] == ':')
292 | {
293 | int slot = arg[5] - _T('A');
294 | LPCTSTR filePath = arg + 7;
295 | Settings_SetFloppyFilePath(slot, filePath);
296 | }
297 | }
298 | //TODO: "/state:filepath"
299 | }
300 |
301 | ::LocalFree(args);
302 | }
303 |
304 |
305 | //////////////////////////////////////////////////////////////////////
306 |
--------------------------------------------------------------------------------
/emulator/Main.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | #pragma once
12 |
13 | #include "res/resource.h"
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 |
18 | #define FRAMERATE 25 // Количество фремов в секунду
19 |
20 | #define MAX_LOADSTRING 100
21 |
22 | extern TCHAR g_szTitle[MAX_LOADSTRING]; // The title bar text
23 | extern TCHAR g_szWindowClass[MAX_LOADSTRING]; // Main window class name
24 |
25 | extern HINSTANCE g_hInst; // current instance
26 |
27 |
28 | //////////////////////////////////////////////////////////////////////
29 | // Main Window
30 |
31 | extern HWND g_hwnd; // Main window handle
32 |
33 | extern LPCTSTR g_CommandLineHelp;
34 |
35 | void MainWindow_RegisterClass();
36 | BOOL CreateMainWindow();
37 | void MainWindow_RestoreSettings();
38 | void MainWindow_UpdateMenu();
39 | void MainWindow_UpdateWindowTitle();
40 | void MainWindow_UpdateAllViews();
41 | BOOL MainWindow_InitToolbar();
42 | BOOL MainWindow_InitStatusbar();
43 | void MainWindow_ShowHideDebug();
44 | void MainWindow_ShowHideToolbar();
45 | void MainWindow_ShowHideKeyboard();
46 | void MainWindow_ShowHideTape();
47 | void MainWindow_ShowHideMemoryMap();
48 | void MainWindow_ShowHideSpriteViewer();
49 | void MainWindow_AdjustWindowSize();
50 |
51 | void MainWindow_SetToolbarImage(int commandId, int imageIndex);
52 | void MainWindow_SetStatusbarText(int part, LPCTSTR message);
53 | void MainWindow_SetStatusbarBitmap(int part, UINT resourceId);
54 | void MainWindow_SetStatusbarIcon(int part, HICON hIcon);
55 |
56 | enum ToolbarButtons
57 | {
58 | ToolbarButtonRun = 0,
59 | ToolbarButtonReset = 1,
60 | // Separator
61 | ToolbarButtonDiskA = 3,
62 | ToolbarButtonDiskB = 4,
63 | ToolbarButtonDiskC = 5,
64 | ToolbarButtonDiskD = 6,
65 | // Separator
66 | ToolbarButtonColor = 8,
67 | ToolbarButtonSound = 9,
68 | ToolbarButtonScreenshot = 10,
69 | };
70 |
71 | enum ToolbarButtonImages
72 | {
73 | ToolbarImageRun = 0,
74 | ToolbarImagePause = 1,
75 | ToolbarImageReset = 2,
76 | ToolbarImageFloppyDisk = 3,
77 | ToolbarImageFloppySlot = 4,
78 | ToolbarImageCartridge = 5,
79 | ToolbarImageCartSlot = 6,
80 | ToolbarImageSoundOn = 7,
81 | ToolbarImageSoundOff = 8,
82 | ToolbarImageFloppyDiskWP = 9,
83 | ToolbarImageColorScreen = 10,
84 | ToolbarImageBWScreen = 11,
85 | ToolbarImageScreenshot = 12,
86 | ToolbarImageDebugger = 14,
87 | ToolbarImageStepInto = 15,
88 | ToolbarImageStepOver = 16,
89 | ToolbarImageWordByte = 18,
90 | ToolbarImageGotoAddress = 19,
91 | ToolbarImageSpriteViewer = 20,
92 | ToolbarImageHexMode = 21,
93 | };
94 |
95 | enum StatusbarParts
96 | {
97 | StatusbarPartMessage = 0,
98 | StatusbarPartSound = 1,
99 | StatusbarPartFloppyEngine = 2,
100 | StatusbarPartFPS = 3,
101 | StatusbarPartUptime = 4,
102 | };
103 |
104 |
105 | enum ColorIndices
106 | {
107 | ColorDebugText = 0,
108 | ColorDebugBackCurrent = 1,
109 | ColorDebugValueChanged = 2,
110 | ColorDebugPrevious = 3,
111 | ColorDebugMemoryRom = 4,
112 | ColorDebugMemoryIO = 5,
113 | ColorDebugMemoryNA = 6,
114 | ColorDebugValue = 7,
115 | ColorDebugValueRom = 8,
116 | ColorDebugSubtitles = 9,
117 | ColorDebugJump = 10,
118 | ColorDebugJumpYes = 11,
119 | ColorDebugJumpNo = 12,
120 | ColorDebugJumpHint = 13,
121 | ColorDebugHint = 14,
122 | ColorDebugBreakpoint = 15,
123 | ColorDebugHighlight = 16,
124 | ColorDebugBreakptZone = 17,
125 |
126 | ColorIndicesCount = 18,
127 | };
128 |
129 |
130 | //////////////////////////////////////////////////////////////////////
131 | // Settings
132 |
133 | void Settings_Init();
134 | void Settings_Done();
135 | BOOL Settings_GetWindowRect(RECT * pRect);
136 | void Settings_SetWindowRect(const RECT * pRect);
137 | void Settings_SetWindowMaximized(BOOL flag);
138 | BOOL Settings_GetWindowMaximized();
139 | void Settings_SetConfiguration(int configuration);
140 | int Settings_GetConfiguration();
141 | void Settings_SetFloppyFilePath(int slot, LPCTSTR sFilePath);
142 | void Settings_GetFloppyFilePath(int slot, LPTSTR buffer);
143 | void Settings_SetScreenViewMode(int mode);
144 | int Settings_GetScreenViewMode();
145 | void Settings_SetScreenHeightMode(int mode);
146 | int Settings_GetScreenHeightMode();
147 | void Settings_SetDebug(BOOL flag);
148 | BOOL Settings_GetDebug();
149 | void Settings_GetDebugFontName(LPTSTR buffer);
150 | void Settings_SetDebugFontName(LPCTSTR sFontName);
151 | WORD Settings_GetDebugBreakpoint(int bpno);
152 | void Settings_SetDebugBreakpoint(int bpno, WORD address);
153 | void Settings_SetDebugMemoryAddress(WORD address);
154 | WORD Settings_GetDebugMemoryAddress();
155 | void Settings_SetDebugMemoryBase(WORD address);
156 | WORD Settings_GetDebugMemoryBase();
157 | BOOL Settings_GetDebugMemoryByte();
158 | void Settings_SetDebugMemoryByte(BOOL flag);
159 | void Settings_SetDebugMemoryNumeral(WORD mode);
160 | WORD Settings_GetDebugMemoryNumeral();
161 | void Settings_SetAutostart(BOOL flag);
162 | BOOL Settings_GetAutostart();
163 | void Settings_SetRealSpeed(WORD speed);
164 | WORD Settings_GetRealSpeed();
165 | void Settings_SetSound(BOOL flag);
166 | BOOL Settings_GetSound();
167 | void Settings_SetSoundVolume(WORD value);
168 | WORD Settings_GetSoundVolume();
169 | void Settings_SetSoundCovox(BOOL flag);
170 | BOOL Settings_GetSoundCovox();
171 | void Settings_SetSoundAY(BOOL flag);
172 | BOOL Settings_GetSoundAY();
173 | void Settings_SetJoystick(int joystick);
174 | int Settings_GetJoystick();
175 | void Settings_SetToolbar(BOOL flag);
176 | BOOL Settings_GetToolbar();
177 | void Settings_SetKeyboard(BOOL flag);
178 | BOOL Settings_GetKeyboard();
179 | void Settings_SetTape(BOOL flag);
180 | BOOL Settings_GetTape();
181 | void Settings_SetMemoryMap(BOOL flag);
182 | BOOL Settings_GetMemoryMap();
183 | WORD Settings_GetSpriteAddress();
184 | void Settings_SetSpriteAddress(WORD value);
185 | WORD Settings_GetSpriteWidth();
186 | void Settings_SetSpriteWidth(WORD value);
187 |
188 | LPCTSTR Settings_GetColorFriendlyName(ColorIndices colorIndex);
189 | COLORREF Settings_GetColor(ColorIndices colorIndex);
190 | COLORREF Settings_GetDefaultColor(ColorIndices colorIndex);
191 | void Settings_SetColor(ColorIndices colorIndex, COLORREF color);
192 |
193 |
194 | //////////////////////////////////////////////////////////////////////
195 | // Options
196 |
197 | extern bool Option_ShowHelp;
198 |
199 |
200 | //////////////////////////////////////////////////////////////////////
201 |
--------------------------------------------------------------------------------
/emulator/MemoryMapView.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // MemoryMapView.cpp
12 |
13 | #include "stdafx.h"
14 | #include
15 | #include "Main.h"
16 | #include "Views.h"
17 | #include "ToolWindow.h"
18 | #include "Emulator.h"
19 |
20 | //////////////////////////////////////////////////////////////////////
21 |
22 |
23 | HWND g_hwndMemoryMap = (HWND)INVALID_HANDLE_VALUE; // MemoryMap view window handler
24 | WNDPROC m_wndprocMemoryMapToolWindow = NULL; // Old window proc address of the ToolWindow
25 |
26 | HWND m_hwndMemoryMapViewer = (HWND)INVALID_HANDLE_VALUE;
27 | HDRAWDIB m_hMemoryMapDrawDib = NULL;
28 | BITMAPINFO m_bmpinfoMemoryMap;
29 | HBITMAP m_hMemoryMapBitmap = NULL;
30 | DWORD * m_pMemoryMap_bits = NULL;
31 |
32 | const int m_nMemoryMap_ViewCX = 256;
33 | const int m_nMemoryMap_ViewCY = 256;
34 |
35 | int m_nMemoryMap_xpos = 0;
36 | int m_nMemoryMap_ypos = 0;
37 | int m_nMemoryMap_scale = 1;
38 |
39 | void MemoryMapView_OnDraw(HDC hdc);
40 | BOOL MemoryMapView_OnKeyDown(WPARAM vkey, LPARAM lParam);
41 | BOOL MemoryMapView_OnVScroll(WPARAM wParam, LPARAM lParam);
42 | BOOL MemoryMapView_OnHScroll(WPARAM wParam, LPARAM lParam);
43 | BOOL MemoryMapView_OnMouseWheel(WPARAM wParam, LPARAM lParam);
44 | void MemoryMapView_InitBitmap();
45 | void MemoryMapView_DoneBitmap();
46 | void MemoryMapView_PrepareBitmap();
47 | void MemoryMapView_Zoom(BOOL inout);
48 | void MemoryMapView_Scroll(int dx, int dy);
49 | void MemoryMapView_UpdateScrollPos();
50 |
51 |
52 | //////////////////////////////////////////////////////////////////////
53 |
54 |
55 | void MemoryMapView_RegisterClass()
56 | {
57 | WNDCLASSEX wcex;
58 | wcex.cbSize = sizeof(WNDCLASSEX);
59 |
60 | wcex.style = CS_HREDRAW | CS_VREDRAW;
61 | wcex.lpfnWndProc = MemoryMapViewViewerWndProc;
62 | wcex.cbClsExtra = 0;
63 | wcex.cbWndExtra = 0;
64 | wcex.hInstance = g_hInst;
65 | wcex.hIcon = NULL;
66 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
67 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
68 | wcex.lpszMenuName = NULL;
69 | wcex.lpszClassName = CLASSNAME_MEMORYMAPVIEW;
70 | wcex.hIconSm = NULL;
71 |
72 | RegisterClassEx(&wcex);
73 | }
74 |
75 | void MemoryMapView_Create(HWND hwndParent, int x, int y)
76 | {
77 | int cxScroll = ::GetSystemMetrics(SM_CXVSCROLL);
78 | int cyScroll = ::GetSystemMetrics(SM_CYHSCROLL);
79 | int cyCaption = TOOLWINDOW_CAPTION_HEIGHT;
80 |
81 | int width = m_nMemoryMap_ViewCX + cxScroll;
82 | int height = m_nMemoryMap_ViewCY + cyScroll + cyCaption;
83 | g_hwndMemoryMap = CreateWindow(
84 | CLASSNAME_TOOLWINDOW, _T("Memory Map"),
85 | WS_CHILD | WS_VISIBLE,
86 | x, y, width, height,
87 | hwndParent, NULL, g_hInst, NULL);
88 |
89 | // ToolWindow subclassing
90 | m_wndprocMemoryMapToolWindow = (WNDPROC)LongToPtr( SetWindowLongPtr(
91 | g_hwndMemoryMap, GWLP_WNDPROC, PtrToLong(MemoryMapViewWndProc)) );
92 |
93 | RECT rcClient; GetClientRect(g_hwndMemoryMap, &rcClient);
94 |
95 | m_hwndMemoryMapViewer = CreateWindow(
96 | CLASSNAME_MEMORYMAPVIEW, NULL,
97 | WS_CHILD | WS_VISIBLE | WS_HSCROLL | WS_VSCROLL | WS_TABSTOP,
98 | 0, 0, rcClient.right, rcClient.bottom,
99 | g_hwndMemoryMap, NULL, g_hInst, NULL);
100 |
101 | MemoryMapView_InitBitmap();
102 | MemoryMapView_UpdateScrollPos();
103 | }
104 |
105 | void MemoryMapView_InitBitmap()
106 | {
107 | m_hMemoryMapDrawDib = DrawDibOpen();
108 | HDC hdc = ::GetDC(g_hwnd);
109 |
110 | m_bmpinfoMemoryMap.bmiHeader.biSize = sizeof( BITMAPINFOHEADER );
111 | m_bmpinfoMemoryMap.bmiHeader.biWidth = 256;
112 | m_bmpinfoMemoryMap.bmiHeader.biHeight = 256;
113 | m_bmpinfoMemoryMap.bmiHeader.biPlanes = 1;
114 | m_bmpinfoMemoryMap.bmiHeader.biBitCount = 32;
115 | m_bmpinfoMemoryMap.bmiHeader.biCompression = BI_RGB;
116 | m_bmpinfoMemoryMap.bmiHeader.biSizeImage = 0;
117 | m_bmpinfoMemoryMap.bmiHeader.biXPelsPerMeter = 0;
118 | m_bmpinfoMemoryMap.bmiHeader.biYPelsPerMeter = 0;
119 | m_bmpinfoMemoryMap.bmiHeader.biClrUsed = 0;
120 | m_bmpinfoMemoryMap.bmiHeader.biClrImportant = 0;
121 |
122 | m_hMemoryMapBitmap = CreateDIBSection( hdc, &m_bmpinfoMemoryMap, DIB_RGB_COLORS, (void **)&m_pMemoryMap_bits, NULL, 0 );
123 |
124 | VERIFY(::ReleaseDC(g_hwnd, hdc));
125 | }
126 |
127 | void MemoryMapView_DoneBitmap()
128 | {
129 | if (m_hMemoryMapBitmap != NULL)
130 | {
131 | VERIFY(::DeleteObject(m_hMemoryMapBitmap)); m_hMemoryMapBitmap = NULL;
132 | }
133 |
134 | DrawDibClose( m_hMemoryMapDrawDib );
135 | }
136 |
137 | LRESULT CALLBACK MemoryMapViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
138 | {
139 | UNREFERENCED_PARAMETER(lParam);
140 | switch (message)
141 | {
142 | case WM_SETFOCUS:
143 | ::SetFocus(m_hwndMemoryMapViewer);
144 | break;
145 | case WM_DESTROY:
146 | g_hwndMemoryMap = (HWND) INVALID_HANDLE_VALUE; // We are closed! Bye-bye!..
147 | return CallWindowProc(m_wndprocMemoryMapToolWindow, hWnd, message, wParam, lParam);
148 | default:
149 | return CallWindowProc(m_wndprocMemoryMapToolWindow, hWnd, message, wParam, lParam);
150 | }
151 | return (LRESULT)FALSE;
152 | }
153 |
154 | LRESULT CALLBACK MemoryMapViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
155 | {
156 | UNREFERENCED_PARAMETER(lParam);
157 | switch (message)
158 | {
159 | case WM_PAINT:
160 | {
161 | PAINTSTRUCT ps;
162 | HDC hdc = BeginPaint(hWnd, &ps);
163 |
164 | MemoryMapView_OnDraw(hdc); // Draw memory dump
165 |
166 | EndPaint(hWnd, &ps);
167 | }
168 | break;
169 | case WM_DESTROY:
170 | // Free resources
171 | MemoryMapView_DoneBitmap();
172 | return DefWindowProc(hWnd, message, wParam, lParam);
173 | case WM_LBUTTONDOWN:
174 | SetFocus(hWnd);
175 | break;
176 | case WM_KEYDOWN:
177 | return (LRESULT) MemoryMapView_OnKeyDown(wParam, lParam);
178 | case WM_HSCROLL:
179 | return (LRESULT) MemoryMapView_OnHScroll(wParam, lParam);
180 | case WM_VSCROLL:
181 | return (LRESULT) MemoryMapView_OnVScroll(wParam, lParam);
182 | case WM_MOUSEWHEEL:
183 | return (LRESULT) MemoryMapView_OnMouseWheel(wParam, lParam);
184 | default:
185 | return DefWindowProc(hWnd, message, wParam, lParam);
186 | }
187 | return (LRESULT)FALSE;
188 | }
189 |
190 | void MemoryMapView_Zoom(BOOL inout)
191 | {
192 | if (inout)
193 | {
194 | if (m_nMemoryMap_scale >= 40)
195 | return;
196 | m_nMemoryMap_scale += 1;
197 | }
198 | else
199 | {
200 | if (m_nMemoryMap_scale <= 2)
201 | return;
202 | m_nMemoryMap_scale -= 1;
203 | }
204 |
205 | InvalidateRect(m_hwndMemoryMapViewer, NULL, FALSE);
206 | MemoryMapView_UpdateScrollPos();
207 | }
208 | void MemoryMapView_ScrollTo(int newxpos, int newypos)
209 | {
210 | int maxxpos = 256 - m_nMemoryMap_ViewCX / m_nMemoryMap_scale;
211 | int maxypos = 256 - m_nMemoryMap_ViewCY / m_nMemoryMap_scale;
212 | if (newxpos < 0) newxpos = 0;
213 | if (newxpos > maxxpos) newxpos = maxxpos;
214 | if (newypos < 0) newypos = 0;
215 | if (newypos > maxypos) newypos = maxypos;
216 |
217 | m_nMemoryMap_xpos = newxpos;
218 | m_nMemoryMap_ypos = newypos;
219 |
220 | InvalidateRect(m_hwndMemoryMapViewer, NULL, TRUE);
221 |
222 | MemoryMapView_UpdateScrollPos();
223 | }
224 | void MemoryMapView_Scroll(int dx, int dy)
225 | {
226 | int newxpos = m_nMemoryMap_xpos + dx;
227 | int newypos = m_nMemoryMap_ypos + dy;
228 | MemoryMapView_ScrollTo(newxpos, newypos);
229 | }
230 |
231 | BOOL MemoryMapView_OnMouseWheel(WPARAM wParam, LPARAM /*lParam*/)
232 | {
233 | short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
234 |
235 | MemoryMapView_Scroll(0, (zDelta > 0) ? -24 : 24);
236 |
237 | return FALSE;
238 | }
239 |
240 | BOOL MemoryMapView_OnKeyDown(WPARAM vkey, LPARAM /*lParam*/)
241 | {
242 | switch (vkey)
243 | {
244 | case VK_OEM_MINUS:
245 | MemoryMapView_Zoom(FALSE);
246 | break;
247 | case VK_OEM_PLUS:
248 | MemoryMapView_Zoom(TRUE);
249 | break;
250 | case VK_LEFT:
251 | MemoryMapView_Scroll(-2, 0);
252 | break;
253 | case VK_RIGHT:
254 | MemoryMapView_Scroll(2, 0);
255 | break;
256 | case VK_UP:
257 | MemoryMapView_Scroll(0, -2);
258 | break;
259 | case VK_DOWN:
260 | MemoryMapView_Scroll(0, 2);
261 | break;
262 | default:
263 | return TRUE;
264 | }
265 | return FALSE;
266 | }
267 |
268 | BOOL MemoryMapView_OnHScroll(WPARAM wParam, LPARAM /*lParam*/)
269 | {
270 | WORD scrollpos = HIWORD(wParam);
271 | WORD scrollcmd = LOWORD(wParam);
272 | switch (scrollcmd)
273 | {
274 | case SB_LINEDOWN:
275 | MemoryMapView_Scroll(8, 0);
276 | break;
277 | case SB_LINEUP:
278 | MemoryMapView_Scroll(-8, 0);
279 | break;
280 | case SB_PAGEDOWN:
281 | MemoryMapView_Scroll(m_nMemoryMap_ViewCX / m_nMemoryMap_scale, 0);
282 | break;
283 | case SB_PAGEUP:
284 | MemoryMapView_Scroll(-m_nMemoryMap_ViewCX / m_nMemoryMap_scale, 0);
285 | break;
286 | case SB_THUMBPOSITION:
287 | MemoryMapView_ScrollTo(scrollpos, m_nMemoryMap_ypos);
288 | break;
289 | }
290 |
291 | return FALSE;
292 | }
293 |
294 | BOOL MemoryMapView_OnVScroll(WPARAM wParam, LPARAM /*lParam*/)
295 | {
296 | WORD scrollpos = HIWORD(wParam);
297 | WORD scrollcmd = LOWORD(wParam);
298 | switch (scrollcmd)
299 | {
300 | case SB_LINEDOWN:
301 | MemoryMapView_Scroll(0, 8);
302 | break;
303 | case SB_LINEUP:
304 | MemoryMapView_Scroll(0, -8);
305 | break;
306 | case SB_PAGEDOWN:
307 | MemoryMapView_Scroll(0, m_nMemoryMap_ViewCY / m_nMemoryMap_scale);
308 | break;
309 | case SB_PAGEUP:
310 | MemoryMapView_Scroll(0, -m_nMemoryMap_ViewCY / m_nMemoryMap_scale);
311 | break;
312 | case SB_THUMBPOSITION:
313 | MemoryMapView_ScrollTo(m_nMemoryMap_xpos, scrollpos);
314 | break;
315 | }
316 |
317 | return FALSE;
318 | }
319 |
320 | void MemoryMapView_OnDraw(HDC hdc)
321 | {
322 | ASSERT(g_pBoard != NULL);
323 |
324 | MemoryMapView_PrepareBitmap();
325 |
326 | DrawDibDraw(m_hMemoryMapDrawDib, hdc,
327 | -m_nMemoryMap_xpos * m_nMemoryMap_scale, -m_nMemoryMap_ypos * m_nMemoryMap_scale,
328 | 256 * m_nMemoryMap_scale, 256 * m_nMemoryMap_scale,
329 | &m_bmpinfoMemoryMap.bmiHeader, m_pMemoryMap_bits, 0, 0,
330 | 256, 256,
331 | 0);
332 | }
333 |
334 | void MemoryMapView_RedrawMap()
335 | {
336 | if (g_hwndMemoryMap == (HWND)INVALID_HANDLE_VALUE) return;
337 |
338 | MemoryMapView_PrepareBitmap();
339 |
340 | HDC hdc = GetDC(g_hwndMemoryMap);
341 | MemoryMapView_OnDraw(hdc);
342 | VERIFY(::ReleaseDC(g_hwndMemoryMap, hdc));
343 | }
344 |
345 | void MemoryMapView_UpdateScrollPos()
346 | {
347 | SCROLLINFO siH;
348 | ZeroMemory(&siH, sizeof(siH));
349 | siH.cbSize = sizeof(siH);
350 | siH.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
351 | siH.nPage = m_nMemoryMap_ViewCX / m_nMemoryMap_scale;
352 | siH.nPos = m_nMemoryMap_xpos;
353 | siH.nMin = 0;
354 | siH.nMax = 256 - 1;
355 | SetScrollInfo(m_hwndMemoryMapViewer, SB_HORZ, &siH, TRUE);
356 |
357 | SCROLLINFO siV;
358 | ZeroMemory(&siV, sizeof(siV));
359 | siV.cbSize = sizeof(siV);
360 | siV.fMask = SIF_PAGE | SIF_POS | SIF_RANGE | SIF_DISABLENOSCROLL;
361 | siV.nPage = m_nMemoryMap_ViewCY / m_nMemoryMap_scale;
362 | siV.nPos = m_nMemoryMap_ypos;
363 | siV.nMin = 0;
364 | siV.nMax = 256 - 1;
365 | SetScrollInfo(m_hwndMemoryMapViewer, SB_VERT, &siV, TRUE);
366 | }
367 |
368 | void MemoryMapView_PrepareBitmap()
369 | {
370 | for (int y = 0; y < 256; y += 1)
371 | {
372 | DWORD* pBits = m_pMemoryMap_bits + (256 - 1 - y) * 256;
373 | for (int x = 0; x < 256; x += 2)
374 | {
375 | WORD address = (WORD)(x + y * 256);
376 | int addrtype;
377 | WORD value = g_pBoard->GetWordView(address, FALSE, FALSE, &addrtype);
378 | COLORREF color1, color2;
379 | BYTE val;
380 | switch (addrtype & ADDRTYPE_MASK)
381 | {
382 | case ADDRTYPE_IO:
383 | color1 = color2 = RGB(128, 0, 128);
384 | break;
385 | case ADDRTYPE_DENY:
386 | color1 = color2 = RGB(0, 0, 128);
387 | break;
388 | case ADDRTYPE_ROM:
389 | val = (value & 0xff00) >> 8;
390 | color1 = RGB(192, val, val);
391 | val = value & 0x00ff;
392 | color2 = RGB(192, val, val);
393 | break;
394 | case ADDRTYPE_RAM:
395 | val = (value & 0xff00) >> 8;
396 | color1 = RGB(val, val, val);
397 | val = value & 0x00ff;
398 | color2 = RGB(val, val, val);
399 | break;
400 | default:
401 | color1 = color2 = RGB(0, 0, 0);
402 | break;
403 | }
404 |
405 | *pBits = color1;
406 | pBits++;
407 | *pBits = color2;
408 | pBits++;
409 | }
410 | }
411 | }
412 |
413 |
414 | //////////////////////////////////////////////////////////////////////
415 |
416 |
--------------------------------------------------------------------------------
/emulator/Settings.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Settings.cpp
12 |
13 | #include "stdafx.h"
14 | #include "Main.h"
15 |
16 | //////////////////////////////////////////////////////////////////////
17 |
18 |
19 | const TCHAR m_Settings_IniAppName[] = _T("BKBTL");
20 | TCHAR m_Settings_IniPath[MAX_PATH];
21 |
22 |
23 | //////////////////////////////////////////////////////////////////////
24 | // Options
25 |
26 | bool Option_ShowHelp = false;
27 |
28 |
29 | //////////////////////////////////////////////////////////////////////
30 |
31 |
32 | void Settings_Init()
33 | {
34 | // Prepare m_Settings_IniPath: get .exe file path and change extension to .ini
35 | ::GetModuleFileName(GetModuleHandle(NULL), m_Settings_IniPath, MAX_PATH);
36 | TCHAR* pExt = m_Settings_IniPath + _tcslen(m_Settings_IniPath) - 3;
37 | *pExt++ = _T('i');
38 | *pExt++ = _T('n');
39 | *pExt = _T('i');
40 | }
41 | void Settings_Done()
42 | {
43 | }
44 |
45 | BOOL Settings_SaveStringValue(LPCTSTR sName, LPCTSTR sValue)
46 | {
47 | BOOL result = WritePrivateProfileString(
48 | m_Settings_IniAppName, sName, sValue, m_Settings_IniPath);
49 | return result;
50 | }
51 | BOOL Settings_LoadStringValue(LPCTSTR sName, LPTSTR sBuffer, int nBufferLengthChars)
52 | {
53 | DWORD result = GetPrivateProfileString(
54 | m_Settings_IniAppName, sName, NULL, sBuffer, nBufferLengthChars, m_Settings_IniPath);
55 | if (result > 0)
56 | return TRUE;
57 |
58 | sBuffer[0] = _T('\0');
59 | return FALSE;
60 | }
61 |
62 | BOOL Settings_SaveDwordValue(LPCTSTR sName, DWORD dwValue)
63 | {
64 | TCHAR buffer[12];
65 | _sntprintf(buffer, sizeof(buffer) / sizeof(TCHAR) - 1, _T("%lu"), dwValue);
66 |
67 | return Settings_SaveStringValue(sName, buffer);
68 | }
69 | BOOL Settings_LoadDwordValue(LPCTSTR sName, DWORD* dwValue)
70 | {
71 | TCHAR buffer[12];
72 | if (!Settings_LoadStringValue(sName, buffer, 12))
73 | return FALSE;
74 |
75 | int result = _stscanf(buffer, _T("%lu"), dwValue);
76 | if (result == 0)
77 | return FALSE;
78 |
79 | return TRUE;
80 | }
81 |
82 | BOOL Settings_SaveColorValue(LPCTSTR sName, COLORREF color)
83 | {
84 | // 00BBGGRR -> 00RRGGBB conversion
85 | DWORD dwValue = ((color & 0x0000ff) << 16) | (color & 0x00ff00) | ((color & 0xff0000) >> 16);
86 |
87 | TCHAR buffer[12];
88 | _sntprintf(buffer, sizeof(buffer) / sizeof(TCHAR) - 1, _T("%06lX"), dwValue);
89 |
90 | return Settings_SaveStringValue(sName, buffer);
91 | }
92 | BOOL Settings_LoadColorValue(LPCTSTR sName, COLORREF* pColor)
93 | {
94 | TCHAR buffer[12];
95 | if (!Settings_LoadStringValue(sName, buffer, 12))
96 | return FALSE;
97 |
98 | DWORD dwValue;
99 | int result = _stscanf(buffer, _T("%lX"), &dwValue);
100 | if (result == 0)
101 | return FALSE;
102 |
103 | // 00RRGGBB -> 00BBGGRR conversion
104 | *pColor = ((dwValue & 0x0000ff) << 16) | (dwValue & 0x00ff00) | ((dwValue & 0xff0000) >> 16);
105 |
106 | return TRUE;
107 | }
108 |
109 |
110 | BOOL Settings_SaveBinaryValue(LPCTSTR sName, const void * pData, int size)
111 | {
112 | TCHAR* buffer = static_cast(::calloc(size * 2 + 1, sizeof(TCHAR)));
113 | if (buffer == NULL)
114 | return FALSE;
115 | const BYTE* p = static_cast(pData);
116 | TCHAR* buf = buffer;
117 | for (int i = 0; i < size; i++)
118 | {
119 | int a = *p;
120 | _sntprintf(buf, 3, _T("%02X"), a);
121 | p++;
122 | buf += 2;
123 | }
124 |
125 | BOOL result = Settings_SaveStringValue(sName, buffer);
126 |
127 | free(buffer);
128 |
129 | return result;
130 | }
131 |
132 | BOOL Settings_LoadBinaryValue(LPCTSTR sName, void * pData, int size)
133 | {
134 | size_t buffersize = size * 2 + 1;
135 | TCHAR* buffer = static_cast(::calloc(buffersize, sizeof(TCHAR)));
136 | if (buffer == NULL)
137 | return FALSE;
138 | if (!Settings_LoadStringValue(sName, buffer, buffersize))
139 | {
140 | free(buffer);
141 | return FALSE;
142 | }
143 |
144 | BYTE* p = static_cast(pData);
145 | TCHAR* buf = buffer;
146 | for (int i = 0; i < size; i++)
147 | {
148 | BYTE v = 0;
149 |
150 | TCHAR ch = *buf;
151 | if (ch >= _T('0') && ch <= _T('9'))
152 | v = (BYTE)(ch - _T('0'));
153 | else if (ch >= _T('A') && ch <= _T('F'))
154 | v = (BYTE)(ch - _T('A') + 10);
155 | else // Not hex
156 | {
157 | free(buffer);
158 | return FALSE;
159 | }
160 | buf++;
161 |
162 | v = v << 4;
163 |
164 | ch = *buf;
165 | if (ch >= _T('0') && ch <= _T('9'))
166 | v |= (BYTE)(ch - _T('0'));
167 | else if (ch >= _T('A') && ch <= _T('F'))
168 | v |= (BYTE)(ch - _T('A') + 10);
169 | else // Not hex
170 | {
171 | free(buffer);
172 | return FALSE;
173 | }
174 | buf++;
175 |
176 | *p = v;
177 | p++;
178 | }
179 |
180 | free(buffer);
181 |
182 | return TRUE;
183 | }
184 |
185 |
186 | //////////////////////////////////////////////////////////////////////
187 |
188 |
189 | #define SETTINGS_GETSET_DWORD(PARAMNAME, PARAMNAMESTR, OUTTYPE, DEFVALUE) \
190 | OUTTYPE m_Settings_##PARAMNAME = DEFVALUE; \
191 | BOOL m_Settings_##PARAMNAME##_Valid = FALSE; \
192 | void Settings_Set##PARAMNAME(OUTTYPE newvalue) { \
193 | m_Settings_##PARAMNAME = newvalue; \
194 | m_Settings_##PARAMNAME##_Valid = TRUE; \
195 | Settings_SaveDwordValue(PARAMNAMESTR, (DWORD) newvalue); \
196 | } \
197 | OUTTYPE Settings_Get##PARAMNAME() { \
198 | if (!m_Settings_##PARAMNAME##_Valid) { \
199 | DWORD dwValue = (DWORD)(DEFVALUE); \
200 | Settings_LoadDwordValue(PARAMNAMESTR, &dwValue); \
201 | m_Settings_##PARAMNAME = (OUTTYPE) dwValue; \
202 | m_Settings_##PARAMNAME##_Valid = TRUE; \
203 | } \
204 | return m_Settings_##PARAMNAME; \
205 | }
206 |
207 |
208 | BOOL Settings_GetWindowRect(RECT * pRect)
209 | {
210 | RECT rc;
211 | if (Settings_LoadBinaryValue(_T("WindowRect"), &rc, sizeof(RECT)))
212 | {
213 | ::memcpy(pRect, &rc, sizeof(RECT));
214 | return TRUE;
215 | }
216 |
217 | return FALSE;
218 | }
219 | void Settings_SetWindowRect(const RECT * pRect)
220 | {
221 | Settings_SaveBinaryValue(_T("WindowRect"), pRect, sizeof(RECT));
222 | }
223 |
224 | SETTINGS_GETSET_DWORD(WindowMaximized, _T("WindowMaximized"), BOOL, FALSE);
225 |
226 | SETTINGS_GETSET_DWORD(Configuration, _T("Configuration"), int, 0);
227 |
228 | void Settings_GetFloppyFilePath(int slot, LPTSTR buffer)
229 | {
230 | TCHAR bufValueName[8];
231 | lstrcpy(bufValueName, _T("Floppy0"));
232 | bufValueName[6] = _T('0') + (TCHAR)slot;
233 | Settings_LoadStringValue(bufValueName, buffer, MAX_PATH);
234 | }
235 | void Settings_SetFloppyFilePath(int slot, LPCTSTR sFilePath)
236 | {
237 | TCHAR bufValueName[8];
238 | lstrcpy(bufValueName, _T("Floppy0"));
239 | bufValueName[6] = _T('0') + (TCHAR)slot;
240 | Settings_SaveStringValue(bufValueName, sFilePath);
241 | }
242 |
243 | SETTINGS_GETSET_DWORD(ScreenViewMode, _T("ScreenViewMode"), int, 0);
244 |
245 | SETTINGS_GETSET_DWORD(ScreenHeightMode, _T("ScreenHeightMode"), int, 0);
246 |
247 | SETTINGS_GETSET_DWORD(Toolbar, _T("Toolbar"), BOOL, TRUE);
248 |
249 | SETTINGS_GETSET_DWORD(Debug, _T("Debug"), BOOL, FALSE);
250 |
251 | void Settings_GetDebugFontName(LPTSTR buffer)
252 | {
253 | if (!Settings_LoadStringValue(_T("DebugFontName"), buffer, 32))
254 | {
255 | _tcscpy(buffer, _T("Lucida Console"));
256 | }
257 | }
258 | void Settings_SetDebugFontName(LPCTSTR sFontName)
259 | {
260 | Settings_SaveStringValue(_T("DebugFontName"), sFontName);
261 | }
262 |
263 | void Settings_SetDebugBreakpoint(int bpno, WORD address)
264 | {
265 | TCHAR bufValueName[14];
266 | lstrcpy(bufValueName, _T("DebugBreakpt0"));
267 | bufValueName[12] = bpno < 10 ? _T('0') + (TCHAR)bpno : _T('A') + (TCHAR)(bpno - 10);
268 | if (address == 0177777)
269 | Settings_SaveStringValue(bufValueName, NULL); // delete value
270 | else
271 | Settings_SaveDwordValue(bufValueName, address);
272 | }
273 | WORD Settings_GetDebugBreakpoint(int bpno)
274 | {
275 | TCHAR bufValueName[14];
276 | lstrcpy(bufValueName, _T("DebugBreakpt0"));
277 | bufValueName[12] = bpno < 10 ? _T('0') + (TCHAR)bpno : _T('A') + (TCHAR)(bpno - 10);
278 | DWORD dwValue = 0xFFFFFFFF;
279 | Settings_LoadDwordValue(bufValueName, &dwValue);
280 | return (WORD)dwValue;
281 | }
282 |
283 | SETTINGS_GETSET_DWORD(DebugMemoryAddress, _T("DebugMemoryAddress"), WORD, 0);
284 | SETTINGS_GETSET_DWORD(DebugMemoryBase, _T("DebugMemoryBase"), WORD, 0);
285 | SETTINGS_GETSET_DWORD(DebugMemoryByte, _T("DebugMemoryByte"), BOOL, FALSE);
286 | SETTINGS_GETSET_DWORD(DebugMemoryNumeral, _T("DebugMemoryNumeral"), WORD, 0);
287 |
288 | SETTINGS_GETSET_DWORD(Autostart, _T("Autostart"), BOOL, FALSE);
289 |
290 | SETTINGS_GETSET_DWORD(RealSpeed, _T("RealSpeed"), WORD, 1);
291 |
292 | SETTINGS_GETSET_DWORD(Sound, _T("Sound"), BOOL, FALSE);
293 | SETTINGS_GETSET_DWORD(SoundVolume, _T("SoundVolume"), WORD, 0x3fff);
294 | SETTINGS_GETSET_DWORD(SoundCovox, _T("SoundCovox"), BOOL, FALSE);
295 | SETTINGS_GETSET_DWORD(SoundAY, _T("SoundAY"), BOOL, FALSE);
296 |
297 | SETTINGS_GETSET_DWORD(Joystick, _T("Joystick"), int, 0);
298 |
299 | SETTINGS_GETSET_DWORD(Keyboard, _T("Keyboard"), BOOL, TRUE);
300 |
301 | SETTINGS_GETSET_DWORD(Tape, _T("Tape"), BOOL, FALSE);
302 |
303 | SETTINGS_GETSET_DWORD(MemoryMap, _T("MemoryMap"), BOOL, FALSE);
304 |
305 | SETTINGS_GETSET_DWORD(SpriteAddress, _T("SpriteAddress"), WORD, 0);
306 |
307 | SETTINGS_GETSET_DWORD(SpriteWidth, _T("SpriteWidth"), WORD, 2);
308 |
309 |
310 | //////////////////////////////////////////////////////////////////////
311 | // Colors
312 |
313 | struct ColorDescriptorStruct
314 | {
315 | LPCTSTR settingname;
316 | COLORREF defaultcolor;
317 | BOOL valid;
318 | LPCTSTR friendlyname;
319 | COLORREF currentcolor;
320 | }
321 | static ColorDescriptors[ColorIndicesCount] =
322 | {
323 | { _T("ColorDebugText"), RGB(0, 0, 0), FALSE, _T("Debug Text") },
324 | { _T("ColorDebugBackCurrent"), RGB(255, 255, 224), FALSE, _T("Debug Current Line Background") },
325 | { _T("ColorDebugValueChanged"), RGB(255, 0, 0), FALSE, _T("Debug Value Changed") },
326 | { _T("ColorDebugPrevious"), RGB(0, 0, 255), FALSE, _T("Debug Previous Address Marker") },
327 | { _T("ColorDebugMemoryROM"), RGB(0, 0, 255), FALSE, _T("Debug Memory ROM") },
328 | { _T("ColorDebugMemoryIO"), RGB(0, 128, 0), FALSE, _T("Debug Memory IO") },
329 | { _T("ColorDebugMemoryNA"), RGB(128, 128, 128), FALSE, _T("Debug Memory NA") },
330 | { _T("ColorDebugValue"), RGB(128, 128, 128), FALSE, _T("Debug Value") },
331 | { _T("ColorDebugValueRom"), RGB(128, 128, 192), FALSE, _T("Debug Value ROM") },
332 | { _T("ColorDebugSubtitles"), RGB(0, 128, 0), FALSE, _T("Debug Subtitles") },
333 | { _T("ColorDebugJump"), RGB(80, 192, 224), FALSE, _T("Debug Jump") },
334 | { _T("ColorDebugJumpYes"), RGB(80, 240, 80), FALSE, _T("Debug Jump Yes") },
335 | { _T("ColorDebugJumpNo"), RGB(180, 180, 180), FALSE, _T("Debug Jump No") },
336 | { _T("ColorDebugJumpHint"), RGB(40, 128, 160), FALSE, _T("Debug Jump Hint") },
337 | { _T("ColorDebugHint"), RGB(40, 40, 160), FALSE, _T("Debug Hint") },
338 | { _T("ColorDebugBreakpoint"), RGB(255, 128, 128), FALSE, _T("Debug Breakpoint") },
339 | { _T("ColorDebugHighlight"), RGB(200, 230, 255), FALSE, _T("Debug Highlight") },
340 | { _T("ColorDebugBreakptZone"), RGB(242, 242, 242), FALSE, _T("Debug Breakpoint Zone") },
341 | };
342 |
343 | LPCTSTR Settings_GetColorFriendlyName(ColorIndices colorIndex)
344 | {
345 | ColorDescriptorStruct* desc = ColorDescriptors + colorIndex;
346 |
347 | return desc->friendlyname;
348 | }
349 |
350 | COLORREF Settings_GetColor(ColorIndices colorIndex)
351 | {
352 | if (colorIndex < 0 || colorIndex >= ColorIndicesCount)
353 | return 0;
354 |
355 | ColorDescriptorStruct* desc = ColorDescriptors + colorIndex;
356 |
357 | if (desc->valid)
358 | return desc->currentcolor;
359 |
360 | COLORREF color;
361 | if (Settings_LoadColorValue(desc->settingname, &color))
362 | desc->currentcolor = color;
363 | else
364 | desc->currentcolor = desc->defaultcolor;
365 |
366 | desc->valid = TRUE;
367 | return desc->currentcolor;
368 | }
369 |
370 | void Settings_SetColor(ColorIndices colorIndex, COLORREF color)
371 | {
372 | if (colorIndex < 0 || colorIndex >= ColorIndicesCount)
373 | return;
374 |
375 | ColorDescriptorStruct* desc = ColorDescriptors + colorIndex;
376 |
377 | desc->currentcolor = color;
378 | desc->valid = TRUE;
379 |
380 | Settings_SaveColorValue(desc->settingname, color);
381 | }
382 |
383 | COLORREF Settings_GetDefaultColor(ColorIndices colorIndex)
384 | {
385 | if (colorIndex < 0 || colorIndex >= ColorIndicesCount)
386 | return 0;
387 |
388 | ColorDescriptorStruct* desc = ColorDescriptors + colorIndex;
389 |
390 | return desc->defaultcolor;
391 | }
392 |
393 |
394 | //////////////////////////////////////////////////////////////////////
395 |
--------------------------------------------------------------------------------
/emulator/SoundGen.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // SoundGen.cpp
12 |
13 | #include "stdafx.h"
14 | #include "emubase/Emubase.h"
15 | #include "SoundGen.h"
16 | #include "mmsystem.h"
17 |
18 | //////////////////////////////////////////////////////////////////////
19 |
20 |
21 | static void CALLBACK waveOutProc(HWAVEOUT, UINT, DWORD, DWORD, DWORD);
22 |
23 | static CRITICAL_SECTION waveCriticalSection;
24 | static WAVEHDR* waveBlocks;
25 | static volatile int waveFreeBlockCount;
26 | static int waveCurrentBlock;
27 |
28 | static bool m_SoundGenInitialized = false;
29 |
30 | HWAVEOUT hWaveOut;
31 |
32 | WAVEFORMATEX wfx;
33 | char buffer[BUFSIZE];
34 |
35 | int bufcurpos;
36 |
37 |
38 | //////////////////////////////////////////////////////////////////////
39 |
40 |
41 | static void CALLBACK WaveCallback(HWAVEOUT /*hwo*/, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR /*dwParam1*/, DWORD_PTR /*dwParam2*/)
42 | {
43 | int* freeBlockCounter = reinterpret_cast(dwInstance);
44 | if (uMsg != WOM_DONE)
45 | return;
46 |
47 | EnterCriticalSection(&waveCriticalSection);
48 | (*freeBlockCounter)++;
49 |
50 | LeaveCriticalSection(&waveCriticalSection);
51 | }
52 |
53 | void SoundGen_Initialize(WORD volume)
54 | {
55 | if (m_SoundGenInitialized)
56 | return;
57 |
58 | size_t totalBufferSize = (BLOCK_SIZE + sizeof(WAVEHDR)) * BLOCK_COUNT;
59 |
60 | unsigned char* mbuffer = static_cast(HeapAlloc(
61 | GetProcessHeap(),
62 | HEAP_ZERO_MEMORY,
63 | totalBufferSize));
64 | if (mbuffer == nullptr)
65 | {
66 | return;
67 | }
68 |
69 | waveBlocks = reinterpret_cast(mbuffer);
70 | mbuffer += sizeof(WAVEHDR) * BLOCK_COUNT;
71 | for (int i = 0; i < BLOCK_COUNT; i++)
72 | {
73 | waveBlocks[i].dwBufferLength = BLOCK_SIZE;
74 | waveBlocks[i].lpData = reinterpret_cast(mbuffer);
75 | mbuffer += BLOCK_SIZE;
76 | }
77 |
78 | waveFreeBlockCount = BLOCK_COUNT;
79 | waveCurrentBlock = 0;
80 |
81 | wfx.nSamplesPerSec = SOUNDSAMPLERATE;
82 | wfx.wBitsPerSample = 16;
83 | wfx.nChannels = 2;
84 | wfx.cbSize = 0;
85 | wfx.wFormatTag = WAVE_FORMAT_PCM;
86 | wfx.nBlockAlign = (wfx.wBitsPerSample * wfx.nChannels) >> 3;
87 | wfx.nAvgBytesPerSec = wfx.nBlockAlign * wfx.nSamplesPerSec;
88 |
89 | MMRESULT result = waveOutOpen(
90 | &hWaveOut, WAVE_MAPPER, &wfx, (DWORD_PTR)WaveCallback, (DWORD_PTR)&waveFreeBlockCount, CALLBACK_FUNCTION);
91 | if (result != MMSYSERR_NOERROR)
92 | {
93 | return;
94 | }
95 |
96 | waveOutSetVolume(hWaveOut, ((DWORD)volume << 16) | ((DWORD)volume));
97 |
98 | InitializeCriticalSection(&waveCriticalSection);
99 | bufcurpos = 0;
100 |
101 | m_SoundGenInitialized = true;
102 | }
103 |
104 | void SoundGen_Finalize()
105 | {
106 | if (!m_SoundGenInitialized)
107 | return;
108 |
109 | while (waveFreeBlockCount < BLOCK_COUNT)
110 | Sleep(1);
111 |
112 | for (int i = 0; i < waveFreeBlockCount; i++)
113 | {
114 | if (waveBlocks[i].dwFlags & WHDR_PREPARED)
115 | waveOutUnprepareHeader(hWaveOut, &waveBlocks[i], sizeof(WAVEHDR));
116 | }
117 |
118 | DeleteCriticalSection(&waveCriticalSection);
119 | waveOutClose(hWaveOut);
120 |
121 | HeapFree(GetProcessHeap(), 0, waveBlocks);
122 | waveBlocks = nullptr;
123 |
124 | m_SoundGenInitialized = false;
125 | }
126 |
127 | void SoundGen_SetVolume(WORD volume)
128 | {
129 | if (!m_SoundGenInitialized)
130 | return;
131 |
132 | waveOutSetVolume(hWaveOut, ((DWORD)volume << 16) | ((DWORD)volume));
133 | }
134 |
135 | void SoundGen_SetSpeed(WORD speedpercent)
136 | {
137 | DWORD dwRate = 0x00010000;
138 | if (speedpercent > 0 && speedpercent < 1000)
139 | dwRate = (((DWORD)speedpercent / 100) << 16) | ((speedpercent % 100) * 0x00010000 / 100);
140 |
141 | waveOutSetPlaybackRate(hWaveOut, dwRate);
142 | }
143 |
144 | void CALLBACK SoundGen_FeedDAC(unsigned short L, unsigned short R)
145 | {
146 | if (!m_SoundGenInitialized)
147 | return;
148 |
149 | unsigned int word = ((unsigned int)R << 16) + L;
150 | memcpy(&buffer[bufcurpos], &word, 4);
151 | bufcurpos += 4;
152 |
153 | if (bufcurpos >= BUFSIZE)
154 | {
155 | WAVEHDR* current = &waveBlocks[waveCurrentBlock];
156 |
157 | if (current->dwFlags & WHDR_PREPARED)
158 | waveOutUnprepareHeader(hWaveOut, current, sizeof(WAVEHDR));
159 |
160 | memcpy(current->lpData, buffer, BUFSIZE);
161 | current->dwBufferLength = BLOCK_SIZE;
162 |
163 | waveOutPrepareHeader(hWaveOut, current, sizeof(WAVEHDR));
164 | waveOutWrite(hWaveOut, current, sizeof(WAVEHDR));
165 |
166 | EnterCriticalSection(&waveCriticalSection);
167 | waveFreeBlockCount--;
168 | LeaveCriticalSection(&waveCriticalSection);
169 |
170 | while (!waveFreeBlockCount)
171 | Sleep(1);
172 |
173 | waveCurrentBlock++;
174 | if (waveCurrentBlock >= BLOCK_COUNT)
175 | waveCurrentBlock = 0;
176 |
177 | bufcurpos = 0;
178 | }
179 | }
180 |
181 |
182 | //////////////////////////////////////////////////////////////////////
183 |
--------------------------------------------------------------------------------
/emulator/SoundGen.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // SoundGen.h
12 |
13 | #pragma once
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 |
18 | #define BUFSIZE ((SOUNDSAMPLERATE / 25) * 4)
19 | #define BLOCK_COUNT 8
20 | #define BLOCK_SIZE BUFSIZE
21 |
22 | void SoundGen_Initialize(WORD volume);
23 | void SoundGen_Finalize();
24 | void SoundGen_SetVolume(WORD volume);
25 | void SoundGen_SetSpeed(WORD speedpercent);
26 | void CALLBACK SoundGen_FeedDAC(unsigned short L, unsigned short R);
27 |
28 |
29 | //////////////////////////////////////////////////////////////////////
30 |
--------------------------------------------------------------------------------
/emulator/SpriteView.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // SpriteView.cpp
12 |
13 | #include "stdafx.h"
14 | #include
15 | #include "Main.h"
16 | #include "Views.h"
17 | #include "ToolWindow.h"
18 | #include "Dialogs.h"
19 | #include "Emulator.h"
20 | #include "emubase/Emubase.h"
21 |
22 | //////////////////////////////////////////////////////////////////////
23 |
24 |
25 | HWND g_hwndSprite = (HWND)INVALID_HANDLE_VALUE; // Sprite view window handler
26 | WNDPROC m_wndprocSpriteToolWindow = NULL; // Old window proc address of the ToolWindow
27 |
28 | HWND m_hwndSpriteViewer = (HWND)INVALID_HANDLE_VALUE;
29 | HDRAWDIB m_hSpriteDrawDib = NULL;
30 | BITMAPINFO m_bmpinfoSprite;
31 | HBITMAP m_hSpriteBitmap = NULL;
32 | DWORD * m_pSprite_bits = NULL;
33 |
34 | const int m_nSprite_scale = 2;
35 | const int m_nSprite_ImageCX = 262;
36 | const int m_nSprite_ImageCY = 256;
37 | const int m_nSprite_ViewCX = m_nSprite_ImageCX * m_nSprite_scale;
38 | const int m_nSprite_ViewCY = m_nSprite_ImageCY * m_nSprite_scale;
39 |
40 | WORD m_wSprite_BaseAddress = 0;
41 | int m_nSprite_width = 2;
42 | int m_nSprite_PageSizeBytes = m_nSprite_ImageCY * (m_nSprite_ImageCX / (8 + 2));
43 |
44 | void SpriteView_OnDraw(HDC hdc);
45 | BOOL SpriteView_OnKeyDown(WPARAM vkey, LPARAM lParam);
46 | BOOL SpriteView_OnVScroll(WPARAM wParam, LPARAM lParam);
47 | BOOL SpriteView_OnMouseWheel(WPARAM wParam, LPARAM lParam);
48 | void SpriteView_InitBitmap();
49 | void SpriteView_DoneBitmap();
50 | void SpriteView_UpdateWindowText();
51 | void SpriteView_PrepareBitmap();
52 | void SpriteView_UpdateScrollPos();
53 |
54 |
55 | //////////////////////////////////////////////////////////////////////
56 |
57 | void SpriteView_RegisterClass()
58 | {
59 | WNDCLASSEX wcex;
60 | wcex.cbSize = sizeof(WNDCLASSEX);
61 |
62 | wcex.style = CS_HREDRAW | CS_VREDRAW;
63 | wcex.lpfnWndProc = SpriteViewViewerWndProc;
64 | wcex.cbClsExtra = 0;
65 | wcex.cbWndExtra = 0;
66 | wcex.hInstance = g_hInst;
67 | wcex.hIcon = NULL;
68 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
69 | wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
70 | wcex.lpszMenuName = NULL;
71 | wcex.lpszClassName = CLASSNAME_SPRITEVIEW;
72 | wcex.hIconSm = NULL;
73 |
74 | RegisterClassEx(&wcex);
75 | }
76 |
77 | void SpriteView_Create(int x, int y)
78 | {
79 | int cxBorder = ::GetSystemMetrics(SM_CXDLGFRAME);
80 | int cyBorder = ::GetSystemMetrics(SM_CYDLGFRAME);
81 | int cxScroll = ::GetSystemMetrics(SM_CXVSCROLL);
82 | int cyCaption = ::GetSystemMetrics(SM_CYSMCAPTION);
83 |
84 | int width = m_nSprite_ViewCX + cxScroll + cxBorder * 2;
85 | int height = m_nSprite_ViewCY + cyBorder * 2 + cyCaption;
86 | g_hwndSprite = CreateWindowEx(
87 | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
88 | CLASSNAME_OVERLAPPEDWINDOW, _T("Sprite Viewer"),
89 | WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE,
90 | x, y, width, height,
91 | NULL, NULL, g_hInst, NULL);
92 |
93 | // ToolWindow subclassing
94 | m_wndprocSpriteToolWindow = (WNDPROC)LongToPtr(SetWindowLongPtr(
95 | g_hwndSprite, GWLP_WNDPROC, PtrToLong(SpriteViewWndProc)));
96 |
97 | RECT rcClient; GetClientRect(g_hwndSprite, &rcClient);
98 |
99 | m_hwndSpriteViewer = CreateWindow(
100 | CLASSNAME_SPRITEVIEW, NULL,
101 | WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_TABSTOP,
102 | 0, 0, rcClient.right, rcClient.bottom,
103 | g_hwndSprite, NULL, g_hInst, NULL);
104 |
105 | m_wSprite_BaseAddress = Settings_GetSpriteAddress();
106 | m_nSprite_width = (int)Settings_GetSpriteWidth();
107 | if (m_nSprite_width <= 0) m_nSprite_width = 1;
108 | if (m_nSprite_width > 32) m_nSprite_width = 32;
109 |
110 | SpriteView_InitBitmap();
111 | SpriteView_UpdateWindowText();
112 | SpriteView_UpdateScrollPos();
113 | ::SetFocus(m_hwndSpriteViewer);
114 | }
115 |
116 | void SpriteView_InitBitmap()
117 | {
118 | m_hSpriteDrawDib = DrawDibOpen();
119 | HDC hdc = GetDC(g_hwnd);
120 |
121 | m_bmpinfoSprite.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
122 | m_bmpinfoSprite.bmiHeader.biWidth = m_nSprite_ImageCX;
123 | m_bmpinfoSprite.bmiHeader.biHeight = m_nSprite_ImageCY;
124 | m_bmpinfoSprite.bmiHeader.biPlanes = 1;
125 | m_bmpinfoSprite.bmiHeader.biBitCount = 32;
126 | m_bmpinfoSprite.bmiHeader.biCompression = BI_RGB;
127 | m_bmpinfoSprite.bmiHeader.biSizeImage = 0;
128 | m_bmpinfoSprite.bmiHeader.biXPelsPerMeter = 0;
129 | m_bmpinfoSprite.bmiHeader.biYPelsPerMeter = 0;
130 | m_bmpinfoSprite.bmiHeader.biClrUsed = 0;
131 | m_bmpinfoSprite.bmiHeader.biClrImportant = 0;
132 |
133 | m_hSpriteBitmap = CreateDIBSection(hdc, &m_bmpinfoSprite, DIB_RGB_COLORS, (void **)&m_pSprite_bits, NULL, 0);
134 |
135 | VERIFY(::ReleaseDC(g_hwnd, hdc));
136 | }
137 |
138 | void SpriteView_DoneBitmap()
139 | {
140 | if (m_hSpriteBitmap != NULL)
141 | {
142 | VERIFY(::DeleteObject(m_hSpriteBitmap)); m_hSpriteBitmap = NULL;
143 | }
144 |
145 | DrawDibClose(m_hSpriteDrawDib);
146 | }
147 |
148 | LRESULT CALLBACK SpriteViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
149 | {
150 | UNREFERENCED_PARAMETER(lParam);
151 | switch (message)
152 | {
153 | case WM_SETFOCUS:
154 | ::SetFocus(m_hwndSpriteViewer);
155 | break;
156 | case WM_DESTROY:
157 | g_hwndSprite = (HWND)INVALID_HANDLE_VALUE; // We are closed! Bye-bye!..
158 | return CallWindowProc(m_wndprocSpriteToolWindow, hWnd, message, wParam, lParam);
159 | default:
160 | return CallWindowProc(m_wndprocSpriteToolWindow, hWnd, message, wParam, lParam);
161 | }
162 | return (LRESULT)FALSE;
163 | }
164 |
165 | LRESULT CALLBACK SpriteViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
166 | {
167 | UNREFERENCED_PARAMETER(lParam);
168 | switch (message)
169 | {
170 | case WM_PAINT:
171 | {
172 | PAINTSTRUCT ps;
173 | HDC hdc = BeginPaint(hWnd, &ps);
174 |
175 | SpriteView_OnDraw(hdc); // Draw memory dump
176 |
177 | EndPaint(hWnd, &ps);
178 | }
179 | break;
180 | case WM_DESTROY:
181 | // Free resources
182 | SpriteView_DoneBitmap();
183 | return DefWindowProc(hWnd, message, wParam, lParam);
184 | case WM_LBUTTONDOWN:
185 | SetFocus(hWnd);
186 | break;
187 | case WM_KEYDOWN:
188 | return (LRESULT)SpriteView_OnKeyDown(wParam, lParam);
189 | case WM_VSCROLL:
190 | return (LRESULT)SpriteView_OnVScroll(wParam, lParam);
191 | case WM_MOUSEWHEEL:
192 | return (LRESULT)SpriteView_OnMouseWheel(wParam, lParam);
193 | default:
194 | return DefWindowProc(hWnd, message, wParam, lParam);
195 | }
196 | return (LRESULT)FALSE;
197 | }
198 |
199 | void SpriteView_OnDraw(HDC hdc)
200 | {
201 | ASSERT(g_pBoard != NULL);
202 |
203 | SpriteView_PrepareBitmap();
204 |
205 | DrawDibDraw(m_hSpriteDrawDib, hdc,
206 | 0, 0,
207 | m_nSprite_ImageCX * m_nSprite_scale, m_nSprite_ImageCY * m_nSprite_scale,
208 | &m_bmpinfoSprite.bmiHeader, m_pSprite_bits, 0, 0,
209 | m_nSprite_ImageCX, m_nSprite_ImageCY,
210 | 0);
211 | }
212 |
213 | void SpriteView_GoToAddress(WORD address)
214 | {
215 | if (address == m_wSprite_BaseAddress)
216 | return;
217 |
218 | m_wSprite_BaseAddress = address;
219 | Settings_SetSpriteAddress(m_wSprite_BaseAddress);
220 |
221 | SpriteView_UpdateWindowText();
222 | SpriteView_PrepareBitmap();
223 | InvalidateRect(m_hwndSpriteViewer, NULL, TRUE);
224 | SpriteView_UpdateScrollPos();
225 | }
226 | void SpriteView_SetSpriteWidth(int width)
227 | {
228 | if (width < 1) width = 1;
229 | if (width > m_nSprite_ImageCX / 8) width = m_nSprite_ImageCX / 8;
230 | if (width == m_nSprite_width)
231 | return;
232 |
233 | m_nSprite_width = width;
234 | Settings_SetSpriteWidth((WORD)width);
235 |
236 | SpriteView_UpdateWindowText();
237 | SpriteView_PrepareBitmap();
238 | InvalidateRect(m_hwndSpriteViewer, NULL, TRUE);
239 | SpriteView_UpdateScrollPos();
240 | }
241 |
242 | void SpriteView_UpdateWindowText()
243 | {
244 | TCHAR buffer[48];
245 | _sntprintf(buffer, sizeof(buffer) / sizeof(TCHAR) - 1,
246 | _T("Sprite Viewer - address %06o, width %d"), m_wSprite_BaseAddress, m_nSprite_width);
247 | ::SetWindowText(g_hwndSprite, buffer);
248 | }
249 |
250 | BOOL SpriteView_OnKeyDown(WPARAM vkey, LPARAM /*lParam*/)
251 | {
252 | switch (vkey)
253 | {
254 | case VK_LEFT:
255 | SpriteView_GoToAddress(m_wSprite_BaseAddress - (WORD)(m_nSprite_ImageCY * m_nSprite_width));
256 | break;
257 | case VK_RIGHT:
258 | SpriteView_GoToAddress(m_wSprite_BaseAddress + (WORD)(m_nSprite_ImageCY * m_nSprite_width));
259 | break;
260 | case VK_UP:
261 | if (GetKeyState(VK_CONTROL) & 0x8000)
262 | SpriteView_GoToAddress(m_wSprite_BaseAddress - (WORD)m_nSprite_width);
263 | else
264 | SpriteView_GoToAddress(m_wSprite_BaseAddress - 1);
265 | break;
266 | case VK_DOWN:
267 | if (GetKeyState(VK_CONTROL) & 0x8000)
268 | SpriteView_GoToAddress(m_wSprite_BaseAddress + (WORD)m_nSprite_width);
269 | else
270 | SpriteView_GoToAddress(m_wSprite_BaseAddress + 1);
271 | break;
272 | case VK_OEM_4: // '[' -- Decrement Sprite Width
273 | SpriteView_SetSpriteWidth(m_nSprite_width - 1);
274 | break;
275 | case VK_OEM_6: // ']' -- Increment Sprite Width
276 | SpriteView_SetSpriteWidth(m_nSprite_width + 1);
277 | break;
278 | case 0x47: // 'G' - Go To Address
279 | {
280 | WORD value = m_wSprite_BaseAddress;
281 | if (InputBoxOctal(m_hwndSpriteViewer, _T("Go To Address"), &value))
282 | SpriteView_GoToAddress(value);
283 | break;
284 | }
285 | case VK_HOME:
286 | SpriteView_GoToAddress(0);
287 | break;
288 | case VK_END:
289 | SpriteView_GoToAddress((WORD)(0x10000 - 1));
290 | break;
291 | case VK_PRIOR:
292 | SpriteView_GoToAddress(m_wSprite_BaseAddress - (WORD)m_nSprite_PageSizeBytes);
293 | break;
294 | case VK_NEXT:
295 | SpriteView_GoToAddress(m_wSprite_BaseAddress + (WORD)m_nSprite_PageSizeBytes);
296 | break;
297 | default:
298 | return TRUE;
299 | }
300 | return FALSE;
301 | }
302 |
303 | BOOL SpriteView_OnMouseWheel(WPARAM wParam, LPARAM /*lParam*/)
304 | {
305 | short zDelta = GET_WHEEL_DELTA_WPARAM(wParam);
306 |
307 | int nDelta = zDelta / 120;
308 | if (nDelta > 4) nDelta = 4;
309 | if (nDelta < -4) nDelta = -4;
310 |
311 | SpriteView_GoToAddress(m_wSprite_BaseAddress - (WORD)(nDelta * 3 * m_nSprite_width));
312 |
313 | return FALSE;
314 | }
315 |
316 | BOOL SpriteView_OnVScroll(WPARAM wParam, LPARAM /*lParam*/)
317 | {
318 | //WORD scrollpos = HIWORD(wParam);
319 | WORD scrollcmd = LOWORD(wParam);
320 | switch (scrollcmd)
321 | {
322 | case SB_LINEDOWN:
323 | SpriteView_GoToAddress(m_wSprite_BaseAddress + (WORD)m_nSprite_width);
324 | break;
325 | case SB_LINEUP:
326 | SpriteView_GoToAddress(m_wSprite_BaseAddress - (WORD)m_nSprite_width);
327 | break;
328 | case SB_PAGEDOWN:
329 | SpriteView_GoToAddress(m_wSprite_BaseAddress + (WORD)m_nSprite_PageSizeBytes);
330 | break;
331 | case SB_PAGEUP:
332 | SpriteView_GoToAddress(m_wSprite_BaseAddress - (WORD)m_nSprite_PageSizeBytes);
333 | break;
334 | case SB_THUMBPOSITION:
335 | {
336 | WORD scrollpos = HIWORD(wParam);
337 | SpriteView_GoToAddress(scrollpos);
338 | }
339 | break;
340 | }
341 |
342 | return FALSE;
343 | }
344 |
345 | void SpriteView_UpdateScrollPos()
346 | {
347 | int columns = 0;
348 | int cx = m_nSprite_ImageCX;
349 | while (cx > m_nSprite_width * 8)
350 | {
351 | columns++;
352 | cx -= m_nSprite_width * 8;
353 | if (cx <= 2)
354 | break;
355 | cx -= 2;
356 | }
357 | m_nSprite_PageSizeBytes = m_nSprite_ImageCY * columns * m_nSprite_width;
358 |
359 | SCROLLINFO si;
360 | ZeroMemory(&si, sizeof(si));
361 | si.cbSize = sizeof(si);
362 | si.fMask = SIF_PAGE | SIF_POS | SIF_RANGE;
363 | si.nPage = m_nSprite_PageSizeBytes;
364 | si.nPos = m_wSprite_BaseAddress;
365 | si.nMin = 0;
366 | si.nMax = 0x10000 - 1 + m_nSprite_PageSizeBytes;
367 | SetScrollInfo(m_hwndSpriteViewer, SB_VERT, &si, TRUE);
368 | }
369 |
370 | void SpriteView_PrepareBitmap()
371 | {
372 | // Clear bitmap
373 | memset(m_pSprite_bits, 0x7f, m_nSprite_ImageCX * m_nSprite_ImageCY * 4);
374 |
375 | WORD address = m_wSprite_BaseAddress;
376 |
377 | for (int x = 0; x + m_nSprite_width * 8 <= m_nSprite_ImageCX; x += m_nSprite_width * 8 + 2)
378 | {
379 | for (int y = 0; y < m_nSprite_ImageCY; y++)
380 | {
381 | DWORD* pBits = m_pSprite_bits + (m_nSprite_ImageCY - 1 - y) * m_nSprite_ImageCX + x;
382 |
383 | for (int w = 0; w < m_nSprite_width; w++)
384 | {
385 | // Get byte from memory
386 | int addrtype = 0;
387 | bool okHalt = g_pBoard->GetCPU()->IsHaltMode();
388 | WORD value = g_pBoard->GetWordView(address & ~1, okHalt, FALSE, &addrtype);
389 | if (address & 1)
390 | value = value >> 8;
391 |
392 | for (int i = 0; i < 8; i++)
393 | {
394 | COLORREF color = (value & 1) ? 0xffffff : 0;
395 | *pBits = color;
396 | pBits++;
397 |
398 | value = value >> 1;
399 | }
400 |
401 | address++;
402 | }
403 | }
404 | }
405 | }
406 |
407 |
408 | //////////////////////////////////////////////////////////////////////
409 |
--------------------------------------------------------------------------------
/emulator/TeletypeView.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // TeletypeView.cpp
12 |
13 | #include "stdafx.h"
14 | #include "Main.h"
15 | #include "Views.h"
16 | #include "ToolWindow.h"
17 |
18 | //////////////////////////////////////////////////////////////////////
19 |
20 |
21 | HWND g_hwndTeletype = (HWND)INVALID_HANDLE_VALUE; // Teletype view window handler
22 | WNDPROC m_wndprocTeletypeToolWindow = NULL; // Old window proc address of the ToolWindow
23 |
24 | HWND m_hwndTeletypeLog = (HWND)INVALID_HANDLE_VALUE; // Teletype log window - read-only edit control
25 | HFONT m_hfontTeletype = NULL;
26 |
27 |
28 | //////////////////////////////////////////////////////////////////////
29 |
30 |
31 | void TeletypeView_Create(int x, int y, int width, int height)
32 | {
33 | //int cxBorder = ::GetSystemMetrics(SM_CXDLGFRAME);
34 | //int cyBorder = ::GetSystemMetrics(SM_CYDLGFRAME);
35 | //int cxScroll = ::GetSystemMetrics(SM_CXVSCROLL);
36 | //int cyScroll = ::GetSystemMetrics(SM_CYHSCROLL);
37 | //int cyCaption = ::GetSystemMetrics(SM_CYSMCAPTION);
38 |
39 | g_hwndTeletype = CreateWindowEx(
40 | WS_EX_TOOLWINDOW | WS_EX_TOPMOST,
41 | CLASSNAME_OVERLAPPEDWINDOW, _T("BK Teletype"),
42 | WS_POPUPWINDOW | WS_CAPTION | WS_VISIBLE,
43 | x, y, width, height,
44 | NULL, NULL, g_hInst, NULL);
45 |
46 | // ToolWindow subclassing
47 | m_wndprocTeletypeToolWindow = (WNDPROC)LongToPtr( SetWindowLongPtr(
48 | g_hwndTeletype, GWLP_WNDPROC, PtrToLong(TeletypeViewWndProc)) );
49 |
50 | RECT rcClient; ::GetClientRect(g_hwndTeletype, &rcClient);
51 |
52 | m_hwndTeletypeLog = CreateWindowEx(
53 | WS_EX_CLIENTEDGE,
54 | _T("EDIT"), NULL,
55 | WS_CHILD | WS_VSCROLL | WS_VISIBLE | ES_READONLY | ES_MULTILINE,
56 | 0, 0,
57 | rcClient.right, rcClient.bottom,
58 | g_hwndTeletype, NULL, g_hInst, NULL);
59 |
60 | m_hfontTeletype = CreateMonospacedFont();
61 | ::SendMessage(m_hwndTeletypeLog, WM_SETFONT, (WPARAM)m_hfontTeletype, 0);
62 |
63 | ::ShowWindow(g_hwndTeletype, SW_SHOW);
64 | }
65 |
66 | // Adjust position of client windows
67 | void TeletypeView_AdjustWindowLayout()
68 | {
69 | RECT rc; GetClientRect(g_hwndTeletype, &rc);
70 |
71 | if (m_hwndTeletypeLog != (HWND)INVALID_HANDLE_VALUE)
72 | SetWindowPos(m_hwndTeletypeLog, NULL, 0, 0, rc.right, rc.bottom, SWP_NOZORDER);
73 | }
74 |
75 | LRESULT CALLBACK TeletypeViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
76 | {
77 | UNREFERENCED_PARAMETER(lParam);
78 | LRESULT lResult;
79 | switch (message)
80 | {
81 | case WM_DESTROY:
82 | g_hwndTeletype = (HWND)INVALID_HANDLE_VALUE; // We are closed! Bye-bye!..
83 | return CallWindowProc(m_wndprocTeletypeToolWindow, hWnd, message, wParam, lParam);
84 | case WM_SIZE:
85 | lResult = CallWindowProc(m_wndprocTeletypeToolWindow, hWnd, message, wParam, lParam);
86 | TeletypeView_AdjustWindowLayout();
87 | return lResult;
88 | default:
89 | return CallWindowProc(m_wndprocTeletypeToolWindow, hWnd, message, wParam, lParam);
90 | }
91 | }
92 |
93 | void TeletypeView_Output(LPCTSTR message)
94 | {
95 | // Put selection to the end of text
96 | SendMessage(m_hwndTeletypeLog, EM_SETSEL, 0x100000, 0x100000);
97 | // Insert the message
98 | SendMessage(m_hwndTeletypeLog, EM_REPLACESEL, (WPARAM)FALSE, (LPARAM)message);
99 | // Scroll to caret
100 | SendMessage(m_hwndTeletypeLog, EM_SCROLLCARET, 0, 0);
101 | }
102 |
103 | void TeletypeView_OutputSymbol(TCHAR symbol)
104 | {
105 | if (m_hwndTeletypeLog == NULL) return;
106 |
107 | TCHAR message[2];
108 | message[0] = symbol;
109 | message[1] = 0;
110 |
111 | TeletypeView_Output(message);
112 | }
113 |
114 |
115 | //////////////////////////////////////////////////////////////////////
116 |
--------------------------------------------------------------------------------
/emulator/ToolWindow.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // ToolWindow.cpp
12 |
13 | #include "stdafx.h"
14 | #include "Main.h"
15 | #include "ToolWindow.h"
16 | #include
17 |
18 | //////////////////////////////////////////////////////////////////////
19 |
20 |
21 | void ToolWindow_RegisterClass()
22 | {
23 | WNDCLASSEX wcex;
24 | wcex.cbSize = sizeof(WNDCLASSEX);
25 |
26 | wcex.style = CS_HREDRAW | CS_VREDRAW;
27 | wcex.lpfnWndProc = ToolWindow_WndProc;
28 | wcex.cbClsExtra = 0;
29 | wcex.cbWndExtra = 0;
30 | wcex.hInstance = g_hInst;
31 | wcex.hIcon = NULL;
32 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
33 | wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
34 | wcex.lpszMenuName = NULL;
35 | wcex.lpszClassName = CLASSNAME_TOOLWINDOW;
36 | wcex.hIconSm = NULL;
37 |
38 | RegisterClassEx(&wcex);
39 | }
40 |
41 | LRESULT CALLBACK ToolWindow_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
42 | {
43 | UNREFERENCED_PARAMETER(lParam);
44 | switch (message)
45 | {
46 | case WM_NCCALCSIZE:
47 | {
48 | LPRECT pRect = (LPRECT) lParam;
49 | pRect->top += TOOLWINDOW_CAPTION_HEIGHT;
50 | }
51 | break;
52 | case WM_NCPAINT:
53 | {
54 | RECT rcClient; ::GetClientRect(hWnd, &rcClient);
55 | RECT rcWindow; ::GetWindowRect(hWnd, &rcWindow);
56 | MapWindowPoints(NULL, hWnd, (LPPOINT)&rcWindow, 2);
57 |
58 | rcClient.left -= rcWindow.left; rcClient.top -= rcWindow.top;
59 | rcClient.right -= rcWindow.left; rcClient.bottom -= rcWindow.top;
60 | rcWindow.left -= rcWindow.left; rcWindow.top -= rcWindow.top;
61 | rcWindow.right -= rcWindow.left; rcWindow.bottom -= rcWindow.top;
62 |
63 | HDC hdc = ::GetWindowDC(hWnd);
64 | ::ExcludeClipRect(hdc, rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
65 |
66 | // Draw caption background
67 | BOOL okActive = (::GetActiveWindow() == hWnd);
68 | HBRUSH brushCaption = ::GetSysColorBrush(okActive ? COLOR_ACTIVECAPTION : COLOR_INACTIVECAPTION);
69 | RECT rc;
70 | rc.left = rc.top = 0;
71 | rc.right = rcWindow.right; rc.bottom = TOOLWINDOW_CAPTION_HEIGHT;
72 | ::FillRect(hdc, &rc, brushCaption);
73 |
74 | // Draw caption text
75 | TCHAR buffer[64];
76 | ::GetWindowText(hWnd, buffer, 64);
77 | rc.left += 8; rc.right -= 8;
78 | HFONT hfont = CreateDialogFont();
79 | HGDIOBJ hOldFont = ::SelectObject(hdc, hfont);
80 | ::SetTextColor(hdc, ::GetSysColor(COLOR_CAPTIONTEXT));
81 | ::SetBkMode(hdc, TRANSPARENT);
82 | ::DrawText(hdc, buffer, (int)wcslen(buffer), &rc, DT_LEFT | DT_VCENTER | DT_SINGLELINE);
83 | ::SelectObject(hdc, hOldFont);
84 | VERIFY(::DeleteObject(hfont));
85 |
86 | VERIFY(::ReleaseDC(hWnd, hdc));
87 | }
88 | break;
89 | case WM_SETTEXT:
90 | {
91 | LRESULT lResult = DefWindowProc(hWnd, message, wParam, lParam);
92 |
93 | // Invalidate non-client area
94 | RECT rcWindow; ::GetWindowRect(hWnd, &rcWindow);
95 | MapWindowPoints(NULL, hWnd, (LPPOINT)&rcWindow, 2);
96 | ::RedrawWindow(hWnd, &rcWindow, NULL, RDW_FRAME | RDW_INVALIDATE);
97 |
98 | return lResult;
99 | }
100 | default:
101 | return DefWindowProc(hWnd, message, wParam, lParam);
102 | }
103 | return (LRESULT)FALSE;
104 | }
105 |
106 |
107 | //////////////////////////////////////////////////////////////////////
108 |
109 |
110 | void OverlappedWindow_RegisterClass()
111 | {
112 | WNDCLASSEX wcex;
113 | wcex.cbSize = sizeof(WNDCLASSEX);
114 |
115 | wcex.style = CS_HREDRAW | CS_VREDRAW;
116 | wcex.lpfnWndProc = DefWindowProc;
117 | wcex.cbClsExtra = 0;
118 | wcex.cbWndExtra = 0;
119 | wcex.hInstance = g_hInst;
120 | wcex.hIcon = NULL;
121 | wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
122 | wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
123 | wcex.lpszMenuName = NULL;
124 | wcex.lpszClassName = CLASSNAME_OVERLAPPEDWINDOW;
125 | wcex.hIconSm = NULL;
126 |
127 | RegisterClassEx(&wcex);
128 | }
129 |
130 |
131 | //////////////////////////////////////////////////////////////////////
132 |
133 | bool m_SplitterWindow_IsMoving = false;
134 | int m_SplitterWindow_MovingStartY = 0;
135 |
136 | const int SPLITTERWINDOW_MINWINDOWHEIGHT = 64;
137 |
138 | void SplitterWindow_RegisterClass()
139 | {
140 | WNDCLASSEX wcex;
141 | wcex.cbSize = sizeof(WNDCLASSEX);
142 |
143 | wcex.style = CS_HREDRAW | CS_VREDRAW;
144 | wcex.lpfnWndProc = SplitterWindow_WndProc;
145 | wcex.cbClsExtra = 0;
146 | wcex.cbWndExtra = 8 * 2;
147 | wcex.hInstance = g_hInst;
148 | wcex.hIcon = NULL;
149 | wcex.hCursor = LoadCursor(NULL, IDC_SIZENS);
150 | wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
151 | wcex.lpszMenuName = NULL;
152 | wcex.lpszClassName = CLASSNAME_SPLITTERWINDOW;
153 | wcex.hIconSm = NULL;
154 |
155 | RegisterClassEx(&wcex);
156 | }
157 |
158 | HWND SplitterWindow_Create(HWND hwndParent, HWND hwndTop, HWND hwndBottom)
159 | {
160 | ASSERT(hwndParent != NULL);
161 | ASSERT(hwndTop != NULL);
162 | ASSERT(hwndBottom != NULL);
163 |
164 | HWND hwnd = CreateWindow(
165 | CLASSNAME_SPLITTERWINDOW, NULL,
166 | WS_CHILD | WS_VISIBLE,
167 | 0, 0, 100, 4,
168 | hwndParent, NULL, g_hInst, NULL);
169 |
170 | SetWindowLongPtr(hwnd, 0, (LONG_PTR)hwndTop);
171 | SetWindowLongPtr(hwnd, 8, (LONG_PTR)hwndBottom);
172 |
173 | m_SplitterWindow_IsMoving = false;
174 |
175 | return hwnd;
176 | }
177 |
178 | void SplitterWindow_MoveWindows(HWND hwndSplitter, int deltaY)
179 | {
180 | if (deltaY == 0)
181 | return;
182 |
183 | HWND hwndTop = (HWND)GetWindowLongPtr(hwndSplitter, 0);
184 | HWND hwndBottom = (HWND)GetWindowLongPtr(hwndSplitter, 8);
185 |
186 | RECT rcTop; ::GetWindowRect(hwndTop, &rcTop);
187 | ::ScreenToClient(g_hwnd, (POINT*)&rcTop);
188 | ::ScreenToClient(g_hwnd, ((POINT*)&rcTop) + 1);
189 | RECT rcBottom; ::GetWindowRect(hwndBottom, &rcBottom);
190 | ::ScreenToClient(g_hwnd, (POINT*)&rcBottom);
191 | ::ScreenToClient(g_hwnd, ((POINT*)&rcBottom) + 1);
192 |
193 | if (deltaY < 0 && rcTop.bottom - rcTop.top + deltaY < SPLITTERWINDOW_MINWINDOWHEIGHT)
194 | deltaY = SPLITTERWINDOW_MINWINDOWHEIGHT - (rcTop.bottom - rcTop.top);
195 | if (deltaY > 0 && rcBottom.bottom - rcBottom.top - deltaY < SPLITTERWINDOW_MINWINDOWHEIGHT)
196 | deltaY = (rcBottom.bottom - rcBottom.top) - SPLITTERWINDOW_MINWINDOWHEIGHT;
197 |
198 | SetWindowPos(hwndTop, NULL, rcTop.left, rcTop.top, rcTop.right - rcTop.left, rcTop.bottom - rcTop.top + deltaY, SWP_NOZORDER);
199 | SetWindowPos(hwndBottom, NULL, rcBottom.left, rcBottom.top + deltaY, rcBottom.right - rcBottom.left, rcBottom.bottom - rcBottom.top - deltaY, SWP_NOZORDER);
200 | SetWindowPos(hwndSplitter, NULL, rcBottom.left, rcBottom.top + deltaY - 4, rcBottom.right - rcBottom.left, 4, SWP_NOZORDER);
201 | }
202 |
203 | LRESULT CALLBACK SplitterWindow_WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
204 | {
205 | UNREFERENCED_PARAMETER(lParam);
206 | switch (message)
207 | {
208 | case WM_LBUTTONDOWN:
209 | m_SplitterWindow_IsMoving = true;
210 | m_SplitterWindow_MovingStartY = GET_Y_LPARAM(lParam);
211 | ::SetCapture(hWnd);
212 | //TODO: Draw frame
213 | return 0;
214 | case WM_LBUTTONUP:
215 | if (m_SplitterWindow_IsMoving)
216 | {
217 | m_SplitterWindow_IsMoving = false;
218 | ::ReleaseCapture();
219 |
220 | int deltaY = GET_Y_LPARAM(lParam) - m_SplitterWindow_MovingStartY;
221 | SplitterWindow_MoveWindows(hWnd, deltaY);
222 | }
223 | return 0;
224 | case WM_MOUSEMOVE:
225 | if ((wParam == MK_LBUTTON) && m_SplitterWindow_IsMoving)
226 | {
227 | //TODO: Redraw frame
228 | }
229 | return 0;
230 | default:
231 | return DefWindowProc(hWnd, message, wParam, lParam);
232 | }
233 | //return (LRESULT)FALSE;
234 | }
235 |
236 |
237 | //////////////////////////////////////////////////////////////////////
238 |
--------------------------------------------------------------------------------
/emulator/ToolWindow.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // ToolWindow.h
12 |
13 | #pragma once
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 |
18 | #define CLASSNAMEPREFIX _T("BKBTL")
19 |
20 | const LPCTSTR CLASSNAME_TOOLWINDOW = CLASSNAMEPREFIX _T("TOOLWINDOW");
21 | const LPCTSTR CLASSNAME_OVERLAPPEDWINDOW = CLASSNAMEPREFIX _T("OVERLAPPEDWINDOW");
22 | const LPCTSTR CLASSNAME_SPLITTERWINDOW = CLASSNAMEPREFIX _T("SPLITTERWINDOW");
23 |
24 | const int TOOLWINDOW_CAPTION_HEIGHT = 16;
25 |
26 | void ToolWindow_RegisterClass();
27 | LRESULT CALLBACK ToolWindow_WndProc(HWND, UINT, WPARAM, LPARAM);
28 |
29 | void OverlappedWindow_RegisterClass();
30 |
31 | void SplitterWindow_RegisterClass();
32 | LRESULT CALLBACK SplitterWindow_WndProc(HWND, UINT, WPARAM, LPARAM);
33 | HWND SplitterWindow_Create(HWND hwndParent, HWND hwndTop, HWND hwndBottom);
34 |
35 |
36 | //////////////////////////////////////////////////////////////////////
37 |
38 |
--------------------------------------------------------------------------------
/emulator/Views.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Views.h
12 | // Defines for all views of the application
13 |
14 | #pragma once
15 |
16 | //////////////////////////////////////////////////////////////////////
17 | // Window class names
18 |
19 | #define CLASSNAMEPREFIX _T("BKBTL")
20 |
21 | const LPCTSTR CLASSNAME_SCREENVIEW = CLASSNAMEPREFIX _T("SCREEN");
22 | const LPCTSTR CLASSNAME_KEYBOARDVIEW = CLASSNAMEPREFIX _T("KEYBOARD");
23 | const LPCTSTR CLASSNAME_DEBUGVIEW = CLASSNAMEPREFIX _T("DEBUG");
24 | const LPCTSTR CLASSNAME_DISASMVIEW = CLASSNAMEPREFIX _T("DISASM");
25 | const LPCTSTR CLASSNAME_MEMORYVIEW = CLASSNAMEPREFIX _T("MEMORY");
26 | const LPCTSTR CLASSNAME_MEMORYMAPVIEW = CLASSNAMEPREFIX _T("MEMORYMAP");
27 | const LPCTSTR CLASSNAME_SPRITEVIEW = CLASSNAMEPREFIX _T("SPRITE");
28 | const LPCTSTR CLASSNAME_TELETYPEVIEW = CLASSNAMEPREFIX _T("TELETYPE");
29 | const LPCTSTR CLASSNAME_CONSOLEVIEW = CLASSNAMEPREFIX _T("CONSOLE");
30 | const LPCTSTR CLASSNAME_TAPEVIEW = CLASSNAMEPREFIX _T("TAPE");
31 |
32 |
33 | //////////////////////////////////////////////////////////////////////
34 | // ScreenView
35 |
36 | extern HWND g_hwndScreen; // Screen View window handle
37 |
38 | void ScreenView_RegisterClass();
39 | void ScreenView_Init();
40 | void ScreenView_Done();
41 | int ScreenView_GetScreenMode();
42 | void ScreenView_SetScreenMode(int);
43 | void ScreenView_PrepareScreen();
44 | void ScreenView_ScanKeyboard();
45 | void ScreenView_ProcessKeyboard();
46 | void ScreenView_RedrawScreen(); // Force to call PrepareScreen and to draw the image
47 | void ScreenView_Create(HWND hwndParent, int x, int y);
48 | LRESULT CALLBACK ScreenViewWndProc(HWND, UINT, WPARAM, LPARAM);
49 | BOOL ScreenView_SaveScreenshot(LPCTSTR sFileName);
50 | HGLOBAL ScreenView_GetScreenshotAsDIB();
51 | void ScreenView_KeyEvent(BYTE keyscan, BOOL pressed);
52 |
53 |
54 | //////////////////////////////////////////////////////////////////////
55 | // KeyboardView
56 |
57 | extern HWND g_hwndKeyboard; // Keyboard View window handle
58 |
59 | void KeyboardView_RegisterClass();
60 | void KeyboardView_Init();
61 | void KeyboardView_Done();
62 | void KeyboardView_Create(HWND hwndParent, int x, int y, int width, int height);
63 | LRESULT CALLBACK KeyboardViewWndProc(HWND, UINT, WPARAM, LPARAM);
64 | void KeyboardView_Update();
65 | void KeyboardView_KeyEvent(BYTE keyscan, BOOL pressed);
66 |
67 |
68 | //////////////////////////////////////////////////////////////////////
69 | // DebugView
70 |
71 | extern HWND g_hwndDebug; // Debug View window handle
72 |
73 | void DebugView_RegisterClass();
74 | void DebugView_Init();
75 | void DebugView_Create(HWND hwndParent, int x, int y, int width, int height);
76 | void DebugView_Redraw();
77 | LRESULT CALLBACK DebugViewWndProc(HWND, UINT, WPARAM, LPARAM);
78 | LRESULT CALLBACK DebugViewViewerWndProc(HWND, UINT, WPARAM, LPARAM);
79 | void DebugView_OnUpdate();
80 | BOOL DebugView_IsRegisterChanged(int regno);
81 |
82 |
83 | //////////////////////////////////////////////////////////////////////
84 | // DisasmView
85 |
86 | extern HWND g_hwndDisasm; // Disasm View window handle
87 |
88 | void DisasmView_RegisterClass();
89 | void DisasmView_Init();
90 | void DisasmView_Done();
91 | void DisasmView_Create(HWND hwndParent, int x, int y, int width, int height);
92 | void DisasmView_Redraw();
93 | LRESULT CALLBACK DisasmViewWndProc(HWND, UINT, WPARAM, LPARAM);
94 | LRESULT CALLBACK DisasmViewViewerWndProc(HWND, UINT, WPARAM, LPARAM);
95 | void DisasmView_OnUpdate();
96 | void DisasmView_LoadUnloadSubtitles();
97 |
98 |
99 | //////////////////////////////////////////////////////////////////////
100 | // MemoryView
101 |
102 | extern HWND g_hwndMemory; // Memory view window handler
103 |
104 | enum MemoryViewNumeralMode
105 | {
106 | MEMMODENUM_OCT = 0,
107 | MEMMODENUM_HEX = 1,
108 | };
109 |
110 | void MemoryView_RegisterClass();
111 | void MemoryView_Create(HWND hwndParent, int x, int y, int width, int height);
112 | LRESULT CALLBACK MemoryViewWndProc(HWND, UINT, WPARAM, LPARAM);
113 | LRESULT CALLBACK MemoryViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
114 | void MemoryView_SwitchWordByte();
115 | void MemoryView_SwitchNumeralMode();
116 | void MemoryView_SelectAddress();
117 |
118 |
119 | //////////////////////////////////////////////////////////////////////
120 | // MemoryMapView
121 |
122 | extern HWND g_hwndMemoryMap; // MemoryMap view window handler
123 |
124 | void MemoryMapView_RegisterClass();
125 | void MemoryMapView_Create(HWND hwndParent, int x, int y);
126 | LRESULT CALLBACK MemoryMapViewWndProc(HWND, UINT, WPARAM, LPARAM);
127 | LRESULT CALLBACK MemoryMapViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
128 | void MemoryMapView_RedrawMap();
129 |
130 |
131 | //////////////////////////////////////////////////////////////////////
132 | // SpriteView
133 |
134 | extern HWND g_hwndSprite; // Sprite view window handler
135 |
136 | void SpriteView_RegisterClass();
137 | void SpriteView_Create(int x, int y);
138 | LRESULT CALLBACK SpriteViewWndProc(HWND, UINT, WPARAM, LPARAM);
139 | LRESULT CALLBACK SpriteViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
140 |
141 |
142 | //////////////////////////////////////////////////////////////////////
143 | // TeletypeView
144 |
145 | extern HWND g_hwndTeletype; // Teletype View window handle
146 | void TeletypeView_RegisterClass();
147 | void TeletypeView_Create(int x, int y, int width, int height);
148 | LRESULT CALLBACK TeletypeViewWndProc(HWND, UINT, WPARAM, LPARAM);
149 | LRESULT CALLBACK TeletypeViewViewerWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
150 | void TeletypeView_OutputSymbol(TCHAR symbol);
151 | void TeletypeView_Output(LPCTSTR message);
152 |
153 |
154 | //////////////////////////////////////////////////////////////////////
155 | // ConsoleView
156 |
157 | extern HWND g_hwndConsole; // Console View window handle
158 |
159 | void ConsoleView_RegisterClass();
160 | void ConsoleView_Create(HWND hwndParent, int x, int y, int width, int height);
161 | LRESULT CALLBACK ConsoleViewWndProc(HWND, UINT, WPARAM, LPARAM);
162 | void ConsoleView_PrintFormat(LPCTSTR pszFormat, ...);
163 | void ConsoleView_Print(LPCTSTR message);
164 | void ConsoleView_Activate();
165 | void ConsoleView_StepInto();
166 | void ConsoleView_StepOver();
167 | void ConsoleView_ClearConsole();
168 | void ConsoleView_DeleteAllBreakpoints();
169 |
170 |
171 | //////////////////////////////////////////////////////////////////////
172 | // TapeView
173 |
174 | extern HWND g_hwndTape; // Tape View window handle
175 |
176 | void TapeView_RegisterClass();
177 | void TapeView_Create(HWND hwndParent, int x, int y, int width, int height);
178 | LRESULT CALLBACK TapeViewWndProc(HWND, UINT, WPARAM, LPARAM);
179 |
180 |
181 | //////////////////////////////////////////////////////////////////////
182 |
--------------------------------------------------------------------------------
/emulator/emubase/Board.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Board.h
12 | //
13 |
14 | #pragma once
15 |
16 | class CProcessor;
17 |
18 |
19 | //////////////////////////////////////////////////////////////////////
20 |
21 | // Machine configurations
22 | enum BKConfiguration
23 | {
24 | // Configuration options
25 | BK_COPT_BK0010 = 0,
26 | BK_COPT_BK0011 = 1,
27 | BK_COPT_ROM_BASIC = 2,
28 | BK_COPT_ROM_FOCAL = 4,
29 | BK_COPT_FDD = 16,
30 |
31 | // Configurations BK-0010(01)
32 | BK_CONF_BK0010_BASIC = // БК-0010(01) и BASIC-86
33 | BK_COPT_BK0010 | BK_COPT_ROM_BASIC,
34 | BK_CONF_BK0010_FOCAL = // БК-0010(01) и Фокал + тесты
35 | BK_COPT_BK0010 | BK_COPT_ROM_FOCAL,
36 | BK_CONF_BK0010_FDD = // БК-0010(01) и блок КНГМД с 16 КБ ОЗУ
37 | BK_COPT_BK0010 | BK_COPT_FDD,
38 | // Configurations BK-0011M
39 | BK_CONF_BK0011 = // БК-0011М без блока КНГМД
40 | BK_COPT_BK0011,
41 | BK_CONF_BK0011_FDD = // БК-0011М и блок КНГМД
42 | BK_COPT_BK0011 | BK_COPT_FDD,
43 | };
44 |
45 |
46 | //////////////////////////////////////////////////////////////////////
47 |
48 |
49 | // TranslateAddress result code
50 | #define ADDRTYPE_RAM 0 // RAM
51 | #define ADDRTYPE_ROM 32 // ROM
52 | #define ADDRTYPE_IO 64 // I/O port
53 | #define ADDRTYPE_DENY 128 // Access denied
54 | #define ADDRTYPE_MASK 224 // RAM type mask
55 | #define ADDRTYPE_RAMMASK 7 // RAM chunk number mask
56 |
57 | // Trace flags
58 | #define TRACE_NONE 0 // Turn off all tracing
59 | #define TRACE_CPUROM 1 // Trace CPU instructions from ROM
60 | #define TRACE_CPURAM 2 // Trace CPU instructions from RAM
61 | #define TRACE_CPU 3 // Trace CPU instructions (mask)
62 | #define TRACE_FLOPPY 0100 // Trace floppies
63 | #define TRACE_ALL 0177777 // Trace all
64 |
65 | //floppy debug
66 | #define FLOPPY_FSM_WAITFORLSB 0
67 | #define FLOPPY_FSM_WAITFORMSB 1
68 | #define FLOPPY_FSM_WAITFORTERM1 2
69 | #define FLOPPY_FSM_WAITFORTERM2 3
70 |
71 | // Emulator image constants
72 | #define BKIMAGE_HEADER_SIZE 32
73 | #define BKIMAGE_SIZE 200704
74 | #define BKIMAGE_HEADER1 0x30304B41 // "BK00"
75 | #define BKIMAGE_HEADER2 0x214C5442 // "BTL!"
76 | #define BKIMAGE_VERSION 0x00010000 // 1.0
77 |
78 |
79 | //////////////////////////////////////////////////////////////////////
80 | // BK special key codes
81 |
82 | #define BK_KEY_REPEAT 0201
83 | #define BK_KEY_LOWER 0273
84 | #define BK_KEY_UPPER 0274
85 | #define BK_KEY_BACKSHIFT 0275
86 | #define BK_KEY_AR2 0276
87 | #define BK_KEY_STOP 0277
88 |
89 | // События от джойстика - передавать в метод KeyboardEvent
90 | #define BK_KEY_JOYSTICK_BUTTON1 0260
91 | #define BK_KEY_JOYSTICK_BUTTON2 0261
92 | #define BK_KEY_JOYSTICK_BUTTON3 0262
93 | #define BK_KEY_JOYSTICK_BUTTON4 0263
94 | #define BK_KEY_JOYSTICK_RIGHT 0264
95 | #define BK_KEY_JOYSTICK_DOWN 0265
96 | #define BK_KEY_JOYSTICK_LEFT 0266
97 | #define BK_KEY_JOYSTICK_UP 0267
98 |
99 | // Состояния клавиатуры БК - возвращаются из метода GetKeyboardRegister
100 | #define KEYB_RUS 0x01
101 | #define KEYB_LAT 0x02
102 | #define KEYB_LOWERREG 0x10
103 |
104 |
105 | // Tape emulator callback used to read a tape recorded data.
106 | // Input:
107 | // samples Number of samples to play.
108 | // Output:
109 | // result Bit to put in tape input port.
110 | typedef bool (CALLBACK* TAPEREADCALLBACK)(unsigned int samples);
111 |
112 | // Tape emulator callback used to write a data to tape.
113 | // Input:
114 | // value Sample value to write.
115 | typedef void (CALLBACK* TAPEWRITECALLBACK)(int value, unsigned int samples);
116 |
117 | // Sound generator callback function type
118 | typedef void (CALLBACK* SOUNDGENCALLBACK)(unsigned short L, unsigned short R);
119 |
120 | // Teletype callback function type - board calls it if symbol ready to transmit
121 | typedef void (CALLBACK* TELETYPECALLBACK)(unsigned char value);
122 |
123 | class CFloppyController;
124 | class CSoundAY;
125 |
126 | //////////////////////////////////////////////////////////////////////
127 |
128 | class CMotherboard // BK computer
129 | {
130 | private: // Devices
131 | CProcessor* m_pCPU; // CPU device
132 | CFloppyController* m_pFloppyCtl; // FDD control
133 | CSoundAY* m_pSoundAY;
134 | private: // Memory
135 | uint16_t m_Configuration; // See BK_COPT_Xxx flag constants
136 | uint8_t m_MemoryMap; // Memory map, every bit defines how 8KB mapped: 0 - RAM, 1 - ROM
137 | uint8_t m_MemoryMapOnOff; // Memory map, every bit defines how 8KB: 0 - deny, 1 - OK
138 | uint8_t* m_pRAM; // RAM, 8 * 16 = 128 KB
139 | uint8_t* m_pROM; // ROM, 4 * 16 = 64 KB
140 | public: // Construct / destruct
141 | CMotherboard();
142 | ~CMotherboard();
143 | public: // Getting devices
144 | CProcessor* GetCPU() { return m_pCPU; }
145 | public: // Memory access //TODO: Make it private
146 | uint16_t GetRAMWord(uint16_t offset) const;
147 | uint16_t GetRAMWord(uint8_t chunk, uint16_t offset) const;
148 | uint8_t GetRAMByte(uint16_t offset) const;
149 | uint8_t GetRAMByte(uint8_t chunk, uint16_t offset) const;
150 | void SetRAMWord(uint16_t offset, uint16_t word);
151 | void SetRAMWord(uint8_t chunk, uint16_t offset, uint16_t word);
152 | void SetRAMByte(uint16_t offset, uint8_t byte);
153 | void SetRAMByte(uint8_t chunk, uint16_t offset, uint8_t byte);
154 | uint16_t GetROMWord(uint16_t offset) const;
155 | uint8_t GetROMByte(uint16_t offset) const;
156 | public: // Debug
157 | void DebugTicks(); // One Debug CPU tick -- use for debug step or debug breakpoint
158 | void SetCPUBreakpoints(const uint16_t* bps) { m_CPUbps = bps; } // Set CPU breakpoint list
159 | uint32_t GetTrace() const { return m_dwTrace; }
160 | void SetTrace(uint32_t dwTrace);
161 | public: // System control
162 | void SetConfiguration(uint16_t conf);
163 | uint16_t GetConfiguration() const { return m_Configuration; }
164 | void Reset(); // Reset computer
165 | void LoadROM(int bank, const uint8_t* pBuffer); // Load 8 KB ROM image from the biffer
166 | void LoadRAM(int startbank, const uint8_t* pBuffer, int length); // Load data into the RAM
167 | void Tick50(); // Tick 50 Hz - goes to CPU EVNT line
168 | void TimerTick(); // Timer Tick, 31250 Hz, 32uS -- dividers are within timer routine
169 | void ResetDevices(); // INIT signal
170 | void SetSoundAY(bool onoff);
171 | public:
172 | void ExecuteCPU(); // Execute one CPU instruction
173 | bool SystemFrame(); // Do one frame -- use for normal run
174 | void KeyboardEvent(uint8_t scancode, bool okPressed, bool okAr2); // Key pressed or released
175 | uint16_t GetKeyboardRegister() const;
176 | uint16_t GetPrinterOutPort() const { return m_Port177714out; }
177 | void SetPrinterInPort(uint8_t data);
178 | bool IsTapeMotorOn() const { return (m_Port177716tap & 0200) == 0; }
179 | int GetSoundChanges() const { return m_SoundChanges; } ///< Sound signal 0 to 1 changes since the beginning of the frame
180 | public: // Floppy
181 | bool AttachFloppyImage(int slot, LPCTSTR sFileName);
182 | void DetachFloppyImage(int slot);
183 | bool IsFloppyImageAttached(int slot) const;
184 | bool IsFloppyReadOnly(int slot) const;
185 | bool IsFloppyEngineOn() const; // Check if the floppy drive engine rotates the disks
186 | public: // Callbacks
187 | void SetTapeReadCallback(TAPEREADCALLBACK callback, int sampleRate);
188 | void SetTapeWriteCallback(TAPEWRITECALLBACK callback, int sampleRate);
189 | void SetSoundGenCallback(SOUNDGENCALLBACK callback);
190 | void SetTeletypeCallback(TELETYPECALLBACK callback);
191 | public: // Memory
192 | // Read command for execution
193 | uint16_t GetWordExec(uint16_t address, bool okHaltMode) { return GetWord(address, okHaltMode, true); }
194 | // Read word from memory
195 | uint16_t GetWord(uint16_t address, bool okHaltMode) { return GetWord(address, okHaltMode, false); }
196 | // Read word
197 | uint16_t GetWord(uint16_t address, bool okHaltMode, bool okExec);
198 | // Write word
199 | void SetWord(uint16_t address, bool okHaltMode, uint16_t word);
200 | // Read byte
201 | uint8_t GetByte(uint16_t address, bool okHaltMode);
202 | // Write byte
203 | void SetByte(uint16_t address, bool okHaltMode, uint8_t byte);
204 | // Read word from memory for debugger
205 | uint16_t GetWordView(uint16_t address, bool okHaltMode, bool okExec, int* pAddrType) const;
206 | // Read word from port for debugger
207 | uint16_t GetPortView(uint16_t address) const;
208 | // Read SEL register
209 | uint16_t GetSelRegister() const { return m_Port177716; }
210 | // Get palette number 0..15 (BK0011 only)
211 | uint8_t GetPalette() const { return (m_Port177662wr >> 8) & 0x0f; }
212 | // Get video buffer address
213 | const uint8_t* GetVideoBuffer() const;
214 | private:
215 | void TapeInput(bool inputBit); // Tape input bit received
216 | private:
217 | // Determine memory type for given address - see ADDRTYPE_Xxx constants
218 | // okHaltMode - processor mode (USER/HALT)
219 | // okExec - true: read instruction for execution; false: read memory
220 | // pOffset - result - offset in memory plane
221 | int TranslateAddress(uint16_t address, bool okHaltMode, bool okExec, uint16_t* pOffset) const;
222 | private: // Access to I/O ports
223 | uint16_t GetPortWord(uint16_t address);
224 | void SetPortWord(uint16_t address, uint16_t word);
225 | uint8_t GetPortByte(uint16_t address);
226 | void SetPortByte(uint16_t address, uint8_t byte);
227 | public: // Saving/loading emulator status
228 | void SaveToImage(uint8_t* pImage);
229 | void LoadFromImage(const uint8_t* pImage);
230 | private: // Ports: implementation
231 | uint16_t m_Port177560; // Serial port input state register
232 | uint16_t m_Port177562; // Serial port input data register
233 | uint16_t m_Port177564; // Serial port output state register
234 | uint16_t m_Port177566; // Serial port output data register
235 | uint16_t m_Port177660; // Keyboard status register
236 | uint16_t m_Port177662rd; // Keyboard register
237 | uint16_t m_Port177662wr; // Palette register
238 | uint16_t m_Port177664; // Scroll register
239 | uint16_t m_Port177714in; // Parallel port, input register
240 | uint16_t m_Port177714out; // Parallel port, output register
241 | uint16_t m_Port177716; // System register (read only)
242 | uint16_t m_Port177716mem; // System register (memory)
243 | uint16_t m_Port177716tap; // System register (tape)
244 | bool m_okSoundAY;
245 | uint8_t m_nSoundAYReg; // AY current register
246 | private: // Timer implementation
247 | uint16_t m_timer;
248 | uint16_t m_timerreload;
249 | uint16_t m_timerflags;
250 | uint16_t m_timerdivider;
251 | void SetTimerReload(uint16_t val); //sets timer reload value
252 | void SetTimerState(uint16_t val); //sets timer state
253 | private:
254 | const uint16_t* m_CPUbps; // CPU breakpoint list, ends with 177777 value
255 | uint32_t m_dwTrace; // Trace flags
256 | int m_SoundPrevValue; // Previous value of the sound signal
257 | int m_SoundChanges; // Sound signal 0 to 1 changes since the beginning of the frame
258 | private:
259 | TAPEREADCALLBACK m_TapeReadCallback;
260 | TAPEWRITECALLBACK m_TapeWriteCallback;
261 | int m_nTapeSampleRate;
262 | SOUNDGENCALLBACK m_SoundGenCallback;
263 | TELETYPECALLBACK m_TeletypeCallback;
264 | private:
265 | void DoSound();
266 | };
267 |
268 |
269 | //////////////////////////////////////////////////////////////////////
270 |
--------------------------------------------------------------------------------
/emulator/emubase/Defines.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Defines.h
12 | // PDP11-like processor defines
13 |
14 | #pragma once
15 |
16 |
17 | //////////////////////////////////////////////////////////////////////
18 |
19 | inline uint8_t GetDigit(uint16_t word, int pos)
20 | {
21 | //return (word >>= pos * 3) % 8;
22 | return static_cast((word >>= ((pos << 1) + pos)) & 7);
23 | }
24 |
25 | // Constants for "pos" argument
26 | #define SRC 2
27 | #define DST 0
28 |
29 |
30 | //////////////////////////////////////////////////////////////////////
31 |
32 | // Process Status Word (PSW) bits
33 | #define PSW_C 1 // Carry
34 | #define PSW_V 2 // Arithmetic overflow
35 | #define PSW_Z 4 // Zero result
36 | #define PSW_N 8 // Negative result
37 | #define PSW_T 16 // Trap/Debug
38 | #define PSW_P 0200 // Priority
39 | #define PSW_HALT 0400 // Halt
40 |
41 | // Commands -- no operands
42 | #define PI_HALT 0000000
43 | #define PI_WAIT 0000001
44 | #define PI_RTI 0000002
45 | #define PI_BPT 0000003
46 | #define PI_IOT 0000004
47 | #define PI_RESET 0000005
48 | #define PI_RTT 0000006
49 | #define PI_MFPT 0000007
50 | #define PI_HALT10 0000010
51 | #define PI_HALT11 0000011
52 | #define PI_HALT12 0000012
53 | #define PI_HALT13 0000013
54 | #define PI_HALT14 0000014
55 | #define PI_HALT15 0000015
56 | #define PI_HALT16 0000016
57 | #define PI_HALT17 0000017
58 | #define PI_NOP 0000240
59 | #define PI_CLC 0000241
60 | #define PI_CLV 0000242
61 | #define PI_CLVC 0000243
62 | #define PI_CLZ 0000244
63 | #define PI_CLZC 0000245
64 | #define PI_CLZV 0000246
65 | #define PI_CLZVC 0000247
66 | #define PI_CLN 0000250
67 | #define PI_CLNC 0000251
68 | #define PI_CLNV 0000252
69 | #define PI_CLNVC 0000253
70 | #define PI_CLNZ 0000254
71 | #define PI_CLNZC 0000255
72 | #define PI_CLNZV 0000256
73 | #define PI_CCC 0000257
74 | #define PI_NOP260 0000260
75 | #define PI_SEC 0000261
76 | #define PI_SEV 0000262
77 | #define PI_SEVC 0000263
78 | #define PI_SEZ 0000264
79 | #define PI_SEZC 0000265
80 | #define PI_SEZV 0000266
81 | #define PI_SEZVC 0000267
82 | #define PI_SEN 0000270
83 | #define PI_SENC 0000271
84 | #define PI_SENV 0000272
85 | #define PI_SENVC 0000273
86 | #define PI_SENZ 0000274
87 | #define PI_SENZC 0000275
88 | #define PI_SENZV 0000276
89 | #define PI_SCC 0000277
90 | #define PI_MED 0076600
91 |
92 | // Commands -- single operand
93 | #define PI_RTS 0000200
94 |
95 | // Commands -- two operands
96 | #define PI_JMP 0000100
97 | #define PI_SWAB 0000300
98 | #define PI_CLR 0005000
99 | #define PI_COM 0005100
100 | #define PI_INC 0005200
101 | #define PI_DEC 0005300
102 | #define PI_NEG 0005400
103 | #define PI_ADC 0005500
104 | #define PI_SBC 0005600
105 | #define PI_TST 0005700
106 | #define PI_ROR 0006000
107 | #define PI_ROL 0006100
108 | #define PI_ASR 0006200
109 | #define PI_ASL 0006300
110 | #define PI_MARK 0006400
111 | #define PI_SXT 0006700
112 | #define PI_MTPS 0106400
113 | #define PI_MFPS 0106700
114 |
115 | // Commands -- branchs
116 | #define PI_BR 0000400
117 | #define PI_BNE 0001000
118 | #define PI_BEQ 0001400
119 | #define PI_BGE 0002000
120 | #define PI_BLT 0002400
121 | #define PI_BGT 0003000
122 | #define PI_BLE 0003400
123 | #define PI_BPL 0100000
124 | #define PI_BMI 0100400
125 | #define PI_BHI 0101000
126 | #define PI_BLOS 0101400
127 | #define PI_BVC 0102000
128 | #define PI_BVS 0102400
129 | #define PI_BHIS 0103000
130 | #define PI_BLO 0103400
131 |
132 | #define PI_EMT 0104000
133 | #define PI_TRAP 0104400
134 |
135 | // Commands -- three operands
136 | #define PI_JSR 0004000
137 | #define PI_MUL 0070000
138 | #define PI_DIV 0071000
139 | #define PI_ASH 0072000
140 | #define PI_ASHC 0073000
141 | #define PI_XOR 0074000
142 | #define PI_SOB 0077000
143 |
144 | // Commands -- four operands
145 | #define PI_MOV 0010000
146 | #define PI_CMP 0020000
147 | #define PI_BIT 0030000
148 | #define PI_BIC 0040000
149 | #define PI_BIS 0050000
150 |
151 | #define PI_ADD 0060000
152 | #define PI_SUB 0160000
153 |
154 | // Commands -- VM2 specifics
155 | #define PI_MUL 0070000
156 | #define PI_DIV 0071000
157 | #define PI_ASH 0072000
158 | #define PI_ASHC 0073000
159 | #define PI_FADD 0075000
160 | #define PI_FSUB 0075010
161 | #define PI_FMUL 0075020
162 | #define PI_FDIV 0075030
163 |
164 |
--------------------------------------------------------------------------------
/emulator/emubase/Emubase.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // Emubase.h Header for use of all emubase classes
12 | //
13 |
14 | #pragma once
15 |
16 | #include "Board.h"
17 | #include "Processor.h"
18 |
19 |
20 | //////////////////////////////////////////////////////////////////////
21 |
22 |
23 | #define SOUNDSAMPLERATE 22050
24 |
25 |
26 | //////////////////////////////////////////////////////////////////////
27 | // Disassembler
28 |
29 | // Disassemble one instruction of KM1801VM2 processor
30 | // pMemory - memory image (we read only words of the instruction)
31 | // sInstr - instruction mnemonics buffer - at least 8 characters
32 | // sArg - instruction arguments buffer - at least 32 characters
33 | // Return value: number of words in the instruction
34 | uint16_t DisassembleInstruction(const uint16_t* pMemory, uint16_t addr, TCHAR* sInstr, TCHAR* sArg);
35 |
36 | bool Disasm_CheckForJump(const uint16_t* memory, int* pDelta);
37 |
38 | // Prepare "Jump Hint" string, and also calculate condition for conditional jump
39 | // Returns: jump prediction flag: true = will jump, false = will not jump
40 | bool Disasm_GetJumpConditionHint(
41 | const uint16_t* memory, const CProcessor * pProc, const CMotherboard * pBoard, LPTSTR buffer);
42 |
43 | // Prepare "Instruction Hint" for a regular instruction (not a branch/jump one)
44 | // buffer, buffer2 - buffers for 1st and 2nd lines of the instruction hint, min size 42
45 | // Returns: number of hint lines; 0 = no hints
46 | int Disasm_GetInstructionHint(
47 | const uint16_t* memory, const CProcessor * pProc, const CMotherboard * pBoard,
48 | LPTSTR buffer, LPTSTR buffer2);
49 |
50 |
51 | //////////////////////////////////////////////////////////////////////
52 | // CFloppy
53 |
54 | #define FLOPPY_FSM_IDLE 0
55 |
56 | #define FLOPPY_CMD_ENGINESTART 020
57 | #define FLOPPY_CMD_SIDEUP 040
58 | #define FLOPPY_CMD_DIR 0100
59 | #define FLOPPY_CMD_STEP 0200
60 | #define FLOPPY_CMD_READDATA 0400
61 | #define FLOPPY_CMD_WRITEMARKER 01000
62 | #define FLOPPY_CMD_PRECORRECTION 02000
63 |
64 | //dir == 0 to center (towards trk0)
65 | //dir == 1 from center (towards trk80)
66 |
67 | #define FLOPPY_STATUS_TRACK0 01
68 | #define FLOPPY_STATUS_RDY 02
69 | #define FLOPPY_STATUS_WRITEPROTECT 04
70 | #define FLOPPY_STATUS_MOREDATA 0200
71 | #define FLOPPY_STATUS_CHECKSUMOK 040000
72 | #define FLOPPY_STATUS_INDEXMARK 0100000
73 |
74 | #define FLOPPY_RAWTRACKSIZE 6250 // Raw track size, bytes
75 | #define FLOPPY_RAWMARKERSIZE (FLOPPY_RAWTRACKSIZE / 2)
76 | #define FLOPPY_INDEXLENGTH 30 // Length of index hole, in bytes of raw track image
77 |
78 | struct CFloppyDrive
79 | {
80 | FILE* fpFile;
81 | bool okReadOnly; // Write protection flag
82 | uint16_t dataptr; // Data offset within m_data - "head" position
83 | uint8_t data[FLOPPY_RAWTRACKSIZE]; // Raw track image for the current track
84 | uint8_t marker[FLOPPY_RAWMARKERSIZE]; // Marker positions
85 | uint16_t datatrack; // Track number of data in m_data array
86 | uint16_t dataside; // Disk side of data in m_data array
87 |
88 | public:
89 | CFloppyDrive();
90 | void Reset();
91 | };
92 |
93 | class CFloppyController
94 | {
95 | protected:
96 | CFloppyDrive m_drivedata[4];
97 | int m_drive; // Drive number: from 0 to 3; -1 if not selected
98 | CFloppyDrive* m_pDrive; // Current drive; nullptr if not selected
99 | uint16_t m_track; // Track number: from 0 to 79
100 | uint16_t m_side; // Disk side: 0 or 1
101 | uint16_t m_status; // See FLOPPY_STATUS_XXX defines
102 | uint16_t m_flags; // See FLOPPY_CMD_XXX defines
103 | uint16_t m_datareg; // Read mode data register
104 | uint16_t m_writereg; // Write mode data register
105 | bool m_writeflag; // Write mode data register has data
106 | bool m_writemarker; // Write marker in m_marker
107 | uint16_t m_shiftreg; // Write mode shift register
108 | bool m_shiftflag; // Write mode shift register has data
109 | bool m_shiftmarker; // Write marker in m_marker
110 | bool m_writing; // TRUE = write mode, false = read mode
111 | bool m_searchsynctrig; // Search for sync trigger
112 | bool m_searchsync; // Read sub-mode: TRUE = search for sync, false = just read
113 | bool m_crccalculus; // TRUE = CRC is calculated now
114 | bool m_trackchanged; // TRUE = m_data was changed - need to save it into the file
115 | bool m_okTrace; // Trace mode on/off
116 |
117 | public:
118 | CFloppyController();
119 | ~CFloppyController();
120 | void Reset();
121 |
122 | public:
123 | bool AttachImage(int drive, LPCTSTR sFileName);
124 | void DetachImage(int drive);
125 | bool IsAttached(int drive) const { return (m_drivedata[drive].fpFile != nullptr); }
126 | bool IsReadOnly(int drive) const { return m_drivedata[drive].okReadOnly; } // return (m_status & FLOPPY_STATUS_WRITEPROTECT) != 0; }
127 | bool IsEngineOn() { return (m_flags & FLOPPY_CMD_ENGINESTART) != 0; }
128 | uint16_t GetData(); // Reading port 177132 - data
129 | uint16_t GetState(); // Reading port 177130 - device status
130 | uint16_t GetDataView() const { return m_datareg; } // Get port 177132 value for debugger
131 | uint16_t GetStateView() const { return m_status; } // Get port 177130 value for debugger
132 | void SetCommand(uint16_t cmd); // Writing to port 177130 - commands
133 | void WriteData(uint16_t Data); // Writing to port 177132 - data
134 | void Periodic(); // Rotate disk; call it each 64 us - 15625 times per second
135 | void SetTrace(bool okTrace) { m_okTrace = okTrace; } // Set trace mode on/off
136 |
137 | private:
138 | void PrepareTrack();
139 | void FlushChanges(); // If current track was changed - save it
140 | };
141 |
142 |
143 | //////////////////////////////////////////////////////////////////////
144 |
145 | class CSoundAY
146 | {
147 | protected:
148 | int index;
149 | int ready;
150 | unsigned Regs[16];
151 | int32_t lastEnable;
152 | int32_t PeriodA, PeriodB, PeriodC, PeriodN, PeriodE;
153 | int32_t CountA, CountB, CountC, CountN, CountE;
154 | uint32_t VolA, VolB, VolC, VolE;
155 | uint8_t EnvelopeA, EnvelopeB, EnvelopeC;
156 | uint8_t OutputA, OutputB, OutputC, OutputN;
157 | int8_t CountEnv;
158 | uint8_t Hold, Alternate, Attack, Holding;
159 | int32_t RNG;
160 | protected:
161 | static unsigned int VolTable[32];
162 |
163 | public:
164 | CSoundAY();
165 | void Reset();
166 |
167 | public:
168 | void SetReg(int r, int v);
169 | void Callback(uint8_t* stream, int length);
170 |
171 | protected:
172 | static void BuildMixerTable();
173 | };
174 |
175 |
176 | //////////////////////////////////////////////////////////////////////
177 |
--------------------------------------------------------------------------------
/emulator/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/emulator/res/BKBTL.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/emulator/res/BKBTL.ico
--------------------------------------------------------------------------------
/emulator/res/BKBTL.rc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/emulator/res/BKBTL.rc
--------------------------------------------------------------------------------
/emulator/res/Keyboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/emulator/res/Keyboard.png
--------------------------------------------------------------------------------
/emulator/res/Keyboard11m.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/emulator/res/Keyboard11m.png
--------------------------------------------------------------------------------
/emulator/res/Toolbar.bmp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/emulator/res/Toolbar.bmp
--------------------------------------------------------------------------------
/emulator/res/resource.h:
--------------------------------------------------------------------------------
1 | //{{NO_DEPENDENCIES}}
2 | // Microsoft Visual C++ generated include file.
3 | // Used by BKBTL.rc
4 | //
5 | #define IDC_MYICON 2
6 | #define IDD_BKBTL_DIALOG 102
7 | #define IDS_APP_TITLE 103
8 | #define IDD_ABOUTBOX 103
9 | #define IDM_ABOUT 104
10 | #define IDM_EXIT 105
11 | #define IDI_APPICON 107
12 | #define IDI_SMALL 108
13 | #define IDC_APPLICATION 109
14 | #define IDR_MAINFRAME 128
15 | #define IDD_INPUTBOX 129
16 | #define IDI_DISKETTE 138
17 | #define IDI_DISKETTEWP 139
18 | #define IDB_KEYBOARD 140
19 | #define IDB_KEYBOARD11M 141
20 | #define IDB_TOOLBAR 142
21 | #define IDD_CREATEDISK 143
22 | #define IDD_LOADBIN 144
23 | #define IDD_SETTINGS 145
24 | #define IDD_SETTINGS_COLORS 146
25 | #define IDD_COMMANDLINEHELP 152
26 | #define IDC_EDIT1 1000
27 | #define IDC_BUILDDATE 1001
28 | #define IDC_EDITADDR 1001
29 | #define IDC_TRACKS40 1002
30 | #define IDC_EDIT2 1002
31 | #define IDC_EDITSIZE 1002
32 | #define IDC_RADIO2 1003
33 | #define IDC_TRACKS80 1003
34 | #define IDC_EDITNAME 1003
35 | #define IDC_BUTTONBROWSE 1004
36 | #define IDC_EDITFILE 1005
37 | #define IDC_VOLUME 1006
38 | #define IDC_BUTTON1 1025
39 | #define IDC_BUTTON2 1026
40 | #define IDC_TREE1 1028
41 | #define IDC_LIST1 1029
42 | #define IDC_DEBUGFONT 1030
43 | #define IDC_SYSLINK1 1032
44 | #define IDC_VERSION 1033
45 | #define IDC_COMBO1 1034
46 | #define ID_FILE 32771
47 | #define ID_FILE_SAVESTATE 32772
48 | #define ID_FILE_LOADSTATE 32773
49 | #define ID_FILE_SCREENSHOT 32774
50 | #define ID_FILE_SAVESCREENSHOTAS 32775
51 | #define ID_FILE_SCREENSHOTTOCLIPBOARD 32776
52 | #define ID_FILE_LOADBIN 32777
53 | #define ID_FILE_CREATEDISK 32778
54 | #define ID_FILE_SETTINGS 32779
55 | #define ID_FILE_SETTINGS_COLORS 32780
56 | #define ID_VIEW 32784
57 | #define ID_VIEW_MEMORY 32785
58 | #define ID_VIEW_KEYBOARD 32786
59 | #define ID_VIEW_TAPE 32787
60 | #define ID_VIEW_TOOLBAR 32788
61 | #define ID_VIEW_RGBSCREEN 32789
62 | #define ID_EMULATOR 32793
63 | #define ID_EMULATOR_RUN 32794
64 | #define ID_EMULATOR_RESET 32795
65 | #define ID_EMULATOR_AUTOSTART 32796
66 | #define ID_EMULATOR_SPEED10 32797
67 | #define ID_EMULATOR_SPEED25 32798
68 | #define ID_EMULATOR_SPEED50 32799
69 | #define ID_EMULATOR_SPEEDMAX 32800
70 | #define ID_EMULATOR_REALSPEED 32801
71 | #define ID_EMULATOR_SPEED200 32802
72 | #define ID_EMULATOR_SPEED400 32803
73 | #define ID_EMULATOR_CONF 32804
74 | #define ID_EMULATOR_FLOPPY0 32805
75 | #define ID_EMULATOR_FLOPPY1 32806
76 | #define ID_EMULATOR_FLOPPY2 32807
77 | #define ID_EMULATOR_FLOPPY3 32808
78 | #define ID_CONF_BK0010MONIT 32812
79 | #define ID_CONF_BK0010BASIC 32813
80 | #define ID_CONF_BK0010FOCAL 32814
81 | #define ID_CONF_BK0010FDD 32815
82 | #define ID_CONF_BK0011 32816
83 | #define ID_CONF_BK0011FDD 32817
84 | #define ID_EMULATOR_JOYSTICKNUMPAD 32820
85 | #define ID_EMULATOR_JOYSTICK1 32821
86 | #define ID_EMULATOR_JOYSTICK2 32822
87 | #define ID_EMULATOR_SOUND 32831
88 | #define ID_EMULATOR_COVOX 32832
89 | #define ID_EMULATOR_SOUNDAY 32833
90 | #define ID_SCREEN 32846
91 | #define ID_VIEW_SCREENMODE0 32847
92 | #define ID_VIEW_SCREENMODE1 32848
93 | #define ID_VIEW_SCREENMODE2 32849
94 | #define ID_VIEW_SCREENMODE3 32850
95 | #define ID_VIEW_SCREENMODE4 32851
96 | #define ID_VIEW_SCREENMODE5 32852
97 | #define ID_VIEW_SCREENMODE6 32853
98 | #define ID_VIEW_SCREENMODE7 32854
99 | #define ID_VIEW_SCREENMODE8 32855
100 | #define ID_VIEW_SCREENMODE9 32856
101 | #define ID_VIEW_SCREENMODE10 32857
102 | #define ID_VIEW_SCREENMODE11 32858
103 | #define ID_VIEW_SCREENMODE12 32859
104 | #define ID_VIEW_SCREENMODE13 32860
105 | #define ID_VIEW_SCREENMODE14 32861
106 | #define ID_VIEW_SCREENMODE15 32862
107 | #define ID_DEBUG 32881
108 | #define ID_VIEW_DEBUG 32882
109 | #define ID_DEBUG_STEPINTO 32883
110 | #define ID_DEBUG_STEPOVER 32884
111 | #define ID_DEBUG_TELETYPE 32885
112 | #define ID_DEBUG_SPRITES 32886
113 | #define ID_VIEW_MEMORYMAP 32887
114 | #define ID_DEBUG_MEMORY_WORDBYTE 32894
115 | #define ID_DEBUG_MEMORY_HEXMODE 32895
116 | #define ID_DEBUG_MEMORY_GOTO 32896
117 | #define ID_DEBUG_CLEARCONSOLE 32897
118 | #define ID_DEBUG_DELETEALLBREAKPTS 32898
119 | #define ID_DEBUG_SUBTITLES 32899
120 | #define ID_DEBUG_COPY_ADDRESS 32900
121 | #define ID_DEBUG_COPY_VALUE 32901
122 | #define ID_DEBUG_GOTO_ADDRESS 32902
123 | #define ID_HELP_COMMAND_LINE_HELP 32921
124 | #define IDC_STATIC -1
125 |
126 | // Next default values for new objects
127 | //
128 | #ifdef APSTUDIO_INVOKED
129 | #ifndef APSTUDIO_READONLY_SYMBOLS
130 | #define _APS_NO_MFC 1
131 | #define _APS_NEXT_RESOURCE_VALUE 153
132 | #define _APS_NEXT_COMMAND_VALUE 32999
133 | #define _APS_NEXT_CONTROL_VALUE 1035
134 | #define _APS_NEXT_SYMED_VALUE 110
135 | #endif
136 | #endif
137 |
--------------------------------------------------------------------------------
/emulator/res/small.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/emulator/res/small.ico
--------------------------------------------------------------------------------
/emulator/stdafx.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // stdafx.cpp : source file that includes just the standard includes
12 | // BKBTL.pch will be the pre-compiled header
13 | // stdafx.obj will contain the pre-compiled type information
14 |
15 | #include "stdafx.h"
16 |
17 | // TODO: reference any additional headers you need in STDAFX.H
18 | // and not in this file
19 |
--------------------------------------------------------------------------------
/emulator/stdafx.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // stdafx.h : include file for standard system include files,
12 | // or project specific include files that are used frequently, but
13 | // are changed infrequently
14 | //
15 |
16 | #pragma once
17 |
18 | //NOTE: I know, we use unsafe string copy functions
19 | #define _CRT_SECURE_NO_WARNINGS
20 |
21 | // NOTE: This trick is needed to bind assembly manifest to the current version of the VC CRT
22 | // See also: http://msdn.microsoft.com/ru-ru/library/cc664727.aspx
23 | #define _BIND_TO_CURRENT_CRT_VERSION 1
24 |
25 | // Modify the following defines if you have to target a platform prior to the ones specified below.
26 | // Refer to MSDN for the latest info on corresponding values for different platforms.
27 | #ifndef WINVER // Allow use of features specific to Windows XP or later.
28 | #define WINVER 0x0501 // Change this to the appropriate value to target other versions of Windows.
29 | #endif
30 |
31 | #ifndef _WIN32_WINNT // Allow use of features specific to Windows XP or later.
32 | #define _WIN32_WINNT 0x0501 // Change this to the appropriate value to target other versions of Windows.
33 | #endif
34 |
35 | #ifndef _WIN32_WINDOWS // Allow use of features specific to Windows 98 or later.
36 | #define _WIN32_WINDOWS 0x0410 // Change this to the appropriate value to target Windows Me or later.
37 | #endif
38 |
39 | #ifndef _WIN32_IE // Allow use of features specific to IE 6.0 or later.
40 | #define _WIN32_IE 0x0600 // Change this to the appropriate value to target other versions of IE.
41 | #endif
42 |
43 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
44 | // Windows Header Files:
45 | #include
46 |
47 | // C RunTime Header Files
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 |
54 | // Define C99 stdint.h types for VS2008
55 | #ifdef _MSC_VER
56 | typedef signed __int8 int8_t;
57 | typedef unsigned __int8 uint8_t;
58 | typedef unsigned __int16 uint16_t;
59 | typedef signed __int32 int32_t;
60 | typedef unsigned __int32 uint32_t;
61 | typedef unsigned __int64 uint64_t;
62 | #else
63 | #include
64 | #include
65 | #endif
66 |
67 | // TODO: reference additional headers your program requires here
68 |
69 | #include "Common.h"
70 |
--------------------------------------------------------------------------------
/emulator/util/BitmapFile.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // BitmapFile.cpp
12 |
13 | #include "stdafx.h"
14 | #include "BitmapFile.h"
15 |
16 | #include
17 | #include
18 | #pragma comment(lib, "WindowsCodecs.lib")
19 |
20 |
21 | //////////////////////////////////////////////////////////////////////
22 | // Globals
23 |
24 | IWICImagingFactory * BitmapFile_pIWICFactory = NULL;
25 |
26 |
27 | void BitmapFile_Init()
28 | {
29 | // Initialize COM
30 | CoInitialize(NULL);
31 |
32 | CoCreateInstance(
33 | CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER,
34 | IID_PPV_ARGS(&BitmapFile_pIWICFactory));
35 | }
36 |
37 | void BitmapFile_Done()
38 | {
39 | BitmapFile_pIWICFactory->Release();
40 | BitmapFile_pIWICFactory = NULL;
41 | }
42 |
43 |
44 | //////////////////////////////////////////////////////////////////////
45 |
46 |
47 | HBITMAP CreateHBITMAP(IWICBitmapSource * ipBitmap)
48 | {
49 | // get image attributes and check for valid image
50 | UINT width = 0;
51 | UINT height = 0;
52 | if (FAILED(ipBitmap->GetSize(&width, &height)) || width == 0 || height == 0)
53 | return NULL;
54 |
55 | // prepare structure giving bitmap information (negative height indicates a top-down DIB)
56 | BITMAPINFO bminfo;
57 | ZeroMemory(&bminfo, sizeof(bminfo));
58 | bminfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
59 | bminfo.bmiHeader.biWidth = width;
60 | bminfo.bmiHeader.biHeight = -((LONG)height);
61 | bminfo.bmiHeader.biPlanes = 1;
62 | bminfo.bmiHeader.biBitCount = 32;
63 | bminfo.bmiHeader.biCompression = BI_RGB;
64 |
65 | // create a DIB section that can hold the image
66 | void * pvImageBits = NULL;
67 | HDC hdcScreen = ::GetDC(NULL);
68 | HBITMAP hbmp = ::CreateDIBSection(hdcScreen, &bminfo, DIB_RGB_COLORS, &pvImageBits, NULL, 0);
69 | ReleaseDC(NULL, hdcScreen);
70 | if (hbmp == NULL)
71 | return NULL;
72 |
73 | // extract the image into the HBITMAP
74 |
75 | const UINT cbStride = width * 4;
76 | const UINT cbImage = cbStride * height;
77 | if (FAILED(ipBitmap->CopyPixels(NULL, cbStride, cbImage, static_cast(pvImageBits))))
78 | {
79 | // couldn't extract image; delete HBITMAP
80 | ::DeleteObject(hbmp);
81 | return NULL;
82 | }
83 |
84 | return hbmp;
85 | }
86 |
87 | HBITMAP BitmapFile_LoadPngFromResource(LPCTSTR lpName)
88 | {
89 | IWICImagingFactory * piFactory = BitmapFile_pIWICFactory;
90 | ASSERT(piFactory != NULL);
91 |
92 | HRESULT hr = NULL;
93 |
94 | // find the resource
95 | HRSRC hrsrc = FindResource(NULL, lpName, _T("IMAGE"));
96 | if (hrsrc == NULL)
97 | return NULL;
98 |
99 | // load the resource
100 | DWORD dwResourceSize = ::SizeofResource(NULL, hrsrc);
101 | HGLOBAL hglbImage = ::LoadResource(NULL, hrsrc);
102 | if (hglbImage == NULL)
103 | return NULL;
104 |
105 | // lock the resource, getting a pointer to its data
106 | LPVOID pvSourceResourceData = ::LockResource(hglbImage);
107 | if (pvSourceResourceData == NULL)
108 | return NULL;
109 |
110 | IWICStream *pIWICStream = NULL;
111 | hr = piFactory->CreateStream(&pIWICStream);
112 | if (hr != S_OK)
113 | return NULL;
114 |
115 | hr = pIWICStream->InitializeFromMemory(reinterpret_cast(pvSourceResourceData), dwResourceSize);
116 | if (hr != S_OK)
117 | return NULL;
118 |
119 | IWICBitmapDecoder *pIDecoder = NULL;
120 | hr = piFactory->CreateDecoderFromStream(pIWICStream, NULL, WICDecodeMetadataCacheOnLoad, &pIDecoder);
121 | if (hr != S_OK)
122 | return NULL;
123 |
124 | IWICBitmapFrameDecode *pIDecoderFrame = NULL;
125 | hr = pIDecoder->GetFrame(0, &pIDecoderFrame);
126 | ::FreeResource(hglbImage);
127 | if (hr != S_OK)
128 | return NULL;
129 |
130 | // convert the image to 32bpp BGRA format with pre-multiplied alpha
131 | // (it may not be stored in that format natively in the PNG resource,
132 | // but we need this format to create the DIB to use on-screen)
133 | IWICBitmapSource * ipBitmap = NULL;
134 | hr = WICConvertBitmapSource(GUID_WICPixelFormat32bppPBGRA, pIDecoderFrame, &ipBitmap);
135 | pIDecoderFrame->Release();
136 | if (hr != S_OK)
137 | return NULL;
138 |
139 | // create a HBITMAP containing the image
140 | HBITMAP hbmp = CreateHBITMAP(ipBitmap);
141 | ipBitmap->Release();
142 | if (hbmp == NULL)
143 | return NULL;
144 |
145 | pIWICStream->Release();
146 | return hbmp;
147 | }
148 |
149 |
150 | //////////////////////////////////////////////////////////////////////
151 |
152 |
153 | bool BitmapFile_SaveImageFile(
154 | const uint32_t* pBits,
155 | LPCTSTR sFileName, BitmapFileFormat format,
156 | int width, int height)
157 | {
158 | ASSERT(pBits != NULL);
159 | ASSERT(sFileName != NULL);
160 |
161 | IWICImagingFactory * piFactory = BitmapFile_pIWICFactory;
162 | ASSERT(piFactory != NULL);
163 |
164 | GUID containerFormatGuid = GUID_ContainerFormatPng;
165 | switch (format)
166 | {
167 | case BitmapFileFormatBmp:
168 | containerFormatGuid = GUID_ContainerFormatBmp; break;
169 | case BitmapFileFormatTiff:
170 | containerFormatGuid = GUID_ContainerFormatTiff; break;
171 | default:
172 | containerFormatGuid = GUID_ContainerFormatPng;
173 | }
174 |
175 | bool result = false;
176 | HRESULT hr = NULL;
177 | IWICStream *piStream = NULL;
178 | IWICBitmapFrameEncode *piBitmapFrame = NULL;
179 | IPropertyBag2 *pPropertyBag = NULL;
180 | WICPixelFormatGUID formatGUID = GUID_WICPixelFormat24bppBGR;
181 |
182 | IWICBitmapEncoder *piEncoder = NULL;
183 | hr = piFactory->CreateEncoder(containerFormatGuid, NULL, &piEncoder);
184 | if (hr != S_OK) goto Cleanup;
185 |
186 | hr = piFactory->CreateStream(&piStream);
187 | if (hr != S_OK) goto Cleanup;
188 |
189 | hr = piStream->InitializeFromFilename(sFileName, GENERIC_WRITE);
190 | if (hr != S_OK) goto Cleanup;
191 |
192 | hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache);
193 | if (hr != S_OK) goto Cleanup;
194 |
195 | hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertyBag);
196 | if (hr != S_OK) goto Cleanup;
197 |
198 | hr = piBitmapFrame->Initialize(pPropertyBag);
199 | if (hr != S_OK) goto Cleanup;
200 |
201 | hr = piBitmapFrame->SetSize(width, height);
202 | if (hr != S_OK) goto Cleanup;
203 |
204 | hr = piBitmapFrame->SetPixelFormat(&formatGUID);
205 | if (hr != S_OK) goto Cleanup;
206 |
207 | hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat24bppBGR) ? S_OK : E_FAIL;
208 | if (hr != S_OK) goto Cleanup;
209 |
210 | // Convert upside-down 32bpp bitmap to normal 24bpp bitmap
211 | UINT cbStride = (width * 24 + 7) / 8;
212 | UINT cbBufferSize = height * cbStride;
213 | BYTE *pbBuffer = new BYTE[cbBufferSize];
214 | for (int line = 0; line < height; line++)
215 | {
216 | const BYTE* pSrc = reinterpret_cast(pBits) + (height - line - 1) * width * 4;
217 | BYTE* pDst = pbBuffer + line * width * 3;
218 | for (int x = 0; x < width; x++)
219 | {
220 | *pDst++ = *pSrc++;
221 | *pDst++ = *pSrc++;
222 | *pDst++ = *pSrc++;
223 | pSrc++;
224 | }
225 | }
226 |
227 | hr = piBitmapFrame->WritePixels(height, cbStride, cbBufferSize, pbBuffer);
228 | delete[] pbBuffer;
229 | if (hr != S_OK) goto Cleanup;
230 |
231 | hr = piBitmapFrame->Commit();
232 | if (hr != S_OK) goto Cleanup;
233 |
234 | hr = piEncoder->Commit();
235 | if (hr != S_OK) goto Cleanup;
236 |
237 | result = true;
238 |
239 | Cleanup:
240 | if (piEncoder != NULL)
241 | piEncoder->Release();
242 | if (piBitmapFrame != NULL)
243 | piBitmapFrame->Release();
244 | if (pPropertyBag != NULL)
245 | pPropertyBag->Release();
246 | if (piStream != NULL)
247 | piStream->Release();
248 |
249 | return result;
250 | }
251 |
252 |
253 | //////////////////////////////////////////////////////////////////////
254 |
--------------------------------------------------------------------------------
/emulator/util/BitmapFile.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // BitmapFile.h
12 |
13 | #pragma once
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 |
18 | void BitmapFile_Init();
19 | void BitmapFile_Done();
20 |
21 | enum BitmapFileFormat
22 | {
23 | BitmapFileFormatBmp = 1,
24 | BitmapFileFormatPng = 2,
25 | BitmapFileFormatTiff = 3,
26 | };
27 |
28 | HBITMAP BitmapFile_LoadPngFromResource(LPCTSTR lpName);
29 |
30 | // Save the image as .PNG file
31 | bool BitmapFile_SaveImageFile(
32 | const uint32_t* pBits,
33 | LPCTSTR sFileName, BitmapFileFormat format,
34 | int screenWidth, int screenHeight);
35 |
36 |
37 | //////////////////////////////////////////////////////////////////////
38 |
--------------------------------------------------------------------------------
/emulator/util/WavPcmFile.cpp:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // WavPcmFile.cpp
12 |
13 | #include "stdafx.h"
14 | #include "WavPcmFile.h"
15 | #include
16 | #include
17 |
18 |
19 | //////////////////////////////////////////////////////////////////////
20 |
21 | // WAV PCM format description: https://ccrma.stanford.edu/courses/422/projects/WaveFormat/
22 |
23 | static const char magic1[4] = { 'R', 'I', 'F', 'F' };
24 | static const char magic2[4] = { 'W', 'A', 'V', 'E' };
25 | static const char format_tag_id[4] = { 'f', 'm', 't', ' ' };
26 | static const char data_tag_id[4] = { 'd', 'a', 't', 'a' };
27 |
28 | const int WAV_FORMAT_PCM = 1;
29 |
30 | struct WAVPCMFILE
31 | {
32 | FILE* fpFile;
33 | int nChannels;
34 | int nBitsPerSample;
35 | int nSampleFrequency;
36 | int nBlockAlign;
37 | uint32_t dwDataOffset;
38 | uint32_t dwDataSize;
39 | uint32_t dwCurrentPosition;
40 | bool okWriting;
41 | };
42 |
43 | int WavPcmFile_GetFrequency(HWAVPCMFILE wavpcmfile)
44 | {
45 | if (wavpcmfile == INVALID_HANDLE_VALUE)
46 | return 0;
47 |
48 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
49 |
50 | return pWavPcm->nSampleFrequency;
51 | }
52 |
53 | uint32_t WavPcmFile_GetLength(HWAVPCMFILE wavpcmfile)
54 | {
55 | if (wavpcmfile == INVALID_HANDLE_VALUE)
56 | return 0;
57 |
58 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
59 |
60 | return pWavPcm->dwDataSize / pWavPcm->nBlockAlign;
61 | }
62 |
63 | uint32_t WavPcmFile_GetPosition(HWAVPCMFILE wavpcmfile)
64 | {
65 | if (wavpcmfile == INVALID_HANDLE_VALUE)
66 | return 0;
67 |
68 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
69 |
70 | return pWavPcm->dwCurrentPosition;
71 | }
72 |
73 | void WavPcmFile_SetPosition(HWAVPCMFILE wavpcmfile, uint32_t position)
74 | {
75 | if (wavpcmfile == INVALID_HANDLE_VALUE)
76 | return;
77 |
78 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
79 |
80 | uint32_t offsetInData = position * pWavPcm->nBlockAlign;
81 | ::fseek(pWavPcm->fpFile, pWavPcm->dwDataOffset + offsetInData, SEEK_SET);
82 |
83 | pWavPcm->dwCurrentPosition = position;
84 | }
85 |
86 | HWAVPCMFILE WavPcmFile_Create(LPCTSTR filename, int sampleRate)
87 | {
88 | const int bitsPerSample = 8;
89 | const int channels = 1;
90 | const int blockAlign = channels * bitsPerSample / 8;
91 |
92 | FILE* fpFileNew = ::_tfsopen(filename, _T("w+b"), _SH_DENYWR);
93 | if (fpFileNew == nullptr)
94 | return static_cast(INVALID_HANDLE_VALUE); // Failed to create file
95 |
96 | // Prepare and write file header
97 | uint8_t consolidated_header[12 + 8 + 16 + 8];
98 | ::memset(consolidated_header, 0, sizeof(consolidated_header));
99 |
100 | memcpy(&consolidated_header[0], magic1, 4); // RIFF
101 | memcpy(&consolidated_header[8], magic2, 4); // WAVE
102 |
103 | memcpy(&consolidated_header[12], format_tag_id, 4); // fmt
104 | *reinterpret_cast(consolidated_header + 16) = 16; // Size of "fmt" chunk
105 | *reinterpret_cast(consolidated_header + 20) = WAV_FORMAT_PCM; // AudioFormat = PCM
106 | *reinterpret_cast(consolidated_header + 22) = channels; // NumChannels = mono
107 | *reinterpret_cast(consolidated_header + 24) = sampleRate; // SampleRate
108 | *reinterpret_cast(consolidated_header + 28) = sampleRate * channels * bitsPerSample / 8; // ByteRate
109 | *reinterpret_cast(consolidated_header + 32) = blockAlign;
110 | *reinterpret_cast(consolidated_header + 34) = bitsPerSample;
111 |
112 | memcpy(&consolidated_header[36], data_tag_id, 4); // data
113 |
114 | // Write consolidated header
115 | uint32_t bytesWritten = ::fwrite(consolidated_header, 1, sizeof(consolidated_header), fpFileNew);
116 | if (bytesWritten != sizeof(consolidated_header))
117 | {
118 | ::fclose(fpFileNew);
119 | return static_cast(INVALID_HANDLE_VALUE); // Failed to write consolidated header
120 | }
121 |
122 | WAVPCMFILE* pWavPcm = static_cast(::calloc(1, sizeof(WAVPCMFILE)));
123 | if (pWavPcm == nullptr)
124 | {
125 | ::fclose(fpFileNew);
126 | return static_cast(INVALID_HANDLE_VALUE); // Failed to allocate memory
127 | }
128 | pWavPcm->fpFile = fpFileNew;
129 | pWavPcm->nChannels = channels;
130 | pWavPcm->nSampleFrequency = sampleRate;
131 | pWavPcm->nBitsPerSample = bitsPerSample;
132 | pWavPcm->nBlockAlign = blockAlign;
133 | pWavPcm->dwDataOffset = sizeof(consolidated_header);
134 | pWavPcm->dwDataSize = 0;
135 | pWavPcm->okWriting = true;
136 |
137 | WavPcmFile_SetPosition(reinterpret_cast(pWavPcm), 0);
138 |
139 | return reinterpret_cast(pWavPcm);
140 | }
141 |
142 | HWAVPCMFILE WavPcmFile_Open(LPCTSTR filename)
143 | {
144 | FILE* fpFileOpen = ::_tfsopen(filename, _T("rb"), _SH_DENYWR);
145 | if (fpFileOpen == nullptr)
146 | return static_cast(INVALID_HANDLE_VALUE); // Failed to open file
147 |
148 | uint32_t offset = 0;
149 | ::fseek(fpFileOpen, 0, SEEK_END);
150 | uint32_t fileSize = ::ftell(fpFileOpen);
151 | ::fseek(fpFileOpen, 0, SEEK_SET);
152 |
153 | uint8_t fileHeader[12];
154 | size_t bytesRead = ::fread(fileHeader, 1, sizeof(fileHeader), fpFileOpen);
155 | if (bytesRead != sizeof(fileHeader) ||
156 | memcmp(&fileHeader[0], magic1, 4) != 0 ||
157 | memcmp(&fileHeader[8], magic2, 4) != 0)
158 | {
159 | ::fclose(fpFileOpen);
160 | return static_cast(INVALID_HANDLE_VALUE); // Failed to read file header OR invalid 'RIFF' tag OR invalid 'WAVE' tag
161 | }
162 | offset += bytesRead;
163 |
164 | uint32_t statedSize = *reinterpret_cast(fileHeader + 4) + 8;
165 | if (statedSize > fileSize)
166 | statedSize = fileSize;
167 |
168 | uint8_t tagHeader[8];
169 | uint16_t formatTag[8];
170 | bool formatSpecified = false;
171 | uint16_t formatType = 1, channels = 1, bitsPerSample = 1, blockAlign = 0;
172 | uint32_t sampleFrequency = 22050, bytesPerSecond, dataOffset = 0, dataSize = 0;
173 | while (offset < statedSize)
174 | {
175 | bytesRead = ::fread(tagHeader, 1, sizeof(tagHeader), fpFileOpen);
176 | if (bytesRead != sizeof(tagHeader))
177 | {
178 | ::fclose(fpFileOpen);
179 | return static_cast(INVALID_HANDLE_VALUE); // Failed to read tag header
180 | }
181 | offset += bytesRead;
182 |
183 | uint32_t tagSize = *reinterpret_cast(tagHeader + 4);
184 | if (!memcmp(tagHeader, format_tag_id, 4))
185 | {
186 | if (formatSpecified || tagSize < sizeof(formatTag))
187 | {
188 | ::fclose(fpFileOpen);
189 | return static_cast(INVALID_HANDLE_VALUE); // Wrong tag header
190 | }
191 | formatSpecified = true;
192 |
193 | bytesRead = ::fread(formatTag, 1, sizeof(formatTag), fpFileOpen);
194 | if (bytesRead != sizeof(formatTag))
195 | {
196 | ::fclose(fpFileOpen);
197 | return static_cast(INVALID_HANDLE_VALUE); // Failed to read format tag
198 | }
199 |
200 | formatType = formatTag[0];
201 | channels = formatTag[1];
202 | sampleFrequency = formatTag[2];
203 | bytesPerSecond = formatTag[4];
204 | blockAlign = formatTag[6];
205 | bitsPerSample = formatTag[7];
206 |
207 | if (formatType != WAV_FORMAT_PCM)
208 | {
209 | ::fclose(fpFileOpen);
210 | return static_cast(INVALID_HANDLE_VALUE); // Unsupported format
211 | }
212 | if (sampleFrequency * bitsPerSample * channels / 8 != bytesPerSecond ||
213 | (bitsPerSample != 8 && bitsPerSample != 16 && bitsPerSample != 32))
214 | {
215 | ::fclose(fpFileOpen);
216 | return static_cast(INVALID_HANDLE_VALUE); // Wrong format tag
217 | }
218 | }
219 | else if (!memcmp(tagHeader, data_tag_id, 4))
220 | {
221 | if (!formatSpecified)
222 | {
223 | ::fclose(fpFileOpen);
224 | return static_cast(INVALID_HANDLE_VALUE); // Wrong tag
225 | }
226 |
227 | dataOffset = offset;
228 | dataSize = tagSize;
229 | }
230 | else // Ignore all other tags
231 | {
232 | }
233 |
234 | offset += tagSize;
235 | ::fseek(fpFileOpen, offset, SEEK_SET);
236 | }
237 |
238 | WAVPCMFILE* pWavPcm = static_cast(::calloc(1, sizeof(WAVPCMFILE)));
239 | if (pWavPcm == nullptr)
240 | {
241 | ::fclose(fpFileOpen);
242 | return static_cast(INVALID_HANDLE_VALUE); // Failed to allocate memory
243 | }
244 | pWavPcm->fpFile = fpFileOpen;
245 | pWavPcm->nChannels = channels;
246 | pWavPcm->nSampleFrequency = sampleFrequency;
247 | pWavPcm->nBitsPerSample = bitsPerSample;
248 | pWavPcm->nBlockAlign = blockAlign;
249 | pWavPcm->dwDataOffset = dataOffset;
250 | pWavPcm->dwDataSize = dataSize;
251 | pWavPcm->okWriting = false;
252 |
253 | WavPcmFile_SetPosition(reinterpret_cast(pWavPcm), 0);
254 |
255 | return reinterpret_cast(pWavPcm);
256 | }
257 |
258 | void WavPcmFile_Close(HWAVPCMFILE wavpcmfile)
259 | {
260 | if (wavpcmfile == INVALID_HANDLE_VALUE)
261 | return;
262 |
263 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
264 |
265 | if (pWavPcm->okWriting)
266 | {
267 | // Write data chunk size
268 | ::fseek(pWavPcm->fpFile, 4, SEEK_SET);
269 | uint32_t chunkSize = 36 + pWavPcm->dwDataSize;
270 | uint32_t bytesWritten = ::fwrite(&chunkSize, 1, 4, pWavPcm->fpFile);
271 | // Write data subchunk size
272 | ::fseek(pWavPcm->fpFile, 40, SEEK_SET);
273 | bytesWritten = ::fwrite(&(pWavPcm->dwDataSize), 1, 4, pWavPcm->fpFile);
274 | }
275 |
276 | ::fclose(pWavPcm->fpFile);
277 | pWavPcm->fpFile = nullptr;
278 | ::free(pWavPcm);
279 | }
280 |
281 | bool WavPcmFile_WriteOne(HWAVPCMFILE wavpcmfile, unsigned int value)
282 | {
283 | if (wavpcmfile == INVALID_HANDLE_VALUE)
284 | return false;
285 |
286 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
287 | if (!pWavPcm->okWriting)
288 | return false;
289 | ASSERT(pWavPcm->nBitsPerSample == 8);
290 | ASSERT(pWavPcm->nChannels == 1);
291 |
292 | uint8_t data = (uint8_t)((value >> 24) & 0xff);
293 |
294 | size_t bytesWritten = ::fwrite(&data, 1, 1, pWavPcm->fpFile);
295 | if (bytesWritten != 1)
296 | return false;
297 |
298 | pWavPcm->dwCurrentPosition++;
299 | pWavPcm->dwDataSize += pWavPcm->nBlockAlign;
300 |
301 | return true;
302 | }
303 |
304 | unsigned int WavPcmFile_ReadOne(HWAVPCMFILE wavpcmfile)
305 | {
306 | if (wavpcmfile == INVALID_HANDLE_VALUE)
307 | return 0;
308 |
309 | WAVPCMFILE* pWavPcm = reinterpret_cast(wavpcmfile);
310 | if (pWavPcm->okWriting)
311 | return 0;
312 |
313 | // Read one sample
314 | uint32_t bytesToRead = pWavPcm->nBlockAlign;
315 | uint8_t data[16];
316 | size_t bytesRead = ::fread(data, 1, bytesToRead, pWavPcm->fpFile);
317 | if (bytesRead != bytesToRead)
318 | return 0;
319 |
320 | pWavPcm->dwCurrentPosition++;
321 |
322 | // Decode first channel
323 | unsigned int value = 0;
324 | switch (pWavPcm->nBitsPerSample)
325 | {
326 | case 8:
327 | value = *data;
328 | value = value << 24;
329 | break;
330 | case 16:
331 | value = *reinterpret_cast(data);
332 | value = value << 16;
333 | break;
334 | case 32:
335 | value = *reinterpret_cast(data);
336 | break;
337 | }
338 |
339 | return value;
340 | }
341 |
342 |
343 | //////////////////////////////////////////////////////////////////////
344 |
--------------------------------------------------------------------------------
/emulator/util/WavPcmFile.h:
--------------------------------------------------------------------------------
1 | /* This file is part of BKBTL.
2 | BKBTL is free software: you can redistribute it and/or modify it under the terms
3 | of the GNU Lesser General Public License as published by the Free Software Foundation,
4 | either version 3 of the License, or (at your option) any later version.
5 | BKBTL is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
6 | without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
7 | See the GNU Lesser General Public License for more details.
8 | You should have received a copy of the GNU Lesser General Public License along with
9 | BKBTL. If not, see . */
10 |
11 | // WavPcmFile.h
12 |
13 | #pragma once
14 |
15 | //////////////////////////////////////////////////////////////////////
16 |
17 | DECLARE_HANDLE(HWAVPCMFILE);
18 |
19 | // Creates WAV file, one-channel, 8 bits per sample
20 | HWAVPCMFILE WavPcmFile_Create(LPCTSTR filename, int sampleRate);
21 | // Prepare WAV file of PCM format for reading
22 | HWAVPCMFILE WavPcmFile_Open(LPCTSTR filename);
23 | // Close WAV file
24 | void WavPcmFile_Close(HWAVPCMFILE wavpcmfile);
25 |
26 | // Samples per second, Hz
27 | int WavPcmFile_GetFrequency(HWAVPCMFILE wavpcmfile);
28 | // Length of the stream, in samples
29 | uint32_t WavPcmFile_GetLength(HWAVPCMFILE wavpcmfile);
30 |
31 | // Current position in the stream, in samples, zero-based
32 | uint32_t WavPcmFile_GetPosition(HWAVPCMFILE wavpcmfile);
33 | // Set current position in the stream, in samples, zero-based
34 | void WavPcmFile_SetPosition(HWAVPCMFILE wavpcmfile, uint32_t position);
35 |
36 | // Read one sample scaled to int type range
37 | unsigned int WavPcmFile_ReadOne(HWAVPCMFILE wavpcmfile);
38 | // Write one sample scaled to int type range
39 | bool WavPcmFile_WriteOne(HWAVPCMFILE wavpcmfile, unsigned int value);
40 |
41 |
42 | //////////////////////////////////////////////////////////////////////
43 |
--------------------------------------------------------------------------------
/roms/b11m_bos.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/b11m_bos.rom
--------------------------------------------------------------------------------
/roms/b11m_ext.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/b11m_ext.rom
--------------------------------------------------------------------------------
/roms/b11m_mstd.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/b11m_mstd.rom
--------------------------------------------------------------------------------
/roms/basic10_1.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/basic10_1.rom
--------------------------------------------------------------------------------
/roms/basic10_2.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/basic10_2.rom
--------------------------------------------------------------------------------
/roms/basic10_3.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/basic10_3.rom
--------------------------------------------------------------------------------
/roms/basic11m_0.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/basic11m_0.rom
--------------------------------------------------------------------------------
/roms/basic11m_1.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/basic11m_1.rom
--------------------------------------------------------------------------------
/roms/disk_253.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/disk_253.rom
--------------------------------------------------------------------------------
/roms/disk_326.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/disk_326.rom
--------------------------------------------------------------------------------
/roms/disk_327.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/disk_327.rom
--------------------------------------------------------------------------------
/roms/focal.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/focal.rom
--------------------------------------------------------------------------------
/roms/monit10.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/monit10.rom
--------------------------------------------------------------------------------
/roms/tests.rom:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/nzeemin/bkbtl/01c755430088bca9c57310c26cb6470acbe32d2a/roms/tests.rom
--------------------------------------------------------------------------------