mirror of
https://github.com/libretro/vemulator-libretro.git
synced 2025-02-16 23:09:36 +00:00
Initial commit
This commit is contained in:
commit
9bb36f82ed
674
COPYING
Normal file
674
COPYING
Normal file
@ -0,0 +1,674 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
140
Makefile
Normal file
140
Makefile
Normal file
@ -0,0 +1,140 @@
|
||||
STATIC_LINKING := 0
|
||||
AR := ar
|
||||
CC := g++
|
||||
|
||||
ifeq ($(platform),)
|
||||
platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
platform = win
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
platform = osx
|
||||
else ifneq ($(findstring win,$(shell uname -a)),)
|
||||
platform = win
|
||||
endif
|
||||
endif
|
||||
|
||||
# system platform
|
||||
system_platform = unix
|
||||
ifeq ($(shell uname -a),)
|
||||
EXE_EXT = .exe
|
||||
system_platform = win
|
||||
else ifneq ($(findstring Darwin,$(shell uname -a)),)
|
||||
system_platform = osx
|
||||
arch = intel
|
||||
ifeq ($(shell uname -p),powerpc)
|
||||
arch = ppc
|
||||
endif
|
||||
else ifneq ($(findstring MINGW,$(shell uname -a)),)
|
||||
system_platform = win
|
||||
endif
|
||||
|
||||
TARGET_NAME := vemulator
|
||||
LIBM = -lm
|
||||
|
||||
ifeq ($(ARCHFLAGS),)
|
||||
ifeq ($(archs),ppc)
|
||||
ARCHFLAGS = -arch ppc -arch ppc64
|
||||
else
|
||||
ARCHFLAGS = -arch i386 -arch x86_64
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(platform), osx)
|
||||
ifndef ($(NOUNIVERSAL))
|
||||
CFLAGS += $(ARCHFLAGS)
|
||||
LFLAGS += $(ARCHFLAGS)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(STATIC_LINKING), 1)
|
||||
EXT := a
|
||||
endif
|
||||
|
||||
ifeq ($(platform), unix)
|
||||
EXT ?= so
|
||||
TARGET := $(TARGET_NAME)_libretro.$(EXT)
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined
|
||||
else ifeq ($(platform), linux-portable)
|
||||
TARGET := $(TARGET_NAME)_libretro.$(EXT)
|
||||
fpic := -fPIC -nostdlib
|
||||
SHARED := -shared -Wl,--version-script=link.T
|
||||
LIBM :=
|
||||
else ifneq (,$(findstring osx,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
else ifneq (,$(findstring ios,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro_ios.dylib
|
||||
fpic := -fPIC
|
||||
SHARED := -dynamiclib
|
||||
|
||||
ifeq ($(IOSSDK),)
|
||||
IOSSDK := $(shell xcodebuild -version -sdk iphoneos Path)
|
||||
endif
|
||||
|
||||
DEFINES := -DIOS
|
||||
CC = CC -arch armv7 -isysroot $(IOSSDK)
|
||||
ifeq ($(platform),ios9)
|
||||
CC += -miphoneos-version-min=8.0
|
||||
CFLAGS += -miphoneos-version-min=8.0
|
||||
else
|
||||
CC += -miphoneos-version-min=5.0
|
||||
CFLAGS += -miphoneos-version-min=5.0
|
||||
endif
|
||||
else ifneq (,$(findstring qnx,$(platform)))
|
||||
TARGET := $(TARGET_NAME)_libretro_qnx.so
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined
|
||||
else ifeq ($(platform), emscripten)
|
||||
TARGET := $(TARGET_NAME)_libretro_emscripten.bc
|
||||
fpic := -fPIC
|
||||
SHARED := -shared -Wl,--version-script=link.T -Wl,--no-undefined
|
||||
else ifeq ($(platform), vita)
|
||||
TARGET := $(TARGET_NAME)_vita.a
|
||||
CC = arm-vita-eabi-g++
|
||||
AR = arm-vita-eabi-ar
|
||||
CFLAGS += -Wl,-q -Wall -O3
|
||||
STATIC_LINKING = 1
|
||||
else
|
||||
CC = g++
|
||||
TARGET := $(TARGET_NAME)_libretro.dll
|
||||
SHARED := -shared -static-libgcc -static-libstdc++ -s -Wl,--version-script=link.T -Wl,--no-undefined
|
||||
endif
|
||||
|
||||
LDFLAGS += $(LIBM)
|
||||
|
||||
ifeq ($(DEBUG), 1)
|
||||
CFLAGS += -O0 -g
|
||||
else
|
||||
CFLAGS += -O3
|
||||
endif
|
||||
|
||||
OBJECTS := *.cpp
|
||||
CFLAGS += -Wall -pedantic $(fpic)
|
||||
|
||||
ifneq (,$(findstring qnx,$(platform)))
|
||||
CFLAGS += -Wc,-std=c++99
|
||||
else
|
||||
CFLAGS += -std=gnu++99
|
||||
endif
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
$(TARGET): $(OBJECTS)
|
||||
ifeq ($(STATIC_LINKING), 1)
|
||||
$(AR) rcs $@ $(OBJECTS)
|
||||
else
|
||||
$(CC) $(fpic) $(SHARED) $(INCLUDES) -o $@ $(OBJECTS) $(LDFLAGS)
|
||||
endif
|
||||
|
||||
%.o: %.cpp
|
||||
$(CC) $(CFLAGS) $(fpic) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f *.so *.o
|
||||
|
||||
.PHONY: clean
|
||||
|
115
audio.cpp
Normal file
115
audio.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
VE_VMS_AUDIO::VE_VMS_AUDIO(VE_VMS_CPU *_cpu, VE_VMS_RAM *_ram)
|
||||
{
|
||||
T1LR_reg = 0;
|
||||
T1LC_reg = 128;
|
||||
IsEnabled = false;
|
||||
T1LR_old = -1;
|
||||
|
||||
ram = _ram;
|
||||
cpu = _cpu;
|
||||
|
||||
sampleArray = (int16_t *)calloc(2*SAMPLE_RATE, sizeof(int16_t)); //Multiplied by 2 because 2 channels
|
||||
|
||||
frequency = 146539.3;
|
||||
}
|
||||
|
||||
VE_VMS_AUDIO::~VE_VMS_AUDIO()
|
||||
{
|
||||
free(sampleArray);
|
||||
}
|
||||
|
||||
void VE_VMS_AUDIO::generateSignal(retro_audio_sample_t &audio_cb)
|
||||
{
|
||||
if(!IsEnabled)
|
||||
{
|
||||
audio_cb(0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
double T1LC_reg_D = T1LC_reg;
|
||||
double T1LR_reg_D = T1LR_reg;
|
||||
|
||||
//1 second is equal to 32768 samples
|
||||
|
||||
int16_t waveWidth = (int16_t) ((256 - T1LR_reg_D) * (SAMPLE_RATE / frequency)); //1 Wave (In samples not seconds)
|
||||
|
||||
double lowLevelWidth = abs((((T1LC_reg_D - T1LR_reg_D)/(256 - T1LR_reg_D)) * waveWidth));
|
||||
|
||||
//lowLevelWidth = 0.5 * waveWidth; //Many mini-games don't care about T1LD, 0.5 would play a sound close to the original.
|
||||
|
||||
for(int i = 0; i < SAMPLE_RATE / FPS; i++)
|
||||
{
|
||||
int16_t amplitude = 0x7FFF;
|
||||
if(waveWidth != 0)
|
||||
{
|
||||
if((i%waveWidth) < lowLevelWidth) amplitude = 0;
|
||||
}
|
||||
|
||||
audio_cb(amplitude, amplitude);
|
||||
}
|
||||
}
|
||||
|
||||
void VE_VMS_AUDIO::setAudioFrequency(double f)
|
||||
{
|
||||
frequency = f;
|
||||
}
|
||||
|
||||
void VE_VMS_AUDIO::setT1(int b)
|
||||
{
|
||||
T1LR_reg = b & 0xFF;
|
||||
}
|
||||
|
||||
void VE_VMS_AUDIO::setT1C(int b)
|
||||
{
|
||||
T1LC_reg = b & 0xFF;
|
||||
}
|
||||
|
||||
void VE_VMS_AUDIO::setEnabled(bool e)
|
||||
{
|
||||
IsEnabled = e;
|
||||
}
|
||||
|
||||
void VE_VMS_AUDIO::runAudioCheck()
|
||||
{
|
||||
if(!IsEnabled)
|
||||
{
|
||||
size_t count = SAMPLE_RATE * 2;
|
||||
|
||||
//Empty signal (No sound)
|
||||
for(size_t i = 0; i < count; i++)
|
||||
sampleArray[i] = 0;
|
||||
|
||||
T1LR_old = -1;
|
||||
}
|
||||
else if(T1LR_old != T1LR_reg)
|
||||
//generateSignal();
|
||||
|
||||
T1LR_old = T1LR_reg;
|
||||
|
||||
}
|
||||
|
||||
int16_t *VE_VMS_AUDIO::getSignal()
|
||||
{
|
||||
return sampleArray;
|
||||
}
|
||||
|
63
audio.h
Normal file
63
audio.h
Normal file
@ -0,0 +1,63 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_H_
|
||||
#define _AUDIO_H_
|
||||
|
||||
#include <math.h>
|
||||
#include "libretro.h"
|
||||
#include "common.h"
|
||||
#include "cpu.h"
|
||||
#include "ram.h"
|
||||
|
||||
class VE_VMS_AUDIO
|
||||
{
|
||||
public:
|
||||
VE_VMS_AUDIO(VE_VMS_CPU *_cpu, VE_VMS_RAM *_ram);
|
||||
|
||||
~VE_VMS_AUDIO();
|
||||
|
||||
void generateSignal(retro_audio_sample_t &audio_cb);
|
||||
|
||||
void setAudioFrequency(double f);
|
||||
|
||||
void setT1(int b);
|
||||
|
||||
void setT1C(int b);
|
||||
|
||||
void setEnabled(bool e);
|
||||
|
||||
void runAudioCheck();
|
||||
|
||||
int16_t *getSignal();
|
||||
|
||||
private:
|
||||
int T1LR_reg;
|
||||
int T1LC_reg;
|
||||
bool IsEnabled;
|
||||
int T1LR_old;
|
||||
|
||||
double frequency; //This is supposed to be the CPU's frequency, but we have made the CPU's clock fixed
|
||||
|
||||
int16_t *sampleArray;
|
||||
|
||||
VE_VMS_CPU *cpu;
|
||||
VE_VMS_RAM *ram;
|
||||
};
|
||||
|
||||
#endif // _AUDIO_H_
|
90
basetimer.cpp
Normal file
90
basetimer.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "basetimer.h"
|
||||
|
||||
VE_VMS_BASETIMER::VE_VMS_BASETIMER(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_CPU *_cpu)
|
||||
{
|
||||
ram = _ram;
|
||||
intHandler = _intHandler;
|
||||
cpu = _cpu;
|
||||
BTR = 0;
|
||||
}
|
||||
|
||||
VE_VMS_BASETIMER::~VE_VMS_BASETIMER()
|
||||
{
|
||||
}
|
||||
|
||||
void VE_VMS_BASETIMER::runTimer()
|
||||
{
|
||||
int BTCR_data = ram->readByte_RAW(BTCR);
|
||||
|
||||
bool BTStarted = (BTCR_data & 64) != 0;
|
||||
bool Int0Enabled = (BTCR_data & 1) != 0;
|
||||
bool Int1Enabled = (BTCR_data & 4) != 0;
|
||||
int int1cycle;
|
||||
|
||||
int cycleControl = ((BTCR_data & 16) >> 4) | ((BTCR_data & 32) >> 4);
|
||||
|
||||
switch (cycleControl)
|
||||
{
|
||||
case 0:
|
||||
int1cycle = 32;
|
||||
break;
|
||||
case 1:
|
||||
int1cycle = 128;
|
||||
break;
|
||||
case 2:
|
||||
int1cycle = 512;
|
||||
break;
|
||||
case 3:
|
||||
int1cycle = 2048;
|
||||
break;
|
||||
default:
|
||||
int1cycle = 2048;
|
||||
}
|
||||
|
||||
if(BTStarted)
|
||||
{
|
||||
BTR += 32786.0 / cpu->getCurrentFrequency();
|
||||
|
||||
//Throw interrupt 1 source when cycle chosen is reached
|
||||
if(BTR >= int1cycle)
|
||||
{
|
||||
BTCR_data |= 8;
|
||||
ram->writeByte_RAW(BTCR, BTCR_data);
|
||||
|
||||
if (Int1Enabled)
|
||||
intHandler->setINT3();
|
||||
|
||||
}
|
||||
|
||||
|
||||
if((BTR > 16383) || (BTR > 63 && ((BTCR_data & 128) != 0)))
|
||||
{
|
||||
//Throw full (14-bit) overflow interrupt (Interrupt 0 source)
|
||||
BTCR_data |= 2;
|
||||
ram->writeByte_RAW(BTCR, BTCR_data);
|
||||
|
||||
if(Int0Enabled)
|
||||
intHandler->setINT3();
|
||||
|
||||
if(BTR > 16383) BTR = 0;
|
||||
}
|
||||
}
|
||||
}
|
41
basetimer.h
Normal file
41
basetimer.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _BASETIMER_H_
|
||||
#define _BASETIMER_H_
|
||||
|
||||
#include "ram.h"
|
||||
#include "interrupts.h"
|
||||
#include "cpu.h"
|
||||
|
||||
class VE_VMS_BASETIMER
|
||||
{
|
||||
public:
|
||||
VE_VMS_BASETIMER(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_CPU *_cpu);
|
||||
~VE_VMS_BASETIMER();
|
||||
|
||||
void runTimer();
|
||||
|
||||
private:
|
||||
double BTR; //14-bit
|
||||
VE_VMS_RAM *ram;
|
||||
VE_VMS_INTERRUPTS *intHandler;
|
||||
VE_VMS_CPU *cpu;
|
||||
};
|
||||
|
||||
#endif // _BASETIMER_H_
|
205
bitwisemath.cpp
Normal file
205
bitwisemath.cpp
Normal file
@ -0,0 +1,205 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "bitwisemath.h"
|
||||
|
||||
//Flags [0|0|0|0|0|O|A|C/B]
|
||||
//This is an 8-bit adder. Returns sum as first in array, then flags.
|
||||
void add8(byte i1, byte i2, byte carry, byte *result)
|
||||
{
|
||||
byte op1 = i1 & 0xFF;
|
||||
byte op2 = i2 & 0xFF;
|
||||
|
||||
byte s = 0; //8-bits
|
||||
byte c = carry; //Assume its 1-bit
|
||||
|
||||
byte flags = 0;
|
||||
|
||||
byte c6 = 0;
|
||||
byte c7 = 0;
|
||||
|
||||
//Start operation
|
||||
for(byte i = 0; i < 8; ++i)
|
||||
{
|
||||
//Take next bit
|
||||
byte bit1 = ((op1 & ((1 << i) & 0xFF)) >> i) & 0xFF;
|
||||
byte bit2 = ((op2 & ((1 << i) & 0xFF)) >> i) & 0xFF;
|
||||
|
||||
//Sum them together
|
||||
byte z1 = (bit1 ^ bit2) & 0xFF;
|
||||
s |= ((c ^ z1) << i) & 0xFF;
|
||||
|
||||
//Calculate carry
|
||||
byte c1 = (c & z1) & 0xFF;
|
||||
byte c2 = (bit1 & bit2) & 0xFF;
|
||||
c = (c1 | c2) & 0xFF;
|
||||
|
||||
//Auxiliary flag set
|
||||
if(c != 0 && i == 3)
|
||||
flags |= 0x2;
|
||||
|
||||
if(i == 6) c6 = c & 1;
|
||||
else if(i == 7) c7 = c & 1;
|
||||
}
|
||||
|
||||
c &= 1;
|
||||
|
||||
//Check carry
|
||||
if(c == 1)
|
||||
flags |= 0x1;
|
||||
//Check overflow
|
||||
if(c6 != c7)
|
||||
flags |= 0x4;
|
||||
result[0] = s & 0xFF;
|
||||
result[1] = flags & 0xFF;
|
||||
}
|
||||
|
||||
void sub8(byte i1, byte i2, byte carry, byte *result)
|
||||
{
|
||||
|
||||
byte op1 = i1 & 0xFF;
|
||||
byte op2 = i2 & 0xFF;
|
||||
|
||||
op2 ^= 0xFF; //2's Complement
|
||||
op2 &= 0xFF;
|
||||
|
||||
byte s = 0; //8-bits
|
||||
byte c = carry ^ 0xFF; //Assume its 1-bit
|
||||
c &= 1;
|
||||
|
||||
byte flags = 0;
|
||||
|
||||
byte c6 = 0;
|
||||
byte c7 = 0;
|
||||
|
||||
//Start operation
|
||||
for(byte i = 0; i < 8; ++i)
|
||||
{
|
||||
//Take next bit
|
||||
byte bit1 = ((op1 & ((1 << i) & 0xFF)) >> i) & 0xFF;
|
||||
byte bit2 = ((op2 & ((1 << i) & 0xFF)) >> i) & 0xFF;
|
||||
|
||||
//Sum them together
|
||||
byte z1 = (bit1 ^ bit2) & 0xFF;
|
||||
s |= ((c ^ z1) << i) & 0xFF;
|
||||
|
||||
//Calculate carry
|
||||
byte c1 = (c & z1) & 0xFF;
|
||||
byte c2 = (bit1 & bit2) & 0xFF;
|
||||
c = (c1 | c2) & 0xFF;
|
||||
|
||||
//Auxiliary flag set
|
||||
if(c == 0 && i == 3)
|
||||
flags |= 0x2;
|
||||
|
||||
if(i == 6) c6 = c & 1;
|
||||
else if(i == 7) c7 = c & 1;
|
||||
}
|
||||
|
||||
c ^= 0xFF;
|
||||
c &= 1;
|
||||
|
||||
//Check carry
|
||||
if(c == 1)
|
||||
flags |= 0x1;
|
||||
//Check overflow
|
||||
if(c6 != c7)
|
||||
flags |= 0x4;
|
||||
|
||||
result[0] = s & 0xFF;
|
||||
result[1] = flags & 0xFF;
|
||||
}
|
||||
|
||||
//This is an 8-bit subtractor (op1 - op2). Returns difference as first in array, then flags.
|
||||
void sub8_old(byte i1, byte i2, byte *result)
|
||||
{
|
||||
byte op1 = i1 & 0xFF;
|
||||
byte op2 = i2 & 0xFF;
|
||||
|
||||
|
||||
byte d = 0; //8-bits
|
||||
byte b = 0; //Assume its 1-bit
|
||||
|
||||
byte flags = 0;
|
||||
|
||||
//Those following two will be used to calculate overflow flag later
|
||||
byte MSB1 = (op1 & 0x80) & 0xFF; //No need to shift them, since all of them are in the same place
|
||||
byte MSB2 = (op2 & 0x80) & 0xFF;
|
||||
|
||||
for(byte i = 0; i < 8; ++i)
|
||||
{
|
||||
//Take next bit
|
||||
byte bit1 = ((op1 & ((1 << i) & 0xFF)) >> i) & 0xFF;
|
||||
byte bit2 = ((op2 & ((1 << i) & 0xFF)) >> i) & 0xFF;
|
||||
|
||||
//Sub them from each other
|
||||
byte z1 = (bit1 ^ bit2) & 0xFF;
|
||||
d |= ((b ^ z1) << i) & 0xFF;
|
||||
|
||||
//Calculate borrow
|
||||
byte bit1_neg = (~bit1) & 0xF; //Invert the bit (Only the bit)
|
||||
byte z1_neg = (~z1) & 0xF;
|
||||
|
||||
byte b1 = (z1_neg & b) & 0xFF;
|
||||
byte b2 = (bit1_neg & bit2) & 0xFF;
|
||||
b = (b1 | b2) & 0xFF;
|
||||
|
||||
//Auxiliary flag set
|
||||
if(b != 0 && i == 1)
|
||||
flags |= 0x2;
|
||||
}
|
||||
|
||||
//Check carry flag
|
||||
if(b == 1)
|
||||
flags |= 0x1;
|
||||
|
||||
//Check overflow
|
||||
byte resultMSB = (d & 0x80) & 0xFF;
|
||||
if((MSB1 == MSB2) && MSB1 != resultMSB)
|
||||
flags |= 0x4;
|
||||
result[0] = d & 0xFF;
|
||||
result[1] = flags & 0xFF;
|
||||
}
|
||||
|
||||
//Take complement
|
||||
byte comp8(byte op)
|
||||
{
|
||||
return (((~op) & 0xFF) + 1) & 0xFF;
|
||||
}
|
||||
|
||||
//Convert to signed
|
||||
byte toSigned8(byte op)
|
||||
{
|
||||
if(op < -127)
|
||||
return comp8(op);
|
||||
else return op;
|
||||
}
|
||||
|
||||
//Converts normal number to BCD
|
||||
//https://stackoverflow.com/questions/13247647/convert-integer-from-pure-binary-to-bcd
|
||||
int int2BCD(int dec)
|
||||
{
|
||||
int i = dec;
|
||||
int bcd = 0;
|
||||
int j = 0;
|
||||
|
||||
for(; i > 0; i /= 10, j++)
|
||||
bcd |= (i % 10) << (j << 2);
|
||||
|
||||
return bcd;
|
||||
}
|
43
bitwisemath.h
Normal file
43
bitwisemath.h
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _BITWISEMATH_H_
|
||||
#define _BITWISEMATH_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
//These functions perform low-level bitwise operations.
|
||||
//Flags [0|0|0|0|0|O|A|C/B]
|
||||
///This is an 8-bit adder. Returns sum as first in array, then flags.
|
||||
void add8(byte i1, byte i2, byte carry, byte *result);
|
||||
|
||||
void sub8(byte i1, byte i2, byte carry, byte *result);
|
||||
|
||||
///This is an 8-bit subtractor (op1 - op2). Returns difference as first in array, then flags.
|
||||
void sub8_old(byte i1, byte i2, byte *result);
|
||||
|
||||
//Take complement
|
||||
byte comp8(byte op);
|
||||
|
||||
//Convert to signed
|
||||
byte toSigned8(byte op);
|
||||
|
||||
///Converts normal number byteo BCD
|
||||
int int2BCD(int dec);
|
||||
|
||||
#endif // _BITWISEMATH_H_
|
33
common.h
Normal file
33
common.h
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define FPS 60
|
||||
#define SAMPLE_RATE 32768
|
||||
#define SCREEN_WIDTH 48
|
||||
#define SCREEN_HEIGHT 32
|
||||
|
||||
typedef unsigned char byte;
|
||||
|
||||
#endif // _COMMON_H_
|
153
cpu.h
Normal file
153
cpu.h
Normal file
@ -0,0 +1,153 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _CPU_H_
|
||||
#define _CPU_H_
|
||||
|
||||
#include <vector>
|
||||
#include "ram.h"
|
||||
#include "rom.h"
|
||||
#include "flash.h"
|
||||
#include "interrupts.h"
|
||||
#include "bitwisemath.h"
|
||||
|
||||
class VE_VMS_CPU
|
||||
{
|
||||
public:
|
||||
|
||||
int state; //0: stopped. 1: started.
|
||||
int EXTOld;
|
||||
int EXTNew;
|
||||
bool P3_taken;
|
||||
|
||||
VE_VMS_CPU(VE_VMS_RAM *_ram, VE_VMS_ROM *_rom, VE_VMS_FLASH *_flash, VE_VMS_INTERRUPTS *_intHandler, bool hle);
|
||||
~VE_VMS_CPU();
|
||||
|
||||
double getCurrentFrequency();
|
||||
void setFrequency(double f);
|
||||
|
||||
//Memory operations
|
||||
//Reads a byte either from ROM or Flash, depending on value of EXT
|
||||
byte readByteRF(size_t address);
|
||||
|
||||
//Writes a byte either from ROM or Flash, depending on value of EXT
|
||||
void writeByteRF(size_t address, byte d);
|
||||
|
||||
|
||||
//Read
|
||||
byte *readFromROM(size_t address, size_t byteCount);
|
||||
byte *readFromRAM(size_t address, size_t byteCount);
|
||||
|
||||
//Write
|
||||
void writeToROM(byte *data, size_t dataSize, size_t address);
|
||||
void writeToRAM(byte *data, size_t dataSize, size_t address);
|
||||
|
||||
//Address/Data functions
|
||||
//Immediate
|
||||
byte getAddress_i8();
|
||||
|
||||
//Relative 8-bit (signed)
|
||||
signed char getAddress_r8();
|
||||
|
||||
//Relative 8-bit when the opcode has bit specifiers (signed)
|
||||
signed char getAddress_r8_b3();
|
||||
|
||||
//Relative 16-bit
|
||||
size_t getAddress_r16();
|
||||
|
||||
//Direct 9-bit
|
||||
size_t getAddress_d9();
|
||||
|
||||
//Direct 9-bit with bit assignment
|
||||
size_t getAddress_d9_b3();
|
||||
|
||||
//Get bits (b3)
|
||||
byte getAddress_b3();
|
||||
|
||||
//Indirect
|
||||
size_t getAddress_R();
|
||||
|
||||
//Absolute 12-bit
|
||||
size_t getAddress_a12();
|
||||
|
||||
//Absolute 16-bit
|
||||
size_t getAddress_a16();
|
||||
|
||||
//Absolute 16-bit (But can select to get operand from ROM (EXT = 0) or Flash (EXT = 1), important for when an instruction changes EXT, it will always be followed by a JMPF)
|
||||
size_t getAddress_a16(byte _EXT);
|
||||
|
||||
//FLAG operations
|
||||
void FLAG_setP();
|
||||
|
||||
void FLAG_clearP();
|
||||
|
||||
byte FLAG_getP();
|
||||
|
||||
void FLAG_setOV();
|
||||
|
||||
void FLAG_clearOV();
|
||||
|
||||
byte FLAG_getOV();
|
||||
|
||||
void FLAG_setAC();
|
||||
|
||||
void FLAG_clearAC();
|
||||
|
||||
byte FLAG_getAC();
|
||||
|
||||
void FLAG_setCY();
|
||||
|
||||
void FLAG_clearCY();
|
||||
|
||||
byte FLAG_getCY();
|
||||
|
||||
|
||||
/******************************************************
|
||||
******************************************************
|
||||
* Instructions and interrupts
|
||||
******************************************************
|
||||
******************************************************/
|
||||
|
||||
void processInterrupts();
|
||||
|
||||
void performHLE(size_t entryAddress);
|
||||
|
||||
//Interpreter
|
||||
int processInstruction(bool dbg);
|
||||
|
||||
private:
|
||||
size_t PC; //This counts where we reached in instruction memory (Starting from first instruction executed)
|
||||
int clock; //In nanoseconds
|
||||
double frequency;
|
||||
int interruptLevel;
|
||||
int currentInterrupt;
|
||||
bool interruptsMasked = false;
|
||||
|
||||
int instructionCount = 0;
|
||||
|
||||
VE_VMS_RAM *ram;
|
||||
VE_VMS_ROM *rom;
|
||||
VE_VMS_FLASH *flash;
|
||||
VE_VMS_INTERRUPTS *intHandler;
|
||||
|
||||
std::vector<int> interruptQueue;
|
||||
|
||||
bool IsHLE;
|
||||
};
|
||||
|
||||
#endif // _CPU_H_
|
466
flash.cpp
Normal file
466
flash.cpp
Normal file
@ -0,0 +1,466 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "flash.h"
|
||||
|
||||
VE_VMS_FLASH::VE_VMS_FLASH(VE_VMS_RAM *_ram)
|
||||
{
|
||||
userData = new byte[0x19000];
|
||||
directory = new byte[0x1A00];
|
||||
FAT = new byte[0x200];
|
||||
rootBlock = new byte[0x200];
|
||||
data = new byte[0x20000];
|
||||
|
||||
IsRealFlash = true;
|
||||
IsSaveEnabled = true;
|
||||
|
||||
ram = _ram;
|
||||
}
|
||||
|
||||
VE_VMS_FLASH::~VE_VMS_FLASH()
|
||||
{
|
||||
if(flashWriter != NULL)
|
||||
fclose(flashWriter);
|
||||
}
|
||||
|
||||
///Loads raw VMS data to be easily accessed.
|
||||
//romType 0: Memory Dump (.bin)
|
||||
//romType 1: VMS file
|
||||
//romType 2: DCI file
|
||||
void VE_VMS_FLASH::loadROM(byte *d, size_t buffSize, int romType, const char *fileName, bool enableSave)
|
||||
{
|
||||
byte *romData = new byte[0x20000];
|
||||
|
||||
size_t romSize = buffSize;
|
||||
|
||||
if(romType == 2) romSize -= 32;
|
||||
|
||||
if(romType == 2)
|
||||
{
|
||||
for(size_t i = 32, i2 = 0; i < romSize; i += 4, i2 += 4)
|
||||
{
|
||||
for(int j = 3, k = 0; j >= 0; j--, k++)
|
||||
romData[i2 + k] = d[i + j] & 0xFF;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < romSize; i++)
|
||||
romData[i] = d[i] & 0xFF;
|
||||
}
|
||||
|
||||
//If VMS or DCI, create a bogus flash memory to contain it in.
|
||||
if(romType == 1 || romType == 2)
|
||||
{
|
||||
IsRealFlash = false;
|
||||
int rootPtr = 255*512;
|
||||
int FATPtr = 254*512;
|
||||
int dirPtr = 253*512;
|
||||
int sz = (romSize+511) >> 9;
|
||||
int i = 0;
|
||||
|
||||
//FAT init
|
||||
for(; i < 256*2; i += 2)
|
||||
{
|
||||
romData[FATPtr + i] = 0xFC;
|
||||
romData[FATPtr + i + 1] = 0xFF;
|
||||
}
|
||||
|
||||
for(i = 0; i < sz; i++)
|
||||
{
|
||||
romData[FATPtr + 2*i] = i+1;
|
||||
romData[FATPtr + (2*i)+1] = 0;
|
||||
}
|
||||
|
||||
if((--i) >= 0)
|
||||
{
|
||||
romData[FATPtr + 2*i] = 0xFA;
|
||||
romData[FATPtr + (2*i)+1] = 0xFF;
|
||||
}
|
||||
romData[FATPtr + 254*2] = 0xFA;
|
||||
romData[FATPtr + (254*2)+1] = 0xFF;
|
||||
romData[FATPtr + 255*2] = 0xFA;
|
||||
romData[FATPtr + (255*2)+1] = 0xFF;
|
||||
|
||||
for(i = 253; i > 241; --i)
|
||||
{
|
||||
romData[FATPtr + 2*i] = i-1;
|
||||
romData[FATPtr + (2*i)+1] = 0;
|
||||
}
|
||||
romData[FATPtr + 241*2] = 0xFA;
|
||||
romData[FATPtr + (241*2) + 1] = 0xFA;
|
||||
|
||||
//Dir init
|
||||
romData[dirPtr] = 0xCC;
|
||||
//Fill bogus name (Spaces)
|
||||
for(i = 4; i < 12; i++)
|
||||
romData[dirPtr + i] = ' ';
|
||||
|
||||
romData[dirPtr + 0x18] = sz & 0xFF;
|
||||
romData[dirPtr + 0x19] = sz >> 8;
|
||||
romData[dirPtr + 0x1A] = 1;
|
||||
|
||||
for(i = 0; i < 16; i++)
|
||||
romData[rootPtr + i] = 0x55;
|
||||
|
||||
romData[rootPtr + 0x10] = 1;
|
||||
|
||||
for(i = 0; i < 8; i++)
|
||||
romData[rootPtr + 0x30 + i] = romData[dirPtr+0x10 + i];
|
||||
|
||||
romData[rootPtr+ 0x44] = 255;
|
||||
romData[rootPtr + 0x46] = 254;
|
||||
romData[rootPtr + 0x48] = 1;
|
||||
romData[rootPtr + 0x4A] = 253;
|
||||
romData[rootPtr + 0x4C] = 13;
|
||||
romData[rootPtr + 0x50] = 200;
|
||||
}
|
||||
|
||||
|
||||
if(romType == 0)
|
||||
{
|
||||
//Loading userData (200 blocks, blocks are ordered descending)
|
||||
for (int i = 0, c = 0; i < 200; ++i)
|
||||
{
|
||||
for (int j = 0; j < 512; j++) {
|
||||
userData[c] = romData[(i * 512) + j];
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
//Loading directory (13 blocks)
|
||||
for (int i = 253, c = 0; i >= 241; --i)
|
||||
{
|
||||
for (int j = 0; j < 512; j++) {
|
||||
directory[c] = romData[(i * 512) + j];
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
//Loading FAT and rootBlock
|
||||
for (int j = 0; j < 512; j++)
|
||||
FAT[j] = romData[(0x1FC00) + j]; //0x1FC00 being 254 x 512
|
||||
|
||||
for (int j = 0; j < 512; j++)
|
||||
rootBlock[j] = romData[(0x1FE00) + j]; //0x1FE00 being 255 x 512
|
||||
}
|
||||
|
||||
//We also need data as a whole
|
||||
for(size_t j = 0; j < romSize; j++)
|
||||
data[j] = romData[j];
|
||||
|
||||
IsSaveEnabled = enableSave;
|
||||
|
||||
if(IsSaveEnabled && romType == 0)
|
||||
flashWriter = fopen(fileName, "r+b");
|
||||
|
||||
}
|
||||
|
||||
///Returns raw VMS data and its size
|
||||
size_t VE_VMS_FLASH::getROM(byte *out)
|
||||
{
|
||||
//Loading userData (200 blocks, blocks are ordered descending)
|
||||
for(int i = 0, c = 0; i < 200; ++i)
|
||||
{
|
||||
for(int j = 0; j < 512; j++){
|
||||
out[(i*512) + j] = userData[c];
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
//Loading directory (13 blocks)
|
||||
for(int i = 253, c = 0; i >= 241; --i)
|
||||
{
|
||||
for(int j = 0; j < 512; j++){
|
||||
out[(i*512) + j] = directory[c];
|
||||
c++;
|
||||
}
|
||||
}
|
||||
|
||||
//Loading FAT and rootBlock
|
||||
for(int j = 0; j < 512; j++)
|
||||
{
|
||||
out[(0x1FC00) + j] = FAT[j]; //0x1FC00 being 254 x 512
|
||||
|
||||
// for(int j = 0; j < 512; j++)
|
||||
out[(0x1FE00) + j] = rootBlock[j]; //0x1FE00 being 255 x 512
|
||||
}
|
||||
}
|
||||
|
||||
///Returns data
|
||||
size_t VE_VMS_FLASH::getData(byte *out)
|
||||
{
|
||||
for(size_t i = 0; i < 0x20000; ++i, out[i] = data[i]);
|
||||
|
||||
return 0x20000;
|
||||
}
|
||||
|
||||
|
||||
//Operations
|
||||
///Returns byte at address. (No banking)
|
||||
byte VE_VMS_FLASH::getByte(size_t address)
|
||||
{
|
||||
/*if(address < 0x19000)
|
||||
return userData[address] & 0xFF;
|
||||
else if(address >= 0x19000 && address < 0x1E200)
|
||||
return 0; //This area of ROM is not used, why request it?
|
||||
else if(address >= 0x1E200 && address < 0x1FC00)
|
||||
return directory[address - 0x1E200] & 0xFF;
|
||||
else if(address >= 0x1FC00 && address < 0x1FE00)
|
||||
return FAT[address - 0x1FC00] & 0xFF;
|
||||
else if(address >= 0x1FE00 && address < 0x20000)
|
||||
return rootBlock[address - 0x1FE00] & 0xFF;
|
||||
else return 0;*/
|
||||
|
||||
return data[address] & 0xFF;
|
||||
}
|
||||
|
||||
///Returns byte at address (With banking)
|
||||
byte VE_VMS_FLASH::readByte(size_t address)
|
||||
{
|
||||
if((ram->readByte(0x154) & 1) == 1) address += 0x10000;
|
||||
|
||||
return data[address] & 0xFF;
|
||||
}
|
||||
|
||||
//Returns int16 at address (Little-endian)
|
||||
int VE_VMS_FLASH::getWord(size_t address)
|
||||
{
|
||||
int word = 0;
|
||||
if(address < 0x19000)
|
||||
{
|
||||
word = (userData[address+1] << 16) | (userData[address] & 0xFF);
|
||||
return word;
|
||||
}
|
||||
else if(address >= 0x19000 && address < 0x1E200)
|
||||
return 0; //This area of ROM is not used, why request it?
|
||||
else if(address >= 0x1E200 && address < 0x1FC00)
|
||||
{
|
||||
word = (directory[address - 0x1E200 + 1] << 16) | (directory[address - 0x1E200] & 0xFF);
|
||||
return word;
|
||||
}
|
||||
else if(address >= 0x1FC00 && address < 0x1FE00)
|
||||
{
|
||||
word = (FAT[address - 0x1FC00 + 1] << 16) | (FAT[address - 0x1FC00] & 0xFF);
|
||||
return word;
|
||||
}
|
||||
else if(address >= 0x1FE00 && address < 0x20000)
|
||||
{
|
||||
word = (rootBlock[address - 0x1FE00 + 1] << 16) | (rootBlock[address - 0x1FE00] & 0xFF);
|
||||
return word;
|
||||
}
|
||||
else return 0;
|
||||
}
|
||||
|
||||
///Writes int to address
|
||||
void VE_VMS_FLASH::writeByte(size_t address, byte d)
|
||||
{
|
||||
/*if(address < 0x19000)
|
||||
userData[address] = (int)(d & 0xFF);
|
||||
else if(address >= 0x19000 && address < 0x1E200)
|
||||
return; //This area of ROM is not used, why request it?
|
||||
else if(address >= 0x1E200 && address < 0x1FC00)
|
||||
directory[address - 0x1E200] = (int)(d & 0xFF);
|
||||
else if(address >= 0x1FC00 && address < 0x1FE00)
|
||||
FAT[address - 0x1FC00] = (int)(d & 0xFF);
|
||||
else if(address >= 0x1FE00 && address < 0x20000)
|
||||
rootBlock[address - 0x1FE00] = (int)(d & 0xFF);*/
|
||||
|
||||
if((ram->readByte(0x154) & 2) != 0) return; //An EXT similar register but for Flash
|
||||
|
||||
if((ram->readByte(0x154) & 1) == 1) address += 0x10000;
|
||||
|
||||
data[address] = d & 0xFF;
|
||||
|
||||
//If playing a flashrom, save changes in real time
|
||||
if(IsRealFlash && IsSaveEnabled)
|
||||
{
|
||||
fseek(flashWriter, address, SEEK_SET);
|
||||
fputc(d, flashWriter);
|
||||
}
|
||||
}
|
||||
|
||||
//Writes int to raw address
|
||||
void VE_VMS_FLASH::writeByte_RAW(size_t address, byte d)
|
||||
{
|
||||
data[address] = d & 0xFF;
|
||||
|
||||
//If playing a flashrom, save changes in real time
|
||||
if(IsRealFlash && IsSaveEnabled)
|
||||
{
|
||||
fseek(flashWriter, address, SEEK_SET);
|
||||
fputc(d, flashWriter);
|
||||
}
|
||||
}
|
||||
|
||||
///Writes int16 to address (Little-endian)
|
||||
void VE_VMS_FLASH::writeWord(size_t address, byte d)
|
||||
{
|
||||
if(address < 0x19000)
|
||||
{
|
||||
userData[address] = (int)(d & 0xFF);
|
||||
userData[address + 1] = (int)((d >> 16) & 0xFF);
|
||||
}
|
||||
else if(address >= 0x19000 && address < 0x1E200)
|
||||
return; //This area of ROM is not used, why request it?
|
||||
else if(address >= 0x1E200 && address < 0x1FC00)
|
||||
{
|
||||
directory[address - 0x1E200] = (int)(d & 0xFF);
|
||||
directory[address - 0x1E200 + 1] = (int)((d >> 16) & 0xFF);
|
||||
}
|
||||
else if(address >= 0x1FC00 && address < 0x1FE00)
|
||||
{
|
||||
FAT[address - 0x1FC00] = (int)(d & 0xFF);
|
||||
FAT[address - 0x1FC00 + 1] = (int)((d >> 16) & 0xFF);
|
||||
}
|
||||
else if(address >= 0x1FE00 && address < 0x20000)
|
||||
{
|
||||
rootBlock[address - 0x1FE00] = (int)(d & 0xFF);
|
||||
rootBlock[address - 0x1FE00 + 1] = (int)((d >> 16) & 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
///Get block data (512)
|
||||
void VE_VMS_FLASH::readBlock(int blockNumber, byte *out)
|
||||
{
|
||||
for(int j = 0; j < 512; j++)
|
||||
out[j] = getByte((blockNumber * 512) + j);
|
||||
}
|
||||
///Write data to block (512)
|
||||
void VE_VMS_FLASH::writeBlock(int blockNumber, byte *in)
|
||||
{
|
||||
for(int j = 0; j < 512; j++)
|
||||
writeByte((blockNumber * 512 + j), in[j]);
|
||||
}
|
||||
|
||||
///Checks if card is corrupt
|
||||
bool VE_VMS_FLASH::IsCorrupt()
|
||||
{
|
||||
for(int i = 0; i < 0x0F; ++i)
|
||||
if(rootBlock[i] != 0x55)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///Counts files in directory
|
||||
int VE_VMS_FLASH::countFiles()
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
//Read entries in dictionary (Each entry is 32-bytes long)
|
||||
for(int i = 0x1E200; i < 0x1FC00; i += 32)
|
||||
{
|
||||
byte d = getByte(i);
|
||||
|
||||
//If first int in entry is not 0x00, it means that the file is either data or a game
|
||||
if(d != 0x00)
|
||||
++count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
//File operations
|
||||
///Get file info from directory depending on its index
|
||||
VE_VMS_FLASH_FILE VE_VMS_FLASH::getFileAt(int index)
|
||||
{
|
||||
int pos = index * 32; //Each entry is 32-bits
|
||||
|
||||
VMS_FILE_TYPE type = VE_VMS_FLASH_FILE::getType(directory[pos + 0]);
|
||||
int startBlock = directory[pos + 1] | (directory[pos + 2] << 16);
|
||||
byte *nameArray = new byte[12];
|
||||
|
||||
for(int i = 0; i < 12; ++i)
|
||||
{
|
||||
int c = directory[pos + 4 + i];
|
||||
if((char)c == ' ') break;
|
||||
nameArray[i] = (byte)c;
|
||||
if(c == '\0') break;
|
||||
}
|
||||
|
||||
char *fileName = (char *)malloc(12);
|
||||
for(int i = 0; i < 12; i++, fileName[i] = nameArray[i]); //Filenames in VMS are UTF-8 encoded
|
||||
|
||||
int fileSize = directory[pos + 0x18] | (directory[pos + 0x19] << 16);
|
||||
int fileHeader = directory[pos + 0x1A] | (directory[pos + 0x1B] << 16);
|
||||
|
||||
VE_VMS_FLASH_FILE file(index, type, startBlock, fileName, fileSize, fileHeader);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
///Get file info from directory depending on its name
|
||||
VE_VMS_FLASH_FILE VE_VMS_FLASH::getFile(const char *name){
|
||||
VE_VMS_FLASH_FILE file;
|
||||
int fileCount = countFiles();
|
||||
|
||||
for(int i = 0; i < fileCount; ++i)
|
||||
{
|
||||
file = getFileAt(i);
|
||||
|
||||
if(strcmp(file.getFileName(), name))
|
||||
break;
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
///Counts number of mini-games found in ROM
|
||||
int VE_VMS_FLASH::countGames()
|
||||
{
|
||||
int fileCount = countFiles();
|
||||
int gameCount = 0;
|
||||
|
||||
for(int i = 0; i < fileCount; i++)
|
||||
if(getFileAt(i).getType() == GAME)
|
||||
gameCount++;
|
||||
|
||||
return gameCount;
|
||||
}
|
||||
|
||||
|
||||
//FAT operations
|
||||
///Get data of file from FAT FS
|
||||
size_t VE_VMS_FLASH::getFileData(VE_VMS_FLASH_FILE fileinfo, byte *out)
|
||||
{
|
||||
byte startBlock = fileinfo.getStartBlock();
|
||||
byte blockCount = fileinfo.getFileSize();
|
||||
|
||||
out = new byte[blockCount * 512];
|
||||
|
||||
for(int i = startBlock * 2, e = startBlock, w = 0; i < 512; i+=2, e++)
|
||||
{ //e is for entry
|
||||
byte FATEntry = FAT[i] | (FAT[i+1] << 16); //Little-endian
|
||||
|
||||
if(FATEntry != 0xFFFC){
|
||||
byte *block = new byte[512];
|
||||
readBlock(e, block); //Block is allocated to our file
|
||||
|
||||
//Write read block to 'data'
|
||||
for(int j = 0; j < 512; ++j)
|
||||
data[(w * 512) + j] = block[j];
|
||||
|
||||
++w; //Indicates number of blocks written
|
||||
|
||||
if(FATEntry == 0xFFFA) break;
|
||||
}
|
||||
}
|
||||
|
||||
return blockCount * 512;
|
||||
}
|
107
flash.h
Normal file
107
flash.h
Normal file
@ -0,0 +1,107 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FLASH_H_
|
||||
#define _FLASH_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "common.h"
|
||||
#include "flashfile.h"
|
||||
#include "ram.h"
|
||||
|
||||
class VE_VMS_FLASH
|
||||
{
|
||||
public:
|
||||
VE_VMS_FLASH(VE_VMS_RAM *_ram);
|
||||
~VE_VMS_FLASH();
|
||||
|
||||
///Loads raw VMS data to be easily accessed.
|
||||
//romType 0: Memory Dump (.bin)
|
||||
//romType 1: VMS file
|
||||
//romType 2: DCI file
|
||||
void loadROM(byte *d, size_t buffSize, int romType, const char *fileName, bool enableSave);
|
||||
|
||||
///Returns raw VMS data and its size
|
||||
size_t getROM(byte *out);
|
||||
|
||||
///Returns data
|
||||
size_t getData(byte *out);
|
||||
|
||||
|
||||
//Operations
|
||||
///Returns byte at address. (No banking)
|
||||
byte getByte(size_t address);
|
||||
|
||||
///Returns byte at address (With banking)
|
||||
byte readByte(size_t address);
|
||||
|
||||
//Returns int16 at address (Little-endian)
|
||||
int getWord(size_t address);
|
||||
|
||||
///Writes int to address
|
||||
void writeByte(size_t address, byte d);
|
||||
|
||||
//Writes int to raw address
|
||||
void writeByte_RAW(size_t address, byte d);
|
||||
|
||||
///Writes int16 to address (Little-endian)
|
||||
void writeWord(size_t address, byte d);
|
||||
|
||||
///Get block data (512)
|
||||
void readBlock(int blockNumber, byte *out);
|
||||
|
||||
///Write data to block (512)
|
||||
void writeBlock(int blockNumber, byte *in);
|
||||
|
||||
///Checks if card is corrupt
|
||||
bool IsCorrupt();
|
||||
|
||||
///Counts files in directory
|
||||
int countFiles();
|
||||
|
||||
//File operations
|
||||
///Get file info from directory depending on its index
|
||||
VE_VMS_FLASH_FILE getFileAt(int index);
|
||||
|
||||
///Get file info from directory depending on its name
|
||||
VE_VMS_FLASH_FILE getFile(const char *name);
|
||||
|
||||
///Counts number of mini-games found in ROM
|
||||
int countGames();
|
||||
|
||||
//FAT operations
|
||||
///Get data of file from FAT FS
|
||||
size_t getFileData(VE_VMS_FLASH_FILE fileinfo, byte *out);
|
||||
|
||||
private:
|
||||
//File structure
|
||||
byte *userData;
|
||||
byte *directory;
|
||||
byte *FAT;
|
||||
byte *rootBlock;
|
||||
byte *data;
|
||||
FILE *flashWriter;
|
||||
char *romName;
|
||||
bool IsRealFlash;
|
||||
bool IsSaveEnabled;
|
||||
|
||||
VE_VMS_RAM *ram;
|
||||
};
|
||||
|
||||
#endif // _FLASH_H_
|
117
flashfile.cpp
Normal file
117
flashfile.cpp
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "flashfile.h"
|
||||
|
||||
|
||||
VE_VMS_FLASH_FILE::VE_VMS_FLASH_FILE()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
VE_VMS_FLASH_FILE::VE_VMS_FLASH_FILE(int index, VMS_FILE_TYPE t, int firstblock, char *name, int size, int header)
|
||||
{
|
||||
//fileNumber means directory entry
|
||||
fileIndex = index;
|
||||
type = t;
|
||||
startBlock = firstblock;
|
||||
fileName = name;
|
||||
fileSize = size;
|
||||
headerBlock = header;
|
||||
}
|
||||
|
||||
///Copy constructor
|
||||
VE_VMS_FLASH_FILE::VE_VMS_FLASH_FILE(VE_VMS_FLASH_FILE &c)
|
||||
{
|
||||
fileIndex = c.getFileIndex();
|
||||
type = c.getType();
|
||||
startBlock = c.getStartBlock();
|
||||
fileName = c.getFileName();
|
||||
fileSize = c.getFileSize();
|
||||
headerBlock = c.getHeaderBlock();
|
||||
}
|
||||
|
||||
VMS_FILE_TYPE VE_VMS_FLASH_FILE::getType(int d)
|
||||
{
|
||||
d &= 0xFF;
|
||||
if(d == 0x00) return NONE;
|
||||
else if(d == 0x33) return DATA;
|
||||
else if(d == 0xCC) return GAME;
|
||||
else return UNKNOWN;
|
||||
}
|
||||
|
||||
//Setters and getters
|
||||
VMS_FILE_TYPE VE_VMS_FLASH_FILE::getType()
|
||||
{
|
||||
return type;
|
||||
}
|
||||
|
||||
int VE_VMS_FLASH_FILE::getStartBlock()
|
||||
{
|
||||
return startBlock;
|
||||
}
|
||||
|
||||
char * VE_VMS_FLASH_FILE::getFileName()
|
||||
{
|
||||
return fileName;
|
||||
}
|
||||
|
||||
int VE_VMS_FLASH_FILE::getFileSize()
|
||||
{
|
||||
return fileSize;
|
||||
}
|
||||
|
||||
int VE_VMS_FLASH_FILE::getHeaderBlock()
|
||||
{
|
||||
return headerBlock;
|
||||
}
|
||||
|
||||
int VE_VMS_FLASH_FILE::getFileIndex()
|
||||
{
|
||||
return fileIndex;
|
||||
}
|
||||
|
||||
void VE_VMS_FLASH_FILE::setType(VMS_FILE_TYPE t)
|
||||
{
|
||||
type = t;
|
||||
}
|
||||
|
||||
void VE_VMS_FLASH_FILE::setStartBlock(int s)
|
||||
{
|
||||
startBlock = s;
|
||||
}
|
||||
|
||||
void VE_VMS_FLASH_FILE::setFileName(char *name)
|
||||
{
|
||||
fileName = name;
|
||||
}
|
||||
|
||||
void VE_VMS_FLASH_FILE::setFileSize(int size)
|
||||
{
|
||||
fileSize = size;
|
||||
}
|
||||
|
||||
void VE_VMS_FLASH_FILE::setHeaderBlock(int header)
|
||||
{
|
||||
headerBlock = header;
|
||||
}
|
||||
|
||||
void VE_VMS_FLASH_FILE::setFileIndex(int index)
|
||||
{
|
||||
fileIndex = index;
|
||||
}
|
78
flashfile.h
Normal file
78
flashfile.h
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _FLASHFILE_H_
|
||||
#define _FLASHFILE_H_
|
||||
|
||||
enum VMS_FILE_TYPE
|
||||
{
|
||||
DATA,
|
||||
GAME,
|
||||
NONE,
|
||||
UNKNOWN = -1
|
||||
};
|
||||
|
||||
///This describes a file inside the VMS
|
||||
class VE_VMS_FLASH_FILE
|
||||
{
|
||||
|
||||
public:
|
||||
VE_VMS_FLASH_FILE();
|
||||
|
||||
VE_VMS_FLASH_FILE(int index, VMS_FILE_TYPE t, int firstblock, char *name, int size, int header);
|
||||
|
||||
///Copy constructor
|
||||
VE_VMS_FLASH_FILE(VE_VMS_FLASH_FILE &c);
|
||||
|
||||
static VMS_FILE_TYPE getType(int d);
|
||||
|
||||
//Setters and getters
|
||||
VMS_FILE_TYPE getType();
|
||||
|
||||
int getStartBlock();
|
||||
|
||||
char *getFileName();
|
||||
|
||||
int getFileSize();
|
||||
|
||||
int getHeaderBlock();
|
||||
|
||||
int getFileIndex();
|
||||
|
||||
void setType(VMS_FILE_TYPE t);
|
||||
|
||||
void setStartBlock(int s);
|
||||
|
||||
void setFileName(char *name);
|
||||
|
||||
void setFileSize(int size);
|
||||
|
||||
void setHeaderBlock(int header);
|
||||
|
||||
void setFileIndex(int index);
|
||||
|
||||
private:
|
||||
VMS_FILE_TYPE type;
|
||||
int startBlock;
|
||||
char *fileName;
|
||||
int fileSize; ///In blocks
|
||||
int headerBlock;
|
||||
int fileIndex;
|
||||
};
|
||||
|
||||
#endif // _FLASHFILE_H_
|
20
implements
Normal file
20
implements
Normal file
@ -0,0 +1,20 @@
|
||||
radius - Today at 3:31 PM
|
||||
set_environment, set_init, load, run
|
||||
and the audio, video, input callbacks
|
||||
the rest need to be there too though
|
||||
just stubbed
|
||||
MJaoune - Today at 3:31 PM
|
||||
yeah sure to prevent "Undefined" errors
|
||||
the system is a Dreamcast VMU
|
||||
radius - Today at 3:31 PM
|
||||
retro_api_version too
|
||||
and get_system_info
|
||||
MJaoune - Today at 3:32 PM
|
||||
as for the audio, it generates square waves, how do I implement that?
|
||||
radius - Today at 3:32 PM
|
||||
I think that's all
|
||||
MJaoune - Today at 3:32 PM
|
||||
video is just a framebuffer with pixels, how is that implemented too?
|
||||
radius - Today at 3:32 PM
|
||||
get_system_av_info
|
||||
don't forget that
|
173
interrupts.cpp
Normal file
173
interrupts.cpp
Normal file
@ -0,0 +1,173 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "interrupts.h"
|
||||
|
||||
VE_VMS_INTERRUPTS::VE_VMS_INTERRUPTS()
|
||||
{
|
||||
Reset = 0;
|
||||
INT0 = 0;
|
||||
INT1 = 0;
|
||||
INT2 = 0;
|
||||
INT3 = 0;
|
||||
T0HOV = 0;
|
||||
T1HLOV = 0;
|
||||
SIO0 = 0;
|
||||
SIO1 = 0;
|
||||
RFB = 0;
|
||||
P3_data = 0;
|
||||
P3_Taken = true;
|
||||
}
|
||||
|
||||
VE_VMS_INTERRUPTS::~VE_VMS_INTERRUPTS()
|
||||
{
|
||||
}
|
||||
|
||||
//Setters
|
||||
void VE_VMS_INTERRUPTS::setReset(){
|
||||
Reset = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearReset(){
|
||||
Reset = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setINT0(){
|
||||
INT0 = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearINT0(){
|
||||
INT0 = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setINT1(){
|
||||
INT1 = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearINT1(){
|
||||
INT1 = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setINT2(){
|
||||
INT2 = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearINT2(){
|
||||
INT2 = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setINT3(){
|
||||
INT3 = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearINT3(){
|
||||
INT3 = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setT0HOV(){
|
||||
T0HOV = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearT0HOV(){
|
||||
T0HOV = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setT1HLOV(){
|
||||
T1HLOV = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearT1HLOV(){
|
||||
T1HLOV = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setSIO0(){
|
||||
SIO0 = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearSIO0(){
|
||||
SIO0 = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setSIO1(){
|
||||
SIO1 = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearSIO1(){
|
||||
SIO1 = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setRFB(){
|
||||
RFB = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearRFB(){
|
||||
RFB = 0;
|
||||
}
|
||||
|
||||
void VE_VMS_INTERRUPTS::setP3(){
|
||||
P3_data = 1;
|
||||
}
|
||||
void VE_VMS_INTERRUPTS::clearP3(){
|
||||
P3_data = 0;
|
||||
}
|
||||
|
||||
//Getters
|
||||
byte VE_VMS_INTERRUPTS::getReset()
|
||||
{
|
||||
return Reset;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getINT0()
|
||||
{
|
||||
return INT0;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getINT1()
|
||||
{
|
||||
return INT1;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getINT2()
|
||||
{
|
||||
return INT2;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getINT3()
|
||||
{
|
||||
return INT3;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getT0HOV()
|
||||
{
|
||||
return T0HOV;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getT1HLOV()
|
||||
{
|
||||
return T1HLOV;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getSIO0()
|
||||
{
|
||||
return SIO0;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getSIO1()
|
||||
{
|
||||
return SIO1;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getRFB()
|
||||
{
|
||||
return RFB;
|
||||
}
|
||||
|
||||
byte VE_VMS_INTERRUPTS::getP3()
|
||||
{
|
||||
return P3_data;
|
||||
}
|
94
interrupts.h
Normal file
94
interrupts.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _INTERRUPTS_H_
|
||||
#define _INTERRUPTS_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class VE_VMS_INTERRUPTS
|
||||
{
|
||||
|
||||
public:
|
||||
VE_VMS_INTERRUPTS();
|
||||
~VE_VMS_INTERRUPTS();
|
||||
|
||||
//Setters
|
||||
void setReset();
|
||||
void clearReset();
|
||||
|
||||
void setINT0();
|
||||
void clearINT0();
|
||||
|
||||
void setINT1();
|
||||
void clearINT1();
|
||||
|
||||
void setINT2();
|
||||
void clearINT2();
|
||||
|
||||
void setINT3();
|
||||
void clearINT3();
|
||||
void setT0HOV();
|
||||
void clearT0HOV();
|
||||
|
||||
void setT1HLOV();
|
||||
void clearT1HLOV();
|
||||
|
||||
void setSIO0();
|
||||
void clearSIO0();
|
||||
|
||||
void setSIO1();
|
||||
void clearSIO1();
|
||||
|
||||
void setRFB();
|
||||
void clearRFB();
|
||||
|
||||
void setP3();
|
||||
void clearP3();
|
||||
|
||||
//Getters
|
||||
byte getReset();
|
||||
byte getINT0();
|
||||
byte getINT1();
|
||||
byte getINT2();
|
||||
byte getINT3();
|
||||
byte getT0HOV();
|
||||
byte getT1HLOV();
|
||||
byte getSIO0();
|
||||
byte getSIO1();
|
||||
byte getRFB();
|
||||
byte getP3();
|
||||
|
||||
bool P3_Taken;
|
||||
|
||||
private:
|
||||
//Interrupts
|
||||
byte Reset;
|
||||
byte INT0;
|
||||
byte INT1;
|
||||
byte INT2;
|
||||
byte INT3;
|
||||
byte T0HOV;
|
||||
byte T1HLOV;
|
||||
byte SIO0;
|
||||
byte SIO1;
|
||||
byte RFB;
|
||||
byte P3_data;
|
||||
};
|
||||
|
||||
#endif // _INTERRUPTS_H_
|
25
jni/Android.mk
Normal file
25
jni/Android.mk
Normal file
@ -0,0 +1,25 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
APP_DIR := ../../src
|
||||
|
||||
LOCAL_MODULE := vemulator
|
||||
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
LOCAL_CFLAGS += -DANDROID_ARM
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH),x86)
|
||||
LOCAL_CFLAGS += -DANDROID_X86
|
||||
endif
|
||||
|
||||
ifeq ($(TARGET_ARCH),mips)
|
||||
LOCAL_CFLAGS += -DANDROID_MIPS -D__mips__ -D__MIPSEL__
|
||||
endif
|
||||
|
||||
LOCAL_SRC_FILES += ../*.cpp
|
||||
LOCAL_CFLAGS += -O3 -std=gnu++99 -ffast-math -funroll-loops
|
||||
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
1
jni/Application.mk
Normal file
1
jni/Application.mk
Normal file
@ -0,0 +1 @@
|
||||
APP_ABI := all
|
2342
libretro.h
Normal file
2342
libretro.h
Normal file
File diff suppressed because it is too large
Load Diff
309
main.cpp
Normal file
309
main.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "libretro.h"
|
||||
#include "vmu.h"
|
||||
|
||||
retro_environment_t environment_cb;
|
||||
retro_video_refresh_t video_cb;
|
||||
retro_audio_sample_t audio_cb;
|
||||
retro_audio_sample_batch_t audio_batch_cb;
|
||||
retro_input_poll_t inputPoll_cb;
|
||||
retro_input_state_t inputState_cb;
|
||||
|
||||
struct retro_variable options[2];
|
||||
|
||||
VMU *vmu;
|
||||
uint16_t *frameBuffer;
|
||||
byte *romData;
|
||||
|
||||
|
||||
RETRO_API void retro_set_environment(retro_environment_t env)
|
||||
{
|
||||
environment_cb = env;
|
||||
|
||||
//Set variables (Options)
|
||||
options[0] = { "enable_flash_write", "Enable flash write (.bin, requires restart); enabled|disabled"};
|
||||
options[1] = {NULL, NULL};
|
||||
|
||||
env(RETRO_ENVIRONMENT_SET_VARIABLES, options);
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_video_refresh(retro_video_refresh_t vr)
|
||||
{
|
||||
video_cb = vr;
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_audio_sample(retro_audio_sample_t sample)
|
||||
{
|
||||
audio_cb = sample;
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_audio_sample_batch(retro_audio_sample_batch_t batch)
|
||||
{
|
||||
audio_batch_cb = batch;
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_input_poll(retro_input_poll_t ipoll)
|
||||
{
|
||||
inputPoll_cb = ipoll;
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_input_state(retro_input_state_t istate)
|
||||
{
|
||||
inputState_cb = istate;
|
||||
}
|
||||
|
||||
RETRO_API void retro_init(void)
|
||||
{
|
||||
frameBuffer = (uint16_t*)calloc(SCREEN_WIDTH*SCREEN_HEIGHT, sizeof(uint16_t));
|
||||
vmu = new VMU(frameBuffer);
|
||||
}
|
||||
|
||||
RETRO_API void retro_deinit(void)
|
||||
{
|
||||
delete vmu;
|
||||
if(frameBuffer != NULL) free(frameBuffer);
|
||||
if(romData != NULL) free(romData);
|
||||
}
|
||||
|
||||
RETRO_API unsigned retro_api_version(void)
|
||||
{
|
||||
return RETRO_API_VERSION;
|
||||
}
|
||||
|
||||
RETRO_API void retro_get_system_info(struct retro_system_info *info)
|
||||
{
|
||||
info->library_name = "VeMUlator";
|
||||
info->library_version = "0.1";
|
||||
info->valid_extensions = "vms|bin|dci";
|
||||
info->need_fullpath = true;
|
||||
info->block_extract = false;
|
||||
}
|
||||
|
||||
RETRO_API void retro_get_system_av_info(struct retro_system_av_info *info)
|
||||
{
|
||||
info->geometry.base_width = SCREEN_WIDTH;
|
||||
info->geometry.base_height = SCREEN_HEIGHT;
|
||||
info->geometry.max_width = SCREEN_WIDTH;
|
||||
info->geometry.max_height = SCREEN_HEIGHT;
|
||||
info->geometry.aspect_ratio = 0;
|
||||
|
||||
info->timing.fps = FPS;
|
||||
info->timing.sample_rate = SAMPLE_RATE;
|
||||
}
|
||||
|
||||
RETRO_API void retro_set_controller_port_device(unsigned port, unsigned device)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void processInput()
|
||||
{
|
||||
inputPoll_cb();
|
||||
|
||||
if(!vmu->cpu->P3_taken) return; //Don't accept new input until previous is processed
|
||||
|
||||
byte P3_reg = vmu->ram->readByte_RAW(P3);
|
||||
int pressFlag = 0;
|
||||
byte P3_int = vmu->ram->readByte_RAW(P3INT);
|
||||
|
||||
P3_reg = ~P3_reg; //Active low
|
||||
|
||||
//Up
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_UP))
|
||||
{
|
||||
P3_reg |= 1;
|
||||
pressFlag++;
|
||||
}
|
||||
else P3_reg &= 0xFE;
|
||||
|
||||
//Down
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_DOWN))
|
||||
{
|
||||
P3_reg |= 2;
|
||||
pressFlag++;
|
||||
}
|
||||
else P3_reg &= 0xFD;
|
||||
|
||||
//Left
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_LEFT))
|
||||
{
|
||||
P3_reg |= 4;
|
||||
pressFlag++;
|
||||
}
|
||||
else P3_reg &= 0xFB;
|
||||
|
||||
//Right
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_RIGHT))
|
||||
{
|
||||
P3_reg |= 8;
|
||||
pressFlag++;
|
||||
}
|
||||
else P3_reg &= 0xF7;
|
||||
|
||||
//A
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_A))
|
||||
{
|
||||
P3_reg |= 16;
|
||||
pressFlag++;
|
||||
}
|
||||
else P3_reg &= 0xEF;
|
||||
|
||||
//B
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_B))
|
||||
{
|
||||
P3_reg |= 32;
|
||||
pressFlag++;
|
||||
}
|
||||
else P3_reg &= 0xDF;
|
||||
|
||||
//Start
|
||||
if(inputState_cb(0, RETRO_DEVICE_JOYPAD, 0, RETRO_DEVICE_ID_JOYPAD_START))
|
||||
{
|
||||
//Clicking MODE without a BIOS causes hang
|
||||
//P3_reg |= 64;
|
||||
//pressFlag++;
|
||||
}
|
||||
//else P3_reg &= 0xBF;
|
||||
|
||||
P3_reg = ~P3_reg;
|
||||
|
||||
vmu->ram->writeByte_RAW(P3, P3_reg);
|
||||
|
||||
if(pressFlag)
|
||||
{
|
||||
vmu->ram->writeByte_RAW(P3INT, P3_int | 2);
|
||||
vmu->intHandler->setP3();
|
||||
vmu->cpu->P3_taken = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RETRO_API void retro_reset(void)
|
||||
{
|
||||
vmu->reset();
|
||||
}
|
||||
|
||||
RETRO_API void retro_run(void)
|
||||
{
|
||||
processInput();
|
||||
|
||||
//Cycles passed since last screen refresh
|
||||
uint cyclesPassed = vmu->cpu->getCurrentFrequency() / FPS;
|
||||
|
||||
for(uint i = 0; i < cyclesPassed; i++)
|
||||
vmu->runCycle();
|
||||
|
||||
//Video
|
||||
vmu->video->drawFrame(frameBuffer);
|
||||
if(vmu->ram->readByte_RAW(MCR) & 8) video_cb(frameBuffer, SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_WIDTH * 2);
|
||||
|
||||
//Audio
|
||||
vmu->audio->generateSignal(audio_cb);
|
||||
}
|
||||
|
||||
RETRO_API size_t retro_serialize_size(void)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
RETRO_API bool retro_serialize(void *data, size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API bool retro_unserialize(const void *data, size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API void retro_cheat_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API bool retro_load_game(const struct retro_game_info *game)
|
||||
{
|
||||
//Set environment variables
|
||||
enum retro_pixel_format format = RETRO_PIXEL_FORMAT_RGB565;
|
||||
environment_cb(RETRO_ENVIRONMENT_SET_PIXEL_FORMAT, &format);
|
||||
|
||||
//Opening file
|
||||
FILE *rom = fopen(game->path, "rb");
|
||||
if(rom == NULL) return false;
|
||||
fseek(rom, 0, SEEK_END);
|
||||
size_t romSize = ftell(rom);
|
||||
fseek(rom, 0 , SEEK_SET);
|
||||
|
||||
romData = (byte *)malloc(romSize);
|
||||
for(size_t i = 0; i < romSize; i++)
|
||||
romData[i] = fgetc(rom);
|
||||
|
||||
fclose(rom);
|
||||
|
||||
//Check extension
|
||||
char *path = (char *)malloc(strlen(game->path) + 1);
|
||||
strcpy(path, game->path);
|
||||
char *ext = strchr(path, '.');
|
||||
|
||||
//Check needed variables
|
||||
struct retro_variable var = {0};
|
||||
var.key = "enable_flash_write";
|
||||
environment_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var);
|
||||
|
||||
//Loading ROM
|
||||
if(!strcmp(ext, ".bin") || !strcmp(ext, ".BIN"))
|
||||
{
|
||||
//Check if user wants core to be able to write to flash
|
||||
if(!strcmp(var.value, "enabled")) vmu->flash->loadROM(romData, romSize, 0, game->path, true);
|
||||
else vmu->flash->loadROM(romData, romSize, 0, game->path, false);
|
||||
}
|
||||
else if(!strcmp(ext, ".vms") || !strcmp(ext, ".VMS")) vmu->flash->loadROM(romData, romSize, 1, game->path, false);
|
||||
else if(!strcmp(ext, ".dci") || !strcmp(ext, ".DCI")) vmu->flash->loadROM(romData, romSize, 2, game->path, false);
|
||||
|
||||
free(path);
|
||||
|
||||
//Initializing system
|
||||
vmu->startCPU();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
RETRO_API bool retro_load_game_special(unsigned game_type, const struct retro_game_info *info, size_t num_info)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RETRO_API void retro_unload_game(void)
|
||||
{
|
||||
vmu->reset();
|
||||
}
|
||||
|
||||
RETRO_API unsigned retro_get_region(void)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API void *retro_get_memory_data(unsigned id)
|
||||
{
|
||||
}
|
||||
|
||||
RETRO_API size_t retro_get_memory_size(unsigned id)
|
||||
{
|
||||
}
|
221
ram.cpp
Normal file
221
ram.cpp
Normal file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "ram.h"
|
||||
|
||||
VE_VMS_RAM::VE_VMS_RAM()
|
||||
{
|
||||
T1LC_Temp = 0;
|
||||
T1HC_Temp = 0;
|
||||
|
||||
data = new byte[1024];
|
||||
wram = new byte[512];
|
||||
xram0 = new byte[0x7C];
|
||||
xram1 = new byte[0x7C];
|
||||
xram2 = new byte[0x7C];
|
||||
|
||||
T1RL_data = 0;
|
||||
T1RH_data = 0;
|
||||
}
|
||||
|
||||
VE_VMS_RAM::~VE_VMS_RAM()
|
||||
{
|
||||
delete []data;
|
||||
delete []wram;
|
||||
delete []xram0;
|
||||
delete []xram1;
|
||||
delete []xram2;
|
||||
}
|
||||
|
||||
//Setters and getters
|
||||
byte VE_VMS_RAM::readByte(size_t adr)
|
||||
{
|
||||
//printf("Reading raw address %ul\n", adr);
|
||||
size_t xaddress = adr + (data[STAD] & 0xFF); //Remove start address of XRAM
|
||||
size_t address = adr;
|
||||
|
||||
//If first half of ram is accessed (Not SFR), check Bank to choose whether to access first bank of RAM or second.
|
||||
//Second bank starts at 256
|
||||
if(address < 0x100)
|
||||
{
|
||||
byte mainBank = ((data[PSW] & 0x2) >> 1) & 0x1; //Get RAM bank
|
||||
|
||||
if(mainBank == 1) address += 512;
|
||||
}
|
||||
//If XRAM is accessed, we choose the address depending on XBNK SFR.
|
||||
else if(address >= 0x180 && address <= 0x1FB)
|
||||
{
|
||||
byte XRAMBank = data[XBNK] & 0xFF;
|
||||
|
||||
switch(XRAMBank)
|
||||
{
|
||||
case 0:
|
||||
return xram0[xaddress - 0x180] & 0xFF;
|
||||
case 1:
|
||||
return xram1[xaddress - 0x180] & 0xFF;
|
||||
case 2:
|
||||
return xram2[xaddress - 0x180] & 0xFF;
|
||||
default:
|
||||
return xram0[xaddress - 0x180] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//Work RAM access
|
||||
if(adr == 0x166)
|
||||
{
|
||||
byte VSEL_ = data[VSEL] & 0xFF;
|
||||
size_t VRMAD = (data[VRMAD1] | (data[VRMAD2] << 8)) & 0x1FF;
|
||||
size_t VRMAD_original = VRMAD;
|
||||
|
||||
//Check if auto increment is enabled
|
||||
if((VSEL_ & 16) != 0)
|
||||
{
|
||||
VRMAD++;
|
||||
data[VRMAD1] = VRMAD & 0xFF;
|
||||
data[VRMAD2] = (VRMAD >> 8) & 1;
|
||||
}
|
||||
//printf("Work ram buffer accessed! Read\n");
|
||||
|
||||
return (wram[VRMAD_original] & 0xFF);
|
||||
}
|
||||
|
||||
|
||||
if(adr != T1LR && adr != T1HR) //T1 reload registers are the same as T1, so we need to separate them
|
||||
return (data[address] & 0xFF);
|
||||
else if(adr == T1LR) return T1RL_data & 0xFF;
|
||||
else return T1RH_data & 0xFF;
|
||||
}
|
||||
|
||||
//No banking or checking, use carefully!
|
||||
byte VE_VMS_RAM::readByte_RAW(size_t adr)
|
||||
{
|
||||
return data[adr] & 0xFF;
|
||||
}
|
||||
|
||||
//This is used by the GPU only.
|
||||
byte VE_VMS_RAM::readByteXRAM(size_t adr, int bank)
|
||||
{
|
||||
size_t address = adr + (data[STAD] & 0xFF);
|
||||
|
||||
switch(bank)
|
||||
{
|
||||
case 0:
|
||||
return xram0[address - 0x180] & 0xFF;
|
||||
case 1:
|
||||
return xram1[address - 0x180] & 0xFF;
|
||||
case 2:
|
||||
return xram2[address - 0x180] & 0xFF;
|
||||
default:
|
||||
return xram0[address - 0x180] & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
void VE_VMS_RAM::writeByte(size_t adr, byte b)
|
||||
{
|
||||
//printf("Writing raw address %ul\n", adr);
|
||||
size_t xaddress = adr + (data[STAD] & 0xFF);
|
||||
size_t address = adr;
|
||||
|
||||
//If first half of ram is accessed (Not SFR), check Bank to choose whether to access first bank of RAM or second.
|
||||
//Second bank starts at 256
|
||||
if(address < 0x100)
|
||||
{
|
||||
byte mainBank = ((data[PSW] & 0x2) >> 1) & 0x1; //Get RAM bank
|
||||
|
||||
if(mainBank == 1) address += 512; //To access second bank in "data[]"
|
||||
}
|
||||
//If XRAM is accessed, we choose the address depending on XBNK SFR.
|
||||
else if(address >= 0x180 && address <= 0x1FB)
|
||||
{
|
||||
byte XRAMBank = data[XBNK] & 0xFF;
|
||||
|
||||
switch(XRAMBank)
|
||||
{
|
||||
case 0:
|
||||
//VMU_Debug.debugGFX("Writing to XRAM Bank 0, Data= " + Integer.toHexString(b & 0xFF));
|
||||
xram0[xaddress - 0x180] = b & 0xFF;
|
||||
return;
|
||||
case 1:
|
||||
//VMU_Debug.debugGFX("Writing to XRAM Bank 1, Data= " + Integer.toHexString(b & 0xFF));
|
||||
xram1[xaddress - 0x180] = b & 0xFF;
|
||||
return;
|
||||
case 2:
|
||||
//VMU_Debug.debugGFX("Writing to XRAM Bank 2, Data= " + Integer.toHexString(b & 0xFF));
|
||||
xram2[xaddress - 0x180] = b & 0xFF;
|
||||
return;
|
||||
default:
|
||||
//VMU_Debug.debugGFX("(Fault) Writing to XRAM Bank 0, Data= " + Integer.toHexString(b & 0xFF));
|
||||
xram0[xaddress - 0x180] = b & 0xFF;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Work RAM access
|
||||
if(adr == 0x166)
|
||||
{
|
||||
byte VSEL_ = data[VSEL] & 0xFF;
|
||||
size_t VRMAD = (data[VRMAD1] | (data[VRMAD2] << 8)) & 0x1FF;
|
||||
size_t VRMAD_original = VRMAD;
|
||||
|
||||
//Check if auto increment is enabled
|
||||
if((VSEL_ & 16) != 0)
|
||||
{
|
||||
VRMAD++;
|
||||
data[VRMAD1] = VRMAD & 0xFF;
|
||||
data[VRMAD2] = (VRMAD >> 8) & 1;
|
||||
}
|
||||
//printf("Work ram buffer accessed! Write");
|
||||
|
||||
wram[VRMAD_original] = b & 0xFF;
|
||||
return;
|
||||
}
|
||||
|
||||
if(address != T1LC && address != T1HC)
|
||||
{
|
||||
data[address] = b & 0xFF;
|
||||
return;
|
||||
}
|
||||
|
||||
//T1LC and T1HC are updated only when bit4 of T1CNT is enabled (This is checked each cycle).
|
||||
if(address == T1LC) T1LC_Temp = b & 0xFF;
|
||||
else T1HC_Temp = b & 0xFF;
|
||||
}
|
||||
|
||||
void VE_VMS_RAM::writeByte_RAW(size_t adr, byte b)
|
||||
{
|
||||
data[adr] = b & 0xFF;
|
||||
}
|
||||
|
||||
//Stack operations (To ensure writing to bank 0 only)
|
||||
void VE_VMS_RAM::stackPush(byte d)
|
||||
{
|
||||
data[SP] += 1;
|
||||
data[data[SP]] = d & 0xFF;
|
||||
}
|
||||
|
||||
byte VE_VMS_RAM::stackPop()
|
||||
{
|
||||
data[SP] -= 1;
|
||||
return data[data[SP] + 1] & 0xFF;
|
||||
}
|
||||
|
||||
byte *VE_VMS_RAM::getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
120
ram.h
Normal file
120
ram.h
Normal file
@ -0,0 +1,120 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _RAM_H_
|
||||
#define _RAM_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
//SFR
|
||||
#define ACC 0x100
|
||||
#define PSW 0x101
|
||||
#define B 0x102
|
||||
#define C 0x103
|
||||
#define TRL 0x104
|
||||
#define TRH 0x105
|
||||
#define SP 0x106
|
||||
#define PCON 0x107
|
||||
#define IE 0x108
|
||||
#define IP 0x109
|
||||
#define EXT 0x10D
|
||||
#define OCR 0x10E
|
||||
#define T0CNT 0x110
|
||||
#define T0PRR 0x111
|
||||
#define T0L 0x112
|
||||
#define T0LR 0x113
|
||||
#define T0H 0x114
|
||||
#define T0HR 0x115
|
||||
#define T1CNT 0x118
|
||||
#define T1LC 0x11a
|
||||
#define T1LR 0x11b
|
||||
#define T1HC 0x11c
|
||||
#define T1HR 0x11d
|
||||
#define MCR 0x120
|
||||
#define STAD 0x122
|
||||
#define CNR 0x123
|
||||
#define TDR 0x124
|
||||
#define XBNK 0x125
|
||||
#define VCCR 0x127
|
||||
#define SCON0 0x130
|
||||
#define SBUF0 0x131
|
||||
#define SBR 0x132
|
||||
#define SCON1 0x134
|
||||
#define SBUF1 0x135
|
||||
#define P1 0x144
|
||||
#define P1DDR 0x145
|
||||
#define P1FCR 0x146
|
||||
#define P3 0x14c
|
||||
#define P3DDR 0x14d
|
||||
#define P3INT 0x14e
|
||||
#define P7 0x15c
|
||||
#define I01CR 0x15d
|
||||
#define I23CR 0x15e
|
||||
#define ISL 0x15f
|
||||
#define VSEL 0x163
|
||||
#define VRMAD1 0x164
|
||||
#define VRMAD2 0x165
|
||||
#define VTRBF 0x166
|
||||
#define BTCR 0x17f
|
||||
#define XRAM 0x180
|
||||
|
||||
class VE_VMS_RAM
|
||||
{
|
||||
public:
|
||||
//Extra
|
||||
//The following 2 hold values for T1LC and T1HC until T1CNT bit 4 is set
|
||||
byte T1LC_Temp;
|
||||
byte T1HC_Temp;
|
||||
|
||||
//Timer 1 reload registers (Stored here since they will be used in this class too)
|
||||
byte T1RL_data;
|
||||
byte T1RH_data;
|
||||
|
||||
|
||||
VE_VMS_RAM();
|
||||
~VE_VMS_RAM();
|
||||
|
||||
//Setters and getters
|
||||
byte readByte(size_t adr);
|
||||
|
||||
//No banking or checking, use carefully!
|
||||
byte readByte_RAW(size_t adr);
|
||||
|
||||
///This is used by the GPU only.
|
||||
byte readByteXRAM(size_t adr, int bank);
|
||||
|
||||
void writeByte(size_t adr, byte b);
|
||||
|
||||
void writeByte_RAW(size_t adr, byte b);
|
||||
|
||||
//Stack operations (To ensure writing to bank 0 only)
|
||||
void stackPush(byte d);
|
||||
|
||||
byte stackPop();
|
||||
|
||||
byte *getData();
|
||||
|
||||
private:
|
||||
byte *data;
|
||||
byte *wram;
|
||||
byte *xram0;
|
||||
byte *xram1;
|
||||
byte *xram2;
|
||||
};
|
||||
|
||||
#endif // _RAM_H_
|
60
rom.cpp
Normal file
60
rom.cpp
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "rom.h"
|
||||
|
||||
VE_VMS_ROM::VE_VMS_ROM()
|
||||
{
|
||||
data = new size_t[0x100000];
|
||||
}
|
||||
|
||||
VE_VMS_ROM::~VE_VMS_ROM()
|
||||
{
|
||||
delete []data;
|
||||
}
|
||||
|
||||
//Setters and getters
|
||||
byte VE_VMS_ROM::readByte(size_t address)
|
||||
{
|
||||
return data[address] & 0xFF;
|
||||
}
|
||||
|
||||
void VE_VMS_ROM::writeByte(size_t address, byte b)
|
||||
{
|
||||
data[address] = b & 0xFF;
|
||||
}
|
||||
|
||||
//Memory operations
|
||||
void VE_VMS_ROM::loadData(byte *d, size_t buffSize, size_t size)
|
||||
{
|
||||
if(buffSize < size) return;
|
||||
for(size_t i = 0; i < size; i++)
|
||||
data[i] = d[i];
|
||||
}
|
||||
|
||||
void VE_VMS_ROM::loadData(byte *d, size_t buffSize)
|
||||
{
|
||||
for(size_t i = 0; i < buffSize; i++)
|
||||
data[i] = d[i];
|
||||
}
|
||||
|
||||
size_t *VE_VMS_ROM::getData()
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
46
rom.h
Normal file
46
rom.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ROM_H_
|
||||
#define _ROM_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
class VE_VMS_ROM
|
||||
{
|
||||
public:
|
||||
VE_VMS_ROM();
|
||||
~VE_VMS_ROM();
|
||||
|
||||
//Setters and getters
|
||||
byte readByte(size_t address);
|
||||
|
||||
void writeByte(size_t address, byte b);
|
||||
|
||||
//Memory operations
|
||||
void loadData(byte *d, size_t buffSize, size_t size);
|
||||
|
||||
void loadData(byte *d, size_t buffSize);
|
||||
|
||||
size_t *getData();
|
||||
|
||||
private:
|
||||
size_t *data;
|
||||
};
|
||||
|
||||
#endif // _ROM_H_
|
12
status
Normal file
12
status
Normal file
@ -0,0 +1,12 @@
|
||||
cpu => Done
|
||||
bitwisemath => Done
|
||||
flash => Done
|
||||
flashfile => Done
|
||||
interrupts => Done
|
||||
ram => Done
|
||||
rom => Done
|
||||
t0 => Done
|
||||
t1 => Done
|
||||
basetimer => Done
|
||||
video => Done
|
||||
audio => Done
|
156
t0.cpp
Normal file
156
t0.cpp
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "t0.h"
|
||||
|
||||
VE_VMS_TIMER0::VE_VMS_TIMER0(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_CPU *_cpu, byte *_prescaler)
|
||||
{
|
||||
ram = _ram;
|
||||
intHandler = _intHandler;
|
||||
cpu = _cpu;
|
||||
prescaler = _prescaler;
|
||||
|
||||
TRLStarted = 0;
|
||||
TRHStarted = 0;
|
||||
|
||||
TRL_data = 0;
|
||||
TRH_data = 0;
|
||||
}
|
||||
|
||||
VE_VMS_TIMER0::~VE_VMS_TIMER0()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void VE_VMS_TIMER0::runTimer()
|
||||
{
|
||||
int TCNT_data = ram->readByte_RAW(T0CNT); //Timer control register
|
||||
|
||||
bool TRLEnabled;
|
||||
bool TRHEnabled;
|
||||
bool TRLONGEnabled;
|
||||
|
||||
TRLEnabled = (TCNT_data & 64) != 0;
|
||||
TRHEnabled = (TCNT_data & 128) != 0;
|
||||
TRLONGEnabled = (TCNT_data & 32) != 0;
|
||||
|
||||
//int clockSource = ((TCNT_data & 16) >> 4) & 0xFF;
|
||||
|
||||
//if(clockSource == 1) return; //External pin, not supported
|
||||
|
||||
//Increase timers
|
||||
if(TRLEnabled)
|
||||
{
|
||||
if(TRLStarted++ == 0)
|
||||
{
|
||||
TRL_data = ram->readByte_RAW(T0LR);
|
||||
//printf("Started T0RL\n");
|
||||
}
|
||||
else if(*prescaler == 1) TRL_data++;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRL_data = ram->readByte_RAW(T0LR);
|
||||
TRLStarted = 0;
|
||||
}
|
||||
|
||||
if(TRHEnabled)
|
||||
{
|
||||
if(TRHStarted++ == 0)
|
||||
{
|
||||
TRH_data = ram->readByte_RAW(T0HR);
|
||||
//printf("Started T0RH\n");
|
||||
}
|
||||
else if(!TRLONGEnabled)
|
||||
{
|
||||
if(*prescaler == 1)
|
||||
TRH_data++;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
TRH_data = ram->readByte_RAW(T0HR);
|
||||
TRHStarted = 0;
|
||||
}
|
||||
|
||||
//if(TRLONGEnabled) printf("Long mode.\n");
|
||||
|
||||
//Overflow in TRL_data, 8-bit mode
|
||||
if(TRL_data > 255 && !TRLONGEnabled)
|
||||
{
|
||||
TCNT_data |= 2;
|
||||
|
||||
if (TCNT_data & 1) intHandler->setINT2();
|
||||
|
||||
//Stop timer
|
||||
//TCNT_data &= 0xBF;
|
||||
|
||||
//Reload contents
|
||||
TRL_data = ram->readByte_RAW(T0LR);
|
||||
}
|
||||
//Overflow in TRL_data, 16-bit mode
|
||||
else if(TRL_data > 255 && TRLONGEnabled)
|
||||
{
|
||||
TRH_data++;
|
||||
|
||||
|
||||
if (TCNT_data & 1) intHandler->setINT2();
|
||||
//Reload contents
|
||||
TRL_data = ram->readByte_RAW(T0LR);
|
||||
//TRL_data = 0;
|
||||
}
|
||||
|
||||
//Overflow in TRH_data, 8-bit mode
|
||||
if(TRH_data > 255 && !TRLONGEnabled)
|
||||
{
|
||||
//printf("T0RH overflow 8-bit\n");
|
||||
TCNT_data |= 8;
|
||||
|
||||
if (TCNT_data & 4) intHandler->setT0HOV();
|
||||
|
||||
//Stop timer
|
||||
TCNT_data &= 0x7F; //Not forcefully stopping it causes a hang in Chao Adventure 1 when navigating through the menu
|
||||
|
||||
//Reload contents
|
||||
TRH_data = ram->readByte_RAW(T0HR);
|
||||
}
|
||||
//Overflow in 16-bit mode
|
||||
else if(TRH_data > 255 && TRLONGEnabled)
|
||||
{
|
||||
//printf("T0 LONG overflow 16-bit\n");
|
||||
TCNT_data |= 2;
|
||||
TCNT_data |= 8;
|
||||
|
||||
if (TCNT_data & 4) intHandler->setT0HOV();
|
||||
|
||||
//Stop both timers
|
||||
//TCNT_data &= 0x3F;
|
||||
|
||||
//Reload contents
|
||||
TRL_data = ram->readByte_RAW(T0LR);
|
||||
TRH_data = ram->readByte_RAW(T0HR);
|
||||
}
|
||||
|
||||
ram->writeByte_RAW(T0L, TRL_data);
|
||||
ram->writeByte_RAW(T0H, TRH_data);
|
||||
|
||||
|
||||
ram->writeByte_RAW(T0CNT, TCNT_data);
|
||||
}
|
||||
|
46
t0.h
Normal file
46
t0.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _T0_H_
|
||||
#define _T0_H_
|
||||
|
||||
#include "ram.h"
|
||||
#include "interrupts.h"
|
||||
#include "cpu.h"
|
||||
|
||||
class VE_VMS_TIMER0
|
||||
{
|
||||
public:
|
||||
VE_VMS_TIMER0(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_CPU *_cpu, byte *_prescaler);
|
||||
~VE_VMS_TIMER0();
|
||||
|
||||
void runTimer();
|
||||
|
||||
private:
|
||||
int TRLStarted;
|
||||
int TRHStarted;
|
||||
VE_VMS_RAM *ram;
|
||||
VE_VMS_INTERRUPTS *intHandler;
|
||||
VE_VMS_CPU *cpu;
|
||||
byte *prescaler;
|
||||
|
||||
double TRL_data;
|
||||
double TRH_data;
|
||||
};
|
||||
|
||||
#endif // _T0_H_
|
139
t1.cpp
Normal file
139
t1.cpp
Normal file
@ -0,0 +1,139 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "t1.h"
|
||||
|
||||
VE_VMS_TIMER1::VE_VMS_TIMER1(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_AUDIO *_audio)
|
||||
{
|
||||
ram = _ram;
|
||||
intHandler = _intHandler;
|
||||
audio = _audio;
|
||||
|
||||
TRLStarted = 0;
|
||||
TRHStarted = 0;
|
||||
}
|
||||
|
||||
VE_VMS_TIMER1::~VE_VMS_TIMER1()
|
||||
{
|
||||
}
|
||||
|
||||
void VE_VMS_TIMER1::runTimer()
|
||||
{
|
||||
int TCNT_data = ram->readByte_RAW(T1CNT); //Timer control register
|
||||
|
||||
bool TRLEnabled;
|
||||
bool TRHEnabled;
|
||||
bool TRLONGEnabled;
|
||||
|
||||
TRLEnabled = (TCNT_data & 64) != 0;
|
||||
TRHEnabled = (TCNT_data & 128) != 0;
|
||||
TRLONGEnabled = (TCNT_data & 32) != 0;
|
||||
|
||||
//Increase timers
|
||||
if(TRLEnabled)
|
||||
{
|
||||
if(TRLStarted++ == 0)
|
||||
{
|
||||
ram->T1RL_data = ram->readByte_RAW(T1LR);
|
||||
|
||||
audio->setT1(ram->T1RL_data);
|
||||
//printf("Started T1RL\n");
|
||||
}
|
||||
|
||||
ram->T1RL_data++;
|
||||
if(TRLONGEnabled && !TRHEnabled) ram->T1RL_data++; //Tcyc/2, equivalent to ram->T1RL_data += 2;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ram->T1RL_data = ram->readByte_RAW(T1LR);
|
||||
TRLStarted = 0;
|
||||
}
|
||||
|
||||
audio->setEnabled(TRLEnabled & !TRLONGEnabled);
|
||||
|
||||
|
||||
|
||||
if(TRHEnabled)
|
||||
{
|
||||
TRHStarted++;
|
||||
if(!TRLONGEnabled) ram->T1RH_data++;
|
||||
}
|
||||
else
|
||||
{
|
||||
ram->T1RH_data = ram->readByte_RAW(T1HR);
|
||||
TRHStarted = 0;
|
||||
}
|
||||
|
||||
//Overflow in ram->T1RL_data, 8-bit mode
|
||||
if(ram->T1RL_data > 255 && !TRLONGEnabled)
|
||||
{
|
||||
TCNT_data |= 2;
|
||||
|
||||
if ((TCNT_data & 1) != 0) intHandler->setT1HLOV();
|
||||
|
||||
//Stop timer
|
||||
//TCNT_data &= 0xBF;
|
||||
|
||||
//Reload contents
|
||||
ram->T1RL_data = ram->readByte_RAW(T1LR);
|
||||
}
|
||||
//Overflow in ram->T1RL_data, 16-bit mode
|
||||
else if(ram->T1RL_data > 255 && TRLONGEnabled)
|
||||
{
|
||||
ram->T1RH_data++;
|
||||
|
||||
//Reload contents
|
||||
ram->T1RL_data = ram->readByte_RAW(T0LR);
|
||||
}
|
||||
|
||||
//Overflow in ram->T1RH_data, 8-bit mode
|
||||
if(ram->T1RH_data > 255 && !TRLONGEnabled)
|
||||
{
|
||||
TCNT_data |= 8;
|
||||
|
||||
if ((TCNT_data & 4) != 0) intHandler->setT1HLOV();
|
||||
|
||||
//Stop timer
|
||||
//TCNT_data &= 0x7F;
|
||||
|
||||
//Reload contents
|
||||
ram->T1RH_data = ram->readByte_RAW(T1HR);
|
||||
}
|
||||
|
||||
//Overflow in 16-bit mode
|
||||
else if(ram->T1RH_data > 255 && TRLONGEnabled)
|
||||
{
|
||||
TCNT_data |= 2;
|
||||
TCNT_data |= 8;
|
||||
|
||||
if ((TCNT_data & 4) != 0) intHandler->setT1HLOV();
|
||||
|
||||
//Stop both timers
|
||||
//TCNT_data &= 0x1F;
|
||||
|
||||
//Reload contents
|
||||
ram->T1RL_data = ram->readByte_RAW(T1LR);
|
||||
ram->T1RH_data = ram->readByte_RAW(T1HR);
|
||||
}
|
||||
|
||||
|
||||
//ram->writeByte_RAW(ram->T1LR, ram->T1RL_data);
|
||||
//ram->writeByte_RAW(ram->T1HR, ram->T1RH_data);
|
||||
ram->writeByte_RAW(T1CNT, TCNT_data);
|
||||
}
|
44
t1.h
Normal file
44
t1.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _T1_H_
|
||||
#define _T1_H_
|
||||
|
||||
#include "audio.h"
|
||||
#include "ram.h"
|
||||
#include "interrupts.h"
|
||||
|
||||
class VE_VMS_TIMER1
|
||||
{
|
||||
public:
|
||||
VE_VMS_TIMER1(VE_VMS_RAM *_ram, VE_VMS_INTERRUPTS *_intHandler, VE_VMS_AUDIO *_audio);
|
||||
~VE_VMS_TIMER1();
|
||||
|
||||
void runTimer();
|
||||
|
||||
private:
|
||||
int TRLStarted;
|
||||
int TRHStarted;
|
||||
|
||||
//The counters in T1 are implicit (Not visible to the programmer)
|
||||
VE_VMS_RAM *ram;
|
||||
VE_VMS_INTERRUPTS *intHandler;
|
||||
VE_VMS_AUDIO *audio;
|
||||
};
|
||||
|
||||
#endif // _T1_H_
|
10
vemulator_libretro.info
Normal file
10
vemulator_libretro.info
Normal file
@ -0,0 +1,10 @@
|
||||
display_name = "VeMUlator"
|
||||
authors = "Mahmoud Jaoune"
|
||||
supported_extensions = "vms|dci|bin"
|
||||
corename = "VeMUlator"
|
||||
categories = "Game"
|
||||
systemname = "SEGA Visual Memory Unit"
|
||||
license = "GPL v3"
|
||||
permissions = ""
|
||||
display_version = "0.1"
|
||||
supports_no_game = "false"
|
89
video.cpp
Normal file
89
video.cpp
Normal file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "video.h"
|
||||
|
||||
VE_VMS_VIDEO::VE_VMS_VIDEO(VE_VMS_RAM *_ram)
|
||||
{
|
||||
ram = _ram;
|
||||
}
|
||||
|
||||
VE_VMS_VIDEO::~VE_VMS_VIDEO()
|
||||
{
|
||||
}
|
||||
|
||||
void VE_VMS_VIDEO::drawFrame(uint16_t *buffer)
|
||||
{
|
||||
//Read XRAM buffer from RAM (WRAM starts at 180), each 6 bytes make 1 horizontal line on-screen
|
||||
//Each bit declares whether the pixel is on or off
|
||||
//There is a 4-byte empty space between each two lines (96 bytes) of XRAM buffer.
|
||||
|
||||
if((ram->readByte_RAW(MCR) & 8) == 0)
|
||||
return;
|
||||
|
||||
|
||||
size_t XRAMAddress;
|
||||
byte MSB = 0x80; //10000000b
|
||||
//Draw pixels (48x32) for banks 0 and 1 ("i" selects bank)
|
||||
for(int i = 0, c = 0; i < 2; ++i)
|
||||
{
|
||||
XRAMAddress = 0x180;
|
||||
for (int y = 0; y < 16; y++)
|
||||
{
|
||||
byte *pixelLine = new byte[6];
|
||||
|
||||
if((y % 2 == 0) && (y > 0)) XRAMAddress += 4;
|
||||
|
||||
for(int p = 0; p < 6; p++)
|
||||
pixelLine[p] = ram->readByteXRAM(XRAMAddress++, i);
|
||||
|
||||
//Big-Endian
|
||||
for (int x = 0; x < 6; x++)
|
||||
for (int j = 0; j < 8; j++)
|
||||
buffer[c++] = ((pixelLine[x] & (MSB >> j)) != 0) ? 0 : 0xFFFF;
|
||||
|
||||
delete []pixelLine;
|
||||
}
|
||||
}
|
||||
|
||||
//Draw pixels for bank 2 (BIOS Icons)
|
||||
/*
|
||||
* BIOS Icons not needed when HLE is used
|
||||
*
|
||||
scaleX /= 2; //Since icons are more pixel dense
|
||||
scaleY /= 2;
|
||||
scaleXM8 = 8*scaleX;
|
||||
float scaleXM24 = 24*scaleX;
|
||||
float scaleYM66 = 66*scaleY;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(ram->readByteXRAM(0x181 + i, 2) == 0x00) continue; //Only draw icons shown in XRAM bank 2
|
||||
|
||||
int []icon = ICONS[i];
|
||||
for (int y = 0; y < 32; y++) {
|
||||
int []pixelLine = new int[3];
|
||||
|
||||
System.arraycopy(icon, y * 3, pixelLine, 0, 3);
|
||||
|
||||
for (int x = 0; x < 3; x++)
|
||||
for (int j = 0; j < 8; j++)
|
||||
screenCanvas.drawRect(marginX + ((x * scaleXM8) + (j * scaleX)) + (i * scaleXM24), marginY + (scaleYM66 + (y * scaleY)), marginX + ((x * scaleXM8) + (j * scaleX)) + scaleX + (i * scaleXM24), marginY + (scaleYM66 + (y * scaleY)) + scaleY, ((pixelLine[x] & (0x80 >> j)) != 0)?pixelColor:noPixelColor);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
177
video.h
Normal file
177
video.h
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _VIDEO_H_
|
||||
#define _VIDEO_H_
|
||||
|
||||
#include "ram.h"
|
||||
|
||||
///This keeps track of XRAM and draws on the canvas when refresh rate occurs.
|
||||
class VE_VMS_VIDEO
|
||||
{
|
||||
public:
|
||||
VE_VMS_VIDEO(VE_VMS_RAM *_ram);
|
||||
~VE_VMS_VIDEO();
|
||||
|
||||
void drawFrame(uint16_t *buffer);
|
||||
|
||||
private:
|
||||
VE_VMS_RAM *ram;
|
||||
|
||||
//BIOS icons
|
||||
/*static int FILE_ICON[] = {
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x01, 0xFF, 0xFC,
|
||||
0x02, 0x00, 0x0C,
|
||||
0x04, 0x00, 0x14,
|
||||
0x08, 0x00, 0x24,
|
||||
0x10, 0x00, 0x44,
|
||||
0x20, 0x00, 0x84,
|
||||
0x40, 0x01, 0x04,
|
||||
0xFF, 0xFE, 0xF4,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x7F, 0xF4,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x7F, 0xF4,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x7F, 0xF4,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0xFF, 0xFC,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
|
||||
static int GAME_ICON[] = {
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x01, 0xFF, 0xFC,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x02, 0x04,
|
||||
0x01, 0x07, 0x04,
|
||||
0x01, 0x0F, 0x84,
|
||||
0x01, 0x1F, 0xC4,
|
||||
0x01, 0x3F, 0xE4,
|
||||
0x01, 0x7F, 0xF4,
|
||||
0x01, 0x7F, 0xF4,
|
||||
0x01, 0x7F, 0xF4,
|
||||
0x01, 0x1A, 0xC4,
|
||||
0x01, 0x02, 0x04,
|
||||
0x01, 0x07, 0x04,
|
||||
0x01, 0x0F, 0x84,
|
||||
0x01, 0x1F, 0xC4,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0x00, 0x04,
|
||||
0x01, 0xFF, 0xFC,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
static int CLOCK_ICON[] = {
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x03, 0x80,
|
||||
0x00, 0x0C, 0x60,
|
||||
0x00, 0x11, 0x10,
|
||||
0x00, 0x21, 0x08,
|
||||
0x00, 0x41, 0x04,
|
||||
0x00, 0x41, 0x04,
|
||||
0x00, 0x41, 0x04,
|
||||
0x00, 0x40, 0xF4,
|
||||
0x00, 0x40, 0x04,
|
||||
0x00, 0x40, 0x04,
|
||||
0x00, 0x40, 0x04,
|
||||
0x00, 0x20, 0x08,
|
||||
0x00, 0x10, 0x10,
|
||||
0x00, 0x0C, 0x60,
|
||||
0x00, 0x03, 0x80,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
static int WRITE_ICON[] = {
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x7E, 0xFC,
|
||||
0x00, 0x7E, 0xFC,
|
||||
0x00, 0x7E, 0xFC,
|
||||
0x00, 0x7E, 0xFC,
|
||||
0x00, 0x7E, 0xFC,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x7E, 0xFC,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x7F, 0xFC,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00};
|
||||
|
||||
static int ICONS[1][4] = {FILE_ICON, GAME_ICON, CLOCK_ICON, WRITE_ICON};*/
|
||||
};
|
||||
|
||||
#endif // _VIDEO_H_
|
363
vmu.cpp
Normal file
363
vmu.cpp
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "vmu.h"
|
||||
|
||||
VMU::VMU(uint16_t *_frameBuffer)
|
||||
{
|
||||
//Initialize system
|
||||
ram = new VE_VMS_RAM();
|
||||
rom = new VE_VMS_ROM();
|
||||
flash = new VE_VMS_FLASH(ram);
|
||||
intHandler = new VE_VMS_INTERRUPTS();
|
||||
|
||||
cpu = new VE_VMS_CPU(ram, rom, flash, intHandler, true);
|
||||
|
||||
audio = new VE_VMS_AUDIO(cpu, ram);
|
||||
|
||||
t0 = new VE_VMS_TIMER0(ram, intHandler, cpu, &prescaler);
|
||||
t1 = new VE_VMS_TIMER1(ram, intHandler, audio);
|
||||
baseTimer = new VE_VMS_BASETIMER(ram, intHandler, cpu);
|
||||
|
||||
video = new VE_VMS_VIDEO(ram);
|
||||
frameBuffer = _frameBuffer;
|
||||
|
||||
|
||||
//Initialize variables
|
||||
ccount = 0; //Cycle count
|
||||
cycle_count = 0;
|
||||
time_reg = 0;
|
||||
frame_skip = 0;
|
||||
CPS = 0; //Real cycles per second
|
||||
prescaler = 0;
|
||||
pcount = 0;
|
||||
oldPRR = -1;
|
||||
|
||||
OSC = 0;
|
||||
OCR_old = -1; //For performance, not to calculate clock each time, unless OCR is changed.
|
||||
threadReady = false;
|
||||
inSleepState = false;
|
||||
BIOSExists = false;
|
||||
enableSound = true;
|
||||
useT1ELD = false; //Some mini-game programmers (Especially homebrew creators) don't use it
|
||||
cycles_left = 0;
|
||||
}
|
||||
|
||||
VMU::~VMU()
|
||||
{
|
||||
delete t0;
|
||||
delete t1;
|
||||
delete baseTimer;
|
||||
delete audio;
|
||||
delete video;
|
||||
delete flash;
|
||||
delete cpu;
|
||||
delete intHandler;
|
||||
delete ram;
|
||||
delete rom;
|
||||
}
|
||||
|
||||
int VMU::loadBIOS(const char *filePath)
|
||||
{
|
||||
FILE *bios = fopen(filePath, "rb");
|
||||
|
||||
if(bios == NULL) return -1;
|
||||
|
||||
fseek(bios, 0, SEEK_END);
|
||||
size_t fileSize = ftell(bios);
|
||||
fseek(bios, 0, SEEK_SET);
|
||||
|
||||
byte *BIOS_Data_Encrypted = new byte[0xF004];
|
||||
byte *BIOS_Data = new byte[0xF000];
|
||||
|
||||
if(fileSize > 0xF004) return -2; //Unknown BIOS image type
|
||||
|
||||
|
||||
for(size_t i = 0; i < fileSize; ++i)
|
||||
BIOS_Data_Encrypted[i] = fgetc(bios);
|
||||
|
||||
fclose(bios);
|
||||
|
||||
|
||||
//Decrypt BIOS file if encrypted (First opcode is not JMPF)
|
||||
if(BIOS_Data_Encrypted[0] != 0x2A)
|
||||
{
|
||||
//Remove first 4 bytes
|
||||
for (int i = 0; i < 0xF000; ++i)
|
||||
{
|
||||
BIOS_Data[i] = BIOS_Data_Encrypted[i + 4];
|
||||
}
|
||||
|
||||
//XOR 0x37
|
||||
for (int i = 0; i < 0xF000; ++i)
|
||||
{
|
||||
BIOS_Data[i] = (byte) ((BIOS_Data[i] ^ 0x37) & 0xFF);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//BIOS is not encrypted
|
||||
for(size_t i = 0; i < 0xF000; ++i)
|
||||
BIOS_Data[i] = BIOS_Data_Encrypted[i];
|
||||
}
|
||||
|
||||
//Check BIOS one last time (After decrypting)
|
||||
if(BIOS_Data[0] != 0x2A)
|
||||
return -1;
|
||||
|
||||
BIOSExists = true;
|
||||
|
||||
//This is loaded in (64KB) of ROM
|
||||
for(size_t i = 0; i < 0xF000; ++i)
|
||||
rom->writeByte(i, BIOS_Data[i]);
|
||||
|
||||
delete []BIOS_Data;
|
||||
delete []BIOS_Data_Encrypted;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void VMU::halt()
|
||||
{
|
||||
cpu->state = 0;
|
||||
}
|
||||
|
||||
void VMU::setDate()
|
||||
{
|
||||
//Set time and date
|
||||
time_t rawTime;
|
||||
time(&rawTime);
|
||||
|
||||
struct tm *currentTime = localtime(&rawTime);
|
||||
|
||||
byte day = currentTime->tm_mday & 0xFF;
|
||||
byte month = currentTime->tm_mon & 0xFF;
|
||||
byte year = (currentTime->tm_year + 1900) & 0xFF;
|
||||
byte yearH = (year & 0xFF00) >> 8;
|
||||
byte yearL = year & 0xFF;
|
||||
byte hour = currentTime->tm_hour & 0xFF;
|
||||
byte min = currentTime->tm_min & 0xFF;
|
||||
byte sec = currentTime->tm_sec & 0xFF;
|
||||
|
||||
//BCD time
|
||||
ram->writeByte_RAW(0x10, int2BCD(year) & 0xFF);
|
||||
ram->writeByte_RAW(0x11, (int2BCD(year) & 0xFF00) >> 8);
|
||||
ram->writeByte_RAW(0x12, int2BCD(month));
|
||||
ram->writeByte_RAW(0x13, int2BCD(day));
|
||||
ram->writeByte_RAW(0x14, int2BCD(hour));
|
||||
ram->writeByte_RAW(0x15, int2BCD(min));
|
||||
ram->writeByte_RAW(0x16, int2BCD(sec));
|
||||
|
||||
ram->writeByte_RAW(0x17, yearH);
|
||||
ram->writeByte_RAW(0x18, yearL);
|
||||
ram->writeByte_RAW(0x19, month);
|
||||
ram->writeByte_RAW(0x1A, day);
|
||||
ram->writeByte_RAW(0x1B, hour);
|
||||
ram->writeByte_RAW(0x1C, min);
|
||||
ram->writeByte_RAW(0x1D, sec);
|
||||
|
||||
ram->writeByte_RAW(0x50, yearH / 4);
|
||||
ram->writeByte_RAW(0x51, yearL / 4);
|
||||
}
|
||||
|
||||
//Sets system variables in RAM
|
||||
void VMU::initBIOS()
|
||||
{
|
||||
setDate();
|
||||
|
||||
ram->writeByte_RAW(0x31, 0xFF);
|
||||
|
||||
//No buttons clicked
|
||||
ram->writeByte_RAW(P3, 0xFF);
|
||||
|
||||
|
||||
//ram->writeByte(0x6E, 0xFF);
|
||||
}
|
||||
|
||||
void VMU::startCPU()
|
||||
{
|
||||
//printf("Starting CPU\n");
|
||||
if(!BIOSExists)
|
||||
{
|
||||
//Enable HLE
|
||||
ram->writeByte_RAW(EXT, 1);
|
||||
cpu->EXTOld = 1;
|
||||
initializeHLE();
|
||||
} else initBIOS();
|
||||
|
||||
cpu->state = 1;
|
||||
|
||||
//if(enableSound)
|
||||
//audioThread.start();
|
||||
}
|
||||
|
||||
void VMU::initializeHLE()
|
||||
{
|
||||
//Initialize system variables
|
||||
setDate();
|
||||
ram->writeByte_RAW(0x31, 0xFF);
|
||||
ram->writeByte_RAW(0x6E, 0xFF);
|
||||
|
||||
//Initialize SFR
|
||||
ram->writeByte_RAW(P3, 0xFF);
|
||||
ram->writeByte_RAW(SP, 0x7F);
|
||||
ram->writeByte_RAW(PSW, 0x02);
|
||||
ram->writeByte_RAW(IE, 0x80);
|
||||
ram->writeByte_RAW(MCR, 0x08);
|
||||
ram->writeByte_RAW(P7, 0x02);
|
||||
ram->writeByte_RAW(OCR, 0xA3);
|
||||
ram->writeByte_RAW(BTCR, 0x41);
|
||||
}
|
||||
|
||||
void VMU::runCycle()
|
||||
{
|
||||
//Calculate cpu clock frequency (Only when OCR is changed)
|
||||
byte OCR_data = ram->readByte_RAW(OCR);
|
||||
if (OCR_data != OCR_old)
|
||||
{
|
||||
int freqDiv = 12;
|
||||
if ((OCR_data & 128) != 0) freqDiv = 6;
|
||||
OSC = 0; //Main clock by default is RC
|
||||
if ((OCR_data & 32) != 0) OSC = 1; //Quartz
|
||||
//double freq;
|
||||
if (OSC == 0)
|
||||
{
|
||||
//freq = 879.236 / freqDiv;
|
||||
audio->setAudioFrequency(600000 / freqDiv); //What the real frequency should be
|
||||
cpu->setFrequency(600000 / freqDiv);
|
||||
}
|
||||
else //RC
|
||||
{
|
||||
//freq = 32.768 / freqDiv;
|
||||
audio->setAudioFrequency(32768 / freqDiv); //What the real frequency should be
|
||||
cpu->setFrequency(32768 / freqDiv);
|
||||
}
|
||||
//double clock = (1.00 / freq) * 1000; //In milliseconds
|
||||
//cpu->clock = (int) clock;//(int) clock;
|
||||
|
||||
}
|
||||
OCR_old = OCR_data;
|
||||
|
||||
//int cyclesUsed = 1;
|
||||
|
||||
//Set T1LC and T1HC when bit 4 of T1CNT is 1
|
||||
byte T1CNT_data = ram->readByte_RAW(T1CNT);
|
||||
bool T1CUpdate = (T1CNT_data & 16) != 0;
|
||||
if(T1CUpdate)
|
||||
{
|
||||
ram->writeByte_RAW(T1LC, ram->T1LC_Temp);
|
||||
ram->writeByte_RAW(T1HC, ram->T1HC_Temp);
|
||||
|
||||
audio->setT1C(ram->T1LC_Temp);
|
||||
}
|
||||
|
||||
//Battery not low
|
||||
ram->writeByte_RAW(0x31, 0xFF);
|
||||
ram->writeByte_RAW(P7, 2);
|
||||
|
||||
byte PCON_data = ram->readByte_RAW(PCON);
|
||||
|
||||
//Execute
|
||||
if (cpu->state != 0)
|
||||
{
|
||||
cpu->processInterrupts();
|
||||
if (PCON_data == 0) cycles_left = cpu->processInstruction(false);
|
||||
}
|
||||
--cycles_left;
|
||||
|
||||
//Set prescaler
|
||||
byte PRR = ram->readByte_RAW(T0PRR);
|
||||
|
||||
//This is important since Base Timer interrupts sometimes manipulates PRR, so we reset it so the modulo would be 0 in case number came.
|
||||
if (PRR != oldPRR)
|
||||
pcount = PRR;
|
||||
|
||||
if (pcount / 256 == 1)
|
||||
{
|
||||
prescaler = 1;
|
||||
pcount = PRR;
|
||||
}
|
||||
else
|
||||
{
|
||||
prescaler = 0;
|
||||
pcount++;
|
||||
}
|
||||
oldPRR = PRR;
|
||||
|
||||
|
||||
//Run timers (t0 and t1)
|
||||
t0->runTimer();
|
||||
t1->runTimer();
|
||||
baseTimer->runTimer();
|
||||
|
||||
//Set VMU date (I just randomly put it at 10000, that is, till the BIOS has fully initialized memory, so it wont manipulate date value)
|
||||
if (ccount == 10000 && BIOSExists)
|
||||
setDate();
|
||||
else ccount++;
|
||||
|
||||
cycle_count++;
|
||||
}
|
||||
|
||||
void VMU::reset()
|
||||
{
|
||||
delete t0;
|
||||
delete t1;
|
||||
delete baseTimer;
|
||||
delete audio;
|
||||
delete video;
|
||||
delete flash;
|
||||
delete cpu;
|
||||
delete intHandler;
|
||||
delete ram;
|
||||
delete rom;
|
||||
|
||||
//Re-initialize system
|
||||
ram = new VE_VMS_RAM();
|
||||
rom = new VE_VMS_ROM();
|
||||
flash = new VE_VMS_FLASH(ram);
|
||||
intHandler = new VE_VMS_INTERRUPTS();
|
||||
|
||||
cpu = new VE_VMS_CPU(ram, rom, flash, intHandler, true);
|
||||
|
||||
audio = new VE_VMS_AUDIO(cpu, ram);
|
||||
|
||||
t0 = new VE_VMS_TIMER0(ram, intHandler, cpu, &prescaler);
|
||||
t1 = new VE_VMS_TIMER1(ram, intHandler, audio);
|
||||
baseTimer = new VE_VMS_BASETIMER(ram, intHandler, cpu);
|
||||
|
||||
video = new VE_VMS_VIDEO(ram);
|
||||
|
||||
//Re-nitialize variables
|
||||
ccount = 0; //Cycle count
|
||||
cycle_count = 0;
|
||||
time_reg = 0;
|
||||
frame_skip = 0;
|
||||
CPS = 0; //Real cycles per second
|
||||
prescaler = 0;
|
||||
pcount = 0;
|
||||
oldPRR = -1;
|
||||
|
||||
OSC = 0;
|
||||
OCR_old = -1; //For performance, not to calculate clock each time, unless OCR is changed.
|
||||
threadReady = false;
|
||||
inSleepState = false;
|
||||
BIOSExists = false;
|
||||
enableSound = true;
|
||||
useT1ELD = false; //Some mini-game programmers (Especially homebrew creators) don't use it
|
||||
cycles_left = 0;
|
||||
}
|
94
vmu.h
Normal file
94
vmu.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
VeMUlator - A Dreamcast Visual Memory Unit emulator for libretro
|
||||
Copyright (C) 2018 Mahmoud Jaoune
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _VMU_H_
|
||||
#define _VMU_H_
|
||||
|
||||
#include <time.h>
|
||||
#include "common.h"
|
||||
#include "ram.h"
|
||||
#include "cpu.h"
|
||||
#include "video.h"
|
||||
#include "rom.h"
|
||||
#include "audio.h"
|
||||
#include "t0.h"
|
||||
#include "t1.h"
|
||||
#include "basetimer.h"
|
||||
#include "interrupts.h"
|
||||
#include "bitwisemath.h"
|
||||
|
||||
class VMU
|
||||
{
|
||||
public:
|
||||
VE_VMS_RAM *ram;
|
||||
VE_VMS_ROM *rom;
|
||||
VE_VMS_FLASH *flash;
|
||||
VE_VMS_CPU *cpu;
|
||||
VE_VMS_TIMER0 *t0;
|
||||
VE_VMS_TIMER1 *t1;
|
||||
VE_VMS_BASETIMER *baseTimer;
|
||||
VE_VMS_INTERRUPTS *intHandler;
|
||||
VE_VMS_VIDEO *video;
|
||||
VE_VMS_AUDIO *audio;
|
||||
|
||||
VMU(uint16_t *_frameBuffer);
|
||||
|
||||
~VMU();
|
||||
|
||||
|
||||
int loadBIOS(const char *filePath);
|
||||
|
||||
void halt();
|
||||
|
||||
void setDate();
|
||||
|
||||
//Sets system variables in RAM
|
||||
void initBIOS();
|
||||
|
||||
void startCPU();
|
||||
|
||||
void initializeHLE();
|
||||
|
||||
void runCycle();
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
int ccount;
|
||||
long cycle_count;
|
||||
long time_reg;
|
||||
long frame_skip;
|
||||
double CPS;
|
||||
byte prescaler;
|
||||
int pcount;
|
||||
int oldPRR;
|
||||
|
||||
int OSC;
|
||||
int OCR_old;
|
||||
bool threadReady;
|
||||
bool inSleepState;
|
||||
bool BIOSExists;
|
||||
bool enableSound;
|
||||
bool useT1ELD;
|
||||
|
||||
int cycles_left; //This counts how many cycles an instruction has, and gets decreased each cycle. Next instruction is processed when it gets 0.
|
||||
|
||||
uint16_t *frameBuffer;
|
||||
};
|
||||
|
||||
#endif // _VMU_H_
|
Loading…
x
Reference in New Issue
Block a user