Compare commits
82 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37589c72ef | ||
|
|
8e62b1c934 | ||
|
|
4280979f87 | ||
|
|
2ec7a9c21e | ||
|
|
221417c0ee | ||
|
|
1d6afc5473 | ||
|
|
d37ad746b1 | ||
|
|
c7c0f708d8 | ||
|
|
8fcf756566 | ||
|
|
cd00346978 | ||
|
|
9fb3a09f05 | ||
|
|
b44faef4ac | ||
|
|
55a82312c4 | ||
|
|
46683a86f6 | ||
|
|
cdda587579 | ||
|
|
ad195d6c20 | ||
|
|
a3d67a4de3 | ||
|
|
1e13490c36 | ||
|
|
c1d8e858aa | ||
|
|
ac50dea14b | ||
|
|
97fa1cc4d1 | ||
|
|
621cac64e3 | ||
|
|
ef1ff8deb9 | ||
|
|
8f51c4712c | ||
|
|
223b0080c8 | ||
|
|
1d20c0ab11 | ||
|
|
fd980059f1 | ||
|
|
b178988fbe | ||
|
|
4a1af785c9 | ||
|
|
f6d0c8d93a | ||
|
|
e837f43f86 | ||
|
|
7e1afab7e3 | ||
|
|
28dbaa8d08 | ||
|
|
4bab10621f | ||
|
|
cc291907c2 | ||
|
|
c3e9d57379 | ||
|
|
cfe0099595 | ||
|
|
e96f36b6de | ||
|
|
12663ba99a | ||
|
|
9673b4694b | ||
|
|
cd3d4bfc47 | ||
|
|
5336cf6272 | ||
|
|
29a2deb1f3 | ||
|
|
05f17740fd | ||
|
|
6e179a5866 | ||
|
|
a6586b3467 | ||
|
|
79e43a98e4 | ||
|
|
9413fc5e27 | ||
|
|
1158daab8b | ||
|
|
6f2bf79917 | ||
|
|
c7c21ce752 | ||
|
|
8b34ba6c26 | ||
|
|
e8171d4705 | ||
|
|
f5c15c741b | ||
|
|
1ac164cbda | ||
|
|
4da1c434cd | ||
|
|
6a1064a852 | ||
|
|
0a0d086f31 | ||
|
|
a09f33fe33 | ||
|
|
b6c4793f44 | ||
|
|
b0ed951235 | ||
|
|
ff80e60879 | ||
|
|
bfd4597afa | ||
|
|
7ffe343e7a | ||
|
|
75bac739ee | ||
|
|
779a22006c | ||
|
|
3d3d6729f6 | ||
|
|
d26bd788cf | ||
|
|
cc9fe51828 | ||
|
|
866dcfa969 | ||
|
|
54a685cdaa | ||
|
|
bcf60e8d96 | ||
|
|
0d6ed068ca | ||
|
|
bc65a7a4f0 | ||
|
|
211b1f86c8 | ||
|
|
8e99ac85ff | ||
|
|
c2ae371bed | ||
|
|
79ac4c42f1 | ||
|
|
02a8b24523 | ||
|
|
735217df00 | ||
|
|
5d3895f08a | ||
|
|
bc118baac8 |
10
.gitignore
vendored
Normal file
10
.gitignore
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
#Temp files
|
||||
/build*
|
||||
cmake-*/
|
||||
sonar/
|
||||
.idea/
|
||||
.scannerwork/
|
||||
venv/
|
||||
|
||||
*~
|
||||
*.swp
|
||||
9
.gitmodules
vendored
Normal file
9
.gitmodules
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
[submodule "external/glfw"]
|
||||
path = external/glfw
|
||||
url = https://github.com/glfw/glfw.git
|
||||
[submodule "external/coveralls-cmake"]
|
||||
path = external/coveralls-cmake
|
||||
url = https://github.com/JoakimSoderberg/coveralls-cmake.git
|
||||
[submodule "external/portaudio"]
|
||||
path = external/portaudio
|
||||
url = https://git.assembla.com/portaudio.git
|
||||
82
.travis.yml
Normal file
82
.travis.yml
Normal file
@ -0,0 +1,82 @@
|
||||
language: c
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- lcov
|
||||
- curl
|
||||
- xorg-dev
|
||||
- libglu1-mesa-dev
|
||||
|
||||
script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake -DUSE_ALLEGRO=OFF -DUSE_PROFILING=OFF -DCOVERALLS=OFF -DCMAKE_BUILD_TYPE=Release ..
|
||||
- cmake --build .
|
||||
|
||||
before_install:
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
|
||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install glew; fi
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- os: linux
|
||||
dist: bionic
|
||||
arch: amd64
|
||||
compiler: gcc
|
||||
|
||||
- os: linux
|
||||
dist: bionic
|
||||
arch: amd64
|
||||
compiler: clang
|
||||
|
||||
- os: linux
|
||||
dist: focal
|
||||
arch: amd64
|
||||
compiler: gcc
|
||||
|
||||
- os: linux
|
||||
dist: focal
|
||||
arch: amd64
|
||||
compiler: clang
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode12.2
|
||||
|
||||
- os: linux
|
||||
dist: focal
|
||||
arch: arm64
|
||||
compiler: gcc
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode10.3
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode11.6
|
||||
|
||||
- os: osx
|
||||
compiler: clang
|
||||
osx_image: xcode12
|
||||
|
||||
- stage: "Coverage"
|
||||
os: linux
|
||||
dist: bionic
|
||||
arch: amd64
|
||||
compiler: gcc
|
||||
script:
|
||||
- mkdir coverage
|
||||
- cd coverage
|
||||
- cmake -DUSE_ALLEGRO=OFF -DUSE_PROFILING=OFF -DCOVERALLS=ON -DCMAKE_BUILD_TYPE=Debug ..
|
||||
- cmake --build .
|
||||
- cmake --build . --target coveralls
|
||||
after_success:
|
||||
- bash <(curl -s https://codecov.io/bash)
|
||||
|
||||
allow_failures:
|
||||
- os: linux
|
||||
arch: arm64
|
||||
|
||||
- os: osx
|
||||
48
CMakeLists.txt
Normal file
48
CMakeLists.txt
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoel TRAPIER.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
cmake_minimum_required (VERSION 2.8)
|
||||
|
||||
project (peTI-NESulator)
|
||||
|
||||
# External cmake modules
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/external/cmake ${CMAKE_MODULE_PATH})
|
||||
|
||||
# Include GLFW
|
||||
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory("external/glfw")
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
include_directories(${OPENGL_INCLUDE_DIR})
|
||||
|
||||
# Include PortAudio
|
||||
set(PA_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
|
||||
set(PA_BUILD_TESTS OFF CACHE BOOL "" FORCE)
|
||||
set(PA_ENABLE_DEBUG_OUTPUT OFF CACHE BOOL "" FORCE)
|
||||
add_subdirectory("external/portaudio")
|
||||
|
||||
if (COVERALLS)
|
||||
enable_testing()
|
||||
endif (COVERALLS)
|
||||
|
||||
# Generate version from Git Tag
|
||||
include(GetGitRevisionDescription)
|
||||
git_describe(VERSION --tags --dirty=-dirty)
|
||||
|
||||
#parse the version information into pieces.
|
||||
string(REGEX REPLACE "^v([0-9]+)\\..*" "\\1" VERSION_MAJOR "${VERSION}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.([0-9]+).*" "\\1" VERSION_MINOR "${VERSION}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" VERSION_MICRO "${VERSION}")
|
||||
string(REGEX REPLACE "^v[0-9]+\\.[0-9]+\\.[0-9]+-(.*)" "\\1" VERSION_SHA1 "${VERSION}")
|
||||
message("-- Building version ${VERSION}")
|
||||
add_compile_options(-DV_MAJOR=${VERSION_MAJOR})
|
||||
add_compile_options(-DV_MINOR=${VERSION_MINOR})
|
||||
add_compile_options(-DV_MICRO=${VERSION_MICRO})
|
||||
add_compile_options(-DV_TEXT="${VERSION_SHA1}")
|
||||
|
||||
add_subdirectory (src)
|
||||
11
LICENSE
Normal file
11
LICENSE
Normal file
@ -0,0 +1,11 @@
|
||||
Copyright (c) 2002-2019 986-Studio / Manoel <godzil> Trapier
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
||||
peTI-NESulator
|
||||
============
|
||||
|
||||
[](https://coveralls.io/github/Godzil/peTI-NESulator?branch=master) [](https://codecov.io/gh/Godzil/peTI-NESulator) [](https://travis-ci.org/Godzil/peTI-NESulator) [](https://www.codacy.com/app/Godzil/peTI-NESulator?utm_source=github.com&utm_medium=referral&utm_content=Godzil/peTI-NESulator&utm_campaign=Badge_Grade)
|
||||
|
||||
This is a cleaned version of the peTI-NESulator repository (all non free data has been removed)
|
||||
|
||||
Some part of the original subversion has been lost because of harddrive crash so the
|
||||
early stage of the project is completely lost. Or I would need to check all the
|
||||
backups arount to recreate part of that history, but that not a fun thing to do to be
|
||||
honest, and there is virtually nothing to gain from that.
|
||||
|
||||
This software is released under a three clauses BSD.
|
||||
|
||||
If you plan to use that project in your projects, I would be glad if you could just send me a message, I love to know where my work is used!
|
||||
BIN
data/bad_apple_2.nes
Normal file
BIN
data/bad_apple_2.nes
Normal file
Binary file not shown.
BIN
data/trollburner_demo.nes
Normal file
BIN
data/trollburner_demo.nes
Normal file
Binary file not shown.
@ -1,3 +1,15 @@
|
||||
25/02/2008: V0.30 part 2
|
||||
- Correct a bug in CPU emulation related with cycle count and the stupid R_FLAG
|
||||
- Correct bugs in PAL emulation where VBlank line count was incorrect.
|
||||
- Correct a bug with VBlank (it occured one line too late)
|
||||
- Correct a bug with cart loading, if the file name was incorrect it crashed instead
|
||||
exiting gently.
|
||||
- All mappers are remerged.
|
||||
- Unix & Windows build are totaly broken...
|
||||
- Sprite are back! There are some bad behaviour, but they will be corrected with next versions.
|
||||
- New SVN repository (the disk where the old one was had crashed...)
|
||||
- Iremh3100 is now active! (finaly)
|
||||
|
||||
05/10/2007 V0.30 part 2 ... In progress ...
|
||||
- Start rewrite of mapper manager. The goal, like for plugin manager, is
|
||||
to allow in the future to have plugins or mapper in external libraries.
|
||||
@ -101,5 +113,5 @@
|
||||
- Premiere version public, ne sert que de démonstration.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
$Id: Changements.txt 29 2007-04-03 14:34:02Z mtrapier $
|
||||
$Id$
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
@ -1,20 +1,32 @@
|
||||
05/10/2007 V0.30 part 2 ... In progress ...
|
||||
- Start rewrite of mapper manager. The goal, like for plugin manager, is
|
||||
to allow in the future to have plugins or mapper in external libraries.
|
||||
- New sound layer using Allegro. Not really accurate, but more portable.
|
||||
A lot of work has to be done on this (especialy because the actual sound
|
||||
is really bad.)
|
||||
- Started a new source organisation. Should be the good one this time !
|
||||
25/02/2008: V0.30 part 2
|
||||
- Correct a bug in CPU emulation related with cycle count and the stupid R_FLAG
|
||||
- Correct bugs in PAL emulation where VBlank line count was incorrect.
|
||||
- Correct a bug with VBlank (it occured one line too late)
|
||||
- Correct a bug with cart loading, if the file name was incorrect it crashed instead
|
||||
exiting gently.
|
||||
- All mappers are remerged.
|
||||
- Unix & Windows build are totaly broken...
|
||||
- Sprite are back! There are some bad behaviour, but they will be corrected with next versions.
|
||||
- New SVN repository (the disk where the old one was had crashed...)
|
||||
- Iremh3100 is now active! (finaly)
|
||||
|
||||
25/10/2007:
|
||||
- Savestate now work correctly (It was not loaded at the right time...)
|
||||
- Mapper manager seems to work correctly ok
|
||||
- [MACOSX] Buils options are better now
|
||||
|
||||
- [MACOSX] Builds options are better now
|
||||
|
||||
- [TODO] Remerge old PPU debug utilities in real plugin form
|
||||
- [TODO] Change the make util. Maybe cmake ?
|
||||
- [TODO] Remerge all mappers with the new manager
|
||||
- [TODO] Rewrite UNIX Makefile for support new src organization.
|
||||
|
||||
05/10/2007:
|
||||
- Start rewrite of mapper manager. The goal, like for plugin manager, is
|
||||
to allow in the future to have plugins or mapper in external libraries.
|
||||
- New sound layer using Allegro. Not really accurate, but more portable.
|
||||
A lot of work has to be done on this (especialy because the actual sound
|
||||
is really bad.)
|
||||
- Started a new source organisation. Should be the good one this time!
|
||||
|
||||
03/05/2007 V0.30 part 1
|
||||
- Started the process of PPU total rewrite.
|
||||
@ -123,5 +135,5 @@
|
||||
- Premiere version public, ne sert que de dŽmonstration.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
$Id: Changes.txt 51 2007-05-22 16:33:04Z mtrapier $
|
||||
$Id$
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
438
doc/LisezMoi.txt
438
doc/LisezMoi.txt
@ -1,233 +1,205 @@
|
||||
<---------------------------------------------------------------------------------->
|
||||
TI-NESulator
|
||||
Version 0.26 beta
|
||||
|
||||
Par Manoël TRAPIER aka Godzil
|
||||
godzil at godzil point net
|
||||
|
||||
1 -> #include <disclamer.h>
|
||||
|
||||
L'utilisation de se logiciel se fait a vos risque et périls. Il s'agit d'une pars
|
||||
d'une version non terminée, et en cours de dévellopement, et la diffusion n'a été
|
||||
faite que pour permettre le teste, et la démonstration de se que sera le logiciel
|
||||
final.
|
||||
|
||||
Je ne peut donc être tenu pour responsable en cas de problème lié a l'utilisation
|
||||
ou posession de se logiciel.
|
||||
|
||||
Vous êtes libre de l'utiliser à partir du moment au se logiciel n'a pas été modifié
|
||||
que sa soit de manière binaire, ou par désassemblage. Si vous trouver une version
|
||||
modifié ou fourni avec des fichiers illégaux, veuillez me le faire savoir. Vous
|
||||
trouverez comment me contacter dans la suite de se fichier.
|
||||
|
||||
Vous êtes libre aussi de le distribuer tant que les fichiers contenus dans le
|
||||
paquetage original sont laissé intouché (les fichiers Changements.txt LisezMoi.txt
|
||||
et TINes.exe)
|
||||
|
||||
Information légales :
|
||||
NES, Famicon, Nintendo Entertainment System, Nintendo sont des marques déposé de
|
||||
Nintendo France, Nintendo of america et Nintendo Company, Ltd.
|
||||
Tout les titres et marques apparaisant dans se fichier texte sont la propriété de
|
||||
leurs auteurs respectifs.
|
||||
|
||||
N'oubliez pas aussi que la posession de ROM (Fichier binaire représentant le
|
||||
contenue d'une cartouche) sans en posseder l'originale (la cartouche) est absolument
|
||||
illégale, que vous la gardiez 24 heures ou seulement 30 secondes
|
||||
|
||||
|
||||
2 -> Qu'est-ce que TI-NESulator ?
|
||||
|
||||
TI-NESulator est un émulateur de la console Nintendo Entertainment System
|
||||
(connunément appelé NES) fabriqué par Nintendo au milieu des année 80. L'originalité
|
||||
de cet emulateur est que sa plateforme de fonctionnement principal est les
|
||||
calculatrices TI-89 et TI-92+ de chez Texas Instrument. Ses calculatrices on la
|
||||
particularité de posseder un microprocesseur 68000 de chez motorola, qui est pour
|
||||
se genre de plateforme relativement puissant et programmer un emulateur, meme de
|
||||
NES, sur ses machine est un véritable défit.
|
||||
Tant au niveau matériel que mémoire, la NES et les TI-68k sont completements
|
||||
différents.
|
||||
La NES utilise une version légérement personalisé du microprocesseur 6502
|
||||
fonctionnant a environ 1.7Mhz.
|
||||
|
||||
Vous avez actuellement une version spéciale (comprendre pas faite pour
|
||||
calculatrices TI.) Cette version ne me sert qu'a mettre en oeuvre de nouvelles
|
||||
choses dans la version TI de l'émulateur (notemment a cause d'un gros manque
|
||||
de debuggueur C dans le monde TI.)
|
||||
|
||||
Cette version est et sera toujours plus avancé que la version TI dans le sens ou
|
||||
elle me sert a expérimenter les nouveaux hardware émulé et a finaliser le hardware
|
||||
deja emuler. Une fois fonctionnant d'un maniere convenable sur le portage Windows,
|
||||
les mises a jours sont faites dans la version TI. Mais la version Windows au final
|
||||
contiendra plus de fonctionnalité que la version TI (support des palletes, de la
|
||||
couleur, voir meme le son etc...)
|
||||
|
||||
|
||||
3 -> Utilisation de TI-NESulator
|
||||
|
||||
[A faire.]
|
||||
|
||||
Version courte :
|
||||
|
||||
C:\TINes\>TINES jeux.nes
|
||||
|
||||
Utilisation du Joystick :
|
||||
|
||||
Manette NES Clavier
|
||||
|
||||
HAUT HAUT
|
||||
BAS BAS
|
||||
GAUCHE GAUCHE
|
||||
DROITE DROITE
|
||||
A W
|
||||
B S
|
||||
START ENTER
|
||||
SELECT P
|
||||
|
||||
--------------------------
|
||||
|
||||
Autres touches :
|
||||
R identique a l'apuis du bouton Reset de la console
|
||||
|
||||
|
||||
1-2 A un effet, mais vous risque de pas le voir ;)
|
||||
3 Affiche les Name Tables
|
||||
4 Affiche les Tables d'attributs (de couleur)
|
||||
5 Affiche les palettes
|
||||
6 Affiche la table des sprites
|
||||
|
||||
--------------------------
|
||||
|
||||
Il faut noter aussi qu'afficher ces tables ralenti considérablement la vitesse de
|
||||
l'émulateur
|
||||
|
||||
4 -> Compatibilité
|
||||
|
||||
TI-NESulator version Win32 est normalement compatible avec tous les Windows (95, 98,
|
||||
Me, NT 4, 2000, XP)
|
||||
TI-NESulator version .X (MacOS X) est normalement compatible toutes version de OS X
|
||||
(.1.x .2.x .3.x)
|
||||
L'émulateur émule actuellement avec les mappers :
|
||||
|
||||
- 0 aucun mapper (Super Mario Bros 1, Donkey Kong, ...)
|
||||
|
||||
- 1 MMC1 (a 99%, Megaman 2, Zelda1 & 2, Final Fantasy 1, ...)
|
||||
|
||||
- 2 UNROM (MegaMan, Final fantasy 2, ...)
|
||||
|
||||
- 3 CNROM
|
||||
|
||||
- 4 *NOUVEAU* MMC3 (Super mario Bross 2 & 3, MegaMan 3 à 6, ...)
|
||||
|
||||
- 7 *NOUVEAU* AOROM (Battletoad, ...)
|
||||
|
||||
Les mappers marqué comme *NOUVEAU* sont ceux qui on été ajouté dans la derniere
|
||||
version disponible. Merci de faire un rapport détaillé si vous rencontrer des
|
||||
problèmes avec.
|
||||
|
||||
|
||||
5 -> A faire
|
||||
|
||||
* Optimisation du coeur de l'émulation du CPU de la NES.
|
||||
|
||||
* Son ?
|
||||
|
||||
* Supprimer les printf et les remplacer par l'affichage dans une console (prochaine
|
||||
maj) pour eviter les soucis sur
|
||||
|
||||
- PC: car la console n'est pas forcement ouverte tout le temps
|
||||
- Unix: pour la meme raison
|
||||
- MacOS: aussi (%))
|
||||
- TI: pasqu'on peut pas avoir les deux en meme temps.
|
||||
|
||||
* Recoder le ppu (gestion de l'affichage)
|
||||
|
||||
6 -> Question Réponses
|
||||
|
||||
Q: Pourquoi le jeu xxx ne fonctionne pas ?
|
||||
R: TI-NESulator est actuellement en cours de dévellopement. Beaucoup de jeux ne
|
||||
sont pas supporté.
|
||||
|
||||
Q: Vous dites que certain de jeux ne sont pas supporté, mais si j'essaye xxx, il
|
||||
marche ! Pourquoi ?
|
||||
R: Ceci est du a une des particularité du Hardware de la NES/Famicon. Le hardware
|
||||
de base de la console est assé limité, et la mémoire est aussi tres limité. pour
|
||||
palier à ses limitations, certains jeux utilise ce qu'on appele des Mappers, qui
|
||||
permettent notemment d'avoir des jeux plus gros, et qui sont implémenté dans la
|
||||
cartouche du jeu. Malheureusement supporter tout ses mappers font grossir
|
||||
l'emulateur, et certain on un fonctionnement qui est malheureusement encore
|
||||
inconnu. N'oubliez pas non plus que TI-NESulator est encore en dévellopement.
|
||||
Certain mapper connu ne sont pas encore implémenté.
|
||||
|
||||
Q: Oui puis-je trouver le jeux xxxx ?
|
||||
R: Désolé, je ne donne aucun lien menant, ni aucune ROM de jeux commerciaux.
|
||||
N'oubliez pas que les personnes vous disant que vous avez le droit de ne garder que
|
||||
24h une ROM, vous raconte absolument n'importe quoi. Il est absolument *ILLEGAL* de
|
||||
posseder la ROM d'un jeu que vous ne possedez pas officiellement.
|
||||
|
||||
Q: XXX donne l'air de fonctionner, pourtant il ne reagis pas au touches
|
||||
R: Cet emulateur n'est pas parfait. Certain jeux/demo demandent un fonctionnement
|
||||
tres proche de celui de la console originale, ce que TI-NESulator est encore loin
|
||||
d'arriver a faire
|
||||
|
||||
Q:J'ai des problèmes graphiques avec XXXX
|
||||
R:Cf réponse-ci dessus
|
||||
|
||||
Q: C'est lent :(
|
||||
R: Désolé. Le code est toujours en cours de devellopement. Si vous trouvez trop lent,
|
||||
attendez la prochaine version une surprise vous y attendra peut-etre !
|
||||
|
||||
7 -> En cas de problème
|
||||
|
||||
a) Un jeu indiqué compatible ne fonctionne pas (ie "Mapper non supporté")
|
||||
|
||||
Alors plusieurs possibilité, soit vous avez une autre version du jeu officielle
|
||||
ou non, cela peut changer par exemple le mapper utilisé par le jeux, soit vous
|
||||
avez recuperer un "bad dump", c'est a dire plus simplement une rom foireuse.
|
||||
|
||||
Dans ces deux cas essayez d'en recuperer une autre version.
|
||||
|
||||
b) TI-NESulator à planté !!
|
||||
Si cela arrive regulierement pour le meme jeu et au meme endroit faites moi un
|
||||
crash report avec les information que TI-NESulator vous met dans la console
|
||||
(pour pouvoir la copier tranquillement il faut lancer a partir d'une console
|
||||
et pas faire glisser la rom sur l'executable)
|
||||
|
||||
N'oubliez pas de préciser le nom complet du jeu, la taille du fichier et toutes
|
||||
les infos que vous trouverez pertinante (manipulation a faire etc...)
|
||||
|
||||
|
||||
8 -> Remerciement
|
||||
|
||||
PpHd pour PreOS, et SMA :)
|
||||
TiMad Membre de la XTeam sans lequel XLib existerait pas.
|
||||
nEUrOO Membre de la XTeam sans lequel XLib existerait pas.
|
||||
|
||||
Loopy, Y0Shi,
|
||||
Marrat Fayzullin,
|
||||
et bcp d'autre pour la documentation technique sur la NES
|
||||
|
||||
Ainsi que tout ceux que j'ai pu oublier
|
||||
|
||||
9 -> Litérature
|
||||
|
||||
[A faire.]
|
||||
|
||||
mais lien rapide :
|
||||
|
||||
http://www.nesdev.org
|
||||
|
||||
10 -> Comment me contacter ?
|
||||
s
|
||||
Vous pouvez me contacter grace au forum yAronet
|
||||
http://www.yaronet.com
|
||||
|
||||
Et surtout grace au lien suivant :
|
||||
http://www.yaronet.com/posts.php?sl=&s=2339
|
||||
|
||||
Vous pouvez aussi me joindre par mail en m'écrivant à "godzil chez godzil point net"
|
||||
Vous pouvez aussi essayer de visiter un de mes sites :
|
||||
http://www.godzil.net
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
$Id: LisezMoi.txt 17 2007-03-27 09:25:23Z mtrapier $
|
||||
--------------------------------------------------------------------------------
|
||||
<------------------------------------------------------------------------------>
|
||||
peTI-NESulator
|
||||
Version 0.30.2 beta
|
||||
|
||||
Par Manoel TRAPIER aka Godzil
|
||||
petines at godzil point net
|
||||
|
||||
1 -> #include <disclamer.h>
|
||||
|
||||
L'utilisation de se logiciel se fait a vos risque et p<>rils. Il s'agit d'une
|
||||
pars d'une version non termin<69>e, et en cours de d<>vellopement, et la diffusion
|
||||
n'a <20>t<EFBFBD> faite que pour permettre le teste, et la d<>monstration de se que sera le
|
||||
logiciel final.
|
||||
|
||||
Je ne peut donc <20>tre tenu pour responsable en cas de probl<62>me li<6C> <20>
|
||||
l'utilisation ou posession de se logiciel.
|
||||
|
||||
Vous <20>tes libre de l'utiliser <20> partir du moment au se logiciel n'a pas <20>t<EFBFBD>
|
||||
modifi<EFBFBD> que sa soit de mani<6E>re binaire, ou par d<>sassemblage. Si vous trouver
|
||||
une version modifi<66> ou fourni avec des fichiers ill<6C>gaux, veuillez me le faire
|
||||
savoir. Vous trouverez comment me contacter dans la suite de se fichier.
|
||||
|
||||
Vous <20>tes libre aussi de le distribuer tant que les fichiers contenus dans le
|
||||
paquetage original sont laiss<73> intouch<63>.
|
||||
|
||||
Information l<>gales :
|
||||
NES, Famicon, Nintendo Entertainment System, Nintendo sont des marques d<>pos<6F> de
|
||||
Nintendo France, Nintendo of america et Nintendo Company, Ltd.
|
||||
Tout les titres et marques apparaisant dans se fichier texte sont la propri<72>t<EFBFBD>
|
||||
de leurs auteurs respectifs.
|
||||
|
||||
N'oubliez pas aussi que la posession de ROM (Fichier binaire repr<70>sentant le
|
||||
contenue d'une cartouche) sans en posseder l'originale (la cartouche) est
|
||||
absolument ill<6C>gale, que vous la gardiez 24 heures ou seulement 30 secondes
|
||||
|
||||
|
||||
2 -> Qu'est-ce que peTI-NESulator ?
|
||||
|
||||
peTI-NESulator est un <20>mulateur de la console Nintendo Entertainment System
|
||||
(connun<75>ment appel<65> NES) fabriqu<71> par Nintendo au milieu des ann<6E>e 80.
|
||||
L'originalit<69> de cet emulateur est que sa plateforme de fonctionnement principal
|
||||
est les calculatrices TI-89 et TI-92+ de chez Texas Instrument. Ses
|
||||
calculatrices on la particularit<69> de posseder un microprocesseur 68000 de chez
|
||||
motorola, qui est pour se genre de plateforme relativement puissant et
|
||||
programmer un emulateur, meme de NES, sur ses machine est un v<>ritable d<>fit
|
||||
tant au niveau mat<61>riel que m<>moire, la NES et les TI-68k sont completements
|
||||
diff<EFBFBD>rents.
|
||||
La NES utilise une version l<>g<EFBFBD>rement personalis<69> du microprocesseur 6502
|
||||
fonctionnant <20> environ 1.7Mhz.
|
||||
|
||||
Vous avez actuellement une version sp<73>ciale (comprendre pas faite pour
|
||||
calculatrices TI.) Cette version ne me sert qu'a mettre en oeuvre de nouvelles
|
||||
choses dans la version TI de l'<27>mulateur (notemment a cause d'un gros manque
|
||||
de debuggueur C dans le monde TI.)
|
||||
|
||||
Cette version est et sera toujours plus avanc<6E> que la version TI dans le sens ou
|
||||
elle me sert a exp<78>rimenter les nouveaux hardware <20>mul<75> et a finaliser le
|
||||
hardware deja emuler. Une fois fonctionnant d'un maniere convenable sur le
|
||||
portage Windows, les mises a jours sont faites dans la version TI. Mais la
|
||||
version Windows au final contiendra plus de fonctionnalit<69> que la version TI
|
||||
(support des palletes, de la couleur, voir meme le son etc...)
|
||||
|
||||
|
||||
3 -> Utilisation de peTI-NESulator
|
||||
|
||||
[A faire.]
|
||||
|
||||
Version courte :
|
||||
|
||||
C:\TINes\>TINES jeux.nes
|
||||
|
||||
Utilisation du Joystick :
|
||||
|
||||
Manette NES Clavier
|
||||
|
||||
HAUT HAUT
|
||||
BAS BAS
|
||||
GAUCHE GAUCHE
|
||||
DROITE DROITE
|
||||
A W
|
||||
B S
|
||||
START ENTER
|
||||
SELECT P
|
||||
|
||||
--------------------------
|
||||
|
||||
Autres touches :
|
||||
R identique <20> l'apuis du bouton Reset de la console
|
||||
|
||||
|
||||
1-2 A un effet, mais vous risque de pas le voir ;)
|
||||
3 Affiche les Name Tables
|
||||
4 Affiche les Tables d'attributs (de couleur)
|
||||
5 Affiche les palettes
|
||||
6 Affiche la table des sprites
|
||||
|
||||
--------------------------
|
||||
|
||||
Il faut noter aussi qu'afficher ces tables ralentisent consid<69>rablement la
|
||||
vitesse de l'<27>mulateur
|
||||
|
||||
4 -> Compatibilit<69>
|
||||
|
||||
peTI-NESulator version Win32 est normalement compatible avec tous les Windows
|
||||
(95, 98,Me, NT 4, 2000, XP)
|
||||
peTI-NESulator version .X (MacOS X) est normalement compatible toutes version
|
||||
de OS X (.1.x .2.x .3.x)
|
||||
|
||||
L'<27>mulateur <20>mule actuellement avec les mappers :
|
||||
|
||||
- 0 aucun mapper (Super Mario Bros 1, Donkey Kong, ...)
|
||||
- 1 MMC1 (a 99%, Megaman 2, Zelda1 & 2, Final Fantasy 1, ...)
|
||||
- 2 UNROM (MegaMan, Final fantasy 2, ...)
|
||||
- 3 CNROM
|
||||
- 4 MMC3 (Super mario Bross 2 & 3, MegaMan 3 <20> 6, ...)
|
||||
- 7 AOROM (Battletoad, ...)
|
||||
|
||||
Les mappers marqu<71> comme *NOUVEAU* sont ceux qui on <20>t<EFBFBD> ajout<75> dans la derniere
|
||||
version disponible. Merci de faire un rapport d<>taill<6C> si vous rencontrer des
|
||||
probl<EFBFBD>mes avec.
|
||||
|
||||
5 -> Question R<>ponses
|
||||
|
||||
Q: Pourquoi le jeu xxx ne fonctionne pas ?
|
||||
R: peTI-NESulator est actuellement en cours de d<>vellopement. Beaucoup de jeux ne
|
||||
sont pas support<72>.
|
||||
|
||||
Q: Vous dites que certain de jeux ne sont pas support<72>, mais si j'essaye xxx, il
|
||||
marche ! Pourquoi ?
|
||||
R: Ceci est du a une des particularit<69> du Hardware de la NES/Famicon. Le
|
||||
hardware de base de la console est ass<73> limit<69>, et la m<>moire est aussi tres
|
||||
limit<EFBFBD>. pour palier <20> ses limitations, certains jeux utilise ce qu'on appele des
|
||||
Mappers, qui permettent notemment d'avoir des jeux plus gros, et qui sont
|
||||
impl<EFBFBD>ment<EFBFBD> dans la cartouche du jeu. Malheureusement supporter tout ses mappers
|
||||
font grossir l'emulateur, et certain on un fonctionnement qui est
|
||||
malheureusement encore inconnu. N'oubliez pas non plus que peTI-NESulator est
|
||||
encore en d<>vellopement. Certain mapper connu ne sont pas encore impl<70>ment<6E>.
|
||||
|
||||
Q: Oui puis-je trouver le jeux xxxx ?
|
||||
R: D<>sol<6F>, je ne donne aucun lien menant, ni aucune ROM de jeux commerciaux.
|
||||
N'oubliez pas que les personnes vous disant que vous avez le droit de ne garder
|
||||
que 24h une ROM, vous raconte absolument n'importe quoi. Il est absolument
|
||||
*ILLEGAL* de posseder la ROM d'un jeu que vous ne possedez pas officiellement.
|
||||
|
||||
Q: XXX donne l'air de fonctionner, pourtant il ne reagis pas au touches
|
||||
R: Cet emulateur n'est pas parfait. Certain jeux/demo demandent un
|
||||
fonctionnement tres proche de celui de la console originale, ce que peTI-NESulator
|
||||
est encore loin d'arriver a faire.
|
||||
|
||||
Q: J'ai des probl<62>mes graphiques avec XXXX
|
||||
R: Cf r<>ponse-ci dessus
|
||||
|
||||
Q: C'est lent :(
|
||||
R: D<>sol<6F>. Le code est toujours en cours de devellopement. Si vous trouvez trop
|
||||
lent, attendez la prochaine version une surprise vous y attendra peut-etre !
|
||||
|
||||
7 -> En cas de probl<62>me
|
||||
|
||||
a) Un jeu indiqu<71> compatible ne fonctionne pas (ie "Mapper non support<72>")
|
||||
|
||||
Alors plusieurs possibilit<69>, soit vous avez une autre version du jeu officielle
|
||||
ou non, cela peut changer par exemple le mapper utilis<69> par le jeux, soit vous
|
||||
avez recuperer un "bad dump", c'est a dire plus simplement une rom foireuse.
|
||||
|
||||
Dans ces deux cas essayez d'en recuperer une autre version.
|
||||
|
||||
b) peTI-NESulator <20> plant<6E> !!
|
||||
Si cela arrive regulierement pour le meme jeu et au meme endroit faites moi un
|
||||
crash report avec les information que peTI-NESulator vous met dans la console
|
||||
(pour pouvoir la copier tranquillement il faut lancer a partir d'une console
|
||||
et pas faire glisser la rom sur l'executable)
|
||||
|
||||
N'oubliez pas de pr<70>ciser le nom complet du jeu, la taille du fichier et toutes
|
||||
les infos que vous trouverez pertinante (manipulation a faire etc...)
|
||||
|
||||
8 -> Remerciement
|
||||
|
||||
Loopy, Y0Shi, Marrat Fayzullin, et bcp d'autre pour la documentation technique
|
||||
sur la NES
|
||||
|
||||
Ainsi que tout ceux que j'ai pu oublier
|
||||
|
||||
9 -> Lit<69>rature
|
||||
|
||||
[A faire.]
|
||||
|
||||
mais lien rapide :
|
||||
|
||||
http://nesdev.parodius.com/
|
||||
http://nesdevwiki.org/
|
||||
|
||||
|
||||
10 -> Comment me contacter ?
|
||||
|
||||
Vous pouvez me contacter grace au forum yAronet: http://www.yaronet.com
|
||||
|
||||
Et surtout grace au lien suivant : http://www.yaronet.com/posts.php?sl=&s=2339
|
||||
|
||||
Vous pouvez aussi me joindre par mail en m'<27>crivant <20>
|
||||
"petines chez godzil point net"
|
||||
Vous pouvez aussi essayer de visiter mon site : http://www.godzil.net
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
$Id$
|
||||
--------------------------------------------------------------------------------
|
||||
14
doc/TODO.txt
14
doc/TODO.txt
@ -1,7 +1,15 @@
|
||||
07/10/2007 V0.30 part 2
|
||||
25/02/2008
|
||||
- Finish th Quick6502 C project to merge it into peTI-NESulator [ ]
|
||||
- Extract graphic primitive to be less dependent of Allegro [ ]
|
||||
- Rewrite sound engine [ ]
|
||||
|
||||
07/10/2007
|
||||
- Remerge old PPU debug utilities in real plugin form [ ]
|
||||
- Change the make util for UNIX. Maybe cmake ? [ ]
|
||||
- Cleanup os/win32 folder [ ]
|
||||
- Thinks about a better svn repository (Maybe a dedibox is a good choice?)
|
||||
[ ]
|
||||
|
||||
[X]
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
$Id$
|
||||
--------------------------------------------------------------------------------
|
||||
168
external/cmake/GetGitRevisionDescription.cmake
vendored
Normal file
168
external/cmake/GetGitRevisionDescription.cmake
vendored
Normal file
@ -0,0 +1,168 @@
|
||||
# - Returns a version string from Git
|
||||
#
|
||||
# These functions force a re-configure on each git commit so that you can
|
||||
# trust the values of the variables in your build system.
|
||||
#
|
||||
# get_git_head_revision(<refspecvar> <hashvar> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the refspec and sha hash of the current head revision
|
||||
#
|
||||
# git_describe(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe on the source tree, and adjusting
|
||||
# the output so that it tests false if an error occurs.
|
||||
#
|
||||
# git_get_exact_tag(<var> [<additional arguments to git describe> ...])
|
||||
#
|
||||
# Returns the results of git describe --exact-match on the source tree,
|
||||
# and adjusting the output so that it tests false if there was no exact
|
||||
# matching tag.
|
||||
#
|
||||
# git_local_changes(<var>)
|
||||
#
|
||||
# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes.
|
||||
# Uses the return code of "git diff-index --quiet HEAD --".
|
||||
# Does not regard untracked files.
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
if(__get_git_revision_description)
|
||||
return()
|
||||
endif()
|
||||
set(__get_git_revision_description YES)
|
||||
|
||||
# We must run the following at "include" time, not at function call time,
|
||||
# to find the path to this module rather than the path to a calling list file
|
||||
get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH)
|
||||
|
||||
function(get_git_head_revision _refspecvar _hashvar)
|
||||
set(GIT_PARENT_DIR "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories
|
||||
set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}")
|
||||
get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH)
|
||||
if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT)
|
||||
# We have reached the root directory, we are not in git
|
||||
set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
set(GIT_DIR "${GIT_PARENT_DIR}/.git")
|
||||
endwhile()
|
||||
# check if this is a submodule
|
||||
if(NOT IS_DIRECTORY ${GIT_DIR})
|
||||
file(READ ${GIT_DIR} submodule)
|
||||
string(REGEX REPLACE "gitdir: (.*)\n$" "\\1" GIT_DIR_RELATIVE ${submodule})
|
||||
get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH)
|
||||
get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} ABSOLUTE)
|
||||
endif()
|
||||
set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data")
|
||||
if(NOT EXISTS "${GIT_DATA}")
|
||||
file(MAKE_DIRECTORY "${GIT_DATA}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS "${GIT_DIR}/HEAD")
|
||||
return()
|
||||
endif()
|
||||
set(HEAD_FILE "${GIT_DATA}/HEAD")
|
||||
configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY)
|
||||
|
||||
configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in"
|
||||
"${GIT_DATA}/grabRef.cmake"
|
||||
@ONLY)
|
||||
include("${GIT_DATA}/grabRef.cmake")
|
||||
|
||||
set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE)
|
||||
set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_describe _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# TODO sanitize
|
||||
#if((${ARGN}" MATCHES "&&") OR
|
||||
# (ARGN MATCHES "||") OR
|
||||
# (ARGN MATCHES "\\;"))
|
||||
# message("Please report the following error to the project!")
|
||||
# message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}")
|
||||
#endif()
|
||||
|
||||
#message(STATUS "Arguments to execute_process: ${ARGN}")
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
describe
|
||||
#${hash}
|
||||
${ARGN}
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(NOT res EQUAL 0)
|
||||
set(out "${out}-${res}-NOTFOUND")
|
||||
endif()
|
||||
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_get_exact_tag _var)
|
||||
git_describe(out --exact-match ${ARGN})
|
||||
set(${_var} "${out}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(git_local_changes _var)
|
||||
if(NOT GIT_FOUND)
|
||||
find_package(Git QUIET)
|
||||
endif()
|
||||
get_git_head_revision(refspec hash)
|
||||
if(NOT GIT_FOUND)
|
||||
set(${_var} "GIT-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
if(NOT hash)
|
||||
set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE)
|
||||
return()
|
||||
endif()
|
||||
|
||||
execute_process(COMMAND
|
||||
"${GIT_EXECUTABLE}"
|
||||
diff-index --quiet HEAD --
|
||||
WORKING_DIRECTORY
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE
|
||||
res
|
||||
OUTPUT_VARIABLE
|
||||
out
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if(res EQUAL 0)
|
||||
set(${_var} "CLEAN" PARENT_SCOPE)
|
||||
else()
|
||||
set(${_var} "DIRTY" PARENT_SCOPE)
|
||||
endif()
|
||||
endfunction()
|
||||
41
external/cmake/GetGitRevisionDescription.cmake.in
vendored
Normal file
41
external/cmake/GetGitRevisionDescription.cmake.in
vendored
Normal file
@ -0,0 +1,41 @@
|
||||
#
|
||||
# Internal file for GetGitRevisionDescription.cmake
|
||||
#
|
||||
# Requires CMake 2.6 or newer (uses the 'function' command)
|
||||
#
|
||||
# Original Author:
|
||||
# 2009-2010 Ryan Pavlik <rpavlik@iastate.edu> <abiryan@ryand.net>
|
||||
# http://academic.cleardefinition.com
|
||||
# Iowa State University HCI Graduate Program/VRAC
|
||||
#
|
||||
# Copyright Iowa State University 2009-2010.
|
||||
# Distributed under the Boost Software License, Version 1.0.
|
||||
# (See accompanying file LICENSE_1_0.txt or copy at
|
||||
# http://www.boost.org/LICENSE_1_0.txt)
|
||||
|
||||
set(HEAD_HASH)
|
||||
|
||||
file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024)
|
||||
|
||||
string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS)
|
||||
if(HEAD_CONTENTS MATCHES "ref")
|
||||
# named branch
|
||||
string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}")
|
||||
if(EXISTS "@GIT_DIR@/${HEAD_REF}")
|
||||
configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
else()
|
||||
configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY)
|
||||
file(READ "@GIT_DATA@/packed-refs" PACKED_REFS)
|
||||
if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}")
|
||||
set(HEAD_HASH "${CMAKE_MATCH_1}")
|
||||
endif()
|
||||
endif()
|
||||
else()
|
||||
# detached HEAD
|
||||
configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY)
|
||||
endif()
|
||||
|
||||
if(NOT HEAD_HASH)
|
||||
file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024)
|
||||
string(STRIP "${HEAD_HASH}" HEAD_HASH)
|
||||
endif()
|
||||
1
external/coveralls-cmake
vendored
Submodule
1
external/coveralls-cmake
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit e37d5b8674dab235185b07ad9208c88d84f81823
|
||||
1
external/glfw
vendored
Submodule
1
external/glfw
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 525ad7bfb8884b7cf497bc8e6ebf743df0dada8c
|
||||
1
external/portaudio
vendored
Submodule
1
external/portaudio
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 1bdcb9e41357ec76d8cf73f9ef278202a3ea1e3b
|
||||
6
sonar-project.properties
Normal file
6
sonar-project.properties
Normal file
@ -0,0 +1,6 @@
|
||||
sonar.projectKey=peTI-NESulator
|
||||
sonar.projectName=peTI-NESulator
|
||||
sonar.projectVersion=git-edition
|
||||
sonar.sources=src
|
||||
|
||||
sonar.cfamily.build-wrapper-output=sonar/bw-output
|
||||
109
src/CMakeLists.txt
Normal file
109
src/CMakeLists.txt
Normal file
@ -0,0 +1,109 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
##########################
|
||||
# Configurations variables
|
||||
##########################
|
||||
set(PPU_ISPAL OFF CACHE BOOL "When switch to ON the PPU is in PAL mode, else it will act as a NTSC one.")
|
||||
set(Q6502_DEBUGGER OFF CACHE BOOL "Activate the Quick6502 debugger?")
|
||||
set(USE_SOUND OFF CACHE BOOL "Activate the sound?")
|
||||
set(DETECT_BUS_CONFLICT OFF CACHE BOOL "Activate the bus conflit detector? (Could slow down the emulator a lot.)")
|
||||
|
||||
set(USE_EFENCE OFF CACHE BOOL "Use electricfence memory debugger?")
|
||||
set(USE_PROFILING OFF CACHE BOOL "Use profiling tools? (Will slow down a lot.)")
|
||||
|
||||
set(USE_ALLEGRO ON CACHE BOOL "Use Allegro backend")
|
||||
|
||||
option(COVERALLS "Generate coveralls data" OFF)
|
||||
|
||||
option(WARN_AS_ERROR "Enable warning as error" OFF)
|
||||
|
||||
##########################
|
||||
# Link & Compile flags
|
||||
##########################
|
||||
|
||||
set(COMP_FLAGS "-march=native -Wall -Wextra -Wno-unused-parameter -Wno-unused-result -Wno-write-strings ${PLATFORM_FLAGS}")
|
||||
if (WARN_AS_ERROR)
|
||||
set(COMP_FLAGS "${COMP_FLAGS} -Werror")
|
||||
endif()
|
||||
|
||||
set(CMAKE_C_FLAGS ${COMP_FLAGS})
|
||||
set(CMAKE_CXX_FLAGS ${COMP_FLAGS})
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/external/coveralls-cmake/cmake)
|
||||
|
||||
add_executable(petines main.c paddle.c NESCarts.c)
|
||||
|
||||
add_definitions(-DNO_DECIMAL)
|
||||
|
||||
if (PPU_ISPAL)
|
||||
add_definitions(-DISPAL)
|
||||
else (PPU_ISPAL)
|
||||
add_definitions(-DISNTSC)
|
||||
endif (PPU_ISPAL)
|
||||
|
||||
if (Q6502_DEBUGGER)
|
||||
add_definitions(-DDEBUG)
|
||||
endif (Q6502_DEBUGGER)
|
||||
|
||||
if (USE_SOUND)
|
||||
add_definitions(-DUSE_SOUND)
|
||||
endif (USE_SOUND)
|
||||
|
||||
if (DETECT_BUS_CONFLICT)
|
||||
add_definitions(-DDETECT_BUS_CONFLICT)
|
||||
endif (DETECT_BUS_CONFLICT)
|
||||
|
||||
if (USE_PROFILING)
|
||||
if (CMAKE_BUILD_TYPE MATCHES Rel)
|
||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING "Debug info is forced" FORCE)
|
||||
else (CMAKE_BUILD_TYPE MATCHES Rel)
|
||||
SET(CMAKE_BUILD_TYPE Debug CACHE STRING "Debug info is forced" FORCE)
|
||||
endif (CMAKE_BUILD_TYPE MATCHES Rel)
|
||||
|
||||
set(CMAKE_C_FLAGS -pg)
|
||||
endif (USE_PROFILING)
|
||||
|
||||
if (COVERALLS)
|
||||
add_definitions(-DRUN_COVERAGE)
|
||||
include(Coveralls)
|
||||
coveralls_turn_on_coverage()
|
||||
endif ()
|
||||
|
||||
include_directories(include)
|
||||
|
||||
add_subdirectory(apu)
|
||||
add_subdirectory(corecpu)
|
||||
add_subdirectory(mappersmanager)
|
||||
add_subdirectory(memorymanager)
|
||||
add_subdirectory(pluginsmanager)
|
||||
add_subdirectory(ppu)
|
||||
|
||||
|
||||
if (TARGET_TI68k)
|
||||
add_subdirectory(os/ti68k)
|
||||
elseif (WIN32)
|
||||
add_subdirectory(os/win32)
|
||||
else (TARGET_TI68k)
|
||||
add_subdirectory(os/unix)
|
||||
endif (TARGET_TI68k)
|
||||
|
||||
#find_library(PTHREADLIB pthread)
|
||||
|
||||
if (COVERALLS)
|
||||
set(COVERAGE_SRCS src/main.c src/paddle.c src/NESCarts.c ${COVERAGE_SRCS})
|
||||
|
||||
# Create the coveralls target.
|
||||
coveralls_setup(
|
||||
"${COVERAGE_SRCS}" # The source files.
|
||||
ON # If we should upload.
|
||||
) # (Optional) Alternate project cmake module path.
|
||||
endif ()
|
||||
|
||||
target_link_libraries(petines apu corecpu mappermanager memorymanager pluginsmanager ppu oslib)# ${PTHREADLIB})
|
||||
|
||||
add_test(NAME petines_test_1 COMMAND $<TARGET_FILE:petines> ${PROJECT_SOURCE_DIR}/data/bad_apple_2.nes)
|
||||
add_test(NAME petines_test_2 COMMAND $<TARGET_FILE:petines> ${PROJECT_SOURCE_DIR}/data/trollburner_demo.nes)
|
||||
155
src/NESCarts.c
155
src/NESCarts.c
@ -1,112 +1,119 @@
|
||||
/*
|
||||
* Cart manager - The TI-NESulator Project
|
||||
* Cart manager - The peTI-NESulator Project
|
||||
* NESCart.c
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/NESCarts.c $
|
||||
* $Revision: 50 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "include/NESCarts.h"
|
||||
#include "include/mappers/manager.h"
|
||||
|
||||
/* System Headers */
|
||||
#if !defined(__TIGCC__) && !defined(__GCC4TI__) && !defined(__GTC__)
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <memory.h>
|
||||
|
||||
/* Plateform dependent function */
|
||||
void *LoadFilePtr(char * filename);
|
||||
#else /* Support for TI-68k compilation */
|
||||
|
||||
void DumpCartProperties(FILE *out, NesCart * cart)
|
||||
#define TIGCC_COMPAT
|
||||
#include <tigcclib.h>
|
||||
#endif
|
||||
|
||||
/* peTI-NESulator headers */
|
||||
#include <os_dependent.h>
|
||||
#include <NESCarts.h>
|
||||
#include <os_dependent.h>
|
||||
#include <mappers/manager.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
void DumpCartProperties(FILE *out, NesCart *cart)
|
||||
{
|
||||
fprintf(out,
|
||||
"'%s' informations:\n"
|
||||
" Total ROM Size : 0x%06X | Total VROM Size : 0x%06X\n"
|
||||
" Mapper ID : 0x%06X | Mirroring ? : %s\n"
|
||||
" Battery ? : %s | 4 Screen ? : %s \n"
|
||||
" PROMBanks start at : %p |\n"
|
||||
" VROMBanks start at : %p |\n",
|
||||
cart->FileName,
|
||||
cart->PROMSize,
|
||||
cart->VROMSize,
|
||||
cart->MapperID,
|
||||
cart->Flags & iNES_MIRROR? "Horizontal" : "Vertical",
|
||||
cart->Flags & iNES_BATTERY? "Yes": "No ",
|
||||
cart->Flags & iNES_4SCREEN? "Yes": "No ",
|
||||
cart->PROMBanks,
|
||||
cart->VROMBanks);
|
||||
console_printf(Console_Verbose,
|
||||
"'%s' informations:\n"
|
||||
" Total ROM Size : 0x%06lX | Total VROM Size : 0x%06lX\n"
|
||||
" Mapper ID : 0x%06X | Mirroring ? : %s\n"
|
||||
" Battery ? : %s | 4 Screen ? : %s \n"
|
||||
" PROMBanks start at : %p |\n"
|
||||
" VROMBanks start at : %p |\n",
|
||||
cart->FileName,
|
||||
cart->PROMSize,
|
||||
cart->VROMSize,
|
||||
cart->MapperID,
|
||||
(cart->Flags & iNES_MIRROR) ? "Horizontal" : "Vertical",
|
||||
(cart->Flags & iNES_BATTERY) ? "Yes" : "No ",
|
||||
(cart->Flags & iNES_4SCREEN) ? "Yes" : "No ",
|
||||
cart->PROMBanks,
|
||||
cart->VROMBanks);
|
||||
}
|
||||
|
||||
int LoadCart(const char *filename, NesCart * cart)
|
||||
int LoadCart(const char *filename, NesCart *cart)
|
||||
{
|
||||
byte buffer[6];
|
||||
char buffer[6];
|
||||
/* Load the cart into memory */
|
||||
cart->File = (byte *)LoadFilePtr(filename);
|
||||
|
||||
|
||||
if (cart->File == -1)
|
||||
return -1;
|
||||
|
||||
sprintf(buffer, "%c%c%c%c", 0x4E, 0x45, 0x53, 0x1A);
|
||||
|
||||
/* Verify that this is a real iNES valid file */
|
||||
if (memcmp(cart->File, buffer, 4))
|
||||
return -1;
|
||||
|
||||
if ((cart->File == NULL) || (cart->File == -1))
|
||||
cart->File = (uint8_t *)LoadFilePtr((char *)filename);
|
||||
|
||||
|
||||
if ((cart->File == NULL) || (cart->File == MAP_FAILED))
|
||||
{
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
sprintf(buffer, "%c%c%c%c", 0x4E, 0x45, 0x53, 0x1A);
|
||||
|
||||
/* Verify that this is a real iNES valid file */
|
||||
if (memcmp(cart->File, buffer, 4) != 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Before go elsewhere, verify that the header is clean !
|
||||
(aka no DiskDude! in it) */
|
||||
if (memcmp(cart->File+7, "DiskDude!", 9) == 0)
|
||||
if (memcmp(cart->File + 7, "DiskDude!", 9) == 0)
|
||||
{
|
||||
printf("\n"
|
||||
"*******************WARNING****************\n"
|
||||
"* The header of this game is not clean *\n"
|
||||
"* (DiskDude! pollution) I will only use *\n"
|
||||
"* basic MapperID (mapper 0-15). This can *\n"
|
||||
"* led to unexpected behavior... *\n"
|
||||
"* *\n"
|
||||
"* PLEASE CLEAN THIS FILE! *\n"
|
||||
"******************WARNING*****************\n\n");
|
||||
console_printf(Console_Warning, "\n"
|
||||
"*******************WARNING****************\n"
|
||||
"* The header of this game is not clean *\n"
|
||||
"* (DiskDude! pollution) I will only use *\n"
|
||||
"* basic MapperID (mapper 0-15). This can *\n"
|
||||
"* led to unexpected behavior... *\n"
|
||||
"* *\n"
|
||||
"* PLEASE CLEAN THIS FILE! *\n"
|
||||
"******************WARNING*****************\n\n");
|
||||
/* So this rom file is not clean, we can only rely on the "basic" mapperID */
|
||||
cart->MapperID = cart->File[6]>>4; /* Mapper Type */
|
||||
cart->MapperID = cart->File[6] >> 4; /* Mapper Type */
|
||||
|
||||
}
|
||||
else
|
||||
{ /* This rom file is clean, we can read the extended MapperID */
|
||||
cart->MapperID = (cart->File[6]>>4)|(cart->File[7]&0xF0); /* Mapper Type */
|
||||
cart->MapperID = (cart->File[6] >> 4) | (cart->File[7] & 0xF0); /* Mapper Type */
|
||||
}
|
||||
|
||||
/* Now fill the structure */
|
||||
cart->FileName = filename;
|
||||
cart->FileName = (char *)filename;
|
||||
|
||||
cart->PROMSize = cart->File[4] * 16 * 1024; /* Size of PROM */
|
||||
cart->VROMSize = cart->File[5] * 8 * 1024; /* Size of VROM */
|
||||
cart->PROMSize = cart->File[4] * 16U * 1024U; /* Size of PROM */
|
||||
cart->VROMSize = cart->File[5] * 8U * 1024U; /* Size of VROM */
|
||||
cart->Flags = cart->File[6] & 0x0F;
|
||||
|
||||
|
||||
/* We don't and we will never support trainer-ed ROM */
|
||||
if (cart->Flags & iNES_TRAINER)
|
||||
{
|
||||
printf("\n"
|
||||
"********************ERROR*****************\n"
|
||||
"* This cart have an embedded trainer. *\n"
|
||||
"* There is NO support for them. *\n"
|
||||
"* Please use a CLEAN dump if you want *\n"
|
||||
"* to play this game. *\n"
|
||||
"********************ERROR*****************\n\n");
|
||||
return -1;
|
||||
console_printf(Console_Error, "\n"
|
||||
"********************ERROR*****************\n"
|
||||
"* This cart have an embedded trainer. *\n"
|
||||
"* There is NO support for them. *\n"
|
||||
"* Please use a CLEAN dump if you want *\n"
|
||||
"* to play this game. *\n"
|
||||
"********************ERROR*****************\n\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
cart->PROMBanks = cart->File + 16; /* Pointer on the first PROM */
|
||||
|
||||
cart->VROMBanks = cart->PROMBanks + cart->PROMSize; /* Pointer on the first VROM */
|
||||
|
||||
cart->VROMBanks = cart->PROMBanks + cart->PROMSize; /* Pointer on the first VROM */
|
||||
|
||||
DumpCartProperties(stdout, cart);
|
||||
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
8
src/apu/CMakeLists.txt
Normal file
8
src/apu/CMakeLists.txt
Normal file
@ -0,0 +1,8 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
add_library(apu apu.c apu.c)
|
||||
target_link_libraries(apu portaudio_static)
|
||||
@ -1,418 +0,0 @@
|
||||
/** EMULib Emulation Library *********************************/
|
||||
/** **/
|
||||
/** SndUnix.c **/
|
||||
/** **/
|
||||
/** This file contains standard sound generation routines **/
|
||||
/** for Unix using /dev/dsp and /dev/audio. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#include "Sound.h"
|
||||
|
||||
#include <allegro.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
//#include <unistd.h>
|
||||
//#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
//#include <sys/ioctl.h>
|
||||
|
||||
#define AUDIO_CONV(A) (128+(A))
|
||||
|
||||
|
||||
AUDIOSTREAM *stream;
|
||||
|
||||
static pthread_t ThreadID;
|
||||
static int SoundFD;
|
||||
static int SoundRate = 0;
|
||||
static int MasterVolume = 64;
|
||||
static int MasterSwitch = (1<<SND_CHANNELS)-1;
|
||||
static int LoopFreq = 25;
|
||||
static int NoiseGen = 1;
|
||||
static int Suspended = 0;
|
||||
|
||||
static struct
|
||||
{
|
||||
int Type; /* Channel type (SND_*) */
|
||||
int Freq; /* Channel frequency (Hz) */
|
||||
int Volume; /* Channel volume (0..255) */
|
||||
|
||||
signed char *Data; /* Wave data (-128..127 each) */
|
||||
int Length; /* Wave length in Data */
|
||||
int Rate; /* Wave playback rate (or 0Hz) */
|
||||
int Pos; /* Wave current position in Data */
|
||||
|
||||
int Count; /* Phase counter */
|
||||
} CH[SND_CHANNELS];
|
||||
|
||||
static void UnixSetWave(int Channel,signed char *Data,int Length,int Rate);
|
||||
static void UnixSetSound(int Channel,int NewType);
|
||||
static void UnixDrum(int Type,int Force);
|
||||
static void UnixSetChannels(int Volume,int Switch);
|
||||
static void UnixSound(int Channel,int NewFreq,int NewVolume);
|
||||
|
||||
static int OpenSoundDevice(int Rate,int Verbose);
|
||||
static void *DSPLoop(void *Arg);
|
||||
|
||||
/** StopSound() **********************************************/
|
||||
/** Temporarily suspend sound. **/
|
||||
/*************************************************************/
|
||||
void StopSound(void) { Suspended=1; }
|
||||
|
||||
/** ResumeSound() ********************************************/
|
||||
/** Resume sound after StopSound(). **/
|
||||
/*************************************************************/
|
||||
void ResumeSound(void) { Suspended=0; }
|
||||
|
||||
/** OpenSoundDevice() ****************************************/
|
||||
/** Open /dev/dsp with a given level of sound quality. **/
|
||||
/** Returns 0 if failed or sound quality (Mode). **/
|
||||
/*************************************************************/
|
||||
static int OpenSoundDevice(int Rate,int Verbose)
|
||||
{
|
||||
voice_start(stream->voice);
|
||||
|
||||
if(Verbose) puts("OK");
|
||||
return(Rate);
|
||||
}
|
||||
|
||||
/** DSPLoop() ************************************************/
|
||||
/** Main loop of the sound server. **/
|
||||
/*************************************************************/
|
||||
static void *DSPLoop(void *Arg)
|
||||
{
|
||||
int Wave[SND_BUFSIZE];
|
||||
unsigned char *Buf;
|
||||
register int J,I,K,L,M,N,L1,L2,A1,A2,V;
|
||||
int FreqCount;
|
||||
|
||||
for(J=0;J<SND_CHANNELS;J++)
|
||||
{
|
||||
CH[J].Type = SND_MELODIC;
|
||||
CH[J].Count = 0;
|
||||
CH[J].Volume = 0;
|
||||
CH[J].Freq = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
FreqCount=SoundRate/SND_BUFSIZE;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
Buf = get_audio_stream_buffer(stream);
|
||||
|
||||
if (Buf) {
|
||||
FreqCount-=LoopFreq;
|
||||
|
||||
/* If suspending sound... */
|
||||
if(Suspended)
|
||||
{
|
||||
/* Close sound device */
|
||||
while(Suspended) sleep(1);
|
||||
/* Reopen sound device */
|
||||
SoundRate=OpenSoundDevice(SoundRate,0);
|
||||
}
|
||||
|
||||
/* Waveform generator */
|
||||
for(J=0,M=MasterSwitch;M&&(J<SND_CHANNELS);J++,M>>=1)
|
||||
if(CH[J].Freq&&(V=CH[J].Volume)&&(M&1))
|
||||
switch(CH[J].Type)
|
||||
{
|
||||
case SND_NOISE: /* White Noise */
|
||||
/* For high frequencies, recompute volume */
|
||||
if(CH[J].Freq<=SoundRate) K=0x10000*CH[J].Freq/SoundRate;
|
||||
else { V=V*SoundRate/CH[J].Freq;K=0x10000; }
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L1+=K;
|
||||
if(L1&0xFFFF0000)
|
||||
{
|
||||
L1&=0xFFFF;
|
||||
if((NoiseGen<<=1)&0x80000000) NoiseGen^=0x08000001;
|
||||
}
|
||||
Wave[I]+=NoiseGen&1? V:-V;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_WAVE: /* Custom Waveform */
|
||||
/* Waveform data must have correct length! */
|
||||
if(CH[J].Length<=0) break;
|
||||
/* Start counting */
|
||||
K = CH[J].Rate>0? (SoundRate<<15)/CH[J].Freq/CH[J].Rate
|
||||
: (SoundRate<<15)/CH[J].Freq/CH[J].Length;
|
||||
L1 = CH[J].Pos%CH[J].Length;
|
||||
L2 = CH[J].Count;
|
||||
A1 = CH[J].Data[L1]*V;
|
||||
/* If expecting interpolation... */
|
||||
if(L2<K)
|
||||
{
|
||||
/* Compute interpolation parameters */
|
||||
A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
|
||||
L = (L2>>15)+1;
|
||||
N = ((K-(L2&0x7FFF))>>15)+1;
|
||||
}
|
||||
/* Add waveform to the buffer */
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
if(L2<K)
|
||||
{
|
||||
/* Interpolate linearly */
|
||||
Wave[I]+=A1+L*(A2-A1)/N;
|
||||
/* Next waveform step */
|
||||
L2+=0x8000;
|
||||
/* Next interpolation step */
|
||||
L++;
|
||||
}
|
||||
else
|
||||
{
|
||||
L1 = (L1+L2/K)%CH[J].Length;
|
||||
L2 = (L2%K)+0x8000;
|
||||
A1 = CH[J].Data[L1]*V;
|
||||
Wave[I]+=A1;
|
||||
/* If expecting interpolation... */
|
||||
if(L2<K)
|
||||
{
|
||||
/* Compute interpolation parameters */
|
||||
A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
|
||||
L = 1;
|
||||
N = ((K-L2)>>15)+1;
|
||||
}
|
||||
}
|
||||
/* End counting */
|
||||
CH[J].Pos = L1;
|
||||
CH[J].Count = L2;
|
||||
break;
|
||||
|
||||
|
||||
case SND_QS_DU0:
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0x2000?(L2&0x8000? V:0):(L2&0x8000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_QS_DU1:
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0x4000?(L2&0x8000? V:0):(L2&0x8000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_QS_DU3:
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0xC000?(L2&0x4000? V:0):(L2&0xC000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_QS_DU2:
|
||||
case SND_MELODIC: /* Melodic Sound */
|
||||
default: /* Default Sound */
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0x8000? (L2&0x8000? V:0):(L2&0x8000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_TRIANGLE: /* Default Sound */
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+= L1&0x2000?V:-V /*(L2&0x8000? V:0):(L2&0x8000? 0:-V)*/;
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mix and convert waveforms */
|
||||
for(J=0;J<SND_BUFSIZE;J++)
|
||||
{
|
||||
I=(Wave[J]*MasterVolume)>>16;
|
||||
I=I<-128? -128:I>127? 127:I;
|
||||
Buf[J]=AUDIO_CONV(I);
|
||||
Wave[J]=0;
|
||||
}
|
||||
free_audio_stream_buffer(stream);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/** InitSound() **********************************************/
|
||||
/** Initialize DSP. Returns Rate on success, 0 otherwise. **/
|
||||
/** Mode is 0 to skip initialization (will be silent). **/
|
||||
/*************************************************************/
|
||||
int InitSound(int Rate,int Verbose)
|
||||
{
|
||||
/* If sound was initialized, kill it */
|
||||
TrashSound();
|
||||
|
||||
/* Silence requested */
|
||||
if(Rate<=0) return(0);
|
||||
|
||||
/* Synthesis rate should be at least 8kHz */
|
||||
if(Rate<8192) Rate=44100;
|
||||
|
||||
/* Initialize things */
|
||||
SoundRate = 0;
|
||||
ThreadID = 0;
|
||||
Suspended = 0;
|
||||
|
||||
/* Set driver functions */
|
||||
SndDriver.SetSound = UnixSetSound;
|
||||
SndDriver.Drum = UnixDrum;
|
||||
SndDriver.SetChannels = UnixSetChannels;
|
||||
SndDriver.Sound = UnixSound;
|
||||
SndDriver.SetWave = UnixSetWave;
|
||||
|
||||
if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0)
|
||||
{
|
||||
fprintf(stderr, "%s!\n", allegro_error);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
stream = play_audio_stream(SND_BUFSIZE, 8, FALSE, Rate, 255, 128);
|
||||
if (!stream) {
|
||||
fprintf(stderr, "Error creating audio stream!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
voice_stop(stream->voice);
|
||||
|
||||
/* Open sound device */
|
||||
if(Verbose) puts("Starting sound server:");
|
||||
if(!(Rate=OpenSoundDevice(Rate,Verbose))) return(0);
|
||||
|
||||
/* Create DSPLoop() thread */
|
||||
if(Verbose) printf(" Creating thread...");
|
||||
if(pthread_create(&ThreadID,0,DSPLoop,0))
|
||||
{ if(Verbose) puts("FAILED");return(0); }
|
||||
|
||||
/* Detach the thread */
|
||||
pthread_detach(ThreadID);
|
||||
|
||||
/* Done */
|
||||
if(Verbose) puts("OK");
|
||||
return(SoundRate=Rate);
|
||||
}
|
||||
|
||||
/** TrashSound() *********************************************/
|
||||
/** Shut DSP down. **/
|
||||
/*************************************************************/
|
||||
void TrashSound(void)
|
||||
{
|
||||
StopSound();
|
||||
printf("%s: Kill thread...\n", __func__);
|
||||
if(ThreadID) pthread_cancel(ThreadID);
|
||||
|
||||
SoundRate = 0;
|
||||
ThreadID = 0;
|
||||
}
|
||||
|
||||
/** UnixSound() **********************************************/
|
||||
/** Generate sound of given frequency (Hz) and volume **/
|
||||
/** (0..255) via given channel. **/
|
||||
/*************************************************************/
|
||||
void UnixSound(int Channel,int NewFreq,int NewVolume)
|
||||
{
|
||||
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
|
||||
if(!NewVolume||!NewFreq) { NewVolume=0;NewFreq=0; }
|
||||
|
||||
CH[Channel].Volume = NewVolume;
|
||||
CH[Channel].Freq = NewFreq;
|
||||
}
|
||||
|
||||
/** UnixSetChannels() ****************************************/
|
||||
/** Set master volume (0..255) and turn channels on/off. **/
|
||||
/** Each bit in Toggle corresponds to a channel (1=on). **/
|
||||
/*************************************************************/
|
||||
void UnixSetChannels(int MVolume,int MSwitch)
|
||||
{
|
||||
/* Set new MasterSwitch value */
|
||||
MasterSwitch = MSwitch;
|
||||
MasterVolume = MVolume;
|
||||
}
|
||||
|
||||
/** UnixSetSound() *******************************************/
|
||||
/** Set sound type (SND_NOISE/SND_MELODIC) for a given **/
|
||||
/** channel. **/
|
||||
/*************************************************************/
|
||||
void UnixSetSound(int Channel,int NewType)
|
||||
{
|
||||
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
|
||||
CH[Channel].Type = NewType;
|
||||
}
|
||||
|
||||
|
||||
/** UnixSetWave() ********************************************/
|
||||
/** Set waveform for a given channel. The channel will be **/
|
||||
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
|
||||
/** waveform to be an instrument or set it to the waveform **/
|
||||
/** own playback rate. **/
|
||||
/*************************************************************/
|
||||
void UnixSetWave(int Channel,signed char *Data,int Length,int Rate)
|
||||
{
|
||||
if((Channel<0)||(Channel>=SND_CHANNELS)||(Length<=0)) return;
|
||||
|
||||
CH[Channel].Type = SND_WAVE;
|
||||
CH[Channel].Length = Length;
|
||||
CH[Channel].Rate = Rate;
|
||||
CH[Channel].Pos = 0;
|
||||
CH[Channel].Count = 0;
|
||||
CH[Channel].Data = Data;
|
||||
}
|
||||
|
||||
/** UnixDrum() ***********************************************/
|
||||
/** Hit a drum of a given type with given force. **/
|
||||
/*************************************************************/
|
||||
void UnixDrum(int Type,int Force)
|
||||
{
|
||||
/* This function is currently empty */
|
||||
}
|
||||
@ -1,554 +0,0 @@
|
||||
/** EMULib Emulation Library *********************************/
|
||||
/** **/
|
||||
/** SndUnix.c **/
|
||||
/** **/
|
||||
/** This file contains standard sound generation routines **/
|
||||
/** for Unix using /dev/dsp and /dev/audio. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#ifdef UNIX
|
||||
|
||||
#include "Sound.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef SUN_AUDIO
|
||||
|
||||
#include <sys/audioio.h>
|
||||
#include <sys/conf.h>
|
||||
#include <stropts.h>
|
||||
|
||||
#define AUDIO_CONV(A) (ULAW[0xFF&(128+(A))])
|
||||
|
||||
static unsigned char ULAW[256] =
|
||||
{
|
||||
31, 31, 31, 32, 32, 32, 32, 33,
|
||||
33, 33, 33, 34, 34, 34, 34, 35,
|
||||
35, 35, 35, 36, 36, 36, 36, 37,
|
||||
37, 37, 37, 38, 38, 38, 38, 39,
|
||||
39, 39, 39, 40, 40, 40, 40, 41,
|
||||
41, 41, 41, 42, 42, 42, 42, 43,
|
||||
43, 43, 43, 44, 44, 44, 44, 45,
|
||||
45, 45, 45, 46, 46, 46, 46, 47,
|
||||
47, 47, 47, 48, 48, 49, 49, 50,
|
||||
50, 51, 51, 52, 52, 53, 53, 54,
|
||||
54, 55, 55, 56, 56, 57, 57, 58,
|
||||
58, 59, 59, 60, 60, 61, 61, 62,
|
||||
62, 63, 63, 64, 65, 66, 67, 68,
|
||||
69, 70, 71, 72, 73, 74, 75, 76,
|
||||
77, 78, 79, 81, 83, 85, 87, 89,
|
||||
91, 93, 95, 99, 103, 107, 111, 119,
|
||||
255, 247, 239, 235, 231, 227, 223, 221,
|
||||
219, 217, 215, 213, 211, 209, 207, 206,
|
||||
205, 204, 203, 202, 201, 200, 199, 198,
|
||||
219, 217, 215, 213, 211, 209, 207, 206,
|
||||
205, 204, 203, 202, 201, 200, 199, 198,
|
||||
197, 196, 195, 194, 193, 192, 191, 191,
|
||||
190, 190, 189, 189, 188, 188, 187, 187,
|
||||
186, 186, 185, 185, 184, 184, 183, 183,
|
||||
182, 182, 181, 181, 180, 180, 179, 179,
|
||||
178, 178, 177, 177, 176, 176, 175, 175,
|
||||
175, 175, 174, 174, 174, 174, 173, 173,
|
||||
173, 173, 172, 172, 172, 172, 171, 171,
|
||||
171, 171, 170, 170, 170, 170, 169, 169,
|
||||
169, 169, 168, 168, 168, 168, 167, 167,
|
||||
167, 167, 166, 166, 166, 166, 165, 165,
|
||||
165, 165, 164, 164, 164, 164, 163, 163
|
||||
};
|
||||
|
||||
#else /* SUN_AUDIO */
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#include <machine/soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifdef __NetBSD__
|
||||
#include <soundcard.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <sys/soundcard.h>
|
||||
#endif
|
||||
|
||||
#define AUDIO_CONV(A) (128+(A))
|
||||
|
||||
#endif /* SUN_AUDIO */
|
||||
|
||||
static pthread_t ThreadID;
|
||||
static int SoundFD;
|
||||
static int SoundRate = 0;
|
||||
static int MasterVolume = 64;
|
||||
static int MasterSwitch = (1<<SND_CHANNELS)-1;
|
||||
static int LoopFreq = 25;
|
||||
static int NoiseGen = 1;
|
||||
static int Suspended = 0;
|
||||
|
||||
static struct
|
||||
{
|
||||
int Type; /* Channel type (SND_*) */
|
||||
int Freq; /* Channel frequency (Hz) */
|
||||
int Volume; /* Channel volume (0..255) */
|
||||
|
||||
signed char *Data; /* Wave data (-128..127 each) */
|
||||
int Length; /* Wave length in Data */
|
||||
int Rate; /* Wave playback rate (or 0Hz) */
|
||||
int Pos; /* Wave current position in Data */
|
||||
|
||||
int Count; /* Phase counter */
|
||||
} CH[SND_CHANNELS];
|
||||
|
||||
static void UnixSetWave(int Channel,signed char *Data,int Length,int Rate);
|
||||
static void UnixSetSound(int Channel,int NewType);
|
||||
static void UnixDrum(int Type,int Force);
|
||||
static void UnixSetChannels(int Volume,int Switch);
|
||||
static void UnixSound(int Channel,int NewFreq,int NewVolume);
|
||||
|
||||
static int OpenSoundDevice(int Rate,int Verbose);
|
||||
static void *DSPLoop(void *Arg);
|
||||
|
||||
/** StopSound() **********************************************/
|
||||
/** Temporarily suspend sound. **/
|
||||
/*************************************************************/
|
||||
void StopSound(void) { Suspended=1; }
|
||||
|
||||
/** ResumeSound() ********************************************/
|
||||
/** Resume sound after StopSound(). **/
|
||||
/*************************************************************/
|
||||
void ResumeSound(void) { Suspended=0; }
|
||||
|
||||
/** OpenSoundDevice() ****************************************/
|
||||
/** Open /dev/dsp with a given level of sound quality. **/
|
||||
/** Returns 0 if failed or sound quality (Mode). **/
|
||||
/*************************************************************/
|
||||
static int OpenSoundDevice(int Rate,int Verbose)
|
||||
{
|
||||
int I,J,K;
|
||||
|
||||
#ifdef SUN_AUDIO
|
||||
|
||||
if(Verbose) printf(" Opening /dev/audio...");
|
||||
if((SoundFD=open("/dev/audio",O_WRONLY | O_NONBLOCK))==-1)
|
||||
{
|
||||
if(Verbose) puts("FAILED");
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
** Sun's specific initialization should be here...
|
||||
** We assume, that it's set to 8000Hz u-law mono right now.
|
||||
*/
|
||||
|
||||
#else /* SUN_AUDIO */
|
||||
|
||||
/* At first, we need to open /dev/dsp: */
|
||||
if(Verbose) printf(" Opening /dev/dsp...");
|
||||
I=((SoundFD=open("/dev/dsp",O_WRONLY))<0);
|
||||
|
||||
/* Set 8-bit sound */
|
||||
if(!I)
|
||||
{
|
||||
if(Verbose) printf("OK\n Setting mode: 8bit...");
|
||||
J=AFMT_U8;
|
||||
I=(ioctl(SoundFD,SNDCTL_DSP_SETFMT,&J)<0);
|
||||
}
|
||||
|
||||
/* Set mono sound */
|
||||
if(!I)
|
||||
{
|
||||
if(Verbose) printf("mono...");
|
||||
J=0;
|
||||
I=(ioctl(SoundFD,SNDCTL_DSP_STEREO,&J)<0);
|
||||
}
|
||||
|
||||
/* Set sampling rate */
|
||||
if(!I)
|
||||
{
|
||||
if(Verbose) printf("OK\n Setting sampling rate: %dHz...",Rate);
|
||||
I=(ioctl(SoundFD,SNDCTL_DSP_SPEED,&Rate)<0);
|
||||
if(Verbose) printf("(got %dHz)...",Rate);
|
||||
}
|
||||
|
||||
/* Here we set the number of buffers to use */
|
||||
if(!I)
|
||||
{
|
||||
if(Verbose)
|
||||
printf
|
||||
(
|
||||
"OK\n Adjusting buffers: %d buffers %d bytes each...",
|
||||
SND_BUFFERS,1<<SND_BITS
|
||||
);
|
||||
|
||||
/* Set buffer length and number of buffers */
|
||||
J=K=SND_BITS|(SND_BUFFERS<<16);
|
||||
I=(ioctl(SoundFD,SNDCTL_DSP_SETFRAGMENT,&J)<0);
|
||||
|
||||
/* Buffer length as n, not 2^n! */
|
||||
if((J&0xFFFF)<16) J=(J&0xFFFF0000)|(1<<(J&0xFFFF));
|
||||
K=(1<<SND_BITS)|(SND_BUFFERS<<16);
|
||||
|
||||
/* If something went wrong... */
|
||||
if(J!=K)
|
||||
{
|
||||
if((J>>16)<SND_BUFFERS) I=-1;
|
||||
if((J&0xFFFF)!=(1<<SND_BITS)) I=-1;
|
||||
}
|
||||
}
|
||||
|
||||
/* If something failed, fall out */
|
||||
if(I) { if(Verbose) puts("FAILED");return(0); }
|
||||
|
||||
#endif /* SUN_AUDIO */
|
||||
|
||||
if(Verbose) puts("OK");
|
||||
return(Rate);
|
||||
}
|
||||
|
||||
/** DSPLoop() ************************************************/
|
||||
/** Main loop of the sound server. **/
|
||||
/*************************************************************/
|
||||
static void *DSPLoop(void *Arg)
|
||||
{
|
||||
int Wave[SND_BUFSIZE];
|
||||
unsigned char Buf[SND_BUFSIZE];
|
||||
register int J,I,K,L,M,N,L1,L2,A1,A2,V;
|
||||
int FreqCount;
|
||||
|
||||
for(J=0;J<SND_CHANNELS;J++)
|
||||
{
|
||||
CH[J].Type = SND_MELODIC;
|
||||
CH[J].Count = 0;
|
||||
CH[J].Volume = 0;
|
||||
CH[J].Freq = 0;
|
||||
}
|
||||
|
||||
FreqCount=SoundRate/SND_BUFSIZE;
|
||||
for(;;FreqCount-=LoopFreq)
|
||||
{
|
||||
/* If suspending sound... */
|
||||
if(Suspended)
|
||||
{
|
||||
/* Close sound device */
|
||||
#ifndef SUN_AUDIO
|
||||
ioctl(SoundFD,SNDCTL_DSP_RESET);
|
||||
#endif
|
||||
close(SoundFD);
|
||||
/* Suspend execution until Suspended=0 */
|
||||
while(Suspended) sleep(1);
|
||||
/* Reopen sound device */
|
||||
SoundRate=OpenSoundDevice(SoundRate,0);
|
||||
}
|
||||
|
||||
/* Waveform generator */
|
||||
for(J=0,M=MasterSwitch;M&&(J<SND_CHANNELS);J++,M>>=1)
|
||||
if(CH[J].Freq&&(V=CH[J].Volume)&&(M&1))
|
||||
switch(CH[J].Type)
|
||||
{
|
||||
case SND_NOISE: /* White Noise */
|
||||
/* For high frequencies, recompute volume */
|
||||
if(CH[J].Freq<=SoundRate) K=0x10000*CH[J].Freq/SoundRate;
|
||||
else { V=V*SoundRate/CH[J].Freq;K=0x10000; }
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L1+=K;
|
||||
if(L1&0xFFFF0000)
|
||||
{
|
||||
L1&=0xFFFF;
|
||||
if((NoiseGen<<=1)&0x80000000) NoiseGen^=0x08000001;
|
||||
}
|
||||
Wave[I]+=NoiseGen&1? V:-V;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_WAVE: /* Custom Waveform */
|
||||
/* Waveform data must have correct length! */
|
||||
if(CH[J].Length<=0) break;
|
||||
/* Start counting */
|
||||
K = CH[J].Rate>0? (SoundRate<<15)/CH[J].Freq/CH[J].Rate
|
||||
: (SoundRate<<15)/CH[J].Freq/CH[J].Length;
|
||||
L1 = CH[J].Pos%CH[J].Length;
|
||||
L2 = CH[J].Count;
|
||||
A1 = CH[J].Data[L1]*V;
|
||||
/* If expecting interpolation... */
|
||||
if(L2<K)
|
||||
{
|
||||
/* Compute interpolation parameters */
|
||||
A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
|
||||
L = (L2>>15)+1;
|
||||
N = ((K-(L2&0x7FFF))>>15)+1;
|
||||
}
|
||||
/* Add waveform to the buffer */
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
if(L2<K)
|
||||
{
|
||||
/* Interpolate linearly */
|
||||
Wave[I]+=A1+L*(A2-A1)/N;
|
||||
/* Next waveform step */
|
||||
L2+=0x8000;
|
||||
/* Next interpolation step */
|
||||
L++;
|
||||
}
|
||||
else
|
||||
{
|
||||
L1 = (L1+L2/K)%CH[J].Length;
|
||||
L2 = (L2%K)+0x8000;
|
||||
A1 = CH[J].Data[L1]*V;
|
||||
Wave[I]+=A1;
|
||||
/* If expecting interpolation... */
|
||||
if(L2<K)
|
||||
{
|
||||
/* Compute interpolation parameters */
|
||||
A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
|
||||
L = 1;
|
||||
N = ((K-L2)>>15)+1;
|
||||
}
|
||||
}
|
||||
/* End counting */
|
||||
CH[J].Pos = L1;
|
||||
CH[J].Count = L2;
|
||||
break;
|
||||
|
||||
|
||||
case SND_QS_DU0:
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0x2000?(L2&0x8000? V:0):(L2&0x8000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_QS_DU1:
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0x4000?(L2&0x8000? V:0):(L2&0x8000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_QS_DU3:
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0xC000?(L2&0x4000? V:0):(L2&0xC000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_QS_DU2:
|
||||
case SND_MELODIC: /* Melodic Sound */
|
||||
default: /* Default Sound */
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+=L1&0x8000? (L2&0x8000? V:0):(L2&0x8000? 0:-V);
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
|
||||
case SND_TRIANGLE: /* Default Sound */
|
||||
/* Do not allow frequencies that are too high */
|
||||
if(CH[J].Freq>=SoundRate/3) break;
|
||||
K=0x10000*CH[J].Freq/SoundRate;
|
||||
L1=CH[J].Count;
|
||||
V<<=7;
|
||||
for(I=0;I<SND_BUFSIZE;I++)
|
||||
{
|
||||
L2=L1+K;
|
||||
Wave[I]+= L1&0x2000?V:-V /*(L2&0x8000? V:0):(L2&0x8000? 0:-V)*/;
|
||||
L1=L2;
|
||||
}
|
||||
CH[J].Count=L1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Mix and convert waveforms */
|
||||
for(J=0;J<SND_BUFSIZE;J++)
|
||||
{
|
||||
I=(Wave[J]*MasterVolume)>>16;
|
||||
I=I<-128? -128:I>127? 127:I;
|
||||
Buf[J]=AUDIO_CONV(I);
|
||||
Wave[J]=0;
|
||||
}
|
||||
|
||||
if(SoundFD==-1) sleep(1);
|
||||
else
|
||||
{
|
||||
#ifdef SUN_AUDIO
|
||||
/* Flush output first, don't care about return status. After this
|
||||
** write next buffer of audio data. This method produces a horrible
|
||||
** click on each buffer :( Any ideas, how to fix this?
|
||||
*/
|
||||
ioctl(SoundFD,AUDIO_DRAIN);
|
||||
write(SoundFD,Buf,SND_BUFSIZE);
|
||||
#else
|
||||
/* We'll block here until next DMA buffer becomes free. It happens
|
||||
** once per (1<<SND_BITS)/SoundRate seconds.
|
||||
*/
|
||||
write(SoundFD,Buf,SND_BUFSIZE);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/** InitSound() **********************************************/
|
||||
/** Initialize DSP. Returns Rate on success, 0 otherwise. **/
|
||||
/** Mode is 0 to skip initialization (will be silent). **/
|
||||
/*************************************************************/
|
||||
int InitSound(int Rate,int Verbose)
|
||||
{
|
||||
/* If sound was initialized, kill it */
|
||||
TrashSound();
|
||||
|
||||
/* Silence requested */
|
||||
if(Rate<=0) return(0);
|
||||
|
||||
/* Synthesis rate should be at least 8kHz */
|
||||
if(Rate<8192) Rate=44100;
|
||||
|
||||
/* Initialize things */
|
||||
SoundRate = 0;
|
||||
SoundFD = -1;
|
||||
ThreadID = 0;
|
||||
Suspended = 0;
|
||||
|
||||
/* Set driver functions */
|
||||
SndDriver.SetSound = UnixSetSound;
|
||||
SndDriver.Drum = UnixDrum;
|
||||
SndDriver.SetChannels = UnixSetChannels;
|
||||
SndDriver.Sound = UnixSound;
|
||||
SndDriver.SetWave = UnixSetWave;
|
||||
|
||||
/* Open sound device */
|
||||
if(Verbose) puts("Starting sound server:");
|
||||
if(!(Rate=OpenSoundDevice(Rate,Verbose))) return(0);
|
||||
|
||||
/* Create DSPLoop() thread */
|
||||
if(Verbose) printf(" Creating thread...");
|
||||
if(pthread_create(&ThreadID,0,DSPLoop,0))
|
||||
{ if(Verbose) puts("FAILED");return(0); }
|
||||
|
||||
/* Detach the thread */
|
||||
pthread_detach(ThreadID);
|
||||
|
||||
/* Done */
|
||||
if(Verbose) puts("OK");
|
||||
return(SoundRate=Rate);
|
||||
}
|
||||
|
||||
/** TrashSound() *********************************************/
|
||||
/** Shut DSP down. **/
|
||||
/*************************************************************/
|
||||
void TrashSound(void)
|
||||
{
|
||||
StopSound();
|
||||
printf("%s: Kill thread...\n", __func__);
|
||||
if(ThreadID) pthread_cancel(ThreadID);
|
||||
printf("%s: close /dev/xxx ...\n", __func__);
|
||||
if(SoundFD!=-1) close(SoundFD);
|
||||
|
||||
SoundRate = 0;
|
||||
SoundFD = -1;
|
||||
ThreadID = 0;
|
||||
}
|
||||
|
||||
/** UnixSound() **********************************************/
|
||||
/** Generate sound of given frequency (Hz) and volume **/
|
||||
/** (0..255) via given channel. **/
|
||||
/*************************************************************/
|
||||
void UnixSound(int Channel,int NewFreq,int NewVolume)
|
||||
{
|
||||
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
|
||||
if(!NewVolume||!NewFreq) { NewVolume=0;NewFreq=0; }
|
||||
|
||||
CH[Channel].Volume = NewVolume;
|
||||
CH[Channel].Freq = NewFreq;
|
||||
}
|
||||
|
||||
/** UnixSetChannels() ****************************************/
|
||||
/** Set master volume (0..255) and turn channels on/off. **/
|
||||
/** Each bit in Toggle corresponds to a channel (1=on). **/
|
||||
/*************************************************************/
|
||||
void UnixSetChannels(int MVolume,int MSwitch)
|
||||
{
|
||||
/* Set new MasterSwitch value */
|
||||
MasterSwitch = MSwitch;
|
||||
MasterVolume = MVolume;
|
||||
}
|
||||
|
||||
/** UnixSetSound() *******************************************/
|
||||
/** Set sound type (SND_NOISE/SND_MELODIC) for a given **/
|
||||
/** channel. **/
|
||||
/*************************************************************/
|
||||
void UnixSetSound(int Channel,int NewType)
|
||||
{
|
||||
if((Channel<0)||(Channel>=SND_CHANNELS)) return;
|
||||
CH[Channel].Type = NewType;
|
||||
}
|
||||
|
||||
|
||||
/** UnixSetWave() ********************************************/
|
||||
/** Set waveform for a given channel. The channel will be **/
|
||||
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
|
||||
/** waveform to be an instrument or set it to the waveform **/
|
||||
/** own playback rate. **/
|
||||
/*************************************************************/
|
||||
void UnixSetWave(int Channel,signed char *Data,int Length,int Rate)
|
||||
{
|
||||
if((Channel<0)||(Channel>=SND_CHANNELS)||(Length<=0)) return;
|
||||
|
||||
CH[Channel].Type = SND_WAVE;
|
||||
CH[Channel].Length = Length;
|
||||
CH[Channel].Rate = Rate;
|
||||
CH[Channel].Pos = 0;
|
||||
CH[Channel].Count = 0;
|
||||
CH[Channel].Data = Data;
|
||||
}
|
||||
|
||||
/** UnixDrum() ***********************************************/
|
||||
/** Hit a drum of a given type with given force. **/
|
||||
/*************************************************************/
|
||||
void UnixDrum(int Type,int Force)
|
||||
{
|
||||
/* This function is currently empty */
|
||||
}
|
||||
|
||||
#endif /* UNIX */
|
||||
497
src/apu/Sound.c
497
src/apu/Sound.c
@ -1,497 +0,0 @@
|
||||
/** EMULib Emulation Library *********************************/
|
||||
/** **/
|
||||
/** Sound.c **/
|
||||
/** **/
|
||||
/** This file file implements core part of the sound API **/
|
||||
/** and functions needed to log soundtrack into a MIDI **/
|
||||
/** file. See Sound.h for declarations. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
#include "Sound.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef UNIX
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
typedef unsigned char byte;
|
||||
typedef unsigned short word;
|
||||
|
||||
struct SndDriverStruct SndDriver =
|
||||
{
|
||||
(void (*)(int,int))0,
|
||||
(void (*)(int,int))0,
|
||||
(void (*)(int,int))0,
|
||||
(void (*)(int,int,int))0,
|
||||
(void (*)(int,const signed char *,int,int))0,
|
||||
(const signed char *(*)(int))0
|
||||
};
|
||||
|
||||
static const struct { byte Note;word Wheel; } Freqs[4096] =
|
||||
{
|
||||
#include "MIDIFreq.h"
|
||||
};
|
||||
|
||||
static const int Programs[5] =
|
||||
{
|
||||
80, /* SND_MELODIC/SND_RECTANGLE */
|
||||
80, /* SND_TRIANGLE */
|
||||
122, /* SND_NOISE */
|
||||
122, /* SND_PERIODIC */
|
||||
80 /* SND_WAVE */
|
||||
};
|
||||
|
||||
static struct
|
||||
{
|
||||
int Type;
|
||||
int Note;
|
||||
int Pitch;
|
||||
int Level;
|
||||
} CH[MIDI_CHANNELS] =
|
||||
{
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 },
|
||||
{ -1,-1,-1,-1 }
|
||||
};
|
||||
|
||||
static const char *LogName = 0;
|
||||
static int Logging = MIDI_OFF;
|
||||
static int TickCount = 0;
|
||||
static int LastMsg = -1;
|
||||
static int DrumOn = 0;
|
||||
static FILE *MIDIOut = 0;
|
||||
|
||||
static void MIDISound(int Channel,int Freq,int Volume);
|
||||
static void MIDISetSound(int Channel,int Type);
|
||||
static void MIDIDrum(int Type,int Force);
|
||||
static void MIDIMessage(byte D0,byte D1,byte D2);
|
||||
static void NoteOn(byte Channel,byte Note,byte Level);
|
||||
static void NoteOff(byte Channel);
|
||||
static void WriteDelta(void);
|
||||
static void WriteTempo(int Freq);
|
||||
|
||||
/** SHIFT() **************************************************/
|
||||
/** Make MIDI channel#10 last, as it is normally used for **/
|
||||
/** percussion instruments only and doesn't sound nice. **/
|
||||
/*************************************************************/
|
||||
#define SHIFT(Ch) (Ch==15? 9:Ch>8? Ch+1:Ch)
|
||||
|
||||
/** Sound() **************************************************/
|
||||
/** Generate sound of given frequency (Hz) and volume **/
|
||||
/** (0..255) via given channel. Setting Freq=0 or Volume=0 **/
|
||||
/** turns sound off. **/
|
||||
/*************************************************************/
|
||||
void Sound(int Channel,int Freq,int Volume)
|
||||
{
|
||||
if(Channel<0) return;
|
||||
Freq = Freq<0? 0:Freq;
|
||||
Volume = Volume<0? 0:Volume>255? 255:Volume;
|
||||
|
||||
/* Call sound driver if present */
|
||||
if(SndDriver.Sound) (*SndDriver.Sound)(Channel,Freq,Volume);
|
||||
|
||||
/* Log sound to MIDI file */
|
||||
MIDISound(Channel,Freq,Volume);
|
||||
}
|
||||
|
||||
/** Drum() ***************************************************/
|
||||
/** Hit a drum of given type with given force (0..255). **/
|
||||
/** MIDI drums can be used by ORing their numbers with **/
|
||||
/** SND_MIDI. **/
|
||||
/*************************************************************/
|
||||
void Drum(int Type,int Force)
|
||||
{
|
||||
Force = Force<0? 0:Force>255? 255:Force;
|
||||
|
||||
if(SndDriver.Drum) (*SndDriver.Drum)(Type,Force);
|
||||
|
||||
/* Log drum to MIDI file */
|
||||
MIDIDrum(Type,Force);
|
||||
}
|
||||
|
||||
/** SetSound() ***********************************************/
|
||||
/** Set sound type at a given channel. MIDI instruments can **/
|
||||
/** be set directly by ORing their numbers with SND_MIDI. **/
|
||||
/*************************************************************/
|
||||
void SetSound(int Channel,int Type)
|
||||
{
|
||||
if(Channel<0) return;
|
||||
|
||||
if(SndDriver.SetSound) (*SndDriver.SetSound)(Channel,Type);
|
||||
|
||||
/* Log instrument change to MIDI file */
|
||||
MIDISetSound(Channel,Type);
|
||||
}
|
||||
|
||||
/** SetChannels() ********************************************/
|
||||
/** Set master volume (0..255) and switch channels on/off. **/
|
||||
/** Each channel N has corresponding bit 2^N in Switch. Set **/
|
||||
/** or reset this bit to turn the channel on or off. **/
|
||||
/*************************************************************/
|
||||
void SetChannels(int Volume,int Switch)
|
||||
{
|
||||
Volume = Volume<0? 0:Volume>255? 255:Volume;
|
||||
|
||||
if(SndDriver.SetChannels) (*SndDriver.SetChannels)(Volume,Switch);
|
||||
}
|
||||
|
||||
/** SetWave() ************************************************/
|
||||
/** Set waveform for a given channel. The channel will be **/
|
||||
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
|
||||
/** waveform to be an instrument or set it to the waveform **/
|
||||
/** own playback rate. **/
|
||||
/*************************************************************/
|
||||
void SetWave(int Channel,const signed char *Data,int Length,int Rate)
|
||||
{
|
||||
if((Channel<0)||(Length<=0)) return;
|
||||
|
||||
if(SndDriver.SetWave) (*SndDriver.SetWave)(Channel,Data,Length,Rate);
|
||||
|
||||
/* Log instrument change to MIDI file */
|
||||
MIDISetSound(Channel,Rate? -1:SND_MELODIC);
|
||||
}
|
||||
|
||||
/** GetWave() ************************************************/
|
||||
/** Get current read position for the buffer set with the **/
|
||||
/** SetWave() call. Returns 0 if no buffer has been set, or **/
|
||||
/** if there is no playrate set (i.e. wave is instrument). **/
|
||||
/*************************************************************/
|
||||
const signed char *GetWave(int Channel)
|
||||
{
|
||||
return(SndDriver.GetWave? (*SndDriver.GetWave)(Channel):0);
|
||||
}
|
||||
|
||||
/** InitMIDI() ***********************************************/
|
||||
/** Initialize soundtrack logging into MIDI file FileName. **/
|
||||
/** Repeated calls to InitMIDI() will close current MIDI **/
|
||||
/** file and continue logging into a new one. **/
|
||||
/*************************************************************/
|
||||
void InitMIDI(const char *FileName)
|
||||
{
|
||||
int WasLogging;
|
||||
|
||||
/* Must pass a name! */
|
||||
if(!FileName) return;
|
||||
|
||||
/* Memorize logging status */
|
||||
WasLogging=Logging;
|
||||
|
||||
/* If MIDI logging in progress, close current file */
|
||||
if(MIDIOut) TrashMIDI();
|
||||
|
||||
/* Set log file name and ticks/second parameter, no logging yet */
|
||||
LogName = FileName;
|
||||
Logging = MIDI_OFF;
|
||||
LastMsg = -1;
|
||||
TickCount = 0;
|
||||
MIDIOut = 0;
|
||||
DrumOn = 0;
|
||||
|
||||
/* If was logging, restart */
|
||||
if(WasLogging) MIDILogging(MIDI_ON);
|
||||
}
|
||||
|
||||
/** TrashMIDI() **********************************************/
|
||||
/** Finish logging soundtrack and close the MIDI file. **/
|
||||
/*************************************************************/
|
||||
void TrashMIDI(void)
|
||||
{
|
||||
long Length;
|
||||
int J;
|
||||
|
||||
/* If not logging, drop out */
|
||||
if(!MIDIOut) return;
|
||||
/* Turn sound off */
|
||||
for(J=0;J<MIDI_CHANNELS;J++) NoteOff(J);
|
||||
/* End of track */
|
||||
MIDIMessage(0xFF,0x2F,0x00);
|
||||
/* Put track length in file */
|
||||
fseek(MIDIOut,0,SEEK_END);
|
||||
Length=ftell(MIDIOut)-22;
|
||||
fseek(MIDIOut,18,SEEK_SET);
|
||||
fputc((Length>>24)&0xFF,MIDIOut);
|
||||
fputc((Length>>16)&0xFF,MIDIOut);
|
||||
fputc((Length>>8)&0xFF,MIDIOut);
|
||||
fputc(Length&0xFF,MIDIOut);
|
||||
|
||||
/* Done logging */
|
||||
fclose(MIDIOut);
|
||||
Logging = MIDI_OFF;
|
||||
LastMsg = -1;
|
||||
TickCount = 0;
|
||||
MIDIOut = 0;
|
||||
}
|
||||
|
||||
/** MIDILogging() ********************************************/
|
||||
/** Turn soundtrack logging on/off and return its current **/
|
||||
/** status. Possible values of Switch are MIDI_OFF (turn **/
|
||||
/** logging off), MIDI_ON (turn logging on), MIDI_TOGGLE **/
|
||||
/** (toggle logging), and MIDI_QUERY (just return current **/
|
||||
/** state of logging). **/
|
||||
/*************************************************************/
|
||||
int MIDILogging(int Switch)
|
||||
{
|
||||
static const char MThd[] = "MThd\0\0\0\006\0\0\0\1";
|
||||
/* ID DataLen Fmt Trks */
|
||||
static const char MTrk[] = "MTrk\0\0\0\0";
|
||||
/* ID TrkLen */
|
||||
int J,I;
|
||||
|
||||
/* Toggle logging if requested */
|
||||
if(Switch==MIDI_TOGGLE) Switch=!Logging;
|
||||
|
||||
if((Switch==MIDI_ON)||(Switch==MIDI_OFF))
|
||||
if(Switch^Logging)
|
||||
{
|
||||
/* When turning logging off, silence all channels */
|
||||
if(!Switch&&MIDIOut)
|
||||
for(J=0;J<MIDI_CHANNELS;J++) NoteOff(J);
|
||||
|
||||
/* When turning logging on, open MIDI file */
|
||||
if(Switch&&!MIDIOut&&LogName)
|
||||
{
|
||||
/* No messages have been sent yet */
|
||||
LastMsg=-1;
|
||||
|
||||
/* Clear all storage */
|
||||
for(J=0;J<MIDI_CHANNELS;J++)
|
||||
CH[J].Note=CH[J].Pitch=CH[J].Level=-1;
|
||||
|
||||
/* Open new file and write out the header */
|
||||
MIDIOut=fopen(LogName,"wb");
|
||||
if(!MIDIOut) return(MIDI_OFF);
|
||||
if(fwrite(MThd,1,12,MIDIOut)!=12)
|
||||
{ fclose(MIDIOut);MIDIOut=0;return(MIDI_OFF); }
|
||||
fputc((MIDI_DIVISIONS>>8)&0xFF,MIDIOut);
|
||||
fputc(MIDI_DIVISIONS&0xFF,MIDIOut);
|
||||
if(fwrite(MTrk,1,8,MIDIOut)!=8)
|
||||
{ fclose(MIDIOut);MIDIOut=0;return(MIDI_OFF); }
|
||||
|
||||
/* Write out the tempo */
|
||||
WriteTempo(MIDI_DIVISIONS);
|
||||
}
|
||||
|
||||
/* Turn logging off on failure to open MIDIOut */
|
||||
if(!MIDIOut) Switch=MIDI_OFF;
|
||||
|
||||
/* Assign new switch value */
|
||||
Logging=Switch;
|
||||
|
||||
/* If switching logging on... */
|
||||
if(Switch)
|
||||
{
|
||||
/* Start logging without a pause */
|
||||
TickCount=0;
|
||||
|
||||
/* Write instrument changes */
|
||||
for(J=0;J<MIDI_CHANNELS;J++)
|
||||
if((CH[J].Type>=0)&&(CH[J].Type&0x10000))
|
||||
{
|
||||
I=CH[J].Type&~0x10000;
|
||||
CH[J].Type=-1;
|
||||
MIDISetSound(J,I);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return current logging status */
|
||||
return(Logging);
|
||||
}
|
||||
|
||||
/** MIDITicks() **********************************************/
|
||||
/** Log N 1ms MIDI ticks. **/
|
||||
/*************************************************************/
|
||||
void MIDITicks(int N)
|
||||
{
|
||||
if(Logging&&MIDIOut&&(N>0)) TickCount+=N;
|
||||
}
|
||||
|
||||
/** MIDISound() **********************************************/
|
||||
/** Set sound frequency (Hz) and volume (0..255) for a **/
|
||||
/** given channel. **/
|
||||
/*************************************************************/
|
||||
void MIDISound(int Channel,int Freq,int Volume)
|
||||
{
|
||||
int MIDIVolume,MIDINote,MIDIWheel;
|
||||
|
||||
/* If logging off, file closed, or invalid channel, drop out */
|
||||
if(!Logging||!MIDIOut||(Channel>=MIDI_CHANNELS-1)||(Channel<0)) return;
|
||||
/* Frequency must be in range */
|
||||
if((Freq<MIDI_MINFREQ)||(Freq>MIDI_MAXFREQ)) Freq=0;
|
||||
/* Volume must be in range */
|
||||
if(Volume<0) Volume=0; else if(Volume>255) Volume=255;
|
||||
/* Instrument number must be valid */
|
||||
if(CH[Channel].Type<0) Freq=0;
|
||||
|
||||
if(!Volume||!Freq) NoteOff(Channel);
|
||||
else
|
||||
{
|
||||
/* SND_TRIANGLE is twice quieter than SND_MELODIC */
|
||||
if(CH[Channel].Type==SND_TRIANGLE) Volume=(Volume+1)/2;
|
||||
/* Compute MIDI note parameters */
|
||||
MIDIVolume = (127*Volume+128)/255;
|
||||
MIDINote = Freqs[Freq/3].Note;
|
||||
MIDIWheel = Freqs[Freq/3].Wheel;
|
||||
|
||||
/* Play new note */
|
||||
NoteOn(Channel,MIDINote,MIDIVolume);
|
||||
|
||||
/* Change pitch */
|
||||
if(CH[Channel].Pitch!=MIDIWheel)
|
||||
{
|
||||
MIDIMessage(0xE0+SHIFT(Channel),MIDIWheel&0x7F,(MIDIWheel>>7)&0x7F);
|
||||
CH[Channel].Pitch=MIDIWheel;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** MIDISetSound() *******************************************/
|
||||
/** Set sound type for a given channel. **/
|
||||
/*************************************************************/
|
||||
void MIDISetSound(int Channel,int Type)
|
||||
{
|
||||
/* Channel must be valid */
|
||||
if((Channel>=MIDI_CHANNELS-1)||(Channel<0)) return;
|
||||
|
||||
/* If instrument changed... */
|
||||
if(CH[Channel].Type!=Type)
|
||||
{
|
||||
/* If logging off or file closed, drop out */
|
||||
if(!Logging||!MIDIOut) CH[Channel].Type=Type|0x10000;
|
||||
else
|
||||
{
|
||||
CH[Channel].Type=Type;
|
||||
if(Type<0) NoteOff(Channel);
|
||||
else
|
||||
{
|
||||
Type=Type&SND_MIDI? (Type&0x7F):Programs[Type%5];
|
||||
MIDIMessage(0xC0+SHIFT(Channel),Type,255);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** MIDIDrum() ***********************************************/
|
||||
/** Hit a drum of a given type with given force. **/
|
||||
/*************************************************************/
|
||||
void MIDIDrum(int Type,int Force)
|
||||
{
|
||||
/* If logging off or invalid channel, drop out */
|
||||
if(!Logging||!MIDIOut) return;
|
||||
/* The only non-MIDI drum is a click ("Low Wood Block") */
|
||||
Type=Type&DRM_MIDI? (Type&0x7F):77;
|
||||
/* Release previous drum */
|
||||
if(DrumOn) MIDIMessage(0x89,DrumOn,127);
|
||||
/* Hit next drum */
|
||||
if(Type) MIDIMessage(0x99,Type,(Force&0xFF)/2);
|
||||
DrumOn=Type;
|
||||
}
|
||||
|
||||
/** MIDIMessage() ********************************************/
|
||||
/** Write out a MIDI message. **/
|
||||
/*************************************************************/
|
||||
void MIDIMessage(byte D0,byte D1,byte D2)
|
||||
{
|
||||
/* Write number of ticks that passed */
|
||||
WriteDelta();
|
||||
|
||||
/* Write out the command */
|
||||
if(D0!=LastMsg) { LastMsg=D0;fputc(D0,MIDIOut); }
|
||||
|
||||
/* Write out the arguments */
|
||||
if(D1<128)
|
||||
{
|
||||
fputc(D1,MIDIOut);
|
||||
if(D2<128) fputc(D2,MIDIOut);
|
||||
}
|
||||
}
|
||||
|
||||
/** NoteOn() *************************************************/
|
||||
/** Turn on a note on a given channel. **/
|
||||
/*************************************************************/
|
||||
void NoteOn(byte Channel,byte Note,byte Level)
|
||||
{
|
||||
Note = Note>0x7F? 0x7F:Note;
|
||||
Level = Level>0x7F? 0x7F:Level;
|
||||
|
||||
if((CH[Channel].Note!=Note)||(CH[Channel].Level!=Level))
|
||||
{
|
||||
if(CH[Channel].Note>=0) NoteOff(Channel);
|
||||
MIDIMessage(0x90+SHIFT(Channel),Note,Level);
|
||||
CH[Channel].Note=Note;
|
||||
CH[Channel].Level=Level;
|
||||
}
|
||||
}
|
||||
|
||||
/** NoteOff() ************************************************/
|
||||
/** Turn off a note on a given channel. **/
|
||||
/*************************************************************/
|
||||
void NoteOff(byte Channel)
|
||||
{
|
||||
if(CH[Channel].Note>=0)
|
||||
{
|
||||
MIDIMessage(0x80+SHIFT(Channel),CH[Channel].Note,127);
|
||||
CH[Channel].Note=-1;
|
||||
}
|
||||
}
|
||||
|
||||
/** WriteDelta() *********************************************/
|
||||
/** Write number of ticks since the last MIDI command and **/
|
||||
/** reset the counter. **/
|
||||
/*************************************************************/
|
||||
void WriteDelta(void)
|
||||
{
|
||||
if(TickCount<128) fputc(TickCount,MIDIOut);
|
||||
else
|
||||
{
|
||||
if(TickCount<128*128)
|
||||
{
|
||||
fputc((TickCount>>7)|0x80,MIDIOut);
|
||||
fputc(TickCount&0x7F,MIDIOut);
|
||||
}
|
||||
else
|
||||
{
|
||||
fputc(((TickCount>>14)&0x7F)|0x80,MIDIOut);
|
||||
fputc(((TickCount>>7)&0x7F)|0x80,MIDIOut);
|
||||
fputc(TickCount&0x7F,MIDIOut);
|
||||
}
|
||||
}
|
||||
|
||||
TickCount=0;
|
||||
}
|
||||
|
||||
/** WriteTempo() *********************************************/
|
||||
/** Write out soundtrack tempo (Hz). **/
|
||||
/*************************************************************/
|
||||
void WriteTempo(int Freq)
|
||||
{
|
||||
int J;
|
||||
|
||||
J=500000*MIDI_DIVISIONS*2/Freq;
|
||||
WriteDelta();
|
||||
fputc(0xFF,MIDIOut);
|
||||
fputc(0x51,MIDIOut);
|
||||
fputc(0x03,MIDIOut);
|
||||
fputc((J>>16)&0xFF,MIDIOut);
|
||||
fputc((J>>8)&0xFF,MIDIOut);
|
||||
fputc(J&0xFF,MIDIOut);
|
||||
}
|
||||
10
src/apu/apu.c
Normal file
10
src/apu/apu.c
Normal file
@ -0,0 +1,10 @@
|
||||
/*
|
||||
* APU emulation - The peTI-NESulator Project
|
||||
* apu.c
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
/* Empty, for now */
|
||||
11
src/corecpu/CMakeLists.txt
Normal file
11
src/corecpu/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
if (COVERALLS)
|
||||
set(COVERAGE_SRCS src/corecpu/corecpu.c ${COVERAGE_SRCS} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
add_library(corecpu corecpu.c)
|
||||
@ -1,837 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** Codes.h **/
|
||||
/** **/
|
||||
/** This file contains implementation for the main table of **/
|
||||
/** 6502 commands. It is included from 6502.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate: 2007-05-31 18:01:41 +0200 (jeu, 31 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/Codes.h $
|
||||
* $Revision: 57 $
|
||||
*/
|
||||
|
||||
case 0x10:
|
||||
if (R->P & N_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BPL * REL */
|
||||
|
||||
case 0x30:
|
||||
if (R->P & N_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BMI * REL */
|
||||
|
||||
case 0xD0:
|
||||
if (R->P & Z_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BNE * REL */
|
||||
|
||||
case 0xF0:
|
||||
if (R->P & Z_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BEQ * REL */
|
||||
|
||||
case 0x90:
|
||||
if (R->P & C_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BCC * REL */
|
||||
|
||||
case 0xB0:
|
||||
if (R->P & C_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BCS * REL */
|
||||
|
||||
case 0x50:
|
||||
if (R->P & V_FLAG)
|
||||
R->PC.W++;
|
||||
else
|
||||
{
|
||||
M_JR;
|
||||
} break; /* BVC * REL */
|
||||
|
||||
case 0x70:
|
||||
if (R->P & V_FLAG)
|
||||
{
|
||||
M_JR;
|
||||
}
|
||||
else
|
||||
R->PC.W++;
|
||||
break; /* BVS * REL */
|
||||
|
||||
|
||||
/* RTI */
|
||||
case 0x40:
|
||||
|
||||
M_POP(R->P);
|
||||
R->P |= R_FLAG;
|
||||
M_POP(R->PC.B.l);
|
||||
M_POP(R->PC.B.h);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* RTS */
|
||||
case 0x60:
|
||||
|
||||
M_POP(R->PC.B.l);
|
||||
M_POP(R->PC.B.h);
|
||||
R->PC.W++;
|
||||
break;
|
||||
|
||||
|
||||
/* JSR $ssss ABS */
|
||||
case 0x20:
|
||||
|
||||
K.B.l = Op6502(R->PC.W++);
|
||||
|
||||
K.B.h = Op6502(R->PC.W);
|
||||
|
||||
M_PUSH(R->PC.B.h);
|
||||
|
||||
M_PUSH(R->PC.B.l);
|
||||
|
||||
R->PC = K;
|
||||
break;
|
||||
|
||||
|
||||
/* JMP $ssss ABS */
|
||||
case 0x4C:
|
||||
M_LDWORD(K);
|
||||
R->PC = K;
|
||||
break;
|
||||
|
||||
|
||||
/* JMP ($ssss) ABDINDIR */
|
||||
case 0x6C:
|
||||
|
||||
M_LDWORD(K);
|
||||
|
||||
R->PC.B.l = Rd6502(K.W);
|
||||
|
||||
K.B.l++;
|
||||
|
||||
R->PC.B.h = Rd6502(K.W);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* BRK */
|
||||
case 0x00:
|
||||
|
||||
R->PC.W++;
|
||||
|
||||
M_PUSH(R->PC.B.h);
|
||||
M_PUSH(R->PC.B.l);
|
||||
|
||||
M_PUSH(R->P | B_FLAG);
|
||||
|
||||
R->P = (R->P | I_FLAG) & ~D_FLAG;
|
||||
|
||||
R->PC.B.l = Rd6502(0xFFFE);
|
||||
|
||||
R->PC.B.h = Rd6502(0xFFFF);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* CLI */
|
||||
case 0x58:
|
||||
|
||||
if ((R->IRequest != INT_NONE) && (R->P & I_FLAG))
|
||||
|
||||
{
|
||||
|
||||
R->AfterCLI = 1;
|
||||
|
||||
R->IBackup = R->ICount;
|
||||
|
||||
R->ICount = 1;
|
||||
|
||||
}
|
||||
R->P &= ~I_FLAG;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/* PLP */
|
||||
case 0x28:
|
||||
|
||||
M_POP(I);
|
||||
|
||||
if ((R->IRequest != INT_NONE) && ((I ^ R->P) & ~I & I_FLAG))
|
||||
|
||||
{
|
||||
|
||||
R->AfterCLI = 1;
|
||||
|
||||
R->IBackup = R->ICount;
|
||||
|
||||
R->ICount = 1;
|
||||
|
||||
}
|
||||
R->P = I | R_FLAG | B_FLAG;
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 0x08:
|
||||
M_PUSH(R->P);
|
||||
break; /* PHP */
|
||||
|
||||
case 0x18:
|
||||
R->P &= ~C_FLAG;
|
||||
break; /* CLC */
|
||||
|
||||
case 0xB8:
|
||||
R->P &= ~V_FLAG;
|
||||
break; /* CLV */
|
||||
|
||||
case 0xD8:
|
||||
R->P &= ~D_FLAG;
|
||||
break; /* CLD */
|
||||
|
||||
case 0x38:
|
||||
R->P |= C_FLAG;
|
||||
break; /* SEC */
|
||||
|
||||
case 0xF8:
|
||||
R->P |= D_FLAG;
|
||||
break; /* SED */
|
||||
|
||||
case 0x78:
|
||||
R->P |= I_FLAG;
|
||||
break; /* SEI */
|
||||
|
||||
case 0x48:
|
||||
M_PUSH(R->A);
|
||||
break; /* PHA */
|
||||
|
||||
case 0x68:
|
||||
M_POP(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* PLA */
|
||||
|
||||
case 0x98:
|
||||
R->A = R->Y;
|
||||
M_FL(R->A);
|
||||
break; /* TYA */
|
||||
|
||||
case 0xA8:
|
||||
R->Y = R->A;
|
||||
M_FL(R->Y);
|
||||
break; /* TAY */
|
||||
|
||||
case 0xC8:
|
||||
R->Y++;
|
||||
M_FL(R->Y);
|
||||
break; /* INY */
|
||||
|
||||
case 0x88:
|
||||
R->Y--;
|
||||
M_FL(R->Y);
|
||||
break; /* DEY */
|
||||
|
||||
case 0x8A:
|
||||
R->A = R->X;
|
||||
M_FL(R->A);
|
||||
break; /* TXA */
|
||||
|
||||
case 0xAA:
|
||||
R->X = R->A;
|
||||
M_FL(R->X);
|
||||
break; /* TAX */
|
||||
|
||||
case 0xE8:
|
||||
R->X++;
|
||||
M_FL(R->X);
|
||||
break; /* INX */
|
||||
|
||||
case 0xCA:
|
||||
R->X--;
|
||||
M_FL(R->X);
|
||||
break; /* DEX */
|
||||
|
||||
default: /* In CMOS version unrecognized instructions are concidered as
|
||||
NOP */
|
||||
case 0xEA:
|
||||
break; /* NOP */
|
||||
|
||||
case 0x9A:
|
||||
R->S = R->X;
|
||||
break; /* TXS */
|
||||
|
||||
case 0xBA:
|
||||
R->X = R->S;
|
||||
M_FL(R->X);
|
||||
break; /* TSX */
|
||||
|
||||
|
||||
case 0x24:
|
||||
MR_Zp(I);
|
||||
M_BIT(I);
|
||||
break; /* BIT $ss ZP */
|
||||
|
||||
case 0x2C:
|
||||
MR_Ab(I);
|
||||
M_BIT(I);
|
||||
break; /* BIT $ssss ABS */
|
||||
|
||||
|
||||
case 0x05:
|
||||
MR_Zp(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ss ZP */
|
||||
|
||||
case 0x06:
|
||||
MM_Zp(M_ASL);
|
||||
break; /* ASL $ss ZP */
|
||||
|
||||
case 0x25:
|
||||
MR_Zp(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ss ZP */
|
||||
|
||||
case 0x26:
|
||||
MM_Zp(M_ROL);
|
||||
break; /* ROL $ss ZP */
|
||||
|
||||
case 0x45:
|
||||
MR_Zp(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ss ZP */
|
||||
|
||||
case 0x46:
|
||||
MM_Zp(M_LSR);
|
||||
break; /* LSR $ss ZP */
|
||||
|
||||
case 0x65:
|
||||
MR_Zp(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ss ZP */
|
||||
|
||||
case 0x66:
|
||||
MM_Zp(M_ROR);
|
||||
break; /* ROR $ss ZP */
|
||||
|
||||
case 0x84:
|
||||
MW_Zp(R->Y);
|
||||
break; /* STY $ss ZP */
|
||||
|
||||
case 0x85:
|
||||
MW_Zp(R->A);
|
||||
break; /* STA $ss ZP */
|
||||
|
||||
case 0x86:
|
||||
MW_Zp(R->X);
|
||||
break; /* STX $ss ZP */
|
||||
|
||||
case 0xA4:
|
||||
MR_Zp(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ss ZP */
|
||||
|
||||
case 0xA5:
|
||||
MR_Zp(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ss ZP */
|
||||
|
||||
case 0xA6:
|
||||
MR_Zp(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ss ZP */
|
||||
|
||||
case 0xC4:
|
||||
MR_Zp(I);
|
||||
M_CMP(R->Y, I);
|
||||
break; /* CPY $ss ZP */
|
||||
|
||||
case 0xC5:
|
||||
MR_Zp(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ss ZP */
|
||||
|
||||
case 0xC6:
|
||||
MM_Zp(M_DEC);
|
||||
break; /* DEC $ss ZP */
|
||||
|
||||
case 0xE4:
|
||||
MR_Zp(I);
|
||||
M_CMP(R->X, I);
|
||||
break; /* CPX $ss ZP */
|
||||
|
||||
case 0xE5:
|
||||
MR_Zp(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ss ZP */
|
||||
|
||||
case 0xE6:
|
||||
MM_Zp(M_INC);
|
||||
break; /* INC $ss ZP */
|
||||
|
||||
|
||||
case 0x0D:
|
||||
MR_Ab(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ssss ABS */
|
||||
|
||||
case 0x0E:
|
||||
MM_Ab(M_ASL);
|
||||
break; /* ASL $ssss ABS */
|
||||
|
||||
case 0x2D:
|
||||
MR_Ab(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ssss ABS */
|
||||
|
||||
case 0x2E:
|
||||
MM_Ab(M_ROL);
|
||||
break; /* ROL $ssss ABS */
|
||||
|
||||
case 0x4D:
|
||||
MR_Ab(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ssss ABS */
|
||||
|
||||
case 0x4E:
|
||||
MM_Ab(M_LSR);
|
||||
break; /* LSR $ssss ABS */
|
||||
|
||||
case 0x6D:
|
||||
MR_Ab(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ssss ABS */
|
||||
|
||||
case 0x6E:
|
||||
MM_Ab(M_ROR);
|
||||
break; /* ROR $ssss ABS */
|
||||
|
||||
case 0x8C:
|
||||
MW_Ab(R->Y);
|
||||
break; /* STY $ssss ABS */
|
||||
|
||||
case 0x8D:
|
||||
MW_Ab(R->A);
|
||||
break; /* STA $ssss ABS */
|
||||
|
||||
case 0x8E:
|
||||
MW_Ab(R->X);
|
||||
break; /* STX $ssss ABS */
|
||||
|
||||
case 0xAC:
|
||||
MR_Ab(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ssss ABS */
|
||||
|
||||
case 0xAD:
|
||||
MR_Ab(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ssss ABS */
|
||||
|
||||
case 0xAE:
|
||||
MR_Ab(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ssss ABS */
|
||||
|
||||
case 0xCC:
|
||||
MR_Ab(I);
|
||||
M_CMP(R->Y, I);
|
||||
break; /* CPY $ssss ABS */
|
||||
|
||||
case 0xCD:
|
||||
MR_Ab(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ssss ABS */
|
||||
|
||||
case 0xCE:
|
||||
MM_Ab(M_DEC);
|
||||
break; /* DEC $ssss ABS */
|
||||
|
||||
case 0xEC:
|
||||
MR_Ab(I);
|
||||
M_CMP(R->X, I);
|
||||
break; /* CPX $ssss ABS */
|
||||
|
||||
case 0xED:
|
||||
MR_Ab(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ssss ABS */
|
||||
|
||||
case 0xEE:
|
||||
MM_Ab(M_INC);
|
||||
break; /* INC $ssss ABS */
|
||||
|
||||
|
||||
case 0x09:
|
||||
MR_Im(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA #$ss IMM */
|
||||
|
||||
case 0x29:
|
||||
MR_Im(I);
|
||||
M_AND(I);
|
||||
break; /* AND #$ss IMM */
|
||||
|
||||
case 0x49:
|
||||
MR_Im(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR #$ss IMM */
|
||||
|
||||
case 0x69:
|
||||
MR_Im(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC #$ss IMM */
|
||||
|
||||
case 0xA0:
|
||||
MR_Im(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY #$ss IMM */
|
||||
|
||||
case 0xA2:
|
||||
MR_Im(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX #$ss IMM */
|
||||
|
||||
case 0xA9:
|
||||
MR_Im(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA #$ss IMM */
|
||||
|
||||
case 0xC0:
|
||||
MR_Im(I);
|
||||
M_CMP(R->Y, I);
|
||||
break; /* CPY #$ss IMM */
|
||||
|
||||
case 0xC9:
|
||||
MR_Im(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP #$ss IMM */
|
||||
|
||||
case 0xE0:
|
||||
MR_Im(I);
|
||||
M_CMP(R->X, I);
|
||||
break; /* CPX #$ss IMM */
|
||||
|
||||
case 0xE9:
|
||||
MR_Im(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC #$ss IMM */
|
||||
|
||||
|
||||
case 0x15:
|
||||
MR_Zx(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ss,x ZP,x */
|
||||
|
||||
case 0x16:
|
||||
MM_Zx(M_ASL);
|
||||
break; /* ASL $ss,x ZP,x */
|
||||
|
||||
case 0x35:
|
||||
MR_Zx(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ss,x ZP,x */
|
||||
|
||||
case 0x36:
|
||||
MM_Zx(M_ROL);
|
||||
break; /* ROL $ss,x ZP,x */
|
||||
|
||||
case 0x55:
|
||||
MR_Zx(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ss,x ZP,x */
|
||||
|
||||
case 0x56:
|
||||
MM_Zx(M_LSR);
|
||||
break; /* LSR $ss,x ZP,x */
|
||||
|
||||
case 0x75:
|
||||
MR_Zx(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ss,x ZP,x */
|
||||
|
||||
case 0x76:
|
||||
MM_Zx(M_ROR);
|
||||
break; /* ROR $ss,x ZP,x */
|
||||
|
||||
case 0x94:
|
||||
MW_Zx(R->Y);
|
||||
break; /* STY $ss,x ZP,x */
|
||||
|
||||
case 0x95:
|
||||
MW_Zx(R->A);
|
||||
break; /* STA $ss,x ZP,x */
|
||||
|
||||
case 0x96:
|
||||
MW_Zy(R->X);
|
||||
break; /* STX $ss,y ZP,y */
|
||||
|
||||
case 0xB4:
|
||||
MR_Zx(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ss,x ZP,x */
|
||||
|
||||
case 0xB5:
|
||||
MR_Zx(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ss,x ZP,x */
|
||||
|
||||
case 0xB6:
|
||||
MR_Zy(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ss,y ZP,y */
|
||||
|
||||
case 0xD5:
|
||||
MR_Zx(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ss,x ZP,x */
|
||||
|
||||
case 0xD6:
|
||||
MM_Zx(M_DEC);
|
||||
break; /* DEC $ss,x ZP,x */
|
||||
|
||||
case 0xF5:
|
||||
MR_Zx(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ss,x ZP,x */
|
||||
|
||||
case 0xF6:
|
||||
MM_Zx(M_INC);
|
||||
break; /* INC $ss,x ZP,x */
|
||||
|
||||
|
||||
case 0x19:
|
||||
MR_Ay(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ssss,y ABS,y */
|
||||
|
||||
case 0x1D:
|
||||
MR_Ax(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA $ssss,x ABS,x */
|
||||
|
||||
case 0x1E:
|
||||
MM_Ax(M_ASL);
|
||||
break; /* ASL $ssss,x ABS,x */
|
||||
|
||||
case 0x39:
|
||||
MR_Ay(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ssss,y ABS,y */
|
||||
|
||||
case 0x3D:
|
||||
MR_Ax(I);
|
||||
M_AND(I);
|
||||
break; /* AND $ssss,x ABS,x */
|
||||
|
||||
case 0x3E:
|
||||
MM_Ax(M_ROL);
|
||||
break; /* ROL $ssss,x ABS,x */
|
||||
|
||||
case 0x59:
|
||||
MR_Ay(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ssss,y ABS,y */
|
||||
|
||||
case 0x5D:
|
||||
MR_Ax(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR $ssss,x ABS,x */
|
||||
|
||||
case 0x5E:
|
||||
MM_Ax(M_LSR);
|
||||
break; /* LSR $ssss,x ABS,x */
|
||||
|
||||
case 0x79:
|
||||
MR_Ay(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ssss,y ABS,y */
|
||||
|
||||
case 0x7D:
|
||||
MR_Ax(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC $ssss,x ABS,x */
|
||||
|
||||
case 0x7E:
|
||||
MM_Ax(M_ROR);
|
||||
break; /* ROR $ssss,x ABS,x */
|
||||
|
||||
case 0x99:
|
||||
MW_Ay(R->A);
|
||||
break; /* STA $ssss,y ABS,y */
|
||||
|
||||
case 0x9D:
|
||||
MW_Ax(R->A);
|
||||
break; /* STA $ssss,x ABS,x */
|
||||
|
||||
case 0xB9:
|
||||
MR_Ay(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ssss,y ABS,y */
|
||||
|
||||
case 0xBC:
|
||||
MR_Ax(R->Y);
|
||||
M_FL(R->Y);
|
||||
break; /* LDY $ssss,x ABS,x */
|
||||
|
||||
case 0xBD:
|
||||
MR_Ax(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA $ssss,x ABS,x */
|
||||
|
||||
case 0xBE:
|
||||
MR_Ay(R->X);
|
||||
M_FL(R->X);
|
||||
break; /* LDX $ssss,y ABS,y */
|
||||
|
||||
case 0xD9:
|
||||
MR_Ay(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ssss,y ABS,y */
|
||||
|
||||
case 0xDD:
|
||||
MR_Ax(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP $ssss,x ABS,x */
|
||||
|
||||
case 0xDE:
|
||||
MM_Ax(M_DEC);
|
||||
break; /* DEC $ssss,x ABS,x */
|
||||
|
||||
case 0xF9:
|
||||
MR_Ay(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ssss,y ABS,y */
|
||||
|
||||
case 0xFD:
|
||||
MR_Ax(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC $ssss,x ABS,x */
|
||||
|
||||
case 0xFE:
|
||||
MM_Ax(M_INC);
|
||||
break; /* INC $ssss,x ABS,x */
|
||||
|
||||
|
||||
case 0x01:
|
||||
MR_Ix(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x11:
|
||||
MR_Iy(I);
|
||||
M_ORA(I);
|
||||
break; /* ORA ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x21:
|
||||
MR_Ix(I);
|
||||
M_AND(I);
|
||||
break; /* AND ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x31:
|
||||
MR_Iy(I);
|
||||
M_AND(I);
|
||||
break; /* AND ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x41:
|
||||
MR_Ix(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x51:
|
||||
MR_Iy(I);
|
||||
M_EOR(I);
|
||||
break; /* EOR ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x61:
|
||||
MR_Ix(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x71:
|
||||
MR_Iy(I);
|
||||
M_ADC(I);
|
||||
break; /* ADC ($ss),y INDIRINDEX */
|
||||
|
||||
case 0x81:
|
||||
MW_Ix(R->A);
|
||||
break; /* STA ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0x91:
|
||||
MW_Iy(R->A);
|
||||
break; /* STA ($ss),y INDIRINDEX */
|
||||
|
||||
case 0xA1:
|
||||
MR_Ix(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0xB1:
|
||||
MR_Iy(R->A);
|
||||
M_FL(R->A);
|
||||
break; /* LDA ($ss),y INDIRINDEX */
|
||||
|
||||
case 0xC1:
|
||||
MR_Ix(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0xD1:
|
||||
MR_Iy(I);
|
||||
M_CMP(R->A, I);
|
||||
break; /* CMP ($ss),y INDIRINDEX */
|
||||
|
||||
case 0xE1:
|
||||
MR_Ix(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC ($ss,x) INDEXINDIR */
|
||||
|
||||
case 0xF1:
|
||||
MR_Iy(I);
|
||||
M_SBC(I);
|
||||
break; /* SBC ($ss),y INDIRINDEX */
|
||||
|
||||
|
||||
case 0x0A:
|
||||
M_ASL(R->A);
|
||||
break; /* ASL a ACC */
|
||||
|
||||
case 0x2A:
|
||||
M_ROL(R->A);
|
||||
break; /* ROL a ACC */
|
||||
|
||||
case 0x4A:
|
||||
M_LSR(R->A);
|
||||
break; /* LSR a ACC */
|
||||
|
||||
case 0x6A:
|
||||
M_ROR(R->A);
|
||||
break; /* ROR a ACC */
|
||||
|
||||
@ -1,480 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** Debug.c **/
|
||||
/** **/
|
||||
/** This file contains the built-in debugging routine for **/
|
||||
/** the 6502 emulator which is called on each 6502 step **/
|
||||
/** when Trap!=0. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-1997 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate: 2007-04-19 18:18:57 +0200 (jeu, 19 avr 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/Debug.c $
|
||||
* $Revision: 43 $
|
||||
*/
|
||||
|
||||
#include "M6502.h"
|
||||
#ifdef DEBUG
|
||||
#include <allegro.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <ppu/ppu.h>
|
||||
|
||||
#include <Sound.h>
|
||||
|
||||
#define RDWORD(A) (Rd6502(A+1)*256+Rd6502(A))
|
||||
|
||||
extern unsigned char *Memory;
|
||||
|
||||
void showlastop();
|
||||
|
||||
enum Addressing_Modes
|
||||
{
|
||||
Ac = 0, Il, Im, Ab, Zp, Zx, Zy, Ax, Ay, Rl, Ix, Iy, In, No
|
||||
};
|
||||
|
||||
|
||||
|
||||
static byte *mn[] =
|
||||
{
|
||||
"adc ", "and ", "asl ", "bcc ", "bcs ", "beq ", "bit ", "bmi ",
|
||||
"bne ", "bpl ", "brk", "bvc ", "bvs ", "clc", "cld", "cli",
|
||||
"clv", "cmp ", "cpx ", "cpy ", "dec ", "dex", "dey", "inx",
|
||||
"iny", "eor ", "inc ", "jmp ", "jsr ", "lda ", "nop ", "ldx ",
|
||||
"ldy ", "lsr ", "ora ", "pha", "php", "pla", "plp", "rol ",
|
||||
"ror ", "rti", "rts", "sbc ", "sta ", "stx ", "sty ", "sec ",
|
||||
"sed", "sei", "tax", "tay", "txa", "tya", "tsx", "txs"
|
||||
};
|
||||
|
||||
|
||||
|
||||
static byte ad[512] =
|
||||
{
|
||||
10, Il, 34, Ix, No, No, No, No, No, No, 34, Zp, 2, Zp, No, No,
|
||||
36, Il, 34, Im, 2, Ac, No, No, No, No, 34, Ab, 2, Ab, No, No,
|
||||
9, Rl, 34, Iy, No, No, No, No, No, No, 34, Zx, 2, Zx, No, No,
|
||||
13, Il, 34, Ay, No, No, No, No, No, No, 34, Ax, 2, Ax, No, No,
|
||||
28, Ab, 1, Ix, No, No, No, No, 6, Zp, 1, Zp, 39, Zp, No, No,
|
||||
38, Il, 1, Im, 39, Ac, No, No, 6, Ab, 1, Ab, 39, Ab, No, No,
|
||||
7, Rl, 1, Iy, No, No, No, No, No, No, 1, Zx, 39, Zx, No, No,
|
||||
47, Il, 1, Ay, No, No, No, No, No, No, 1, Ax, 39, Ax, No, No,
|
||||
41, Il, 25, Ix, No, No, No, No, No, No, 25, Zp, 33, Zp, No, No,
|
||||
35, Il, 25, Im, 33, Ac, No, No, 27, Ab, 25, Ab, 33, Ab, No, No,
|
||||
11, Rl, 25, Iy, No, No, No, No, No, No, 25, Zx, 33, Zx, No, No,
|
||||
15, Il, 25, Ay, No, No, No, No, No, No, 25, Ax, 33, Ax, No, No,
|
||||
42, Il, 0, Ix, No, No, No, No, No, No, 0, Zp, 40, Zp, No, No,
|
||||
37, Il, 0, Im, 40, Ac, No, No, 27, In, 0, Ab, 40, Ab, No, No,
|
||||
12, Rl, 0, Iy, No, No, No, No, No, No, 0, Zx, 40, Zx, No, No,
|
||||
49, Il, 0, Ay, No, No, No, No, No, No, 0, Ax, 40, Ax, No, No,
|
||||
No, No, 44, Ix, No, No, No, No, 46, Zp, 44, Zp, 45, Zp, No, No,
|
||||
22, Il, No, No, 52, Il, No, No, 46, Ab, 44, Ab, 45, Ab, No, No,
|
||||
3, Rl, 44, Iy, No, No, No, No, 46, Zx, 44, Zx, 45, Zy, No, No,
|
||||
53, Il, 44, Ay, 55, Il, No, No, No, No, 44, Ax, No, No, No, No,
|
||||
32, Im, 29, Ix, 31, Im, No, No, 32, Zp, 29, Zp, 31, Zp, No, No,
|
||||
51, Il, 29, Im, 50, Il, No, No, 32, Ab, 29, Ab, 31, Ab, No, No,
|
||||
4, Rl, 29, Iy, No, No, No, No, 32, Zx, 29, Zx, 31, Zy, No, No,
|
||||
16, Il, 29, Ay, 54, Il, No, No, 32, Ax, 29, Ax, 31, Ay, No, No,
|
||||
19, Im, 17, Ix, No, No, No, No, 19, Zp, 17, Zp, 20, Zp, No, No,
|
||||
24, Il, 17, Im, 21, Il, No, No, 19, Ab, 17, Ab, 20, Ab, No, No,
|
||||
8, Rl, 17, Iy, No, No, No, No, No, No, 17, Zx, 20, Zx, No, No,
|
||||
14, Il, 17, Ay, No, No, No, No, No, No, 17, Ax, 20, Ax, No, No,
|
||||
18, Im, 43, Ix, No, No, No, No, 18, Zp, 43, Zp, 26, Zp, No, No,
|
||||
23, Il, 43, Im, 30, Il, No, No, 18, Ab, 43, Ab, 26, Ab, No, No,
|
||||
5, Rl, 43, Iy, No, No, No, No, No, No, 43, Zx, 26, Zx, No, No,
|
||||
48, Il, 43, Ay, No, No, No, No, No, No, 43, Ax, 26, Ax, No, No
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** DAsm() ****************************************************/
|
||||
/** This function will disassemble a single command and **/
|
||||
/** return the number of bytes disassembled. **/
|
||||
/**************************************************************/
|
||||
int DAsm(char *S, word A)
|
||||
{
|
||||
|
||||
byte J;
|
||||
|
||||
word B, OP, TO;
|
||||
|
||||
|
||||
B = A;
|
||||
OP = Rd6502(B++) * 2;
|
||||
|
||||
|
||||
switch (ad[OP + 1])
|
||||
|
||||
{
|
||||
|
||||
case Ac:
|
||||
sprintf(S, "%s a", mn[ad[OP]]);
|
||||
break;
|
||||
|
||||
case Il:
|
||||
sprintf(S, "%s", mn[ad[OP]]);
|
||||
break;
|
||||
|
||||
|
||||
case Rl:
|
||||
J = Rd6502(B++);
|
||||
TO = A + 2 + ((J < 0x80) ? J : (J - 256));
|
||||
|
||||
sprintf(S, "%s $%04X", mn[ad[OP]], TO);
|
||||
break;
|
||||
|
||||
|
||||
case Im:
|
||||
sprintf(S, "%s #$%02X", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zp:
|
||||
sprintf(S, "%s $%02X", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zx:
|
||||
sprintf(S, "%s $%02X,x", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Zy:
|
||||
sprintf(S, "%s $%02X,y", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Ix:
|
||||
sprintf(S, "%s ($%02X,x)", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
case Iy:
|
||||
sprintf(S, "%s ($%02X),y", mn[ad[OP]], Rd6502(B++));
|
||||
break;
|
||||
|
||||
|
||||
case Ab:
|
||||
sprintf(S, "%s $%04X", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case Ax:
|
||||
sprintf(S, "%s $%04X,x", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case Ay:
|
||||
sprintf(S, "%s $%04X,y", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
case In:
|
||||
sprintf(S, "%s ($%04X)", mn[ad[OP]], RDWORD(B));
|
||||
B += 2;
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
sprintf(S, ".db $%02X; <Invalid OPcode>", OP / 2);
|
||||
|
||||
}
|
||||
return (B - A);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** Debug6502() **********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the 6502 registers. Emulation exits **/
|
||||
/** if Debug6502() returns 0. **/
|
||||
/*************************************************************/
|
||||
byte Debug6502(M6502 * R)
|
||||
{
|
||||
static char FA[8] = "NVRBDIZC";
|
||||
char S[128];
|
||||
byte F;
|
||||
int J, I;
|
||||
|
||||
DAsm(S, R->PC.W);
|
||||
|
||||
printf
|
||||
(
|
||||
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
|
||||
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
|
||||
);
|
||||
|
||||
|
||||
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
|
||||
|
||||
printf("%c", F & 0x80 ? FA[J] : '.');
|
||||
|
||||
puts("]");
|
||||
|
||||
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
|
||||
Rd6502(R->PC.W), S,
|
||||
Rd6502(0x0100 + (byte) (R->S + 1)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 2)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 3))
|
||||
);
|
||||
|
||||
|
||||
sprintf(S, "");
|
||||
remove_keyboard();
|
||||
|
||||
#ifdef USE_SOUND
|
||||
StopSound();
|
||||
#endif
|
||||
|
||||
|
||||
while (1)
|
||||
{
|
||||
printf("\n[Command,'?']-> ");
|
||||
|
||||
fflush(stdout);
|
||||
fflush(stdin);
|
||||
|
||||
|
||||
fgets(S, 50, stdin);
|
||||
|
||||
for (J = 0; S[J] >= ' '; J++)
|
||||
S[J] = toupper(S[J]);
|
||||
|
||||
S[J] = '\0';
|
||||
|
||||
|
||||
switch (S[0])
|
||||
{
|
||||
case 'H':
|
||||
case '?':
|
||||
puts("\n***** Built-in 6502 Debugger Commands *****");
|
||||
puts("<CR> : Break at the next instruction");
|
||||
puts("= <addr> : Break at addr");
|
||||
puts("+ <offset> : Break at PC + offset");
|
||||
puts("t <addr> : Set PC to addr");
|
||||
puts("c : Continue without break");
|
||||
puts("j <addr> : Continue from addr");
|
||||
puts("m <addr> : Memory dump at addr");
|
||||
puts("d <addr> : Disassembly at addr");
|
||||
puts("v : Show ;interrupt vectors");
|
||||
puts("?,h : Show this help text");
|
||||
puts("r : Show Register Status");
|
||||
puts("q : Exit 6502 emulation");
|
||||
|
||||
puts("----- TI-NES Specific -----");
|
||||
puts("w : Dump Memory State");
|
||||
puts("o : Show PPU registers");
|
||||
puts("p <addr> : Dump PPU memory at addr");
|
||||
puts("a : Dump all memory to memory.log");
|
||||
puts("s : Dump sprite table to sprite.log");
|
||||
puts("n <nb> : Dump name table <nb> to nt.log");
|
||||
puts("z : Show lastest opcode executed");
|
||||
puts("i : SpriteTable Dump");
|
||||
puts("g <nb> : Get sprite <nb> info");
|
||||
break;
|
||||
|
||||
case '\0':
|
||||
return (1);
|
||||
|
||||
case 'Z':
|
||||
showlastop();
|
||||
break;
|
||||
|
||||
case 'W':
|
||||
DumpMemoryState(stdout);
|
||||
break;
|
||||
|
||||
|
||||
case 'A':
|
||||
{
|
||||
|
||||
FILE * fpDmpMem;
|
||||
|
||||
if ((fpDmpMem = fopen("memory.log", "wb")) != NULL)
|
||||
|
||||
{
|
||||
|
||||
// fwrite(Memory, 1, 0x8000, fpDmpMem);
|
||||
//fwrite(mLBank, 1, 0x4000, fpDmpMem);
|
||||
//fwrite(mUBank, 1, 0x4000, fpDmpMem);
|
||||
|
||||
fclose(fpDmpMem);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
case '=':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
sscanf(S + 1, "%hX", &(R->Trap));
|
||||
R->Trace = 0;
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
|
||||
case '+':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
|
||||
sscanf(S + 1, "%hX", &(R->Trap));
|
||||
|
||||
R->Trap += R->PC.W;
|
||||
R->Trace = 0;
|
||||
|
||||
return (1);
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case 'J':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
sscanf(S + 1, "%hX", &(R->PC.W));
|
||||
R->Trace = 0;
|
||||
return (1);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
if (strlen(S) >= 2)
|
||||
|
||||
{
|
||||
sscanf(S + 1, "%hX", &(R->PC.W));
|
||||
R->Trace = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
R->Trap = 0xFFFF;
|
||||
R->Trace = 0;
|
||||
install_keyboard();
|
||||
|
||||
//ResumeSound();
|
||||
|
||||
SetSound(0, SND_RECTANGLE);
|
||||
SetSound(1, SND_RECTANGLE);
|
||||
SetSound(2, SND_TRIANGLE);
|
||||
SetSound(3, SND_NOISE);
|
||||
|
||||
return (1);
|
||||
|
||||
case 'Q':
|
||||
return (0);
|
||||
|
||||
|
||||
case 'V':
|
||||
puts("\n6502 Interrupt Vectors:");
|
||||
printf("[$FFFC] INIT: $%04X\n", Rd6502(0xFFFC) + 256 * Rd6502(0xFFFD));
|
||||
printf("[$FFFE] IRQ: $%04X\n", Rd6502(0xFFFE) + 256 * Rd6502(0xFFFF));
|
||||
printf("[$FFFA] NMI: $%04X\n", Rd6502(0xFFFA) + 256 * Rd6502(0xFFFB));
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
{
|
||||
word Addr;
|
||||
|
||||
if (strlen(S) > 1)
|
||||
sscanf(S + 1, "%hX", &Addr);
|
||||
else
|
||||
Addr = R->PC.W;
|
||||
puts("");
|
||||
for (J = 0; J < 16; J++)
|
||||
{
|
||||
printf("%04X: ", Addr);
|
||||
for (I = 0; I < 16; I++, Addr++)
|
||||
|
||||
printf("%02X ", Rd6502(Addr));
|
||||
|
||||
printf(" | ");
|
||||
Addr -= 16;
|
||||
|
||||
for (I = 0; I < 16; I++, Addr++)
|
||||
|
||||
putchar(isprint(Rd6502(Addr)) ? Rd6502(Addr) : '.');
|
||||
|
||||
puts("");
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
|
||||
printf
|
||||
(
|
||||
"A:%02X P:%02X X:%02X Y:%02X S:%04X PC:%04X Flags:[",
|
||||
R->A, R->P, R->X, R->Y, R->S + 0x0100, R->PC.W
|
||||
);
|
||||
|
||||
|
||||
for (J = 0, F = R->P; J < 8; J++, F <<= 1)
|
||||
|
||||
printf("%c", F & 0x80 ? FA[J] : '.');
|
||||
|
||||
puts("]");
|
||||
|
||||
|
||||
printf
|
||||
(
|
||||
"AT PC: [%02X - %s] AT SP: [%02X %02X %02X]\n",
|
||||
Rd6502(R->PC.W), S,
|
||||
Rd6502(0x0100 + (byte) (R->S + 1)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 2)),
|
||||
Rd6502(0x0100 + (byte) (R->S + 3))
|
||||
);
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case 'D':
|
||||
|
||||
{
|
||||
|
||||
word Addr;
|
||||
|
||||
|
||||
if (strlen(S) > 1)
|
||||
sscanf(S + 1, "%hX", &Addr);
|
||||
else
|
||||
Addr = R->PC.W;
|
||||
|
||||
puts("");
|
||||
|
||||
for (J = 0; J < 16; J++)
|
||||
|
||||
{
|
||||
|
||||
printf("%04X: ", Addr);
|
||||
|
||||
Addr += DAsm(S, Addr);
|
||||
|
||||
puts(S);
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* Continue with emulation */
|
||||
return (1);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* DEBUG */
|
||||
@ -1,317 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** M6502.c **/
|
||||
/** **/
|
||||
/** This file contains implementation for 6502 CPU. Don't **/
|
||||
/** forget to provide Rd6502(), Wr6502(), Loop6502(), and **/
|
||||
/** possibly Op6502() functions to accomodate the emulated **/
|
||||
/** machine's architecture. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/M6502.c $
|
||||
* $Revision: 39 $
|
||||
*/
|
||||
|
||||
#include "M6502.h"
|
||||
#include "Tables.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/** INLINE ***************************************************/
|
||||
/** Different compilers inline C functions differently. **/
|
||||
/*************************************************************/
|
||||
#ifdef __GNUC__
|
||||
#define INLINE inline
|
||||
#else
|
||||
#define INLINE static
|
||||
#endif
|
||||
|
||||
int icount = 0;
|
||||
|
||||
/** System-Dependent Stuff ***********************************/
|
||||
/** This is system-dependent code put here to speed things **/
|
||||
/** up. It has to stay inlined to be fast. **/
|
||||
/*************************************************************/
|
||||
#ifdef INES
|
||||
#define FAST_RDOP
|
||||
extern byte *Page[];
|
||||
INLINE byte Op6502(register word A) { return(Page[A>>13][A&0x1FFF]); }
|
||||
#endif
|
||||
|
||||
/** FAST_RDOP ************************************************/
|
||||
/** With this #define not present, Rd6502() should perform **/
|
||||
/** the functions of Rd6502(). **/
|
||||
/*************************************************************/
|
||||
#ifndef FAST_RDOP
|
||||
#define Op6502(A) Rd6502(A)
|
||||
#endif
|
||||
|
||||
/** Addressing Methods ***************************************/
|
||||
/** These macros calculate and return effective addresses. **/
|
||||
/*************************************************************/
|
||||
#define MC_Ab(Rg) M_LDWORD(Rg)
|
||||
#define MC_Zp(Rg) Rg.W=Op6502(R->PC.W++)
|
||||
#define MC_Zx(Rg) Rg.W=(byte)(Op6502(R->PC.W++)+R->X)
|
||||
#define MC_Zy(Rg) Rg.W=(byte)(Op6502(R->PC.W++)+R->Y)
|
||||
#define MC_Ax(Rg) M_LDWORD(Rg);Rg.W+=R->X
|
||||
#define MC_Ay(Rg) M_LDWORD(Rg);Rg.W+=R->Y
|
||||
#define MC_Ix(Rg) K.W=(byte)(Op6502(R->PC.W++)+R->X); \
|
||||
Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W)
|
||||
#define MC_Iy(Rg) K.W=Op6502(R->PC.W++); \
|
||||
Rg.B.l=Op6502(K.W++);Rg.B.h=Op6502(K.W); \
|
||||
Rg.W+=R->Y
|
||||
|
||||
/** Reading From Memory **************************************/
|
||||
/** These macros calculate address and read from it. **/
|
||||
/*************************************************************/
|
||||
#define MR_Ab(Rg) MC_Ab(J);Rg=Rd6502(J.W)
|
||||
#define MR_Im(Rg) Rg=Op6502(R->PC.W++)
|
||||
#define MR_Zp(Rg) MC_Zp(J);Rg=Rd6502(J.W)
|
||||
#define MR_Zx(Rg) MC_Zx(J);Rg=Rd6502(J.W)
|
||||
#define MR_Zy(Rg) MC_Zy(J);Rg=Rd6502(J.W)
|
||||
#define MR_Ax(Rg) MC_Ax(J);Rg=Rd6502(J.W)
|
||||
#define MR_Ay(Rg) MC_Ay(J);Rg=Rd6502(J.W)
|
||||
#define MR_Ix(Rg) MC_Ix(J);Rg=Rd6502(J.W)
|
||||
#define MR_Iy(Rg) MC_Iy(J);Rg=Rd6502(J.W)
|
||||
|
||||
/** Writing To Memory ****************************************/
|
||||
/** These macros calculate address and write to it. **/
|
||||
/*************************************************************/
|
||||
#define MW_Ab(Rg) MC_Ab(J);Wr6502(J.W,Rg)
|
||||
#define MW_Zp(Rg) MC_Zp(J);Wr6502(J.W,Rg)
|
||||
#define MW_Zx(Rg) MC_Zx(J);Wr6502(J.W,Rg)
|
||||
#define MW_Zy(Rg) MC_Zy(J);Wr6502(J.W,Rg)
|
||||
#define MW_Ax(Rg) MC_Ax(J);Wr6502(J.W,Rg)
|
||||
#define MW_Ay(Rg) MC_Ay(J);Wr6502(J.W,Rg)
|
||||
#define MW_Ix(Rg) MC_Ix(J);Wr6502(J.W,Rg)
|
||||
#define MW_Iy(Rg) MC_Iy(J);Wr6502(J.W,Rg)
|
||||
|
||||
/** Modifying Memory *****************************************/
|
||||
/** These macros calculate address and modify it. **/
|
||||
/*************************************************************/
|
||||
#define MM_Ab(Cmd) MC_Ab(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
#define MM_Zp(Cmd) MC_Zp(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
#define MM_Zx(Cmd) MC_Zx(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
#define MM_Ax(Cmd) MC_Ax(J);I=Rd6502(J.W);Cmd(I);Wr6502(J.W,I)
|
||||
|
||||
/** Other Macros *********************************************/
|
||||
/** Calculating flags, stack, jumps, arithmetics, etc. **/
|
||||
/*************************************************************/
|
||||
#define M_FL(Rg) R->P=(R->P&~(Z_FLAG|N_FLAG))|ZNTable[Rg]
|
||||
#define M_LDWORD(Rg) Rg.B.l=Op6502(R->PC.W++);Rg.B.h=Op6502(R->PC.W++)
|
||||
|
||||
#define M_PUSH(Rg) Wr6502(0x0100|R->S,Rg);R->S--
|
||||
#define M_POP(Rg) R->S++;Rg=Op6502(0x0100|R->S)
|
||||
#define M_JR R->PC.W+=(offset)Op6502(R->PC.W)+1;R->ICount--
|
||||
|
||||
#ifdef NO_DECIMAL
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
K.W=R->A+Rg+(R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l
|
||||
|
||||
/* Warning! C_FLAG is inverted before SBC and after it */
|
||||
#define M_SBC(Rg) \
|
||||
K.W=R->A-Rg-(~R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l
|
||||
|
||||
#else /* NO_DECIMAL */
|
||||
|
||||
#define M_ADC(Rg) \
|
||||
if(R->P&D_FLAG) \
|
||||
{ \
|
||||
K.B.l=(R->A&0x0F)+(Rg&0x0F)+(R->P&C_FLAG); \
|
||||
if(K.B.l>9) K.B.l+=6; \
|
||||
K.B.h=(R->A>>4)+(Rg>>4)+(K.B.l>15? 1:0); \
|
||||
R->A=(K.B.l&0x0F)|(K.B.h<<4); \
|
||||
R->P=(R->P&~C_FLAG)|(K.B.h>15? C_FLAG:0); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
K.W=R->A+Rg+(R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=(~(R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? C_FLAG:0)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l; \
|
||||
}
|
||||
|
||||
/* Warning! C_FLAG is inverted before SBC and after it */
|
||||
#define M_SBC(Rg) \
|
||||
if(R->P&D_FLAG) \
|
||||
{ \
|
||||
K.B.l=(R->A&0x0F)-(Rg&0x0F)-(~R->P&C_FLAG); \
|
||||
if(K.B.l&0x10) K.B.l-=6; \
|
||||
K.B.h=(R->A>>4)-(Rg>>4)-((K.B.l&0x10)>>4); \
|
||||
if(K.B.h&0x10) K.B.h-=6; \
|
||||
R->A=(K.B.l&0x0F)|(K.B.h<<4); \
|
||||
R->P=(R->P&~C_FLAG)|(K.B.h>15? 0:C_FLAG); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
K.W=R->A-Rg-(~R->P&C_FLAG); \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=((R->A^Rg)&(R->A^K.B.l)&0x80? V_FLAG:0)| \
|
||||
(K.B.h? 0:C_FLAG)|ZNTable[K.B.l]; \
|
||||
R->A=K.B.l; \
|
||||
}
|
||||
|
||||
#endif /* NO_DECIMAL */
|
||||
|
||||
#define M_CMP(Rg1,Rg2) \
|
||||
K.W=Rg1-Rg2; \
|
||||
R->P&=~(N_FLAG|Z_FLAG|C_FLAG); \
|
||||
R->P|=ZNTable[K.B.l]|(K.B.h? 0:C_FLAG)
|
||||
#define M_BIT(Rg) \
|
||||
R->P&=~(N_FLAG|V_FLAG|Z_FLAG); \
|
||||
R->P|=(Rg&(N_FLAG|V_FLAG))|(Rg&R->A? 0:Z_FLAG)
|
||||
|
||||
#define M_AND(Rg) R->A&=Rg;M_FL(R->A)
|
||||
#define M_ORA(Rg) R->A|=Rg;M_FL(R->A)
|
||||
#define M_EOR(Rg) R->A^=Rg;M_FL(R->A)
|
||||
#define M_INC(Rg) Rg++;M_FL(Rg)
|
||||
#define M_DEC(Rg) Rg--;M_FL(Rg)
|
||||
|
||||
#define M_ASL(Rg) R->P&=~C_FLAG;R->P|=Rg>>7;Rg<<=1;M_FL(Rg)
|
||||
#define M_LSR(Rg) R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg>>=1;M_FL(Rg)
|
||||
#define M_ROL(Rg) K.B.l=(Rg<<1)|(R->P&C_FLAG); \
|
||||
R->P&=~C_FLAG;R->P|=Rg>>7;Rg=K.B.l; \
|
||||
M_FL(Rg)
|
||||
#define M_ROR(Rg) K.B.l=(Rg>>1)|(R->P<<7); \
|
||||
R->P&=~C_FLAG;R->P|=Rg&C_FLAG;Rg=K.B.l; \
|
||||
M_FL(Rg)
|
||||
|
||||
/** Reset6502() **********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with Run6502(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void Reset6502(M6502 *R)
|
||||
{
|
||||
R->A=R->X=R->Y=0x00;
|
||||
R->P=Z_FLAG|R_FLAG;
|
||||
R->S=0xFF;
|
||||
R->PC.B.l=Rd6502(0xFFFC);
|
||||
R->PC.B.h=Rd6502(0xFFFD);
|
||||
R->ICount=R->IPeriod;
|
||||
R->IRequest=INT_NONE;
|
||||
R->AfterCLI=0;
|
||||
}
|
||||
|
||||
/** Exec6502() ***********************************************/
|
||||
/** This function will execute a single 6502 opcode. It **/
|
||||
/** will then return next PC, and current register values **/
|
||||
/** in R. **/
|
||||
/*************************************************************/
|
||||
word Exec6502(M6502 *R)
|
||||
{
|
||||
register pair J,K;
|
||||
register byte I;
|
||||
|
||||
I=Op6502(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
}
|
||||
|
||||
/* We are done */
|
||||
return(R->PC.W);
|
||||
}
|
||||
|
||||
/** Int6502() ************************************************/
|
||||
/** This function will generate interrupt of a given type. **/
|
||||
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ **/
|
||||
/** will cause a normal interrupt, unless I_FLAG set in R. **/
|
||||
/*************************************************************/
|
||||
void Int6502(M6502 *R,byte Type)
|
||||
{
|
||||
register pair J;
|
||||
|
||||
if((Type==INT_NMI)||((Type==INT_IRQ)&&!(R->P&I_FLAG)))
|
||||
{
|
||||
R->ICount-=7;
|
||||
M_PUSH(R->PC.B.h);
|
||||
M_PUSH(R->PC.B.l);
|
||||
M_PUSH(R->P&~B_FLAG);
|
||||
R->P&=~D_FLAG;
|
||||
if(R->IAutoReset&&(Type==R->IRequest)) R->IRequest=INT_NONE;
|
||||
if(Type==INT_NMI) J.W=0xFFFA; else { R->P|=I_FLAG;J.W=0xFFFE; }
|
||||
R->PC.B.l=Rd6502(J.W++);
|
||||
R->PC.B.h=Rd6502(J.W);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Run6502() ************************************************/
|
||||
/** This function will run 6502 code until Loop6502() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word Run6502(M6502 *R)
|
||||
{
|
||||
register pair J,K;
|
||||
register byte I;
|
||||
|
||||
for(;;)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
/* Turn tracing on when reached trap address */
|
||||
if(R->PC.W==R->Trap) R->Trace=1;
|
||||
/* Call single-step debugger, exit if requested */
|
||||
if(R->Trace)
|
||||
if(!Debug6502(R)) return(R->PC.W);
|
||||
#endif
|
||||
|
||||
I=Op6502(R->PC.W++);
|
||||
R->ICount-=Cycles[I];
|
||||
|
||||
//#ifdef DEBUG
|
||||
// pushop(I);
|
||||
//#endif
|
||||
|
||||
icount++;
|
||||
|
||||
switch(I)
|
||||
{
|
||||
#include "Codes.h"
|
||||
}
|
||||
|
||||
/* If cycle counter expired... */
|
||||
if(R->ICount<=0)
|
||||
{
|
||||
/* If we have come after CLI, get INT_? from IRequest */
|
||||
/* Otherwise, get it from the loop handler */
|
||||
if(R->AfterCLI)
|
||||
{
|
||||
I=R->IRequest; /* Get pending interrupt */
|
||||
R->ICount+=R->IBackup-1; /* Restore the ICount */
|
||||
R->AfterCLI=0; /* Done with AfterCLI state */
|
||||
}
|
||||
else
|
||||
{
|
||||
I=Loop6502(R); /* Call the periodic handler */
|
||||
R->ICount+=R->IPeriod; /* Reset the cycle counter */
|
||||
if(!I) I=R->IRequest; /* Realize pending interrupt */
|
||||
}
|
||||
|
||||
if(I==INT_QUIT) return(R->PC.W); /* Exit if INT_QUIT */
|
||||
if(I) Int6502(R,I); /* Interrupt if needed */
|
||||
}
|
||||
}
|
||||
|
||||
/* Execution stopped */
|
||||
return(R->PC.W);
|
||||
}
|
||||
@ -1,148 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** M6502.h **/
|
||||
/** **/
|
||||
/** This file contains declarations relevant to emulation **/
|
||||
/** of 6502 CPU. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** Alex Krasivsky 1996 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate: 2007-04-23 18:55:35 +0200 (lun, 23 avr 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/M6502.h $
|
||||
* $Revision: 45 $
|
||||
*/
|
||||
|
||||
#ifndef M6502_H
|
||||
#define M6502_H
|
||||
/* Loop6502() returns: */
|
||||
#define INT_NONE 0 /* No interrupt required */
|
||||
#define INT_IRQ 1 /* Standard IRQ interrupt */
|
||||
#define INT_NMI 2 /* Non-maskable interrupt */
|
||||
#define INT_QUIT 3 /* Exit the emulation */
|
||||
|
||||
/* 6502 status flags: */
|
||||
#define C_FLAG 0x01 /* 1: Carry occured */
|
||||
#define Z_FLAG 0x02 /* 1: Result is zero */
|
||||
#define I_FLAG 0x04 /* 1: Interrupts disabled */
|
||||
#define D_FLAG 0x08 /* 1: Decimal mode */
|
||||
#define B_FLAG 0x10 /* Break [0 on stk after int] */
|
||||
#define R_FLAG 0x20 /* Always 1 */
|
||||
#define V_FLAG 0x40 /* 1: Overflow occured */
|
||||
#define N_FLAG 0x80 /* 1: Result is negative */
|
||||
|
||||
/** Simple Datatypes *****************************************/
|
||||
/** NOTICE: sizeof(byte)=1 and sizeof(word)=2 **/
|
||||
/*************************************************************/
|
||||
#ifndef BYTE_TYPE_DEFINED
|
||||
#define BYTE_TYPE_DEFINED
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
#ifndef WORD_TYPE_DEFINED
|
||||
#define WORD_TYPE_DEFINED
|
||||
typedef unsigned short word;
|
||||
#endif
|
||||
typedef signed char offset;
|
||||
|
||||
/** Structured Datatypes *************************************/
|
||||
/** NOTICE: #define LSB_FIRST for machines where least **/
|
||||
/** signifcant byte goes first. **/
|
||||
/*************************************************************/
|
||||
typedef union
|
||||
{
|
||||
#ifdef LSB_FIRST
|
||||
struct { byte l,h; } B;
|
||||
#else
|
||||
struct { byte h,l; } B;
|
||||
#endif
|
||||
word W;
|
||||
} pair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
byte A,P,X,Y,S; /* CPU registers and program counter */
|
||||
pair PC;
|
||||
|
||||
int IPeriod,ICount; /* Set IPeriod to number of CPU cycles */
|
||||
/* between calls to Loop6502() */
|
||||
byte IRequest; /* Set to the INT_IRQ when pending IRQ */
|
||||
byte AfterCLI; /* Private, don't touch */
|
||||
int IBackup; /* Private, don't touch */
|
||||
byte IAutoReset; /* Set to 1 to autom. reset IRequest */
|
||||
byte TrapBadOps; /* Set to 1 to warn of illegal opcodes */
|
||||
word Trap; /* Set Trap to address to trace from */
|
||||
byte Trace; /* Set Trace=1 to start tracing */
|
||||
void *User; /* Arbitrary user data (ID,RAM*,etc.) */
|
||||
} M6502;
|
||||
|
||||
/** Reset6502() **********************************************/
|
||||
/** This function can be used to reset the registers before **/
|
||||
/** starting execution with Run6502(). It sets registers to **/
|
||||
/** their initial values. **/
|
||||
/*************************************************************/
|
||||
void Reset6502(register M6502 *R);
|
||||
|
||||
/** Exec6502() ***********************************************/
|
||||
/** This function will execute a single 6502 opcode. It **/
|
||||
/** will then return next PC, and current register values **/
|
||||
/** in R. **/
|
||||
/*************************************************************/
|
||||
word Exec6502(register M6502 *R);
|
||||
|
||||
/** Int6502() ************************************************/
|
||||
/** This function will generate interrupt of a given type. **/
|
||||
/** INT_NMI will cause a non-maskable interrupt. INT_IRQ **/
|
||||
/** will cause a normal interrupt, unless I_FLAG set in R. **/
|
||||
/*************************************************************/
|
||||
void Int6502(register M6502 *R,register byte Type);
|
||||
|
||||
/** Run6502() ************************************************/
|
||||
/** This function will run 6502 code until Loop6502() call **/
|
||||
/** returns INT_QUIT. It will return the PC at which **/
|
||||
/** emulation stopped, and current register values in R. **/
|
||||
/*************************************************************/
|
||||
word Run6502(register M6502 *R);
|
||||
|
||||
/** Rd6502()/Wr6502/Op6502() *********************************/
|
||||
/** These functions are called when access to RAM occurs. **/
|
||||
/** They allow to control memory access. Op6502 is the same **/
|
||||
/** as Rd6502, but used to read *opcodes* only, when many **/
|
||||
/** checks can be skipped to make it fast. It is only **/
|
||||
/** required if there is a #define FAST_RDOP. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
void Wr6502(register word Addr,register byte Value);
|
||||
byte Rd6502(register word Addr);
|
||||
byte Op6502(register word Addr);
|
||||
|
||||
/** Debug6502() **********************************************/
|
||||
/** This function should exist if DEBUG is #defined. When **/
|
||||
/** Trace!=0, it is called after each command executed by **/
|
||||
/** the CPU, and given the 6502 registers. Emulation exits **/
|
||||
/** if Debug6502() returns 0. **/
|
||||
/*************************************************************/
|
||||
byte Debug6502(register M6502 *R);
|
||||
|
||||
/** Loop6502() ***********************************************/
|
||||
/** 6502 emulation calls this function periodically to **/
|
||||
/** check if the system hardware requires any interrupts. **/
|
||||
/** This function must return one of following values: **/
|
||||
/** INT_NONE, INT_IRQ, INT_NMI, or INT_QUIT to exit the **/
|
||||
/** emulation loop. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
byte Loop6502(register M6502 *R);
|
||||
|
||||
/** Patch6502() **********************************************/
|
||||
/** Emulation calls this function when it encounters an **/
|
||||
/** unknown opcode. This can be used to patch the code to **/
|
||||
/** emulate BIOS calls, such as disk and tape access. The **/
|
||||
/** function should return 1 if the exception was handled, **/
|
||||
/** or 0 if the opcode was truly illegal. **/
|
||||
/************************************ TO BE WRITTEN BY USER **/
|
||||
byte Patch6502(register byte Op,register M6502 *R);
|
||||
|
||||
#endif /* M6502_H */
|
||||
@ -1,71 +0,0 @@
|
||||
/** M6502: portable 6502 emulator ****************************/
|
||||
/** **/
|
||||
/** Tables.h **/
|
||||
/** **/
|
||||
/** This file contains tables of used by 6502 emulation to **/
|
||||
/** compute NEGATIVE and ZERO flags. There are also timing **/
|
||||
/** tables for 6502 opcodes. This file is included from **/
|
||||
/** 6502.c. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2002 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
/*
|
||||
* $LastChangedDate: 2007-05-24 15:07:13 +0200 (jeu, 24 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/Tables.h $
|
||||
* $Revision: 52 $
|
||||
*/
|
||||
|
||||
static byte Cycles[256] =
|
||||
{
|
||||
7, 6, 2, 1, 5, 3, 5, 5, 3, 2, 2, 1, 6, 4, 6, 2,
|
||||
2, 5, 5, 1, 5, 4, 6, 5, 2, 4, 2, 1, 6, 4, 6, 2,
|
||||
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 4, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 2, 1, 4, 4, 6, 2,
|
||||
6, 6, 2, 1, 3, 3, 5, 5, 3, 2, 2, 1, 3, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 1, 8, 4, 6, 2,
|
||||
6, 6, 2, 1, 3, 3, 5, 5, 4, 2, 2, 1, 6, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 5, 4, 4, 1, 6, 4, 6, 2,
|
||||
3, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
|
||||
2, 6, 5, 1, 4, 4, 4, 5, 2, 5, 2, 1, 4, 5, 5, 2,
|
||||
2, 6, 2, 1, 3, 3, 3, 5, 2, 2, 2, 1, 4, 4, 4, 2,
|
||||
2, 5, 5, 1, 4, 4, 4, 5, 2, 4, 2, 1, 4, 4, 4, 2,
|
||||
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 2, 4, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 3, 2, 4, 4, 6, 2,
|
||||
2, 6, 2, 1, 3, 3, 5, 5, 2, 2, 2, 1, 4, 4, 6, 2,
|
||||
2, 5, 5, 1, 4, 4, 6, 5, 2, 4, 4, 1, 4, 4, 6, 2
|
||||
};
|
||||
|
||||
|
||||
byte ZNTable[256] =
|
||||
{
|
||||
|
||||
Z_FLAG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG, N_FLAG,
|
||||
};
|
||||
|
||||
2342
src/corecpu/corecpu.c
Normal file
2342
src/corecpu/corecpu.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,20 +1,16 @@
|
||||
/*
|
||||
* Cart manager - The TI-NESulator Project
|
||||
* Cart manager - The peTI-NESulator Project
|
||||
* NESCart.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/NESCarts.h $
|
||||
* $Revision: 39 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*/
|
||||
|
||||
#ifndef NESCARTS_H
|
||||
#define NESCARTS_H
|
||||
|
||||
#include "types.h"
|
||||
#include <stdint.h>
|
||||
#include <types.h>
|
||||
|
||||
#define iNES_MIRROR 0x01
|
||||
#define iNES_BATTERY 0x02
|
||||
@ -22,18 +18,18 @@
|
||||
#define iNES_4SCREEN 0x08
|
||||
|
||||
typedef struct NesCart_
|
||||
{
|
||||
unsigned long PROMSize, /* Size of PROM */
|
||||
VROMSize; /* Size of VROM */
|
||||
char MapperID; /* Mapper Type */
|
||||
byte Flags;
|
||||
{
|
||||
uint32_t PROMSize, /* Size of PROM */
|
||||
VROMSize; /* Size of VROM */
|
||||
char MapperID; /* Mapper Type */
|
||||
uint8_t Flags;
|
||||
char *FileName;
|
||||
byte *File; /* Pointer on the file in memory */
|
||||
byte *PROMBanks; /* Pointer on the first PROM */
|
||||
byte *VROMBanks; /* Pointer on the first VROM */
|
||||
uint8_t *File; /* Pointer on the file in memory */
|
||||
uint8_t *PROMBanks; /* Pointer on the first PROM */
|
||||
uint8_t *VROMBanks; /* Pointer on the first VROM */
|
||||
} NesCart;
|
||||
|
||||
void DumpCartProperties();
|
||||
int LoadCart(const char *filename, NesCart * cart);
|
||||
void DumpCartProperties(FILE *out, NesCart *cart);
|
||||
int LoadCart(const char *filename, NesCart *cart);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,232 +0,0 @@
|
||||
/** EMULib Emulation Library *********************************/
|
||||
/** **/
|
||||
/** Sound.h **/
|
||||
/** **/
|
||||
/** This file defines standard sound generation API and **/
|
||||
/** functions needed to log soundtrack into a MIDI file. **/
|
||||
/** See Sound.c and the sound drivers for the code. **/
|
||||
/** **/
|
||||
/** Copyright (C) Marat Fayzullin 1996-2007 **/
|
||||
/** You are not allowed to distribute this software **/
|
||||
/** commercially. Please, notify me, if you make any **/
|
||||
/** changes to this file. **/
|
||||
/*************************************************************/
|
||||
|
||||
#ifndef SOUND_H
|
||||
#define SOUND_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* SetSound() arguments: */
|
||||
#define SND_MELODIC 0 /* Melodic sound (default) */
|
||||
#define SND_RECTANGLE 0 /* Rectangular wave */
|
||||
#define SND_QS_DU0 5
|
||||
#define SND_QS_DU1 6
|
||||
#define SND_QS_DU2 7
|
||||
#define SND_QS_DU3 8
|
||||
#define SND_TRIANGLE 1 /* Triangular wave (1/2 rect.)*/
|
||||
#define SND_NOISE 2 /* White noise */
|
||||
#define SND_PERIODIC 3 /* Periodic noise (not im-ed) */
|
||||
#define SND_WAVE 4 /* Wave sound set by SetWave()*/
|
||||
#define SND_MIDI 0x100 /* MIDI instrument (ORable) */
|
||||
|
||||
/* Drum() arguments: */
|
||||
#define DRM_CLICK 0 /* Click (default) */
|
||||
#define DRM_MIDI 0x100 /* MIDI drum (ORable) */
|
||||
|
||||
/* MIDI characteristics: */
|
||||
#define MIDI_CHANNELS 16 /* Number of MIDI channels */
|
||||
#define MIDI_MINFREQ 9 /* Min MIDI frequency (Hz) */
|
||||
#define MIDI_MAXFREQ 12285 /* Max MIDI frequency (Hz) */
|
||||
#define MIDI_DIVISIONS 1000 /* Number of ticks per second */
|
||||
|
||||
/* MIDILogging() arguments: */
|
||||
#define MIDI_OFF 0 /* Turn MIDI logging off */
|
||||
#define MIDI_ON 1 /* Turn MIDI logging on */
|
||||
#define MIDI_TOGGLE 2 /* Toggle MIDI logging */
|
||||
#define MIDI_QUERY 3 /* Query MIDI logging status */
|
||||
|
||||
/** TrashSound() *********************************************/
|
||||
/** Shut down sound driver. Each driver implements its own **/
|
||||
/** TrashSound() function. **/
|
||||
/*************************************************************/
|
||||
void TrashSound(void);
|
||||
|
||||
/** Sound() **************************************************/
|
||||
/** Generate sound of given frequency (Hz) and volume **/
|
||||
/** (0..255) via given channel. Setting Freq=0 or Volume=0 **/
|
||||
/** turns sound off. **/
|
||||
/*************************************************************/
|
||||
void Sound(int Channel,int Freq,int Volume);
|
||||
|
||||
/** Drum() ***************************************************/
|
||||
/** Hit a drum of given type with given force (0..255). **/
|
||||
/** MIDI drums can be used by ORing their numbers with **/
|
||||
/** SND_MIDI. **/
|
||||
/*************************************************************/
|
||||
void Drum(int Type,int Force);
|
||||
|
||||
/** SetSound() ***********************************************/
|
||||
/** Set sound type at a given channel. MIDI instruments can **/
|
||||
/** be set directly by ORing their numbers with SND_MIDI. **/
|
||||
/*************************************************************/
|
||||
void SetSound(int Channel,int NewType);
|
||||
|
||||
/** SetChannels() ********************************************/
|
||||
/** Set master volume (0..255) and switch channels on/off. **/
|
||||
/** Each channel N has corresponding bit 2^N in Switch. Set **/
|
||||
/** or reset this bit to turn the channel on or off. **/
|
||||
/*************************************************************/
|
||||
void SetChannels(int Volume,int Switch);
|
||||
|
||||
/** SetWave() ************************************************/
|
||||
/** Set waveform for a given channel. The channel will be **/
|
||||
/** marked with sound type SND_WAVE. Set Rate=0 if you want **/
|
||||
/** waveform to be an instrument or set it to the waveform **/
|
||||
/** own playback rate. **/
|
||||
/*************************************************************/
|
||||
void SetWave(int Channel,const signed char *Data,int Length,int Rate);
|
||||
|
||||
/** GetWave() ************************************************/
|
||||
/** Get current read position for the buffer set with the **/
|
||||
/** SetWave() call. Returns 0 if no buffer has been set, or **/
|
||||
/** if there is no playrate set (i.e. wave is instrument). **/
|
||||
/*************************************************************/
|
||||
const signed char *GetWave(int Channel);
|
||||
|
||||
/** InitMIDI() ***********************************************/
|
||||
/** Initialize soundtrack logging into MIDI file FileName. **/
|
||||
/** Repeated calls to InitMIDI() will close current MIDI **/
|
||||
/** file and continue logging into a new one. **/
|
||||
/*************************************************************/
|
||||
void InitMIDI(const char *FileName);
|
||||
|
||||
/** TrashMIDI() **********************************************/
|
||||
/** Finish logging soundtrack and close the MIDI file. **/
|
||||
/*************************************************************/
|
||||
void TrashMIDI(void);
|
||||
|
||||
/** MIDILogging() ********************************************/
|
||||
/** Turn soundtrack logging on/off and return its current **/
|
||||
/** status. Possible values of Switch are MIDI_OFF (turn **/
|
||||
/** logging off), MIDI_ON (turn logging on), MIDI_TOGGLE **/
|
||||
/** (toggle logging), and MIDI_QUERY (just return current **/
|
||||
/** state of logging). **/
|
||||
/*************************************************************/
|
||||
int MIDILogging(int Switch);
|
||||
|
||||
/** MIDITicks() **********************************************/
|
||||
/** Log N 1ms MIDI ticks. **/
|
||||
/*************************************************************/
|
||||
void MIDITicks(int N);
|
||||
|
||||
//#ifdef UNIX
|
||||
#define SND_CHANNELS 16 /* Number of channels */
|
||||
#define SND_SAMPLESIZE 256 /* Max. SetWave() sample size */
|
||||
#define SND_BUFSIZE 256 /* Buffer size, <= 2^SND_BITS */
|
||||
#define SND_BITS 8 /* Number of bits in a fragment */
|
||||
#define SND_BUFFERS 64 /* Number of fragments, >= 2 */
|
||||
/* Bigger value results in better behaviour on loaded */
|
||||
/* but output gets more delayed. */
|
||||
|
||||
/** InitSound() **********************************************/
|
||||
/** Initialize Unix sound driver with given synthesis rate. **/
|
||||
/** Returns Rate on success, 0 otherwise. Pass Rate=0 to **/
|
||||
/** skip initialization and be silent. Pass Verbose!=0 to **/
|
||||
/** see initialization messages. **/
|
||||
/*************************************************************/
|
||||
#warning You Suck !
|
||||
int InitSound(int Rate,int Verbose);
|
||||
|
||||
/** StopSound() **********************************************/
|
||||
/** Temporarily suspend sound. **/
|
||||
/*************************************************************/
|
||||
void StopSound(void);
|
||||
|
||||
/** ResumeSound() ********************************************/
|
||||
/** Resume sound after StopSound(). **/
|
||||
/*************************************************************/
|
||||
void ResumeSound(void);
|
||||
//#endif /* UNIX */
|
||||
|
||||
#ifdef MSDOS
|
||||
#define SND_CHANNELS 16 /* Number of sound channels */
|
||||
#define OPL_CHANNELS 7 /* Number of Adlib channels */
|
||||
#define SND_SAMPLESIZE 256 /* Max. SetWave() sample size */
|
||||
#define SND_BUFSIZE 512 /* Buffer size for DMA */
|
||||
#define SND_MAXDELAY 10 /* Maximal sound delay 1/n s */
|
||||
|
||||
/** InitSound() **********************************************/
|
||||
/** Initialize sound. Returns Rate on success, 0 otherwise. **/
|
||||
/** Rate=0 to skip initialization (will be silent). **/
|
||||
/*************************************************************/
|
||||
int InitSound(unsigned int Rate,unsigned int Latency);
|
||||
#endif /* MSDOS */
|
||||
|
||||
#ifdef WINDOWS
|
||||
#define SND_CHANNELS 16 /* Number of channels */
|
||||
#define SND_SAMPLESIZE 256 /* Max. SetWave() sample size */
|
||||
#define SND_BUFSIZE 512 /* Size of a wave buffer */
|
||||
#define SND_BUFFERS 32 /* Number of wave buffers */
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
/** InitSound() **********************************************/
|
||||
/** Initialize Windows sound driver with given synthesis **/
|
||||
/** rate. Returns Rate on success, 0 otherwise. Pass Rate=0 **/
|
||||
/** to skip initialization and be silent. Pass Rate=1 to **/
|
||||
/** use MIDI (midiOut). Pass Rate=8192..44100 to use wave **/
|
||||
/** synthesis (waveOut). Number of wave synthesis buffers **/
|
||||
/** must be in 2..SND_BUFFERS range. **/
|
||||
/*************************************************************/
|
||||
unsigned int InitSound(unsigned int Rate,unsigned int Delay);
|
||||
#endif /* WINDOWS */
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
#ifndef MSDOS
|
||||
#ifndef WINDOWS
|
||||
#ifndef UNIX
|
||||
#define SND_CHANNELS MIDI_CHANNELS /* Default number */
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** InitSound() **********************************************/
|
||||
/** Initialize Series60 sound driver with given synthesis **/
|
||||
/** rate. Returns Rate on success, 0 otherwise. Pass Rate=0 **/
|
||||
/** to skip initialization and be silent. **/
|
||||
/*************************************************************/
|
||||
unsigned int InitSound(unsigned int Rate,unsigned int Delay);
|
||||
#endif
|
||||
|
||||
/** RenderAudio() ********************************************/
|
||||
/** Render given number of melodic sound samples. Returns **/
|
||||
/** number of samples actually rendered. **/
|
||||
/*************************************************************/
|
||||
unsigned int RenderAudio(unsigned int Samples);
|
||||
|
||||
/** SndDriver ************************************************/
|
||||
/** Each sound driver should fill this structure with **/
|
||||
/** pointers to hardware-dependent handlers. This has to be **/
|
||||
/** done inside the InitSound() function. **/
|
||||
/*************************************************************/
|
||||
struct SndDriverStruct
|
||||
{
|
||||
void (*SetSound)(int Channel,int NewType);
|
||||
void (*Drum)(int Type,int Force);
|
||||
void (*SetChannels)(int Volume,int Switch);
|
||||
void (*Sound)(int Channel,int NewFreq,int NewVolume);
|
||||
void (*SetWave)(int Channel,const signed char *Data,int Length,int Freq);
|
||||
const signed char *(*GetWave)(int Channel);
|
||||
};
|
||||
extern struct SndDriverStruct SndDriver;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SOUND_H */
|
||||
14
src/include/apu/apu.h
Normal file
14
src/include/apu/apu.h
Normal file
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* APU emulation - The peTI-NESulator Project
|
||||
* apu.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
#ifndef PETI_NESULATOR_APU_H
|
||||
#define PETI_NESULATOR_APU_H
|
||||
|
||||
/* Empty, for now */
|
||||
|
||||
#endif /* PETI_NESULATOR_APU_H */
|
||||
43
src/include/color.h
Normal file
43
src/include/color.h
Normal file
@ -0,0 +1,43 @@
|
||||
/**
|
||||
* ANSI Color definition - The Quick6502 Project
|
||||
* include/color.h
|
||||
*
|
||||
* Created by Manoël Trapier on 25/06/10
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COLOR_H
|
||||
#define COLOR_H
|
||||
|
||||
#define ALLOW_COLORS
|
||||
|
||||
#ifdef ALLOW_COLORS
|
||||
#define __C(c) "\x1B[" c "m"
|
||||
#else
|
||||
#define __C(c) ""
|
||||
#endif
|
||||
|
||||
#define ANSI_COLOR __C
|
||||
#define FBLACK ANSI_COLOR("30")
|
||||
#define FRED ANSI_COLOR("31")
|
||||
#define FGREEN ANSI_COLOR("32")
|
||||
#define FYELLOW ANSI_COLOR("33")
|
||||
#define FBLUE ANSI_COLOR("34")
|
||||
#define FMAGENTA ANSI_COLOR("35")
|
||||
#define FCYAN ANSI_COLOR("36")
|
||||
#define FWHITE ANSI_COLOR("37")
|
||||
|
||||
#define BBLACK ANSI_COLOR("40")
|
||||
#define BRED ANSI_COLOR("41")
|
||||
#define BGREEN ANSI_COLOR("42")
|
||||
#define BYELLOW ANSI_COLOR("43")
|
||||
#define BBLUE ANSI_COLOR("44")
|
||||
#define BMAGENTA ANSI_COLOR("45")
|
||||
#define BCYAN ANSI_COLOR("46")
|
||||
#define BWHITE ANSI_COLOR("47")
|
||||
|
||||
#define CNORMAL ANSI_COLOR("0")
|
||||
|
||||
#endif /* COLOR_H */
|
||||
|
||||
166
src/include/corecpu.h
Normal file
166
src/include/corecpu.h
Normal file
@ -0,0 +1,166 @@
|
||||
/**
|
||||
* CoreCPU - The Quick6502 Project
|
||||
* corecpu.h
|
||||
*
|
||||
* Created by Manoël Trapier on 24/02/08
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _QUICK6502_CORECPU_H_
|
||||
#define _QUICK6502_CORECPU_H_
|
||||
|
||||
/* M6502 configuration
|
||||
*
|
||||
* Supported DEFINEs :
|
||||
* Q6502_NO_DECIMAL Quick6502 will not support BDC arithemtic (used for NES)
|
||||
* Q6502_CMOS Quick6502 will act as a CMOS 6502 (Not actually used)
|
||||
* Q6502_DEBUGGER Quick6502 will be build with debugguer support. Add some KB to the binary
|
||||
* and may slowdown a bit the emulation.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef Q6502_CMOS
|
||||
//#warning Quick6502 CMOS support is actually desactivated, desactivate it
|
||||
#undef Q6502_CMOS
|
||||
#endif
|
||||
|
||||
#ifndef Q6502_NO_DECIMAL
|
||||
//#warning Quick6502 have actually no BCD support, fallback to no NO_DECIMAL
|
||||
#define Q6502_NO_DECIMAL
|
||||
#endif
|
||||
|
||||
#include "types.h"
|
||||
|
||||
typedef uint8_t (*quick6502_MemoryReadFunction)(uint16_t addr);
|
||||
typedef void (*quick6502_MemoryWriteFunction)(uint16_t addr, uint8_t value);
|
||||
|
||||
typedef struct quick6502_cpu_
|
||||
{
|
||||
/* 6502 registers */
|
||||
uint8_t reg_A, reg_X, reg_Y;
|
||||
uint8_t reg_P, reg_S;
|
||||
uint16_t reg_PC;
|
||||
|
||||
/* Read/Write memory functions */
|
||||
quick6502_MemoryReadFunction memory_read;
|
||||
quick6502_MemoryWriteFunction memory_write;
|
||||
quick6502_MemoryReadFunction memory_page0_read;
|
||||
quick6502_MemoryWriteFunction memory_page0_write;
|
||||
quick6502_MemoryReadFunction memory_stack_read;
|
||||
quick6502_MemoryWriteFunction memory_stack_write;
|
||||
quick6502_MemoryReadFunction memory_opcode_read;
|
||||
|
||||
/* Timing related */
|
||||
long cycle_done;
|
||||
uint8_t exit_loop;
|
||||
uint8_t int_pending;
|
||||
|
||||
/* Other config options */
|
||||
uint8_t running; /* This field is used to prevent cpu free if this cpu is running */
|
||||
uint8_t page_crossed;
|
||||
|
||||
/* TODO add support for Inst/MemAccess breakpoints */
|
||||
|
||||
} quick6502_cpu;
|
||||
|
||||
typedef struct quick6502_cpuconfig_
|
||||
{
|
||||
/* Read/Write memory functions */
|
||||
quick6502_MemoryReadFunction memory_read;
|
||||
quick6502_MemoryWriteFunction memory_write;
|
||||
quick6502_MemoryReadFunction memory_page0_read;
|
||||
quick6502_MemoryWriteFunction memory_page0_write;
|
||||
quick6502_MemoryReadFunction memory_stack_read;
|
||||
quick6502_MemoryWriteFunction memory_stack_write;
|
||||
quick6502_MemoryReadFunction memory_opcode_read;
|
||||
} quick6502_cpuconfig;
|
||||
|
||||
/*** Signal that we can send to the CPU ***/
|
||||
typedef enum
|
||||
{
|
||||
Q6502_NO_SIGNAL = 0,
|
||||
Q6502_IRQ_SIGNAL,
|
||||
Q6502_NMI_SIGNAL,
|
||||
Q6502_STOPLOOP_SIGNAL
|
||||
} quick6502_signal;
|
||||
|
||||
/*** Some 6502 related definitions ***/
|
||||
|
||||
/*** P register flags ***/
|
||||
#define Q6502_N_FLAG 0x80 /* Negavite flag */
|
||||
#define Q6502_V_FLAG 0x40 /* oVerflow flag */
|
||||
#define Q6502_R_FLAG 0x20 /* Not a real flag, but need to be to 1 on PHP */
|
||||
#define Q6502_B_FLAG 0x10 /* Break flag */
|
||||
#define Q6502_D_FLAG 0x08 /* BCD flag */
|
||||
#define Q6502_I_FLAG 0x04 /* IRQ/BRK flag */
|
||||
#define Q6502_Z_FLAG 0x02 /* Zero flag */
|
||||
#define Q6502_C_FLAG 0x01 /* Carry flag */
|
||||
|
||||
/*** Interuption Vectors ***/
|
||||
#define Q6502_NMI_LOW 0xFFFA
|
||||
#define Q6502_NMI_HIGH 0xFFFB
|
||||
#define Q6502_RESET_LOW 0xFFFC
|
||||
#define Q6502_RESET_HIGH 0xFFFD
|
||||
#define Q6502_IRQ_LOW 0xFFFE
|
||||
#define Q6502_IRQ_HIGH 0xFFFF
|
||||
|
||||
/**
|
||||
* Initialise the CPU
|
||||
*
|
||||
* Inputs:
|
||||
*
|
||||
* - CPU Init structure:
|
||||
* +- Memory Read function pointer
|
||||
* +- Memory Write function pointer
|
||||
* +- Fast memory read function pointer (for opcodes read)
|
||||
* +- Fast page 0 function / Read/Write
|
||||
* +- Fast page 1 function / Read/Write
|
||||
*
|
||||
* Output:
|
||||
*
|
||||
* (void *): An opaque pointer to the internal structure of the CPU
|
||||
*
|
||||
*/
|
||||
quick6502_cpu *quick6502_init(quick6502_cpuconfig *config);
|
||||
|
||||
/* Reset the CPU (must be done after init) */
|
||||
void quick6502_reset(quick6502_cpu *cpu);
|
||||
|
||||
/**
|
||||
* Run cpu for at least X cycles
|
||||
*
|
||||
* Output:
|
||||
*
|
||||
* int: (Number of cycle really done) - (Number of cycle asked)
|
||||
*/
|
||||
uint32_t quick6502_run(quick6502_cpu *cpu, uint32_t cycles);
|
||||
|
||||
/** Loop CPU until explicit quit */
|
||||
void quick6502_loop(quick6502_cpu *cpu);
|
||||
|
||||
/** Run CPU for one instruction */
|
||||
void quick6502_exec(quick6502_cpu *cpu);
|
||||
|
||||
/** Send IRQ/NMI/EXITLOOP signal to CPU */
|
||||
void quick6502_int(quick6502_cpu *cpu, quick6502_signal signal);
|
||||
|
||||
/** Dump CPU State to the given file */
|
||||
void quick6502_dump(quick6502_cpu *cpu, FILE *fp);
|
||||
|
||||
/** Get current instruction name at specified address and put it into buffer */
|
||||
#define MINE
|
||||
|
||||
int quick6502_getinstruction(quick6502_cpu *cpu, char interpret,
|
||||
uint16_t addr, char *buffer, int *strlength);
|
||||
|
||||
/**
|
||||
* Free the CPU
|
||||
*
|
||||
* This function will free the CPU only if it's not currently used, it will
|
||||
* return !0 if everything goes well and 0 if the free is impossible
|
||||
*/
|
||||
int quick6502_free(quick6502_cpu *cpu);
|
||||
|
||||
#endif /* _QUICK6502_CORECPU_H_ */
|
||||
|
||||
37
src/include/log.h
Normal file
37
src/include/log.h
Normal file
@ -0,0 +1,37 @@
|
||||
/**
|
||||
* Log Facility - The Quick6502 Project
|
||||
* include/log.h
|
||||
*
|
||||
* Created by Manoël Trapier on 19/05/10
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _LOG_H
|
||||
#define _LOG_H
|
||||
|
||||
enum
|
||||
{
|
||||
LOG_ALWAYS = -1,
|
||||
LOG_PANIC = 0,
|
||||
LOG_ERROR,
|
||||
LOG_WARNING,
|
||||
LOG_NORMAL,
|
||||
LOG_VERBOSE,
|
||||
LOG_DEBUG,
|
||||
};
|
||||
|
||||
#define TIME_STAMP_LOG
|
||||
|
||||
#define MAX_DEBUG_LEVEL LOG_PANIC
|
||||
#define log(_level, _user, _fmt, ...) if ((_level <= MAX_DEBUG_LEVEL) || (_level <= LOG_PANIC)) do { log_real(_level, _user, _fmt, ##__VA_ARGS__); } while(0)
|
||||
|
||||
void log_real(int level, char *user, char *fmt, ...);
|
||||
|
||||
#define LOG(_level, _str, ...) if ((_level <= MAX_DEBUG_LEVEL) || (_level <= LOG_PANIC)) do { puts(_str); } while(0)
|
||||
#define LOGCODE(_level, _user, _code) log(_level, _user, ""); \
|
||||
if ((_level <= MAX_DEBUG_LEVEL) || (_level <= LOG_PANIC)) \
|
||||
do { _code; printf("\n"); } while(0)
|
||||
|
||||
#endif /* _LOG_H */
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* Mappers manager & facilities - The TI-NESulator Project
|
||||
* Mappers manager & facilities - The peTI-NESulator Project
|
||||
* mappers.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -19,14 +14,17 @@
|
||||
#include <stdio.h>
|
||||
#include <NESCarts.h>
|
||||
|
||||
typedef int (*MapperInit) (NesCart * cart);
|
||||
typedef int (*MapperWriteHook) (register unsigned short Addr,
|
||||
register unsigned char Value);
|
||||
typedef int (*MapperIRQ) (int cycledone);
|
||||
typedef void (*MapperDump) ();
|
||||
typedef int (*MapperInit)(NesCart *cart);
|
||||
typedef int (*MapperWriteHook)(register uint16_t Addr, register uint8_t Value);
|
||||
typedef int (*MapperIRQ)(int cycledone);
|
||||
typedef void (*MapperDump)(FILE *fp);
|
||||
|
||||
#ifdef __TINES_MAPPERS__
|
||||
|
||||
#include <ppu/ppu.h>
|
||||
#include <memory/manager.h>
|
||||
#include <os_dependent.h>
|
||||
|
||||
extern NesCart *Cart;
|
||||
|
||||
/* Available functions for mappers */
|
||||
@ -34,27 +32,30 @@ extern NesCart *Cart;
|
||||
#define GETLAST16KBANK(c) ((c->PROMSize>>14)-1)
|
||||
#define GETLAST32KBANK(c) ((c->PROMSize>>15)-1)
|
||||
|
||||
void map_sram(); /* Map SRAM */
|
||||
void unmap_sram(); /* Unmap SRAM */
|
||||
void set_vrom_bank_1k(uint16_t addr, int slot);
|
||||
void set_vrom_bank_2k(uint16_t addr, int slot);
|
||||
void set_vrom_bank_4k(uint16_t addr, int slot);
|
||||
void set_vrom_bank_8k(uint16_t addr, int slot);
|
||||
|
||||
void set_vrom_bank_1k(unsigned short addr,int slot);
|
||||
void set_vrom_bank_2k(unsigned short addr,int slot);
|
||||
void set_vrom_bank_4k(unsigned short addr,int slot);
|
||||
void set_vrom_bank_8k(unsigned short addr, int slot);
|
||||
|
||||
void set_prom_bank_8k(unsigned short addr,int slot);
|
||||
void set_prom_bank_16k(unsigned short addr,int slot);
|
||||
void set_prom_bank_32k(unsigned short addr,int slot);
|
||||
void set_prom_bank_8k(uint16_t addr, int slot);
|
||||
void set_prom_bank_16k(uint16_t addr, int slot);
|
||||
void set_prom_bank_32k(uint16_t addr, int slot);
|
||||
|
||||
#else /* __TINES_MAPPERS__ */
|
||||
|
||||
/* Available functions outside of mappers */
|
||||
|
||||
void mapper_list ();
|
||||
int mapper_init (NesCart *cart);
|
||||
extern int (*mapper_irqloop) (int cyclodone);
|
||||
extern void (*mapper_dump) (FILE *fp);
|
||||
void mapper_list();
|
||||
|
||||
int mapper_init(NesCart *cart);
|
||||
|
||||
extern MapperIRQ mapper_irqloop;
|
||||
extern MapperDump mapper_dump;
|
||||
extern MapperWriteHook mapper_hook;
|
||||
|
||||
#endif /* __TINES_MAPPERS__ */
|
||||
|
||||
void map_sram(); /* Map SRAM */
|
||||
void unmap_sram(); /* Unmap SRAM */
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* 6502 Memory manager - The TI-NESulator Project
|
||||
* 6502 Memory manager - The peTI-NESulator Project
|
||||
* memory.h - Taken from the Quick6502 project
|
||||
*
|
||||
* Created by Manoël Trapier on 18/09/06.
|
||||
* Copyright 2003-2007 986 Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-05 16:30:20 +0200 (jeu, 05 avr 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/memory.h $
|
||||
* $Revision: 31 $
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
#ifndef MEMORY_H
|
||||
@ -23,46 +18,35 @@
|
||||
#define ATTR_PAGE_GHOST 0x02
|
||||
#define ATTR_PAGE_MAPPED 0x01
|
||||
|
||||
typedef byte (*func_rdhook)(byte /* addr */);
|
||||
typedef void (*func_wrhook)(byte addr, byte data);
|
||||
typedef uint8_t (*func_rdhook)(uint8_t /* addr */);
|
||||
|
||||
typedef void (*func_wrhook)(uint8_t addr, uint8_t data);
|
||||
|
||||
/* Functions to manage pages data */
|
||||
void set_page_ptr(byte page, byte *ptr);
|
||||
void set_page_ptr_1k(byte page, byte *ptr);
|
||||
void set_page_ptr_2k(byte page, byte *ptr);
|
||||
void set_page_ptr_4k(byte page, byte *ptr);
|
||||
void set_page_ptr_8k(byte page, byte *ptr);
|
||||
void set_page_ptr_16k(byte page, byte *ptr);
|
||||
void set_page_ptr_32k(byte page, byte *ptr);
|
||||
|
||||
byte *get_page_ptr(byte page);
|
||||
void set_page_ptr(uint8_t page, uint8_t *ptr);
|
||||
void set_page_ptr_1k(uint8_t page, uint8_t *ptr);
|
||||
void set_page_ptr_2k(uint8_t page, uint8_t *ptr);
|
||||
void set_page_ptr_4k(uint8_t page, uint8_t *ptr);
|
||||
void set_page_ptr_8k(uint8_t page, uint8_t *ptr);
|
||||
void set_page_ptr_16k(uint8_t page, uint8_t *ptr);
|
||||
void set_page_ptr_32k(uint8_t page, uint8_t *ptr);
|
||||
uint8_t *get_page_ptr(uint8_t page);
|
||||
|
||||
|
||||
/* Functions to set pages attributes */
|
||||
|
||||
void set_page_rd_hook(byte page, func_rdhook func);
|
||||
|
||||
void set_page_wr_hook(byte page, func_wrhook func);
|
||||
|
||||
void set_page_readable(byte page, bool value);
|
||||
|
||||
void set_page_writeable(byte page, bool value);
|
||||
|
||||
void set_page_ghost(byte page, bool value, byte ghost);
|
||||
|
||||
byte get_page_attributes(byte page);
|
||||
|
||||
func_rdhook get_page_rdhook(byte page);
|
||||
|
||||
func_wrhook get_page_wrhook(byte page);
|
||||
void set_page_rd_hook(uint8_t page, func_rdhook func);
|
||||
void set_page_wr_hook(uint8_t page, func_wrhook func);
|
||||
void set_page_readable(uint8_t page, uint8_t value);
|
||||
void set_page_writeable(uint8_t page, uint8_t value);
|
||||
void set_page_ghost(uint8_t page, uint8_t value, uint8_t ghost);
|
||||
uint8_t get_page_attributes(uint8_t page);
|
||||
func_rdhook get_page_rdhook(uint8_t page);
|
||||
func_wrhook get_page_wrhook(uint8_t page);
|
||||
|
||||
/* Generalist functions */
|
||||
|
||||
void InitMemory();
|
||||
|
||||
byte ReadMemory(byte page, byte addr);
|
||||
void WriteMemory(byte page, byte addr, byte value);
|
||||
|
||||
void DumpMemoryState();
|
||||
uint8_t ReadMemory(uint8_t page, uint8_t addr);
|
||||
void WriteMemory(uint8_t page, uint8_t addr, uint8_t value);
|
||||
void DumpMemoryState(FILE *fp);
|
||||
|
||||
#endif
|
||||
|
||||
66
src/include/os_dependent.h
Normal file
66
src/include/os_dependent.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* OS Dependent functions - The peTI-NESulator Project
|
||||
* os_dependent.h
|
||||
*
|
||||
* Created by Manoël Trapier on 08/05/08.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OS_DEPENDENT_H
|
||||
#define OS_DEPENDENT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "text.h"
|
||||
|
||||
/* File related functions */
|
||||
/* Graphics related functions */
|
||||
int graphics_init();
|
||||
int graphics_drawpixel(long x, long y, long color);
|
||||
int graphics_blit(long x, long y, long w, long h);
|
||||
int graphics_drawline(uint32_t x, uint32_t y, uint32_t x1, uint32_t y1, uint32_t colour);
|
||||
int graphics_drawRect(uint32_t x0, uint32_t y0, uint32_t w, uint32_t h, uint32_t colour);
|
||||
int graphics_drawFillrect(int x0, int y0, int w, int h, uint32_t colour);
|
||||
int graphics_getScreenSize(int *w, int *h);
|
||||
|
||||
void vsync(void);
|
||||
|
||||
typedef struct Palette_t
|
||||
{
|
||||
uint8_t r, g, b, a;
|
||||
} Palette;
|
||||
|
||||
int getKeyStatus(int key);
|
||||
|
||||
/* Sound related functions */
|
||||
|
||||
/* IO functions */
|
||||
void *LoadFilePtr(char *filename);
|
||||
|
||||
/* Console functions */
|
||||
typedef enum ConsoleLevel_t
|
||||
{
|
||||
Console_Error = 0,
|
||||
Console_Warning,
|
||||
Console_Alert,
|
||||
Console_Default,
|
||||
Console_Verbose,
|
||||
Console_Debug,
|
||||
} ConsoleLevel;
|
||||
|
||||
int console_init(ConsoleLevel DefaultLevel);
|
||||
int console_printf(const ConsoleLevel level, const char *format, ...);
|
||||
int console_printf_d(const char *format, ...);
|
||||
|
||||
|
||||
#define KEY_ENTER (257)
|
||||
#define KEY_LEFT (263)
|
||||
#define KEY_RIGHT (262)
|
||||
#define KEY_UP (265)
|
||||
#define KEY_DOWN (264)
|
||||
//#define KEY_ENTER 13
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* OS_DEPENDENT_H */
|
||||
@ -1,36 +1,23 @@
|
||||
/*
|
||||
* Paddle manager - The TI-NESulator Project
|
||||
* Paddle manager - The peTI-NESulator Project
|
||||
* paddle.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/paddle.h $
|
||||
* $Revision: 39 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PADDLE_H
|
||||
#define PADDLE_H
|
||||
|
||||
typedef struct Paddle_
|
||||
typedef struct Paddle_
|
||||
{
|
||||
|
||||
unsigned char Bit;
|
||||
|
||||
unsigned char LastWrite;
|
||||
|
||||
uint8_t bitPos;
|
||||
uint8_t strobeState;
|
||||
} Paddle;
|
||||
|
||||
|
||||
unsigned char ReadPaddle(Paddle * pdl);
|
||||
|
||||
|
||||
void InitPaddle(Paddle * pdl);
|
||||
|
||||
void WritePaddle(Paddle * pdl, unsigned char val);
|
||||
|
||||
uint8_t ReadPaddle(Paddle *pdl);
|
||||
void InitPaddle(Paddle *pdl);
|
||||
void WritePaddle(Paddle *pdl, uint8_t val);
|
||||
|
||||
#endif
|
||||
|
||||
@ -1,261 +1,260 @@
|
||||
/* Generated data file from file 'stdin' */
|
||||
|
||||
|
||||
PALETTE basicPalette = {
|
||||
{ 0x1E, 0x1E, 0x1E, 0x07 },
|
||||
{ 0x03, 0x09, 0x28, 0xB7 },
|
||||
{ 0x0A, 0x04, 0x2B, 0x0D },
|
||||
{ 0x17, 0x02, 0x28, 0x00 },
|
||||
{ 0x22, 0x00, 0x1D, 0xB7 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0xB7 },
|
||||
{ 0x1B, 0x09, 0x01, 0xB7 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0x00 },
|
||||
{ 0x01, 0x17, 0x02, 0xB7 },
|
||||
{ 0x00, 0x14, 0x0B, 0xBF },
|
||||
{ 0x01, 0x11, 0x1B, 0xBF },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x2F, 0x30, 0x2F, 0xB7 },
|
||||
{ 0x05, 0x1A, 0x37, 0xBF },
|
||||
{ 0x12, 0x10, 0x3B, 0xBF },
|
||||
{ 0x23, 0x09, 0x38, 0xB7 },
|
||||
{ 0x31, 0x06, 0x2E, 0xBF },
|
||||
{ 0x35, 0x08, 0x18, 0xB7 },
|
||||
{ 0x35, 0x0D, 0x08, 0x00 },
|
||||
{ 0x2D, 0x16, 0x03, 0xB7 },
|
||||
{ 0x22, 0x1E, 0x01, 0x00 },
|
||||
{ 0x0E, 0x24, 0x01, 0x00 },
|
||||
{ 0x05, 0x26, 0x06, 0x00 },
|
||||
{ 0x02, 0x26, 0x16, 0xB7 },
|
||||
{ 0x02, 0x22, 0x2A, 0xBF },
|
||||
{ 0x0B, 0x0B, 0x0B, 0xBF },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0x00 },
|
||||
{ 0x12, 0x2C, 0x3E, 0xB7 },
|
||||
{ 0x22, 0x25, 0x3F, 0xB7 },
|
||||
{ 0x30, 0x1E, 0x3E, 0xB7 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0xBF },
|
||||
{ 0x3D, 0x1D, 0x2E, 0xB7 },
|
||||
{ 0x3D, 0x20, 0x1B, 0xB7 },
|
||||
{ 0x3B, 0x28, 0x11, 0x07 },
|
||||
{ 0x35, 0x30, 0x08, 0x01 },
|
||||
{ 0x26, 0x35, 0x08, 0x00 },
|
||||
{ 0x14, 0x37, 0x11, 0x00 },
|
||||
{ 0x0F, 0x37, 0x25, 0x00 },
|
||||
{ 0x0A, 0x36, 0x37, 0xB7 },
|
||||
{ 0x18, 0x19, 0x19, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0xB7 },
|
||||
{ 0x2D, 0x37, 0x3E, 0xB7 },
|
||||
{ 0x33, 0x34, 0x3F, 0x10 },
|
||||
{ 0x37, 0x31, 0x3E, 0x00 },
|
||||
{ 0x3C, 0x30, 0x3D, 0x00 },
|
||||
{ 0x3D, 0x30, 0x38, 0x00 },
|
||||
{ 0x3D, 0x33, 0x30, 0x00 },
|
||||
{ 0x3D, 0x36, 0x2B, 0x00 },
|
||||
{ 0x3B, 0x39, 0x26, 0x00 },
|
||||
{ 0x34, 0x3B, 0x27, 0x00 },
|
||||
{ 0x2E, 0x3C, 0x2D, 0x00 },
|
||||
{ 0x2C, 0x3C, 0x36, 0x00 },
|
||||
{ 0x29, 0x3C, 0x3C, 0x00 },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x1E, 0x1E, 0x1E, 0xB7 },
|
||||
{ 0x03, 0x09, 0x28, 0xB7 },
|
||||
{ 0x0A, 0x04, 0x2B, 0xBF },
|
||||
{ 0x17, 0x02, 0x28, 0xB7 },
|
||||
{ 0x22, 0x00, 0x1D, 0xB7 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0x00 },
|
||||
{ 0x1B, 0x09, 0x01, 0x00 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0xB7 },
|
||||
{ 0x01, 0x17, 0x02, 0x00 },
|
||||
{ 0x00, 0x14, 0x0B, 0xB7 },
|
||||
{ 0x01, 0x11, 0x1B, 0x50 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x2F, 0x30, 0x2F, 0xBF },
|
||||
{ 0x05, 0x1A, 0x37, 0xB7 },
|
||||
{ 0x12, 0x10, 0x3B, 0xB7 },
|
||||
{ 0x23, 0x09, 0x38, 0x20 },
|
||||
{ 0x31, 0x06, 0x2E, 0xBF },
|
||||
{ 0x35, 0x08, 0x18, 0xB7 },
|
||||
{ 0x35, 0x0D, 0x08, 0xBF },
|
||||
{ 0x2D, 0x16, 0x03, 0xBF },
|
||||
{ 0x22, 0x1E, 0x01, 0xB7 },
|
||||
{ 0x0E, 0x24, 0x01, 0xBF },
|
||||
{ 0x05, 0x26, 0x06, 0xB7 },
|
||||
{ 0x02, 0x26, 0x16, 0xBF },
|
||||
{ 0x02, 0x22, 0x2A, 0xBF },
|
||||
{ 0x0B, 0x0B, 0x0B, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0xBF },
|
||||
{ 0x12, 0x2C, 0x3E, 0x53 },
|
||||
{ 0x22, 0x25, 0x3F, 0x54 },
|
||||
{ 0x30, 0x1E, 0x3E, 0x46 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0x31 },
|
||||
{ 0x3D, 0x1D, 0x2E, 0x3A },
|
||||
{ 0x3D, 0x20, 0x1B, 0x32 },
|
||||
{ 0x3B, 0x28, 0x11, 0x54 },
|
||||
{ 0x35, 0x30, 0x08, 0x30 },
|
||||
{ 0x26, 0x35, 0x08, 0x00 },
|
||||
{ 0x14, 0x37, 0x11, 0x00 },
|
||||
{ 0x0F, 0x37, 0x25, 0x00 },
|
||||
{ 0x0A, 0x36, 0x37, 0x00 },
|
||||
{ 0x18, 0x19, 0x19, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0x00 },
|
||||
{ 0x2D, 0x37, 0x3E, 0x00 },
|
||||
{ 0x33, 0x34, 0x3F, 0x00 },
|
||||
{ 0x37, 0x31, 0x3E, 0x00 },
|
||||
{ 0x3C, 0x30, 0x3D, 0x00 },
|
||||
{ 0x3D, 0x30, 0x38, 0x00 },
|
||||
{ 0x3D, 0x33, 0x30, 0xB7 },
|
||||
{ 0x3D, 0x36, 0x2B, 0xB7 },
|
||||
{ 0x3B, 0x39, 0x26, 0x00 },
|
||||
{ 0x34, 0x3B, 0x27, 0xBF },
|
||||
{ 0x2E, 0x3C, 0x2D, 0xB7 },
|
||||
{ 0x2C, 0x3C, 0x36, 0xB7 },
|
||||
{ 0x29, 0x3C, 0x3C, 0xB7 },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x1E, 0x1E, 0x1E, 0x07 },
|
||||
{ 0x03, 0x09, 0x28, 0xB7 },
|
||||
{ 0x0A, 0x04, 0x2B, 0x0D },
|
||||
{ 0x17, 0x02, 0x28, 0x00 },
|
||||
{ 0x22, 0x00, 0x1D, 0xB7 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0xB7 },
|
||||
{ 0x1B, 0x09, 0x01, 0xB7 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0x00 },
|
||||
{ 0x01, 0x17, 0x02, 0xB7 },
|
||||
{ 0x00, 0x14, 0x0B, 0x00 },
|
||||
{ 0x01, 0x11, 0x1B, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x2F, 0x30, 0x2F, 0xB7 },
|
||||
{ 0x05, 0x1A, 0x37, 0xBF },
|
||||
{ 0x12, 0x10, 0x3B, 0xB7 },
|
||||
{ 0x23, 0x09, 0x38, 0xB7 },
|
||||
{ 0x31, 0x06, 0x2E, 0x00 },
|
||||
{ 0x35, 0x08, 0x18, 0xBF },
|
||||
{ 0x35, 0x0D, 0x08, 0xB7 },
|
||||
{ 0x2D, 0x16, 0x03, 0xB7 },
|
||||
{ 0x22, 0x1E, 0x01, 0xB7 },
|
||||
{ 0x0E, 0x24, 0x01, 0x00 },
|
||||
{ 0x05, 0x26, 0x06, 0x00 },
|
||||
{ 0x02, 0x26, 0x16, 0xB7 },
|
||||
{ 0x02, 0x22, 0x2A, 0x06 },
|
||||
{ 0x0B, 0x0B, 0x0B, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0xB7 },
|
||||
{ 0x12, 0x2C, 0x3E, 0xB7 },
|
||||
{ 0x22, 0x25, 0x3F, 0xB7 },
|
||||
{ 0x30, 0x1E, 0x3E, 0xB7 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0x00 },
|
||||
{ 0x3D, 0x1D, 0x2E, 0x00 },
|
||||
{ 0x3D, 0x20, 0x1B, 0xB7 },
|
||||
{ 0x3B, 0x28, 0x11, 0xB7 },
|
||||
{ 0x35, 0x30, 0x08, 0x03 },
|
||||
{ 0x26, 0x35, 0x08, 0xB7 },
|
||||
{ 0x14, 0x37, 0x11, 0xBF },
|
||||
{ 0x0F, 0x37, 0x25, 0x00 },
|
||||
{ 0x0A, 0x36, 0x37, 0xB7 },
|
||||
{ 0x18, 0x19, 0x19, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0x00 },
|
||||
{ 0x2D, 0x37, 0x3E, 0x00 },
|
||||
{ 0x33, 0x34, 0x3F, 0xB7 },
|
||||
{ 0x37, 0x31, 0x3E, 0xB7 },
|
||||
{ 0x3C, 0x30, 0x3D, 0x00 },
|
||||
{ 0x3D, 0x30, 0x38, 0x00 },
|
||||
{ 0x3D, 0x33, 0x30, 0xB7 },
|
||||
{ 0x3D, 0x36, 0x2B, 0xB7 },
|
||||
{ 0x3B, 0x39, 0x26, 0xB7 },
|
||||
{ 0x34, 0x3B, 0x27, 0xBF },
|
||||
{ 0x2E, 0x3C, 0x2D, 0xBF },
|
||||
{ 0x2C, 0x3C, 0x36, 0xB7 },
|
||||
{ 0x29, 0x3C, 0x3C, 0xBF },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x1E, 0x1E, 0x1E, 0xB7 },
|
||||
{ 0x03, 0x09, 0x28, 0x08 },
|
||||
{ 0x0A, 0x04, 0x2B, 0xBF },
|
||||
{ 0x17, 0x02, 0x28, 0xB7 },
|
||||
{ 0x22, 0x00, 0x1D, 0x08 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0x08 },
|
||||
{ 0x1B, 0x09, 0x01, 0xB7 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0xBF },
|
||||
{ 0x01, 0x17, 0x02, 0xB7 },
|
||||
{ 0x00, 0x14, 0x0B, 0xB7 },
|
||||
{ 0x01, 0x11, 0x1B, 0x08 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x08 },
|
||||
{ 0x2F, 0x30, 0x2F, 0x01 },
|
||||
{ 0x05, 0x1A, 0x37, 0x08 },
|
||||
{ 0x12, 0x10, 0x3B, 0x0D },
|
||||
{ 0x23, 0x09, 0x38, 0x00 },
|
||||
{ 0x31, 0x06, 0x2E, 0xB7 },
|
||||
{ 0x35, 0x08, 0x18, 0xB7 },
|
||||
{ 0x35, 0x0D, 0x08, 0xB7 },
|
||||
{ 0x2D, 0x16, 0x03, 0xB7 },
|
||||
{ 0x22, 0x1E, 0x01, 0x00 },
|
||||
{ 0x0E, 0x24, 0x01, 0x00 },
|
||||
{ 0x05, 0x26, 0x06, 0xB7 },
|
||||
{ 0x02, 0x26, 0x16, 0x00 },
|
||||
{ 0x02, 0x22, 0x2A, 0xB7 },
|
||||
{ 0x0B, 0x0B, 0x0B, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x08 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0xB7 },
|
||||
{ 0x12, 0x2C, 0x3E, 0xBF },
|
||||
{ 0x22, 0x25, 0x3F, 0xBF },
|
||||
{ 0x30, 0x1E, 0x3E, 0xB7 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0xBF },
|
||||
{ 0x3D, 0x1D, 0x2E, 0xB7 },
|
||||
{ 0x3D, 0x20, 0x1B, 0x00 },
|
||||
{ 0x3B, 0x28, 0x11, 0xB7 },
|
||||
{ 0x35, 0x30, 0x08, 0x00 },
|
||||
{ 0x26, 0x35, 0x08, 0x00 },
|
||||
{ 0x14, 0x37, 0x11, 0x00 },
|
||||
{ 0x0F, 0x37, 0x25, 0xB7 },
|
||||
{ 0x0A, 0x36, 0x37, 0xB7 },
|
||||
{ 0x18, 0x19, 0x19, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0x00 },
|
||||
{ 0x2D, 0x37, 0x3E, 0xB7 },
|
||||
{ 0x33, 0x34, 0x3F, 0x00 },
|
||||
{ 0x37, 0x31, 0x3E, 0xB7 },
|
||||
{ 0x3C, 0x30, 0x3D, 0xBF },
|
||||
{ 0x3D, 0x30, 0x38, 0xB7 },
|
||||
{ 0x3D, 0x33, 0x30, 0x08 },
|
||||
{ 0x3D, 0x36, 0x2B, 0x01 },
|
||||
{ 0x3B, 0x39, 0x26, 0x01 },
|
||||
{ 0x34, 0x3B, 0x27, 0x00 },
|
||||
{ 0x2E, 0x3C, 0x2D, 0xB7 },
|
||||
{ 0x2C, 0x3C, 0x36, 0xB7 },
|
||||
{ 0x29, 0x3C, 0x3C, 0x08 },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0x08 },
|
||||
{ 0x01, 0x01, 0x01, 0xBF }
|
||||
};
|
||||
Palette basicPalette[] = {
|
||||
{ 0x1E, 0x1E, 0x1E, 0x07 },
|
||||
{ 0x03, 0x09, 0x28, 0xB7 },
|
||||
{ 0x0A, 0x04, 0x2B, 0x0D },
|
||||
{ 0x17, 0x02, 0x28, 0x00 },
|
||||
{ 0x22, 0x00, 0x1D, 0xB7 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0xB7 },
|
||||
{ 0x1B, 0x09, 0x01, 0xB7 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0x00 },
|
||||
{ 0x01, 0x17, 0x02, 0xB7 },
|
||||
{ 0x00, 0x14, 0x0B, 0xBF },
|
||||
{ 0x01, 0x11, 0x1B, 0xBF },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x2F, 0x30, 0x2F, 0xB7 },
|
||||
{ 0x05, 0x1A, 0x37, 0xBF },
|
||||
{ 0x12, 0x10, 0x3B, 0xBF },
|
||||
{ 0x23, 0x09, 0x38, 0xB7 },
|
||||
{ 0x31, 0x06, 0x2E, 0xBF },
|
||||
{ 0x35, 0x08, 0x18, 0xB7 },
|
||||
{ 0x35, 0x0D, 0x08, 0x00 },
|
||||
{ 0x2D, 0x16, 0x03, 0xB7 },
|
||||
{ 0x22, 0x1E, 0x01, 0x00 },
|
||||
{ 0x0E, 0x24, 0x01, 0x00 },
|
||||
{ 0x05, 0x26, 0x06, 0x00 },
|
||||
{ 0x02, 0x26, 0x16, 0xB7 },
|
||||
{ 0x02, 0x22, 0x2A, 0xBF },
|
||||
{ 0x0B, 0x0B, 0x0B, 0xBF },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0x00 },
|
||||
{ 0x12, 0x2C, 0x3E, 0xB7 },
|
||||
{ 0x22, 0x25, 0x3F, 0xB7 },
|
||||
{ 0x30, 0x1E, 0x3E, 0xB7 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0xBF },
|
||||
{ 0x3D, 0x1D, 0x2E, 0xB7 },
|
||||
{ 0x3D, 0x20, 0x1B, 0xB7 },
|
||||
{ 0x3B, 0x28, 0x11, 0x07 },
|
||||
{ 0x35, 0x30, 0x08, 0x01 },
|
||||
{ 0x26, 0x35, 0x08, 0x00 },
|
||||
{ 0x14, 0x37, 0x11, 0x00 },
|
||||
{ 0x0F, 0x37, 0x25, 0x00 },
|
||||
{ 0x0A, 0x36, 0x37, 0xB7 },
|
||||
{ 0x18, 0x19, 0x19, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0xB7 },
|
||||
{ 0x2D, 0x37, 0x3E, 0xB7 },
|
||||
{ 0x33, 0x34, 0x3F, 0x10 },
|
||||
{ 0x37, 0x31, 0x3E, 0x00 },
|
||||
{ 0x3C, 0x30, 0x3D, 0x00 },
|
||||
{ 0x3D, 0x30, 0x38, 0x00 },
|
||||
{ 0x3D, 0x33, 0x30, 0x00 },
|
||||
{ 0x3D, 0x36, 0x2B, 0x00 },
|
||||
{ 0x3B, 0x39, 0x26, 0x00 },
|
||||
{ 0x34, 0x3B, 0x27, 0x00 },
|
||||
{ 0x2E, 0x3C, 0x2D, 0x00 },
|
||||
{ 0x2C, 0x3C, 0x36, 0x00 },
|
||||
{ 0x29, 0x3C, 0x3C, 0x00 },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x1E, 0x1E, 0x1E, 0xB7 },
|
||||
{ 0x03, 0x09, 0x28, 0xB7 },
|
||||
{ 0x0A, 0x04, 0x2B, 0xBF },
|
||||
{ 0x17, 0x02, 0x28, 0xB7 },
|
||||
{ 0x22, 0x00, 0x1D, 0xB7 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0x00 },
|
||||
{ 0x1B, 0x09, 0x01, 0x00 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0xB7 },
|
||||
{ 0x01, 0x17, 0x02, 0x00 },
|
||||
{ 0x00, 0x14, 0x0B, 0xB7 },
|
||||
{ 0x01, 0x11, 0x1B, 0x50 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x2F, 0x30, 0x2F, 0xBF },
|
||||
{ 0x05, 0x1A, 0x37, 0xB7 },
|
||||
{ 0x12, 0x10, 0x3B, 0xB7 },
|
||||
{ 0x23, 0x09, 0x38, 0x20 },
|
||||
{ 0x31, 0x06, 0x2E, 0xBF },
|
||||
{ 0x35, 0x08, 0x18, 0xB7 },
|
||||
{ 0x35, 0x0D, 0x08, 0xBF },
|
||||
{ 0x2D, 0x16, 0x03, 0xBF },
|
||||
{ 0x22, 0x1E, 0x01, 0xB7 },
|
||||
{ 0x0E, 0x24, 0x01, 0xBF },
|
||||
{ 0x05, 0x26, 0x06, 0xB7 },
|
||||
{ 0x02, 0x26, 0x16, 0xBF },
|
||||
{ 0x02, 0x22, 0x2A, 0xBF },
|
||||
{ 0x0B, 0x0B, 0x0B, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0xBF },
|
||||
{ 0x12, 0x2C, 0x3E, 0x53 },
|
||||
{ 0x22, 0x25, 0x3F, 0x54 },
|
||||
{ 0x30, 0x1E, 0x3E, 0x46 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0x31 },
|
||||
{ 0x3D, 0x1D, 0x2E, 0x3A },
|
||||
{ 0x3D, 0x20, 0x1B, 0x32 },
|
||||
{ 0x3B, 0x28, 0x11, 0x54 },
|
||||
{ 0x35, 0x30, 0x08, 0x30 },
|
||||
{ 0x26, 0x35, 0x08, 0x00 },
|
||||
{ 0x14, 0x37, 0x11, 0x00 },
|
||||
{ 0x0F, 0x37, 0x25, 0x00 },
|
||||
{ 0x0A, 0x36, 0x37, 0x00 },
|
||||
{ 0x18, 0x19, 0x19, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0x00 },
|
||||
{ 0x2D, 0x37, 0x3E, 0x00 },
|
||||
{ 0x33, 0x34, 0x3F, 0x00 },
|
||||
{ 0x37, 0x31, 0x3E, 0x00 },
|
||||
{ 0x3C, 0x30, 0x3D, 0x00 },
|
||||
{ 0x3D, 0x30, 0x38, 0x00 },
|
||||
{ 0x3D, 0x33, 0x30, 0xB7 },
|
||||
{ 0x3D, 0x36, 0x2B, 0xB7 },
|
||||
{ 0x3B, 0x39, 0x26, 0x00 },
|
||||
{ 0x34, 0x3B, 0x27, 0xBF },
|
||||
{ 0x2E, 0x3C, 0x2D, 0xB7 },
|
||||
{ 0x2C, 0x3C, 0x36, 0xB7 },
|
||||
{ 0x29, 0x3C, 0x3C, 0xB7 },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x1E, 0x1E, 0x1E, 0x07 },
|
||||
{ 0x03, 0x09, 0x28, 0xB7 },
|
||||
{ 0x0A, 0x04, 0x2B, 0x0D },
|
||||
{ 0x17, 0x02, 0x28, 0x00 },
|
||||
{ 0x22, 0x00, 0x1D, 0xB7 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0xB7 },
|
||||
{ 0x1B, 0x09, 0x01, 0xB7 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0x00 },
|
||||
{ 0x01, 0x17, 0x02, 0xB7 },
|
||||
{ 0x00, 0x14, 0x0B, 0x00 },
|
||||
{ 0x01, 0x11, 0x1B, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x2F, 0x30, 0x2F, 0xB7 },
|
||||
{ 0x05, 0x1A, 0x37, 0xBF },
|
||||
{ 0x12, 0x10, 0x3B, 0xB7 },
|
||||
{ 0x23, 0x09, 0x38, 0xB7 },
|
||||
{ 0x31, 0x06, 0x2E, 0x00 },
|
||||
{ 0x35, 0x08, 0x18, 0xBF },
|
||||
{ 0x35, 0x0D, 0x08, 0xB7 },
|
||||
{ 0x2D, 0x16, 0x03, 0xB7 },
|
||||
{ 0x22, 0x1E, 0x01, 0xB7 },
|
||||
{ 0x0E, 0x24, 0x01, 0x00 },
|
||||
{ 0x05, 0x26, 0x06, 0x00 },
|
||||
{ 0x02, 0x26, 0x16, 0xB7 },
|
||||
{ 0x02, 0x22, 0x2A, 0x06 },
|
||||
{ 0x0B, 0x0B, 0x0B, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x00, 0x00, 0x00, 0x00 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0xB7 },
|
||||
{ 0x12, 0x2C, 0x3E, 0xB7 },
|
||||
{ 0x22, 0x25, 0x3F, 0xB7 },
|
||||
{ 0x30, 0x1E, 0x3E, 0xB7 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0x00 },
|
||||
{ 0x3D, 0x1D, 0x2E, 0x00 },
|
||||
{ 0x3D, 0x20, 0x1B, 0xB7 },
|
||||
{ 0x3B, 0x28, 0x11, 0xB7 },
|
||||
{ 0x35, 0x30, 0x08, 0x03 },
|
||||
{ 0x26, 0x35, 0x08, 0xB7 },
|
||||
{ 0x14, 0x37, 0x11, 0xBF },
|
||||
{ 0x0F, 0x37, 0x25, 0x00 },
|
||||
{ 0x0A, 0x36, 0x37, 0xB7 },
|
||||
{ 0x18, 0x19, 0x19, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0x00 },
|
||||
{ 0x2D, 0x37, 0x3E, 0x00 },
|
||||
{ 0x33, 0x34, 0x3F, 0xB7 },
|
||||
{ 0x37, 0x31, 0x3E, 0xB7 },
|
||||
{ 0x3C, 0x30, 0x3D, 0x00 },
|
||||
{ 0x3D, 0x30, 0x38, 0x00 },
|
||||
{ 0x3D, 0x33, 0x30, 0xB7 },
|
||||
{ 0x3D, 0x36, 0x2B, 0xB7 },
|
||||
{ 0x3B, 0x39, 0x26, 0xB7 },
|
||||
{ 0x34, 0x3B, 0x27, 0xBF },
|
||||
{ 0x2E, 0x3C, 0x2D, 0xBF },
|
||||
{ 0x2C, 0x3C, 0x36, 0xB7 },
|
||||
{ 0x29, 0x3C, 0x3C, 0xBF },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0xB7 },
|
||||
{ 0x1E, 0x1E, 0x1E, 0xB7 },
|
||||
{ 0x03, 0x09, 0x28, 0x08 },
|
||||
{ 0x0A, 0x04, 0x2B, 0xBF },
|
||||
{ 0x17, 0x02, 0x28, 0xB7 },
|
||||
{ 0x22, 0x00, 0x1D, 0x08 },
|
||||
{ 0x24, 0x01, 0x0A, 0xB7 },
|
||||
{ 0x24, 0x04, 0x02, 0x08 },
|
||||
{ 0x1B, 0x09, 0x01, 0xB7 },
|
||||
{ 0x11, 0x10, 0x01, 0x00 },
|
||||
{ 0x05, 0x15, 0x01, 0xBF },
|
||||
{ 0x01, 0x17, 0x02, 0xB7 },
|
||||
{ 0x00, 0x14, 0x0B, 0xB7 },
|
||||
{ 0x01, 0x11, 0x1B, 0x08 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x08 },
|
||||
{ 0x2F, 0x30, 0x2F, 0x01 },
|
||||
{ 0x05, 0x1A, 0x37, 0x08 },
|
||||
{ 0x12, 0x10, 0x3B, 0x0D },
|
||||
{ 0x23, 0x09, 0x38, 0x00 },
|
||||
{ 0x31, 0x06, 0x2E, 0xB7 },
|
||||
{ 0x35, 0x08, 0x18, 0xB7 },
|
||||
{ 0x35, 0x0D, 0x08, 0xB7 },
|
||||
{ 0x2D, 0x16, 0x03, 0xB7 },
|
||||
{ 0x22, 0x1E, 0x01, 0x00 },
|
||||
{ 0x0E, 0x24, 0x01, 0x00 },
|
||||
{ 0x05, 0x26, 0x06, 0xB7 },
|
||||
{ 0x02, 0x26, 0x16, 0x00 },
|
||||
{ 0x02, 0x22, 0x2A, 0xB7 },
|
||||
{ 0x0B, 0x0B, 0x0B, 0xB7 },
|
||||
{ 0x00, 0x00, 0x00, 0x08 },
|
||||
{ 0x00, 0x00, 0x00, 0xB7 },
|
||||
{ 0x3D, 0x3D, 0x3E, 0xB7 },
|
||||
{ 0x12, 0x2C, 0x3E, 0xBF },
|
||||
{ 0x22, 0x25, 0x3F, 0xBF },
|
||||
{ 0x30, 0x1E, 0x3E, 0xB7 },
|
||||
{ 0x3A, 0x1B, 0x3B, 0xBF },
|
||||
{ 0x3D, 0x1D, 0x2E, 0xB7 },
|
||||
{ 0x3D, 0x20, 0x1B, 0x00 },
|
||||
{ 0x3B, 0x28, 0x11, 0xB7 },
|
||||
{ 0x35, 0x30, 0x08, 0x00 },
|
||||
{ 0x26, 0x35, 0x08, 0x00 },
|
||||
{ 0x14, 0x37, 0x11, 0x00 },
|
||||
{ 0x0F, 0x37, 0x25, 0xB7 },
|
||||
{ 0x0A, 0x36, 0x37, 0xB7 },
|
||||
{ 0x18, 0x19, 0x19, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x01, 0x01, 0x01, 0x00 },
|
||||
{ 0x3E, 0x3E, 0x3E, 0x00 },
|
||||
{ 0x2D, 0x37, 0x3E, 0xB7 },
|
||||
{ 0x33, 0x34, 0x3F, 0x00 },
|
||||
{ 0x37, 0x31, 0x3E, 0xB7 },
|
||||
{ 0x3C, 0x30, 0x3D, 0xBF },
|
||||
{ 0x3D, 0x30, 0x38, 0xB7 },
|
||||
{ 0x3D, 0x33, 0x30, 0x08 },
|
||||
{ 0x3D, 0x36, 0x2B, 0x01 },
|
||||
{ 0x3B, 0x39, 0x26, 0x01 },
|
||||
{ 0x34, 0x3B, 0x27, 0x00 },
|
||||
{ 0x2E, 0x3C, 0x2D, 0xB7 },
|
||||
{ 0x2C, 0x3C, 0x36, 0xB7 },
|
||||
{ 0x29, 0x3C, 0x3C, 0x08 },
|
||||
{ 0x32, 0x31, 0x32, 0xB7 },
|
||||
{ 0x01, 0x01, 0x01, 0x08 },
|
||||
{ 0x01, 0x01, 0x01, 0xBF },
|
||||
};
|
||||
|
||||
@ -1,46 +1,38 @@
|
||||
/*
|
||||
* Plugins manager - The TI-NESulator Project
|
||||
* Plugins manager - The peTI-NESulator Project
|
||||
* plugins.h
|
||||
*
|
||||
* Created by Manoel TRAPIER on 02/04/07.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate$
|
||||
* $Author$
|
||||
* $HeadURL$
|
||||
* $Revision$
|
||||
* Created by Manoël Trapier on 02/04/07.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PLUGINS_H
|
||||
#define PLUGINS_H
|
||||
#ifndef PLUGINS_H
|
||||
#define PLUGINS_H
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/* Function pointer for prototyping function that plugins may export */
|
||||
typedef int (*PluginInit) (void);
|
||||
typedef int (*PluginDeinit) (void);
|
||||
typedef void (*PluginKeypress) (void);
|
||||
typedef int (*PluginInit)(void);
|
||||
typedef int (*PluginDeinit)(void);
|
||||
typedef void (*PluginKeypress)(void);
|
||||
|
||||
#ifdef __TINES_PLUGINS__
|
||||
|
||||
/* Available functions for plugins */
|
||||
int plugin_install_keypressHandler(byte key, PluginKeypress);
|
||||
int plugin_remove_keypressHandler(byte key, PluginKeypress);
|
||||
int plugin_install_keypressHandler(uint8_t key, PluginKeypress);
|
||||
int plugin_remove_keypressHandler(uint8_t key, PluginKeypress);
|
||||
|
||||
#else /* __TINES_PLUGINS__ */
|
||||
|
||||
/* Available functions outside of plugins */
|
||||
int plugin_keypress(byte key);
|
||||
int plugin_keypress();
|
||||
|
||||
/* Real Prototype: TBD */
|
||||
void plugin_list();
|
||||
|
||||
int plugin_load(int id);
|
||||
|
||||
int plugin_unload(int id);
|
||||
|
||||
|
||||
#endif /* __TINES_PLUGINS__ */
|
||||
|
||||
#endif /* PLUGINS_H */
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* PPU debug utilities - The TI-NESulator Project
|
||||
* PPU debug utilities - The peTI-NESulator Project
|
||||
* ppu.debug.h
|
||||
*
|
||||
* Created by Manoël Trapier on 12/04/07.
|
||||
* Copyright 2003-2007 986 Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-24 15:11:55 +0200 (jeu, 24 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/ppu/ppu.debug.h $
|
||||
* $Revision: 53 $
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@ -1,16 +1,11 @@
|
||||
/*
|
||||
* PPU emulation - The TI-NESulator Project
|
||||
* PPU emulation - The peTI-NESulator Project
|
||||
* ppu.h
|
||||
*
|
||||
* Define and emulate the PPU (Picture Processing Unit) of the real NES
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-26 18:47:34 +0200 (jeu, 26 avr 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/ppu.h $
|
||||
* $Revision: 46 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -21,24 +16,20 @@
|
||||
|
||||
typedef struct PPU_Sprite_
|
||||
{
|
||||
byte y;
|
||||
byte tileid;
|
||||
byte flags;
|
||||
byte x;
|
||||
uint8_t y;
|
||||
uint8_t tileid;
|
||||
uint8_t flags;
|
||||
uint8_t x;
|
||||
} PPU_Sprite;
|
||||
|
||||
/*
|
||||
PPU must be initialized after memory initialisation..
|
||||
*/
|
||||
int ppu_init();
|
||||
|
||||
int ppu_hblank(int scanline);
|
||||
|
||||
byte ppu_readReg(byte id);
|
||||
|
||||
void ppu_writeReg(byte id, byte val);
|
||||
|
||||
void ppu_fillSprRamDMA(byte value);
|
||||
int ppu_hblank(uint16_t scanline);
|
||||
uint8_t ppu_readReg(uint8_t id);
|
||||
void ppu_writeReg(uint8_t id, uint8_t val);
|
||||
void ppu_fillSprRamDMA(uint8_t value);
|
||||
|
||||
#define PPU_MIRROR_HORIZTAL 0
|
||||
#define PPU_MIRROR_VERTICAL 1
|
||||
@ -52,16 +43,12 @@ void ppu_fillSprRamDMA(byte value);
|
||||
#define PPU_SCMODE_NORMAL 1
|
||||
#define PPU_SCMODE_FOURSC 2
|
||||
|
||||
void ppu_setMirroring(byte direction);
|
||||
void ppu_setSingleScreen(byte screen);
|
||||
void ppu_setScreenMode(byte mode);
|
||||
|
||||
|
||||
PPU_Sprite ppu_getSprite(unsigned short i);
|
||||
|
||||
unsigned char ppu_memoryRead(byte page, byte addr);
|
||||
void ppu_memoryWrite(byte page, byte addr, byte value);
|
||||
|
||||
void ppu_setMirroring(uint8_t direction);
|
||||
void ppu_setSingleScreen(uint8_t screen);
|
||||
void ppu_setScreenMode(uint8_t mode);
|
||||
PPU_Sprite ppu_getSprite(uint16_t i);
|
||||
uint8_t ppu_memoryRead(uint8_t page, uint8_t addr);
|
||||
void ppu_memoryWrite(uint8_t page, uint8_t addr, uint8_t value);
|
||||
void ppu_debugSprites();
|
||||
void ppu_debugColor();
|
||||
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* PPU Memory manager - The TI-NESulator Project
|
||||
* PPU Memory manager - The peTI-NESulator Project
|
||||
* ppu.memory.h - Inspired from the memory manager of the Quick6502 Project.
|
||||
*
|
||||
* Created by Manoël Trapier on 12/04/07.
|
||||
* Copyright 2003-2007 986 Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-24 15:11:55 +0200 (jeu, 24 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/ppu/ppu.memory.h $
|
||||
* $Revision: 53 $
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -16,16 +11,15 @@
|
||||
|
||||
int ppu_initMemory();
|
||||
|
||||
void ppu_setPagePtr (byte page, byte *ptr);
|
||||
void ppu_setPagePtr1k(byte page, byte *ptr);
|
||||
void ppu_setPagePtr2k(byte page, byte *ptr);
|
||||
void ppu_setPagePtr4k(byte page, byte *ptr);
|
||||
void ppu_setPagePtr8k(byte page, byte *ptr);
|
||||
|
||||
void ppu_setPagePtr(uint8_t page, uint8_t *ptr);
|
||||
void ppu_setPagePtr1k(uint8_t page, uint8_t *ptr);
|
||||
void ppu_setPagePtr2k(uint8_t page, uint8_t *ptr);
|
||||
void ppu_setPagePtr4k(uint8_t page, uint8_t *ptr);
|
||||
void ppu_setPagePtr8k(uint8_t page, uint8_t *ptr);
|
||||
void ppu_memoryDumpState(FILE *fp);
|
||||
|
||||
byte ppu_readMemory(byte page, byte addr);
|
||||
void ppu_writeMemory(byte page, byte addr, byte value);
|
||||
uint8_t ppu_readMemory(uint8_t page, uint8_t addr);
|
||||
void ppu_writeMemory(uint8_t page, uint8_t addr, uint8_t value);
|
||||
void ppu_setPageGhost(uint8_t page, uint8_t value, uint8_t ghost);
|
||||
|
||||
#else
|
||||
#error Must only be included inside the PPU code
|
||||
|
||||
58
src/include/text.h
Normal file
58
src/include/text.h
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* FbLib graphic library
|
||||
*
|
||||
* Created by Manoël TRAPIER.
|
||||
* Copyright (c) 2003-2019 986-Studio. All rights reserved.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _FBLIB_INCLUDE_TEXT_H
|
||||
#define _FBLIB_INCLUDE_TEXT_H
|
||||
|
||||
typedef struct FBLibFont
|
||||
{
|
||||
char *name; /* Font name. */
|
||||
int height; /* Height in pixels. */
|
||||
int index_mask; /* ((1 << N) - 1). */
|
||||
int *offset; /* (1 << N) offsets into index. */
|
||||
int *index;
|
||||
uint32_t *content;
|
||||
//void *private;
|
||||
} FBLibFont;
|
||||
|
||||
/* ? */
|
||||
FBLibFont *load_psf(char *filename);
|
||||
|
||||
void graphics_text_line(int x, int y, int w, int charw, uint32_t color, int valign, void *font, char *text);
|
||||
|
||||
int graphics_text_ex(int x, int y, int w, int h,
|
||||
void *font,
|
||||
uint32_t bgcolor, uint32_t fgcolor,
|
||||
char valign, char halign,
|
||||
uint16_t options,
|
||||
void *format, ...);
|
||||
|
||||
void graphics_get_text_size(int *width, int *height,
|
||||
const FBLibFont *font,
|
||||
const char *text);
|
||||
|
||||
void graphics_draw_text (int x, int y,
|
||||
uint32_t colour,
|
||||
const FBLibFont *font,
|
||||
const char *text);
|
||||
|
||||
#define TEXT_VALIGN_LEFT (1)
|
||||
#define TEXT_VALIGN_RIGHT (2)
|
||||
#define TEXT_VALIGN_CENTER (3)
|
||||
|
||||
#define TEXT_HALIGN_TOP (1)
|
||||
#define TEXT_HALIGN_CENTER (2)
|
||||
#define TEXT_HALIGN_BOTTOM (3)
|
||||
|
||||
#define TEXT_OPT_WORDWRAP (1<<0)
|
||||
|
||||
#define TEXT_DEFAULTFONT ((void*)(1))
|
||||
#define TEXT_SMALLFONT ((void*)(2))
|
||||
#define TEXT_LARGEFONT ((void*)(3))
|
||||
|
||||
#endif /* _FBLIB_INCLUDE_TEXT_H */
|
||||
@ -1,26 +1,16 @@
|
||||
/*
|
||||
* Base type definitions - The TI-NESulator Project
|
||||
* Base type definitions - The peTI-NESulator Project
|
||||
* types.h - Taken from the Quick6502 project
|
||||
*
|
||||
* Created by Manoël Trapier on 18/09/06.
|
||||
* Copyright 2003-2007 986 Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-03-28 15:50:50 +0200 (mer, 28 mar 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/types.h $
|
||||
* $Revision: 25 $
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
#ifndef BYTE_TYPE_DEFINED
|
||||
#define BYTE_TYPE_DEFINED
|
||||
typedef unsigned char byte;
|
||||
#endif
|
||||
|
||||
typedef unsigned char bool;
|
||||
#include <stdint.h>
|
||||
|
||||
#define true (0)
|
||||
#define false (!true)
|
||||
|
||||
149
src/log.c
Normal file
149
src/log.c
Normal file
@ -0,0 +1,149 @@
|
||||
/**
|
||||
* Log Facility - The Quick6502 Project
|
||||
* log.c
|
||||
*
|
||||
* Created by Manoël Trapier on 19/05/10
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <color.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <log.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef TIME_STAMP_LOG
|
||||
|
||||
void time_stamp_line(void)
|
||||
{
|
||||
/* Time "0" will be thefirst log line */
|
||||
static char firstRun = 1;
|
||||
static struct timeval firstTime;
|
||||
struct timeval curTime;
|
||||
|
||||
int cMin, cSec;
|
||||
long long cMSec;
|
||||
|
||||
/* Get datetime */
|
||||
gettimeofday(&curTime, NULL);
|
||||
|
||||
if (firstRun == 1)
|
||||
{
|
||||
firstRun = 0;
|
||||
firstTime.tv_sec = curTime.tv_sec;
|
||||
firstTime.tv_usec = curTime.tv_usec;
|
||||
}
|
||||
|
||||
cMSec = ((curTime.tv_sec - firstTime.tv_sec) * 1000) + (curTime.tv_usec - firstTime.tv_usec) / 1000;
|
||||
cSec = (cMSec / 1000);
|
||||
cMSec %= 1000;
|
||||
|
||||
cMin = cSec / 60;
|
||||
|
||||
cSec %= 60;
|
||||
|
||||
/* Put cursor at start of line */
|
||||
printf("%c[s", 0x1B);
|
||||
printf("%c[7000D", 0x1B);
|
||||
printf("%c[1C", 0x1B);
|
||||
printf(FWHITE"[" FYELLOW "%03d" FRED "." FBLUE "%02d" FRED "." FGREEN "%03lld" FWHITE "]" CNORMAL, cMin, cSec,
|
||||
cMSec);
|
||||
printf("%c[u", 0x1B);
|
||||
}
|
||||
|
||||
#endif /* TIME_STAMP_LOG */
|
||||
|
||||
void log_real(int level, char *user, char *fmt, ...)
|
||||
{
|
||||
/* The LOG_PANIC must always be displayed */
|
||||
if ((level <= MAX_DEBUG_LEVEL) || (level <= LOG_PANIC))
|
||||
{
|
||||
va_list va;
|
||||
|
||||
switch (level)
|
||||
{
|
||||
case LOG_PANIC:
|
||||
printf(BRED FWHITE);
|
||||
break;
|
||||
case LOG_ERROR:
|
||||
printf(FRED);
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
printf(FYELLOW);
|
||||
break;
|
||||
default:
|
||||
case LOG_NORMAL:
|
||||
printf(FGREEN);
|
||||
break;
|
||||
case LOG_VERBOSE:
|
||||
printf(FCYAN);
|
||||
break;
|
||||
case LOG_DEBUG:
|
||||
printf(BBLUE FWHITE);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef TIME_STAMP_LOG
|
||||
printf(" ");
|
||||
#endif
|
||||
|
||||
if (user != NULL)
|
||||
{
|
||||
int i;
|
||||
i = strlen(user);
|
||||
if (i < 12)
|
||||
{
|
||||
i = 12 - i;
|
||||
for (; i >= 0 ; i--)
|
||||
{
|
||||
putchar(' ');
|
||||
}
|
||||
}
|
||||
printf("%s", user);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (level)
|
||||
{
|
||||
case LOG_PANIC:
|
||||
printf(" PANIC");
|
||||
break;
|
||||
case LOG_ERROR:
|
||||
printf(" Error");
|
||||
break;
|
||||
case LOG_WARNING:
|
||||
printf(" Warning");
|
||||
break;
|
||||
default:
|
||||
case LOG_NORMAL:
|
||||
printf(" Info");
|
||||
break;
|
||||
case LOG_VERBOSE:
|
||||
printf(" Verbose");
|
||||
break;
|
||||
case LOG_DEBUG:
|
||||
printf(" Debug");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf(CNORMAL ": ");
|
||||
|
||||
#ifdef TIME_STAMP_LOG
|
||||
time_stamp_line();
|
||||
#endif /* TIME_STAMP_LOG */
|
||||
|
||||
va_start(va, fmt);
|
||||
vprintf(fmt, va);
|
||||
va_end(va);
|
||||
|
||||
if (fmt[0] != 0)
|
||||
{
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
1919
src/main.c
1919
src/main.c
File diff suppressed because it is too large
Load Diff
15
src/mappersmanager/CMakeLists.txt
Normal file
15
src/mappersmanager/CMakeLists.txt
Normal file
@ -0,0 +1,15 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
|
||||
|
||||
file(GLOB mappers_list mappers/*.c)
|
||||
|
||||
if (COVERALLS)
|
||||
set(COVERAGE_SRCS src/mappersmanager/manager.c src/mappersmanager/utils.c ${COVERAGE_SRCS} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
add_library(mappermanager utils.c manager.c ${mappers_list} )
|
||||
@ -1,9 +1,9 @@
|
||||
/*
|
||||
* Mapper manager - The peTI-NESulator Project
|
||||
* manager.c
|
||||
* TI-NESulator.X
|
||||
*
|
||||
* Created by Manoël Trapier on 07/10/07.
|
||||
* Copyright 2007 986 Corp. All rights reserved.
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -12,51 +12,57 @@
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
MapperIRQ mapper_irqloop;
|
||||
MapperDump mapper_dump;
|
||||
#include <os_dependent.h>
|
||||
|
||||
MapperIRQ mapper_irqloop;
|
||||
MapperDump mapper_dump;
|
||||
MapperWriteHook mapper_hook;
|
||||
|
||||
typedef struct Mapper_
|
||||
{
|
||||
byte id;
|
||||
byte *name;
|
||||
{
|
||||
uint8_t id;
|
||||
char *name;
|
||||
|
||||
MapperInit init;
|
||||
MapperIRQ irq;
|
||||
MapperDump dump;
|
||||
|
||||
MapperInit init;
|
||||
MapperIRQ irq;
|
||||
MapperDump dump;
|
||||
|
||||
} Mapper;
|
||||
|
||||
#include "mappers_list.h"
|
||||
|
||||
void mapper_list ()
|
||||
void mapper_list()
|
||||
{
|
||||
Mapper *ptr = &(Mappers[0]);
|
||||
printf("Available mapers:\n");
|
||||
while(ptr->name != NULL)
|
||||
{
|
||||
printf("%d - %s\n", ptr->id, ptr->name);
|
||||
ptr++;
|
||||
}
|
||||
Mapper *ptr = &(Mappers[0]);
|
||||
console_printf(Console_Default, "Available mappers:\n");
|
||||
while (ptr->name != NULL)
|
||||
{
|
||||
console_printf(Console_Default, "%d - %s\n", ptr->id, ptr->name);
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
int mapper_init (NesCart *cart)
|
||||
int mapper_init(NesCart *cart)
|
||||
{
|
||||
Mapper *ptr = &(Mappers[0]);
|
||||
printf ("Search for a compatible mapper ID #%X:\n", cart->MapperID);
|
||||
while (ptr->name != NULL)
|
||||
{
|
||||
if (ptr->id == cart->MapperID)
|
||||
{
|
||||
printf ("Found mapper ID #%X - '%s'\n", ptr->id, ptr->name);
|
||||
ptr->init (cart);
|
||||
|
||||
mapper_irqloop = ptr->irq;
|
||||
mapper_dump = ptr->dump;
|
||||
|
||||
return 0;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
Mapper *ptr = &(Mappers[0]);
|
||||
console_printf(Console_Default, "Search for a compatible mapper ID #%d:\n", cart->MapperID);
|
||||
while (ptr->name != NULL)
|
||||
{
|
||||
if (ptr->id == cart->MapperID)
|
||||
{
|
||||
console_printf(Console_Default, "Found mapper ID #%d - '%s'\n", ptr->id, ptr->name);
|
||||
if (ptr->init)
|
||||
{
|
||||
ptr->init(cart);
|
||||
}
|
||||
|
||||
mapper_irqloop = ptr->irq;
|
||||
mapper_dump = ptr->dump;
|
||||
|
||||
return 0;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
console_printf(Console_Default, "No compatible mapper found!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
64
src/mappersmanager/mappers/aorom.c
Executable file
64
src/mappersmanager/mappers/aorom.c
Executable file
@ -0,0 +1,64 @@
|
||||
/*
|
||||
* AOROM Mapper - The peTI-NESulator Project
|
||||
* aorom.c
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "aorom.h"
|
||||
|
||||
uint8_t aorom_load_bank;
|
||||
|
||||
void aorom_MapperWriteHook(register uint8_t Addr, register uint8_t Value);
|
||||
|
||||
extern uint8_t *ppu_mem_nameTables;
|
||||
|
||||
int aorom_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_32k(0x8000, 0);
|
||||
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
|
||||
aorom_load_bank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, aorom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void aorom_MapperWriteHook(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
int BankNb;
|
||||
|
||||
if (Value & (1 << 4))
|
||||
{
|
||||
ppu_setSingleScreen(PPU_SCREEN_000);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppu_setSingleScreen(PPU_SCREEN_400);
|
||||
}
|
||||
|
||||
BankNb = Value & 0x0F;
|
||||
|
||||
aorom_load_bank = BankNb;
|
||||
|
||||
//console_printf(Console_Default, "aorom: Asking bank %d - NT is 0x%04X\n",BankNb,(Value&0x10)?0x2400:0x2000);
|
||||
set_prom_bank_32k(0x8000, BankNb);
|
||||
}
|
||||
|
||||
void aorom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "aorom: bank:%d\n", aorom_load_bank);
|
||||
}
|
||||
15
src/mappersmanager/mappers/aorom.h
Executable file
15
src/mappersmanager/mappers/aorom.h
Executable file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* AOROM Mapper - The peTI-NESulator Project
|
||||
* aorom.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int aorom_InitMapper(NesCart *cart);
|
||||
void aorom_MapperDump(FILE *fp);
|
||||
44
src/mappersmanager/mappers/cnrom.c
Executable file
44
src/mappersmanager/mappers/cnrom.c
Executable file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* CNROM Mapper - The peTI-NESulator Project
|
||||
* cnrom.c
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "cnrom.h"
|
||||
|
||||
uint8_t cnrom_load_bank;
|
||||
|
||||
void cnrom_MapperWriteHook(register uint8_t Addr, register uint8_t Value);
|
||||
|
||||
int cnrom_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart)); /* Set the last one */
|
||||
cnrom_load_bank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, cnrom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cnrom_MapperWriteHook(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
set_prom_bank_16k(0x8000, Value);
|
||||
cnrom_load_bank = Value;
|
||||
}
|
||||
|
||||
void cnrom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "cnrom: bank:%d\n", cnrom_load_bank);
|
||||
}
|
||||
15
src/mappersmanager/mappers/cnrom.h
Executable file
15
src/mappersmanager/mappers/cnrom.h
Executable file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* CNROM Mapper - The peTI-NESulator Project
|
||||
* cnrom.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int cnrom_InitMapper(NesCart *cart);
|
||||
void cnrom_MapperDump(FILE *fp);
|
||||
30
src/mappersmanager/mappers/genericmapper.c.template
Executable file
30
src/mappersmanager/mappers/genericmapper.c.template
Executable file
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Generic mapper implementation - The peTI-NESulator Project
|
||||
* genericmapper.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
int _InitMapper(NesCart * cart)
|
||||
{
|
||||
|
||||
set_prom_bank_16k(0xC000,0);
|
||||
set_prom_bank_16k(0x8000,-1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int _MapperWriteHook(register word Addr, register uint8_t Value)
|
||||
{
|
||||
|
||||
if (Addr > 0x7FFF) /* Try to write to the rom */
|
||||
{
|
||||
set_vrom_bank_8k(0x0000,Value)
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
122
src/mappersmanager/mappers/iremh3001.c
Executable file
122
src/mappersmanager/mappers/iremh3001.c
Executable file
@ -0,0 +1,122 @@
|
||||
/*
|
||||
* IREMH3001 Mapper - The peTI-NESulator Project
|
||||
* iremh3001.c
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "iremh3001.h"
|
||||
|
||||
uint16_t iremh3001_prom_slot[3];
|
||||
|
||||
uint16_t iremh3001_vrom_slot[8];
|
||||
|
||||
int iremh3001_InitMapper(NesCart *cart)
|
||||
{
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
iremh3001_prom_slot[0] = 0;
|
||||
iremh3001_prom_slot[1] = 1;
|
||||
iremh3001_prom_slot[2] = GETLAST16KBANK(cart);
|
||||
|
||||
set_vrom_bank_8k(0x0000, 4);
|
||||
|
||||
iremh3001_vrom_slot[0] = 0;
|
||||
iremh3001_vrom_slot[1] = 0;
|
||||
iremh3001_vrom_slot[2] = 0;
|
||||
iremh3001_vrom_slot[3] = 0;
|
||||
iremh3001_vrom_slot[4] = 0;
|
||||
iremh3001_vrom_slot[5] = 0;
|
||||
iremh3001_vrom_slot[6] = 0;
|
||||
iremh3001_vrom_slot[7] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int iremh3001_MapperWriteHook(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
#if 0
|
||||
switch(Addr)
|
||||
{
|
||||
case 0x8000: /* Set 8k PROM @ 8000 */
|
||||
console_printf(Console_Default, "iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0x8000, Value);
|
||||
iremh3001_prom_slot[0] = Value;
|
||||
break;
|
||||
|
||||
case 0x9003: /* Mirroring ??? */
|
||||
console_printf(Console_Default, "iremh3001: Mirroring[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0x9005: /* IRQ ??? */
|
||||
console_printf(Console_Default, "iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0x9006: /* IRQ ??? */
|
||||
console_printf(Console_Default, "iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0xA000: /* Set 8k PROM @ A000 */
|
||||
console_printf(Console_Default, "iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0xA000, Value);
|
||||
iremh3001_prom_slot[1] = Value;
|
||||
break;
|
||||
|
||||
case 0xB000: /* Set 1k VROM @ 0000 */
|
||||
case 0xB001: /* Set 1k VROM @ 0400 */
|
||||
case 0xB002: /* Set 1k VROM @ 0800 */
|
||||
case 0xB003: /* Set 1k VROM @ 0C00 */
|
||||
case 0xB004: /* Set 1k VROM @ 1000 */
|
||||
case 0xB005: /* Set 1k VROM @ 1400 */
|
||||
case 0xB006: /* Set 1k VROM @ 1800 */
|
||||
case 0xB007: /* Set 1k VROM @ 1C00 */
|
||||
console_printf(Console_Default, "iremh3001: %X: change VROM to %d[%X]\n", (Addr&0x0F)<<10, Value, Value);
|
||||
set_vrom_bank_1k((Addr&0xF)<<10, Value);
|
||||
iremh3001_vrom_slot[Addr&0x0F] = Value;
|
||||
break;
|
||||
|
||||
case 0xC000: /* Set 8k PROM @ C000 */
|
||||
console_printf(Console_Default, "iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0xC000, Value);
|
||||
iremh3001_prom_slot[2] = Value;
|
||||
break;
|
||||
|
||||
default:
|
||||
console_printf(Console_Default, "@:%X -- V:%X", Addr, Value);
|
||||
return 0;
|
||||
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iremh3001_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "iremh3001: prom: $8000:%d $A000:%d $C000:%d\n",
|
||||
iremh3001_prom_slot[0],
|
||||
iremh3001_prom_slot[1],
|
||||
iremh3001_prom_slot[2]);
|
||||
|
||||
fprintf(fp, "iremh3001: vrom: $0000:%d $0400:%d $0800:%d $0C00:%d\n" \
|
||||
" $1000:%d $1400:%d $1800:%d $1C00:%d\n",
|
||||
iremh3001_vrom_slot[0],
|
||||
iremh3001_vrom_slot[1],
|
||||
iremh3001_vrom_slot[2],
|
||||
iremh3001_vrom_slot[3],
|
||||
iremh3001_vrom_slot[4],
|
||||
iremh3001_vrom_slot[5],
|
||||
iremh3001_vrom_slot[6],
|
||||
iremh3001_vrom_slot[7]);
|
||||
}
|
||||
|
||||
|
||||
int iremh3001_MapperIRQ(int cycledone)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
16
src/mappersmanager/mappers/iremh3001.h
Executable file
16
src/mappersmanager/mappers/iremh3001.h
Executable file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* IREMH3001 Mapper - The peTI-NESulator Project
|
||||
* iremh3001.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int iremh3001_InitMapper(NesCart *cart);
|
||||
void iremh3001_MapperDump(FILE *fp);
|
||||
int iremh3001_MapperIRQ(int cycledone);
|
||||
@ -1,31 +1,23 @@
|
||||
/*
|
||||
* MMC1 Mapper - The TI-NESulator Project
|
||||
* MMC1 Mapper - The peTI-NESulator Project
|
||||
* mmc1.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc1.h $
|
||||
* $Revision: 50 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "norom.h"
|
||||
#include "mmc1.h"
|
||||
|
||||
#include <ppu/ppu.h>
|
||||
#include <memory/manager.h>
|
||||
uint8_t MMC1_reg0;
|
||||
|
||||
unsigned char MMC1_reg0;
|
||||
uint8_t MMC1_reg1;
|
||||
|
||||
unsigned char MMC1_reg1;
|
||||
uint8_t MMC1_reg2;
|
||||
|
||||
unsigned char MMC1_reg2;
|
||||
uint8_t MMC1_reg3;
|
||||
|
||||
unsigned char MMC1_reg3;
|
||||
|
||||
unsigned char mmc1_CurrentBank;
|
||||
uint8_t mmc1_CurrentBank;
|
||||
|
||||
#define MMC1_R0_MIRROR 0x01
|
||||
#define MMC1_R0_ONESCREEN 0x02
|
||||
@ -47,68 +39,69 @@ unsigned char mmc1_CurrentBank;
|
||||
#define MMC1_R3_RESET 0x80
|
||||
|
||||
|
||||
#define MMC1_REG0_DEFAULT MMC1_R0_PRGSIZE | MMC1_R0_PRGAREA
|
||||
#define MMC1_REG1_DEFAULT 0
|
||||
#define MMC1_REG2_DEFAULT 0
|
||||
#define MMC1_REG3_DEFAULT 0
|
||||
#define MMC1_REG0_DEFAULT (MMC1_R0_PRGSIZE | MMC1_R0_PRGAREA)
|
||||
#define MMC1_REG1_DEFAULT (0)
|
||||
#define MMC1_REG2_DEFAULT (0)
|
||||
#define MMC1_REG3_DEFAULT (0)
|
||||
|
||||
|
||||
void mmc1_MapperWriteReg0(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg1(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg2(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg3(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg0(register uint8_t Addr, register uint8_t Value);
|
||||
void mmc1_MapperWriteReg1(register uint8_t Addr, register uint8_t Value);
|
||||
void mmc1_MapperWriteReg2(register uint8_t Addr, register uint8_t Value);
|
||||
void mmc1_MapperWriteReg3(register uint8_t Addr, register uint8_t Value);
|
||||
|
||||
void mmc1_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"MMC1: r0:0x%02X r1:0x%02X r2:0x%02X r3:0x%02X\n",MMC1_reg0,MMC1_reg1,MMC1_reg2,MMC1_reg3);
|
||||
fprintf(fp, "MMC1: r0:0x%02X r1:0x%02X r2:0x%02X r3:0x%02X\n", MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
|
||||
}
|
||||
|
||||
int mmc1_InitMapper(NesCart * cart)
|
||||
int mmc1_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
MMC1_reg0 = MMC1_REG0_DEFAULT;
|
||||
|
||||
MMC1_reg1 = MMC1_REG1_DEFAULT;
|
||||
|
||||
MMC1_reg2 = MMC1_REG2_DEFAULT;
|
||||
|
||||
MMC1_reg3 = MMC1_REG3_DEFAULT;
|
||||
|
||||
set_prom_bank_16k(0x8000,0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
mmc1_CurrentBank = 0;
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
set_vrom_bank_4k(0x0000,0);
|
||||
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0x80; i < 0xA0 ; i++)
|
||||
MMC1_reg0 = MMC1_REG0_DEFAULT;
|
||||
|
||||
MMC1_reg1 = MMC1_REG1_DEFAULT;
|
||||
|
||||
MMC1_reg2 = MMC1_REG2_DEFAULT;
|
||||
|
||||
MMC1_reg3 = MMC1_REG3_DEFAULT;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
mmc1_CurrentBank = 0;
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg0);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xA0; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg1);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg2);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg3);
|
||||
set_page_writeable(i, true);
|
||||
set_vrom_bank_4k(0x0000, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0x80 ; i < 0xA0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg0);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xA0 ; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg1);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0 ; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg2);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg3);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
@ -129,24 +122,26 @@ Reg 0
|
||||
F : 1111
|
||||
|
||||
((Addr & 0x6000) >> 13) <- port number
|
||||
*/
|
||||
#define MMC1_GetReg(a) ((a & 0x6000) >> 13)
|
||||
/* (Val & 0x01) recuperation du bit */
|
||||
#define MMC1_GetBit(v) (v & 0x01)
|
||||
/* ( ( b & (1 << Bit)) | (v << Bit) ) Ajout du bit */
|
||||
#define MMC1_AddBit(b,v) ( ( b & ~(1 << Bit)) | (v << Bit) )
|
||||
*/
|
||||
|
||||
void mmc1_ApplyReg0Mod()
|
||||
#define MMC1_GetReg(_a) (((_a) & 0x6000) >> 13)
|
||||
/* (Val & 0x01) recuperation du bit */
|
||||
#define MMC1_GetBit(_v) ((_v) & 0x01)
|
||||
/* ( ( b & (1 << Bit)) | (v << Bit) ) Ajout du bit */
|
||||
#define MMC1_AddBit(_b, _v) ( ( (_b) & ~(1 << Bit)) | ( (_v) << Bit) )
|
||||
|
||||
void mmc1_ApplyReg0Mod()
|
||||
{
|
||||
|
||||
static unsigned char OldSwitchArea = MMC1_R0_PRGAREA;
|
||||
|
||||
|
||||
|
||||
//printf("Change to reg0 done ! (0x%x)\n\tMiror flag : %d\n\tOneScreen Flag : %d\n\tPRG Size : %d\n\tPRG Area : %d\n\tVROM Switch size : %d\n", MMC1_reg0, MMC1_reg0 & MMC1_R0_MIRROR, MMC1_reg0 & MMC1_R0_ONESCREEN, MMC1_reg0 & MMC1_R0_PRGAREA, MMC1_reg0 & MMC1_R0_PRGSIZE, MMC1_reg0 & MMC1_R0_VROMSW);
|
||||
|
||||
|
||||
static uint8_t OldSwitchArea = MMC1_R0_PRGAREA;
|
||||
|
||||
|
||||
|
||||
//console_printf(Console_Default, "Change to reg0 done ! (0x%x)\n\tMiror flag : %d\n\tOneScreen Flag : %d\n\tPRG Size : %d\n\tPRG Area : %d\n\tVROM Switch size : %d\n", MMC1_reg0, MMC1_reg0 & MMC1_R0_MIRROR, MMC1_reg0 & MMC1_R0_ONESCREEN, MMC1_reg0 & MMC1_R0_PRGAREA, MMC1_reg0 & MMC1_R0_PRGSIZE, MMC1_reg0 & MMC1_R0_VROMSW);
|
||||
|
||||
switch (MMC1_reg0 & 0x03)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
ppu_setSingleScreen(PPU_SCREEN_000);
|
||||
@ -164,38 +159,38 @@ void mmc1_ApplyReg0Mod()
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (OldSwitchArea != (MMC1_reg0 & MMC1_R0_PRGAREA)) && ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0 ) )
|
||||
|
||||
if ((OldSwitchArea != (MMC1_reg0 & MMC1_R0_PRGAREA)) && ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0))
|
||||
{
|
||||
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
|
||||
{ /* 0x8000 area */
|
||||
set_prom_bank_16k(0x8000,mmc1_CurrentBank);
|
||||
set_prom_bank_16k(0x8000, mmc1_CurrentBank);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(Cart));
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* 0xC000 area */
|
||||
|
||||
set_prom_bank_16k(0x8000,0);
|
||||
set_prom_bank_16k(0xC000,mmc1_CurrentBank);
|
||||
|
||||
}
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, mmc1_CurrentBank);
|
||||
|
||||
}
|
||||
|
||||
OldSwitchArea = (MMC1_reg0 & MMC1_R0_PRGAREA);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int VROMBankNb;
|
||||
unsigned char Bit = 0;
|
||||
unsigned char BitBuf = 0;
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg0(register byte Addr, register byte Value)
|
||||
uint32_t VROMBankNb;
|
||||
uint8_t Bit = 0;
|
||||
uint8_t BitBuf = 0;
|
||||
|
||||
void mmc1_MapperWriteReg0(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg0 = MMC1_REG0_DEFAULT;
|
||||
printf("MMC1: Reg0 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg0 Reset occurred !\n");
|
||||
mmc1_ApplyReg0Mod();
|
||||
}
|
||||
else
|
||||
@ -204,25 +199,25 @@ void mmc1_MapperWriteReg0(register byte Addr, register byte Value)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
|
||||
MMC1_reg0 = BitBuf;
|
||||
|
||||
|
||||
mmc1_ApplyReg0Mod();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg1(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg1(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg1 = MMC1_REG1_DEFAULT;
|
||||
printf("MMC1: Reg1 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg1 Reset occurred !\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -230,42 +225,43 @@ void mmc1_MapperWriteReg1(register byte Addr, register byte Value)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
|
||||
MMC1_reg1 = BitBuf;
|
||||
|
||||
|
||||
VROMBankNb = (MMC1_reg1 /* & MMC1_R1_VROMB1 */ );
|
||||
|
||||
if (Cart->VROMSize == 0)
|
||||
{
|
||||
printf("Try to change VROM but with didn't have any VROM ! [%04X]\n", VROMBankNb);
|
||||
console_printf(Console_Default, "Try to change VROM but with didn't have any VROM ! [%04X]\n",
|
||||
VROMBankNb);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (MMC1_reg0 & MMC1_R0_VROMSW) != 0 )
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_VROMSW) != 0)
|
||||
{ /* 4K vram */
|
||||
//printf("Switching VROM at 0x0000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x0000,VROMBankNb);
|
||||
//console_printf(Console_Default, "Switching VROM at 0x0000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x0000, VROMBankNb);
|
||||
}
|
||||
else
|
||||
{ /* 8K vram */
|
||||
//printf("Switching VROM at 0x0000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
set_vrom_bank_8k(0x0000,VROMBankNb>>1);
|
||||
//console_printf(Console_Default, "Switching VROM at 0x0000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
set_vrom_bank_8k(0x0000, VROMBankNb >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg2(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg2(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg2 = MMC1_REG2_DEFAULT;
|
||||
printf("MMC1: Reg2 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg2 Reset occurred !\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -273,43 +269,43 @@ void mmc1_MapperWriteReg2(register byte Addr, register byte Value)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
MMC1_reg2 = BitBuf;
|
||||
|
||||
|
||||
VROMBankNb = (MMC1_reg2 /* & MMC1_R2_VROMB2 */ );
|
||||
|
||||
//printf("Want to switch VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
|
||||
//console_printf(Console_Default, "Want to switch VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
if (Cart->VROMSize == 0)
|
||||
{
|
||||
//printf(": No\n");
|
||||
//console_printf(Console_Default, ": No\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (MMC1_reg0 & MMC1_R0_VROMSW) != 0 )
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_VROMSW) != 0)
|
||||
{ /* 4K vram */
|
||||
//printf("Switching VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x1000,VROMBankNb);
|
||||
//console_printf(Console_Default, "Switching VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x1000, VROMBankNb);
|
||||
}
|
||||
else
|
||||
{ /* 8K vram */
|
||||
// printf("Switching VROM at 0x1000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
// set_vrom_bank_8k(0x1000,VROMBankNb>>1);
|
||||
// console_printf(Console_Default, "Switching VROM at 0x1000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
// set_vrom_bank_8k(0x1000,VROMBankNb>>1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg3(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg3(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg3 = MMC1_REG3_DEFAULT;
|
||||
printf("MMC1: Reg3 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg3 Reset occurred !\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -317,36 +313,38 @@ void mmc1_MapperWriteReg3(register byte Addr, register byte Value)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
|
||||
MMC1_reg3 = BitBuf;
|
||||
|
||||
if (MMC1_reg3<<14 > Cart->PROMSize)
|
||||
|
||||
if (((uint32_t)MMC1_reg3 << 14) > Cart->PROMSize)
|
||||
{
|
||||
return;
|
||||
|
||||
if ( (MMC1_reg0 & MMC1_R0_PRGSIZE) != 0 )
|
||||
}
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0)
|
||||
{ /* 16K Switch */
|
||||
if ( (MMC1_reg0 & MMC1_R0_PRGAREA) != 0 )
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
|
||||
{ /* 0x8000 switch */
|
||||
set_prom_bank_16k(0x8000,MMC1_reg3);
|
||||
//printf("LowBank is now %d ( 0x%p )\n", MMC1_reg3, mLBank);
|
||||
set_prom_bank_16k(0x8000, MMC1_reg3);
|
||||
//console_printf(Console_Default, "LowBank is now %d ( 0x%p )\n", MMC1_reg3, mLBank);
|
||||
}
|
||||
else
|
||||
{ /* 0xC000 switch */
|
||||
set_prom_bank_16k(0xC000,MMC1_reg3);
|
||||
//printf("HighBank is now %d ( 0x%p )\n", MMC1_reg3, mUBank);
|
||||
set_prom_bank_16k(0xC000, MMC1_reg3);
|
||||
//console_printf(Console_Default, "HighBank is now %d ( 0x%p )\n", MMC1_reg3, mUBank);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* 32K Switch */
|
||||
set_prom_bank_32k(0x8000,MMC1_reg3>>1);
|
||||
set_prom_bank_32k(0x8000, MMC1_reg3 >> 1);
|
||||
}
|
||||
|
||||
if ( ( MMC1_reg3 & MMC1_R3_SAVECE ) != 0)
|
||||
|
||||
if ((MMC1_reg3 & MMC1_R3_SAVECE) != 0)
|
||||
{
|
||||
unmap_sram();
|
||||
}
|
||||
@ -356,6 +354,6 @@ void mmc1_MapperWriteReg3(register byte Addr, register byte Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("MMC1: Debug (Reg:%d,Val:0x%02X,reg0:0x%02X,reg1:0x%02X,reg2:0x%02X,reg3:0x%02X)\n", MMC1_GetReg(Addr), Value, MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
|
||||
}
|
||||
|
||||
//console_printf(Console_Default, "MMC1: Debug (Reg:%d,Val:0x%02X,reg0:0x%02X,reg1:0x%02X,reg2:0x%02X,reg3:0x%02X)\n", MMC1_GetReg(Addr), Value, MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
|
||||
|
||||
@ -1,16 +1,16 @@
|
||||
/*
|
||||
* MMC1 Mapper - The peTI-NESulator Project
|
||||
* mmc1.h
|
||||
* TI-NESulator.X
|
||||
*
|
||||
* Created by Manoël Trapier on 02/12/07.
|
||||
* Copyright 2007 986 Corp. All rights reserved.
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int mmc1_InitMapper (NesCart *cart);
|
||||
int mmc1_MapperIRQ (int cycledone);
|
||||
void mmc1_MapperDump ();
|
||||
void mmc1_MapperWriteHook(register byte Addr, register byte Value);
|
||||
int mmc1_InitMapper(NesCart *cart);
|
||||
int mmc1_MapperIRQ(int cycledone);
|
||||
void mmc1_MapperDump(FILE *fp);
|
||||
340
src/mappersmanager/mappers/mmc3.c
Executable file
340
src/mappersmanager/mappers/mmc3.c
Executable file
@ -0,0 +1,340 @@
|
||||
/*
|
||||
* MMC3 Mapper - The peTI-NESulator Project
|
||||
* mmc3.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
#include "mmc3.h"
|
||||
|
||||
extern uint16_t ScanLine;
|
||||
|
||||
uint16_t mmc3_command;
|
||||
|
||||
uint8_t mmc3_irq_counter;
|
||||
uint8_t mmc3_irq_counter_reload;
|
||||
uint8_t mmc3_irq_enable;
|
||||
|
||||
uint16_t mmc3_first_prom_page;
|
||||
uint16_t mmc3_second_prom_page;
|
||||
|
||||
uint8_t mmc3_use_xor;
|
||||
uint8_t mmc3_last_vrom[6];
|
||||
|
||||
uint8_t mmc3_last_prom[2];
|
||||
uint8_t mmc3_last_prom_switch;
|
||||
|
||||
uint16_t dummy;
|
||||
|
||||
void mmc3_MapperWrite80Hook(uint8_t addr, uint8_t Value);
|
||||
void mmc3_MapperWriteA0Hook(uint8_t addr, uint8_t Value);
|
||||
void mmc3_MapperWriteC0Hook(uint8_t addr, uint8_t Value);
|
||||
void mmc3_MapperWriteE0Hook(uint8_t addr, uint8_t Value);
|
||||
|
||||
void mmc3_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "MMC3: CMD:%d IC:%d IR:%d IE:%d FPP:0x%04X SPP:0x%04X UX:%d\n", mmc3_command, mmc3_irq_counter,
|
||||
mmc3_irq_counter_reload, mmc3_irq_enable, mmc3_first_prom_page, mmc3_second_prom_page, mmc3_use_xor);
|
||||
fprintf(fp, "MMC3: LV0:%d LV1:%d LV2:%d LV3:%d LV4:%d LV5:%d\n", mmc3_last_vrom[0], mmc3_last_vrom[1],
|
||||
mmc3_last_vrom[2], mmc3_last_vrom[3], mmc3_last_vrom[4], mmc3_last_vrom[5]);
|
||||
fprintf(fp, "MMC3: LP0:%d LP1:%d LPS:%d\n", mmc3_last_prom[0], mmc3_last_prom[1], mmc3_last_prom_switch);
|
||||
}
|
||||
|
||||
int mmc3_InitMapper(NesCart *cart)
|
||||
{
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
if (Cart->VROMSize > 0)
|
||||
{
|
||||
set_vrom_bank_8k(0, 0x0000);
|
||||
}
|
||||
|
||||
mmc3_command = -1;
|
||||
|
||||
mmc3_irq_counter = -1;
|
||||
mmc3_irq_enable = 0;
|
||||
mmc3_irq_counter_reload = 0;
|
||||
|
||||
mmc3_use_xor = 0x42;
|
||||
|
||||
mmc3_last_prom_switch = 0x42;
|
||||
|
||||
mmc3_last_prom[0] = 0;
|
||||
mmc3_last_prom[1] = 1;
|
||||
|
||||
mmc3_last_vrom[0] = 0;
|
||||
mmc3_last_vrom[1] = 2;
|
||||
mmc3_last_vrom[2] = 3;
|
||||
mmc3_last_vrom[3] = 4;
|
||||
mmc3_last_vrom[4] = 5;
|
||||
mmc3_last_vrom[5] = 6;
|
||||
|
||||
mmc3_first_prom_page = 0x8000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
/* Register mapper write hook */
|
||||
set_page_wr_hook(0x80, mmc3_MapperWrite80Hook);
|
||||
set_page_writeable(0x80, true);
|
||||
|
||||
set_page_wr_hook(0xA0, mmc3_MapperWriteA0Hook);
|
||||
set_page_writeable(0xA0, true);
|
||||
|
||||
set_page_wr_hook(0xC0, mmc3_MapperWriteC0Hook);
|
||||
set_page_writeable(0xC0, true);
|
||||
|
||||
set_page_wr_hook(0xE0, mmc3_MapperWriteE0Hook);
|
||||
set_page_writeable(0xE0, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void mmc3_MapperWrite80Hook(uint8_t addr, uint8_t Value)
|
||||
{
|
||||
//console_printf(Console_Default, "%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
|
||||
if ((Cart->VROMSize > 0) && (mmc3_use_xor != (Value & 0x80)))
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
set_vrom_bank_1k(0x0000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x0400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x0800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x0C00, mmc3_last_vrom[5]);
|
||||
set_vrom_bank_2k(0x1000, mmc3_last_vrom[0] >> 1);
|
||||
set_vrom_bank_2k(0x1800, mmc3_last_vrom[1] >> 1);
|
||||
//chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1
|
||||
}
|
||||
else
|
||||
{
|
||||
set_vrom_bank_2k(0x0000, mmc3_last_vrom[0] >> 1);
|
||||
set_vrom_bank_2k(0x0800, mmc3_last_vrom[1] >> 1);
|
||||
set_vrom_bank_1k(0x1000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x1400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x1800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x1C00, mmc3_last_vrom[5]);
|
||||
//chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7
|
||||
}
|
||||
mmc3_use_xor = (Value & 0x80);
|
||||
}
|
||||
|
||||
|
||||
if (mmc3_last_prom_switch != (Value & 0x40))
|
||||
{
|
||||
if (!(Value & 0x40))
|
||||
{
|
||||
console_printf(Console_Default, "MMC3: Switch -> 8/A\n");
|
||||
mmc3_first_prom_page = 0x8000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
|
||||
set_prom_bank_8k(0xC000, GETLAST08KBANK(Cart) - 1);
|
||||
//set_prom_bank_8k(0xE000, GETLAST08KBANK(cart));
|
||||
//prg_bank(prg0,prg1,max_prg-1,max_prg);
|
||||
}
|
||||
else
|
||||
{
|
||||
console_printf(Console_Default, "MMC3: Switch -> C/A\n");
|
||||
mmc3_first_prom_page = 0xC000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
|
||||
set_prom_bank_8k(0x8000, GETLAST08KBANK(Cart) - 1);
|
||||
|
||||
|
||||
//prg_bank(max_prg-1,prg1,prg0,max_prg);
|
||||
}
|
||||
mmc3_last_prom_switch = (Value & 0x40);
|
||||
}
|
||||
mmc3_command = Value & 0x07;
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{ /* 8001 */
|
||||
switch (mmc3_command)
|
||||
{
|
||||
default:
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
if (Cart->VROMSize == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
mmc3_last_vrom[mmc3_command] = Value;
|
||||
|
||||
if (mmc3_use_xor)
|
||||
{
|
||||
set_vrom_bank_1k(0x0000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x0400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x0800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x0C00, mmc3_last_vrom[5]);
|
||||
set_vrom_bank_2k(0x1000, mmc3_last_vrom[0] >> 1);
|
||||
set_vrom_bank_2k(0x1800, mmc3_last_vrom[1] >> 1);
|
||||
//chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1
|
||||
}
|
||||
else
|
||||
{
|
||||
set_vrom_bank_2k(0x0000, mmc3_last_vrom[0] >> 1);
|
||||
set_vrom_bank_2k(0x0800, mmc3_last_vrom[1] >> 1);
|
||||
set_vrom_bank_1k(0x1000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x1400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x1800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x1C00, mmc3_last_vrom[5]);
|
||||
//chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
mmc3_last_prom[0] = Value;
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
mmc3_last_prom[1] = Value;
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/*if(mmc3_use_xor)
|
||||
chr_bank(chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1);
|
||||
else
|
||||
chr_bank(chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7);*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteA0Hook(uint8_t addr, uint8_t Value)
|
||||
{
|
||||
//console_printf(Console_Default, "%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
//console_printf(Console_Default, "MMC3: Select mirroring (0xA000) : 0x%X\n",Value);
|
||||
|
||||
if (Value & 0x1)
|
||||
{
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//console_printf(Console_Default, "MMC3: SaveRAM Toggle (0xA001) : 0x%X\n",Value);
|
||||
if (Value)
|
||||
{
|
||||
map_sram();
|
||||
}
|
||||
else
|
||||
{
|
||||
unmap_sram();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteC0Hook(uint8_t addr, uint8_t Value)
|
||||
{
|
||||
//console_printf(Console_Default, "%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
mmc3_irq_counter_reload = Value;
|
||||
mmc3_irq_counter = Value;
|
||||
//console_printf(Console_Default, "MMC3 IRQ[%d]: SetIRQ reload to %d\n", ScanLine, Value);
|
||||
|
||||
}
|
||||
else
|
||||
{ /* C001 */
|
||||
//console_printf(Console_Default, "MMC3: New tmp IRQ value (0xC001) : 0x%X\n",Value);
|
||||
//console_printf(Console_Default, "MMC3 IRQ[%d]: Reset IRQ counter to val %d [Value = %d]\n", ScanLine, mmc3_irq_counter_reload, Value);
|
||||
mmc3_irq_counter = Value;
|
||||
}
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteE0Hook(uint8_t addr, uint8_t Value)
|
||||
{
|
||||
//console_printf(Console_Default, "%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
//console_printf(Console_Default, "MMC3: Writing to 0xE001 : 0x%X\n",Value);
|
||||
//console_printf(Console_Default, "MMC3 IRQ[%d]: IRQ disabled\n", ScanLine);
|
||||
mmc3_irq_enable = 0;
|
||||
//MapperWantIRQ = 1;
|
||||
// Add a way to raise an IRQ
|
||||
|
||||
}
|
||||
else
|
||||
{ /* E001 */
|
||||
//console_printf(Console_Default, "MMC3: Writing to 0xE001 : 0x%X\n",Value);
|
||||
//console_printf(Console_Default, "MMC3: IRQ Enabled (value : %d)\n",mmc3_irq_counter);
|
||||
//console_printf(Console_Default, "MMC3 IRQ[%d]: Enable IRQ\nr", ScanLine);
|
||||
mmc3_irq_enable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int mmc3_MapperIRQ(int cycledone)
|
||||
{
|
||||
if (((cycledone > 0) && (cycledone < 241)) /*&&
|
||||
(ppu.ControlRegister2.b & (PPU_CR2_BGVISIBILITY | PPU_CR2_SPRTVISIBILITY)) == (PPU_CR2_BGVISIBILITY | PPU_CR2_SPRTVISIBILITY)*/)
|
||||
{
|
||||
|
||||
if ((mmc3_irq_counter--) > 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Load next counter position */
|
||||
mmc3_irq_counter = mmc3_irq_counter_reload;
|
||||
|
||||
if (mmc3_irq_enable == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
mmc3_irq_enable = 0;
|
||||
|
||||
//console_printf(Console_Default, "MMC3 IRQ[%d]: Tick next at %d\n", ScanLine, mmc3_irq_counter_reload);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
16
src/mappersmanager/mappers/mmc3.h
Executable file
16
src/mappersmanager/mappers/mmc3.h
Executable file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* MMC3 Mapper - The peTI-NESulator Project
|
||||
* mmc3.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
void mmc3_MapperDump(FILE *fp);
|
||||
int mmc3_InitMapper(NesCart *cart);
|
||||
int mmc3_MapperIRQ(int cycledone);
|
||||
141
src/mappersmanager/mappers/mmc4.c
Normal file
141
src/mappersmanager/mappers/mmc4.c
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* MMC4 Mapper - The peTI-NESulator Project
|
||||
* mmc4.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mmc4.h"
|
||||
|
||||
uint8_t mmc4_RegA;
|
||||
uint8_t mmc4_RegB;
|
||||
uint8_t mmc4_RegC;
|
||||
uint8_t mmc4_RegD;
|
||||
uint8_t mmc4_RegE;
|
||||
uint8_t mmc4_RegF;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG(s) printf s
|
||||
#else
|
||||
#define LOG(s) { }
|
||||
#endif
|
||||
|
||||
/* MAPPER WARNING: This mapper need to attach to the PPU memory... Need more work on this parts.. */
|
||||
|
||||
void mmc4_MapperWriteRegA(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
LOG(("%s(%02X, %02X)\n", __func__, Addr, Value));
|
||||
mmc4_RegA = Value;
|
||||
|
||||
set_prom_bank_16k(0x8000, Value & 0x0F);
|
||||
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegB(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
LOG(("%s(%02X, %02X)\n", __func__, Addr, Value));
|
||||
mmc4_RegB = Value;
|
||||
|
||||
set_vrom_bank_4k(0x0000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegC(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
LOG(("%s(%02X, %02X)\n", __func__, Addr, Value));
|
||||
mmc4_RegC = Value;
|
||||
set_vrom_bank_4k(0x0000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegD(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
LOG(("%s(%02X, %02X)\n", __func__, Addr, Value));
|
||||
mmc4_RegD = Value;
|
||||
set_vrom_bank_4k(0x1000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegE(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
LOG(("%s(%02X, %02X)\n", __func__, Addr, Value));
|
||||
mmc4_RegE = Value;
|
||||
set_vrom_bank_4k(0x1000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegF(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
LOG(("%s(%02X, %02X)\n", __func__, Addr, Value));
|
||||
mmc4_RegF = Value;
|
||||
if (Value & 0x01)
|
||||
{
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void mmc4_MapperDump(FILE *fp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int mmc4_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
{
|
||||
set_vrom_bank_8k(0x0000, 0);
|
||||
}
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0xA0 ; i < 0xB0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegA);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xB0 ; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegB);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0 ; i < 0xD0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegC);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xD0 ; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegD);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0 ; i < 0xF0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegE);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xF0 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegF);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
for (i = 0x60 ; i < 0x80 ; i++)
|
||||
{
|
||||
set_page_writeable(i, true);
|
||||
set_page_readable(i, true);
|
||||
}
|
||||
|
||||
//ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
//ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
15
src/mappersmanager/mappers/mmc4.h
Normal file
15
src/mappersmanager/mappers/mmc4.h
Normal file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* MMC4 Mapper - The peTI-NESulator Project
|
||||
* mmc4.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
void mmc4_MapperDump(FILE *fp);
|
||||
int mmc4_InitMapper(NesCart *cart);
|
||||
@ -1,48 +1,47 @@
|
||||
/*
|
||||
* NOROM Mapper - The peTI-NESulator Project
|
||||
* norom.c
|
||||
* TI-NESulator.X
|
||||
*
|
||||
* Created by Manoël Trapier on 25/10/07.
|
||||
* Copyright 2007 986 Corp. All rights reserved.
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "norom.h"
|
||||
|
||||
int norom_InitMapper(NesCart *cart)
|
||||
int norom_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_page_ptr_16k(0x80, cart->PROMBanks);
|
||||
|
||||
/* mUBank = 0xC000 */
|
||||
if (cart->PROMSize > (16*1024))
|
||||
{
|
||||
set_prom_bank_16k(0xC000, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_prom_bank_16k(0xC000, 0);
|
||||
}
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
set_vrom_bank_8k(0x2000, 0);
|
||||
|
||||
return 0;
|
||||
set_page_ptr_16k(0x80, cart->PROMBanks);
|
||||
|
||||
/* mUBank = 0xC000 */
|
||||
if (cart->PROMSize > (16 * 1024))
|
||||
{
|
||||
set_prom_bank_16k(0xC000, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_prom_bank_16k(0xC000, 0);
|
||||
}
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
{
|
||||
set_vrom_bank_8k(0x2000, 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int norom_MapperIRQ(int cycledone)
|
||||
{
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void norom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
void norom_MapperWriteHook(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
/* Nothing to do */
|
||||
return;
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
void norom_MapperDump (FILE *fp)
|
||||
void norom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "norom mapper have nothing to dump");
|
||||
fprintf(fp, "norom mapper have nothing to dump");
|
||||
}
|
||||
@ -1,16 +1,16 @@
|
||||
/*
|
||||
* norom.h
|
||||
* TI-NESulator.X
|
||||
* NOROM Mapper - The peTI-NESulator Project
|
||||
* norom.c
|
||||
*
|
||||
* Created by Manoël Trapier on 25/10/07.
|
||||
* Copyright 2007 986 Corp. All rights reserved.
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int norom_InitMapper (NesCart *cart);
|
||||
int norom_MapperIRQ (int cycledone);
|
||||
void norom_MapperDump ();
|
||||
void norom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
int norom_InitMapper(NesCart *cart);
|
||||
int norom_MapperIRQ(int cycledone);
|
||||
void norom_MapperDump(FILE *fp);
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* AOROM Mapper - The TI-NESulator Project
|
||||
* aorom.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-26 18:47:34 +0200 (jeu, 26 avr 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/aorom.h $
|
||||
* $Revision: 46 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char aorom_load_bank;
|
||||
|
||||
void aorom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
|
||||
extern byte *ppu_mem_nameTables;
|
||||
|
||||
int aorom_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_32k(0x8000,0);
|
||||
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
|
||||
aorom_load_bank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80; i < 0x100; i++)
|
||||
{
|
||||
set_page_wr_hook(i, aorom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void aorom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
{
|
||||
int BankNb;
|
||||
|
||||
if (Value & (1 << 4))
|
||||
ppu_setSingleScreen(PPU_SCREEN_000);
|
||||
else
|
||||
ppu_setSingleScreen(PPU_SCREEN_400);
|
||||
|
||||
BankNb = Value & 0x0F;
|
||||
|
||||
aorom_load_bank = BankNb;
|
||||
|
||||
//printf("aorom: Asking bank %d (giving %d & %d) - mirror is %d\n",BankNb,BankNb,(Value<<1)+1,Value&0x0F);
|
||||
set_prom_bank_32k(0x8000,BankNb);
|
||||
}
|
||||
|
||||
void aorom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"aorom: bank:%d\n",aorom_load_bank);
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* CNROM Mapper - The TI-NESulator Project
|
||||
* cnrom.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/cnrom.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char cnrom_load_bank;
|
||||
|
||||
void cnrom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
|
||||
int cnrom_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart)); /* Set the last one */
|
||||
cnrom_load_bank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80; i < 0x100; i++)
|
||||
{
|
||||
set_page_wr_hook(i, cnrom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cnrom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
{
|
||||
set_prom_bank_16k(0x8000,Value);
|
||||
cnrom_load_bank = Value;
|
||||
}
|
||||
|
||||
void cnrom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"cnrom: bank:%d\n",cnrom_load_bank);
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
/*
|
||||
* Generic mapper implementation - The TI-NESulator Project
|
||||
* genericmapper.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/genericmapper.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
int _InitMapper(NesCart * cart)
|
||||
{
|
||||
|
||||
set_prom_bank_16k(0xC000,0);
|
||||
set_prom_bank_16k(0x8000,-1);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int _MapperWriteHook(register word Addr, register byte Value)
|
||||
{
|
||||
|
||||
if (Addr > 0x7FFF) /* Try to write to the rom */
|
||||
{
|
||||
set_vrom_bank_8k(0x0000,Value)
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* IREMH3001 Mapper - The TI-NESulator Project
|
||||
* iremh3001.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/iremh3001.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned short iremh3001_prom_slot[3];
|
||||
|
||||
unsigned short iremh3001_vrom_slot[8];
|
||||
|
||||
int iremh3001_InitMapper(NesCart * cart)
|
||||
{
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
iremh3001_prom_slot[0] = 0;
|
||||
iremh3001_prom_slot[1] = 1;
|
||||
iremh3001_prom_slot[2] = GETLAST16KBANK(cart);
|
||||
|
||||
set_vrom_bank_8k(0x0000,4);
|
||||
|
||||
iremh3001_vrom_slot[0] = 0;
|
||||
iremh3001_vrom_slot[1] = 0;
|
||||
iremh3001_vrom_slot[2] = 0;
|
||||
iremh3001_vrom_slot[3] = 0;
|
||||
iremh3001_vrom_slot[4] = 0;
|
||||
iremh3001_vrom_slot[5] = 0;
|
||||
iremh3001_vrom_slot[6] = 0;
|
||||
iremh3001_vrom_slot[7] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int iremh3001_MapperWriteHook(register word Addr, register byte Value)
|
||||
{
|
||||
|
||||
switch(Addr)
|
||||
{
|
||||
case 0x8000: /* Set 8k PROM @ 8000 */
|
||||
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0x8000, Value);
|
||||
iremh3001_prom_slot[0] = Value;
|
||||
break;
|
||||
|
||||
case 0x9003: /* Mirroring ??? */
|
||||
printf("iremh3001: Mirroring[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0x9005: /* IRQ ??? */
|
||||
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0x9006: /* IRQ ??? */
|
||||
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0xA000: /* Set 8k PROM @ A000 */
|
||||
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0xA000, Value);
|
||||
iremh3001_prom_slot[1] = Value;
|
||||
break;
|
||||
|
||||
case 0xB000: /* Set 1k VROM @ 0000 */
|
||||
case 0xB001: /* Set 1k VROM @ 0400 */
|
||||
case 0xB002: /* Set 1k VROM @ 0800 */
|
||||
case 0xB003: /* Set 1k VROM @ 0C00 */
|
||||
case 0xB004: /* Set 1k VROM @ 1000 */
|
||||
case 0xB005: /* Set 1k VROM @ 1400 */
|
||||
case 0xB006: /* Set 1k VROM @ 1800 */
|
||||
case 0xB007: /* Set 1k VROM @ 1C00 */
|
||||
printf("iremh3001: %X: change VROM to %d[%X]\n", (Addr&0x0F)<<10, Value, Value);
|
||||
set_vrom_bank_1k((Addr&0xF)<<10, Value);
|
||||
iremh3001_vrom_slot[Addr&0x0F] = Value;
|
||||
break;
|
||||
|
||||
case 0xC000: /* Set 8k PROM @ C000 */
|
||||
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0xC000, Value);
|
||||
iremh3001_prom_slot[2] = Value;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("@:%X -- V:%X", Addr, Value);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iremh3001_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"iremh3001: prom: $8000:%d $A000:%d $C000:%d\n",
|
||||
iremh3001_prom_slot[0],
|
||||
iremh3001_prom_slot[1],
|
||||
iremh3001_prom_slot[2]);
|
||||
|
||||
fprintf(fp,"iremh3001: vrom: $0000:%d $0400:%d $0800:%d $0C00:%d\n" \
|
||||
" $1000:%d $1400:%d $1800:%d $1C00:%d\n",
|
||||
iremh3001_vrom_slot[0],
|
||||
iremh3001_vrom_slot[1],
|
||||
iremh3001_vrom_slot[2],
|
||||
iremh3001_vrom_slot[3],
|
||||
iremh3001_vrom_slot[4],
|
||||
iremh3001_vrom_slot[5],
|
||||
iremh3001_vrom_slot[6],
|
||||
iremh3001_prom_slot[7]);
|
||||
}
|
||||
|
||||
|
||||
int iremh3001_MapperIRQ(int cycledone)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,317 +0,0 @@
|
||||
/*
|
||||
* MMC3 Mapper - The TI-NESulator Project
|
||||
* mmc3.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc3.h $
|
||||
* $Revision: 50 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned short mmc3_command;
|
||||
|
||||
unsigned char mmc3_irq_counter;
|
||||
unsigned char mmc3_irq_counter_reload;
|
||||
unsigned char mmc3_irq_enable;
|
||||
|
||||
unsigned short mmc3_first_prom_page;
|
||||
unsigned short mmc3_second_prom_page;
|
||||
|
||||
unsigned char mmc3_use_xor;
|
||||
unsigned char mmc3_last_vrom[6];
|
||||
|
||||
unsigned char mmc3_last_prom[2];
|
||||
unsigned char mmc3_last_prom_switch;
|
||||
|
||||
unsigned short dummy;
|
||||
|
||||
void mmc3_MapperWrite80Hook(byte addr, byte value);
|
||||
void mmc3_MapperWriteA0Hook(byte addr, byte value);
|
||||
void mmc3_MapperWriteC0Hook(byte addr, byte value);
|
||||
void mmc3_MapperWriteE0Hook(byte addr, byte value);
|
||||
|
||||
void mmc3_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"MMC3: CMD:%d IC:%d IR:%d IE:%d FPP:0x%04X SPP:0x%04X UX:%d\n",mmc3_command,mmc3_irq_counter,mmc3_irq_counter_reload,mmc3_irq_enable,mmc3_first_prom_page,mmc3_second_prom_page,mmc3_use_xor);
|
||||
fprintf(fp,"MMC3: LV0:%d LV1:%d LV2:%d LV3:%d LV4:%d LV5:%d\n",mmc3_last_vrom[0],mmc3_last_vrom[1],mmc3_last_vrom[2],mmc3_last_vrom[3],mmc3_last_vrom[4],mmc3_last_vrom[5]);
|
||||
fprintf(fp,"MMC3: LP0:%d LP1:%d LPS:%d\n",mmc3_last_prom[0],mmc3_last_prom[1],mmc3_last_prom_switch);
|
||||
}
|
||||
|
||||
int mmc3_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
if ( Cart->VROMSize > 0)
|
||||
{
|
||||
set_vrom_bank_8k(0, 0x0000);
|
||||
}
|
||||
|
||||
mmc3_command = -1;
|
||||
|
||||
mmc3_irq_counter = -1;
|
||||
mmc3_irq_enable = 1;
|
||||
mmc3_irq_counter_reload = 0;
|
||||
|
||||
mmc3_use_xor = 0x42;
|
||||
|
||||
mmc3_last_prom_switch = 0x42;
|
||||
|
||||
mmc3_last_prom[0] = 0;
|
||||
mmc3_last_prom[1] = 1;
|
||||
|
||||
mmc3_last_vrom[0] = 0;
|
||||
mmc3_last_vrom[1] = 2;
|
||||
mmc3_last_vrom[2] = 3;
|
||||
mmc3_last_vrom[3] = 4;
|
||||
mmc3_last_vrom[4] = 5;
|
||||
mmc3_last_vrom[5] = 6;
|
||||
|
||||
mmc3_first_prom_page = 0x8000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
//mmc3_first_prom_page = 0; // Set it to 0x8000
|
||||
|
||||
|
||||
/* Register mapper write hook */
|
||||
set_page_wr_hook(0x80, mmc3_MapperWrite80Hook);
|
||||
set_page_writeable(0x80, true);
|
||||
|
||||
set_page_wr_hook(0xA0, mmc3_MapperWriteA0Hook);
|
||||
set_page_writeable(0xA0, true);
|
||||
|
||||
set_page_wr_hook(0xC0, mmc3_MapperWriteC0Hook);
|
||||
set_page_writeable(0xC0, true);
|
||||
|
||||
set_page_wr_hook(0xE0, mmc3_MapperWriteE0Hook);
|
||||
set_page_writeable(0xE0, true);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void mmc3_MapperWrite80Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
|
||||
if ((Cart->VROMSize > 0) && ( mmc3_use_xor != (Value & 0x80) ))
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
set_vrom_bank_1k(0x0000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x0400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x0800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x0C00, mmc3_last_vrom[5]);
|
||||
set_vrom_bank_2k(0x1000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x1800, mmc3_last_vrom[1]>>1);
|
||||
//chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1
|
||||
}
|
||||
else
|
||||
{
|
||||
set_vrom_bank_2k(0x0000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x0800, mmc3_last_vrom[1]>>1);
|
||||
set_vrom_bank_1k(0x1000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x1400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x1800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x1C00, mmc3_last_vrom[5]);
|
||||
//chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7
|
||||
}
|
||||
mmc3_use_xor = (Value & 0x80);
|
||||
}
|
||||
|
||||
|
||||
if (mmc3_last_prom_switch != (Value & 0x40))
|
||||
{
|
||||
if (!(Value & 0x40))
|
||||
{
|
||||
printf("MMC3: Switch -> 8/A\n");
|
||||
mmc3_first_prom_page = 0x8000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
|
||||
set_prom_bank_8k(0xC000, GETLAST08KBANK(Cart)-1);
|
||||
//set_prom_bank_8k(0xE000, GETLAST08KBANK(cart));
|
||||
//prg_bank(prg0,prg1,max_prg-1,max_prg);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("MMC3: Switch -> C/A\n");
|
||||
mmc3_first_prom_page = 0xC000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
|
||||
set_prom_bank_8k(0x8000, GETLAST08KBANK(Cart)-1);
|
||||
|
||||
|
||||
//prg_bank(max_prg-1,prg1,prg0,max_prg);
|
||||
}
|
||||
mmc3_last_prom_switch = (Value & 0x40);
|
||||
}
|
||||
mmc3_command = Value & 0x07;
|
||||
|
||||
|
||||
|
||||
} else { /* 8001 */
|
||||
switch (mmc3_command)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
if (Cart->VROMSize == 0)
|
||||
return;
|
||||
|
||||
mmc3_last_vrom[mmc3_command] = Value;
|
||||
|
||||
if (mmc3_use_xor)
|
||||
{
|
||||
set_vrom_bank_1k(0x0000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x0400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x0800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x0C00, mmc3_last_vrom[5]);
|
||||
set_vrom_bank_2k(0x1000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x1800, mmc3_last_vrom[1]>>1);
|
||||
//chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1
|
||||
}
|
||||
else
|
||||
{
|
||||
set_vrom_bank_2k(0x0000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x0800, mmc3_last_vrom[1]>>1);
|
||||
set_vrom_bank_1k(0x1000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x1400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x1800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x1C00, mmc3_last_vrom[5]);
|
||||
//chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
mmc3_last_prom[0] = Value;
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
mmc3_last_prom[1] = Value;
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/*if(mmc3_use_xor)
|
||||
chr_bank(chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1);
|
||||
else
|
||||
chr_bank(chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7);*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteA0Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
//printf("MMC3: Select mirroring (0xA000) : 0x%X\n",Value);
|
||||
|
||||
if (Value & 0x1)
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
else
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("MMC3: SaveRAM Toggle (0xA001) : 0x%X\n",Value);
|
||||
if (Value)
|
||||
map_sram();
|
||||
else
|
||||
unmap_sram();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern unsigned short ScanLine;
|
||||
|
||||
void mmc3_MapperWriteC0Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
mmc3_irq_counter_reload = Value;
|
||||
mmc3_irq_counter = Value;
|
||||
//printf("MMC3 IRQ[%d]: SetIRQ reload to %d\n", ScanLine, Value);
|
||||
|
||||
}else{ /* C001 */
|
||||
//printf("MMC3: New tmp IRQ value (0xC001) : 0x%X\n",Value);
|
||||
//printf("MMC3 IRQ[%d]: Reset IRQ counter to val %d [Value = %d]\n", ScanLine, mmc3_irq_counter_reload, Value);
|
||||
mmc3_irq_counter = Value;
|
||||
}
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteE0Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
//printf("MMC3: Writing to 0xE001 : 0x%X\n",Value);
|
||||
//printf("MMC3 IRQ[%d]: IRQ disabled\n", ScanLine);
|
||||
mmc3_irq_enable = 0;
|
||||
//MapperWantIRQ = 1;
|
||||
// Add a way to raise an IRQ
|
||||
|
||||
}else{ /* E001 */
|
||||
//printf("MMC3: Writing to 0xE001 : 0x%X\n",Value);
|
||||
//printf("MMC3: IRQ Enabled (value : %d)\n",mmc3_irq_counter);
|
||||
//printf("MMC3 IRQ[%d]: Enable IRQ\nr", ScanLine);
|
||||
mmc3_irq_enable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int mmc3_MapperIRQ(int cycledone)
|
||||
{
|
||||
if (((cycledone > 0) && (cycledone < 241)) /*&&
|
||||
(ppu.ControlRegister2.b & (PPU_CR2_BGVISIBILITY | PPU_CR2_SPRTVISIBILITY)) == (PPU_CR2_BGVISIBILITY | PPU_CR2_SPRTVISIBILITY)*/)
|
||||
{
|
||||
|
||||
if ((mmc3_irq_counter --) > 0 )return 0;
|
||||
|
||||
|
||||
/* Load next counter position */
|
||||
mmc3_irq_counter = mmc3_irq_counter_reload;
|
||||
|
||||
if (mmc3_irq_enable == 0) return 0;
|
||||
|
||||
mmc3_irq_enable = 0;
|
||||
|
||||
//printf("MMC3 IRQ[%d]: Tick next at %d\n", ScanLine, mmc3_irq_counter_reload);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* MMC4 Mapper - The TI-NESulator Project
|
||||
* mmc4.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-31 18:00:41 +0200 (jeu, 31 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc4.h $
|
||||
* $Revision: 56 $
|
||||
*
|
||||
*/
|
||||
|
||||
byte mmc4_RegA;
|
||||
byte mmc4_RegB;
|
||||
byte mmc4_RegC;
|
||||
byte mmc4_RegD;
|
||||
byte mmc4_RegE;
|
||||
byte mmc4_RegF;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG
|
||||
//printf
|
||||
#else
|
||||
#define LOG
|
||||
#endif
|
||||
|
||||
|
||||
void mmc4_MapperWriteRegA(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegA = Value;
|
||||
|
||||
set_prom_bank_16k(0x8000, Value & 0x0F);
|
||||
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegB(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegB = Value;
|
||||
|
||||
set_vrom_bank_4k(0x0000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegC(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegC = Value;
|
||||
set_vrom_bank_4k(0x0000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegD(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegD = Value;
|
||||
set_vrom_bank_4k(0x1000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegE(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegE = Value;
|
||||
set_vrom_bank_4k(0x1000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegF(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegF = Value;
|
||||
if (Value & 0x01)
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
else
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
}
|
||||
|
||||
|
||||
void mmc4_MapperDump(FILE *fp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int mmc4_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000,0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
if (cart->VROMSize > 0)
set_vrom_bank_8k(0x0000,0);
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0xA0; i < 0xB0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegA);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xB0; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegB);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0; i < 0xD0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegC);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xD0; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegD);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0; i < 0xF0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegE);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xF0; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegF);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
for (i = 0x60; i < 0x80 ; i++)
|
||||
{
|
||||
set_page_writeable(i, true);
|
||||
set_page_readable(i, true);
|
||||
}
|
||||
|
||||
//ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
//ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* UNROM Mapper - The TI-NESulator Project
|
||||
* unrom.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/unrom.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char unrom_load_vbank;
|
||||
|
||||
void unrom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
|
||||
int unrom_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0xC000, 0);
|
||||
set_prom_bank_16k(0x8000, GETLAST16KBANK(cart)); /* Set the last one */
|
||||
|
||||
if (Cart->VROMSize > 0)
|
||||
set_vrom_bank_8k(0x0000,0);
|
||||
|
||||
unrom_load_vbank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80; i < 0x100; i++)
|
||||
{
|
||||
set_page_wr_hook(i, unrom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void unrom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
{
|
||||
set_vrom_bank_8k(0x0000,Value);
|
||||
unrom_load_vbank = Value;
|
||||
}
|
||||
|
||||
void unrom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"unrom: vbank:%d\n",unrom_load_vbank);
|
||||
}
|
||||
50
src/mappersmanager/mappers/unrom.c
Executable file
50
src/mappersmanager/mappers/unrom.c
Executable file
@ -0,0 +1,50 @@
|
||||
/*
|
||||
* UNROM Mapper - The peTI-NESulator Project
|
||||
* unrom.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "unrom.h"
|
||||
|
||||
uint8_t unrom_load_vbank;
|
||||
|
||||
void unrom_MapperWriteHook(uint8_t Addr, uint8_t Value);
|
||||
|
||||
int unrom_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0xC000, 0);
|
||||
set_prom_bank_16k(0x8000, GETLAST16KBANK(cart)); /* Set the last one */
|
||||
|
||||
if (Cart->VROMSize > 0)
|
||||
{
|
||||
set_vrom_bank_8k(0x0000, 0);
|
||||
}
|
||||
|
||||
unrom_load_vbank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, unrom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void unrom_MapperWriteHook(uint8_t Addr, uint8_t Value)
|
||||
{
|
||||
set_vrom_bank_8k(0x0000, Value);
|
||||
unrom_load_vbank = Value;
|
||||
}
|
||||
|
||||
void unrom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "unrom: vbank:%d\n", unrom_load_vbank);
|
||||
}
|
||||
15
src/mappersmanager/mappers/unrom.h
Executable file
15
src/mappersmanager/mappers/unrom.h
Executable file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* UNROM Mapper - The peTI-NESulator Project
|
||||
* unrom.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int unrom_InitMapper(NesCart *cart);
|
||||
void unrom_MapperDump(FILE *fp);
|
||||
72
src/mappersmanager/mappers/unrom512.c
Executable file
72
src/mappersmanager/mappers/unrom512.c
Executable file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* UNROM Mapper - The peTI-NESulator Project
|
||||
* unrom.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ppu/ppu.h>
|
||||
#include "unrom512.h"
|
||||
|
||||
static uint8_t mirroring_set;
|
||||
static uint8_t loaded_vbank;
|
||||
static uint8_t loaded_pbank;
|
||||
|
||||
/*
|
||||
* not great but as we currently don't support higher than 8K VRAM, allocate it here as we can have
|
||||
* 32K on such a cart
|
||||
*/
|
||||
static uint8_t vram[32768];
|
||||
|
||||
void ppu_setPagePtr8k(uint8_t page, uint8_t *ptr);
|
||||
|
||||
static void unrom512_applyValues()
|
||||
{
|
||||
/*if (mirroring_set)
|
||||
{
|
||||
ppu_setMirroring(PPU);
|
||||
}
|
||||
else
|
||||
{
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
}*/
|
||||
|
||||
ppu_setPagePtr8k(0x00, vram + (loaded_vbank * 8 * 1024));
|
||||
set_prom_bank_16k(0x8000, loaded_pbank);
|
||||
}
|
||||
|
||||
static void unrom512_MapperWriteHook(uint8_t Addr, uint8_t Value)
|
||||
{
|
||||
mirroring_set = (Value >> 7) & 0x01;
|
||||
loaded_vbank = (Value >> 5) & 0x03;
|
||||
loaded_pbank = (Value) & 0x1F;
|
||||
|
||||
unrom512_applyValues();
|
||||
}
|
||||
|
||||
int unrom512_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
loaded_vbank = 0;
|
||||
loaded_pbank = 0;
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
unrom512_applyValues();
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, unrom512_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void unrom512_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp, "unrom512: vbank:%d pbank:%d\n", loaded_vbank, loaded_pbank);
|
||||
}
|
||||
15
src/mappersmanager/mappers/unrom512.h
Executable file
15
src/mappersmanager/mappers/unrom512.h
Executable file
@ -0,0 +1,15 @@
|
||||
/*
|
||||
* UNROM Mapper - The peTI-NESulator Project
|
||||
* unrom.h
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define __TINES_MAPPERS__
|
||||
|
||||
#include <mappers/manager.h>
|
||||
|
||||
int unrom512_InitMapper(NesCart *cart);
|
||||
void unrom512_MapperDump(FILE *fp);
|
||||
@ -1,20 +1,42 @@
|
||||
/*
|
||||
* Mapper list - The peTI-NESulator Project
|
||||
* mappers_list.h
|
||||
* TI-NESulator.X
|
||||
*
|
||||
* Created by Manoël Trapier on 25/10/07.
|
||||
* Copyright 2007 986 Corp. All rights reserved.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
/* This file could be generated from the mappers directory... */
|
||||
#include "mappers/norom.h"
|
||||
#include "mappers/aorom.h"
|
||||
#include "mappers/unrom.h"
|
||||
#include "mappers/cnrom.h"
|
||||
|
||||
#include "mappers/unrom512.h"
|
||||
|
||||
#include "mappers/iremh3001.h"
|
||||
|
||||
#include "mappers/mmc1.h"
|
||||
#include "mappers/mmc3.h"
|
||||
#include "mappers/mmc4.h"
|
||||
|
||||
Mapper Mappers[] = {
|
||||
{ 0, "No Mapper", norom_InitMapper, norom_MapperIRQ, norom_MapperDump },
|
||||
{ 1, "MMC1", mmc1_InitMapper, norom_MapperIRQ, mmc1_MapperDump },
|
||||
{ 0 , "No Mapper", norom_InitMapper, norom_MapperIRQ, norom_MapperDump },
|
||||
{ 7 , "AOROM", aorom_InitMapper, norom_MapperIRQ, aorom_MapperDump },
|
||||
{ 2 , "CNROM", cnrom_InitMapper, norom_MapperIRQ, cnrom_MapperDump },
|
||||
{ 3 , "UNROM", unrom_InitMapper, norom_MapperIRQ, unrom_MapperDump },
|
||||
|
||||
{ 1 , "MMC1", mmc1_InitMapper, norom_MapperIRQ, mmc1_MapperDump },
|
||||
{ 4 , "MMC3", mmc3_InitMapper, mmc3_MapperIRQ, mmc3_MapperDump },
|
||||
{ 10, "MMC4", mmc4_InitMapper, norom_MapperIRQ, mmc4_MapperDump },
|
||||
|
||||
{ 30, "UNROM512", unrom512_InitMapper, norom_MapperIRQ, unrom512_MapperDump },
|
||||
|
||||
{ 65, "Irem H3001", iremh3001_InitMapper, iremh3001_MapperIRQ, iremh3001_MapperDump },
|
||||
|
||||
|
||||
{ 100, "Floppy Disk System", NULL, norom_MapperIRQ, norom_MapperDump },
|
||||
/* EOL tag */
|
||||
{ 0, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* AOROM Mapper - The TI-NESulator Project
|
||||
* aorom.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-26 18:47:34 +0200 (jeu, 26 avr 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/aorom.h $
|
||||
* $Revision: 46 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char aorom_load_bank;
|
||||
|
||||
void aorom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
|
||||
extern byte *ppu_mem_nameTables;
|
||||
|
||||
int aorom_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_32k(0x8000,0);
|
||||
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
|
||||
aorom_load_bank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80; i < 0x100; i++)
|
||||
{
|
||||
set_page_wr_hook(i, aorom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void aorom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
{
|
||||
int BankNb;
|
||||
|
||||
if (Value & (1 << 4))
|
||||
ppu_setSingleScreen(PPU_SCREEN_000);
|
||||
else
|
||||
ppu_setSingleScreen(PPU_SCREEN_400);
|
||||
|
||||
BankNb = Value & 0x0F;
|
||||
|
||||
aorom_load_bank = BankNb;
|
||||
|
||||
//printf("aorom: Asking bank %d (giving %d & %d) - mirror is %d\n",BankNb,BankNb,(Value<<1)+1,Value&0x0F);
|
||||
set_prom_bank_32k(0x8000,BankNb);
|
||||
}
|
||||
|
||||
void aorom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"aorom: bank:%d\n",aorom_load_bank);
|
||||
}
|
||||
@ -1,47 +0,0 @@
|
||||
/*
|
||||
* CNROM Mapper - The TI-NESulator Project
|
||||
* cnrom.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/cnrom.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char cnrom_load_bank;
|
||||
|
||||
void cnrom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
|
||||
int cnrom_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart)); /* Set the last one */
|
||||
cnrom_load_bank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80; i < 0x100; i++)
|
||||
{
|
||||
set_page_wr_hook(i, cnrom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void cnrom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
{
|
||||
set_prom_bank_16k(0x8000,Value);
|
||||
cnrom_load_bank = Value;
|
||||
}
|
||||
|
||||
void cnrom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"cnrom: bank:%d\n",cnrom_load_bank);
|
||||
}
|
||||
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* Generic mapper implementation - The TI-NESulator Project
|
||||
* Generic mapper implementation - The peTI-NESulator Project
|
||||
* genericmapper.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/genericmapper.h $
|
||||
* $Revision: 39 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -22,12 +17,12 @@ int _InitMapper(NesCart * cart)
|
||||
|
||||
}
|
||||
|
||||
int _MapperWriteHook(register word Addr, register byte Value)
|
||||
int _MapperWriteHook(register word Addr, register uint8_t Value)
|
||||
{
|
||||
|
||||
if (Addr > 0x7FFF) /* Try to write to the rom */
|
||||
{
|
||||
set_vrom_bank_8k(0x0000,Value)
|
||||
set_vrom_bank_8k(0x0000,Value);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -1,125 +0,0 @@
|
||||
/*
|
||||
* IREMH3001 Mapper - The TI-NESulator Project
|
||||
* iremh3001.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/iremh3001.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned short iremh3001_prom_slot[3];
|
||||
|
||||
unsigned short iremh3001_vrom_slot[8];
|
||||
|
||||
int iremh3001_InitMapper(NesCart * cart)
|
||||
{
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
iremh3001_prom_slot[0] = 0;
|
||||
iremh3001_prom_slot[1] = 1;
|
||||
iremh3001_prom_slot[2] = GETLAST16KBANK(cart);
|
||||
|
||||
set_vrom_bank_8k(0x0000,4);
|
||||
|
||||
iremh3001_vrom_slot[0] = 0;
|
||||
iremh3001_vrom_slot[1] = 0;
|
||||
iremh3001_vrom_slot[2] = 0;
|
||||
iremh3001_vrom_slot[3] = 0;
|
||||
iremh3001_vrom_slot[4] = 0;
|
||||
iremh3001_vrom_slot[5] = 0;
|
||||
iremh3001_vrom_slot[6] = 0;
|
||||
iremh3001_vrom_slot[7] = 0;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int iremh3001_MapperWriteHook(register word Addr, register byte Value)
|
||||
{
|
||||
|
||||
switch(Addr)
|
||||
{
|
||||
case 0x8000: /* Set 8k PROM @ 8000 */
|
||||
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0x8000, Value);
|
||||
iremh3001_prom_slot[0] = Value;
|
||||
break;
|
||||
|
||||
case 0x9003: /* Mirroring ??? */
|
||||
printf("iremh3001: Mirroring[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0x9005: /* IRQ ??? */
|
||||
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0x9006: /* IRQ ??? */
|
||||
printf("iremh3001: IRQ[0x%X:%d] ?\n", Value, Value);
|
||||
break;
|
||||
|
||||
case 0xA000: /* Set 8k PROM @ A000 */
|
||||
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0xA000, Value);
|
||||
iremh3001_prom_slot[1] = Value;
|
||||
break;
|
||||
|
||||
case 0xB000: /* Set 1k VROM @ 0000 */
|
||||
case 0xB001: /* Set 1k VROM @ 0400 */
|
||||
case 0xB002: /* Set 1k VROM @ 0800 */
|
||||
case 0xB003: /* Set 1k VROM @ 0C00 */
|
||||
case 0xB004: /* Set 1k VROM @ 1000 */
|
||||
case 0xB005: /* Set 1k VROM @ 1400 */
|
||||
case 0xB006: /* Set 1k VROM @ 1800 */
|
||||
case 0xB007: /* Set 1k VROM @ 1C00 */
|
||||
printf("iremh3001: %X: change VROM to %d[%X]\n", (Addr&0x0F)<<10, Value, Value);
|
||||
set_vrom_bank_1k((Addr&0xF)<<10, Value);
|
||||
iremh3001_vrom_slot[Addr&0x0F] = Value;
|
||||
break;
|
||||
|
||||
case 0xC000: /* Set 8k PROM @ C000 */
|
||||
printf("iremh3001: %X: change PROM to %d[%X]\n", Addr, Value, Value);
|
||||
set_prom_bank_8k(0xC000, Value);
|
||||
iremh3001_prom_slot[2] = Value;
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("@:%X -- V:%X", Addr, Value);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void iremh3001_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"iremh3001: prom: $8000:%d $A000:%d $C000:%d\n",
|
||||
iremh3001_prom_slot[0],
|
||||
iremh3001_prom_slot[1],
|
||||
iremh3001_prom_slot[2]);
|
||||
|
||||
fprintf(fp,"iremh3001: vrom: $0000:%d $0400:%d $0800:%d $0C00:%d\n" \
|
||||
" $1000:%d $1400:%d $1800:%d $1C00:%d\n",
|
||||
iremh3001_vrom_slot[0],
|
||||
iremh3001_vrom_slot[1],
|
||||
iremh3001_vrom_slot[2],
|
||||
iremh3001_vrom_slot[3],
|
||||
iremh3001_vrom_slot[4],
|
||||
iremh3001_vrom_slot[5],
|
||||
iremh3001_vrom_slot[6],
|
||||
iremh3001_prom_slot[7]);
|
||||
}
|
||||
|
||||
|
||||
int iremh3001_MapperIRQ(int cycledone)
|
||||
{
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1,25 +1,16 @@
|
||||
/*
|
||||
* MMC1 Mapper - The TI-NESulator Project
|
||||
* MMC1 Mapper - The peTI-NESulator Project
|
||||
* mmc1.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc1.h $
|
||||
* $Revision: 50 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
unsigned char MMC1_reg0;
|
||||
|
||||
unsigned char MMC1_reg1;
|
||||
|
||||
unsigned char MMC1_reg2;
|
||||
|
||||
unsigned char MMC1_reg3;
|
||||
|
||||
unsigned char mmc1_CurrentBank;
|
||||
uint8_t MMC1_reg0;
|
||||
uint8_t MMC1_reg1;
|
||||
uint8_t MMC1_reg2;
|
||||
uint8_t MMC1_reg3;
|
||||
uint8_t mmc1_CurrentBank;
|
||||
|
||||
#define MMC1_R0_MIRROR 0x01
|
||||
#define MMC1_R0_ONESCREEN 0x02
|
||||
@ -47,300 +38,310 @@ unsigned char mmc1_CurrentBank;
|
||||
#define MMC1_REG3_DEFAULT 0
|
||||
|
||||
|
||||
void mmc1_MapperWriteReg0(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg1(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg2(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg3(register byte Addr, register byte Value);
|
||||
void mmc1_MapperWriteReg0(register uint8_t Addr, register uint8_t Value);
|
||||
void mmc1_MapperWriteReg1(register uint8_t Addr, register uint8_t Value);
|
||||
void mmc1_MapperWriteReg2(register uint8_t Addr, register uint8_t Value);
|
||||
void mmc1_MapperWriteReg3(register uint8_t Addr, register uint8_t Value);
|
||||
|
||||
void mmc1_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"MMC1: r0:0x%02X r1:0x%02X r2:0x%02X r3:0x%02X\n",MMC1_reg0,MMC1_reg1,MMC1_reg2,MMC1_reg3);
|
||||
fprintf(fp, "MMC1: r0:0x%02X r1:0x%02X r2:0x%02X r3:0x%02X\n", MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
|
||||
}
|
||||
|
||||
int mmc1_InitMapper(NesCart * cart)
|
||||
int mmc1_InitMapper(NesCart *cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
MMC1_reg0 = MMC1_REG0_DEFAULT;
|
||||
|
||||
MMC1_reg1 = MMC1_REG1_DEFAULT;
|
||||
|
||||
MMC1_reg2 = MMC1_REG2_DEFAULT;
|
||||
|
||||
MMC1_reg3 = MMC1_REG3_DEFAULT;
|
||||
|
||||
set_prom_bank_16k(0x8000,0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
mmc1_CurrentBank = 0;
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
set_vrom_bank_4k(0x0000,0);
|
||||
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0x80; i < 0xA0 ; i++)
|
||||
MMC1_reg0 = MMC1_REG0_DEFAULT;
|
||||
MMC1_reg1 = MMC1_REG1_DEFAULT;
|
||||
MMC1_reg2 = MMC1_REG2_DEFAULT;
|
||||
MMC1_reg3 = MMC1_REG3_DEFAULT;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
mmc1_CurrentBank = 0;
|
||||
|
||||
if (cart->VROMSize > 0)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg0);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xA0; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg1);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg2);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg3);
|
||||
set_page_writeable(i, true);
|
||||
set_vrom_bank_4k(0x0000, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0x80 ; i < 0xA0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg0);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xA0 ; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg1);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0 ; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg2);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0 ; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc1_MapperWriteReg3);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Reg 0
|
||||
8 : 1000
|
||||
9 : 1001
|
||||
|
||||
Reg 1
|
||||
A : 1010
|
||||
B : 1011
|
||||
|
||||
Reg 2
|
||||
C : 1100
|
||||
D : 1101
|
||||
|
||||
Reg 3
|
||||
E : 1110
|
||||
F : 1111
|
||||
|
||||
((Addr & 0x6000) >> 13) <- port number
|
||||
*/
|
||||
* Reg 0
|
||||
* 8 : 1000
|
||||
* 9 : 1001
|
||||
*
|
||||
* Reg 1
|
||||
* A : 1010
|
||||
* B : 1011
|
||||
*
|
||||
* Reg 2
|
||||
* C : 1100
|
||||
* D : 1101
|
||||
*
|
||||
* Reg 3
|
||||
* E : 1110
|
||||
* F : 1111
|
||||
*
|
||||
* ((Addr & 0x6000) >> 13) <- port number
|
||||
*/
|
||||
#define MMC1_GetReg(a) ((a & 0x6000) >> 13)
|
||||
/* (Val & 0x01) recuperation du bit */
|
||||
#define MMC1_GetBit(v) (v & 0x01)
|
||||
/* ( ( b & (1 << Bit)) | (v << Bit) ) Ajout du bit */
|
||||
#define MMC1_AddBit(b,v) ( ( b & ~(1 << Bit)) | (v << Bit) )
|
||||
#define MMC1_AddBit(b, v) ( ( b & ~(1 << Bit)) | (v << Bit) )
|
||||
|
||||
void mmc1_ApplyReg0Mod()
|
||||
void mmc1_ApplyReg0Mod()
|
||||
{
|
||||
|
||||
static unsigned char OldSwitchArea = MMC1_R0_PRGAREA;
|
||||
|
||||
|
||||
|
||||
//printf("Change to reg0 done ! (0x%x)\n\tMiror flag : %d\n\tOneScreen Flag : %d\n\tPRG Size : %d\n\tPRG Area : %d\n\tVROM Switch size : %d\n", MMC1_reg0, MMC1_reg0 & MMC1_R0_MIRROR, MMC1_reg0 & MMC1_R0_ONESCREEN, MMC1_reg0 & MMC1_R0_PRGAREA, MMC1_reg0 & MMC1_R0_PRGSIZE, MMC1_reg0 & MMC1_R0_VROMSW);
|
||||
|
||||
switch (MMC1_reg0 & 0x03)
|
||||
{
|
||||
case 0:
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
ppu_setSingleScreen(PPU_SCREEN_000);
|
||||
break;
|
||||
case 1:
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
ppu_setSingleScreen(PPU_SCREEN_400);
|
||||
break;
|
||||
case 2:
|
||||
ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
break;
|
||||
case 3:
|
||||
ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
break;
|
||||
}
|
||||
|
||||
if ( (OldSwitchArea != (MMC1_reg0 & MMC1_R0_PRGAREA)) && ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0 ) )
|
||||
{
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
|
||||
{ /* 0x8000 area */
|
||||
set_prom_bank_16k(0x8000,mmc1_CurrentBank);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(Cart));
|
||||
}
|
||||
else
|
||||
{ /* 0xC000 area */
|
||||
|
||||
set_prom_bank_16k(0x8000,0);
|
||||
set_prom_bank_16k(0xC000,mmc1_CurrentBank);
|
||||
|
||||
}
|
||||
|
||||
OldSwitchArea = (MMC1_reg0 & MMC1_R0_PRGAREA);
|
||||
static uint8_t OldSwitchArea = MMC1_R0_PRGAREA;
|
||||
|
||||
//console_printf(Console_Default, "Change to reg0 done ! (0x%x)\n\tMirror flag : %d\n\tOneScreen Flag : %d\n\tPRG Size : %d\n\tPRG Area : %d\n\tVROM Switch size : %d\n", MMC1_reg0, MMC1_reg0 & MMC1_R0_MIRROR, MMC1_reg0 & MMC1_R0_ONESCREEN, MMC1_reg0 & MMC1_R0_PRGAREA, MMC1_reg0 & MMC1_R0_PRGSIZE, MMC1_reg0 & MMC1_R0_VROMSW);
|
||||
|
||||
switch (MMC1_reg0 & 0x03)
|
||||
{
|
||||
case 0:
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
ppu_setSingleScreen(PPU_SCREEN_000);
|
||||
break;
|
||||
case 1:
|
||||
ppu_setScreenMode(PPU_SCMODE_SINGLE);
|
||||
ppu_setSingleScreen(PPU_SCREEN_400);
|
||||
break;
|
||||
case 2:
|
||||
ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
break;
|
||||
case 3:
|
||||
ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((OldSwitchArea != (MMC1_reg0 & MMC1_R0_PRGAREA)) && ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0))
|
||||
{
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
|
||||
{
|
||||
/* 0x8000 area */
|
||||
set_prom_bank_16k(0x8000, mmc1_CurrentBank);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(Cart));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 0xC000 area */
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, mmc1_CurrentBank);
|
||||
}
|
||||
|
||||
OldSwitchArea = (MMC1_reg0 & MMC1_R0_PRGAREA);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int VROMBankNb;
|
||||
unsigned char Bit = 0;
|
||||
unsigned char BitBuf = 0;
|
||||
uint8_t Bit = 0;
|
||||
uint8_t BitBuf = 0;
|
||||
|
||||
void mmc1_MapperWriteReg0(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg0(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg0 = MMC1_REG0_DEFAULT;
|
||||
printf("MMC1: Reg0 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg0 Reset occurred !\n");
|
||||
mmc1_ApplyReg0Mod();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Bit < 4)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
{
|
||||
/* Haven't written the 5 bits yet */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
|
||||
MMC1_reg0 = BitBuf;
|
||||
|
||||
|
||||
mmc1_ApplyReg0Mod();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg1(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg1(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg1 = MMC1_REG1_DEFAULT;
|
||||
printf("MMC1: Reg1 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg1 Reset occurred !\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Bit < 4)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
{
|
||||
/* Haven't written the 5 bits yet */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
|
||||
MMC1_reg1 = BitBuf;
|
||||
|
||||
|
||||
VROMBankNb = (MMC1_reg1 /* & MMC1_R1_VROMB1 */ );
|
||||
|
||||
if (Cart->VROMSize == 0)
|
||||
{
|
||||
printf("Try to change VROM but with didn't have any VROM ! [%04X]\n", VROMBankNb);
|
||||
return;
|
||||
if (Cart->VROMSize == 0)
|
||||
{
|
||||
console_printf(Console_Default, "Try to change VROM but with didn't have any VROM ! [%04X]\n",
|
||||
VROMBankNb);
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (MMC1_reg0 & MMC1_R0_VROMSW) != 0 )
|
||||
{ /* 4K vram */
|
||||
//printf("Switching VROM at 0x0000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x0000,VROMBankNb);
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_VROMSW) != 0)
|
||||
{
|
||||
/* 4K vram */
|
||||
//console_printf(Console_Default, "Switching VROM at 0x0000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x0000, VROMBankNb);
|
||||
}
|
||||
else
|
||||
{ /* 8K vram */
|
||||
//printf("Switching VROM at 0x0000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
set_vrom_bank_8k(0x0000,VROMBankNb>>1);
|
||||
{
|
||||
/* 8K vram */
|
||||
//console_printf(Console_Default, "Switching VROM at 0x0000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
set_vrom_bank_8k(0x0000, VROMBankNb >> 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg2(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg2(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg2 = MMC1_REG2_DEFAULT;
|
||||
printf("MMC1: Reg2 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg2 Reset occurred !\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Bit < 4)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
{
|
||||
/* Haven't written the 5 bits yet */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
MMC1_reg2 = BitBuf;
|
||||
|
||||
|
||||
VROMBankNb = (MMC1_reg2 /* & MMC1_R2_VROMB2 */ );
|
||||
|
||||
//printf("Want to switch VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
|
||||
//console_printf(Console_Default, "Want to switch VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
if (Cart->VROMSize == 0)
|
||||
{
|
||||
//printf(": No\n");
|
||||
//console_printf(Console_Default, ": No\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if ( (MMC1_reg0 & MMC1_R0_VROMSW) != 0 )
|
||||
{ /* 4K vram */
|
||||
//printf("Switching VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x1000,VROMBankNb);
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_VROMSW) != 0)
|
||||
{
|
||||
/* 4K vram */
|
||||
//console_printf(Console_Default, "Switching VROM at 0x1000 to 4k bank %d\n", VROMBankNb);
|
||||
set_vrom_bank_4k(0x1000, VROMBankNb);
|
||||
}
|
||||
else
|
||||
{ /* 8K vram */
|
||||
// printf("Switching VROM at 0x1000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
// set_vrom_bank_8k(0x1000,VROMBankNb>>1);
|
||||
{
|
||||
/* 8K vram */
|
||||
// console_printf(Console_Default, "Switching VROM at 0x1000 to 8k bank %d\n", VROMBankNb>>1);
|
||||
// set_vrom_bank_8k(0x1000,VROMBankNb>>1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mmc1_MapperWriteReg3(register byte Addr, register byte Value)
|
||||
void mmc1_MapperWriteReg3(register uint8_t Addr, register uint8_t Value)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
MMC1_reg3 = MMC1_REG3_DEFAULT;
|
||||
printf("MMC1: Reg3 Reset occured !\n");
|
||||
console_printf(Console_Default, "MMC1: Reg3 Reset occurred !\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Bit < 4)
|
||||
{ /* Pas encore ecrit les 5 bits */
|
||||
{
|
||||
/* Haven't written the 5 bits yet */
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BitBuf = MMC1_AddBit(BitBuf, MMC1_GetBit(Value));
|
||||
Bit = 0;
|
||||
|
||||
|
||||
MMC1_reg3 = BitBuf;
|
||||
|
||||
if (MMC1_reg3<<14 > Cart->PROMSize)
|
||||
|
||||
if (MMC1_reg3 << 14 > Cart->PROMSize)
|
||||
{
|
||||
return;
|
||||
|
||||
if ( (MMC1_reg0 & MMC1_R0_PRGSIZE) != 0 )
|
||||
{ /* 16K Switch */
|
||||
if ( (MMC1_reg0 & MMC1_R0_PRGAREA) != 0 )
|
||||
{ /* 0x8000 switch */
|
||||
set_prom_bank_16k(0x8000,MMC1_reg3);
|
||||
//printf("LowBank is now %d ( 0x%p )\n", MMC1_reg3, mLBank);
|
||||
}
|
||||
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGSIZE) != 0)
|
||||
{
|
||||
/* 16K Switch */
|
||||
if ((MMC1_reg0 & MMC1_R0_PRGAREA) != 0)
|
||||
{
|
||||
/* 0x8000 switch */
|
||||
set_prom_bank_16k(0x8000, MMC1_reg3);
|
||||
//console_printf(Console_Default, "LowBank is now %d ( 0x%p )\n", MMC1_reg3, mLBank);
|
||||
}
|
||||
else
|
||||
{ /* 0xC000 switch */
|
||||
set_prom_bank_16k(0xC000,MMC1_reg3);
|
||||
//printf("HighBank is now %d ( 0x%p )\n", MMC1_reg3, mUBank);
|
||||
{
|
||||
/* 0xC000 switch */
|
||||
set_prom_bank_16k(0xC000, MMC1_reg3);
|
||||
//console_printf(Console_Default, "HighBank is now %d ( 0x%p )\n", MMC1_reg3, mUBank);
|
||||
}
|
||||
}
|
||||
else
|
||||
{ /* 32K Switch */
|
||||
set_prom_bank_32k(0x8000,MMC1_reg3>>1);
|
||||
{
|
||||
/* 32K Switch */
|
||||
set_prom_bank_32k(0x8000, MMC1_reg3 >> 1);
|
||||
}
|
||||
|
||||
if ( ( MMC1_reg3 & MMC1_R3_SAVECE ) != 0)
|
||||
|
||||
if ((MMC1_reg3 & MMC1_R3_SAVECE) != 0)
|
||||
{
|
||||
unmap_sram();
|
||||
}
|
||||
@ -350,6 +351,6 @@ void mmc1_MapperWriteReg3(register byte Addr, register byte Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//printf("MMC1: Debug (Reg:%d,Val:0x%02X,reg0:0x%02X,reg1:0x%02X,reg2:0x%02X,reg3:0x%02X)\n", MMC1_GetReg(Addr), Value, MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
|
||||
}
|
||||
|
||||
//console_printf(Console_Default, "MMC1: Debug (Reg:%d,Val:0x%02X,reg0:0x%02X,reg1:0x%02X,reg2:0x%02X,reg3:0x%02X)\n", MMC1_GetReg(Addr), Value, MMC1_reg0, MMC1_reg1, MMC1_reg2, MMC1_reg3);
|
||||
|
||||
@ -1,317 +0,0 @@
|
||||
/*
|
||||
* MMC3 Mapper - The TI-NESulator Project
|
||||
* mmc3.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc3.h $
|
||||
* $Revision: 50 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned short mmc3_command;
|
||||
|
||||
unsigned char mmc3_irq_counter;
|
||||
unsigned char mmc3_irq_counter_reload;
|
||||
unsigned char mmc3_irq_enable;
|
||||
|
||||
unsigned short mmc3_first_prom_page;
|
||||
unsigned short mmc3_second_prom_page;
|
||||
|
||||
unsigned char mmc3_use_xor;
|
||||
unsigned char mmc3_last_vrom[6];
|
||||
|
||||
unsigned char mmc3_last_prom[2];
|
||||
unsigned char mmc3_last_prom_switch;
|
||||
|
||||
unsigned short dummy;
|
||||
|
||||
void mmc3_MapperWrite80Hook(byte addr, byte value);
|
||||
void mmc3_MapperWriteA0Hook(byte addr, byte value);
|
||||
void mmc3_MapperWriteC0Hook(byte addr, byte value);
|
||||
void mmc3_MapperWriteE0Hook(byte addr, byte value);
|
||||
|
||||
void mmc3_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"MMC3: CMD:%d IC:%d IR:%d IE:%d FPP:0x%04X SPP:0x%04X UX:%d\n",mmc3_command,mmc3_irq_counter,mmc3_irq_counter_reload,mmc3_irq_enable,mmc3_first_prom_page,mmc3_second_prom_page,mmc3_use_xor);
|
||||
fprintf(fp,"MMC3: LV0:%d LV1:%d LV2:%d LV3:%d LV4:%d LV5:%d\n",mmc3_last_vrom[0],mmc3_last_vrom[1],mmc3_last_vrom[2],mmc3_last_vrom[3],mmc3_last_vrom[4],mmc3_last_vrom[5]);
|
||||
fprintf(fp,"MMC3: LP0:%d LP1:%d LPS:%d\n",mmc3_last_prom[0],mmc3_last_prom[1],mmc3_last_prom_switch);
|
||||
}
|
||||
|
||||
int mmc3_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000, 0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
if ( Cart->VROMSize > 0)
|
||||
{
|
||||
set_vrom_bank_8k(0, 0x0000);
|
||||
}
|
||||
|
||||
mmc3_command = -1;
|
||||
|
||||
mmc3_irq_counter = -1;
|
||||
mmc3_irq_enable = 1;
|
||||
mmc3_irq_counter_reload = 0;
|
||||
|
||||
mmc3_use_xor = 0x42;
|
||||
|
||||
mmc3_last_prom_switch = 0x42;
|
||||
|
||||
mmc3_last_prom[0] = 0;
|
||||
mmc3_last_prom[1] = 1;
|
||||
|
||||
mmc3_last_vrom[0] = 0;
|
||||
mmc3_last_vrom[1] = 2;
|
||||
mmc3_last_vrom[2] = 3;
|
||||
mmc3_last_vrom[3] = 4;
|
||||
mmc3_last_vrom[4] = 5;
|
||||
mmc3_last_vrom[5] = 6;
|
||||
|
||||
mmc3_first_prom_page = 0x8000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
//mmc3_first_prom_page = 0; // Set it to 0x8000
|
||||
|
||||
|
||||
/* Register mapper write hook */
|
||||
set_page_wr_hook(0x80, mmc3_MapperWrite80Hook);
|
||||
set_page_writeable(0x80, true);
|
||||
|
||||
set_page_wr_hook(0xA0, mmc3_MapperWriteA0Hook);
|
||||
set_page_writeable(0xA0, true);
|
||||
|
||||
set_page_wr_hook(0xC0, mmc3_MapperWriteC0Hook);
|
||||
set_page_writeable(0xC0, true);
|
||||
|
||||
set_page_wr_hook(0xE0, mmc3_MapperWriteE0Hook);
|
||||
set_page_writeable(0xE0, true);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void mmc3_MapperWrite80Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
|
||||
if ((Cart->VROMSize > 0) && ( mmc3_use_xor != (Value & 0x80) ))
|
||||
{
|
||||
if (Value & 0x80)
|
||||
{
|
||||
set_vrom_bank_1k(0x0000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x0400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x0800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x0C00, mmc3_last_vrom[5]);
|
||||
set_vrom_bank_2k(0x1000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x1800, mmc3_last_vrom[1]>>1);
|
||||
//chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1
|
||||
}
|
||||
else
|
||||
{
|
||||
set_vrom_bank_2k(0x0000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x0800, mmc3_last_vrom[1]>>1);
|
||||
set_vrom_bank_1k(0x1000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x1400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x1800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x1C00, mmc3_last_vrom[5]);
|
||||
//chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7
|
||||
}
|
||||
mmc3_use_xor = (Value & 0x80);
|
||||
}
|
||||
|
||||
|
||||
if (mmc3_last_prom_switch != (Value & 0x40))
|
||||
{
|
||||
if (!(Value & 0x40))
|
||||
{
|
||||
printf("MMC3: Switch -> 8/A\n");
|
||||
mmc3_first_prom_page = 0x8000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
|
||||
set_prom_bank_8k(0xC000, GETLAST08KBANK(Cart)-1);
|
||||
//set_prom_bank_8k(0xE000, GETLAST08KBANK(cart));
|
||||
//prg_bank(prg0,prg1,max_prg-1,max_prg);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("MMC3: Switch -> C/A\n");
|
||||
mmc3_first_prom_page = 0xC000;
|
||||
mmc3_second_prom_page = 0xA000;
|
||||
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
|
||||
set_prom_bank_8k(0x8000, GETLAST08KBANK(Cart)-1);
|
||||
|
||||
|
||||
//prg_bank(max_prg-1,prg1,prg0,max_prg);
|
||||
}
|
||||
mmc3_last_prom_switch = (Value & 0x40);
|
||||
}
|
||||
mmc3_command = Value & 0x07;
|
||||
|
||||
|
||||
|
||||
} else { /* 8001 */
|
||||
switch (mmc3_command)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
case 4:
|
||||
case 5:
|
||||
if (Cart->VROMSize == 0)
|
||||
return;
|
||||
|
||||
mmc3_last_vrom[mmc3_command] = Value;
|
||||
|
||||
if (mmc3_use_xor)
|
||||
{
|
||||
set_vrom_bank_1k(0x0000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x0400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x0800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x0C00, mmc3_last_vrom[5]);
|
||||
set_vrom_bank_2k(0x1000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x1800, mmc3_last_vrom[1]>>1);
|
||||
//chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1
|
||||
}
|
||||
else
|
||||
{
|
||||
set_vrom_bank_2k(0x0000, mmc3_last_vrom[0]>>1);
|
||||
set_vrom_bank_2k(0x0800, mmc3_last_vrom[1]>>1);
|
||||
set_vrom_bank_1k(0x1000, mmc3_last_vrom[2]);
|
||||
set_vrom_bank_1k(0x1400, mmc3_last_vrom[3]);
|
||||
set_vrom_bank_1k(0x1800, mmc3_last_vrom[4]);
|
||||
set_vrom_bank_1k(0x1C00, mmc3_last_vrom[5]);
|
||||
//chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 6:
|
||||
mmc3_last_prom[0] = Value;
|
||||
set_prom_bank_8k(mmc3_first_prom_page, mmc3_last_prom[0]);
|
||||
break;
|
||||
|
||||
case 7:
|
||||
mmc3_last_prom[1] = Value;
|
||||
set_prom_bank_8k(mmc3_second_prom_page, mmc3_last_prom[1]);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
/*if(mmc3_use_xor)
|
||||
chr_bank(chr4,chr5,chr6,chr7,chr01,chr01+1,chr23,chr23+1);
|
||||
else
|
||||
chr_bank(chr01,chr01+1,chr23,chr23+1,chr4,chr5,chr6,chr7);*/
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteA0Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
//printf("MMC3: Select mirroring (0xA000) : 0x%X\n",Value);
|
||||
|
||||
if (Value & 0x1)
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
else
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
//printf("MMC3: SaveRAM Toggle (0xA001) : 0x%X\n",Value);
|
||||
if (Value)
|
||||
map_sram();
|
||||
else
|
||||
unmap_sram();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern unsigned short ScanLine;
|
||||
|
||||
void mmc3_MapperWriteC0Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
mmc3_irq_counter_reload = Value;
|
||||
mmc3_irq_counter = Value;
|
||||
//printf("MMC3 IRQ[%d]: SetIRQ reload to %d\n", ScanLine, Value);
|
||||
|
||||
}else{ /* C001 */
|
||||
//printf("MMC3: New tmp IRQ value (0xC001) : 0x%X\n",Value);
|
||||
//printf("MMC3 IRQ[%d]: Reset IRQ counter to val %d [Value = %d]\n", ScanLine, mmc3_irq_counter_reload, Value);
|
||||
mmc3_irq_counter = Value;
|
||||
}
|
||||
}
|
||||
|
||||
void mmc3_MapperWriteE0Hook(byte addr, byte Value)
|
||||
{
|
||||
//printf("%s(0x%02X, 0x%02X)\n", __func__, addr, Value);
|
||||
if (addr > 0x01)
|
||||
return;
|
||||
|
||||
if (!addr)
|
||||
{
|
||||
//printf("MMC3: Writing to 0xE001 : 0x%X\n",Value);
|
||||
//printf("MMC3 IRQ[%d]: IRQ disabled\n", ScanLine);
|
||||
mmc3_irq_enable = 0;
|
||||
//MapperWantIRQ = 1;
|
||||
// Add a way to raise an IRQ
|
||||
|
||||
}else{ /* E001 */
|
||||
//printf("MMC3: Writing to 0xE001 : 0x%X\n",Value);
|
||||
//printf("MMC3: IRQ Enabled (value : %d)\n",mmc3_irq_counter);
|
||||
//printf("MMC3 IRQ[%d]: Enable IRQ\nr", ScanLine);
|
||||
mmc3_irq_enable = 1;
|
||||
}
|
||||
}
|
||||
|
||||
int mmc3_MapperIRQ(int cycledone)
|
||||
{
|
||||
if (((cycledone > 0) && (cycledone < 241)) /*&&
|
||||
(ppu.ControlRegister2.b & (PPU_CR2_BGVISIBILITY | PPU_CR2_SPRTVISIBILITY)) == (PPU_CR2_BGVISIBILITY | PPU_CR2_SPRTVISIBILITY)*/)
|
||||
{
|
||||
|
||||
if ((mmc3_irq_counter --) > 0 )return 0;
|
||||
|
||||
|
||||
/* Load next counter position */
|
||||
mmc3_irq_counter = mmc3_irq_counter_reload;
|
||||
|
||||
if (mmc3_irq_enable == 0) return 0;
|
||||
|
||||
mmc3_irq_enable = 0;
|
||||
|
||||
//printf("MMC3 IRQ[%d]: Tick next at %d\n", ScanLine, mmc3_irq_counter_reload);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1,137 +0,0 @@
|
||||
/*
|
||||
* MMC4 Mapper - The TI-NESulator Project
|
||||
* mmc4.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-31 18:00:41 +0200 (jeu, 31 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mmc4.h $
|
||||
* $Revision: 56 $
|
||||
*
|
||||
*/
|
||||
|
||||
byte mmc4_RegA;
|
||||
byte mmc4_RegB;
|
||||
byte mmc4_RegC;
|
||||
byte mmc4_RegD;
|
||||
byte mmc4_RegE;
|
||||
byte mmc4_RegF;
|
||||
|
||||
#ifdef DEBUG
|
||||
#define LOG
|
||||
//printf
|
||||
#else
|
||||
#define LOG
|
||||
#endif
|
||||
|
||||
|
||||
void mmc4_MapperWriteRegA(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegA = Value;
|
||||
|
||||
set_prom_bank_16k(0x8000, Value & 0x0F);
|
||||
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegB(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegB = Value;
|
||||
|
||||
set_vrom_bank_4k(0x0000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegC(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegC = Value;
|
||||
set_vrom_bank_4k(0x0000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegD(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegD = Value;
|
||||
set_vrom_bank_4k(0x1000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegE(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegE = Value;
|
||||
set_vrom_bank_4k(0x1000, Value & 0x1F);
|
||||
}
|
||||
|
||||
void mmc4_MapperWriteRegF(register byte Addr, register byte Value)
|
||||
{
|
||||
LOG("%s(%02X, %02X)\n", __func__, Addr, Value);
|
||||
mmc4_RegF = Value;
|
||||
if (Value & 0x01)
|
||||
ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
else
|
||||
ppu_setMirroring(PPU_MIRROR_VERTICAL);
|
||||
}
|
||||
|
||||
|
||||
void mmc4_MapperDump(FILE *fp)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int mmc4_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0x8000,0);
|
||||
set_prom_bank_16k(0xC000, GETLAST16KBANK(cart));
|
||||
|
||||
if (cart->VROMSize > 0)
set_vrom_bank_8k(0x0000,0);
|
||||
|
||||
/* Mapper should register itself for write hook */
|
||||
for (i = 0xA0; i < 0xB0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegA);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xB0; i < 0xC0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegB);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xC0; i < 0xD0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegC);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xD0; i < 0xE0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegD);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xE0; i < 0xF0 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegE);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
for (i = 0xF0; i < 0x100 ; i++)
|
||||
{
|
||||
set_page_wr_hook(i, mmc4_MapperWriteRegF);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
for (i = 0x60; i < 0x80 ; i++)
|
||||
{
|
||||
set_page_writeable(i, true);
|
||||
set_page_readable(i, true);
|
||||
}
|
||||
|
||||
//ppu_setScreenMode(PPU_SCMODE_NORMAL);
|
||||
//ppu_setMirroring(PPU_MIRROR_HORIZTAL);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@ -1,51 +0,0 @@
|
||||
/*
|
||||
* UNROM Mapper - The TI-NESulator Project
|
||||
* unrom.h
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-04-16 01:55:35 +0200 (lun, 16 avr 2007) $
|
||||
* $Author: godzil $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/unrom.h $
|
||||
* $Revision: 39 $
|
||||
*
|
||||
*/
|
||||
|
||||
unsigned char unrom_load_vbank;
|
||||
|
||||
void unrom_MapperWriteHook(register byte Addr, register byte Value);
|
||||
|
||||
int unrom_InitMapper(NesCart * cart)
|
||||
{
|
||||
int i;
|
||||
|
||||
set_prom_bank_16k(0xC000, 0);
|
||||
set_prom_bank_16k(0x8000, GETLAST16KBANK(cart)); /* Set the last one */
|
||||
|
||||
if (Cart->VROMSize > 0)
|
||||
set_vrom_bank_8k(0x0000,0);
|
||||
|
||||
unrom_load_vbank = 0;
|
||||
|
||||
/* Register the write hook */
|
||||
for (i = 0x80; i < 0x100; i++)
|
||||
{
|
||||
set_page_wr_hook(i, unrom_MapperWriteHook);
|
||||
set_page_writeable(i, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void unrom_MapperWriteHook(register byte Addr, register byte Value)
|
||||
{
|
||||
set_vrom_bank_8k(0x0000,Value);
|
||||
unrom_load_vbank = Value;
|
||||
}
|
||||
|
||||
void unrom_MapperDump(FILE *fp)
|
||||
{
|
||||
fprintf(fp,"unrom: vbank:%d\n",unrom_load_vbank);
|
||||
}
|
||||
@ -1,14 +1,9 @@
|
||||
/*
|
||||
* Mapper facilities - The TI-NESulator Project
|
||||
* Mapper facilities - The peTI-NESulator Project
|
||||
* mappers.c
|
||||
*
|
||||
* Created by Manoel TRAPIER.
|
||||
* Copyright (c) 2003-2007 986Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-31 18:00:41 +0200 (jeu, 31 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/mappers.c $
|
||||
* $Revision: 56 $
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -23,77 +18,75 @@
|
||||
#include <mappers/manager.h>
|
||||
#include <memory/manager.h>
|
||||
|
||||
#define __TINES_PPU_INTERNAL__
|
||||
#include <ppu/ppu.memory.h>
|
||||
#undef __TINES_PPU_INTERNAL__
|
||||
|
||||
extern NesCart *Cart;
|
||||
|
||||
extern char MapperWantIRQ;
|
||||
|
||||
/*
|
||||
Here are some fonction useful for mappers
|
||||
* Here are some function useful for mappers
|
||||
*/
|
||||
|
||||
void set_vrom_bank_1k(unsigned short addr,int slot)
|
||||
void set_vrom_bank_1k(uint16_t addr,int slot)
|
||||
{
|
||||
#ifdef DEBUG_VROM_BANK_SWITCH
|
||||
printf("Change vrom 1k bank 0x%X to slot %d\n",addr,slot);
|
||||
console_printf(Console_Default, "Change vrom 1k bank 0x%X to slot %d\n",addr,slot);
|
||||
#endif
|
||||
ppu_setPagePtr1k((addr>>8)&0xFF, Cart->VROMBanks + (slot * 1024));
|
||||
// memcpy(ppu.Memory+addr, Cart->VROMBanks + (slot * 1024), 0x0400);
|
||||
}
|
||||
|
||||
void set_vrom_bank_2k(unsigned short addr,int slot)
|
||||
void set_vrom_bank_2k(uint16_t addr,int slot)
|
||||
{
|
||||
#ifdef DEBUG_VROM_BANK_SWITCH
|
||||
printf("Change vrom 2k bank 0x%X to slot %d\n",addr,slot);
|
||||
console_printf(Console_Default, "Change vrom 2k bank 0x%X to slot %d\n",addr,slot);
|
||||
#endif
|
||||
ppu_setPagePtr2k((addr>>8)&0xFF, Cart->VROMBanks + (slot * 2 * 1024));
|
||||
// memcpy(ppu.Memory+addr, Cart->VROMBanks + (slot * 2 * 1024), 0x0800);
|
||||
}
|
||||
|
||||
void set_vrom_bank_4k(unsigned short addr,int slot)
|
||||
void set_vrom_bank_4k(uint16_t addr,int slot)
|
||||
{
|
||||
#ifdef DEBUG_VROM_BANK_SWITCH
|
||||
printf("Change vrom 4k bank 0x%X to slot %d\n",addr,slot);
|
||||
console_printf(Console_Default, "Change vrom 4k bank 0x%X to slot %d\n",addr,slot);
|
||||
#endif
|
||||
ppu_setPagePtr4k((addr>>8)&0xFF, Cart->VROMBanks + (slot * 4 * 1024));
|
||||
// memcpy(ppu.Memory+addr, Cart->VROMBanks + (slot * 4 * 1024), 0x1000);
|
||||
}
|
||||
|
||||
void set_vrom_bank_8k(unsigned short addr, int slot)
|
||||
void set_vrom_bank_8k(uint16_t addr, int slot)
|
||||
{
|
||||
#ifdef DEBUG_VROM_BANK_SWITCH
|
||||
printf("Change vrom 8k bank 0x%X to slot %d\n",addr,slot);
|
||||
console_printf(Console_Default, "Change vrom 8k bank 0x%X to slot %d\n",addr,slot);
|
||||
#endif
|
||||
ppu_setPagePtr8k(0x00, Cart->VROMBanks + (slot * 8 * 1024));
|
||||
// memcpy(ppu.Memory, Cart->VROMBanks + (slot * 8 * 1024) , 0x2000);
|
||||
}
|
||||
|
||||
/*-----------*/
|
||||
|
||||
void set_prom_bank_8k(unsigned short addr,int slot)
|
||||
void set_prom_bank_8k(uint16_t addr,int slot)
|
||||
{
|
||||
#ifdef DEBUG_PROM_BANK_SWITCH
|
||||
printf("Change prom 8k bank 0x%X to slot %d\n",addr,slot);
|
||||
console_printf(Console_Default, "Change prom 8k bank 0x%X to slot %d\n",addr,slot);
|
||||
#endif
|
||||
set_page_ptr_8k(addr >> 8, Cart->PROMBanks + (slot * 8 * 1024));
|
||||
}
|
||||
|
||||
void set_prom_bank_16k(unsigned short addr,int slot)
|
||||
void set_prom_bank_16k(uint16_t addr,int slot)
|
||||
{
|
||||
#ifdef DEBUG_PROM_BANK_SWITCH
|
||||
printf("Change prom 16k bank @ 0x%X [0x%X] to slot 0x%X\n",addr, addr>>8,slot);
|
||||
console_printf(Console_Default, "Change prom 16k bank @ 0x%X [0x%X] to slot 0x%X\n",addr, addr>>8,slot);
|
||||
#endif
|
||||
set_page_ptr_16k(addr >> 8, Cart->PROMBanks + (slot * 16 * 1024));
|
||||
}
|
||||
|
||||
void set_prom_bank_32k(unsigned short addr,int slot)
|
||||
void set_prom_bank_32k(uint16_t addr,int slot)
|
||||
{ /* addr may not be different from 0x8000 !*/
|
||||
/* Anyway I don't use it */
|
||||
#ifdef DEBUG_PROM_BANK_SWITCH
|
||||
printf("Change prom 32k bank 0x%X to slot %d\n",addr,slot);
|
||||
console_printf(Console_Default, "Change prom 32k bank 0x%X to slot %d\n",addr,slot);
|
||||
#endif
|
||||
set_page_ptr_32k(addr >> 8, Cart->PROMBanks + (slot * 32 * 1024));
|
||||
/* set_page_ptr_16k(0x80, Cart->PROMBanks[(slot<<1)]);
|
||||
set_page_ptr_16k(0xC0, Cart->PROMBanks[(slot<<1)+1]);*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
11
src/memorymanager/CMakeLists.txt
Normal file
11
src/memorymanager/CMakeLists.txt
Normal file
@ -0,0 +1,11 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
if (COVERALLS)
|
||||
set(COVERAGE_SRCS src/memorymanager/memory.c ${COVERAGE_SRCS} PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
add_library(memorymanager memory.c)
|
||||
@ -1,39 +1,36 @@
|
||||
/*
|
||||
* 6502 Memory manager - The TI-NESulator Project
|
||||
* 6502 Memory manager - The peTI-NESulator Project
|
||||
* memory.c - Taken from the Quick6502 project
|
||||
*
|
||||
* Created by Manoël Trapier on 18/09/06.
|
||||
* Copyright 2003-2007 986 Corp. All rights reserved.
|
||||
*
|
||||
* $LastChangedDate: 2007-05-02 18:37:41 +0200 (mer, 02 mai 2007) $
|
||||
* $Author: mtrapier $
|
||||
* $HeadURL: file:///media/HD6G/SVNROOT/trunk/TI-NESulator/src/memory.c $
|
||||
* $Revision: 50 $
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include "types.h"
|
||||
#include "../include/memory/manager.h"
|
||||
#include <types.h>
|
||||
|
||||
#include <os_dependent.h>
|
||||
|
||||
#include <memory/manager.h>
|
||||
|
||||
/* Private structures */
|
||||
|
||||
#define KBYTE * (1024)
|
||||
#define KByte * (1024)
|
||||
|
||||
/*
|
||||
* What inside memory manager:
|
||||
*
|
||||
* Table of attributes
|
||||
* Table of original page ptr
|
||||
* Table of moded page ptr
|
||||
* Table of modded page ptr
|
||||
*
|
||||
*/
|
||||
|
||||
/* Private data */
|
||||
|
||||
byte *memory_pages[0x100];
|
||||
byte memory_pages_attr[0x100];
|
||||
uint8_t *memory_pages[0x100];
|
||||
uint8_t memory_pages_attr[0x100];
|
||||
|
||||
func_rdhook rdh_table[0x100];
|
||||
func_wrhook wrh_table[0x100];
|
||||
@ -48,26 +45,26 @@ func_wrhook wrh_table[0x100];
|
||||
#endif
|
||||
|
||||
/* Public functions */
|
||||
void set_page_ptr(byte page, byte *ptr)
|
||||
void set_page_ptr(uint8_t page, uint8_t *ptr)
|
||||
{
|
||||
LOG(printf("Set page 0x%X to ptr %p\n", page, ptr));
|
||||
LOG(console_printf(Console_Default, "Set page 0x%X to ptr %p\n", page, ptr));
|
||||
memory_pages[page] = ptr;
|
||||
}
|
||||
|
||||
void set_page_ptr_1k(byte page, byte *ptr)
|
||||
void set_page_ptr_1k(uint8_t page, uint8_t *ptr)
|
||||
{ /* 1k = 4 * 256 */
|
||||
LOG(printf("Set page(1k) 0x%X to ptr %p\n", page, ptr));
|
||||
LOG(console_printf(Console_Default, "Set page(1k) 0x%X to ptr %p\n", page, ptr));
|
||||
memory_pages[page + 0] = ptr;
|
||||
memory_pages[page + 1] = ptr + 0x100;
|
||||
memory_pages[page + 1] = ptr + 0x100;
|
||||
memory_pages[page + 2] = ptr + (0x100 * 2);
|
||||
memory_pages[page + 3] = ptr + (0x100 * 3);
|
||||
}
|
||||
|
||||
void set_page_ptr_2k(byte page, byte *ptr)
|
||||
void set_page_ptr_2k(uint8_t page, uint8_t *ptr)
|
||||
{
|
||||
LOG(printf("Set page(2k) 0x%X to ptr %p\n", page, ptr));
|
||||
LOG(console_printf(Console_Default, "Set page(2k) 0x%X to ptr %p\n", page, ptr));
|
||||
memory_pages[page + 0] = ptr;
|
||||
memory_pages[page + 1] = ptr + 0x100;
|
||||
memory_pages[page + 1] = ptr + 0x100;
|
||||
memory_pages[page + 2] = ptr + (0x100 * 2);
|
||||
memory_pages[page + 3] = ptr + (0x100 * 3);
|
||||
memory_pages[page + 4] = ptr + (0x100 * 4);
|
||||
@ -76,33 +73,33 @@ void set_page_ptr_2k(byte page, byte *ptr)
|
||||
memory_pages[page + 7] = ptr + (0x100 * 7);
|
||||
}
|
||||
|
||||
void set_page_ptr_4k(byte page, byte *ptr)
|
||||
void set_page_ptr_4k(uint8_t page, uint8_t *ptr)
|
||||
{
|
||||
LOG(printf("Set page(4k) 0x%X to ptr %p\n", page, ptr));
|
||||
LOG(console_printf(Console_Default, "Set page(4k) 0x%X to ptr %p\n", page, ptr));
|
||||
set_page_ptr_2k(page, ptr);
|
||||
set_page_ptr_2k(page+((4 KBYTE / 256) / 2), ptr + 2 KBYTE);
|
||||
set_page_ptr_2k(page + ((4 KByte / 256) / 2), ptr + 2 KByte);
|
||||
}
|
||||
|
||||
void set_page_ptr_8k(byte page, byte *ptr)
|
||||
void set_page_ptr_8k(uint8_t page, uint8_t *ptr)
|
||||
{
|
||||
LOG(printf("Set page(8k) 0x%X to ptr %p\n", page, ptr));
|
||||
LOG(console_printf(Console_Default, "Set page(8k) 0x%X to ptr %p\n", page, ptr));
|
||||
set_page_ptr_4k(page, ptr);
|
||||
set_page_ptr_4k(page+((8 KBYTE / 256) / 2), ptr + 4 KBYTE);
|
||||
set_page_ptr_4k(page + ((8 KByte / 256) / 2), ptr + 4 KByte);
|
||||
}
|
||||
|
||||
void set_page_ptr_16k(byte page, byte *ptr)
|
||||
void set_page_ptr_16k(uint8_t page, uint8_t *ptr)
|
||||
{
|
||||
set_page_ptr_8k(page, ptr);
|
||||
set_page_ptr_8k(page+((16 KBYTE / 256) / 2), ptr + 8 KBYTE);
|
||||
set_page_ptr_8k(page + ((16 KByte / 256) / 2), ptr + 8 KByte);
|
||||
}
|
||||
|
||||
void set_page_ptr_32k(byte page, byte *ptr)
|
||||
void set_page_ptr_32k(uint8_t page, uint8_t *ptr)
|
||||
{
|
||||
set_page_ptr_16k(page, ptr);
|
||||
set_page_ptr_16k(page+((32 KBYTE / 256) / 2), ptr + 16 KBYTE);
|
||||
set_page_ptr_16k(page + ((32 KByte / 256) / 2), ptr + 16 KByte);
|
||||
}
|
||||
|
||||
byte *get_page_ptr(byte page)
|
||||
uint8_t *get_page_ptr(uint8_t page)
|
||||
{
|
||||
return memory_pages[page];
|
||||
}
|
||||
@ -110,60 +107,76 @@ byte *get_page_ptr(byte page)
|
||||
|
||||
/* Functions to set pages attributes */
|
||||
|
||||
void set_page_rd_hook(byte page, func_rdhook func)
|
||||
void set_page_rd_hook(uint8_t page, func_rdhook func)
|
||||
{
|
||||
if (func == NULL)
|
||||
{
|
||||
memory_pages_attr[page] &= (~ATTR_PAGE_HAVE_RDHOOK);
|
||||
if (memory_pages[page] == (byte *)0x01)
|
||||
if (memory_pages[page] == (uint8_t *)0x01)
|
||||
{
|
||||
memory_pages[page] = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_pages_attr[page] |= ATTR_PAGE_HAVE_RDHOOK;
|
||||
if (memory_pages[page] == NULL)
|
||||
memory_pages[page] = (byte *)0x01;
|
||||
{
|
||||
memory_pages[page] = (uint8_t *)0x01;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
rdh_table[page] = func;
|
||||
}
|
||||
|
||||
void set_page_wr_hook(byte page, func_wrhook func)
|
||||
void set_page_wr_hook(uint8_t page, func_wrhook func)
|
||||
{
|
||||
if (func == NULL)
|
||||
{
|
||||
memory_pages_attr[page] &= (~ATTR_PAGE_HAVE_WRHOOK);
|
||||
if (memory_pages[page] == (byte*)0x01)
|
||||
if (memory_pages[page] == (uint8_t *)0x01)
|
||||
{
|
||||
memory_pages[page] = NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
memory_pages_attr[page] |= ATTR_PAGE_HAVE_WRHOOK;
|
||||
if (memory_pages[page] == NULL)
|
||||
memory_pages[page] = (byte *)0x01;
|
||||
{
|
||||
memory_pages[page] = (uint8_t *)0x01;
|
||||
}
|
||||
}
|
||||
|
||||
wrh_table[page] = func;
|
||||
|
||||
wrh_table[page] = func;
|
||||
}
|
||||
|
||||
void set_page_readable(byte page, bool value)
|
||||
void set_page_readable(uint8_t page, uint8_t value)
|
||||
{
|
||||
if (value == true)
|
||||
{
|
||||
memory_pages_attr[page] |= ATTR_PAGE_READABLE;
|
||||
}
|
||||
else
|
||||
memory_pages_attr[page] &= (~ATTR_PAGE_READABLE);
|
||||
{
|
||||
memory_pages_attr[page] &= (~ATTR_PAGE_READABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void set_page_writeable(byte page, bool value)
|
||||
void set_page_writeable(uint8_t page, uint8_t value)
|
||||
{
|
||||
if (value == true)
|
||||
{
|
||||
memory_pages_attr[page] |= ATTR_PAGE_WRITEABLE;
|
||||
}
|
||||
else
|
||||
memory_pages_attr[page] &= (~ATTR_PAGE_WRITEABLE);
|
||||
{
|
||||
memory_pages_attr[page] &= (~ATTR_PAGE_WRITEABLE);
|
||||
}
|
||||
}
|
||||
|
||||
void set_page_ghost(byte page, bool value, byte ghost)
|
||||
void set_page_ghost(uint8_t page, uint8_t value, uint8_t ghost)
|
||||
{
|
||||
if (value == true)
|
||||
{
|
||||
@ -174,102 +187,112 @@ void set_page_ghost(byte page, bool value, byte ghost)
|
||||
}
|
||||
}
|
||||
|
||||
byte get_page_attributes(byte page)
|
||||
uint8_t get_page_attributes(uint8_t page)
|
||||
{
|
||||
return memory_pages_attr[page];
|
||||
}
|
||||
|
||||
func_rdhook get_page_rdhook(byte page)
|
||||
func_rdhook get_page_rdhook(uint8_t page)
|
||||
{
|
||||
if (memory_pages_attr[page] & ATTR_PAGE_HAVE_RDHOOK)
|
||||
{
|
||||
return rdh_table[page];
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
func_wrhook get_page_wrhook(byte page)
|
||||
func_wrhook get_page_wrhook(uint8_t page)
|
||||
{
|
||||
if (memory_pages_attr[page] & ATTR_PAGE_HAVE_WRHOOK)
|
||||
{
|
||||
return wrh_table[page];
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
byte ReadMemory(byte page, byte addr)
|
||||
uint8_t ReadMemory(uint8_t page, uint8_t addr)
|
||||
{
|
||||
static byte LastRetByte = 0xA5;
|
||||
byte *page_ptr;
|
||||
byte attributes;
|
||||
LOG(printf("Read @ 0x%X-%X\n", page, addr));
|
||||
static uint8_t LastRetByte = 0xA5;
|
||||
uint8_t *page_ptr;
|
||||
uint8_t attributes;
|
||||
LOG(console_printf(Console_Default, "Read @ 0x%X-%X\n", page, addr));
|
||||
/* Est-ce que la page est mappé ? && Est-ce que la page est "readable" ? */
|
||||
if ((page_ptr = memory_pages[page]) &&
|
||||
( (attributes = memory_pages_attr[page]) & ATTR_PAGE_READABLE) )
|
||||
((attributes = memory_pages_attr[page]) & ATTR_PAGE_READABLE))
|
||||
{
|
||||
LOG(printf("Page is non null & readable\n"));
|
||||
if ( attributes & ATTR_PAGE_HAVE_RDHOOK )
|
||||
return ( LastRetByte = rdh_table[page](addr) );
|
||||
LOG(console_printf(Console_Default, "Page is non null & readable\n"));
|
||||
if (attributes & ATTR_PAGE_HAVE_RDHOOK)
|
||||
{
|
||||
return (LastRetByte = rdh_table[page](addr));
|
||||
}
|
||||
else
|
||||
return ( LastRetByte = page_ptr[addr] );
|
||||
{
|
||||
return (LastRetByte = page_ptr[addr]);
|
||||
}
|
||||
}
|
||||
//printf("Trying to read @ 0x%X-%X\n", page, addr);
|
||||
//console_printf(Console_Default, "Trying to read @ 0x%X-%X\n", page, addr);
|
||||
return LastRetByte;
|
||||
}
|
||||
|
||||
void WriteMemory(byte page, byte addr, byte value)
|
||||
void WriteMemory(uint8_t page, uint8_t addr, uint8_t value)
|
||||
{
|
||||
byte *page_ptr;
|
||||
byte attributes;
|
||||
LOG(printf("Write 0x%x @ 0x%X-%X\n", value, page, addr));
|
||||
uint8_t *page_ptr;
|
||||
uint8_t attributes;
|
||||
LOG(console_printf(Console_Default, "Write 0x%x @ 0x%X-%X\n", value, page, addr));
|
||||
/* Est-ce que la page est mappé ? && Est-ce que la page est "writable" ? */
|
||||
if ( (page_ptr = memory_pages[page]) &&
|
||||
( (attributes = memory_pages_attr[page]) & ATTR_PAGE_WRITEABLE) )
|
||||
if ((page_ptr = memory_pages[page]) &&
|
||||
((attributes = memory_pages_attr[page]) & ATTR_PAGE_WRITEABLE))
|
||||
{
|
||||
if ( attributes & ATTR_PAGE_HAVE_WRHOOK )
|
||||
if (attributes & ATTR_PAGE_HAVE_WRHOOK)
|
||||
{
|
||||
#ifdef DETECT_BUS_CONFLICT
|
||||
if ((page >= 0x80) && (memory_pages[page][addr] != value))
|
||||
printf("WriteHook: bus conflict at %02X%02X rom:%02X write:%02X\n", page, addr, memory_pages[page][addr], value);
|
||||
console_printf(Console_Default, "WriteHook: bus conflict at %02X%02X rom:%02X write:%02X\n", page, addr, memory_pages[page][addr], value);
|
||||
#endif
|
||||
wrh_table[page](addr, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
page_ptr[addr] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
console_printf(Console_Default, "Trying to write 0x%X @ 0x%X-%X\n", value, page, addr);
|
||||
}
|
||||
else { printf("Trying to write 0x%X @ 0x%X-%X\n", value, page, addr); }
|
||||
}
|
||||
|
||||
void DumpMemoryState(FILE *fp)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0x00; i < 0x100; i++)
|
||||
|
||||
for (i = 0x00 ; i < 0x100 ; i++)
|
||||
{
|
||||
fprintf(fp,
|
||||
"Page 0x%02X : [%c%c%c%c%c%c] RdH:%p WrH:%p ptr:%p\n",
|
||||
i,
|
||||
(memory_pages_attr[i]&ATTR_PAGE_HAVE_RDHOOK)?'r':'.',
|
||||
(memory_pages_attr[i]&ATTR_PAGE_HAVE_WRHOOK)?'w':'.',
|
||||
(memory_pages_attr[i]&ATTR_PAGE_READABLE)?'R':'.',
|
||||
(memory_pages_attr[i]&ATTR_PAGE_WRITEABLE)?'W':'.',
|
||||
(memory_pages_attr[i]&ATTR_PAGE_GHOST)?'G':'.',
|
||||
(memory_pages_attr[i]&ATTR_PAGE_MAPPED)?'M':'.',
|
||||
(memory_pages_attr[i] & ATTR_PAGE_HAVE_RDHOOK) ? 'r' : '.',
|
||||
(memory_pages_attr[i] & ATTR_PAGE_HAVE_WRHOOK) ? 'w' : '.',
|
||||
(memory_pages_attr[i] & ATTR_PAGE_READABLE) ? 'R' : '.',
|
||||
(memory_pages_attr[i] & ATTR_PAGE_WRITEABLE) ? 'W' : '.',
|
||||
(memory_pages_attr[i] & ATTR_PAGE_GHOST) ? 'G' : '.',
|
||||
(memory_pages_attr[i] & ATTR_PAGE_MAPPED) ? 'M' : '.',
|
||||
rdh_table[i],
|
||||
wrh_table[i],
|
||||
memory_pages[i]
|
||||
);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void InitMemory()
|
||||
{
|
||||
int page;
|
||||
|
||||
for(page = 0 ; page < 0x100 ; page++)
|
||||
|
||||
for (page = 0 ; page < 0x100 ; page++)
|
||||
{
|
||||
set_page_ptr(page,NULL);
|
||||
set_page_ptr(page, NULL);
|
||||
memory_pages_attr[page] = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
7
src/os/macos/CMakeLists.txt
Normal file
7
src/os/macos/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
add_library(oslib loadfile.c graphics.c sound.c io.c)
|
||||
24
src/os/macos/graphics.c
Normal file
24
src/os/macos/graphics.c
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Graphic Manager - The peTI-NESulator Project
|
||||
* os/macos/graphics.c
|
||||
*
|
||||
* Created by Manoël Trapier on 08/05/08.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
#include <os_dependent.h>
|
||||
|
||||
int graphics_init()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int graphics_drawpixel(long x, long y, long color)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
int graphics_blit(long x, long y, long w, long h)
|
||||
{
|
||||
|
||||
}
|
||||
57
src/os/macos/io.c
Normal file
57
src/os/macos/io.c
Normal file
@ -0,0 +1,57 @@
|
||||
/*
|
||||
* IO Manager - The peTI-NESulator Project
|
||||
* os/macos/graphics.c
|
||||
*
|
||||
* Created by Manoël Trapier on 04/01/09.
|
||||
* Copyright (c) 2003-2009 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <os_dependent.h>
|
||||
|
||||
char LevelChar[] = { 'E', 'W', 'A', 'N', 'V', 'D'};
|
||||
|
||||
ConsoleLevel console_ActualLevel = Console_Default;
|
||||
|
||||
/* Actually nothing to do */
|
||||
int console_init(ConsoleLevel DefaultLevel)
|
||||
{
|
||||
console_ActualLevel = DefaultLevel;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Actually a simple printf with levels */
|
||||
int console_vprintf(const ConsoleLevel level, const char *format, va_list ap)
|
||||
{
|
||||
if (console_ActualLevel >= level)
|
||||
vprintf(format, ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int console_printf(const ConsoleLevel level, const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
ret = console_vprintf(level, format, ap);
|
||||
|
||||
va_end(ap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int console_printf_d(const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
va_start(ap, format);
|
||||
|
||||
console_vprintf (Console_Debug, format, ap);
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return 0;
|
||||
}
|
||||
40
src/os/macos/loadfile.c
Normal file
40
src/os/macos/loadfile.c
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* File functions - The peTI-NESulator Project
|
||||
* os/macos/load.c
|
||||
*
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
|
||||
#include <os_dependent.h>
|
||||
|
||||
/* Map a file in memory */
|
||||
void *LoadFilePtr(char * filename)
|
||||
{
|
||||
int fd;
|
||||
void *RetPtr;
|
||||
struct stat FileStat;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
|
||||
fstat(fd, &FileStat);
|
||||
|
||||
RetPtr = mmap(NULL, FileStat.st_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
|
||||
|
||||
close(fd);
|
||||
|
||||
return RetPtr;
|
||||
}
|
||||
0
src/os/macos/sound.c
Normal file
0
src/os/macos/sound.c
Normal file
7
src/os/ti68k/CMakeLists.txt
Normal file
7
src/os/ti68k/CMakeLists.txt
Normal file
@ -0,0 +1,7 @@
|
||||
#
|
||||
# peTI-NESulator CMake
|
||||
#
|
||||
# Created by Manoël Trapier.
|
||||
# Copyright (c) 2002-2019 986-Studio.
|
||||
#
|
||||
add_library(oslib loadfile.c)
|
||||
29
src/os/ti68k/loadfile.c
Normal file
29
src/os/ti68k/loadfile.c
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* TI-68k Loading external file functions - The peTI-NESulator Project
|
||||
* ti68k/loadfile.c
|
||||
*
|
||||
* Created by Manoël Trapier.
|
||||
* Copyright (c) 2002-2019 986-Studio.
|
||||
*
|
||||
*/
|
||||
|
||||
#define TIGCC_COMPAT
|
||||
#include <tigcclib.h>
|
||||
|
||||
/* Map a file in memory */
|
||||
void *LoadFilePtr(char * filename)
|
||||
{
|
||||
void *RetPtr = NULL;
|
||||
FILE *fp;
|
||||
|
||||
if ((fp = fopen(filename,"rb")) == NULL)
|
||||
return -1;
|
||||
|
||||
/* TI Related stuff, very ugly, and need to be changed.. */
|
||||
HeapLock(fp->handle);
|
||||
RetPtr = 2 + HeapDeref(fp->handle);
|
||||
|
||||
fclose (fp);
|
||||
|
||||
return RetPtr;
|
||||
}
|
||||
8
src/os/ti68k/main.c
Normal file
8
src/os/ti68k/main.c
Normal file
@ -0,0 +1,8 @@
|
||||
#include <tigcclib.h>
|
||||
|
||||
int main(int argc, char *argv[]);
|
||||
|
||||
void _main()
|
||||
{
|
||||
main(1, "smb1.nes");
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user